Merge branch 'develop' into svyat/feat/subcollections_crud

This commit is contained in:
SvyatoslavArtymovych 2023-04-28 10:10:26 +03:00
commit ef428b16e2
21 changed files with 9524 additions and 6224 deletions

View File

@ -4,5 +4,5 @@ from wtforms.validators import DataRequired, Length
class CreateBookForm(FlaskForm): class CreateBookForm(FlaskForm):
label = StringField("Label", [DataRequired(), Length(6, 1024)]) label = StringField("Label", [DataRequired(), Length(6, 256)])
submit = SubmitField("Add new book") submit = SubmitField("Add new book")

View File

@ -4,14 +4,14 @@ from wtforms.validators import DataRequired, Length
class CreateCollectionForm(FlaskForm): class CreateCollectionForm(FlaskForm):
label = StringField("Label", [DataRequired(), Length(6, 1024)]) label = StringField("Label", [DataRequired(), Length(6, 256)])
about = StringField("About") about = StringField("About")
submit = SubmitField("Create") submit = SubmitField("Create")
class EditCollectionForm(FlaskForm): class EditCollectionForm(FlaskForm):
label = StringField("Label", [Length(6, 1024)]) label = StringField("Label", [Length(6, 256)])
about = StringField("About") about = StringField("About")
submit = SubmitField("Edit") submit = SubmitField("Edit")

View File

@ -5,7 +5,7 @@ from app.models.utils import BaseModel
class Book(BaseModel): class Book(BaseModel):
__tablename__ = "books" __tablename__ = "books"
label = db.Column(db.String(1024), unique=False, nullable=False) label = db.Column(db.String(256), unique=False, nullable=False)
about = db.Column(db.Text, unique=False, nullable=True) about = db.Column(db.Text, unique=False, nullable=True)
# Foreign keys # Foreign keys

View File

@ -9,7 +9,7 @@ class BookVersion(BaseModel):
# need to redeclare id to use it in the derivative relationship # need to redeclare id to use it in the derivative relationship
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
semver = db.Column(db.String(1024), unique=False, nullable=False) semver = db.Column(db.String(16), unique=False, nullable=False)
exported = db.Column(db.Boolean, default=False) exported = db.Column(db.Boolean, default=False)
updated_at = db.Column(db.DateTime, default=datetime.now) updated_at = db.Column(db.DateTime, default=datetime.now)

View File

@ -5,20 +5,19 @@ from app.models.utils import BaseModel
class Collection(BaseModel): class Collection(BaseModel):
__tablename__ = "collections" __tablename__ = "collections"
# need to redeclare id to use it in the parrent relationship # need to redeclare id to use it in the parent relationship
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
label = db.Column(db.String(1024), unique=False, nullable=False) label = db.Column(db.String(256), unique=False, nullable=False)
about = db.Column(db.Text, unique=False, nullable=True) about = db.Column(db.Text, unique=False, nullable=True)
is_root = db.Column(db.Boolean, default=False) is_root = db.Column(db.Boolean, default=False)
is_leaf = db.Column(db.Boolean, default=False) is_leaf = db.Column(db.Boolean, default=False)
# Foreign keys # Foreign keys
version_id = db.Column(db.ForeignKey("book_versions.id")) version_id = db.Column(db.ForeignKey("book_versions.id"))
parrent_id = db.Column(db.ForeignKey("collections.id")) parent_id = db.Column(db.ForeignKey("collections.id"))
# Relationships # Relationships
version = db.relationship("BookVersion") version = db.relationship("BookVersion")
parrent = db.relationship("Collection", remote_side=[id])
children = db.relationship( children = db.relationship(
"Collection", backref=db.backref("parent", remote_side=[id]), viewonly=True "Collection", backref=db.backref("parent", remote_side=[id]), viewonly=True
) )

View File

@ -5,20 +5,19 @@ from app.models.utils import BaseModel
class Comment(BaseModel): class Comment(BaseModel):
__tablename__ = "comments" __tablename__ = "comments"
# need to redeclare id to use it in the parrent relationship # need to redeclare id to use it in the parent relationship
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.Text, unique=False, nullable=False) text = db.Column(db.Text, unique=False, nullable=False)
marked = db.Column(db.Boolean, default=False) marked = db.Column(db.Boolean, default=False)
included_with_interpreation = db.Column(db.Boolean, default=False) included_with_interpretation = db.Column(db.Boolean, default=False)
# Foreign keys # Foreign keys
user_id = db.Column(db.ForeignKey("users.id")) user_id = db.Column(db.ForeignKey("users.id"))
parrent_id = db.Column(db.ForeignKey("comments.id")) parent_id = db.Column(db.ForeignKey("comments.id"))
interpretation_id = db.Column(db.ForeignKey("interpretations.id")) interpretation_id = db.Column(db.ForeignKey("interpretations.id"))
# Relationships # Relationships
user = db.relationship("User") user = db.relationship("User")
parrent = db.relationship("Comment", remote_side=[id])
children = db.relationship( children = db.relationship(
"Comment", backref=db.backref("parent", remote_side=[id]), viewonly=True "Comment", backref=db.backref("parent", remote_side=[id]), viewonly=True
) )

