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

5
6
import ipaddress

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

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

Robin Sonnabend's avatar
Robin Sonnabend committed
13
def get_protocoltype_choices(protocoltypes, add_all=True):
14
15
16
17
18
    choices = [
        (protocoltype.id, protocoltype.short_name)
        for protocoltype
        in sorted(protocoltypes, key=lambda t: t.short_name)
    ]
Robin Sonnabend's avatar
Robin Sonnabend committed
19
    if add_all:
20
21
22
23
24
25
26
27
28
29
30
        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
31
32
    return choices

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

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

def get_printer_choices():
55
56
57
    choices = []
    if config.PRINTING_PRINTERS is not None:
        choices = list(zip(config.PRINTING_PRINTERS, config.PRINTING_PRINTERS))
58
59
60
61
62
    choices.insert(0, ("", "Nicht drucken"))
    return choices

def get_group_choices():
    user = current_user()
Robin Sonnabend's avatar
Robin Sonnabend committed
63
64
    groups = sorted(user.groups)
    choices = list(zip(groups, groups))
65
66
    choices.insert(0, ("", "Keine Gruppe"))
    return choices
Robin Sonnabend's avatar
Robin Sonnabend committed
67

68
69
70
71
72
73
def coerce_todostate(key):
    if isinstance(key, str):
        class_part, key_part = key.split(".")
        key = TodoState[key_part]
    return key

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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))

102
103
class FocusedStringField(StringField):
    def __call__(self, **kwargs):
104
105
        kwargs['autofocus'] = True
        return super().__call__(**kwargs)
106

107
class LoginForm(FlaskForm):
108
    username = FocusedStringField("Benutzer", validators=[InputRequired("Bitte gib deinen Benutzernamen ein.")])
Robin Sonnabend's avatar
Robin Sonnabend committed
109
    password = PasswordField("Passwort", validators=[InputRequired("Bitte gib dein Passwort ein.")])
110
    permanent = BooleanField("Eingeloggt bleiben?")
Robin Sonnabend's avatar
Robin Sonnabend committed
111
112
113
114
115

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
116
    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
117
    is_public = BooleanField("Öffentlich sichtbar")
Robin Sonnabend's avatar
Robin Sonnabend committed
118
    publish_group = SelectField("Verwaltungsgruppe", choices=[])
119
    modify_group = SelectField("Bearbeitungsgruppe", choices=[])
120
121
    private_group = SelectField("Interne Gruppe", choices=[])
    public_group = SelectField("Öffentliche Gruppe", choices=[])
122
    non_reproducible_pad_links = BooleanField("nicht nachvollziehbare Etherpad-Links")
Robin Sonnabend's avatar
Robin Sonnabend committed
123
124
    private_mail = StringField("Interner Verteiler")
    public_mail = StringField("Öffentlicher Verteiler")
Robin Sonnabend's avatar
Robin Sonnabend committed
125
126
127
    wiki_category = StringField("Wiki-Kategorie")
    use_wiki = BooleanField("Wiki benutzen")
    wiki_only_public = BooleanField("Wiki ist öffentlich")
128
    printer = SelectField("Drucker", choices=[])
129
    calendar = SelectField("Kalender", choices=[])
130
131
    restrict_networks = BooleanField("Netzwerke einschränken")
    allowed_networks = IPNetworkField("Erlaubte Netzwerke")
132
133

    def __init__(self, **kwargs):
134
        super().__init__(**kwargs)
Robin Sonnabend's avatar
Robin Sonnabend committed
135
136
        protocoltype = kwargs["obj"] if "obj" in kwargs else None
        self.calendar.choices = get_calendar_choices(protocoltype=protocoltype)
137
138
        self.printer.choices = get_printer_choices()
        group_choices = get_group_choices()
Robin Sonnabend's avatar
Robin Sonnabend committed
139
        self.publish_group.choices = group_choices
140
        self.modify_group.choices = group_choices
141
142
        self.private_group.choices = group_choices
        self.public_group.choices = group_choices
Robin Sonnabend's avatar
Robin Sonnabend committed
143
144
145
146

class DefaultTopForm(FlaskForm):
    name = StringField("Name", validators=[InputRequired("Du musst einen Namen angeben.")])
    number = IntegerField("Nummer", validators=[InputRequired("Du musst eine Nummer angeben.")])
147
    description = TextAreaField("Standardinhalt")
148
149
150
151
152

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
153
    additional_text = TextAreaField("Zusätzlicher Mailinhalt")
Robin Sonnabend's avatar
Robin Sonnabend committed
154
155

class NewProtocolForm(FlaskForm):
156
    protocoltype_id = SelectField("Typ", choices=[], coerce=int)
