From 1daed4c5aa7c5be8997701ddb7784bf1845d1134 Mon Sep 17 00:00:00 2001
From: Robin Sonnabend <robin@fsmpi.rwth-aachen.de>
Date: Sun, 26 Feb 2017 05:04:37 +0100
Subject: [PATCH] Error overview and deletion

---
 models/database.py         |  6 ++++++
 server.py                  | 39 +++++++++++++++++++++++++++++++++++++-
 templates/error-show.html  |  9 +++++++++
 templates/errors-list.html |  9 +++++++++
 templates/layout.html      |  1 +
 views/tables.py            | 24 ++++++++++++++++++++---
 6 files changed, 84 insertions(+), 4 deletions(-)
 create mode 100644 templates/error-show.html
 create mode 100644 templates/errors-list.html

diff --git a/models/database.py b/models/database.py
index 561b14c..f2664d3 100644
--- a/models/database.py
+++ b/models/database.py
@@ -422,3 +422,9 @@ class Error(db.Model):
     def __repr__(self):
         return "<Error(id={}, protocol_id={}, action={}, name={}, datetime={})>".format(
             self.id, self.protocol_id, self.action, self.name, self.datetime)
+
+    def get_short_description(self):
+        lines = self.description.splitlines()
+        if len(lines) <= 4:
+            return "\n".join(lines)
+        return "\n".join(lines[:2], "…", lines[-2:])
diff --git a/server.py b/server.py
index 6584081..2ef4e0a 100755
--- a/server.py
+++ b/server.py
@@ -23,7 +23,7 @@ from shared import db, date_filter, datetime_filter, date_filter_long, time_filt
 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, NewTodoForm, TodoForm
-from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable, DecisionsTable, TodoTable
+from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable, DecisionsTable, TodoTable, ErrorTable
 
 app = Flask(__name__)
 app.config.from_object(config)
@@ -930,6 +930,43 @@ def print_document(document_id):
     flash("Das Dokument {} wird gedruckt.".format(document.name), "alert-success")
     return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=document.protocol.id))
 
+@app.route("/errors/list")
+@login_required
+def list_errors():
+    user = current_user()
+    errors = [
+        error for error in Error.query.all()
+        if error.protocol.protocoltype.has_private_view_right(user)
+    ]
+    errors_table = ErrorsTable(errors)
+    return render_template("errors-list.html", errros=errors, errors_table=errors_table)
+
+@app.route("/error/show/<int:error_id>")
+@login_required
+def show_error(error_id):
+    user = current_user()
+    error = Error.query.filter_by(id=error_id).first()
+    if error is None or not error.protocol.protocoltype.has_modify_right(user):
+        flash("Invalider Fehler oder fehlende Zugriffsrechte.", "alert-error")
+        return redirect(request.args.get("next") or url_for("index"))
+    error_table = ErrorTable(error)
+    return render_template("error-show.html", error=error, error_table=error_table)
+
+@app.route("/error/delete/<int:error_id>")
+@login_required
+def delete_error(error_id):
+    user = current_user()
+    error = Error.query.filter_by(id=error_id).first()
+    if error is None or not error.protocol.protocoltype.has_modify_right(user):
+        flash("Invalider Fehler oder fehlende Zugriffsrechte.", "alert-error")
+        return redirect(request.args.get("next") or url_for("index"))
+    name = error.name
+    db.session.delete(error)
+    db.session.commit()
+    flash("Fehler {} gelöscht.".format(name), "alert-success")
+    return redirect(request.args.get("next") or url_for("list_errors"))
+    
+
 @app.route("/login", methods=["GET", "POST"])
 def login():
     if "auth" in session:
diff --git a/templates/error-show.html b/templates/error-show.html
new file mode 100644
index 0000000..a3d0614
--- /dev/null
+++ b/templates/error-show.html
@@ -0,0 +1,9 @@
+{% extends "layout.html" %}
+{% from "macros.html" import render_single_table %}
+{% block title %}Fehler{% endblock %}
+
+{% block content %}
+<div class="container">
+    {{render_single_table(error_table)}}
+</div>
+{% endblock %}
diff --git a/templates/errors-list.html b/templates/errors-list.html
new file mode 100644
index 0000000..aaab0b7
--- /dev/null
+++ b/templates/errors-list.html
@@ -0,0 +1,9 @@
+{% extends "layout.html" %}
+{% from "macros.html" import render_table %}
+{% block title %}Fehler{% endblock %}
+
+{% block content %}
+<div class="container">
+    {{render_table(errors_table)}}
+</div>
+{% endblock %}
diff --git a/templates/layout.html b/templates/layout.html
index d06902a..e141b04 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -36,6 +36,7 @@
                 <li><a href="{{url_for("list_decisions")}}">Beschlüsse</a></li>
                 {% if check_login() %}
                 <li><a href="{{url_for("list_types")}}">Typen</a></li>
+                <li><a href="{{url_for("list_errors")}}">Fehler</a></li>
                 {% endif %}
                 {# todo: add more links #}
             </ul>
diff --git a/views/tables.py b/views/tables.py
index 0cc7c30..72c6390 100644
--- a/views/tables.py
+++ b/views/tables.py
@@ -183,14 +183,32 @@ class ErrorsTable(Table):
         super().__init__("Fehler", errors)
 
     def headers(self):
-        return ["Protokoll", "Fehler", "Zeitpunkt", "Beschreibung"]
+        return ["Protokoll", "Aktion", "Fehler", "Zeitpunkt", "Beschreibung", ""]
 
     def row(self, error):
         return [
             Table.link(url_for("show_protocol", protocol_id=error.protocol.id), error.protocol.get_identifier()),
-            error.name,
+            error.action,
+            Table.link(url_for("show_error", error_id=error.id), error.name),
             datetime_filter(error.datetime),
-            error.description
+            error.get_short_description(),
+            Table.link(url_for("delete_error", error_id=error.id), "Löschen", confirm="Bist du dir sicher, dass du den Fehler löschen möchtest?")
+        ]
+
+class ErrorTable(SingleValueTable):
+    def __init__(self, error):
+        super().__init__(error.action, error)
+
+    def headers(self):
+        return ["Protokoll", "Aktion", "Fehler", "Zeitpunkt", "Beschreibung"]
+
+    def row(self):
+        return [
+            Table.link(url_for("show_protocol", protocol_id=self.value.protocol.id), self.value.protocol.get_identifier()),
+            self.value.action,
+            self.value.name,
+            datetime_filter(self.value.datetime),
+            Markup("<pre>{}</pre>".format(self.value.description))
         ]
 
 class TodosTable(Table):
-- 
GitLab