View File

@ -8,11 +8,11 @@ class CommentVote(BaseModel):
# Foreign keys # Foreign keys
user_id = db.Column(db.Integer, db.ForeignKey("users.id")) user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
comment_id = db.Column(db.Integer, db.ForeignKey("comments.id")) comment_id = db.Column(db.Integer, db.ForeignKey("comments.id"))
possitive = db.Column(db.Boolean, default=True) positive = db.Column(db.Boolean, default=True)
# Relationships # Relationships
user = db.relationship("User", viewonly=True) user = db.relationship("User", viewonly=True)
comment = db.relationship("Comment", viewonly=True) comment = db.relationship("Comment", viewonly=True)
def __repr__(self): def __repr__(self):
return f"<{self.user} to {self.comment} Positive:{self.possitive}>" return f"<{self.user} to {self.comment} Positive:{self.positive}>"

View File

@ -5,7 +5,7 @@ from app.models.utils import BaseModel
class Interpretation(BaseModel): class Interpretation(BaseModel):
__tablename__ = "interpretations" __tablename__ = "interpretations"
label = db.Column(db.String(1024), unique=False, nullable=False) label = db.Column(db.String(256), unique=False, nullable=False)
text = db.Column(db.Text, unique=False, nullable=False) text = db.Column(db.Text, unique=False, nullable=False)
marked = db.Column(db.Boolean, default=False) marked = db.Column(db.Boolean, default=False)

View File

@ -8,11 +8,11 @@ class InterpretationVote(BaseModel):
# Foreign keys # Foreign keys
user_id = db.Column(db.Integer, db.ForeignKey("users.id")) user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
interpretation_id = db.Column(db.Integer, db.ForeignKey("interpretations.id")) interpretation_id = db.Column(db.Integer, db.ForeignKey("interpretations.id"))
possitive = db.Column(db.Boolean, default=True) positive = db.Column(db.Boolean, default=True)
# Relationships # Relationships
user = db.relationship("User", viewonly=True) user = db.relationship("User", viewonly=True)
interpretation = db.relationship("Interpretation", viewonly=True) interpretation = db.relationship("Interpretation", viewonly=True)
def __repr__(self): def __repr__(self):
return f"<{self.user} to {self.interpretation} Positive:{self.possitive}>" return f"<{self.user} to {self.interpretation} Positive:{self.positive}>"

View File

@ -5,7 +5,7 @@ from app.models.utils import BaseModel
class Section(BaseModel): class Section(BaseModel):
__tablename__ = "sections" __tablename__ = "sections"
label = db.Column(db.String(1024), unique=False, nullable=False) label = db.Column(db.String(256), unique=False, nullable=False)
about = db.Column(db.Text, unique=False, nullable=True) about = db.Column(db.Text, unique=False, nullable=True)
# Foreign keys # Foreign keys
@ -20,5 +20,17 @@ class Section(BaseModel):
version = db.relationship("BookVersion", viewonly=True) version = db.relationship("BookVersion", viewonly=True)
interpretations = db.relationship("Interpretation", viewonly=True) interpretations = db.relationship("Interpretation", viewonly=True)
@property
def path(self):
parent = self.collection
grand_parent = parent.parent
path = f"{self.version.book.label} / "
if grand_parent.is_root:
path += f"{parent.label} / "
else:
path += f"{grand_parent.label} / {parent.label} / "
path += self.label
return path
def __repr__(self): def __repr__(self):
return f"<{self.id}: {self.label}>" return f"<{self.id}: {self.label}>"

File diff suppressed because one or more lines are too long

View File

@ -84,7 +84,7 @@
<!-- prettier-ignore --> <!-- prettier-ignore -->
<script src="{{ url_for('static', filename='js/flowbite.min.js') }}" defer></script> <script src="{{ url_for('static', filename='js/flowbite.min.js') }}" defer></script>
<div class="p-0 mt-16 h-full overflow-x-scroll md:ml-64"> <div class="p-0 mt-16 h-full md:ml-64">
<!-- Main Content --> <!-- Main Content -->
{% block content %}{% endblock %} {% block content %}{% endblock %}
</div> </div>

