This commit is contained in:
Kostiantyn Stoliarskyi 2023-06-14 17:17:43 +03:00
parent 8493087f66
commit 41eadf801d
10 changed files with 133 additions and 152738 deletions

View File

@ -0,0 +1,26 @@
from sqlalchemy import text
from app.logger import log
from app.controllers import create_pagination
def sort_by(query, sort: str):
match sort:
case "favored":
query = query.order_by(text("stars_count DESC"))
case "upvoted":
query = query.order_by(text("score DESC"))
case "recent":
query = query.order_by(text("created_at DESC"))
case "commented":
query = query.order_by(text("comments_count DESC"))
case "interpretations":
query = query.order_by(text("interpretations_count DESC"))
case _:
query = query.order_by(text("created_at DESC"))
pagination = create_pagination(total=query.count())
log(log.INFO, "Returns data for front end")
query = query.paginate(page=pagination.page, per_page=pagination.per_page)
query.items = [item[0] for item in query.items]
return pagination, query

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -8,6 +8,7 @@
<!-- prettier-ignore -->
<button id="dropdownDelayButton" data-dropdown-toggle="dropdownDelay" data-dropdown-delay="500" data-dropdown-trigger="hover" class="text-white ml-4 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" type="button">
Sort by
{{request.args.get('sort',"")}}
<!-- prettier-ignore -->
<svg class="w-4 h-4 ml-auto" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> </svg>
</button>
@ -20,14 +21,14 @@
<li> <a href="?sort=upvoted" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" >Most upvoted</a > </li>
{% endif %}
{% if selected_tab=='my_library' or selected_tab=='favorite_books' or selected_tab=='explore_books'%}
<li> <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" >Most favored</a > </li>
<li> <a href="?sort=favored" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" >Most favored</a > </li>
{% endif %}
<li> <a href="?sort=recent" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" >Most recent</a > </li>
{% if selected_tab=='latest_interpretations' or selected_tab=='my_contributions' %}
<li> <a href="?sort=commented" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" >Most comments</a > </li>
{% endif %}
{% if selected_tab=='my_library' or selected_tab=='favorite_books' or selected_tab=='explore_books'%}
<li> <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" >Most interpretations</a > </li>
<li> <a href="?sort=interpretations" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" >Most interpretations</a > </li>
{% endif %}
</ul>
</div>

View File

@ -10,23 +10,25 @@
{% if not current_user.is_authenticated %}
<!-- prettier-ignore -->
<div class="mx-auto my-auto h-full w-full p-2">
<button type="button" id="connectWalletBtn" class="w-full h-full text-black dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-100 font-medium rounded-lg text-sm px-4 py-2.5 justify-center text-center inline-flex items-center border border-gray-200 dark:border-gray-700"><div class="my-auto"></div> Connect you wallet to see your favorite books! </div></button></div>
<button type="button" id="connectWalletBtn" class="w-full h-full text-black dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-100 font-medium rounded-lg text-sm px-4 py-2.5 justify-center text-center inline-flex items-center border border-gray-200 dark:border-gray-700"> Connect you wallet to see your favorite books! </div></button></div>
<!-- prettier-ignore -->
{% endif %}
{% if current_user.is_authenticated and current_user.stars|length==0 %}
<!-- prettier-ignore -->
<div class="mx-auto my-auto h-full w-full ">
<a type="button" href="{{ url_for('book.get_all') }}" class="w-full h-full text-black dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-100 font-medium rounded-lg text-sm px-4 py-2.5 justify-center text-center inline-flex items-center border border-gray-200 dark:border-gray-700"><div class="my-auto"></div><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> </svg> You don't have favorite books start to explore book to choose one! </div></button></div>
<a href="{{ url_for('home.explore_books') }}" class="w-full h-full text-black dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-100 font-medium rounded-lg text-sm px-4 py-2.5 justify-center text-center inline-flex items-center border border-gray-200 dark:border-gray-700"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> </svg> You don't have favorite books start to explore book to choose one! </div></a></div>
<!-- prettier-ignore -->
{% endif %}
<!-- prettier-ignore -->
<div class="flex flex-col w-full">
{% if current_user.is_authenticated and current_user.stars|length>0 %}
<div class="flex justify-between mt-1">
<h1 class=" text-lg font-extrabold dark:text-white ml-4">Fav books</h1>
{% if current_user.is_authenticated %}
{% include 'book/components/header_buttons.html' %}
{% endif %}
</div>
{% endif %}
{% for book in books %}
<!-- prettier-ignore -->
<dl class="bg-white dark:bg-gray-900 h-max w-full p-5 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
@ -40,7 +42,7 @@
<div class="flex ml-auto align-center justify-center space-x-3">
<span class="book-star-block space-x-0.5 flex items-center">
<svg class="star-btn cursor-pointer w-4 h-4 inline-flex mr-1 {% if book.current_user_has_star %}fill-yellow-300{% endif %}" data-book-id={{ book.id }} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22" stroke-width="1" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z" /> </svg>
<a href={{ url_for('book.statistic_view', book_id=book.id ) }} class="total-stars">{{ book.stars|length }}</a>
<a href="{{ url_for('book.statistic_view', book_id=book.id ) }}" class="total-stars">{{ book.stars|length }}</a>
</span>
<span class="space-x-0.5 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22" stroke-width="1" stroke="currentColor" class="w-4 h-4 inline-flex mr-1"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>