157
    date = DateField("Datum (dd.mm.yyyy)", validators=[InputRequired("Du musst ein Datum angeben.")], format="%d.%m.%Y")
158
    start_time = DateTimeField("Uhrzeit (HH:MM, optional)", validators=[Optional()], format="%H:%M")
Robin Sonnabend's avatar
Robin Sonnabend committed
159
160
161

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

Robin Sonnabend's avatar
Robin Sonnabend committed
164
165
166
167
class DocumentEditForm(FlaskForm):
    name = StringField("Dateiname")
    is_private = BooleanField("Intern")

168
class DocumentUploadForm(FlaskForm):
Robin Sonnabend's avatar
Robin Sonnabend committed
169
    document = FileField("Datei")
170
    is_private = BooleanField("Intern")
Robin Sonnabend's avatar
Robin Sonnabend committed
171
172
173
174
175
176

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

class NewProtocolSourceUploadForm(FlaskForm):
    source = FileField("Quellcode")
177
    protocoltype_id = SelectField("Typ", choices=[], coerce=int)
Robin Sonnabend's avatar
Robin Sonnabend committed
178
179
180

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

183
184
class NewProtocolFileUploadForm(FlaskForm):
    file = FileField("Datei")
185
    protocoltype_id = SelectField("Typ", choices=[], coerce=int)
186
187
188
189
    private = BooleanField("Intern")

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

192
193
194
195
196
197
198
199
200
201
202
203
204
205
def generate_protocol_form(protocol):
    class ProtocolMetasForm(FlaskForm):
        pass
    for meta in protocol.metas:
        setattr(ProtocolMetasForm, meta.name, StringField(meta.name))
    class ProtocolForm(FlaskForm):
        date = DateField("Datum (dd.mm.yyyy)", validators=[InputRequired("Bitte gib das Datum des Protkolls an.")], format="%d.%m.%Y")
        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
206

Robin Sonnabend's avatar
Robin Sonnabend committed
207
208
209
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.")])
210
    description = TextAreaField("Beschreibung")
Robin Sonnabend's avatar
Robin Sonnabend committed
211

212
213
214
class LocalTopForm(FlaskForm):
    description = TextAreaField("Beschreibung")

Robin Sonnabend's avatar
Robin Sonnabend committed
215
216
class SearchForm(FlaskForm):
    search = StringField("Suchbegriff")
217
    protocoltype_id = SelectField("Typ", choices=[], coerce=int)
Robin Sonnabend's avatar
Robin Sonnabend committed
218
219
220

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

223
224
225
226
227
228
229
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
230
class ProtocolSearchForm(SearchForm):
Robin Sonnabend's avatar
Robin Sonnabend committed
231
    state_open = SelectField("Offen", choices=[(-1, "Alle"), (0, "Geplant"), (1, "Fertig")], coerce=int)
Robin Sonnabend's avatar
Robin Sonnabend committed
232

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

Robin Sonnabend's avatar
Robin Sonnabend committed
236
237
238
239
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.")])
240
    state = SelectField("Status", choices=[], coerce=coerce_todostate, validators=[CheckTodoDateByState()])
241
    date = DateField("Datum (dd.mm.yyyy)", format="%d.%m.%Y", validators=[Optional()])
Robin Sonnabend's avatar
Robin Sonnabend committed
242
243
244
245
    
    def __init__(self, protocoltypes, **kwargs):
        super().__init__(**kwargs)
        self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False)
246
        self.state.choices = get_todostate_choices()
Robin Sonnabend's avatar
Robin Sonnabend committed
247
248

class TodoForm(FlaskForm):
Robin Sonnabend's avatar
Robin Sonnabend committed
249
    who = StringField("Person")
Robin Sonnabend's avatar
Robin Sonnabend committed
250
    description = StringField("Aufgabe", validators=[InputRequired("Bitte gib an, was erledigt werden soll.")])
251
    state = SelectField("Status", choices=[], coerce=coerce_todostate, validators=[CheckTodoDateByState()])
252
    date = DateField("Datum (dd.mm.yyyy)", format="%d.%m.%Y", validators=[Optional()])
253

254
255
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
256
        self.state.choices = get_todostate_choices()
Robin Sonnabend's avatar
Robin Sonnabend committed
257
258
259
260

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
261
262
263
264

class MetaForm(FlaskForm):
    name = StringField("Name", validators=[InputRequired("Bitte gib den Namen der Metadaten an.")])
    value = StringField("Wert")
265
    internal = BooleanField("Intern")
Robin Sonnabend's avatar
Robin Sonnabend committed
266
267
268
269

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.")])
270
    value = StringField("Standardwert")
271
    internal = BooleanField("Intern")
272
    prior = BooleanField("Planungsrelevant")
273

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

277
278
279
280
281
282
283
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