summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2025-05-10 20:16:56 +0200
committerpolo <ordipolo@gmx.fr>2025-05-10 20:16:56 +0200
commitaa8898ae00beaa0ac7e65e45c5f28199b25a9267 (patch)
tree19cde1aa42478bc594f4a2ea71b8cecdcdcdda85
parentd2bdfa7d0f746f060090a9e8c8ad6e376b5a1480 (diff)
downloadcms-aa8898ae00beaa0ac7e65e45c5f28199b25a9267.zip
modification de page en mode modif page, déplacement modif_page js et css et MAJ BDD, vue page nouvelle page
-rw-r--r--public/css/body.css147
-rw-r--r--public/css/modif_page.css74
-rw-r--r--public/css/new_page.css30
-rw-r--r--public/js/modif_page.js188
-rw-r--r--public/js/new_page.js18
-rw-r--r--src/view/NewPageBuilder.php49
-rw-r--r--src/view/templates/main.php45
-rw-r--r--src/view/templates/new_page.php27
8 files changed, 577 insertions, 1 deletions
diff --git a/public/css/body.css b/public/css/body.css
index 87f71f2..20e53e0 100644
--- a/public/css/body.css
+++ b/public/css/body.css
@@ -36,4 +36,149 @@ body
36.infobulle img 36.infobulle img
37{ 37{
38 vertical-align: middle; 38 vertical-align: middle;
39}*/ \ No newline at end of file 39}*/
40
41main
42{
43 margin: auto;
44 /*max-width: 1200px;*/
45 background-color: #E3F3FF;
46 padding: 15px 0;
47}
48section > h3
49{
50 padding: 15px;
51 margin: 0;
52 text-align: center;
53}
54.grid_columns
55{
56 display: grid;
57 grid-template-columns: repeat(3, 1fr);
58}
59@media screen and (max-width: 800px)
60{
61 .grid_columns
62 {
63 grid-template-columns: repeat(2, 1fr);
64 }
65}
66@media screen and (max-width: 550px)
67{
68 .grid_columns
69 {
70 display: block;
71 }
72}
73.galery_photos
74{
75 display: flex;
76 flex-wrap: wrap;
77 justify-content: space-evenly;
78}
79.galery_photos .html_from_editor img
80{
81 max-width: 300px;
82 max-height: 200px;
83}
84article
85{
86 /*display: flex;*/
87 background-color: white;
88 margin: 15px;
89 padding: 0 15px;
90 /*min-height: 150px;*/
91}
92article .logo2
93{
94 vertical-align: middle;
95 max-width: 200px;
96 max-height: 200px;
97 margin-right: 15px;
98}
99.new_content, .article_content
100{
101 width: 100%;
102}
103.new_content
104{
105 /*max-height: 400;*/
106 overflow: hidden;
107}
108article img
109{
110 max-width: 100%; /* règle compliquée, vérifier selon la page et la taille de l'image */
111 height: auto;
112}
113
114.action_icon
115{
116 width: 24px;
117 vertical-align: bottom;
118 border: transparent 2px solid; /* invisible */
119}
120button .action_icon
121{
122 border: none;
123}
124.action_icon:hover
125{
126 background-color: #ffff00;
127 border-radius: 4px;
128 border: lightgrey 2px outset;
129 cursor: pointer;
130}
131button .action_icon:hover
132{
133 border: none;
134}
135
136.button_zone
137{
138 display: flex;
139}
140
141.share
142{
143 float: right;
144}
145.article_title_zone
146{
147 padding: 10px;
148}
149.under_an_article
150{
151 display: flex;
152 justify-content: space-between;
153 font-size: small;
154}
155.under_an_article img
156{
157 width: 24px;
158 margin-right: 5px;
159 vertical-align: middle;
160}
161.article_admin_zone
162{
163 display: flex;
164 justify-content: end;
165}
166section button
167{
168 color: #ff1d04;
169 font-size: medium;
170 border-radius: 4px;
171 background-color: white;
172 border: lightgrey 2px outset; /* rend identiques les boutons firefox et chromium */
173}
174section button:hover
175{
176 background-color: #ffff00;
177 border-radius: 4px;
178 cursor: pointer;
179}
180
181article a:hover
182{
183 cursor: pointer;
184} \ No newline at end of file
diff --git a/public/css/modif_page.css b/public/css/modif_page.css
new file mode 100644
index 0000000..c494221
--- /dev/null
+++ b/public/css/modif_page.css
@@ -0,0 +1,74 @@
1/* -- mode modification d'une page -- */
2.page_modification
3{
4 background-color: white;
5 padding: 10px;
6 margin: 10px 15px;
7}
8.page_modification form select, .page_modification form input[type=submit]
9{
10 color: #ff1d04;
11 font-size: medium;
12 border-radius: 4px;
13 background-color: white;
14 border: lightgrey 2px outset;
15}
16.page_modificationselect:hover
17{
18 cursor: pointer;
19}
20.page_modification form input[type=submit]:hover
21{
22 background-color: #ffff00;
23 border-radius: 4px;
24 cursor: pointer;
25}
26.edit_page_title_zone
27{
28 display: flex;
29 flex-wrap: wrap;
30 justify-content: space-evenly;
31}
32.edit_page_zone, .edit_bloc_zone
33{
34 background-color: #f0f0f0f0;
35 margin: 5px;
36 padding: 10px;
37}
38#edit_description
39{
40 margin: 5px;
41 display: flex;
42 flex-wrap: wrap;
43 justify-content: center;
44 gap: 5px;
45}
46#edit_description button
47{
48 vertical-align: top;
49}
50.edit_bloc_zone
51{
52 display: flex;
53 justify-content: space-evenly;
54 flex-wrap: wrap;
55}
56.edit_page_zone p, .edit_bloc_zone p, .edit_page_zone form
57{
58 margin: 5px;
59}
60
61.new_bloc #bloc_title
62{
63 width: 70%;
64 max-width: 300px;
65}
66.modify_bloc > div
67{
68 display: flex;
69 align-items: baseline;
70}
71.modify_bloc img
72{
73 vertical-align: middle;
74} \ No newline at end of file
diff --git a/public/css/new_page.css b/public/css/new_page.css
new file mode 100644
index 0000000..0cc067a
--- /dev/null
+++ b/public/css/new_page.css
@@ -0,0 +1,30 @@
1/*-- page "Nouvelle page" uniquement --*/
2.new_page
3{
4 padding: 0 20px;
5}
6.new_page .form_zone
7{
8 background-color: white;
9 padding: 10px;
10}
11
12.new_page #page_location, .new_page input[type=submit]
13{
14 color: #ff1d04;
15 font-size: medium;
16 border-radius: 4px;
17 background-color: white;
18 border: lightgrey 2px outset;
19}
20.new_page #page_location:hover, .new_page input[type=submit]:hover
21{
22 background-color: #ffff00;
23 border-radius: 4px;
24 border: lightgrey 2px outset;
25 cursor: pointer;
26}
27.label_textarea
28{
29 vertical-align: top;
30} \ No newline at end of file
diff --git a/public/js/modif_page.js b/public/js/modif_page.js
new file mode 100644
index 0000000..8ff26c1
--- /dev/null
+++ b/public/js/modif_page.js
@@ -0,0 +1,188 @@
1/* -- mode modification d'une page -- */
2
3// même fonction que dans new_page.js
4function makePageNamePath(){
5 const page_name = document.getElementById("page_name");
6 const page_name_path = document.getElementById("page_name_path");
7 page_name_path.value = page_name.value.replace(/\W+/g, " ").trim().toLowerCase().split(' ').join('_');
8
9 /* explication de l'expression régulière
10 / = début et fin, \W+ = lettres et chiffres, g = global */
11}
12
13
14// partie "page"
15function changePageTitle(page_id){
16 const page_name = document.getElementById("page_name");
17
18 fetch('index.php?page_edit=page_title', {
19 method: 'POST',
20 headers: {
21 'Content-Type': 'application/json'
22 },
23 body: JSON.stringify({title: page_name.value, page_id: page_id})
24 })
25 .then(response => response.json())
26 .then(data => {
27 if(data.success){
28 document.querySelector("title").innerHTML = data.title; // metadonnées
29 document.getElementById("m_" + page_id).innerHTML = data.title; // menu
30 const thesee = document.getElementById("thesee"); // fil d'Ariane
31 if(thesee != null){
32 thesee.innerHTML = data.title;
33 }
34 console.log("la page a été renommée: " + data.title);
35 toastNotify("la page a été renommée: " + data.title);
36 }
37 else{
38 console.error('Erreur au renommage de la page.');
39 }
40 })
41 .catch(error => {
42 console.error('Erreur:', error);
43 });
44}
45/*function changePageMenuPath(page_id){
46 const page_name_path = document.getElementById("page_name_path");
47
48 fetch('index.php?page_edit=page_menu_path', {
49 method: 'POST',
50 headers: {
51 'Content-Type': 'application/json'
52 },
53 body: JSON.stringify({page_menu_path: page_name_path.value, page_id: page_id})
54 })
55 .then(response => response.json())
56 .then(data => {
57 if(data.success){
58 // oh putaing...
59 let url = new URL(document.getElementById("m_" + page_id).parentElement.href); // url attrapée dans une balise <a>
60 let params = new URLSearchParams(url.search); // params à droite du ?
61 let path_array = params.get('page').split('/'); // chemin 'page' découpé dans un tableau
62 console.log(data.page_name_path);
63 path_array[path_array.length - 1] = data.page_name_path; // modif de la dernière case
64 params.set('page', path_array.join('/')); // réassemblage du chemin et MAJ de params
65 url.search = params.toString(); // MAJ de url
66 document.getElementById("m_" + page_id).parentElement.href = url.toString(); // MAJ de la balise <a>
67
68 // modifier l'URL sans rafraichir en touchant à l'historique
69 params.set('action', 'modif_page'); // on veut rester en mode "modif"
70 url.search = params.toString();
71 history.pushState({}, '', url.toString())
72
73 console.log("la nouveau chemin est: " + data.page_name_path);
74 toastNotify("la nouveau chemin est: " + data.page_name_path);
75 }
76 else{
77 console.error("Erreur à la modification du chemin de la page dans l'URL.");
78 }
79 })
80 .catch(error => {
81 console.error('Erreur:', error);
82 });
83}*/
84function changeDescription(node_data_id){
85 const textarea = document.getElementById("description_textarea");
86
87 fetch('index.php?page_edit=page_description', {
88 method: 'POST',
89 headers: {
90 'Content-Type': 'application/json'
91 },
92 body: JSON.stringify({description: textarea.value, node_data_id: node_data_id})
93 })
94 .then(response => response.json())
95 .then(data => {
96 if(data.success){
97 document.querySelector('meta[name="description"]').setAttribute('content', data.description); // c'était vraiment nécéssaire?
98 console.log("la nouvelle description de la page est: " + data.description);
99 toastNotify("la nouvelle description de la page est: " + data.description);
100 }
101 else{
102 console.error('Erreur à la modification de la description de la page.');
103 }
104 })
105 .catch(error => {
106 console.error('Erreur:', error);
107 });
108}
109
110
111// partie "blocs"
112function renamePageBloc(bloc_id){
113 const input = document.getElementById("bloc_rename_" + bloc_id);
114 const title = document.getElementById(bloc_id).querySelector("h3");
115
116 fetch('index.php?bloc_edit=rename_page_bloc', {
117 method: 'POST',
118 headers: {
119 'Content-Type': 'application/json'
120 },
121 body: JSON.stringify({bloc_title: input.value, bloc_id: bloc_id})
122 })
123 .then(response => response.json())
124 .then(data => {
125 if(data.success){
126 title.innerHTML = data.title;
127 console.log(data.title);
128 toastNotify('Le bloc a été renommé: ' + data.title);
129 }
130 else{
131 console.error('Erreur au renommage du titre.');
132 }
133 })
134 .catch(error => {
135 console.error('Erreur:', error);
136 });
137}
138
139function switchBlocsPositions(bloc_id, direction, current_page) {
140 const current_bloc = document.getElementById(bloc_id);
141 const current_bloc_edit_zone = document.getElementById("bloc_edit_" + bloc_id);
142 var other_bloc;
143
144 if(direction == 'down'){
145 other_bloc = current_bloc.nextElementSibling;
146 }
147 else if(direction == 'up'){
148 other_bloc = current_bloc.previousElementSibling;
149 }
150
151 if(other_bloc == null || other_bloc.tagName !== 'SECTION')
152 {
153 console.log('Inversion impossible');
154 return;
155 }
156 const other_bloc_edit_zone = document.getElementById("bloc_edit_" + other_bloc.id);
157
158 fetch('index.php?page=' + current_page + '&bloc_edit=switch_blocs_positions', {
159 method: 'POST',
160 headers: {
161 'Content-Type': 'application/json'
162 },
163 body: JSON.stringify({ id1: bloc_id, id2: parseInt(other_bloc.id) })
164 })
165 .then(response => response.json())
166 .then(data => {
167 if(data.success)
168 {
169 if(direction == 'down'){
170 current_bloc.parentElement.insertBefore(other_bloc, current_bloc);
171 current_bloc_edit_zone.parentElement.insertBefore(other_bloc_edit_zone, current_bloc_edit_zone);
172 console.log('Inversion réussie');
173 }
174 else if(direction == 'up'){
175 other_bloc.parentElement.insertBefore(current_bloc, other_bloc);
176 other_bloc_edit_zone.parentElement.insertBefore(current_bloc_edit_zone, other_bloc_edit_zone);
177 console.log('Inversion réussie');
178 }
179 }
180 else {
181
182 console.error('Échec de l\'inversion');
183 }
184 })
185 .catch(error => {
186 console.error('Erreur:', error);
187 });
188} \ No newline at end of file
diff --git a/public/js/new_page.js b/public/js/new_page.js
new file mode 100644
index 0000000..7cfa5b8
--- /dev/null
+++ b/public/js/new_page.js
@@ -0,0 +1,18 @@
1/*-- page Nouvelle page --*/
2
3// même fonction que dans modif_page.js
4function makePageNamePath(){
5 const page_name = document.getElementById("page_name");
6 const page_name_path = document.getElementById("page_name_path");
7 page_name_path.value = page_name.value.replace(/\W+/g, " ").trim().toLowerCase().split(' ').join('_');
8
9 /* explication de l'expression régulière
10 / = début et fin, \W+ = lettres et chiffres, g = global */
11}
12
13
14/* to do list:
15=> au submit l'utilisateur est emmener sur la nouvelle page
16=> interdir les doublons dans new_page_name_path
17=> écrire la description avec l'éditeur?
18*/ \ No newline at end of file
diff --git a/src/view/NewPageBuilder.php b/src/view/NewPageBuilder.php
new file mode 100644
index 0000000..2fae6fa
--- /dev/null
+++ b/src/view/NewPageBuilder.php
@@ -0,0 +1,49 @@
1<?php
2// src/view/NewPageBuilder.php
3//
4// page Nouvelle page en mode admin, fonctionne avec new_page.js
5
6declare(strict_types=1);
7
8use App\Entity\Node;
9use App\Entity\Page;
10
11class NewPageBuilder extends AbstractBuilder
12{
13 //private int $margin_left_multiplier = 29;
14 private string $options = '';
15
16 public function __construct(Node $node = null)
17 {
18 //parent::__construct($node);
19 $viewFile = self::VIEWS_PATH . $node->getName() . '.php';
20
21 if(isset($_SESSION['admin']) && $_SESSION['admin'] && file_exists($viewFile))
22 {
23 /*if(!empty($node->getNodeData()->getData()))
24 {
25 extract($node->getNodeData()->getData());
26 }*/
27
28 $this->unfoldOptions(Director::$menu_data);
29
30 ob_start();
31 require $viewFile; // insertion de $this->html généré par unfoldMenu
32 $this->html = ob_get_clean(); // pas de concaténation .= cette fois on écrase
33 }
34 else{
35 header('Location: ' . new URL);
36 die;
37 }
38 }
39
40 private function unfoldOptions(Page $page): void
41 {
42 foreach($page->getChildren() as $entry){
43 $this->options .= '<option value="' . $entry->getId() . '">' . $entry->getPageName() . "</option>\n";
44 if(count($entry->getChildren()) > 0){
45 $this->unfoldOptions($entry);
46 }
47 }
48 }
49} \ No newline at end of file
diff --git a/src/view/templates/main.php b/src/view/templates/main.php
new file mode 100644
index 0000000..7ff03a8
--- /dev/null
+++ b/src/view/templates/main.php
@@ -0,0 +1,45 @@
1<?php declare(strict_types=1); ?>
2<section class="page_modification">
3 <h3>Modification de la page</h3>
4 <div class="edit_page_zone">
5 <div class="edit_page_title_zone">
6 <p id="edit_page_title">
7 <label for="page_name">Titre de la page</label>
8 <input type="text" id="page_name" name="edit_page_title" value="<?= Director::$page_path->getLast()->getPageName() ?>" onchange="makePageNamePath()" required>
9 <button onclick="changePageTitle('<?= Director::$page_path->getLast()->getId() ?>')">Renommer</button>
10 </p>
11 <form id="edit_page_menu_path" method="post" action="<?= new URL(['page' => CURRENT_PAGE]) ?>">
12 <label for="page_name_path">Chemin en "snake_case"</label>
13 <input type="text" id="page_name_path" name="page_menu_path" value="<?= Director::$page_path->getLast()->getEndOfPath() ?>" placeholder="ex: nouvelle_page" required>
14 <input type="hidden" name="page_id" value="<?= Director::$page_path->getLast()->getId() ?>"><input type="hidden" name="page_name_path_hidden">
15 <input type="submit" value="Modifier">
16 </form>
17 </div>
18 <div id="edit_description">
19 <label for="description_textarea">Description sous le titre dans les moteurs de recherche</label>
20 <div>
21 <textarea id="description_textarea" name="edit_description" cols="40" rows="3" placeholder="ex: nous faisons ceci et cela, etc" required><?= $head_node->getNodeData()->getData()['description'] ?></textarea>
22 <button onclick="changeDescription('<?= $head_node->getNodeData()->getId() ?>')">Modifier</button>
23 </div>
24 </div>
25 </div>
26 <div class="edit_bloc_zone">
27 <div class="new_bloc">
28 <p>Ajouter un bloc de page</p>
29 <form method="post" action="<?= new URL(['page' => CURRENT_PAGE]) ?>">
30 <p><label for="bloc_title">Titre</label>
31 <input type="text" id="bloc_title" name="bloc_title" required></p>
32 <p><label for="bloc_select">Type</label>
33 <select id="bloc_select" name="bloc_select" required>
34 <?= $options ?>
35 </select>
36 <input type="hidden" name="bloc_title_hidden">
37 <input type="submit" value="Valider"></p>
38 </form>
39 </div>
40 <div class="modify_bloc">
41 <p>Modifier un bloc</p>
42 <?= $bloc_edit ?>
43 </div>
44 </div>
45</section> \ No newline at end of file
diff --git a/src/view/templates/new_page.php b/src/view/templates/new_page.php
new file mode 100644
index 0000000..db48496
--- /dev/null
+++ b/src/view/templates/new_page.php
@@ -0,0 +1,27 @@
1<?php declare(strict_types=1); ?>
2<section class="new_page">
3 <h3>Création d'une nouvelle page</h3>
4 <div class="form_zone">
5 <form method="post" action="<?= new URL(['from' => 'nouvelle_page']) ?>">
6 <p>
7 <label for="new_page_name">Nom de la page</label>
8 <input id="page_name" type="text" name="new_page_name" onchange="makePageNamePath()" required>
9 </p>
10 <p>
11 <label for="new_page_name_path">Chemin de l'URL</label>
12 <input id="page_name_path" type="text" name="new_page_name_path" placeholder="ex: nouvelle_page" required>
13 </p>
14 <p>
15 <label for="page_location">Placer la page juste après cette entrée</label>
16 <select id="page_location" name="page_location">
17 <?= $this->options ?>
18 </select>
19 </p>
20 <p>
21 <label class="label_textarea" for="new_page_description">Description qui apparaît sous le titre dans les moteurs de recherche</label>
22 <textarea id="new_page_description" name="new_page_description" cols="40" rows="3" placeholder="ex: nous faisons ceci et cela, etc" required></textarea>
23 </p>
24 <input type="submit" value="Créer la page">
25 </form>
26 </div>
27</section> \ No newline at end of file