View File

@ -13,20 +13,22 @@
<button type="button" id="connectWalletBtn" class="w-full h-full text-black dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-100 font-medium rounded-lg text-sm px-4 py-2.5 justify-center text-center inline-flex items-center border border-gray-200 dark:border-gray-700"><div class="my-auto"></div> Connect you wallet to see your contributions! </div></button></div>
<!-- prettier-ignore -->
{% endif %}
{% if current_user.is_authenticated and not interpretations %}
{% if current_user.is_authenticated and not interpretations.total %}
<!-- prettier-ignore -->
<div class="mx-auto my-auto h-full w-full p-2">
<a href="{{url_for('home.get_all')}}" type="button" class="w-full h-full text-black dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-100 font-medium rounded-lg text-sm px-4 py-2.5 justify-center text-center inline-flex items-center border border-gray-200 dark:border-gray-700"><div class="my-auto"></div><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> </svg> You don't have contributions! Start review books to create one!</div></button></div>
<a href="{{url_for('home.get_all')}}" type="button" class="w-full h-full text-black dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-100 font-medium rounded-lg text-sm px-4 py-2.5 justify-center text-center inline-flex items-center border border-gray-200 dark:border-gray-700"><div class="my-auto"></div><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> </svg> You don't have contributions! Start review books to create one!</div></a></div>
<!-- prettier-ignore -->
{% endif %}
<!-- prettier-ignore -->
<div class="flex flex-col w-full">
{% if current_user.is_authenticated and interpretations.total %}
<div class="flex justify-between mt-1">
<h1 class=" text-lg font-extrabold dark:text-white ml-4">My contributions</h1>
{% if current_user.is_authenticated %}
{% include 'book/components/header_buttons.html' %}
{% endif %}
</div>
{% endif %}
{% for interpretation in interpretations %}
<!-- prettier-ignore -->
<dl class="bg-white dark:bg-gray-900 max-w-full p-3 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">

View File

@ -28,11 +28,13 @@
<!-- prettier-ignore -->
<div class="flex flex-col w-full">
<div class="flex justify-between mt-1">
{% if current_user.is_authenticated and books.total>0 %}
<h1 class=" text-lg font-extrabold dark:text-white ml-4">My library</h1>
{% if current_user.is_authenticated %}
{% include 'book/components/header_buttons.html' %}
{% endif %}
</div>
{% endif %}
{% for book in books if not book.is_deleted%}
<!-- prettier-ignore -->

View File

