예제 #1
0
    def customize_form_field(self, name, field):
        attrs = field.widget.attrs if field.widget.attrs else {}

        # don't replace the widget if it is already one of us
        if isinstance(field.widget,
                      (forms.widgets.HiddenInput, CheckboxWidget, InputWidget,
                       SelectWidget, SelectMultipleWidget)):
            return field

        if isinstance(field.widget, (forms.widgets.Textarea, )):
            attrs["textarea"] = True
            field.widget = InputWidget(attrs=attrs)
        elif isinstance(
                field.widget,
            (forms.widgets.PasswordInput, )):  # pragma: needs cover
            attrs["password"] = True
            field.widget = InputWidget(attrs=attrs)
        elif isinstance(
                field.widget,
            (forms.widgets.TextInput, forms.widgets.EmailInput,
             forms.widgets.URLInput, forms.widgets.NumberInput),
        ):
            field.widget = InputWidget(attrs=attrs)
        elif isinstance(field.widget, (forms.widgets.Select, )):
            if isinstance(field, (forms.models.ModelMultipleChoiceField, )):
                field.widget = SelectMultipleWidget(
                    attrs)  # pragma: needs cover
            else:
                field.widget = SelectWidget(attrs)

            field.widget.choices = field.choices
        elif isinstance(field.widget, (forms.widgets.CheckboxInput, )):
            field.widget = CheckboxWidget(attrs)

        return field
