forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -53,7 +53,6 @@ import requests
|
||||
|
||||
from pytz import timezone
|
||||
|
||||
import dateutil.parser as dtparser
|
||||
|
||||
import flask
|
||||
from flask import g, request, Response
|
||||
@ -230,7 +229,7 @@ def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or No
|
||||
"""
|
||||
|
||||
try:
|
||||
date: datetime.datetime = dtparser.isoparse(date)
|
||||
date: datetime.datetime = datetime.datetime.fromisoformat(date)
|
||||
return date if convert else True
|
||||
except (dtparser.ParserError, ValueError, TypeError):
|
||||
return None if convert else False
|
||||
|
@ -32,6 +32,17 @@ Object.defineProperty(String.prototype, "capitalize", {
|
||||
},
|
||||
enumerable: false,
|
||||
});
|
||||
|
||||
const DatePrecisions = [
|
||||
"year",
|
||||
"month",
|
||||
"day",
|
||||
"hour",
|
||||
"minute",
|
||||
"second",
|
||||
"millisecond",
|
||||
];
|
||||
|
||||
// <<== Outils ==>>
|
||||
Object.defineProperty(Array.prototype, "reversed", {
|
||||
value: function () {
|
||||
@ -126,7 +137,7 @@ function validateSelectors(btn) {
|
||||
}
|
||||
|
||||
function onlyAbs() {
|
||||
if (getDate() > moment()) {
|
||||
if (getDate() > Date.now()) {
|
||||
document
|
||||
.querySelectorAll(".rbtn.present, .rbtn.retard")
|
||||
.forEach((el) => el.remove());
|
||||
@ -268,8 +279,8 @@ function executeMassActionQueue() {
|
||||
*/
|
||||
const tlTimes = getTimeLineTimes();
|
||||
let assiduite = {
|
||||
date_debut: tlTimes.deb.format(),
|
||||
date_fin: tlTimes.fin.format(),
|
||||
date_debut: tlTimes.deb.toIsoUtcString(),
|
||||
date_fin: tlTimes.fin.toIsoUtcString(),
|
||||
};
|
||||
|
||||
assiduite = setModuleImplId(assiduite);
|
||||
@ -613,19 +624,10 @@ function getNearestWorkDay(date) {
|
||||
}
|
||||
|
||||
function verifyDateInSemester() {
|
||||
const date = new moment.tz(
|
||||
document.querySelector("#tl_date").value,
|
||||
TIMEZONE
|
||||
);
|
||||
const date = getDate();
|
||||
|
||||
const periodSemester = getFormSemestreDates();
|
||||
|
||||
return date.isBetween(
|
||||
periodSemester.deb,
|
||||
periodSemester.fin,
|
||||
undefined,
|
||||
"[]"
|
||||
);
|
||||
return date.isBetween(periodSemester.deb, periodSemester.fin, "[]");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -664,8 +666,8 @@ function getAssiduitesOnDateChange() {
|
||||
* @param {String} separator le séparateur de la date intelligible (01/01/2000 {separtor} 10:00)
|
||||
* @returns {String} la date intelligible
|
||||
*/
|
||||
function formatDateModal(str, separator = "·") {
|
||||
return new moment.tz(str, TIMEZONE).format(`DD/MM/Y ${separator} HH:mm`);
|
||||
function formatDateModal(str, separator = " ") {
|
||||
return new Date(str).format("DD/MM/Y HH:mm").replace(" ", separator);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -705,8 +707,8 @@ function verifyNonWorkDays(day, nonWorkdays) {
|
||||
* Fonction qui vérifie si une période est dans un interval
|
||||
* Objet période / interval
|
||||
* {
|
||||
* deb: moment.tz(<Date>),
|
||||
* fin: moment.tz(<Date>),
|
||||
* deb: Date,
|
||||
* fin: Date,
|
||||
* }
|
||||
* @param {object} period
|
||||
* @param {object} interval
|
||||
@ -718,7 +720,7 @@ function hasTimeConflict(period, interval) {
|
||||
|
||||
/**
|
||||
* On récupère la période de la timeline
|
||||
* @returns {deb : moment.tz(), fin: moment.tz()}
|
||||
* @returns {deb : Date, fin: Date)}
|
||||
*/
|
||||
function getTimeLineTimes() {
|
||||
//getPeriodValues() -> retourne la position de la timeline [a,b] avec a et b des number
|
||||
@ -726,11 +728,11 @@ function getTimeLineTimes() {
|
||||
//On récupère la date
|
||||
const dateiso = document.querySelector("#tl_date").value;
|
||||
|
||||
//On génère des objets temps (moment.tz)
|
||||
//On génère des objets temps
|
||||
values = values.map((el) => {
|
||||
el = toTime(el).replace("h", ":");
|
||||
el = `${dateiso}T${el}`;
|
||||
return moment.tz(el, TIMEZONE);
|
||||
return new Date(el);
|
||||
});
|
||||
|
||||
return { deb: values[0], fin: values[1] };
|
||||
@ -744,8 +746,8 @@ function getTimeLineTimes() {
|
||||
function isConflictSameAsPeriod(conflict, period = undefined) {
|
||||
const tlTimes = period == undefined ? getTimeLineTimes() : period;
|
||||
const clTimes = {
|
||||
deb: moment.tz(conflict.date_debut, TIMEZONE),
|
||||
fin: moment.tz(conflict.date_fin, TIMEZONE),
|
||||
deb: new Date(conflict.date_debut),
|
||||
fin: new Date(conflict.date_fin),
|
||||
};
|
||||
return tlTimes.deb.isSame(clTimes.deb) && tlTimes.fin.isSame(clTimes.fin);
|
||||
}
|
||||
@ -815,9 +817,9 @@ function toIsoString(date) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforme un temps numérique en une date moment.tz
|
||||
* Transforme un temps numérique en une date
|
||||
* @param {number} nb
|
||||
* @returns {moment.tz} Une date formée du temps donné et de la date courante
|
||||
* @returns {Date} Une date formée du temps donné et de la date courante
|
||||
*/
|
||||
function numberTimeToDate(nb) {
|
||||
time = toTime(nb).replace("h", ":");
|
||||
@ -825,7 +827,7 @@ function numberTimeToDate(nb) {
|
||||
|
||||
datetime = `${date}T${time}`;
|
||||
|
||||
return moment.tz(datetime, TIMEZONE);
|
||||
return new Date(datetime);
|
||||
}
|
||||
|
||||
// <<== Gestion des assiduités ==>>
|
||||
@ -885,8 +887,8 @@ function getAssiduitesFromEtuds(clear, deb, fin) {
|
||||
function createAssiduite(etat, etudid) {
|
||||
const tlTimes = getTimeLineTimes();
|
||||
let assiduite = {
|
||||
date_debut: tlTimes.deb.format(),
|
||||
date_fin: tlTimes.fin.format(),
|
||||
date_debut: tlTimes.deb.toIsoUtcString(),
|
||||
date_fin: tlTimes.fin.toIsoUtcString(),
|
||||
etat: etat,
|
||||
};
|
||||
|
||||
@ -1067,10 +1069,11 @@ function getAssiduitesConflict(etudid, periode) {
|
||||
|
||||
return etudAssiduites.filter((assi) => {
|
||||
const interval = {
|
||||
deb: moment.tz(assi.date_debut, TIMEZONE),
|
||||
fin: moment.tz(assi.date_fin, TIMEZONE),
|
||||
deb: new Date(assi.date_debut),
|
||||
fin: new Date(assi.date_fin),
|
||||
};
|
||||
return hasTimeConflict(periode, interval);
|
||||
const test = hasTimeConflict(periode, interval);
|
||||
return test;
|
||||
});
|
||||
}
|
||||
|
||||
@ -1085,21 +1088,21 @@ function getLastAssiduiteOfPrevDate(etudid) {
|
||||
return "";
|
||||
}
|
||||
const period = {
|
||||
deb: moment.tz(getPrevDate(), TIMEZONE),
|
||||
fin: moment.tz(getDate(), TIMEZONE),
|
||||
deb: getPrevDate(),
|
||||
fin: getDate(),
|
||||
};
|
||||
const prevAssiduites = etudAssiduites
|
||||
.filter((assi) => {
|
||||
const interval = {
|
||||
deb: moment.tz(assi.date_debut, TIMEZONE),
|
||||
fin: moment.tz(assi.date_fin, TIMEZONE),
|
||||
deb: new Date(assi.date_debut),
|
||||
fin: new Date(assi.date_fin),
|
||||
};
|
||||
|
||||
return hasTimeConflict(period, interval);
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const a_fin = moment.tz(a.date_fin, TIMEZONE);
|
||||
const b_fin = moment.tz(b.date_fin, TIMEZONE);
|
||||
const a_fin = new Date(a.date_fin);
|
||||
const b_fin = new Date(b.date_fin);
|
||||
return b_fin < a_fin;
|
||||
});
|
||||
|
||||
@ -1232,8 +1235,8 @@ function assiduiteAction(element) {
|
||||
assiduites[etudid],
|
||||
getTimeLineTimes(),
|
||||
{
|
||||
deb: new moment.tz(getDate(), TIMEZONE),
|
||||
fin: new moment.tz(getNextDate(), TIMEZONE),
|
||||
deb: getDate(),
|
||||
fin: getNextDate(),
|
||||
}
|
||||
);
|
||||
const update = (assi) => {
|
||||
@ -1377,7 +1380,6 @@ function insertEtudRow(etud, index, output = false) {
|
||||
date_fin: null,
|
||||
prevAssiduites: prevAssiduite,
|
||||
};
|
||||
|
||||
if (conflict.length > 0) {
|
||||
assiduite.etatAssiduite = conflict[0].etat;
|
||||
|
||||
@ -1545,8 +1547,8 @@ function getFormSemestreDates() {
|
||||
const dateFin = document.getElementById("formsemestre_date_fin").textContent;
|
||||
|
||||
return {
|
||||
deb: dateDeb,
|
||||
fin: dateFin,
|
||||
deb: new Date(dateDeb),
|
||||
fin: new Date(dateFin),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1613,8 +1615,10 @@ function getJustificatifFromPeriod(date, etudid, update) {
|
||||
url:
|
||||
getUrl() +
|
||||
`/api/justificatifs/${etudid}/query?date_debut=${date.deb
|
||||
.add(1, "s")
|
||||
.format()}&date_fin=${date.fin.subtract(1, "s").format()}`,
|
||||
.add(1, "seconds")
|
||||
.toIsoUtcString()}&date_fin=${date.fin
|
||||
.add(-1, "seconds")
|
||||
.toIsoUtcString()}`,
|
||||
success: (data) => {
|
||||
update(data);
|
||||
},
|
||||
@ -1646,8 +1650,8 @@ function fastJustify(assiduite) {
|
||||
}
|
||||
|
||||
const period = {
|
||||
deb: new moment.tz(assiduite.date_debut, TIMEZONE),
|
||||
fin: new moment.tz(assiduite.date_fin, TIMEZONE),
|
||||
deb: new Date(assiduite.date_debut),
|
||||
fin: new Date(assiduite.date_fin),
|
||||
};
|
||||
const action = (justifs) => {
|
||||
//créer un nouveau justificatif
|
||||
@ -1660,8 +1664,8 @@ function fastJustify(assiduite) {
|
||||
//créer justificatif
|
||||
|
||||
const justif = {
|
||||
date_debut: new moment.tz(assiduite.date_debut, TIMEZONE).format(),
|
||||
date_fin: new moment.tz(assiduite.date_fin, TIMEZONE).format(),
|
||||
date_debut: new Date(assiduite.date_debut).toIsoUtcString(),
|
||||
date_fin: new Date(assiduite.date_fin).toIsoUtcString(),
|
||||
raison: raison,
|
||||
etat: etat,
|
||||
};
|
||||
|
451
app/static/js/date_utils.js
Normal file
451
app/static/js/date_utils.js
Normal file
@ -0,0 +1,451 @@
|
||||
Object.defineProperty(Date.prototype, "startOf", {
|
||||
/**
|
||||
* Génère u la date à la plus petite valeur pour la précision donnée.
|
||||
* @param {string} precision - La précision souhaitée (year, month, day, hours, minutes, seconds, milliseconds).
|
||||
* @returns {Date} - Une nouvelle date ajustée.
|
||||
*/
|
||||
value: function (precision) {
|
||||
const newDate = this.clone();
|
||||
switch (precision) {
|
||||
case "year":
|
||||
newDate.setMonth(0);
|
||||
case "month":
|
||||
newDate.setDate(1);
|
||||
case "day":
|
||||
newDate.setHours(0);
|
||||
case "hours":
|
||||
newDate.setMinutes(0);
|
||||
case "minutes":
|
||||
newDate.setSeconds(0);
|
||||
case "seconds":
|
||||
newDate.setMilliseconds(0);
|
||||
break;
|
||||
case "milliseconds":
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Invalid precision for startOf function [${precision}]`
|
||||
);
|
||||
}
|
||||
return newDate;
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Date.prototype, "endOf", {
|
||||
/**
|
||||
* Ajuste la date à la plus grande valeur pour la précision donnée.
|
||||
* @param {string} precision - La précision souhaitée (year, month, day, hours, minutes, seconds, milliseconds).
|
||||
* @returns {Date} - Une nouvelle date ajustée.
|
||||
*/
|
||||
value: function (precision) {
|
||||
const newDate = this.clone();
|
||||
switch (precision) {
|
||||
case "year":
|
||||
newDate.setMonth(11); // Décembre est le 11ème mois (0-indexé)
|
||||
case "month":
|
||||
newDate.setDate(0); // Le jour 0 du mois suivant est le dernier jour du mois courant
|
||||
newDate.setMonth(newDate.getMonth() + 1);
|
||||
case "day":
|
||||
newDate.setHours(23); // 23 heures est la dernière heure de la journée
|
||||
case "hours":
|
||||
newDate.setMinutes(59); // 59 minutes est la dernière minute de l'heure
|
||||
case "minutes":
|
||||
newDate.setSeconds(59); // 59 secondes est la dernière seconde de la minute
|
||||
case "seconds":
|
||||
newDate.setMilliseconds(999); // 999 millisecondes est la dernière milliseconde de la seconde
|
||||
break;
|
||||
case "milliseconds":
|
||||
// Rien à faire pour les millisecondes
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid precision for endOf function");
|
||||
}
|
||||
return newDate;
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Date.prototype, "isBefore", {
|
||||
/**
|
||||
* Retourne vrai si la date est située avant la date fournie
|
||||
* @param {Date} date
|
||||
* @returns {boolean}
|
||||
*/
|
||||
value: function (date) {
|
||||
return this.valueOf() < date.valueOf();
|
||||
},
|
||||
});
|
||||
Object.defineProperty(Date.prototype, "isAfter", {
|
||||
/**
|
||||
* Retourne vrai si la date est située après la date fournie
|
||||
* @param {Date} date
|
||||
* @returns {boolean}
|
||||
*/
|
||||
value: function (date) {
|
||||
return this.valueOf() > date.valueOf();
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Date.prototype, "isSame", {
|
||||
/**
|
||||
* Retourne vrai si les dates sont les mêmes
|
||||
* @param {Date} date
|
||||
* @param {string} precision default : "milliseconds"
|
||||
* @returns boolean
|
||||
*/
|
||||
value: function (date, precision = "milliseconds") {
|
||||
return (
|
||||
this.startOf(precision).valueOf() == date.startOf(precision).valueOf()
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Date.prototype, "isBetween", {
|
||||
/**
|
||||
* Vérifie si la date est comprise dans une période avec une précision et une inclusivité optionnelles
|
||||
* @param {Date} deb - La date de début de la période
|
||||
* @param {Date} fin - La date de fin de la période
|
||||
* @param {String} bornes - L'inclusivité/exclusivité de la comparaison ("[]", "()", "[)", "(]")
|
||||
* - bornes incluses : []
|
||||
* - bornes excluses : ()
|
||||
* - borne gauche incluse et borne droit excluse : [)
|
||||
* - borne gauche excluse et borne droit incluse : (]
|
||||
*/
|
||||
value: function (deb, fin, bornes = "[]") {
|
||||
// Ajuste la date actuelle, la date de début et la date de fin à la précision spécifiée
|
||||
|
||||
// Vérifie les bornes en fonction de l'inclusivité/exclusivité spécifiée dans 'bornes'
|
||||
const check_deb =
|
||||
bornes[0] === "("
|
||||
? this.valueOf() > deb.valueOf()
|
||||
: this.valueOf() >= deb.valueOf();
|
||||
const check_fin =
|
||||
bornes[1] === ")"
|
||||
? fin.valueOf() > this.valueOf()
|
||||
: fin.valueOf() >= this.valueOf();
|
||||
|
||||
return check_deb && check_fin;
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Date.prototype, "toIsoUtcString", {
|
||||
/**
|
||||
* @returns date au format iso utc (yyyy-mm-ddThh:MM±oo:oo:oo)
|
||||
*/
|
||||
value: function () {
|
||||
const date = this;
|
||||
var tzo = -date.getTimezoneOffset(),
|
||||
dif = tzo >= 0 ? "+" : "-",
|
||||
pad = function (num) {
|
||||
return (num < 10 ? "0" : "") + num;
|
||||
};
|
||||
|
||||
return (
|
||||
date.getFullYear() +
|
||||
"-" +
|
||||
pad(date.getMonth() + 1) +
|
||||
"-" +
|
||||
pad(date.getDate()) +
|
||||
"T" +
|
||||
pad(date.getHours()) +
|
||||
":" +
|
||||
pad(date.getMinutes()) +
|
||||
":" +
|
||||
pad(date.getSeconds()) +
|
||||
dif +
|
||||
pad(Math.floor(Math.abs(tzo) / 60)) +
|
||||
":" +
|
||||
pad(Math.abs(tzo) % 60)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Date.prototype, "clone", {
|
||||
/**
|
||||
* @returns Retourne une copie de la date (copie non liée)
|
||||
*/
|
||||
value: function () {
|
||||
return structuredClone(this);
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Date.prototype, "format", {
|
||||
value: function (formatString) {
|
||||
switch (formatString) {
|
||||
case "DD/MM/Y HH:mm":
|
||||
return this.toLocaleString("fr-FR", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
});
|
||||
case "DD/MM/YYYY HH:mm":
|
||||
return this.toLocaleString("fr-FR", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
});
|
||||
|
||||
case "YYYY-MM-DDTHH:mm":
|
||||
let iso = this.toIsoUtcString();
|
||||
// slice : YYYY-MM-DDTHH
|
||||
// slice + 3 : YYYY-MM-DDTHH:mm
|
||||
return iso.slice(0, iso.indexOf(":") + 3);
|
||||
default:
|
||||
return this.toIsoUtcString();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Date.prototype, "add", {
|
||||
/**
|
||||
* Ajoute une valeur spécifiée à un élément de la date.
|
||||
* @param {number} value - La valeur à ajouter.
|
||||
* @param {string} type - Le type de la valeur (year, month, day, hours, minutes, seconds).
|
||||
*/
|
||||
value: function (value, type) {
|
||||
switch (type) {
|
||||
case "years":
|
||||
this.setFullYear(this.getFullYear() + value);
|
||||
break;
|
||||
case "months":
|
||||
this.setMonth(this.getMonth() + value);
|
||||
break;
|
||||
case "days":
|
||||
this.setDate(this.getDate() + value);
|
||||
break;
|
||||
case "hours":
|
||||
this.setHours(this.getHours() + value);
|
||||
break;
|
||||
case "minutes":
|
||||
this.setMinutes(this.getMinutes() + value);
|
||||
break;
|
||||
case "seconds":
|
||||
this.setSeconds(this.getSeconds() + value);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Invalid type for adding to date | type : ${type} value : ${value}`
|
||||
);
|
||||
}
|
||||
return this; // Return the modified date
|
||||
},
|
||||
});
|
||||
|
||||
class Duration {
|
||||
/**
|
||||
* Constructeur de la classe Duration.
|
||||
* @param {Date} start - La date de début de la période.
|
||||
* @param {Date} end - La date de fin de la période.
|
||||
*/
|
||||
constructor(start, end) {
|
||||
this.start = start; // Stocke la date de début.
|
||||
this.end = end; // Stocke la date de fin.
|
||||
this.duration = end - start; // Calcule la durée en millisecondes entre les deux dates.
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le nombre d'années entre les deux dates et arrondit le résultat à quatre décimales.
|
||||
* @return {number} Le nombre d'années arrondi à quatre décimales.
|
||||
*/
|
||||
get years() {
|
||||
const startYear = this.start.getFullYear(); // Obtient l'année de la date de début.
|
||||
const endYear = this.end.getFullYear(); // Obtient l'année de la date de fin.
|
||||
// Calcule la différence en années et arrondit à quatre décimales.
|
||||
return parseFloat((endYear - startYear).toFixed(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le nombre de mois entre les deux dates, en tenant compte des années et des jours, et arrondit le résultat à quatre décimales.
|
||||
* @return {number} Le nombre de mois arrondi à quatre décimales.
|
||||
*/
|
||||
get months() {
|
||||
const years = this.years; // Nombre d'années complètes.
|
||||
// Calcule la différence en mois, en ajoutant la différence en jours divisée par 30 pour une approximation.
|
||||
const months =
|
||||
years * 12 +
|
||||
(this.end.getMonth() - this.start.getMonth()) +
|
||||
(this.end.getDate() - this.start.getDate()) / 30;
|
||||
// Arrondit à quatre décimales.
|
||||
return parseFloat(months.toFixed(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le nombre de jours entre les deux dates et arrondit le résultat à quatre décimales.
|
||||
* @return {number} Le nombre de jours arrondi à quatre décimales.
|
||||
*/
|
||||
get days() {
|
||||
// Convertit la durée en millisecondes en jours et arrondit à quatre décimales.
|
||||
return parseFloat((this.duration / (24 * 60 * 60 * 1000)).toFixed(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le nombre d'heures entre les deux dates et arrondit le résultat à quatre décimales.
|
||||
* @return {number} Le nombre d'heures arrondi à quatre décimales.
|
||||
*/
|
||||
get hours() {
|
||||
// Convertit la durée en millisecondes en heures et arrondit à quatre décimales.
|
||||
return parseFloat((this.duration / (60 * 60 * 1000)).toFixed(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le nombre de minutes entre les deux dates et arrondit le résultat à quatre décimales.
|
||||
* @return {number} Le nombre de minutes arrondi à quatre décimales.
|
||||
*/
|
||||
get minutes() {
|
||||
// Convertit la durée en millisecondes en minutes et arrondit à quatre décimales.
|
||||
return parseFloat((this.duration / (60 * 1000)).toFixed(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le nombre de secondes entre les deux dates et arrondit le résultat à quatre décimales.
|
||||
* @return {number} Le nombre de secondes arrondi à quatre décimales.
|
||||
*/
|
||||
get seconds() {
|
||||
// Convertit la durée en millisecondes en secondes et arrondit à quatre décimales.
|
||||
return parseFloat((this.duration / 1000).toFixed(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtient le nombre de millisecondes entre les deux dates et arrondit le résultat à quatre décimales.
|
||||
* @return {number} Le nombre de millisecondes arrondi à quatre décimales.
|
||||
*/
|
||||
get milliseconds() {
|
||||
// Arrondit la durée totale en millisecondes à quatre décimales.
|
||||
return parseFloat(this.duration.toFixed(4));
|
||||
}
|
||||
}
|
||||
|
||||
class ScoDocDateTimePicker extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
// Définir si le champ est requis
|
||||
this.required = this.hasAttribute("required");
|
||||
|
||||
// Initialiser le shadow DOM
|
||||
const shadow = this.attachShadow({ mode: "open" });
|
||||
|
||||
// Créer l'input pour la date
|
||||
const dateInput = document.createElement("input");
|
||||
dateInput.type = "date";
|
||||
dateInput.id = "date";
|
||||
|
||||
// Créer l'input pour l'heure
|
||||
const timeInput = document.createElement("input");
|
||||
timeInput.type = "time";
|
||||
timeInput.id = "time";
|
||||
|
||||
// Ajouter les inputs dans le shadow DOM
|
||||
shadow.appendChild(dateInput);
|
||||
shadow.appendChild(timeInput);
|
||||
|
||||
// Gestionnaires d'événements pour la mise à jour de la valeur
|
||||
dateInput.addEventListener("change", () => this.updateValue());
|
||||
timeInput.addEventListener("change", () => this.updateValue());
|
||||
|
||||
// Style CSS pour les inputs
|
||||
const style = document.createElement("style");
|
||||
style.textContent = `
|
||||
input {
|
||||
display: inline-block;
|
||||
}
|
||||
input:invalid {
|
||||
border: 1px solid red;
|
||||
}
|
||||
`;
|
||||
|
||||
// Ajouter le style au shadow DOM
|
||||
shadow.appendChild(style);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
// Récupérer l'attribut 'name'
|
||||
this.name = this.getAttribute("name");
|
||||
|
||||
// Créer un input caché pour la valeur datetime
|
||||
this.hiddenInput = document.createElement("input");
|
||||
this.hiddenInput.type = "hidden";
|
||||
this.hiddenInput.name = this.name;
|
||||
this.appendChild(this.hiddenInput);
|
||||
|
||||
// Gérer la soumission du formulaire
|
||||
this.closest("form")?.addEventListener("submit", (e) => {
|
||||
if (!this.validate()) {
|
||||
e.preventDefault(); // Empêcher la soumission si non valide
|
||||
this.dispatchEvent(
|
||||
new Event("invalid", { bubbles: true, cancelable: true })
|
||||
);
|
||||
} else {
|
||||
// Mettre à jour la valeur de l'input caché avant la soumission
|
||||
this.hiddenInput.value = this.isValid()
|
||||
? this.valueAsDate.toIsoUtcString()
|
||||
: "";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Vérifier si la valeur forme une date valide
|
||||
isValid() {
|
||||
return !Number.isNaN(this.valueAsDate.getTime());
|
||||
}
|
||||
|
||||
// Valider l'élément
|
||||
validate() {
|
||||
if (this.required && !this.isValid()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mettre à jour la valeur interne
|
||||
updateValue() {
|
||||
const dateInput = this.shadowRoot.querySelector("#date");
|
||||
const timeInput = this.shadowRoot.querySelector("#time");
|
||||
this._value = `${dateInput.value}T${timeInput.value}`;
|
||||
this.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
|
||||
// Appliquer le style 'invalid' si nécessaire
|
||||
dateInput.classList.toggle("invalid", this.required && !this.isValid());
|
||||
timeInput.classList.toggle("invalid", this.required && !this.isValid());
|
||||
}
|
||||
|
||||
// Getter pour obtenir la valeur actuelle.
|
||||
get value() {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
// Setter pour définir la valeur. Sépare la valeur en date et heure et les définit individuellement.
|
||||
set value(val) {
|
||||
let [date, time] = val.split("T");
|
||||
this.shadowRoot.querySelector("#date").value = date;
|
||||
|
||||
if ((time.match(/0/g) || []).length > 1) {
|
||||
time = time.slice(0, time.indexOf(":") + 3);
|
||||
}
|
||||
|
||||
this.shadowRoot.querySelector("#time").value = time;
|
||||
this._value = val;
|
||||
}
|
||||
|
||||
// Getter pour obtenir la valeur en tant qu'objet Date.
|
||||
get valueAsDate() {
|
||||
return new Date(this._value);
|
||||
}
|
||||
|
||||
// Setter pour définir la valeur à partir d'un objet Date.
|
||||
set valueAsDate(dateVal) {
|
||||
// Formatage de l'objet Date en string et mise à jour de la valeur.
|
||||
this.value = `${dateVal.getFullYear()}-${String(
|
||||
dateVal.getMonth() + 1
|
||||
).padStart(2, "0")}-${String(dateVal.getDate()).padStart(2, "0")}T${String(
|
||||
dateVal.getHours()
|
||||
).padStart(2, "0")}:${String(dateVal.getMinutes()).padStart(2, "0")}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Définition du nouvel élément personnalisé 'scodoc-datetime'.
|
||||
customElements.define("scodoc-datetime", ScoDocDateTimePicker);
|
2
app/static/libjs/moment-2.29.4.min.js
vendored
2
app/static/libjs/moment-2.29.4.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -18,12 +18,12 @@
|
||||
<div class="justi-row">
|
||||
<div class="justi-label">
|
||||
<legend for="justi_date_debut" required>Date de début</legend>
|
||||
<input type="datetime-local" name="justi_date_debut" id="justi_date_debut">
|
||||
<scodoc-datetime name="justi_date_debut" id="justi_date_debut"> </scodoc-datetime>
|
||||
<span>Journée(s) entière(s)</span> <input type="checkbox" name="justi_journee" id="justi_journee">
|
||||
</div>
|
||||
<div class="justi-label" id="date_fin">
|
||||
<legend for="justi_date_fin" required>Date de fin</legend>
|
||||
<input type="datetime-local" name="justi_date_fin" id="justi_date_fin">
|
||||
<scodoc-datetime name="justi_date_fin" id="justi_date_fin"></scodoc-datetime>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -118,8 +118,8 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
const date_debut = moment.tz(deb, TIMEZONE);
|
||||
const date_fin = moment.tz(fin, TIMEZONE);
|
||||
const date_debut = new Date(deb);
|
||||
const date_fin = new Date(fin);
|
||||
|
||||
if (date_fin.isBefore(date_debut)) {
|
||||
openAlertModal("Erreur détéctée", document.createTextNode("La date de fin doit se trouver après la date de début."), "", color = "crimson");
|
||||
@ -138,8 +138,8 @@
|
||||
const raison = field.querySelector('#justi_raison').value;
|
||||
|
||||
return {
|
||||
date_debut: moment.tz(deb, TIMEZONE).format(),
|
||||
date_fin: moment.tz(fin, TIMEZONE).format(),
|
||||
date_debut: new Date(deb).toIsoUtcString(),
|
||||
date_fin: new Date(fin).toIsoUtcString(),
|
||||
etat: etat,
|
||||
raison: raison,
|
||||
}
|
||||
|
@ -93,16 +93,15 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const date_debut = new moment.tz(dd_val + "T00:00", TIMEZONE);
|
||||
const date_fin = new moment.tz(df_val + "T23:59", TIMEZONE);
|
||||
const date_debut = new Date(dd_val + "T00:00");
|
||||
const date_fin = new Date(df_val + "T23:59");
|
||||
|
||||
if (date_debut.valueOf() > date_fin.valueOf()) {
|
||||
openAlertModal("Dates invalides", document.createTextNode('La date de début se situe après la date de fin.'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
countAssiduites(date_debut.format(), date_fin.format())
|
||||
countAssiduites(date_debut.toIsoUtcString(), date_fin.toIsoUtcString())
|
||||
|
||||
}
|
||||
|
||||
|
@ -111,10 +111,11 @@
|
||||
|
||||
<script>
|
||||
function getDaysBetweenDates(start, end) {
|
||||
let now = moment(start);
|
||||
let now = new Date(start);
|
||||
end = new Date(end);
|
||||
let dates = [];
|
||||
|
||||
while (now.isSameOrBefore(end)) {
|
||||
while (now.isBefore(end) || now.isSame(end)) {
|
||||
dates.push(now.clone());
|
||||
now.add(1, "days");
|
||||
}
|
||||
@ -126,7 +127,7 @@
|
||||
let datesByMonth = {};
|
||||
|
||||
dates.forEach((date) => {
|
||||
let month = date.format("MMMM"); // Obtenir le mois
|
||||
let month = date.toLocaleString('fr-FR', { month: "short" }); // Obtenir le mois
|
||||
|
||||
if (!datesByMonth[month]) {
|
||||
datesByMonth[month] = [];
|
||||
@ -146,24 +147,22 @@
|
||||
|
||||
datesByMonth[month].forEach((date) => {
|
||||
let dayAssiduities = assiduities.filter((assiduity) => {
|
||||
return moment.tz(date, TIMEZONE).isBetween(
|
||||
moment.tz(assiduity.date_debut, TIMEZONE),
|
||||
moment.tz(assiduity.date_fin, TIMEZONE),
|
||||
"day",
|
||||
return new Date(date).isBetween(
|
||||
new Date(assiduity.date_debut).startOf("day"),
|
||||
new Date(assiduity.date_fin).startOf("day"),
|
||||
"[]"
|
||||
)
|
||||
});
|
||||
|
||||
let dayJustificatifs = justificatifs.filter((justif) => {
|
||||
return moment.tz(date, TIMEZONE).isBetween(
|
||||
moment.tz(justif.date_debut, TIMEZONE),
|
||||
moment.tz(justif.date_fin, TIMEZONE),
|
||||
"day",
|
||||
return new Date(date).isBetween(
|
||||
new Date(justif.date_debut).startOf("day"),
|
||||
new Date(justif.date_fin).startOf("day"),
|
||||
"[]"
|
||||
)
|
||||
});
|
||||
|
||||
assiduitiesByDay[month][date.format("YYYY-MM-DD")] = {
|
||||
assiduitiesByDay[month][date.toLocaleDateString("en-US")] = {
|
||||
assiduites: dayAssiduities,
|
||||
justificatifs: dayJustificatifs
|
||||
};
|
||||
@ -200,35 +199,20 @@
|
||||
calendar.innerHTML = ""
|
||||
|
||||
const days = {
|
||||
Mon: "Lun",
|
||||
Tue: "Mar",
|
||||
Wed: "Mer",
|
||||
Thu: "Jeu",
|
||||
Fri: "Ven",
|
||||
Sat: "Sam",
|
||||
Sun: "Dim",
|
||||
};
|
||||
|
||||
const months = {
|
||||
January: "Jan.",
|
||||
February: "Fev.",
|
||||
March: "Mar.",
|
||||
April: "Avr.",
|
||||
May: "Mai",
|
||||
June: "Juin",
|
||||
July: "Juil.",
|
||||
August: "Août",
|
||||
September: "Sep.",
|
||||
October: "Oct.",
|
||||
November: "Nov.",
|
||||
December: "Déc.",
|
||||
1: "Lun",
|
||||
2: "Mar",
|
||||
3: "Mer",
|
||||
4: "Jeu",
|
||||
5: "Ven",
|
||||
6: "Sam",
|
||||
0: "Dim",
|
||||
};
|
||||
|
||||
Object.keys(assiduitiesByDay).forEach((month) => {
|
||||
const monthEl = document.createElement('div')
|
||||
monthEl.classList.add("month")
|
||||
const title = document.createElement('h2');
|
||||
title.textContent = `${months[month]}`;
|
||||
title.textContent = `${month.capitalize()}`;
|
||||
monthEl.appendChild(title)
|
||||
|
||||
const daysEl = document.createElement('div')
|
||||
@ -250,12 +234,12 @@
|
||||
} else if (dayJustificatifs.some((j) => j.etat.toLowerCase() !== "valide")) {
|
||||
est_just = "est_just invalide";
|
||||
}
|
||||
const momentDate = moment.tz(date, TIMEZONE);
|
||||
let dayOfMonth = momentDate.format("D");
|
||||
let dayOfWeek = momentDate.format("ddd");
|
||||
|
||||
const momentDate = new Date(date);
|
||||
let dayOfMonth = momentDate.getDate();
|
||||
let dayOfWeek = momentDate.getDay();
|
||||
dayOfWeek = days[dayOfWeek];
|
||||
|
||||
|
||||
if (nonWorkdays.includes(dayOfWeek.toLowerCase())) color = "nonwork";
|
||||
|
||||
const day = document.createElement('div');
|
||||
|
@ -41,7 +41,7 @@
|
||||
if (defaultDates != null) {
|
||||
defaultDates.forEach((dateString) => {
|
||||
|
||||
d = moment(dateString).weekday();
|
||||
d = new Date(dateString).getDay();
|
||||
|
||||
if (verifyNonWorkDays(d, nonWorkDays)) return;
|
||||
|
||||
|
18
app/templates/assiduites/pages/test.j2
Normal file
18
app/templates/assiduites/pages/test.j2
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Test DateUtils</title>
|
||||
<script src="{{scu.STATIC_DIR}}/js/date_utils.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form action="" method="post">
|
||||
<scodoc-datetime name="scodoc-datetime"></scodoc-datetime>
|
||||
<input type="submit" value="valider">
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -5,8 +5,8 @@
|
||||
* @returns {String} un déplacement par rapport à la gauche en %
|
||||
*/
|
||||
function getLeftPosition(start) {
|
||||
const startTime = new moment.tz(start, TIMEZONE);
|
||||
const startMins = (startTime.hours() - 8) * 60 + startTime.minutes();
|
||||
const startTime = new Date(start);
|
||||
const startMins = (startTime.getHours() - 8) * 60 + startTime.getMinutes();
|
||||
return (startMins / (18 * 60 - 8 * 60)) * 100 + "%";
|
||||
}
|
||||
/**
|
||||
@ -21,8 +21,8 @@
|
||||
return a.start < b.end && a.end > b.start;
|
||||
};
|
||||
|
||||
const startTime = new moment.tz(start, TIMEZONE);
|
||||
const endTime = new moment.tz(end, TIMEZONE);
|
||||
const startTime = new Date(start);
|
||||
const endTime = new Date(end);
|
||||
const assiduiteDuration = { start: startTime, end: endTime };
|
||||
|
||||
let position = 0;
|
||||
@ -31,8 +31,8 @@
|
||||
while (hasOverlap) {
|
||||
hasOverlap = false;
|
||||
Array.from(container.children).some((el) => {
|
||||
const elStart = new moment.tz(el.getAttribute("data-start"));
|
||||
const elEnd = new moment.tz(el.getAttribute("data-end"));
|
||||
const elStart = new Date(el.getAttribute("data-start"));
|
||||
const elEnd = new Date(el.getAttribute("data-end"));
|
||||
const elDuration = { start: elStart, end: elEnd };
|
||||
|
||||
if (overlaps(assiduiteDuration, elDuration)) {
|
||||
@ -71,8 +71,8 @@
|
||||
* @returns {String} la taille en %
|
||||
*/
|
||||
function getWidth(start, end) {
|
||||
const startTime = new moment.tz(start, TIMEZONE);
|
||||
const endTime = new moment.tz(end, TIMEZONE);
|
||||
const startTime = new Date(start);
|
||||
const endTime = new Date(end);
|
||||
|
||||
const duration = (endTime - startTime) / 1000 / 60;
|
||||
|
||||
@ -259,10 +259,10 @@
|
||||
const separatorTime = document.getElementById("promptTime").value;
|
||||
const dateString =
|
||||
document.querySelector("#tl_date").value + `T${separatorTime}`;
|
||||
const separtorDate = new moment.tz(dateString, TIMEZONE);
|
||||
const separtorDate = new Date(dateString);
|
||||
|
||||
const assiduite_debut = new moment.tz(this.selectedAssiduite.date_debut, TIMEZONE);
|
||||
const assiduite_fin = new moment.tz(this.selectedAssiduite.date_fin, TIMEZONE);
|
||||
const assiduite_debut = new Date(this.selectedAssiduite.date_debut);
|
||||
const assiduite_fin = new Date(this.selectedAssiduite.date_fin);
|
||||
|
||||
if (
|
||||
separtorDate.isAfter(assiduite_debut) &&
|
||||
@ -270,14 +270,14 @@
|
||||
) {
|
||||
const assiduite_avant = {
|
||||
etat: this.selectedAssiduite.etat,
|
||||
date_debut: assiduite_debut.format(),
|
||||
date_fin: separtorDate.format(),
|
||||
date_debut: assiduite_debut.toIsoUtcString()(),
|
||||
date_fin: separtorDate.toIsoUtcString()(),
|
||||
};
|
||||
|
||||
const assiduite_apres = {
|
||||
etat: this.selectedAssiduite.etat,
|
||||
date_debut: separtorDate.format(),
|
||||
date_fin: assiduite_fin.format(),
|
||||
date_debut: separtorDate.toIsoUtcString()(),
|
||||
date_fin: assiduite_fin.toIsoUtcString()(),
|
||||
};
|
||||
|
||||
if (this.selectedAssiduite.moduleimpl_id) {
|
||||
@ -396,8 +396,8 @@
|
||||
//Placement des assiduités sur la timeline
|
||||
this.list.forEach((assiduite) => {
|
||||
const period = {
|
||||
deb: new moment.tz(assiduite.date_debut, TIMEZONE),
|
||||
fin: new moment.tz(assiduite.date_fin, TIMEZONE),
|
||||
deb: new Date(assiduite.date_debut),
|
||||
fin: new Date(assiduite.date_fin),
|
||||
};
|
||||
if (!hasTimeConflict(period, this.interval)) {
|
||||
return;
|
||||
|
@ -274,17 +274,21 @@
|
||||
|
||||
<script>
|
||||
const assi_etat_defaut = "{{assi_etat_defaut}}";
|
||||
|
||||
window.forceModule = "{{ forcer_module }}"
|
||||
window.forceModule = window.forceModule == "True" ? true : false
|
||||
{% if scu.is_assiduites_module_forced(request.args.get('formsemestre_id', None)) %}
|
||||
window.forceModule = true;
|
||||
{% else %}
|
||||
window.forceModule = false;
|
||||
{% endif %}
|
||||
|
||||
let colCount = 1;
|
||||
|
||||
let currentDate = "{{date}}";
|
||||
if (currentDate == "") {
|
||||
currentDate = moment().tz(TIMEZONE).format("YYYY-MM-DDTHH:mm");
|
||||
currentDate = new Date();
|
||||
currentDate = currentDate.format("YYYY-MM-DDTHH:mm");
|
||||
} else {
|
||||
currentDate = moment(currentDate).tz(TIMEZONE).format("YYYY-MM-DDTHH:mm");
|
||||
currentDate = new Date(currentDate);
|
||||
currentDate = currentDate.format("YYYY-MM-DDTHH:mm");
|
||||
}
|
||||
|
||||
|
||||
@ -432,7 +436,10 @@
|
||||
const last = document.querySelector(`[col='${num}'] #dateEnd`);
|
||||
let date = undefined;
|
||||
if (last == undefined) {
|
||||
date = currentDate;
|
||||
date = new Date(currentDate);
|
||||
const start = typeof mt_start !== 'undefined' ? mt_start : 0
|
||||
date.setHours(start);
|
||||
date = date.format("YYYY-MM-DDTHH:mm")
|
||||
} else {
|
||||
date = last.value;
|
||||
}
|
||||
@ -444,9 +451,10 @@
|
||||
() => {
|
||||
const el = element.parentElement.querySelector("#dateEnd");
|
||||
const el2 = element.parentElement.querySelector("#dateStart");
|
||||
el.value = moment(el2.valueAsDate).tz(TIMEZONE).utc()
|
||||
.add(2, "hours")
|
||||
.format("YYYY-MM-DDTHH:mm");
|
||||
const newDate = new Date(el2.valueAsDate)
|
||||
.add(2, "hours");
|
||||
el.valueAsDate = newDate;
|
||||
|
||||
const colid = element.parentElement.parentElement.getAttribute('col');
|
||||
getAndUpdateCol(colid);
|
||||
},
|
||||
@ -517,8 +525,8 @@
|
||||
const inputDeb = col.querySelector("#dateStart").value;
|
||||
const inputFin = col.querySelector("#dateEnd").value;
|
||||
const moduleSelect = col.querySelector("#moduleimpl_select,.dynaSelect").value;
|
||||
const d_debut = moment(inputDeb).tz(TIMEZONE);
|
||||
const d_fin = moment(inputFin).tz(TIMEZONE);
|
||||
const d_debut = new Date(inputDeb);
|
||||
const d_fin = new Date(inputFin);
|
||||
|
||||
|
||||
if (inputDeb == "" || inputFin == "" || d_debut >= d_fin) {
|
||||
@ -547,14 +555,14 @@
|
||||
}
|
||||
|
||||
if (get) {
|
||||
getAssiduitesFromEtuds(false, d_debut.format(), d_fin.format())
|
||||
getAssiduitesFromEtuds(false, d_debut.toIsoUtcString(), d_fin.toIsoUtcString())
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
return {
|
||||
moduleimpl: moduleSelect,
|
||||
deb: d_debut.format(),
|
||||
fin: d_fin.format(),
|
||||
deb: d_debut.toIsoUtcString(),
|
||||
fin: d_fin.toIsoUtcString(),
|
||||
}
|
||||
|
||||
|
||||
@ -568,8 +576,8 @@
|
||||
|
||||
const inputDeb = col.querySelector("#dateStart").value;
|
||||
const inputFin = col.querySelector("#dateEnd").value;
|
||||
const d_debut = moment(inputDeb).tz(TIMEZONE);
|
||||
const d_fin = moment(inputFin).tz(TIMEZONE);
|
||||
const d_debut = new Date(inputDeb);
|
||||
const d_fin = new Date(inputFin);
|
||||
|
||||
const moduleimpl_id = col.querySelector("#moduleimpl_select,.dynaSelect").value;
|
||||
|
||||
@ -715,15 +723,27 @@
|
||||
assiduites[etudid].push(assiduite);
|
||||
updateAllCol()
|
||||
launchToast(etudid, etat);
|
||||
|
||||
} else {
|
||||
let error = data.errors[Object.keys(data.errors)[0]];
|
||||
if (error.message.indexOf("Module") != -1) {
|
||||
const html = `
|
||||
<h3>Aucun module n'a été spécifié (préférence du semestre concerné)</h3>
|
||||
`;
|
||||
const div = document.createElement("div");
|
||||
div.innerHTML = html;
|
||||
openAlertModal("Erreur Module", div);
|
||||
rbtn.checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
break;
|
||||
case "conflit":
|
||||
// Conflit, afficher résolveur
|
||||
const assiduitesList = assiduites[etudid];
|
||||
const d_debut = new moment.tz(deb, TIMEZONE);
|
||||
const d_fin = new moment.tz(fin, TIMEZONE);
|
||||
const d_debut = new Date(deb);
|
||||
const d_fin = new Date(fin);
|
||||
|
||||
const period = {
|
||||
deb: deb,
|
||||
@ -733,8 +753,8 @@
|
||||
assiduites[etudid],
|
||||
period,
|
||||
{
|
||||
deb: new moment.tz(d_debut.startOf('day'), TIMEZONE),
|
||||
fin: new moment.tz(d_fin.endOf('day'), TIMEZONE),
|
||||
deb: d_debut.startOf('day'),
|
||||
fin: d_fin.endOf('day'),
|
||||
}
|
||||
);
|
||||
const update = () => {
|
||||
@ -944,11 +964,24 @@
|
||||
|
||||
})
|
||||
).done((c, e) => {
|
||||
let error;
|
||||
Object.keys(c[0].success).forEach((k) => {
|
||||
const assiduite = createList[Number.parseInt(k)];
|
||||
assiduite["assiduite_id"] = c[0].success[k].message.assiduite_id;
|
||||
assiduites[assiduite.etudid].push(assiduite);
|
||||
})
|
||||
if (c[0].errors.length > 0) {
|
||||
error = c[0].errors[Object.keys(c[0].errors)[0]];
|
||||
if (error.message.indexOf("Module") != -1) {
|
||||
const html = `
|
||||
<h3>Aucun module n'a été spécifié (préférence du semestre concerné)</h3>
|
||||
`;
|
||||
const div = document.createElement("div");
|
||||
div.innerHTML = html;
|
||||
openAlertModal("Erreur Module", div);
|
||||
toCreate.length = 0
|
||||
}
|
||||
}
|
||||
Object.keys(e[0].success).forEach((k) => {
|
||||
const { etudid, assiduite_id, moduleimpl_id, etat } = editList[Number.parseInt(k)]
|
||||
assiduites[etudid].map((a) => {
|
||||
|
@ -19,10 +19,10 @@
|
||||
if (isSingleEtud()) {
|
||||
timeline.classList.add("single");
|
||||
}
|
||||
const timelineDate = moment(dateiso).startOf("day");
|
||||
const timelineDate = new Date(dateiso).startOf("day");
|
||||
const dayStart = timelineDate.clone().add(mt_start, "hours");
|
||||
const dayEnd = timelineDate.clone().add(mt_end, "hours");
|
||||
const dayDuration = moment.duration(dayEnd.diff(dayStart)).asMinutes();
|
||||
const dayDuration = new Duration(dayStart, dayEnd).minutes;
|
||||
|
||||
timeline.appendChild(setMiniTick(timelineDate, dayStart, dayDuration));
|
||||
|
||||
@ -38,8 +38,8 @@
|
||||
}
|
||||
|
||||
array.forEach((assiduité) => {
|
||||
let startDate = moment(assiduité.date_debut);
|
||||
let endDate = moment(assiduité.date_fin);
|
||||
let startDate = new Date(assiduité.date_debut);
|
||||
let endDate = new Date(assiduité.date_fin);
|
||||
|
||||
if (startDate.isBefore(dayStart)) {
|
||||
startDate = dayEnd.clone().startOf("day").add(mt_start, "hours");
|
||||
@ -51,8 +51,8 @@
|
||||
|
||||
const block = document.createElement("div");
|
||||
block.className = "mini-timeline-block";
|
||||
const duration = moment.duration(endDate.diff(startDate)).asMinutes();
|
||||
const startOffset = moment.duration(startDate.diff(dayStart)).asMinutes();
|
||||
const duration = new Duration(startDate, endDate).minutes;
|
||||
const startOffset = new Duration(dayStart, startDate).minutes;
|
||||
const leftPercentage = (startOffset / dayDuration) * 100;
|
||||
const widthPercentage = (duration / dayDuration) * 100;
|
||||
|
||||
@ -61,8 +61,8 @@
|
||||
|
||||
if (assiduité.etat != "CRENEAU") {
|
||||
block.addEventListener("click", () => {
|
||||
let deb = startDate.hours() + startDate.minutes() / 60;
|
||||
let fin = endDate.hours() + endDate.minutes() / 60;
|
||||
let deb = startDate.getHours() + startDate.getMinutes() / 60;
|
||||
let fin = endDate.getHours() + endDate.getMinutes() / 60;
|
||||
deb = Math.max(mt_start, deb);
|
||||
fin = Math.min(mt_end, fin);
|
||||
|
||||
@ -98,8 +98,8 @@
|
||||
if (assiduité.etudid) {
|
||||
getJustificatifFromPeriod(
|
||||
{
|
||||
deb: new moment.tz(assiduité.date_debut, TIMEZONE),
|
||||
fin: new moment.tz(assiduité.date_fin, TIMEZONE),
|
||||
deb: new Date(assiduité.date_debut),
|
||||
fin: new Date(assiduité.date_fin),
|
||||
},
|
||||
assiduité.etudid,
|
||||
action
|
||||
@ -184,8 +184,9 @@
|
||||
}
|
||||
|
||||
function setMiniTick(timelineDate, dayStart, dayDuration) {
|
||||
const endDate = timelineDate.clone().set({ 'hour': 13, 'minute': 0 });
|
||||
const duration = moment.duration(endDate.diff(dayStart)).asMinutes();
|
||||
const endDate = timelineDate.clone().startOf("day");
|
||||
endDate.setHours(13, 0);
|
||||
const duration = new Duration(dayStart, endDate).minutes;
|
||||
const widthPercentage = (duration / dayDuration) * 100;
|
||||
const tick = document.createElement('span');
|
||||
tick.className = "mini_tick"
|
||||
|
@ -21,13 +21,9 @@
|
||||
}
|
||||
|
||||
function filterFormSemestres(semestres, dateIso) {
|
||||
const date = new moment.tz(
|
||||
dateIso,
|
||||
TIMEZONE
|
||||
);
|
||||
|
||||
const date = new Date(dateIso);
|
||||
semestres = semestres.filter((fm) => {
|
||||
return date.isBetween(fm.date_debut_iso, fm.date_fin_iso, null, '[]')
|
||||
return date.isBetween(new Date(fm.date_debut_iso), new Date(fm.date_fin_iso), '[]');
|
||||
})
|
||||
|
||||
return semestres;
|
||||
|
@ -83,7 +83,7 @@
|
||||
filterAssiduites.columns.forEach((k) => {
|
||||
const td = document.createElement('td');
|
||||
if (k.indexOf('date') != -1) {
|
||||
td.textContent = moment.tz(assiduite[k], TIMEZONE).format(`DD/MM/Y HH:mm`)
|
||||
td.textContent = new Date(assiduite[k]).format(`DD/MM/Y HH:mm`)
|
||||
} else if (k.indexOf("module") != -1) {
|
||||
td.textContent = getModuleImpl(assiduite);
|
||||
} else if (k.indexOf('est_just') != -1) {
|
||||
@ -115,9 +115,9 @@
|
||||
const user = getUser(data);
|
||||
const module = getModuleImpl(data);
|
||||
|
||||
const date_debut = moment.tz(data.date_debut, TIMEZONE).format("DD/MM/YYYY HH:mm");
|
||||
const date_fin = moment.tz(data.date_fin, TIMEZONE).format("DD/MM/YYYY HH:mm");
|
||||
const entry_date = moment.tz(data.entry_date, TIMEZONE).format("DD/MM/YYYY HH:mm");
|
||||
const date_debut = new Date(data.date_debut).format("DD/MM/YYYY HH:mm");
|
||||
const date_fin = new Date(data.date_fin).format("DD/MM/YYYY HH:mm");
|
||||
const entry_date = new Date(data.entry_date).format("DD/MM/YYYY HH:mm");
|
||||
|
||||
const etat = data.etat.capitalize();
|
||||
const desc = data.desc == null ? "" : data.desc;
|
||||
@ -433,7 +433,7 @@
|
||||
if (l.querySelector(`#${key}_time`).value != "") {
|
||||
filterAssiduites.filters[key] = {
|
||||
pref: pref,
|
||||
time: new moment.tz(time, TIMEZONE)
|
||||
time: new Date(time)
|
||||
}
|
||||
}
|
||||
} else if (key.indexOf('etat') != -1) {
|
||||
|
@ -75,7 +75,7 @@
|
||||
}
|
||||
}
|
||||
if (k.indexOf('date') != -1) {
|
||||
const assi_time = moment.tz(el[k], TIMEZONE);
|
||||
const assi_time = new Date(el[k]);
|
||||
const filter_time = f[k].time;
|
||||
switch (f[k].pref) {
|
||||
|
||||
@ -262,8 +262,8 @@
|
||||
let keyValueB = b[keyword];
|
||||
|
||||
if (keyword.indexOf("date") != -1) {
|
||||
keyValueA = moment.tz(keyValueA, TIMEZONE)
|
||||
keyValueB = moment.tz(keyValueB, TIMEZONE)
|
||||
keyValueA = new Date(keyValueA)
|
||||
keyValueB = new Date(keyValueB)
|
||||
}
|
||||
|
||||
if (keyword.indexOf("module") != -1) {
|
||||
|
@ -82,7 +82,7 @@
|
||||
filterJustificatifs.columns.forEach((k) => {
|
||||
const td = document.createElement('td');
|
||||
if (k.indexOf('date') != -1) {
|
||||
td.textContent = moment.tz(justificatif[k], TIMEZONE).format(`DD/MM/Y HH:mm`)
|
||||
td.textContent = new Date(justificatif[k]).format(`DD/MM/Y HH:mm`)
|
||||
} else if (k.indexOf('fichier') != -1) {
|
||||
td.textContent = justificatif.fichier ? "Oui" : "Non";
|
||||
} else if (k.indexOf('etudid') != -1) {
|
||||
@ -120,9 +120,9 @@
|
||||
path,
|
||||
(data) => {
|
||||
const user = getUser(data);
|
||||
const date_debut = moment.tz(data.date_debut, TIMEZONE).format("DD/MM/YYYY HH:mm");
|
||||
const date_fin = moment.tz(data.date_fin, TIMEZONE).format("DD/MM/YYYY HH:mm");
|
||||
const entry_date = moment.tz(data.entry_date, TIMEZONE).format("DD/MM/YYYY HH:mm");
|
||||
const date_debut = new Date(data.date_debut).format("DD/MM/YYYY HH:mm");
|
||||
const date_fin = new Date(data.date_fin).format("DD/MM/YYYY HH:mm");
|
||||
const entry_date = new Date(data.entry_date).format("DD/MM/YYYY HH:mm");
|
||||
|
||||
const etat = data.etat.capitalize();
|
||||
const desc = data.raison == null ? "" : data.raison;
|
||||
@ -305,9 +305,8 @@
|
||||
|
||||
assiEdit.querySelector('#justi_etat').value = data.etat.toLowerCase();
|
||||
assiEdit.querySelector('#justi_raison').value = desc;
|
||||
const d_deb = moment.tz(data.date_debut, TIMEZONE).format("YYYY-MM-DDTHH:mm")
|
||||
const d_fin = moment.tz(data.date_fin, TIMEZONE).format("YYYY-MM-DDTHH:mm")
|
||||
console.warn(d_deb, d_fin, data.date_debut, data.date_fin)
|
||||
const d_deb = new Date(data.date_debut).format("YYYY-MM-DDTHH:mm")
|
||||
const d_fin = new Date(data.date_fin).format("YYYY-MM-DDTHH:mm")
|
||||
assiEdit.querySelector('#justi_date_debut').value = d_deb
|
||||
assiEdit.querySelector('#justi_date_fin').value = d_fin
|
||||
|
||||
@ -357,8 +356,8 @@
|
||||
openAlertModal("Dates erronées", document.createTextNode('Les dates sont invalides'));
|
||||
return true
|
||||
}
|
||||
date_debut = moment.tz(date_debut, TIMEZONE)
|
||||
date_fin = moment.tz(date_fin, TIMEZONE)
|
||||
date_debut = new Date(date_debut)
|
||||
date_fin = new Date(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'));
|
||||
@ -626,7 +625,7 @@
|
||||
if (l.querySelector(`#${key}_time`).value != "") {
|
||||
filterJustificatifs.filters[key] = {
|
||||
pref: pref,
|
||||
time: new moment.tz(time, TIMEZONE)
|
||||
time: new Date(time)
|
||||
}
|
||||
}
|
||||
} else if (key.indexOf('etat') != -1) {
|
||||
|
@ -144,7 +144,6 @@
|
||||
const startLeft = parseFloat(periodTimeLine.style.left);
|
||||
|
||||
const onMouseMove = (moveEvent) => {
|
||||
console.warn("move Period")
|
||||
if (handleMoving) return;
|
||||
const deltaX = (moveEvent.clientX || moveEvent.changedTouches[0].clientX) - startX;
|
||||
const containerWidth = timelineContainer.clientWidth;
|
||||
|
@ -167,8 +167,7 @@ def bilan_dept():
|
||||
page_title="Saisie de l'assiduité",
|
||||
javascripts=[
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
],
|
||||
cssstyles=[
|
||||
"css/assiduites.css",
|
||||
@ -290,8 +289,7 @@ def signal_assiduites_etud():
|
||||
init_qtip=True,
|
||||
javascripts=[
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
"js/etud_info.js",
|
||||
],
|
||||
cssstyles=[
|
||||
@ -371,8 +369,7 @@ def liste_assiduites_etud():
|
||||
init_qtip=True,
|
||||
javascripts=[
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
],
|
||||
cssstyles=CSSSTYLES
|
||||
+ [
|
||||
@ -419,8 +416,7 @@ def bilan_etud():
|
||||
init_qtip=True,
|
||||
javascripts=[
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
],
|
||||
cssstyles=CSSSTYLES
|
||||
+ [
|
||||
@ -480,8 +476,7 @@ def ajout_justificatif_etud():
|
||||
init_qtip=True,
|
||||
javascripts=[
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
],
|
||||
cssstyles=CSSSTYLES
|
||||
+ [
|
||||
@ -530,8 +525,7 @@ def calendrier_etud():
|
||||
init_qtip=True,
|
||||
javascripts=[
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
],
|
||||
cssstyles=CSSSTYLES
|
||||
+ [
|
||||
@ -681,12 +675,10 @@ def signal_assiduites_group():
|
||||
javascripts=html_sco_header.BOOTSTRAP_MULTISELECT_JS
|
||||
+ [
|
||||
# Voir fonctionnement JS
|
||||
# XXX Retirer moment
|
||||
"js/etud_info.js",
|
||||
"js/groups_view.js",
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
],
|
||||
cssstyles=CSSSTYLES
|
||||
+ [
|
||||
@ -833,8 +825,7 @@ def visu_assiduites_group():
|
||||
"js/etud_info.js",
|
||||
"js/groups_view.js",
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
],
|
||||
cssstyles=CSSSTYLES
|
||||
+ [
|
||||
@ -1113,8 +1104,7 @@ def signal_assiduites_diff():
|
||||
javascripts=html_sco_header.BOOTSTRAP_MULTISELECT_JS
|
||||
+ [
|
||||
"js/assiduites.js",
|
||||
"libjs/moment-2.29.4.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/date_utils.js",
|
||||
"js/etud_info.js",
|
||||
],
|
||||
)
|
||||
@ -1315,6 +1305,16 @@ def generate_bul_list(etud: Identite, semestre: FormSemestre) -> str:
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/test", methods=["GET", "POST"])
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
def test():
|
||||
"""XXX fonction de test a retirer"""
|
||||
if request.method == "POST":
|
||||
print("test date_utils : ", request.form)
|
||||
return render_template("assiduites/pages/test.j2")
|
||||
|
||||
|
||||
# --- Fonctions internes ---
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user