tables.py 13.3 KB
Newer Older
1
2
3
# coding: utf-8
from flask import Markup, url_for, request
from models.database import Protocol, ProtocolType, DefaultTOP, TOP, Todo, Decision
Robin Sonnabend's avatar
Robin Sonnabend committed
4
from shared import date_filter, datetime_filter, date_filter_short, current_user, check_login 
5

6
7
import config

8
class Table:
Robin Sonnabend's avatar
Robin Sonnabend committed
9
    def __init__(self, title, values, newlink=None, newtext=None):
10
11
12
        self.title = title
        self.values = values
        self.newlink = newlink
Robin Sonnabend's avatar
Robin Sonnabend committed
13
        self.newtext = newtext or "Neu"
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

    def rows(self):
        return [row for row in [self.row(value) for value in self.values] if row is not None]

    @staticmethod
    def link(target, text, confirm=None):
        confirmation = ""
        if confirm:
            confirmation = " onclick=\"return confirm('{}');\"".format(confirm)
        return Markup("<a href=\"{}\"{}>{}</a>".format(target, confirmation, text))

    @staticmethod
    def mail(target):
        return Markup("<a href=\"mailto:{}\">{}</a>".format(target, target))

    @staticmethod
    def bool(value):
Robin Sonnabend's avatar
Robin Sonnabend committed
31
        return "Ja" if value else "Nein"
32
33
34

    @staticmethod
    def concat(values):
Robin Sonnabend's avatar
Robin Sonnabend committed
35
        return Markup(", ".join(values))
36
37
38
39
40
41
42
        #if len(values) <= 1:
        #    return "".join(values)
        #else:
        #    return "{} and {}".format(", ".join(values[:-1]), values[-1])
            

class SingleValueTable:
Robin Sonnabend's avatar
Robin Sonnabend committed
43
    def __init__(self, title, value, newlink=None, newtext=None):
44
45
46
        self.title = title
        self.value = value
        self.newlink = newlink if newlink else None
Robin Sonnabend's avatar
Robin Sonnabend committed
47
        self.newtext = newtext or "Ändern"
48
49
50
51
52

    def rows(self):
        return [self.row()]

class ProtocolsTable(Table):
Robin Sonnabend's avatar
Robin Sonnabend committed
53
    def __init__(self, protocols, search_results=None):
Robin Sonnabend's avatar
Robin Sonnabend committed
54
        super().__init__("Protokolle", protocols, newlink=url_for("new_protocol"))
Robin Sonnabend's avatar
Robin Sonnabend committed
55
        self.search_results = search_results
56
57

    def headers(self):
Robin Sonnabend's avatar
Robin Sonnabend committed
58
59
60
61
62
63
64
65
        result = ["ID", "Sitzung", "Datum"]
        state_part = ["Status"]
        search_part = ["Suchergebnis"]
        login_part = ["Typ", "Löschen"]
        if self.search_results is None:
            result.extend(state_part)
        else:
            result.extend(search_part)
Robin Sonnabend's avatar
Robin Sonnabend committed
66
        if check_login():
Robin Sonnabend's avatar
Robin Sonnabend committed
67
            result.extend(login_part)
Robin Sonnabend's avatar
Robin Sonnabend committed
68
        return result
69
70

    def row(self, protocol):
Robin Sonnabend's avatar
Robin Sonnabend committed
71
72
        user = current_user()
        result = [
Robin Sonnabend's avatar
Robin Sonnabend committed
73
            Table.link(url_for("show_protocol", protocol_id=protocol.id), str(protocol.id)),
Robin Sonnabend's avatar
Robin Sonnabend committed
74
75
            Table.link(url_for("show_protocol", protocol_id=protocol.id), protocol.protocoltype.name),
            date_filter(protocol.date),
76
        ]
Robin Sonnabend's avatar
Robin Sonnabend committed
77
78
79
80
        if self.search_results is None:
            result.append("Fertig" if protocol.is_done() else "Geplant")
        elif protocol in self.search_results:
            result.append(Markup(self.search_results[protocol]))
