From 93019d5c30a6e471d61ea8204f9bc971b91c1112 Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Fri, 8 Nov 2024 11:22:26 +0100 Subject: [PATCH 01/24] Add additional data to new hedges --- envergo/hedges/forms.py | 17 ++++++++++++++ envergo/hedges/models.py | 3 ++- envergo/hedges/static/hedge_input/app.js | 30 ++++++++++++++++++++++++ envergo/hedges/views.py | 3 ++- envergo/templates/hedges/input.html | 26 ++++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 envergo/hedges/forms.py diff --git a/envergo/hedges/forms.py b/envergo/hedges/forms.py new file mode 100644 index 000000000..160a4f0ba --- /dev/null +++ b/envergo/hedges/forms.py @@ -0,0 +1,17 @@ +from django import forms + +TYPES = ( + ("degradee", "Haie dégradée ou résiduelle basse"), + ("buissonnante", "Haie buissonnante basse"), + ("arbustive", "Haie arbustive basse"), + ("alignement", "Alignement d'arbres"), + ("mixte", "Mixte"), +) + + +class HedgeDataForm(forms.Form): + hedge_type = forms.ChoiceField(choices=TYPES, label="Type de haie") + sur_parcelle_pac = forms.BooleanField(label="Sur parcelle PAC", required=False) + proximite_mare = forms.BooleanField( + label="Présence d'une mare à moins de 200m", required=False + ) diff --git a/envergo/hedges/models.py b/envergo/hedges/models.py index 2b8c67ff6..1e9b2106c 100644 --- a/envergo/hedges/models.py +++ b/envergo/hedges/models.py @@ -24,12 +24,13 @@ class Hedge: """Represent a single hedge.""" - def __init__(self, id, latLngs, type): + def __init__(self, id, latLngs, type, additionalData=None): self.id = id # The edge reference, e.g A1, A2… self.geometry = LineString( [(latLng["lng"], latLng["lat"]) for latLng in latLngs] ) self.type = type + self.additionalData = additionalData @property def length(self): diff --git a/envergo/hedges/static/hedge_input/app.js b/envergo/hedges/static/hedge_input/app.js index e45b1da0a..e0a617fee 100644 --- a/envergo/hedges/static/hedge_input/app.js +++ b/envergo/hedges/static/hedge_input/app.js @@ -120,6 +120,7 @@ class Hedge { id: this.id, latLngs: this.latLngs.map((latLng) => ({ lat: latLng.lat, lng: latLng.lng })), type: this.type, + additionalData: this.additionalData, }; } } @@ -229,11 +230,40 @@ createApp({ // Cacher la bulle d'aide à la fin du tracé newHedge.polyline.on('editable:drawing:end', () => { showHelpBubble.value = false; + showHedgeModal(newHedge); }); return newHedge; }; + // Show the "description de la haie" form modal + const showHedgeModal = (hedge) => { + const dialog = document.getElementById("hedge-data-dialog"); + const form = dialog.querySelector("form"); + dsfr(dialog).modal.disclose(); + + // Save form data to the hedge object + // This is the form submit event handler + const saveModalData = (event) => { + event.preventDefault(); + + const hedgeType = document.getElementById("id_hedge_type").value; + const isOnPacField = document.getElementById("id_sur_parcelle_pac").checked; + const isNearPond = document.getElementById("id_proximite_mare").checked; + hedge.additionalData = { + type: hedgeType, + onPacField: isOnPacField, + nearPond: isNearPond, + }; + + // Reset the form and hide the modal + form.reset(); + dsfr(dialog).modal.conceal(); + }; + + form.addEventListener("submit", saveModalData, { once: true }); + }; + const startDrawingToPlant = () => { return addHedge(TO_PLANT); }; diff --git a/envergo/hedges/views.py b/envergo/hedges/views.py index f533aa813..b286e4788 100644 --- a/envergo/hedges/views.py +++ b/envergo/hedges/views.py @@ -6,6 +6,7 @@ from django.views.decorators.csrf import csrf_exempt from django.views.generic import DetailView +from envergo.hedges.forms import HedgeDataForm from envergo.hedges.models import HedgeData @@ -32,7 +33,7 @@ def get_context_data(self, **kwargs): hedge_data = json.dumps(self.object.data) if self.object else "[]" context["hedge_data_json"] = hedge_data - + context["hedge_data_form"] = HedgeDataForm() return context def post(self, request, *args, **kwargs): diff --git a/envergo/templates/hedges/input.html b/envergo/templates/hedges/input.html index 95016566b..376a104b1 100644 --- a/envergo/templates/hedges/input.html +++ b/envergo/templates/hedges/input.html @@ -153,6 +153,32 @@

