mirror of https://github.com/logos-co/open-law.git
Merge pull request #159 from Simple2B/svyat/feat/version_form
Svyat/feat/version form
This commit is contained in:
commit
5576e59678
|
@ -54,3 +54,43 @@ def fork_book(book: m.Book, label: str, about: str):
|
|||
copy_book_version(book_copy, version)
|
||||
|
||||
return version
|
||||
|
||||
|
||||
def fork_version(book: m.Book, label: str, about: str, version: m.BookVersion):
|
||||
book_copy: m.Book = m.Book(
|
||||
label=label, about=about, user_id=current_user.id, original_book_id=book.id
|
||||
)
|
||||
log(log.INFO, "Create fork of book [%s]", book)
|
||||
book_copy.save()
|
||||
|
||||
active_version = m.BookVersion(
|
||||
semver="Active", book_id=book_copy.id, is_active=True
|
||||
).save()
|
||||
log(log.INFO, "Create new version for book [%s]", book)
|
||||
active_version.save()
|
||||
|
||||
root_collection = m.Collection(
|
||||
label="Root Collection", version_id=active_version.id, is_root=True
|
||||
).save()
|
||||
|
||||
# access groups
|
||||
editor_access_group = create_editor_group(book_id=book_copy.id)
|
||||
moderator_access_group = create_moderator_group(book_id=book_copy.id)
|
||||
access_groups = [editor_access_group, moderator_access_group]
|
||||
|
||||
for access_group in access_groups:
|
||||
m.BookAccessGroups(book_id=book_copy.id, access_group_id=access_group.id).save()
|
||||
m.CollectionAccessGroups(
|
||||
collection_id=root_collection.id, access_group_id=access_group.id
|
||||
).save()
|
||||
# -------------
|
||||
|
||||
# tags
|
||||
for tag in book.tags:
|
||||
m.BookTags(tag_id=tag.id, book_id=book_copy.id).save()
|
||||
# ----
|
||||
|
||||
for collection in version.root_collection.active_children:
|
||||
recursive_copy_collection(
|
||||
collection, root_collection.id, active_version.id, False, book=book_copy
|
||||
)
|
||||
|
|
|
@ -19,4 +19,4 @@ from .vote import VoteForm
|
|||
from .comment import CreateCommentForm, DeleteCommentForm, EditCommentForm
|
||||
from .permission import EditPermissionForm
|
||||
from .version import EditVersionForm, DeleteVersionForm, CreateVersionForm
|
||||
from .fork import ForkBookForm
|
||||
from .fork import ForkBookForm, ForkVersionForm
|
||||
|
|
|
@ -6,3 +6,9 @@ from wtforms.validators import DataRequired
|
|||
class ForkBookForm(FlaskForm):
|
||||
label = StringField("Fork Label", [DataRequired()])
|
||||
about = StringField("Fork About")
|
||||
|
||||
|
||||
class ForkVersionForm(FlaskForm):
|
||||
version_id = StringField("Version ID", [DataRequired()])
|
||||
label = StringField("Fork Label", [DataRequired()])
|
||||
about = StringField("Fork About")
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -15,6 +15,8 @@
|
|||
{% include 'book/modals/delete_sub_collection_modal.html' %}
|
||||
{% include 'book/modals/add_section_modal.html' %}
|
||||
{% include 'book/modals/delete_section_modal.html' %}
|
||||
{% else %}
|
||||
{% include 'book/modals/fork_version_modal.html' %}
|
||||
{% endif %}
|
||||
|
||||
<div class="flex">
|
||||
|
@ -139,11 +141,16 @@
|
|||
</p>
|
||||
|
||||
{% if version %}
|
||||
<p class="flex text-s font-bold mb-3">
|
||||
<!-- prettier-ignore -->
|
||||
<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="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z" /> </svg>
|
||||
Version: {{ version.semver.title() }}
|
||||
</p>
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<p class="flex text-s font-bold mb-3">
|
||||
<!-- prettier-ignore -->
|
||||
<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="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z" /> </svg>
|
||||
Version: {{ version.semver.title() }}
|
||||
</p>
|
||||
<button type="button" data-modal-target="fork-version-modal" data-modal-toggle="fork-version-modal" class="border-2 border-black focus:outline-none font-medium rounded-lg text-sm px-3 py-2 text-center mr-2 mb-2 dark:border-white dark:text-white dark:focus:ring-white">
|
||||
+ Create a new fork
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="flex justify-between item-center">
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<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')}}
|
||||
Last updated on {{book.active_version.updated_at.strftime('%B %d, %Y')}}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="flex ml-auto align-center justify-center space-x-3">
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<!-- Add book modal -->
|
||||
<!-- prettier-ignore-->
|
||||
<div id="fork-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.fork_specific_version', book_id=book.id) }}" method="post" class="prevent-submit-on-enter relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||
{{ form_hidden_tag() }}
|
||||
<input type="hidden" name="version_id" id="version_id" value="{{version.id}}" />
|
||||
<!-- Modal header -->
|
||||
<div class="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600">
|
||||
<h3 class="text-xl font-semibold text-gray-900 dark:text-white"> Create a new fork of version "{{ version.semver.title() }}"</h3>
|
||||
<button id="modalAddCloseButton" data-modal-hide="fork-version-modal" type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white"> <svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path> </svg> </button>
|
||||
</div>
|
||||
<!-- Modal body -->
|
||||
<div class="p-6">
|
||||
<p class="dark:text-white mb-6">
|
||||
A fork is a copy of a book. Forking a book allows you to freely experiment with changes without affecting the original project.
|
||||
</p>
|
||||
<p class="dark:text-white">
|
||||
By default, forks are named the same as their upstream project. You can customize the name to distinguish it further.
|
||||
</p>
|
||||
</div>
|
||||
<div class="p-6 space-y-6 pt-0">
|
||||
<div>
|
||||
<div class="col-span-6 sm:col-span-3 mb-2">
|
||||
<label for="label" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Label</label >
|
||||
<input value="{{book.label}}" type="text" name="label" id="label" maxlength="256" minlength="6" maxlength="256" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Name" required />
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="about" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white" >About</label >
|
||||
<textarea type="text" name="about" id="about" maxlength="640" class="max-h-40 shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Optional">{{book.about}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6 pt-0">
|
||||
<p class="dark:text-white">
|
||||
You are creating a fork in your personal account.
|
||||
</p>
|
||||
</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">Create fork</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -67,7 +67,7 @@
|
|||
<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')}}
|
||||
Last updated on {{book.active_version.updated_at.strftime('%B %d, %Y')}}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="flex ml-auto align-center justify-center space-x-3">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
{% block content %}
|
||||
|
||||
{% include 'book/modals/fork_book_modal.html' %}
|
||||
{% include 'book/modals/fork_book_modal.html' %}
|
||||
|
||||
<div class="border-b border-gray-200 dark:border-gray-700 pt-3">
|
||||
<!-- prettier-ignore -->
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<dt class="mb-2"><a class="flex flex-col" href="{{url_for('book.collection_view',book_id=book.id)}}">{{book.label}}</a></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 by <a href="{{url_for('user.profile',user_id=book.owner.id)}}" class=" text-blue-500 {% if book.owner.is_deleted %}line-through{% endif %}">{{book.owner.username}}</a> on {{book.versions[-1].updated_at.strftime('%B %d, %Y')}} </p>
|
||||
<p> Last updated by <a href="{{url_for('user.profile',user_id=book.owner.id)}}" class=" text-blue-500 {% if book.owner.is_deleted %}line-through{% endif %}">{{book.owner.username}}</a> on {{book.active_version.updated_at.strftime('%B %d, %Y')}} </p>
|
||||
{% endif %}
|
||||
<div class="flex ml-auto align-center justify-center space-x-3">
|
||||
<span class="book-star-block space-x-0.5 flex items-center">
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<dt class="mb-2"><a class="flex flex-col pb-4" href="{{url_for('book.collection_view',book_id=book.id)}}">{{book.label}}</a></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 by <a href="{{url_for('user.profile',user_id=book.owner.id)}}" class=" text-blue-500 {% if book.owner.is_deleted %}line-through{% endif %}">{{book.owner.username}}</a> on {{book.versions[-1].updated_at.strftime('%B %d, %Y')}} </p>
|
||||
<p> Last updated by <a href="{{url_for('user.profile',user_id=book.owner.id)}}" class=" text-blue-500 {% if book.owner.is_deleted %}line-through{% endif %}">{{book.owner.username}}</a> on {{book.active_version.updated_at.strftime('%B %d, %Y')}} </p>
|
||||
{% endif %}
|
||||
<div class="flex ml-auto align-center justify-center space-x-3">
|
||||
<span class="book-star-block space-x-0.5 flex items-center">
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<dt class="mb-2"><a class="flex flex-col pb-4" href="{{url_for('book.collection_view',book_id=book.id)}}">{{book.label}}</a></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 by <a href="{{url_for('user.profile',user_id=book.owner.id)}}" class=" text-blue-500 {% if book.owner.is_deleted %}line-through{% endif %}">{{book.owner.username}}</a> on {{book.versions[-1].updated_at.strftime('%B %d, %Y')}} </p>
|
||||
<p> Last updated by <a href="{{url_for('user.profile',user_id=book.owner.id)}}" class=" text-blue-500 {% if book.owner.is_deleted %}line-through{% endif %}">{{book.owner.username}}</a> on {{book.active_version.updated_at.strftime('%B %d, %Y')}} </p>
|
||||
{% endif %}
|
||||
<div class="flex ml-auto align-center justify-center space-x-3">
|
||||
<span class="book-star-block space-x-0.5 flex items-center">
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<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')}}
|
||||
Last updated on {{book.active_version.updated_at.strftime('%B %d, %Y')}}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="flex ml-auto align-center justify-center space-x-3">
|
||||
|
|
|
@ -80,7 +80,7 @@ def collection_create(book_id: int, collection_id: int | None = None):
|
|||
collection = collection.filter_by(parent_id=collection_id)
|
||||
else:
|
||||
collection = collection.filter_by(
|
||||
parent_id=book.versions[-1].root_collection.id
|
||||
parent_id=book.active_version.root_collection.id
|
||||
)
|
||||
collection = collection.first()
|
||||
|
||||
|
@ -102,7 +102,7 @@ def collection_create(book_id: int, collection_id: int | None = None):
|
|||
collection: m.Collection = m.Collection(
|
||||
label=label,
|
||||
about=form.about.data,
|
||||
parent_id=book.versions[-1].root_collection.id,
|
||||
parent_id=book.active_version.root_collection.id,
|
||||
version_id=book.active_version.id,
|
||||
position=position,
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@ from flask import flash, redirect, url_for
|
|||
from flask_login import login_required
|
||||
|
||||
from app import models as m, db, forms as f
|
||||
from app.controllers.fork import fork_book
|
||||
from app.controllers.fork import fork_book, fork_version
|
||||
from app.controllers.error_flashes import create_error_flash
|
||||
from app.logger import log
|
||||
from .bp import bp
|
||||
|
@ -23,3 +23,26 @@ def fork(book_id):
|
|||
log(log.ERROR, "Fork book errors: [%s]", form.errors)
|
||||
create_error_flash(form)
|
||||
return redirect(redirect_url)
|
||||
|
||||
|
||||
@bp.route("/<int:book_id>/fork_version", methods=["POST"])
|
||||
@login_required
|
||||
def fork_specific_version(book_id):
|
||||
form: f.ForkVersionForm = f.ForkVersionForm()
|
||||
|
||||
book = db.session.get(m.Book, book_id)
|
||||
redirect_url = url_for("book.statistic_view", book_id=book.id, active_tab="forks")
|
||||
if form.validate_on_submit():
|
||||
book_version: m.BookVersion = db.session.get(
|
||||
m.BookVersion, form.version_id.data
|
||||
)
|
||||
if not book_version or book_version.book_id != book_id:
|
||||
flash("Invalid version data", "warning")
|
||||
else:
|
||||
fork_version(book, form.label.data, form.about.data, book_version)
|
||||
flash("Success!", "success")
|
||||
return redirect(redirect_url)
|
||||
else:
|
||||
log(log.ERROR, "Fork book errors: [%s]", form.errors)
|
||||
create_error_flash(form)
|
||||
return redirect(redirect_url)
|
||||
|
|
Loading…
Reference in New Issue