Commit 42e8970d authored by Robin Sonnabend's avatar Robin Sonnabend

Add descriptions for default tops (per protocol)

/close #64
parent a85e279e
"""empty message
Revision ID: a06cc03bdef4
Revises: 4b813bbbd8ef
Create Date: 2017-03-15 22:47:07.462793
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'a06cc03bdef4'
down_revision = '4b813bbbd8ef'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('localtops',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('protocol_id', sa.Integer(), nullable=True),
sa.Column('defaulttop_id', sa.Integer(), nullable=True),
sa.Column('description', sa.String(), nullable=True),
sa.ForeignKeyConstraint(['defaulttop_id'], ['defaulttops.id'], ),
sa.ForeignKeyConstraint(['protocol_id'], ['protocols.id'], ),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('localtops')
# ### end Alembic commands ###
......@@ -98,7 +98,6 @@ class ProtocolType(DatabaseModel):
return ((user is not None
and (self.private_group != "" and self.private_group in user.groups))
or self.has_admin_right(user))
def has_modify_right(self, user):
return ((user is not None
......@@ -135,6 +134,7 @@ class ProtocolType(DatabaseModel):
def get_wiki_infobox_title(self):
return "Vorlage:{}".format(self.get_wiki_infobox())
class Protocol(DatabaseModel):
__tablename__ = "protocols"
__model_name__ = "protocol"
......@@ -155,6 +155,7 @@ class Protocol(DatabaseModel):
documents = relationship("Document", backref=backref("protocol"), cascade="all, delete-orphan", order_by="Document.is_compiled")
errors = relationship("Error", backref=backref("protocol"), cascade="all, delete-orphan", order_by="Error.id")
metas = relationship("Meta", backref=backref("protocol"), cascade="all, delete-orphan")
localtops = relationship("LocalTOP", backref=backref("protocol"), cascade="all, delete-orphan")
def get_parent(self):
return self.protocoltype
......@@ -282,6 +283,17 @@ class Protocol(DatabaseModel):
self.todos.remove(todo)
db.session.delete(todo)
def get_tops(self):
tops_before, tops_after = [], []
if not self.has_nonplanned_tops():
for default_top in self.protocoltype.default_tops:
top = default_top.get_top(self)
if default_top.is_at_end():
tops_after.append(top)
else:
tops_before.append(top)
return tops_before + self.tops + tops_after
@event.listens_for(Protocol, "before_delete")
def on_protocol_delete(mapper, connection, protocol):
protocol.delete_orphan_todos()
......@@ -295,12 +307,30 @@ class DefaultTOP(DatabaseModel):
name = db.Column(db.String)
number = db.Column(db.Integer)
localtops = relationship("LocalTOP", backref=backref("defaulttop"), cascade="all, delete-orphan")
def get_parent(self):
return self.protocoltype
def is_at_end(self):
return self.number > 0
def get_localtop(self, protocol):
localtop = LocalTOP.query.filter_by(defaulttop_id=self.id,
protocol_id=protocol.id).first()
if localtop is None:
localtop = LocalTOP(protocol_id=protocol.id, defaulttop_id=self.id,
description="")
db.session.add(localtop)
db.session.commit()
return localtop
def get_top(self, protocol):
localtop = self.get_localtop(protocol)
top = TOP(protocol_id=protocol.id, name=self.name,
description=localtop.description)
return top
class TOP(DatabaseModel):
__tablename__ = "tops"
__model_name__ = "top"
......@@ -314,6 +344,17 @@ class TOP(DatabaseModel):
def get_parent(self):
return self.protocol
class LocalTOP(DatabaseModel):
__tablename__ = "localtops"
__model_name__ = "localtop"
id = db.Column(db.Integer, primary_key=True)
protocol_id = db.Column(db.Integer, db.ForeignKey("protocols.id"))
defaulttop_id = db.Column(db.Integer, db.ForeignKey("defaulttops.id"))
description = db.Column(db.String)
def get_parent(self):
return self.protocol
class Document(DatabaseModel):
__tablename__ = "documents"
__model_name__ = "document"
......
......@@ -23,8 +23,8 @@ import config
from shared import db, date_filter, datetime_filter, date_filter_long, date_filter_short, time_filter, time_filter_short, ldap_manager, security_manager, current_user, check_login, login_required, group_required, class_filter, needs_date_test, todostate_name_filter, code_filter, indent_tab_filter
from utils import is_past, mail_manager, url_manager, get_first_unused_int, set_etherpad_text, get_etherpad_text, split_terms, optional_int_arg
from decorators import db_lookup, require_public_view_right, require_private_view_right, require_modify_right, require_admin_right
from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error, TodoMail, DecisionDocument, TodoState, Meta, DefaultMeta, DecisionCategory
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm, TopForm, SearchForm, DecisionSearchForm, ProtocolSearchForm, TodoSearchForm, NewProtocolFileUploadForm, NewTodoForm, TodoForm, TodoMailForm, DefaultMetaForm, MetaForm, MergeTodosForm, DecisionCategoryForm
from models.database import ProtocolType, Protocol, DefaultTOP, TOP, LocalTOP, Document, Todo, Decision, MeetingReminder, Error, TodoMail, DecisionDocument, TodoState, Meta, DefaultMeta, DecisionCategory
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm, TopForm, LocalTopForm, SearchForm, DecisionSearchForm, ProtocolSearchForm, TodoSearchForm, NewProtocolFileUploadForm, NewTodoForm, TodoForm, TodoMailForm, DefaultMetaForm, MetaForm, MergeTodosForm, DecisionCategoryForm
from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable, DecisionsTable, TodoTable, ErrorTable, TodoMailsTable, DefaultMetasTable, DecisionCategoriesTable
from legacy import import_old_todos, import_old_protocols, import_old_todomails
......@@ -760,6 +760,18 @@ def move_top(top, diff):
flash("Die angegebene Differenz ist keine Zahl.", "alert-error")
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=top.protocol.id))
@app.route("/protocol/localtop/edit/<int:localtop_id>", methods=["GET", "POST"])
@login_required
@db_lookup(LocalTOP)
@require_modify_right()
def edit_localtop(localtop):
form = LocalTopForm(obj=localtop)
if form.validate_on_submit():
form.populate_obj(localtop)
db.session.commit()
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=localtop.protocol.id))
return render_template("localtop-edit.html", form=form, localtop=localtop)
def _get_page():
try:
page = request.args.get("page")
......
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if not default_top.is_at_end() %}
{{default_top.name}}
{% endif %}
{% endfor %}
{% endif %}
{% for top in protocol.tops %}
{% for top in protocol.get_tops() %}
{{top.name}}
{% endfor %}
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if default_top.is_at_end() %}
{{default_top.name}}
{% endif %}
{% endfor %}
{% endif %}
{% extends "layout.html" %}
{% from "macros.html" import render_form %}
{% block title %}TOP-Beschreibung bearbeiten{% endblock %}
{% block content %}
<div class="container">
<h3>{{localtop.defaulttop.name}}</h3>
{{render_form(form, action_url=url_for("edit_localtop", localtop_id=localtop.id, next=request.args.get("next") or url_for("show_protocol", protocol_id=localtop.protocol.id)), action_text="Ändern", textarea_rows=5)}}
</div>
{% endblock %}
......@@ -9,23 +9,9 @@ Zeit: von {{protocol.start_time|timify}} bis {{protocol.end_time|timify}}
{% endfor %}
Die Tagesordnung ist:
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if not default_top.is_at_end() %}
* {{default_top.name}}
{% endif %}
{% endfor %}
{% endif %}
{% for top in protocol.tops %}
* {{top.name }}
{% for top in protocol.get_tops() %}
* {{top.name}}
{% endfor %}
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if default_top.is_at_end() %}
* {{default_top.name}}
{% endif %}
{% endfor %}
{% endif %}
Beschlüsse:
{% if protocol.decisions|length > 0 %}
......
......@@ -32,7 +32,7 @@
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if not default_top.is_at_end() %}
{{-render_top(default_top)}}
{{-render_top(default_top.get_top(protocol), use_description=True)}}
{% endif %}
{% endfor %}
{% endif %}
......@@ -42,7 +42,7 @@
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if default_top.is_at_end() %}
{{render_top(default_top)}}
{{-render_top(default_top.get_top(protocol), use_description=True)}}
{% endif %}
{% endfor %}
{% endif %}
......@@ -2,7 +2,19 @@
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if not default_top.is_at_end() %}
<li>{{default_top.name}}</li>
{% set localtop = default_top.get_localtop(protocol) %}
<li{% if has_private_view_right and localtop.description is not none and localtop.description|length > 0 %} class="expansion-button" id="localtop-{{localtop.id}}" title="{{localtop.description}}"{% endif %}>
{{default_top.name}}
{% if not protocol.is_done() and has_modify_right %}
<a href="{{url_for('edit_localtop', localtop_id=localtop.id)}}">Ändern</a>
{% endif %}
{% if has_private_view_right and localtop.description is not none and localtop.description|length > 0 %}
<span class="glyphicon glyphicon-info-sign"></span>
<pre id="localtop-{{localtop.id}}-description" class="expansion-text">
{{-localtop.description-}}
</pre>
{% endif %}
</li>
{% endif %}
{% endfor %}
{% endif %}
......@@ -29,7 +41,19 @@
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if default_top.is_at_end() %}
<li>{{default_top.name}}</li>
{% set localtop = default_top.get_localtop(protocol) %}
<li{% if has_private_view_right and localtop.description is not none and localtop.description|length > 0 %} class="expansion-button" id="localtop-{{localtop.id}}" title="{{localtop.description}}"{% endif %}>
{{default_top.name}}
{% if not protocol.is_done() and has_modify_right %}
<a href="{{url_for('edit_localtop', localtop_id=localtop.id)}}">Ändern</a>
{% endif %}
{% if has_private_view_right and localtop.description is not none and localtop.description|length > 0 %}
<span class="glyphicon glyphicon-info-sign"></span>
<pre id="localtop-{{localtop.id}}-description" class="expansion-text">
{{-localtop.description-}}
</pre>
{% endif %}
</li>
{% endif %}
{% endfor %}
{% endif %}
......
Die nächste {{protocol.protocoltype.name}} findet am {{protocol.date|datify}} um {{protocol.protocoltype.usual_time|timify}} statt.
Die vorläufige Tagesordnung ist:
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if not default_top.is_at_end() %}
* {{default_top.name}}
{% endif %}
{% endfor %}
{% endif %}
{% for top in protocol.tops %}
{% for top in protocol.get_tops() %}
* {{top.name }}
{% endfor %}
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if default_top.is_at_end() %}
* {{default_top.name}}
{% endif %}
{% endfor %}
{% endif %}
{% if reminder.additional_text is not none %}
{{reminder.additional_text}}
{% endif %}
......@@ -190,6 +190,9 @@ class TopForm(FlaskForm):
number = IntegerField("Sortierung", validators=[InputRequired("Du musst eine Sortierung in der Reihenfolge angebene.")])
description = TextAreaField("Beschreibung")
class LocalTopForm(FlaskForm):
description = TextAreaField("Beschreibung")
class SearchForm(FlaskForm):
search = StringField("Suchbegriff")
protocoltype_id = SelectField("Typ", choices=[], coerce=int)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment