Пример #1
0
class UCRExpressionForm(forms.ModelForm):
    class Meta:
        model = UCRExpression
        fields = [
            "name",
            "expression_type",
            "description",
            "definition",
        ]

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.domain = request.domain
        self.fields['description'] = forms.CharField(required=False)
        self.fields['definition'] = JsonField(initial={
            "type": "property_name",
            "property_name": "name"
        })
        self.helper = HQFormHelper()
        self.helper.layout = crispy.Layout(
            crispy.Fieldset(
                _('Expression'),
                crispy.Field('name'),
                crispy.Field('expression_type'),
                crispy.Field('description'),
                crispy.Field('definition'),
            ))
        self.helper.add_input(crispy.Submit('submit', _('Save')))
        self.helper.render_required_fields = True

    def save(self, commit=True):
        self.instance.domain = self.domain
        return super().save(commit)
Пример #2
0
    def __init__(self, domain, *args, **kwargs):
        if 'initial' in kwargs:
            raise ValueError(_("Initial values are set by the form."))

        self.is_system_admin = kwargs.pop('is_system_admin', False)

        self.initial_rule = kwargs.pop('rule', None)
        if self.initial_rule:
            kwargs['initial'] = self.compute_initial(domain, self.initial_rule)

        super(CaseRuleCriteriaForm, self).__init__(*args, **kwargs)

        self.domain = domain
        self.set_case_type_choices(self.initial.get('case_type'))
        self.fields[
            'criteria_operator'].choices = AutomaticUpdateRule.CriteriaOperator.choices

        self.helper = HQFormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                _("Case Filters") if self.show_fieldset_title else "",
                HTML(
                    '<p class="help-block alert alert-info"><i class="fa fa-info-circle"></i> %s</p>'
                    % self.fieldset_help_text),
                hidden_bound_field('filter_on_server_modified',
                                   'filterOnServerModified'),
                hidden_bound_field('server_modified_boundary',
                                   'serverModifiedBoundary'),
                hidden_bound_field('custom_match_definitions',
                                   'customMatchDefinitions'),
                hidden_bound_field('property_match_definitions',
                                   'propertyMatchDefinitions'),
                hidden_bound_field('filter_on_closed_parent',
                                   'filterOnClosedParent'),
                Div(data_bind="template: {name: 'case-filters'}"),
                css_id="rule-criteria-panel",
            ), )

        self.form_beginning_helper = HQFormHelper()
        self.form_beginning_helper.form_tag = False
        self.form_beginning_helper.layout = Layout(
            Fieldset(
                _("Rule Criteria"),
                Field('case_type',
                      data_bind="value: caseType",
                      css_class="hqwebapp-select2"),
                Field('criteria_operator'),
            ))

        self.custom_filters = settings.AVAILABLE_CUSTOM_RULE_CRITERIA.keys()
Пример #3
0
 def __init__(self, request, *args, **kwargs):
     super(UpdateIncrementalExportForm, self).__init__(*args, **kwargs)
     self.domain = request.domain
     self.fields['id'] = forms.CharField(widget=forms.HiddenInput())
     self.fields['export_instance_id'] = forms.ChoiceField(
         label=_('Case Data Export'),
         choices=_get_case_data_export_choices(request),
     )
     self.fields[
         'connection_settings'].queryset = ConnectionSettings.objects.filter(
             domain=self.domain)
     self.helper = HQFormHelper()
     self.helper.layout = crispy.Layout(
         crispy.Field('id'), crispy.Field('name'),
         crispy.Field('export_instance_id'),
         crispy.Field('connection_settings'), crispy.Field('active'),
         hqcrispy.FormActions(
             twbscrispy.StrictButton(
                 gettext_lazy("Update"),
                 css_class='btn btn-primary',
                 type='submit',
             ),
             crispy.HTML(
                 '<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>'
             ),
             css_class="modal-footer",
         ))
