# coding: utf-8 from flask import Markup, url_for, request from models.database import Protocol, ProtocolType, DefaultTOP, TOP, Todo, Decision, Meta, DefaultMeta from shared import date_filter, datetime_filter, date_filter_short, current_user, check_login import config class Table: def __init__(self, title, values, newlink=None, newtext=None): self.title = title self.values = values self.newlink = newlink self.newtext = newtext or "Neu" def rows(self): return [row for row in [self.row(value) for value in self.values] if row is not None] def classes(self): return [None for header in self.headers()] @staticmethod def link(target, text, confirm=None): confirmation = "" if confirm: confirmation = " onclick=\"return confirm('{}');\"".format(confirm) return Markup("{}".format(target, confirmation, text)) @staticmethod def button(target, icon, style, confirm=None): confirmation = "" if confirm: confirmation = " onclick=\"return confirm('{}');\"".format(confirm) return Markup( '''
'''.format(target=target, style=style, confirmation=confirmation, icon=icon)) @staticmethod def mail(target): return Markup("{}".format(target, target)) @staticmethod def bool(value): return "Ja" if value else "Nein" @staticmethod def concat(values): return Markup(", ".join(values)) #if len(values) <= 1: # return "".join(values) #else: # return "{} and {}".format(", ".join(values[:-1]), values[-1]) class SingleValueTable: def __init__(self, title, value, newlink=None, newtext=None): self.title = title self.value = value self.newlink = newlink if newlink else None self.newtext = newtext or "Ändern" def rows(self): return [self.row()] class ProtocolsTable(Table): def __init__(self, protocols, search_results=None): super().__init__("Protokolle", protocols, newlink=url_for("new_protocol")) self.search_results = search_results def headers(self): user = current_user() result = ["Sitzung", "Sitzung", "Datum"] state_part = ["Status"] search_part = ["Suchergebnis"] login_part = [""] if self.search_results is None: result.extend(state_part) else: result.extend(search_part) if check_login(): result.extend(login_part) return result def classes(self): state_or_search_class = "hidden-xs" if self.search_results is None else None result = ["hidden-sm hidden-md hidden-lg", "hidden-xs", "hidden-xs", None] #result.append(state_or_search_class) login_part = ["hidden-xs"] if check_login(): result.extend(login_part) return result def row(self, protocol): user = current_user() protocol_link = url_for("show_protocol", protocol_id=protocol.id) result = [ Markup("
").join([Table.link(protocol_link, protocol.protocoltype.name), date_filter(protocol.date)]), Table.link(protocol_link, protocol.protocoltype.name), date_filter(protocol.date), ] if self.search_results is None: state = "pencil" #"Geplant" if protocol.is_done(): state = "unchecked" #"Fertig" if protocol.public: state = "check" #"Veröffentlicht" result.append(Markup(''.format(state=state))) elif protocol in self.search_results: result.append(Markup(self.search_results[protocol])) login_part1="" login_part2="" if state != "pencil": document = protocol.get_compiled_document() if document is not None: login_part1 = Table.button( url_for("download_document", document_id=document.id), icon="download", style="") if protocol.protocoltype.has_admin_right(user): login_part2 = Table.button( url_for("delete_protocol", protocol_id=protocol.id), icon="trash", style="danger", confirm="Bist du dir sicher, dass du das Protokoll {} löschen möchtest?") result.append(Markup( '
{}
'.format( "".join((login_part1, login_part2))))) return result class ProtocolTypesTable(Table): def __init__(self, types): super().__init__("Protokolltypen", types, newlink=url_for("new_type")) def headers(self): return [ "Typ", "Protokoll", "Typ", "Name", "Neuestes Protokoll", "" ] def classes(self): return [ "hidden-sm hidden-md hidden-lg", "hidden-sm hidden-md hidden-lg", "hidden-xs", "hidden-xs", "hidden-xs", "hidden-xs" ] def row(self, protocoltype): protocol = protocoltype.get_latest_protocol() user = current_user() has_private_view_right = protocoltype.has_private_view_right(user) has_modify_right = protocoltype.has_modify_right(user) protocoltype_link = url_for("show_type", protocoltype_id=protocoltype.id) protocol_link = (url_for("show_protocol", protocol_id=protocol.id) if protocol is not None else "") new_protocol_link = url_for("new_protocol", protocoltype_id=protocoltype.id) mobile_name = "{} ({})".format(protocoltype.name, protocoltype.short_name) mobile_links = [] if protocol is not None: mobile_links.append(Table.link(protocol_link, protocol.get_short_identifier())) if has_modify_right: mobile_links.append(Table.link(new_protocol_link, "Neues Protokoll")) mobile_part = [ Table.link(protocoltype_link, mobile_name) if has_private_view_right else mobile_name, Markup("
".join(mobile_links)) ] desktop_part = [ Table.link(protocoltype_link, protocoltype.short_name) if has_private_view_right else protocoltype.short_name, protocoltype.name, Table.link(protocol_link, protocol.get_short_identifier()) if protocol is not None else "Noch kein Protokoll", Table.link(new_protocol_link, "Neues Protokoll") if has_modify_right else "" "" # TODO: add link for modify, delete ] return mobile_part + desktop_part class ProtocolTypeTable(SingleValueTable): def __init__(self, protocoltype): super().__init__(protocoltype.name, protocoltype, newlink=url_for("edit_type", protocoltype_id=protocoltype.id)) def headers(self): general_headers = ["Name", "Abkürzung", "Organisation", "Beginn", "Öffentlich", "Verwaltungsgruppe", "Bearbeitungsgruppe", "Interne Gruppe", "Öffentliche Gruppe"] etherpad_headers = ["Nicht-reproduzierbare Etherpadlinks"] if not config.ETHERPAD_ACTIVE: etherpad_headers = [] mail_headers = ["Interner Verteiler", "Öffentlicher Verteiler"] if not config.MAIL_ACTIVE: mail_headers = [] printing_headers = ["Drucker"] if config.PRINTING_ACTIVE else [] wiki_headers = ["Wiki"] if self.value.use_wiki: wiki_headers.append("Wiki-Kategorie") if not config.WIKI_ACTIVE: wiki_headers = [] calendar_headers = ["Kalender"] if not config.CALENDAR_ACTIVE: calendar_headers = [] network_headers = ["Netzwerke einschränken", "Erlaubte Netzwerke"] action_headers = ["Aktion"] return (general_headers + etherpad_headers + mail_headers + printing_headers + wiki_headers + calendar_headers + network_headers + action_headers) def row(self): user = current_user() general_part = [ self.value.name, self.value.short_name, self.value.organization, self.value.usual_time.strftime("%H:%M") if self.value.usual_time is not None else "", # todo: remove if, this field is required Table.bool(self.value.is_public), self.value.publish_group, self.value.modify_group, self.value.private_group, self.value.public_group, ] etherpad_part = [ Table.bool(self.value.non_reproducible_pad_links) ] if not config.ETHERPAD_ACTIVE: ethernet_part = [] mail_part = [ self.value.private_mail, self.value.public_mail, ] if not config.MAIL_ACTIVE: mail_part = [] printing_part = [self.value.printer] if not config.PRINTING_ACTIVE: printing_part = [] wiki_part = [ (Table.bool(self.value.use_wiki) + ((", " + ("Öffentlich" if self.value.wiki_only_public else "Intern")) if self.value.use_wiki else "")) ] if self.value.use_wiki: wiki_part.append(self.value.wiki_category) if not config.WIKI_ACTIVE: wiki_part = [] calendar_part = [self.value.calendar if self.value.calendar is not None else ""] if not config.CALENDAR_ACTIVE: calendar_part = [] network_part = [Table.bool(self.value.restrict_networks)] if self.value.allowed_networks is not None: network_part.append(", ".join(map(str.strip, self.value.allowed_networks.split(",")))) else: network_part.append("") action_part = [Table.link(url_for("delete_type", protocoltype_id=self.value.id), "Löschen", confirm="Bist du dir sicher, dass du den Protokolltype {} löschen möchtest?".format(self.value.name))] if not self.value.has_admin_right(user): action_part = [""] return (general_part + etherpad_part + mail_part + printing_part + wiki_part + calendar_part + network_part + action_part) class DefaultTOPsTable(Table): def __init__(self, tops, protocoltype=None): super().__init__("Standard-TOPs", tops, newlink=url_for("new_default_top", protocoltype_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", defaulttop_id=top.id, diff=1), "Runter"), Table.link(url_for("move_default_top", defaulttop_id=top.id, diff=-1), "Hoch"), Table.link(url_for("edit_default_top", protocoltype_id=self.protocoltype.id, defaulttop_id=top.id), "Ändern"), Table.link(url_for("delete_default_top", defaulttop_id=top.id), "Löschen", confirm="Bist du dir sicher, dass du den Standard-TOP {} löschen willst?".format(top.name)) ]) ] class MeetingRemindersTable(Table): def __init__(self, reminders, protocoltype=None): super().__init__("Einladungsmails", reminders, newlink=url_for("new_reminder", protocoltype_id=protocoltype.id) if protocoltype is not None else None) self.protocoltype = protocoltype def headers(self): return ["Zeit", "Einladen", "Zusätzlicher Mailinhalt", ""] def row(self, reminder): user = current_user() general_part = [ "{} Tage".format(reminder.days_before), self.get_send_summary(reminder), reminder.additional_text or "" ] action_links = [ Table.link(url_for("edit_reminder", meetingreminder_id=reminder.id), "Ändern"), Table.link(url_for("delete_reminder", meetingreminder_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)) ] action_part = [Table.concat(action_links)] return general_part + action_part 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) class ErrorsTable(Table): def __init__(self, errors): super().__init__("Fehler", errors) def headers(self): return ["Protokoll", "Aktion", "Fehler", "Zeitpunkt", "Beschreibung", ""] def classes(self): return [None, None, None, None, "hidden-xs", "hidden-xs"] def row(self, error): return [ Table.link(url_for("show_protocol", protocol_id=error.protocol.id), error.protocol.get_short_identifier()), error.action, Table.link(url_for("show_error", error_id=error.id), error.name), datetime_filter(error.datetime), error.get_short_description(), Table.link(url_for("delete_error", error_id=error.id, next=request.path), "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"] def row(self): return [ Table.link(url_for("show_protocol", protocol_id=self.value.protocol.id), self.value.protocol.get_short_identifier()), self.value.action, self.value.name, datetime_filter(self.value.datetime) ] class TodosTable(Table): def __init__(self, todos): super().__init__("Todos", todos, newlink=url_for("new_todo")) def headers(self): return ["Todo", "ID", "Status", "Sitzung", "Name", "Aufgabe", ""] def classes(self): return ["hidden-sm hidden-md hidden-lg", "hidden-xs", "hidden-xs", "hidden-xs", "hidden-xs", None, "hidden-xs"] def row(self, todo): user = current_user() protocol = todo.get_first_protocol() mobile_parts = [Table.link(url_for("show_todo", todo_id=todo.id), todo.get_state())] if protocol is not None: mobile_parts.append(Table.link(url_for("show_protocol", protocol_id=protocol.id), todo.protocoltype.short_name)) mobile_parts.append(todo.who) row = [ Markup("
").join(mobile_parts), 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_short_identifier()) if protocol is not None else Table.link(url_for("list_protocols", protocoltype_id=todo.protocoltype.id), todo.protocoltype.short_name), todo.who, todo.description, ] if todo.protocoltype.has_modify_right(user): row.append(Table.concat([ Table.link(url_for("edit_todo", todo_id=todo.id), "Ändern"), Table.link(url_for("delete_todo", todo_id=todo.id), "Löschen") ])) 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", ""] def row(self): user = current_user() protocol = self.value.get_first_protocol() row = [ self.value.get_id(), self.value.get_state_plain(), Table.concat([ Table.link(url_for("show_protocol", protocol_id=protocol.id), protocol.get_short_identifier()) for protocol in self.value.protocols ]), self.value.who, self.value.description ] 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): super().__init__("Beschlüsse", decisions) self.category_present = len([ decision for decision in decisions if len(decision.categories) > 0 ]) > 0 def headers(self): content_part = ["Sitzung", "Beschluss"] category_part = ["Kategorie"] if not self.category_present: category_part = [] action_part = [""] return content_part + category_part + action_part def row(self, decision): user = current_user() content_part = [ Table.link(url_for("show_protocol", protocol_id=decision.protocol.id), decision.protocol.get_short_identifier()), decision.content ] category_part = [decision.get_categories_str()] if not self.category_present: category_part = [] action_part = [ Table.link(url_for("print_decision", decisiondocument_id=decision.document.id), "Drucken") if config.PRINTING_ACTIVE and decision.protocol.protocoltype.has_modify_right(user) and decision.document is not None else "" ] return content_part + category_part + action_part class DocumentsTable(Table): def __init__(self, documents, protocol): super().__init__("Anhang", documents) self.protocol = protocol def headers(self): user = current_user() general_headers = ["ID", "Name"] visibility_headers = [] if self.protocol.has_private_view_right(user): visibility_headers = ["Sichtbarkeit"] action_headers=[""] return general_headers + visibility_headers + action_headers def classes(self): user = current_user() general_part = [None, None] visibility_part = [] if self.protocol.has_private_view_right(user): visibility_part = [None] action_part = ["hidden-xs"] return general_part + visibility_part + action_part def row(self, document): user = current_user() links = [] if document.protocol.has_modify_right(user): links.append(Table.link(url_for("edit_document", document_id=document.id), "Bearbeiten")) if config.PRINTING_ACTIVE and document.protocol.has_modify_right(user): links.append(Table.link(url_for("print_document", document_id=document.id), "Drucken")) if document.protocol.protocoltype.has_admin_right(user): links.append(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))) general_part = [ document.id, Table.link(url_for("download_document", document_id=document.id), document.name), ] visibility_part = [] if document.protocol.has_private_view_right(user): visibility_part = ["Intern" if document.is_private else "Öffentlich"] action_part = [Table.concat(links)] return general_part + visibility_part + action_part 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)) ]) ] class DefaultMetasTable(Table): def __init__(self, metas, protocoltype): super().__init__( "Metadatenfelder", metas, url_for("new_defaultmeta", protocoltype_id=protocoltype.id) ) def headers(self): return ["Name", "Key", "Standardwert", "Intern", "Vorher", ""] def row(self, meta): user = current_user() general_part = [ meta.name, meta.key, meta.value, Table.bool(meta.internal), Table.bool(meta.prior) ] links = [ Table.link(url_for("edit_defaultmeta", defaultmeta_id=meta.id), "Ändern"), Table.link(url_for("delete_defaultmeta", defaultmeta_id=meta.id), "Löschen", confirm="Bist du dir sicher, dass du das Metadatenfeld {} löschen willst?".format(meta.name)) ] link_part = [Table.concat(links)] return general_part + link_part class DecisionCategoriesTable(Table): def __init__(self, categories, protocoltype): super().__init__( "Beschlusskategorien", categories, url_for("new_decisioncategory", protocoltype_id=protocoltype.id) ) def headers(self): return ["Name", ""] def row(self, category): user = current_user() general_part = [category.name] action_part = [ Table.concat([ Table.link(url_for("edit_decisioncategory", decisioncategory_id=category.id), "Ändern"), Table.link(url_for("delete_decisioncategory", decisioncategory_id=category.id), "Löschen", confirm="Bist du dir sicher, dass du die Beschlusskategorie {} löschen willst?".format(category.name)) ]) ] return general_part + action_part