@ -1,9 +1,8 @@
from flask import render_template, flash, redirect, url_for, request
from flask_login import login_required, current_user
from sqlalchemy import and_, or_
from sqlalchemy import and_, or_, func
from app.controllers import (
create_pagination,
register_book_verify_route,
)
from app.controllers.tags import (
@ -17,6 +16,7 @@ from app.controllers.create_access_groups import (
create_moderator_group,
)
from app.controllers.require_permission import require_permission
from app.controllers.sorting import sort_by
from app import models as m, db, forms as f
from app.logger import log
from .bp import bp
@ -26,9 +26,21 @@ from .bp import bp
def my_library():
if current_user.is_authenticated:
log(log.INFO, "Create query for my_library page for books")
sort = request.args.get("sort")
books: m.Book = (
db.session.query(m.Book)
db.session.query(
m.Book,
m.Book.created_at.label("created_at"),
func.count(m.Interpretation.id).label("interpretations_count"),
func.count(m.BookStar.id).label("stars_count"),
)
.join(m.BookStar, m.BookStar.book_id == m.Book.id, full=True)
.join(m.BookVersion, m.BookVersion.book_id == m.Book.id)
.join(m.Section, m.BookVersion.id == m.Section.version_id, full=True)
.join(
m.Interpretation, m.Interpretation.section_id == m.Section.id, full=True
)
.join(m.BookContributor, m.BookContributor.book_id == m.Book.id, full=True)
.filter(
or_(
@ -36,18 +48,21 @@ def my_library():
m.BookContributor.user_id == current_user.id,
),
m.Book.is_deleted == False, # noqa: E712
m.BookStar.is_deleted == False, # noqa: E712
m.BookVersion.is_deleted == False, # noqa: E712
m.Section.is_deleted == False, # noqa: E712
m.Interpretation.is_deleted == False, # noqa: E712
)
.group_by(m.Book.id)
)
log(log.INFO, "Create pagination for books")
pagination, books = sort_by(books, sort)
pagination = create_pagination(total=books.count())
log(log.INFO, "Returns data for front end")
return render_template(
"book/my_library.html",
books=books.paginate(page=pagination.page, per_page=pagination.per_page),
books=books,
page=pagination,
)
log(log.INFO, "Returns data for front end is user is anonym")
@ -168,30 +183,40 @@ def statistic_view(book_id: int):
def favorite_books():
if current_user.is_authenticated:
log(log.INFO, "Creating query for books")
sort = request.args.get("sort")
books = (
db.session.query(
m.Book,
m.Book.created_at.label("created_at"),
func.count(m.Interpretation.id).label("interpretations_count"),
func.count(m.BookStar.id).label("stars_count"),
)
.join(m.BookStar, m.BookStar.book_id == m.Book.id, full=True)
.join(m.BookVersion, m.BookVersion.book_id == m.Book.id)
.join(m.Section, m.BookVersion.id == m.Section.version_id, full=True)
.join(
m.Interpretation, m.Interpretation.section_id == m.Section.id, full=True
)
.filter(
and_(
m.Book.id == m.BookStar.book_id,
m.BookStar.user_id == current_user.id,
m.Book.is_deleted.is_(False),
)
m.Book.id == m.BookStar.book_id,
m.BookStar.user_id == current_user.id,
m.Book.is_deleted == False, # noqa: E712
m.BookStar.is_deleted == False, # noqa: E712
m.BookVersion.is_deleted == False, # noqa: E712
m.Section.is_deleted == False, # noqa: E712
m.Interpretation.is_deleted == False, # noqa: E712
)
.order_by(m.Book.created_at.desc())
.group_by(m.Book.id)
)
books = books.filter_by(is_deleted=False)
log(log.INFO, "Creating pagination for books")
pagination, books = sort_by(books, sort)
pagination = create_pagination(total=books.count())
log(log.INFO, "Returns data for front end")
return render_template(
"book/favorite_books.html",
books=books.paginate(page=pagination.page, per_page=pagination.per_page),
books=books,
page=pagination,
)
return render_template("book/favorite_books.html", books=[])
@ -201,9 +226,15 @@ def favorite_books():
def my_contributions():
if current_user.is_authenticated:
log(log.INFO, "Creating query for interpretations")
sort = request.args.get("sort")
interpretations = (
db.session.query(m.Interpretation)
db.session.query(
m.Interpretation,
m.Interpretation.score.label("score"),
m.Interpretation.created_at.label("created_at"),
func.count(m.Comment.interpretation_id).label("comments_count"),
)
.join(
m.Comment, m.Comment.interpretation_id == m.Interpretation.id, full=True
)
@ -230,18 +261,15 @@ def my_contributions():
m.Interpretation.is_deleted == False, # noqa: E712
)
.group_by(m.Interpretation.id)
.order_by(m.Interpretation.created_at.desc())
)
log(log.INFO, "Creating pagination for interpretations")
pagination = create_pagination(total=interpretations.count())
pagination, interpretations = sort_by(interpretations, sort)
log(log.INFO, "Returns data for front end")
return render_template(
"book/my_contributions.html",
interpretations=interpretations.paginate(
page=pagination.page, per_page=pagination.per_page
),
interpretations=interpretations,
page=pagination,
)
return render_template("book/my_contributions.html", interpretations=[])