View File

@ -56,14 +56,12 @@
<div class="flex flex-col pb-3 p-3 w-full"> <div class="flex flex-col pb-3 p-3 w-full">
<!-- prettier-ignore --> <!-- prettier-ignore -->
<dt class="flex w-full mb-1 text-gray-500 md:text-lg dark:text-gray-400 flex-col"> <dt class="flex w-full mb-1 text-gray-500 md:text-lg dark:text-gray-400 flex-col">
<p>{{ collection.label }}</p> <p>{{ collection.label }}</p>
<div class="flex ml-auto align-center justify-center space-x-3"> <div class="flex ml-auto align-center justify-center space-x-3">
<span class="space-x-0.5 flex items-center"> <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> <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>
<p>55</p> <p>55</p>
</span> </span>
<span class="space-x-0.5 flex items-center"> <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="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /></svg> <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="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /></svg>
<p>55</p> <p>55</p>

View File

@ -15,25 +15,63 @@
{% for book in books %} {% for book in books %}
<!-- prettier-ignore --> <!-- prettier-ignore -->
<dl class="bg-white dark:bg-gray-900 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"> <dl
<a class="flex flex-col pb-2" href="{{url_for('book.collection_view',book_id=book.id)}}"> class=" bg-white dark:bg-gray-900 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">
<dt class="mb-2"> {{book.owner.username}}/{{book.label}} </dt> <a
<dd class="flex flex-col md:flex-row text-lg font-semibold text-gray-500 md:text-lg dark:text-gray-400"> class="flex flex-col pb-2"
href="{{url_for('book.collection_view',book_id=book.id)}}">
<dt class="mb-2">{{book.owner.username}}/{{book.label}}</dt>
<dd
class="flex flex-col md:flex-row text-lg font-semibold text-gray-500 md:text-lg dark:text-gray-400">
{% if book.versions %} {% if book.versions %}
<p> Last updated on {{book.versions[-1].updated_at.strftime('%B %d, %Y')}}</p> <p>
Last updated on {{book.versions[-1].updated_at.strftime('%B %d, %Y')}}
</p>
{% endif %} {% endif %}
<div class="flex ml-auto align-center justify-center space-x-3"> <div class="flex ml-auto align-center justify-center space-x-3">
<span class="space-x-0.5 flex items-center"> <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="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> <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="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>
<p>{{ book.stars|length }}</p> <p>{{ book.stars|length }}</p>
</span> </span>
<span class="space-x-0.5 flex items-center"> <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> <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>
<p>55</p> <p>55</p>
</span> </span>
<span class="space-x-0.5 flex items-center"> <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="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /> </svg> <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="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
</svg>
<p>55</p> <p>55</p>
</span> </span>
</div> </div>

View File

