mirror of https://github.com/logos-co/open-law.git
tagging sub comments
This commit is contained in:
parent
0666a29de6
commit
4b8ff4ba40
|
@ -5,11 +5,11 @@ from wtforms.validators import DataRequired, Length
|
||||||
|
|
||||||
class BaseCommentForm(FlaskForm):
|
class BaseCommentForm(FlaskForm):
|
||||||
text = StringField("Text", [DataRequired(), Length(3, 256)])
|
text = StringField("Text", [DataRequired(), Length(3, 256)])
|
||||||
|
tags = StringField("Tags")
|
||||||
|
|
||||||
|
|
||||||
class CreateCommentForm(BaseCommentForm):
|
class CreateCommentForm(BaseCommentForm):
|
||||||
parent_id = StringField("Text")
|
parent_id = StringField("Text")
|
||||||
tags = StringField("Tags")
|
|
||||||
submit = SubmitField("Create")
|
submit = SubmitField("Create")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1157,14 +1157,14 @@ input:checked + .toggle-bg {
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.z-\[55\] {
|
|
||||||
z-index: 55;
|
|
||||||
}
|
|
||||||
|
|
||||||
.z-\[150\] {
|
.z-\[150\] {
|
||||||
z-index: 150;
|
z-index: 150;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.z-\[55\] {
|
||||||
|
z-index: 55;
|
||||||
|
}
|
||||||
|
|
||||||
.col-span-6 {
|
.col-span-6 {
|
||||||
grid-column: span 6 / span 6;
|
grid-column: span 6 / span 6;
|
||||||
}
|
}
|
||||||
|
@ -1409,6 +1409,10 @@ input:checked + .toggle-bg {
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-40 {
|
||||||
|
height: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
.h-5 {
|
.h-5 {
|
||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
}
|
}
|
||||||
|
@ -1454,14 +1458,6 @@ input:checked + .toggle-bg {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-40 {
|
|
||||||
height: 10rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-\[calc\(100\%\)\] {
|
|
||||||
height: calc(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-h-full {
|
.max-h-full {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -1724,6 +1720,10 @@ input:checked + .toggle-bg {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gap-1 {
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.gap-2 {
|
.gap-2 {
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@ -1732,10 +1732,6 @@ input:checked + .toggle-bg {
|
||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gap-1 {
|
|
||||||
gap: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.-space-x-px > :not([hidden]) ~ :not([hidden]) {
|
.-space-x-px > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-x-reverse: 0;
|
--tw-space-x-reverse: 0;
|
||||||
margin-right: calc(-1px * var(--tw-space-x-reverse));
|
margin-right: calc(-1px * var(--tw-space-x-reverse));
|
||||||
|
@ -2046,6 +2042,11 @@ input:checked + .toggle-bg {
|
||||||
background-color: rgb(200 30 30 / var(--tw-bg-opacity));
|
background-color: rgb(200 30 30 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-sky-300 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(125 211 252 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-slate-300 {
|
.bg-slate-300 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(203 213 225 / var(--tw-bg-opacity));
|
background-color: rgb(203 213 225 / var(--tw-bg-opacity));
|
||||||
|
@ -2074,16 +2075,6 @@ input:checked + .toggle-bg {
|
||||||
background-color: rgb(255 255 255 / 0.5);
|
background-color: rgb(255 255 255 / 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-sky-300 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(125 211 252 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-black {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-opacity-50 {
|
.bg-opacity-50 {
|
||||||
--tw-bg-opacity: 0.5;
|
--tw-bg-opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
@ -2537,16 +2528,16 @@ input:checked + .toggle-bg {
|
||||||
background-color: rgb(155 28 28 / var(--tw-bg-opacity));
|
background-color: rgb(155 28 28 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:bg-white:hover {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\:bg-sky-400:hover {
|
.hover\:bg-sky-400:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(56 189 248 / var(--tw-bg-opacity));
|
background-color: rgb(56 189 248 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:bg-white:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:bg-gradient-to-bl:hover {
|
.hover\:bg-gradient-to-bl:hover {
|
||||||
background-image: linear-gradient(to bottom left, var(--tw-gradient-stops));
|
background-image: linear-gradient(to bottom left, var(--tw-gradient-stops));
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,12 +213,38 @@
|
||||||
>
|
>
|
||||||
{{ form_hidden_tag() }}
|
{{ form_hidden_tag() }}
|
||||||
<input type="hidden" name="parent_id" id="parent_id" value="{{comment.id}}" />
|
<input type="hidden" name="parent_id" id="parent_id" value="{{comment.id}}" />
|
||||||
<div class="relative z-0 w-full mb-6 group">
|
<div class="relative z-0 w-full group">
|
||||||
<!-- prettier-ignore -->
|
<div class="mb-2">
|
||||||
<input autocomplete="off" maxlength="256" type="text" name="text" id="floating_email" class="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer" placeholder=" " required />
|
<label for="tags-input" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
|
||||||
<!-- prettier-ignore -->
|
Comment
|
||||||
<label for="floating_email" class="peer-focus:font-medium absolute text-sm text-gray-500 dark:text-gray-400 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:left-0 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6" >Comment</label >
|
</label>
|
||||||
</div>
|
<input
|
||||||
|
name="text"
|
||||||
|
autocomplete="off"
|
||||||
|
maxlength="256"
|
||||||
|
type="text"
|
||||||
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||||
|
placeholder="Leave your comment here"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="multiple-input-block mb-6">
|
||||||
|
<label for="tags-input" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
Tags
|
||||||
|
</label>
|
||||||
|
<input type="text" name="tags" class="hidden tags-to-submit">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="tags-input"
|
||||||
|
class="multiple-input mb-3 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||||
|
placeholder="e.g. Law (press 'Enter' or Comma to add tag. Click on tag to edit it)"
|
||||||
|
data-save-results-to="tags-to-submit"
|
||||||
|
>
|
||||||
|
<div class="multiple-input-items gap-1 flex flex-wrap">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<button type="submit" class="ml-auto 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 w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"> Leave comment </button>
|
<button type="submit" class="ml-auto 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 w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"> Leave comment </button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1013,7 +1013,6 @@ def qa_view(
|
||||||
sub_collection=sub_collection if sub_collection_id else None,
|
sub_collection=sub_collection if sub_collection_id else None,
|
||||||
section=section,
|
section=section,
|
||||||
interpretation=interpretation,
|
interpretation=interpretation,
|
||||||
breadcrumbs=breadcrumbs,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1079,7 +1078,6 @@ def create_comment(
|
||||||
sub_collection_id=sub_collection_id,
|
sub_collection_id=sub_collection_id,
|
||||||
section_id=section_id,
|
section_id=section_id,
|
||||||
interpretation_id=interpretation_id,
|
interpretation_id=interpretation_id,
|
||||||
breadcrumbs=breadcrumbs,
|
|
||||||
)
|
)
|
||||||
section: m.Section = db.session.get(m.Section, section_id)
|
section: m.Section = db.session.get(m.Section, section_id)
|
||||||
if not section or section.is_deleted:
|
if not section or section.is_deleted:
|
||||||
|
@ -1119,7 +1117,7 @@ def create_comment(
|
||||||
set_comment_tags(comment, tags)
|
set_comment_tags(comment, tags)
|
||||||
|
|
||||||
flash("Success!", "success")
|
flash("Success!", "success")
|
||||||
return redirect(request.referrer)
|
return redirect(redirect_url)
|
||||||
else:
|
else:
|
||||||
log(log.ERROR, "Comment create errors: [%s]", form.errors)
|
log(log.ERROR, "Comment create errors: [%s]", form.errors)
|
||||||
for field, errors in form.errors.items():
|
for field, errors in form.errors.items():
|
||||||
|
@ -1127,7 +1125,7 @@ def create_comment(
|
||||||
for error in errors:
|
for error in errors:
|
||||||
flash(error.lower().replace("field", field_label).title(), "danger")
|
flash(error.lower().replace("field", field_label).title(), "danger")
|
||||||
|
|
||||||
return redirect(request.referrer)
|
return redirect(redirect_url)
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
|
@ -1200,13 +1198,18 @@ def comment_edit(
|
||||||
sub_collection_id: int | None = None,
|
sub_collection_id: int | None = None,
|
||||||
):
|
):
|
||||||
form = f.EditCommentForm()
|
form = f.EditCommentForm()
|
||||||
comment_id = form.comment_id.data
|
|
||||||
comment: m.Comment = db.session.get(m.Comment, comment_id)
|
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
|
comment_id = form.comment_id.data
|
||||||
|
comment: m.Comment = db.session.get(m.Comment, comment_id)
|
||||||
comment.text = form.text.data
|
comment.text = form.text.data
|
||||||
comment.edited = True
|
comment.edited = True
|
||||||
log(log.INFO, "Delete comment [%s]", comment)
|
log(log.INFO, "Edit comment [%s]", comment)
|
||||||
|
|
||||||
|
tags = form.tags.data
|
||||||
|
if tags:
|
||||||
|
set_comment_tags(comment, tags)
|
||||||
|
|
||||||
comment.save()
|
comment.save()
|
||||||
|
|
||||||
flash("Success!", "success")
|
flash("Success!", "success")
|
||||||
|
|
|
@ -23,11 +23,11 @@ def get_all():
|
||||||
m.Collection.id == m.Section.collection_id,
|
m.Collection.id == m.Section.collection_id,
|
||||||
m.BookVersion.id == m.Section.version_id,
|
m.BookVersion.id == m.Section.version_id,
|
||||||
m.Book.id == m.BookVersion.book_id,
|
m.Book.id == m.BookVersion.book_id,
|
||||||
m.Book.is_deleted.is_(False),
|
m.Book.is_deleted == False, # noqa: E712
|
||||||
m.BookVersion.is_deleted.is_(False),
|
m.BookVersion.is_deleted == False, # noqa: E712
|
||||||
m.Interpretation.is_deleted.is_(False),
|
m.Interpretation.is_deleted == False, # noqa: E712
|
||||||
m.Section.is_deleted.is_(False),
|
m.Section.is_deleted == False, # noqa: E712
|
||||||
m.Collection.is_deleted.is_(False),
|
m.Collection.is_deleted == False, # noqa: E712
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.order_by(m.Interpretation.created_at.desc())
|
.order_by(m.Interpretation.created_at.desc())
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# flake8: noqa F501
|
# flake8: noqa F501
|
||||||
from flask import current_app as Response
|
from flask import current_app as Response, url_for
|
||||||
from flask.testing import FlaskClient, FlaskCliRunner
|
from flask.testing import FlaskClient, FlaskCliRunner
|
||||||
|
|
||||||
from app import models as m, db
|
from app import models as m, db
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from flask import current_app as Response
|
from flask import current_app as Response
|
||||||
from flask.testing import FlaskClient
|
from flask.testing import FlaskClient
|
||||||
|
|
||||||
from app import models as m
|
from app import models as m, db
|
||||||
from tests.utils import login, create_test_book
|
from tests.utils import login, create_test_book
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ def test_create_tags_on_book_edit(client: FlaskClient):
|
||||||
_, user = login(client)
|
_, user = login(client)
|
||||||
|
|
||||||
book: m.Book = m.Book(label="Test book", user_id=user.id).save()
|
book: m.Book = m.Book(label="Test book", user_id=user.id).save()
|
||||||
m.BookVersion = m.BookVersion(semver="1.0.0", book_id=book.id).save()
|
m.BookVersion(semver="1.0.0", book_id=book.id).save()
|
||||||
|
|
||||||
assert not book.tags
|
assert not book.tags
|
||||||
|
|
||||||
|
@ -87,14 +87,14 @@ def test_create_tags_on_book_edit(client: FlaskClient):
|
||||||
assert len(book.tags) == 0
|
assert len(book.tags) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_create_tags_on_comment_create(client: FlaskClient):
|
def test_create_tags_on_comment_create_and_edit(client: FlaskClient):
|
||||||
_, user = login(client)
|
_, user = login(client)
|
||||||
create_test_book(user.id, 1)
|
create_test_book(user.id, 1)
|
||||||
|
|
||||||
book = m.Book.query.get(1)
|
book = db.session.get(m.Book, 1)
|
||||||
collection = m.Collection.query.get(1)
|
collection = db.session.get(m.Collection, 1)
|
||||||
section = m.Section.query.get(1)
|
section = db.session.get(m.Section, 1)
|
||||||
interpretation = m.Interpretation.query.get(1)
|
interpretation = db.session.get(m.Interpretation, 1)
|
||||||
|
|
||||||
tags = "tag1,tag2,tag3"
|
tags = "tag1,tag2,tag3"
|
||||||
response: Response = client.post(
|
response: Response = client.post(
|
||||||
|
@ -122,14 +122,35 @@ def test_create_tags_on_comment_create(client: FlaskClient):
|
||||||
tags_from_db: m.Tag = m.Tag.query.all()
|
tags_from_db: m.Tag = m.Tag.query.all()
|
||||||
assert len(tags_from_db) == 3
|
assert len(tags_from_db) == 3
|
||||||
|
|
||||||
|
tags = "tag1,tag5,tag7"
|
||||||
|
response: Response = client.post(
|
||||||
|
f"/book/{book.id}/{collection.id}/{section.id}/{interpretation.id}/comment_edit",
|
||||||
|
data=dict(text=comment.text, tags=tags, comment_id=comment.id),
|
||||||
|
follow_redirects=True,
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
comment: m.Comment = m.Comment.query.filter_by(text="some text").first()
|
||||||
|
assert comment
|
||||||
|
assert comment.tags
|
||||||
|
|
||||||
|
splitted_tags = [tag.title() for tag in tags.split(",")]
|
||||||
|
assert len(comment.tags) == 3
|
||||||
|
for tag in comment.tags:
|
||||||
|
tag: m.Tag
|
||||||
|
assert tag.name in splitted_tags
|
||||||
|
|
||||||
|
tags_from_db: m.Tag = m.Tag.query.all()
|
||||||
|
assert len(tags_from_db) == 5
|
||||||
|
|
||||||
|
|
||||||
def test_create_tags_on_interpretation_create_and_edit(client: FlaskClient):
|
def test_create_tags_on_interpretation_create_and_edit(client: FlaskClient):
|
||||||
_, user = login(client)
|
_, user = login(client)
|
||||||
create_test_book(user.id, 1)
|
create_test_book(user.id, 1)
|
||||||
|
|
||||||
book = m.Book.query.get(1)
|
book = db.session.get(m.Book, 1)
|
||||||
collection = m.Collection.query.get(1)
|
collection = db.session.get(m.Collection, 1)
|
||||||
section = m.Section.query.get(1)
|
section = db.session.get(m.Section, 1)
|
||||||
|
|
||||||
tags = "tag1,tag2,tag3"
|
tags = "tag1,tag2,tag3"
|
||||||
label_1 = "Test Interpretation #1 Label"
|
label_1 = "Test Interpretation #1 Label"
|
||||||
|
|
Loading…
Reference in New Issue