예제 #2
0
class ScheduleForm(BaseScheduleForm, forms.ModelForm):
    repeat_period = forms.ChoiceField(choices=Schedule.REPEAT_CHOICES)

    repeat_days_of_week = forms.MultipleChoiceField(
        choices=Schedule.REPEAT_DAYS_CHOICES,
        label="Repeat Days",
        required=False,
        widget=SelectMultipleWidget(
            attrs=({
                "placeholder": _("Select days to repeat on")
            })),
    )

    start_datetime = forms.DateTimeField(
        required=False,
        label=_(" "),
        widget=InputWidget(
            attrs={
                "datetimepicker": True,
                "placeholder": "Select a time to send the message"
            }),
    )

    def __init__(self, org, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["start_datetime"].help_text = _("%s Time Zone" %
                                                    org.timezone)

    def clean_repeat_days_of_week(self):
        return "".join(self.cleaned_data["repeat_days_of_week"])

    class Meta:
        model = Schedule
        fields = "__all__"
예제 #3
0
class ScheduleFormMixin(forms.Form):
    start_datetime = forms.DateTimeField(
        label=_("Start Time"),
        widget=InputWidget(attrs={
            "datetimepicker": True,
            "placeholder": _("Select a date and time")
        }),
    )
    repeat_period = forms.ChoiceField(choices=Schedule.REPEAT_CHOICES,
                                      label=_("Repeat"),
                                      widget=SelectWidget())
    repeat_days_of_week = forms.MultipleChoiceField(
        choices=Schedule.REPEAT_DAYS_CHOICES,
        label=_("Repeat On Days"),
        help_text=_("The days of the week to repeat on for weekly schedules"),
        required=False,
        widget=SelectMultipleWidget(attrs=({
            "placeholder": _("Select days")
        })),
    )

    def set_user(self, user):
        """
        Because this mixin is mixed with other forms it can't have a __init__ constructor that takes non standard Django
        forms args and kwargs, so we have to customize based on user after the form has been created.
        """
        tz = user.get_org().timezone
        self.fields["start_datetime"].help_text = _(
            "First time this should happen in the %s timezone.") % tz

    def clean_repeat_days_of_week(self):
        value = self.cleaned_data["repeat_days_of_week"]

        # sort by Monday to Sunday
        value = sorted(value,
                       key=lambda c: Schedule.DAYS_OF_WEEK_OFFSET.index(c))

        return "".join(value)

    def clean(self):
        cleaned_data = super().clean()

        if self.is_valid():
            if cleaned_data[
                    "repeat_period"] == Schedule.REPEAT_WEEKLY and not cleaned_data.get(
                        "repeat_days_of_week"):
                self.add_error("repeat_days_of_week",
                               _("Must specify at least one day of the week."))

        return cleaned_data

    class Meta:
        fields = ("start_datetime", "repeat_period", "repeat_days_of_week")
예제 #4
0
class ExportForm(Form):
    LABEL_CHOICES = ((0, _("Just this label")), (1, _("All messages")))

    SYSTEM_LABEL_CHOICES = ((0, _("Just this folder")), (1, _("All messages")))

    export_all = forms.ChoiceField(
        choices=(), label=_("Selection"), initial=0, widget=SelectWidget(attrs={"widget_only": True})
    )

    start_date = forms.DateField(
        required=False,
        help_text=_("Leave blank for the oldest message"),
        widget=InputWidget(attrs={"datepicker": True, "hide_label": True, "placeholder": _("Start Date")}),
    )

    end_date = forms.DateField(
        required=False,
        help_text=_("Leave blank for the latest message"),
        widget=InputWidget(attrs={"datepicker": True, "hide_label": True, "placeholder": _("End Date")}),
    )

    groups = forms.ModelMultipleChoiceField(
        queryset=ContactGroup.user_groups.none(),
        required=False,
        label=_("Groups"),
        widget=SelectMultipleWidget(
            attrs={"widget_only": True, "placeholder": _("Optional: Choose groups to show in your export")}
        ),
    )

    def __init__(self, user, label, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.user = user

        self.fields["export_all"].choices = self.LABEL_CHOICES if label else self.SYSTEM_LABEL_CHOICES

        self.fields["groups"].queryset = ContactGroup.user_groups.filter(org=self.user.get_org(), is_active=True)
        self.fields["groups"].help_text = _(
            "Export only messages from these contact groups. " "(Leave blank to export all messages)."
        )

    def clean(self):
        cleaned_data = super().clean()
        start_date = cleaned_data.get("start_date")
        end_date = cleaned_data.get("end_date")

        if start_date and start_date > date.today():  # pragma: needs cover
            raise forms.ValidationError(_("Start date can't be in the future."))

        if end_date and start_date and end_date < start_date:  # pragma: needs cover
            raise forms.ValidationError(_("End date can't be before start date"))

        return cleaned_data
예제 #5
0
class UpdateForm(UpdateTelChannelForm):
    role = forms.MultipleChoiceField(
        choices=((Channel.ROLE_RECEIVE, _("Receive")), (Channel.ROLE_SEND, _("Send"))),
        widget=SelectMultipleWidget(attrs={"widget_only": True}),
        label=_("Channel Role"),
        help_text=_("The roles this channel can fulfill"),
    )

    def clean_role(self):
        return "".join(self.cleaned_data.get("role", []))

    class Meta(UpdateTelChannelForm.Meta):
        fields = "name", "alert_email", "role"
        readonly = []
예제 #6
0
class GroupBasedTriggerForm(BaseTriggerForm):

    groups = forms.ModelMultipleChoiceField(
        queryset=ContactGroup.user_groups.filter(pk__lt=0),
        required=False,
        widget=SelectMultipleWidget(
            attrs={
                "widget_only": True,
                "placeholder": _(
                    "Optional: Trigger only applies to these groups")
            }),
    )

    def __init__(self, user, flows, *args, **kwargs):
        super().__init__(user, flows, *args, **kwargs)
        self.fields["groups"].queryset = ContactGroup.user_groups.filter(
            org=self.user.get_org(), is_active=True)

    def get_existing_triggers(self, cleaned_data):
        groups = cleaned_data.get("groups", [])
        org = self.user.get_org()
        existing = Trigger.objects.filter(org=org,
                                          is_archived=False,
                                          is_active=True)

        if groups:
            existing = existing.filter(groups__in=groups)
        else:
            existing = existing.filter(groups=None)

        if self.instance:
            existing = existing.exclude(pk=self.instance.pk)

        return existing

    class Meta(BaseTriggerForm.Meta):
        fields = ("flow", "groups")
예제 #7
0
파일: views.py 프로젝트: Ilhasoft/rapidpro
class BaseTriggerForm(forms.ModelForm):
    """
    Base form for different trigger types
    """

    flow = TembaChoiceField(
        Flow.objects.none(),
        label=_("Flow"),
        required=True,
        widget=SelectWidget(attrs={
            "placeholder": _("Select a flow"),
            "searchable": True
        }),
    )

    groups = TembaMultipleChoiceField(
        queryset=ContactGroup.user_groups.none(),
        label=_("Groups To Include"),
        help_text=_("Only includes contacts in these groups."),
        required=False,
        widget=SelectMultipleWidget(
            attrs={
                "icons": True,
                "placeholder": _("Optional: Select contact groups"),
                "searchable": True
            }),
    )
    exclude_groups = TembaMultipleChoiceField(
        queryset=ContactGroup.user_groups.none(),
        label=_("Groups To Exclude"),
        help_text=_("Excludes contacts in these groups."),
        required=False,
        widget=SelectMultipleWidget(
            attrs={
                "icons": True,
                "placeholder": _("Optional: Select contact groups"),
                "searchable": True
            }),
    )

    def __init__(self, user, trigger_type, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.user = user
        self.org = user.get_org()
        self.trigger_type = Trigger.get_type(code=trigger_type)

        flow_types = self.trigger_type.allowed_flow_types
        flows = self.org.flows.filter(flow_type__in=flow_types,
                                      is_active=True,
                                      is_archived=False,
                                      is_system=False)

        self.fields["flow"].queryset = flows.order_by("name")

        groups = ContactGroup.get_user_groups(self.org, ready_only=False)

        self.fields["groups"].queryset = groups
        self.fields["exclude_groups"].queryset = groups

    def get_channel_choices(self, schemes):
        return self.org.channels.filter(
            is_active=True, schemes__overlap=list(schemes)).order_by("name")

    def get_conflicts(self, cleaned_data):
        conflicts = Trigger.get_conflicts(
            self.org, self.trigger_type.code,
            **self.get_conflicts_kwargs(cleaned_data))

        # if we're editing a trigger we can't conflict with ourselves
        if self.instance:
            conflicts = conflicts.exclude(id=self.instance.id)

        return conflicts

    def get_conflicts_kwargs(self, cleaned_data):
        return {"groups": cleaned_data.get("groups", [])}

    def clean_keyword(self):
        keyword = self.cleaned_data.get("keyword") or ""
        keyword = keyword.strip()

        if not self.trigger_type.is_valid_keyword(keyword):
            raise forms.ValidationError(
                _("Must be a single word containing only letters and numbers, or a single emoji character."
                  ))

        return keyword.lower()

    def clean(self):
        cleaned_data = super().clean()

        groups = cleaned_data.get("groups", [])
        exclude_groups = cleaned_data.get("exclude_groups", [])

        if set(groups).intersection(exclude_groups):
            raise forms.ValidationError(
                _("Can't include and exclude the same group."))

        # only check for conflicts if user is submitting valid data for all fields
        if not self.errors and self.get_conflicts(cleaned_data):
            raise forms.ValidationError(
                _("There already exists a trigger of this type with these options."
                  ))

        return cleaned_data

    class Meta:
        model = Trigger
        fields = ("flow", "groups", "exclude_groups")
예제 #8
0
class ScheduleTriggerForm(BaseScheduleForm, forms.ModelForm):
    repeat_period = forms.ChoiceField(choices=Schedule.REPEAT_CHOICES,
                                      label="Repeat",
                                      required=False,
                                      widget=SelectWidget())

    repeat_days_of_week = forms.MultipleChoiceField(
        choices=Schedule.REPEAT_DAYS_CHOICES,
        label="Repeat Days",
        required=False,
        widget=SelectMultipleWidget(
            attrs=({
                "placeholder": _("Select days to repeat on")
            })),
    )

    start_datetime = forms.DateTimeField(
        required=False,
        label=_("Start Time"),
        widget=InputWidget(
            attrs={
                "datetimepicker": True,
                "placeholder": "Select a time to start the flow"
            }),
    )

    flow = forms.ModelChoiceField(
        Flow.objects.filter(pk__lt=0),
        label=_("Flow"),
        required=True,
        widget=SelectWidget(attrs={
            "placeholder": _("Select a flow"),
            "searchable": True
        }),
        empty_label=None,
    )

    omnibox = JSONField(
        label=_("Contacts"),
        required=True,
        help_text=_("The groups and contacts the flow will be broadcast to"),
        widget=OmniboxChoice(
            attrs={
                "placeholder": _("Recipients, enter contacts or groups"),
                "groups": True,
                "contacts": True
            }),
    )

    def __init__(self, user, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.user = user
        org = user.get_org()
        flows = Flow.get_triggerable_flows(org)

        self.fields["start_datetime"].help_text = _("%s Time Zone" %
                                                    org.timezone)
        self.fields["flow"].queryset = flows

    def clean_repeat_days_of_week(self):
        return "".join(self.cleaned_data["repeat_days_of_week"])

    def clean_omnibox(self):
        return omnibox_deserialize(self.user.get_org(),
                                   self.cleaned_data["omnibox"])

    class Meta:
        model = Trigger
        fields = ("flow", "omnibox", "repeat_period", "repeat_days_of_week",
                  "start_datetime")