@ -1,18 +1,75 @@
<!-- prettier-ignore --> <!-- prettier-ignore -->
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
<div class="mt-4 border-b border-gray-200 dark:border-gray-700 mr-64"> <div class="border-b border-gray-200 dark:border-gray-700 mr-64">
<!-- prettier-ignore --> <!-- prettier-ignore -->
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center text-gray-500 dark:text-gray-400"> <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"> <li class="mr-2" role="presentation">
<a href="" class="inline-flex p-4 text-blue-600 border-b-2 border-blue-600 rounded-t-lg active dark:text-blue-500 dark:border-blue-500 group" aria-current="page"> <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 mr-3"> <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> Last Sections </a> <!-- prettier-ignore -->
<button class="inline-flex p-4 border-b-2 rounded-t-lg" id="last-sections-tab" data-tabs-target="#last-sections" type="button" role="tab" aria-controls="last-sections" aria-selected="false"> <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 mr-3"> <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>
Last Sections
</button>
</li> </li>
<li class="mr-2"> <li class="mr-2" role="presentation">
<a href="#" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group" ><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 mr-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg> Explore Books </a> <!-- prettier-ignore -->
<button class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="explore-books-tab" data-tabs-target="#explore-books" type="button" role="tab" aria-controls="explore-books" aria-selected="false"> <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 mr-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg>
Explore Books
</button>
</li> </li>
<li class="mr-2"> <li class="mr-2" role="presentation">
<a href="#" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group"><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 mr-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m5.231 13.481L15 17.25m-4.5-15H5.625c-.621 0-1.125.504-1.125 1.125v16.5c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9zm3.75 11.625a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" /> </svg> All sections </a> <!-- prettier-ignore -->
<button class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="all-sections-tab" data-tabs-target="#all-sections" type="button" role="tab" aria-controls="all-sections" aria-selected="false"> <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 mr-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m5.231 13.481L15 17.25m-4.5-15H5.625c-.621 0-1.125.504-1.125 1.125v16.5c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9zm3.75 11.625a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" /> </svg>
All Sections
</button>
</li> </li>
</ul> </ul>
</div> </div>
<div id="myTabContent" class="mr-64">
<!-- prettier-ignore -->
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="last-sections" role="tabpanel" aria-labelledby="last-sections-tab">
<p class="text-sm text-gray-500 dark:text-gray-400">Last sections</p>
</div>
<!-- prettier-ignore -->
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="explore-books" role="tabpanel" aria-labelledby="explore-books-tab">
{% for book in books %}
<!-- prettier-ignore -->
<dl
class=" bg-white dark:bg-gray-900 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">
<a
class="flex flex-col pb-2"
href="{{url_for('book.collection_view',book_id=book.id)}}">
<dt class="mb-2">{{book.owner.username}}/{{book.label}}</dt>
<dd class="flex flex-col md:flex-row text-lg font-semibold text-gray-500 md:text-lg dark:text-gray-400">
{% if book.versions %}
<p> Last updated on {{book.versions[-1].updated_at.strftime('%B %d, %Y')}} </p>
{% endif %}
<div class="flex ml-auto align-center justify-center space-x-3">
<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="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>
<p>{{ book.stars|length }}</p>
</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>
<p>55</p>
</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="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /> </svg>
<p>55</p>
</span>
</div>
</dd>
</a>
</dl>
{% endfor %}
<a type="button" href="{{ url_for('book.get_all') }}" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"> Explore all books... <svg aria-hidden="true" class="w-5 h-5 ml-2 -mr-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg> </a>
</div>
<!-- prettier-ignore -->
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="all-sections" role="tabpanel" aria-labelledby="all-sections-tab">
{% for section in sections %}
<!-- prettier-ignore -->
<h1 class="text-l font-extrabold dark:text-white my-2">{{section.path}}</h1>
{% endfor %}
<a type="button" href="#" class="mt-4 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"> Explore all sections... <svg aria-hidden="true" class="w-5 h-5 ml-2 -mr-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg> </a>
</div>
</div>
{% endblock %} {% endblock %}

View File

@ -2,14 +2,25 @@ from flask import (
Blueprint, Blueprint,
render_template, render_template,
) )
from flask_login import current_user
from app import models as m
bp = Blueprint("home", __name__, url_prefix="/home") bp = Blueprint("home", __name__, url_prefix="/home")
@bp.route("/", methods=["GET"]) @bp.route("/", methods=["GET"])
def get_all(): def get_all():
books: m.Book = m.Book.query.order_by(m.Book.id).limit(5)
sections: m.Section = m.Section.query.order_by(m.Section.id).limit(5)
if current_user.is_authenticated:
last_user_sections: m.Section = m.Section.query.order_by(
m.Section.created_at
).limit(5)
return render_template( return render_template(
"home/index.html", "home/index.html",
books=books,
sections=sections,
last_user_sections=last_user_sections,
) )

View File

