mirror of
https://github.com/logos-co/open-law.git
synced 2025-01-24 05:38:52 +00:00
works
This commit is contained in:
parent
df86263a55
commit
fc2a735e32
@ -1,20 +1,116 @@
|
|||||||
|
from flask import url_for
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from app import models as m, db
|
from app import models as m, db
|
||||||
|
from app import schema as s
|
||||||
|
|
||||||
|
|
||||||
def create_breadcrumbs(
|
def create_breadcrumbs(
|
||||||
book_id: int,
|
book_id: int,
|
||||||
collection_id: int = 0,
|
collection_path: tuple[int],
|
||||||
sub_collection_id: int = 0,
|
|
||||||
section_id: int = 0,
|
section_id: int = 0,
|
||||||
):
|
interpretation_id: int = 0,
|
||||||
book = db.session.get(m.Book, book_id)
|
) -> list[s.BreadCrumb]:
|
||||||
if book.owner.id == current_user.id:
|
crumples: list[s.BreadCrumb] = []
|
||||||
pass
|
book: m.Book = db.session.get(m.Book, book_id)
|
||||||
if collection_id != 0:
|
if current_user.is_authenticated and book.user_id == current_user.id:
|
||||||
collection = db.session.get(m.Collection, collection_id)
|
# My Book
|
||||||
if sub_collection_id != 0:
|
crumples += [
|
||||||
sub_collection = db.session.get(m.Collection, sub_collection_id)
|
s.BreadCrumb(
|
||||||
if section_id != 0:
|
type=s.BreadCrumbType.MyBookList,
|
||||||
section = db.session.get(m.Section, section_id)
|
url=url_for("book.my_books"),
|
||||||
pass
|
label="My Books",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
# Not mine book
|
||||||
|
crumples += [
|
||||||
|
s.BreadCrumb(
|
||||||
|
type=s.BreadCrumbType.AuthorBookList,
|
||||||
|
url="#",
|
||||||
|
label=book.owner.username + "'s books",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
crumples += [
|
||||||
|
s.BreadCrumb(
|
||||||
|
type=s.BreadCrumbType.Collection,
|
||||||
|
url=url_for("book.collection_view", book_id=book_id),
|
||||||
|
label=book.label,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
for collection_id in collection_path:
|
||||||
|
collection: m.Collection = db.session.get(m.Collection, collection_id)
|
||||||
|
crumples += [
|
||||||
|
s.BreadCrumb(
|
||||||
|
type=s.BreadCrumbType.Collection,
|
||||||
|
url=url_for(
|
||||||
|
"book.sub_collection_view",
|
||||||
|
book_id=book_id,
|
||||||
|
collection_id=collection_id,
|
||||||
|
),
|
||||||
|
label=collection.label,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
if section_id != 0 and collection_path:
|
||||||
|
section: m.Section = db.session.get(m.Section, section_id)
|
||||||
|
if len(collection_path) == 2:
|
||||||
|
crumples += [
|
||||||
|
s.BreadCrumb(
|
||||||
|
type=s.BreadCrumbType.Section,
|
||||||
|
url=url_for(
|
||||||
|
"book.section_view",
|
||||||
|
book_id=book_id,
|
||||||
|
collection_id=collection_path[0],
|
||||||
|
sub_collection_id=collection_path[-1],
|
||||||
|
),
|
||||||
|
label=section.label,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
crumples += [
|
||||||
|
s.BreadCrumb(
|
||||||
|
type=s.BreadCrumbType.Section,
|
||||||
|
url=url_for(
|
||||||
|
"book.section_view",
|
||||||
|
book_id=book_id,
|
||||||
|
collection_id=collection_path[0],
|
||||||
|
sub_collection_id=collection_path[0],
|
||||||
|
),
|
||||||
|
label=section.label,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
if interpretation_id != 0:
|
||||||
|
interpretation: m.Interpretation = db.session.get(
|
||||||
|
m.Interpretation, interpretation_id
|
||||||
|
)
|
||||||
|
if len(collection_path) == 2:
|
||||||
|
crumples += [
|
||||||
|
s.BreadCrumb(
|
||||||
|
type=s.BreadCrumbType.Interpretation,
|
||||||
|
url=url_for(
|
||||||
|
"book.interpretation_view",
|
||||||
|
book_id=book_id,
|
||||||
|
collection_id=collection_path[0],
|
||||||
|
sub_collection_id=collection_path[-1],
|
||||||
|
section_id=section_id,
|
||||||
|
),
|
||||||
|
label=interpretation.label,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
crumples += [
|
||||||
|
s.BreadCrumb(
|
||||||
|
type=s.BreadCrumbType.Interpretation,
|
||||||
|
url=url_for(
|
||||||
|
"book.interpretation_view",
|
||||||
|
book_id=book_id,
|
||||||
|
collection_id=collection_path[0],
|
||||||
|
sub_collection_id=collection_path[0],
|
||||||
|
section_id=section_id,
|
||||||
|
),
|
||||||
|
label=interpretation.label,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
return crumples
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
# flake8: noqa F401
|
# flake8: noqa F401
|
||||||
from .pagination import Pagination
|
from .pagination import Pagination
|
||||||
from .user import User
|
from .user import User
|
||||||
|
from .breadcrumbs import BreadCrumbType, BreadCrumb
|
||||||
|
@ -1,18 +1,30 @@
|
|||||||
|
import enum
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class Breadcrumbs(BaseModel):
|
class BreadCrumbType(enum.StrEnum):
|
||||||
"""Breadcrumbs for navigation"""
|
"""Bread Crumb Type"""
|
||||||
|
|
||||||
book_owner: str # book owner name
|
MyBookList = "MyBookList"
|
||||||
route_for_all_owners_books: str # route for all book of this book owner
|
AuthorBookList = "AuthorBookList"
|
||||||
current_user_is_owner: bool # if current_user is owner of book
|
Collection = "Collection"
|
||||||
book_name: str # book label
|
Section = "Section"
|
||||||
|
Interpretation = "Interpretation"
|
||||||
|
|
||||||
|
|
||||||
|
class BreadCrumb(BaseModel):
|
||||||
|
"""Bread Crumb for navigation"""
|
||||||
|
|
||||||
|
label: str
|
||||||
|
url: str
|
||||||
|
type: BreadCrumbType
|
||||||
|
|
||||||
# How breadcrumbs must look like
|
# How breadcrumbs must look like
|
||||||
|
# Book List > Book Name > Top Level Collection > SubCollection > Section > Interpretation
|
||||||
|
|
||||||
# if im not owner of a book
|
# if im not owner of a book
|
||||||
# Home > Owner_name/All his books > This_book_name > Collection_name > Sub_collection_name > Section_name
|
# John's books > Book Name > Top Level Collection > SubCollection > Section > Interpretation
|
||||||
|
|
||||||
# if i owner
|
# if i owner
|
||||||
# Home > My_books > This_book_name > Collection_name > Sub_collection_name > Section_name
|
# My Books > Book Title > Part I > Chapter X > Paragraph 1.7 > By John
|
||||||
|
File diff suppressed because one or more lines are too long
@ -21,25 +21,22 @@
|
|||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<nav class="flex mt-5 mb-3" aria-label="Breadcrumb">
|
<nav class="flex mt-5 mb-3" aria-label="Breadcrumb">
|
||||||
<ol class="inline-flex items-center space-x-1 md:space-x-3 ml-5">
|
<ol class="inline-flex items-center space-x-1 md:space-x-3 ml-5">
|
||||||
|
{% for breadcrumb in breadcrumbs %}
|
||||||
<li class="inline-flex items-center">
|
<li class="inline-flex items-center">
|
||||||
<span href="{{ url_for('book.my_books') }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
<a href="{{ breadcrumb.url }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
||||||
<svg aria-hidden="true" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path> </svg>
|
<!-- prettier-ignore -->
|
||||||
{{ book.owner.username }}
|
<!--svg for all types of breadcrumb-->
|
||||||
</span>
|
{% if breadcrumb.type == "MyBookList" or breadcrumb.type == "AuthorBookList" %}
|
||||||
|
<svg aria-hidden="true" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path></svg>
|
||||||
|
{% else %}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" /> </svg>
|
||||||
|
{% endif %}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{{ breadcrumb.label }}
|
||||||
|
</a>
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
||||||
</li>
|
</li>
|
||||||
<li class="inline-flex items-center">
|
{% endfor %}
|
||||||
<a href="{{ url_for('book.my_books') }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
|
||||||
<svg aria-hidden="true" class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path> </svg>
|
|
||||||
My books
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
|
||||||
<span class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 dark:text-gray-400 dark:hover:text-white disabled" > {{ book.label }}</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
<h1 class="text-l font-extrabold dark:text-white ml-4">Collections page</h1>
|
<h1 class="text-l font-extrabold dark:text-white ml-4">Collections page</h1>
|
||||||
@ -87,7 +84,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
</a >
|
</a >
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,18 +3,30 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="relative overflow-x-auto shadow-md sm:rounded-lg mt-5 md:mr-64">
|
<div class="relative overflow-x-auto shadow-md sm:rounded-lg mt-5 md:mr-64">
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<div class="flex p-2">
|
<nav class="flex mt-5 mb-3" aria-label="Breadcrumb">
|
||||||
<div>
|
<ol class="inline-flex items-center space-x-1 md:space-x-3 ml-5">
|
||||||
<h1 class="text-l font-extrabold dark:text-white ml-4">
|
{% for breadcrumb in breadcrumbs %}
|
||||||
{{ book.owner.username }}/{{ book.label }}
|
<li class="inline-flex items-center">
|
||||||
</h1>
|
<a href="{{ breadcrumb.url }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
||||||
<h1 class="text-2xl font-extrabold dark:text-white ml-4">
|
<!-- prettier-ignore -->
|
||||||
{{collection.label}}/{{sub_collection.label}}/{{section.label}}
|
<!--svg for all types of breadcrumb-->
|
||||||
</h1>
|
{% if breadcrumb.type == "MyBookList" or breadcrumb.type == "AuthorBookList" %}
|
||||||
</div>
|
<svg aria-hidden="true" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path> </svg>
|
||||||
</div>
|
{% else %}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" /> </svg>
|
||||||
|
{% endif %}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{{ breadcrumb.label }}
|
||||||
|
</a>
|
||||||
|
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
<h1 class="text-l font-extrabold dark:text-white ml-4">
|
||||||
|
Interpretations page
|
||||||
|
</h1>
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
|
|
||||||
<div class="mb-1 border-b border-gray-200 dark:border-gray-700">
|
<div class="mb-1 border-b border-gray-200 dark:border-gray-700">
|
||||||
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center" id="myTab" data-tabs-toggle="#myTabContent" role="tablist">
|
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center" id="myTab" data-tabs-toggle="#myTabContent" role="tablist">
|
||||||
<li class="mr-2" role="presentation">
|
<li class="mr-2" role="presentation">
|
||||||
|
@ -21,39 +21,22 @@
|
|||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<nav class="flex mt-5 mb-3" aria-label="Breadcrumb">
|
<nav class="flex mt-5 mb-3" aria-label="Breadcrumb">
|
||||||
<ol class="inline-flex items-center space-x-1 md:space-x-3 ml-5">
|
<ol class="inline-flex items-center space-x-1 md:space-x-3 ml-5">
|
||||||
<li class="inline-flex items-center">
|
{% for breadcrumb in breadcrumbs %}
|
||||||
<span class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
<li class="inline-flex items-center">
|
||||||
<svg aria-hidden="true" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path> </svg>
|
<a href="{{ breadcrumb.url }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
||||||
{{ book.owner.username }}
|
<!-- prettier-ignore -->
|
||||||
</span>
|
<!--svg for all types of breadcrumb-->
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
{% if breadcrumb.type == "MyBookList" or breadcrumb.type == "AuthorBookList" %}
|
||||||
</li>
|
<svg aria-hidden="true" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path> </svg>
|
||||||
<li class="inline-flex items-center">
|
{% else %}
|
||||||
<a href="{{ url_for('book.my_books') }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" /> </svg>
|
||||||
<svg aria-hidden="true" class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path> </svg>
|
{% endif %}
|
||||||
My books
|
<!-- prettier-ignore -->
|
||||||
</a>
|
{{ breadcrumb.label }}
|
||||||
</li>
|
</a>
|
||||||
<li>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
||||||
<a class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 dark:text-gray-400 dark:hover:text-white disabled" href="{{url_for('book.collection_view',book_id=book.id)}}"> {{ book.label }}</a>
|
</li>
|
||||||
</div>
|
{% endfor %}
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
|
||||||
<a class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 dark:text-gray-400 dark:hover:text-white disabled" href="{{url_for('book.collection_view',book_id=book.id,collection_id=collection.id)}}"> {{collection.label}}</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
{% if sub_collection.id != collection.id %}
|
|
||||||
<li>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
|
||||||
<a class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 dark:text-gray-400 dark:hover:text-white disabled" href="{{url_for('book.sub_collection_view',book_id=book.id,collection_id=collection.id)}}"> {{sub_collection.label}}</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
<h1 class="text-l font-extrabold dark:text-white ml-4">Sections page</h1>
|
<h1 class="text-l font-extrabold dark:text-white ml-4">Sections page</h1>
|
||||||
|
@ -25,31 +25,22 @@
|
|||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<nav class="flex mt-5 mb-3" aria-label="Breadcrumb">
|
<nav class="flex mt-5 mb-3" aria-label="Breadcrumb">
|
||||||
<ol class="inline-flex items-center space-x-1 md:space-x-3 ml-5">
|
<ol class="inline-flex items-center space-x-1 md:space-x-3 ml-5">
|
||||||
|
{% for breadcrumb in breadcrumbs %}
|
||||||
<li class="inline-flex items-center">
|
<li class="inline-flex items-center">
|
||||||
<span href="{{ url_for('book.my_books') }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
<a href="{{ breadcrumb.url }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
||||||
<svg aria-hidden="true" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path> </svg>
|
<!-- prettier-ignore -->
|
||||||
{{ book.owner.username }}
|
<!--svg for all types of breadcrumb-->
|
||||||
</span>
|
{% if breadcrumb.type == "MyBookList" or breadcrumb.type == "AuthorBookList" %}
|
||||||
|
<svg aria-hidden="true" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path> </svg>
|
||||||
|
{% else %}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="flex-shrink-0 w-4 h-4 mr-2 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" /> </svg>
|
||||||
|
{% endif %}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{{ breadcrumb.label }}
|
||||||
|
</a>
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
||||||
</li>
|
</li>
|
||||||
<li class="inline-flex items-center">
|
{% endfor %}
|
||||||
<a href="{{ url_for('book.my_books') }}" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
|
|
||||||
<svg aria-hidden="true" class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path> </svg>
|
|
||||||
My books
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
|
||||||
<a class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 dark:text-gray-400 dark:hover:text-white disabled" href="{{url_for('book.collection_view',book_id=book.id)}}"> {{ book.label }}</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<svg aria-hidden="true" class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path> </svg>
|
|
||||||
<span class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2 dark:text-gray-400 dark:hover:text-white disabled"> {{collection.label}}</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
<h1 class="text-l font-extrabold dark:text-white ml-4">
|
<h1 class="text-l font-extrabold dark:text-white ml-4">
|
||||||
|
@ -10,6 +10,7 @@ from flask_login import login_required, current_user
|
|||||||
|
|
||||||
from app.controllers import create_pagination
|
from app.controllers import create_pagination
|
||||||
from app import models as m, db, forms as f
|
from app import models as m, db, forms as f
|
||||||
|
from app.controllers.breadcrumbs import create_breadcrumbs
|
||||||
from app.logger import log
|
from app.logger import log
|
||||||
|
|
||||||
bp = Blueprint("book", __name__, url_prefix="/book")
|
bp = Blueprint("book", __name__, url_prefix="/book")
|
||||||
@ -79,12 +80,15 @@ def create():
|
|||||||
@bp.route("/<int:book_id>", methods=["GET"])
|
@bp.route("/<int:book_id>", methods=["GET"])
|
||||||
def collection_view(book_id: int):
|
def collection_view(book_id: int):
|
||||||
book = db.session.get(m.Book, book_id)
|
book = db.session.get(m.Book, book_id)
|
||||||
|
breadcrumbs = create_breadcrumbs(book_id=book_id, collection_path=())
|
||||||
if not book or book.is_deleted:
|
if not book or book.is_deleted:
|
||||||
log(log.WARNING, "Book with id [%s] not found", book_id)
|
log(log.WARNING, "Book with id [%s] not found", book_id)
|
||||||
flash("Book not found", "danger")
|
flash("Book not found", "danger")
|
||||||
return redirect(url_for("book.my_books"))
|
return redirect(url_for("book.my_books"))
|
||||||
else:
|
else:
|
||||||
return render_template("book/collection_view.html", book=book)
|
return render_template(
|
||||||
|
"book/collection_view.html", book=book, breadcrumbs=breadcrumbs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:book_id>/<int:collection_id>", methods=["GET"])
|
@bp.route("/<int:book_id>/<int:collection_id>", methods=["GET"])
|
||||||
@ -94,22 +98,26 @@ def sub_collection_view(book_id: int, collection_id: int):
|
|||||||
log(log.WARNING, "Book with id [%s] not found", book_id)
|
log(log.WARNING, "Book with id [%s] not found", book_id)
|
||||||
flash("Book not found", "danger")
|
flash("Book not found", "danger")
|
||||||
return redirect(url_for("book.my_books"))
|
return redirect(url_for("book.my_books"))
|
||||||
|
|
||||||
collection: m.Collection = db.session.get(m.Collection, collection_id)
|
collection: m.Collection = db.session.get(m.Collection, collection_id)
|
||||||
if not collection or collection.is_deleted:
|
if not collection or collection.is_deleted:
|
||||||
log(log.WARNING, "Collection with id [%s] not found", collection_id)
|
log(log.WARNING, "Collection with id [%s] not found", collection_id)
|
||||||
flash("Collection not found", "danger")
|
flash("Collection not found", "danger")
|
||||||
return redirect(url_for("book.collection_view", book_id=book_id))
|
return redirect(url_for("book.collection_view", book_id=book_id))
|
||||||
|
breadcrumbs = create_breadcrumbs(book_id=book_id, collection_path=(collection.id,))
|
||||||
if collection.is_leaf:
|
if collection.is_leaf:
|
||||||
return render_template(
|
return render_template(
|
||||||
"book/section_view.html",
|
"book/section_view.html",
|
||||||
book=book,
|
book=book,
|
||||||
collection=collection,
|
collection=collection,
|
||||||
sub_collection=collection,
|
sub_collection=collection,
|
||||||
|
breadcrumbs=breadcrumbs,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return render_template(
|
return render_template(
|
||||||
"book/sub_collection_view.html", book=book, collection=collection
|
"book/sub_collection_view.html",
|
||||||
|
book=book,
|
||||||
|
collection=collection,
|
||||||
|
breadcrumbs=breadcrumbs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -137,11 +145,19 @@ def section_view(book_id: int, collection_id: int, sub_collection_id: int):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
breadcrumbs = create_breadcrumbs(
|
||||||
|
book_id=book_id,
|
||||||
|
collection_path=(
|
||||||
|
collection_id,
|
||||||
|
sub_collection_id,
|
||||||
|
),
|
||||||
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"book/section_view.html",
|
"book/section_view.html",
|
||||||
book=book,
|
book=book,
|
||||||
collection=collection,
|
collection=collection,
|
||||||
sub_collection=sub_collection,
|
sub_collection=sub_collection,
|
||||||
|
breadcrumbs=breadcrumbs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -187,12 +203,21 @@ def interpretation_view(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
breadcrumbs = create_breadcrumbs(
|
||||||
|
book_id=book_id,
|
||||||
|
collection_path=(
|
||||||
|
collection_id,
|
||||||
|
sub_collection_id,
|
||||||
|
),
|
||||||
|
section_id=section_id,
|
||||||
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"book/interpretation_view.html",
|
"book/interpretation_view.html",
|
||||||
book=book,
|
book=book,
|
||||||
collection=collection,
|
collection=collection,
|
||||||
sub_collection=sub_collection,
|
sub_collection=sub_collection,
|
||||||
section=section,
|
section=section,
|
||||||
|
breadcrumbs=breadcrumbs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
18
tests/test_breadcrumbs.py
Normal file
18
tests/test_breadcrumbs.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from flask.testing import FlaskCliRunner
|
||||||
|
from app.controllers import create_breadcrumbs
|
||||||
|
from app import models as m, db
|
||||||
|
|
||||||
|
|
||||||
|
def test_breadcrumbs(runner: FlaskCliRunner, app):
|
||||||
|
runner.invoke(args=["db-populate"])
|
||||||
|
with app.app_context(), app.test_request_context():
|
||||||
|
res = create_breadcrumbs(1, (1,), 1)
|
||||||
|
assert len(res) == 4
|
||||||
|
book: m.Book = db.session.get(m.Book, 1)
|
||||||
|
assert book
|
||||||
|
assert book.owner.username in res[0].label
|
||||||
|
assert res[1].label == book.label
|
||||||
|
with app.app_context(), app.test_request_context():
|
||||||
|
res = create_breadcrumbs(1, (), 1)
|
||||||
|
assert res
|
||||||
|
assert len(res) == 2
|
Loading…
x
Reference in New Issue
Block a user