forms.py 12.2 KB
Newer Older
1
from flask_wtf import FlaskForm
2
3
from wtforms import StringField, PasswordField, BooleanField, HiddenField, IntegerField, SelectField, FileField, DateTimeField, TextAreaField, Field, widgets, FormField
from wtforms.fields.html5 import DateField
Robin Sonnabend's avatar
Robin Sonnabend committed
4
from wtforms.validators import InputRequired, Optional
5

6
7
import ipaddress

8
9
from models.database import TodoState
from validators import CheckTodoDateByState
10
from shared import current_user
11

Robin Sonnabend's avatar
Robin Sonnabend committed
12
13
import config

Robin Sonnabend's avatar
Robin Sonnabend committed
14
def get_protocoltype_choices(protocoltypes, add_all=True):
15
16
17
18
19
    choices = [
        (protocoltype.id, protocoltype.short_name)
        for protocoltype
        in sorted(protocoltypes, key=lambda t: t.short_name)
    ]
Robin Sonnabend's avatar
Robin Sonnabend committed
20
    if add_all:
21
22
23
24
25
26
27
28
29
30
31
        choices.insert(0, (-1, "Alle Typen"))
    return choices

def get_category_choices(categories, add_all=True):
    choices = [
        (category.id, category.name)
        for category
        in sorted(categories, key=lambda c: c.name)
    ]
    if add_all:
        choices.insert(0, (-1, "Alle Kategorien"))
Robin Sonnabend's avatar
Robin Sonnabend committed
32
33
    return choices

34
35
def get_todostate_choices():
    return [
36
        (state, state.get_name())
37
38
39
        for state in TodoState
    ]

Robin Sonnabend's avatar
Robin Sonnabend committed
40
def get_calendar_choices(protocoltype=None):
Robin Sonnabend's avatar
Robin Sonnabend committed
41
    from calendarpush import Client as CalendarClient
42
    calendars = CalendarClient().get_calendars()
43
44
45
46
    choices = []
    if calendars is not None:
        calendars = sorted(calendars)
        choices = list(zip(calendars, calendars))
Robin Sonnabend's avatar
Robin Sonnabend committed
47
48
49
50
51
    else:
        if (protocoltype is not None
        and protocoltype.calendar is not None
        and protocoltype.calendar != ""):
            choices.append((protocoltype.calendar, protocoltype.calendar))
52
53
54
55
    choices.insert(0, ("", "Kein Kalender"))
    return choices

def get_printer_choices():
56
57
58
    choices = []
    if config.PRINTING_PRINTERS is not None:
        choices = list(zip(config.PRINTING_PRINTERS, config.PRINTING_PRINTERS))
59
60
    choices.insert(0, ("", "Nicht drucken"))
    return choices
61
62
63
	
def get_latex_template_choices():
    choices = []
64
65
    _latex_templates = getattr(config, "LATEX_TEMPLATES", None)
    if _latex_templates is not None:
66
67
68
        choices = [
            (key, values['name'])
            for key, values
69
            in _latex_templates.items()
70
71
72
        ]
    choices.insert(0, ("", "Standardvorlage"))
    return choices
73
74
75

def get_group_choices():
    user = current_user()
Robin Sonnabend's avatar
Robin Sonnabend committed
76
77
    groups = sorted(user.groups)
    choices = list(zip(groups, groups))
78
79
    choices.insert(0, ("", "Keine Gruppe"))
    return choices
Robin Sonnabend's avatar
Robin Sonnabend committed
80

81
82
83
84
85
86
def coerce_todostate(key):
    if isinstance(key, str):
        class_part, key_part = key.split(".")
        key = TodoState[key_part]
    return key

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
class IPNetworkField(Field):
    widget = widgets.TextInput()

    def __init__(self, label=None, validators=None, **kwargs):
        super().__init__(label, validators, **kwargs)

    def _value(self):
        if self.raw_data:
            return " ".join(self.raw_data)
        else:
            return self.data and str(self.data) or ""

    def process_formdata(self, valuelist):
        if valuelist:
            data_str = valuelist[0]
            result_parts = []
            try:
                for part in data_str.split(","):
                    part = part.strip()
                    if len(part) > 0:
                        network = ipaddress.ip_network(part)
                        result_parts.append(network)
            except ValueError as exc:
                print(exc)
                self.data = None
                raise ValueError(self.gettext("Not a valid IP Network: {}".format(str(exc))))
            self.data = ",".join(map(str, result_parts))

