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.
Files changed (227) hide show
  1. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/PKG-INFO +1 -1
  2. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_backends.py +8 -0
  3. 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
  4. django_forms_workflows-0.76.6/django_forms_workflows/static/django_forms_workflows/js/form-builder.js +129 -0
  5. {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
  6. {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
  7. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/pyproject.toml +1 -1
  8. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/CHANGELOG.md +0 -0
  9. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/LICENSE +0 -0
  10. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/README.md +0 -0
  11. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/__init__.py +0 -0
  12. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/admin.py +0 -0
  13. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/api_urls.py +0 -0
  14. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/api_views.py +0 -0
  15. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/apps.py +0 -0
  16. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/callback_registry.py +0 -0
  17. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/conditions.py +0 -0
  18. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/context_processors.py +0 -0
  19. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/__init__.py +0 -0
  20. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/base.py +0 -0
  21. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/database_source.py +0 -0
  22. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/ldap_source.py +0 -0
  23. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/data_sources/user_source.py +0 -0
  24. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/diff_views.py +0 -0
  25. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/email_backends/__init__.py +0 -0
  26. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/email_backends/gmail_api.py +0 -0
  27. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/form_builder_urls.py +0 -0
  28. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/form_builder_views.py +0 -0
  29. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/forms.py +0 -0
  30. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/__init__.py +0 -0
  31. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/api_handler.py +0 -0
  32. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/base.py +0 -0
  33. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/database_handler.py +0 -0
  34. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/email_handler.py +0 -0
  35. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/executor.py +0 -0
  36. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/file_handler.py +0 -0
  37. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/handlers/ldap_handler.py +0 -0
  38. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/history.py +0 -0
  39. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/ldap_backend.py +0 -0
  40. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/create_default_templates.py +0 -0
  41. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/pull_forms.py +0 -0
  42. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/push_forms.py +0 -0
  43. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_farm_demo.py +0 -0
  44. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_pcn_form.py +0 -0
  45. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/seed_prefill_sources.py +0 -0
  46. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/sync_ldap_profiles.py +0 -0
  47. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/sync_ldap_users.py +0 -0
  48. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/management/commands/test_db_connection.py +0 -0
  49. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0001_initial.py +0 -0
  50. {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
  51. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0003_postsubmissionaction.py +0 -0
  52. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0004_formtemplate.py +0 -0
  53. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0005_advanced_conditional_logic.py +0 -0
  54. {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
  55. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0007_add_userprofile_ldap_enhancements.py +0 -0
  56. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0008_add_file_workflow_models.py +0 -0
  57. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0009_add_formfield_readonly.py +0 -0
  58. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0010_add_prefillsource_template_fields.py +0 -0
  59. {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
  60. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0012_add_approval_step_fields.py +0 -0
  61. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0013_add_database_query_key.py +0 -0
  62. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0014_add_form_category.py +0 -0
  63. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0015_add_workflowstage_staged_approvals.py +0 -0
  64. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0016_add_pdf_generation.py +0 -0
  65. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0017_add_notification_batching.py +0 -0
  66. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0018_add_form_category_parent.py +0 -0
  67. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0019_add_ldap_group_profile.py +0 -0
  68. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0020_add_bulk_export_field.py +0 -0
  69. {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
  70. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0022_add_bulk_pdf_export.py +0 -0
  71. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0023_add_performance_indexes.py +0 -0
  72. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0024_add_allow_resubmit.py +0 -0
  73. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0025_workflowstage_approve_label.py +0 -0
  74. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0026_alter_formfield_width.py +0 -0
  75. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0027_formsubmission_form_data_gin.py +0 -0
  76. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0028_workflowstagegroupconfig.py +0 -0
  77. {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
  78. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0030_formfield_phone_type.py +0 -0
  79. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0031_sub_workflows.py +0 -0
  80. {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
  81. {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
  82. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0034_add_notificationlog.py +0 -0
  83. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0035_migrate_prefill_source_strings.py +0 -0
  84. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0036_add_workflowstage_auto_created.py +0 -0
  85. {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
  86. {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
  87. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0039_update_help_text.py +0 -0
  88. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0040_migrate_deprecated_features.py +0 -0
  89. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0041_remove_deprecated_fields.py +0 -0
  90. {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
  91. {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
  92. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0044_remove_subworkflowinstance_label.py +0 -0
  93. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0045_stageapprovalgroup_workflow_name_label.py +0 -0
  94. {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
  95. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0047_add_hide_approval_history.py +0 -0
  96. {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
  97. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0049_formfield_multifile_type.py +0 -0
  98. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0050_workflowdefinition_collapse_parallel_stages.py +0 -0
  99. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0051_formdefinition_is_listed.py +0 -0
  100. {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
  101. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0053_stageformfieldnotification_static_emails.py +0 -0
  102. {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
  103. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0055_add_send_back.py +0 -0
  104. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0056_calculated_formula_spreadsheet.py +0 -0
  105. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0057_add_currency_field_type.py +0 -0
  106. {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
  107. {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
  108. {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
  109. {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
  110. {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
  111. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0063_formdefinition_api_enabled_apitoken.py +0 -0
  112. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0064_add_reviewer_groups.py +0 -0
  113. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0065_workflownotification.py +0 -0
  114. {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
  115. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0067_migrate_legacy_notify_flags.py +0 -0
  116. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0068_drop_legacy_notify_fields.py +0 -0
  117. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0069_add_signature_field_type.py +0 -0
  118. {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
  119. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0071_alter_pendingnotification_notification_type.py +0 -0
  120. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0072_add_change_history.py +0 -0
  121. {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
  122. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0074_add_notification_rule.py +0 -0
  123. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0075_migrate_to_notification_rules.py +0 -0
  124. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0076_update_notification_event_choices.py +0 -0
  125. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0077_drop_legacy_notification_models.py +0 -0
  126. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0078_allow_anonymous_submissions.py +0 -0
  127. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0079_webhookendpoint_webhookdeliverylog.py +0 -0
  128. {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
  129. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0081_add_success_page_fields.py +0 -0
  130. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0082_add_document_template_model.py +0 -0
  131. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0083_workflowdefinition_start_trigger.py +0 -0
  132. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0084_add_shared_option_list.py +0 -0
  133. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0085_add_payment_system.py +0 -0
  134. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0086_add_embed_enabled.py +0 -0
  135. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0087_notificationrule_use_triggering_stage.py +0 -0
  136. {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
  137. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0089_workflowstage_hide_comment_field.py +0 -0
  138. {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
  139. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0091_add_uuid_fields.py +0 -0
  140. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0092_add_user_notification_preference.py +0 -0
  141. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0093_normalize_conditional_operators.py +0 -0
  142. {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
  143. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0095_notificationrule_cc_fields.py +0 -0
  144. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0096_notificationlog_cc_bcc_emails.py +0 -0
  145. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/0097_notificationlog_delivery_reconciliation.py +0 -0
  146. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/migrations/__init__.py +0 -0
  147. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/models.py +0 -0
  148. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/__init__.py +0 -0
  149. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/base.py +0 -0
  150. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/registry.py +0 -0
  151. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/stripe_provider.py +0 -0
  152. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/payments/views.py +0 -0
  153. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/reporting_views.py +0 -0
  154. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/signals.py +0 -0
  155. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_urls.py +0 -0
  156. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sso_views.py +0 -0
  157. {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
  158. {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
  159. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/static/django_forms_workflows/css/forms.css +0 -0
  160. {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
  161. {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
  162. {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
  163. {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
  164. {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
  165. {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
  166. {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
  167. {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
  168. {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
  169. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sync_api.py +0 -0
  170. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/sync_views.py +0 -0
  171. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/tasks.py +0 -0
  172. {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
  173. {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
  174. {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
  175. {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
  176. {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
  177. {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
  178. {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
  179. {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
  180. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/_category_node.html +0 -0
  181. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/_field_value.html +0 -0
  182. {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
  183. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/analytics_dashboard.html +0 -0
  184. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/api/docs.html +0 -0
  185. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/approval_inbox.html +0 -0
  186. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/approve.html +0 -0
  187. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/base.html +0 -0
  188. {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
  189. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/completed_approvals.html +0 -0
  190. {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
  191. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/embed_base.html +0 -0
  192. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/embed_success.html +0 -0
  193. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_categories.html +0 -0
  194. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_embed.html +0 -0
  195. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_list.html +0 -0
  196. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/form_submit.html +0 -0
  197. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/my_submissions.html +0 -0
  198. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/notification_preferences.html +0 -0
  199. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/payment_collect.html +0 -0
  200. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/payment_error.html +0 -0
  201. {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
  202. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/rate_limited.html +0 -0
  203. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/reassign_task.html +0 -0
  204. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/resubmit_confirm.html +0 -0
  205. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/sso/login.html +0 -0
  206. {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
  207. {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
  208. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_detail.html +0 -0
  209. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_pdf.html +0 -0
  210. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/submission_success.html +0 -0
  211. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/django_forms_workflows/withdraw_confirm.html +0 -0
  212. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_notification.html +0 -0
  213. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_reminder.html +0 -0
  214. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/approval_request.html +0 -0
  215. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/email_styles.html +0 -0
  216. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/escalation_notification.html +0 -0
  217. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/notification_digest.html +0 -0
  218. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/rejection_notification.html +0 -0
  219. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/emails/submission_notification.html +0 -0
  220. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templates/registration/login.html +0 -0
  221. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templatetags/__init__.py +0 -0
  222. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/templatetags/forms_workflows_tags.py +0 -0
  223. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/urls.py +0 -0
  224. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/utils.py +0 -0
  225. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/views.py +0 -0
  226. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/workflow_builder_views.py +0 -0
  227. {django_forms_workflows-0.76.5 → django_forms_workflows-0.76.6}/django_forms_workflows/workflow_engine.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-forms-workflows
3
- Version: 0.76.5
3
+ Version: 0.76.6
4
4
  Summary: Enterprise-grade, database-driven form builder with approval workflows and external data integration
5
5
  License: LGPL-3.0-only
6
6
  License-File: LICENSE
@@ -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
- * Visual Form Builder
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
- * Provides drag-and-drop interface for creating and editing forms
5
- * without code.
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: `new_${this.fieldIdCounter++}`,
325
+ id: this.store.nextFieldId('new'),
364
326
  order: position + 1,
365
327
  field_label: this.getDefaultLabel(fieldType),
366
- field_name: this.getDefaultName(fieldType),
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 = `new_${this.fieldIdCounter++}`;
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: `new_${this.fieldIdCounter++}`,
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);