django-forms-workflows 0.76.5__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.5 → django_forms_workflows-0.76.6}/PKG-INFO +1 -1
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_backends.py +8 -0
- django_forms_workflows-0.76.5/django_forms_workflows/static/django_forms_workflows/js/form-builder.js → django_forms_workflows-0.76.6/django_forms_workflows/static/django_forms_workflows/js/form-builder-canvas.js +72 -185
- django_forms_workflows-0.76.6/django_forms_workflows/static/django_forms_workflows/js/form-builder.js +129 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/workflow-builder.js +16 -19
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/workflow_builder.html +3 -2
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/pyproject.toml +1 -1
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/CHANGELOG.md +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/LICENSE +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/README.md +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/__init__.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/admin.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/api_urls.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/api_views.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/apps.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/callback_registry.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/conditions.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/context_processors.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/__init__.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/base.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/database_source.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/ldap_source.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/user_source.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/diff_views.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/email_backends/__init__.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/email_backends/gmail_api.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/form_builder_urls.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/form_builder_views.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/forms.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/__init__.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/api_handler.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/base.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/database_handler.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/email_handler.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/executor.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/file_handler.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/ldap_handler.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/history.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/ldap_backend.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/create_default_templates.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/pull_forms.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/push_forms.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_farm_demo.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_pcn_form.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_prefill_sources.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/sync_ldap_profiles.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/sync_ldap_users.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/test_db_connection.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0001_initial.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0003_postsubmissionaction.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0004_formtemplate.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0005_advanced_conditional_logic.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0007_add_userprofile_ldap_enhancements.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0008_add_file_workflow_models.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0009_add_formfield_readonly.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0010_add_prefillsource_template_fields.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0012_add_approval_step_fields.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0013_add_database_query_key.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0014_add_form_category.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0015_add_workflowstage_staged_approvals.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0016_add_pdf_generation.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0017_add_notification_batching.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0018_add_form_category_parent.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0019_add_ldap_group_profile.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0020_add_bulk_export_field.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0022_add_bulk_pdf_export.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0023_add_performance_indexes.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0024_add_allow_resubmit.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0025_workflowstage_approve_label.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0026_alter_formfield_width.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0027_formsubmission_form_data_gin.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0028_workflowstagegroupconfig.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0030_formfield_phone_type.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0031_sub_workflows.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0032_approved_pending_detached_sub_workflow.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0033_add_reject_parent_to_subworkflowdefinition.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0034_add_notificationlog.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0035_migrate_prefill_source_strings.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0036_add_workflowstage_auto_created.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0037_migrate_flat_workflows_to_staged.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0039_update_help_text.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0040_migrate_deprecated_features.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0041_remove_deprecated_fields.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0042_add_sub_workflow_section_label.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0043_fix_form_data_decimal_encoding.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0044_remove_subworkflowinstance_label.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0045_stageapprovalgroup_workflow_name_label.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0046_workflow_definition_one_to_many.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0047_add_hide_approval_history.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0048_workflowdefinition_trigger_conditions_and_more.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0049_formfield_multifile_type.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0050_workflowdefinition_collapse_parallel_stages.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0051_formdefinition_is_listed.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0053_stageformfieldnotification_static_emails.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0055_add_send_back.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0056_calculated_formula_spreadsheet.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0057_add_currency_field_type.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0059_add_multiselect_list_field_type.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0062_add_batch_import_to_formdefinition.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0063_formdefinition_api_enabled_apitoken.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0064_add_reviewer_groups.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0065_workflownotification.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0066_add_notify_submitter_to_workflownotification.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0067_migrate_legacy_notify_flags.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0068_drop_legacy_notify_fields.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0069_add_signature_field_type.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0070_workflowstage_allow_edit_form_data.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0071_alter_pendingnotification_notification_type.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0072_add_change_history.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0074_add_notification_rule.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0075_migrate_to_notification_rules.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0076_update_notification_event_choices.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0077_drop_legacy_notification_models.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0078_allow_anonymous_submissions.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0079_webhookendpoint_webhookdeliverylog.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0081_add_success_page_fields.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0082_add_document_template_model.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0083_workflowdefinition_start_trigger.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0084_add_shared_option_list.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0085_add_payment_system.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0086_add_embed_enabled.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0087_notificationrule_use_triggering_stage.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0088_notificationrule_body_template_and_events.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0089_workflowstage_hide_comment_field.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0090_alter_stageapprovalgroup_options_and_more.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0091_add_uuid_fields.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0092_add_user_notification_preference.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0093_normalize_conditional_operators.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0095_notificationrule_cc_fields.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0096_notificationlog_cc_bcc_emails.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0097_notificationlog_delivery_reconciliation.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/__init__.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/models.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/__init__.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/base.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/registry.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/stripe_provider.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/views.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/reporting_views.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/signals.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_urls.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_views.py +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui.css +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/css/forms.css +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/dfw-embed.js +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/form-builder-api.js +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/form-builder-property-editor.js +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/form-enhancements.js +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/payment-stripe.js +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/js/signature-pad.js +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sync_api.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sync_views.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/tasks.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/_sync_diff.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/diff_forms.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/form_builder.html +0 -0
- {django_forms_workflows-0.76.5 → 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.5 → 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.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/sync_import.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/sync_pull.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/admin/django_forms_workflows/sync_push.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/_category_node.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/_field_value.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/_form_data_rows.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/analytics_dashboard.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/api/docs.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/approval_inbox.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/approve.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/base.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/batch_import_result.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/completed_approvals.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/discard_draft_confirm.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/embed_base.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/embed_success.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_categories.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_embed.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_list.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_submit.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/my_submissions.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/notification_preferences.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/payment_collect.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/payment_error.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/public_submission_confirmation.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/rate_limited.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/reassign_task.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/resubmit_confirm.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/sso/login.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/sub_workflow_detail.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_bulk_pdf.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_detail.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_pdf.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_success.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/withdraw_confirm.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_notification.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_reminder.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_request.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/email_styles.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/escalation_notification.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/notification_digest.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/rejection_notification.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/submission_notification.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/registration/login.html +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templatetags/__init__.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templatetags/forms_workflows_tags.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/urls.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/utils.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/views.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/workflow_builder_views.py +0 -0
- {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/workflow_engine.py +0 -0
|
@@ -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
|
"""
|
|
@@ -1,65 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Canvas and drag-drop controller for the Form Builder: the field palette,
|
|
3
|
+
* the single-step and multi-step canvases (SortableJS wiring, native
|
|
4
|
+
* HTML5 drag-drop for palette-to-canvas drops), field CRUD, canvas/step
|
|
5
|
+
* rendering, and the field context menu.
|
|
3
6
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
7
|
+
* Mixed onto FormBuilder.prototype in form-builder.js (Object.assign), not a
|
|
8
|
+
* standalone class of its own - these methods read/write `this.fields`/
|
|
9
|
+
* `this.formSteps` (proxied onto `this.store`), plus a number of
|
|
10
|
+
* FormBuilder-owned DOM/drag-state fields (`this.draggingFieldType`,
|
|
11
|
+
* `this.dragPlaceholder`, `this.contextMenu`, `this.fieldTypes`/
|
|
12
|
+
* `this.fieldTypeCategories`), and call back into
|
|
13
|
+
* pushUndo()/updatePreview()/saveForm()/editField(), which still live on
|
|
14
|
+
* historyMethods/apiMethods/propertyEditorMethods respectively - all mixed
|
|
15
|
+
* onto the same FormBuilder instance, so `this.*` resolves regardless of
|
|
16
|
+
* which module a given method came from.
|
|
6
17
|
*/
|
|
7
|
-
|
|
8
|
-
import { historyMethods } from './form-builder-history.js';
|
|
9
|
-
import { apiMethods } from './form-builder-api.js';
|
|
10
|
-
import { propertyEditorMethods } from './form-builder-property-editor.js';
|
|
11
|
-
import { createBuilderStore } from './form-builder-store.js';
|
|
12
|
-
|
|
13
|
-
export class FormBuilder {
|
|
14
|
-
constructor(config) {
|
|
15
|
-
this.config = config;
|
|
16
|
-
this.store = createBuilderStore();
|
|
17
|
-
this.fields = [];
|
|
18
|
-
this.currentFieldIndex = null;
|
|
19
|
-
this.fieldIdCounter = 1;
|
|
20
|
-
this.previewTimeout = null;
|
|
21
|
-
this.draggingFieldType = null; // Track field type being dragged from palette
|
|
22
|
-
this.dragPlaceholder = null; // Track the placeholder element
|
|
23
|
-
this.isNewField = false; // Track if editing a newly created field
|
|
24
|
-
this.formSteps = []; // Track multi-step configuration
|
|
25
|
-
this.contextMenu = null; // Track context menu element
|
|
26
|
-
this.undoStack = []; // Undo history
|
|
27
|
-
this.redoStack = []; // Redo history
|
|
28
|
-
this.maxUndoSteps = 50;
|
|
29
|
-
|
|
30
|
-
this.init();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// fields/formSteps live on this.store now (single source of truth for
|
|
34
|
-
// history's undo/redo snapshots); these proxy the existing this.fields/
|
|
35
|
-
// this.formSteps call sites throughout this file so they don't all need
|
|
36
|
-
// to change in this pass.
|
|
37
|
-
get fields() { return this.store.fields; }
|
|
38
|
-
set fields(value) { this.store.setFields(value); }
|
|
39
|
-
|
|
40
|
-
get formSteps() { return this.store.formSteps; }
|
|
41
|
-
set formSteps(value) { this.store.setFormSteps(value); }
|
|
42
|
-
|
|
43
|
-
get fieldIdCounter() { return this.store.fieldIdCounter; }
|
|
44
|
-
set fieldIdCounter(value) { this.store.fieldIdCounter = value; }
|
|
45
|
-
|
|
46
|
-
init() {
|
|
47
|
-
this.setupFieldPalette();
|
|
48
|
-
this.setupCanvas();
|
|
49
|
-
this.setupEventListeners();
|
|
50
|
-
|
|
51
|
-
// Load existing form if editing
|
|
52
|
-
if (!this.config.isNew && this.config.formId && this.config.apiUrls.load) {
|
|
53
|
-
this.loadForm();
|
|
54
|
-
} else if (this.config.isNew) {
|
|
55
|
-
// Show template selection modal for new forms
|
|
56
|
-
this.showTemplateSelection();
|
|
57
|
-
} else {
|
|
58
|
-
// Generate initial preview for forms without fields
|
|
59
|
-
this.updatePreview();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
18
|
+
export const canvasMethods = {
|
|
63
19
|
setupFieldPalette() {
|
|
64
20
|
const palette = document.getElementById('fieldPalette');
|
|
65
21
|
|
|
@@ -174,8 +130,8 @@ export class FormBuilder {
|
|
|
174
130
|
this.cleanupDragPlaceholder();
|
|
175
131
|
}
|
|
176
132
|
});
|
|
177
|
-
}
|
|
178
|
-
|
|
133
|
+
},
|
|
134
|
+
|
|
179
135
|
renderPalette(filter) {
|
|
180
136
|
const palette = document.getElementById('fieldPalette');
|
|
181
137
|
// Remove all items but keep the search (which is in the panel-header)
|
|
@@ -208,7 +164,7 @@ export class FormBuilder {
|
|
|
208
164
|
palette.appendChild(item);
|
|
209
165
|
});
|
|
210
166
|
});
|
|
211
|
-
}
|
|
167
|
+
},
|
|
212
168
|
|
|
213
169
|
setupCanvas() {
|
|
214
170
|
const canvas = document.getElementById('formCanvas');
|
|
@@ -244,6 +200,7 @@ export class FormBuilder {
|
|
|
244
200
|
}
|
|
245
201
|
} else {
|
|
246
202
|
// Existing field moved - update order
|
|
203
|
+
this.pushUndo();
|
|
247
204
|
const movedField = this.fields.splice(evt.oldIndex, 1)[0];
|
|
248
205
|
this.fields.splice(evt.newIndex, 0, movedField);
|
|
249
206
|
this.updateFieldOrders();
|
|
@@ -252,6 +209,7 @@ export class FormBuilder {
|
|
|
252
209
|
},
|
|
253
210
|
onUpdate: (evt) => {
|
|
254
211
|
// Field reordered within canvas
|
|
212
|
+
this.pushUndo();
|
|
255
213
|
const movedField = this.fields.splice(evt.oldIndex, 1)[0];
|
|
256
214
|
this.fields.splice(evt.newIndex, 0, movedField);
|
|
257
215
|
this.updateFieldOrders();
|
|
@@ -262,7 +220,7 @@ export class FormBuilder {
|
|
|
262
220
|
canvas.classList.remove('dragging');
|
|
263
221
|
}
|
|
264
222
|
});
|
|
265
|
-
|
|
223
|
+
|
|
266
224
|
// Allow dropping from palette with visual feedback
|
|
267
225
|
canvas.addEventListener('dragover', (e) => {
|
|
268
226
|
e.preventDefault();
|
|
@@ -328,7 +286,7 @@ export class FormBuilder {
|
|
|
328
286
|
|
|
329
287
|
this.cleanupDragPlaceholder();
|
|
330
288
|
});
|
|
331
|
-
}
|
|
289
|
+
},
|
|
332
290
|
|
|
333
291
|
getDragAfterElement(container, y) {
|
|
334
292
|
const draggableElements = [...container.querySelectorAll('.canvas-field:not(.drag-placeholder):not(.sortable-drag)')];
|
|
@@ -343,7 +301,7 @@ export class FormBuilder {
|
|
|
343
301
|
return closest;
|
|
344
302
|
}
|
|
345
303
|
}, { offset: Number.NEGATIVE_INFINITY }).element;
|
|
346
|
-
}
|
|
304
|
+
},
|
|
347
305
|
|
|
348
306
|
cleanupDragPlaceholder() {
|
|
349
307
|
// Remove the drag placeholder and clean up canvas state
|
|
@@ -355,15 +313,19 @@ export class FormBuilder {
|
|
|
355
313
|
if (canvas) {
|
|
356
314
|
canvas.classList.remove('dragging');
|
|
357
315
|
}
|
|
358
|
-
}
|
|
316
|
+
},
|
|
359
317
|
|
|
360
318
|
addFieldAtPosition(fieldType, position) {
|
|
361
319
|
this.pushUndo();
|
|
320
|
+
// field_name must be read before nextFieldId() advances the counter,
|
|
321
|
+
// so the id and the name it's derived from carry the same number -
|
|
322
|
+
// matching handleFieldDroppedToStep's order, which already does this.
|
|
323
|
+
const fieldName = this.getDefaultName(fieldType);
|
|
362
324
|
const field = {
|
|
363
|
-
id:
|
|
325
|
+
id: this.store.nextFieldId('new'),
|
|
364
326
|
order: position + 1,
|
|
365
327
|
field_label: this.getDefaultLabel(fieldType),
|
|
366
|
-
field_name:
|
|
328
|
+
field_name: fieldName,
|
|
367
329
|
field_type: fieldType,
|
|
368
330
|
required: false,
|
|
369
331
|
help_text: '',
|
|
@@ -397,82 +359,18 @@ export class FormBuilder {
|
|
|
397
359
|
|
|
398
360
|
// Automatically open property editor for new field
|
|
399
361
|
this.editField(insertIndex, true); // true = isNew
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
setupEventListeners() {
|
|
403
|
-
// Save button
|
|
404
|
-
document.getElementById('btnSave').addEventListener('click', () => {
|
|
405
|
-
this.saveForm();
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
// Cancel button
|
|
409
|
-
document.getElementById('btnCancel').addEventListener('click', () => {
|
|
410
|
-
if (confirm('Are you sure you want to cancel? Unsaved changes will be lost.')) {
|
|
411
|
-
window.location.href = '/admin/django_forms_workflows/formdefinition/';
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
// Save field button in modal
|
|
416
|
-
document.getElementById('btnSaveField').addEventListener('click', () => {
|
|
417
|
-
this.saveFieldProperties();
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
// Auto-generate slug from name
|
|
421
|
-
document.getElementById('formName').addEventListener('input', (e) => {
|
|
422
|
-
const slug = e.target.value
|
|
423
|
-
.toLowerCase()
|
|
424
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
425
|
-
.replace(/^-+|-+$/g, '');
|
|
426
|
-
document.getElementById('formSlug').value = slug;
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
// Keyboard shortcuts
|
|
430
|
-
document.addEventListener('keydown', (e) => {
|
|
431
|
-
// Ctrl+S / Cmd+S = Save
|
|
432
|
-
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
|
433
|
-
e.preventDefault();
|
|
434
|
-
this.saveForm();
|
|
435
|
-
}
|
|
436
|
-
// Ctrl+Z / Cmd+Z = Undo
|
|
437
|
-
if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {
|
|
438
|
-
e.preventDefault();
|
|
439
|
-
this.undo();
|
|
440
|
-
}
|
|
441
|
-
// Ctrl+Shift+Z / Cmd+Shift+Z = Redo
|
|
442
|
-
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'z') {
|
|
443
|
-
e.preventDefault();
|
|
444
|
-
this.redo();
|
|
445
|
-
}
|
|
446
|
-
});
|
|
362
|
+
},
|
|
447
363
|
|
|
448
|
-
// Multi-step toggle
|
|
449
|
-
const multiStepCheckbox = document.getElementById('formEnableMultiStep');
|
|
450
|
-
|
|
451
|
-
if (multiStepCheckbox) {
|
|
452
|
-
multiStepCheckbox.addEventListener('change', (e) => {
|
|
453
|
-
this.toggleMultiStepMode(e.target.checked);
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// Add step tab button
|
|
458
|
-
const addStepTabBtn = document.getElementById('btnAddStepTab');
|
|
459
|
-
if (addStepTabBtn) {
|
|
460
|
-
addStepTabBtn.addEventListener('click', () => {
|
|
461
|
-
this.addStepTab();
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
|
|
466
364
|
addField(fieldType) {
|
|
467
365
|
// Add field at the end
|
|
468
366
|
this.addFieldAtPosition(fieldType, this.fields.length);
|
|
469
|
-
}
|
|
367
|
+
},
|
|
470
368
|
|
|
471
369
|
duplicateField(index) {
|
|
472
370
|
this.pushUndo();
|
|
473
371
|
const original = this.fields[index];
|
|
474
372
|
const clone = JSON.parse(JSON.stringify(original));
|
|
475
|
-
clone.id =
|
|
373
|
+
clone.id = this.store.nextFieldId('new');
|
|
476
374
|
clone.field_name = original.field_name + '_copy';
|
|
477
375
|
clone.field_label = original.field_label + ' (Copy)';
|
|
478
376
|
clone.order = index + 2;
|
|
@@ -499,7 +397,7 @@ export class FormBuilder {
|
|
|
499
397
|
this.renderCanvas();
|
|
500
398
|
}
|
|
501
399
|
this.updatePreview();
|
|
502
|
-
}
|
|
400
|
+
},
|
|
503
401
|
|
|
504
402
|
getDefaultLabel(fieldType) {
|
|
505
403
|
const labels = {
|
|
@@ -536,12 +434,12 @@ export class FormBuilder {
|
|
|
536
434
|
'slider': 'Slider'
|
|
537
435
|
};
|
|
538
436
|
return labels[fieldType] || 'Field';
|
|
539
|
-
}
|
|
540
|
-
|
|
437
|
+
},
|
|
438
|
+
|
|
541
439
|
getDefaultName(fieldType) {
|
|
542
440
|
return fieldType + '_' + this.fieldIdCounter;
|
|
543
|
-
}
|
|
544
|
-
|
|
441
|
+
},
|
|
442
|
+
|
|
545
443
|
renderCanvas() {
|
|
546
444
|
const canvas = document.getElementById('formCanvas');
|
|
547
445
|
|
|
@@ -574,8 +472,8 @@ export class FormBuilder {
|
|
|
574
472
|
canvas.appendChild(dropZone);
|
|
575
473
|
|
|
576
474
|
document.getElementById('fieldCount').textContent = `${this.fields.length} field${this.fields.length !== 1 ? 's' : ''}`;
|
|
577
|
-
}
|
|
578
|
-
|
|
475
|
+
},
|
|
476
|
+
|
|
579
477
|
createFieldElement(field, index) {
|
|
580
478
|
const div = document.createElement('div');
|
|
581
479
|
div.dataset.index = index;
|
|
@@ -609,8 +507,8 @@ export class FormBuilder {
|
|
|
609
507
|
// Regular field
|
|
610
508
|
div.className = 'canvas-field field-item';
|
|
611
509
|
const requiredBadge = field.required ? '<span class="badge bg-danger ms-1" style="font-size: 0.65rem; padding: 0.15rem 0.35rem;">REQ</span>' : '';
|
|
612
|
-
const fieldInfo = `<span class="text-muted" style="font-size: 0.75rem;">${field.field_name}</span>`;
|
|
613
|
-
const widthBadge = field.width && field.width !== 'full' ? `<span class="badge bg-secondary ms-1" style="font-size: 0.6rem;">${field.width}</span>` : '';
|
|
510
|
+
const fieldInfo = `<span class="text-muted" style="font-size: 0.75rem;">${this.escapeHtml(field.field_name)}</span>`;
|
|
511
|
+
const widthBadge = field.width && field.width !== 'full' ? `<span class="badge bg-secondary ms-1" style="font-size: 0.6rem;">${this.escapeHtml(field.width)}</span>` : '';
|
|
614
512
|
|
|
615
513
|
div.innerHTML = `
|
|
616
514
|
<div class="field-header field-drag-handle" style="cursor: move;">
|
|
@@ -621,7 +519,7 @@ export class FormBuilder {
|
|
|
621
519
|
<span class="ms-2">${fieldInfo}</span>
|
|
622
520
|
</div>
|
|
623
521
|
<div class="field-actions">
|
|
624
|
-
<span class="field-type-badge">${field.field_type}</span>
|
|
522
|
+
<span class="field-type-badge">${this.escapeHtml(field.field_type)}</span>
|
|
625
523
|
<button class="btn btn-sm btn-outline-primary btn-field-action" onclick="formBuilder.editField(${index})" title="Edit field">
|
|
626
524
|
<i class="bi bi-pencil"></i>
|
|
627
525
|
</button>
|
|
@@ -643,8 +541,8 @@ export class FormBuilder {
|
|
|
643
541
|
});
|
|
644
542
|
|
|
645
543
|
return div;
|
|
646
|
-
}
|
|
647
|
-
|
|
544
|
+
},
|
|
545
|
+
|
|
648
546
|
toggleMultiStepMode(enabled) {
|
|
649
547
|
const singleCanvas = document.getElementById('singleStepCanvas');
|
|
650
548
|
const multiCanvas = document.getElementById('multiStepCanvas');
|
|
@@ -679,7 +577,7 @@ export class FormBuilder {
|
|
|
679
577
|
// Move all fields back to main canvas
|
|
680
578
|
this.moveAllFieldsToMainCanvas();
|
|
681
579
|
}
|
|
682
|
-
}
|
|
580
|
+
},
|
|
683
581
|
|
|
684
582
|
renderStepTabs() {
|
|
685
583
|
const contentContainer = document.getElementById('stepTabContent');
|
|
@@ -731,7 +629,7 @@ export class FormBuilder {
|
|
|
731
629
|
|
|
732
630
|
// Render fields in their respective steps
|
|
733
631
|
this.renderFieldsInSteps();
|
|
734
|
-
}
|
|
632
|
+
},
|
|
735
633
|
|
|
736
634
|
setupStepCanvasSortable(stepIndex) {
|
|
737
635
|
const canvas = document.getElementById(`step-canvas-${stepIndex}`);
|
|
@@ -773,7 +671,7 @@ export class FormBuilder {
|
|
|
773
671
|
// Field was moved to another step, handled by onAdd of target
|
|
774
672
|
}
|
|
775
673
|
});
|
|
776
|
-
}
|
|
674
|
+
},
|
|
777
675
|
|
|
778
676
|
setupStepCanvasDragDrop(stepIndex) {
|
|
779
677
|
const canvas = document.getElementById(`step-canvas-${stepIndex}`);
|
|
@@ -802,7 +700,7 @@ export class FormBuilder {
|
|
|
802
700
|
this.handleFieldDroppedToStep(fieldType, stepIndex);
|
|
803
701
|
}
|
|
804
702
|
});
|
|
805
|
-
}
|
|
703
|
+
},
|
|
806
704
|
|
|
807
705
|
handleFieldDroppedToStep(fieldType, stepIndex, position) {
|
|
808
706
|
// Create a new field when dropped from palette
|
|
@@ -813,7 +711,7 @@ export class FormBuilder {
|
|
|
813
711
|
|
|
814
712
|
const fieldName = this.getDefaultName(fieldType);
|
|
815
713
|
const newField = {
|
|
816
|
-
id:
|
|
714
|
+
id: this.store.nextFieldId('new'),
|
|
817
715
|
field_type: fieldType,
|
|
818
716
|
field_name: fieldName,
|
|
819
717
|
field_label: this.getDefaultLabel(fieldType),
|
|
@@ -870,7 +768,7 @@ export class FormBuilder {
|
|
|
870
768
|
// Automatically open property editor for new field
|
|
871
769
|
const fieldIndex = this.fields.findIndex(f => f.field_name === fieldName);
|
|
872
770
|
this.editField(fieldIndex, true); // true = isNew
|
|
873
|
-
}
|
|
771
|
+
},
|
|
874
772
|
|
|
875
773
|
addStepTab() {
|
|
876
774
|
const newIndex = this.formSteps.length;
|
|
@@ -879,7 +777,7 @@ export class FormBuilder {
|
|
|
879
777
|
fields: []
|
|
880
778
|
});
|
|
881
779
|
this.renderStepTabs();
|
|
882
|
-
}
|
|
780
|
+
},
|
|
883
781
|
|
|
884
782
|
removeStepTab(index) {
|
|
885
783
|
if (this.formSteps.length === 1) {
|
|
@@ -898,7 +796,7 @@ export class FormBuilder {
|
|
|
898
796
|
// Re-render
|
|
899
797
|
this.renderStepTabs();
|
|
900
798
|
}
|
|
901
|
-
}
|
|
799
|
+
},
|
|
902
800
|
|
|
903
801
|
updateStepTitle(index, newTitle) {
|
|
904
802
|
if (this.formSteps[index]) {
|
|
@@ -911,7 +809,7 @@ export class FormBuilder {
|
|
|
911
809
|
tab.innerHTML = `${icon} ${this.escapeHtml(newTitle)} ${deleteBtn}`;
|
|
912
810
|
}
|
|
913
811
|
}
|
|
914
|
-
}
|
|
812
|
+
},
|
|
915
813
|
|
|
916
814
|
handleFieldMovedToStep(fieldElement, stepIndex) {
|
|
917
815
|
const fieldIndex = parseInt(fieldElement.dataset.fieldIndex);
|
|
@@ -921,13 +819,6 @@ export class FormBuilder {
|
|
|
921
819
|
|
|
922
820
|
this.pushUndo();
|
|
923
821
|
|
|
924
|
-
// Find which step the field was in before
|
|
925
|
-
let sourceStepIndex = -1;
|
|
926
|
-
this.formSteps.forEach((step, idx) => {
|
|
927
|
-
if (step.fields && step.fields.includes(field.field_name)) {
|
|
928
|
-
sourceStepIndex = idx;
|
|
929
|
-
}
|
|
930
|
-
});
|
|
931
822
|
|
|
932
823
|
// Remove field from all steps
|
|
933
824
|
this.formSteps.forEach(step => {
|
|
@@ -963,7 +854,7 @@ export class FormBuilder {
|
|
|
963
854
|
|
|
964
855
|
// Update preview
|
|
965
856
|
this.updatePreview();
|
|
966
|
-
}
|
|
857
|
+
},
|
|
967
858
|
|
|
968
859
|
updateFieldOrderInStep(stepIndex) {
|
|
969
860
|
const canvas = document.getElementById(`step-canvas-${stepIndex}`);
|
|
@@ -991,7 +882,7 @@ export class FormBuilder {
|
|
|
991
882
|
this.updateFieldOrderFromSteps();
|
|
992
883
|
this.renderFieldsInSteps();
|
|
993
884
|
this.updatePreview();
|
|
994
|
-
}
|
|
885
|
+
},
|
|
995
886
|
|
|
996
887
|
updateStepFieldCount(stepIndex) {
|
|
997
888
|
const panel = document.getElementById(`step-panel-${stepIndex}`);
|
|
@@ -1002,7 +893,7 @@ export class FormBuilder {
|
|
|
1002
893
|
badge.textContent = `${count} fields`;
|
|
1003
894
|
}
|
|
1004
895
|
}
|
|
1005
|
-
}
|
|
896
|
+
},
|
|
1006
897
|
|
|
1007
898
|
organizeFieldsIntoSteps() {
|
|
1008
899
|
// Assign all fields to their respective steps based on formSteps configuration
|
|
@@ -1026,14 +917,14 @@ export class FormBuilder {
|
|
|
1026
917
|
});
|
|
1027
918
|
|
|
1028
919
|
this.renderFieldsInSteps();
|
|
1029
|
-
}
|
|
920
|
+
},
|
|
1030
921
|
|
|
1031
922
|
renderFieldsInSteps() {
|
|
1032
923
|
// Render fields in their respective steps
|
|
1033
924
|
this.formSteps.forEach((step, stepIndex) => {
|
|
1034
925
|
this.renderSingleStep(stepIndex);
|
|
1035
926
|
});
|
|
1036
|
-
}
|
|
927
|
+
},
|
|
1037
928
|
|
|
1038
929
|
renderSingleStep(stepIndex) {
|
|
1039
930
|
const step = this.formSteps[stepIndex];
|
|
@@ -1062,7 +953,7 @@ export class FormBuilder {
|
|
|
1062
953
|
});
|
|
1063
954
|
|
|
1064
955
|
this.updateStepFieldCount(stepIndex);
|
|
1065
|
-
}
|
|
956
|
+
},
|
|
1066
957
|
|
|
1067
958
|
moveAllFieldsToMainCanvas() {
|
|
1068
959
|
// Collect all fields from all steps
|
|
@@ -1076,7 +967,7 @@ export class FormBuilder {
|
|
|
1076
967
|
// Re-render main canvas
|
|
1077
968
|
this.renderCanvas();
|
|
1078
969
|
this.updatePreview();
|
|
1079
|
-
}
|
|
970
|
+
},
|
|
1080
971
|
|
|
1081
972
|
updateFieldOrderFromSteps() {
|
|
1082
973
|
// Update field order based on step order
|
|
@@ -1101,16 +992,14 @@ export class FormBuilder {
|
|
|
1101
992
|
this.fields.forEach((field, index) => {
|
|
1102
993
|
field.order = index;
|
|
1103
994
|
});
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
|
|
995
|
+
},
|
|
1107
996
|
|
|
1108
997
|
deleteField(index) {
|
|
1109
998
|
if (confirm('Are you sure you want to delete this field?')) {
|
|
1110
999
|
this.pushUndo();
|
|
1111
1000
|
this.deleteFieldSilently(index);
|
|
1112
1001
|
}
|
|
1113
|
-
}
|
|
1002
|
+
},
|
|
1114
1003
|
|
|
1115
1004
|
deleteFieldSilently(index) {
|
|
1116
1005
|
// Delete field without confirmation (used when canceling new field)
|
|
@@ -1142,19 +1031,19 @@ export class FormBuilder {
|
|
|
1142
1031
|
}
|
|
1143
1032
|
|
|
1144
1033
|
this.updatePreview();
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1034
|
+
},
|
|
1035
|
+
|
|
1147
1036
|
updateFieldOrders() {
|
|
1148
1037
|
this.fields.forEach((field, index) => {
|
|
1149
1038
|
field.order = index + 1;
|
|
1150
1039
|
});
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1040
|
+
},
|
|
1041
|
+
|
|
1153
1042
|
escapeHtml(text) {
|
|
1154
1043
|
const div = document.createElement('div');
|
|
1155
1044
|
div.textContent = text;
|
|
1156
1045
|
return div.innerHTML;
|
|
1157
|
-
}
|
|
1046
|
+
},
|
|
1158
1047
|
|
|
1159
1048
|
showFieldContextMenu(event, fieldIndex) {
|
|
1160
1049
|
// Only show context menu in multi-step mode
|
|
@@ -1194,14 +1083,14 @@ export class FormBuilder {
|
|
|
1194
1083
|
setTimeout(() => {
|
|
1195
1084
|
document.addEventListener('click', () => this.hideFieldContextMenu(), { once: true });
|
|
1196
1085
|
}, 10);
|
|
1197
|
-
}
|
|
1086
|
+
},
|
|
1198
1087
|
|
|
1199
1088
|
hideFieldContextMenu() {
|
|
1200
1089
|
if (this.contextMenu) {
|
|
1201
1090
|
this.contextMenu.remove();
|
|
1202
1091
|
this.contextMenu = null;
|
|
1203
1092
|
}
|
|
1204
|
-
}
|
|
1093
|
+
},
|
|
1205
1094
|
|
|
1206
1095
|
moveFieldToStepFromMenu(fieldIndex, targetStepIndex) {
|
|
1207
1096
|
this.hideFieldContextMenu();
|
|
@@ -1243,7 +1132,5 @@ export class FormBuilder {
|
|
|
1243
1132
|
|
|
1244
1133
|
// Update preview
|
|
1245
1134
|
this.updatePreview();
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
Object.assign(FormBuilder.prototype, historyMethods, apiMethods, propertyEditorMethods);
|
|
1135
|
+
},
|
|
1136
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual Form Builder
|
|
3
|
+
*
|
|
4
|
+
* Provides drag-and-drop interface for creating and editing forms
|
|
5
|
+
* without code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { historyMethods } from './form-builder-history.js';
|
|
9
|
+
import { apiMethods } from './form-builder-api.js';
|
|
10
|
+
import { propertyEditorMethods } from './form-builder-property-editor.js';
|
|
11
|
+
import { canvasMethods } from './form-builder-canvas.js';
|
|
12
|
+
import { createBuilderStore } from './form-builder-store.js';
|
|
13
|
+
|
|
14
|
+
export class FormBuilder {
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.store = createBuilderStore();
|
|
18
|
+
this.fields = [];
|
|
19
|
+
this.currentFieldIndex = null;
|
|
20
|
+
this.fieldIdCounter = 1;
|
|
21
|
+
this.previewTimeout = null;
|
|
22
|
+
this.draggingFieldType = null; // Track field type being dragged from palette
|
|
23
|
+
this.dragPlaceholder = null; // Track the placeholder element
|
|
24
|
+
this.isNewField = false; // Track if editing a newly created field
|
|
25
|
+
this.formSteps = []; // Track multi-step configuration
|
|
26
|
+
this.contextMenu = null; // Track context menu element
|
|
27
|
+
this.undoStack = []; // Undo history
|
|
28
|
+
this.redoStack = []; // Redo history
|
|
29
|
+
this.maxUndoSteps = 50;
|
|
30
|
+
|
|
31
|
+
this.init();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// fields/formSteps live on this.store now (single source of truth for
|
|
35
|
+
// history's undo/redo snapshots); these proxy the existing this.fields/
|
|
36
|
+
// this.formSteps call sites throughout this file so they don't all need
|
|
37
|
+
// to change in this pass.
|
|
38
|
+
get fields() { return this.store.fields; }
|
|
39
|
+
set fields(value) { this.store.setFields(value); }
|
|
40
|
+
|
|
41
|
+
get formSteps() { return this.store.formSteps; }
|
|
42
|
+
set formSteps(value) { this.store.setFormSteps(value); }
|
|
43
|
+
|
|
44
|
+
get fieldIdCounter() { return this.store.fieldIdCounter; }
|
|
45
|
+
set fieldIdCounter(value) { this.store.fieldIdCounter = value; }
|
|
46
|
+
|
|
47
|
+
init() {
|
|
48
|
+
this.setupFieldPalette();
|
|
49
|
+
this.setupCanvas();
|
|
50
|
+
this.setupEventListeners();
|
|
51
|
+
|
|
52
|
+
// Load existing form if editing
|
|
53
|
+
if (!this.config.isNew && this.config.formId && this.config.apiUrls.load) {
|
|
54
|
+
this.loadForm();
|
|
55
|
+
} else if (this.config.isNew) {
|
|
56
|
+
// Show template selection modal for new forms
|
|
57
|
+
this.showTemplateSelection();
|
|
58
|
+
} else {
|
|
59
|
+
// Generate initial preview for forms without fields
|
|
60
|
+
this.updatePreview();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setupEventListeners() {
|
|
65
|
+
// Save button
|
|
66
|
+
document.getElementById('btnSave').addEventListener('click', () => {
|
|
67
|
+
this.saveForm();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Cancel button
|
|
71
|
+
document.getElementById('btnCancel').addEventListener('click', () => {
|
|
72
|
+
if (confirm('Are you sure you want to cancel? Unsaved changes will be lost.')) {
|
|
73
|
+
window.location.href = '/admin/django_forms_workflows/formdefinition/';
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Save field button in modal
|
|
78
|
+
document.getElementById('btnSaveField').addEventListener('click', () => {
|
|
79
|
+
this.saveFieldProperties();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Auto-generate slug from name
|
|
83
|
+
document.getElementById('formName').addEventListener('input', (e) => {
|
|
84
|
+
const slug = e.target.value
|
|
85
|
+
.toLowerCase()
|
|
86
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
87
|
+
.replace(/^-+|-+$/g, '');
|
|
88
|
+
document.getElementById('formSlug').value = slug;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Keyboard shortcuts
|
|
92
|
+
document.addEventListener('keydown', (e) => {
|
|
93
|
+
// Ctrl+S / Cmd+S = Save
|
|
94
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
this.saveForm();
|
|
97
|
+
}
|
|
98
|
+
// Ctrl+Z / Cmd+Z = Undo
|
|
99
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
this.undo();
|
|
102
|
+
}
|
|
103
|
+
// Ctrl+Shift+Z / Cmd+Shift+Z = Redo
|
|
104
|
+
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'z') {
|
|
105
|
+
e.preventDefault();
|
|
106
|
+
this.redo();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Multi-step toggle
|
|
111
|
+
const multiStepCheckbox = document.getElementById('formEnableMultiStep');
|
|
112
|
+
|
|
113
|
+
if (multiStepCheckbox) {
|
|
114
|
+
multiStepCheckbox.addEventListener('change', (e) => {
|
|
115
|
+
this.toggleMultiStepMode(e.target.checked);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Add step tab button
|
|
120
|
+
const addStepTabBtn = document.getElementById('btnAddStepTab');
|
|
121
|
+
if (addStepTabBtn) {
|
|
122
|
+
addStepTabBtn.addEventListener('click', () => {
|
|
123
|
+
this.addStepTab();
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
Object.assign(FormBuilder.prototype, historyMethods, apiMethods, propertyEditorMethods, canvasMethods);
|