summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2025-04-27 23:58:46 +0200
committerpolo <ordipolo@gmx.fr>2025-04-27 23:58:46 +0200
commit962d315ec0c99974df3dc2261bf94c54ca8cdbdd (patch)
tree7463f74a722e759067daf8c3ef43202a60352759 /src
parenta3ba7dde60dc1c94b7170ec28266a966e5004d33 (diff)
downloadcms-962d315ec0c99974df3dc2261bf94c54ca8cdbdd.zip
page menu et chemins, partie3
Diffstat (limited to 'src')
-rw-r--r--src/controller/ajax.php87
-rw-r--r--src/controller/installation.php14
-rw-r--r--src/controller/post.php82
-rw-r--r--src/model/Position.php22
-rw-r--r--src/model/entities/Page.php16
-rw-r--r--src/view/MenuBuilder.php46
-rw-r--r--src/view/templates/menu.php9
7 files changed, 223 insertions, 53 deletions
diff --git a/src/controller/ajax.php b/src/controller/ajax.php
index 9d1cc42..a20bd87 100644
--- a/src/controller/ajax.php
+++ b/src/controller/ajax.php
@@ -170,7 +170,8 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['action']))
170} 170}
171 171
172// détection des requêtes d'upload d'image de tinymce 172// détection des requêtes d'upload d'image de tinymce
173if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image'){ 173if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image')
174{
174 if (isset($_FILES['file'])) { 175 if (isset($_FILES['file'])) {
175 $file = $_FILES['file']; 176 $file = $_FILES['file'];
176 $dest = 'images/'; 177 $dest = 'images/';
@@ -211,6 +212,90 @@ if($_SERVER['CONTENT_TYPE'] === 'application/json' && isset($_GET['menu_edit']))
211 $json = json_decode($data, true); 212 $json = json_decode($data, true);
212 Director::$menu_data = new Menu($entityManager); 213 Director::$menu_data = new Menu($entityManager);
213 214
215 // flèche gauche <=: position = position du parent + 1, parent = grand-parent, recalculer les positions
216 if($_GET['menu_edit'] === 'move_one_level_up' && isset($json['id'])){
217 $id = $json['id'];
218 $page = Director::$menu_data->findPageById((int)$id);
219
220 $parent = $page->getParent(); // peut être null
221 if($parent === null){
222 // 1er niveau: ne rien faire
223 echo json_encode(['success' => false]);
224 die;
225 }
226 // BDD
227 else{
228 $page->setPosition($parent->getPosition() + 1); // nouvelle position
229
230 // 2ème niveau: le parent devient $menu_data, puis null après tri
231 if($parent->getParent() === null){
232 // connexion dans les deux sens
233 $page->setParent(Director::$menu_data); // => pour la persistance
234
235 //Director::$menu_data->addChild($page); // => pour sortChildren
236 $page->getParent()->addChild($page); // => pour sortChildren
237 //Director::$menu_data->sortChildren(true); // positions décaléees des nouveaux petits frères
238 $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères
239 $page->setParent(null);
240
241 // affichage
242 $page->setPagePath($page->getEndOfPath());
243 $page->fillChildrenPagePath();
244 }
245 // 3ème niveau et plus
246 else{
247 $page->setParent($parent->getParent()); // nouveau parent
248 $page->getParent()->addChild($page); // => pour sortChildren
249 $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères
250 $page->fillChildrenPagePath($page->getParent()->getPagePath());
251 }
252 //$parent->sortChildren(true); // positions des enfants restants, inutile si la fonction est récursive?
253 $entityManager->flush();
254
255 // affichage
256 $parent->removeChild($page);
257 $nav_builder = new NavBuilder();
258 $menu_builder = new MenuBuilder(null, false);
259 echo json_encode(['success' => true, 'nav' => $nav_builder->render(), 'menu_buttons' => $menu_builder->render()]);
260 die;
261 }
262 }
263
264 // flèche droite =>: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent
265 if($_GET['menu_edit'] === 'move_one_level_down' && isset($json['id'])){
266 $id = $json['id'];
267 $page = Director::$menu_data->findPageById((int)$id);
268
269 $parent = $page->getParent(); // peut être null
270 if($parent == null){
271 $parent = Director::$menu_data;
272 }
273
274 // BDD
275 $parent->sortChildren(true); // trie et réindexe par sécurité: 1, 2, 3...
276 if($page->getPosition() > 1){
277 foreach($parent->getChildren() as $child){
278 //echo $child->getPageName();
279 if($child->getPosition() === $page->getPosition() - 1){
280 $page->setParent($child);
281 break;
282 }
283 }
284 $page->setPosition(count($page->getParent()->getChildren()) + 1);
285 }
286 $entityManager->flush();
287
288 // affichage
289 $parent->removeChild($page);
290 $page->getParent()->addChild($page);
291 $page->fillChildrenPagePath($page->getParent()->getPagePath()); // variable non mappée $page_path
292 $nav_builder = new NavBuilder();
293 $menu_builder = new MenuBuilder(null, false);
294
295 echo json_encode(['success' => true, 'nav' => $nav_builder->render(), 'menu_buttons' => $menu_builder->render()]);
296 die;
297 }
298
214 if($_GET['menu_edit'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])) 299 if($_GET['menu_edit'] === 'switch_positions' && isset($json['id1']) && isset($json['id2']))
215 { 300 {
216 $id1 = $json['id1']; 301 $id1 = $json['id1'];
diff --git a/src/controller/installation.php b/src/controller/installation.php
index ff168eb..4aaa4e0 100644
--- a/src/controller/installation.php
+++ b/src/controller/installation.php
@@ -77,12 +77,12 @@ HTACCESS;
77function makeStartPage(EntityManager $entityManager){ 77function makeStartPage(EntityManager $entityManager){
78 /* -- table page -- */ 78 /* -- table page -- */
79 // paramètres: name_page, end_of_path, reachable, in_menu, position, parent 79 // paramètres: name_page, end_of_path, reachable, in_menu, position, parent
80 $accueil = new Page('Accueil', 'accueil', true, true, 1, NULL); 80 $accueil = new Page('Accueil', 'accueil', true, true, false, 1, NULL);
81 $connection = new Page('Connexion', 'connexion', true, false, NULL, NULL); 81 $connection = new Page('Connexion', 'connexion', true, false, false, NULL, NULL);
82 $article = new Page('Article', 'article', true, false, NULL, NULL); 82 $article = new Page('Article', 'article', true, false, false, NULL, NULL);
83 $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, NULL, NULL); 83 $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, false, NULL, NULL);
84 $edit_page = new Page("Modification d'une page", 'modif_page', true, false, NULL, NULL); 84 $edit_page = new Page("Modification d'une page", 'modif_page', true, false, false, NULL, NULL);
85 $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, NULL, NULL); 85 $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, false, NULL, NULL);
86 86
87 /* -- table node -- */ 87 /* -- table node -- */
88 // paramètres: name_node, article_timestamp, attributes, position, parent, page, article 88 // paramètres: name_node, article_timestamp, attributes, position, parent, page, article
@@ -95,7 +95,7 @@ function makeStartPage(EntityManager $entityManager){
95 $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav', 'main'], 'js_array' => ['main']], 1, NULL, $connection, NULL); 95 $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav', 'main'], 'js_array' => ['main']], 1, NULL, $connection, NULL);
96 $login = new Node('login', NULL, [], 1, $main, $connection, NULL); 96 $login = new Node('login', NULL, [], 1, $main, $connection, NULL);
97 $head_article = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL); 97 $head_article = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL);
98 $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'menu'], 'js_array' => ['main']], 1, NULL, $menu_paths, NULL); 98 $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'main', 'menu'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL);
99 $edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL); 99 $edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL);
100 100
101 /* -- table image -- */ 101 /* -- table image -- */
diff --git a/src/controller/post.php b/src/controller/post.php
index 926a5ae..8924686 100644
--- a/src/controller/post.php
+++ b/src/controller/post.php
@@ -5,13 +5,89 @@ declare(strict_types=1);
5 5
6if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true) 6if($_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION['admin'] === true)
7{ 7{
8 // requêtes AJAX 8 /* -- requêtes non AJAX -- */
9 // page Menu et chemin
10 /*if(isset($_POST['menu_edit_post']) && isset($_POST['id']))
11 {
12 // <= flèche gauche: le parent devient le grand-parent position = position du parent + 1, recalculer les positions des enfants restants
13 if($_POST['menu_edit_post'] == 'move_one_level_up'){
14 Director::$menu_data = new Menu($entityManager);
15 $page = Director::$menu_data->findPageById((int)$_POST['id']);
16
17 $parent = $page->getParent(); // peut être null
18 if($parent === null){
19 // 1er niveau: ne rien faire
20 header('Location: ' . new URL(['page' => 'menu_chemins']));
21 die;
22 }
23 else{
24 $page->setPosition($parent->getPosition() + 1); // nouvelle position
25
26 // 2ème niveau: le parent devient $menu_data, puis null après tri
27 if($parent->getParent() === null){
28 // connexion dans les deux sens
29 $page->setParent(Director::$menu_data); // => pour la persistance
30 Director::$menu_data->addChild($page); // => pour sortChildren
31
32 //Director::$menu_data->sortChildren(true); // positions décaléees des nouveaux petits frères
33 $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères
34
35 $page->setParent(null);
36 }
37 // 3ème niveau et plus
38 else{
39 $page->setParent($parent->getParent()); // nouveau parent
40 $page->getParent()->sortChildren(true); // positions décaléees des nouveaux petits frères
41 }
42 //$parent->sortChildren(true); // positions des enfants restants, inutile si la fonction est récursive?
43 echo $page->getPosition();
44 //die;
45 }
46 $entityManager->flush();
47
48 header('Location: ' . new URL(['page' => 'menu_chemins']));
49 die;
50 }
51 // => flèche droite: l'élément précédent devient le parent, position = nombre d'éléments de la fraterie + 1
52 elseif($_POST['menu_edit_post'] == 'move_one_level_down')
53 {
54 Director::$menu_data = new Menu($entityManager);
55 $page = Director::$menu_data->findPageById((int)$_POST['id']);
56
57 $parent = $page->getParent(); // peut être null
58 if($parent == null){
59 $parent = Director::$menu_data;
60 }
61
62 $parent->sortChildren(true); // trie et réindexe par sécurité: 1, 2, 3...
63 if($page->getPosition() > 1){
64 foreach($parent->getChildren() as $child){
65 echo $child->getPageName();
66 if($child->getPosition() === $page->getPosition() - 1){
67 $page->setParent($child);
68 break;
69 }
70 }
71 $page->setPosition(count($page->getParent()->getChildren()) + 1);
72 }
73 $entityManager->flush();
74
75 header('Location: ' . new URL(['page' => 'menu_chemins']));
76 die;
77 }
78 else{
79 // you talking to me?
80 die;
81 }
82 }*/
83
84 /* -- requêtes AJAX -- */
9 require '../src/controller/ajax.php'; 85 require '../src/controller/ajax.php';
10 86
11 // formulaires HTML 87 // formulaires HTML
12 if(isset($_POST['from']) // page d'où vient la requête 88 /*if(isset($_POST['from']) // page d'où vient la requête
13 && isset($_POST)) // données 89 && isset($_POST)) // données
14 { 90 {
15 echo "requête envoyée en validant un formulaire"; 91 echo "requête envoyée en validant un formulaire";
16 } 92 }*/
17} 93}
diff --git a/src/model/Position.php b/src/model/Position.php
index 74d173a..76de966 100644
--- a/src/model/Position.php
+++ b/src/model/Position.php
@@ -7,34 +7,30 @@ declare(strict_types=1);
7 7
8trait Position 8trait Position
9{ 9{
10 public function sortChildren(bool $reposition = false): void 10 public function sortChildren(bool $reindexation = false): void
11 { 11 {
12 // ordre du tableau des enfants 12 // tri par insertion du tableau des enfants
13 // inefficace quand des noeuds ont la même position
14
15 // tri par insertion avant affichage
16 for($i = 1; $i < count($this->children); $i++) 13 for($i = 1; $i < count($this->children); $i++)
17 { 14 {
18 $tmp = $this->children[$i]; 15 $tmp = $this->children[$i];
19 $j = $i - 1; 16 $j = $i - 1;
20 17
21 // Déplacez les éléments du tableau qui sont plus grands que la clé 18 // Déplacez les éléments du tableau qui sont plus grands que la clé à une position devant leur position actuelle
22 // à une position devant leur position actuelle 19 while($j >= 0 && $this->children[$j]->getPosition() > $tmp->getPosition()) {
23 while ($j >= 0 && $this->children[$j]->getPosition() > $tmp->getPosition()) {
24 $this->children[$j + 1] = $this->children[$j]; 20 $this->children[$j + 1] = $this->children[$j];
25 $j = $j - 1; 21 $j--;
26 } 22 }
27 $this->children[$j + 1] = $tmp; 23 $this->children[$j + 1] = $tmp;
28 } 24 }
29 25
30 foreach ($this->children as $child) { 26 foreach($this->children as $child) {
31 if (count($child->children) > 0) { 27 if(count($child->children) > 0) {
32 $child->sortChildren($reposition); 28 $child->sortChildren($reindexation);
33 } 29 }
34 } 30 }
35 31
36 // nouvelles positions (tableau $children => BDD) 32 // nouvelles positions (tableau $children => BDD)
37 if($reposition){ 33 if($reindexation){
38 $i = 1; 34 $i = 1;
39 foreach($this->children as $child){ 35 foreach($this->children as $child){
40 $child->setPosition($i); 36 $child->setPosition($i);
diff --git a/src/model/entities/Page.php b/src/model/entities/Page.php
index e3e60ca..aaff1ff 100644
--- a/src/model/entities/Page.php
+++ b/src/model/entities/Page.php
@@ -75,6 +75,10 @@ class Page
75 { 75 {
76 return $this->page_path; 76 return $this->page_path;
77 } 77 }
78 public function setPagePath(string $path):void
79 {
80 $this->page_path = $path;
81 }
78 public function getEndOfPath(): string 82 public function getEndOfPath(): string
79 { 83 {
80 return $this->end_of_path; 84 return $this->end_of_path;
@@ -107,6 +111,10 @@ class Page
107 { 111 {
108 return $this->parent; 112 return $this->parent;
109 } 113 }
114 public function setParent(?Page $parent): void
115 {
116 $this->parent = $parent;
117 }
110 public function getChildren(): Collection 118 public function getChildren(): Collection
111 { 119 {
112 return $this->children; 120 return $this->children;
@@ -125,6 +133,14 @@ class Page
125 $this->children[] = $child; 133 $this->children[] = $child;
126 $this->sortChildren(false); 134 $this->sortChildren(false);
127 } 135 }
136 public function removeChild(self $child): void
137 {
138 foreach($this->children as $index => $candidate){
139 if($candidate === $child){
140 unset($this->children[$index]);
141 }
142 }
143 }
128 144
129 public function findPageById(int $id): ?Page 145 public function findPageById(int $id): ?Page
130 { 146 {
diff --git a/src/view/MenuBuilder.php b/src/view/MenuBuilder.php
index 5a010d5..42c9273 100644
--- a/src/view/MenuBuilder.php
+++ b/src/view/MenuBuilder.php
@@ -1,19 +1,19 @@
1<?php 1<?php
2// src/view/MenuBuilder.php 2// src/view/MenuBuilder.php
3// 3//
4// page Menu et chemins en mode admin 4// page Menu et chemins en mode admin, fonctionne avec menu.js
5 5
6use App\Entity\Node; 6use App\Entity\Node;
7use App\Entity\Page; 7use App\Entity\Page;
8 8
9class MenuBuilder extends AbstractBuilder 9class MenuBuilder extends AbstractBuilder
10{ 10{
11 private int $margin_left_multiplier = 29; 11 //private int $margin_left_multiplier = 29;
12 12
13 public function __construct(Node $node) 13 public function __construct(Node $node = null, bool $template = true)
14 { 14 {
15 parent::__construct($node); 15 //parent::__construct($node);
16 $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; 16 $viewFile = $node === null ? self::VIEWS_PATH . 'menu.php' : self::VIEWS_PATH . $node->getName() . '.php';
17 17
18 if(file_exists($viewFile)) 18 if(file_exists($viewFile))
19 { 19 {
@@ -22,33 +22,33 @@ class MenuBuilder extends AbstractBuilder
22 extract($node->getNodeData()->getData()); 22 extract($node->getNodeData()->getData());
23 }*/ 23 }*/
24 24
25 if($_SESSION['admin']) 25 if($_SESSION['admin']){
26 { 26 $this->unfoldMenu(Director::$menu_data/*, 0 - $this->margin_left_multiplier*/);
27 $this->unfoldMenu(Director::$menu_data, 0 - $this->margin_left_multiplier);
28 } 27 }
29 else{ 28 else{
30 header('Location: ' . new URL); 29 header('Location: ' . new URL);
31 die; 30 die;
32 } 31 }
33 32
34 ob_start(); 33 // si faux, n'utilise pas le template
35 require $viewFile; 34 if($template){
36 $this->html = ob_get_clean(); // pas de concaténation ici, on écrase 35 ob_start();
36 require $viewFile; // insertion de $this->html généré par unfoldMenu
37 $this->html = ob_get_clean(); // pas de concaténation .= cette fois on écrase
38 }
37 } 39 }
38 } 40 }
39 41
40 private function unfoldMenu(Page $menu, int $margin_left): void 42 private function unfoldMenu(Page $menu): void
41 { 43 {
42 $margin_left += $this->margin_left_multiplier;
43 $this->html .= '<div class="level">' . "\n"; 44 $this->html .= '<div class="level">' . "\n";
44 45
45 foreach($menu->getChildren() as $entry) 46 foreach($menu->getChildren() as $entry)
46 { 47 {
47 $div_style = 'margin-left: ' . $margin_left . 'px;';
48 $checked = $entry->isHidden() ? '' : 'checked'; 48 $checked = $entry->isHidden() ? '' : 'checked';
49 $this->html .= '<div id="' . $entry->getId() . '" style="' . $div_style . '"> 49 $this->html .= '<div id="' . $entry->getId() . '" class="menu_edit_entry">
50 <img class="move_entry_icon" onclick="" src="assets/arrow-left.svg"> 50 <img class="move_entry_icon" onclick="moveOneLevelUp(' . $entry->getId() . ')" src="assets/arrow-left.svg">
51 <img class="move_entry_icon" onclick="" src="assets/arrow-right.svg"> 51 <img class="move_entry_icon" onclick="moveOneLevelDown(' . $entry->getId() . ')" src="assets/arrow-right.svg">
52 <img class="move_entry_icon" onclick="switchMenuPositions(' . $entry->getId() . ', \'up\')" src="assets/arrow-up.svg"> 52 <img class="move_entry_icon" onclick="switchMenuPositions(' . $entry->getId() . ', \'up\')" src="assets/arrow-up.svg">
53 <img class="move_entry_icon" onclick="switchMenuPositions(' . $entry->getId() . ', \'down\')" src="assets/arrow-down.svg"> 53 <img class="move_entry_icon" onclick="switchMenuPositions(' . $entry->getId() . ', \'down\')" src="assets/arrow-down.svg">
54 <span class="menu_entry_checkbox"> 54 <span class="menu_entry_checkbox">
@@ -58,24 +58,18 @@ class MenuBuilder extends AbstractBuilder
58 58
59 if(str_starts_with($entry->getEndOfPath(), 'http')){ 59 if(str_starts_with($entry->getEndOfPath(), 'http')){
60 $this->html .= '<span id="edit-i..."><img class="move_entry_icon" src="assets/edit.svg" onclick="openEditor(\'i...\')"></span> 60 $this->html .= '<span id="edit-i..."><img class="move_entry_icon" src="assets/edit.svg" onclick="openEditor(\'i...\')"></span>
61 <i>' . $entry->getEndOfPath() . '</i> 61 <i class="url">' . $entry->getEndOfPath() . '</i>
62 <span id="delete-i..."><img class="move_entry_icon" src="assets/delete-bin.svg" onclick="delete(\'i...\')"></span>'; 62 <span id="delete-i..."><img class="move_entry_icon" src="assets/delete-bin.svg" onclick="delete(\'i...\')"></span>';
63 } 63 }
64 else{ 64 else{
65 $this->html .= '<i>' . $entry->getPagePath() . '</i>'; 65 $this->html .= '<i class="path">' . $entry->getPagePath() . '</i>';
66 } 66 }
67 67
68 /*
69 => flèche gauche: position = position du parent + 1, parent = grand-parent, recalculer les positions
70 => flèche droite: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent
71 */
72
73 if(count($entry->getChildren()) > 0){ 68 if(count($entry->getChildren()) > 0){
74 $this->unfoldMenu($entry, $margin_left); 69 $this->unfoldMenu($entry);
75 } 70 }
76 $this->html .= '</div>' . "\n"; 71 $this->html .= '</div>' . "\n";
77 } 72 }
78 $this->html .= "</div>\n"; 73 $this->html .= "</div>\n";
79 $margin_left -= $this->margin_left_multiplier;
80 } 74 }
81} \ No newline at end of file 75} \ No newline at end of file
diff --git a/src/view/templates/menu.php b/src/view/templates/menu.php
index a7f318e..1414ab0 100644
--- a/src/view/templates/menu.php
+++ b/src/view/templates/menu.php
@@ -6,10 +6,13 @@
6 <p><img src="assets/arrow-up.svg"><img src="assets/arrow-down.svg"> déplacer la branche parmi celles de même niveau</p> 6 <p><img src="assets/arrow-up.svg"><img src="assets/arrow-down.svg"> déplacer la branche parmi celles de même niveau</p>
7 <p><input type="checkbox" checked>afficher/cacher</p> 7 <p><input type="checkbox" checked>afficher/cacher</p>
8 </aside> 8 </aside>
9 <div id="menu_edit_buttons">
9<?= $this->html ?> 10<?= $this->html ?>
11 </div>
10 <div class="new_entry_buttons"> 12 <div class="new_entry_buttons">
11 <p>Ajouter une nouvelle entrée dans le menu?</p> 13 <p>Ajouter une nouvelle entrée dans le menu
12 <button id="new-i..." onclick="openEditor('i...')"><img class="action_icon" src="assets/edit.svg">avec une URL</button> 14 <button id="new-i..." onclick="openEditor('i...')"><img class="action_icon" src="assets/edit.svg">avec une URL</button>
13 ...sinon cliquer sur Nouvelle page<img src="assets/arrow-down.svg">dans la barre jaune 15 ?</p>
16 <p>... ou cliquer sur <span style="color: #ff1d04;">Nouvelle page</span><img src="assets/arrow-down.svg">dans la barre jaune</p>
14 </div> 17 </div>
15</section> \ No newline at end of file 18</section> \ No newline at end of file