115
116
class FocusedStringField(StringField):
    def __call__(self, **kwargs):
117
118
        kwargs['autofocus'] = True
        return super().__call__(**kwargs)
119

120
class LoginForm(FlaskForm):
121
    username = FocusedStringField("Benutzer", validators=[InputRequired("Bitte gib deinen Benutzernamen ein.")])
Robin Sonnabend's avatar
Robin Sonnabend committed
122
    password = PasswordField("Passwort", validators=[InputRequired("Bitte gib dein Passwort ein.")])
123
    permanent = BooleanField("Eingeloggt bleiben?")
Robin Sonnabend's avatar
Robin Sonnabend committed
124
125
126
127
128

class ProtocolTypeForm(FlaskForm):
    name = StringField("Name", validators=[InputRequired("Du musst einen Namen angeben.")])
    short_name = StringField("Abkürzung", validators=[InputRequired("Du musst eine Abkürzung angebene.")])
    organization = StringField("Organisation", validators=[InputRequired("Du musst eine zugehörige Organisation angeben.")])
Robin Sonnabend's avatar
Robin Sonnabend committed
129
    usual_time = DateTimeField("Üblicher Beginn", validators=[InputRequired("Bitte gib die Zeit an, zu der die Sitzung beginnt.")], format="%H:%M")
Robin Sonnabend's avatar
Robin Sonnabend committed
130
    is_public = BooleanField("Öffentlich sichtbar")
Robin Sonnabend's avatar
Robin Sonnabend committed
131
    publish_group = SelectField("Verwaltungsgruppe", choices=[])
132
    modify_group = SelectField("Bearbeitungsgruppe", choices=[])
133
134
    private_group = SelectField("Interne Gruppe", choices=[])
    public_group = SelectField("Öffentliche Gruppe", choices=[])
135
    non_reproducible_pad_links = BooleanField("nicht nachvollziehbare Etherpad-Links")
Robin Sonnabend's avatar
Robin Sonnabend committed
136
137
    private_mail = StringField("Interner Verteiler")
    public_mail = StringField("Öffentlicher Verteiler")
Robin Sonnabend's avatar
Robin Sonnabend committed
138
139
140
    wiki_category = StringField("Wiki-Kategorie")
    use_wiki = BooleanField("Wiki benutzen")
    wiki_only_public = BooleanField("Wiki ist öffentlich")
141
    printer = SelectField("Drucker", choices=[])
142
    calendar = SelectField("Kalender", choices=[])
143
144
    restrict_networks = BooleanField("Netzwerke einschränken")
    allowed_networks = IPNetworkField("Erlaubte Netzwerke")
145
    latex_template = SelectField("LaTeX Vorlage", choices=[])
146
147

    def __init__(self, **kwargs):
148
        super().__init__(**kwargs)
Robin Sonnabend's avatar
Robin Sonnabend committed
149
150
        protocoltype = kwargs["obj"] if "obj" in kwargs else None
        self.calendar.choices = get_calendar_choices(protocoltype=protocoltype)
151
        self.printer.choices = get_printer_choices()
152
        self.latex_template.choices = get_latex_template_choices()
153
        group_choices = get_group_choices()
Robin Sonnabend's avatar
Robin Sonnabend committed
154
        self.publish_group.choices = group_choices
155
        self.modify_group.choices = group_choices
156
157
        self.private_group.choices = group_choices
        self.public_group.choices = group_choices
Robin Sonnabend's avatar
Robin Sonnabend committed
158
159
160
161

class DefaultTopForm(FlaskForm):
    name = StringField("Name", validators=[InputRequired("Du musst einen Namen angeben.")])
    number = IntegerField("Nummer", validators=[InputRequired("Du musst eine Nummer angeben.")])
