• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

chiefonboarding / ChiefOnboarding / 6427167771

06 Oct 2023 03:33AM UTC coverage: 93.316% (-0.06%) from 93.378%
6427167771

Pull #364

github

web-flow
Merge 6cef66109 into 80bf55996
Pull Request #364: Allow trigger items on admin task (sequence)

5878 of 6299 relevant lines covered (93.32%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.19
back/admin/sequences/forms.py
1
from crispy_forms.helper import FormHelper
1✔
2
from crispy_forms.layout import HTML, Div, Field, Layout
1✔
3
from django import forms
1✔
4
from django.core.exceptions import ValidationError
1✔
5
from django.utils.translation import gettext_lazy as _
1✔
6

7
from admin.templates.forms import MultiSelectField, WYSIWYGField
1✔
8
from admin.to_do.models import ToDo
1✔
9
from users.models import User
1✔
10

11
from .models import (
1✔
12
    Condition,
13
    ExternalMessage,
14
    PendingAdminTask,
15
    PendingEmailMessage,
16
    PendingSlackMessage,
17
    PendingTextMessage,
18
)
19

20

21
class ConditionCreateForm(forms.ModelForm):
1✔
22
    condition_to_do = forms.ModelMultipleChoiceField(
1✔
23
        queryset=ToDo.templates.defer_content().all(),
24
        to_field_name="id",
25
        required=False,
26
    )
27
    condition_admin_tasks = forms.ModelMultipleChoiceField(
1✔
28
        queryset=PendingAdminTask.objects.all(),
29
        to_field_name="id",
30
        required=False,
31
    )
32

33
    def _get_save_button(self):
1✔
34
        return (
1✔
35
            (
36
                '<button hx-post="{% url "sequences:condition-create" object.id %}" '
37
                'hx-target="#condition_form" hx-swap="#condition_form" '
38
                'class="btn btn-primary ms-auto">'
39
            )
40
            + _("Add block")
41
            + "</button>"
42
        )
43

44
    def __init__(self, *args, **kwargs):
1✔
45
        sequence = kwargs.pop("sequence")
1✔
46
        super().__init__(*args, **kwargs)
1✔
47
        self.helper = FormHelper()
1✔
48
        self.helper.layout = Layout(
1✔
49
            Field("condition_type"),
50
            Div(
51
                MultiSelectField("condition_to_do"),
52
                css_class="" if self.instance.based_on_to_do else "d-none",
53
            ),
54
            Div(
55
                Field("days"),
56
                Field("time"),
57
                css_class="" if self.instance.based_on_time else "d-none",
58
            ),
59
            Div(
60
                Field("condition_admin_tasks"),
61
                css_class="" if self.instance.based_on_admin_task else "d-none",
62
            ),
63
            HTML(self._get_save_button()),
64
        )
65
        self.fields["time"].required = False
1✔
66
        self.fields["days"].required = False
1✔
67
        self.fields["condition_to_do"].required = False
1✔
68
        pending_tasks = PendingAdminTask.objects.filter(condition__sequence=sequence)
1✔
69
        self.fields["condition_admin_tasks"].queryset = pending_tasks
1✔
70
        # Remove last option, which will only be one of
71
        self.fields["condition_type"].choices = tuple(
1✔
72
            x for x in Condition.Type.choices if x[0] != 3
73
        )
74

75
    class Meta:
1✔
76
        model = Condition
1✔
77
        fields = [
1✔
78
            "condition_type",
79
            "days",
80
            "time",
81
            "condition_to_do",
82
            "condition_admin_tasks",
83
        ]
84
        widgets = {
1✔
85
            "time": forms.TimeInput(attrs={"type": "time", "step": 300}),
86
        }
87
        help_texts = {
1✔
88
            "time": _("Must be in a 5 minute interval."),
89
        }
90

91
    def clean_days(self):
1✔
92
        day = self.cleaned_data["days"]
1✔
93
        if day is None:
1✔
94
            # Handled in clean() function
95
            return day
1✔
96
        if (
1✔
97
            self.cleaned_data["condition_type"]
98
            in [Condition.Type.AFTER, Condition.Type.BEFORE]
99
            and day <= 0
100
        ):
101
            raise ValidationError(
1✔
102
                _(
103
                    "You cannot use 0 or less. The day before starting is 1 and the "
104
                    "first workday is 1"
105
                )
106
            )
107

108
        return day
1✔
109

110
    def clean_time(self):
1✔
111
        time = self.cleaned_data["time"]
1✔
112
        if time is None:
1✔
113
            # Handled in clean() function
114
            return time
1✔
115
        if time.minute % 10 not in [0, 5] and self.cleaned_data["condition_type"] in [
1✔
116
            Condition.Type.BEFORE,
117
            Condition.Type.AFTER,
118
        ]:
119
            raise ValidationError(
1✔
120
                _(
121
                    "Time must be in an interval of 5 minutes. %(minutes)s must end in "
122
                    "0 or 5."
123
                )
124
                % {"minutes": time.minute}
125
            )
126

127
        return time
1✔
128

129
    def clean(self):
1✔
130
        cleaned_data = super().clean()
1✔
131
        condition_type = cleaned_data.get("condition_type", None)
1✔
132
        time = cleaned_data.get("time", None)
1✔
133
        days = cleaned_data.get("days", None)
1✔
134
        condition_to_do = cleaned_data.get("condition_to_do", None)
1✔
135
        condition_admin_tasks = cleaned_data.get("condition_admin_tasks", None)
1✔
136
        if condition_type == Condition.Type.TODO and (
1✔
137
            condition_to_do is None or len(condition_to_do) == 0
138
        ):
139
            raise ValidationError(_("You must add at least one to do item"))
1✔
140
        if condition_type == Condition.Type.ADMIN_TASK and (
1✔
141
            condition_admin_tasks is None or len(condition_admin_tasks) == 0
142
        ):
143
            raise ValidationError(_("You must add at least one admin task"))
1✔
144
        if condition_type in [Condition.Type.AFTER, Condition.Type.BEFORE] and (
1✔
145
            time is None or days is None
146
        ):
147
            raise ValidationError(_("Both the time and days have to be filled in."))
1✔
148
        return cleaned_data
1✔
149

150

151
class ConditionUpdateForm(ConditionCreateForm):
1✔
152
    def _get_save_button(self):
1✔
153
        return (
1✔
154
            (
155
                '<button hx-post="{% url "sequences:condition-update" object.id '
156
                'condition.id %}" hx-target="#condition_form" '
157
                'hx-swap="#add-condition-form" class="btn btn-primary ms-auto">'
158
            )
159
            + _("Edit block")
160
            + "</button>"
161
        )
162

163

164
class PendingAdminTaskForm(forms.ModelForm):
1✔
165
    assigned_to = forms.ModelChoiceField(
1✔
166
        queryset=User.managers_and_admins.all(), required=False
167
    )
168
    slack_user = forms.ModelChoiceField(
1✔
169
        queryset=User.objects.exclude(slack_user_id=""),
170
        required=False,
171
    )
172
    date = forms.DateField(
1✔
173
        label=_("Due date"),
174
        required=False,
175
        widget=forms.DateInput(attrs={"type": "date"}, format=("%Y-%m-%d")),
176
    )
177

178
    def __init__(self, *args, **kwargs):
1✔
179
        super().__init__(*args, **kwargs)
1✔
180
        self.fields["option"].initial = PendingAdminTask.Notification.NO
1✔
181
        self.fields["comment"].required = True
1✔
182
        self.helper = FormHelper()
1✔
183
        self.helper.form_tag = False
1✔
184

185
        # Check if assigned_to field should be hidden
186
        hide_assigned_to = "d-none"
1✔
187
        if (
1✔
188
            self.instance is not None
189
            and self.instance.person_type == PendingAdminTask.PersonType.CUSTOM
190
        ):
191
            hide_assigned_to = ""
1✔
192

193
        self.helper.layout = Layout(
1✔
194
            Div(
195
                Field("name"),
196
                Field("person_type"),
197
                Div(
198
                    Field("assigned_to"),
199
                    css_class=hide_assigned_to,
200
                ),
201
                Field("date"),
202
                Field("priority"),
203
                Field("comment"),
204
                Field("option"),
205
                Field("slack_user"),
206
                Field("email"),
207
            ),
208
        )
209

210
    class Meta:
1✔
211
        model = PendingAdminTask
1✔
212
        fields = [
1✔
213
            "name",
214
            "person_type",
215
            "assigned_to",
216
            "date",
217
            "priority",
218
            "comment",
219
            "option",
220
            "slack_user",
221
            "email",
222
        ]
223

224
    def clean(self):
1✔
225
        cleaned_data = super().clean()
×
226
        assigned_to = cleaned_data.get("assigned_to", None)
×
227
        person_type = cleaned_data["person_type"]
×
228
        if person_type == PendingAdminTask.PersonType.CUSTOM and assigned_to is None:
×
229
            self.add_error("assigned_to", _("This field is required"))
×
230
        return cleaned_data
×
231

232

233
class PendingSlackMessageForm(forms.ModelForm):
1✔
234
    def __init__(self, *args, **kwargs):
1✔
235
        super().__init__(*args, **kwargs)
1✔
236
        self.helper = FormHelper()
1✔
237
        self.helper.form_tag = False
1✔
238

239
        # Check if send_to field should be hidden
240
        hide_send_to = "d-none"
1✔
241
        if (
1✔
242
            self.instance is not None
243
            and self.instance.person_type == ExternalMessage.PersonType.CUSTOM
244
        ):
245
            hide_send_to = ""
×
246

247
        hide_send_to_channel = "d-none"
1✔
248
        if (
1✔
249
            self.instance is not None
250
            and self.instance.person_type == ExternalMessage.PersonType.SLACK_CHANNEL
251
        ):
252
            hide_send_to_channel = ""
×
253

254
        self.helper.layout = Layout(
1✔
255
            Div(
256
                Field("name"),
257
                WYSIWYGField("content_json"),
258
                Field("person_type"),
259
                Div(
260
                    Field("send_to"),
261
                    css_class=hide_send_to,
262
                ),
263
                Div(
264
                    Field("send_to_channel"),
265
                    css_class=hide_send_to_channel,
266
                ),
267
            ),
268
        )
269

270
    class Meta:
1✔
271
        model = PendingSlackMessage
1✔
272
        fields = [
1✔
273
            "name",
274
            "content_json",
275
            "person_type",
276
            "send_to",
277
            "send_to_channel",
278
        ]
279

280

281
class PendingTextMessageForm(forms.ModelForm):
1✔
282
    def __init__(self, *args, **kwargs):
1✔
283
        super().__init__(*args, **kwargs)
1✔
284
        self.helper = FormHelper()
1✔
285
        self.helper.form_tag = False
1✔
286

287
        # Check if send_to field should be hidden
288
        hide_send_to = "d-none"
1✔
289
        if (
1✔
290
            self.instance is not None
291
            and self.instance.person_type == ExternalMessage.PersonType.CUSTOM
292
        ):
293
            hide_send_to = ""
×
294

295
        # Remove the Slack channel options
296
        self.fields["person_type"].choices = PendingAdminTask.PersonType.choices
1✔
297
        self.fields["person_type"].widget.choices = PendingAdminTask.PersonType.choices
1✔
298

299
        self.helper.layout = Layout(
1✔
300
            Div(
301
                Field("name"),
302
                Field("content"),
303
                Field("person_type"),
304
                Div(
305
                    Field("send_to"),
306
                    css_class=hide_send_to,
307
                ),
308
            ),
309
        )
310

311
    class Meta:
1✔
312
        model = PendingTextMessage
1✔
313
        fields = [
1✔
314
            "name",
315
            "content",
316
            "person_type",
317
            "send_to",
318
        ]
319

320

321
class PendingEmailMessageForm(forms.ModelForm):
1✔
322
    def __init__(self, *args, **kwargs):
1✔
323
        super().__init__(*args, **kwargs)
1✔
324
        self.helper = FormHelper()
1✔
325
        self.helper.form_tag = False
1✔
326

327
        # Check if send_to field should be hidden
328
        hide_send_to = "d-none"
1✔
329
        if (
1✔
330
            self.instance is not None
331
            and self.instance.person_type == ExternalMessage.PersonType.CUSTOM
332
        ):
333
            hide_send_to = ""
×
334

335
        # Remove the Slack channel options
336
        self.fields["person_type"].choices = PendingAdminTask.PersonType.choices
1✔
337
        self.fields["person_type"].widget.choices = PendingAdminTask.PersonType.choices
1✔
338

339
        self.helper.layout = Layout(
1✔
340
            Div(
341
                Field("name"),
342
                Field("subject"),
343
                WYSIWYGField("content_json"),
344
                Field("person_type"),
345
                Div(
346
                    Field("send_to"),
347
                    css_class=hide_send_to,
348
                ),
349
            ),
350
        )
351

352
    class Meta:
1✔
353
        model = PendingEmailMessage
1✔
354
        fields = [
1✔
355
            "name",
356
            "subject",
357
            "content_json",
358
            "person_type",
359
            "send_to",
360
        ]
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc