forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -30,7 +30,7 @@ Formulaire configuration Module Assiduités
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import SubmitField
|
from wtforms import SubmitField, DecimalField
|
||||||
from wtforms.fields.simple import StringField
|
from wtforms.fields.simple import StringField
|
||||||
from wtforms.widgets import TimeInput
|
from wtforms.widgets import TimeInput
|
||||||
import datetime
|
import datetime
|
||||||
@ -82,5 +82,7 @@ class ConfigAssiduitesForm(FlaskForm):
|
|||||||
lunch_time = TimeField("Heure de midi (date pivot entre Matin et Après Midi)")
|
lunch_time = TimeField("Heure de midi (date pivot entre Matin et Après Midi)")
|
||||||
afternoon_time = TimeField("Fin de la journée")
|
afternoon_time = TimeField("Fin de la journée")
|
||||||
|
|
||||||
|
tick_time = DecimalField("Granularité de la Time Line (temps en minutes)", places=0)
|
||||||
|
|
||||||
submit = SubmitField("Valider")
|
submit = SubmitField("Valider")
|
||||||
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})
|
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})
|
||||||
|
@ -439,9 +439,9 @@ function hideLoader() {
|
|||||||
*/
|
*/
|
||||||
function toTime(time) {
|
function toTime(time) {
|
||||||
let heure = Math.floor(time);
|
let heure = Math.floor(time);
|
||||||
let minutes = (time - heure) * 60;
|
let minutes = Math.round((time - heure) * 60);
|
||||||
if (minutes < 1) {
|
if (minutes < 10) {
|
||||||
minutes = "00";
|
minutes = `0${minutes}`;
|
||||||
}
|
}
|
||||||
if (heure < 10) {
|
if (heure < 10) {
|
||||||
heure = `0${heure}`;
|
heure = `0${heure}`;
|
||||||
@ -997,7 +997,6 @@ function generateEtudRow(
|
|||||||
</div>
|
</div>
|
||||||
<div class="assiduites_bar">
|
<div class="assiduites_bar">
|
||||||
<div id="prevDateAssi" class="${assiduite.prevAssiduites?.etat?.toLowerCase()}">
|
<div id="prevDateAssi" class="${assiduite.prevAssiduites?.etat?.toLowerCase()}">
|
||||||
<span class="mini_tick">13h</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<fieldset class="btns_field single" etudid="${etud.id}" assiduite_id="${
|
<fieldset class="btns_field single" etudid="${etud.id}" assiduite_id="${
|
||||||
@ -1065,172 +1064,6 @@ function insertEtudRow(etud, index, output = false) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Création de la minitiline d'un étudiant
|
|
||||||
* @param {Array[Assiduité]} assiduitesArray
|
|
||||||
* @returns {HTMLElement} l'élément correspondant à la mini timeline
|
|
||||||
*/
|
|
||||||
function createMiniTimeline(assiduitesArray) {
|
|
||||||
const array = [...assiduitesArray];
|
|
||||||
const dateiso = document.getElementById("tl_date").value;
|
|
||||||
const timeline = document.createElement("div");
|
|
||||||
timeline.className = "mini-timeline";
|
|
||||||
if (isSingleEtud()) {
|
|
||||||
timeline.classList.add("single");
|
|
||||||
}
|
|
||||||
const timelineDate = moment(dateiso).startOf("day");
|
|
||||||
const dayStart = timelineDate.clone().add(8, "hours");
|
|
||||||
const dayEnd = timelineDate.clone().add(18, "hours");
|
|
||||||
const dayDuration = moment.duration(dayEnd.diff(dayStart)).asMinutes();
|
|
||||||
|
|
||||||
const tlTimes = getTimeLineTimes();
|
|
||||||
|
|
||||||
const period_assi = {
|
|
||||||
date_debut: tlTimes.deb.format(),
|
|
||||||
date_fin: tlTimes.fin.format(),
|
|
||||||
etat: "CRENEAU",
|
|
||||||
};
|
|
||||||
|
|
||||||
array.push(period_assi);
|
|
||||||
|
|
||||||
array.forEach((assiduité) => {
|
|
||||||
const startDate = moment(assiduité.date_debut);
|
|
||||||
const endDate = moment(assiduité.date_fin);
|
|
||||||
|
|
||||||
if (startDate.isBefore(dayStart)) {
|
|
||||||
startDate.startOf("day").add(8, "hours");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endDate.isAfter(dayEnd)) {
|
|
||||||
endDate.startOf("day").add(18, "hours");
|
|
||||||
}
|
|
||||||
|
|
||||||
const block = document.createElement("div");
|
|
||||||
block.className = "mini-timeline-block";
|
|
||||||
|
|
||||||
const startOffset = moment.duration(startDate.diff(dayStart)).asMinutes();
|
|
||||||
const duration = moment.duration(endDate.diff(startDate)).asMinutes();
|
|
||||||
const leftPercentage = (startOffset / dayDuration) * 100;
|
|
||||||
const widthPercentage = (duration / dayDuration) * 100;
|
|
||||||
|
|
||||||
block.style.left = `${leftPercentage}%`;
|
|
||||||
block.style.width = `${widthPercentage}%`;
|
|
||||||
|
|
||||||
if (assiduité.etat != "CRENEAU") {
|
|
||||||
if (isSingleEtud()) {
|
|
||||||
block.addEventListener("click", () => {
|
|
||||||
let deb = startDate.hours() + startDate.minutes() / 60;
|
|
||||||
let fin = endDate.hours() + endDate.minutes() / 60;
|
|
||||||
deb = Math.max(8, deb);
|
|
||||||
fin = Math.min(18, fin);
|
|
||||||
|
|
||||||
setPeriodValues(deb, fin);
|
|
||||||
updateSelectedSelect(getCurrentAssiduiteModuleImplId());
|
|
||||||
updateJustifyBtn();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//ajouter affichage assiduites on over
|
|
||||||
setupAssiduiteBuble(block, assiduité);
|
|
||||||
}
|
|
||||||
|
|
||||||
const action = (justificatifs) => {
|
|
||||||
if (justificatifs.length > 0) {
|
|
||||||
let j = "invalid_justified";
|
|
||||||
|
|
||||||
justificatifs.forEach((ju) => {
|
|
||||||
if (ju.etat == "VALIDE") {
|
|
||||||
j = "justified";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
block.classList.add(j);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (assiduité.etudid) {
|
|
||||||
getJustificatifFromPeriod(
|
|
||||||
{
|
|
||||||
deb: new moment.tz(assiduité.date_debut, TIMEZONE),
|
|
||||||
fin: new moment.tz(assiduité.date_fin, TIMEZONE),
|
|
||||||
},
|
|
||||||
assiduité.etudid,
|
|
||||||
action
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (assiduité.etat) {
|
|
||||||
case "PRESENT":
|
|
||||||
block.classList.add("present");
|
|
||||||
break;
|
|
||||||
case "RETARD":
|
|
||||||
block.classList.add("retard");
|
|
||||||
break;
|
|
||||||
case "ABSENT":
|
|
||||||
block.classList.add("absent");
|
|
||||||
break;
|
|
||||||
case "CRENEAU":
|
|
||||||
block.classList.add("creneau");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
block.style.backgroundColor = "white";
|
|
||||||
}
|
|
||||||
|
|
||||||
timeline.appendChild(block);
|
|
||||||
});
|
|
||||||
|
|
||||||
return timeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ajout de la visualisation des assiduités de la mini timeline
|
|
||||||
* @param {HTMLElement} el l'élément survollé
|
|
||||||
* @param {Assiduité} assiduite l'assiduité représentée par l'élément
|
|
||||||
*/
|
|
||||||
function setupAssiduiteBuble(el, assiduite) {
|
|
||||||
if (!assiduite) return;
|
|
||||||
el.addEventListener("mouseenter", (event) => {
|
|
||||||
const bubble = document.querySelector(".assiduite-bubble");
|
|
||||||
bubble.className = "assiduite-bubble";
|
|
||||||
bubble.classList.add("is-active", assiduite.etat.toLowerCase());
|
|
||||||
|
|
||||||
bubble.innerHTML = "";
|
|
||||||
|
|
||||||
const idDiv = document.createElement("div");
|
|
||||||
idDiv.className = "assiduite-id";
|
|
||||||
idDiv.textContent = `ID: ${assiduite.assiduite_id}`;
|
|
||||||
bubble.appendChild(idDiv);
|
|
||||||
|
|
||||||
const periodDivDeb = document.createElement("div");
|
|
||||||
periodDivDeb.className = "assiduite-period";
|
|
||||||
periodDivDeb.textContent = `${formatDateModal(assiduite.date_debut)}`;
|
|
||||||
bubble.appendChild(periodDivDeb);
|
|
||||||
const periodDivFin = document.createElement("div");
|
|
||||||
periodDivFin.className = "assiduite-period";
|
|
||||||
periodDivFin.textContent = `${formatDateModal(assiduite.date_fin)}`;
|
|
||||||
bubble.appendChild(periodDivFin);
|
|
||||||
|
|
||||||
const stateDiv = document.createElement("div");
|
|
||||||
stateDiv.className = "assiduite-state";
|
|
||||||
stateDiv.textContent = `État: ${assiduite.etat.capitalize()}`;
|
|
||||||
bubble.appendChild(stateDiv);
|
|
||||||
|
|
||||||
const userIdDiv = document.createElement("div");
|
|
||||||
userIdDiv.className = "assiduite-user_id";
|
|
||||||
userIdDiv.textContent = `saisi le ${formatDateModal(
|
|
||||||
assiduite.entry_date,
|
|
||||||
"à"
|
|
||||||
)} \npar ${getUserFromId(assiduite.user_id)}`;
|
|
||||||
bubble.appendChild(userIdDiv);
|
|
||||||
|
|
||||||
bubble.style.left = `${event.clientX - bubble.offsetWidth / 2}px`;
|
|
||||||
bubble.style.top = `${event.clientY + 20}px`;
|
|
||||||
});
|
|
||||||
el.addEventListener("mouseout", () => {
|
|
||||||
const bubble = document.querySelector(".assiduite-bubble");
|
|
||||||
bubble.classList.remove("is-active");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mise à jour d'une ligne étudiant
|
* Mise à jour d'une ligne étudiant
|
||||||
* @param {String | Number} etudid l'identifiant de l'étudiant
|
* @param {String | Number} etudid l'identifiant de l'étudiant
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
{{ wtf.form_field(form.morning_time) }}
|
{{ wtf.form_field(form.morning_time) }}
|
||||||
{{ wtf.form_field(form.lunch_time) }}
|
{{ wtf.form_field(form.lunch_time) }}
|
||||||
{{ wtf.form_field(form.afternoon_time) }}
|
{{ wtf.form_field(form.afternoon_time) }}
|
||||||
|
{{ wtf.form_field(form.tick_time) }}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{ wtf.form_field(form.submit) }}
|
{{ wtf.form_field(form.submit) }}
|
||||||
{{ wtf.form_field(form.cancel) }}
|
{{ wtf.form_field(form.cancel) }}
|
||||||
|
@ -3,6 +3,189 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
const mt_start = {{ t_start }};
|
||||||
|
const mt_end = {{ t_end }};
|
||||||
|
/**
|
||||||
|
* Création de la minitiline d'un étudiant
|
||||||
|
* @param {Array[Assiduité]} assiduitesArray
|
||||||
|
* @returns {HTMLElement} l'élément correspondant à la mini timeline
|
||||||
|
*/
|
||||||
|
function createMiniTimeline(assiduitesArray) {
|
||||||
|
const array = [...assiduitesArray];
|
||||||
|
const dateiso = document.getElementById("tl_date").value;
|
||||||
|
const timeline = document.createElement("div");
|
||||||
|
timeline.className = "mini-timeline";
|
||||||
|
if (isSingleEtud()) {
|
||||||
|
timeline.classList.add("single");
|
||||||
|
}
|
||||||
|
const timelineDate = moment(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();
|
||||||
|
|
||||||
|
timeline.appendChild(setMiniTick(timelineDate, dayStart, dayDuration));
|
||||||
|
|
||||||
|
const tlTimes = getTimeLineTimes();
|
||||||
|
|
||||||
|
const period_assi = {
|
||||||
|
date_debut: tlTimes.deb.format(),
|
||||||
|
date_fin: tlTimes.fin.format(),
|
||||||
|
etat: "CRENEAU",
|
||||||
|
};
|
||||||
|
|
||||||
|
array.push(period_assi);
|
||||||
|
|
||||||
|
array.forEach((assiduité) => {
|
||||||
|
const startDate = moment(assiduité.date_debut);
|
||||||
|
const endDate = moment(assiduité.date_fin);
|
||||||
|
|
||||||
|
if (startDate.isBefore(dayStart)) {
|
||||||
|
startDate.startOf("day").add(mt_start, "hours");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endDate.isAfter(dayEnd)) {
|
||||||
|
endDate.startOf("day").add(mt_end, "hours");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 leftPercentage = (startOffset / dayDuration) * 100;
|
||||||
|
const widthPercentage = (duration / dayDuration) * 100;
|
||||||
|
|
||||||
|
block.style.left = `${leftPercentage}%`;
|
||||||
|
block.style.width = `${widthPercentage}%`;
|
||||||
|
|
||||||
|
if (assiduité.etat != "CRENEAU") {
|
||||||
|
if (isSingleEtud()) {
|
||||||
|
block.addEventListener("click", () => {
|
||||||
|
let deb = startDate.hours() + startDate.minutes() / 60;
|
||||||
|
let fin = endDate.hours() + endDate.minutes() / 60;
|
||||||
|
deb = Math.max(mt_start, deb);
|
||||||
|
fin = Math.min(mt_end, fin);
|
||||||
|
|
||||||
|
setPeriodValues(deb, fin);
|
||||||
|
updateSelectedSelect(getCurrentAssiduiteModuleImplId());
|
||||||
|
updateJustifyBtn();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//ajouter affichage assiduites on over
|
||||||
|
setupAssiduiteBuble(block, assiduité);
|
||||||
|
}
|
||||||
|
|
||||||
|
const action = (justificatifs) => {
|
||||||
|
if (justificatifs.length > 0) {
|
||||||
|
let j = "invalid_justified";
|
||||||
|
|
||||||
|
justificatifs.forEach((ju) => {
|
||||||
|
if (ju.etat == "VALIDE") {
|
||||||
|
j = "justified";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
block.classList.add(j);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (assiduité.etudid) {
|
||||||
|
getJustificatifFromPeriod(
|
||||||
|
{
|
||||||
|
deb: new moment.tz(assiduité.date_debut, TIMEZONE),
|
||||||
|
fin: new moment.tz(assiduité.date_fin, TIMEZONE),
|
||||||
|
},
|
||||||
|
assiduité.etudid,
|
||||||
|
action
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (assiduité.etat) {
|
||||||
|
case "PRESENT":
|
||||||
|
block.classList.add("present");
|
||||||
|
break;
|
||||||
|
case "RETARD":
|
||||||
|
block.classList.add("retard");
|
||||||
|
break;
|
||||||
|
case "ABSENT":
|
||||||
|
block.classList.add("absent");
|
||||||
|
break;
|
||||||
|
case "CRENEAU":
|
||||||
|
block.classList.add("creneau");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
block.style.backgroundColor = "white";
|
||||||
|
}
|
||||||
|
|
||||||
|
timeline.appendChild(block);
|
||||||
|
});
|
||||||
|
|
||||||
|
return timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ajout de la visualisation des assiduités de la mini timeline
|
||||||
|
* @param {HTMLElement} el l'élément survollé
|
||||||
|
* @param {Assiduité} assiduite l'assiduité représentée par l'élément
|
||||||
|
*/
|
||||||
|
function setupAssiduiteBuble(el, assiduite) {
|
||||||
|
if (!assiduite) return;
|
||||||
|
el.addEventListener("mouseenter", (event) => {
|
||||||
|
const bubble = document.querySelector(".assiduite-bubble");
|
||||||
|
bubble.className = "assiduite-bubble";
|
||||||
|
bubble.classList.add("is-active", assiduite.etat.toLowerCase());
|
||||||
|
|
||||||
|
bubble.innerHTML = "";
|
||||||
|
|
||||||
|
const idDiv = document.createElement("div");
|
||||||
|
idDiv.className = "assiduite-id";
|
||||||
|
idDiv.textContent = `ID: ${assiduite.assiduite_id}`;
|
||||||
|
bubble.appendChild(idDiv);
|
||||||
|
|
||||||
|
const periodDivDeb = document.createElement("div");
|
||||||
|
periodDivDeb.className = "assiduite-period";
|
||||||
|
periodDivDeb.textContent = `${formatDateModal(assiduite.date_debut)}`;
|
||||||
|
bubble.appendChild(periodDivDeb);
|
||||||
|
const periodDivFin = document.createElement("div");
|
||||||
|
periodDivFin.className = "assiduite-period";
|
||||||
|
periodDivFin.textContent = `${formatDateModal(assiduite.date_fin)}`;
|
||||||
|
bubble.appendChild(periodDivFin);
|
||||||
|
|
||||||
|
const stateDiv = document.createElement("div");
|
||||||
|
stateDiv.className = "assiduite-state";
|
||||||
|
stateDiv.textContent = `État: ${assiduite.etat.capitalize()}`;
|
||||||
|
bubble.appendChild(stateDiv);
|
||||||
|
|
||||||
|
const userIdDiv = document.createElement("div");
|
||||||
|
userIdDiv.className = "assiduite-user_id";
|
||||||
|
userIdDiv.textContent = `saisi le ${formatDateModal(
|
||||||
|
assiduite.entry_date,
|
||||||
|
"à"
|
||||||
|
)} \npar ${getUserFromId(assiduite.user_id)}`;
|
||||||
|
bubble.appendChild(userIdDiv);
|
||||||
|
|
||||||
|
bubble.style.left = `${event.clientX - bubble.offsetWidth / 2}px`;
|
||||||
|
bubble.style.top = `${event.clientY + 20}px`;
|
||||||
|
});
|
||||||
|
el.addEventListener("mouseout", () => {
|
||||||
|
const bubble = document.querySelector(".assiduite-bubble");
|
||||||
|
bubble.classList.remove("is-active");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMiniTick(timelineDate, dayStart, dayDuration) {
|
||||||
|
const endDate = timelineDate.clone().set({ 'hour': 13, 'minute': 0 });
|
||||||
|
const duration = moment.duration(endDate.diff(dayStart)).asMinutes();
|
||||||
|
const widthPercentage = (duration / dayDuration) * 100;
|
||||||
|
console.log(endDate, duration, widthPercentage)
|
||||||
|
const tick = document.createElement('span');
|
||||||
|
tick.className = "mini_tick"
|
||||||
|
tick.textContent = "13h"
|
||||||
|
tick.style.left = `${widthPercentage}%`
|
||||||
|
|
||||||
|
return tick
|
||||||
|
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -87,10 +270,9 @@
|
|||||||
|
|
||||||
.mini_tick {
|
.mini_tick {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: start;
|
||||||
top: -16px;
|
top: -40px;
|
||||||
left: 50%;
|
transform: translateX(-50%)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mini_tick::after {
|
.mini_tick::after {
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
const t_start = {{ t_start }};
|
const t_start = {{ t_start }};
|
||||||
const t_end = {{ t_end }};
|
const t_end = {{ t_end }};
|
||||||
|
|
||||||
|
const tick_time = 60 / {{ tick_time }}
|
||||||
|
const tick_delay = 1 / tick_time
|
||||||
|
|
||||||
const period_default = {{ periode_defaut }};
|
const period_default = {{ periode_defaut }};
|
||||||
|
|
||||||
function createTicks() {
|
function createTicks() {
|
||||||
@ -33,7 +36,7 @@
|
|||||||
let j = Math.floor(i + 1)
|
let j = Math.floor(i + 1)
|
||||||
|
|
||||||
while (i < j) {
|
while (i < j) {
|
||||||
i += 0.25;
|
i += tick_delay;
|
||||||
|
|
||||||
if (i <= t_end) {
|
if (i <= t_end) {
|
||||||
const quarterTick = document.createElement("div");
|
const quarterTick = document.createElement("div");
|
||||||
@ -43,6 +46,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
i = j
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +70,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function snapToQuarter(value) {
|
function snapToQuarter(value) {
|
||||||
return Math.round(value * 4) / 4;
|
|
||||||
|
|
||||||
|
return Math.round(value * tick_time) / tick_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupTimeLine(callback) {
|
function setupTimeLine(callback) {
|
||||||
@ -153,8 +159,8 @@
|
|||||||
const startHour = (leftPercentage / 100) * (t_end - t_start) + t_start;
|
const startHour = (leftPercentage / 100) * (t_end - t_start) + t_start;
|
||||||
const endHour = ((leftPercentage + widthPercentage) / 100) * (t_end - t_start) + t_start;
|
const endHour = ((leftPercentage + widthPercentage) / 100) * (t_end - t_start) + t_start;
|
||||||
|
|
||||||
const startValue = Math.round(startHour * 4) / 4;
|
const startValue = snapToQuarter(startHour);
|
||||||
const endValue = Math.round(endHour * 4) / 4;
|
const endValue = snapToQuarter(endHour);
|
||||||
|
|
||||||
const computedValues = [Math.max(startValue, t_start), Math.min(t_end, endValue)]
|
const computedValues = [Math.max(startValue, t_start), Math.min(t_end, endValue)]
|
||||||
|
|
||||||
@ -162,8 +168,8 @@
|
|||||||
return [t_start, min(t_end, t_start + period_default)]
|
return [t_start, min(t_end, t_start + period_default)]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (computedValues[1] - computedValues[0] <= 0.25 && computedValues[1] < t_end - 0.25) {
|
if (computedValues[1] - computedValues[0] <= tick_delay && computedValues[1] < t_end - tick_delay) {
|
||||||
computedValues[1] += 0.25;
|
computedValues[1] += tick_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
return computedValues
|
return computedValues
|
||||||
@ -183,13 +189,13 @@
|
|||||||
|
|
||||||
function snapHandlesToQuarters() {
|
function snapHandlesToQuarters() {
|
||||||
const periodValues = getPeriodValues();
|
const periodValues = getPeriodValues();
|
||||||
let lef = Math.min(computePercentage(periodValues[0], t_start), computePercentage(t_end, 0.25))
|
let lef = Math.min(computePercentage(periodValues[0], t_start), computePercentage(t_end, tick_delay))
|
||||||
if (lef < 0) {
|
if (lef < 0) {
|
||||||
lef = 0;
|
lef = 0;
|
||||||
}
|
}
|
||||||
const left = `${lef}%`
|
const left = `${lef}%`
|
||||||
|
|
||||||
let wid = Math.max(computePercentage(periodValues[1], periodValues[0]), computePercentage(0.25, 0))
|
let wid = Math.max(computePercentage(periodValues[1], periodValues[0]), computePercentage(tick_delay, 0))
|
||||||
if (wid > 100) {
|
if (wid > 100) {
|
||||||
wid = 100;
|
wid = 100;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ def signal_assiduites_etud():
|
|||||||
|
|
||||||
return HTMLBuilder(
|
return HTMLBuilder(
|
||||||
header,
|
header,
|
||||||
render_template("assiduites/minitimeline.j2"),
|
_mini_timeline(),
|
||||||
render_template(
|
render_template(
|
||||||
"assiduites/signal_assiduites_etud.j2",
|
"assiduites/signal_assiduites_etud.j2",
|
||||||
sco=ScoData(etud),
|
sco=ScoData(etud),
|
||||||
@ -385,7 +385,7 @@ def signal_assiduites_group():
|
|||||||
|
|
||||||
return HTMLBuilder(
|
return HTMLBuilder(
|
||||||
header,
|
header,
|
||||||
render_template("assiduites/minitimeline.j2"),
|
_mini_timeline(),
|
||||||
render_template(
|
render_template(
|
||||||
"assiduites/signal_assiduites_group.j2",
|
"assiduites/signal_assiduites_group.j2",
|
||||||
gr_tit=gr_tit,
|
gr_tit=gr_tit,
|
||||||
@ -449,7 +449,16 @@ def _timeline(formsemestre_id=None) -> HTMLElement:
|
|||||||
"assiduites/timeline.j2",
|
"assiduites/timeline.j2",
|
||||||
t_start=get_time("assi_morning_time", "08:00:00"),
|
t_start=get_time("assi_morning_time", "08:00:00"),
|
||||||
t_end=get_time("assi_afternoon_time", "18:00:00"),
|
t_end=get_time("assi_afternoon_time", "18:00:00"),
|
||||||
|
tick_time=ScoDocSiteConfig.get("assi_tick_time", 0.25),
|
||||||
periode_defaut=sco_preferences.get_preference(
|
periode_defaut=sco_preferences.get_preference(
|
||||||
"periode_defaut", formsemestre_id
|
"periode_defaut", formsemestre_id
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _mini_timeline() -> HTMLElement:
|
||||||
|
return render_template(
|
||||||
|
"assiduites/minitimeline.j2",
|
||||||
|
t_start=get_time("assi_morning_time", "08:00:00"),
|
||||||
|
t_end=get_time("assi_afternoon_time", "18:00:00"),
|
||||||
|
)
|
||||||
|
@ -203,6 +203,8 @@ def config_assiduites():
|
|||||||
flash("Heure de midi enregistrée")
|
flash("Heure de midi enregistrée")
|
||||||
if ScoDocSiteConfig.set("assi_afternoon_time", form.data["afternoon_time"]):
|
if ScoDocSiteConfig.set("assi_afternoon_time", form.data["afternoon_time"]):
|
||||||
flash("Heure de fin de la journée enregistrée")
|
flash("Heure de fin de la journée enregistrée")
|
||||||
|
if ScoDocSiteConfig.set("assi_tick_time", form.data["tick_time"]):
|
||||||
|
flash("Granularité de la timeline enregistrée")
|
||||||
return redirect(url_for("scodoc.configuration"))
|
return redirect(url_for("scodoc.configuration"))
|
||||||
|
|
||||||
elif request.method == "GET":
|
elif request.method == "GET":
|
||||||
@ -215,6 +217,7 @@ def config_assiduites():
|
|||||||
form.afternoon_time.data = ScoDocSiteConfig.get(
|
form.afternoon_time.data = ScoDocSiteConfig.get(
|
||||||
"assi_afternoon_time", datetime.time(18, 0, 0)
|
"assi_afternoon_time", datetime.time(18, 0, 0)
|
||||||
)
|
)
|
||||||
|
form.tick_time.data = float(ScoDocSiteConfig.get("assi_tick_time", 0.25))
|
||||||
return render_template(
|
return render_template(
|
||||||
"assiduites/config_assiduites.j2",
|
"assiduites/config_assiduites.j2",
|
||||||
form=form,
|
form=form,
|
||||||
|
Loading…
Reference in New Issue
Block a user