Пример #4
0
    def __init__(self, domain, *args, **kwargs):
        if 'initial' in kwargs:
            raise ValueError(_("Initial values are set by the form."))

        self.is_system_admin = kwargs.pop('is_system_admin', False)

        rule = kwargs.pop('rule', None)
        if rule:
            kwargs['initial'] = self.compute_initial(rule)

        super(CaseRuleActionsForm, self).__init__(*args, **kwargs)

        self.domain = domain

        self.helper = HQFormHelper()
        self.helper.form_tag = False
        self.helper.form_show_errors = False
        self.helper.layout = Layout(
            Fieldset(
                _("Actions"),
                hidden_bound_field('close_case', 'closeCase'),
                hidden_bound_field('properties_to_update',
                                   'propertiesToUpdate'),
                hidden_bound_field('custom_action_definitions',
                                   'customActionDefinitions'),
                Div(data_bind="template: {name: 'case-actions'}"),
                css_id="rule-actions",
            ), )
Пример #5
0
 def __init__(self, request, domain, *args, **kwargs):
     self.domain = domain
     super(HostedCCZForm, self).__init__(*args, **kwargs)
     self.fields['link_id'].choices = self.link_choices()
     self.fields['app_id'].choices = self.app_id_choices()
     self.helper = HQFormHelper()
     if request.GET.get('app_id'):
         self.fields['app_id'].initial = request.GET.get('app_id')
     if request.GET.get('link_id'):
         self.fields['link_id'].initial = request.GET.get('link_id')
     self.helper.layout = crispy.Layout(
         crispy.Field('link_id', css_class="hqwebapp-select2", id="link-id-select"),
         crispy.Field('app_id', css_class="hqwebapp-select2", id='app-id-search-select'),
         crispy.Field('version', id='version-input'),
         crispy.Field('profile_id', id='app-profile-id-input'),
         crispy.Field('file_name'),
         crispy.Field('note'),
         hqcrispy.FormActions(
             crispy.ButtonHolder(
                 crispy.Button('search', ugettext_lazy("Search"), data_bind="click: search"),
                 crispy.Button('clear', ugettext_lazy("Clear"), data_bind="click: clear"),
                 Submit('submit', ugettext_lazy("Create"))
             )
         )
     )
Пример #6
0
    def __init__(self, is_superuser=False, *args, **kwargs):
        super(InitiateAddSMSBackendForm, self).__init__(*args, **kwargs)

        from corehq.messaging.smsbackends.telerivet.models import SQLTelerivetBackend
        backend_classes = get_sms_backend_classes()
        backend_choices = []
        for api_id, klass in backend_classes.items():
            if is_superuser or api_id == SQLTelerivetBackend.get_api_id():
                friendly_name = klass.get_generic_name()
                backend_choices.append((api_id, friendly_name))
        backend_choices = sorted(backend_choices,
                                 key=lambda backend: backend[1])
        self.fields['hq_api_id'].choices = backend_choices

        self.helper = HQFormHelper()
        self.helper.layout = crispy.Layout(
            hqcrispy.B3MultiField(
                _("Create Another Gateway"),
                InlineField('action'),
                Div(InlineField('hq_api_id', css_class="ko-select2"),
                    css_class='col-sm-6 col-md-6 col-lg-4'),
                Div(StrictButton(mark_safe(
                    '<i class="fa fa-plus"></i> Add Another Gateway'),
                                 css_class='btn-primary',
                                 type='submit',
                                 style="margin-left:5px;"),
                    css_class='col-sm-3 col-md-2 col-lg-2'),
            ), )