@ -1,200 +0,0 @@
"""init
Revision ID: e96f96cb7d02
Revises:
Create Date: 2023-04-26 11:40:49.008918
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'e96f96cb7d02'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('tags',
sa.Column('name', sa.String(length=32), nullable=False),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_table('users',
sa.Column('username', sa.String(length=60), nullable=False),
sa.Column('password_hash', sa.String(length=255), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('username')
)
op.create_table('books',
sa.Column('label', sa.String(length=1024), nullable=False),
sa.Column('about', sa.Text(), nullable=True),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('book_contributors',
sa.Column('role', sa.Enum('UNKNOWN', 'MODERATOR', 'EDITOR', name='roles'), nullable=True),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('book_id', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['book_id'], ['books.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('book_versions',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('semver', sa.String(length=1024), nullable=False),
sa.Column('exported', sa.Boolean(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('derivative_id', sa.Integer(), nullable=True),
sa.Column('book_id', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['book_id'], ['books.id'], ),
sa.ForeignKeyConstraint(['derivative_id'], ['book_versions.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('books_stars',
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('book_id', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['book_id'], ['books.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('collections',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('label', sa.String(length=1024), nullable=False),
sa.Column('about', sa.Text(), nullable=False),
sa.Column('is_root', sa.Boolean(), nullable=True),
sa.Column('is_leaf', sa.Boolean(), nullable=True),
sa.Column('version_id', sa.Integer(), nullable=True),
sa.Column('parrent_id', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['parrent_id'], ['collections.id'], ),
sa.ForeignKeyConstraint(['version_id'], ['book_versions.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('sections',
sa.Column('label', sa.String(length=1024), nullable=False),
sa.Column('about', sa.Text(), nullable=True),
sa.Column('collection_id', sa.Integer(), nullable=True),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('version_id', sa.Integer(), nullable=True),
sa.Column('selected_interpretation_id', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['collection_id'], ['collections.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.ForeignKeyConstraint(['version_id'], ['book_versions.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('interpretations',
sa.Column('label', sa.String(length=1024), nullable=False),
sa.Column('text', sa.Text(), nullable=False),
sa.Column('marked', sa.Boolean(), nullable=True),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('section_id', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['section_id'], ['sections.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('comments',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('text', sa.Text(), nullable=False),
sa.Column('marked', sa.Boolean(), nullable=True),
sa.Column('included_with_interpreation', sa.Boolean(), nullable=True),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('parrent_id', sa.Integer(), nullable=True),
sa.Column('interpretation_id', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['interpretation_id'], ['interpretations.id'], ),
sa.ForeignKeyConstraint(['parrent_id'], ['comments.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('interpretation_tags',
sa.Column('tag_id', sa.Integer(), nullable=True),
sa.Column('interpretation_id', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['interpretation_id'], ['interpretations.id'], ),
sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('interpretation_votes',
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('interpretation_id', sa.Integer(), nullable=True),
sa.Column('possitive', sa.Boolean(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['interpretation_id'], ['interpretations.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('comment_tags',
sa.Column('tag_id', sa.Integer(), nullable=True),
sa.Column('comment_id', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['comment_id'], ['comments.id'], ),
sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('comment_votes',
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('comment_id', sa.Integer(), nullable=True),
sa.Column('possitive', sa.Boolean(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['comment_id'], ['comments.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('comment_votes')
op.drop_table('comment_tags')
op.drop_table('interpretation_votes')
op.drop_table('interpretation_tags')
op.drop_table('comments')
op.drop_table('interpretations')
op.drop_table('sections')
op.drop_table('collections')
op.drop_table('books_stars')
op.drop_table('book_versions')
op.drop_table('book_contributors')
op.drop_table('books')
op.drop_table('users')
op.drop_table('tags')
# ### end Alembic commands ###

View File

@ -0,0 +1,293 @@
"""empty message
Revision ID: febf8dfa148f
Revises:
Create Date: 2023-04-27 16:07:14.727110
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "febf8dfa148f"
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"tags",
sa.Column("name", sa.String(length=32), nullable=False),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table(
"users",
sa.Column("username", sa.String(length=60), nullable=False),
sa.Column("password_hash", sa.String(length=255), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("username"),
)
op.create_table(
"books",
sa.Column("label", sa.String(length=256), nullable=False),
sa.Column("about", sa.Text(), nullable=True),
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"book_contributors",
sa.Column(
"role",
sa.Enum("UNKNOWN", "MODERATOR", "EDITOR", name="roles"),
nullable=True,
),
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("book_id", sa.Integer(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["book_id"],
["books.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"book_versions",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("semver", sa.String(length=16), nullable=False),
sa.Column("exported", sa.Boolean(), nullable=True),
sa.Column("updated_at", sa.DateTime(), nullable=True),
sa.Column("derivative_id", sa.Integer(), nullable=True),
sa.Column("book_id", sa.Integer(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["book_id"],
["books.id"],
),
sa.ForeignKeyConstraint(
["derivative_id"],
["book_versions.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"books_stars",
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("book_id", sa.Integer(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["book_id"],
["books.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"collections",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("label", sa.String(length=256), nullable=False),
sa.Column("about", sa.Text(), nullable=True),
sa.Column("is_root", sa.Boolean(), nullable=True),
sa.Column("is_leaf", sa.Boolean(), nullable=True),
sa.Column("version_id", sa.Integer(), nullable=True),
sa.Column("parent_id", sa.Integer(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["parent_id"],
["collections.id"],
),
sa.ForeignKeyConstraint(
["version_id"],
["book_versions.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"sections",
sa.Column("label", sa.String(length=256), nullable=False),
sa.Column("about", sa.Text(), nullable=True),
sa.Column("collection_id", sa.Integer(), nullable=True),
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("version_id", sa.Integer(), nullable=True),
sa.Column("selected_interpretation_id", sa.Integer(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["collection_id"],
["collections.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.ForeignKeyConstraint(
["version_id"],
["book_versions.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"interpretations",
sa.Column("label", sa.String(length=256), nullable=False),
sa.Column("text", sa.Text(), nullable=False),
sa.Column("marked", sa.Boolean(), nullable=True),
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("section_id", sa.Integer(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["section_id"],
["sections.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"comments",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("text", sa.Text(), nullable=False),
sa.Column("marked", sa.Boolean(), nullable=True),
sa.Column("included_with_interpretation", sa.Boolean(), nullable=True),
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("parent_id", sa.Integer(), nullable=True),
sa.Column("interpretation_id", sa.Integer(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["interpretation_id"],
["interpretations.id"],
),
sa.ForeignKeyConstraint(
["parent_id"],
["comments.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"interpretation_tags",
sa.Column("tag_id", sa.Integer(), nullable=True),
sa.Column("interpretation_id", sa.Integer(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["interpretation_id"],
["interpretations.id"],
),
sa.ForeignKeyConstraint(
["tag_id"],
["tags.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"interpretation_votes",
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("interpretation_id", sa.Integer(), nullable=True),
sa.Column("positive", sa.Boolean(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["interpretation_id"],
["interpretations.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"comment_tags",
sa.Column("tag_id", sa.Integer(), nullable=True),
sa.Column("comment_id", sa.Integer(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["comment_id"],
["comments.id"],
),
sa.ForeignKeyConstraint(
["tag_id"],
["tags.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"comment_votes",
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("comment_id", sa.Integer(), nullable=True),
sa.Column("positive", sa.Boolean(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("is_deleted", sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(
["comment_id"],
["comments.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("comment_votes")
op.drop_table("comment_tags")
op.drop_table("interpretation_votes")
op.drop_table("interpretation_tags")
op.drop_table("comments")
op.drop_table("interpretations")
op.drop_table("sections")
op.drop_table("collections")
op.drop_table("books_stars")
op.drop_table("book_versions")
op.drop_table("book_contributors")
op.drop_table("books")
op.drop_table("users")
op.drop_table("tags")
# ### end Alembic commands ###

View File

@ -47,7 +47,7 @@ def create_dummy_data():
label="Dummy Collection 1 Label", label="Dummy Collection 1 Label",
about="Dummy Collection 1 About", about="Dummy Collection 1 About",
version_id=unexported_version.id, version_id=unexported_version.id,
parrent_id=rool_collection.id, parent_id=rool_collection.id,
is_leaf=True, is_leaf=True,
).save() ).save()
@ -55,7 +55,7 @@ def create_dummy_data():
label="Dummy Collection 2 Label", label="Dummy Collection 2 Label",
about="Dummy Collection 2 About", about="Dummy Collection 2 About",
version_id=unexported_version.id, version_id=unexported_version.id,
parrent_id=rool_collection.id, parent_id=rool_collection.id,
).save() ).save()
subcollection_2_1 = m.Collection( subcollection_2_1 = m.Collection(
@ -63,7 +63,7 @@ def create_dummy_data():
about="Dummy SubCollection 2.1 About", about="Dummy SubCollection 2.1 About",
is_leaf=True, is_leaf=True,
version_id=unexported_version.id, version_id=unexported_version.id,
parrent_id=collection_2.id, parent_id=collection_2.id,
).save() ).save()
# sections # sections
@ -150,7 +150,7 @@ def create_dummy_data():
# - comment 2 # - comment 2
# - comment 3 # - comment 3
# - comment 3.1 (marked) # - comment 3.1 (marked)
# - comment 3.2 (included_with_interpreation) # - comment 3.2 (included_with_interpretation)
# - comment 3.3 # - comment 3.3
comment_1 = m.Comment( comment_1 = m.Comment(
@ -162,14 +162,14 @@ def create_dummy_data():
m.Comment( m.Comment(
text="Dummy Comment 1.1 Text", text="Dummy Comment 1.1 Text",
user_id=user_3.id, user_id=user_3.id,
parrent_id=comment_1.id, parent_id=comment_1.id,
interpretation_id=interpretation_2.id, interpretation_id=interpretation_2.id,
).save() ).save()
m.Comment( m.Comment(
text="Dummy Comment 1.2 Text", text="Dummy Comment 1.2 Text",
user_id=user_2.id, user_id=user_2.id,
parrent_id=comment_1.id, parent_id=comment_1.id,
marked=True, marked=True,
interpretation_id=interpretation_2.id, interpretation_id=interpretation_2.id,
).save() ).save()
@ -190,52 +190,52 @@ def create_dummy_data():
text="Dummy Comment 3.1 Text", text="Dummy Comment 3.1 Text",
user_id=user.id, user_id=user.id,
marked=True, marked=True,
parrent_id=comment_3.id, parent_id=comment_3.id,
interpretation_id=interpretation_2.id, interpretation_id=interpretation_2.id,
).save() ).save()
comment_3_2 = m.Comment( comment_3_2 = m.Comment(
text="Dummy Comment 3.2 Text", text="Dummy Comment 3.2 Text",
user_id=user.id, user_id=user.id,
included_with_interpreation=True, included_with_interpretation=True,
parrent_id=comment_3.id, parent_id=comment_3.id,
interpretation_id=interpretation_2.id, interpretation_id=interpretation_2.id,
).save() ).save()
comment_3_3 = m.Comment( comment_3_3 = m.Comment(
text="Dummy Comment 3.3 Text", text="Dummy Comment 3.3 Text",
user_id=user.id, user_id=user.id,
parrent_id=comment_3.id, parent_id=comment_3.id,
interpretation_id=interpretation_2.id, interpretation_id=interpretation_2.id,
).save() ).save()
# - comment 3.1 (2 possitive, 2 negative) # - comment 3.1 (2 positive, 2 negative)
# - comment 3.2 (1 negative) # - comment 3.2 (1 negative)
# - comment 3.3 (1 possitive) # - comment 3.3 (1 positive)
m.CommentVote(comment_id=comment_3_1.id, user_id=user.id, possitive=True).save() m.CommentVote(comment_id=comment_3_1.id, user_id=user.id, positive=True).save()
m.CommentVote(comment_id=comment_3_1.id, user_id=user_2.id, possitive=True).save() m.CommentVote(comment_id=comment_3_1.id, user_id=user_2.id, positive=True).save()
m.CommentVote(comment_id=comment_3_1.id, user_id=user_3.id, possitive=False).save() m.CommentVote(comment_id=comment_3_1.id, user_id=user_3.id, positive=False).save()
m.CommentVote(comment_id=comment_3_1.id, user_id=user_4.id, possitive=False).save() m.CommentVote(comment_id=comment_3_1.id, user_id=user_4.id, positive=False).save()
m.CommentVote(comment_id=comment_3_2.id, user_id=user_2.id, possitive=False).save() m.CommentVote(comment_id=comment_3_2.id, user_id=user_2.id, positive=False).save()
m.CommentVote(comment_id=comment_3_3.id, user_id=user_3.id, possitive=True).save() m.CommentVote(comment_id=comment_3_3.id, user_id=user_3.id, positive=True).save()
# - interpretation 1 (2 possitive, 1 negative) # - interpretation 1 (2 positive, 1 negative)
# - interpretation 2 (1 negative) # - interpretation 2 (1 negative)
# - interpretation 3 (1 possitive) # - interpretation 3 (1 positive)
m.InterpretationVote( m.InterpretationVote(
interpretation_id=interpretation_1.id, user_id=user.id, possitive=True interpretation_id=interpretation_1.id, user_id=user.id, positive=True
).save() ).save()
m.InterpretationVote( m.InterpretationVote(
interpretation_id=interpretation_1.id, user_id=user_2.id, possitive=True interpretation_id=interpretation_1.id, user_id=user_2.id, positive=True
).save() ).save()
m.InterpretationVote( m.InterpretationVote(
interpretation_id=interpretation_1.id, user_id=user_3.id, possitive=False interpretation_id=interpretation_1.id, user_id=user_3.id, positive=False
).save() ).save()
m.InterpretationVote( m.InterpretationVote(
interpretation_id=interpretation_2.id, user_id=user_2.id, possitive=False interpretation_id=interpretation_2.id, user_id=user_2.id, positive=False
).save() ).save()
m.InterpretationVote( m.InterpretationVote(
interpretation_id=interpretation_3.id, user_id=user_3.id, possitive=True interpretation_id=interpretation_3.id, user_id=user_3.id, positive=True
).save() ).save()
# tags # tags

View File

@ -20,14 +20,14 @@ def test_create_book(client: FlaskClient):
) )
assert response.status_code == 200 assert response.status_code == 200
assert b"Label must be between 6 and 1024 characters long." in response.data assert b"Label must be between 6 and 256 characters long." in response.data
book = m.Book.query.filter_by(label=BOOK_NAME).first() book = m.Book.query.filter_by(label=BOOK_NAME).first()
assert not book assert not book
assert not m.Book.query.count() assert not m.Book.query.count()
# label len > 1024 # label len > 256
response: Response = client.post( response: Response = client.post(
"/book/create", "/book/create",
data=dict( data=dict(
@ -37,7 +37,7 @@ def test_create_book(client: FlaskClient):
) )
assert response.status_code == 200 assert response.status_code == 200
assert b"Label must be between 6 and 1024 characters long." in response.data assert b"Label must be between 6 and 256 characters long." in response.data
book = m.Book.query.filter_by(label=BOOK_NAME).first() book = m.Book.query.filter_by(label=BOOK_NAME).first()

View File

@ -190,14 +190,14 @@ def test_dummy_data(runner: FlaskCliRunner):
# - comment 2 # - comment 2
# - comment 3 # - comment 3
# - comment 3.1 (marked) # - comment 3.1 (marked)
# - comment 3.2 (included_with_interpreation) # - comment 3.2 (included_with_interpretation)
# - comment 3.3 # - comment 3.3
comment_1: m.Comment = m.Comment.query.filter_by( comment_1: m.Comment = m.Comment.query.filter_by(
text="Dummy Comment 1 Text" text="Dummy Comment 1 Text"
).first() ).first()
assert not comment_1.parrent assert not comment_1.parent
comment_1_1: m.Comment = m.Comment.query.filter_by( comment_1_1: m.Comment = m.Comment.query.filter_by(
text="Dummy Comment 1.1 Text" text="Dummy Comment 1.1 Text"
@ -209,22 +209,22 @@ def test_dummy_data(runner: FlaskCliRunner):
assert comment_1_1 in comment_1.children assert comment_1_1 in comment_1.children
assert comment_1_1 in comment_1.children assert comment_1_1 in comment_1.children
assert comment_1_2.parrent == comment_1 assert comment_1_2.parent == comment_1
assert comment_1_2.parrent == comment_1 assert comment_1_2.parent == comment_1
assert comment_1_2.marked assert comment_1_2.marked
comment_2: m.Comment = m.Comment.query.filter_by( comment_2: m.Comment = m.Comment.query.filter_by(
text="Dummy Comment 2 Text" text="Dummy Comment 2 Text"
).first() ).first()
assert not comment_2.parrent assert not comment_2.parent
assert not comment_2.children assert not comment_2.children
comment_3: m.Comment = m.Comment.query.filter_by( comment_3: m.Comment = m.Comment.query.filter_by(
text="Dummy Comment 3 Text" text="Dummy Comment 3 Text"
).first() ).first()
assert not comment_3.parrent assert not comment_3.parent
assert comment_3.children assert comment_3.children
comment_3_1: m.Comment = m.Comment.query.filter_by( comment_3_1: m.Comment = m.Comment.query.filter_by(
@ -243,23 +243,23 @@ def test_dummy_data(runner: FlaskCliRunner):
assert comment_3_2 in comment_3.children assert comment_3_2 in comment_3.children
assert comment_3_3 in comment_3.children assert comment_3_3 in comment_3.children
assert comment_3_1.marked assert comment_3_1.marked
assert comment_3_2.included_with_interpreation assert comment_3_2.included_with_interpretation
assert comment_1 in interpretation_2.comments assert comment_1 in interpretation_2.comments
assert comment_2 in interpretation_2.comments assert comment_2 in interpretation_2.comments
assert comment_3 in interpretation_2.comments assert comment_3 in interpretation_2.comments
# - comment 3.1 (2 possitive, 2 negative) # - comment 3.1 (2 positive, 2 negative)
# - comment 3.2 (1 negative) # - comment 3.2 (1 negative)
# - comment 3.3 (1 possitive) # - comment 3.3 (1 positive)
assert len(comment_3_1.votes) == 4 assert len(comment_3_1.votes) == 4
assert len(comment_3_2.votes) == 1 assert len(comment_3_2.votes) == 1
assert len(comment_3_3.votes) == 1 assert len(comment_3_3.votes) == 1
# - interpretation 1 (2 possitive, 1 negative) # - interpretation 1 (2 positive, 1 negative)
# - interpretation 2 (1 negative) # - interpretation 2 (1 negative)
# - interpretation 3 (1 possitive) # - interpretation 3 (1 positive)
assert len(interpretation_1.votes) == 3 assert len(interpretation_1.votes) == 3
assert len(interpretation_2.votes) == 1 assert len(interpretation_2.votes) == 1
assert len(interpretation_3.votes) == 1 assert len(interpretation_3.votes) == 1