mirror of
https://github.com/logos-co/open-law.git
synced 2025-01-21 20:30:28 +00:00
version CUD
This commit is contained in:
parent
62c42b7144
commit
c8b7878d61
@ -1,4 +1,5 @@
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from flask import Flask, render_template
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
@ -110,8 +111,6 @@ def create_app(environment="development"):
|
||||
index_view=CustomAdminIndexView(),
|
||||
)
|
||||
|
||||
import warnings
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", "Fields missing from ruleset", UserWarning)
|
||||
|
||||
|
88
app/controllers/version.py
Normal file
88
app/controllers/version.py
Normal file
@ -0,0 +1,88 @@
|
||||
from app import models as m
|
||||
from app.logger import log
|
||||
|
||||
|
||||
def recursive_copy_collection(
|
||||
collection: m.Collection, parent_id: int, version_id: int
|
||||
):
|
||||
collection_copy = m.Collection(
|
||||
label=collection.label,
|
||||
about=collection.about,
|
||||
is_root=collection.is_root,
|
||||
is_leaf=collection.is_leaf,
|
||||
position=collection.position,
|
||||
parent_id=parent_id,
|
||||
version_id=version_id,
|
||||
copy_of=collection.id,
|
||||
)
|
||||
log(log.INFO, "Create copy of collection [%s]", collection)
|
||||
collection_copy.save()
|
||||
|
||||
if collection.active_sections:
|
||||
for section in collection.active_sections:
|
||||
section: m.Section
|
||||
section_copy = m.Section(
|
||||
label=section.label,
|
||||
collection_id=collection_copy.id,
|
||||
user_id=section.user_id,
|
||||
version_id=version_id,
|
||||
position=section.position,
|
||||
copy_of=section.id,
|
||||
)
|
||||
log(log.INFO, "Create copy of section [%s]", section)
|
||||
section_copy.save()
|
||||
|
||||
interpretation: m.Interpretation = section.approved_interpretation
|
||||
if not interpretation:
|
||||
continue
|
||||
|
||||
interpretation_copy = m.Interpretation(
|
||||
text=interpretation.text,
|
||||
plain_text=interpretation.plain_text,
|
||||
approved=interpretation.approved,
|
||||
user_id=interpretation.user_id,
|
||||
section_id=section_copy.id,
|
||||
copy_of=interpretation.id,
|
||||
)
|
||||
log(log.INFO, "Create copy of interpretation [%s]", interpretation_copy)
|
||||
interpretation_copy.save()
|
||||
|
||||
comments: list[m.Comment] = section.approved_comments
|
||||
for comment in comments:
|
||||
comment_copy = m.Comment(
|
||||
text=comment.text,
|
||||
approved=comment.approved,
|
||||
edited=comment.edited,
|
||||
user_id=comment.user_id,
|
||||
interpretation_id=interpretation_copy.id,
|
||||
copy_of=comment.id,
|
||||
)
|
||||
log(log.INFO, "Create copy of comment [%s]", comment)
|
||||
comment_copy.save()
|
||||
|
||||
elif collection.active_children:
|
||||
for child in collection.active_children:
|
||||
recursive_copy_collection(child, collection_copy.id, version_id)
|
||||
|
||||
|
||||
def create_new_version(book: m.Book, semver: str):
|
||||
book_active_version: m.BookVersion = book.active_version
|
||||
book_root_collection: m.Collection = book_active_version.root_collection
|
||||
|
||||
version: m.BookVersion = m.BookVersion(
|
||||
semver=semver, derivative_id=book.active_version.id, book_id=book.id
|
||||
)
|
||||
log(log.INFO, "Create new version for book [%s]", book)
|
||||
version.save()
|
||||
|
||||
root_collection = m.Collection(
|
||||
label="Root Collection",
|
||||
version_id=version.id,
|
||||
is_root=True,
|
||||
copy_of=book_root_collection.id,
|
||||
).save()
|
||||
|
||||
for collection in book_root_collection.active_children:
|
||||
recursive_copy_collection(collection, root_collection.id, version.id)
|
||||
|
||||
return version
|
@ -18,4 +18,4 @@ from .comment import CreateCommentForm
|
||||
from .vote import VoteForm
|
||||
from .comment import CreateCommentForm, DeleteCommentForm, EditCommentForm
|
||||
from .permission import EditPermissionForm
|
||||
from .version import EditVersionForm, DeleteVersionForm
|
||||
from .version import EditVersionForm, DeleteVersionForm, CreateVersionForm
|
||||
|
@ -2,8 +2,6 @@ from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, SubmitField, IntegerField, ValidationError
|
||||
from wtforms.validators import DataRequired
|
||||
|
||||
from app.controllers import clean_html
|
||||
from app.logger import log
|
||||
from app import models as m, db
|
||||
|
||||
|
||||
@ -31,3 +29,8 @@ class EditVersionForm(BaseVersionForm):
|
||||
|
||||
class DeleteVersionForm(BaseVersionForm):
|
||||
submit = SubmitField("Delete")
|
||||
|
||||
|
||||
class CreateVersionForm(FlaskForm):
|
||||
semver = StringField("Semver", validators=[DataRequired()])
|
||||
submit = SubmitField("Delete")
|
||||
|
@ -12,6 +12,7 @@ class Collection(BaseModel):
|
||||
is_root = db.Column(db.Boolean, default=False)
|
||||
is_leaf = db.Column(db.Boolean, default=False)
|
||||
position = db.Column(db.Integer, default=-1, nullable=True)
|
||||
copy_of = db.Column(db.Integer, default=0, nullable=True)
|
||||
|
||||
# Foreign keys
|
||||
version_id = db.Column(db.ForeignKey("book_versions.id"))
|
||||
|
@ -12,6 +12,7 @@ class Comment(BaseModel):
|
||||
text = db.Column(db.Text, unique=False, nullable=False)
|
||||
approved = db.Column(db.Boolean, default=False)
|
||||
edited = db.Column(db.Boolean, default=False)
|
||||
copy_of = db.Column(db.Integer, default=0, nullable=True)
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.ForeignKey("users.id"))
|
||||
|
@ -10,6 +10,7 @@ class Interpretation(BaseModel):
|
||||
text = db.Column(db.Text, unique=False, nullable=False)
|
||||
plain_text = db.Column(db.Text, unique=False)
|
||||
approved = db.Column(db.Boolean, default=False)
|
||||
copy_of = db.Column(db.Integer, default=0, nullable=True)
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.ForeignKey("users.id"))
|
||||
|
@ -13,12 +13,13 @@ class Section(BaseModel):
|
||||
__tablename__ = "sections"
|
||||
|
||||
label = db.Column(db.String(256), unique=False, nullable=False)
|
||||
position = db.Column(db.Integer, default=-1, nullable=True)
|
||||
copy_of = db.Column(db.Integer, default=0, nullable=True)
|
||||
|
||||
# Foreign keys
|
||||
collection_id = db.Column(db.ForeignKey("collections.id"))
|
||||
user_id = db.Column(db.ForeignKey("users.id"))
|
||||
version_id = db.Column(db.ForeignKey("book_versions.id"))
|
||||
position = db.Column(db.Integer, default=-1, nullable=True)
|
||||
|
||||
# Relationships
|
||||
collection = db.relationship("Collection", viewonly=True)
|
||||
|
File diff suppressed because one or more lines are too long
24
app/templates/book/modals/add_version_modal.html
Normal file
24
app/templates/book/modals/add_version_modal.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!-- Add contributor modal -->
|
||||
<!-- prettier-ignore-->
|
||||
<div id="edit-version-label-modal" tabindex="-1" aria-hidden="true" class="fixed top-0 left-0 right-0 z-[150] hidden w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full">
|
||||
<div class="relative w-full max-w-2xl max-h-full">
|
||||
<!-- Modal content -->
|
||||
<form action="{{ url_for('book.edit_version', book_id=book.id) }}" method="post" class="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||
{{ form_hidden_tag() }}
|
||||
<!-- Modal header -->
|
||||
<input type="hidden" name="version_id" id="version_id" value="0" class="version-id-input"/>
|
||||
|
||||
<div class="p-6 space-y-6">
|
||||
<div>
|
||||
<label for="semver-input" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Name</label>
|
||||
<input type="text" name="semver" id="semver-input" class="version-semver-input 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="1.0.0" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal footer -->
|
||||
<div class="flex items-center p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600">
|
||||
<button name="submit" type="submit" 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 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -2,7 +2,7 @@
|
||||
<div id="delete_version_modal" tabindex="-1" aria-hidden="true" class="fixed top-0 left-0 right-0 z-[150] hidden w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full">
|
||||
<div class="relative w-full max-w-2xl max-h-full">
|
||||
<!-- Modal content -->
|
||||
<form action="{{ url_for('book.delete_contributor', book_id=book.id) }}" id="delete_version_modal_form" method="post" class="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||
<form action="{{ url_for('book.delete_version', book_id=book.id) }}" id="delete_version_modal_form" method="post" class="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||
{{ form_hidden_tag() }}
|
||||
<!-- Modal header -->
|
||||
<input type="hidden" name="version_id" id="version_id" value="0" class="delete-version-id-input"/>
|
||||
|
@ -1,13 +1,11 @@
|
||||
<!-- Add contributor modal -->
|
||||
<!-- prettier-ignore-->
|
||||
<div id="edit-version-label-modal" tabindex="-1" aria-hidden="true" class="fixed top-0 left-0 right-0 z-[150] hidden w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full">
|
||||
<div id="add-version-modal" tabindex="-1" aria-hidden="true" class="fixed top-0 left-0 right-0 z-[150] hidden w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full">
|
||||
<div class="relative w-full max-w-2xl max-h-full">
|
||||
<!-- Modal content -->
|
||||
<form action="{{ url_for('book.edit_version', book_id=book.id) }}" method="post" class="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||
<form action="{{ url_for('book.create_version', book_id=book.id) }}" method="post" class="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||
{{ form_hidden_tag() }}
|
||||
<!-- Modal header -->
|
||||
<input type="hidden" name="version_id" id="version_id" value="0" class="version-id-input"/>
|
||||
|
||||
<div class="p-6 space-y-6">
|
||||
<div>
|
||||
<label for="semver-input" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Name</label>
|
||||
|
@ -12,6 +12,7 @@
|
||||
{% include 'book/modals/delete_contributor_modal.html' %}
|
||||
{% include 'book/modals/edit_version_label_modal.html' %}
|
||||
{% include 'book/modals/delete_version_modal.html' %}
|
||||
{% include 'book/modals/edit_version_label_modal.html' %}
|
||||
|
||||
<!-- Hide right_sidebar -->
|
||||
<!-- prettier-ignore -->
|
||||
@ -188,7 +189,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for version in book.versions %}
|
||||
{% for version in book.versions if not version.is_deleted and not version.is_active %}
|
||||
<tr class="bg-white border-b dark:bg-gray-900 dark:border-gray-700">
|
||||
<td class="px-6 truncate max-w-[280]">{{ version.semver }}</td>
|
||||
<td class="px-6"> {{ version.created_at }} </td>
|
||||
@ -198,7 +199,7 @@
|
||||
</button>
|
||||
</td>
|
||||
<td class="px-4 py-4">
|
||||
<button type="button" data-modal-target="delete_version_modal" data-modal-toggle="delete_version_modal" class="delete-version-btn text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-sm rounded-lg text-sm px-5 py-1.5 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-none dark:focus:ring-red-800">
|
||||
<button type="button" data-version-id="{{ version.id }}" data-modal-target="delete_version_modal" data-modal-toggle="delete_version_modal" class="delete-version-btn text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-sm rounded-lg text-sm px-5 py-1.5 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-none dark:focus:ring-red-800">
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
@ -207,7 +208,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button type="button" data-modal-target="add-version-modal" data-modal-toggle="add-versions-modal" class="add-versions-btn 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-4 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
||||
<button type="button" data-modal-target="add-version-modal" data-modal-toggle="add-version-modal" class="add-versions-btn 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-4 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
||||
<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-1"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> </svg>
|
||||
New Version
|
||||
</button>
|
||||
|
@ -1,50 +1,38 @@
|
||||
from flask import render_template, flash, redirect, url_for, request
|
||||
from flask import flash, redirect, url_for
|
||||
from flask_login import login_required, current_user
|
||||
from sqlalchemy import and_, or_
|
||||
|
||||
from app.controllers import (
|
||||
create_pagination,
|
||||
register_book_verify_route,
|
||||
)
|
||||
from app.controllers.tags import (
|
||||
set_book_tags,
|
||||
)
|
||||
from app.controllers.delete_nested_book_entities import (
|
||||
delete_nested_book_entities,
|
||||
)
|
||||
from app.controllers.create_access_groups import (
|
||||
create_editor_group,
|
||||
create_moderator_group,
|
||||
)
|
||||
from app.controllers.require_permission import require_permission
|
||||
|
||||
from app import models as m, db, forms as f
|
||||
from app.controllers.version import create_new_version
|
||||
from app.controllers.delete_nested_book_entities import delete_nested_version_entities
|
||||
from app.logger import log
|
||||
from .bp import bp
|
||||
|
||||
|
||||
# @bp.route("/all", methods=["GET"])
|
||||
# def get_all():
|
||||
# log(log.INFO, "Create query for books")
|
||||
# books: m.Book = m.Book.query.filter(m.Book.is_deleted is not False).order_by(
|
||||
# m.Book.id
|
||||
# )
|
||||
# log(log.INFO, "Create pagination for books")
|
||||
|
||||
# pagination = create_pagination(total=books.count())
|
||||
# log(log.INFO, "Returning data for front end")
|
||||
|
||||
# return render_template(
|
||||
# "book/all.html",
|
||||
# books=books.paginate(page=pagination.page, per_page=pagination.per_page),
|
||||
# page=pagination,
|
||||
# all_books=True,
|
||||
# )
|
||||
|
||||
|
||||
@bp.route("/create_version", methods=["POST"])
|
||||
@bp.route("/<int:book_id>/create_version", methods=["POST"])
|
||||
@login_required
|
||||
def create_version():
|
||||
raise NotImplementedError
|
||||
def create_version(book_id):
|
||||
form: f.CreateVersionForm = f.CreateVersionForm()
|
||||
|
||||
redirect_url = url_for("book.settings", selected_tab="versions", book_id=book_id)
|
||||
if form.validate_on_submit():
|
||||
book = db.session.get(m.Book, book_id)
|
||||
if book.user_id != current_user.id:
|
||||
flash("You are not owner of this book", "warning")
|
||||
return redirect(redirect_url)
|
||||
create_new_version(book, form.semver.data)
|
||||
flash("Success!", "success")
|
||||
return redirect(redirect_url)
|
||||
else:
|
||||
log(log.ERROR, "Create version 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)
|
||||
|
||||
|
||||
@bp.route("/<int:book_id>/edit_version", methods=["POST"])
|
||||
@ -75,7 +63,7 @@ def edit_version(book_id: int):
|
||||
flash("Success!", "success")
|
||||
return redirect(redirect_url)
|
||||
else:
|
||||
log(log.ERROR, "Section edit errors: [%s]", form.errors)
|
||||
log(log.ERROR, "Edit version errors: [%s]", form.errors)
|
||||
for field, errors in form.errors.items():
|
||||
field_label = form._fields[field].label.text
|
||||
for error in errors:
|
||||
@ -105,14 +93,15 @@ def delete_version(book_id: int):
|
||||
flash("You cant delete active version", "warning")
|
||||
return redirect(redirect_url)
|
||||
|
||||
# TODO delete nested items
|
||||
# log(log.INFO, "Edit version [%s]", version)
|
||||
# version.save()
|
||||
version.is_deleted = True
|
||||
delete_nested_version_entities(version)
|
||||
log(log.INFO, "Delete version [%s]", version)
|
||||
version.save()
|
||||
|
||||
flash("Success!", "success")
|
||||
return redirect(redirect_url)
|
||||
else:
|
||||
log(log.ERROR, "Section edit errors: [%s]", form.errors)
|
||||
log(log.ERROR, "Delete version errors: [%s]", form.errors)
|
||||
for field, errors in form.errors.items():
|
||||
field_label = form._fields[field].label.text
|
||||
for error in errors:
|
||||
|
@ -10,25 +10,27 @@ import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '03e8384a23e1'
|
||||
down_revision = 'a41f004cad1a'
|
||||
revision = "03e8384a23e1"
|
||||
down_revision = "a41f004cad1a"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('book_versions', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('is_active', sa.Boolean(), nullable=True))
|
||||
batch_op.drop_column('exported')
|
||||
with op.batch_alter_table("book_versions", schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column("is_active", sa.Boolean(), nullable=True))
|
||||
batch_op.drop_column("exported")
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('book_versions', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('exported', sa.BOOLEAN(), autoincrement=False, nullable=True))
|
||||
batch_op.drop_column('is_active')
|
||||
with op.batch_alter_table("book_versions", schema=None) as batch_op:
|
||||
batch_op.add_column(
|
||||
sa.Column("exported", sa.BOOLEAN(), autoincrement=False, nullable=True)
|
||||
)
|
||||
batch_op.drop_column("is_active")
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
50
migrations/versions/ef2254f9bc92_copy_of_fields.py
Normal file
50
migrations/versions/ef2254f9bc92_copy_of_fields.py
Normal file
@ -0,0 +1,50 @@
|
||||
"""copy of fields
|
||||
|
||||
Revision ID: ef2254f9bc92
|
||||
Revises: 03e8384a23e1
|
||||
Create Date: 2023-06-13 09:43:26.575245
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "ef2254f9bc92"
|
||||
down_revision = "03e8384a23e1"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("collections", schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column("copy_of", sa.Integer(), nullable=True))
|
||||
|
||||
with op.batch_alter_table("comments", schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column("copy_of", sa.Integer(), nullable=True))
|
||||
|
||||
with op.batch_alter_table("interpretations", schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column("copy_of", sa.Integer(), nullable=True))
|
||||
|
||||
with op.batch_alter_table("sections", schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column("copy_of", sa.Integer(), nullable=True))
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("sections", schema=None) as batch_op:
|
||||
batch_op.drop_column("copy_of")
|
||||
|
||||
with op.batch_alter_table("interpretations", schema=None) as batch_op:
|
||||
batch_op.drop_column("copy_of")
|
||||
|
||||
with op.batch_alter_table("comments", schema=None) as batch_op:
|
||||
batch_op.drop_column("copy_of")
|
||||
|
||||
with op.batch_alter_table("collections", schema=None) as batch_op:
|
||||
batch_op.drop_column("copy_of")
|
||||
|
||||
# ### end Alembic commands ###
|
@ -6,9 +6,10 @@ export function initDeleteVersion() {
|
||||
if (versionIdInput) {
|
||||
const deleteBtns = document.querySelectorAll('.delete-version-btn');
|
||||
deleteBtns.forEach(el => {
|
||||
const versionId = el.getAttribute('data-version-id');
|
||||
|
||||
versionIdInput.value = versionId;
|
||||
el.addEventListener('click', () => {
|
||||
const versionId = el.getAttribute('data-version-id');
|
||||
versionIdInput.value = versionId;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,13 @@ export function initEditVersion() {
|
||||
if (versionIdInput && versionSemverInput) {
|
||||
const editBtns = document.querySelectorAll('.edit-version-label-btns');
|
||||
editBtns.forEach(el => {
|
||||
const versionId = el.getAttribute('data-version-id');
|
||||
const versionSemver = el.getAttribute('data-version-semver');
|
||||
el.addEventListener('click', () => {
|
||||
const versionId = el.getAttribute('data-version-id');
|
||||
const versionSemver = el.getAttribute('data-version-semver');
|
||||
|
||||
versionIdInput.value = versionId;
|
||||
versionSemverInput.value = versionSemver;
|
||||
versionIdInput.value = versionId;
|
||||
versionSemverInput.value = versionSemver;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
from flask import current_app as Response
|
||||
from flask.testing import FlaskClient, FlaskCliRunner
|
||||
from flask.testing import FlaskClient
|
||||
|
||||
from app import models as m, db
|
||||
from app.controllers.create_access_groups import create_moderator_group
|
||||
from tests.utils import (
|
||||
login,
|
||||
logout,
|
||||
create_book,
|
||||
check_if_nested_version_entities_is_deleted,
|
||||
)
|
||||
|
||||
|
||||
@ -128,17 +128,34 @@ def test_delete_version(client: FlaskClient):
|
||||
assert response.status_code == 200
|
||||
assert b"Invalid version id" in response.data
|
||||
|
||||
# TODO improve test to check if nested items are deleted
|
||||
# response: Response = client.post(
|
||||
# f"/book/{book.id}/delete_version",
|
||||
# data=dict(
|
||||
# version_id=book_2.versions[0].id,
|
||||
# ),
|
||||
# follow_redirects=True,
|
||||
# )
|
||||
response: Response = client.post(
|
||||
f"/book/{book_2.id}/create_version",
|
||||
data=dict(
|
||||
semver="MyVer",
|
||||
),
|
||||
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
|
||||
assert len(book_2.versions) == 2
|
||||
|
||||
new_version: m.BookVersion = book_2.versions[-1]
|
||||
|
||||
for collection in new_version.root_collection.active_children:
|
||||
recursive_copy_collection(collection)
|
||||
|
||||
response: Response = client.post(
|
||||
f"/book/{book_2.id}/delete_version",
|
||||
data=dict(
|
||||
version_id=new_version.id,
|
||||
),
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert b"Success" in response.data
|
||||
check_if_nested_version_entities_is_deleted(new_version)
|
||||
|
||||
logout(client)
|
||||
login(client, username="test_user")
|
||||
@ -153,3 +170,89 @@ def test_delete_version(client: FlaskClient):
|
||||
|
||||
assert response.status_code == 200
|
||||
assert b"You are not owner of this book" in response.data
|
||||
|
||||
|
||||
def recursive_copy_collection(collection: m.Collection):
|
||||
collection: m.Collection
|
||||
assert collection.copy_of
|
||||
|
||||
copy_of: m.Collection = db.session.get(m.Collection, collection.copy_of)
|
||||
assert collection.label == copy_of.label
|
||||
assert collection.about == copy_of.about
|
||||
assert collection.is_root == copy_of.is_root
|
||||
assert collection.is_leaf == copy_of.is_leaf
|
||||
assert collection.position == copy_of.position
|
||||
|
||||
if collection.active_sections:
|
||||
for section in collection.active_sections:
|
||||
section: m.Section
|
||||
copy_of = db.session.get(m.Section, section.copy_of)
|
||||
assert section.label == copy_of.label
|
||||
assert section.position == copy_of.position
|
||||
|
||||
interpretations: list[m.Interpretation] = section.approved_interpretation
|
||||
for interpretation in interpretations:
|
||||
interpretation: m.Interpretation
|
||||
assert interpretation.copy_of
|
||||
|
||||
copy_of: m.Interpretation = db.session.get(
|
||||
m.Interpretation, interpretation.copy_of
|
||||
)
|
||||
assert interpretation.text == copy_of.text
|
||||
assert interpretation.plain_text == copy_of.plain_text
|
||||
assert interpretation.approved == copy_of.approved
|
||||
|
||||
comments: list[m.Comment] = section.approved_comments
|
||||
for comment in comments:
|
||||
comment: m.Comment
|
||||
assert comment.copy_of
|
||||
|
||||
copy_of: m.Comment = db.session.get(m.Comment, comment.copy_of)
|
||||
assert comment.text == copy_of.text
|
||||
assert comment.approved == copy_of.approved
|
||||
assert comment.edited == copy_of.edited
|
||||
|
||||
elif collection.active_children:
|
||||
for child in collection.active_children:
|
||||
recursive_copy_collection(child)
|
||||
|
||||
|
||||
def test_create_version(client):
|
||||
login(client)
|
||||
|
||||
book: m.Book = create_book(client)
|
||||
book_2: m.Book = create_book(client)
|
||||
|
||||
logout(client)
|
||||
login(client, "test_2")
|
||||
|
||||
response: Response = client.post(
|
||||
f"/book/{book.id}/create_version",
|
||||
data=dict(
|
||||
semver="MyVer",
|
||||
),
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert b"You are not owner of this book" in response.data
|
||||
|
||||
logout(client)
|
||||
login(client)
|
||||
|
||||
response: Response = client.post(
|
||||
f"/book/{book.id}/create_version",
|
||||
data=dict(
|
||||
semver="MyVer",
|
||||
),
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert b"Success" in response.data
|
||||
assert len(book.versions) == 2
|
||||
|
||||
new_version: m.BookVersion = book.versions[-1]
|
||||
|
||||
for collection in new_version.root_collection.active_children:
|
||||
recursive_copy_collection(collection)
|
||||
|
Loading…
x
Reference in New Issue
Block a user