162
    description = TextAreaField("Standardinhalt")
163
164
165
166
167

class MeetingReminderForm(FlaskForm):
    days_before = IntegerField("Tage vor Sitzung", validators=[InputRequired("Du musst eine Dauer angeben.")])
    send_public = BooleanField("Öffentlich einladen")
    send_private = BooleanField("Intern einladen")
Robin Sonnabend's avatar
Robin Sonnabend committed
168
    additional_text = TextAreaField("Zusätzlicher Mailinhalt")
Robin Sonnabend's avatar
Robin Sonnabend committed
169
170

class NewProtocolForm(FlaskForm):
171
    protocoltype_id = SelectField("Typ", choices=[], coerce=int)
172
    date = DateField("Datum", validators=[InputRequired("Du musst ein Datum angeben.")])
173
    start_time = DateTimeField("Uhrzeit (HH:MM, optional)", validators=[Optional()], format="%H:%M")
Robin Sonnabend's avatar
Robin Sonnabend committed
174
175
176

    def __init__(self, protocoltypes, **kwargs):
        super().__init__(**kwargs)
177
        self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False)
178

Robin Sonnabend's avatar
Robin Sonnabend committed
179
180
181
182
class DocumentEditForm(FlaskForm):
    name = StringField("Dateiname")
    is_private = BooleanField("Intern")

183
class DocumentUploadForm(FlaskForm):
Robin Sonnabend's avatar
Robin Sonnabend committed
184
    document = FileField("Datei")
185
    is_private = BooleanField("Intern")
Robin Sonnabend's avatar
Robin Sonnabend committed
186
187
188
189
190
191

class KnownProtocolSourceUploadForm(FlaskForm):
    source = FileField("Quellcode")

class NewProtocolSourceUploadForm(FlaskForm):
    source = FileField("Quellcode")
192
    protocoltype_id = SelectField("Typ", choices=[], coerce=int)
Robin Sonnabend's avatar
Robin Sonnabend committed
193
194
195

    def __init__(self, protocoltypes, **kwargs):
        super().__init__(**kwargs)
196
        self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False)
Robin Sonnabend's avatar
Robin Sonnabend committed
197

198
199
class NewProtocolFileUploadForm(FlaskForm):
    file = FileField("Datei")
200
    protocoltype_id = SelectField("Typ", choices=[], coerce=int)
201
202
203
204
    private = BooleanField("Intern")

    def __init__(self, protocoltypes, **kwargs):
        super().__init__(**kwargs)
205
        self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False)
206

207
208
209
210
211
212
def generate_protocol_form(protocol):
    class ProtocolMetasForm(FlaskForm):
        pass
    for meta in protocol.metas:
        setattr(ProtocolMetasForm, meta.name, StringField(meta.name))
    class ProtocolForm(FlaskForm):
213
        date = DateField("Datum", validators=[InputRequired("Bitte gib das Datum des Protkolls an.")])
214
215
216
217
218
219
220
        start_time = DateTimeField("Beginn (%H:%M)", format="%H:%M", validators=[Optional()])
        end_time = DateTimeField("Ende (%H:%M)", format="%H:%M", validators=[Optional()])
        metas = FormField(ProtocolMetasForm)
        done = BooleanField("Fertig")
        public = BooleanField("Veröffentlicht")
    return ProtocolForm
    
Robin Sonnabend's avatar
Robin Sonnabend committed
221

Robin Sonnabend's avatar
Robin Sonnabend committed
222
223
224
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.")])
225
    description = TextAreaField("Beschreibung")
Robin Sonnabend's avatar
Robin Sonnabend committed
226

227
228
229
class LocalTopForm(FlaskForm):
    description = TextAreaField("Beschreibung")

Robin Sonnabend's avatar
Robin Sonnabend committed
230
231
class SearchForm(FlaskForm):
    search = StringField("Suchbegriff")
232
    protocoltype_id = SelectField("Typ", choices=[], coerce=int)
Robin Sonnabend's avatar
Robin Sonnabend committed
233
234
235

    def __init__(self, protocoltypes, **kwargs):
        super().__init__(**kwargs)