+ + +
+
+
+
+ +
+
+

Description de la haie

+ + {% include '_form_snippet.html' with form=hedge_data_form %} +
+ + +
+
+
+
+
+
{% endblock %} From 0c8a6027eef45e38f334c3a1a9e30bf1b9f40aa8 Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Fri, 8 Nov 2024 11:41:10 +0100 Subject: [PATCH 02/24] Render delete / update buttons --- envergo/static/sass/project_haie.scss | 20 ++++++++++---------- envergo/templates/hedges/input.html | 8 ++++++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/envergo/static/sass/project_haie.scss b/envergo/static/sass/project_haie.scss index 48e8d1cbb..bff61db13 100644 --- a/envergo/static/sass/project_haie.scss +++ b/envergo/static/sass/project_haie.scss @@ -182,11 +182,12 @@ div#app { } div#hedge-lists { - padding: 16px; + padding: 16px 0; --title-spacing: 0 0 0.5rem 0; h3 { + padding: 0 16px; font-weight: 500 !important; font-size: 16px !important; } @@ -202,6 +203,7 @@ div#app { p.fr-text--light { font-size: 14px; + padding: 0 16px; } table { @@ -220,27 +222,25 @@ div#app { th { text-align: left; - padding-left: 2rem; - min-width: 6rem; font-weight: 900; + padding-left: 16px; } td { - text-align: right; - color: #666; - } - - td:first-of-type { - min-width: 3rem; + text-align: center; } td:last-child { - width: 100%; + text-align: right; + padding-right: 16px; } button { visibility: hidden; margin-left: auto; + + --hover-tint: var(--background-alt-grey-hover); + --active-tint: var(--background-alt-grey-active); } &:hover, diff --git a/envergo/templates/hedges/input.html b/envergo/templates/hedges/input.html index 376a104b1..573b52c02 100644 --- a/envergo/templates/hedges/input.html +++ b/envergo/templates/hedges/input.html @@ -108,11 +108,15 @@