Robin Sonnabend's avatar
Robin Sonnabend committed
81
82
83
84
        if user is not None and protocol.protocoltype.has_private_view_right(user):
            result.append(Table.link(url_for("show_type", type_id=protocol.protocoltype.id), protocol.protocoltype.short_name))
            result.append(Table.link(url_for("delete_protocol", protocol_id=protocol.id), "Löschen", confirm="Bist du dir sicher, dass du das Protokoll {} löschen möchtest?".format(protocol.get_identifier())))
        return result
85

Robin Sonnabend's avatar
Robin Sonnabend committed
86
87
88
89
90
91
92
93
class ProtocolTypesTable(Table):
    def __init__(self, types):
        super().__init__("Protokolltypen", types, newlink=url_for("new_type"))

    def headers(self):
        return ["Typ", "Name", "Neuestes Protokoll", ""]

    def row(self, protocoltype):
Robin Sonnabend's avatar
Robin Sonnabend committed
94
95
96
        protocol = protocoltype.get_latest_protocol()
        user = current_user()
        has_modify_right = protocoltype.has_modify_right(user)
Robin Sonnabend's avatar
Robin Sonnabend committed
97
        return [
Robin Sonnabend's avatar
Robin Sonnabend committed
98
            Table.link(url_for("show_type", type_id=protocoltype.id), protocoltype.short_name) if has_modify_right else protocoltype.short_name,
Robin Sonnabend's avatar
Robin Sonnabend committed
99
            protocoltype.name,
Robin Sonnabend's avatar
Robin Sonnabend committed
100
101
102
            Table.link(url_for("show_protocol", protocol_id=protocol.id), protocol.get_identifier()) if protocol is not None else "Noch kein Protokoll",
            Table.link(url_for("new_protocol", type_id=protocoltype.id), "Neues Protokoll") if has_modify_right else ""
            "" # TODO: add link for modify, delete
Robin Sonnabend's avatar
Robin Sonnabend committed
103
104
105
106
107
108
109
        ]

class ProtocolTypeTable(SingleValueTable):
    def __init__(self, protocoltype):
        super().__init__(protocoltype.name, protocoltype, newlink=url_for("edit_type", type_id=protocoltype.id))

    def headers(self):
110
111
112
113
114
115
116
        general_headers = ["Name", "Abkürzung", "Organisation", "Beginn",
            "Öffentlich", "Interne Gruppe", "Öffentliche Gruppe"]
        mail_headers = ["Interner Verteiler", "Öffentlicher Verteiler"]
        if not config.MAIL_ACTIVE:
            mail_headers = []
        printing_headers = ["Drucker"] if config.PRINTING_ACTIVE else []
        wiki_headers = ["Wiki"]
Robin Sonnabend's avatar
Robin Sonnabend committed
117
        if self.value.use_wiki:
118
119
120
121
            wiki_headers.append("Wiki-Kategorie")
        if not config.WIKI_ACTIVE:
            wiki_headers = []
        return general_headers + mail_headers + printing_headers + wiki_headers
Robin Sonnabend's avatar
Robin Sonnabend committed
122
123

    def row(self):
124
        general_part = [
Robin Sonnabend's avatar
Robin Sonnabend committed
125
126
127
            self.value.name,
            self.value.short_name,
            self.value.organization,
Robin Sonnabend's avatar
Robin Sonnabend committed
128
            self.value.usual_time.strftime("%H:%M") if self.value.usual_time is not None else "", # todo: remove if, this field is required
Robin Sonnabend's avatar
Robin Sonnabend committed
129
130
131
            Table.bool(self.value.is_public),
            self.value.private_group,
            self.value.public_group,
132
133
        ]
        mail_part = [
Robin Sonnabend's avatar
Robin Sonnabend committed
134
            self.value.private_mail,
Robin Sonnabend's avatar
Robin Sonnabend committed
135
            self.value.public_mail,
136
137
138
139
140
141
142
        ]
        if not config.MAIL_ACTIVE:
            mail_part = []
        printing_part = [self.value.printer]
        if not config.PRINTING_ACTIVE:
            printing_part = []
        wiki_part = [
Robin Sonnabend's avatar
Robin Sonnabend committed
143
            (Table.bool(self.value.use_wiki) + ((", " + ("Öffentlich" if self.value.wiki_only_public else "Intern")) if self.value.use_wiki else ""))
Robin Sonnabend's avatar
Robin Sonnabend committed
144
        ]
