Merge pull request #28 from Simple2B/kostia/feature/interpretations

work
This commit is contained in:
Костя Столярский 2023-05-05 12:05:55 +03:00 committed by GitHub
commit 2d20671eaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 53 additions and 148 deletions

View File

@ -1,10 +1,7 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, ValidationError from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired, Length from wtforms.validators import DataRequired, Length
from app import models as m, db
from app.logger import log
class BaseInterpretationForm(FlaskForm): class BaseInterpretationForm(FlaskForm):
label = StringField("Label", [DataRequired(), Length(3, 256)]) label = StringField("Label", [DataRequired(), Length(3, 256)])
@ -16,47 +13,8 @@ class CreateInterpretationForm(BaseInterpretationForm):
text = StringField("Text") text = StringField("Text")
submit = SubmitField("Create") 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 EditInterpretationForm(BaseInterpretationForm): class EditInterpretationForm(BaseInterpretationForm):
interpretation_id = StringField("Interpretation ID", [DataRequired()]) interpretation_id = StringField("Interpretation ID", [DataRequired()])
text = StringField("Text") text = StringField("Text")
submit = SubmitField("Edit") submit = SubmitField("Edit")
def validate_label(self, field):
label = field.data
interpretation_id = self.interpretation_id.data
section_id = db.session.get(m.Interpretation, interpretation_id).section_id
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!")

View File

@ -47,5 +47,13 @@ class Section(BaseModel):
_sub_collection_id = grand_parent.id _sub_collection_id = grand_parent.id
return _sub_collection_id return _sub_collection_id
@property
def active_interpretations(self):
return [
interpretation
for interpretation in self.interpretations
if not interpretation.is_deleted
]
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

@ -66,7 +66,7 @@
<input type="hidden" name="section_id" id="section_id" value="{{section.id}}" /> <input type="hidden" name="section_id" id="section_id" value="{{section.id}}" />
<input type="hidden" name="label" id="label" value="{{section.label}}" /> <input type="hidden" name="label" id="label" value="{{section.label}}" />
<input type="hidden" name="interpretation-text" id="interpretation-text" /> <input type="hidden" name="text" id="interpretation-text" />
<!-- Form body --> <!-- Form body -->
<div class="p-6 space-y-6"> <div class="p-6 space-y-6">
<div class="grid gap-6"> <div class="grid gap-6">
@ -89,20 +89,21 @@
</form> </form>
<dl class="w-md md:w-full text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700"> <dl class="w-md md:w-full text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700">
<!-- prettier-ignore --> <!-- prettier-ignore -->
{% for interpretation in section.interpretations %} {% for interpretation in section.active_interpretations %}
{% if sub_collection %} {% if sub_collection %}
<a href="{{url_for('book.interpretation_view', book_id=book.id, collection_id=collection.id, sub_collection_id=sub_collection.id, section_id=section.id)}}" > <a href="{{url_for('book.interpretation_view', book_id=book.id, collection_id=collection.id, sub_collection_id=sub_collection.id, section_id=section.id)}}" >
{% else %} {% else %}
<a href="{{url_for('book.interpretation_view', book_id=book.id, collection_id=collection.id, section_id=section.id)}}" > <a href="{{url_for('book.interpretation_view', book_id=book.id, collection_id=collection.id, section_id=section.id)}}" >
{% endif %} {% endif %}
<h1>Other</h1>
<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"> <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">
<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">
<div> <div>
<h1>{{ section.label }}</h1> <h1>{{ section.label }}</h1>
<p>{{ interpretation.text }}</p> <div id="editor" class="dark:text-white h-80">
<p>{{ interpretation.text|safe }}</p>
</div>
</div> </div>
<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">

View File

