Skip to content

Commit 5938808

Browse files
committed
Pouvoir modifier une fiche événement produit
- Quelques modifications de JS et HTML pour initialiser des données (liens libre, picker produit et danger, etc.) - Changement du nom de l'utilitaire de form pour utiliser le même sur la page de création et de modification - Quelques changement dans le form pour ne pas changer le créateur à chaque modification
1 parent ef4ab81 commit 5938808

12 files changed

+277
-41
lines changed

conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ def _choice_js_cant_pick(page, locator, exact_name):
133133
return _choice_js_cant_pick
134134

135135

136+
@pytest.fixture
137+
def choice_js_get_values(db, page):
138+
def _choice_js_get_values(page, locator):
139+
selected_options = page.locator(f'{locator} ~ div [aria-selected="true"]')
140+
texts = []
141+
for i in range(selected_options.count()):
142+
texts.append(selected_options.nth(i).inner_text())
143+
return texts
144+
145+
return _choice_js_get_values
146+
147+
136148
def _check_select_options_on_element(element, expected_options, with_default_value):
137149
options = element.locator("option").element_handles()
138150
visible_texts = []

ssa/forms.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ def __init__(self, *args, **kwargs):
8989
def save(self, commit=True):
9090
if self.data.get("action") == "publish":
9191
self.instance.etat = WithEtatMixin.Etat.EN_COURS
92-
self.instance.createur = self.user.agent.structure
92+
93+
if not self.instance.pk:
94+
self.instance.createur = self.user.agent.structure
9395
instance = super().save(commit)
9496
self.save_free_links(instance)
9597
return instance