Robin Sonnabend's avatar
Robin Sonnabend committed
145
        if self.value.use_wiki:
146
147
148
149
            wiki_part.append(self.value.wiki_category)
        if not config.WIKI_ACTIVE:
            wiki_part = []
        return general_part + mail_part + printing_part + wiki_part
Robin Sonnabend's avatar
Robin Sonnabend committed
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

class DefaultTOPsTable(Table):
    def __init__(self, tops, protocoltype=None):
        super().__init__("Standard-TOPs", tops, newlink=url_for("new_default_top", type_id=protocoltype.id) if protocoltype is not None else None)
        self.protocoltype = protocoltype

    def headers(self):
        return ["TOP", "Sortierung", ""]

    def row(self, top):
        return [
            top.name,
            top.number,
            Table.concat([
                Table.link(url_for("move_default_top", type_id=self.protocoltype.id, top_id=top.id, diff=1), "Runter"),
                Table.link(url_for("move_default_top", type_id=self.protocoltype.id, top_id=top.id, diff=-1), "Hoch"),
                Table.link(url_for("edit_default_top", type_id=self.protocoltype.id, top_id=top.id), "Ändern"),
                Table.link(url_for("delete_default_top", type_id=self.protocoltype.id, top_id=top.id), "Löschen", confirm="Bist du dir sicher, dass du den Standard-TOP {} löschen willst?".format(top.name))
            ])
        ]
170
171
172
173
174
175
176

class MeetingRemindersTable(Table):
    def __init__(self, reminders, protocoltype=None):
        super().__init__("Einladungsmails", reminders, newlink=url_for("new_reminder", type_id=protocoltype.id) if protocoltype is not None else None)
        self.protocoltype = protocoltype

    def headers(self):
Robin Sonnabend's avatar
Robin Sonnabend committed
177
        return ["Zeit", "Einladen", "Zusätzlicher Mailinhalt", ""]
178
179
180
181
182

    def row(self, reminder):
        return [
            "{} Tage".format(reminder.days_before),
            self.get_send_summary(reminder),
Robin Sonnabend's avatar
Robin Sonnabend committed
183
            reminder.additional_text or "",
184
185
186
187
188
189
190
191
192
193
194
195
196
            Table.concat([
                Table.link(url_for("edit_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Ändern"),
                Table.link(url_for("delete_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Löschen", confirm="Bist du dir sicher, dass du die Einladungsmail {} Tage vor der Sitzung löschen willst?".format(reminder.days_before))
            ])
        ]

    def get_send_summary(self, reminder):
        parts = []
        if reminder.send_public:
            parts.append("Öffentlich")
        if reminder.send_private:
            parts.append("Intern")
        return " und ".join(parts)
Robin Sonnabend's avatar
Robin Sonnabend committed
197
198
199
200
201
202

class ErrorsTable(Table):
    def __init__(self, errors):
        super().__init__("Fehler", errors)

    def headers(self):
Robin Sonnabend's avatar
Robin Sonnabend committed
203
        return ["Protokoll", "Aktion", "Fehler", "Zeitpunkt", "Beschreibung", ""]
Robin Sonnabend's avatar
Robin Sonnabend committed
204
205
206
207

    def row(self, error):
        return [
            Table.link(url_for("show_protocol", protocol_id=error.protocol.id), error.protocol.get_identifier()),
Robin Sonnabend's avatar
Robin Sonnabend committed
208
209
            error.action,
            Table.link(url_for("show_error", error_id=error.id), error.name),
Robin Sonnabend's avatar
Robin Sonnabend committed
210
            datetime_filter(error.datetime),
Robin Sonnabend's avatar
Robin Sonnabend committed
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
            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))
Robin Sonnabend's avatar
Robin Sonnabend committed
229
230
231
232
        ]

