aboutsummaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
Diffstat (limited to 'public')
-rw-r--r--public/css/body.css8
-rw-r--r--public/js/main.js57
-rw-r--r--public/js/modif_page.js78
-rw-r--r--public/js/tinymce.js28
4 files changed, 140 insertions, 31 deletions
diff --git a/public/css/body.css b/public/css/body.css
index 140655b..b728d05 100644
--- a/public/css/body.css
+++ b/public/css/body.css
@@ -49,12 +49,20 @@ main
49{ 49{
50 display: none; 50 display: none;
51} 51}
52section
53{
54 margin: 10px 0;
55}
52section > h3 56section > h3
53{ 57{
54 padding: 15px; 58 padding: 15px;
55 margin: 0; 59 margin: 0;
56 text-align: center; 60 text-align: center;
57} 61}
62section .fetch_articles
63{
64 margin-left: 15px;
65}
58.login_form 66.login_form
59{ 67{
60 background-color: white; 68 background-color: white;
diff --git a/public/js/main.js b/public/js/main.js
index d2f8876..59a9331 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -36,15 +36,10 @@ function toastNotify(message){
36 setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 5000); 36 setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 5000);
37} 37}
38 38
39
40// exécuté à la fin du chargement de la page 39// exécuté à la fin du chargement de la page
41document.addEventListener('DOMContentLoaded', () => { 40document.addEventListener('DOMContentLoaded', () => {
42 41
43 // détection des dates et conversion à l'heure locale 42 insertLocalDates();
44 document.querySelectorAll('.local_date').forEach(function(element){
45 const utc_date = element.getAttribute('date-utc'); // forme: 2025-10-10T12:17:00+00:00
46 element.innerText = toFormatedLocalDate(utc_date);
47 });
48 43
49 // ouvrir/fermer les sous-menus avec écran tactile 44 // ouvrir/fermer les sous-menus avec écran tactile
50 document.querySelectorAll('.sub-menu-toggle').forEach(button => { 45 document.querySelectorAll('.sub-menu-toggle').forEach(button => {
@@ -85,6 +80,48 @@ document.addEventListener('DOMContentLoaded', () => {
85}); 80});
86 81
87 82
83function fetchArticles(bloc_id){
84 const parent = document.getElementById(bloc_id);
85
86 const block_type = parent.getAttribute('block-type');
87 let last_article = '';
88 if(block_type === 'post_block'){
89 // pas parfait, suppose que les positions sont correctes
90 last_article = parent.querySelectorAll('article').length - 1;
91 }
92 else if(block_type === 'news_block'){
93 // date_time du dernier article affiché (heure UTC), date vide si bloc vide
94 const news_elements = parent.querySelector('.section_child').querySelectorAll('article');
95 last_article = news_elements.length !== 0 ? news_elements[news_elements.length - 1].querySelector('.local_date').getAttribute('date-utc') : '';
96 }
97 else{
98 console.log("Erreur, le type de bloc n'est pas reconnu");
99 return;
100 }
101
102 fetch('index.php?fetch=next_articles&id=' + bloc_id + '&last_article=' + last_article) // méthode GET par défaut
103 .then(response => response.json())
104 .then(data => {
105 if(data.success){
106 // insérer les articles
107 parent.querySelector('.section_child').innerHTML += data.html;
108 insertLocalDates();
109
110 // cacher le bouton
111 parent.querySelector('.fetch_articles').querySelector('button').className = data.truncated ? '' : 'hidden';
112
113 console.log("Articles insérés dans le bloc");
114 }
115 else{
116 console.log("Erreur côté serveur à la récupération d'articles");
117 }
118 })
119 .catch(error => {
120 console.error('Erreur:', error);
121 });
122}
123
124
88// complète les fonctions dans tinymce.js 125// complète les fonctions dans tinymce.js
89function switchPositions(article_id, direction) 126function switchPositions(article_id, direction)
90{ 127{
@@ -239,6 +276,14 @@ function submitDate(id_date)
239 } 276 }
240} 277}
241 278
279function insertLocalDates(){
280 // détection des dates et conversion à l'heure locale
281 document.querySelectorAll('.local_date').forEach(function(element){
282 const utc_date = element.getAttribute('date-utc'); // forme: 2025-10-10T12:17:00+00:00
283 element.innerText = toFormatedLocalDate(utc_date);
284 });
285}
286
242function toFormatedLocalDate(utc_string_date){ // forme: 2025-07-17T13:54:00.000Z ou 2025-02-04T00:24 287function toFormatedLocalDate(utc_string_date){ // forme: 2025-07-17T13:54:00.000Z ou 2025-02-04T00:24
243 const date = new Date(utc_string_date); 288 const date = new Date(utc_string_date);
244 289
diff --git a/public/js/modif_page.js b/public/js/modif_page.js
index bf269ee..15f3598 100644
--- a/public/js/modif_page.js
+++ b/public/js/modif_page.js
@@ -1,5 +1,8 @@
1/* -- mode modification d'une page -- */ 1/* -- mode modification d'une page -- */
2 2
3// beaucoup de fonctions similaires
4// à factoriser avec le pattern stratégie?
5
3// même fonction que dans new_page.js 6// même fonction que dans new_page.js
4function makePageNamePath(){ 7function makePageNamePath(){
5 document.getElementById("page_name_path").value = document.getElementById("page_name").value 8 document.getElementById("page_name_path").value = document.getElementById("page_name").value
@@ -92,7 +95,7 @@ function changeDescription(node_data_id){
92 toastNotify("la nouvelle description de la page est: " + data.description); 95 toastNotify("la nouvelle description de la page est: " + data.description);
93 } 96 }
94 else{ 97 else{
95 console.error('Erreur à la modification de la description de la page.'); 98 console.error('Erreur côté serveur à la modification de la description de la page.');
96 } 99 }
97 }) 100 })
98 .catch(error => { 101 .catch(error => {
@@ -119,7 +122,7 @@ function renamePageBloc(bloc_id){
119 toastNotify('Le bloc a été renommé: ' + data.title); 122 toastNotify('Le bloc a été renommé: ' + data.title);
120 } 123 }
121 else{ 124 else{
122 console.error('Erreur au renommage du titre.'); 125 console.error('Erreur côté serveur au renommage du titre.');
123 } 126 }
124 }) 127 })
125 .catch(error => { 128 .catch(error => {
@@ -168,7 +171,7 @@ function switchBlocsPositions(bloc_id, direction) {
168 } 171 }
169 else { 172 else {
170 173
171 console.error('Échec de l\'inversion'); 174 console.error("Échec de l'inversion côté serveur");
172 } 175 }
173 }) 176 })
174 .catch(error => { 177 .catch(error => {
@@ -187,17 +190,21 @@ function articlesOrderSelect(bloc_id){
187 .then(response => response.json()) 190 .then(response => response.json())
188 .then(data => { 191 .then(data => {
189 if(data.success){ 192 if(data.success){
190 // inverser l'ordre des articles!! 193 // inversion des articles
191 const parent = document.getElementById(bloc_id).querySelector(".section_child"); 194 /*const parent = document.getElementById(bloc_id).querySelector(".section_child");
192 const articles = Array.from(parent.querySelectorAll("article")); 195 const articles = Array.from(parent.querySelectorAll("article"));
193 articles.reverse().forEach(article => { 196 articles.reverse().forEach(article => {
194 parent.appendChild(article); // déplace dans le DOM, ne copie pas 197 parent.appendChild(article); // déplace dans le DOM, ne copie pas
195 }); 198 });*/
199
200 // à cause de la pagination, au lieu d'inverser, on remplace les articles par les 1er dans le nouveau sens
201 document.getElementById(bloc_id).querySelector('.section_child').innerHTML = '';
202 fetchArticles(bloc_id);
196 203
197 console.log('ordre ' + articles_order_select); 204 console.log('ordre ' + articles_order_select);
198 } 205 }
199 else{ 206 else{
200 console.log("Erreur au changement de l'ordre d'affichage côté serveur"); 207 console.log("Erreur côté serveur au changement de l'ordre d'affichage");
201 } 208 }
202 }) 209 })
203 .catch(error => { 210 .catch(error => {
@@ -219,10 +226,10 @@ function changePresentation(bloc_id){
219 document.getElementById(bloc_id).className = presentation; 226 document.getElementById(bloc_id).className = presentation;
220 document.getElementById(bloc_id).querySelector(".section_child").style.gridTemplateColumns = presentation === 'grid' ? 'repeat(auto-fit, minmax(' + data.cols_min_width + 'px, 1fr))' : ''; 227 document.getElementById(bloc_id).querySelector(".section_child").style.gridTemplateColumns = presentation === 'grid' ? 'repeat(auto-fit, minmax(' + data.cols_min_width + 'px, 1fr))' : '';
221 document.getElementById('cols_min_width_edit_' + bloc_id).className = presentation === 'grid' ? '' : 'hidden'; 228 document.getElementById('cols_min_width_edit_' + bloc_id).className = presentation === 'grid' ? '' : 'hidden';
222 console.log('changement de présentation'); 229 console.log('Changement de présentation');
223 } 230 }
224 else{ 231 else{
225 console.log('Erreur au changement de présentation côté serveur'); 232 console.log('Erreur côté serveur au changement de présentation');
226 } 233 }
227 }) 234 })
228 .catch(error => { 235 .catch(error => {
@@ -230,6 +237,7 @@ function changePresentation(bloc_id){
230 }); 237 });
231} 238}
232 239
240// ressemble à changePaginationLimit
233function changeColsMinWidth(bloc_id){ 241function changeColsMinWidth(bloc_id){
234 const cols_min_width_input = document.getElementById('cols_min_width_select_' + bloc_id); 242 const cols_min_width_input = document.getElementById('cols_min_width_select_' + bloc_id);
235 243
@@ -250,10 +258,58 @@ function changeColsMinWidth(bloc_id){
250 if(data.success){ 258 if(data.success){
251 document.getElementById(bloc_id).className = 'grid'; 259 document.getElementById(bloc_id).className = 'grid';
252 document.getElementById(bloc_id).querySelector(".section_child").style.gridTemplateColumns = 'repeat(auto-fit, minmax(' + data.cols_min_width + 'px, 1fr))'; 260 document.getElementById(bloc_id).querySelector(".section_child").style.gridTemplateColumns = 'repeat(auto-fit, minmax(' + data.cols_min_width + 'px, 1fr))';
253 console.log('changement de la largeur minimum en mode grille'); 261 console.log('Changement de la largeur minimum en mode grille');
262 }
263 else{
264 console.log('Erreur côté serveur au changement du nb de colonnes en mode grille');
265 }
266 })
267 .catch(error => {
268 console.error('Erreur:', error);
269 });
270}
271
272// ressemble à changeColsMinWidth
273function changePaginationLimit(bloc_id){
274 const pagination_limit_input = document.getElementById('pagination_limit_' + bloc_id);
275
276 if(pagination_limit_input.value > 30){
277 pagination_limit_input.value = 30;
278 }
279 else if(pagination_limit_input.value < 0){
280 pagination_limit_input.value = 0; // fait joli dans la BDD, les valeurs négatives ont le même effet que 0
281 }
282
283 fetch('index.php?bloc_edit=change_pagination_limit', {
284 method: 'POST',
285 headers: { 'Content-Type': 'application/json' },
286 body: JSON.stringify({ id: bloc_id, pagination_limit: pagination_limit_input.value })
287 })
288 .then(response => response.json())
289 .then(data => {
290 if(data.success){
291 const parent = document.getElementById(bloc_id).querySelector('.section_child');
292 const articles_list = parent.querySelectorAll('article');
293
294 if(data.new_limit > data.old_limit || data.new_limit <= 0){ // si 0, fetchArticles va TOUT chercher!
295 parent.innerHTML = ''; // pas opti, mais améliorer ça serait très compliqué
296 fetchArticles(bloc_id);
297 }
298 else if(data.new_limit < articles_list.length){
299 // retirer les articles
300 const articles_array = Array.from(articles_list).slice(0, data.new_limit);
301 parent.innerHTML = '';
302 for(let i = 0; i < articles_array.length; i++){
303 parent.appendChild(articles_array[i]);
304 }
305 // remettre le bouton "Articles suivants"
306 document.getElementById(bloc_id).querySelector('.fetch_articles').querySelector('button').className = '';
307 }
308
309 console.log("Changement du nombre d'articles affichés simultanément dans ce bloc");
254 } 310 }
255 else{ 311 else{
256 console.log('Erreur au changement du nb de colonnes en mode grille ´té serveur'); 312 console.log("Erreur côté serveur au changement du nb d'éléments affichés par la pagination");
257 } 313 }
258 }) 314 })
259 .catch(error => { 315 .catch(error => {
diff --git a/public/js/tinymce.js b/public/js/tinymce.js
index 97ecad8..d2f9c46 100644
--- a/public/js/tinymce.js
+++ b/public/js/tinymce.js
@@ -1,5 +1,5 @@
1// code à réorganiser 1// code à réorganiser
2// seule certaines fonctions ont leur place dans Editor, d'autres servent à manipuler les articles d'une autre manière (déplacer, supprimer...) 2// seules certaines fonctions ont leur place dans Editor, d'autres servent à manipuler les articles d'une autre manière (déplacer, supprimer...)
3// => encapsuler Editor dans une classe Article (comme la balise) qui existe même quand l'éditeur est fermé 3// => encapsuler Editor dans une classe Article (comme la balise) qui existe même quand l'éditeur est fermé
4 4
5 5
@@ -292,7 +292,7 @@ class Editor
292 } 292 }
293 293
294 submit(clone = null){ 294 submit(clone = null){
295 var content; 295 let content;
296 const params = new URL(document.location).searchParams; // "search" = ? et paramètres, searchParams = objet avec des getters 296 const params = new URL(document.location).searchParams; // "search" = ? et paramètres, searchParams = objet avec des getters
297 // à comparer avec: new URLSearchParams(window.location.search); 297 // à comparer avec: new URLSearchParams(window.location.search);
298 // c'est pareil ou pas? 298 // c'est pareil ou pas?
@@ -302,7 +302,7 @@ class Editor
302 const prefixes = ['t', 'p', 'i', 'd']; 302 const prefixes = ['t', 'p', 'i', 'd'];
303 const allElemsWithId = document.querySelectorAll('.data'); 303 const allElemsWithId = document.querySelectorAll('.data');
304 content = {}; 304 content = {};
305 var id_from_builder; 305 let id_from_builder;
306 306
307 allElemsWithId.forEach(element => { 307 allElemsWithId.forEach(element => {
308 const first_letter = element.id.charAt(0).toLowerCase(); 308 const first_letter = element.id.charAt(0).toLowerCase();
@@ -394,14 +394,14 @@ class Editor
394// restera ici jusqu'à ce que la gestion des balises soient faite ailleurs 394// restera ici jusqu'à ce que la gestion des balises soient faite ailleurs
395function makeNewArticleButtons(id, article_id, clone, placement = 'last') 395function makeNewArticleButtons(id, article_id, clone, placement = 'last')
396{ 396{
397 var share_btn = document.querySelector(`.share.hidden`); // combinaison de deux classes 397 let share_btn = document.querySelector(`.share.hidden`); // combinaison de deux classes
398 var new_btn = document.getElementById(`new-${id}`); 398 let new_btn = document.getElementById(`new-${id}`);
399 var edit_btn = document.getElementById(`edit-${id}`); 399 let edit_btn = document.getElementById(`edit-${id}`);
400 var pos_up_btn = document.getElementById(`position_up-${id}`); 400 let pos_up_btn = document.getElementById(`position_up-${id}`);
401 var pos_down_btn = document.getElementById(`position_down-${id}`); 401 let pos_down_btn = document.getElementById(`position_down-${id}`);
402 var delete_btn = document.getElementById(`delete-${id}`); 402 let delete_btn = document.getElementById(`delete-${id}`);
403 var cancel_btn = document.getElementById(`cancel-${id}`); 403 let cancel_btn = document.getElementById(`cancel-${id}`);
404 var submit_btn = document.getElementById(`submit-${id}`); 404 let submit_btn = document.getElementById(`submit-${id}`);
405 405
406 share_btn.classList.remove('hidden'); 406 share_btn.classList.remove('hidden');
407 new_btn.classList.add('hidden'); 407 new_btn.classList.add('hidden');
@@ -412,8 +412,8 @@ function makeNewArticleButtons(id, article_id, clone, placement = 'last')
412 //cancel_btn.classList.add('hidden'); 412 //cancel_btn.classList.add('hidden');
413 //submit_btn.classList.add('hidden'); 413 //submit_btn.classList.add('hidden');
414 414
415 var article = document.getElementById(id); 415 let article = document.getElementById(id);
416 var article_elem_parent = findParentByTagName(article, 'article'); 416 let article_elem_parent = findParentByTagName(article, 'article');
417 417
418 share_btn.setAttribute('onclick', "copyInClipBoard('" + window.location.href + article_id + "')"); // # de l'ancre ajouté au clic sur le lien ouvrant l'éditeur 418 share_btn.setAttribute('onclick', "copyInClipBoard('" + window.location.href + article_id + "')"); // # de l'ancre ajouté au clic sur le lien ouvrant l'éditeur
419 article.id = article_id; 419 article.id = article_id;
@@ -430,7 +430,7 @@ function makeNewArticleButtons(id, article_id, clone, placement = 'last')
430 submit_btn.id = 'submit-' + article_id; 430 submit_btn.id = 'submit-' + article_id;
431 submit_btn.querySelector('button').setAttribute('onclick', "submitArticle('" + article_id + "')"); 431 submit_btn.querySelector('button').setAttribute('onclick', "submitArticle('" + article_id + "')");
432 432
433 var section_child = article_elem_parent.parentNode.querySelector('.section_child'); // renommer section_child 433 let section_child = article_elem_parent.parentNode.querySelector('.section_child'); // renommer section_child
434 434
435 // parentNode vise la balise section 435 // parentNode vise la balise section
436 article_elem_parent.parentNode.replaceChild(clone.cloneNode(true), article_elem_parent); // clone du squelette pour le garder intact 436 article_elem_parent.parentNode.replaceChild(clone.cloneNode(true), article_elem_parent); // clone du squelette pour le garder intact