class BroadcastForm(forms.ModelForm): message = forms.CharField( required=True, widget=CompletionTextarea(attrs={"placeholder": _("Hi @contact.name!")}), max_length=Broadcast.MAX_TEXT_LEN, ) omnibox = JSONField( label=_("Recipients"), required=False, help_text=_("The contacts to send the message to"), widget=OmniboxChoice( attrs={ "placeholder": _("Recipients, enter contacts or groups"), "groups": True, "contacts": True, "urns": True, } ), ) def is_valid(self): valid = super().is_valid() if valid: if "omnibox" not in self.data or len(self.data["omnibox"].strip()) == 0: # pragma: needs cover self.errors["__all__"] = self.error_class([_("At least one recipient is required")]) return False return valid class Meta: model = Broadcast fields = "__all__"
class BroadcastForm(forms.ModelForm): message = forms.CharField( required=True, widget=CompletionTextarea(attrs={"placeholder": _("Hi @contact.name!")}), max_length=Broadcast.MAX_TEXT_LEN, ) omnibox = OmniboxField() def __init__(self, user, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["omnibox"].set_user(user) def is_valid(self): valid = super().is_valid() if valid: if "omnibox" not in self.data or len(self.data["omnibox"].strip()) == 0: # pragma: needs cover self.errors["__all__"] = self.error_class([_("At least one recipient is required")]) return False return valid class Meta: model = Broadcast fields = "__all__"
class RegisterTriggerForm(BaseTriggerForm): """ Wizard form that creates keyword trigger which starts contacts in a newly created flow which adds them to a group """ class AddNewGroupChoiceField(forms.ModelChoiceField): def clean(self, value): if value.startswith("[_NEW_]"): # pragma: needs cover value = value[7:] # we must get groups for this org only group = ContactGroup.get_user_group_by_name( self.user.get_org(), value) if not group: group = ContactGroup.create_static(self.user.get_org(), self.user, name=value) return group return super().clean(value) keyword = forms.CharField( max_length=16, required=True, help_text=_("The first word of the message text"), widget=InputWidget()) action_join_group = AddNewGroupChoiceField( ContactGroup.user_groups.filter(pk__lt=0), required=True, label=_("Group to Join"), help_text=_( "The group the contact will join when they send the above keyword" ), widget=SelectWidget(), ) response = forms.CharField( widget=CompletionTextarea( attrs={"placeholder": _("Hi @contact.name!")}), required=False, label=_("Response"), help_text= _("The message to send in response after they join the group (optional)" ), ) def __init__(self, user, *args, **kwargs): flows = Flow.get_triggerable_flows(user.get_org()) super().__init__(user, flows, *args, **kwargs) self.fields["flow"].required = False group_field = self.fields["action_join_group"] group_field.queryset = ContactGroup.user_groups.filter( org=self.user.get_org(), is_active=True).order_by("name") group_field.user = user class Meta(BaseTriggerForm.Meta): fields = ("keyword", "action_join_group", "response", "flow")
class RegisterTriggerForm(BaseTriggerForm): """ Wizard form that creates keyword trigger which starts contacts in a newly created flow which adds them to a group """ class AddNewGroupChoiceField(TembaChoiceField): def clean(self, value): if value.startswith("[_NEW_]"): # pragma: needs cover value = value[7:] # we must get groups for this org only group = ContactGroup.get_user_group_by_name(self.user.get_org(), value) if not group: group = ContactGroup.create_static(self.user.get_org(), self.user, name=value) return group return super().clean(value) keyword = forms.CharField( max_length=16, required=True, label=_("Join Keyword"), help_text=_("The first word of the message"), widget=InputWidget(), ) action_join_group = AddNewGroupChoiceField( ContactGroup.user_groups.none(), required=True, label=_("Group to Join"), help_text=_("The group the contact will join when they send the above keyword"), widget=SelectWidget(), ) response = forms.CharField( widget=CompletionTextarea(attrs={"placeholder": _("Hi @contact.name!")}), required=False, label=ngettext_lazy("Response", "Responses", 1), help_text=_("The message to send in response after they join the group (optional)"), ) def __init__(self, user, *args, **kwargs): super().__init__(user, Trigger.TYPE_KEYWORD, *args, **kwargs) # on this form flow becomes the flow to be triggered from the generated flow and is optional self.fields["flow"].required = False self.fields["action_join_group"].queryset = ContactGroup.user_groups.filter( org=self.org, is_active=True ).order_by("name") self.fields["action_join_group"].user = user def get_conflicts_kwargs(self, cleaned_data): kwargs = super().get_conflicts_kwargs(cleaned_data) kwargs["keyword"] = cleaned_data.get("keyword") or "" return kwargs class Meta(BaseTriggerForm.Meta): fields = ("keyword", "action_join_group", "response") + BaseTriggerForm.Meta.fields
class SendMessageForm(Form): omnibox = JSONField( label=_("Recipients"), required=False, help_text=_("The contacts to send the message to"), widget=OmniboxChoice( attrs={ "placeholder": _("Recipients, enter contacts or groups"), "groups": True, "contacts": True, "urns": True, }), ) text = forms.CharField(widget=CompletionTextarea( attrs={ "placeholder": _("Hi @contact.name!"), "widget_only": True })) schedule = forms.BooleanField( widget=CheckboxWidget(attrs={"widget_only": True}), required=False, label=_("Schedule for later"), help_text=None, ) step_node = forms.CharField(widget=forms.HiddenInput, max_length=36, required=False) def __init__(self, user, *args, **kwargs): super().__init__(*args, **kwargs) self.user = user def is_valid(self): valid = super().is_valid() if valid: if ("step_node" not in self.data or not self.data["step_node"] ) and ("omnibox" not in self.data or len(self.data["omnibox"].strip()) == 0): self.errors["__all__"] = self.error_class( [str(_("At least one recipient is required"))]) return False return valid def clean(self): cleaned = super().clean() org = self.user.get_org() if org.is_suspended: raise ValidationError( _("Sorry, your account is currently suspended. To enable sending messages, please contact support." )) if org.is_flagged: raise ValidationError( _("Sorry, your account is currently flagged. To enable sending messages, please contact support." )) return cleaned
class SendMessageForm(Form): omnibox = OmniboxField( label=_("Recipients"), required=False, help_text=_("The contacts to send the message to"), widget=OmniboxChoice( attrs={ "placeholder": _("Recipients, enter contacts or groups"), "widget_only": True, "groups": True, "contacts": True, "urns": True, }), ) text = forms.CharField(widget=CompletionTextarea( attrs={ "placeholder": _("Hi @contact.name!"), "widget_only": True, "counter": "temba-charcount" })) schedule = forms.BooleanField( widget=CheckboxWidget(attrs={"widget_only": True}), required=False, label=_("Schedule for later"), help_text=None, ) step_node = forms.CharField(widget=forms.HiddenInput, max_length=36, required=False) def __init__(self, org, *args, **kwargs): super().__init__(*args, **kwargs) self.org = org self.fields["omnibox"].default_country = org.default_country_code def clean(self): cleaned = super().clean() if self.is_valid(): omnibox = cleaned.get("omnibox") step_node = cleaned.get("step_node") if not step_node and not omnibox: self.add_error("omnibox", _("At least one recipient is required.")) return cleaned
def __init__(self, user, *args, **kwargs): self.user = user super().__init__(*args, **kwargs) org = self.user.get_org() relative_to = self.fields["relative_to"] relative_to.queryset = ContactField.all_fields.filter( org=org, is_active=True, value_type=ContactField.TYPE_DATETIME).order_by("label") flow = self.fields["flow_to_start"] flow.queryset = Flow.objects.filter( org=self.user.get_org(), flow_type__in=[Flow.TYPE_MESSAGE, Flow.TYPE_VOICE], is_active=True, is_archived=False, is_system=False, ).order_by("name") message = self.instance.message or {} self.languages = [] # add in all of our languages for message forms languages = org.languages.all() for language in languages: insert = None # if it's our primary language, allow use to steal the 'base' message if org.primary_language and org.primary_language.iso_code == language.iso_code: initial = message.get(language.iso_code, "") if not initial: initial = message.get("base", "") # also, let's show it first insert = 0 else: # otherwise, its just a normal language initial = message.get(language.iso_code, "") field = forms.CharField( widget=CompletionTextarea( attrs={ "placeholder": _("Hi @contact.name! This is just a friendly reminder to apply your fertilizer." ), "widget_only": True, }), required=False, label=language.name, initial=initial, ) self.fields[language.iso_code] = field field.language = dict(name=language.name, iso_code=language.iso_code) # see if we need to insert or append if insert is not None: self.languages.insert(insert, field) else: self.languages.append(field) # determine our base language if necessary base_language = None if not org.primary_language: base_language = "base" # if we are editing, always include the flow base language if self.instance.id: base_language = self.instance.flow.base_language # add our default language, we'll insert it at the front of the list if base_language and base_language not in self.fields: field = forms.CharField( widget=CompletionTextarea( attrs={ "placeholder": _("Hi @contact.name! This is just a friendly reminder to apply your fertilizer." ), "widget_only": True, }), required=False, label=_("Default"), initial=message.get(base_language), ) self.fields[base_language] = field field.language = dict(iso_code=base_language, name="Default") self.languages.insert(0, field)