class TodosTable(Table):
    def __init__(self, todos):
Robin Sonnabend's avatar
Robin Sonnabend committed
233
        super().__init__("Todos", todos, newlink=url_for("new_todo"))
Robin Sonnabend's avatar
Robin Sonnabend committed
234
235

    def headers(self):
Robin Sonnabend's avatar
Robin Sonnabend committed
236
        return ["ID", "Status", "Sitzung", "Name", "Aufgabe", ""]
Robin Sonnabend's avatar
Robin Sonnabend committed
237
238

    def row(self, todo):
Robin Sonnabend's avatar
Robin Sonnabend committed
239
        user = current_user()
Robin Sonnabend's avatar
Robin Sonnabend committed
240
        protocol = todo.get_first_protocol()
Robin Sonnabend's avatar
Robin Sonnabend committed
241
242
        row = [
            Table.link(url_for("show_todo", todo_id=todo.id), todo.get_id()),
Robin Sonnabend's avatar
Robin Sonnabend committed
243
            todo.get_state(),
Robin Sonnabend's avatar
Robin Sonnabend committed
244
245
246
            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),
Robin Sonnabend's avatar
Robin Sonnabend committed
247
            todo.who,
Robin Sonnabend's avatar
Robin Sonnabend committed
248
            todo.description,
Robin Sonnabend's avatar
Robin Sonnabend committed
249
        ]
Robin Sonnabend's avatar
Robin Sonnabend committed
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
        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
284

Robin Sonnabend's avatar
Robin Sonnabend committed
285
286
287
288
289
290
291
292
293
294
295
296
297
class DecisionsTable(Table):
    def __init__(self, decisions):
        super().__init__("Beschlüsse", decisions)

    def headers(self):
        return ["Sitzung", "Beschluss"]

    def row(self, decision):
        return [
            Table.link(url_for("show_protocol", protocol_id=decision.protocol.id), decision.protocol.get_identifier()),
            decision.content
        ]

298
299
300
301
302
303
304
305
class DocumentsTable(Table):
    def __init__(self, documents):
        super().__init__("Anhang", documents)

    def headers(self):
        return ["ID", "Name", ""]

    def row(self, document):
Robin Sonnabend's avatar
Robin Sonnabend committed
306
        user = current_user()
307
308
309
        links = [Table.link(url_for("delete_document", document_id=document.id), "Löschen", confirm="Bist du dir sicher, dass du das Dokument {} löschen willst?".format(document.name))]
        if config.PRINTING_ACTIVE:
            links.append(Table.link(url_for("print_document", document_id=document.id), "Drucken"))
310
311
312
        return [
            document.id,
            Table.link(url_for("download_document", document_id=document.id), document.name),
313
314
315
            Table.concat(links)
                if document.protocol.protocoltype.has_modify_right(user)
                else ""
316
        ]
Robin Sonnabend's avatar
Robin Sonnabend committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

class TodoMailsTable(Table):
    def __init__(self, todomails):
        super().__init__("Todo-Mail-Zuordnungen", todomails, url_for("new_todomail"))

    def headers(self):
        return ["Name", "Mail", ""]

    def row(self, todomail):
        return [
            todomail.name,
            todomail.mail,
            Table.concat([
                Table.link(url_for("edit_todomail", todomail_id=todomail.id), "Ändern"),
                Table.link(url_for("delete_todomail", todomail_id=todomail.id), "Löschen", confirm="Bist du dir sicher, dass du die Todomailzuordnung {} zu {} löschen willst?".format(todomail.name, todomail.mail))
            ])
        ]