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

new, edit, show, delete todo

parent 403dd2d6
......@@ -20,10 +20,10 @@ import math
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, class_filter
from utils import is_past, mail_manager, url_manager, get_first_unused_int, set_etherpad_text, get_etherpad_text, split_terms
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 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, TopForm, SearchForm, NewProtocolFileUploadForm
from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable, DecisionsTable
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm, TopForm, SearchForm, NewProtocolFileUploadForm, NewTodoForm, TodoForm
from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable, DecisionsTable, TodoTable
app = Flask(__name__)
app.config.from_object(config)
......@@ -718,6 +718,11 @@ def list_todos():
todo for todo in todos
if search_term.lower() in todo.description.lower()
]
def _sort_key(todo):
first_protocol = todo.get_first_protocol()
result = (not todo.done, first_protocol.date if first_protocol is not None else datetime.now().date())
return result
todos = sorted(todos, key=_sort_key, reverse=True)
page = _get_page()
page_count = int(math.ceil(len(todos) / config.PAGE_LENGTH))
if page >= page_count:
......@@ -728,6 +733,88 @@ def list_todos():
todos_table = TodosTable(todos)
return render_template("todos-list.html", todos=todos, todos_table=todos_table, search_form=search_form, page=page, page_count=page_count, page_diff=config.PAGE_DIFF, protocoltype_id=protocoltype_id, search_term=search_term)
@app.route("/todo/new", methods=["GET", "POST"])
@login_required
def new_todo():
user = current_user()
protocoltype_id = optional_int_arg("type_id")
protocol_id = optional_int_arg("protocol_id")
protocoltype = ProtocolType.query.filter_by(id=protocoltype_id).first()
protocol = Protocol.query.filter_by(id=protocol_id).first()
if protocoltype is not None and protocol is not None:
if protocol.protocoltype != protocoltype:
flash("Ungültige Protokoll-Typ-Kombination", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
if protocoltype is None and protocol is not None:
protocoltype = protocol.protocoltype
protocoltypes = ProtocolType.get_modifiable_protocoltypes(user)
form = NewTodoForm(protocoltypes)
if form.validate_on_submit():
added_protocoltype = ProtocolType.query.filter_by(id=form.protocoltype_id.data).first()
if added_protocoltype is None or not added_protocoltype.has_modify_right(user):
flash("Invalider Protokolltyp.")
return redirect(request.args.get("next") or url_for("index"))
todo = Todo(type_id=form.protocoltype_id.data, who=form.who.data,
description=form.description.data, tags=form.tags.data,
done=form.done.data)
if protocol is not None:
todo.protocols.append(protocol)
db.session.add(todo)
db.session.commit()
todo.number = todo.id
db.session.commit()
flash("Todo wurde angelegt.", "alert-success")
if protocol is not None:
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
else:
return redirect(request.args.get("next") or url_for("list_todos", protocoltype_id=protocoltype_id))
else:
if protocoltype is not None:
form.protocoltype_id.data = protocoltype.id
return render_template("todo-new.html", form=form, protocol=protocol, protocoltype=protocoltype)
@app.route("/todo/edit/<int:todo_id>", methods=["GET", "POST"])
@login_required
def edit_todo(todo_id):
user = current_user()
todo = Todo.query.filter_by(id=todo_id).first()
if todo is None or not todo.protocoltype.has_modify_right(user):
flash("Invalides Todo oder unzureichende Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
form = TodoForm(obj=todo)
if form.validate_on_submit():
form.populate_obj(todo)
db.session.commit()
return redirect(request.args.get("next") or url_for("list_todos", protocoltype=todo.protocoltype.id))
return render_template("todo-edit.html", form=form, todo=todo)
@app.route("/todo/show/<int:todo_id>")
@login_required
def show_todo(todo_id):
user = current_user()
todo = Todo.query.filter_by(id=todo_id).first()
if todo is None or not todo.protocoltype.has_private_view_right(user):
flash("Invalides Todo oder unzureichende Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
todo_table = TodoTable(todo)
return render_template("todo-show.html", todo=todo, todo_table=todo_table)
@app.route("/todo/delete/<int:todo_id>")
@login_required
def delete_todo(todo_id):
user = current_user()
todo = Todo.query.filter_by(id=todo_id).first()
if todo is None or not todo.protocoltype.has_private_view_right(user):
flash("Invalides Todo oder unzureichende Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
type_id = todo.protocoltype.id
db.session.delete(todo)
db.session.commit()
flash("Todo gelöscht.", "alert-success")
return redirect(request.args.get("next") or url_for("list_todos", protocoltype=type_id))
@app.route("/decisions/list")
def list_decisions():
is_logged_In = check_login()
......
......@@ -2,7 +2,7 @@
{% from "macros.html" import render_table, render_form %}
{% block title %}Protokoll{% endblock %}
{% set loggedin = check_login() %}
{% set logged_in = 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) %}
......@@ -69,7 +69,7 @@
</div>
<div id="right-column" class="col-lg-6">
{% if protocol.is_done() and has_public_view_right and logged_in %}
<h3>Todos dieser Sitzung <a href="{{url_for("list_todos")}}">Aktuelle Todos</a></h3>
<h3>Todos dieser Sitzung <a href="{{url_for("list_todos")}}">Aktuelle Todos</a> <a href="{{url_for("new_todo", protocol_id=protocol.id)}}">Neu</a></h3>
<ul>
{% if protocol.get_originating_todos()|length > 0 %}
{% for todo in protocol.get_originating_todos() %}
......
......@@ -10,7 +10,7 @@
{% if top.name == "Todos" %}
{% if protocol.todos|length > 0 %}
{% for todo in protocol.todos %}
[todo;{{todo.who}};{{todo.description}};id {{todo.get_number()}}];
[todo;{{todo.who}};{{todo.description}};id {{todo.get_id()}}];
{% endfor %}
{% else %}
......
{% extends "layout.html" %}
{% from "macros.html" import render_form %}
{% block title %}Todo ändern{% endblock %}
{% block content %}
<div class="container">
{{render_form(form, action_url=url_for("edit_todo", todo_id=todo.id), action_text="Ändern")}}
</div>
{% endblock %}
{% extends "layout.html" %}
{% from "macros.html" import render_form %}
{% block title %}Todo anlegen{% endblock %}
{% block content %}
<div class="container">
{{render_form(form, action_url=url_for("new_todo", protocol_id=protocol.id, protocoltype_id=protocoltype.id), action_text="Anlegen")}}
</div>
{% endblock %}
{% extends "layout.html" %}
{% from "macros.html" import render_single_table %}
{% block title %}Todo{% endblock %}
{% block content %}
<div class="container">
{{render_single_table(todo_table)}}
</div>
{% endblock %}
from flask import render_template
from flask import render_template, request
import random
import string
......@@ -152,3 +152,9 @@ def split_terms(text, quote_chars="\"'", separators=" \t\n"):
if len(current_term) > 0:
terms.append(current_term)
return terms
def optional_int_arg(name):
try:
return int(request.args.get(name))
except (ValueError, TypeError):
return None
......@@ -4,6 +4,12 @@ from wtforms.validators import InputRequired, Optional
import config
def get_protocoltype_choices(protocoltypes, add_all=True):
choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes]
if add_all:
choices.insert(0, (-1, "Alle"))
return choices
class LoginForm(FlaskForm):
username = StringField("Benutzer", validators=[InputRequired("Bitte gib deinen Benutzernamen ein.")])
password = PasswordField("Passwort", validators=[InputRequired("Bitte gib dein Passwort ein.")])
......@@ -39,7 +45,7 @@ class NewProtocolForm(FlaskForm):
def __init__(self, protocoltypes, **kwargs):
super().__init__(**kwargs)
self.protocoltype.choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes]
self.protocoltype.choices = get_protocoltype_choices(protocoltypes, add_all=False)
class DocumentUploadForm(FlaskForm):
document = FileField("Datei")
......@@ -54,7 +60,7 @@ class NewProtocolSourceUploadForm(FlaskForm):
def __init__(self, protocoltypes, **kwargs):
super().__init__(**kwargs)
self.protocoltype.choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes]
self.protocoltype.choices = get_protocoltype_choices(protocoltypes, add_all=False)
class NewProtocolFileUploadForm(FlaskForm):
file = FileField("Datei")
......@@ -63,7 +69,7 @@ class NewProtocolFileUploadForm(FlaskForm):
def __init__(self, protocoltypes, **kwargs):
super().__init__(**kwargs)
self.protocoltype.choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes]
self.protocoltype.choices = get_protocoltype_choices(protocoltypes, add_all=False)
class ProtocolForm(FlaskForm):
date = DateField("Datum", validators=[InputRequired("Bitte gib das Datum des Protkolls an.")], format="%d.%m.%Y")
......@@ -84,6 +90,21 @@ class SearchForm(FlaskForm):
def __init__(self, protocoltypes, **kwargs):
super().__init__(**kwargs)
choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes]
choices.insert(0, (-1, "Alle"))
self.protocoltype.choices = choices
self.protocoltype.choices = get_protocoltype_choices(protocoltypes)
class NewTodoForm(FlaskForm):
protocoltype_id = SelectField("Typ", choices=[], coerce=int)
who = StringField("Person", validators=[InputRequired("Bitte gib an, wer das Todo erledigen soll.")])
description = StringField("Aufgabe", validators=[InputRequired("Bitte gib an, was erledigt werden soll.")])
tags = StringField("Weitere Tags")
done = BooleanField("Erledigt")
def __init__(self, protocoltypes, **kwargs):
super().__init__(**kwargs)
self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False)
class TodoForm(FlaskForm):
who = StringField("Person", validators=[InputRequired("Bitte gib an, wer das Todo erledigen soll.")])
description = StringField("Aufgabe", validators=[InputRequired("Bitte gib an, was erledigt werden soll.")])
tags = StringField("Weitere Tags")
done = BooleanField("Erledigt")
......@@ -195,19 +195,57 @@ class ErrorsTable(Table):
class TodosTable(Table):
def __init__(self, todos):
super().__init__("Todos", todos)
super().__init__("Todos", todos, newlink=url_for("new_todo"))
def headers(self):
return ["Status", "Sitzung", "Name", "Aufgabe"]
return ["ID", "Status", "Sitzung", "Name", "Aufgabe", ""]
def row(self, todo):
user = current_user()
protocol = todo.get_first_protocol()
return [
row = [
Table.link(url_for("show_todo", todo_id=todo.id), todo.get_id()),
todo.get_state(),
Table.link(url_for("show_protocol", protocol_id=protocol.id), protocol.get_identifier()) if protocol is not None else "",
Table.link(url_for("show_protocol", protocol_id=protocol.id), protocol.get_identifier())
if protocol is not None
else Table.link(url_for("list_protocols", protocoltype=todo.protocoltype.id), todo.protocoltype.short_name),
todo.who,
todo.description
todo.description,
]
if todo.protocoltype.has_modify_right(user):
row.append(Table.link(url_for("edit_todo", todo_id=todo.id), "Ändern"))
else:
row.append("")
return row
class TodoTable(SingleValueTable):
def __init__(self, todo):
super().__init__("Todo", todo)
def headers(self):
return ["ID", "Status", "Sitzung", "Name", "Aufgabe", "Tags", ""]
def row(self):
user = current_user()
protocol = self.value.get_first_protocol()
row = [
self.value.get_id(),
self.value.get_state_plain(),
Table.link(url_for("show_protocol", protocol_id=protocol.id), protocol.get_identifier())
if protocol is not None
else Table.link(url_for("list_protocols", protocolttype=self.value.protocoltype.id), self.value.protocoltype.short_name),
self.value.who,
self.value.description,
self.value.tags
]
if self.value.protocoltype.has_modify_right(user):
row.append(Table.concat([
Table.link(url_for("edit_todo", todo_id=self.value.id), "Ändern"),
Table.link(url_for("delete_todo", todo_id=self.value.id), "Löschen", confirm="Bist du dir sicher, dass du das Todo löschen willst?")
]))
else:
row.append("")
return row
class DecisionsTable(Table):
def __init__(self, decisions):
......
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