Commit 6ebc35e9 authored by Robin Sonnabend's avatar Robin Sonnabend
Browse files

Managing TOPs

parent 6936e129
......@@ -15,9 +15,9 @@ from datetime import datetime
import config
from shared import db, date_filter, datetime_filter, date_filter_long, time_filter, ldap_manager, security_manager, current_user, check_login, login_required, group_required
from utils import is_past, mail_manager, url_manager
from utils import is_past, mail_manager, url_manager, get_first_unused_int
from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm, TopForm
from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable
app = Flask(__name__)
......@@ -188,7 +188,6 @@ def delete_reminder(type_id, reminder_id):
db.session.commit()
return redirect(request.args.get("next") or url_for("show_type", type_id=protocoltype.id))
@app.route("/type/tops/new/<int:type_id>", methods=["GET", "POST"])
@login_required
def new_default_top(type_id):
......@@ -265,8 +264,11 @@ def move_default_top(type_id, top_id, diff):
if default_top is None or default_top.protocoltype != protocoltype:
flash("Invalider Standard-TOP.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
try:
default_top.number += int(diff)
db.session.commit()
except ValueError:
flash("Die angegebene Differenz ist keine Zahl.", "alert-error")
return redirect(request.args.get("next") or url_for("show_type", type_id=protocoltype.id))
......@@ -426,9 +428,6 @@ def upload_new_protocol():
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
return redirect(request.args.get("fail") or url_for("new_protocol"))
@app.route("/protocol/source/<int:protocol_id>")
@login_required
def get_protocol_source(protocol_id):
......@@ -452,6 +451,73 @@ def update_protocol(protocol_id):
edit_form = ProtocolForm(obj=protocol)
return render_template("protocol-update.html", upload_form=upload_form, edit_form=edit_form, protocol=protocol)
@app.route("/protocol/tops/new/<int:protocol_id>", methods=["GET", "POST"])
@login_required
def new_top(protocol_id):
user = current_user()
protocol = Protocol.query.filter_by(id=protocol_id).first()
if protocol is None or not protocol.protocoltype.has_modify_right(user):
flash("Invalides Protokoll oder keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
form = TopForm()
if form.validate_on_submit():
top = TOP(protocol_id=protocol.id, name=form.name.data, number=form.number.data, planned=True)
db.session.add(top)
db.session.commit()
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
else:
print(form.number.data)
current_numbers = list(map(lambda t: t.number, protocol.tops))
suggested_number = get_first_unused_int(current_numbers)
form.number.data = suggested_number
return render_template("top-new.html", form=form, protocol=protocol)
@app.route("/protocol/top/edit/<int:top_id>", methods=["GET", "POST"])
@login_required
def edit_top(top_id):
user = current_user()
top = TOP.query.filter_by(id=top_id).first()
if top is None or not top.protocol.protocoltype.has_modify_right(user):
flash("Invalider TOP oder keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
form = TopForm(obj=top)
if form.validate_on_submit():
form.populate_obj(top)
db.session.commit()
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=top.protocol.id))
return render_template("top-edit.html", form=form, top=top)
@app.route("/protocol/top/delete/<int:top_id>")
@login_required
def delete_top(top_id):
user = current_user()
top = TOP.query.filter_by(id=top_id).first()
if top is None or not top.protocol.protocoltype.has_modify_right(user):
flash("Invalider TOP oder keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
name = top.name
protocol_id = top.protocol.id
db.session.delete(top)
db.session.commit()
flash("Der TOP {} wurde gelöscht.".format(name), "alert-success")
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol_id))
@app.route("/protocol/top/move/<int:top_id>/<diff>")
@login_required
def move_top(top_id, diff):
user = current_user()
top = TOP.query.filter_by(id=top_id).first()
if top is None or not top.protocol.protocoltype.has_modify_right(user):
flash("Invalider TOP oder keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
try:
top.number += int(diff)
db.session.commit()
except ValueError:
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("/todos/list")
def list_todos():
is_logged_in = check_login()
......
......@@ -111,3 +111,9 @@ def group_required(function, group):
return redirect(request.args.get("next") or url_for("index"))
return decorated_function
EMPTY_ETHERPAD = """Welcome to Etherpad!
This pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!
Get involved with Etherpad at http://etherpad.org
"""
......@@ -2,10 +2,16 @@
{% from "macros.html" import render_table, render_form %}
{% block title %}Protokoll{% endblock %}
{% set loggedin = check_login() %}
{% set user = current_user() %}
{% set has_public_view_right = protocol.protocoltype.has_public_view_right(user) %}
{% set has_private_view_right = protocol.protocoltype.has_private_view_right(user) %}
{% set has_modify_right = protocol.protocoltype.has_modify_right(user) %}
{% block content %}
<div class="container">
<div class="btn-group">
{% if protocol.protocoltype.has_modify_right(current_user()) %}
{% if has_modify_right %}
<a class="btn {% if protocol.source is none %}btn-primary{% else %}btn-default{% endif %}" href="{{url_for("etherpull_protocol", protocol_id=protocol.id)}}">From etherpad</a>
{% if protocol.source is not none %}
<a class="btn btn-primary" href="{{url_for("get_protocol_source", protocol_id=protocol.id)}}">Download Quelltext</a>
......@@ -39,26 +45,8 @@
{% if protocol.date is not none %}<p><strong>Geplant:</strong> {{protocol.date|datify_long}}{% endif %}</p>
{% endif %}
<h3>Tagesordnung</h3>
<ul>
{% 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>
{% endif %}
{% endfor %}
{% endif %}
{% for top in protocol.tops %}
<li>{{top.name}}</li>
{% endfor %}
{% 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>
{% endif %}
{% endfor %}
{% endif %}
</ul>
<h3>Tagesordnung{% if has_modify_right and not protocol.has_nonplanned_tops() %} <a href="{{url_for("new_top", protocol_id=protocol.id)}}">Top hinzufügen</a>{% endif %}</h3>
{% include "protocol-tops-include.html" %}
{% if protocol.is_done() %}
<h3>Beschlüsse</h3>
......@@ -82,7 +70,7 @@
{% endif %}
</ul>
{% endif %}
{% if protocol.protocoltype.has_modify_right(current_user()) %}
{% if has_modify_right %}
{% if protocol.errors|length > 0 %}
{{render_table(errors_table)}}
{% endif %}
......@@ -90,9 +78,11 @@
{% if protocol.documents|length > 0 %}
{{render_table(documents_table)}}
{% else %}
{% if has_modify_right %}
<h3>Hochladen</h3>
{% endif %}
{% if protocol.protocoltype.has_modify_right(current_user()) %}
{% endif %}
{% if has_modify_right %}
{{render_form(source_upload_form, action_url=url_for("upload_source_to_known_protocol", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Hochladen", enctype="multipart/form-data")}}
{{render_form(document_upload_form, action_url=url_for("upload_document", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Hochladen", enctype="multipart/form-data")}}
{% endif %}
......
<ul>
{% 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>
{% endif %}
{% endfor %}
{% endif %}
{% for top in protocol.tops %}
<li>
{{top.name}}
{% if has_private_view_right %}
({{top.number}})
{% endif %}
{% if has_modify_right %}
<a href="{{url_for('edit_top', top_id=top.id)}}">Ändern</a>
<a href="{{url_for('move_top', top_id=top.id, diff=1)}}">Runter</a>
<a href="{{url_for('move_top', top_id=top.id, diff=-1)}}">Hoch</a>
<a href="{{url_for('delete_top', top_id=top.id)}}" onclick="return confirm('Bist du dir sicher, dass du den TOP {{top.name}} löschen möchtest?');">Löschen</a>
{% endif %}
</li>
{% endfor %}
{% 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>
{% endif %}
{% endfor %}
{% endif %}
</ul>
{% extends "layout.html" %}
{% from "macros.html" import render_form %}
{% block title %}TOP bearbeiten{% endblock %}
{% block content %}
<div class="container">
{{render_form(form, action_url=url_for("edit_top", top_id=top.id, next=request.args.get("next") or url_for("show_protocol", protocol_id=top.protocol.id)), action_text="Ändern")}}
</div>
{% endblock %}
{% extends "layout.html" %}
{% from "macros.html" import render_form %}
{% block title %}TOP hinzufügen{% endblock %}
{% set loggedin = check_login() %}
{% set user = current_user() %}
{% set has_public_view_right = protocol.protocoltype.has_public_view_right(user) %}
{% set has_private_view_right = protocol.protocoltype.has_private_view_right(user) %}
{% set has_modify_right = protocol.protocoltype.has_modify_right(user) %}
{% block content %}
<div class="container">
<div class="row">
<div id="left-column" class="col-lg-6">
<h3>Tagesordnung</h3>
{% include "protocol-tops-include.html" %}
</div>
<div id="right-column" class="col-lg-6">
<h3>TOP hinzufügen</h3>
{{render_form(form, action_url=url_for("new_top", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Anlegen")}}
</div>
</div>
</div>
{% endblock %}
......@@ -90,3 +90,13 @@ class MailManager:
return True
mail_manager = MailManager(config)
def get_first_unused_int(numbers):
positive_numbers = [number for number in numbers if number >= 0]
if len(positive_numbers) == 0:
return 0
highest = max(positive_numbers)
for given, linear in zip(positive_numbers, range(highest+1)):
if linear < given:
return linear
return highest + 1
......@@ -57,3 +57,7 @@ class ProtocolForm(FlaskForm):
participants = StringField("Anwesende")
done = BooleanField("Fertig")
class TopForm(FlaskForm):
name = StringField("TOP", validators=[InputRequired("Du musst den Namen des TOPs angeben.")])
number = IntegerField("Sortierung", validators=[InputRequired("Du musst eine Sortierung in der Reihenfolge angebene.")])
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