mirror of
https://git.topisto.net/tibo/template.git
synced 2026-03-31 21:39:10 +00:00
initialisation with SMETI code
This commit is contained in:
19
frontend/src/scripts/UI/IntersectionObserver/footer.js
Normal file
19
frontend/src/scripts/UI/IntersectionObserver/footer.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// Create a function that will handle any intersection between some elements and the viewport.
|
||||
const handleFooterIntersection = function (entries) {
|
||||
// Loop through all the observed elements
|
||||
for (let entry of entries) {
|
||||
// Check if the element is intersecting the viewport
|
||||
if (entry.isIntersecting) {
|
||||
console.log("The footer is visible in the viewport");
|
||||
if (typeof footerIsNowVisible === 'function') footerIsNowVisible(entry);
|
||||
} else {
|
||||
console.log("The footer is invisible in the viewport");
|
||||
if (typeof footerIsNowInvisible === 'function') footerIsNowInvisible(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
const footer = document.querySelector("#footer");
|
||||
if (footer) {
|
||||
const footerObserver = new IntersectionObserver(handleFooterIntersection);
|
||||
footerObserver.observe(footer);
|
||||
}
|
||||
12
frontend/src/scripts/UI/IntersectionObserver/header.js
Normal file
12
frontend/src/scripts/UI/IntersectionObserver/header.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const headerObserver = new IntersectionObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
if (typeof headerIsVisible === 'function') headerIsVisible(entry.isIntersecting);
|
||||
});
|
||||
});
|
||||
|
||||
const header = document.querySelector("header");
|
||||
if (header) headerObserver.observe(header);
|
||||
else myLog('No header to observe');
|
||||
|
||||
|
||||
|
||||
17
frontend/src/scripts/UI/IntersectionObserver/synthesis.js
Normal file
17
frontend/src/scripts/UI/IntersectionObserver/synthesis.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const synthesisTopObserver = new IntersectionObserver(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') synthesisTopIsNowVisible(entry);
|
||||
} else {
|
||||
myLog("The synthesis is invisible in the viewport");
|
||||
if (typeof synthesisTopIsNowInvisible === 'function') synthesisTopIsNowInvisible(entry);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const synthesis_top = document.querySelector("#synthesis_top");
|
||||
if (synthesis_top) synthesisTopObserver.observe(synthesis_top);
|
||||
else myLog('No #synthesis_top to obseve');
|
||||
|
||||
855
frontend/src/scripts/UI/calendrier.js
Normal file
855
frontend/src/scripts/UI/calendrier.js
Normal file
@@ -0,0 +1,855 @@
|
||||
// Affichage une colonne par intervenant
|
||||
//function afficher_planning_atos_2(unModeAffichage) {
|
||||
|
||||
|
||||
function ajouterClientColonne(client, colonne, indexCol) {
|
||||
if (colonne[indexCol].indexOf(client) == -1) {
|
||||
colonne[indexCol] += '/' + client;
|
||||
}
|
||||
}
|
||||
|
||||
datagrid_hooks['calendar_intervenants'] = function(){
|
||||
let element = document.querySelector("#datagrid");
|
||||
|
||||
let filtre = getTrigrammeCollaborateur(getContexteValeur('intervenant'));
|
||||
|
||||
let lebreak = 0;
|
||||
let annee = new Date().getFullYear();
|
||||
let ladate = dateGetPrevMonday(new Date(annee, 0, 1));
|
||||
let ladateToString;
|
||||
let intervenants = [];
|
||||
let jours_semaine = ["D", "L", "M", "M", "J", "V", "S"];
|
||||
let lastWeekNumber = 99;
|
||||
let tamponWeek = "";
|
||||
let tamponWeekFlag = false;
|
||||
let header = '';
|
||||
|
||||
let jours_feries = [];
|
||||
|
||||
let contenu = '';
|
||||
|
||||
// Tout le calendirer est encapsulé dans une cellule d'un tableau
|
||||
// Permet de garantir le comportement du scroll avec le sticky des thead et tfoot
|
||||
/*
|
||||
contenu += '<table width="100vw">';
|
||||
contenu += '<thead><tr><th>Calendrier</th></tr></thead>';
|
||||
contenu += '<tr><td align="center" style="background:#aaaaaa">';
|
||||
*/
|
||||
|
||||
sortItemsByStartDate();
|
||||
|
||||
setItemsVisibility();
|
||||
|
||||
if (getContexteValeur('debut'))
|
||||
{
|
||||
ladate = stringdateToDate(getContexteValeur('debut'));
|
||||
ladate = dateGetPrevMonday(ladate);
|
||||
}
|
||||
|
||||
ladateToString = formatDatetoStringDate(ladate);
|
||||
|
||||
// Se limiter à un an
|
||||
annee = ladate.getFullYear() + 1;
|
||||
annee += 1;
|
||||
// Et à 2 ans si calendrier glissant
|
||||
// TODO : ajouter un contexte qui indique si on est en calendrier annuel ou glissant
|
||||
//if (select_date_debut == 2) annee += 1;
|
||||
|
||||
// Définir la liste des intervenants
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
let debut = item['debut'].substring(0,8);
|
||||
let fin = item['fin'].substring(0,8);
|
||||
|
||||
// On ne s'occupe que des feuilles
|
||||
if (item.childs.length != 0) return true;
|
||||
|
||||
// Au passage alimenter les jours fériés , mais ne pas les compter
|
||||
if (item['client'] == 'FER') {
|
||||
jours_feries.push(item['fin'].substring(0,8));
|
||||
return true;
|
||||
}
|
||||
|
||||
// On élimine ce qui est masqué
|
||||
if (!item["visible"]) return true;
|
||||
|
||||
// On élimine les items non affectés
|
||||
if (parseInt(item["intervenant"]) == 0) return true;
|
||||
|
||||
// Ne pas compter les Releases
|
||||
if (item['client'] == 'REL') return true;
|
||||
|
||||
// Appliquer le filtre
|
||||
if (filtre != 'ANO')
|
||||
if (getTrigrammeCollaborateur(item['intervenant']) != filtre) return true;
|
||||
|
||||
// On ne compte pas ce qui n'est pas dans la période concernée
|
||||
if (fin < ladateToString ) return true;
|
||||
if (fin == '99999999' ) return true;
|
||||
if (debut > (annee+'1231') ) return true;
|
||||
|
||||
if (intervenants.indexOf(item["intervenant"]) == -1) {
|
||||
intervenants.push(item["intervenant"]);
|
||||
}
|
||||
});
|
||||
intervenants.sort();
|
||||
|
||||
header += ' <th colspan="3">Calendrier</th>';
|
||||
intervenants.forEach((intervenant) => {
|
||||
let trigramme = getTrigrammeCollaborateur(intervenant);
|
||||
header += '<th colspan="11"><center>' + trigramme + "</center></th>";
|
||||
});
|
||||
|
||||
contenu += '<table width="100vw">';
|
||||
|
||||
contenu += " <thead><tr>" + header +"</tr></thead>";
|
||||
|
||||
contenu += " <tbody>";
|
||||
|
||||
let semaine_vide = "";
|
||||
let semaine_paire = false;
|
||||
let couleur = '';
|
||||
semaine_vide += '<tr class="calendrier" style="background:#777777">';
|
||||
semaine_vide += '<td width="30px" style="border-top:1px solid black;font-size:2vh">SXX</td>';
|
||||
semaine_vide += '<td colspan="' + ( 2 + (11 * intervenants.length)) + '" align="center" style="border-top:1px solid black;font-size:2vh"> </td>';
|
||||
semaine_vide += "</tr>";
|
||||
|
||||
while (annee > ladate.getFullYear()) {
|
||||
let bgcolor = "white";
|
||||
let font_weight = 'normal';
|
||||
let jour = ladate.getDay();
|
||||
let jour_courant = formatDatetoStringDate(ladate);
|
||||
let weekNumber = stringdateGetWeekOfYear(jour_courant)%100;
|
||||
let colonnes = [];
|
||||
let colonnes_bw = []; // Before Work
|
||||
let colonnes_am = []; // Matin
|
||||
let colonnes_md = []; // Midi
|
||||
let colonnes_pm = []; // Après-Midi
|
||||
let colonnes_aw = []; // After Work
|
||||
let style_tr = '';
|
||||
let style_td = '';
|
||||
let jour_libelle = '';
|
||||
|
||||
intervenants.forEach((intervenant) => {
|
||||
colonnes.push("");
|
||||
colonnes_bw.push("");
|
||||
colonnes_am.push("");
|
||||
colonnes_md.push("");
|
||||
colonnes_pm.push("");
|
||||
colonnes_aw.push("");
|
||||
});
|
||||
|
||||
// On change de semaine
|
||||
// Si la semaine est vide, tamponWeekFlag == false
|
||||
if (weekNumber != lastWeekNumber) {
|
||||
let semaine = '';
|
||||
if (lastWeekNumber != 99) semaine = semaine_vide.replace("SXX", "S" + stringDatePadDigits(lastWeekNumber,2));
|
||||
if (tamponWeekFlag) {
|
||||
semaine = tamponWeek;
|
||||
semaine_paire = !semaine_paire;
|
||||
}
|
||||
contenu += semaine;
|
||||
tamponWeek = "";
|
||||
tamponWeekFlag = false;
|
||||
}
|
||||
|
||||
// Couleur pour les samedi et dimanche
|
||||
if (jour == 0 || jour == 6) bgcolor = "#f1d4af";
|
||||
// Couleur pour les lundi et vendredi
|
||||
if (jour == 1 || jour == 5) bgcolor = "#eeeeee";
|
||||
// Couleur pour les jours fériés
|
||||
if (jours_feries.includes(jour_courant)) bgcolor = "#f1d4af";
|
||||
|
||||
// Couleur d'aujourd'hui
|
||||
if (jour_courant == todayStringDate){
|
||||
bgcolor='#87cefa';
|
||||
font_weight='bold';
|
||||
tamponWeekFlag = true;
|
||||
}
|
||||
|
||||
items.forEach((element) => {
|
||||
let item = getItemFromElement(element);
|
||||
|
||||
let debut = item["debut"];
|
||||
let fin = item["fin"];
|
||||
let jour_debut;
|
||||
let jour_fin;
|
||||
|
||||
let ajout = false;
|
||||
|
||||
if (isDebugItem(item)){
|
||||
myLog('item ICI');
|
||||
}
|
||||
|
||||
if (!item["visible"]) return true; // Invisible
|
||||
if (item["intervenant"] == 0) return true; // Non affecté
|
||||
if (item.childs.length != 0) return true; // Noeud
|
||||
|
||||
if ((fin.substring(8,12) == '0000')||(fin.substring(8,12) == '9999')) fin = fin.substring(0,8)+'2000';
|
||||
|
||||
if (item['type'] == 'TODO') debut = fin; // Un TODO est un jalon
|
||||
|
||||
jour_debut = debut.substring(0,8);
|
||||
jour_fin = fin.substring(0,8);
|
||||
|
||||
// if (jour_debut > jour_courant) return false;
|
||||
|
||||
// Ceci n'est pas réellement planifié
|
||||
if ((jour_debut == '00000000') && (jour_fin.substring(0,8) == (1+parseInt(todayStringDate.substring(0,4))+'1231'))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// L'item débute ou finit le jour courant
|
||||
if (jour_debut == jour_courant) ajout = true;
|
||||
if (jour_fin == jour_courant) ajout = true;
|
||||
|
||||
// Le jour courant est entièrement contenu dans l'item
|
||||
if (jour_debut < jour_courant && jour_fin > jour_courant) ajout = true;
|
||||
|
||||
if (ajout) {
|
||||
let indexCol = intervenants.indexOf(item["intervenant"]);
|
||||
let client = item["client"];
|
||||
let horaire_debut = 0;
|
||||
let horaire_fin = 20;
|
||||
let colonne = null;
|
||||
|
||||
tamponWeekFlag = true;
|
||||
|
||||
if (jour_courant == jour_debut) horaire_debut = parseInt(debut.substring(8, 10));
|
||||
if (jour_courant == jour_fin) horaire_fin = parseInt(fin.substring(8, 10));
|
||||
|
||||
// Pour les releases et les jour fériés, on affiche le libellé
|
||||
if ((client == 'REL')||(client == 'FER')) {
|
||||
jour_libelle = item['libelle'];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (client == 'REL') return true;
|
||||
if (client == 'FER') return true;
|
||||
|
||||
//if (client == "ABS") bgcolor = "#f1d4af";
|
||||
//if (client == "CGI") font_weight += ";color:blue";
|
||||
|
||||
if (indexCol == -1) {
|
||||
myLog(item["intervenant"] + " inconnu");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((horaire_debut <= 9) && (horaire_fin<=9)) ajouterClientColonne(client, colonnes_bw, indexCol);
|
||||
if ((horaire_debut >= 12) && (horaire_fin<=14)) ajouterClientColonne(client, colonnes_md, indexCol);
|
||||
if ((horaire_debut >= 17) && (horaire_fin<=21)) ajouterClientColonne(client, colonnes_aw, indexCol);
|
||||
|
||||
if ((horaire_debut < 12) && (horaire_fin > 9)) ajouterClientColonne(client, colonnes_am, indexCol);
|
||||
if ((horaire_debut < 17) && (horaire_fin > 14)) ajouterClientColonne(client ,colonnes_pm, indexCol);
|
||||
}
|
||||
});
|
||||
|
||||
style_tr = 'background:'+bgcolor+';font-weight:'+font_weight;
|
||||
tamponWeek += '<tr style="'+style_tr+'" class="js-open-modal-trigger" data-modal-info="type=calendrier:jour=' + jour_courant + '">';
|
||||
|
||||
if (weekNumber != lastWeekNumber) {
|
||||
if (semaine_paire) couleur = '#eeeeee';
|
||||
else couleur = 'white';
|
||||
lastWeekNumber = weekNumber;
|
||||
/*
|
||||
tamponWeek += '<td class="calendrier" width="10px" style="font-family: fixed; width: 30px;background: ' + couleur + '; font-weight: bold" rowspan="7" align="center">';
|
||||
tamponWeek += "S" + lastWeekNumber.toLocaleString(undefined, { minimumIntegerDigits: 2 });
|
||||
tamponWeek += "</td>";
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
if (jour == 1) style_td = 'border-top:1px solid black'; // Le lundi
|
||||
|
||||
tamponWeek += '<td style="font-family: fixed; width: 30px; background:'+couleur+';text-align:center;border-right:1px solid;font-size:2vh;'+style_td+'">';
|
||||
if (jour == 4) tamponWeek += 'S'+lastWeekNumber.toLocaleString(undefined, { minimumIntegerDigits: 2 });
|
||||
tamponWeek += ' </td>';
|
||||
|
||||
tamponWeek += '<td style="font-family: fixed;font-size:2vh; width: 20px;background:'+bgcolor+';font-weight:bold;'+style_td+'">'+jours_semaine[jour]+'</td>';
|
||||
|
||||
if (jour_libelle != '' ) {
|
||||
tamponWeek += '<td style="font-family: fixed;font-size:2vh;width:80px;background:'+bgcolor+';color:red;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-right:1px solid black;'+style_td+'"><small>'+ jour_libelle +'</small></td>';
|
||||
} else {
|
||||
tamponWeek += '<td style="font-family: fixed;font-size:2vh;width: 80px;background:'+bgcolor+';font-weight:bold;border-right:1px solid;'+style_td+'">';
|
||||
tamponWeek +=
|
||||
ladate.getDate().toLocaleString(undefined, { minimumIntegerDigits: 2 }) +
|
||||
" / " +
|
||||
(ladate.getMonth() + 1).toLocaleString(undefined, { minimumIntegerDigits: 2 });
|
||||
tamponWeek += "</td>";
|
||||
}
|
||||
|
||||
intervenants.forEach((intervenant) => {
|
||||
let index = intervenants.indexOf(intervenant);
|
||||
let aligne = "center";
|
||||
let colonne = colonnes[index].substring(1);
|
||||
let colonne_bw = colonnes_bw[index];
|
||||
let colonne_am = colonnes_am[index];
|
||||
let colonne_md = colonnes_md[index];
|
||||
let colonne_pm = colonnes_pm[index];
|
||||
let colonne_aw = colonnes_aw[index];
|
||||
let style_am = "";
|
||||
let style_pm = "";
|
||||
let style_tr_td = "";
|
||||
|
||||
// if (colonne_bw != '' || colonne_am != '' || colonne_md != '' || colonne_pm != '' || colonne_aw != '') {
|
||||
//tamponWeekFlag = true;
|
||||
if (colonne != '') {
|
||||
let tempo = colonne.replace('</span>','');
|
||||
let valeurs = tempo.split('/');
|
||||
valeurs.forEach(valeur => {
|
||||
if (!colonne_am.includes(valeur)) colonne_am += '/'+valeur+'</span>';
|
||||
if (!colonne_pm.includes(valeur)) colonne_pm += '/'+valeur+'</span>';
|
||||
// if (!colonne_aw.includes(valeur)) colonne_aw += '/'+valeur+'</span>';
|
||||
})
|
||||
}
|
||||
|
||||
colonne_bw = colonne_bw.substring(1);
|
||||
colonne_am = colonne_am.substring(1);
|
||||
colonne_md = colonne_md.substring(1);
|
||||
colonne_pm = colonne_pm.substring(1);
|
||||
colonne_aw = colonne_aw.substring(1);
|
||||
|
||||
if (jour == 0 || jour ==6) {
|
||||
colonne_bw = "";
|
||||
colonne_am = "";
|
||||
colonne_md = "";
|
||||
colonne_pm = "";
|
||||
colonne_aw = "";
|
||||
}
|
||||
|
||||
style_tr = 'overflow: hidden;white-space: nowrap;text-overflow:ellipsis';
|
||||
style_tr += ';border-color:black;border-width:1px';
|
||||
style_tr += ';padding-left: 5px; padding-right: 5px';
|
||||
style_tr += ';background:' + bgcolor;
|
||||
|
||||
style_tr_td = style_tr+";"+style_td;
|
||||
|
||||
if (colonne_am.includes("ABS")) style_am+=";background:#f004";
|
||||
if (colonne_pm.includes("ABS")) style_pm+=";background:#f004";
|
||||
|
||||
if (colonne_am.includes("CGI")) style_am+=";color:blue";
|
||||
if (colonne_pm.includes("CGI")) style_pm+=";color:blue";
|
||||
|
||||
tamponWeek += '<td style="width:40px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_td + ';opacity:0.5" align="' + aligne + '"><center>' + colonne_bw + "</center></td>";
|
||||
tamponWeek += '<td colspan="4" style="width:80px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_tr_td+';'+style_am + '"' + aligne + '"><center>' + colonne_am + "</center></td>";
|
||||
tamponWeek += '<td style="width:40px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_td + ';opacity:0.5" align="' + aligne + '"><center>' + colonne_md + "</center></td>";
|
||||
tamponWeek += '<td colspan="4" style="width:80px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_tr_td+';'+style_pm+ ';" align="' + aligne + '"><center>' + colonne_pm + "</center></td>";
|
||||
tamponWeek += '<td style="width:40px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_td + ';opacity:0.5;border-right: 1px solid" align="' + aligne + '"><center>' + colonne_aw + "</center></td>";
|
||||
|
||||
/*} else {
|
||||
//if (colonne != '') tamponWeekFlag = true;
|
||||
tamponWeek += '<td colspan="5" style="background:' + bgcolor + ';min-width: 60px;padding-left: 5px; padding-right: 5px" align="' + aligne + '"><center>' + colonne + "</center></td>";
|
||||
}
|
||||
*/
|
||||
});
|
||||
|
||||
tamponWeek += "</tr>";
|
||||
|
||||
// Pour ne pas boucler indéfiniment
|
||||
if (++lebreak > 400) break;
|
||||
|
||||
/*
|
||||
if (select_date_debut == 1) {
|
||||
// Planning glissant
|
||||
// Stop au dimanche suivant anniversaire
|
||||
if (intJourCourant > intValToDay + 10000) if (jour == 0) break;
|
||||
}
|
||||
*/
|
||||
|
||||
ladate.setDate(ladate.getDate() + 1);
|
||||
}
|
||||
|
||||
contenu += tamponWeek;
|
||||
|
||||
contenu += " <tfoot><tr>" + header +"</tr></tfoot>";
|
||||
contenu += "</table>";
|
||||
|
||||
/*
|
||||
contenu += "</td></tr>";
|
||||
contenu += "<tfoot><tr><th>Calendrier</th></tr></tfoot>";
|
||||
contenu += "</table>";
|
||||
*/
|
||||
|
||||
//element.innerHTML = '<div align="center" style="background:#aaaaaa">'+contenu+'</div>';
|
||||
|
||||
element.innerHTML = contenu;
|
||||
}
|
||||
|
||||
datagrid_hooks['calendar_clients'] = function(){
|
||||
let element = document.querySelector("#datagrid");
|
||||
|
||||
let filtre = getContexteValeur('client');
|
||||
|
||||
let lebreak = 0;
|
||||
let annee = new Date().getFullYear();
|
||||
let ladate = dateGetPrevMonday(new Date(annee, 0, 1));
|
||||
let ladateToString;
|
||||
let entetes = [];
|
||||
let jours_semaine = ["D", "L", "M", "M", "J", "V", "S"];
|
||||
let lastWeekNumber = 99;
|
||||
let tamponWeek = "";
|
||||
let tamponWeekFlag = false;
|
||||
let header = '';
|
||||
|
||||
let jours_feries = [];
|
||||
|
||||
let contenu = '';
|
||||
|
||||
sortItemsByStartDate();
|
||||
|
||||
setItemsVisibility();
|
||||
|
||||
if (getContexteValeur('debut'))
|
||||
{
|
||||
ladate = stringdateToDate(getContexteValeur('debut'));
|
||||
ladate = dateGetPrevMonday(ladate);
|
||||
}
|
||||
|
||||
ladateToString = formatDatetoStringDate(ladate);
|
||||
|
||||
// Se limiter à un an
|
||||
annee = ladate.getFullYear() + 1;
|
||||
annee += 1;
|
||||
// Et à 2 ans si calendrier glissant
|
||||
// TODO : ajouter un contexte qui indique si on est en calendrier annuel ou glissant
|
||||
//if (select_date_debut == 2) annee += 1;
|
||||
|
||||
// Définir la liste des intervenants
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
let debut = item['debut'].substring(0,8);
|
||||
let fin = item['fin'].substring(0,8);
|
||||
|
||||
// On ne s'occupe que des feuilles
|
||||
if (item.childs.length != 0) return true;
|
||||
|
||||
// Au passage alimenter les jours fériés , mais ne pas les compter
|
||||
if (item['client'] == 'FER') {
|
||||
jours_feries.push(item['fin'].substring(0,8));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ne pas compter les Releases
|
||||
if (item['client'] == 'REL') return true;
|
||||
|
||||
if (filtre != '')
|
||||
if (item['client'] != filtre) return true;
|
||||
|
||||
// On élimine ce qui est masqué
|
||||
if (!item["visible"]) return true;
|
||||
|
||||
// On élimine les items non affectés
|
||||
if (parseInt(item["client"]) == 0) return true;
|
||||
|
||||
// On ne compte pas ce qui n'est pas dans la période concernée
|
||||
if (fin < ladateToString ) return true;
|
||||
if (fin == '99999999' ) return true;
|
||||
if (debut > (annee+'1231') ) return true;
|
||||
|
||||
if (entetes.indexOf(item['client']) == -1) {
|
||||
entetes.push(item['client']);
|
||||
}
|
||||
});
|
||||
entetes.sort();
|
||||
|
||||
header += ' <th colspan="3">Calendrier</th>';
|
||||
entetes.forEach((entete) => {
|
||||
header += '<th colspan="11"><center>' + entete + "</center></th>";
|
||||
});
|
||||
|
||||
contenu += '<table width="100vw">';
|
||||
|
||||
contenu += " <thead><tr>" + header +"</tr></thead>";
|
||||
|
||||
contenu += " <tbody>";
|
||||
|
||||
let semaine_vide = "";
|
||||
let semaine_paire = false;
|
||||
let couleur = '';
|
||||
semaine_vide += '<tr class="calendrier" style="background:#777777">';
|
||||
semaine_vide += '<td width="30px" style="border-top:1px solid black;font-size:2vh">SXX</td>';
|
||||
semaine_vide += '<td colspan="' + ( 2 + (11 * entetes.length)) + '" align="center" style="border-top:1px solid black;font-size:2vh"> </td>';
|
||||
semaine_vide += "</tr>";
|
||||
|
||||
while (annee > ladate.getFullYear()) {
|
||||
let bgcolor = "white";
|
||||
let font_weight = 'normal';
|
||||
let jour = ladate.getDay();
|
||||
let jour_courant = formatDatetoStringDate(ladate);
|
||||
let weekNumber = stringdateGetWeekOfYear(jour_courant)%100;
|
||||
let colonnes = [];
|
||||
let colonnes_bw = []; // Before Work
|
||||
let colonnes_am = []; // Matin
|
||||
let colonnes_md = []; // Midi
|
||||
let colonnes_pm = []; // Après-Midi
|
||||
let colonnes_aw = []; // After Work
|
||||
let style_tr = '';
|
||||
let style_td = '';
|
||||
let jour_libelle = '';
|
||||
|
||||
entetes.forEach((intervenant) => {
|
||||
colonnes.push("");
|
||||
colonnes_bw.push("");
|
||||
colonnes_am.push("");
|
||||
colonnes_md.push("");
|
||||
colonnes_pm.push("");
|
||||
colonnes_aw.push("");
|
||||
});
|
||||
|
||||
// On change de semaine
|
||||
// Si la semaine est vide, tamponWeekFlag == false
|
||||
if (weekNumber != lastWeekNumber) {
|
||||
let semaine = '';
|
||||
if (lastWeekNumber != 99) semaine = semaine_vide.replace("SXX", "S" + stringDatePadDigits(lastWeekNumber,2));
|
||||
if (tamponWeekFlag) {
|
||||
semaine = tamponWeek;
|
||||
semaine_paire = !semaine_paire;
|
||||
}
|
||||
contenu += semaine;
|
||||
tamponWeek = "";
|
||||
tamponWeekFlag = false;
|
||||
}
|
||||
|
||||
// Couleur pour les samedi et dimanche
|
||||
if (jour == 0 || jour == 6) bgcolor = "#f1d4af";
|
||||
// Couleur pour les lundi et vendredi
|
||||
if (jour == 1 || jour == 5) bgcolor = "#eeeeee";
|
||||
// Couleur pour les jours fériés
|
||||
if (jours_feries.includes(jour_courant)) bgcolor = "#f1d4af";
|
||||
|
||||
// Couleur d'aujourd'hui
|
||||
if (jour_courant == todayStringDate){
|
||||
bgcolor='#87cefa';
|
||||
font_weight='bold';
|
||||
tamponWeekFlag = true;
|
||||
}
|
||||
|
||||
items.forEach((element) => {
|
||||
let item = getItemFromElement(element);
|
||||
|
||||
let debut = item["debut"];
|
||||
let fin = item["fin"];
|
||||
let jour_debut;
|
||||
let jour_fin;
|
||||
|
||||
let ajout = false;
|
||||
|
||||
if (isDebugItem(item)){
|
||||
myLog('item ICI');
|
||||
}
|
||||
|
||||
if (!item["visible"]) return true; // Invisible
|
||||
if (item["client"] == 0) return true; // Non affecté
|
||||
if (item.childs.length != 0) return true; // Noeud
|
||||
|
||||
if ((fin.substring(8,12) == '0000')||(fin.substring(8,12) == '9999')) fin = fin.substring(0,8)+'2000';
|
||||
|
||||
if (item['type'] == 'TODO') debut = fin; // Un TODO est un jalon
|
||||
|
||||
jour_debut = debut.substring(0,8);
|
||||
jour_fin = fin.substring(0,8);
|
||||
|
||||
// if (jour_debut > jour_courant) return false;
|
||||
|
||||
// Ceci n'est pas réellement planifié
|
||||
if ((jour_debut == '00000000') && (jour_fin.substring(0,8) == (1+parseInt(todayStringDate.substring(0,4))+'1231'))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// L'item débute ou finit le jour courant
|
||||
if (jour_debut == jour_courant) ajout = true;
|
||||
if (jour_fin == jour_courant) ajout = true;
|
||||
|
||||
// Le jour courant est entièrement contenu dans l'item
|
||||
if (jour_debut < jour_courant && jour_fin > jour_courant) ajout = true;
|
||||
|
||||
if (ajout) {
|
||||
let indexCol = entetes.indexOf(item["client"]);
|
||||
let intervenant = getTrigrammeCollaborateur(item["intervenant"]);
|
||||
let client = item["client"];
|
||||
let horaire_debut = 0;
|
||||
let horaire_fin = 20;
|
||||
let colonne = null;
|
||||
|
||||
tamponWeekFlag = true;
|
||||
|
||||
if (jour_courant == jour_debut) horaire_debut = parseInt(debut.substring(8, 10));
|
||||
if (jour_courant == jour_fin) horaire_fin = parseInt(fin.substring(8, 10));
|
||||
|
||||
// Pour les releases et les jour fériés, on affiche le libellé
|
||||
if ((client == 'REL')||(client == 'FER')) {
|
||||
jour_libelle = item['libelle'];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (client == 'REL') return true;
|
||||
if (client == 'FER') return true;
|
||||
|
||||
if (client == "ABS") bgcolor = "#f1d4af";
|
||||
if (client == "CGI") font_weight += ";color:blue";
|
||||
|
||||
if (indexCol == -1) {
|
||||
myLog(item["client"] + " inconnu");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((horaire_debut <= 9) && (horaire_fin<=9)) ajouterClientColonne(intervenant, colonnes_bw, indexCol);
|
||||
if ((horaire_debut >= 12) && (horaire_fin<=14)) ajouterClientColonne(intervenant, colonnes_md, indexCol);
|
||||
if ((horaire_debut >= 17) && (horaire_fin<=21)) ajouterClientColonne(intervenant, colonnes_aw, indexCol);
|
||||
|
||||
if ((horaire_debut < 12) && (horaire_fin > 9)) ajouterClientColonne(intervenant, colonnes_am, indexCol);
|
||||
if ((horaire_debut < 17) && (horaire_fin > 14)) ajouterClientColonne(intervenant ,colonnes_pm, indexCol);
|
||||
}
|
||||
});
|
||||
|
||||
style_tr = 'background:'+bgcolor+';font-weight:'+font_weight;
|
||||
tamponWeek += '<tr style="'+style_tr+'" class="js-open-modal-trigger" data-modal-info="type=calendrier:jour=' + jour_courant + '">';
|
||||
|
||||
if (weekNumber != lastWeekNumber) {
|
||||
if (semaine_paire) couleur = '#eeeeee';
|
||||
else couleur = 'white';
|
||||
lastWeekNumber = weekNumber;
|
||||
/*
|
||||
tamponWeek += '<td class="calendrier" width="10px" style="font-family: fixed; width: 30px;background: ' + couleur + '; font-weight: bold" rowspan="7" align="center">';
|
||||
tamponWeek += "S" + lastWeekNumber.toLocaleString(undefined, { minimumIntegerDigits: 2 });
|
||||
tamponWeek += "</td>";
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
if (jour == 1) style_td = 'border-top:1px solid black'; // Le lundi
|
||||
|
||||
tamponWeek += '<td style="font-family: fixed; width: 30px; background:'+couleur+';text-align:center;border-right:1px solid;font-size:2vh;'+style_td+'">';
|
||||
if (jour == 4) tamponWeek += 'S'+lastWeekNumber.toLocaleString(undefined, { minimumIntegerDigits: 2 });
|
||||
tamponWeek += ' </td>';
|
||||
|
||||
tamponWeek += '<td style="font-family: fixed;font-size:2vh; width: 20px;background:'+bgcolor+';font-weight:bold;'+style_td+'">'+jours_semaine[jour]+'</td>';
|
||||
|
||||
if (jour_libelle != '' ) {
|
||||
tamponWeek += '<td style="font-family: fixed;font-size:2vh;width:80px;background:'+bgcolor+';color:red;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-right:1px solid black;'+style_td+'"><small>'+ jour_libelle +'</small></td>';
|
||||
} else {
|
||||
tamponWeek += '<td style="font-family: fixed;font-size:2vh;width: 80px;background:'+bgcolor+';font-weight:bold;border-right:1px solid;'+style_td+'">';
|
||||
tamponWeek +=
|
||||
ladate.getDate().toLocaleString(undefined, { minimumIntegerDigits: 2 }) +
|
||||
" / " +
|
||||
(ladate.getMonth() + 1).toLocaleString(undefined, { minimumIntegerDigits: 2 });
|
||||
tamponWeek += "</td>";
|
||||
}
|
||||
|
||||
entetes.forEach((entete) => {
|
||||
let index = entetes.indexOf(entete);
|
||||
let aligne = "center";
|
||||
let colonne = colonnes[index].substring(1);
|
||||
let colonne_bw = colonnes_bw[index];
|
||||
let colonne_am = colonnes_am[index];
|
||||
let colonne_md = colonnes_md[index];
|
||||
let colonne_pm = colonnes_pm[index];
|
||||
let colonne_aw = colonnes_aw[index];
|
||||
|
||||
// if (colonne_bw != '' || colonne_am != '' || colonne_md != '' || colonne_pm != '' || colonne_aw != '') {
|
||||
//tamponWeekFlag = true;
|
||||
if (colonne != '') {
|
||||
let tempo = colonne.replace('</span>','');
|
||||
let valeurs = tempo.split('/');
|
||||
valeurs.forEach(valeur => {
|
||||
if (!colonne_am.includes(valeur)) colonne_am += '/'+valeur+'</span>';
|
||||
if (!colonne_pm.includes(valeur)) colonne_pm += '/'+valeur+'</span>';
|
||||
// if (!colonne_aw.includes(valeur)) colonne_aw += '/'+valeur+'</span>';
|
||||
})
|
||||
}
|
||||
|
||||
colonne_bw = colonne_bw.substring(1);
|
||||
colonne_am = colonne_am.substring(1);
|
||||
colonne_md = colonne_md.substring(1);
|
||||
colonne_pm = colonne_pm.substring(1);
|
||||
colonne_aw = colonne_aw.substring(1);
|
||||
|
||||
style_tr = 'overflow: hidden;white-space: nowrap;text-overflow:ellipsis';
|
||||
style_tr += ';border-color:black;border-width:1px';
|
||||
style_tr += ';padding-left: 5px; padding-right: 5px';
|
||||
style_tr += ';background:' + bgcolor;
|
||||
|
||||
tamponWeek += '<td style="width:40px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_td + ';opacity:0.5" align="' + aligne + '"><center>' + colonne_bw + "</center></td>";
|
||||
tamponWeek += '<td colspan="4" style="width:80px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_tr+';'+style_td + '"' + aligne + '"><center>' + colonne_am + "</center></td>";
|
||||
tamponWeek += '<td style="width:40px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_td + ';opacity:0.5" align="' + aligne + '"><center>' + colonne_md + "</center></td>";
|
||||
tamponWeek += '<td colspan="4" style="width:80px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_tr+';'+style_td + ';" align="' + aligne + '"><center>' + colonne_pm + "</center></td>";
|
||||
tamponWeek += '<td style="width:40px;font-size:2vh;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;' + style_td + ';opacity:0.5;border-right: 1px solid" align="' + aligne + '"><center>' + colonne_aw + "</center></td>";
|
||||
|
||||
/*} else {
|
||||
//if (colonne != '') tamponWeekFlag = true;
|
||||
tamponWeek += '<td colspan="5" style="background:' + bgcolor + ';min-width: 60px;padding-left: 5px; padding-right: 5px" align="' + aligne + '"><center>' + colonne + "</center></td>";
|
||||
}
|
||||
*/
|
||||
});
|
||||
|
||||
tamponWeek += "</tr>";
|
||||
|
||||
// Pour ne pas boucler indéfiniment
|
||||
if (++lebreak > 400) break;
|
||||
|
||||
/*
|
||||
if (select_date_debut == 1) {
|
||||
// Planning glissant
|
||||
// Stop au dimanche suivant anniversaire
|
||||
if (intJourCourant > intValToDay + 10000) if (jour == 0) break;
|
||||
}
|
||||
*/
|
||||
|
||||
ladate.setDate(ladate.getDate() + 1);
|
||||
}
|
||||
|
||||
contenu += tamponWeek;
|
||||
|
||||
contenu += " <tfoot><tr>" + header +"</tr></tfoot>";
|
||||
contenu += "</table>";
|
||||
|
||||
element.innerHTML = contenu;
|
||||
}
|
||||
|
||||
|
||||
modal_hooks['calendrier'] = function(parametres){
|
||||
let jour_courant='00000000';
|
||||
let paramSplit = parametres.split(':');
|
||||
|
||||
paramSplit.forEach(element => {
|
||||
let elemSplit=element.split('=');
|
||||
if (elemSplit[0]==='jour') jourInfo(elemSplit[1].substring(0,8));
|
||||
});
|
||||
};
|
||||
|
||||
function testDateItem(item, jour_courant)
|
||||
{
|
||||
let retour = false;
|
||||
let jour_debut = item["debut"].substring(0,8);
|
||||
let jour_fin = item["fin"].substring(0,8);
|
||||
|
||||
// Les TODO sont des jalons
|
||||
if (item['type']=='TODO') jour_debut = jour_fin;
|
||||
|
||||
// Se limiter aux items réellement entièrement plannifiés
|
||||
if ((jour_debut != '00000000') && (jour_fin != (1+parseInt(todayStringDate.substring(0,4))+'1231'))) {
|
||||
// L'item débute ou finit le jour courant
|
||||
if (jour_debut == jour_courant) retour = true;
|
||||
if (jour_fin == jour_courant) retour = true;
|
||||
|
||||
// Le jour courant est entièrement contenu dans l'item
|
||||
if (jour_debut < jour_courant && jour_fin > jour_courant) retour = true;
|
||||
}
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
function jourInfo(jour_courant) {
|
||||
let modal_header='Détail <b>'+formatLocaleDateFromStringDate(jour_courant)+'</b>';
|
||||
let modal_body='TODO inconnu !';
|
||||
let modal_footer='';
|
||||
|
||||
let start = 7; // Mettre un contexte ...
|
||||
let finish = 14; // Mettre un contexte ...
|
||||
|
||||
let horaires = [];
|
||||
|
||||
for(i=0;i<finish;i++){
|
||||
horaires[(i*2)] = '';
|
||||
horaires[(i*2)+1] = '';
|
||||
}
|
||||
|
||||
items.forEach(element => {
|
||||
let resultat = getItemFromElement(element);
|
||||
|
||||
let debut = resultat["debut"];
|
||||
let fin = resultat["fin"];
|
||||
let jour_debut;
|
||||
let jour_fin;
|
||||
let heure_debut;
|
||||
let heure_fin;
|
||||
|
||||
if (isDebugItem(resultat)){
|
||||
myLog('item ICI');
|
||||
}
|
||||
|
||||
// L'item concerne-t-il bien la date courante ?
|
||||
if (!testDateItem(resultat, jour_courant)) return true;
|
||||
|
||||
heure_fin=fin.substring(8,12);
|
||||
if (heure_fin =='0000') fin=fin.substring(0,8)+'2000';
|
||||
|
||||
// Les TODO sont des jalons
|
||||
if (resultat.type=='TODO') debut = fin;
|
||||
|
||||
jour_debut = debut.substring(0,8);
|
||||
jour_fin = fin.substring(0,8);
|
||||
heure_debut = parseInt(debut.substring(8,12));
|
||||
heure_fin = parseInt(fin.substring(8,12));
|
||||
|
||||
// L'item commence avant le jour courant
|
||||
if (jour_debut < jour_courant) heure_debut = '0900';
|
||||
|
||||
// L'item termine après le jour courant
|
||||
if (jour_fin > jour_courant) heure_fin = '1800';
|
||||
|
||||
// Recalibrer les heures de debut et de fin
|
||||
if (heure_debut=='0000') heure_debut='0900';
|
||||
if (heure_fin=='0000') heure_fin='2000';
|
||||
|
||||
for(i=0;i<finish;i++) {
|
||||
let cur_debut, cur_fin;
|
||||
let flag;
|
||||
|
||||
cur_debut = parseInt((start+i)+'00');
|
||||
cur_fin = parseInt((start+i)+'30');
|
||||
flag = false;
|
||||
if ((heure_debut <= cur_debut)&&(heure_fin >= cur_fin)) flag = true;
|
||||
if ((heure_debut >= cur_debut)&&(heure_fin <= cur_fin)) flag = true;
|
||||
if ((heure_debut == heure_fin)&&(heure_fin == cur_fin)) flag = false;
|
||||
// Cas particulier de la pause de midi
|
||||
if (cur_debut == '1300')
|
||||
if ((heure_debut<'1230')&&(heure_fin>'1330')) flag = false;
|
||||
if (flag) horaires[(i*2)] += resultat.libelle+'<br>';
|
||||
|
||||
cur_debut = parseInt((start+i)+'30');
|
||||
cur_fin = parseInt((start+i)+1+'00');
|
||||
flag = false;
|
||||
if ((heure_debut <= cur_debut)&&(heure_fin >= cur_fin)) flag = true;
|
||||
if ((heure_debut >= cur_debut)&&(heure_fin <= cur_fin)) flag = true;
|
||||
if ((heure_debut == heure_fin)&&(heure_fin == cur_fin)) flag = false;
|
||||
// Cas particulier de la pause de midi
|
||||
if (cur_debut == '1230')
|
||||
if ((heure_debut<'1230')&&(heure_fin>'1330')) flag = false;
|
||||
if (flag) horaires[(i*2)+1] += resultat.libelle+'<br>';
|
||||
}
|
||||
});
|
||||
|
||||
modal_body = '<table class="modal_table">';
|
||||
for(i=0;i<finish;i++) {
|
||||
let debut;
|
||||
let fin;
|
||||
let style_tr;
|
||||
debut = stringDatePadDigits((i+start),2)+':00';
|
||||
fin = stringDatePadDigits((i+start),2)+':30';
|
||||
style_tr=' class="tr1"';
|
||||
if (debut < '09:00') style_tr=' class="tr2"';
|
||||
if (fin > '18:00') style_tr=' class="tr2"';
|
||||
if (debut == '13:00') style_tr=' class="tr2"';
|
||||
modal_body += '<tr'+style_tr+'>';
|
||||
modal_body += '<td style="width:40px">'+debut+' - '+fin+'</td>';
|
||||
modal_body += '<td>'+horaires[i*2]+'</td></tr>';
|
||||
modal_body += '</tr>';
|
||||
|
||||
debut = stringDatePadDigits((i+start),2)+':30';
|
||||
fin = stringDatePadDigits((i+start)+1,2)+':00';
|
||||
style_tr=' class="tr1"';
|
||||
if (debut < '09:00') style_tr=' class="tr2"';
|
||||
if (fin > '18:00') style_tr=' class="tr2"';
|
||||
if (debut == '12:30') style_tr=' class="tr2"';
|
||||
modal_body += '<tr'+style_tr+'>';
|
||||
modal_body += '<td style="width:40px">'+debut+' - '+fin+'</td>';
|
||||
modal_body += '<td>'+horaires[(i*2)+1]+'</td></tr>';
|
||||
modal_body += '</tr>';
|
||||
}
|
||||
modal_body += '</table>';
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
}
|
||||
147
frontend/src/scripts/UI/datagrid.js
Normal file
147
frontend/src/scripts/UI/datagrid.js
Normal file
@@ -0,0 +1,147 @@
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// ---- Fonctions pour charger des lignes identiques dans le tableau
|
||||
// ---------------------------------------------------------------------------------------
|
||||
function datagridLignesIdentiques(nblignes, valeur) {
|
||||
let element = document.querySelector('#datagrid');
|
||||
let contenu='';
|
||||
|
||||
contenu += '<table>';
|
||||
contenu += ' <thead>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th> </th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </thead>';
|
||||
|
||||
contenu += ' <tbody>';
|
||||
for(let i=0; i<nblignes; i++)
|
||||
{
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <td align="center">'+valeur+'</td>';
|
||||
contenu += ' </tr>';
|
||||
}
|
||||
|
||||
contenu += ' <tfoot>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th> </th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </foot>';
|
||||
contenu += '</table>';
|
||||
|
||||
element.innerHTML = contenu;
|
||||
}
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// ---- Fonctions pour charger des lignes vides
|
||||
// ---------------------------------------------------------------------------------------
|
||||
function datagridEmptyLines(nblignes) {
|
||||
return datagridLignesIdentiques(nblignes,' ');
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// ---- Fonctions utilitaires
|
||||
// ---------------------------------------------------------------------------------------
|
||||
function datagridLoading() {
|
||||
let nblignes = 25 + Math.floor(Math.random() * 475); // Nbre entre ntre 25 et 500
|
||||
return datagridLignesIdentiques(nblignes, 'Loading data ..');
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// ---- Fonctions pour charger des données au hasard dans le datagrid
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
var nbCols = 5;
|
||||
|
||||
function setDatagridRandomValues(element, nbcols, nblignes)
|
||||
{
|
||||
let contenu='';
|
||||
|
||||
contenu += '<table>';
|
||||
contenu += ' <thead>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th>ID HEAD</th>';
|
||||
for(let i= 0; i<nbcols; i++)
|
||||
{
|
||||
contenu += ' <th>HEAD'+i+'</th>';
|
||||
}
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </thead>';
|
||||
|
||||
|
||||
contenu += ' <tbody>';
|
||||
for(let i=0; i<nblignes; i++)
|
||||
{
|
||||
contenu += ' <tr class="js-open-modal-trigger" data-modal-info="random:idligne='+i+'">';
|
||||
contenu += ' <td>ID</td>';
|
||||
for(let ii= 0; ii<nbcols; ii++)
|
||||
{
|
||||
contenu += ' <td> VALUE '+i+' '+ii+'</td>';
|
||||
}
|
||||
contenu += ' </tr>';
|
||||
}
|
||||
// Rejouter 2 lignes vides
|
||||
for(let i=0; i<2; i++)
|
||||
{
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <td> </td>';
|
||||
for(let ii= 0; ii<nbcols; ii++)
|
||||
{
|
||||
contenu += ' <td> </td>';
|
||||
}
|
||||
contenu += ' </tr>';
|
||||
}
|
||||
contenu += ' </body>';
|
||||
|
||||
contenu += ' <tfoot>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th>ID FOOT</th>';
|
||||
for(let i= 0; i<nbcols; i++)
|
||||
{
|
||||
contenu += ' <th>FOOT'+i+'</th>';
|
||||
}
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </foot>';
|
||||
contenu += '</table>';
|
||||
|
||||
element.innerHTML = contenu;
|
||||
|
||||
init_modal();
|
||||
nbCols = nbcols;
|
||||
}
|
||||
|
||||
modal_hooks['random'] = function(parametres){
|
||||
let paramSplit = parametres.split(',');
|
||||
paramSplit.forEach(element => {
|
||||
let elemSplit=element.split('=');
|
||||
if (elemSplit[0] === 'idligne') {
|
||||
let ligne = elemSplit[1];
|
||||
let modal_header='Détail de la ligne '+ligne;
|
||||
let modal_body='';
|
||||
let modal_footer='<button>Enregistrer</button';
|
||||
|
||||
|
||||
modal_body += '<table class="modal_table">';
|
||||
for(i=0;i<nbCols; i++)
|
||||
{
|
||||
modal_body += '<tr>';
|
||||
modal_body += '<td> PARAM '+i+'</td>';
|
||||
modal_body += '<td> VALUE '+ligne+' '+i+'</td>';
|
||||
modal_body += '</tr>';
|
||||
}
|
||||
modal_body += '</table>';
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// ---- Tableau de hooks pour alimenter le datagrid
|
||||
// --------------------------------------------------------------------------------------------
|
||||
var datagrid_hooks = [];
|
||||
|
||||
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)
|
||||
};
|
||||
154
frontend/src/scripts/UI/modal.js
Normal file
154
frontend/src/scripts/UI/modal.js
Normal file
@@ -0,0 +1,154 @@
|
||||
class Modal {
|
||||
// TODO : industrialiser en créant une classe
|
||||
}
|
||||
|
||||
const modalDialog = document.getElementById('fiche');
|
||||
|
||||
var modal_hooks = [];
|
||||
|
||||
function disableScrolling(){
|
||||
/*
|
||||
document.body.style.position = 'fixed';
|
||||
document.body.style.top = `-${window.scrollY}px`;
|
||||
*/
|
||||
|
||||
/*
|
||||
var x=window.scrollX;
|
||||
var y=window.scrollY;
|
||||
window.onscroll=function(){window.scrollTo(x, y);};
|
||||
*/
|
||||
|
||||
// Ne marche pas :
|
||||
// supprime la scrollbar (déplacement du body vers la droite)
|
||||
// document.body.style.overflow='hidden';
|
||||
|
||||
// Ne marche pas :
|
||||
// la modal ne propage pas le scroll
|
||||
// modalDialog.scroll = function(e) {e.stopPropagation();}
|
||||
}
|
||||
|
||||
function enableScrolling(){
|
||||
/*
|
||||
const scrollY = document.body.style.top;
|
||||
document.body.style.position = '';
|
||||
document.body.style.top = '';
|
||||
window.scrollTo(0, parseInt(scrollY || '0') * -1);
|
||||
*/
|
||||
|
||||
// Ne marche pas :
|
||||
// au retour, certains élements de la page ne sont plus clickables
|
||||
//document.body.style.overflow='scroll';
|
||||
|
||||
// window.onscroll=function(){};
|
||||
}
|
||||
|
||||
function showDialog(){
|
||||
modalDialog.showModal();
|
||||
disableScrolling()
|
||||
}
|
||||
|
||||
function show_modal(data_modal) {
|
||||
showDialog();
|
||||
if (typeof open_modal_hook === 'function') open_modal_hook(data_modal);
|
||||
};
|
||||
|
||||
function close_modal()
|
||||
{
|
||||
modalDialog.close();
|
||||
enableScrolling();
|
||||
}
|
||||
|
||||
function init_modal()
|
||||
{
|
||||
let testElements = document.getElementsByClassName('js-open-modal-trigger');
|
||||
let testDivs = Array.prototype.filter.call(testElements, function(testElement){
|
||||
return true;
|
||||
});
|
||||
|
||||
testDivs.forEach(function(item){
|
||||
item.onclick = function(ev) {
|
||||
show_modal(this.getAttribute("data-modal-info"));
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
testElements = document.getElementsByClassName('js-close-modal-trigger');
|
||||
testDivs = Array.prototype.filter.call(testElements, function(testElement){
|
||||
return true;
|
||||
});
|
||||
|
||||
testDivs.forEach(function(item){
|
||||
item.onclick = function(ev) {
|
||||
close_modal(this.getAttribute("data-modal-info"));
|
||||
};
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function close_modal_hook()
|
||||
{
|
||||
console.log("close_modal_hook");
|
||||
|
||||
modalSetInnerHtml('modal_header', '');
|
||||
modalSetInnerHtml('modal_body', '');
|
||||
modalSetInnerHtml('modal_footer', '');
|
||||
}
|
||||
|
||||
function modalSetInnerHtml(className, valeur)
|
||||
{
|
||||
var testElements = document.getElementsByClassName(className);
|
||||
var testDivs = Array.prototype.filter.call(testElements, function(testElement){
|
||||
return true;
|
||||
});
|
||||
testDivs.forEach(function(element){
|
||||
element.scrollTop = 0;
|
||||
element.innerHTML = valeur;
|
||||
});
|
||||
}
|
||||
|
||||
function modalSetChildren(className, children)
|
||||
{
|
||||
var testElements = document.getElementsByClassName(className);
|
||||
var testDivs = Array.prototype.filter.call(testElements, function(testElement){
|
||||
return true;
|
||||
});
|
||||
modalSetInnerHtml(className, '');
|
||||
testDivs.forEach(function(element){
|
||||
element.scrollTop = 0;
|
||||
element.appendChild(children);
|
||||
});
|
||||
}
|
||||
|
||||
function modalSetHeader(valeur)
|
||||
{
|
||||
modalSetInnerHtml('modal_header', valeur);
|
||||
}
|
||||
function modalSetBody(valeur)
|
||||
{
|
||||
modalSetInnerHtml('modal_body', valeur);
|
||||
}
|
||||
function modalSetFooter(valeur)
|
||||
{
|
||||
modalSetInnerHtml('modal_footer', valeur);
|
||||
}
|
||||
|
||||
/*
|
||||
* Format du paramètre : methode:p1=v1,p2=v2
|
||||
*/
|
||||
function open_modal_hook(parametre)
|
||||
{
|
||||
console.log("open_modal_hook pour "+parametre);
|
||||
let hook = null;
|
||||
let paramSplit = parametre.split(':');
|
||||
paramSplit.forEach(element => {
|
||||
let elemSplit=element.split('=');
|
||||
if (elemSplit[0] === 'type') {
|
||||
hook = modal_hooks[elemSplit[1]];
|
||||
}
|
||||
});
|
||||
if ((hook===null)||(hook===undefined)) hook = modal_hooks['ITEM'];
|
||||
return hook(parametre);
|
||||
}
|
||||
|
||||
init_modal();
|
||||
83
frontend/src/scripts/UI/planning.js
Normal file
83
frontend/src/scripts/UI/planning.js
Normal file
@@ -0,0 +1,83 @@
|
||||
|
||||
datagrid_hooks['planning'] = function() {
|
||||
let element = document.querySelector("#datagrid");
|
||||
let filtre = getTrigrammeCollaborateur(getContexteValeur('intervenant'));
|
||||
let contenu = "";
|
||||
let nbLignes = 1;
|
||||
|
||||
items.sort((a, b) => {
|
||||
let item_a = getItemFromElement(a);
|
||||
let item_b = getItemFromElement(b);
|
||||
let retour = 0;
|
||||
/*
|
||||
if (item_a['client'] < item_b['client']) retour = -1;
|
||||
if (item_a['client'] > item_b['client']) retour = 1;
|
||||
*/
|
||||
if (retour == 0 ) {
|
||||
retour = sort2ItemsByDates(item_a, item_b);
|
||||
}
|
||||
|
||||
return retour;
|
||||
});
|
||||
|
||||
setItemsVisibility();
|
||||
|
||||
contenu += "<table>";
|
||||
contenu += " <thead>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th style="width:50px;text-align:center">Client</td>';
|
||||
contenu += ' <th style="width:50px;text-align:center">Intervenant</td>';
|
||||
contenu += ' <th style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">Libellé</th>';
|
||||
contenu += ' <th style="width:100px;text-align:center">Début</td>';
|
||||
contenu += ' <th style="width:100px;text-align:center">fin</td>';
|
||||
contenu += " </tr>";
|
||||
contenu += " </thead>";
|
||||
|
||||
contenu += " <tbody>";
|
||||
|
||||
items.forEach((element) => {
|
||||
let item = getItemFromElement(element);
|
||||
let texte = getNonNullTextValeur(item.libelle);
|
||||
let debut = formatLocaleDateFromStringDate(item.debut);
|
||||
let heureDebut= formatTimeFromStringDate(item.debut);
|
||||
let fin = formatLocaleDateFromStringDate(item.fin);
|
||||
let heureFin= formatTimeFromStringDate(item.fin);
|
||||
|
||||
|
||||
// On n'affiche pas la racine
|
||||
if (item["idlignes"] == 1) return true;
|
||||
// On n'affiche que ce qui est marqué comme visible
|
||||
if (!item["visible"]) return true;
|
||||
// On n'affiche que les feuilles
|
||||
if (item.childs.length != 0) return true;
|
||||
// On n'affiche que ce qui est plannifié
|
||||
if((debut=='-')&&(fin=='-')) return true;
|
||||
|
||||
// Appliquer le filtre
|
||||
if (filtre != 'ANO')
|
||||
if (getTrigrammeCollaborateur(item['intervenant']) != filtre) return true;
|
||||
|
||||
if (item.status == 3) texte = "<strike>" + texte + "</strike>";
|
||||
if (item.status == 2) texte = "<strike>" + texte + "</strike>";
|
||||
|
||||
contenu += ' <tr class="js-open-modal-trigger" data-modal-info="type='+item.type+':id=' + getNonNullTextValeur(item.idlignes) + '">';
|
||||
contenu += ' <td style="width:50px;text-align:center">' + getNonNullTextValeur(item.client) + "</td>";
|
||||
contenu += ' <td style="width:50px;text-align:center">' + getTrigrammeCollaborateur(item['intervenant']) + "</td>";
|
||||
contenu += ' <td style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">'+ texte + "</td>";
|
||||
contenu += ' <td style="width:100px;text-align:center">' + debut + "<br>" + heureDebut + "</td>";
|
||||
contenu += ' <td style="width:100px;text-align:center">' + fin + "<br>" + heureFin + "</td>";
|
||||
contenu += " </tr>";
|
||||
|
||||
nbLignes += 1;
|
||||
});
|
||||
contenu += " </tbody>";
|
||||
|
||||
contenu += " <tfoot>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th colspan="5">'+setLevelPadding(2)+''+(nbLignes-1)+' tâches</th>';
|
||||
contenu += " </tr>";
|
||||
contenu += " </foot>";
|
||||
contenu += "</table>";
|
||||
|
||||
element.innerHTML = contenu;
|
||||
}
|
||||
74
frontend/src/scripts/UI/pomodoro.js
Normal file
74
frontend/src/scripts/UI/pomodoro.js
Normal file
@@ -0,0 +1,74 @@
|
||||
function lancerPomodoroItem(id) {
|
||||
let cur_type=null;
|
||||
let modal_header='';
|
||||
let modal_body='';
|
||||
let modal_footer='';
|
||||
|
||||
items.filter(item => item.idlignes == id).forEach(resultat => {
|
||||
let flagDisabled='disabled';
|
||||
|
||||
modal_header = getItemDialogHeader(resultat, cur_type);
|
||||
|
||||
modal_body += resultat.client+' > '+getTrigrammeCollaborateur(resultat.intervenant)+' : '+resultat.libelle+'<br>';
|
||||
modal_body += '<textarea id="notes" data-aatribute="'+resultat.id+'" ';
|
||||
modal_body += 'style="width: 100%;height: 100%;overflow: hidden;border: none;outline: none" placeholder="Saisir vos notes...">';
|
||||
modal_body += '</textarea>';
|
||||
|
||||
modal_footer += '<div align="left" width="50%" style="float:left;padding-top:2vh">';
|
||||
modal_footer += '<button onclick="todo()">Notes</button>';
|
||||
modal_footer += '<button onclick="todo()">RIDA</button>';
|
||||
modal_footer += '<button onclick="todo()">Documents</button>';
|
||||
modal_footer += '<button onclick="todo()">Conversation</button>';
|
||||
modal_footer += '</div>';
|
||||
|
||||
modal_footer += '<div align="right" width="50%" style="float:right;padding-top:2vh">';
|
||||
modal_footer += '<button onclick="enregistrerNotes('+resultat.idlignes+')">Sauver</button>';
|
||||
modal_footer += '<button onclick="arreterPomodoroItem('+resultat.idlignes+')">Fermer</button>';
|
||||
modal_footer += '</div>';
|
||||
});
|
||||
|
||||
modal_footer += '<div style="clear:both">';
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
|
||||
lireNotes(id);
|
||||
}
|
||||
|
||||
function arreterPomodoroItem(id) {
|
||||
// STOP le chrono
|
||||
|
||||
// enregistrer la saisie en cours
|
||||
enregistrerNotes(id);
|
||||
|
||||
// Aficher les infos
|
||||
itemInfo(id);
|
||||
}
|
||||
|
||||
function enregistrerNotes(_id){
|
||||
let _notes=document.getElementById('notes').value;
|
||||
postData("../backend/notes.php", {id: _id, action: 'write', notes: _notes}).then((data) => {
|
||||
console.log(data); // JSON data parsed by `data.json()` call
|
||||
});
|
||||
}
|
||||
|
||||
function lireNotes(_id){
|
||||
postData("../backend/notes.php", {id: _id, action: 'read', notes: ''}).then((data) => {
|
||||
document.getElementById('notes').value = data.notes;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Ajouter la prise en charge de "Ctrl + S" dans la textarea
|
||||
*/
|
||||
document.onkeydown = function(e) {
|
||||
if (e.ctrlKey && e.key === 's') {
|
||||
let notes = document.getElementById('notes');
|
||||
if (notes) {
|
||||
enregistrerNotes(notes.getAttribute('data-attribute'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
163
frontend/src/scripts/UI/settings.js
Normal file
163
frontend/src/scripts/UI/settings.js
Normal file
@@ -0,0 +1,163 @@
|
||||
function settingsInitModal(){
|
||||
let template = document.querySelector('#settings_header');
|
||||
|
||||
modalSetHeader('');
|
||||
modalSetBody('');
|
||||
modalSetFooter('');
|
||||
|
||||
template = document.querySelector('#settings_header');
|
||||
if (template) {
|
||||
let contenu = document.importNode(template.content, true);
|
||||
if (contenu) modalSetChildren('modal_header',contenu);
|
||||
}
|
||||
}
|
||||
|
||||
modal_hooks['settings'] = function(parametres){
|
||||
settingsSetModeInfo();
|
||||
};
|
||||
|
||||
modal_hooks['login'] = function(parametres){
|
||||
settingsSetModeLogin();
|
||||
};
|
||||
|
||||
|
||||
function settingsSetModeInfo()
|
||||
{
|
||||
let template = document.querySelector('#settings_body');
|
||||
|
||||
settingsInitModal();
|
||||
if (template) {
|
||||
let contenu = document.importNode(template.content, true);
|
||||
if (contenu) modalSetChildren('modal_body',contenu);
|
||||
}
|
||||
modalSetFooter('');
|
||||
}
|
||||
|
||||
function settingsSetModeLogin()
|
||||
{
|
||||
let intervenant=getContexteValeur('intervenant');
|
||||
let profil=getContexteValeur('profil');
|
||||
let profils=getContexteValeur('profils');
|
||||
let modal_body='';
|
||||
let modal_footer='';
|
||||
let profil_selector=profil;
|
||||
|
||||
if (profils) {
|
||||
let tableau=profils.split(',');
|
||||
profil_selector='<select style="width: 100%;font-size: 1em">';
|
||||
tableau.forEach(element => {
|
||||
let s=(element == profil) ? 'selected' : '';
|
||||
profil_selector+='<option '+s+'>'+element+'</option>';
|
||||
});
|
||||
profil_selector+='</select>';
|
||||
}
|
||||
|
||||
settingsInitModal();
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
|
||||
modal_body+='<div style="height:100%;background: url(\'images/LoginBanner.jpg\');background-size: cover;display: flex;justify-content: center;align-items: center;">';
|
||||
modal_body+=' <div style="background-color: rgba(255, 255, 255, 0.4); border-radius: 5px;min-width: 25%;backdrop-filter: blur(3px);display: flex;flex-direction: column;justify-content: center;align-items: center;">';
|
||||
if (intervenant=='Anonymous') {
|
||||
modal_body+=' <input id="login_username" type="text" placeholder="Username" style="margin: 5px;font-size: 1em;width: 200px"></input>';
|
||||
modal_body+=' <input id="login_password" type="password" style="margin: 5px;font-size: 1em;width: 200px"></input>';
|
||||
modal_body+=' <button style="border:none;background-color: #2196F3;width: 200px;border-radius: 5px;margin: 5px;color: white; font-size: 1em; font-weight: bold; cursor: pointer" onclick="connectUser()">Log In</button>';
|
||||
} else {
|
||||
modal_body+=' <h2 style="width: 200px;display: flex;text-align : center;justify-content: center;align-items: center;margin: 2px;">'+intervenant+'</h2>';
|
||||
modal_body+=' <h3 style="width: 200px;display: flex;text-align : center;justify-content: center;align-items: center;margin: 5px;">'+getTrigrammeCollaborateur(intervenant)+'<h3>';
|
||||
modal_body+=' <div style=""width: 200px;display: flex;text-align : center;justify-content: center;align-items: center;margin: 5px;">'+profil_selector+'</div>';
|
||||
modal_body+=' <button style="border:none;background-color: grey;width: 200px;border-radius: 5px;margin: 5px;color: white; font-size: 1em; font-weight: bold; cursor: pointer" onclick="deconnectUser()">Log Out</button>';
|
||||
}
|
||||
modal_body+=' </div>';
|
||||
modal_body+='<div>';
|
||||
|
||||
modalSetBody(modal_body);
|
||||
}
|
||||
|
||||
function connectUser()
|
||||
{
|
||||
let username = document.getElementById('login_username').value;
|
||||
let password = document.getElementById('login_password').value;
|
||||
// C'est un POC donc on n'a pas de base utilisateur
|
||||
if ((username!='')&&(password==username))
|
||||
{
|
||||
setContexteValeur('intervenant', username);
|
||||
setContexteValeur('profils', 'Utilisateur');
|
||||
setContexteValeur('profil', 'Utilisateur');
|
||||
if (username=='TME')
|
||||
{
|
||||
setContexteValeur('intervenant', 'Thibaud MEUNIER');
|
||||
setContexteValeur('profils', 'Utilisateur,Admin');
|
||||
setContexteValeur('profil', 'Utilisateur');
|
||||
}
|
||||
document.getElementById('username').innerHTML=username;
|
||||
}
|
||||
settingsSetModeLogin();
|
||||
}
|
||||
|
||||
function deconnectUser()
|
||||
{
|
||||
setContexteValeur('intervenant', 'Anonymous');
|
||||
settingsSetModeLogin();
|
||||
document.getElementById('username').innerHTML='Log In';
|
||||
}
|
||||
|
||||
function settingsSetModeFilter()
|
||||
{
|
||||
let modal_body='';
|
||||
let modal_footer='';
|
||||
|
||||
settingsInitModal();
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
|
||||
modal_body+='<div style="height:100%;display: flex;justify-content: center;align-items: center;flex-direction: column;">';
|
||||
modal_body+='<h2>Mode Filter</h2>';
|
||||
modal_body+='<div>';
|
||||
|
||||
modalSetBody(modal_body);
|
||||
}
|
||||
|
||||
function settingsSetModeSetup()
|
||||
{
|
||||
let modal_body='';
|
||||
let modal_footer='';
|
||||
|
||||
settingsInitModal();
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
|
||||
modal_body+='<div style="height:100%;width:100%;display: flex;justify-content: center;align-items: center;flex-direction: column;">';
|
||||
modal_body+=' <h2>Thèmes</h2>';
|
||||
modal_body+=' <div style="display:flex;">';
|
||||
modal_body+=' <div style="flex: 1;border: 1px solid black;text-align: center;cursor: pointer">';
|
||||
modal_body+=' <a onclick="settingsSetTheme(\'default\')">Default</a>';
|
||||
modal_body+=' </div>';
|
||||
modal_body+=' <div style="flex:1;border: 1px solid black;text-align: center;cursor: pointer">';
|
||||
modal_body+=' <a onclick="settingsSetTheme(\'red\')" style="color:#FA0000">Red</a>';
|
||||
modal_body+=' </div>';
|
||||
modal_body+=' <div style="flex:1;border: 1px solid black;text-align: center;cursor: pointer">';
|
||||
modal_body+=' <a onclick="settingsSetTheme(\'blue\')" style="color:#0000FA">Blue</a>';
|
||||
modal_body+=' </div>';
|
||||
modal_body+=' </div>';
|
||||
modal_body+='<div>';
|
||||
|
||||
modalSetBody(modal_body);
|
||||
}
|
||||
|
||||
function settingsSetTheme(valeur)
|
||||
{
|
||||
switch(valeur){
|
||||
case 'blue':
|
||||
CSSsetClair(245,245,240);
|
||||
CSSsetSombre(0,0,245);
|
||||
break;
|
||||
case 'red':
|
||||
CSSsetClair(245,245,240);
|
||||
CSSsetSombre(245,0,0);
|
||||
break;
|
||||
default:
|
||||
CSSsetClair(245,245,240);
|
||||
CSSsetSombre(0,0,0);
|
||||
}
|
||||
}
|
||||
77
frontend/src/scripts/api/clients.js
Normal file
77
frontend/src/scripts/api/clients.js
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
var clients;
|
||||
|
||||
function setClients(data){
|
||||
clients = data;
|
||||
}
|
||||
|
||||
getEntities('client', setClients);
|
||||
|
||||
function initDatagridClients() {
|
||||
setClients(null);
|
||||
datagridLoading();
|
||||
getEntities('client', __initDatagridClients);
|
||||
}
|
||||
|
||||
function __initDatagridClients(data) {
|
||||
let element = document.querySelector('#datagrid');
|
||||
let contenu='';
|
||||
|
||||
setClients(data);
|
||||
|
||||
contenu += '<table>';
|
||||
contenu += ' <thead>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th>Id</th>';
|
||||
contenu += ' <th>Code</th>';
|
||||
contenu += ' <th>Client</th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </thead>';
|
||||
|
||||
contenu += ' <tbody>';
|
||||
clients.forEach(client => {
|
||||
contenu += ' <tr class="js-open-modal-trigger" data-modal-info="client:id='+client.idclient+'">';
|
||||
contenu += ' <td>'+client.idclient+'</td>';
|
||||
contenu += ' <td>'+client.code+'</td>';
|
||||
contenu += ' <td>'+client.nom+'</td>';
|
||||
contenu += ' </tr>';
|
||||
});
|
||||
contenu += ' </body>';
|
||||
|
||||
contenu += ' <tfoot>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th colspan="3"> </th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </foot>';
|
||||
contenu += '</table>';
|
||||
|
||||
element.innerHTML = contenu;
|
||||
|
||||
init_modal();
|
||||
}
|
||||
|
||||
modal_hooks['client'] = function(parametres){
|
||||
let paramSplit = parametres.split(',');
|
||||
paramSplit.forEach(element => {
|
||||
let elemSplit=element.split('=');
|
||||
if (elemSplit[0] === 'id') {
|
||||
let id = elemSplit[1];
|
||||
let modal_header='Fiche client ['+id+']';
|
||||
let modal_body='Client inconnu !';
|
||||
let modal_footer='<button>Enregistrer</button';
|
||||
|
||||
clients.filter(client => client.idclient == id)
|
||||
.forEach(resultat => {
|
||||
modal_body = '<table class="modal_table">';
|
||||
modal_body += '<tr><td style="width:30%">Id</td><td>'+resultat.idclient+'</td></tr>';
|
||||
modal_body += '<tr><td style="width:30%">Code</td><td>'+resultat.code+'</td></tr>';
|
||||
modal_body += '<tr><td style="width:30%">Nom</td><td>'+resultat.nom+'</td></tr>';
|
||||
modal_body += '</table>';
|
||||
});
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
}
|
||||
});
|
||||
};
|
||||
98
frontend/src/scripts/api/collaborateurs.js
Normal file
98
frontend/src/scripts/api/collaborateurs.js
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
var collaborateurs = [];
|
||||
|
||||
function setCollaborateurs(data){
|
||||
collaborateurs = data;
|
||||
}
|
||||
|
||||
getEntities('collaborateur', setCollaborateurs);
|
||||
|
||||
function getTrigrammeCollaborateur(intervenant) {
|
||||
let trigramme = intervenant;
|
||||
collaborateurs.forEach((collaborateur) => {
|
||||
if (collaborateur.nom == intervenant) trigramme = collaborateur.trigramme;
|
||||
});
|
||||
return trigramme;
|
||||
}
|
||||
|
||||
async function addCollaborateurs(collaborateur) {
|
||||
let url = '../backend/api.php?entity=collaborateur';
|
||||
let response = await fetch(url, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(collaborateur),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
let data = await response.json(); //extract JSON from the http response
|
||||
}
|
||||
|
||||
function initDatagridCollaborateurs() {
|
||||
let element = document.querySelector('#datagrid');
|
||||
element.innerHTML= '<center>Loading colaborateurs ...</center>'
|
||||
setCollaborateurs(null);
|
||||
getEntities('collaborateur', __initDatagridCollaborateurs);
|
||||
}
|
||||
|
||||
function __initDatagridCollaborateurs(data) {
|
||||
let element = document.querySelector('#datagrid');
|
||||
let contenu='';
|
||||
|
||||
setCollaborateurs(data);
|
||||
|
||||
contenu += '<table>';
|
||||
contenu += ' <thead>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th>Id</th>';
|
||||
contenu += ' <th>Nom</th>';
|
||||
contenu += ' <th>Trigramme</th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </thead>';
|
||||
|
||||
contenu += ' <tbody>';
|
||||
collaborateurs.forEach(collaborateur => {
|
||||
contenu += ' <tr class="js-open-modal-trigger" data-modal-info="collaborateur:id='+collaborateur.idcollaborateur+'">';
|
||||
contenu += ' <td>'+collaborateur.idcollaborateur+'</td>';
|
||||
contenu += ' <td>'+collaborateur.nom+'</td>';
|
||||
contenu += ' <td>'+collaborateur.trigramme+'</td>';
|
||||
contenu += ' </tr>';
|
||||
});
|
||||
contenu += ' </body>';
|
||||
|
||||
contenu += ' <tfoot>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th colspan="3"> </th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </foot>';
|
||||
contenu += '</table>';
|
||||
|
||||
element.innerHTML = contenu;
|
||||
|
||||
init_modal();
|
||||
}
|
||||
|
||||
modal_hooks['collaborateur'] = function(parametres){
|
||||
let paramSplit = parametres.split(',');
|
||||
paramSplit.forEach(element => {
|
||||
let elemSplit=element.split('=');
|
||||
if (elemSplit[0] === 'id') {
|
||||
let id = elemSplit[1];
|
||||
let modal_header='Fiche collaborateur ['+id+']';
|
||||
let modal_body='Collaborateur inconnu !';
|
||||
let modal_footer='<button>Enregistrer</button';
|
||||
|
||||
collaborateurs.filter(collaborateur => collaborateur.idcollaborateur == id)
|
||||
.forEach(resultat => {
|
||||
modal_body = '<table class="modal_table">';
|
||||
modal_body += '<tr><td style="width:30%">Id</td><td>'+resultat.idcollaborateur+'</td></tr>';
|
||||
modal_body += '<tr><td style="width:30%">Nom</td><td>'+resultat.nom+'</td></tr>';
|
||||
modal_body += '<tr><td style="width:30%">Trigramme</td><td>'+resultat.trigramme+'</td></tr>';
|
||||
modal_body += '</table>';
|
||||
});
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
}
|
||||
});
|
||||
};
|
||||
5
frontend/src/scripts/api/entities.js
Normal file
5
frontend/src/scripts/api/entities.js
Normal file
@@ -0,0 +1,5 @@
|
||||
function getEntities(entity, callback) {
|
||||
return fetch('../backend/api.php?entity='+entity)
|
||||
.then(response => response.json())
|
||||
.then(data => callback(data));
|
||||
}
|
||||
728
frontend/src/scripts/api/items.js
Normal file
728
frontend/src/scripts/api/items.js
Normal file
@@ -0,0 +1,728 @@
|
||||
var items = null;
|
||||
var items_max_level = 0;
|
||||
var padding_end_char = '0';
|
||||
var padding_start_char = '0';
|
||||
var padding_length = 8;
|
||||
|
||||
var useClone = true;
|
||||
|
||||
var itemFields = [];
|
||||
|
||||
var debug_item = -1;
|
||||
function isDebugItem(item) {
|
||||
return (item.idlignes == debug_item);
|
||||
}
|
||||
|
||||
function getItemFromElement(element)
|
||||
{
|
||||
if (useClone) return (element?.clone ?? null);
|
||||
return element;
|
||||
}
|
||||
function AddCloneToElement(element)
|
||||
{
|
||||
if (useClone) element.clone = Object.assign({}, element);
|
||||
return useClone;
|
||||
}
|
||||
|
||||
function setLevelPadding(level)
|
||||
{
|
||||
let retour = '';
|
||||
if (level > 0)
|
||||
for(i=0;i<level;i++) retour += ' ';
|
||||
return retour;
|
||||
}
|
||||
|
||||
function itemGetParentItem(item) {
|
||||
return getItemFromElement(items.filter(ee => ee.idlignes == item.parent)[0]);
|
||||
}
|
||||
|
||||
function setItems(data) {
|
||||
items = data;
|
||||
items_max_level = 0;
|
||||
|
||||
// Ajouter une copie de lui-même à chaque item
|
||||
items.forEach(element => AddCloneToElement(element));
|
||||
|
||||
// Trouver le niveau de l'item et mettre à jour le niveau max
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
let parent = getItemFromElement(items.filter(ee => ee.idlignes == item.parent)[0]);
|
||||
|
||||
if (isDebugItem(item)){
|
||||
myLog("ICI");
|
||||
}
|
||||
|
||||
// gestion du rang vide
|
||||
if (item['rank'] == '') item['rank'] = '0';
|
||||
|
||||
// Recherche du niveau, des ancêtres et des enfants
|
||||
item['level']=0;
|
||||
item['parents'] = [];
|
||||
while(parent != null){
|
||||
item['level'] += 1;
|
||||
item['parents'].push(parent['idlignes']);
|
||||
parent = getItemFromElement(items.filter(ee => ee.idlignes == parent.parent)[0]);
|
||||
}
|
||||
item['childs'] = [];
|
||||
items.forEach(ee => {if (ee['parent'] == item['idlignes']) item['childs'].push(ee['idlignes']) });
|
||||
|
||||
if (items_max_level < item['level']) items_max_level = item['level']+1;
|
||||
|
||||
item['debut'] = item['debut']?.padEnd(12,'0') ?? '000000000000';
|
||||
item['fin'] = item['fin']?.padEnd(12,'0') ?? '999999990000';
|
||||
|
||||
if (item['debut']=='000000000000') item['debut']=item['fin'];
|
||||
|
||||
item['visible'] = true;
|
||||
|
||||
// En mode feuille, seules les feuilles sont visibles
|
||||
if (getParametreValeur(['mode_feuille']))
|
||||
if (item['childs'].length != 0)
|
||||
item['visible'] = false;
|
||||
|
||||
});
|
||||
|
||||
// Gestion de l'héritage des propriétés
|
||||
// On en profite pour calculer le chemin de l'item
|
||||
// Et pour calculer une valeur qui permette le tri dans l'affiche tree
|
||||
// ie
|
||||
let heritage = ['contrat','projet','intervenant','client'];
|
||||
for(i=0;i<items_max_level+1;i++) {
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
if (item['level']==i) {
|
||||
let parent = getItemFromElement(items.filter(ee => ee.idlignes == item.parent)[0]);
|
||||
item['path'] = item['rank'].padStart(3,padding_start_char)+item['idlignes'].padStart(padding_length,padding_start_char);
|
||||
item['tritree']=item['path'];
|
||||
if (parent != null) {
|
||||
item['tritree']=parent['tritree']+item['debut']+item['tritree'];
|
||||
item['path'] = parent['path']+item['path'];
|
||||
for(var field in parent)
|
||||
if (heritage.indexOf(field) !== -1)
|
||||
if ((item[field] == null)||(item[field]==''))
|
||||
item[field] = parent[field];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Gestion de la remontée des propriétés
|
||||
for(i=items_max_level+1;i>=0;i--) {
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
if (item['level']==i) {
|
||||
if (item.childs.length != 0) {
|
||||
item.jours_commandes = 0.0;
|
||||
item.jours_planifies = 0.0;
|
||||
item.jours_realises = 0.0;
|
||||
item.childs.forEach(child => {
|
||||
let childElement = items.filter(ee => ee.idlignes == child)[0];
|
||||
let enfant = getItemFromElement(childElement);
|
||||
if (isDebugItem(item)){
|
||||
myLog("ICI");
|
||||
}
|
||||
item.jours_commandes += customParseFloat(enfant.jours_commandes);
|
||||
item.jours_planifies += customParseFloat(enfant.jours_planifies);
|
||||
item.jours_realises += customParseFloat(enfant.jours_realises);
|
||||
});
|
||||
}
|
||||
}
|
||||
// L'element porte une commande, on annule le calcul
|
||||
if (customParseFloat(element.jours_commandes) > 0) item.jours_commandes = element.jours_commandes;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---- Cette fonction détermine la visibilité des item
|
||||
// -----------------------------------------------------------------------------
|
||||
function setItemsVisibility(){
|
||||
let mode_affichage=getContexteValeur('mode_affichage');
|
||||
let termine=getContexteValeur('termine');
|
||||
let client = getContexteValeur('client');
|
||||
let level = parseInt(getContexteValeur('level'));
|
||||
let idfiltre = stringDatePadDigits(parseInt(getContexteValeur('parent')),8);
|
||||
|
||||
/*
|
||||
TODO : Faire la part des choses entre "contexte" et "filtre"
|
||||
A priori :
|
||||
Un filtre dépend des données exemples
|
||||
- filtrer parmi les clients
|
||||
- filtrer parmi les niveaux
|
||||
Un contexte dépend de l'appli, exemples
|
||||
- utilistaeur connecté
|
||||
- mode d'affichage courant
|
||||
*/
|
||||
client = getFiltreValeur('client');
|
||||
|
||||
level = parseInt(getFiltreValeur('level'));
|
||||
if (idfiltre != '00000000'){
|
||||
let itemFiltre = getItemFromElement(items.filter(ee => ee.idlignes == parseInt(idfiltre))[0]);
|
||||
if (itemFiltre) level += itemFiltre['level'];
|
||||
}
|
||||
|
||||
// Gestion de la visibilité individuelle
|
||||
// Que l'on va appeler 'filtre'
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
|
||||
if (isDebugItem(item)){
|
||||
myLog("ICI");
|
||||
}
|
||||
|
||||
item['visible'] = true;
|
||||
|
||||
// Contrôle du statut
|
||||
if ((item['status'] != 0)&&(item['status'] != 3)) item['visible'] = false;
|
||||
|
||||
// Contrôle du client courant
|
||||
if ((client != '') && (client != item['client'])) item['visible'] = false;
|
||||
|
||||
// Contrôle du niveau courant
|
||||
if (item['level'] > level) item['visible'] = false;
|
||||
|
||||
// Cas particulier
|
||||
// ABS = Absences
|
||||
// FER = Fériés
|
||||
// REL = Releases de version
|
||||
// RDV = Rendez-Vous
|
||||
|
||||
switch(mode_affichage){
|
||||
case 'absences':
|
||||
if (item['client'] != 'ABS') item['visible'] = false;
|
||||
break;
|
||||
case 'releases':
|
||||
if (item['client'] != 'REL') item['visible'] = false;
|
||||
break;
|
||||
case 'feries':
|
||||
if (item['client'] != 'FER') item['visible'] = false;
|
||||
break;
|
||||
case 'rdv':
|
||||
if (item['client'] != 'RDV') item['visible'] = false;
|
||||
break;
|
||||
case 'planning':
|
||||
case 'calendar_intervenants':
|
||||
case 'calendar_clients':
|
||||
|
||||
break;
|
||||
default:
|
||||
//if (item['client'] == 'ABS') item['visible'] = false;
|
||||
if (item['client'] == 'RDV') item['visible'] = false;
|
||||
if (item['client'] == 'FER') item['visible'] = false;
|
||||
if (item['client'] == 'REL') item['visible'] = false;
|
||||
}
|
||||
|
||||
// Appliquer le filtre
|
||||
if ((idfiltre != '00000000') && (!item['path'].includes(idfiltre))) item['visible'] = false;
|
||||
|
||||
if ((termine=='non')&&(item['status']!=0)) item['visible']=false;
|
||||
|
||||
// La racine est toujours visible
|
||||
// if (item['idlignes'] == 1) item['visible'] = true;
|
||||
});
|
||||
|
||||
// Gestion des statuts hérités
|
||||
// Si un parent est terminé alors ses enfants aussi
|
||||
for(i=0; i<items_max_level+1;i++) {
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
if (item['level']==i) {
|
||||
let parent = itemGetParentItem(item);
|
||||
if (parent != null)
|
||||
if (parent['status'] != 0) {
|
||||
item['visible'] = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Gestion de la visibilité héritée
|
||||
// Si un enfant est visible alors ses parents aussi
|
||||
for(i=items_max_level+1;i>=0;i--) {
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
if (item['level']==i) {
|
||||
if (item['visible']) {
|
||||
let parent = itemGetParentItem(item);
|
||||
if (parent != null)
|
||||
parent['visible'] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---- foncttons de tri des items
|
||||
// -----------------------------------------------------------------------------
|
||||
function sort2ItemsByField(item_a, item_b, field){
|
||||
let retour = 0;
|
||||
if (item_a[field] < item_b[field]) retour = -1;
|
||||
if (item_a[field] > item_b[field]) retour = 1;
|
||||
return retour;
|
||||
}
|
||||
|
||||
function sort2ItemsByDates(item_a, item_b){
|
||||
let retour = 0;
|
||||
let maintenant = formatDatetoStringDateTime(new Date);
|
||||
|
||||
// Par défaut, on trie par date de début
|
||||
let val_a = item_a['debut']?.padEnd(12,'0');
|
||||
let val_b = item_b['debut']?.padEnd(12,'0');
|
||||
|
||||
// Sauf si l'item est en cours.
|
||||
if ((item_a.debut < maintenant)&&(item_a.fin>=maintenant))
|
||||
val_a = item_a['fin']?.padEnd(12,'0');
|
||||
|
||||
if ((item_b.debut < maintenant)&&(item_b.fin>=maintenant))
|
||||
val_b = item_b['fin']?.padEnd(12,'0');
|
||||
|
||||
// Ce qui n'est pas planifié est plus tard que le reste
|
||||
if (val_a == '') val_a = '999999999999';
|
||||
if (val_b == '') val_b = '999999999999';
|
||||
|
||||
if (val_a < val_b) return -1;
|
||||
if (val_a > val_b) return 1;
|
||||
|
||||
// retour = sort2ItemsByField(item_a, item_b, 'debut');
|
||||
// if (retour != 0) return retour;
|
||||
|
||||
retour = sort2ItemsByField(item_a, item_b, 'rank');
|
||||
if (retour != 0) return retour;
|
||||
|
||||
retour = sort2ItemsByField(item_a, item_b, 'idlignes');
|
||||
if (retour != 0) return retour;
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
function sort2ItemsByStartDates(item_a, item_b){
|
||||
retour = sort2ItemsByField(item_a, item_b, 'debut');
|
||||
if (retour != 0) return retour;
|
||||
|
||||
retour = sort2ItemsByField(item_a, item_b, 'fin');
|
||||
if (retour != 0) return retour;
|
||||
|
||||
retour = sort2ItemsByField(item_a, item_b, 'idlignes');
|
||||
if (retour != 0) return retour;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function sort2ItemsByEndDates(item_a, item_b){
|
||||
|
||||
retour = sort2ItemsByField(item_a, item_b, 'fin');
|
||||
if (retour != 0) return retour;
|
||||
|
||||
retour = sort2ItemsByField(item_a, item_b, 'debut');
|
||||
if (retour != 0) return retour;
|
||||
|
||||
retour = sort2ItemsByField(item_a, item_b, 'idlignes');
|
||||
if (retour != 0) return retour;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function sortItemsByDate(){
|
||||
let maintenant = formatDatetoStringDateTime(new Date);
|
||||
|
||||
items.sort((a, b) => {
|
||||
let item_a = getItemFromElement(a);
|
||||
let item_b = getItemFromElement(b);
|
||||
|
||||
// Par défaut, on trie par date de début
|
||||
let val_a = item_a['debut'];
|
||||
let val_b = item_b['debut'];
|
||||
|
||||
// Sauf si l'item est en cours.
|
||||
if ((item_a.debut < maintenant)&&(item_a.fin>=maintenant))
|
||||
val_a = item_a['fin'];
|
||||
|
||||
if ((item_b.debut < maintenant)&&(item_b.fin>=maintenant))
|
||||
val_b = item_b['fin'];
|
||||
|
||||
if (val_a < val_b) return -1;
|
||||
if (val_a > val_b) return 1;
|
||||
|
||||
return sort2ItemsByStartDates(item_a, item_b);
|
||||
});
|
||||
}
|
||||
|
||||
function sortItemsByEndDate() {
|
||||
items.sort((a, b) => {
|
||||
let item_a = getItemFromElement(a);
|
||||
let item_b = getItemFromElement(b);
|
||||
return sort2ItemsByEndDates(item_a, item_b);
|
||||
});
|
||||
}
|
||||
|
||||
function sortItemsByStartDate() {
|
||||
items.sort((a, b) => {
|
||||
let item_a = getItemFromElement(a);
|
||||
let item_b = getItemFromElement(b);
|
||||
return sort2ItemsByStartDates(item_a, item_b);
|
||||
});
|
||||
}
|
||||
|
||||
/* TO DELETE
|
||||
function sortItemsByPath() {
|
||||
items.sort((a, b) => {
|
||||
let item_a = getItemFromElement(a);
|
||||
let item_b = getItemFromElement(b);
|
||||
return sort2ItemsByField(item_a, item_b, 'path');
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
function sortItemsByTriTreeValue() {
|
||||
items.sort((a, b) => {
|
||||
let item_a = getItemFromElement(a);
|
||||
let item_b = getItemFromElement(b);
|
||||
|
||||
return sort2ItemsByField(item_a, item_b,'tritree');
|
||||
});
|
||||
}
|
||||
|
||||
function sortItemsByPathDates() {
|
||||
items.sort((a, b) => {
|
||||
let item_a = getItemFromElement(a);
|
||||
let item_b = getItemFromElement(b);
|
||||
let retour = 0;
|
||||
|
||||
// Les 2 items sont des feuilles du même parent
|
||||
// On les trie par rang puis par dates
|
||||
if ((item_a.childs.length == 0)&&(item_b.childs.length == 0)){
|
||||
if (item_a.parent === item_b.parent){
|
||||
retour = sort2ItemsByField(item_a, item_b,'rank');
|
||||
if (retour == 0) retour = sort2ItemsByDates(item_a, item_b);
|
||||
}
|
||||
}
|
||||
|
||||
if (retour == 0) retour = sort2ItemsByField(item_a, item_b,'path');
|
||||
|
||||
return retour;
|
||||
});
|
||||
}
|
||||
|
||||
function sortItemsByClientParentDates() {
|
||||
return sortItemsByTriTreeValue();
|
||||
}
|
||||
|
||||
/* TO DELETE
|
||||
function sortItemsModeTasks() {
|
||||
sortItemsByPath();
|
||||
}
|
||||
*/
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---- Cette fonction charge les items
|
||||
// -----------------------------------------------------------------------------
|
||||
function initDatagridItems() {
|
||||
datagridLoading();
|
||||
return getEntities(getContexteValeur('items_type'), __initDatagridItems);
|
||||
}
|
||||
|
||||
function __initDatagridItems(data) {
|
||||
setItems(data);
|
||||
return afficherItems();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---- Placer un filtre
|
||||
// -----------------------------------------------------------------------------
|
||||
function filtrerItem(id){
|
||||
items.filter(item => item.idlignes == id).forEach(element => {
|
||||
let item=getItemFromElement(element);
|
||||
setContexteValeur('parent',id);
|
||||
setContexteValeur('client',item['client']);
|
||||
setContexteValeur('parent_level',item['level']);
|
||||
});
|
||||
gotoTop();
|
||||
afficherItems();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---- Cette fonction détermine l'entité à afficher en fonction du contexte
|
||||
// -----------------------------------------------------------------------------
|
||||
function clearElement(idElement){
|
||||
let element = document.querySelector(idElement);
|
||||
if (element) element.innerHTML = '';
|
||||
}
|
||||
function afficherItems() {
|
||||
let callback_affichage = datagrid_hooks[getContexteValeur('mode_affichage')];
|
||||
|
||||
clearElement("#datagrid");
|
||||
clearElement("#calendrier");
|
||||
|
||||
setItemsVisibility();
|
||||
|
||||
if (callback_affichage === null) callback_affichage = datagrid_hooks['items'];
|
||||
|
||||
callback_affichage();
|
||||
|
||||
init_modal();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// ---- Édition générique des items
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
var items_edit_hooks = [];
|
||||
var item_save_hooks = [];
|
||||
|
||||
function editerItem(id,libelle){
|
||||
let callback_edition=items_edit_hooks[getContexteValeur('type_courant')];
|
||||
|
||||
items.filter(item => item.idlignes == id).forEach(resultat => {
|
||||
callback_edition = items_edit_hooks[resultat.type];
|
||||
});
|
||||
|
||||
if ((callback_edition===null)||(callback_edition===undefined)) {
|
||||
callback_edition = items_edit_hooks['ITEM'];
|
||||
}
|
||||
|
||||
return callback_edition(id, libelle);
|
||||
}
|
||||
|
||||
function itemAPI(idlignes, bodyJSON) {
|
||||
let url = '../backend/api.php?entity=lignes';
|
||||
|
||||
if (idlignes != 1) // On ne sauve pas la racine
|
||||
{
|
||||
if (idlignes != -1) url += '&id='+idlignes;
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
body: bodyJSON, // string or object
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then((response) => response.json()).then((objet) => {
|
||||
initDatagridItems()
|
||||
.then(() => {
|
||||
if (idlignes != -1) itemInfo(idlignes);
|
||||
else close_modal();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function itemInfo(id){
|
||||
let cur_type='ITEM';
|
||||
items.filter(item => item.idlignes == id).forEach(resultat => {
|
||||
cur_type=resultat.type;
|
||||
});
|
||||
return modal_hooks['ITEM']('type='+cur_type+':id='+id);
|
||||
}
|
||||
|
||||
function itemSave(type, id){
|
||||
return item_save_hooks[type](id);
|
||||
}
|
||||
|
||||
function itemChangeAttribut(id, attribut, valeur) {
|
||||
let bodyJSON = '{"idlignes":'+id+', "'+attribut+'": "'+valeur+'"}';
|
||||
return itemAPI(id, bodyJSON, itemInfo);
|
||||
}
|
||||
|
||||
function eventItemChangeType(id, event) {
|
||||
return itemChangeAttribut(id, 'type',event.target.value);
|
||||
}
|
||||
function eventItemChangeStatus(id, event) {
|
||||
return itemChangeAttribut(id, 'status',event.target.value);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// ---- Gestion générique des items
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
itemFields['ITEM'] = ['parent','type','client','intervenant','libelle'];
|
||||
|
||||
let last_path='';
|
||||
let last_path_retour;
|
||||
function explodePath(path, id)
|
||||
{
|
||||
let retour = '';
|
||||
let start = 0;
|
||||
const nb_numeros = 3;
|
||||
if (!last_path.includes(path)) last_path=path;
|
||||
|
||||
if (last_path.length > nb_numeros*8) {
|
||||
start = (last_path.length - (nb_numeros*11));
|
||||
retour = '... > ';
|
||||
}
|
||||
|
||||
for(let i=start;i<last_path.length;i+=11){
|
||||
let split = parseInt(last_path.substring(i,i+11));
|
||||
if (split != 1) {
|
||||
if (id == split) split = '<b>'+split+'</b>';
|
||||
if (i>start) retour += ' > ';
|
||||
retour += '<span onclick="itemInfo('+split+')" style="cursor: pointer">'+split+'</span>';
|
||||
}
|
||||
else retour = '...';
|
||||
}
|
||||
return retour ;
|
||||
}
|
||||
|
||||
datagrid_hooks['items'] = function(){
|
||||
let element = document.querySelector("#datagrid");
|
||||
let contenu = "";
|
||||
|
||||
sortItemsByTriTreeValue();
|
||||
|
||||
contenu += '<table width="100vw">';
|
||||
contenu += " <thead>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th style="width:50px"><span class="nouveau" onclick="editerItem(-1,\'\')">Nouveau</span></th>';
|
||||
contenu += ' <th colspan="2"> </th>';
|
||||
contenu += ' <th><span class="filtrer">Filtre</span></th>';
|
||||
contenu += " </tr>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th style="width:50px">Client</th>';
|
||||
contenu += " <th>Libelle</th>";
|
||||
contenu += " <th><center>Type</center></th>";
|
||||
contenu += " <th><center>État</center></th>";
|
||||
contenu += " </tr>";
|
||||
contenu += " </thead>";
|
||||
|
||||
contenu += " <tbody>";
|
||||
items.forEach((element) => {
|
||||
let item = getItemFromElement(element);
|
||||
let texte = getNonNullTextValeur(item.libelle);
|
||||
|
||||
if (item.status == 3) texte = "<strike>" + texte + "</strike>";
|
||||
|
||||
// On n'affiche pas la racine
|
||||
if (item["idlignes"] == 1) return true;
|
||||
|
||||
// On n'affiche que ce qui est marqué comme visible
|
||||
if (!item["visible"]) return true;
|
||||
|
||||
contenu += ' <tr class="js-open-modal-trigger" data-modal-info="'+item.type+':id=' + item.idlignes + '">';
|
||||
contenu += ' <td style="width:50px">' + item.client + '</td>';
|
||||
contenu += " <td>" + setLevelPadding(item["level"]) + texte + "</td>";
|
||||
contenu += ' <td><center>' + item.type + "</center></td>";
|
||||
contenu += " <td><center>" + getStatusLibelleFromId(item.status) + "</center></td>";
|
||||
contenu += " </tr>";
|
||||
});
|
||||
contenu += " </body>";
|
||||
|
||||
contenu += " <tfoot>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th colspan="4"> </th>';
|
||||
contenu += " </tr>";
|
||||
contenu += " </foot>";
|
||||
contenu += "</table>";
|
||||
|
||||
element.innerHTML = contenu;
|
||||
}
|
||||
|
||||
function getItemDialogHeader(item){
|
||||
let retour='';
|
||||
let liste_select_types = ['TODO','TACHE','PRESTATION','ITEM'];
|
||||
|
||||
retour += '<select onchange="eventItemChangeType('+item.idlignes+',event)">';
|
||||
liste_select_types.forEach((valeur)=>{
|
||||
let selected = '';
|
||||
if (valeur == item.type) selected='selected';
|
||||
retour += '<option value="'+valeur+'" '+selected+'>'+valeur+'</opton>';
|
||||
});
|
||||
retour += '</select><br>';
|
||||
retour += ' n°'+explodePath(item.clone.path,item.idlignes);
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
modal_hooks['ITEM'] = function(parametres){
|
||||
let cur_type=null;
|
||||
let cur_id=null;
|
||||
let modal_header='';
|
||||
let modal_body='item inconnu !';
|
||||
let modal_footer='';
|
||||
let paramSplit = parametres.split(':');
|
||||
|
||||
paramSplit.forEach(element => {
|
||||
let elemSplit=element.split('=');
|
||||
if (elemSplit[0]==='type') cur_type=elemSplit[1];
|
||||
if (elemSplit[0]==='id') cur_id=elemSplit[1];
|
||||
});
|
||||
|
||||
if (itemFields[cur_type]===undefined) cur_type='ITEM';
|
||||
|
||||
items.filter(item => item.idlignes == cur_id).forEach(resultat => {
|
||||
let liste_status = ['Planifié', 'Supprimé', 'Annulé', 'Terminé','Reporté'];
|
||||
|
||||
modal_header = getItemDialogHeader(resultat);
|
||||
|
||||
modal_body = '<table class="modal_table">';
|
||||
itemFields[cur_type].forEach(attribut => {
|
||||
let valeur = getNonNullTextValeur(resultat[attribut]);
|
||||
if (attribut =='libelle') valeur = '<b>'+valeur+'</b>';
|
||||
modal_body += '<tr class="tr1"><td>'+attribut+'</td><td>'+valeur+'</td></tr>';
|
||||
});
|
||||
modal_body += '</table>';
|
||||
|
||||
modal_footer += '<div align="left" width="50%" style="float:left;padding-top:2vh">';
|
||||
modal_footer += '<button onclick="editerItem('+resultat.idlignes+',null)">Modifier</button>';
|
||||
modal_footer += '<button onclick="filtrerItem('+resultat.idlignes+')">Filtrer</button> ';
|
||||
modal_footer += '</div>';
|
||||
|
||||
modal_footer += '<div align="right" width="50%" style="float:right;padding-top:2vh">';
|
||||
modal_footer += '<button onclick="lancerPomodoroItem('+resultat.idlignes+')">Lancer</button>';
|
||||
modal_footer += '<select onchange="eventItemChangeStatus('+resultat.idlignes+',event)">';
|
||||
liste_status.forEach((valeur,index)=>{
|
||||
let selected = '';
|
||||
if (index == resultat.status) selected='selected';
|
||||
modal_footer += '<option value="'+index+'" '+selected+'>'+valeur+'</option>';
|
||||
});
|
||||
modal_footer += '</select><br>';
|
||||
|
||||
modal_footer += '</div>';
|
||||
});
|
||||
|
||||
modal_footer += '<div style="clear:both">';
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
}
|
||||
|
||||
items_edit_hooks['ITEM'] = function (id, libelle) {
|
||||
let modal_header='';
|
||||
let modal_body='Item inconnu !';
|
||||
let modal_footer='<div align="right" width="100%" style="padding-top:2vh"><button onclick="itemSave('+id+')">Enregistrer</button></div>';
|
||||
|
||||
let local_values = [];
|
||||
let local_placeholder = [];
|
||||
|
||||
local_values['parent']=getContexteValeur('parent');
|
||||
local_values['type']=getContexteValeur('type_courant');
|
||||
local_values['client']=getContexteValeur('client');
|
||||
local_values['intervenant']=getContexteValeur('intervenant');
|
||||
local_values['libelle']=libelle;
|
||||
|
||||
if (local_values['client']=='') local_values['client']=getTrigrammeCollaborateur(local_values['intervenant']);
|
||||
|
||||
items.filter(item => item.idlignes == id).forEach(resultat => {
|
||||
local_values['type']=resultat['type'];
|
||||
itemFields[local_values['type']].forEach(attribut => {
|
||||
local_values[attribut]=resultat[attribut];
|
||||
local_placeholder[attribut]=resultat.clone[attribut];
|
||||
});
|
||||
});
|
||||
|
||||
modal_header=local_values['type'];
|
||||
if (id != -1) modal_header+=' n°<b>'+id+'</b>';
|
||||
|
||||
modal_body = '<table class="modal_table"><form id="formulaire_lignes">';
|
||||
itemFields[local_values['type']].forEach(attribut => {
|
||||
modal_body += '<tr><td>'+attribut+'</td><td>'+getInputLabel(attribut,local_values[attribut], local_placeholder[attribut])+'</td></tr>';
|
||||
});
|
||||
modal_body += '</form></table>';
|
||||
|
||||
modal_footer='<div align="left" width="100%" style="padding-top:2vh"><button onclick="itemSave(\''+local_values['type']+'\','+id+')">Enregistrer</button></div>';
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
|
||||
if (!modalDialog.open) modalDialog.showModal();
|
||||
}
|
||||
118
frontend/src/scripts/api/items/prestations.js
Normal file
118
frontend/src/scripts/api/items/prestations.js
Normal file
@@ -0,0 +1,118 @@
|
||||
|
||||
itemFields['PRESTATION'] = ['libelle','parent','rank','client','intervenant','debut','fin','contrat','projet','jours_commandes','jours_planifies','jours_realises'];
|
||||
|
||||
datagrid_hooks['prestations'] = function() {
|
||||
let element = document.querySelector("#datagrid");
|
||||
let contenu = "";
|
||||
let nbLignes = 1;
|
||||
let parentLevel=getContexteValeur('parent_level');
|
||||
let showPrestationsOnly=(getContexteValeur('prestation')=='oui');
|
||||
|
||||
if (parentLevel == 0) parentLevel=1;
|
||||
|
||||
sortItemsByClientParentDates();
|
||||
|
||||
contenu += "<table>";
|
||||
contenu += " <thead>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th colspan="6" onchange="updateValue(event)"><input id="newitem_input" type="text" placeholder="Nouvel item" style="width: 98%;outline: none"></th>';
|
||||
contenu += " </tr>";
|
||||
contenu += " <tr>";
|
||||
// contenu += " <th><center>Id</center></th>";
|
||||
contenu += ' <th style="width:50px;text-align:center"><span onclick="openFiltrePopup(\'client\')">Client</span></th>';
|
||||
contenu += ' <th style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis"><span onclick="openFiltrePopup(\'libelle\')">Libellé</span></th>';
|
||||
contenu += ' <th style="max-width:150px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis"><span onclick="openFiltrePopup(\'contrat\')">Contrat</span></th>';
|
||||
contenu += ' <th style="max-width:150px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis"><span onclick="openFiltrePopup(\'libelle\')">Commandés</span></th>';
|
||||
contenu += ' <th style="max-width:150px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis"><span onclick="openFiltrePopup(\'libelle\')">Prévus</span></th>';
|
||||
contenu += ' <th style="max-width:150px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis"><span onclick="openFiltrePopup(\'libelle\')">Réalisés</span></th>';
|
||||
// contenu += " <th><center>État</center></th>";
|
||||
contenu += " </tr>";
|
||||
contenu += " </thead>";
|
||||
|
||||
contenu += " <tbody>";
|
||||
|
||||
items.forEach((element) => {
|
||||
let item = getItemFromElement(element);
|
||||
let texte = getNonNullTextValeur(item.libelle);
|
||||
let commandes = "-";
|
||||
let planifies = "-";
|
||||
let realises = "-";
|
||||
|
||||
// On n'affiche pas la racine
|
||||
if (item["idlignes"] == 1) return true;
|
||||
// On n'affiche que ce qui est marqué comme visible
|
||||
if (!item["visible"]) return true;
|
||||
|
||||
if ((showPrestationsOnly)&&((item.jours_commandes + item.jours_realises+item.jours_planifies) == 0)) return true;
|
||||
|
||||
if (item.status == 3) texte = "<strike>" + texte + "</strike>";
|
||||
if (item.status == 2) texte = "<strike>" + texte + "</strike>";
|
||||
|
||||
if (item.jours_commandes > 0)
|
||||
commandes = convertJourHeure(getNonNullTextValeur(item.jours_commandes));
|
||||
|
||||
if (item.jours_realises > 0)
|
||||
realises = convertJourHeure(getNonNullTextValeur(item.jours_realises));
|
||||
|
||||
if (item.jours_planifies > 0)
|
||||
planifies = convertJourHeure(getNonNullTextValeur(item.jours_planifies));
|
||||
|
||||
contenu += ' <tr class="js-open-modal-trigger" data-modal-info="type='+item.type+':id=' + getNonNullTextValeur(item.idlignes) + '">';
|
||||
//contenu += " <td><center>" + getNonNullTextValeur(item.idlignes) + "</center></td>";
|
||||
contenu += ' <td style="width:50px;text-align:center">' + getNonNullTextValeur(item.client) + '</td>';
|
||||
contenu += ' <td style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">' + setLevelPadding(item["level"]-parentLevel) + texte + '</td>';
|
||||
contenu += ' <td style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">' + getNonNullTextValeur(item.contrat) + '</td>';
|
||||
contenu += ' <td style="width:50px;text-align:center">' + commandes + '</td>';
|
||||
contenu += ' <td style="width:100px;text-align:center">' + planifies + '</td>';
|
||||
contenu += ' <td style="width:100px;text-align:center">' + realises + '</td>';
|
||||
//contenu += " <td>" + getStatusLibelleFromId(item.status) + '</td>';
|
||||
contenu += " </tr>";
|
||||
|
||||
nbLignes += 1;
|
||||
});
|
||||
contenu += " </tbody>";
|
||||
|
||||
contenu += " <tfoot>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th colspan="6">'+setLevelPadding(2)+''+(nbLignes-1)+' tâches</th>';
|
||||
contenu += " </tr>";
|
||||
contenu += " </foot>";
|
||||
contenu += "</table>";
|
||||
|
||||
element.innerHTML = contenu;
|
||||
|
||||
// Ne marche pas , ça enlève le stick du header du tableau ...
|
||||
// document.getElementById('newitem_input').focus({preventScroll: true});
|
||||
}
|
||||
|
||||
function prestationSave(idlignes) {
|
||||
let bodyJSON = JSON.stringify(getCurrentPRESTATION(idlignes));
|
||||
return itemAPI(idlignes, bodyJSON, itemInfo);
|
||||
}
|
||||
|
||||
item_save_hooks['PRESTATION'] = prestationSave;
|
||||
|
||||
function getCurrentPRESTATION(idlignes)
|
||||
{
|
||||
let result = new Object();
|
||||
|
||||
if (idlignes > 1) {
|
||||
result['idlignes'] = idlignes;
|
||||
} else {
|
||||
result['type']=getContexteValeur('type_courant');
|
||||
}
|
||||
|
||||
itemFields['PRESTATION'].forEach(attribut => {
|
||||
result[attribut] = documentGetElementById('item_'+attribut);
|
||||
});
|
||||
|
||||
if (result['parent']=='') result['parent']=1;
|
||||
if (result['client']=='') result['client']==getTrigrammeCollaborateur(result['intervenant']);
|
||||
if (result['libelle']=='') result['libelle']='xxxxxxxxxxxx';
|
||||
if (result['intervevant']=='') result['intervenant']=getContexteValeur('intervenant');;
|
||||
if (result['debut']=='') result['debut']=0;
|
||||
if (result['fin']=='') result['fin']=0;
|
||||
if (result['status']=='') result['status']=0;
|
||||
|
||||
return result;
|
||||
}
|
||||
106
frontend/src/scripts/api/items/taches.js
Normal file
106
frontend/src/scripts/api/items/taches.js
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
itemFields['TACHE'] = ['libelle','parent','rank','client','intervenant','debut','fin'];
|
||||
|
||||
datagrid_hooks['taches'] = function() {
|
||||
let element = document.querySelector("#datagrid");
|
||||
let contenu = "";
|
||||
let nbLignes = 1;
|
||||
let parentLevel=getContexteValeur('parent_level');
|
||||
|
||||
if (parentLevel == 0) parentLevel=1;
|
||||
|
||||
sortItemsByClientParentDates();
|
||||
|
||||
contenu += "<table>";
|
||||
contenu += " <thead>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th colspan="4" onchange="updateValue(event)"><input id="newitem_input" type="text" placeholder="Nouvel item" style="width: 98%;outline: none"></th>';
|
||||
contenu += " </tr>";
|
||||
contenu += " <tr>";
|
||||
// contenu += " <th><center>Id</center></th>";
|
||||
contenu += ' <th style="width:50px;text-align:center"><span onclick="openFiltrePopup(\'client\')">Client</span></th>';
|
||||
contenu += ' <th style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis"><span onclick="openFiltrePopup(\'libelle\')">Libellé</span></th>';
|
||||
contenu += ' <th style="width:100px;text-align:center"><span onclick="openFiltrePopup(\'debut\')">Début</span></th>';
|
||||
contenu += ' <th style="width:100px;text-align:center"><span onclick="openFiltrePopup(\'fin\')">Fin</span></th>';
|
||||
// contenu += " <th><center>État</center></th>";
|
||||
contenu += " </tr>";
|
||||
contenu += " </thead>";
|
||||
|
||||
contenu += " <tbody>";
|
||||
|
||||
items.forEach((element) => {
|
||||
let item = getItemFromElement(element);
|
||||
let texte = getNonNullTextValeur(item.libelle);
|
||||
|
||||
if (item.status == 3) texte = "<strike>" + texte + "</strike>";
|
||||
if (item.status == 2) texte = "<strike>" + texte + "</strike>";
|
||||
|
||||
// On n'affiche pas la racine
|
||||
if (item["idlignes"] == 1) return true;
|
||||
// On n'affiche que ce qui est marqué comme visible
|
||||
if (!item["visible"]) return true;
|
||||
|
||||
contenu += ' <tr class="js-open-modal-trigger" data-modal-info="type='+item.type+':id=' + getNonNullTextValeur(item.idlignes) + '">';
|
||||
//contenu += " <td><center>" + getNonNullTextValeur(item.idlignes) + "</center></td>";
|
||||
contenu += ' <td style="width:50px;text-align:center">' + getNonNullTextValeur(item.client) + "</td>";
|
||||
contenu += ' <td style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">' + setLevelPadding(item["level"]-parentLevel) + texte + "</td>";
|
||||
contenu += ' <td style="width:100px;text-align:center">' + formatLocaleDateFromStringDate(item.debut) + "</td>";
|
||||
contenu += ' <td style="width:100px;text-align:center">' + formatLocaleDateFromStringDate(item.fin) + "</td>";
|
||||
//contenu += " <td>" + getStatusLibelleFromId(item.status) + "</td>";
|
||||
contenu += " </tr>";
|
||||
|
||||
nbLignes += 1;
|
||||
});
|
||||
contenu += " </tbody>";
|
||||
|
||||
contenu += " <tfoot>";
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th colspan="4">'+setLevelPadding(2)+''+(nbLignes-1)+' tâches</th>';
|
||||
contenu += " </tr>";
|
||||
contenu += " </foot>";
|
||||
contenu += "</table>";
|
||||
|
||||
element.innerHTML = contenu;
|
||||
|
||||
// Ne marche pas , ça enlève le stick du header du tableau ...
|
||||
// document.getElementById('newitem_input').focus({preventScroll: true});
|
||||
}
|
||||
|
||||
// on affiche ces éléments comme des tâches
|
||||
datagrid_hooks['absences'] = datagrid_hooks['taches'];
|
||||
datagrid_hooks['releases'] = datagrid_hooks['taches'];
|
||||
datagrid_hooks['feries'] = datagrid_hooks['taches'];
|
||||
datagrid_hooks['rdv'] = datagrid_hooks['taches'];
|
||||
|
||||
|
||||
function taskSave(idlignes) {
|
||||
let bodyJSON = JSON.stringify(getCurrentTASK(idlignes));
|
||||
return itemAPI(idlignes, bodyJSON, itemInfo);
|
||||
}
|
||||
|
||||
item_save_hooks['TACHE'] = taskSave;
|
||||
|
||||
function getCurrentTASK(idlignes)
|
||||
{
|
||||
let result = new Object();
|
||||
|
||||
if (idlignes > 1) {
|
||||
result['idlignes'] = idlignes;
|
||||
} else {
|
||||
result['type']=getContexteValeur('type_courant');
|
||||
}
|
||||
|
||||
itemFields['TACHE'].forEach(attribut => {
|
||||
result[attribut] = documentGetElementById('item_'+attribut);
|
||||
});
|
||||
|
||||
if (result['parent']=='') result['parent']=1;
|
||||
if (result['client']=='') result['client']==getTrigrammeCollaborateur(result['intervenant']);
|
||||
if (result['libelle']=='') result['libelle']='xxxxxxxxxxxx';
|
||||
if (result['intervevant']=='') result['intervenant']=getContexteValeur('intervenant');;
|
||||
if (result['debut']=='') result['debut']=0;
|
||||
if (result['fin']=='') result['fin']=0;
|
||||
if (result['status']=='') result['status']=0;
|
||||
|
||||
return result;
|
||||
}
|
||||
525
frontend/src/scripts/api/items/todos.js
Normal file
525
frontend/src/scripts/api/items/todos.js
Normal file
@@ -0,0 +1,525 @@
|
||||
itemFields['TODO'] = ['libelle','parent','client','intervenant','fin'];
|
||||
|
||||
function todoListLigne(item, style)
|
||||
{
|
||||
let retour = '';
|
||||
let client = getNonNullTextValeur(item.client);
|
||||
let intervenant = getTrigrammeCollaborateur(item.intervenant);
|
||||
let texte = getNonNullTextValeur(item.libelle);
|
||||
let date = item.fin;
|
||||
let classe = 'class="js-open-modal-trigger" data-modal-info="type='+item.type+':id='+item.idlignes+'"';
|
||||
let maintenant = formatDatetoStringDateTime(new Date);
|
||||
let localStyle=style;
|
||||
|
||||
if (item.status == 3) localStyle = 'text-decoration: line-through';
|
||||
|
||||
// Si l'item n'est pas un jalon
|
||||
// Si son début est dans le futur
|
||||
// On affiche le début
|
||||
if (item.type != 'TODO')
|
||||
if (item.debut > maintenant)
|
||||
date = item.debut;
|
||||
|
||||
// Ce qui est prévu pour aujourd'hui ou demain
|
||||
// On affiche l'heure
|
||||
if ((date.substring(0,8) == todayStringDate.substring(0,8))||(date.substring(0,8) == tomorrowStringDate.substring(0,8))) {
|
||||
date = formatTimeFromStringDate(date)
|
||||
} else {
|
||||
date = formatLocaleDateFromStringDate(date);
|
||||
}
|
||||
|
||||
if (intervenant != '')
|
||||
if (intervenant != client)
|
||||
texte = ' ['+intervenant+'] '+texte;
|
||||
if (client != '') texte = '['+client+'] '+texte;
|
||||
if (item.type == 'TODO')
|
||||
texte = '[♦] '+texte;
|
||||
else
|
||||
texte = '[¤] '+texte;
|
||||
|
||||
retour += ' <tr '+classe+' style="'+localStyle+'">';
|
||||
retour += ' <td style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-left:15px">'+texte+'</td>';
|
||||
retour += ' <td style="width:100px;text-align:center">'+date+'</td>';
|
||||
retour += ' </tr>';
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
function todoListSection(section, style)
|
||||
{
|
||||
let retour = '';
|
||||
retour += ' <tr style="'+style+'">';
|
||||
retour += ' <td colspan="3" style="max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-left:5px">'+section+'</td>';
|
||||
retour += ' </tr>';
|
||||
return retour;
|
||||
}
|
||||
|
||||
function getNonNullTextValeur(valeur){
|
||||
let val = valeur;
|
||||
if ((val===null)||(val===undefined)) val = '';
|
||||
return val;
|
||||
}
|
||||
|
||||
function getNonNullDateValeur(valeur){
|
||||
if (valeur === null) return '';
|
||||
if (valeur == 0) return '';
|
||||
return valeur;
|
||||
}
|
||||
|
||||
function getInputLabel(nom, valeur, placeholder) {
|
||||
return '<input style="width:99%;border:none" type="text" name="'+nom+'" id="item_'+nom+'" value="'+getNonNullTextValeur(valeur)+'" placeholder="'+getNonNullTextValeur(placeholder)+'"></input>';
|
||||
}
|
||||
|
||||
function todoTermine(idlignes) {
|
||||
myError('Fonction Obsolète : '+arguments.callee.name);
|
||||
return itemTermine(idlignes,'TODO');
|
||||
}
|
||||
|
||||
function todoSave(idlignes) {
|
||||
let bodyJSON = JSON.stringify(getCurrentTODO(idlignes));
|
||||
return itemAPI(idlignes, bodyJSON, itemInfo);
|
||||
}
|
||||
|
||||
function getCurrentTODO(idlignes)
|
||||
{
|
||||
let result = new Object();
|
||||
|
||||
if (idlignes > 1) {
|
||||
result['idlignes'] = idlignes;
|
||||
} else {
|
||||
result['type']=getContexteValeur('type_courant');
|
||||
}
|
||||
|
||||
itemFields['TODO'].forEach(attribut => {
|
||||
result[attribut] = documentGetElementById('item_'+attribut);
|
||||
});
|
||||
|
||||
if (result['parent']=='') result['parent']=1;
|
||||
if (result['client']=='') result['client']=getTrigrammeCollaborateur(result['intervenant']);
|
||||
if (result['libelle']=='') result['libelle']='xxxxxxxxxxxx';
|
||||
if (result['intervevant']=='') result['intervenant']=getContexteValeur('intervenant');;
|
||||
if (result['fin']=='') result['fin']=0;
|
||||
if (result['status']=='') result['status']=0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
datagrid_hooks['todos'] = function(){
|
||||
let datagrid = document.querySelector('#datagrid');
|
||||
let synthesis = document.querySelector('#synthesis_body');
|
||||
|
||||
let thisWeek = parseInt(stringdateGetWeekOfYear(todayStringDate));
|
||||
let thisMonth = parseInt(todayStringDate.substring(0,6));
|
||||
let thisYear = parseInt(todayStringDate.substring(0,4));
|
||||
|
||||
let client = getContexteValeur('client');
|
||||
let termine = getContexteValeur('termine');
|
||||
|
||||
let nextWeek = thisWeek + 1;
|
||||
let nextMonth = thisMonth + 1;
|
||||
let nextYear = thisYear + 1;
|
||||
|
||||
let contenu='';
|
||||
let synthese1='';
|
||||
let synthese2='';
|
||||
let nb_lignes=0;
|
||||
let lignes_vides=0;
|
||||
|
||||
let liste_retard='';
|
||||
let liste_today='';
|
||||
let liste_tomorrow='';
|
||||
let liste_thisWeek='';
|
||||
let liste_nextWeek='';
|
||||
let liste_thisMonth='';
|
||||
let liste_nextMonth='';
|
||||
let liste_thisYear='';
|
||||
let liste_nextYear='';
|
||||
let liste_noplanning = '';
|
||||
|
||||
let liste_before='';
|
||||
let liste_finished='';
|
||||
let liste_encours='';
|
||||
let liste_todo='';
|
||||
|
||||
let tableau_before=[];
|
||||
let tableau_finished=[];
|
||||
let tableau_encours=[];
|
||||
let tableau_todo=[];
|
||||
|
||||
let tableau_retard=[];
|
||||
let tableau_today=[];
|
||||
let tableau_tomorrow=[];
|
||||
let tableau_thisWeek=[];
|
||||
let tableau_nextWeek=[];
|
||||
let tableau_thisMonth=[];
|
||||
let tableau_nextMonth=[];
|
||||
let tableau_thisYear=[];
|
||||
let tableau_nextYear=[];
|
||||
let tableau_noplanning=[];
|
||||
let stats = 0;
|
||||
|
||||
// Gérer les fins d'année
|
||||
if (nextWeek > parseInt(stringdateGetWeek(thisYear+'12310000'))) nextWeek = parseInt(nextYear+'01');
|
||||
if (nextMonth > parseInt(thisYear+'12')) nextMonth = parseInt(nextYear+'01');
|
||||
|
||||
sortItemsByDate();
|
||||
|
||||
contenu += '<table>';
|
||||
contenu += ' <thead>';
|
||||
contenu += " <tr>";
|
||||
contenu += ' <th colspan="2" onchange="updateValue(event)"><input id="newitem_input" type="text" placeholder="Nouvel item" style="width: 98%;outline: none"></th>';
|
||||
contenu += " </tr>";
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th style="padding-left:5px"><span onclick="openFiltrePopup(\'libelle\')">Libellé</span></th>';
|
||||
contenu += ' <th style="width:100px;text-align:center"><span onclick="openFiltrePopup(\'fin\')">Échéance</span></th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </thead>';
|
||||
|
||||
contenu += ' <tbody>';
|
||||
|
||||
liste = '';
|
||||
items.forEach(element => {
|
||||
let item = getItemFromElement(element);
|
||||
|
||||
let itemWeek = parseInt(stringdateGetWeekOfYear(item.fin.substring(0,8)));
|
||||
let itemMonth = parseInt(item.fin.substring(0,6));
|
||||
let itemYear = parseInt(item.fin.substring(0,4));
|
||||
|
||||
// On n'affiche pas la racine
|
||||
if (item['idlignes']==1) return true;
|
||||
// On n'affiche que ce qui est marqué comme visible
|
||||
if (!item['visible']) return true;
|
||||
// On n'affiche que les feuilles
|
||||
if (item.childs.length>0) return true;
|
||||
|
||||
if (item.status == 1) return true;
|
||||
if (item.status == 2) return true;
|
||||
if (termine=='non')
|
||||
if (item['status']==3) return true;
|
||||
|
||||
if (client!='')
|
||||
if (item['client']!=client) return true;
|
||||
|
||||
// Ce qui est non planifié
|
||||
if ((item.fin.substring(0,8) == '00000000')&&(item.status == 0)) {
|
||||
tableau_noplanning.push(todoListLigne(item,'color:var(--nuance-sombre-06)'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui était pour avant cette année
|
||||
if (item.fin.substring(0,8) < thisYear+'0101')
|
||||
tableau_before.push(todoListLigne(item,''));
|
||||
|
||||
// Ce qui est terminé
|
||||
if (item.status == 3)
|
||||
tableau_finished.push(todoListLigne(item,''));
|
||||
else
|
||||
tableau_todo.push(todoListLigne(item,''));
|
||||
|
||||
// Ce qui est en retard
|
||||
if ((item.status == 0)&&(item.fin < todayStringDate)) {
|
||||
tableau_retard.push(todoListLigne(item,''));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui est prévu pour aujourd'hui
|
||||
if (((item.status == 0)||(item.status == 3))&&(item.fin.substr(0,8) == todayStringDate.substr(0,8))) {
|
||||
tableau_today.push(todoListLigne(item,'font-weight:bold'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui est prévu pour demain
|
||||
if (((item.status == 0)||(item.status == 3))&&(item.fin.substr(0,8) == tomorrowStringDate.substr(0,8))) {
|
||||
tableau_tomorrow.push(todoListLigne(item,'font-weight:bold'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui est prévu cette semaine
|
||||
if (item.fin.substring(0,8) > thisYear+'0101')
|
||||
if (itemWeek == thisWeek) {
|
||||
tableau_thisWeek.push(todoListLigne(item,'font-weight:bold'));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item.status != 0) return true;
|
||||
|
||||
// Les tâches qui ont commencé et qui ne sont pas finies
|
||||
if (item.debut.substr(0,8) < todayStringDate.substr(0,8))
|
||||
if (item.fin.substr(0,8) > todayStringDate.substr(0,8)) {
|
||||
if (item.type != 'TODO') tableau_encours.push(todoListLigne(item,'font-weight:bold'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui est prévu la semaine prochaine
|
||||
if (itemWeek == nextWeek) {
|
||||
tableau_nextWeek.push(todoListLigne(item,'color:var(--nuance-sombre-09)'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui est prévu ce mois-ci
|
||||
if (itemMonth == thisMonth) {
|
||||
tableau_thisMonth.push(todoListLigne(item,'color:var(--nuance-sombre-09)'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui est prévu le mois prochain
|
||||
if (itemMonth == nextMonth) {
|
||||
tableau_nextMonth.push(todoListLigne(item,'color:var(--nuance-sombre-09)'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui est prévu cette année
|
||||
if (itemYear == thisYear) {
|
||||
tableau_thisYear.push(todoListLigne(item,'color:var(--nuance-sombre-09)'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ce qui est prévu l'année prochaine
|
||||
if (itemYear == nextYear) {
|
||||
tableau_nextYear.push(todoListLigne(item,'color:var(--nuance-sombre-06)'));
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (tableau_before.length!=0){
|
||||
if (synthese1=='') synthese1+='<div class="statrow">';
|
||||
synthese1+='<div class="statbox2">Avant<br>'+tableau_before.length+'</div>';
|
||||
}
|
||||
|
||||
if (tableau_today.length!=0){
|
||||
liste_today += tableau_today.join('');
|
||||
nb_lignes += tableau_today.length;
|
||||
}
|
||||
stats=tableau_today.length;
|
||||
if (synthese1=='') synthese1+='<div class="statrow">';
|
||||
synthese1+='<div class="statbox1">Aujourd\'hui<br>'+stats+'</div>';
|
||||
|
||||
if (tableau_tomorrow.length!=0){
|
||||
liste_tomorrow += tableau_tomorrow.join('');
|
||||
nb_lignes += tableau_tomorrow.length;
|
||||
}
|
||||
stats+=tableau_tomorrow.length;
|
||||
if (synthese1=='') synthese1+='<div class="statrow">';
|
||||
synthese1+='<div class="statbox1">Demain<br>'+tableau_tomorrow.length+'</div>';
|
||||
|
||||
if (tableau_thisWeek.length!=0){
|
||||
liste_thisWeek += tableau_thisWeek.join('');
|
||||
nb_lignes += tableau_thisWeek.length;
|
||||
}
|
||||
stats+=tableau_thisWeek.length;
|
||||
if (synthese1=='') synthese1+='<div class="statrow">';
|
||||
synthese1+='<div class="statbox1">Cette semaine<br>'+stats+'</div>';
|
||||
|
||||
if (tableau_nextWeek.length!=0){
|
||||
liste_nextWeek += tableau_nextWeek.join('');
|
||||
nb_lignes += tableau_nextWeek.length;
|
||||
}
|
||||
stats+=tableau_nextWeek.length;
|
||||
|
||||
if (tableau_thisMonth.length!=0){
|
||||
liste_thisMonth += tableau_thisMonth.join('');
|
||||
nb_lignes += tableau_thisMonth.length;
|
||||
}
|
||||
stats+=tableau_thisMonth.length;
|
||||
if (synthese1=='') synthese1+='<div class="statrow">';
|
||||
synthese1+='<div class="statbox2">Ce mois-ci<br>'+stats+'</div>';
|
||||
|
||||
if (tableau_nextMonth.length!=0){
|
||||
liste_nextMonth += tableau_nextMonth.join('');
|
||||
nb_lignes += tableau_nextMonth.length;
|
||||
if (synthese1=='') synthese1+='<div class="statrow">';
|
||||
synthese1+='<div class="statbox2">Mois Prochain<br>'+tableau_nextMonth.length+'</div>';
|
||||
}
|
||||
stats+=tableau_nextMonth.length;
|
||||
|
||||
if (tableau_thisYear.length!=0){
|
||||
liste_thisYear += tableau_thisYear.join('');
|
||||
nb_lignes += tableau_thisYear.length;
|
||||
}
|
||||
stats+=tableau_thisYear.length;
|
||||
if (synthese1=='') synthese1+='<div class="statrow">';
|
||||
synthese1+='<div class="statbox2">Cette année<br>'+stats+'</div>';
|
||||
|
||||
if (tableau_nextYear.length!=0){
|
||||
liste_nextYear += tableau_nextYear.join('');
|
||||
nb_lignes += tableau_nextYear.length;
|
||||
if (synthese1=='') synthese1+='<div class="statrow">';
|
||||
synthese1+='<div class="statbox2">Après<br>'+tableau_nextYear.length+'</div>';
|
||||
}
|
||||
|
||||
if (tableau_finished.length != 0){
|
||||
liste_finished += tableau_retard.join('');
|
||||
if (synthese2=='') synthese2+='<div class="statrow" style="margin-top: 5px">';
|
||||
synthese2+='<div class="statbox1">Terminé<br>'+tableau_finished.length+'</div>';
|
||||
}
|
||||
|
||||
if (tableau_retard.length != 0){
|
||||
liste_retard += tableau_retard.join('');
|
||||
nb_lignes += tableau_retard.length;
|
||||
if (synthese2=='') synthese2+='<div class="statrow" style="margin-top: 5px">';
|
||||
synthese2+='<div class="statbox1">En retard<br>'+tableau_retard.length+'</div>';
|
||||
}
|
||||
|
||||
if (tableau_encours.length != 0){
|
||||
liste_encours += tableau_encours.join('');
|
||||
if (synthese2=='') synthese2+='<div class="statrow" style="margin-top: 5px">';
|
||||
synthese2+='<div class="statbox1">En cours<br>'+tableau_encours.length+'</div>';
|
||||
}
|
||||
|
||||
if (tableau_todo.length != 0){
|
||||
liste_todo += tableau_todo.join('');
|
||||
if (synthese2=='') synthese2+='<div class="statrow" style="margin-top: 5px">';
|
||||
synthese2+='<div class="statbox1">A faire<br>'+tableau_todo.length+'</div>';
|
||||
}
|
||||
|
||||
if (tableau_noplanning.length !=0) {
|
||||
liste_noplanning += tableau_noplanning.join('');
|
||||
nb_lignes += tableau_noplanning.length;
|
||||
if (synthese2=='') synthese2+='<div class="statrow" style="margin-top: 5px">';
|
||||
synthese2+='<div class="statbox2">Non-Planifiés<br>'+tableau_noplanning.length+'</div>';
|
||||
}
|
||||
|
||||
if (synthese1!='') synthese1+='</div>';
|
||||
if (synthese2!='') synthese2+='</div>';
|
||||
|
||||
lignes_vides = nb_lignes;
|
||||
|
||||
if (liste_retard != '')
|
||||
{
|
||||
contenu += todoListSection('En retard', '');
|
||||
contenu += liste_retard;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_encours != '')
|
||||
{
|
||||
contenu += todoListSection('En cours', 'font-weight:bold');
|
||||
contenu += liste_encours;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_today != '')
|
||||
{
|
||||
contenu += todoListSection('Aujourd\'hui', 'font-weight:bold');
|
||||
contenu += liste_today;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_tomorrow != '')
|
||||
{
|
||||
contenu += todoListSection('Demain', 'font-weight:bold');
|
||||
contenu += liste_tomorrow;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_thisWeek != '')
|
||||
{
|
||||
contenu += todoListSection('Cette semaine', 'font-weight:bold');
|
||||
contenu += liste_thisWeek;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_nextWeek != '')
|
||||
{
|
||||
contenu += todoListSection('La semaine prochaine', 'color:var(--nuance-sombre-09)');
|
||||
contenu += liste_nextWeek;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_thisMonth != '')
|
||||
{
|
||||
contenu += todoListSection('Ce mois-ci', 'color:var(--nuance-sombre-09)');
|
||||
contenu += liste_thisMonth;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_nextMonth != '')
|
||||
{
|
||||
contenu += todoListSection('Le mois prochain', 'color:var(--nuance-sombre-09)');
|
||||
contenu += liste_nextMonth;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_thisYear != '')
|
||||
{
|
||||
contenu += todoListSection('Cette année', 'color:var(--nuance-sombre-09)');
|
||||
contenu += liste_thisYear;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_nextYear != '')
|
||||
{
|
||||
contenu += todoListSection('L\'année prochaine', 'color:var(--nuance-sombre-06)');
|
||||
contenu += liste_nextYear;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
if (liste_noplanning != '')
|
||||
{
|
||||
// On ne place un titre de section que s'il existe des tâches planifiées ...
|
||||
if (nb_lignes != lignes_vides)
|
||||
contenu += todoListSection('Non planifié', 'color:var(--nuance-sombre-06)');
|
||||
contenu += liste_noplanning;
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
while(lignes_vides < 30)
|
||||
{
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <td colspan="3"> </td>';
|
||||
contenu += ' </tr>';
|
||||
lignes_vides += 1;
|
||||
}
|
||||
|
||||
contenu += ' </tbody>';
|
||||
|
||||
contenu += ' <tfoot>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th colspan="3">'+setLevelPadding(2)+''+(nb_lignes-1)+' tâches</th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </foot>';
|
||||
contenu += '</table>';
|
||||
|
||||
synthesis.innerHTML = synthese1+synthese2;
|
||||
datagrid.innerHTML = contenu;
|
||||
|
||||
// Ne marche pas , ça enlève le stick du header du tableau ...
|
||||
// document.getElementById('newitem_input').focus({preventScroll: true});
|
||||
}
|
||||
|
||||
item_save_hooks['TODO'] = todoSave;
|
||||
|
||||
items_edit_hooks['TODO_OLD'] = function (id, libelle) {
|
||||
let modal_header='Todo n°<b>'+id+'</b>';
|
||||
let modal_body='TODO inconnu !';
|
||||
let modal_footer='<div align="right" width="100%" style="padding-top:2vh"><button onclick="todoSave('+id+')">Enregistrer</button></div>';
|
||||
|
||||
let local_values = [];
|
||||
|
||||
local_values['parent']=getContexteValeur('parent');
|
||||
local_values['type']=getContexteValeur('type_courant');
|
||||
local_values['intervenant']=getContexteValeur('intervenant');
|
||||
local_values['client']=getTrigrammeCollaborateur(local_values['intervenant']);
|
||||
local_values['libelle']=libelle;
|
||||
|
||||
items.filter(item => item.idlignes == id).forEach(resultat => {
|
||||
local_values['type']=resultat['type'];
|
||||
itemFields[local_values['type']].forEach(attribut => {
|
||||
local_values[attribut]=resultat[attribut];
|
||||
});
|
||||
});
|
||||
|
||||
modal_body = '<table class="modal_table"><form id="formulaire_lignes">';
|
||||
itemFields[local_values['type']].forEach(attribut => {
|
||||
modal_body += '<tr><td>'+attribut+'</td><td>'+getInputLabel(attribut,local_values[attribut])+'</td></tr>';
|
||||
});
|
||||
modal_body += '</form></table>';
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
|
||||
if (!modalDialog.open) modalDialog.showModal();
|
||||
}
|
||||
79
frontend/src/scripts/api/status.js
Normal file
79
frontend/src/scripts/api/status.js
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
var allStatus;
|
||||
|
||||
function getStatusLibelleFromId(idstatus){
|
||||
let filtre = allStatus.filter(status => status.idstatus == idstatus);
|
||||
return (filtre[0]?.libelle ?? "Inconnu");
|
||||
}
|
||||
|
||||
function setStatus(data){
|
||||
allStatus = data;
|
||||
}
|
||||
|
||||
getEntities('status', setStatus);
|
||||
|
||||
function initDatagridStatus() {
|
||||
setStatus(null);
|
||||
datagridLoading();
|
||||
getEntities('status', __initDatagridStatus);
|
||||
}
|
||||
|
||||
function __initDatagridStatus(data) {
|
||||
let element = document.querySelector('#datagrid');
|
||||
let contenu='';
|
||||
|
||||
setStatus(data);
|
||||
|
||||
contenu += '<table>';
|
||||
contenu += ' <thead>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th>Id</th>';
|
||||
contenu += ' <th>Status</th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </thead>';
|
||||
|
||||
contenu += ' <tbody>';
|
||||
allStatus.forEach(status => {
|
||||
contenu += ' <tr class="js-open-modal-trigger" data-modal-info="status:id='+status.idstatus+'">';
|
||||
contenu += ' <td>'+status.idstatus+'</td>';
|
||||
contenu += ' <td>'+status.libelle+'</td>';
|
||||
contenu += ' </tr>';
|
||||
});
|
||||
contenu += ' </body>';
|
||||
|
||||
contenu += ' <tfoot>';
|
||||
contenu += ' <tr>';
|
||||
contenu += ' <th colspan="2"> </th>';
|
||||
contenu += ' </tr>';
|
||||
contenu += ' </foot>';
|
||||
contenu += '</table>';
|
||||
|
||||
element.innerHTML = contenu;
|
||||
|
||||
init_modal();
|
||||
}
|
||||
|
||||
modal_hooks['status'] = function(parametres){
|
||||
let paramSplit = parametres.split(',');
|
||||
paramSplit.forEach(element => {
|
||||
let elemSplit=element.split('=');
|
||||
if (elemSplit[0] === 'id') {
|
||||
let id = elemSplit[1];
|
||||
let modal_header='Fiche status ['+id+']';
|
||||
let modal_body='status inconnu !';
|
||||
let modal_footer='<button>Enregistrer</button';
|
||||
|
||||
statuss.filter(status => status.idstatus == id)
|
||||
.forEach(resultat => {
|
||||
modal_body = '<table class="modal_table">';
|
||||
modal_body += '<tr><td style="width:30%">Id</td><td>'+resultat.idstatus+'</td></tr>';
|
||||
modal_body += '<tr><td style="width:30%">Code</td><td>'+resultat.libelle+'</td></tr>';
|
||||
modal_body += '</table>';
|
||||
});
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
}
|
||||
});
|
||||
};
|
||||
11
frontend/src/scripts/ariane.js
Normal file
11
frontend/src/scripts/ariane.js
Normal file
@@ -0,0 +1,11 @@
|
||||
function setFilAriane(ariane){
|
||||
let contenant = document.querySelector('nav>#ariane>#fil');
|
||||
if (contenant != null) {
|
||||
let fil = '';
|
||||
ariane.forEach(element => {
|
||||
fil += ' <span><a onclick="activeMenu(this)">'+element+'</a></span> >';
|
||||
});
|
||||
contenant.innerHTML = fil.slice(0,-2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
15
frontend/src/scripts/contexte.js
Normal file
15
frontend/src/scripts/contexte.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// ----------------------------------------------------------------------
|
||||
// ---- Le contexte contient un ensemble de paramétres
|
||||
// ---- qui contextualisent globalement le coportment de la page
|
||||
// ----------------------------------------------------------------------
|
||||
var contexte = new Object();
|
||||
|
||||
function setContexteValeur(parametre, valeur)
|
||||
{
|
||||
contexte[parametre] = valeur;
|
||||
}
|
||||
|
||||
function getContexteValeur(parametre)
|
||||
{
|
||||
return contexte[parametre];
|
||||
}
|
||||
497
frontend/src/scripts/default.js
Normal file
497
frontend/src/scripts/default.js
Normal file
@@ -0,0 +1,497 @@
|
||||
window.addEventListener('load', function() {
|
||||
window.scrollTo(0,0);
|
||||
}, false);
|
||||
|
||||
/*
|
||||
* Personnalisation
|
||||
* Que se passe-t-il lorsque la bannière est invisible ?
|
||||
*/
|
||||
function setLogoVisiblity(visibilityFlag) {
|
||||
let element = document.querySelector("nav>*>#settings");
|
||||
let value = 'hidden';
|
||||
if (visibilityFlag) value = "visible";
|
||||
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 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');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Personnalisation
|
||||
* Que se passe-t-il lorsque la synthèse est invisible ?
|
||||
*/
|
||||
function setDatagridFirstColSticky(stickyFlag) {
|
||||
let element = null;
|
||||
|
||||
if (stickyFlag) {
|
||||
/*
|
||||
* Mettre la première case sticky au top left
|
||||
*/
|
||||
element = document.querySelector("#datagrid>table>thead>tr>th:first-child");
|
||||
element.style.setProperty('position', 'sticky');
|
||||
element.style.setProperty('left', '0px');
|
||||
element.style.setProperty('z-index', '30');
|
||||
|
||||
//
|
||||
// Mettre la dernière case sticky au bottom left
|
||||
//
|
||||
element = document.querySelector("#datagrid>table>tfoot>tr>th:first-child");
|
||||
element.style.setProperty('position', 'sticky');
|
||||
element.style.setProperty('left', '0px');
|
||||
element.style.setProperty('z-index', '30');
|
||||
|
||||
} else {
|
||||
element = document.querySelector("#datagrid>table>thead>tr>th:first-child");
|
||||
element.style.setProperty('position', 'sticky');
|
||||
element.style.setProperty('left', '0px');
|
||||
element.style.setProperty('z-index', '10');
|
||||
|
||||
element = document.querySelector("#datagrid>table>tfoot>tr>th:first-child");
|
||||
element.style.setProperty('position', 'sticky');
|
||||
element.style.setProperty('left', '0px');
|
||||
element.style.setProperty('z-index', '10');
|
||||
}
|
||||
}
|
||||
|
||||
function setDatagridHeadSticky(stickyFlag) {
|
||||
let element = document.querySelector("#datagrid>table>thead");
|
||||
let navbar = document.querySelector("nav");
|
||||
let offset = navbar.offsetHeight;
|
||||
|
||||
if (stickyFlag) {
|
||||
/*
|
||||
* Mettre le thead sticky au top
|
||||
*/
|
||||
//element = document.querySelector("#datagrid>table>thead");
|
||||
element.style.setProperty('position', 'sticky');
|
||||
element.style.setProperty('top', offset+'px');
|
||||
element.style.setProperty('z-index', '30');
|
||||
} else {
|
||||
//element = document.querySelector("#datagrid>table>thead");
|
||||
element.style.setProperty('position', 'relative');
|
||||
element.style.setProperty('top', '0px');
|
||||
element.style.setProperty('z-index', '10');
|
||||
}
|
||||
}
|
||||
|
||||
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 gotoTop() {
|
||||
let element = document.querySelector('header');
|
||||
window.scrollTo(0, element.offsetHeight + 1);
|
||||
}
|
||||
|
||||
function headerIsVisible(flagVisible) {
|
||||
setLogoVisiblity(!flagVisible);
|
||||
if (!flagVisible) gotoTop();
|
||||
}
|
||||
|
||||
function synthesisTopIsNowVisible(entry) {
|
||||
|
||||
setDatagridHeadSticky(false);
|
||||
setDataGridFootSticky(false);
|
||||
/*
|
||||
setDatagridFirstColSticky(true);
|
||||
*/
|
||||
|
||||
myLog('Trigger synthesis is visible');
|
||||
}
|
||||
|
||||
function synthesisTopIsNowInvisible(entry) {
|
||||
|
||||
setDatagridHeadSticky(true);
|
||||
setDataGridFootSticky(true);
|
||||
/*
|
||||
setDatagridFirstColSticky(true);
|
||||
*/
|
||||
|
||||
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 changeModeAffichageEvent(e)
|
||||
{
|
||||
return changeModeAffichage(e.target.value, e.target.options[e.target.selectedIndex].text);
|
||||
}
|
||||
|
||||
function changeAffichageItemsTermine(e)
|
||||
{
|
||||
setContexteValeur('termine', e.target.value);
|
||||
|
||||
setFiltreValeur('status',e.target.value);
|
||||
|
||||
afficherItems();
|
||||
}
|
||||
|
||||
function changeAffichageItemsPrestations(e)
|
||||
{
|
||||
setContexteValeur('prestation', e.target.value);
|
||||
|
||||
afficherItems();
|
||||
}
|
||||
|
||||
function changeFiltreClient(e)
|
||||
{
|
||||
let valeur = e.target.value;
|
||||
if (valeur == 'ALL') valeur='';
|
||||
setContexteValeur('client', valeur);
|
||||
|
||||
setFiltreValeur('client', valeur);
|
||||
|
||||
afficherItems();
|
||||
}
|
||||
|
||||
function changeAffichageNiveauxEvent(e)
|
||||
{
|
||||
setContexteValeur('level', e.target.value);
|
||||
|
||||
setFiltreValeur('level', e.target.value);
|
||||
|
||||
afficherItems();
|
||||
}
|
||||
|
||||
function changeCalendarEvent(e)
|
||||
{
|
||||
let valeur = todayStringDate;
|
||||
switch(parseInt(e.target.value)) {
|
||||
case 2 :
|
||||
valeur = todayStringDate.substring(0,4)+'0101';
|
||||
break;
|
||||
}
|
||||
setContexteValeur('debut',valeur);
|
||||
setFiltreValeur('debut', valeur);
|
||||
afficherItems();
|
||||
}
|
||||
|
||||
function updateValue(e) {
|
||||
if (e.target.value != '') editerItem(-1, e.target.value);
|
||||
e.target.value = '';
|
||||
}
|
||||
|
||||
function afficher_synthese(mode) {
|
||||
let synthesis_body = document.querySelector('#synthesis_body');
|
||||
if (synthesis_body) {
|
||||
synthesis_body.innerHTML='';
|
||||
let template = document.querySelector('#synthesis_body_' + mode);
|
||||
if (template) {
|
||||
let contenu = document.importNode(template.content, true);
|
||||
if (contenu) synthesis_body.appendChild(contenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function afficher_footer(mode) {
|
||||
let footer_body = document.querySelector('footer');
|
||||
if (footer_body) {
|
||||
footer_body.innerHTML='';
|
||||
let template = document.querySelector('#footer_' + mode);
|
||||
if (template) {
|
||||
let contenu = document.importNode(template.content, true);
|
||||
if (contenu) footer_body.appendChild(contenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 = '<div style="padding:0px 10px;display: flex;flex-wrap: nowrap;justify-content: space-between;">';
|
||||
contenu += '<a onclick="activeMenu(this)">Status</a>';
|
||||
contenu += '<a onclick="activeMenu(this)">Clients</a>';
|
||||
contenu += '<a onclick="activeMenu(this)">Collaborateurs</a>';
|
||||
contenu += '</div>';
|
||||
element.innerHTML = contenu;
|
||||
|
||||
}
|
||||
|
||||
function setDefaultContext()
|
||||
{
|
||||
// Contexte de départ
|
||||
setContexteValeur('level', '9999');
|
||||
setContexteValeur('parent', '1');
|
||||
setContexteValeur('parent_level','0');
|
||||
setContexteValeur('client', '');
|
||||
setContexteValeur('termine', 'oui');
|
||||
}
|
||||
|
||||
// UI
|
||||
setLogoVisiblity(false);
|
||||
|
||||
// Contexte de départ
|
||||
setContexteValeur('intervenant', 'Anonymous');
|
||||
|
||||
init_filtres(['type','client','debut','fin','level'])
|
||||
|
||||
// GO !
|
||||
activeMode('Todo');
|
||||
|
||||
// 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');
|
||||
}
|
||||
71
frontend/src/scripts/filtres.js
Normal file
71
frontend/src/scripts/filtres.js
Normal file
@@ -0,0 +1,71 @@
|
||||
var filtres = [];
|
||||
|
||||
function setFiltreValeur(filtre, valeur)
|
||||
{
|
||||
myError('setFiltreValeur est obsolète ! ['+filtre+' , '+ valeur+'] ')
|
||||
filtres[filtre] = valeur;
|
||||
}
|
||||
|
||||
function getFiltreValeur(filtre)
|
||||
{
|
||||
myError('getFiltreValeur est obsolète ! ['+filtre+'] ');
|
||||
return filtres[filtre];
|
||||
}
|
||||
|
||||
function init_filtres(liste){
|
||||
liste.forEach((element=>{
|
||||
filtres[element]='';
|
||||
}));
|
||||
}
|
||||
|
||||
function addDefaultFiltre(index, valeur){
|
||||
let retour = '';
|
||||
retour += '<tr><td>';
|
||||
retour += '<label for="filtre_'+index+'">'+index+'</label>';
|
||||
retour += '</td><td>';
|
||||
retour += '<input type="" id="filtre_'+index+'" name="filtre_'+index+'" value="'+valeur+'"></inputl>';
|
||||
retour += '</td></tr>';
|
||||
return retour;
|
||||
}
|
||||
|
||||
function openFiltrePopup(filtre)
|
||||
{
|
||||
let modal_header='Filtrer les items';
|
||||
let modal_body='';
|
||||
let modal_footer='<div align="right" width="100%" style="padding-top:2vh"><button onclick="applyFiltre()">Enregistrer</button></div>';
|
||||
|
||||
modal_body += '<table>';
|
||||
Object.entries(filtres).forEach(element=>{
|
||||
const [index,valeur] = element;
|
||||
|
||||
switch(index) {
|
||||
default:
|
||||
modal_body += addDefaultFiltre(index, valeur);
|
||||
}
|
||||
|
||||
});
|
||||
modal_body += '</table>';
|
||||
|
||||
modalSetHeader(modal_header);
|
||||
modalSetBody(modal_body);
|
||||
modalSetFooter(modal_footer);
|
||||
|
||||
if (!modalDialog.open) modalDialog.showModal();
|
||||
}
|
||||
|
||||
function applyFiltre(){
|
||||
Object.entries(filtres).forEach(element=>{
|
||||
const [index,valeur] = element;
|
||||
let new_valeur=valeur;
|
||||
|
||||
switch(index) {
|
||||
default:
|
||||
let input_valeur = document.querySelector('#filtre_' + index);
|
||||
if (input_valeur) new_valeur=input_valeur.value;
|
||||
}
|
||||
|
||||
filtres[index] = new_valeur;
|
||||
});
|
||||
|
||||
afficherItems();
|
||||
}
|
||||
13
frontend/src/scripts/parametres.js
Normal file
13
frontend/src/scripts/parametres.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// ----------------------------------------------------------------------
|
||||
// ---- Obsolète !
|
||||
// ---- A remplacer par la notion de contexte
|
||||
// ----------------------------------------------------------------------
|
||||
function setParametreValeur(parametre, valeur)
|
||||
{
|
||||
return setContexteValeur(parametre, valeur)
|
||||
}
|
||||
|
||||
function getParametreValeur(parametre)
|
||||
{
|
||||
return getContexteValeur(parametre);
|
||||
}
|
||||
128
frontend/src/scripts/tools/dates.js
Normal file
128
frontend/src/scripts/tools/dates.js
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
function stringDatePadDigits(num, digits) {
|
||||
return num.toString().padStart(digits, '0');
|
||||
}
|
||||
|
||||
function formatDatetoStringDateTime(uneDate){
|
||||
let temp = '';
|
||||
if (uneDate) {
|
||||
temp += uneDate.getFullYear();
|
||||
temp += ''+stringDatePadDigits(uneDate.getMonth()+1,2);
|
||||
temp += ''+stringDatePadDigits(uneDate.getDate(),2);
|
||||
temp += ''+stringDatePadDigits(uneDate.getHours(),2);
|
||||
temp += ''+stringDatePadDigits(uneDate.getMinutes(),2);
|
||||
}
|
||||
temp += '000000000000';
|
||||
return temp.substring(0,12);
|
||||
}
|
||||
|
||||
function formatTimeFromStringDate(uneStringDate) {
|
||||
let retour ='';
|
||||
if ('0000' == uneStringDate.substring(8,12)) retour='-';
|
||||
else retour = uneStringDate.substring(8,10)+':'+uneStringDate.substring(10,12);
|
||||
return retour;
|
||||
}
|
||||
|
||||
function formatDatetoStringDate(uneDate){
|
||||
let temp = formatDatetoStringDateTime(uneDate);
|
||||
return temp.substring(0,8);
|
||||
return temp.substring(0,8)+'0000';
|
||||
}
|
||||
|
||||
function formatLocaleDateFromStringDate(uneStringDate) {
|
||||
if (uneStringDate.substring(0,8) == '00000000') return '-';
|
||||
if (uneStringDate.substring(0,8) == '99999999') return '-';
|
||||
return uneStringDate.substring(6,8) +'/'+uneStringDate.substring(4,6)+'/'+uneStringDate.substring(0,4);
|
||||
}
|
||||
|
||||
function stringdateToDate(uneStringDate) {
|
||||
let retour = new Date();
|
||||
retour.setFullYear(parseInt(uneStringDate.substring(0,4)));
|
||||
retour.setMonth(parseInt(uneStringDate.substring(4,6))-1);
|
||||
retour.setDate(parseInt(uneStringDate.substring(6,8)));
|
||||
|
||||
retour = new Date(parseInt(uneStringDate.substring(0,4)), parseInt(uneStringDate.substring(4,6))-1, parseInt(uneStringDate.substring(6,8)))
|
||||
return retour;
|
||||
}
|
||||
|
||||
function stringdateGetDayOfYear(uneStringDate){
|
||||
let currentYear = uneStringDate.substring(0,4);
|
||||
let currentDate = stringdateToDate(uneStringDate);
|
||||
let startDate = new Date(parseInt(currentYear), 0, 4);
|
||||
return currentYear+stringDatePadDigits(Math.floor((currentDate - startDate) / (24 * 60 * 60 * 1000)),3);
|
||||
}
|
||||
|
||||
function stringdateGetWeekOfYear(uneStringDate) {
|
||||
let currentDayOfYear = dateGetPrevMonday(stringdateToDate(uneStringDate));
|
||||
let startDayOfYear = dateGetPrevMonday(stringdateToDate(currentDayOfYear.getUTCFullYear()+'0104'));
|
||||
let weekNo = Math.ceil(((currentDayOfYear-startDayOfYear) / 86400000 + 1) / 7);;
|
||||
return startDayOfYear.getUTCFullYear() * 100 + weekNo;
|
||||
}
|
||||
|
||||
function stringdateGetWeek(uneStringDate) {
|
||||
myError('Fonction Obsolète : '+arguments.callee.name);
|
||||
return stringdateGetWeekOfYear(uneStringDate);
|
||||
}
|
||||
|
||||
function dateGetToday(){
|
||||
let today = now.getDate();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
return today;
|
||||
}
|
||||
|
||||
function dateGetTomorrow(){
|
||||
let now = new Date();
|
||||
let today = now.getDate();
|
||||
let tomorrow = new Date(now);
|
||||
|
||||
tomorrow.setDate(today + 1);
|
||||
tomorrow.setHours(0, 0, 0, 0);
|
||||
|
||||
return tomorrow;
|
||||
}
|
||||
|
||||
function dateGetLastDayOfWeek(uneDate, dayOfWeek){
|
||||
let last = uneDate;
|
||||
last.setHours(0, 0, 0, 0);
|
||||
while(last.getDay() != dayOfWeek) {
|
||||
last.setDate(last - 1)
|
||||
}
|
||||
return last;
|
||||
}
|
||||
function dateGetNextDayOfWeek(uneDate, dayOfWeek){
|
||||
let next = uneDate;
|
||||
next.setHours(0, 0, 0, 0);
|
||||
while(next.getDay() != dayOfWeek) {
|
||||
next.setDate(next - 1)
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
function dateGetPrevMonday(uneDate){
|
||||
// return dateGetLastDayOfWeek(uneDate, 1);
|
||||
let lastMonday = uneDate;
|
||||
let daysDiff = uneDate.getDay() - 1;
|
||||
lastMonday.setDate(uneDate.getDate() - (daysDiff > 0 ? daysDiff : (daysDiff * -6)));
|
||||
lastMonday.setHours(0, 0, 0, 0);
|
||||
return lastMonday;
|
||||
}
|
||||
|
||||
function customParseFloat(valeur) {
|
||||
let retour = valeur;
|
||||
if (retour === null) retour = 0;
|
||||
if (isNaN(retour)) retour = 0;
|
||||
return parseFloat(retour);
|
||||
}
|
||||
|
||||
function convertJourHeure(valeur) {
|
||||
let retour = customParseFloat(valeur);
|
||||
if (retour < 1.0) {
|
||||
retour = (retour/0.125)+'H';
|
||||
} else {
|
||||
retour = retour+'J';
|
||||
}
|
||||
return retour;
|
||||
}
|
||||
|
||||
const todayStringDate = formatDatetoStringDate(new Date());
|
||||
const tomorrowStringDate = formatDatetoStringDate(dateGetTomorrow());
|
||||
27
frontend/src/scripts/tools/delai.js
Normal file
27
frontend/src/scripts/tools/delai.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Fonction pour introduire une attente
|
||||
* usage : await delai(1000);
|
||||
*/
|
||||
function delai(milliseconds){
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, milliseconds);
|
||||
});
|
||||
}
|
||||
|
||||
var waitLoop = (ms) => {
|
||||
const start = Date.now();
|
||||
let now = start;
|
||||
while (now - start < ms) {
|
||||
now = Date.now();
|
||||
}
|
||||
}
|
||||
|
||||
async function attendre1(milliseconds)
|
||||
{
|
||||
await delai(milliseconds);
|
||||
}
|
||||
|
||||
function attendre(milliseconds)
|
||||
{
|
||||
waitLoop(milliseconds);
|
||||
}
|
||||
10
frontend/src/scripts/tools/logs.js
Normal file
10
frontend/src/scripts/tools/logs.js
Normal file
@@ -0,0 +1,10 @@
|
||||
var useLog=false;
|
||||
var useError=true;
|
||||
function myLog(message) {
|
||||
if (useLog)
|
||||
console.log(message);
|
||||
}
|
||||
function myError(message) {
|
||||
if (useError)
|
||||
console.error(message);
|
||||
}
|
||||
19
frontend/src/scripts/tools/postData.js
Normal file
19
frontend/src/scripts/tools/postData.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// Example POST method implementation:
|
||||
async function postData(url = "", data = {}) {
|
||||
// Default options are marked with *
|
||||
const response = await fetch(url, {
|
||||
method: "POST", // *GET, POST, PUT, DELETE, etc.
|
||||
mode: "cors", // no-cors, *cors, same-origin
|
||||
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
|
||||
credentials: "same-origin", // include, *same-origin, omit
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
// 'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
redirect: "follow", // manual, *follow, error
|
||||
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
|
||||
body: JSON.stringify(data), // body data type must match "Content-Type" header
|
||||
});
|
||||
return response.json(); // parses JSON response into native JavaScript objects
|
||||
}
|
||||
|
||||
10
frontend/src/scripts/tools/svg-inject.min.js
vendored
Normal file
10
frontend/src/scripts/tools/svg-inject.min.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
!function(o,l){var r,a,s="createElement",g="getElementsByTagName",b="length",E="style",d="title",y="undefined",k="setAttribute",w="getAttribute",x=null,A="__svgInject",C="--inject-",S=new RegExp(C+"\\d+","g"),I="LOAD_FAIL",t="SVG_NOT_SUPPORTED",L="SVG_INVALID",v=["src","alt","onload","onerror"],j=l[s]("a"),G=typeof SVGRect!=y,f={useCache:!0,copyAttributes:!0,makeIdsUnique:!0},N={clipPath:["clip-path"],"color-profile":x,cursor:x,filter:x,linearGradient:["fill","stroke"],marker:["marker",
|
||||
"marker-end","marker-mid","marker-start"],mask:x,pattern:["fill","stroke"],radialGradient:["fill","stroke"]},u=1,c=2,O=1;function T(e){return(r=r||new XMLSerializer).serializeToString(e)}function P(e,r){var t,n,i,o,a=C+O++,f=/url\("?#([a-zA-Z][\w:.-]*)"?\)/g,u=e.querySelectorAll("[id]"),c=r?[]:x,l={},s=[],d=!1;if(u[b]){for(i=0;i<u[b];i++)(n=u[i].localName)in N&&(l[n]=1);for(n in l)(N[n]||[n]).forEach(function(e){s.indexOf(e)<0&&s.push(e)});s[b]&&s.push(E);var v,p,m,h=e[g]("*"),y=e;for(i=-1;y!=x;
|
||||
){if(y.localName==E)(m=(p=y.textContent)&&p.replace(f,function(e,r){return c&&(c[r]=1),"url(#"+r+a+")"}))!==p&&(y.textContent=m);else if(y.hasAttributes()){for(o=0;o<s[b];o++)v=s[o],(m=(p=y[w](v))&&p.replace(f,function(e,r){return c&&(c[r]=1),"url(#"+r+a+")"}))!==p&&y[k](v,m);["xlink:href","href"].forEach(function(e){var r=y[w](e);/^\s*#/.test(r)&&(r=r.trim(),y[k](e,r+a),c&&(c[r.substring(1)]=1))})}y=h[++i]}for(i=0;i<u[b];i++)t=u[i],c&&!c[t.id]||(t.id+=a,d=!0)}return d}function V(e,r,t,n){if(r){
|
||||
r[k]("data-inject-url",t);var i=e.parentNode;if(i){n.copyAttributes&&function c(e,r){for(var t,n,i,o=e.attributes,a=0;a<o[b];a++)if(n=(t=o[a]).name,-1==v.indexOf(n))if(i=t.value,n==d){var f,u=r.firstElementChild;u&&u.localName.toLowerCase()==d?f=u:(f=l[s+"NS"]("http://www.w3.org/2000/svg",d),r.insertBefore(f,u)),f.textContent=i}else r[k](n,i)}(e,r);var o=n.beforeInject,a=o&&o(e,r)||r;i.replaceChild(a,e),e[A]=u,m(e);var f=n.afterInject;f&&f(e,a)}}else D(e,n)}function p(){for(var e={},r=arguments,
|
||||
t=0;t<r[b];t++){var n=r[t];for(var i in n)n.hasOwnProperty(i)&&(e[i]=n[i])}return e}function _(e,r){if(r){var t;try{t=function i(e){return(a=a||new DOMParser).parseFromString(e,"text/xml")}(e)}catch(o){return x}return t[g]("parsererror")[b]?x:t.documentElement}var n=l.createElement("div");return n.innerHTML=e,n.firstElementChild}function m(e){e.removeAttribute("onload")}function n(e){console.error("SVGInject: "+e)}function i(e,r,t){e[A]=c,t.onFail?t.onFail(e,r):n(r)}function D(e,r){m(e),i(e,L,r)
|
||||
}function F(e,r){m(e),i(e,t,r)}function M(e,r){i(e,I,r)}function q(e){e.onload=x,e.onerror=x}function R(e){n("no img element")}var e=function z(e,r){var t=p(f,r),h={};function n(a,f){f=p(t,f);var e=function(r){var e=function(){var e=f.onAllFinish;e&&e(),r&&r()};if(a&&typeof a[b]!=y){var t=0,n=a[b];if(0==n)e();else for(var i=function(){++t==n&&e()},o=0;o<n;o++)u(a[o],f,i)}else u(a,f,e)};return typeof Promise==y?e():new Promise(e)}function u(u,c,e){if(u){var r=u[A];if(r)Array.isArray(r)?r.push(e
|
||||
):e();else{if(q(u),!G)return F(u,c),void e();var t=c.beforeLoad,n=t&&t(u)||u[w]("src");if(!n)return""===n&&M(u,c),void e();var i=[];u[A]=i;var l=function(){e(),i.forEach(function(e){e()})},s=function f(e){return j.href=e,j.href}(n),d=c.useCache,v=c.makeIdsUnique,p=function(r){d&&(h[s].forEach(function(e){e(r)}),h[s]=r)};if(d){var o,a=function(e){if(e===I)M(u,c);else if(e===L)D(u,c);else{var r,t=e[0],n=e[1],i=e[2];v&&(t===x?(t=P(r=_(n,!1),!1),e[0]=t,e[2]=t&&T(r)):t&&(n=function o(e){
|
||||
return e.replace(S,C+O++)}(i))),r=r||_(n,!1),V(u,r,s,c)}l()};if(typeof(o=h[s])!=y)return void(o.isCallbackQueue?o.push(a):a(o));(o=[]).isCallbackQueue=!0,h[s]=o}!function m(e,r,t){if(e){var n=new XMLHttpRequest;n.onreadystatechange=function(){if(4==n.readyState){var e=n.status;200==e?r(n.responseXML,n.responseText.trim()):400<=e?t():0==e&&t()}},n.open("GET",e,!0),n.send()}}(s,function(e,r){var t=e instanceof Document?e.documentElement:_(r,!0),n=c.afterLoad;if(n){var i=n(t,r)||t;if(i){
|
||||
var o="string"==typeof i;r=o?i:T(t),t=o?_(i,!0):i}}if(t instanceof SVGElement){var a=x;if(v&&(a=P(t,!1)),d){var f=a&&T(t);p([a,r,f])}V(u,t,s,c)}else D(u,c),p(L);l()},function(){M(u,c),p(I),l()})}}else R()}return G&&function i(e){var r=l[g]("head")[0];if(r){var t=l[s](E);t.type="text/css",t.appendChild(l.createTextNode(e)),r.appendChild(t)}}('img[onload^="'+e+'("]{visibility:hidden;}'),n.setOptions=function(e){t=p(t,e)},n.create=z,n.err=function(e,r){e?e[A]!=c&&(q(e),G?(m(e),M(e,t)):F(e,t),r&&(m(
|
||||
e),e.src=r)):R()},o[e]=n}("SVGInject");"object"==typeof module&&"object"==typeof module.exports&&(module.exports=e)}(window,document);
|
||||
Reference in New Issue
Block a user