236
        self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes)
Robin Sonnabend's avatar
Robin Sonnabend committed
237

238
239
240
241
242
243
244
class DecisionSearchForm(SearchForm):
    decisioncategory_id = SelectField("Kategorie", choices=[], coerce=int)

    def __init__(self, protocoltypes, categories, **kwargs):
        super().__init__(protocoltypes=protocoltypes, **kwargs)
        self.decisioncategory_id.choices = get_category_choices(categories)

Robin Sonnabend's avatar
Robin Sonnabend committed
245
class ProtocolSearchForm(SearchForm):
Robin Sonnabend's avatar
Robin Sonnabend committed
246
    state_open = SelectField("Offen", choices=[(-1, "Alle"), (0, "Geplant"), (1, "Fertig")], coerce=int)
Robin Sonnabend's avatar
Robin Sonnabend committed
247

Robin Sonnabend's avatar
Robin Sonnabend committed
248
class TodoSearchForm(SearchForm):
Robin Sonnabend's avatar
Robin Sonnabend committed
249
    state_open = SelectField("Offen", choices=[(-1, "Alle"), (0, "Offen"), (1, "Erledigt")], coerce=int)
Robin Sonnabend's avatar
Robin Sonnabend committed
250

Robin Sonnabend's avatar
Robin Sonnabend committed
251
252
253
254
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.")])
255
    state = SelectField("Status", choices=[], coerce=coerce_todostate, validators=[CheckTodoDateByState()])
256
    date = DateField("Datum)", validators=[Optional()])
Robin Sonnabend's avatar
Robin Sonnabend committed
257
258
259
260
    
    def __init__(self, protocoltypes, **kwargs):
        super().__init__(**kwargs)
        self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False)
261
        self.state.choices = get_todostate_choices()
Robin Sonnabend's avatar
Robin Sonnabend committed
262
263

class TodoForm(FlaskForm):
Robin Sonnabend's avatar
Robin Sonnabend committed
264
    who = StringField("Person")
Robin Sonnabend's avatar
Robin Sonnabend committed
265
    description = StringField("Aufgabe", validators=[InputRequired("Bitte gib an, was erledigt werden soll.")])
266
    state = SelectField("Status", choices=[], coerce=coerce_todostate, validators=[CheckTodoDateByState()])
267
    date = DateField("Datum", validators=[Optional()])
268

269
270
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
271
        self.state.choices = get_todostate_choices()
Robin Sonnabend's avatar
Robin Sonnabend committed
272
273
274
275

class TodoMailForm(FlaskForm):
    name = StringField("Name", validators=[InputRequired("Du musst den Namen angeben, der zugeordnet werden soll.")])
    mail = StringField("Mail", validators=[InputRequired("Du musst die Mailadresse angeben, die zugeordnet werden soll.")])
Robin Sonnabend's avatar
Robin Sonnabend committed
276
277
278
279

class MetaForm(FlaskForm):
    name = StringField("Name", validators=[InputRequired("Bitte gib den Namen der Metadaten an.")])
    value = StringField("Wert")
280
    internal = BooleanField("Intern")
Robin Sonnabend's avatar
Robin Sonnabend committed
281
282
283
284

class DefaultMetaForm(FlaskForm):
    key = StringField("Key", validators=[InputRequired("Bitte gib den Protokoll-Syntax-Schlüssel der Metadaten an.")])
    name = StringField("Name", validators=[InputRequired("Bitte gib den Namen der Metadaten an.")])
285
    value = StringField("Standardwert")
286
    internal = BooleanField("Intern")
287
    prior = BooleanField("Planungsrelevant")
288

289
290
291
class DecisionCategoryForm(FlaskForm):
    name = StringField("Name", validators=[InputRequired("Bitte gib den Namen der Kategorie an.")])

292
293
294
295
296
297
298
class MergeTodosForm(FlaskForm):
    todo1 = IntegerField("todo 1", validators=[InputRequired()])
    todo2 = IntegerField("todo 2", validators=[InputRequired()])

    def __init__(self, todo=None):
        if todo is not None:
            self.todo1.data = todo.id