@mouseout="hedge.handleMouseOut()" @click="hedge.centerOnMap()"> [[ hedge.id ]] - [[ hedge.length.toFixed(0) ]] m - + + + + [[ hedge.length.toFixed(0) ]] m From 4931752c770c2625a7b4247b973c278022462604 Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Tue, 12 Nov 2024 11:14:42 +0100 Subject: [PATCH 03/24] Allow edition of existing hedges --- envergo/hedges/static/hedge_input/app.js | 24 +++++++++++++++++++++--- envergo/templates/hedges/input.html | 10 +++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/envergo/hedges/static/hedge_input/app.js b/envergo/hedges/static/hedge_input/app.js index e0a617fee..77e621a34 100644 --- a/envergo/hedges/static/hedge_input/app.js +++ b/envergo/hedges/static/hedge_input/app.js @@ -240,6 +240,18 @@ createApp({ const showHedgeModal = (hedge) => { const dialog = document.getElementById("hedge-data-dialog"); const form = dialog.querySelector("form"); + const hedgeTypeField = document.getElementById("id_hedge_type"); + const pacField = document.getElementById("id_sur_parcelle_pac"); + const nearPondField = document.getElementById("id_proximite_mare"); + + // Pre-fill the form with hedge data if it's an edition + if (hedge.additionalData) { + hedgeTypeField.value = hedge.additionalData.type; + pacField.checked = hedge.additionalData.onPacField; + nearPondField.checked = hedge.additionalData.nearPond; + } else { + form.reset(); + } dsfr(dialog).modal.disclose(); // Save form data to the hedge object @@ -247,9 +259,9 @@ createApp({ const saveModalData = (event) => { event.preventDefault(); - const hedgeType = document.getElementById("id_hedge_type").value; - const isOnPacField = document.getElementById("id_sur_parcelle_pac").checked; - const isNearPond = document.getElementById("id_proximite_mare").checked; + const hedgeType = hedgeTypeField.value; + const isOnPacField = pacField.checked; + const isNearPond = nearPondField.checked; hedge.additionalData = { type: hedgeType, onPacField: isOnPacField, @@ -264,6 +276,11 @@ createApp({ form.addEventListener("submit", saveModalData, { once: true }); }; + // Open the form modal to edit an existing hedge + const editHedge = (hedge) => { + showHedgeModal(hedge); + }; + const startDrawingToPlant = () => { return addHedge(TO_PLANT); }; @@ -359,6 +376,7 @@ createApp({ showHelpBubble, saveData, cancel, + editHedge, }; } }).mount('#app'); diff --git a/envergo/templates/hedges/input.html b/envergo/templates/hedges/input.html index 573b52c02..2755ccff8 100644 --- a/envergo/templates/hedges/input.html +++ b/envergo/templates/hedges/input.html @@ -114,7 +114,7 @@

+ @click.stop="editHedge(hedge)">Modifier [[ hedge.length.toFixed(0) ]] m @@ -141,11 +141,15 @@

@mouseout="hedge.handleMouseOut()" @click="hedge.centerOnMap()"> [[ hedge.id ]] - [[ hedge.length.toFixed(0) ]] m - + + + + [[ hedge.length.toFixed(0) ]] m From 3755614bcea22c78835283a1ff7c84e52385a408 Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Tue, 12 Nov 2024 15:04:17 +0100 Subject: [PATCH 04/24] Display the hedge name in modal title --- envergo/hedges/static/hedge_input/app.js | 4 ++++ envergo/templates/hedges/input.html | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/envergo/hedges/static/hedge_input/app.js b/envergo/hedges/static/hedge_input/app.js index 77e621a34..2e1dfec4e 100644 --- a/envergo/hedges/static/hedge_input/app.js +++ b/envergo/hedges/static/hedge_input/app.js @@ -243,6 +243,7 @@ createApp({ const hedgeTypeField = document.getElementById("id_hedge_type"); const pacField = document.getElementById("id_sur_parcelle_pac"); const nearPondField = document.getElementById("id_proximite_mare"); + const hedgeName = document.getElementById("hedge-data-dialog-hedge-name"); // Pre-fill the form with hedge data if it's an edition if (hedge.additionalData) { @@ -252,6 +253,9 @@ createApp({ } else { form.reset(); } + hedgeName.textContent = hedge.id; + + dsfr(dialog).modal.disclose(); // Save form data to the hedge object diff --git a/envergo/templates/hedges/input.html b/envergo/templates/hedges/input.html index 2755ccff8..88f5e23d7 100644 --- a/envergo/templates/hedges/input.html +++ b/envergo/templates/hedges/input.html @@ -173,7 +173,9 @@

-

Description de la haie

+

+ Description de la haie +

{% include '_form_snippet.html' with form=hedge_data_form %}
From 80922605cffece41bef5718e8802c451a9857c51 Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Tue, 12 Nov 2024 15:04:25 +0100 Subject: [PATCH 05/24] Fix a nasty bug with multiple event binding --- envergo/hedges/static/hedge_input/app.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/envergo/hedges/static/hedge_input/app.js b/envergo/hedges/static/hedge_input/app.js index 2e1dfec4e..2b2f7278d 100644 --- a/envergo/hedges/static/hedge_input/app.js +++ b/envergo/hedges/static/hedge_input/app.js @@ -277,7 +277,15 @@ createApp({ dsfr(dialog).modal.conceal(); }; + + // Save data upon form submission form.addEventListener("submit", saveModalData, { once: true }); + + // If the modal is closed without saving, let's make sure to remove the + // event listener. + dialog.addEventListener("dsfr.conceal", () => { + form.removeEventListener("submit", saveModalData); + }); }; // Open the form modal to edit an existing hedge From bc63294dd7b8552f5e6094910344e9ad00f1d2e7 Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Tue, 12 Nov 2024 15:10:43 +0100 Subject: [PATCH 06/24] Add hedge length to modal content --- envergo/hedges/static/hedge_input/app.js | 2 ++ envergo/templates/hedges/input.html | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/envergo/hedges/static/hedge_input/app.js b/envergo/hedges/static/hedge_input/app.js index 2b2f7278d..6a1c1462f 100644 --- a/envergo/hedges/static/hedge_input/app.js +++ b/envergo/hedges/static/hedge_input/app.js @@ -244,6 +244,7 @@ createApp({ const pacField = document.getElementById("id_sur_parcelle_pac"); const nearPondField = document.getElementById("id_proximite_mare"); const hedgeName = document.getElementById("hedge-data-dialog-hedge-name"); + const hedgeLength = document.getElementById("hedge-data-dialog-hedge-length"); // Pre-fill the form with hedge data if it's an edition if (hedge.additionalData) { @@ -254,6 +255,7 @@ createApp({ form.reset(); } hedgeName.textContent = hedge.id; + hedgeLength.textContent = hedge.length.toFixed(0); dsfr(dialog).modal.disclose(); diff --git a/envergo/templates/hedges/input.html b/envergo/templates/hedges/input.html index 88f5e23d7..0a399f98e 100644 --- a/envergo/templates/hedges/input.html +++ b/envergo/templates/hedges/input.html @@ -173,9 +173,12 @@

-

+

Description de la haie

+

+ Longueur : m +

{% include '_form_snippet.html' with form=hedge_data_form %}
From a418c71a30735a5ae1928664b6ca95207d60132d Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Thu, 14 Nov 2024 09:53:42 +0100 Subject: [PATCH 07/24] Switch buttons order --- envergo/templates/hedges/input.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/envergo/templates/hedges/input.html b/envergo/templates/hedges/input.html index 0a399f98e..ad6bca69f 100644 --- a/envergo/templates/hedges/input.html +++ b/envergo/templates/hedges/input.html @@ -110,11 +110,11 @@

[[ hedge.id ]] + @click.stop="editHedge(hedge)">Modifier + @click.stop="hedge.remove()">Supprimer [[ hedge.length.toFixed(0) ]] m @@ -143,11 +143,11 @@

[[ hedge.id ]] + @click.stop="editHedge(hedge)">Modifier + @click.stop="hedge.remove()">Supprimer [[ hedge.length.toFixed(0) ]] m From acf85d1b0d18e656860a6c681dce440746f33321 Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Thu, 14 Nov 2024 11:24:06 +0100 Subject: [PATCH 08/24] Trigger dialog closing with form validation --- envergo/templates/hedges/input.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/envergo/templates/hedges/input.html b/envergo/templates/hedges/input.html index ad6bca69f..048d16173 100644 --- a/envergo/templates/hedges/input.html +++ b/envergo/templates/hedges/input.html @@ -171,7 +171,7 @@

- +

Description de la haie From 577a5aaee46e168af28ae3374ed3e9105ec92913 Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Thu, 14 Nov 2024 11:39:00 +0100 Subject: [PATCH 09/24] Display help tag on hedge type field --- envergo/hedges/forms.py | 12 ++++++++++- envergo/hedges/static/hedge_input/app.js | 5 ++--- envergo/pages/templatetags/utils.py | 8 +++++++ envergo/static/sass/project_haie.scss | 7 ++++++ envergo/templates/_form_snippet.html | 3 +++ envergo/templates/_select_snippet.html | 27 ++++++++++++++++++++++++ 6 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 envergo/templates/_select_snippet.html diff --git a/envergo/hedges/forms.py b/envergo/hedges/forms.py index 160a4f0ba..98d256825 100644 --- a/envergo/hedges/forms.py +++ b/envergo/hedges/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.utils.safestring import mark_safe TYPES = ( ("degradee", "Haie dégradée ou résiduelle basse"), @@ -10,7 +11,16 @@ class HedgeDataForm(forms.Form): - hedge_type = forms.ChoiceField(choices=TYPES, label="Type de haie") + hedge_type = forms.ChoiceField( + choices=TYPES, + label=mark_safe( + """ + Type de haie + Aide + """ + ), + ) sur_parcelle_pac = forms.BooleanField(label="Sur parcelle PAC", required=False) proximite_mare = forms.BooleanField( label="Présence d'une mare à moins de 200m", required=False diff --git a/envergo/hedges/static/hedge_input/app.js b/envergo/hedges/static/hedge_input/app.js index 6a1c1462f..3b773ab02 100644 --- a/envergo/hedges/static/hedge_input/app.js +++ b/envergo/hedges/static/hedge_input/app.js @@ -257,9 +257,6 @@ createApp({ hedgeName.textContent = hedge.id; hedgeLength.textContent = hedge.length.toFixed(0); - - dsfr(dialog).modal.disclose(); - // Save form data to the hedge object // This is the form submit event handler const saveModalData = (event) => { @@ -288,6 +285,8 @@ createApp({ dialog.addEventListener("dsfr.conceal", () => { form.removeEventListener("submit", saveModalData); }); + + dsfr(dialog).modal.disclose(); }; // Open the form modal to edit an existing hedge diff --git a/envergo/pages/templatetags/utils.py b/envergo/pages/templatetags/utils.py index 630fc2604..99e36045d 100644 --- a/envergo/pages/templatetags/utils.py +++ b/envergo/pages/templatetags/utils.py @@ -4,6 +4,7 @@ CheckboxSelectMultiple, FileInput, RadioSelect, + Select, ) register = template.Library() @@ -30,6 +31,13 @@ def is_radio(field): return isinstance(field.field.widget, RadioSelect) +@register.filter +def is_select(field): + """Is the given field a select?.""" + + return isinstance(field.field.widget, Select) + + @register.filter def is_input_file(field): """Is the given field an input[type=file] widget?.""" diff --git a/envergo/static/sass/project_haie.scss b/envergo/static/sass/project_haie.scss index bff61db13..8e6311e47 100644 --- a/envergo/static/sass/project_haie.scss +++ b/envergo/static/sass/project_haie.scss @@ -274,6 +274,13 @@ dialog#hedge-input-modal { padding: 0; } +dialog#hedge-data-dialog { + #form-group-hedge_type label span.label-content { + display: flex; + justify-content: space-between; + } +} + div#statistics { background-color: #f6f6f6; padding: 16px; diff --git a/envergo/templates/_form_snippet.html b/envergo/templates/_form_snippet.html index 3f1943186..b948c1aa2 100644 --- a/envergo/templates/_form_snippet.html +++ b/envergo/templates/_form_snippet.html @@ -9,6 +9,9 @@ {% if field|is_checkbox %} {% include '_checkbox_snippet.html' with field=field %} + {% elif field|is_select %} + {% include '_select_snippet.html' with field=field %} + {% elif field|is_radio %} {% include '_radio_snippet.html' with field=field %} diff --git a/envergo/templates/_select_snippet.html b/envergo/templates/_select_snippet.html new file mode 100644 index 000000000..b8c624b5e --- /dev/null +++ b/envergo/templates/_select_snippet.html @@ -0,0 +1,27 @@ +{% load utils %} + +
+ + {% include '_label.html' %} + + {% if nest_field_class %}
{% endif %} + + {% if field.errors %} + {{ field|add_classes:'fr-select fr-input--error' }} + {% else %} + {{ field|add_classes:'fr-select' }} + {% endif %} + + {% if nest_field_class %}
{% endif %} + + {% if field.help_text and bottom_help_text %}{{ field.help_text|safe }}{% endif %} + + {% if field.errors %} +

+ ↑ + {{ field.errors.0 }} + ↑ +

+ {% endif %} +
From 730d114c7290c09e8bda9c067fced6367c1643fc Mon Sep 17 00:00:00 2001 From: Thibault Jouannic Date: Thu, 14 Nov 2024 15:57:50 +0100 Subject: [PATCH 10/24] uMove action bar to the bottom --- envergo/static/sass/project_haie.scss | 5 ++++- envergo/templates/hedges/input.html | 14 ++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/envergo/static/sass/project_haie.scss b/envergo/static/sass/project_haie.scss index 8e6311e47..a9bd55a37 100644 --- a/envergo/static/sass/project_haie.scss +++ b/envergo/static/sass/project_haie.scss @@ -44,9 +44,12 @@ div#app { visibility: hidden; } - header { + footer { display: flex; justify-content: space-between; + padding: 0.75rem 1rem; + background-color: var(--background-alt-blue-france); + border-top: 2px solid var(--border-plain-blue-france); } div#saisie-ui { diff --git a/envergo/templates/hedges/input.html b/envergo/templates/hedges/input.html index 048d16173..ac408bde6 100644 --- a/envergo/templates/hedges/input.html +++ b/envergo/templates/hedges/input.html @@ -14,14 +14,6 @@ data-save-url="{% url 'input_hedges' %}" data-hedges-data='{{ hedge_data_json|safe }}'> - -