Пример #7
0
    def __init__(self, data=None, cchq_domain=None, cchq_is_previewer=False, new_reminders_migrator=False,
            *args, **kwargs):
        self._cchq_domain = cchq_domain
        self._cchq_is_previewer = cchq_is_previewer
        self.new_reminders_migrator = new_reminders_migrator
        super(SettingsForm, self).__init__(data, *args, **kwargs)

        self.helper = HQFormHelper()

        self.helper.layout = crispy.Layout(
            *self.sections
        )

        self.restricted_sms_times_widget_context = {
            "template_name": "ko-template-restricted-sms-times",
            "explanation_text": _("SMS will only be sent when any of the following is true:"),
            "ko_array_name": "restricted_sms_times",
            "remove_window_method": "$parent.removeRestrictedSMSTime",
            "add_window_method": "addRestrictedSMSTime",
        }
        self.sms_conversation_times_widget_context = {
            "template_name": "ko-template-sms-conversation-times",
            "explanation_text": _("Automated SMS will be suppressed during "
                                  "chat conversations when any of the following "
                                  "is true:"),
            "ko_array_name": "sms_conversation_times",
            "remove_window_method": "$parent.removeSMSConversationTime",
            "add_window_method": "addSMSConversationTime",
        }
Пример #8
0
    def __init__(self, *args, **kwargs):
        button_text = kwargs.pop('button_text', _("Create SMS Gateway"))
        self.domain = kwargs.pop('domain')
        self.backend_id = kwargs.pop('backend_id')
        super(BackendForm, self).__init__(*args, **kwargs)
        self.helper = HQFormHelper()
        self.helper.form_method = 'POST'
        self.helper.layout = crispy.Layout(
            crispy.Fieldset(_('General Settings'), *self.general_fields),
            self.gateway_specific_fields,
            crispy.Fieldset(
                _("Phone Numbers"),
                crispy.Div(data_bind="template: {"
                           " name: 'ko-load-balancing-template', "
                           " data: $data"
                           "}", ),
                data_bind="visible: use_load_balancing",
            ),
            hqcrispy.FormActions(
                StrictButton(button_text,
                             type="submit",
                             css_class='btn-primary'), ),
        )

        if self.backend_id:
            #   When editing, don't allow changing the name because name might be
            # referenced as a contact-level backend preference.
            #   By setting disabled to True, Django makes sure the value won't change
            # even if something else gets posted.
            self.fields['name'].disabled = True
Пример #9
0
 def setup_crispy(self):
     self.helper = HQFormHelper()
     self.helper.form_method = 'POST'
     self.helper.layout = crispy.Layout(
         crispy.Fieldset(
             _("Default Gateways"),
             hqcrispy.B3MultiField(
                 _("Default Gateway by Prefix"),
                 hqcrispy.ErrorsOnlyField('backend_map'),
                 crispy.Div(
                     data_bind="template: {"
                               " name: 'ko-template-backend-map', "
                               " data: $data"
                               "}"
                 ),
             ),
             'catchall_backend_id',
         ),
         hqcrispy.FormActions(
             StrictButton(
                 _("Save"),
                 type="submit",
                 css_class='btn-primary'
             ),
         ),
     )
Пример #10
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.helper = HQFormHelper()
        self.helper.form_method = 'get'
        self.helper.layout = crispy.Layout(
            'csv_domain_list', FormActions(crispy.Submit('', 'Check Domains')))
Пример #11
0
    def __init__(self, domain_object, *args, **kwargs):
        self.domain_object = domain_object
        super(BaseFilterExportDownloadForm, self).__init__(*args, **kwargs)

        self.helper = HQFormHelper()
        self.helper.form_tag = False

        self.helper.layout = Layout(*self.extra_fields)