View File

@ -3,10 +3,10 @@ from flask import (
render_template,
request,
)
from sqlalchemy import and_, func, text
from sqlalchemy import and_, func
from app import models as m, db
from app.logger import log
from app.controllers import create_pagination
from app.controllers.sorting import sort_by
bp = Blueprint("home", __name__, url_prefix="/home")
@ -18,48 +18,25 @@ def get_all():
interpretations = (
db.session.query(
m.Interpretation,
m.Interpretation.score.label("score"),
m.Interpretation.created_at.label("created_at"),
func.count(m.Comment.interpretation_id).label("comments_count"),
)
.join(m.Comment, isouter=True)
.filter(
.join(
m.Comment,
and_(
m.Section.id == m.Interpretation.section_id,
m.Collection.id == m.Section.collection_id,
m.BookVersion.id == m.Section.version_id,
m.Book.id == m.BookVersion.book_id,
m.Book.is_deleted == False, # noqa: E712
m.BookVersion.is_deleted == False, # noqa: E712
m.Interpretation.is_deleted == False, # noqa: E712
m.Section.is_deleted == False, # noqa: E712
m.Collection.is_deleted == False, # noqa: E712
)
m.Comment.interpretation_id == m.Interpretation.id,
m.Comment.is_deleted == False, # noqa: E712
),
isouter=True,
)
.filter(
m.Interpretation.is_deleted == False, # noqa: E712
)
.group_by(m.Interpretation.id)
)
match sort:
case "upvoted":
interpretations = interpretations.order_by(m.Interpretation.score.desc())
case "recent":
interpretations = interpretations.order_by(
m.Interpretation.created_at.desc()
)
case "commented":
interpretations = interpretations.order_by(text("comments_count DESC"))
case _:
interpretations = interpretations.order_by(
m.Interpretation.created_at.desc()
)
pagination, interpretations = sort_by(interpretations, sort)
log(log.INFO, "Creating pagination for interpretations")
pagination = create_pagination(total=interpretations.count())
log(log.INFO, "Returns data for front end")
log(log.INFO, "Returning data to front end")
interpretations = interpretations.paginate(
page=pagination.page, per_page=pagination.per_page
)
interpretations.items = [item[0] for item in interpretations.items]
return render_template(
"home/index.html",
interpretations=interpretations,
@ -70,15 +47,32 @@ def get_all():
@bp.route("/explore_books", methods=["GET"])
def explore_books():
log(log.INFO, "Create query for home page for books")
sort = request.args.get("sort")
books: m.Book = m.Book.query.filter_by(is_deleted=False).order_by(m.Book.id)
books: m.Book = (
db.session.query(
m.Book,
m.Book.created_at.label("created_at"),
func.count(m.Interpretation.id).label("interpretations_count"),
func.count(m.BookStar.id).label("stars_count"),
)
.join(m.BookStar, m.BookStar.book_id == m.Book.id, full=True)
.join(m.BookVersion, m.BookVersion.book_id == m.Book.id)
.join(m.Section, m.BookVersion.id == m.Section.version_id, full=True)
.join(m.Interpretation, m.Interpretation.section_id == m.Section.id, full=True)
.filter(
m.Book.is_deleted == False, # noqa: E712
m.BookStar.is_deleted == False, # noqa: E712
m.BookVersion.is_deleted == False, # noqa: E712
m.Section.is_deleted == False, # noqa: E712
m.Interpretation.is_deleted == False, # noqa: E712
)
.group_by(m.Book.id)
)
log(log.INFO, "Creating pagination for books")
pagination = create_pagination(total=books.count())
log(log.INFO, "Returns data for front end")
pagination, books = sort_by(books, sort)
return render_template(
"home/explore_books.html",
books=books.paginate(page=pagination.page, per_page=pagination.per_page),
books=books,
page=pagination,
)

View File

@ -55,7 +55,8 @@ def vote_interpretation(interpretation_id: int):
interpretation,
)
db.session.commit()
# TODO:Add notification if we deal with batching tem to "12 users voted your..."
interpretation.score = interpretation.vote_count
interpretation.save()
# notifications
if current_user.id != interpretation.user_id:
interpretation_notification(