From d55ae415fa907cf251b2603c711d2e1514ba2bb9 Mon Sep 17 00:00:00 2001 From: SvyatoslavArtymovych Date: Thu, 4 May 2023 14:18:41 +0300 Subject: [PATCH 1/4] start write tests --- tests/test_book.py | 247 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) diff --git a/tests/test_book.py b/tests/test_book.py index d1b7bbc..306ec0b 100644 --- a/tests/test_book.py +++ b/tests/test_book.py @@ -698,3 +698,250 @@ def test_crud_sections(client: FlaskClient, runner: FlaskCliRunner): assert response.status_code == 200 assert b"Section not found" in response.data + + +def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): + _, user = login(client) + user: m.User + + # add dummmy data + runner.invoke(args=["db-populate"]) + + book: m.Book = db.session.get(m.Book, 1) + book.user_id = user.id + book.save() + + leaf_collection: m.Collection = m.Collection( + label="Test Leaf Collection #1 Label", + version_id=book.last_version.id, + is_leaf=True, + parent_id=book.last_version.root_collection.id, + ).save() + section_in_collection: m.Section = m.Section( + label="Test Section in Collection #1 Label", + about="Test Section in Collection #1 About", + collection_id=leaf_collection.id, + version_id=book.last_version.id, + ).save() + + collection: m.Collection = m.Collection( + label="Test Collection #1 Label", version_id=book.last_version.id + ).save() + sub_collection: m.Collection = m.Collection( + label="Test SubCollection #1 Label", + version_id=book.last_version.id, + parent_id=collection.id, + is_leaf=True, + ).save() + section_in_subcollection: m.Section = m.Section( + label="Test Section in Subcollection #1 Label", + about="Test Section in Subcollection #1 About", + collection_id=sub_collection.id, + version_id=book.last_version.id, + ).save() + + label_1 = "Test Interpretation #1 Label" + response: Response = client.post( + f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_in_subcollection.id}/create_interpretation", + data=dict( + section_id=section_in_subcollection.id, + label=label_1, + text="Test Interpretation #1 Label", + ), + follow_redirects=True, + ) + + assert response.status_code == 200 + interpretation: m.Interpretation = m.Interpretation.query.filter_by( + label=label_1, section_id=section_in_subcollection.id + ).first() + assert interpretation + assert interpretation.collection_id == section_in_subcollection.id + assert interpretation.version_id == book.last_version.id + assert not interpretation.comments + + response: Response = client.post( + f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_in_subcollection.id}/create_interpretation", + data=dict( + section_id=section_in_subcollection.id, + label=label_1, + text="Test Interpretation #1 Label", + ), + follow_redirects=True, + ) + + assert b"Interpretation label must be unique!" in response.data + + response: Response = client.post( + f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/create_interpretation", + data=dict( + section_id=section_in_collection.id, + label=label_1, + text="Test Interpretation #1 Label", + ), + follow_redirects=True, + ) + + assert response.status_code == 200 + interpretation: m.Interpretation = m.Interpretation.query.filter_by( + label=label_1, section_id=section_in_collection.id + ).first() + assert interpretation + assert interpretation.collection_id == section_in_subcollection.id + assert interpretation.version_id == book.last_version.id + assert not interpretation.comments + + response: Response = client.post( + f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/create_interpretation", + data=dict( + section_id=section_in_collection.id, + label=label_1, + text="Test Interpretation #1 Label", + ), + follow_redirects=True, + ) + + assert b"Interpretation label must be unique!" in response.data + + response: Response = client.post( + f"/book/{book.id}/{collection.id}/999/create_section", + data=dict(collection_id=999, label=label_1, about="Test Section #1 About"), + follow_redirects=True, + ) + + assert response.status_code == 200 + assert b"Subcollection not found" in response.data + + response: Response = client.post( + f"/book/{book.id}/{leaf_collection.id}/999/create_interpretation", + data=dict(collection_id=999, label=label_1, about="Test Section #1 About"), + follow_redirects=True, + ) + + assert response.status_code == 200 + assert b"Section not found" in response.data + + response: Response = client.post( + f"/book/{book.id}/{collection.id}/{sub_collection.id}/888/create_interpretation", + data=dict(collection_id=999, label=label_1, about="Test Section #1 About"), + follow_redirects=True, + ) + + assert response.status_code == 200 + assert b"Section not found" in response.data + + # # edit + + # m.Section( + # label="Test", + # about="Test", + # collection_id=leaf_collection.id, + # version_id=book.last_version.id, + # ).save() + + # m.Section( + # label="Test", + # about="Test", + # collection_id=sub_collection.id, + # version_id=book.last_version.id, + # ).save() + + # section: m.Section = m.Section.query.filter_by( + # label=label_1, collection_id=leaf_collection.id + # ).first() + + # response: Response = client.post( + # f"/book/{book.id}/{leaf_collection.id}/{section.id}/edit_section", + # data=dict( + # section_id=section.id, + # label="Test", + # ), + # follow_redirects=True, + # ) + + # assert response.status_code == 200 + # assert b"Section label must be unique!" in response.data + + # new_label = "Test Section #1 Label(edited)" + # new_about = "Test Section #1 About(edited)" + + # response: Response = client.post( + # f"/book/{book.id}/{leaf_collection.id}/{section.id}/edit_section", + # data=dict(section_id=section.id, label=new_label, about=new_about), + # follow_redirects=True, + # ) + # assert response.status_code == 200 + # assert b"Success!" in response.data + + # edited_section: m.Section = m.Section.query.filter_by( + # label=new_label, about=new_about, id=section.id + # ).first() + # assert edited_section + + # # + # section_2: m.Section = m.Section.query.filter_by( + # label=label_1, collection_id=sub_collection.id + # ).first() + # response: Response = client.post( + # f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_2.id}/edit_section", + # data=dict( + # section_id=section_2.id, + # label="Test", + # ), + # follow_redirects=True, + # ) + + # assert response.status_code == 200 + # assert b"Section label must be unique!" in response.data + + # response: Response = client.post( + # f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_2.id}/edit_section", + # data=dict(section_id=section_2.id, label=new_label, about=new_about), + # follow_redirects=True, + # ) + # assert response.status_code == 200 + # assert b"Success!" in response.data + + # edited_section: m.Section = m.Section.query.filter_by( + # label=new_label, about=new_about, id=section_2.id + # ).first() + # assert edited_section + + # response: Response = client.post( + # f"/book/{book.id}/{collection.id}/{sub_collection.id}/999/edit_section", + # data=dict(section_id=section_2.id, label=new_label, about=new_about), + # follow_redirects=True, + # ) + + # assert response.status_code == 200 + # assert b"Section not found" in response.data + + # response: Response = client.post( + # f"/book/{book.id}/{collection.id}/{leaf_collection.id}/{section.id}/delete_section", + # follow_redirects=True, + # ) + + # assert response.status_code == 200 + # assert b"Success!" in response.data + + # deleted_section: m.Section = db.session.get(m.Section, section.id) + # assert deleted_section.is_deleted + + # response: Response = client.post( + # f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_2.id}/delete_section", + # follow_redirects=True, + # ) + + # assert response.status_code == 200 + # assert b"Success!" in response.data + + # deleted_section: m.Section = db.session.get(m.Section, section_2.id) + # assert deleted_section.is_deleted + + # response: Response = client.post( + # f"/book/{book.id}/{collection.id}/{sub_collection.id}/999/delete_section", + # follow_redirects=True, + # ) + + # assert response.status_code == 200 + # assert b"Section not found" in response.data From d50bf52e4961f3141969022317a6fa10be8fd585 Mon Sep 17 00:00:00 2001 From: SvyatoslavArtymovych Date: Thu, 4 May 2023 15:14:17 +0300 Subject: [PATCH 2/4] create interpretation backend --- app/forms/__init__.py | 1 + app/forms/interpretation.py | 60 ++++++++++++++++++++++++++ app/views/book.py | 85 +++++++++++++++++++++++++++++++++++++ tests/test_book.py | 38 +++++------------ 4 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 app/forms/interpretation.py diff --git a/app/forms/__init__.py b/app/forms/__init__.py index 74aa770..991c639 100644 --- a/app/forms/__init__.py +++ b/app/forms/__init__.py @@ -9,3 +9,4 @@ from .contributor import ( ) from .collection import CreateCollectionForm, EditCollectionForm from .section import CreateSectionForm, EditSectionForm +from .interpretation import CreateInterpretationForm diff --git a/app/forms/interpretation.py b/app/forms/interpretation.py new file mode 100644 index 0000000..cd63c7f --- /dev/null +++ b/app/forms/interpretation.py @@ -0,0 +1,60 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, SubmitField, ValidationError +from wtforms.validators import DataRequired, Length + +from app import models as m +from app.logger import log + + +class BaseInterpretationForm(FlaskForm): + label = StringField("Label", [DataRequired(), Length(3, 256)]) + about = StringField("About") + + +class CreateInterpretationForm(BaseInterpretationForm): + section_id = StringField("Interpretation ID", [DataRequired()]) + text = StringField("Text") + submit = SubmitField("Create") + + def validate_label(self, field): + label = field.data + section_id = self.section_id.data + + interpretation: m.Interpretation = m.Interpretation.query.filter_by( + is_deleted=False, label=label, section_id=section_id + ).first() + if interpretation: + log( + log.WARNING, + "Interpretation with label [%s] already exists: [%s]", + label, + interpretation, + ) + raise ValidationError("Interpretation label must be unique!") + + +# class EditSectionForm(BaseSectionForm): +# section_id = StringField("Section ID", [DataRequired()]) +# submit = SubmitField("Edit") + +# def validate_label(self, field): +# label = field.data +# section_id = self.section_id.data + +# collection_id = db.session.get(m.Section, section_id).collection_id +# section: m.Section = ( +# m.Section.query.filter_by( +# is_deleted=False, label=label, collection_id=collection_id +# ) +# .filter(m.Section.id != section_id) +# .first() +# ) + +# if section: +# log( +# log.WARNING, +# "Section with label [%s] already exists: [%s]", +# label, +# section, +# ) +# raise ValidationError("Section label must be unique!") diff --git a/app/views/book.py b/app/views/book.py index 9ff21b0..099db95 100644 --- a/app/views/book.py +++ b/app/views/book.py @@ -864,3 +864,88 @@ def section_delete( book_id=book_id, ) ) + + +############### +# Interpretation CRUD +############### + + +@bp.route( + "////create_interpretation", + methods=["POST"], +) +@bp.route( + "/////create_interpretation", + methods=["POST"], +) +@login_required +def interpretation_create( + book_id: int, + collection_id: int, + section_id: int, + sub_collection_id: int | None = None, +): + book: m.Book = db.session.get(m.Book, book_id) + if not book or book.is_deleted: + log(log.WARNING, "Book with id [%s] not found", book_id) + flash("Book not found", "danger") + return redirect(url_for("book.my_books")) + + collection: m.Collection = db.session.get(m.Collection, collection_id) + if not collection or collection.is_deleted: + log(log.WARNING, "Collection with id [%s] not found", collection_id) + flash("Collection not found", "danger") + return redirect(url_for("book.collection_view", book_id=book_id)) + + sub_collection = None + if sub_collection_id: + sub_collection: m.Collection = db.session.get(m.Collection, sub_collection_id) + if not sub_collection or sub_collection.is_deleted: + log(log.WARNING, "Sub_collection with id [%s] not found", sub_collection_id) + flash("Subcollection not found", "danger") + return redirect( + url_for( + "book.sub_collection_view", + book_id=book_id, + collection_id=collection_id, + ) + ) + + redirect_url = url_for( + "book.section_view", + book_id=book_id, + collection_id=collection_id, + sub_collection_id=sub_collection_id, + ) + section: m.Section = db.session.get(m.Section, section_id) + if not section or collection.is_deleted: + log(log.WARNING, "Section with id [%s] not found", section) + flash("Section not found", "danger") + return redirect(redirect_url) + + form = f.CreateInterpretationForm() + + if form.validate_on_submit(): + interpretation: m.Interpretation = m.Interpretation( + label=form.label.data, + text=form.text.data, + section_id=section_id, + ) + log( + log.INFO, + "Create interpretation [%s]. Section: [%s]", + interpretation, + section, + ) + interpretation.save() + + flash("Success!", "success") + return redirect(redirect_url) + else: + log(log.ERROR, "Interpretation create errors: [%s]", form.errors) + for field, errors in form.errors.items(): + field_label = form._fields[field].label.text + for error in errors: + flash(error.replace("Field", field_label), "danger") + return redirect(redirect_url) diff --git a/tests/test_book.py b/tests/test_book.py index 306ec0b..f0133b3 100644 --- a/tests/test_book.py +++ b/tests/test_book.py @@ -741,13 +741,11 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): ).save() label_1 = "Test Interpretation #1 Label" + text_1 = "Test Interpretation #1 Text" + response: Response = client.post( f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_in_subcollection.id}/create_interpretation", - data=dict( - section_id=section_in_subcollection.id, - label=label_1, - text="Test Interpretation #1 Label", - ), + data=dict(section_id=section_in_subcollection.id, label=label_1, text=text_1), follow_redirects=True, ) @@ -756,17 +754,12 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): label=label_1, section_id=section_in_subcollection.id ).first() assert interpretation - assert interpretation.collection_id == section_in_subcollection.id - assert interpretation.version_id == book.last_version.id + assert interpretation.section_id == section_in_subcollection.id assert not interpretation.comments response: Response = client.post( f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_in_subcollection.id}/create_interpretation", - data=dict( - section_id=section_in_subcollection.id, - label=label_1, - text="Test Interpretation #1 Label", - ), + data=dict(section_id=section_in_subcollection.id, label=label_1, text=text_1), follow_redirects=True, ) @@ -774,11 +767,7 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): response: Response = client.post( f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/create_interpretation", - data=dict( - section_id=section_in_collection.id, - label=label_1, - text="Test Interpretation #1 Label", - ), + data=dict(section_id=section_in_collection.id, label=label_1, text=text_1), follow_redirects=True, ) @@ -787,17 +776,12 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): label=label_1, section_id=section_in_collection.id ).first() assert interpretation - assert interpretation.collection_id == section_in_subcollection.id - assert interpretation.version_id == book.last_version.id + assert interpretation.section_id == section_in_collection.id assert not interpretation.comments response: Response = client.post( f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/create_interpretation", - data=dict( - section_id=section_in_collection.id, - label=label_1, - text="Test Interpretation #1 Label", - ), + data=dict(section_id=section_in_collection.id, label=label_1, text=text_1), follow_redirects=True, ) @@ -805,7 +789,7 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): response: Response = client.post( f"/book/{book.id}/{collection.id}/999/create_section", - data=dict(collection_id=999, label=label_1, about="Test Section #1 About"), + data=dict(collection_id=999, label=label_1, text=text_1), follow_redirects=True, ) @@ -814,7 +798,7 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): response: Response = client.post( f"/book/{book.id}/{leaf_collection.id}/999/create_interpretation", - data=dict(collection_id=999, label=label_1, about="Test Section #1 About"), + data=dict(collection_id=999, label=label_1, text=text_1), follow_redirects=True, ) @@ -823,7 +807,7 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): response: Response = client.post( f"/book/{book.id}/{collection.id}/{sub_collection.id}/888/create_interpretation", - data=dict(collection_id=999, label=label_1, about="Test Section #1 About"), + data=dict(collection_id=999, label=label_1, text=text_1), follow_redirects=True, ) From 6fce2cd53b141a8f70c8215730580f1aaf5e8bb4 Mon Sep 17 00:00:00 2001 From: SvyatoslavArtymovych Date: Thu, 4 May 2023 16:32:56 +0300 Subject: [PATCH 3/4] edit interpretation ui --- app/forms/__init__.py | 2 +- app/forms/interpretation.py | 48 +++++++------- app/views/book.py | 88 ++++++++++++++++++++++++ tests/test_book.py | 129 +++++++++++++++--------------------- 4 files changed, 167 insertions(+), 100 deletions(-) diff --git a/app/forms/__init__.py b/app/forms/__init__.py index 991c639..e3d931b 100644 --- a/app/forms/__init__.py +++ b/app/forms/__init__.py @@ -9,4 +9,4 @@ from .contributor import ( ) from .collection import CreateCollectionForm, EditCollectionForm from .section import CreateSectionForm, EditSectionForm -from .interpretation import CreateInterpretationForm +from .interpretation import CreateInterpretationForm, EditInterpretationForm diff --git a/app/forms/interpretation.py b/app/forms/interpretation.py index cd63c7f..359819a 100644 --- a/app/forms/interpretation.py +++ b/app/forms/interpretation.py @@ -2,7 +2,7 @@ from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, ValidationError from wtforms.validators import DataRequired, Length -from app import models as m +from app import models as m, db from app.logger import log @@ -33,28 +33,30 @@ class CreateInterpretationForm(BaseInterpretationForm): raise ValidationError("Interpretation label must be unique!") -# class EditSectionForm(BaseSectionForm): -# section_id = StringField("Section ID", [DataRequired()]) -# submit = SubmitField("Edit") +class EditInterpretationForm(BaseInterpretationForm): + interpretation_id = StringField("Interpretation ID", [DataRequired()]) + text = StringField("Text") + submit = SubmitField("Edit") -# def validate_label(self, field): -# label = field.data -# section_id = self.section_id.data + def validate_label(self, field): + label = field.data + interpretation_id = self.interpretation_id.data -# collection_id = db.session.get(m.Section, section_id).collection_id -# section: m.Section = ( -# m.Section.query.filter_by( -# is_deleted=False, label=label, collection_id=collection_id -# ) -# .filter(m.Section.id != section_id) -# .first() -# ) + section_id = db.session.get(m.Interpretation, interpretation_id).section_id -# if section: -# log( -# log.WARNING, -# "Section with label [%s] already exists: [%s]", -# label, -# section, -# ) -# raise ValidationError("Section label must be unique!") + interpretation: m.Interpretation = ( + m.Interpretation.query.filter_by( + is_deleted=False, label=label, section_id=section_id + ) + .filter(m.Interpretation.id != interpretation_id) + .first() + ) + + if interpretation: + log( + log.WARNING, + "Interpretation with label [%s] already exists: [%s]", + label, + interpretation, + ) + raise ValidationError("Interpretation label must be unique!") diff --git a/app/views/book.py b/app/views/book.py index 099db95..622dfb9 100644 --- a/app/views/book.py +++ b/app/views/book.py @@ -949,3 +949,91 @@ def interpretation_create( for error in errors: flash(error.replace("Field", field_label), "danger") return redirect(redirect_url) + + +@bp.route( + "/////edit_interpretation", + methods=["POST"], +) +@bp.route( + ( + "////" + "//edit_interpretation" + ), + methods=["POST"], +) +@login_required +def interpretation_edit( + book_id: int, + collection_id: int, + section_id: int, + interpretation_id: int, + sub_collection_id: int | None = None, +): + book: m.Book = db.session.get(m.Book, book_id) + if not book or book.owner != current_user or book.is_deleted: + log(log.INFO, "User: [%s] is not owner of book: [%s]", current_user, book) + flash("You are not owner of this book!", "danger") + return redirect(url_for("book.my_books")) + + collection: m.Collection = db.session.get(m.Collection, collection_id) + if not collection or collection.is_deleted: + log(log.WARNING, "Collection with id [%s] not found", collection_id) + flash("Collection not found", "danger") + return redirect(url_for("book.collection_view", book_id=book_id)) + + if sub_collection_id: + sub_collection: m.Collection = db.session.get(m.Collection, sub_collection_id) + if not sub_collection or sub_collection.is_deleted: + log(log.WARNING, "Sub_collection with id [%s] not found", sub_collection_id) + flash("SubCollection not found", "danger") + return redirect( + url_for( + "book.sub_collection_view", + book_id=book_id, + collection_id=collection_id, + ) + ) + + redirect_url = url_for( + "book.interpretation_view", + book_id=book_id, + collection_id=collection_id, + sub_collection_id=sub_collection_id, + section_id=section_id, + ) + section: m.Section = db.session.get(m.Section, section_id) + if not section or section.is_deleted: + log(log.WARNING, "Section with id [%s] not found", section_id) + flash("Section not found", "danger") + return redirect(redirect_url) + + interpretation: m.Interpretation = db.session.get( + m.Interpretation, interpretation_id + ) + if not interpretation or interpretation.is_deleted: + log(log.WARNING, "Interpretation with id [%s] not found", interpretation_id) + flash("Interpretation not found", "danger") + return redirect(redirect_url) + + form = f.EditInterpretationForm() + + if form.validate_on_submit(): + label = form.label.data + if label: + interpretation.label = label + + interpretation.text = form.text.data + + log(log.INFO, "Edit interpretation [%s]", interpretation.id) + interpretation.save() + + flash("Success!", "success") + return redirect(redirect_url) + else: + log(log.ERROR, "Interpretation edit errors: [%s]", form.errors) + for field, errors in form.errors.items(): + field_label = form._fields[field].label.text + for error in errors: + flash(error.replace("Field", field_label), "danger") + return redirect(redirect_url) diff --git a/tests/test_book.py b/tests/test_book.py index f0133b3..25ebba1 100644 --- a/tests/test_book.py +++ b/tests/test_book.py @@ -814,91 +814,68 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): assert response.status_code == 200 assert b"Section not found" in response.data - # # edit + # edit - # m.Section( - # label="Test", - # about="Test", - # collection_id=leaf_collection.id, - # version_id=book.last_version.id, - # ).save() + m.Interpretation( + label="Test", + text="Test", + section_id=section_in_collection.id, + ).save() - # m.Section( - # label="Test", - # about="Test", - # collection_id=sub_collection.id, - # version_id=book.last_version.id, - # ).save() + m.Interpretation( + label="Test", + text="Test", + section_id=section_in_subcollection.id, + ).save() - # section: m.Section = m.Section.query.filter_by( - # label=label_1, collection_id=leaf_collection.id - # ).first() + interpretation: m.Interpretation = m.Interpretation.query.filter_by( + label=label_1, section_id=section_in_collection.id + ).first() - # response: Response = client.post( - # f"/book/{book.id}/{leaf_collection.id}/{section.id}/edit_section", - # data=dict( - # section_id=section.id, - # label="Test", - # ), - # follow_redirects=True, - # ) + response: Response = client.post( + f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/{interpretation.id}/edit_interpretation", + data=dict( + interpretation_id=interpretation.id, + label="Test", + text="Test", + ), + follow_redirects=True, + ) - # assert response.status_code == 200 - # assert b"Section label must be unique!" in response.data + assert response.status_code == 200 + assert b"Interpretation label must be unique!" in response.data - # new_label = "Test Section #1 Label(edited)" - # new_about = "Test Section #1 About(edited)" + new_label = "Test Interpretation #1 Label(edited)" + new_text = "Test Interpretation #1 Text(edited)" - # response: Response = client.post( - # f"/book/{book.id}/{leaf_collection.id}/{section.id}/edit_section", - # data=dict(section_id=section.id, label=new_label, about=new_about), - # follow_redirects=True, - # ) - # assert response.status_code == 200 - # assert b"Success!" in response.data + response: Response = client.post( + f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/{interpretation.id}/edit_interpretation", + data=dict( + label=new_label, + interpretation_id=interpretation.id, + text=new_text, + ), + follow_redirects=True, + ) + assert response.status_code == 200 + assert b"Success!" in response.data - # edited_section: m.Section = m.Section.query.filter_by( - # label=new_label, about=new_about, id=section.id - # ).first() - # assert edited_section + edited_interpretation: m.Interpretation = m.Interpretation.query.filter_by( + label=new_label, text=new_text, id=interpretation.id + ).first() + assert edited_interpretation - # # - # section_2: m.Section = m.Section.query.filter_by( - # label=label_1, collection_id=sub_collection.id - # ).first() - # response: Response = client.post( - # f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_2.id}/edit_section", - # data=dict( - # section_id=section_2.id, - # label="Test", - # ), - # follow_redirects=True, - # ) - - # assert response.status_code == 200 - # assert b"Section label must be unique!" in response.data - - # response: Response = client.post( - # f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_2.id}/edit_section", - # data=dict(section_id=section_2.id, label=new_label, about=new_about), - # follow_redirects=True, - # ) - # assert response.status_code == 200 - # assert b"Success!" in response.data - - # edited_section: m.Section = m.Section.query.filter_by( - # label=new_label, about=new_about, id=section_2.id - # ).first() - # assert edited_section - - # response: Response = client.post( - # f"/book/{book.id}/{collection.id}/{sub_collection.id}/999/edit_section", - # data=dict(section_id=section_2.id, label=new_label, about=new_about), - # follow_redirects=True, - # ) - - # assert response.status_code == 200 - # assert b"Section not found" in response.data + response: Response = client.post( + f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/999/edit_interpretation", + data=dict( + interpretation_id=interpretation.id, + label=new_label, + text=new_text, + ), + follow_redirects=True, + ) + assert response.status_code == 200 + assert b"Interpretation not found" in response.data # response: Response = client.post( # f"/book/{book.id}/{collection.id}/{leaf_collection.id}/{section.id}/delete_section", From df740078efb8349615aa02f25549f876a738dd43 Mon Sep 17 00:00:00 2001 From: SvyatoslavArtymovych Date: Thu, 4 May 2023 16:57:47 +0300 Subject: [PATCH 4/4] delete interpretation backend --- app/views/book.py | 82 ++++++++++++++++++++++++++++++++++++++++++++-- tests/test_book.py | 54 +++++++++++++++++------------- 2 files changed, 112 insertions(+), 24 deletions(-) diff --git a/app/views/book.py b/app/views/book.py index 622dfb9..5497677 100644 --- a/app/views/book.py +++ b/app/views/book.py @@ -866,9 +866,9 @@ def section_delete( ) -############### +##################### # Interpretation CRUD -############### +##################### @bp.route( @@ -1037,3 +1037,81 @@ def interpretation_edit( for error in errors: flash(error.replace("Field", field_label), "danger") return redirect(redirect_url) + + +@bp.route( + "/////delete_interpretation", + methods=["POST"], +) +@bp.route( + ( + "////" + "//delete_interpretation" + ), + methods=["POST"], +) +@login_required +def interpretation_delete( + book_id: int, + collection_id: int, + section_id: int, + interpretation_id: int, + sub_collection_id: int | None = None, +): + book: m.Book = db.session.get(m.Book, book_id) + if not book or book.owner != current_user or book.is_deleted: + log(log.INFO, "User: [%s] is not owner of book: [%s]", current_user, book) + flash("You are not owner of this book!", "danger") + return redirect(url_for("book.my_books")) + + collection: m.Collection = db.session.get(m.Collection, collection_id) + if not collection or collection.is_deleted: + log(log.WARNING, "Collection with id [%s] not found", collection_id) + flash("Collection not found", "danger") + return redirect(url_for("book.collection_view", book_id=book_id)) + + if sub_collection_id: + sub_collection: m.Collection = db.session.get(m.Collection, sub_collection_id) + if not sub_collection or sub_collection.is_deleted: + log(log.WARNING, "Sub_collection with id [%s] not found", sub_collection_id) + flash("SubCollection not found", "danger") + return redirect( + url_for( + "book.sub_collection_view", + book_id=book_id, + collection_id=collection_id, + ) + ) + + redirect_url = url_for( + "book.interpretation_view", + book_id=book_id, + collection_id=collection_id, + sub_collection_id=sub_collection_id, + section_id=section_id, + ) + section: m.Section = db.session.get(m.Section, section_id) + if not section or section.is_deleted: + log(log.WARNING, "Section with id [%s] not found", section_id) + flash("Section not found", "danger") + return redirect(redirect_url) + + interpretation: m.Interpretation = db.session.get( + m.Interpretation, interpretation_id + ) + if not interpretation or interpretation.is_deleted: + log(log.WARNING, "Interpretation with id [%s] not found", interpretation_id) + flash("Interpretation not found", "danger") + return redirect(redirect_url) + + interpretation.is_deleted = True + log(log.INFO, "Delete interpretation [%s]", interpretation) + interpretation.save() + + flash("Success!", "success") + return redirect( + url_for( + "book.collection_view", + book_id=book_id, + ) + ) diff --git a/tests/test_book.py b/tests/test_book.py index 25ebba1..31063d3 100644 --- a/tests/test_book.py +++ b/tests/test_book.py @@ -877,32 +877,42 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner): assert response.status_code == 200 assert b"Interpretation not found" in response.data - # response: Response = client.post( - # f"/book/{book.id}/{collection.id}/{leaf_collection.id}/{section.id}/delete_section", - # follow_redirects=True, - # ) + response: Response = client.post( + f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/999/delete_interpretation", + follow_redirects=True, + ) - # assert response.status_code == 200 - # assert b"Success!" in response.data + assert response.status_code == 200 + assert b"Interpretation not found" in response.data - # deleted_section: m.Section = db.session.get(m.Section, section.id) - # assert deleted_section.is_deleted + response: Response = client.post( + ( + f"/book/{book.id}/{collection.id}/{sub_collection.id}/" + f"{section_in_subcollection.id}/{section_in_subcollection.interpretations[0].id}/delete_interpretation" + ), + follow_redirects=True, + ) - # response: Response = client.post( - # f"/book/{book.id}/{collection.id}/{sub_collection.id}/{section_2.id}/delete_section", - # follow_redirects=True, - # ) + assert response.status_code == 200 + assert b"Success!" in response.data - # assert response.status_code == 200 - # assert b"Success!" in response.data + deleted_interpretation: m.Interpretation = db.session.get( + m.Interpretation, section_in_subcollection.interpretations[0].id + ) + assert deleted_interpretation.is_deleted - # deleted_section: m.Section = db.session.get(m.Section, section_2.id) - # assert deleted_section.is_deleted + response: Response = client.post( + ( + f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/" + f"{section_in_collection.interpretations[0].id}/delete_interpretation" + ), + follow_redirects=True, + ) - # response: Response = client.post( - # f"/book/{book.id}/{collection.id}/{sub_collection.id}/999/delete_section", - # follow_redirects=True, - # ) + assert response.status_code == 200 + assert b"Success!" in response.data - # assert response.status_code == 200 - # assert b"Section not found" in response.data + deleted_interpretation: m.Interpretation = db.session.get( + m.Interpretation, section_in_collection.interpretations[0].id + ) + assert deleted_interpretation.is_deleted