Пример #12
0
 def __init__(self, request, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.domain = request.domain
     self.fields['description'] = forms.CharField(required=False)
     self.fields['definition'] = JsonField(initial={
         "type": "property_name",
         "property_name": "name"
     })
     self.helper = HQFormHelper()
     self.helper.layout = crispy.Layout(
         crispy.Fieldset(
             _('Expression'),
             crispy.Field('name'),
             crispy.Field('expression_type'),
             crispy.Field('description'),
             crispy.Field('definition'),
         ))
     self.helper.add_input(crispy.Submit('submit', _('Save')))
     self.helper.render_required_fields = True
Пример #13
0
 def __init__(self, request, domain, *args, **kwargs):
     self.domain = domain
     super(CustomDataPullForm, self).__init__(*args, **kwargs)
     self.helper = HQFormHelper()
     self.helper.layout = crispy.Layout(
         crispy.Field('data_pull'),
         crispy.Field('month', id="month_select", css_class="date-picker"),
         crispy.Field('location_id', id='location_search_select'),
         hqcrispy.FormActions(
             crispy.ButtonHolder(Submit('submit',
                                        ugettext_lazy("Submit")))))
Пример #14
0
 def __init__(self, *args, **kwargs):
     super(CustomSMSReportRequestForm, self).__init__(*args, **kwargs)
     self.helper = HQFormHelper()
     self.helper.form_method = 'post'
     self.helper.layout = crispy.Layout(
         hqcrispy.Field('date_range'), hqcrispy.Field('start_date'),
         hqcrispy.Field('end_date'),
         twbscrispy.StrictButton(
             _('Generate Report'),
             type='submit',
             css_class='btn-primary',
         ))
Пример #15
0
    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.domain = request.domain
        self.fields['export_instance_id'] = forms.ChoiceField(
            label=_('Case Data Export'),
            choices=_get_case_data_export_choices(request),
        )
        self.fields[
            'connection_settings'].queryset = ConnectionSettings.objects.filter(
                domain=self.domain)

        self.helper = HQFormHelper()
        self.helper.layout = crispy.Layout(
            crispy.Fieldset(
                _('Incremental Export'),
                crispy.Field('name'),
                crispy.Field('export_instance_id'),
                crispy.Field('connection_settings'),
                crispy.Field('active'),
            ))
        self.helper.add_input(crispy.Submit('submit', _('Save')))
        self.helper.render_required_fields = True
Пример #16
0
    def __init__(self, *args, **kwargs):
        if 'domain' not in kwargs:
            raise Exception('Expected kwargs: domain')
        self.domain = kwargs.pop('domain')

        super(SendRegistrationInvitationsForm, self).__init__(*args, **kwargs)
        self.set_app_id_choices()

        self.helper = HQFormHelper()
        self.helper.layout = crispy.Layout(
            crispy.Div(
                'app_id',
                crispy.Field(
                    'phone_numbers',
                    placeholder=_("Enter phone number(s) in international "
                        "format. Example: +27..., +91...,"),
                ),
                'phone_type',
                InlineField('action'),
                css_class='modal-body',
            ),
            hqcrispy.FieldsetAccordionGroup(
                _("Advanced"),
                crispy.Field(
                    'registration_message_type',
                    data_bind='value: registration_message_type',
                ),
                crispy.Div(
                    crispy.Field(
                        'custom_registration_message',
                        placeholder=_("Enter registration SMS"),
                    ),
                    data_bind='visible: showCustomRegistrationMessage',
                ),
                'make_email_required',
                active=False
            ),
            crispy.Div(
                twbscrispy.StrictButton(
                    _("Cancel"),
                    data_dismiss='modal',
                    css_class="btn btn-default",
                ),
                twbscrispy.StrictButton(
                    _("Send Invitation"),
                    type="submit",
                    css_class="btn btn-primary",
                ),
                css_class='modal-footer',
            ),
        )
Пример #17
0
    def __init__(self, data, *args, **kwargs):
        self.domain = kwargs.pop('domain')
        kwargs['initial'] = self.initial_data
        super(TableauServerForm, self).__init__(data, *args, **kwargs)

        self.helper = HQFormHelper()
        self.helper.form_method = 'POST'
        self.helper.layout = crispy.Layout(
            crispy.Div(crispy.Field('server_type'), ),
            crispy.Div(crispy.Field('server_name'), ),
            crispy.Div(crispy.Field('validate_hostname'), ),
            crispy.Div(crispy.Field('target_site'), ),
            crispy.Div(crispy.Field('domain_username'), ),
            FormActions(crispy.Submit('submit_btn', 'Submit')))
Пример #18
0
 def helper(self):
     helper = HQFormHelper()
     from corehq.apps.reports.views import TableauVisualizationListView
     helper.layout = crispy.Layout(
         crispy.Field('server'),
         crispy.Field('view_url'),
         FormActions(
             StrictButton(
                 _("Save"),
                 type="submit",
                 css_class="btn btn-primary",
             ),
             LinkButton(
                 _("Cancel"),
                 reverse(
                     TableauVisualizationListView.urlname,
                     kwargs={'domain': self.domain},
                 ),
                 css_class="btn btn-default",
             ),
         ),
     )
     return helper
Пример #19
0
 def __init__(self, *args, **kwargs):
     domain = kwargs.pop('domain')
     super(ComposeMessageForm, self).__init__(*args, **kwargs)
     self.helper = HQFormHelper()
     self.helper.form_action = reverse('send_to_recipients', args=[domain])
     self.helper.layout = crispy.Layout(
         crispy.Field('recipients', rows=2, css_class='sms-typeahead'),
         crispy.Field('message', rows=2),
         hqcrispy.FormActions(
             twbscrispy.StrictButton(
                 _("Send Message"),
                 type="submit",
                 css_class="btn-primary",
             ), ),
     )
Пример #20
0
 def __init__(self, request, domain, *args, **kwargs):
     self.domain = domain
     super(DataManagementForm, self).__init__(*args, **kwargs)
     self.helper = HQFormHelper()
     self.helper.layout = crispy.Layout(
         crispy.Field('slug'),
         crispy.Field('db_alias'),
         crispy.Field('start_date', css_class="date-picker"),
         crispy.Field('end_date', css_class="date-picker"),
         hqcrispy.FormActions(
             crispy.ButtonHolder(
                 Submit('submit', ugettext_lazy("Submit"))
             )
         )
     )
Пример #21
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.helper = HQFormHelper()
        self.helper.layout = Layout(
            crispy.Fieldset(
                ugettext_lazy("Add New API Key"),
                crispy.Field('name'),
                crispy.Field('ip_allowlist'),
            ),
            hqcrispy.FormActions(
                StrictButton(mark_safe('<i class="fa fa-plus"></i> {}'.format(
                    ugettext_lazy("Generate New API Key"))),
                             css_class='btn btn-primary',
                             type='submit')))
Пример #22
0
 def __init__(self, *args, **kwargs):
     super(SubscribeSMSForm, self).__init__(*args, **kwargs)
     self.helper = HQFormHelper()
     self.helper.layout = crispy.Layout(
         crispy.Fieldset(
             _('Subscribe settings'),
             twbscrispy.PrependedText('stock_out_facilities', ''),
             twbscrispy.PrependedText('stock_out_commodities', ''),
             twbscrispy.PrependedText('stock_out_rates', ''),
             twbscrispy.PrependedText('non_report', '')),
         hqcrispy.FormActions(
             twbscrispy.StrictButton(
                 _("Update settings"),
                 type="submit",
                 css_class="btn-primary",
             ), ))
Пример #23
0
    def init_form(self, post_dict=None):
        fields = OrderedDict()
        for field in self.fields:
            fields[field.slug] = self._make_field(field)

        if self.angular_model:
            field_names = [

                Field(
                    field_name,
                    ng_model="{}.{}".format(self.angular_model, field_name),
                    ng_required="true" if field.required else "false"
                )
                for field_name, field in fields.items()
            ]
        else:
            field_names = list(fields)

        CustomDataForm = type('CustomDataForm' if six.PY3 else b'CustomDataForm', (forms.Form,), fields)
        if self.angular_model:
            CustomDataForm.helper = HQModalFormHelper()
        else:
            CustomDataForm.helper = HQFormHelper()
        CustomDataForm.helper.form_tag = False

        additional_fields = []
        if field_names:
            additional_fields.append(Fieldset(_("Additional Information"), *field_names))
        if post_dict is None:
            additional_fields.append(self.uncategorized_form)
        CustomDataForm.helper.layout = Layout(
            *additional_fields
        )

        CustomDataForm._has_uncategorized = bool(self.uncategorized_form) and post_dict is None

        if post_dict:
            fields = post_dict
        elif self.existing_custom_data is not None:
            fields = add_prefix(self.existing_custom_data, self.prefix)
        else:
            fields = None

        self.form = CustomDataForm(fields, prefix=self.prefix)
        return self.form
Пример #24
0
 def __init__(self, domain, *args, **kwargs):
     super(MigrateTransifexProjectForm, self).__init__(*args, **kwargs)
     self.domain = domain
     self._set_choices()
     self.helper = HQFormHelper()
     self.helper.layout = crispy.Layout(
         crispy.Fieldset(
             "Migrate Project",
             hqcrispy.Field('from_app_id', css_class="hqwebapp-select2"),
             hqcrispy.Field('to_app_id', css_class="hqwebapp-select2"),
             hqcrispy.Field('transifex_project_slug'),
             hqcrispy.Field('mapping_file')),
         hqcrispy.FormActions(
             twbscrispy.StrictButton(
                 ugettext_lazy("Submit"),
                 type="submit",
                 css_class="btn btn-primary disable-on-submit",
                 onclick="return confirm('%s')" % ugettext_lazy(
                     "We recommend taking a backup if you have not already."
                     "Please confirm that you want to proceed?"))))
Пример #25
0
    def __init__(self, domain, *args, **kwargs):
        if 'initial' in kwargs:
            raise ValueError(_("Initial values are set by the form"))

        self.is_system_admin = kwargs.pop('is_system_admin', False)

        rule = kwargs.pop('rule', None)
        if rule:
            kwargs['initial'] = self.compute_initial(rule)

        super(CaseUpdateRuleForm, self).__init__(*args, **kwargs)

        self.domain = domain
        self.helper = HQFormHelper()
        self.helper.form_tag = False

        self.helper.layout = Layout(
            Fieldset(
                _("Basic Information"),
                Field('name', data_bind='name'),
            ), )
Пример #26
0
    def __init__(self, *args, **kwargs):
        self.couch_user = kwargs.pop('couch_user')
        super().__init__(*args, **kwargs)

        user_domains = self.couch_user.get_domains()
        all_domains = (self.ALL_DOMAINS, _('All Projects'))
        self.fields['domain'].choices = [all_domains] + [(d, d)
                                                         for d in user_domains]
        self.helper = HQFormHelper()
        self.helper.layout = Layout(
            crispy.Fieldset(
                ugettext_lazy("Add New API Key"),
                crispy.Field('name'),
                crispy.Field('domain'),
                crispy.Field('ip_allowlist'),
            ),
            hqcrispy.FormActions(
                StrictButton(format_html('<i class="fa fa-plus"></i> {}',
                                         _("Generate New API Key")),
                             css_class='btn btn-primary',
                             type='submit')))
Пример #27
0
    def __init__(self, *args, **kwargs):
        super(ForwardingRuleForm, self).__init__(*args, **kwargs)

        self.helper = HQFormHelper()
        self.helper.layout = crispy.Layout(
            crispy.Fieldset(
                _('Forwarding Rule Options'),
                'forward_type',
                crispy.Div(
                    'keyword',
                    css_id="keyword_row",
                    css_class='hide',
                ),
                'backend_id',
                hqcrispy.FormActions(
                    twbscrispy.StrictButton(
                        _("Submit"),
                        type="submit",
                        css_class="btn btn-primary",
                    ), ),
            ))
Пример #28
0
 def __init__(self, request, domain, email, *args, **kwargs):
     self.domain = domain
     self.email = email
     super(HostedCCZForm, self).__init__(*args, **kwargs)
     self.fields['link_id'].choices = self.link_choices()
     self.fields['app_id'].choices = self.app_id_choices()
     self.helper = HQFormHelper()
     if request.GET.get('app_id'):
         self.fields['app_id'].initial = request.GET.get('app_id')
     if request.GET.get('link_id'):
         self.fields['link_id'].initial = request.GET.get('link_id')
     if request.GET.get('status'):
         self.fields['status'].initial = request.GET.get('status')
     self.helper.layout = crispy.Layout(
         crispy.Field('link_id',
                      css_class="hqwebapp-select2",
                      data_bind="value: linkId"),
         crispy.Field('app_id',
                      css_class="hqwebapp-select2",
                      data_bind="value: appId"),
         crispy.Field('version', data_bind="value: version"),
         crispy.Field('profile_id',
                      id="build-profile-id-input",
                      data_bind="value: profileId"),
         crispy.Field('file_name'), crispy.Field('note'),
         crispy.Field('status', data_bind="value: status"),
         hqcrispy.FormActions(
             crispy.ButtonHolder(
                 crispy.Button('search',
                               ugettext_lazy("Search"),
                               css_class="btn-default",
                               data_bind="click: search"),
                 crispy.Button('clear',
                               ugettext_lazy("Clear"),
                               css_class="btn-default",
                               data_bind="click: clear"),
                 Submit('submit', ugettext_lazy("Create")))))
Пример #29
0
    def init_form(self, post_dict=None):
        fields = OrderedDict()
        if domain_has_privilege(self.domain, privileges.APP_USER_PROFILES):
            profiles = self.model.get_profiles()
            if profiles:
                attrs = {
                    'data-placeholder': _('Select a profile'),
                    'data-allow-clear': 'true',
                }
                if not self.ko_model:
                    attrs.update({'class': 'hqwebapp-select2'})
                fields[PROFILE_SLUG] = forms.IntegerField(
                    label=_('Profile'),
                    required=False,
                    widget=Select(choices=[(p.id, p.name) for p in profiles],
                                  attrs=attrs))
        for field in self.fields:
            fields[field.slug] = self._make_field(field)

        if self.ko_model:
            field_names = []
            for field_name, field in fields.items():
                data_binds = [
                    f"value: {self.ko_model}.{field_name}.value",
                    f"disable: {self.ko_model}.{field_name}.disable",
                ]
                if hasattr(field, 'choices') or field_name == PROFILE_SLUG:
                    data_binds.append("select2: " + json.dumps([{
                        "id": id,
                        "text": text
                    } for id, text in field.widget.choices]))
                field_names.append(
                    Field(field_name, data_bind=", ".join(data_binds)))
        else:
            field_names = list(fields)

        CustomDataForm = type('CustomDataForm', (forms.Form, ), fields)
        if self.ko_model:
            CustomDataForm.helper = HQModalFormHelper()
        else:
            CustomDataForm.helper = HQFormHelper()
        CustomDataForm.helper.form_tag = False

        additional_fields = []
        if field_names:
            additional_fields.append(
                Fieldset(_("Additional Information"),
                         *field_names,
                         css_class="custom-data-fieldset"))
        if post_dict is None:
            additional_fields.append(self.uncategorized_form)
        CustomDataForm.helper.layout = Layout(*additional_fields)

        CustomDataForm._has_uncategorized = bool(
            self.uncategorized_form) and post_dict is None

        if post_dict:
            fields = post_dict.copy()  # make mutable
        elif self.existing_custom_data is not None:
            fields = add_prefix(self.existing_custom_data, self.prefix)
        else:
            fields = None

        # Add profile fields so that form validation passes
        if fields:
            try:
                profile_fields = CustomDataFieldsProfile.objects.get(
                    id=int(fields.get(with_prefix(PROFILE_SLUG, self.prefix))),
                    definition__field_type=self.field_view.field_type,
                    definition__domain=self.domain,
                ).fields
            except (ValueError, TypeError,
                    CustomDataFieldsProfile.DoesNotExist):
                profile_fields = {}
            fields.update(add_prefix(profile_fields, self.prefix))

        self.form = CustomDataForm(fields, prefix=self.prefix)
        return self.form