Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
6 changed files with 197 additions and 43 deletions
Showing only changes of commit 99223b760b - Show all commits

View File

@ -278,7 +278,7 @@
padding: 20px;
border: 1px solid #888;
width: 80%;
height: 30%;
height: 40%;
position: relative;
border-radius: 10px;

View File

@ -1570,6 +1570,7 @@ function resetSelection() {
*/
window.onload = () => {
modal = document.getElementById("myModal");
if (modal) {
closeBtn = document.querySelector(".close");
timeline = document.getElementById("timeline");
deleteBtn = document.getElementById("delete");
@ -1590,6 +1591,7 @@ window.onload = () => {
editAssiduiteModal(selectedAssiduite);
}
});
}
};
// <<== Gestion de la récupération d'informations ==>>

View File

@ -59,7 +59,6 @@
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;
@ -67,10 +66,11 @@
fin = Math.min(mt_end, fin);
setPeriodValues(deb, fin);
if (isSingleEtud()) {
updateSelectedSelect(getCurrentAssiduiteModuleImplId());
updateJustifyBtn();
});
}
});
//ajouter affichage assiduites on over
setupAssiduiteBuble(block, assiduité);
}
@ -272,7 +272,9 @@
position: absolute;
text-align: start;
top: -40px;
transform: translateX(-50%)
transform: translateX(-50%);
z-index: 50;
}
.mini_tick::after {

View File

@ -4,7 +4,7 @@
<div id="studentTable">
<div class="thead">
<div class="tr">
<div class="th sticky">Noms</div>
<div class="th sticky" order="ASC" onclick="reOrderEtudiants()">Noms</div>
<button id="addColumn" class="floating-button">+</button>
</div>
</div>
@ -52,7 +52,7 @@
}
.thead .tr .th {
height: 125px;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
@ -61,11 +61,12 @@
.th.sticky {
z-index: 5;
cursor: pointer;
}
.th,
.td {
padding: 10px;
padding: 20px;
text-align: center;
width: 200px;
border: 1px solid #ddd;
@ -124,6 +125,7 @@
.th {
background-color: #007BFF;
color: white;
position: relative;
}
.tbody .tr:nth-child(even) {
@ -143,12 +145,48 @@
}
#moduleimpl_select {
max-width: 175px;
max-width: 190px;
}
.btngroup {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: row;
}
.btngroup>button {
background-color: transparent;
outline: none;
border: none;
cursor: pointer;
color: whitesmoke;
}
.close {
font-size: larger;
}
.activate {
font-size: large;
}
.th[activated] {
transition: all 0.5s;
}
.th[activated='false'] {
opacity: 0.5;
}
</style>
<script>
let verified = false;
const etatDef = "{{etat_def}}";
let forceModule = "{{ forcer_module }}"
forceModule = forceModule == "True" ? true : false
moment.tz.setDefault("Etc/UTC");
function createColumn() {
let table = document.getElementById("studentTable");
@ -156,11 +194,22 @@
th.classList.add("th");
const col_id = `${document.querySelectorAll("[col]").length + 1}`;
th.setAttribute("col", col_id);
th.setAttribute("activated", "true");
th.innerHTML = `
<div class="mini-form">
<div class="btngroup">
<button class="activate" onclick="toggleColumn(${col_id})">Désactiver</button>
<button class="close" onclick="removeColumn(this)">x</button>
</div>
<input type="datetime-local" id="dateStart">
<input type="datetime-local" id="dateEnd">
{{moduleimpl_select|safe}}
<select name="mass_action_${col_id}" id="mass_action_${col_id}" onchange="setEtatCol(${col_id},this.value)">
<option value="">Sélectionner une assiduité</option>
<option value="0">Présent</option>
<option value="1">Retard</option>
<option value="2">Absent</option>
</select>
</div>
`;
table
@ -193,9 +242,68 @@
}
}
function reOrderEtudiants() {
const th = document.querySelector(".th.sticky");
let lines = [...document.querySelectorAll('.tr[etudid]')];
const tbody = document.querySelector('.tbody')
let order = (a, b) => { return a > b }
if (th.getAttribute("order") == "ASC") {
order = (a, b) => { return b > a }
th.setAttribute("order", "DESC")
} else {
th.setAttribute("order", "ASC")
}
lines = lines.sort((a, b) => {
const nameA = a.querySelector(".td.sticky").textContent.split(" ").pop();
const nameB = b.querySelector(".td.sticky").textContent.split(" ").pop();
return order(nameA, nameB)
})
tbody.innerHTML = "";
tbody.append(...lines)
}
function toggleColumn(colId) {
const column = document.querySelector(`[col='${colId}']`)
const btn = column.querySelector(".activate");
if (column.getAttribute('activated') == "true") {
column.setAttribute("activated", "false");
btn.textContent = "Activer"
} else {
column.setAttribute("activated", "true");
btn.textContent = "Déactiver"
}
}
function previousCol(column) {
const cols = [...document.querySelectorAll("[col]")]
let previousCol = null;
let i = 1;
while (i < cols.length) {
previousCol = cols[i - 1];
if (cols[i] == column)
break;
i++;
}
return previousCol
}
function removeColumn(element) {
const col = element.parentElement.parentElement.parentElement;
const col_id = col.getAttribute("col");
document.querySelectorAll(`[col='${col_id}'],[colid='${col_id}']`).forEach((el) => { el.remove() })
}
function defaultDate(element) {
const num = element.parentElement.parentElement.getAttribute("col") - 1;
const last = [...document.querySelectorAll(`[col='${num}'] #dateEnd`)].pop();
const num = previousCol(element.parentElement.parentElement)?.getAttribute("col");
const last = document.querySelector(`[col='${num}'] #dateEnd`);
let date = undefined;
if (last == undefined) {
date = moment().tz("Europe/Paris").format("YYYY-MM-DDTHH:mm");
@ -218,6 +326,17 @@
);
}
function setEtatCol(colId, etatId) {
const tds = [...document.querySelectorAll(`.td[colid='${colId}']`)]
tds.forEach((td) => {
let inputs = [...td.querySelectorAll("input")]
inputs.forEach((el) => { el.checked = false })
if (etatId != "") {
inputs[Number.parseInt(etatId)].checked = true;
}
})
}
function getEtatCol(colId) {
const etats = {};
const tds = [...document.querySelectorAll(`.td[colid='${colId}']`)]
@ -266,6 +385,8 @@
cols.forEach((col) => {
const col_id = col.getAttribute("col");
if (col.getAttribute("activated") == "false") return;
toggleColumn(col_id);
const etats = getEtatCol(col_id);
const inputDeb = col.querySelector("#dateStart").value;
@ -273,10 +394,27 @@
const moduleSelect = col.querySelector("#moduleimpl_select").value;
if (inputDeb == "" || inputFin == "") {
errors.push(`La colonne n°${col_id} n'est pas valide`);
errors.push(`La période de la colonne n°${col_id} n'est pas valide`);
return;
}
const d_debut = moment(inputDeb)
const d_fin = moment(inputFin)
const testPeriode = [
d_debut.isBefore("{{formsemestre_date_debut}}"),
d_debut.isAfter("{{formsemestre_date_fin}}"),
d_fin.isBefore("{{formsemestre_date_debut}}"),
d_fin.isAfter("{{formsemestre_date_fin}}"),
]
if (testPeriode.some((e) => e)) {
errors.push(`La période de la colonne n°${col_id} n'est pas dans le semestre`);
return;
}
if (forceModule && moduleSelect == "") {
errors.push(`Le module de la colonne n°${col_id} n'a pas été entré. (Préférence de semestre)`);
return;
}
// TODO Mettre une erreur lorsque moduleimpl forcé (pref)
// TODO Mettre une erreur lorsque assiduité forcé (pref)
Object.keys(etats).forEach((key) => {
@ -297,8 +435,10 @@
openAlertModal("Erreur(s) détéctée(s)", texte)
} else {
if (assiduites.length > 0) {
createAllAssiduites(assiduites);
}
}
}

View File

@ -45,7 +45,7 @@
<div class="action-buttons">
<button id="delete" class="btnPrompt" disabled>Supprimer</button>
<button id="split" class="btnPrompt" disabled>Séparer</button>
<button id="edit" class="btnPrompt" disabled>Modifier</button>
<button id="edit" class="btnPrompt" disabled>Modifier l'état</button>
</div>
</div>

View File

@ -489,7 +489,6 @@ def get_etat_abs_date():
@permission_required(Permission.ScoAbsChange)
def signal_assiduites_diff():
group_ids: list[int] = request.args.get("group_ids", None)
etudid: int = request.args.get("etudid", None)
formsemestre_id: int = request.args.get("formsemestre_id", -1)
etudiants: list[dict] = []
@ -503,9 +502,6 @@ def signal_assiduites_diff():
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
if etudid is not None:
etudiants.append(sco_etud.get_etud_info(etudid=int(etudid), filled=True)[0])
if group_ids is None:
group_ids = []
else:
@ -514,6 +510,13 @@ def signal_assiduites_diff():
groups_infos = sco_groups_view.DisplayedGroupsInfos(group_ids)
if not groups_infos.members:
return (
html_sco_header.sco_header(page_title="Assiduités Différées")
+ "<h3>Aucun étudiant ! </h3>"
+ html_sco_header.sco_footer()
)
etudiants.extend(
[
sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0]
@ -553,7 +556,14 @@ def signal_assiduites_diff():
"assiduites/signal_assiduites_diff.j2",
etudiants=etudiants,
etat_def=sco_preferences.get_preference("assi_etat_defaut"),
formsemestre_date_debut=str(formsemestre.date_debut),
formsemestre_date_fin=str(formsemestre.date_fin),
moduleimpl_select=_module_selector(formsemestre),
forcer_module=sco_preferences.get_preference(
"forcer_module",
formsemestre_id=formsemestre_id,
dept_id=g.scodoc_dept_id,
),
gr=gr_tit,
sem=sem["titre_num"],
),