django-forms-workflows 0.76.0__tar.gz → 0.76.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/CHANGELOG.md +9 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/PKG-INFO +1 -1
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/form_builder_views.py +202 -183
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/tasks.py +21 -7
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/pyproject.toml +1 -1
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/LICENSE +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/README.md +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/__init__.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/admin.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/api_urls.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/api_views.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/apps.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/callback_registry.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/conditions.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/context_processors.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/data_sources/__init__.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/data_sources/base.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/data_sources/database_source.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/data_sources/ldap_source.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/data_sources/user_source.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/diff_views.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/email_backends/__init__.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/email_backends/gmail_api.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/form_builder_urls.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/forms.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/handlers/__init__.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/handlers/api_handler.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/handlers/base.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/handlers/database_handler.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/handlers/email_handler.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/handlers/executor.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/handlers/file_handler.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/handlers/ldap_handler.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/history.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/ldap_backend.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/create_default_templates.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/pull_forms.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/push_forms.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/seed_farm_demo.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/seed_pcn_form.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/seed_prefill_sources.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/sync_ldap_profiles.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/sync_ldap_users.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/management/commands/test_db_connection.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0001_initial.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0002_prefillsource_alter_formfield_prefill_source_and_more.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0003_postsubmissionaction.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0004_formtemplate.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0005_advanced_conditional_logic.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0006_workflowdefinition_visual_workflow_data_and_more.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0007_add_userprofile_ldap_enhancements.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0008_add_file_workflow_models.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0009_add_formfield_readonly.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0010_add_prefillsource_template_fields.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0011_postsubmissionaction_email_body_template_and_more.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0012_add_approval_step_fields.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0013_add_database_query_key.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0014_add_form_category.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0015_add_workflowstage_staged_approvals.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0016_add_pdf_generation.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0017_add_notification_batching.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0018_add_form_category_parent.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0019_add_ldap_group_profile.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0020_add_bulk_export_field.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0021_alter_pendingnotification_scheduled_for_and_more.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0022_add_bulk_pdf_export.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0023_add_performance_indexes.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0024_add_allow_resubmit.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0025_workflowstage_approve_label.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0026_alter_formfield_width.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0027_formsubmission_form_data_gin.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0028_workflowstagegroupconfig.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0029_formfield_workflow_stage_fk_drop_groupconfig.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0030_formfield_phone_type.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0031_sub_workflows.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0032_approved_pending_detached_sub_workflow.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0033_add_reject_parent_to_subworkflowdefinition.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0034_add_notificationlog.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0035_migrate_prefill_source_strings.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0036_add_workflowstage_auto_created.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0037_migrate_flat_workflows_to_staged.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0038_remove_legacy_prefill_source_and_approval_step.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0039_update_help_text.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0040_migrate_deprecated_features.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0041_remove_deprecated_fields.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0042_add_sub_workflow_section_label.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0043_fix_form_data_decimal_encoding.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0044_remove_subworkflowinstance_label.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0045_stageapprovalgroup_workflow_name_label.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0046_workflow_definition_one_to_many.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0047_add_hide_approval_history.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0048_workflowdefinition_trigger_conditions_and_more.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0049_formfield_multifile_type.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0050_workflowdefinition_collapse_parallel_stages.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0051_formdefinition_is_listed.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0052_dynamic_assignee_and_form_field_notifications.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0053_stageformfieldnotification_static_emails.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0054_rename_approved_pending_to_pending_approval.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0055_add_send_back.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0056_calculated_formula_spreadsheet.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0057_add_currency_field_type.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0058_rename_assignee_email_field_add_lookup_type.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0059_add_multiselect_list_field_type.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0060_alter_workflowstage_assignee_lookup_type_helptext.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0061_add_country_us_state_field_types.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0062_add_batch_import_to_formdefinition.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0063_formdefinition_api_enabled_apitoken.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0064_add_reviewer_groups.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0065_workflownotification.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0066_add_notify_submitter_to_workflownotification.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0067_migrate_legacy_notify_flags.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0068_drop_legacy_notify_fields.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0069_add_signature_field_type.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0070_workflowstage_allow_edit_form_data.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0071_alter_pendingnotification_notification_type.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0072_add_change_history.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0073_add_stage_notify_assignee_on_final_decision.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0074_add_notification_rule.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0075_migrate_to_notification_rules.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0076_update_notification_event_choices.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0077_drop_legacy_notification_models.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0078_allow_anonymous_submissions.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0079_webhookendpoint_webhookdeliverylog.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0080_add_rating_matrix_address_slider_fields_and_form_controls.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0081_add_success_page_fields.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0082_add_document_template_model.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0083_workflowdefinition_start_trigger.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0084_add_shared_option_list.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0085_add_payment_system.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0086_add_embed_enabled.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0087_notificationrule_use_triggering_stage.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0088_notificationrule_body_template_and_events.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0089_workflowstage_hide_comment_field.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0090_alter_stageapprovalgroup_options_and_more.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0091_add_uuid_fields.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0092_add_user_notification_preference.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0093_normalize_conditional_operators.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0094_formfield_show_help_text_in_detail.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0095_notificationrule_cc_fields.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0096_notificationlog_cc_bcc_emails.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/0097_notificationlog_delivery_reconciliation.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/migrations/__init__.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/models.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/payments/__init__.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/payments/base.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/payments/registry.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/payments/stripe_provider.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/payments/views.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/reporting_views.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/signals.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/sso_backends.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/sso_urls.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/sso_views.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui-bundle.js +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui.css +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/css/forms.css +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/js/admin_notification_rule_stage_filter.js +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/js/dfw-embed.js +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/js/form-builder.js +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/js/form-enhancements.js +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/js/payment-stripe.js +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/js/signature-pad.js +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/static/django_forms_workflows/js/workflow-builder.js +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/sync_api.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/sync_views.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/_sync_diff.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/diff_forms.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/form_builder.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/formdef_change_form.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/formdefinition/change_list.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/sync_import.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/sync_pull.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/sync_push.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/admin/django_forms_workflows/workflow_builder.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/_category_node.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/_field_value.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/_form_data_rows.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/analytics_dashboard.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/api/docs.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/approval_inbox.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/approve.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/base.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/batch_import_result.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/completed_approvals.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/discard_draft_confirm.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/embed_base.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/embed_success.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/form_categories.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/form_embed.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/form_list.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/form_submit.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/my_submissions.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/notification_preferences.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/payment_collect.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/payment_error.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/public_submission_confirmation.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/rate_limited.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/reassign_task.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/resubmit_confirm.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/sso/login.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/sub_workflow_detail.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/submission_bulk_pdf.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/submission_detail.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/submission_pdf.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/submission_success.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/django_forms_workflows/withdraw_confirm.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/emails/approval_notification.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/emails/approval_reminder.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/emails/approval_request.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/emails/email_styles.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/emails/escalation_notification.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/emails/notification_digest.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/emails/rejection_notification.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/emails/submission_notification.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templates/registration/login.html +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templatetags/__init__.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/templatetags/forms_workflows_tags.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/urls.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/utils.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/views.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/workflow_builder_views.py +0 -0
- {django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/workflow_engine.py +0 -0
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Changed
|
|
11
|
+
- **Form builder save logic factored into a standalone helper.**
|
|
12
|
+
`form_builder_save`'s create/update logic for `FormDefinition` and its
|
|
13
|
+
`FormField`s now lives in `save_form_definition_from_builder_data()`,
|
|
14
|
+
mirroring the existing `convert_visual_to_workflow` split already used by
|
|
15
|
+
the workflow builder. Makes the logic callable (and unit-testable)
|
|
16
|
+
independently of the `@staff_member_required`-decorated HTTP view — no
|
|
17
|
+
behavior or API change.
|
|
18
|
+
|
|
10
19
|
## [0.76.0] - 2026-06-09
|
|
11
20
|
|
|
12
21
|
### Removed
|
|
@@ -370,36 +370,9 @@ def form_builder_save(request):
|
|
|
370
370
|
try:
|
|
371
371
|
data = json.loads(request.body)
|
|
372
372
|
|
|
373
|
-
# Extract form definition data
|
|
374
373
|
form_id = data.get("id")
|
|
375
374
|
form_name = data.get("name", "").strip()
|
|
376
375
|
form_slug = data.get("slug", "").strip()
|
|
377
|
-
form_description = data.get("description", "").strip()
|
|
378
|
-
form_instructions = data.get("instructions", "").strip()
|
|
379
|
-
is_active = data.get("is_active", True)
|
|
380
|
-
requires_login = data.get("requires_login", True)
|
|
381
|
-
allow_save_draft = data.get("allow_save_draft", True)
|
|
382
|
-
allow_withdrawal = data.get("allow_withdrawal", True)
|
|
383
|
-
success_message = data.get("success_message", "").strip()
|
|
384
|
-
success_redirect_url = data.get("success_redirect_url", "").strip()
|
|
385
|
-
success_redirect_rules = data.get("success_redirect_rules") or None
|
|
386
|
-
close_date = data.get("close_date") or None
|
|
387
|
-
max_submissions = data.get("max_submissions") or None
|
|
388
|
-
one_per_user = data.get("one_per_user", False)
|
|
389
|
-
payment_enabled = data.get("payment_enabled", False)
|
|
390
|
-
payment_provider = data.get("payment_provider", "")
|
|
391
|
-
payment_amount_type = data.get("payment_amount_type", "fixed")
|
|
392
|
-
payment_fixed_amount = data.get("payment_fixed_amount") or None
|
|
393
|
-
payment_amount_field = data.get("payment_amount_field", "")
|
|
394
|
-
payment_currency = data.get("payment_currency", "usd")
|
|
395
|
-
payment_description_template = data.get("payment_description_template", "")
|
|
396
|
-
enable_captcha = data.get("enable_captcha", False)
|
|
397
|
-
embed_enabled = data.get("embed_enabled", False)
|
|
398
|
-
enable_multi_step = data.get("enable_multi_step", False)
|
|
399
|
-
form_steps = data.get("form_steps", [])
|
|
400
|
-
enable_auto_save = data.get("enable_auto_save", True)
|
|
401
|
-
auto_save_interval = data.get("auto_save_interval", 30)
|
|
402
|
-
fields_data = data.get("fields", [])
|
|
403
376
|
|
|
404
377
|
# Validate required fields
|
|
405
378
|
if not form_name:
|
|
@@ -411,165 +384,15 @@ def form_builder_save(request):
|
|
|
411
384
|
{"success": False, "error": "Form slug is required"}, status=400
|
|
412
385
|
)
|
|
413
386
|
|
|
387
|
+
form_definition = (
|
|
388
|
+
get_object_or_404(FormDefinition, id=form_id) if form_id else None
|
|
389
|
+
)
|
|
390
|
+
|
|
414
391
|
# Use transaction to ensure atomicity
|
|
415
392
|
with transaction.atomic():
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
form_definition = get_object_or_404(FormDefinition, id=form_id)
|
|
419
|
-
form_definition.name = form_name
|
|
420
|
-
form_definition.slug = form_slug
|
|
421
|
-
form_definition.description = form_description
|
|
422
|
-
form_definition.instructions = form_instructions
|
|
423
|
-
form_definition.is_active = is_active
|
|
424
|
-
form_definition.requires_login = requires_login
|
|
425
|
-
form_definition.allow_save_draft = allow_save_draft
|
|
426
|
-
form_definition.allow_withdrawal = allow_withdrawal
|
|
427
|
-
form_definition.success_message = success_message
|
|
428
|
-
form_definition.success_redirect_url = success_redirect_url
|
|
429
|
-
form_definition.success_redirect_rules = success_redirect_rules
|
|
430
|
-
form_definition.close_date = close_date
|
|
431
|
-
form_definition.max_submissions = max_submissions
|
|
432
|
-
form_definition.one_per_user = one_per_user
|
|
433
|
-
form_definition.payment_enabled = payment_enabled
|
|
434
|
-
form_definition.payment_provider = payment_provider
|
|
435
|
-
form_definition.payment_amount_type = payment_amount_type
|
|
436
|
-
form_definition.payment_fixed_amount = payment_fixed_amount
|
|
437
|
-
form_definition.payment_amount_field = payment_amount_field
|
|
438
|
-
form_definition.payment_currency = payment_currency
|
|
439
|
-
form_definition.payment_description_template = (
|
|
440
|
-
payment_description_template
|
|
441
|
-
)
|
|
442
|
-
form_definition.enable_captcha = enable_captcha
|
|
443
|
-
form_definition.embed_enabled = embed_enabled
|
|
444
|
-
form_definition.enable_multi_step = enable_multi_step
|
|
445
|
-
form_definition.form_steps = form_steps
|
|
446
|
-
form_definition.enable_auto_save = enable_auto_save
|
|
447
|
-
form_definition.auto_save_interval = auto_save_interval
|
|
448
|
-
form_definition.version += 1 # Increment version on edit
|
|
449
|
-
form_definition.save()
|
|
450
|
-
else:
|
|
451
|
-
form_definition = FormDefinition.objects.create(
|
|
452
|
-
name=form_name,
|
|
453
|
-
slug=form_slug,
|
|
454
|
-
description=form_description,
|
|
455
|
-
instructions=form_instructions,
|
|
456
|
-
is_active=is_active,
|
|
457
|
-
requires_login=requires_login,
|
|
458
|
-
allow_save_draft=allow_save_draft,
|
|
459
|
-
allow_withdrawal=allow_withdrawal,
|
|
460
|
-
success_message=success_message,
|
|
461
|
-
success_redirect_url=success_redirect_url,
|
|
462
|
-
success_redirect_rules=success_redirect_rules,
|
|
463
|
-
close_date=close_date,
|
|
464
|
-
max_submissions=max_submissions,
|
|
465
|
-
one_per_user=one_per_user,
|
|
466
|
-
payment_enabled=payment_enabled,
|
|
467
|
-
payment_provider=payment_provider,
|
|
468
|
-
payment_amount_type=payment_amount_type,
|
|
469
|
-
payment_fixed_amount=payment_fixed_amount,
|
|
470
|
-
payment_amount_field=payment_amount_field,
|
|
471
|
-
payment_currency=payment_currency,
|
|
472
|
-
payment_description_template=payment_description_template,
|
|
473
|
-
enable_captcha=enable_captcha,
|
|
474
|
-
embed_enabled=embed_enabled,
|
|
475
|
-
enable_multi_step=enable_multi_step,
|
|
476
|
-
form_steps=form_steps,
|
|
477
|
-
enable_auto_save=enable_auto_save,
|
|
478
|
-
auto_save_interval=auto_save_interval,
|
|
479
|
-
created_by=request.user,
|
|
480
|
-
)
|
|
481
|
-
|
|
482
|
-
# Track existing field IDs to determine which to delete
|
|
483
|
-
existing_field_ids = set(
|
|
484
|
-
form_definition.fields.values_list("id", flat=True)
|
|
393
|
+
form_definition, field_id_mapping = save_form_definition_from_builder_data(
|
|
394
|
+
data, request.user, form_definition=form_definition
|
|
485
395
|
)
|
|
486
|
-
updated_field_ids = set()
|
|
487
|
-
field_id_mapping = {} # Map old IDs to new IDs for frontend update
|
|
488
|
-
|
|
489
|
-
# Create or update fields
|
|
490
|
-
for field_data in fields_data:
|
|
491
|
-
field_id = field_data.get("id")
|
|
492
|
-
old_id = field_id # Store original ID for mapping
|
|
493
|
-
|
|
494
|
-
# Extract field properties
|
|
495
|
-
field_props = {
|
|
496
|
-
"form_definition": form_definition,
|
|
497
|
-
"order": field_data.get("order", 0),
|
|
498
|
-
"field_label": field_data.get("field_label", ""),
|
|
499
|
-
"field_name": field_data.get("field_name", ""),
|
|
500
|
-
"field_type": field_data.get("field_type", "text"),
|
|
501
|
-
"required": field_data.get("required", False),
|
|
502
|
-
"help_text": field_data.get("help_text", ""),
|
|
503
|
-
"show_help_text_in_detail": field_data.get(
|
|
504
|
-
"show_help_text_in_detail", False
|
|
505
|
-
),
|
|
506
|
-
"placeholder": field_data.get("placeholder", ""),
|
|
507
|
-
"width": field_data.get("width", "full"),
|
|
508
|
-
"css_class": field_data.get("css_class", ""),
|
|
509
|
-
"choices": field_data.get("choices", ""),
|
|
510
|
-
"default_value": field_data.get("default_value", ""),
|
|
511
|
-
"prefill_source_config_id": field_data.get("prefill_source_id"),
|
|
512
|
-
"shared_option_list_id": field_data.get("shared_option_list_id")
|
|
513
|
-
or None,
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
# Add validation properties
|
|
517
|
-
validation = field_data.get("validation", {})
|
|
518
|
-
field_props.update(
|
|
519
|
-
{
|
|
520
|
-
"min_value": validation.get("min_value"),
|
|
521
|
-
"max_value": validation.get("max_value"),
|
|
522
|
-
"min_length": validation.get("min_length"),
|
|
523
|
-
"max_length": validation.get("max_length"),
|
|
524
|
-
"regex_validation": validation.get("regex_validation", ""),
|
|
525
|
-
"regex_error_message": validation.get(
|
|
526
|
-
"regex_error_message", ""
|
|
527
|
-
),
|
|
528
|
-
}
|
|
529
|
-
)
|
|
530
|
-
|
|
531
|
-
# Add conditional properties
|
|
532
|
-
conditional = field_data.get("conditional", {})
|
|
533
|
-
conditional_rules = conditional.get(
|
|
534
|
-
"conditional_rules",
|
|
535
|
-
field_data.get("conditional_rules"),
|
|
536
|
-
)
|
|
537
|
-
|
|
538
|
-
# Add client-side enhancement properties
|
|
539
|
-
field_props.update(
|
|
540
|
-
{
|
|
541
|
-
"conditional_rules": conditional_rules,
|
|
542
|
-
"validation_rules": field_data.get("validation_rules"),
|
|
543
|
-
"field_dependencies": field_data.get("field_dependencies"),
|
|
544
|
-
"step_number": field_data.get("step_number"),
|
|
545
|
-
}
|
|
546
|
-
)
|
|
547
|
-
|
|
548
|
-
# Add workflow stage FK (for staged approval workflows)
|
|
549
|
-
wf_stage_id = field_data.get("workflow_stage_id")
|
|
550
|
-
if wf_stage_id is not None:
|
|
551
|
-
field_props["workflow_stage_id"] = (
|
|
552
|
-
int(wf_stage_id) if wf_stage_id else None
|
|
553
|
-
)
|
|
554
|
-
else:
|
|
555
|
-
field_props["workflow_stage_id"] = None
|
|
556
|
-
|
|
557
|
-
# Create or update field
|
|
558
|
-
if field_id and isinstance(field_id, int):
|
|
559
|
-
# Update existing field
|
|
560
|
-
FormField.objects.filter(id=field_id).update(**field_props)
|
|
561
|
-
updated_field_ids.add(field_id)
|
|
562
|
-
field_id_mapping[str(old_id)] = field_id
|
|
563
|
-
else:
|
|
564
|
-
# Create new field
|
|
565
|
-
new_field = FormField.objects.create(**field_props)
|
|
566
|
-
updated_field_ids.add(new_field.id)
|
|
567
|
-
field_id_mapping[str(old_id)] = new_field.id
|
|
568
|
-
|
|
569
|
-
# Delete fields that were removed
|
|
570
|
-
fields_to_delete = existing_field_ids - updated_field_ids
|
|
571
|
-
if fields_to_delete:
|
|
572
|
-
FormField.objects.filter(id__in=fields_to_delete).delete()
|
|
573
396
|
|
|
574
397
|
return JsonResponse(
|
|
575
398
|
{
|
|
@@ -591,6 +414,202 @@ def form_builder_save(request):
|
|
|
591
414
|
)
|
|
592
415
|
|
|
593
416
|
|
|
417
|
+
def save_form_definition_from_builder_data(data, user, form_definition=None):
|
|
418
|
+
"""
|
|
419
|
+
Create or update a FormDefinition and its FormFields from form builder
|
|
420
|
+
JSON data (see form_builder_save).
|
|
421
|
+
|
|
422
|
+
If `form_definition` is given, updates it in place (its version counter
|
|
423
|
+
is incremented); otherwise creates a new one with created_by=user.
|
|
424
|
+
Assumes data["name"]/data["slug"] have already been validated non-empty
|
|
425
|
+
by the caller.
|
|
426
|
+
|
|
427
|
+
Returns (form_definition, field_id_mapping), where field_id_mapping maps
|
|
428
|
+
each submitted field's original "id" (as sent by the client — an int
|
|
429
|
+
for an existing field, otherwise its client-side placeholder id) to the
|
|
430
|
+
resulting integer pk, as a str-keyed dict, so the frontend can
|
|
431
|
+
reconcile IDs for newly-created fields.
|
|
432
|
+
"""
|
|
433
|
+
form_name = data.get("name", "").strip()
|
|
434
|
+
form_slug = data.get("slug", "").strip()
|
|
435
|
+
form_description = data.get("description", "").strip()
|
|
436
|
+
form_instructions = data.get("instructions", "").strip()
|
|
437
|
+
is_active = data.get("is_active", True)
|
|
438
|
+
requires_login = data.get("requires_login", True)
|
|
439
|
+
allow_save_draft = data.get("allow_save_draft", True)
|
|
440
|
+
allow_withdrawal = data.get("allow_withdrawal", True)
|
|
441
|
+
success_message = data.get("success_message", "").strip()
|
|
442
|
+
success_redirect_url = data.get("success_redirect_url", "").strip()
|
|
443
|
+
success_redirect_rules = data.get("success_redirect_rules") or None
|
|
444
|
+
close_date = data.get("close_date") or None
|
|
445
|
+
max_submissions = data.get("max_submissions") or None
|
|
446
|
+
one_per_user = data.get("one_per_user", False)
|
|
447
|
+
payment_enabled = data.get("payment_enabled", False)
|
|
448
|
+
payment_provider = data.get("payment_provider", "")
|
|
449
|
+
payment_amount_type = data.get("payment_amount_type", "fixed")
|
|
450
|
+
payment_fixed_amount = data.get("payment_fixed_amount") or None
|
|
451
|
+
payment_amount_field = data.get("payment_amount_field", "")
|
|
452
|
+
payment_currency = data.get("payment_currency", "usd")
|
|
453
|
+
payment_description_template = data.get("payment_description_template", "")
|
|
454
|
+
enable_captcha = data.get("enable_captcha", False)
|
|
455
|
+
embed_enabled = data.get("embed_enabled", False)
|
|
456
|
+
enable_multi_step = data.get("enable_multi_step", False)
|
|
457
|
+
form_steps = data.get("form_steps", [])
|
|
458
|
+
enable_auto_save = data.get("enable_auto_save", True)
|
|
459
|
+
auto_save_interval = data.get("auto_save_interval", 30)
|
|
460
|
+
fields_data = data.get("fields", [])
|
|
461
|
+
|
|
462
|
+
# Create or update form definition
|
|
463
|
+
if form_definition is not None:
|
|
464
|
+
form_definition.name = form_name
|
|
465
|
+
form_definition.slug = form_slug
|
|
466
|
+
form_definition.description = form_description
|
|
467
|
+
form_definition.instructions = form_instructions
|
|
468
|
+
form_definition.is_active = is_active
|
|
469
|
+
form_definition.requires_login = requires_login
|
|
470
|
+
form_definition.allow_save_draft = allow_save_draft
|
|
471
|
+
form_definition.allow_withdrawal = allow_withdrawal
|
|
472
|
+
form_definition.success_message = success_message
|
|
473
|
+
form_definition.success_redirect_url = success_redirect_url
|
|
474
|
+
form_definition.success_redirect_rules = success_redirect_rules
|
|
475
|
+
form_definition.close_date = close_date
|
|
476
|
+
form_definition.max_submissions = max_submissions
|
|
477
|
+
form_definition.one_per_user = one_per_user
|
|
478
|
+
form_definition.payment_enabled = payment_enabled
|
|
479
|
+
form_definition.payment_provider = payment_provider
|
|
480
|
+
form_definition.payment_amount_type = payment_amount_type
|
|
481
|
+
form_definition.payment_fixed_amount = payment_fixed_amount
|
|
482
|
+
form_definition.payment_amount_field = payment_amount_field
|
|
483
|
+
form_definition.payment_currency = payment_currency
|
|
484
|
+
form_definition.payment_description_template = payment_description_template
|
|
485
|
+
form_definition.enable_captcha = enable_captcha
|
|
486
|
+
form_definition.embed_enabled = embed_enabled
|
|
487
|
+
form_definition.enable_multi_step = enable_multi_step
|
|
488
|
+
form_definition.form_steps = form_steps
|
|
489
|
+
form_definition.enable_auto_save = enable_auto_save
|
|
490
|
+
form_definition.auto_save_interval = auto_save_interval
|
|
491
|
+
form_definition.version += 1 # Increment version on edit
|
|
492
|
+
form_definition.save()
|
|
493
|
+
else:
|
|
494
|
+
form_definition = FormDefinition.objects.create(
|
|
495
|
+
name=form_name,
|
|
496
|
+
slug=form_slug,
|
|
497
|
+
description=form_description,
|
|
498
|
+
instructions=form_instructions,
|
|
499
|
+
is_active=is_active,
|
|
500
|
+
requires_login=requires_login,
|
|
501
|
+
allow_save_draft=allow_save_draft,
|
|
502
|
+
allow_withdrawal=allow_withdrawal,
|
|
503
|
+
success_message=success_message,
|
|
504
|
+
success_redirect_url=success_redirect_url,
|
|
505
|
+
success_redirect_rules=success_redirect_rules,
|
|
506
|
+
close_date=close_date,
|
|
507
|
+
max_submissions=max_submissions,
|
|
508
|
+
one_per_user=one_per_user,
|
|
509
|
+
payment_enabled=payment_enabled,
|
|
510
|
+
payment_provider=payment_provider,
|
|
511
|
+
payment_amount_type=payment_amount_type,
|
|
512
|
+
payment_fixed_amount=payment_fixed_amount,
|
|
513
|
+
payment_amount_field=payment_amount_field,
|
|
514
|
+
payment_currency=payment_currency,
|
|
515
|
+
payment_description_template=payment_description_template,
|
|
516
|
+
enable_captcha=enable_captcha,
|
|
517
|
+
embed_enabled=embed_enabled,
|
|
518
|
+
enable_multi_step=enable_multi_step,
|
|
519
|
+
form_steps=form_steps,
|
|
520
|
+
enable_auto_save=enable_auto_save,
|
|
521
|
+
auto_save_interval=auto_save_interval,
|
|
522
|
+
created_by=user,
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
# Track existing field IDs to determine which to delete
|
|
526
|
+
existing_field_ids = set(form_definition.fields.values_list("id", flat=True))
|
|
527
|
+
updated_field_ids = set()
|
|
528
|
+
field_id_mapping = {} # Map old IDs to new IDs for frontend update
|
|
529
|
+
|
|
530
|
+
# Create or update fields
|
|
531
|
+
for field_data in fields_data:
|
|
532
|
+
field_id = field_data.get("id")
|
|
533
|
+
old_id = field_id # Store original ID for mapping
|
|
534
|
+
|
|
535
|
+
# Extract field properties
|
|
536
|
+
field_props = {
|
|
537
|
+
"form_definition": form_definition,
|
|
538
|
+
"order": field_data.get("order", 0),
|
|
539
|
+
"field_label": field_data.get("field_label", ""),
|
|
540
|
+
"field_name": field_data.get("field_name", ""),
|
|
541
|
+
"field_type": field_data.get("field_type", "text"),
|
|
542
|
+
"required": field_data.get("required", False),
|
|
543
|
+
"help_text": field_data.get("help_text", ""),
|
|
544
|
+
"show_help_text_in_detail": field_data.get(
|
|
545
|
+
"show_help_text_in_detail", False
|
|
546
|
+
),
|
|
547
|
+
"placeholder": field_data.get("placeholder", ""),
|
|
548
|
+
"width": field_data.get("width", "full"),
|
|
549
|
+
"css_class": field_data.get("css_class", ""),
|
|
550
|
+
"choices": field_data.get("choices", ""),
|
|
551
|
+
"default_value": field_data.get("default_value", ""),
|
|
552
|
+
"prefill_source_config_id": field_data.get("prefill_source_id"),
|
|
553
|
+
"shared_option_list_id": field_data.get("shared_option_list_id") or None,
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
# Add validation properties
|
|
557
|
+
validation = field_data.get("validation", {})
|
|
558
|
+
field_props.update(
|
|
559
|
+
{
|
|
560
|
+
"min_value": validation.get("min_value"),
|
|
561
|
+
"max_value": validation.get("max_value"),
|
|
562
|
+
"min_length": validation.get("min_length"),
|
|
563
|
+
"max_length": validation.get("max_length"),
|
|
564
|
+
"regex_validation": validation.get("regex_validation", ""),
|
|
565
|
+
"regex_error_message": validation.get("regex_error_message", ""),
|
|
566
|
+
}
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
# Add conditional properties
|
|
570
|
+
conditional = field_data.get("conditional", {})
|
|
571
|
+
conditional_rules = conditional.get(
|
|
572
|
+
"conditional_rules",
|
|
573
|
+
field_data.get("conditional_rules"),
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
# Add client-side enhancement properties
|
|
577
|
+
field_props.update(
|
|
578
|
+
{
|
|
579
|
+
"conditional_rules": conditional_rules,
|
|
580
|
+
"validation_rules": field_data.get("validation_rules"),
|
|
581
|
+
"field_dependencies": field_data.get("field_dependencies"),
|
|
582
|
+
"step_number": field_data.get("step_number"),
|
|
583
|
+
}
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
# Add workflow stage FK (for staged approval workflows)
|
|
587
|
+
wf_stage_id = field_data.get("workflow_stage_id")
|
|
588
|
+
if wf_stage_id is not None:
|
|
589
|
+
field_props["workflow_stage_id"] = int(wf_stage_id) if wf_stage_id else None
|
|
590
|
+
else:
|
|
591
|
+
field_props["workflow_stage_id"] = None
|
|
592
|
+
|
|
593
|
+
# Create or update field
|
|
594
|
+
if field_id and isinstance(field_id, int):
|
|
595
|
+
# Update existing field
|
|
596
|
+
FormField.objects.filter(id=field_id).update(**field_props)
|
|
597
|
+
updated_field_ids.add(field_id)
|
|
598
|
+
field_id_mapping[str(old_id)] = field_id
|
|
599
|
+
else:
|
|
600
|
+
# Create new field
|
|
601
|
+
new_field = FormField.objects.create(**field_props)
|
|
602
|
+
updated_field_ids.add(new_field.id)
|
|
603
|
+
field_id_mapping[str(old_id)] = new_field.id
|
|
604
|
+
|
|
605
|
+
# Delete fields that were removed
|
|
606
|
+
fields_to_delete = existing_field_ids - updated_field_ids
|
|
607
|
+
if fields_to_delete:
|
|
608
|
+
FormField.objects.filter(id__in=fields_to_delete).delete()
|
|
609
|
+
|
|
610
|
+
return form_definition, field_id_mapping
|
|
611
|
+
|
|
612
|
+
|
|
594
613
|
@staff_member_required
|
|
595
614
|
@require_POST
|
|
596
615
|
def form_builder_preview(request):
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/tasks.py
RENAMED
|
@@ -1108,10 +1108,22 @@ def _dispatch_conclusion_digest(
|
|
|
1108
1108
|
# ---------------------------------------------------------------------------
|
|
1109
1109
|
|
|
1110
1110
|
|
|
1111
|
-
def
|
|
1112
|
-
"""Extract and validate
|
|
1113
|
-
|
|
1114
|
-
|
|
1111
|
+
def _get_form_field_emails(form_data: dict, email_field: str) -> list[str]:
|
|
1112
|
+
"""Extract and validate email addresses from form_data by field slug.
|
|
1113
|
+
|
|
1114
|
+
A multi-select field (e.g. a picklist of faculty) stores several
|
|
1115
|
+
addresses in one value — as a comma-separated string, or as a list —
|
|
1116
|
+
so the value is always split before validation. Returning them
|
|
1117
|
+
separately keeps each address a single recipient; handing the raw
|
|
1118
|
+
``"a@x.edu,b@x.edu"`` string to the email backend is rejected with
|
|
1119
|
+
"must be a single address".
|
|
1120
|
+
"""
|
|
1121
|
+
raw = form_data.get(email_field, "")
|
|
1122
|
+
if isinstance(raw, list | tuple):
|
|
1123
|
+
raw = ",".join(str(part) for part in raw)
|
|
1124
|
+
return [
|
|
1125
|
+
addr for addr in (part.strip() for part in str(raw).split(",")) if "@" in addr
|
|
1126
|
+
]
|
|
1115
1127
|
|
|
1116
1128
|
|
|
1117
1129
|
def _collect_notification_recipients(
|
|
@@ -1142,9 +1154,10 @@ def _collect_notification_recipients(
|
|
|
1142
1154
|
if getattr(notif, "notify_submitter", False) and submission is not None:
|
|
1143
1155
|
_add(getattr(getattr(submission, "submitter", None), "email", None))
|
|
1144
1156
|
|
|
1145
|
-
# 2. Email field (dynamic from form_data)
|
|
1157
|
+
# 2. Email field (dynamic from form_data; may hold several addresses)
|
|
1146
1158
|
if notif.email_field:
|
|
1147
|
-
|
|
1159
|
+
for addr in _get_form_field_emails(form_data, notif.email_field):
|
|
1160
|
+
_add(addr)
|
|
1148
1161
|
|
|
1149
1162
|
# 3. Static emails
|
|
1150
1163
|
for addr in (notif.static_emails or "").split(","):
|
|
@@ -1294,7 +1307,8 @@ def _collect_notification_cc(notif, form_data: dict) -> list[str]:
|
|
|
1294
1307
|
cc.append(email)
|
|
1295
1308
|
|
|
1296
1309
|
if getattr(notif, "cc_email_field", ""):
|
|
1297
|
-
|
|
1310
|
+
for addr in _get_form_field_emails(form_data, notif.cc_email_field):
|
|
1311
|
+
_add(addr)
|
|
1298
1312
|
|
|
1299
1313
|
for addr in (getattr(notif, "cc_static_emails", "") or "").split(","):
|
|
1300
1314
|
addr = addr.strip()
|
|
File without changes
|
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/__init__.py
RENAMED
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/admin.py
RENAMED
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/api_urls.py
RENAMED
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/api_views.py
RENAMED
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/apps.py
RENAMED
|
File without changes
|
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/conditions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/diff_views.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/forms.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_forms_workflows-0.76.0 → django_forms_workflows-0.76.1}/django_forms_workflows/history.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|