ssa/models/evenement_produit.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
WithMessageUrlsMixin,
1313
EmailNotificationMixin,
1414
AllowsSoftDeleteMixin,
15+
WithFreeLinkIdsMixin,
1516
)
1617
from core.model_mixins import WithBlocCommunFieldsMixin
1718
from core.models import Structure, Document
@@ -138,6 +139,7 @@ class EvenementProduit(
138139
WithContactPermissionMixin,
139140
WithEtatMixin,
140141
WithNumeroMixin,
142+
WithFreeLinkIdsMixin,
141143
models.Model,
142144
):
143145
createur = models.ForeignKey(Structure, on_delete=models.PROTECT, verbose_name="Structure créatrice")
@@ -194,6 +196,9 @@ class EvenementProduit(
194196
def get_absolute_url(self):
195197
return reverse("ssa:evenement-produit-details", kwargs={"numero": self.numero})
196198

199+
def get_update_url(self):
200+
return reverse("ssa:evenement-produit-update", kwargs={"pk": self.pk})
201+
197202
def save(self, *args, **kwargs):
198203
with transaction.atomic():
199204
with reversion.create_revision():
@@ -282,6 +287,9 @@ def can_user_access(self, user):
282287
return True
283288
return not self.is_draft
284289

290+
def can_be_updated(self, user):
291+
return self._user_can_interact(user)
292+
285293
def can_user_delete(self, user):
286294
return self.can_user_access(user)
287295

ssa/static/ssa/_rappel_conso_form.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ document.documentElement.addEventListener('dsfr.ready', () => {
1818
handleDisabledRappelConsoBtn()
1919
}
2020

21+
function initExistingRappelConso(){
22+
if (!document.getElementById("id_numeros_rappel_conso").value) return;
23+
rappelConso = document.getElementById("id_numeros_rappel_conso").value.split(",")
24+
showRappelConso()
25+
}
26+
2127
function showRappelConso() {
2228
const rappelContainer = document.getElementById("rappel-container")
2329
let innerHtml = ""
@@ -85,4 +91,5 @@ document.documentElement.addEventListener('dsfr.ready', () => {
8591
submitDraftBtn.addEventListener("click", addNumeroRappelConsoToHiddenFieldAndSubmit)
8692
submitPublishBtn.addEventListener("click", addNumeroRappelConsoToHiddenFieldAndSubmit)
8793
toNextInput.forEach(element => element.addEventListener("keyup", () => goToNextIfNeeded(element)))
94+
initExistingRappelConso()
8895
})

ssa/static/ssa/evenement_produit_form.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {setUpFreeLinks} from "/static/core/free_links.js";
22
import {patchItems, findPath} from "/static/ssa/_custom_tree_select.js"
33

44
document.addEventListener('DOMContentLoaded', () => {
5-
function disableSourceOptions(typeEvenementInput, sourceInput) {
5+
function disableSourceOptions(typeEvenementInput, sourceInput, reset=true) {
66
const isHumanCase = typeEvenementInput.value === "investigation_cas_humain";
77
sourceInput.querySelectorAll('option').forEach(option => {
88
if (option.value !== "autre") {
@@ -13,14 +13,17 @@ document.addEventListener('DOMContentLoaded', () => {
1313
}
1414
}
1515
});
16-
sourceInput.selectedIndex = 0;
16+
if (reset===true){
17+
sourceInput.selectedIndex = 0;
18+
}
1719
}
1820

1921
function setupCategorieProduit(){
2022
const options = JSON.parse(document.getElementById("categorie-produit-data").textContent)
23+
const selectedValue = document.getElementById("id_categorie_produit").value
2124
const treeselect = new Treeselect({
2225
parentHtmlContainer: document.getElementById("categorie-produit"),
23-
value: null,
26+
value: selectedValue,
2427
options: options,
2528
isSingleSelect: true,
2629
showTags: false,
@@ -57,9 +60,10 @@ document.addEventListener('DOMContentLoaded', () => {
5760

5861
function setupCategorieDanger(){
5962
const options = JSON.parse(document.getElementById("categorie-danger-data").textContent)
63+
const selectedValue = document.getElementById("id_categorie_danger").value
6064
const treeselect = new Treeselect({
6165
parentHtmlContainer: document.getElementById("categorie-danger"),
62-
value: null,
66+
value: selectedValue,
6367
options: options,
6468
isSingleSelect: true,
6569
showTags: false,
@@ -109,7 +113,9 @@ document.addEventListener('DOMContentLoaded', () => {
109113
},
110114
})
111115
document.querySelector("#categorie-danger .treeselect-input").classList.add("fr-input")
112-
document.querySelector("#categorie-danger .treeselect-input__clear").classList.add("fr-hidden")
116+
if (!selectedValue){
117+
document.querySelector("#categorie-danger .treeselect-input__clear").classList.add("fr-hidden")
118+
}
113119
treeselect.srcElement.addEventListener("update-dom", ()=>{patchItems(treeselect.srcElement)})
114120
treeselect.srcElement.addEventListener('input', (e) => {
115121
if (!!e.detail){
@@ -126,8 +132,8 @@ document.addEventListener('DOMContentLoaded', () => {
126132
typeEvenementInput.addEventListener("change", () => {
127133
disableSourceOptions(typeEvenementInput, sourceInput)
128134
})
129-
disableSourceOptions(typeEvenementInput, sourceInput)
130-
setUpFreeLinks(document.getElementById("id_free_link"), null)
135+
disableSourceOptions(typeEvenementInput, sourceInput, false)
136+
setUpFreeLinks(document.getElementById("id_free_link"), document.getElementById('free-links-id'))
131137
new Choices(document.getElementById("id_quantification_unite"), {
132138
classNames: {
133139
containerInner: 'fr-select',

ssa/templates/ssa/evenement_produit_form.html

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,19 @@
3333
<main class="main-container">
3434

3535
<div class="evenement-produit-form-header">
36-
<h1>Création d'un événement</h1>
36+
<h1>{% if form.instance.pk %}Modification de l'événement {{ form.instance.numero }}{% else %}Création d'un événement{% endif %}</h1>
3737
<div class="fr-mb-auto">
3838
<a href="{% url 'ssa:evenement-produit-liste' %}" class="fr-link fr-mr-3w">Annuler</a>
39-
<button id="submit_draft" type="submit" name="action" value="draft" class="fr-btn fr-btn--secondary fr-mr-2w">Enregistrer le brouillon</button>
40-
<button id="submit_publish" type="submit" name="action" value="publish" class="fr-btn">Publier</button>
39+
{% if form.instance and form.instance.is_draft %}
40+
<button id="submit_draft" type="submit" name="action" value="draft" class="fr-btn fr-btn--secondary fr-mr-2w">Enregistrer le brouillon</button>
41+
{% endif %}
42+
<button id="submit_publish" type="submit" name="action" value="publish" class="fr-btn">
43+
{% if form.instance.pk %}
44+
Enregistrer
45+
{% else %}
46+
Publier
47+
{% endif %}
48+
</button>
4149
</div>
4250
</div>
4351

@@ -48,7 +56,7 @@ <h3>Informations</h3>
4856
<div class="fr-col-12 fr-col-lg-4 flex-column ">
4957
<div id="date-creation">
5058
<label class="fr-label" for="date-creation-input">Date de création</label>
51-
<input type="text" id="date-creation-input" class="fr-input fr-mt-0" value="{% now 'd/m/Y' %}" disabled>
59+
<input type="text" id="date-creation-input" class="fr-input fr-mt-0" value="{% if form.instance.date_creation %}{{ form.instance.date_creation|date:"d/m/Y" }}{% else %}{% now 'd/m/Y' %}{% endif %}" disabled>
5260
</div>
5361
{% if form.numero_rasff %}
5462
<div class="rasff">{% render_field form.numero_rasff %}</div>
@@ -171,6 +179,7 @@ <h3>Rappel conso</h3>
171179
{% include "ssa/_etablissement_block.html" %}
172180
<div id="liens-libre" class="white-container fr-mt-2w">
173181
<h3>Liens libres</h3>
182+
{{ form.instance.free_link_ids|json_script:"free-links-id" }}
174183
<span class="fr-hint-text fr-mb-1w">Pour lier un événement saisissez son numéro ci-dessous.</span>
175184
<div>
176185
{{ form.free_link }}

ssa/tests/pages.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
class WithTreeSelect:
1111
def _set_treeselect_option(self, container_id, label):
12+
self.page.locator(f"#{container_id} .treeselect-input__clear").click()
1213
self.page.locator(f"#{container_id} .treeselect-input__edit").click()
1314
for part in label.split(">"):
1415
if part == label.split(">")[-1]:
@@ -18,8 +19,12 @@ def _set_treeselect_option(self, container_id, label):
1819
else:
1920
self.page.get_by_title(part.strip(), exact=True).locator(".treeselect-list__item-icon").click()
2021

22+
def get_treeselect_options(self, container_id):
23+
elements = self.page.locator(f"#{container_id} .treeselect-input__tags-count")
24+
return [elements.nth(i).inner_text() for i in range(elements.count())]
2125

22-
class EvenementProduitCreationPage(WithTreeSelect):
26+
27+
class EvenementProduitFormPage(WithTreeSelect):
2328
info_fields = ["numero_rasff", "type_evenement", "source", "description", "numero_rasff"]
2429
produit_fields = [
2530
"denomination",
@@ -65,6 +70,17 @@ def navigate(self):
6570
}
6671
""")
6772

73+
def navigate_update_page(self, evenement):
74+
self.page.goto(f"{self.base_url}{evenement.get_update_url()}")
75+
self.page.evaluate("""
76+
() => {
77+
const element = document.getElementById('etablissement-template').content.querySelector('[data-token=""]');
78+
if (element) {
79+
element.setAttribute('data-token', 'FAKE');
80+
}
81+
}
82+
""")
83+
6884
def fill_required_fields(self, evenement_produit):
6985
self.type_evenement.select_option(evenement_produit.type_evenement)
7086
self.description.fill(evenement_produit.description)
@@ -113,6 +129,7 @@ def add_rappel_conso(self, numero):
113129

114130
def delete_rappel_conso(self, numero):
115131
tag = self.page.locator(".fr-tag", has_text=numero)
132+
tag.evaluate("el => el.scrollIntoView()")
116133
box = tag.bounding_box()
117134
self.page.mouse.click(box["x"] + box["width"] - 15, box["y"] - 5 + box["height"] / 2)
118135

@@ -129,6 +146,10 @@ def add_etablissement_siren(self, value, full_value, choice_js_fill_from_element
129146
element = self.current_modal.locator("[id^='search-siret-input-']").locator("..")
130147
choice_js_fill_from_element(self.page, element, value, full_value)
131148

149+
@property
150+
def date_creation(self):
151+
return self.page.locator("#date-creation-input")
152+
132153
@property
133154
def current_modal(self):
134155
return self.page.locator(".fr-modal__body").locator("visible=true")

0 commit comments

Comments
 (0)