-
- Un projet est un ensemble d'efforts fournis de manière limitée dans le temps afin de produire un résultat
- unique.
- La gestion de projet met en oeuvre un ensemble de techniques et de compétences pour garantir le succès
- d'un
- projet.
-
- Loi de Parkinson : le travail s'étale de façon à occuper tout le temps disponible pour son achèvement.
- Loi de Hofstadter: il est presque impossible de prévoir le temps qui sera nécessaire à l'accomplissement
- d'une
- tâche complexe.
- Principe de Pareto : 20% des efforts produisent 80% des effets.
-
- Loi de Conway : un produit est le reflet de l'organisation qui l'a conçu.
- On ne peut améliorer que ce que l'on mesure : résultats, performances,...
-
- La tranquillité ce n'est pas l'inaction.
-
-
-
-
- NB : En Tchèque, SMETI c'est la poussière (littéralement : "ce qui peut être balayé")
-
-
-
Explications
-
- L'objectif de cette page est de présenter des données sous forme de tableau.
- La page permet en outre :
-
-
De rappeler l'identité visuelle : logo, bannière
-
De naviguer dans l'application
-
D'accéder à une synthèse et à une explication des données
-
-
-
- Le header est une bannière qui fait 30% du viewport.
- Elle contient une image de background alignée à gauche et un texte aligné à droite.
-
-
- Lorsque le header sort de la partie visible de la page :
-
-
La barre de navigation devient "collée" au haut de page.
-
Le pied de tableau devient "collé" en bas de page
-
le logo apparaît à gauche de la barre de navigation.
-
-
-
Lorsque le tableau sort de la partie visible de la page, le footer et la zone d'explication peuvent occuper
- toute
- la page.
-
Provident pariatur fugit sint autem laudantium omnis. Dolores repudiandae voluptatem molestiae ratione placeat
- similique eaque. Aliquam sit ullam non non qui. Dicta molestiae neque repellendus dicta iure tempora. Et ipsam
- voluptatum nesciunt eligendi. Eos harum rerum vitae.
-
-
Focus sur la gestion des thèmes
-
- Voici comment s'opère la gestion des couleurs.
- Dans le default.css, la section CSS root contient des variables CSS.
- On a le triplet (R,G,B) de la couleur dominante et celui de la couleur de fond.
- Ces couleurs sont respectivement appelées "sombre" et "clair".
-
- Des variables sont ensuite définies pour décliner des dégradés de couleurs.
-
-
- Soit par ajout de transparence, ce sont les variables --nuance-{sombre|clair}-alpha-XX
-
- Soit par calul de dégradé
-
-
- Enfin une batterie de fonctions javascript permettent de modifier à la volée les couleurs "sombre" et "clair".
-
+
+
Modèle de page HTML pour visualisation de données
+
La page est composée comme suit :
+
+
Un header avec le titre et un logo
+
Un bandeau de navigation
+
Une zone pour la synthèse des informations
+
Un tableau d'affichage des données
+
Un footer avec le texte explicatif
+
+
Les règles de comportement de la page:
+
+
Le bandeau de navigation est "sticky" en haut de page.
+
L'entête du tableau de données est "sticky" sous le bandeau de navigation.
+
Lorsque la zone de synthèse n'est plus visible, le pied de tableau est "sticky" en bas de page.
+
+
\ No newline at end of file
diff --git a/frontend/src/scripts/UI/CSS.js b/frontend/src/scripts/UI/CSS.js
new file mode 100644
index 0000000..afd9359
--- /dev/null
+++ b/frontend/src/scripts/UI/CSS.js
@@ -0,0 +1,33 @@
+ // Get the CSS root element
+ const rootCSS = document.querySelector(':root');
+
+ // Create a function for getting a variable value
+ function CSSgetSombre() {
+ let rs = getComputedStyle(rootCSS);
+ alert("The value of --couleur-sombre is: " + rs.getPropertyValue('--couleur-sombre'));
+ }
+
+ function CSSsetSombre(vr, vg, vb) {
+ // Couleur
+ rootCSS.style.setProperty('--r-sombre', vr);
+ rootCSS.style.setProperty('--g-sombre', vg);
+ rootCSS.style.setProperty('--b-sombre', vb);
+ // Logo
+ // let logo = document.querySelector('header>#logo>svg');
+ // if (logo) logo.style.fill = 'rgb(' + vr + ',' + vg + ',' + vb + ')';
+ }
+ function CSSsetClair(vr, vg, vb) {
+ // Couleur
+ rootCSS.style.setProperty('--r-clair', vr);
+ rootCSS.style.setProperty('--g-clair', vg);
+ rootCSS.style.setProperty('--b-clair', vb);
+ }
+
+ function CSSswitchCouleurTexte() {
+ let rs = getComputedStyle(rootCSS);
+ let actuel = rs.getPropertyValue('--couleur-texte');
+ if (actuel == 'black')
+ rootCSS.style.setProperty('--couleur-texte', 'var(--couleur-sombre)');
+ else
+ rootCSS.style.setProperty('--couleur-texte', 'black');
+ }
diff --git a/frontend/src/scripts/UI/IntersectionObserver/footer.js b/frontend/src/scripts/UI/IntersectionObserver/footer.js
index 87f2330..df6e1d9 100644
--- a/frontend/src/scripts/UI/IntersectionObserver/footer.js
+++ b/frontend/src/scripts/UI/IntersectionObserver/footer.js
@@ -3,10 +3,10 @@ const handleFooterIntersection = function (entries) {
// Loop through all the observed elements
entries.forEach(entry => { // Check if the element is intersecting the viewport
if (entry.isIntersecting) {
- console.log("The footer is visible in the viewport");
+ msgConsole('IntersectionObserver','The footer is visible in the viewport');
if (typeof footerIsNowVisible === 'function') footerIsNowVisible(entry);
} else {
- console.log("The footer is invisible in the viewport");
+ msgConsole('IntersectionObserver','The footer is invisible in the viewport');
if (typeof footerIsNowInvisible === 'function') footerIsNowInvisible(entry);
}
});
diff --git a/frontend/src/scripts/UI/IntersectionObserver/header.js b/frontend/src/scripts/UI/IntersectionObserver/header.js
index b679147..5d56544 100644
--- a/frontend/src/scripts/UI/IntersectionObserver/header.js
+++ b/frontend/src/scripts/UI/IntersectionObserver/header.js
@@ -1,13 +1,19 @@
// Create a function that will handle any intersection between some elements and the viewport.
const handleHeaderIntersection = function (entries) {
entries.forEach(entry => {
- if (typeof headerIsVisible === 'function') headerIsNowVisible(entry.isIntersecting);
+ if (entry.isIntersecting) {
+ msgConsole('IntersectionObserver','The header is visible in the viewport');
+ if (typeof headerIsNowVisible === 'function') headerIsNowVisible(entry);
+ } else {
+ msgConsole('IntersectionObserver','The header is invisible in the viewport');
+ if (typeof headerIsNowInvisible === 'function') headerIsNowInvisible(entry);
+ }
});
}
const section_header = document.querySelector("header");
if (section_header) {
- const headerObserver = new IntersectionObserver(handleSynthesisIntersection);
+ const headerObserver = new IntersectionObserver(handleHeaderIntersection);
if (headerObserver) headerObserver.observe(section_header);
} else myLog('No header to observe');
diff --git a/frontend/src/scripts/UI/IntersectionObserver/synthesis.js b/frontend/src/scripts/UI/IntersectionObserver/synthesis.js
index a09c47b..44c6581 100644
--- a/frontend/src/scripts/UI/IntersectionObserver/synthesis.js
+++ b/frontend/src/scripts/UI/IntersectionObserver/synthesis.js
@@ -3,11 +3,11 @@ const handleSynthesisIntersection = function (entries) {
entries.forEach(entry => {
// Check if the element is intersecting the viewport
if (entry.isIntersecting) {
- myLog("The synthesis is visible in the viewport");
- if (typeof synthesisTopIsNowVisible === 'function') synthesisIsNowVisible(entry);
+ msgConsole('IntersectionObserver',"The synthesis is visible in the viewport");
+ if (typeof synthesisIsNowVisible === 'function') synthesisIsNowVisible(entry);
} else {
- myLog("The synthesis is invisible in the viewport");
- if (typeof synthesisTopIsNowInvisible === 'function') synthesisIsNowInvisible(entry);
+ msgConsole('IntersectionObserver',"The synthesis is invisible in the viewport");
+ if (typeof synthesisIsNowInvisible === 'function') synthesisIsNowInvisible(entry);
}
});
}
diff --git a/frontend/src/scripts/UI/datagrid.js b/frontend/src/scripts/UI/datagrid.js
index d4ab6e6..47d35cb 100644
--- a/frontend/src/scripts/UI/datagrid.js
+++ b/frontend/src/scripts/UI/datagrid.js
@@ -1,5 +1,5 @@
// ---------------------------------------------------------------------------------------
-// ---- Fonctions pour charger des lignes identiques dans le tableau
+// ---- Fonction pour charger des lignes identiques dans le tableau
// ---------------------------------------------------------------------------------------
function datagridLignesIdentiques(nblignes, valeur) {
let element = document.querySelector('#datagrid');
@@ -30,14 +30,14 @@ function datagridLignesIdentiques(nblignes, valeur) {
element.innerHTML = contenu;
}
// ---------------------------------------------------------------------------------------
-// ---- Fonctions pour charger des lignes vides
+// ---- Fonction pour charger des lignes vides
// ---------------------------------------------------------------------------------------
function datagridEmptyLines(nblignes) {
return datagridLignesIdentiques(nblignes,' ');
}
// ---------------------------------------------------------------------------------------
-// ---- Fonctions utilitaires
+// ---- Fonction utilitaires
// ---------------------------------------------------------------------------------------
function datagridLoading() {
let nblignes = 25 + Math.floor(Math.random() * 475); // Nbre entre ntre 25 et 500
@@ -45,7 +45,7 @@ function datagridLoading() {
}
// ---------------------------------------------------------------------------------------
-// ---- Fonctions pour charger des données au hasard dans le datagrid
+// ---- Fonction pour charger des données au hasard dans le datagrid
// ---------------------------------------------------------------------------------------
var nbCols = 5;
@@ -144,4 +144,5 @@ datagrid_hooks['random'] = function(){
let element = document.querySelector('#datagrid');
let nblignes = 25 + Math.floor(Math.random() * 475); // Nbre entre ntre 25 et 500
setDatagridRandomValues(element, nbCols, nblignes)
-};
\ No newline at end of file
+};
+
diff --git a/frontend/src/scripts/UI/modal.js b/frontend/src/scripts/UI/modal.js
index 606d079..df61edb 100644
--- a/frontend/src/scripts/UI/modal.js
+++ b/frontend/src/scripts/UI/modal.js
@@ -2,7 +2,7 @@ class Modal {
// TODO : industrialiser en créant une classe
}
-const modalDialog = document.getElementById('fiche');
+const modalDialog = document.getElementById('modal');
var modal_hooks = [];
@@ -138,7 +138,7 @@ function modalSetFooter(valeur)
*/
function open_modal_hook(parametre)
{
- console.log("open_modal_hook pour "+parametre);
+ myLog("open_modal_hook pour "+parametre);
let hook = null;
let paramSplit = parametre.split(':');
paramSplit.forEach(element => {
@@ -147,7 +147,7 @@ function open_modal_hook(parametre)
hook = modal_hooks[elemSplit[1]];
}
});
- if ((hook===null)||(hook===undefined)) hook = modal_hooks['ITEM'];
+ if ((hook===null)||(hook===undefined)) hook = modal_hooks['random'];
return hook(parametre);
}
diff --git a/frontend/src/scripts/default.js b/frontend/src/scripts/default.js
index b3eb4c3..c78df31 100644
--- a/frontend/src/scripts/default.js
+++ b/frontend/src/scripts/default.js
@@ -1,9 +1,7 @@
- window.addEventListener('load', function() {
- window.scrollTo(0,0);
- }, false);
+ window.addEventListener('load', function() { window.scrollTo(0,0); }, false);
/*
- * Personnalisation
+ * Personnalisation HEADER visibility
* Que se passe-t-il lorsque la bannière est invisible ?
*/
function setLogoVisiblity(visibilityFlag) {
@@ -13,31 +11,24 @@
element.style.visibility = value;
}
- function setNavbarStickOnTop(topFlag) {
- let element = document.querySelector("#nav");
- if (topFlag) element.style.setProperty('top', '0px');
- else element.style.removeProperty('top');
+ function setSynthesisTopHeight(hauteur) {
+ let element = document.querySelector("#synthesis_top");
+ element.style.height = hauteur+'px';
}
- function setDataGridFootSticky(stickyFlag) {
- let element = null;
- if (stickyFlag) {
- //
- // Mettre le tfoot sticky au bottom
- //
- element = document.querySelector("#datagrid>table>tfoot");
- element.style.setProperty('position', 'sticky');
- element.style.setProperty('bottom', '0px');
- element.style.setProperty('z-index', '30');
- } else {
- element = document.querySelector("#datagrid>table>tfoot");
- element.style.setProperty('position', 'relative');
- element.style.setProperty('z-index', '10');
- }
+ function headerIsNowVisible(header) {
+ setLogoVisiblity(false);
+ setSynthesisTopHeight(6);
+ }
+
+ function headerIsNowInvisible(header) {
+ setLogoVisiblity(true);
+ setSynthesisTopHeight(80);
+ scrollToElement('#synthesis_top');
}
/*
- * Personnalisation
+ * Personnalisation SYNTHESIS visibility
* Que se passe-t-il lorsque la synthèse est invisible ?
*/
function setDatagridFirstColSticky(stickyFlag) {
@@ -94,48 +85,24 @@
}
}
- function smoothJump(hash) {
- location.replace("#" + hash);
- }
-
- function documentGetElementById(id){
- element = document.getElementById(id);
- if (element === null ) return '';
- return element.value;
- }
-
- function setElementHeight(elementSelector, elementHeight) {
- let element = document.querySelector(elementSelector);
- element.style.height = elementHeight;
- }
-
- function slideElement(elementSelector, elementHeight) {
- let element = document.querySelector(elementSelector);
- element.style.transition = "all 2s ease-in-out";
- setElementHeight(elementSelector, elementHeight);
- }
-
- function scrollToElement(elementSelector) {
- let element = document.querySelector(elementSelector);
- element.scrollIntoView({ behavior: 'smooth' });
- }
-
- function gotoHelp() {
- scrollToElement('#synthesis');
- setTimeout(scrollToElement, 500, '#footer');
- }
+ function setDataGridFootSticky(stickyFlag) {
+ let element = document.querySelector("#datagrid>table>tfoot");;
+ if (stickyFlag) {
+ //
+ // Mettre le tfoot sticky au bottom
+ //
+ element.style.setProperty('position', 'sticky');
+ element.style.setProperty('bottom', '0px');
+ element.style.setProperty('z-index', '30');
- function gotoTop() {
- let element = document.querySelector('header');
- window.scrollTo(0, element.offsetHeight + 1);
- }
+ setDataGridHeadSticky(stickyFlag);
- function headerIsVisible(flagVisible) {
- setLogoVisiblity(!flagVisible);
- if (!flagVisible) gotoTop();
+ } else {
+ element.style.setProperty('position', 'relative');
+ element.style.setProperty('z-index', '10');
+ }
}
-
- function synthesisTopIsNowVisible(entry) {
+ function synthesisIsNowVisible(entry) {
setDatagridHeadSticky(false);
setDataGridFootSticky(false);
@@ -146,7 +113,7 @@
myLog('Trigger synthesis is visible');
}
- function synthesisTopIsNowInvisible(entry) {
+ function synthesisIsNowInvisible(entry) {
setDatagridHeadSticky(true);
setDataGridFootSticky(true);
@@ -157,104 +124,52 @@
myLog('Trigger synthesis is invisible');
}
- function initDatagrid()
- {
- let type = getContexteValeur('type');
- switch(type){
- case 'TODO':
- initDatagridTodos();
- break;
- default:
- initDatagridItems();
- break;
- }
- }
-
- function changeModeAffichage(valeur, texte)
- {
- let type='TODO';
-
- switch(valeur){
- case 'absences':
- case 'releases':
- case 'rdv':
- case 'feries':
- case 'taches':
- type='TACHE';
- break;
- }
-
- setContexteValeur('mode_affichage', valeur);
-
- setContexteValeur('type_courant', type);
- setFiltreValeur('type',type);
-
- setFilAriane(['Home', 'List', texte]);
-
- return afficherItems();
+ function smoothJump(hash) {
+ location.replace("#" + hash);
}
- function changeModeAffichageEvent(e)
- {
- return changeModeAffichage(e.target.value, e.target.options[e.target.selectedIndex].text);
+ function documentGetElementById(id){
+ element = document.getElementById(id);
+ if (element === null ) return '';
+ return element.value;
}
- function changeAffichageItemsTermine(e)
- {
- setContexteValeur('termine', e.target.value);
-
- setFiltreValeur('status',e.target.value);
-
- afficherItems();
+ function setElementHeight(elementSelector, elementHeight) {
+ let element = document.querySelector(elementSelector);
+ element.style.height = elementHeight;
}
- function changeAffichageItemsPrestations(e)
- {
- setContexteValeur('prestation', e.target.value);
-
- afficherItems();
+ function slideElement(elementSelector, elementHeight) {
+ let element = document.querySelector(elementSelector);
+ element.style.transition = "all 2s ease-in-out";
+ setElementHeight(elementSelector, elementHeight);
}
-
- function changeFiltreClient(e)
- {
- let valeur = e.target.value;
- if (valeur == 'ALL') valeur='';
- setContexteValeur('client', valeur);
- setFiltreValeur('client', valeur);
-
- afficherItems();
+ function scrollToElement(elementSelector) {
+ let element = document.querySelector(elementSelector);
+ element.scrollIntoView({ behavior: 'smooth' });
}
- function changeAffichageNiveauxEvent(e)
- {
- setContexteValeur('level', e.target.value);
-
- setFiltreValeur('level', e.target.value);
+ function gotoHelp() {
+ scrollToElement('#synthesis');
+ setTimeout(scrollToElement, 500, '#footer');
+ }
- afficherItems();
+ function gotoTop() {
+ let element = document.querySelector('header');
+ window.scrollTo(0, element.offsetHeight + 1);
}
- function changeCalendarEvent(e)
+ function initDatagrid()
{
- let valeur = todayStringDate;
- switch(parseInt(e.target.value)) {
- case 2 :
- valeur = todayStringDate.substring(0,4)+'0101';
- break;
- }
- setContexteValeur('debut',valeur);
- setFiltreValeur('debut', valeur);
- afficherItems();
+ let fonctionAffichageDataGrid = datagrid_hooks['random'];
+ datagridLoading();
+ fonctionAffichageDataGrid();
}
- function updateValue(e) {
- if (e.target.value != '') editerItem(-1, e.target.value);
- e.target.value = '';
- }
- function afficher_synthese(mode) {
+ function initSynthese(mode) {
let synthesis_body = document.querySelector('#synthesis_body');
if (synthesis_body) {
synthesis_body.innerHTML='';
@@ -266,7 +181,7 @@
}
}
- function afficher_footer(mode) {
+ function initFooter(mode) {
let footer_body = document.querySelector('footer');
if (footer_body) {
footer_body.innerHTML='';
@@ -279,219 +194,23 @@
}
function activeMenu(element) {
- datagridEmptyLines(50);
-
- activeMode(element.innerText);
-
- gotoTop();
- }
-
- function modeToAffichage(mode)
- {
- let retour='taches';
- switch (mode) {
- case 'Releases':
- retour='releases';
- break;
- case 'Hollidays':
- retour='feries';
- break;
- case 'Rendez-Vous':
- retour='rdv';
- break;
- case 'Rendez-Vous':
- retour='rdv';
- break;
- case 'Items':
- retour='items';
- break;
- case 'Project':
- retour='prestations';
- break;
- default:
- case 'Tasks':
- retour='taches';
- break;
- }
- return retour;
+ scrollToElement('#synthesis_top');
+ activeMode(element.innerText);
}
-
+
function activeMode(mode) {
- setContexteValeur('type_courant', 'TODO');
- setContexteValeur('items_type', 'items');
-
- switch (mode) {
- case 'Tree':
- case 'TreeList' :
- case 'List':
- mode='Tasks';
- case 'Tasks':
- case 'Releases':
- case 'Hollidays':
- case 'Rendez-Vous':
- case 'Items':
- setContexteValeur('mode_feuille', false);
- setContexteValeur('type_courant', 'TACHE');
-
- setContexteValeur('mode_affichage', modeToAffichage(mode));
-
- afficher_synthese('taches');
- afficher_footer('taches');
-
- setFilAriane(['Home', 'TreeList', mode]);
-
- initDatagridItems();
- break;
-
- case 'Project':
- setContexteValeur('mode_feuille', false);
- setContexteValeur('termine', true);
- setContexteValeur('prestation', true);
- setContexteValeur('type_courant', 'PRESTATION');
-
- setContexteValeur('mode_affichage', modeToAffichage(mode));
-
- afficher_synthese('project');
- afficher_footer('taches');
-
- setFilAriane(['Home', 'Project']);
-
- initDatagridItems();
- break;
-
- case 'Plan':
- case 'Planning':
-
- setFilAriane([mode]);
-
- setContexteValeur('type_courant', 'TODO');
- setContexteValeur('mode_feuille', true);
- setContexteValeur('mode_affichage', 'planning');
- setContexteValeur('termine', 'non');
-
- afficher_synthese('planning');
- afficher_footer('planning');
-
- initDatagridItems();
- break;
-
- case 'Calendar':
- setFilAriane(['Todo', mode]);
-
- setContexteValeur('mode_feuille', true);
- setContexteValeur('mode_affichage', 'calendar_intervenants');
- setContexteValeur('debut', todayStringDate);
-
- afficher_synthese('calendrier');
- afficher_footer('calendrier');
-
- initDatagridItems();
- break;
-
- case 'Administration':
- setFilAriane(['Todo', mode]);
- initAdministration();
- break;
-
- case 'Status':
- setFilAriane(['Todo', 'Administration', mode]);
- initDatagridStatus();
- break;
-
- case 'Clients':
- setFilAriane(['Todo', 'Administration', mode]);
- initDatagridClients();
- break;
-
- case 'Collaborateurs':
- setFilAriane(['Todo', 'Administration', mode]);
- initDatagridCollaborateurs();
- break;
-
- default:
- case 'Home':
- mode='Todo';
- case 'Todo':
- setFilAriane(['Home', mode]);
-
- setDefaultContext();
-
- setContexteValeur('type', 'TODO');
- setContexteValeur('items_type', 'todos');
- setContexteValeur('mode_affichage', 'todos');
- setContexteValeur('mode_feuille', true);
- setContexteValeur('parent', '1');
-
- afficher_synthese('accueil');
- afficher_footer('accueil');
-
- initDatagridItems();
- break;
- }
- }
-
- function initAdministration() {
- let element = document.querySelector('#synthesis_middle');
- contenu = '