From 1c0e790618605cd4c0cdd08496b29e9f0a516b9e Mon Sep 17 00:00:00 2001 From: Julien Castets Date: Tue, 25 Jul 2023 15:50:36 +0200 Subject: [PATCH] Allow to upload an arbitrary number of legal files --- mesads/app/forms.py | 12 +++- mesads/templates/webpack/formset_files.html | 72 ++++++------------- mesads/templates/webpack/formset_files.ts | 49 +++++++++++++ mesads/templates/webpack/pages/ads.ts | 3 + .../webpack/pages/ads_manager_decree.ts | 3 + 5 files changed, 87 insertions(+), 52 deletions(-) create mode 100644 mesads/templates/webpack/formset_files.ts diff --git a/mesads/app/forms.py b/mesads/app/forms.py index 6a0dce94..675ceaf3 100644 --- a/mesads/app/forms.py +++ b/mesads/app/forms.py @@ -140,7 +140,11 @@ def _should_delete_form(self, form): ADSLegalFileFormSet = inlineformset_factory( - ADS, ADSLegalFile, fields=("file",), can_delete=True, extra=25, max_num=25 + ADS, + ADSLegalFile, + fields=("file",), + can_delete=True, + extra=0, ) @@ -164,7 +168,11 @@ class ADSSearchForm(forms.Form): ADSManagerDecreeFormSet = inlineformset_factory( - ADSManager, ADSManagerDecree, fields=("file",), can_delete=True, extra=5, max_num=5 + ADSManager, + ADSManagerDecree, + fields=("file",), + can_delete=True, + extra=0, ) diff --git a/mesads/templates/webpack/formset_files.html b/mesads/templates/webpack/formset_files.html index fc1e9f55..a4106d82 100644 --- a/mesads/templates/webpack/formset_files.html +++ b/mesads/templates/webpack/formset_files.html @@ -1,49 +1,13 @@ {% comment %}Render a formset to upload one or several files.{% endcomment %} - - - -
+
{{ formset.management_form }} - {% for form in formset %}
- {% comment %}Existing document {% endcomment %} {% if form.instance.file %} {{ form.id.as_hidden }} {{ form.file.as_hidden }} @@ -90,15 +54,6 @@ Annuler la suppression

- {% comment %}New document {% endcomment %} - {% else %} -
- - -
{% endif %} {% comment %}Form errors {% endcomment %} @@ -107,10 +62,27 @@ {{ error }}

{% endfor %} -
{% endfor %} + {% comment %}Extra forms to select new document{% endcomment %} + + {% for error in formset.non_form_errors %}

{{ error }} @@ -120,10 +92,10 @@

\ No newline at end of file diff --git a/mesads/templates/webpack/formset_files.ts b/mesads/templates/webpack/formset_files.ts new file mode 100644 index 00000000..fefbeabc --- /dev/null +++ b/mesads/templates/webpack/formset_files.ts @@ -0,0 +1,49 @@ +import Alpine from "alpinejs"; + +// This function must be called by the javascript page using formset_files.html +// to setup the directive "add-file-button". +export default function SetupFormsetFiles() { + Alpine.directive("add-file-button", (el, { expression }, { evaluate }) => { + el.addEventListener("click", () => { + const form = document.getElementById("formset-files"); + if (!form) { + throw new Error("formset-files not found"); + } + + // Initial number of forms in the formset + const initialForms = Array.from( + form.querySelectorAll("input[type=hidden]") + ).find((form) => form.id.match(/INITIAL_FORMS/)) as HTMLInputElement; + + const numInitialForms = parseInt(initialForms.value, 10); + + // Retrieve the value of the "extra" x-data attribute + const extra = evaluate("extra") as number; + + // For each file input (ie. for each new form), replace the string + // __prefix__ present in formset.empty_form.file.id_for_label and + // formset.empty_form.file.html_name by the form index. If the forms don't + // have a correct index, the files will be ignored by django. + el.parentElement + ?.querySelectorAll("input[type=file]") + .forEach((value) => { + const input = value as HTMLInputElement; + + input.id = input.id.replace( + /__prefix__/g, + (extra + numInitialForms - 1).toString() + ); + input.name = input.name.replace( + /__prefix__/, + (extra + numInitialForms - 1).toString() + ); + }); + + const totalInput = Array.from( + form.querySelectorAll("input[type=hidden]") + ).find((form) => form.id.match(/TOTAL_FORMS/)) as HTMLInputElement; + + totalInput.value = (parseInt(totalInput.value, 10) + 1).toString(); + }); + }); +} diff --git a/mesads/templates/webpack/pages/ads.ts b/mesads/templates/webpack/pages/ads.ts index d5da4781..2f049e5f 100644 --- a/mesads/templates/webpack/pages/ads.ts +++ b/mesads/templates/webpack/pages/ads.ts @@ -1,4 +1,7 @@ import Alpine from "alpinejs"; +import SetupFormsetFiles from "../formset_files"; + +SetupFormsetFiles(); // array.findLastIndex is only available for firefox>104 function findLastIndex(arr: any[], func: (e: any) => boolean) { diff --git a/mesads/templates/webpack/pages/ads_manager_decree.ts b/mesads/templates/webpack/pages/ads_manager_decree.ts index 67a4271b..771fe49b 100644 --- a/mesads/templates/webpack/pages/ads_manager_decree.ts +++ b/mesads/templates/webpack/pages/ads_manager_decree.ts @@ -1,3 +1,6 @@ import Alpine from "alpinejs"; +import SetupFormsetFiles from "../formset_files"; + +SetupFormsetFiles(); Alpine.start();