@ -912,17 +912,25 @@ def interpretation_create(
) )
) )
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) section: m.Section = db.session.get(m.Section, section_id)
if not section or collection.is_deleted: if not section or collection.is_deleted:
log(log.WARNING, "Section with id [%s] not found", section) log(log.WARNING, "Section with id [%s] not found", section)
flash("Section not found", "danger") flash("Section not found", "danger")
return redirect(redirect_url) return redirect(
url_for(
"book.section_view",
book_id=book_id,
collection_id=collection_id,
sub_collection_id=sub_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,
)
form = f.CreateInterpretationForm() form = f.CreateInterpretationForm()

View File

@ -1,38 +1,39 @@
const quill_value_to_textarea = (): undefined => { const quill_value_to_textarea = (): undefined => {
const aboutInput: HTMLButtonElement = document.querySelector('#about'); const aboutInput: HTMLInputElement = document.querySelector('#about');
const qlEditor: HTMLButtonElement = document.querySelector('.ql-editor'); const qlEditor: HTMLElement = document.querySelector('.ql-editor');
const editorContent = qlEditor.innerHTML; const editorContent = qlEditor.innerHTML;
aboutInput.value = editorContent; aboutInput.value = editorContent;
return undefined; return undefined;
}; };
const quill_interpretation_to_textarea = (): undefined => { const quill_interpretation_to_textarea = (): undefined => {
const interpretationTextInput: HTMLButtonElement = document.querySelector( const interpretationTextInput: HTMLInputElement = document.querySelector(
'#interpretation-text', '#interpretation-text',
); );
const qlInterpretationEditor: HTMLButtonElement = document.querySelector( const qlInterpretationEditor: HTMLElement = document.querySelector(
'.ql-interpretation-editor', '#interpretation-editor',
); );
const editorContent = qlInterpretationEditor.innerHTML; const editorContent = qlInterpretationEditor.innerHTML;
console.log('editorContent', editorContent);
interpretationTextInput.value = editorContent; interpretationTextInput.value = editorContent;
return undefined; return undefined;
}; };
export function initQuillValueToTextArea() { export function initQuillValueToTextArea() {
const qlEditor: HTMLButtonElement = document.querySelector('.ql-editor'); const qlEditor: HTMLElement = document.querySelector('.ql-editor');
if (qlEditor) { if (qlEditor) {
qlEditor.addEventListener('DOMSubtreeModified', async e => { qlEditor.addEventListener('DOMSubtreeModified', () => {
quill_value_to_textarea(); quill_value_to_textarea();
}); });
} }
// //
const qlInterpretationEditor: HTMLButtonElement = document.querySelector( const qlInterpretationEditor: HTMLElement = document.querySelector(
'.ql-interpretation-editor', '#interpretation-editor',
); );
if (!qlInterpretationEditor) { if (qlInterpretationEditor) {
qlInterpretationEditor.addEventListener('DOMSubtreeModified', async e => { qlInterpretationEditor.addEventListener('DOMSubtreeModified', () => {
quill_interpretation_to_textarea(); quill_interpretation_to_textarea();
}); });
} }

View File

@ -757,14 +757,6 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner):
assert interpretation.section_id == section_in_subcollection.id assert interpretation.section_id == section_in_subcollection.id
assert not interpretation.comments 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=text_1),
follow_redirects=True,
)
assert b"Interpretation label must be unique!" in response.data
response: Response = client.post( response: Response = client.post(
f"/book/{book.id}/{leaf_collection.id}/{section_in_collection.id}/create_interpretation", 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=text_1), data=dict(section_id=section_in_collection.id, label=label_1, text=text_1),
@ -779,14 +771,6 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner):
assert interpretation.section_id == section_in_collection.id assert interpretation.section_id == section_in_collection.id
assert not interpretation.comments 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=text_1),
follow_redirects=True,
)
assert b"Interpretation label must be unique!" in response.data
response: Response = client.post( response: Response = client.post(
f"/book/{book.id}/{collection.id}/999/create_section", f"/book/{book.id}/{collection.id}/999/create_section",
data=dict(collection_id=999, label=label_1, text=text_1), data=dict(collection_id=999, label=label_1, text=text_1),
@ -832,19 +816,6 @@ def test_crud_interpretation(client: FlaskClient, runner: FlaskCliRunner):
label=label_1, section_id=section_in_collection.id label=label_1, section_id=section_in_collection.id
).first() ).first()
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"Interpretation label must be unique!" in response.data
new_label = "Test Interpretation #1 Label(edited)" new_label = "Test Interpretation #1 Label(edited)"
new_text = "Test Interpretation #1 Text(edited)" new_text = "Test Interpretation #1 Text(edited)"