django-forms-workflows 0.76.4__tar.gz → 0.76.6__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.4 → django_forms_workflows-0.76.6}/PKG-INFO +1 -1
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/admin.py +0 -4
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/email_backends/gmail_api.py +1 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/forms.py +7 -19
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/file_handler.py +4 -4
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0064_add_reviewer_groups.py +0 -3
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_backends.py +8 -0
- django_forms_workflows-0.76.6/django_forms_workflows/static/django_forms_workflows/js/form-builder-api.js +411 -0
- django_forms_workflows-0.76.6/django_forms_workflows/static/django_forms_workflows/js/form-builder-canvas.js +1136 -0
- django_forms_workflows-0.76.6/django_forms_workflows/static/django_forms_workflows/js/form-builder-property-editor.js +730 -0
- django_forms_workflows-0.76.6/django_forms_workflows/static/django_forms_workflows/js/form-builder.js +129 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/workflow-builder.js +16 -19
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/tasks.py +2 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/workflow_builder.html +3 -2
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/utils.py +4 -3
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/views.py +2 -11
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/workflow_builder_views.py +0 -1
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/workflow_engine.py +0 -2
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/pyproject.toml +1 -1
- django_forms_workflows-0.76.4/django_forms_workflows/static/django_forms_workflows/js/form-builder.js +0 -2338
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/CHANGELOG.md +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/LICENSE +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/README.md +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/__init__.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/api_urls.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/api_views.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/apps.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/callback_registry.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/conditions.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/context_processors.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/__init__.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/base.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/database_source.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/ldap_source.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/user_source.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/diff_views.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/email_backends/__init__.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/form_builder_urls.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/form_builder_views.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/__init__.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/api_handler.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/base.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/database_handler.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/email_handler.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/executor.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/ldap_handler.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/history.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/ldap_backend.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/create_default_templates.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/pull_forms.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/push_forms.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_farm_demo.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_pcn_form.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_prefill_sources.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/sync_ldap_profiles.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/sync_ldap_users.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/test_db_connection.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0001_initial.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0002_prefillsource_alter_formfield_prefill_source_and_more.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0003_postsubmissionaction.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0004_formtemplate.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0005_advanced_conditional_logic.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0006_workflowdefinition_visual_workflow_data_and_more.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0007_add_userprofile_ldap_enhancements.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0008_add_file_workflow_models.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0009_add_formfield_readonly.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0010_add_prefillsource_template_fields.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0011_postsubmissionaction_email_body_template_and_more.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0012_add_approval_step_fields.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0013_add_database_query_key.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0014_add_form_category.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0015_add_workflowstage_staged_approvals.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0016_add_pdf_generation.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0017_add_notification_batching.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0018_add_form_category_parent.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0019_add_ldap_group_profile.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0020_add_bulk_export_field.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0021_alter_pendingnotification_scheduled_for_and_more.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0022_add_bulk_pdf_export.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0023_add_performance_indexes.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0024_add_allow_resubmit.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0025_workflowstage_approve_label.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0026_alter_formfield_width.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0027_formsubmission_form_data_gin.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0028_workflowstagegroupconfig.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0029_formfield_workflow_stage_fk_drop_groupconfig.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0030_formfield_phone_type.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0031_sub_workflows.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0032_approved_pending_detached_sub_workflow.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0033_add_reject_parent_to_subworkflowdefinition.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0034_add_notificationlog.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0035_migrate_prefill_source_strings.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0036_add_workflowstage_auto_created.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0037_migrate_flat_workflows_to_staged.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0038_remove_legacy_prefill_source_and_approval_step.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0039_update_help_text.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0040_migrate_deprecated_features.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0041_remove_deprecated_fields.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0042_add_sub_workflow_section_label.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0043_fix_form_data_decimal_encoding.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0044_remove_subworkflowinstance_label.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0045_stageapprovalgroup_workflow_name_label.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0046_workflow_definition_one_to_many.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0047_add_hide_approval_history.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0048_workflowdefinition_trigger_conditions_and_more.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0049_formfield_multifile_type.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0050_workflowdefinition_collapse_parallel_stages.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0051_formdefinition_is_listed.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0052_dynamic_assignee_and_form_field_notifications.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0053_stageformfieldnotification_static_emails.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0054_rename_approved_pending_to_pending_approval.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0055_add_send_back.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0056_calculated_formula_spreadsheet.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0057_add_currency_field_type.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0058_rename_assignee_email_field_add_lookup_type.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0059_add_multiselect_list_field_type.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0060_alter_workflowstage_assignee_lookup_type_helptext.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0061_add_country_us_state_field_types.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0062_add_batch_import_to_formdefinition.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0063_formdefinition_api_enabled_apitoken.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0065_workflownotification.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0066_add_notify_submitter_to_workflownotification.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0067_migrate_legacy_notify_flags.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0068_drop_legacy_notify_fields.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0069_add_signature_field_type.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0070_workflowstage_allow_edit_form_data.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0071_alter_pendingnotification_notification_type.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0072_add_change_history.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0073_add_stage_notify_assignee_on_final_decision.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0074_add_notification_rule.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0075_migrate_to_notification_rules.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0076_update_notification_event_choices.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0077_drop_legacy_notification_models.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0078_allow_anonymous_submissions.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0079_webhookendpoint_webhookdeliverylog.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0080_add_rating_matrix_address_slider_fields_and_form_controls.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0081_add_success_page_fields.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0082_add_document_template_model.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0083_workflowdefinition_start_trigger.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0084_add_shared_option_list.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0085_add_payment_system.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0086_add_embed_enabled.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0087_notificationrule_use_triggering_stage.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0088_notificationrule_body_template_and_events.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0089_workflowstage_hide_comment_field.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0090_alter_stageapprovalgroup_options_and_more.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0091_add_uuid_fields.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0092_add_user_notification_preference.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0093_normalize_conditional_operators.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0094_formfield_show_help_text_in_detail.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0095_notificationrule_cc_fields.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0096_notificationlog_cc_bcc_emails.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0097_notificationlog_delivery_reconciliation.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/__init__.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/models.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/__init__.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/base.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/registry.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/stripe_provider.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/views.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/reporting_views.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/signals.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_urls.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_views.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui-bundle.js +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui.css +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/css/forms.css +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/admin_notification_rule_stage_filter.js +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/dfw-embed.js +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/form-builder-history.js +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/form-builder-store.js +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/form-enhancements.js +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/payment-stripe.js +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/signature-pad.js +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/sync_api.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/sync_views.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/_sync_diff.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/diff_forms.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/form_builder.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/formdef_change_form.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/formdefinition/change_list.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/sync_import.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/sync_pull.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/sync_push.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/_category_node.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/_field_value.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/_form_data_rows.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/analytics_dashboard.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/api/docs.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/approval_inbox.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/approve.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/base.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/batch_import_result.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/completed_approvals.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/discard_draft_confirm.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/embed_base.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/embed_success.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_categories.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_embed.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_list.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_submit.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/my_submissions.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/notification_preferences.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/payment_collect.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/payment_error.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/public_submission_confirmation.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/rate_limited.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/reassign_task.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/resubmit_confirm.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/sso/login.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/sub_workflow_detail.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_bulk_pdf.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_detail.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_pdf.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_success.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/withdraw_confirm.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_notification.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_reminder.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_request.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/email_styles.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/escalation_notification.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/notification_digest.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/rejection_notification.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/submission_notification.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/registration/login.html +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templatetags/__init__.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/templatetags/forms_workflows_tags.py +0 -0
- {django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/urls.py +0 -0
{django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/admin.py
RENAMED
|
@@ -278,8 +278,6 @@ def _render_conditional_rules(rules) -> str:
|
|
|
278
278
|
[SHOW] when ``first_enrollment`` equals ``Yes``
|
|
279
279
|
[REQUIRE] when ``first_enrollment`` equals ``Yes``
|
|
280
280
|
"""
|
|
281
|
-
import json
|
|
282
|
-
|
|
283
281
|
if not rules:
|
|
284
282
|
return ""
|
|
285
283
|
if isinstance(rules, str):
|
|
@@ -1279,8 +1277,6 @@ class FormDefinitionAdmin(nested_admin.NestedModelAdmin):
|
|
|
1279
1277
|
remote_forms = payload.get("forms", [])
|
|
1280
1278
|
|
|
1281
1279
|
# Build per-form diffs: remote vs local
|
|
1282
|
-
import json
|
|
1283
|
-
|
|
1284
1280
|
from .diff_views import _build_summary
|
|
1285
1281
|
|
|
1286
1282
|
form_diffs = []
|
|
@@ -72,6 +72,7 @@ def _is_retryable_gmail_error(exc) -> bool:
|
|
|
72
72
|
if err.get("reason") in _RETRYABLE_GMAIL_REASONS:
|
|
73
73
|
return True
|
|
74
74
|
except (ValueError, AttributeError, KeyError, TypeError):
|
|
75
|
+
# A malformed error payload is not enough evidence to retry safely.
|
|
75
76
|
pass
|
|
76
77
|
return False
|
|
77
78
|
|
{django_forms_workflows-0.76.4 → django_forms_workflows-0.76.6}/django_forms_workflows/forms.py
RENAMED
|
@@ -341,6 +341,8 @@ class DynamicForm(forms.Form):
|
|
|
341
341
|
try:
|
|
342
342
|
self.stashed_files = json.loads(prev)
|
|
343
343
|
except (json.JSONDecodeError, TypeError):
|
|
344
|
+
# Ignore malformed client metadata; uploaded files are rebuilt
|
|
345
|
+
# from validated server-side data below.
|
|
344
346
|
pass
|
|
345
347
|
|
|
346
348
|
# Build form fields from definition
|
|
@@ -1177,8 +1179,6 @@ class DynamicForm(forms.Form):
|
|
|
1177
1179
|
Hidden fields are also dropped from ``cleaned_data`` so that their
|
|
1178
1180
|
values are not persisted in the submission.
|
|
1179
1181
|
"""
|
|
1180
|
-
import json
|
|
1181
|
-
|
|
1182
1182
|
from .conditions import evaluate_conditions
|
|
1183
1183
|
|
|
1184
1184
|
cleaned_data = super().clean()
|
|
@@ -1307,8 +1307,6 @@ class DynamicForm(forms.Form):
|
|
|
1307
1307
|
Generate JavaScript configuration for form enhancements.
|
|
1308
1308
|
Returns a dictionary that can be serialized to JSON.
|
|
1309
1309
|
"""
|
|
1310
|
-
import json
|
|
1311
|
-
|
|
1312
1310
|
from django.urls import reverse
|
|
1313
1311
|
|
|
1314
1312
|
# Disable auto-save for anonymous users (no drafts without a user)
|
|
@@ -1554,8 +1552,6 @@ class ApprovalStepForm(forms.Form):
|
|
|
1554
1552
|
|
|
1555
1553
|
def _add_field(self, field_def):
|
|
1556
1554
|
"""Add a single field to the form."""
|
|
1557
|
-
is_editable = True
|
|
1558
|
-
|
|
1559
1555
|
# Get current value from form data.
|
|
1560
1556
|
# Sub-workflow fields are stored with an index suffix (e.g. payment_dept_code_1);
|
|
1561
1557
|
# try the indexed key first, then fall back to the bare field name.
|
|
@@ -1572,16 +1568,16 @@ class ApprovalStepForm(forms.Form):
|
|
|
1572
1568
|
current_value = field_def.default_value
|
|
1573
1569
|
|
|
1574
1570
|
# Auto-fill approver name from current user
|
|
1575
|
-
if
|
|
1571
|
+
if self._is_approver_name_field(field_def):
|
|
1576
1572
|
current_value = self._get_approver_name()
|
|
1577
1573
|
# Auto-fill date with current date
|
|
1578
|
-
elif
|
|
1574
|
+
elif self._is_date_field(field_def):
|
|
1579
1575
|
current_value = date.today()
|
|
1580
1576
|
|
|
1581
1577
|
# Common field arguments
|
|
1582
1578
|
field_args = {
|
|
1583
1579
|
"label": field_def.field_label,
|
|
1584
|
-
"required": field_def.required
|
|
1580
|
+
"required": field_def.required,
|
|
1585
1581
|
"help_text": field_def.help_text,
|
|
1586
1582
|
"initial": current_value,
|
|
1587
1583
|
}
|
|
@@ -1593,17 +1589,11 @@ class ApprovalStepForm(forms.Form):
|
|
|
1593
1589
|
if field_def.css_class:
|
|
1594
1590
|
widget_attrs["class"] = field_def.css_class
|
|
1595
1591
|
|
|
1596
|
-
# Make non-editable fields read-only
|
|
1597
|
-
if not is_editable:
|
|
1598
|
-
widget_attrs["readonly"] = "readonly"
|
|
1599
|
-
widget_attrs["disabled"] = "disabled"
|
|
1600
|
-
field_args["required"] = False
|
|
1601
|
-
|
|
1602
1592
|
if field_def.field_type in _PM_OPT_OUT_FIELD_TYPES:
|
|
1603
1593
|
widget_attrs.update(_PM_OPT_OUT_ATTRS)
|
|
1604
1594
|
|
|
1605
1595
|
# Create appropriate field type
|
|
1606
|
-
self._create_field(field_def, field_args, widget_attrs
|
|
1596
|
+
self._create_field(field_def, field_args, widget_attrs)
|
|
1607
1597
|
|
|
1608
1598
|
def _is_approver_name_field(self, field_def):
|
|
1609
1599
|
"""Check if this is an approver name field (to auto-fill)."""
|
|
@@ -1629,7 +1619,7 @@ class ApprovalStepForm(forms.Form):
|
|
|
1629
1619
|
return self.user.username
|
|
1630
1620
|
return ""
|
|
1631
1621
|
|
|
1632
|
-
def _create_field(self, field_def, field_args, widget_attrs
|
|
1622
|
+
def _create_field(self, field_def, field_args, widget_attrs):
|
|
1633
1623
|
"""Create the appropriate Django form field."""
|
|
1634
1624
|
if field_def.field_type == "text":
|
|
1635
1625
|
if widget_attrs:
|
|
@@ -2002,8 +1992,6 @@ class ApprovalStepForm(forms.Form):
|
|
|
2002
1992
|
validate fields on input/blur instead of waiting for submit, matching
|
|
2003
1993
|
the behavior of the original submission form.
|
|
2004
1994
|
"""
|
|
2005
|
-
import json
|
|
2006
|
-
|
|
2007
1995
|
stage_id = self.approval_task.workflow_stage_id
|
|
2008
1996
|
if stage_id is None:
|
|
2009
1997
|
stage_fields = []
|
|
@@ -138,7 +138,7 @@ class FileOperationHandler:
|
|
|
138
138
|
self.managed_file.file_path = new_path
|
|
139
139
|
self.managed_file.save(update_fields=["stored_filename", "file_path"])
|
|
140
140
|
|
|
141
|
-
logger.info(
|
|
141
|
+
logger.info("Renamed managed file id=%s", self.managed_file.id)
|
|
142
142
|
return {"success": True, "message": f"Renamed to {new_filename}"}
|
|
143
143
|
return {"success": False, "message": f"File not found: {old_path}"}
|
|
144
144
|
|
|
@@ -174,7 +174,7 @@ class FileOperationHandler:
|
|
|
174
174
|
self.managed_file.stored_filename = os.path.basename(new_path)
|
|
175
175
|
self.managed_file.save(update_fields=["file_path", "stored_filename"])
|
|
176
176
|
|
|
177
|
-
logger.info(
|
|
177
|
+
logger.info("Moved managed file id=%s", self.managed_file.id)
|
|
178
178
|
return {"success": True, "message": f"Moved to {new_path}"}
|
|
179
179
|
return {"success": False, "message": f"File not found: {old_path}"}
|
|
180
180
|
|
|
@@ -204,7 +204,7 @@ class FileOperationHandler:
|
|
|
204
204
|
content = f.read()
|
|
205
205
|
self.storage.save(new_path, content)
|
|
206
206
|
|
|
207
|
-
logger.info(
|
|
207
|
+
logger.info("Copied managed file id=%s", self.managed_file.id)
|
|
208
208
|
return {"success": True, "message": f"Copied to {new_path}"}
|
|
209
209
|
return {"success": False, "message": f"File not found: {old_path}"}
|
|
210
210
|
|
|
@@ -225,7 +225,7 @@ class FileOperationHandler:
|
|
|
225
225
|
self.managed_file.status_changed_at = timezone.now()
|
|
226
226
|
self.managed_file.save(update_fields=["status", "status_changed_at"])
|
|
227
227
|
|
|
228
|
-
logger.info(
|
|
228
|
+
logger.info("Deleted managed file id=%s", self.managed_file.id)
|
|
229
229
|
return {"success": True, "message": f"Deleted {file_path}"}
|
|
230
230
|
return {"success": False, "message": f"File not found: {file_path}"}
|
|
231
231
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import django.db.models.deletion
|
|
2
1
|
from django.db import migrations, models
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
class Migration(migrations.Migration):
|
|
6
|
-
|
|
7
5
|
dependencies = [
|
|
8
6
|
("django_forms_workflows", "0063_formdefinition_api_enabled_apitoken"),
|
|
9
7
|
]
|
|
@@ -24,4 +22,3 @@ class Migration(migrations.Migration):
|
|
|
24
22
|
),
|
|
25
23
|
),
|
|
26
24
|
]
|
|
27
|
-
|
|
@@ -253,6 +253,14 @@ def get_saml_config():
|
|
|
253
253
|
This helper constructs the SAML settings from Django settings,
|
|
254
254
|
providing sensible defaults for common use cases.
|
|
255
255
|
|
|
256
|
+
Compatibility note:
|
|
257
|
+
The default ``security`` configuration sets
|
|
258
|
+
``wantAttributeStatement`` to ``False``. This is intentional to
|
|
259
|
+
support IdPs (including Google SAML in common configurations) that
|
|
260
|
+
may authenticate successfully without returning a SAML AttributeStatement.
|
|
261
|
+
Projects that require attributes can override this through
|
|
262
|
+
``FORMS_WORKFLOWS_SAML["security"]``.
|
|
263
|
+
|
|
256
264
|
Returns:
|
|
257
265
|
dict: SAML configuration for OneLogin's python3-saml
|
|
258
266
|
"""
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API client for the Form Builder: loading/saving the form definition,
|
|
3
|
+
* generating the live preview, and the template picker.
|
|
4
|
+
*
|
|
5
|
+
* Mixed onto FormBuilder.prototype in form-builder.js (Object.assign), not a
|
|
6
|
+
* standalone class of its own - these methods read/write a large number of
|
|
7
|
+
* page DOM fields directly, plus `this.fields`/`this.formSteps`/`this.config`,
|
|
8
|
+
* and call back into canvas-render methods (renderCanvas/renderStepTabs/
|
|
9
|
+
* toggleMultiStepMode) that still live on the single FormBuilder instance.
|
|
10
|
+
*/
|
|
11
|
+
export const apiMethods = {
|
|
12
|
+
updatePreview() {
|
|
13
|
+
// Debounce preview updates to avoid too many API calls
|
|
14
|
+
if (this.previewTimeout) {
|
|
15
|
+
clearTimeout(this.previewTimeout);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
this.previewTimeout = setTimeout(() => {
|
|
19
|
+
this.generatePreview();
|
|
20
|
+
}, 500); // Wait 500ms after last change
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
async generatePreview() {
|
|
24
|
+
const preview = document.getElementById('formPreview');
|
|
25
|
+
|
|
26
|
+
// Show loading state
|
|
27
|
+
preview.innerHTML = `
|
|
28
|
+
<div class="text-center text-muted py-4">
|
|
29
|
+
<div class="spinner-border spinner-border-sm" role="status">
|
|
30
|
+
<span class="visually-hidden">Loading...</span>
|
|
31
|
+
</div>
|
|
32
|
+
<p class="small mt-2">Generating preview...</p>
|
|
33
|
+
</div>
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
// Gather form data
|
|
38
|
+
const formData = {
|
|
39
|
+
name: document.getElementById('formName').value || 'Untitled Form',
|
|
40
|
+
slug: document.getElementById('formSlug').value || 'untitled-form',
|
|
41
|
+
description: document.getElementById('formDescription').value || '',
|
|
42
|
+
instructions: document.getElementById('formInstructions').value || '',
|
|
43
|
+
is_active: document.getElementById('formIsActive').checked,
|
|
44
|
+
requires_login: document.getElementById('formRequiresLogin').checked,
|
|
45
|
+
allow_save_draft: document.getElementById('formAllowDraft').checked,
|
|
46
|
+
allow_withdrawal: document.getElementById('formAllowWithdrawal').checked,
|
|
47
|
+
fields: this.fields
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Call preview API
|
|
51
|
+
const response = await fetch(this.config.apiUrls.preview, {
|
|
52
|
+
method: 'POST',
|
|
53
|
+
headers: {
|
|
54
|
+
'Content-Type': 'application/json',
|
|
55
|
+
'X-CSRFToken': this.config.csrfToken
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify(formData)
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const errorText = await response.text();
|
|
62
|
+
console.error('Preview API error:', response.status, errorText);
|
|
63
|
+
throw new Error(`Server error: ${response.status}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const data = await response.json();
|
|
67
|
+
|
|
68
|
+
if (data.success) {
|
|
69
|
+
preview.innerHTML = data.html;
|
|
70
|
+
} else {
|
|
71
|
+
console.error('Preview generation failed:', data.error);
|
|
72
|
+
throw new Error(data.error || 'Unknown error');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error('Preview error:', error);
|
|
77
|
+
|
|
78
|
+
// If there are no fields, show a helpful message
|
|
79
|
+
if (this.fields.length === 0) {
|
|
80
|
+
preview.innerHTML = `
|
|
81
|
+
<div class="alert alert-info small">
|
|
82
|
+
<i class="bi bi-info-circle"></i>
|
|
83
|
+
<strong>No fields yet</strong><br>
|
|
84
|
+
Drag fields from the palette to get started
|
|
85
|
+
</div>
|
|
86
|
+
`;
|
|
87
|
+
} else {
|
|
88
|
+
preview.innerHTML = `
|
|
89
|
+
<div class="alert alert-warning small">
|
|
90
|
+
<i class="bi bi-exclamation-triangle"></i>
|
|
91
|
+
<strong>Preview unavailable</strong><br>
|
|
92
|
+
${this.fields.length} field(s) configured<br>
|
|
93
|
+
<small class="text-muted">${error.message}</small>
|
|
94
|
+
</div>
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
async loadForm() {
|
|
101
|
+
try {
|
|
102
|
+
const response = await fetch(this.config.apiUrls.load, {
|
|
103
|
+
method: 'GET',
|
|
104
|
+
headers: {
|
|
105
|
+
'X-CSRFToken': this.config.csrfToken
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
throw new Error('Failed to load form');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const data = await response.json();
|
|
114
|
+
|
|
115
|
+
// Populate form settings
|
|
116
|
+
document.getElementById('formName').value = data.name || '';
|
|
117
|
+
document.getElementById('formSlug').value = data.slug || '';
|
|
118
|
+
document.getElementById('formDescription').value = data.description || '';
|
|
119
|
+
document.getElementById('formInstructions').value = data.instructions || '';
|
|
120
|
+
document.getElementById('formIsActive').checked = data.is_active;
|
|
121
|
+
document.getElementById('formRequiresLogin').checked = data.requires_login;
|
|
122
|
+
document.getElementById('formAllowDraft').checked = data.allow_save_draft;
|
|
123
|
+
document.getElementById('formAllowWithdrawal').checked = data.allow_withdrawal;
|
|
124
|
+
|
|
125
|
+
// Load success page settings
|
|
126
|
+
document.getElementById('formSuccessMessage').value = data.success_message || '';
|
|
127
|
+
document.getElementById('formSuccessRedirectUrl').value = data.success_redirect_url || '';
|
|
128
|
+
document.getElementById('formSuccessRedirectRules').value = data.success_redirect_rules ? JSON.stringify(data.success_redirect_rules) : '';
|
|
129
|
+
|
|
130
|
+
// Load payment settings
|
|
131
|
+
document.getElementById('formPaymentEnabled').checked = data.payment_enabled || false;
|
|
132
|
+
if (data.payment_enabled) document.getElementById('paymentSettings').style.display = '';
|
|
133
|
+
// Populate provider dropdown
|
|
134
|
+
const providerSelect = document.getElementById('formPaymentProvider');
|
|
135
|
+
providerSelect.innerHTML = '<option value="">-- Select --</option>';
|
|
136
|
+
(this.config.paymentProviders || []).forEach(([val, label]) => {
|
|
137
|
+
const opt = document.createElement('option');
|
|
138
|
+
opt.value = val;
|
|
139
|
+
opt.textContent = label;
|
|
140
|
+
if (val === data.payment_provider) opt.selected = true;
|
|
141
|
+
providerSelect.appendChild(opt);
|
|
142
|
+
});
|
|
143
|
+
document.getElementById('formPaymentAmountType').value = data.payment_amount_type || 'fixed';
|
|
144
|
+
if (data.payment_fixed_amount) document.getElementById('formPaymentFixedAmount').value = data.payment_fixed_amount;
|
|
145
|
+
if (data.payment_amount_field) document.getElementById('formPaymentAmountField').value = data.payment_amount_field;
|
|
146
|
+
document.getElementById('formPaymentCurrency').value = data.payment_currency || 'usd';
|
|
147
|
+
if (data.payment_description_template) document.getElementById('formPaymentDescription').value = data.payment_description_template;
|
|
148
|
+
|
|
149
|
+
// Load submission controls
|
|
150
|
+
if (data.close_date) document.getElementById('formCloseDate').value = data.close_date.slice(0, 16);
|
|
151
|
+
if (data.max_submissions) document.getElementById('formMaxSubmissions').value = data.max_submissions;
|
|
152
|
+
document.getElementById('formOnePerUser').checked = data.one_per_user || false;
|
|
153
|
+
document.getElementById('formEnableCaptcha').checked = data.enable_captcha || false;
|
|
154
|
+
document.getElementById('formEmbedEnabled').checked = data.embed_enabled || false;
|
|
155
|
+
|
|
156
|
+
// Load client-side enhancement settings
|
|
157
|
+
document.getElementById('formEnableAutoSave').checked = data.enable_auto_save !== false;
|
|
158
|
+
document.getElementById('formAutoSaveInterval').value = data.auto_save_interval || 30;
|
|
159
|
+
document.getElementById('formEnableMultiStep').checked = data.enable_multi_step || false;
|
|
160
|
+
this.formSteps = data.form_steps || [];
|
|
161
|
+
|
|
162
|
+
// Load fields
|
|
163
|
+
this.fields = data.fields || [];
|
|
164
|
+
this.store.seedFieldIdCounterFromFields(this.fields);
|
|
165
|
+
|
|
166
|
+
// If multi-step is enabled, switch to multi-step mode
|
|
167
|
+
if (data.enable_multi_step) {
|
|
168
|
+
this.toggleMultiStepMode(true);
|
|
169
|
+
} else {
|
|
170
|
+
this.renderCanvas();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
this.updatePreview();
|
|
174
|
+
|
|
175
|
+
document.getElementById('saveStatus').textContent = 'Loaded successfully';
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error('Error loading form:', error);
|
|
178
|
+
alert('Failed to load form: ' + error.message);
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
async saveForm() {
|
|
183
|
+
// Validate form settings
|
|
184
|
+
const formName = document.getElementById('formName').value.trim();
|
|
185
|
+
const formSlug = document.getElementById('formSlug').value.trim();
|
|
186
|
+
|
|
187
|
+
if (!formName) {
|
|
188
|
+
alert('Please enter a form name');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!formSlug) {
|
|
193
|
+
alert('Please enter a form slug');
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// If in multi-step mode, update field order from step canvases
|
|
198
|
+
const isMultiStep = document.getElementById('formEnableMultiStep').checked;
|
|
199
|
+
if (isMultiStep) {
|
|
200
|
+
this.updateFieldOrderFromSteps();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Build form data
|
|
204
|
+
const formData = {
|
|
205
|
+
id: this.config.formId,
|
|
206
|
+
name: formName,
|
|
207
|
+
slug: formSlug,
|
|
208
|
+
description: document.getElementById('formDescription').value.trim(),
|
|
209
|
+
instructions: document.getElementById('formInstructions').value.trim(),
|
|
210
|
+
is_active: document.getElementById('formIsActive').checked,
|
|
211
|
+
requires_login: document.getElementById('formRequiresLogin').checked,
|
|
212
|
+
allow_save_draft: document.getElementById('formAllowDraft').checked,
|
|
213
|
+
allow_withdrawal: document.getElementById('formAllowWithdrawal').checked,
|
|
214
|
+
success_message: document.getElementById('formSuccessMessage').value.trim(),
|
|
215
|
+
success_redirect_url: document.getElementById('formSuccessRedirectUrl').value.trim(),
|
|
216
|
+
success_redirect_rules: (() => { try { const v = document.getElementById('formSuccessRedirectRules').value.trim(); return v ? JSON.parse(v) : null; } catch(e) { return null; } })(),
|
|
217
|
+
payment_enabled: document.getElementById('formPaymentEnabled').checked,
|
|
218
|
+
payment_provider: document.getElementById('formPaymentProvider').value,
|
|
219
|
+
payment_amount_type: document.getElementById('formPaymentAmountType').value,
|
|
220
|
+
payment_fixed_amount: document.getElementById('formPaymentFixedAmount').value || null,
|
|
221
|
+
payment_amount_field: document.getElementById('formPaymentAmountField').value,
|
|
222
|
+
payment_currency: document.getElementById('formPaymentCurrency').value,
|
|
223
|
+
payment_description_template: document.getElementById('formPaymentDescription').value,
|
|
224
|
+
close_date: document.getElementById('formCloseDate').value || null,
|
|
225
|
+
max_submissions: parseInt(document.getElementById('formMaxSubmissions').value) || null,
|
|
226
|
+
one_per_user: document.getElementById('formOnePerUser').checked,
|
|
227
|
+
enable_captcha: document.getElementById('formEnableCaptcha').checked,
|
|
228
|
+
embed_enabled: document.getElementById('formEmbedEnabled').checked,
|
|
229
|
+
enable_auto_save: document.getElementById('formEnableAutoSave').checked,
|
|
230
|
+
auto_save_interval: parseInt(document.getElementById('formAutoSaveInterval').value) || 30,
|
|
231
|
+
enable_multi_step: isMultiStep,
|
|
232
|
+
form_steps: this.formSteps || [],
|
|
233
|
+
fields: this.fields
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// Show saving status
|
|
237
|
+
const saveBtn = document.getElementById('btnSave');
|
|
238
|
+
const originalText = saveBtn.innerHTML;
|
|
239
|
+
saveBtn.disabled = true;
|
|
240
|
+
saveBtn.innerHTML = '<i class="bi bi-hourglass-split"></i> Saving...';
|
|
241
|
+
document.getElementById('saveStatus').textContent = 'Saving...';
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
const response = await fetch(this.config.apiUrls.save, {
|
|
245
|
+
method: 'POST',
|
|
246
|
+
headers: {
|
|
247
|
+
'Content-Type': 'application/json',
|
|
248
|
+
'X-CSRFToken': this.config.csrfToken
|
|
249
|
+
},
|
|
250
|
+
body: JSON.stringify(formData)
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const result = await response.json();
|
|
254
|
+
|
|
255
|
+
if (!response.ok || !result.success) {
|
|
256
|
+
throw new Error(result.error || 'Failed to save form');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Update field IDs with the mapping from backend
|
|
260
|
+
if (result.field_id_mapping) {
|
|
261
|
+
this.fields.forEach(field => {
|
|
262
|
+
const oldId = String(field.id);
|
|
263
|
+
if (result.field_id_mapping[oldId]) {
|
|
264
|
+
field.id = result.field_id_mapping[oldId];
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// Re-render to update the UI with new IDs
|
|
269
|
+
const isMultiStep = document.getElementById('formEnableMultiStep')?.checked;
|
|
270
|
+
if (isMultiStep) {
|
|
271
|
+
this.renderStepTabs();
|
|
272
|
+
} else {
|
|
273
|
+
this.renderCanvas();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
document.getElementById('saveStatus').textContent = 'Saved successfully';
|
|
278
|
+
|
|
279
|
+
// If this was a new form, redirect to edit mode
|
|
280
|
+
if (this.config.isNew && result.form_id) {
|
|
281
|
+
setTimeout(() => {
|
|
282
|
+
window.location.href = `/admin/django_forms_workflows/formdefinition/${result.form_id}/builder/`;
|
|
283
|
+
}, 1000);
|
|
284
|
+
} else {
|
|
285
|
+
// Show success message
|
|
286
|
+
setTimeout(() => {
|
|
287
|
+
document.getElementById('saveStatus').textContent = 'All changes saved';
|
|
288
|
+
}, 2000);
|
|
289
|
+
}
|
|
290
|
+
} catch (error) {
|
|
291
|
+
console.error('Error saving form:', error);
|
|
292
|
+
alert('Failed to save form: ' + error.message);
|
|
293
|
+
document.getElementById('saveStatus').textContent = 'Error saving';
|
|
294
|
+
} finally {
|
|
295
|
+
saveBtn.disabled = false;
|
|
296
|
+
saveBtn.innerHTML = originalText;
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
async showTemplateSelection() {
|
|
301
|
+
const modal = new bootstrap.Modal(document.getElementById('templateSelectionModal'));
|
|
302
|
+
const templateList = document.getElementById('templateList');
|
|
303
|
+
|
|
304
|
+
// Load templates
|
|
305
|
+
try {
|
|
306
|
+
const response = await fetch(this.config.apiUrls.templates);
|
|
307
|
+
const data = await response.json();
|
|
308
|
+
|
|
309
|
+
if (data.success && data.templates.length > 0) {
|
|
310
|
+
// Group templates by category
|
|
311
|
+
const grouped = {};
|
|
312
|
+
data.templates.forEach(template => {
|
|
313
|
+
if (!grouped[template.category_display]) {
|
|
314
|
+
grouped[template.category_display] = [];
|
|
315
|
+
}
|
|
316
|
+
grouped[template.category_display].push(template);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// Render templates
|
|
320
|
+
let html = '';
|
|
321
|
+
for (const [category, templates] of Object.entries(grouped)) {
|
|
322
|
+
html += `<div class="col-12"><h6 class="text-muted">${this.escapeHtml(String(category ?? ''))}</h6></div>`;
|
|
323
|
+
templates.forEach(template => {
|
|
324
|
+
html += `
|
|
325
|
+
<div class="col-md-4">
|
|
326
|
+
<div class="card template-card h-100" style="cursor: pointer;" data-template-id="${template.id}">
|
|
327
|
+
<div class="card-body">
|
|
328
|
+
<h6 class="card-title">${this.escapeHtml(template.name)}</h6>
|
|
329
|
+
<p class="card-text small text-muted">${this.escapeHtml(template.description)}</p>
|
|
330
|
+
<div class="d-flex justify-content-between align-items-center">
|
|
331
|
+
<small class="text-muted">
|
|
332
|
+
<i class="bi bi-people"></i> Used ${this.escapeHtml(String(template.usage_count ?? 0))} times
|
|
333
|
+
</small>
|
|
334
|
+
<button class="btn btn-sm btn-primary">Use Template</button>
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
338
|
+
</div>
|
|
339
|
+
`;
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
templateList.innerHTML = html;
|
|
343
|
+
|
|
344
|
+
// Add click handlers
|
|
345
|
+
document.querySelectorAll('.template-card').forEach(card => {
|
|
346
|
+
card.addEventListener('click', () => {
|
|
347
|
+
const templateId = card.dataset.templateId;
|
|
348
|
+
this.loadTemplate(templateId);
|
|
349
|
+
modal.hide();
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
} else {
|
|
353
|
+
templateList.innerHTML = `
|
|
354
|
+
<div class="col-12 text-center py-5">
|
|
355
|
+
<p class="text-muted">No templates available</p>
|
|
356
|
+
</div>
|
|
357
|
+
`;
|
|
358
|
+
}
|
|
359
|
+
} catch (error) {
|
|
360
|
+
console.error('Error loading templates:', error);
|
|
361
|
+
templateList.innerHTML = `
|
|
362
|
+
<div class="col-12 text-center py-5">
|
|
363
|
+
<p class="text-danger">Failed to load templates</p>
|
|
364
|
+
</div>
|
|
365
|
+
`;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Handle "Start with Blank Form" button
|
|
369
|
+
document.getElementById('btnStartBlank').onclick = () => {
|
|
370
|
+
modal.hide();
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
modal.show();
|
|
374
|
+
},
|
|
375
|
+
|
|
376
|
+
async loadTemplate(templateId) {
|
|
377
|
+
try {
|
|
378
|
+
const url = this.config.apiUrls.loadTemplate.replace('{id}', templateId);
|
|
379
|
+
const response = await fetch(url);
|
|
380
|
+
const data = await response.json();
|
|
381
|
+
|
|
382
|
+
if (data.success && data.template_data) {
|
|
383
|
+
const templateData = data.template_data;
|
|
384
|
+
|
|
385
|
+
// Populate form settings
|
|
386
|
+
document.getElementById('formName').value = templateData.name || '';
|
|
387
|
+
document.getElementById('formSlug').value = templateData.slug || '';
|
|
388
|
+
document.getElementById('formDescription').value = templateData.description || '';
|
|
389
|
+
document.getElementById('formInstructions').value = templateData.instructions || '';
|
|
390
|
+
document.getElementById('formIsActive').checked = templateData.is_active !== false;
|
|
391
|
+
document.getElementById('formRequiresLogin').checked = templateData.requires_login !== false;
|
|
392
|
+
document.getElementById('formAllowDraft').checked = templateData.allow_save_draft !== false;
|
|
393
|
+
document.getElementById('formAllowWithdrawal').checked = templateData.allow_withdrawal !== false;
|
|
394
|
+
|
|
395
|
+
// Load fields
|
|
396
|
+
this.fields = templateData.fields || [];
|
|
397
|
+
this.store.seedFieldIdCounterFromFields(this.fields);
|
|
398
|
+
this.renderCanvas();
|
|
399
|
+
this.updatePreview();
|
|
400
|
+
|
|
401
|
+
// Show success message
|
|
402
|
+
alert('Template loaded successfully! You can now customize the form.');
|
|
403
|
+
} else {
|
|
404
|
+
throw new Error('Invalid template data');
|
|
405
|
+
}
|
|
406
|
+
} catch (error) {
|
|
407
|
+
console.error('Error loading template:', error);
|
|
408
|
+
alert('Failed to load template: ' + error.message);
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
};
|