Compare commits

...

10 Commits

25 changed files with 384 additions and 204 deletions

View File

@ -247,9 +247,9 @@ class GroupDescr(db.Model):
d["partition"] = self.partition.to_dict(with_groups=False) d["partition"] = self.partition.to_dict(with_groups=False)
return d return d
def get_edt_id(self) -> str: def get_edt_ids(self) -> list[str]:
"l'id pour l'emploi du temps: à défaut, le nom scodoc du groupe" "les ids pour l'emploi du temps: à défaut, le nom scodoc du groupe"
return self.edt_id or self.group_name or "" return scu.split_id(self.edt_id) or [self.group_name] or []
def get_nb_inscrits(self) -> int: def get_nb_inscrits(self) -> int:
"""Nombre inscrits à ce group et au formsemestre. """Nombre inscrits à ce group et au formsemestre.

View File

@ -213,6 +213,7 @@ def sco_header(
window.onload=function(){{enableTooltips("gtrcontent")}}; window.onload=function(){{enableTooltips("gtrcontent")}};
const SCO_URL="{scu.ScoURL()}"; const SCO_URL="{scu.ScoURL()}";
const SCO_TIMEZONE="{scu.TIME_ZONE}";
</script>""" </script>"""
) )

View File

@ -157,10 +157,15 @@ class JustificatifArchiver(BaseArchiver):
Si trace == True : sauvegarde le nom du/des fichier(s) supprimé(s) Si trace == True : sauvegarde le nom du/des fichier(s) supprimé(s)
dans la trace de l'étudiant dans la trace de l'étudiant
""" """
print("debug : ", archive_name, filename, has_trace)
if str(etud.id) not in self.list_oids(etud.dept_id): if str(etud.id) not in self.list_oids(etud.dept_id):
raise ValueError(f"Aucune archive pour etudid[{etud.id}]") raise ValueError(f"Aucune archive pour etudid[{etud.id}]")
try:
archive_id = self.get_id_from_name(etud.id, archive_name, dept_id=etud.dept_id) archive_id = self.get_id_from_name(
etud.id, archive_name, dept_id=etud.dept_id
)
except ScoValueError:
raise ValueError(f"Archive Inconnue [{archive_name}]")
if filename is not None: if filename is not None:
if filename not in self.list_archive(archive_id, dept_id=etud.dept_id): if filename not in self.list_archive(archive_id, dept_id=etud.dept_id):

View File

@ -55,6 +55,7 @@ def formsemestre_load_calendar(
"""Load ics data, return raw ics and decoded calendar. """Load ics data, return raw ics and decoded calendar.
Raises ScoValueError if not configured or not available or invalid format. Raises ScoValueError if not configured or not available or invalid format.
""" """
edt_ids = []
if edt_id is None and formsemestre: if edt_id is None and formsemestre:
edt_ids = formsemestre.get_edt_ids() edt_ids = formsemestre.get_edt_ids()
if not edt_ids: if not edt_ids:
@ -408,6 +409,7 @@ def formsemestre_retreive_groups_from_edt_id(
"""Construit un dict donnant le groupe de chaque edt_id""" """Construit un dict donnant le groupe de chaque edt_id"""
edt2group = {} edt2group = {}
for partition in formsemestre.partitions: for partition in formsemestre.partitions:
edt2group.update({g.get_edt_id(): g for g in partition.groups}) for g in partition.groups:
edt2group.pop("", None) for edt_id in g.get_edt_ids():
edt2group[edt_id] = g
return edt2group return edt2group

View File

@ -101,7 +101,8 @@ def group_rename(group_id):
"allow_null": True, "allow_null": True,
"explanation": """optionnel : identifiant du groupe dans le logiciel "explanation": """optionnel : identifiant du groupe dans le logiciel
d'emploi du temps, pour le cas où les noms de groupes ne seraient pas d'emploi du temps, pour le cas où les noms de groupes ne seraient pas
les mêmes dans ScoDoc et dans l'emploi du temps.""", les mêmes dans ScoDoc et dans l'emploi du temps (si plusieurs ids,
les séparer par des virgules).""",
}, },
), ),
), ),

View File

@ -305,8 +305,8 @@ function executeMassActionQueue() {
*/ */
const tlTimes = getTimeLineTimes(); const tlTimes = getTimeLineTimes();
let assiduite = { let assiduite = {
date_debut: tlTimes.deb.toIsoUtcString(), date_debut: tlTimes.deb.toFakeIso(),
date_fin: tlTimes.fin.toIsoUtcString(), date_fin: tlTimes.fin.toFakeIso(),
}; };
assiduite = setModuleImplId(assiduite); assiduite = setModuleImplId(assiduite);
@ -601,7 +601,10 @@ function toTime(time) {
* @returns * @returns
*/ */
function formatDate(date, styles = { dateStyle: "full" }) { function formatDate(date, styles = { dateStyle: "full" }) {
return new Intl.DateTimeFormat("fr-FR", styles).format(date); return new Intl.DateTimeFormat("fr-FR", {
...{ timeZone: SCO_TIMEZONE },
...styles,
}).format(date);
} }
/** /**
@ -610,19 +613,25 @@ function formatDate(date, styles = { dateStyle: "full" }) {
function updateDate() { function updateDate() {
const dateInput = document.querySelector("#tl_date"); const dateInput = document.querySelector("#tl_date");
let date = $(dateInput).datepicker("getDate"); let date = $(dateInput).datepicker("getDate");
if (date == null) { if (date == null) {
date = new Date(Date.fromFRA(dateInput.value)); date = new Date(Date.fromFRA(dateInput.value));
} }
const intlOptions = {
dateStyle: "full",
timeZone: SCO_TIMEZONE,
};
let dateStr = ""; let dateStr = "";
if (!isNonWorkDay(date.getDay(), nonWorkDays)) {
dateStr = formatDate(date).capitalize(); if (!isNonWorkDay(date, nonWorkDays)) {
dateStr = formatDate(date, intlOptions).capitalize();
} else { } else {
// On se rend au dernier jour travaillé disponible // On se rend au dernier jour travaillé disponible
const lastWorkDay = getNearestWorkDay(date); const lastWorkDay = getNearestWorkDay(date);
const att = document.createTextNode( const att = document.createTextNode(
`Le jour sélectionné (${formatDate(date)}) n'est pas un jour travaillé.` `Le jour sélectionné (${formatDate(
date,
intlOptions
)}) n'est pas un jour travaillé.`
); );
const div = document.createElement("div"); const div = document.createElement("div");
div.appendChild(att); div.appendChild(att);
@ -630,22 +639,23 @@ function updateDate() {
div.appendChild( div.appendChild(
document.createTextNode( document.createTextNode(
`Le dernier jour travaillé disponible a été sélectionné : ${formatDate( `Le dernier jour travaillé disponible a été sélectionné : ${formatDate(
lastWorkDay lastWorkDay,
intlOptions
)}.` )}.`
) )
); );
openAlertModal("Attention", div, "", "#eec660"); openAlertModal("Attention", div, "", "#eec660");
const date_fra = Date.toFRA(lastWorkDay.toIsoUtcString().split("T")[0]);
$(dateInput).datepicker("setDate", date_fra); $(dateInput).datepicker("setDate", date_fra);
dateInput.value = date_fra; dateInput.value = date_fra;
date = lastWorkDay; date = lastWorkDay;
dateStr = formatDate(lastWorkDay).capitalize(); dateStr = formatDate(lastWorkDay, {
dateStyle: "full",
timeZone: SCO_TIMEZONE,
}).capitalize();
} }
console.warn(dateStr, date, date.toIsoUtcString());
document.querySelector("#datestr").textContent = dateStr; document.querySelector("#datestr").textContent = dateStr;
return true; return true;
} }
@ -654,7 +664,7 @@ function getNearestWorkDay(date) {
const aDay = 86400000; // 24 * 3600 * 1000 | H * s * ms const aDay = 86400000; // 24 * 3600 * 1000 | H * s * ms
let day = date; let day = date;
let count = 0; let count = 0;
while (isNonWorkDay(day.getDay(), nonWorkDays) && count++ < 7) { while (isNonWorkDay(day, nonWorkDays) && count++ < 7) {
day = new Date(day - aDay); day = new Date(day - aDay);
} }
return day; return day;
@ -712,31 +722,12 @@ function formatDateModal(str, separator = " ") {
* Renvoie Vrai si le jour est non travaillé * Renvoie Vrai si le jour est non travaillé
*/ */
function isNonWorkDay(day, nonWorkdays) { function isNonWorkDay(day, nonWorkdays) {
let d = ""; const d = Intl.DateTimeFormat("fr-FR", {
switch (day) { timeZone: SCO_TIMEZONE,
case 0: weekday: "short",
d = "dim"; })
break; .format(day)
case 1: .replace(".", "");
d = "lun";
break;
case 2:
d = "mar";
break;
case 3:
d = "mer";
break;
case 4:
d = "jeu";
break;
case 5:
d = "ven";
break;
case 6:
d = "sam";
break;
}
return nonWorkdays.indexOf(d) != -1; return nonWorkdays.indexOf(d) != -1;
} }
@ -783,8 +774,8 @@ function getTimeLineTimes() {
function isConflictSameAsPeriod(conflict, period = undefined) { function isConflictSameAsPeriod(conflict, period = undefined) {
const tlTimes = period == undefined ? getTimeLineTimes() : period; const tlTimes = period == undefined ? getTimeLineTimes() : period;
const clTimes = { const clTimes = {
deb: new Date(conflict.date_debut), deb: new Date(Date.removeUTC(conflict.date_debut)),
fin: new Date(conflict.date_fin), fin: new Date(Date.removeUTC(conflict.date_fin)),
}; };
return tlTimes.deb.isSame(clTimes.deb) && tlTimes.fin.isSame(clTimes.fin); return tlTimes.deb.isSame(clTimes.deb) && tlTimes.fin.isSame(clTimes.fin);
} }
@ -850,8 +841,8 @@ function numberTimeToDate(nb) {
function getAssiduitesFromEtuds(clear, deb, fin) { function getAssiduitesFromEtuds(clear, deb, fin) {
const etudIds = Object.keys(etuds).join(","); const etudIds = Object.keys(etuds).join(",");
const date_debut = deb ? deb : getPrevDate().toIsoUtcString(); const date_debut = deb ? deb : getPrevDate().toFakeIso();
const date_fin = fin ? fin : getNextDate().toIsoUtcString(); const date_fin = fin ? fin : getNextDate().toFakeIso();
if (clear) { if (clear) {
assiduites = {}; assiduites = {};
@ -894,8 +885,8 @@ function getAssiduitesFromEtuds(clear, deb, fin) {
function createAssiduite(etat, etudid) { function createAssiduite(etat, etudid) {
const tlTimes = getTimeLineTimes(); const tlTimes = getTimeLineTimes();
let assiduite = { let assiduite = {
date_debut: tlTimes.deb.toIsoUtcString(), date_debut: tlTimes.deb.toFakeIso(),
date_fin: tlTimes.fin.toIsoUtcString(), date_fin: tlTimes.fin.toFakeIso(),
etat: etat, etat: etat,
}; };
@ -937,6 +928,19 @@ function createAssiduite(etat, etudid) {
openAlertModal("Sélection du module", content); openAlertModal("Sélection du module", content);
} }
if (
data.errors["0"].message == "L'étudiant n'est pas inscrit au module"
) {
const HTML = `
<p>Attention, l'étudiant n'est pas inscrit à ce module.</p>
<p>Si c'est une erreur, veuillez voir avec le ou les responsables de votre scodoc.</p>
`;
const content = document.createElement("div");
content.innerHTML = HTML;
openAlertModal("Sélection du module", content);
}
with_errors = true; with_errors = true;
} }
}, },
@ -1076,8 +1080,8 @@ function getAssiduitesConflict(etudid, periode) {
return etudAssiduites.filter((assi) => { return etudAssiduites.filter((assi) => {
const interval = { const interval = {
deb: new Date(assi.date_debut), deb: new Date(Date.removeUTC(assi.date_debut)),
fin: new Date(assi.date_fin), fin: new Date(Date.removeUTC(assi.date_fin)),
}; };
const test = hasTimeConflict(periode, interval); const test = hasTimeConflict(periode, interval);
return test; return test;
@ -1101,15 +1105,15 @@ function getLastAssiduiteOfPrevDate(etudid) {
const prevAssiduites = etudAssiduites const prevAssiduites = etudAssiduites
.filter((assi) => { .filter((assi) => {
const interval = { const interval = {
deb: new Date(assi.date_debut), deb: new Date(Date.removeUTC(assi.date_debut)),
fin: new Date(assi.date_fin), fin: new Date(Date.removeUTC(assi.date_fin)),
}; };
return hasTimeConflict(period, interval); return hasTimeConflict(period, interval);
}) })
.sort((a, b) => { .sort((a, b) => {
const a_fin = new Date(a.date_fin); const a_fin = new Date(Date.removeUTC(a.date_fin));
const b_fin = new Date(b.date_fin); const b_fin = new Date(Date.removeUTC(b.date_fin));
return b_fin < a_fin; return b_fin < a_fin;
}); });
@ -1144,8 +1148,8 @@ function getAssiduiteValue(field) {
* @param {String | Number} etudid identifiant de l'étudiant * @param {String | Number} etudid identifiant de l'étudiant
*/ */
function actualizeEtudAssiduite(etudid) { function actualizeEtudAssiduite(etudid) {
const date_debut = getPrevDate().toIsoUtcString(); const date_debut = getPrevDate().toFakeIso();
const date_fin = getNextDate().toIsoUtcString(); const date_fin = getNextDate().toFakeIso();
const url_api = const url_api =
getUrl() + getUrl() +
@ -1391,8 +1395,8 @@ function insertEtudRow(etud, index, output = false) {
assiduite.etatAssiduite = conflict[0].etat; assiduite.etatAssiduite = conflict[0].etat;
assiduite.id = conflict[0].assiduite_id; assiduite.id = conflict[0].assiduite_id;
assiduite.date_debut = conflict[0].date_debut; assiduite.date_debut = Date.removeUTC(conflict[0].date_debut);
assiduite.date_fin = conflict[0].date_fin; assiduite.date_fin = Date.removeUTC(conflict[0].date_fin);
if (isConflictSameAsPeriod(conflict[0])) { if (isConflictSameAsPeriod(conflict[0])) {
assiduite.type = "édition"; assiduite.type = "édition";
} else { } else {
@ -1623,9 +1627,7 @@ function getJustificatifFromPeriod(date, etudid, update) {
getUrl() + getUrl() +
`/api/justificatifs/${etudid}/query?date_debut=${date.deb `/api/justificatifs/${etudid}/query?date_debut=${date.deb
.add(1, "seconds") .add(1, "seconds")
.toIsoUtcString()}&date_fin=${date.fin .toFakeIso()}&date_fin=${date.fin.add(-1, "seconds").toFakeIso()}`,
.add(-1, "seconds")
.toIsoUtcString()}`,
success: (data) => { success: (data) => {
update(data); update(data);
}, },
@ -1657,8 +1659,8 @@ function fastJustify(assiduite) {
} }
const period = { const period = {
deb: new Date(assiduite.date_debut), deb: new Date(Date.removeUTC(assiduite.date_debut)),
fin: new Date(assiduite.date_fin), fin: new Date(Date.removeUTC(assiduite.date_fin)),
}; };
const action = (justifs) => { const action = (justifs) => {
//créer un nouveau justificatif //créer un nouveau justificatif
@ -1671,8 +1673,8 @@ function fastJustify(assiduite) {
//créer justificatif //créer justificatif
const justif = { const justif = {
date_debut: new Date(assiduite.date_debut).toIsoUtcString(), date_debut: new Date(Date.removeUTC(assiduite.date_debut)).toFakeIso(),
date_fin: new Date(assiduite.date_fin).toIsoUtcString(), date_fin: new Date(Date.removeUTC(assiduite.date_fin)).toFakeIso(),
raison: raison, raison: raison,
etat: etat, etat: etat,
}; };

View File

@ -59,6 +59,11 @@ Date.intersect = function (period, interval) {
return period.deb <= interval.fin && period.fin >= interval.deb; return period.deb <= interval.fin && period.fin >= interval.deb;
}; };
Date.removeUTC = function (isoString) {
const reg = new RegExp(/[+-][\d:]+$/);
return isoString.replace(reg, "");
};
Object.defineProperty(Date.prototype, "isValid", { Object.defineProperty(Date.prototype, "isValid", {
value: function () { value: function () {
return !Number.isNaN(this.getTime()); return !Number.isNaN(this.getTime());
@ -198,13 +203,29 @@ Object.defineProperty(Date.prototype, "toIsoUtcString", {
* @returns date au format iso utc (yyyy-mm-ddThh:MM±oo:oo:oo) * @returns date au format iso utc (yyyy-mm-ddThh:MM±oo:oo:oo)
*/ */
value: function () { value: function () {
// Formater la date et l'heure
const date = this; const date = this;
var tzo = -date.getTimezoneOffset(), var tzo = -date.getTimezoneOffset(),
dif = tzo >= 0 ? "+" : "-", dif = tzo >= 0 ? "+" : "-",
pad = function (num) { pad = function (num) {
return (num < 10 ? "0" : "") + num; return (num < 10 ? "0" : "") + num;
}; };
return (
this.toFakeIso() +
dif +
pad(Math.floor(Math.abs(tzo) / 60)) +
":" +
pad(Math.abs(tzo) % 60)
);
},
});
Object.defineProperty(Date.prototype, "toFakeIso", {
value: function () {
const date = this;
pad = function (num) {
return (num < 10 ? "0" : "") + num;
};
return ( return (
date.getFullYear() + date.getFullYear() +
"-" + "-" +
@ -216,11 +237,7 @@ Object.defineProperty(Date.prototype, "toIsoUtcString", {
":" + ":" +
pad(date.getMinutes()) + pad(date.getMinutes()) +
":" + ":" +
pad(date.getSeconds()) + pad(date.getSeconds())
dif +
pad(Math.floor(Math.abs(tzo) / 60)) +
":" +
pad(Math.abs(tzo) % 60)
); );
}, },
}); });
@ -246,6 +263,7 @@ Object.defineProperty(Date.prototype, "format", {
hour: "2-digit", hour: "2-digit",
minute: "2-digit", minute: "2-digit",
hour12: false, hour12: false,
timeZone: SCO_TIMEZONE,
}); });
case "DD/MM/YYYY HH:mm": case "DD/MM/YYYY HH:mm":
return this.toLocaleString("fr-FR", { return this.toLocaleString("fr-FR", {
@ -255,6 +273,7 @@ Object.defineProperty(Date.prototype, "format", {
hour: "2-digit", hour: "2-digit",
minute: "2-digit", minute: "2-digit",
hour12: false, hour12: false,
timeZone: SCO_TIMEZONE,
}); });
case "YYYY-MM-DDTHH:mm": case "YYYY-MM-DDTHH:mm":
@ -264,7 +283,7 @@ Object.defineProperty(Date.prototype, "format", {
case "YYYY-MM-DD": case "YYYY-MM-DD":
return iso.slice(0, iso.indexOf("T")); return iso.slice(0, iso.indexOf("T"));
default: default:
return this.toIsoUtcString(); return this.toFakeIso();
} }
}, },
}); });

View File

@ -0,0 +1,198 @@
const studentsdemo = [
{ "name": "Alice", "wait": 500, "sems": [0, 2] },
{ "name": "Bob", "wait": 500, "sems": [1, 2, 3]}
];
const semsdemo = [
{ "id": 0, "wait": 4, "notes": {"Alice": 13 } },
{ "id": 1, "wait": 3, "notes": {"Bob": 6 } },
{ "id": 2, "wait": 8, "notes": {"Alice": 11, "Bob": 18 } },
{ "id": 3, "wait": 7, "notes": {"Bob": 17 } },
];
/*
getStudents <= [ "Alice", #Bob" ]
getSems("Alice") <= [ 1, 3]
getSems("Bob") <= [ 2, 3, 4]
getMarks(1) <= {"Alice": 13 }
getMarks(2) <= {"Alice": 13 }...
getMarks(3) <= {"Alice": 13 }
getMarks(4) <= {"Alice": 13 }
*/
const api = {
getStudents() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(studentsdemo);
}, 500);
});
},
getStudentSems(student) {
return new Promise(
resolve => { setTimeout(resolve, student.wait, student.sems); }
);
},
getMarks(sem_id) {
return new Promise(
resolve => { setTimeout(resolve, semsdemo[sem_id].wait, semsdemo[sem_id].notes ); }
)
}
}
$(document).ready(function() {
$("#ok").click(function(){
do_export();
});
});
function getData() {
// let students = api.getStudents()
// console.log(students);
// let promises =
// students.map((student) => api.getStudentSems(student));
// return Promise.all(promises);
}
async function asyncCall() {
// const sem_requests = new Map();
console.log('***************** start *****************');
const students = await api.getStudents();
console.log('***************** got students *****************');
console.log(students)
console.log('***************** seeking sems and marks *****************');
const student_requests = students.map((student) => {
return api.getStudentSems(student);
});
const sems = await Promise.all(student_requests);
const full_sem = sems.flat();
const set_sem = [...new Set(full_sem)];
const studentsGrades = await Promise.all(set_sem.map(sem => api.getMarks(sem)));
debugger;
/*
console.log("lookup for " + student.name + "'s sems.");
const sems = api.getStudentSems(student)
console.log(`***************** got ${student.name}'s sems *****************`);
console.log(sems);
return sems;
});
const sems.forEach((sem) => {
console.log(`looking for mark for sem ${sem}`);
console.log("** current sems requests");
console.log(sem_requests)
if (sem_requests[sem] === 'undefined') {
console.log(`seeking ${sem} marks`)
sem_requests[sem] = api.getMarks(sem);
}
})
sems.forEach((sem) => {
console.log(`looking for mark for sem ${sem}`);
console.log("** current sems requests");
console.log(sem_requests)
if (sem_requests[sem] === 'undefined') {
console.log(`seeking ${sem} marks`)
sem_requests[sem] = api.getMarks(sem);
}
})
let result_sems = await Promise.all(sem_requests)
console.log('***************** sems ok *****************');
console.log(result_sems);
console.log('***************** stop *****************');
*/
// Expected output: "resolved"
}
function do_export() {
event.preventDefault();
// students = getData();
// console.log(students);
asyncCall();
}
// let loaded_sems = [];
//
// async function doit() {
// getStudents()
// .then(students => {
// return Promise.all(students.map(student => {
// api.getStudentSems(student)
// .then(sems_id => {
// sem_requests = []
// sems_id.forEach(sem_id => {
// if (typeof sem_requests[sem_id] === 'undefined') {
// sem_requests[sem_id](api.getMarks(sem_id));
// });
// });
// then(allMarks => {
// console.log(allMarks);
// });
// });
// }
/*
let dataSrc = "/ScoDoc/{{dept}}/api/formsemestre/{{formsemestre.id}}/etudiants/long";
let formsemestres = [];
fetch(dataSrc)
.then(r => { return r.json(); })
.then(json => {
let etudiants = json;
promises_etud_semestres = []
promises_semestres = []
etudiants.forEach((etudiant) => {
let url =`/ScoDoc/{{dept}}/api/etudiant/nip/${etudiant.code_nip}/formsemestres`;
console.log(url);
promises_etud_semestres.push(
fetch(url)
.then(r => { return r.json(); })
.then(semestre => {
formsemestre_id = semestre.formsemestre_id;
})
)
// etudiant.formsemestres_id = [];
fetch(url)
.then(r => {return r.json; })
.then(json => {
let forms = json;
console.log(etudiant.code_nip + " " + forms.formsemestre_id);
// forms.forEach((formsem) => {
// if (formsem.is_apc) {
// etudiant.formsemestres_id.push(formsem.formsemestre_id);
// if (formsem.formsemestre_id in_array()) {
// }
// }
// });
});
});
//let releve = document.querySelector("releve-but");
//releve.showData = json;
// Style custom à ajouter
// let style = document.createElement("style");
// style.textContent = `
// .module>div,
// .dateInscription,
// .numerosEtudiant,
// .dateNaissance{
// display: none;
// }`;
//releve.shadowRoot.appendChild(style);
})
.catch(error => { console.log(error)});
// .catch(error => {
// let div = document.createElement("div");
// div.innerText = "Une erreur s'est produite lors du transfert des données.";
// div.style.fontSize = "24px";
// div.style.color = "#d93030";
// let releve = document.querySelector("releve-but");
// releve.after(div);
// releve.remove();
// throw 'Fin du script - données invalides';
// });
*/

View File

@ -103,7 +103,7 @@
[required]::after { [required]::after {
content: "*"; content: "*";
color: crimson; color: var(--color-error);
} }
</style> </style>
<script> <script>
@ -137,8 +137,8 @@
const raison = field.querySelector('#justi_raison').value; const raison = field.querySelector('#justi_raison').value;
return { return {
date_debut: new Date(deb).toIsoUtcString(), date_debut: new Date(deb).toFakeIso(),
date_fin: new Date(fin).toIsoUtcString(), date_fin: new Date(fin).toFakeIso(),
etat: etat, etat: etat,
raison: raison, raison: raison,
} }

View File

@ -167,7 +167,7 @@
margin: 5px 0; margin: 5px 0;
border-radius: 7px; border-radius: 7px;
background-color: crimson; background-color: var(--color-error);
} }

View File

@ -101,7 +101,7 @@
openAlertModal("Dates invalides", document.createTextNode('La date de début se situe après la date de fin.')); openAlertModal("Dates invalides", document.createTextNode('La date de début se situe après la date de fin.'));
return; return;
} }
countAssiduites(date_debut.toIsoUtcString(), date_fin.toIsoUtcString()) countAssiduites(date_debut.toFakeIso(), date_fin.toFakeIso())
} }
@ -366,7 +366,7 @@
margin: 5px 0; margin: 5px 0;
border-radius: 7px; border-radius: 7px;
background-color: crimson; background-color: var(--color-error);
} }

View File

@ -453,17 +453,17 @@
let dayOfWeek = momentDate.getDay(); let dayOfWeek = momentDate.getDay();
dayOfWeek = days[dayOfWeek]; dayOfWeek = days[dayOfWeek];
let isNonWorkDay = nonWorkdays.includes(dayOfWeek.toLowerCase()); let isNonWorkDayVar = nonWorkdays.includes(dayOfWeek.toLowerCase());
const day = document.createElement('div'); const day = document.createElement('div');
day.className = `day`; day.className = `day`;
if (isNonWorkDay) { if (isNonWorkDayVar) {
color = "nonwork"; color = "nonwork";
} else if (!options.mode_demi) { } else if (!options.mode_demi) {
day.className = `day ${est_just}`; day.className = `day ${est_just}`;
} }
if (options.mode_demi && !isNonWorkDay) { if (options.mode_demi && !isNonWorkDayVar) {
est_just = [] est_just = []
// affichage n° jour + matin + aprem // affichage n° jour + matin + aprem
@ -560,7 +560,7 @@
day.classList.add(color); day.classList.add(color);
} }
if (isNonWorkDay) { if (isNonWorkDayVar) {
const span_jour = document.createElement("span") const span_jour = document.createElement("span")
span_jour.textContent = dayOfWeek[0] + dayOfMonth; span_jour.textContent = dayOfWeek[0] + dayOfMonth;
day.appendChild(span_jour); day.appendChild(span_jour);
@ -570,7 +570,6 @@
} }
console.warn(day.classList, day.classList.length)
if (!nonWorkdays.includes(dayOfWeek.toLowerCase()) && dayAssiduities.length > 0) { if (!nonWorkdays.includes(dayOfWeek.toLowerCase()) && dayAssiduities.length > 0) {

View File

@ -41,7 +41,7 @@
if (defaultDates != null) { if (defaultDates != null) {
defaultDates.forEach((dateString) => { defaultDates.forEach((dateString) => {
d = new Date(dateString).getDay(); d = new Date(dateString);
if (isNonWorkDay(d, nonWorkDays)) return; if (isNonWorkDay(d, nonWorkDays)) return;
@ -70,4 +70,4 @@
{% include "assiduites/widgets/alert.j2" %} {% include "assiduites/widgets/alert.j2" %}
{% include "assiduites/widgets/prompt.j2" %} {% include "assiduites/widgets/prompt.j2" %}
{% include "assiduites/widgets/conflict.j2" %} {% include "assiduites/widgets/conflict.j2" %}
{% include "assiduites/widgets/toast.j2" %} {% include "assiduites/widgets/toast.j2" %}

View File

@ -105,13 +105,13 @@
updateJustifyBtn(); updateJustifyBtn();
}); });
updateDate(); window.addEventListener("DOMContentLoaded", () => {
updateDate();
getSingleEtud({{ sco.etud.id }}); getSingleEtud(etudid);
actualizeEtud({{ sco.etud.id }}); actualizeEtud(etudid);
updateSelect() updateSelect()
updateJustifyBtn();
updateJustifyBtn(); })
function setTimeLineTimes(a, b) { function setTimeLineTimes(a, b) {

View File

@ -270,14 +270,14 @@
) { ) {
const assiduite_avant = { const assiduite_avant = {
etat: this.selectedAssiduite.etat, etat: this.selectedAssiduite.etat,
date_debut: assiduite_debut.toIsoUtcString()(), date_debut: assiduite_debut.toFakeIso(),
date_fin: separtorDate.toIsoUtcString()(), date_fin: separtorDate.toFakeIso(),
}; };
const assiduite_apres = { const assiduite_apres = {
etat: this.selectedAssiduite.etat, etat: this.selectedAssiduite.etat,
date_debut: separtorDate.toIsoUtcString()(), date_debut: separtorDate.toFakeIso(),
date_fin: assiduite_fin.toIsoUtcString()(), date_fin: assiduite_fin.toFakeIso(),
}; };
if (this.selectedAssiduite.moduleimpl_id) { if (this.selectedAssiduite.moduleimpl_id) {

View File

@ -285,10 +285,10 @@
let currentDate = "{{date}}"; let currentDate = "{{date}}";
if (currentDate == "") { if (currentDate == "") {
currentDate = new Date(); currentDate = new Date();
currentDate = currentDate.format("YYYY-MM-DDTHH:mm"); currentDate = currentDate.toFakeIso();
} else { } else {
currentDate = new Date(currentDate); currentDate = new Date(currentDate);
currentDate = currentDate.format("YYYY-MM-DDTHH:mm"); currentDate = currentDate.toFakeIso();
} }
@ -439,7 +439,7 @@
date = new Date(currentDate); date = new Date(currentDate);
const start = typeof mt_start !== 'undefined' ? mt_start : 0 const start = typeof mt_start !== 'undefined' ? mt_start : 0
date.setHours(start); date.setHours(start);
date = date.format("YYYY-MM-DDTHH:mm") date = date.toFakeIso()
} else { } else {
date = last.value; date = last.value;
} }
@ -555,14 +555,14 @@
} }
if (get) { if (get) {
getAssiduitesFromEtuds(false, d_debut.toIsoUtcString(), d_fin.toIsoUtcString()) getAssiduitesFromEtuds(false, d_debut.toFakeIso(), d_fin.toFakeIso())
return 0x0; return 0x0;
} }
return { return {
moduleimpl: moduleSelect, moduleimpl: moduleSelect,
deb: d_debut.toIsoUtcString(), deb: d_debut.toFakeIso(),
fin: d_fin.toIsoUtcString(), fin: d_fin.toFakeIso(),
} }
@ -653,6 +653,10 @@
colIds.forEach((colid) => { colIds.forEach((colid) => {
getAndUpdateCol(colid) getAndUpdateCol(colid)
}) })
if (isSingleEtud()) {
actualizeEtud(etudid);
}
} }
function launchToast(etudid, etat) { function launchToast(etudid, etat) {

View File

@ -13,14 +13,13 @@
*/ */
function createMiniTimeline(assiduitesArray, day = null) { function createMiniTimeline(assiduitesArray, day = null) {
const array = [...assiduitesArray]; const array = [...assiduitesArray];
const date = day == null ? getDate() : new Date(day);
const dateiso = day == null ? getDate().format("YYYY-MM-DD") : day;
const timeline = document.createElement("div"); const timeline = document.createElement("div");
timeline.className = "mini-timeline"; timeline.className = "mini-timeline";
if (isSingleEtud()) { if (isSingleEtud()) {
timeline.classList.add("single"); timeline.classList.add("single");
} }
const timelineDate = new Date(dateiso).startOf("day"); const timelineDate = date.startOf("day");
const dayStart = timelineDate.clone().add(mt_start, "hours"); const dayStart = timelineDate.clone().add(mt_start, "hours");
const dayEnd = timelineDate.clone().add(mt_end, "hours"); const dayEnd = timelineDate.clone().add(mt_end, "hours");
const dayDuration = new Duration(dayStart, dayEnd).minutes; const dayDuration = new Duration(dayStart, dayEnd).minutes;
@ -36,12 +35,12 @@
date_fin: tlTimes.fin.format(), date_fin: tlTimes.fin.format(),
etat: "CRENEAU", etat: "CRENEAU",
}); });
} }
array.forEach((assiduité) => { array.forEach((assiduité) => {
let startDate = new Date(assiduité.date_debut); let startDate = new Date(Date.removeUTC(assiduité.date_debut));
let endDate = new Date(assiduité.date_fin); let endDate = new Date(Date.removeUTC(assiduité.date_fin));
if (startDate.isBefore(dayStart)) { if (startDate.isBefore(dayStart)) {
startDate = dayEnd.clone().startOf("day").add(mt_start, "hours"); startDate = dayEnd.clone().startOf("day").add(mt_start, "hours");
} }
@ -52,11 +51,12 @@
const block = document.createElement("div"); const block = document.createElement("div");
block.className = "mini-timeline-block"; block.className = "mini-timeline-block";
const duration = new Duration(startDate, endDate).minutes; const duration = (new Duration(startDate, endDate)).minutes;
const startOffset = new Duration(dayStart, startDate).minutes; const startOffset = (new Duration(dayStart, startDate)).minutes;
const leftPercentage = (startOffset / dayDuration) * 100; const leftPercentage = (startOffset / dayDuration) * 100;
const widthPercentage = (duration / dayDuration) * 100; const widthPercentage = (duration / dayDuration) * 100;
block.style.left = `${leftPercentage}%`; block.style.left = `${leftPercentage}%`;
block.style.width = `${widthPercentage}%`; block.style.width = `${widthPercentage}%`;

View File

@ -21,9 +21,9 @@
} }
function filterFormSemestres(semestres, dateIso) { function filterFormSemestres(semestres, dateIso) {
const date = new Date(dateIso); const date = new Date(Date.removeUTC(dateIso));
semestres = semestres.filter((fm) => { semestres = semestres.filter((fm) => {
return date.isBetween(new Date(fm.date_debut_iso), new Date(fm.date_fin_iso), '[]'); return date.isBetween(new Date(Date.removeUTC(fm.date_debut_iso)), new Date(Date.removeUTC(fm.date_fin_iso)), '[]');
}) })
return semestres; return semestres;

View File

@ -83,7 +83,7 @@
filterAssiduites.columns.forEach((k) => { filterAssiduites.columns.forEach((k) => {
const td = document.createElement('td'); const td = document.createElement('td');
if (k.indexOf('date') != -1) { if (k.indexOf('date') != -1) {
td.textContent = new Date(assiduite[k]).format(`DD/MM/Y HH:mm`) td.textContent = new Date(Date.removeUTC(assiduite[k])).format(`DD/MM/Y HH:mm`)
} else if (k.indexOf("module") != -1) { } else if (k.indexOf("module") != -1) {
td.textContent = getModuleImpl(assiduite); td.textContent = getModuleImpl(assiduite);
} else if (k.indexOf('est_just') != -1) { } else if (k.indexOf('est_just') != -1) {
@ -115,9 +115,9 @@
const user = getUser(data); const user = getUser(data);
const module = getModuleImpl(data); const module = getModuleImpl(data);
const date_debut = new Date(data.date_debut).format("DD/MM/YYYY HH:mm"); const date_debut = new Date(Date.removeUTC(data.date_debut)).format("DD/MM/YYYY HH:mm");
const date_fin = new Date(data.date_fin).format("DD/MM/YYYY HH:mm"); const date_fin = new Date(Date.removeUTC(data.date_fin)).format("DD/MM/YYYY HH:mm");
const entry_date = new Date(data.entry_date).format("DD/MM/YYYY HH:mm"); const entry_date = new Date(Date.removeUTC(data.entry_date)).format("DD/MM/YYYY HH:mm");
const etat = data.etat.capitalize(); const etat = data.etat.capitalize();
const desc = data.desc == null ? "" : data.desc; const desc = data.desc == null ? "" : data.desc;
@ -433,7 +433,7 @@
if (l.querySelector(`#${key}_time`).value != "") { if (l.querySelector(`#${key}_time`).value != "") {
filterAssiduites.filters[key] = { filterAssiduites.filters[key] = {
pref: pref, pref: pref,
time: new Date(time) time: new Date(Date.removeUTC(time))
} }
} }
} else if (key.indexOf('etat') != -1) { } else if (key.indexOf('etat') != -1) {

View File

@ -75,7 +75,7 @@
} }
} }
if (k.indexOf('date') != -1) { if (k.indexOf('date') != -1) {
const assi_time = new Date(el[k]); const assi_time = new Date(Date.removeUTC(el[k]));
const filter_time = f[k].time; const filter_time = f[k].time;
switch (f[k].pref) { switch (f[k].pref) {
@ -262,8 +262,8 @@
let keyValueB = b[keyword]; let keyValueB = b[keyword];
if (keyword.indexOf("date") != -1) { if (keyword.indexOf("date") != -1) {
keyValueA = new Date(keyValueA) keyValueA = new Date(Date.removeUTC(keyValueA))
keyValueB = new Date(keyValueB) keyValueB = new Date(Date.removeUTC(keyValueB))
} }
if (keyword.indexOf("module") != -1) { if (keyword.indexOf("module") != -1) {

View File

@ -82,7 +82,7 @@
filterJustificatifs.columns.forEach((k) => { filterJustificatifs.columns.forEach((k) => {
const td = document.createElement('td'); const td = document.createElement('td');
if (k.indexOf('date') != -1) { if (k.indexOf('date') != -1) {
td.textContent = new Date(justificatif[k]).format(`DD/MM/Y HH:mm`) td.textContent = new Date(Date.removeUTC(justificatif[k])).format(`DD/MM/Y HH:mm`)
} else if (k.indexOf('fichier') != -1) { } else if (k.indexOf('fichier') != -1) {
td.textContent = justificatif.fichier ? "Oui" : "Non"; td.textContent = justificatif.fichier ? "Oui" : "Non";
} else if (k.indexOf('etudid') != -1) { } else if (k.indexOf('etudid') != -1) {
@ -120,9 +120,9 @@
path, path,
(data) => { (data) => {
const user = getUser(data); const user = getUser(data);
const date_debut = new Date(data.date_debut).format("DD/MM/YYYY HH:mm"); const date_debut = new Date(Date.removeUTC(data.date_debut)).format("DD/MM/YYYY HH:mm");
const date_fin = new Date(data.date_fin).format("DD/MM/YYYY HH:mm"); const date_fin = new Date(Date.removeUTC(data.date_fin)).format("DD/MM/YYYY HH:mm");
const entry_date = new Date(data.entry_date).format("DD/MM/YYYY HH:mm"); const entry_date = new Date(Date.removeUTC(data.entry_date)).format("DD/MM/YYYY HH:mm");
const etat = data.etat.capitalize(); const etat = data.etat.capitalize();
const desc = data.raison == null ? "" : data.raison; const desc = data.raison == null ? "" : data.raison;
@ -305,8 +305,8 @@
assiEdit.querySelector('#justi_etat').value = data.etat.toLowerCase(); assiEdit.querySelector('#justi_etat').value = data.etat.toLowerCase();
assiEdit.querySelector('#justi_raison').value = desc; assiEdit.querySelector('#justi_raison').value = desc;
const d_deb = new Date(data.date_debut).format("YYYY-MM-DDTHH:mm") const d_deb = new Date(Date.removeUTC(data.date_debut)).format("YYYY-MM-DDTHH:mm")
const d_fin = new Date(data.date_fin).format("YYYY-MM-DDTHH:mm") const d_fin = new Date(Date.removeUTC(data.date_fin)).format("YYYY-MM-DDTHH:mm")
assiEdit.querySelector('#justi_date_debut').value = d_deb assiEdit.querySelector('#justi_date_debut').value = d_deb
assiEdit.querySelector('#justi_date_fin').value = d_fin assiEdit.querySelector('#justi_date_fin').value = d_fin
@ -356,8 +356,8 @@
openAlertModal("Dates erronées", document.createTextNode('Les dates sont invalides')); openAlertModal("Dates erronées", document.createTextNode('Les dates sont invalides'));
return true return true
} }
date_debut = new Date(date_debut) date_debut = new Date(Date.removeUTC(date_debut))
date_fin = new Date(date_fin) date_fin = new Date(Date.removeUTC(date_fin))
if (date_debut >= date_fin) { if (date_debut >= date_fin) {
openAlertModal("Dates erronées", document.createTextNode('La date de fin doit être après la date de début')); openAlertModal("Dates erronées", document.createTextNode('La date de fin doit être après la date de début'));
@ -625,7 +625,7 @@
if (l.querySelector(`#${key}_time`).value != "") { if (l.querySelector(`#${key}_time`).value != "") {
filterJustificatifs.filters[key] = { filterJustificatifs.filters[key] = {
pref: pref, pref: pref,
time: new Date(time) time: new Date(Date.removeUTC(time))
} }
} }
} else if (key.indexOf('etat') != -1) { } else if (key.indexOf('etat') != -1) {

View File

@ -72,7 +72,7 @@
</div> </div>
<script> <script>
setTimeout(function() { setTimeout(function () {
var flashes = document.getElementsByClassName("flashes")[0]; var flashes = document.getElementsByClassName("flashes")[0];
if (flashes) { if (flashes) {
flashes.style.display = "none"; flashes.style.display = "none";
@ -93,5 +93,6 @@
<script src="{{scu.STATIC_DIR}}/js/scodoc.js"></script> <script src="{{scu.STATIC_DIR}}/js/scodoc.js"></script>
<script> <script>
const SCO_URL = "{{ url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)[:-11] }}"; const SCO_URL = "{{ url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)[:-11] }}";
const SCO_TIMEZONE = {{ scu.TIME_ZONE }}
</script> </script>
{% endblock %} {% endblock %}

View File

@ -18,8 +18,12 @@
Bulletin Bulletin
<span class="bull_liensemestre"> <span class="bull_liensemestre">
{{formsemestre.html_link_status() | safe}} {{formsemestre.html_link_status() | safe}}
{% if formsemestre.etuds_inscriptions[etud.id].parcour %} {% if etud.id in formsemestre.etuds_inscriptions %}
<span class="parcours">Parcours {{formsemestre.etuds_inscriptions[etud.id].parcour.code}}</span> {% if formsemestre.etuds_inscriptions[etud.id].parcour %}
<span class="parcours">Parcours {{formsemestre.etuds_inscriptions[etud.id].parcour.code}}</span>
{% endif %}
{% else %}
<span class="parcours">{{scu.EMO_WARNING|safe}} non inscrit !?</span>
{% endif %} {% endif %}
</span> </span>
</div> </div>
@ -67,8 +71,8 @@
)}}">version courte spéciale BUT</a> )}}">version courte spéciale BUT</a>
{% endif %} {% endif %}
<a style="margin-left: 32px;" class="stdlink" <a style="margin-left: 32px;" class="stdlink"
href="{{url_for('notes.validation_rcues', href="{{url_for('notes.validation_rcues',
scodoc_dept=g.scodoc_dept, etudid=etud.id, scodoc_dept=g.scodoc_dept, etudid=etud.id,
formsemestre_id=formsemestre.id formsemestre_id=formsemestre.id
)}}">visualiser les compétences BUT</a> )}}">visualiser les compétences BUT</a>
</div> </div>

View File

@ -9,80 +9,24 @@
<H1>Export xlsx de fichier de jury</H1> <H1>Export xlsx de fichier de jury</H1>
<form onsubmit="do_export()"> <form>
Formsemestre: {{ formsemestre.id }} <p>Formsemestre: {{ formsemestre.id }}</p><br/>
API root: {{ api_root }} <p>API root: /ScoDoc/{{dept}}/api/</p><br/>
<button>Exporter</button> <button id="ok">Exporter</button>
</form> </form>
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
{{super()}} {{super()}}
<script>
let formsemestre_id = {{ formsemestre.id }};
let dept = "{{ dept }}";
</script>
<script src="{{scu.STATIC_DIR}}/js/export-jury-but.js"></script> <script src="{{scu.STATIC_DIR}}/js/export-jury-but.js"></script>
<script> <script>
let dataSrc = "/ScoDoc/{{dept}}/api/formsemestre/{{formsemestre.id}}/etudiants/long";
let formsemestres = [];
fetch(dataSrc)
.then(r => { return r.json(); })
.then(json => {
let etudiants = json;
promises_etud_semestres = []
promises_semestres = []
etudiants.forEach((etudiant) => {
let url =`/ScoDoc/{{dept}}/api/etudiant/nip/${etudiant.code_nip}/formsemestres`;
console.log(url);
promises_etud_semestres.push(
fetch(url)
.then(r => { return r.json(); })
.then(semestre => {
formsemestre_id = semestre.formsemestre_id;
})
)
// etudiant.formsemestres_id = [];
fetch(url)
.then(r => {return r.json; })
.then(json => {
let forms = json;
console.log(etudiant.code_nip + " " + forms.formsemestre_id);
// forms.forEach((formsem) => {
// if (formsem.is_apc) {
// etudiant.formsemestres_id.push(formsem.formsemestre_id);
// if (formsem.formsemestre_id in_array()) {
// }
// }
// });
});
});
//let releve = document.querySelector("releve-but");
//releve.showData = json;
// Style custom à ajouter
// let style = document.createElement("style");
// style.textContent = `
// .module>div,
// .dateInscription,
// .numerosEtudiant,
// .dateNaissance{
// display: none;
// }`;
//releve.shadowRoot.appendChild(style);
})
.catch(error => { console.log(error)});
// .catch(error => {
// let div = document.createElement("div");
// div.innerText = "Une erreur s'est produite lors du transfert des données.";
// div.style.fontSize = "24px";
// div.style.color = "#d93030";
// let releve = document.querySelector("releve-but");
// releve.after(div);
// releve.remove();
// throw 'Fin du script - données invalides';
// });
document.querySelector("html").style.scrollBehavior = "smooth"; document.querySelector("html").style.scrollBehavior = "smooth";
</script> </script>

View File

@ -1,7 +1,7 @@
# -*- mode: python -*- # -*- mode: python -*-
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
SCOVERSION = "9.6.58" SCOVERSION = "9.6.60"
SCONAME = "ScoDoc" SCONAME = "ScoDoc"