From 41a76267f6b57f1aec49e1b6fe9014169ce838d8 Mon Sep 17 00:00:00 2001 From: ilona Date: Mon, 9 Sep 2024 16:21:51 +0200 Subject: [PATCH] =?UTF-8?q?itemsuivi=20=C3=A9tudiants=20(devenir/d=C3=A9bo?= =?UTF-8?q?uch=C3=A9s):=20r=C3=A9-=C3=A9criture=20du=20backend,=20API,=20a?= =?UTF-8?q?daptation=20frontend=20js.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/__init__.py | 1 + app/api/etud_suivi.py | 213 ++++++++++++++++++++++++++++ app/models/__init__.py | 8 +- app/models/etudiants.py | 42 +++++- app/scodoc/sco_debouche.py | 252 +++++---------------------------- app/scodoc/sco_tag_module.py | 1 + app/static/js/etud_debouche.js | 76 +++++----- app/views/scolar.py | 40 ------ 8 files changed, 336 insertions(+), 297 deletions(-) create mode 100644 app/api/etud_suivi.py diff --git a/app/api/__init__.py b/app/api/__init__.py index a098d7e93..6c2e493ff 100644 --- a/app/api/__init__.py +++ b/app/api/__init__.py @@ -113,6 +113,7 @@ from app.api import ( assiduites, billets_absences, departements, + etud_suivi, etudiants, evaluations, formations, diff --git a/app/api/etud_suivi.py b/app/api/etud_suivi.py new file mode 100644 index 000000000..76703bad5 --- /dev/null +++ b/app/api/etud_suivi.py @@ -0,0 +1,213 @@ +############################################################################## +# ScoDoc +# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved. +# See LICENSE +############################################################################## + +""" + API : itemsuivi devenir/débouché des étudiants + + CATEGORY + -------- + Étudiants +""" +import datetime + +from flask import g, request, Response +from flask_json import as_json +from flask_login import login_required + +from app.api import api_bp as bp, api_web_bp +from app.api import api_permission_required as permission_required +from app import db, log +from app.decorators import scodoc +from app.models import Identite, ItemSuivi, ItemSuiviTag, Scolog +from app.scodoc import sco_permissions_check +from app.scodoc.sco_permissions import Permission +from app.scodoc.sco_exceptions import AccessDenied +import app.scodoc.sco_utils as scu + + +@bp.post("/etudiant//itemsuivi/create") +@api_web_bp.post("/etudiant//itemsuivi/create") +@login_required +@scodoc +@permission_required(Permission.EtudChangeAdr) +@as_json +def itemsuivi_create(etudid): + """Création d'un item de suivi associé à l'étudiant. + + The form MAY contain: + - item_date: date of the item + - situation: text + """ + if not sco_permissions_check.can_edit_suivi(): + raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") + etud = Identite.get_etud(etudid) + ok, item_date = _get_date_from_form() + item_date = item_date if ok else datetime.datetime.now() + situation = request.form.get("situation") or "" + item = ItemSuivi(etudid=etudid, item_date=item_date, situation=situation) + db.session.add(item) + db.session.commit() + Scolog.logdb(method="itemsuivi_create", etudid=etud.id, commit=True) + log(f"itemsuivi_create {item} for {etud}") + db.session.refresh(item) + return item.to_dict(merge_tags=True) + + +@bp.post("/etudiant/itemsuivi//delete") +@api_web_bp.post("/etudiant/itemsuivi//delete") +@login_required +@scodoc +@permission_required(Permission.EtudChangeAdr) +@as_json +def itemsuivi_suppress(itemid): + """Suppression d'un item""" + if not sco_permissions_check.can_edit_suivi(): + raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") + item: ItemSuivi = ItemSuivi.get_instance(itemid, accept_none=True) + if item is None: + return {"status": "ok", "message": "item not found"} + etudid = item.etudid + db.session.delete(item) + db.session.commit() + Scolog.logdb(method="itemsuivi_suppress", etudid=etudid, commit=True) + log(f"itemsuivi_suppress: itemid={itemid}") + return {"status": "ok", "message": "item deleted"} + + +@bp.get("/etudiant//itemsuivis") +@api_web_bp.get("/etudiant//itemsuivis") +@login_required +@scodoc +@permission_required(Permission.ScoView) +@as_json +def itemsuivi_list_etud(etudid: int): + """Liste des items pour cet étudiant, avec tags""" + etud = Identite.get_etud(etudid) + items = [it.to_dict(merge_tags=True) for it in etud.itemsuivis] + return items + + +@bp.post("/etudiant/itemsuivi//tag") +@api_web_bp.post("/etudiant/itemsuivi//tag") +@login_required +@scodoc +@permission_required(Permission.EtudChangeAdr) +@as_json +def itemsuivi_tag_set(itemid: int): + """ + taglist a string with tag names separated by commas e.g.: `un,deux` + """ + if not sco_permissions_check.can_edit_suivi(): + raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") + item: ItemSuivi = ItemSuivi.get_instance(itemid) + taglist_str = request.form.get("taglist")[: scu.MAX_TEXT_LEN] + if taglist_str is None: + return scu.json_error(400, "missing taglist in form") + taglist = [t.strip() for t in taglist_str.split(",")] + item.set_tags(taglist) + db.session.add(item) + db.session.commit() + log(f"itemsuivi_tag_set: itemsuivi_id={item.id} taglist={taglist}") + return item.to_dict(merge_tags=True) + + +@bp.post("/etudiant/itemsuivi//set_situation") +@api_web_bp.post("/etudiant/itemsuivi//set_situation") +@login_required +@scodoc +@permission_required(Permission.EtudChangeAdr) +def itemsuivi_set_situation(itemid: int): + """Modifie le champ situation de l'item de suivi de l'étudiant. + + Form data: "value" : "situation ..." + + Appel utilisé par champ éditable sur fiche étudiant. + """ + if not sco_permissions_check.can_edit_suivi(): + raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") + item: ItemSuivi = ItemSuivi.get_instance(itemid) + if "value" not in request.form: + return scu.json_error(400, "missing value in form") + situation = request.form["value"] + item.situation = situation.strip("-_ \t\r\n")[: scu.MAX_TEXT_LEN] + db.session.add(item) + db.session.commit() + log(f"itemsuivi_set_situation: itemid={itemid} situation={item.situation[:32]}") + return item.situation or scu.IT_SITUATION_MISSING_STR + + +@bp.post("/etudiant/itemsuivi//set_date") +@api_web_bp.post("/etudiant/itemsuivi//set_date") +@login_required +@scodoc +@permission_required(Permission.EtudChangeAdr) +@as_json +def itemsuivi_set_date(itemid: int): + """set item date + + Specify date as an ISO date string + or date_dmy, string dd/mm/yyyy + """ + if not sco_permissions_check.can_edit_suivi(): + raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") + ok, date_or_resp = _get_date_from_form() + if not ok: + return date_or_resp + item: ItemSuivi = ItemSuivi.get_instance(itemid) + item.item_date = date_or_resp + db.session.add(item) + db.session.commit() + log(f"itemsuivi_set_date: itemid={itemid} date={item.item_date}") + return item.to_dict(merge_tags=True) + + +def _get_date_from_form() -> tuple[bool, datetime.datetime | Response]: + """get date from form + Specify date as an ISO date string + or date_dmy, string dd/mm/yyyy + """ + date_iso = request.form.get("date") # ISO format + if date_iso: + try: + return True, datetime.datetime.fromisoformat(date_iso) + except ValueError: + return False, scu.json_error(400, "invalide date format (iso)") + date_dmy = request.form.get("date_dmy") + if not date_dmy: + return False, scu.json_error(400, "missing date or date_dmy in form") + try: + return True, datetime.datetime.strptime(date_dmy, scu.DATE_FMT) + except ValueError: + return False, scu.json_error(400, "invalide date format (jj/mm/aaaa)") + + +@bp.get("/etudiant/itemsuivi/tags/search") +@api_web_bp.get("/etudiant/itemsuivi/tags/search") +@login_required +@scodoc +@permission_required(Permission.ScoView) +@as_json +def itemsuivi_tag_search(): + """List all used tag names (for auto-completion) + + Query: term + """ + if getattr(g, "scodoc_dept_id", None) is None: + return [] # accès départemental seulement + term = request.args.get("term", "").strip()[: scu.MAX_TEXT_LEN] + # restrict charset to avoid injections + if not scu.ALPHANUM_EXP.match(term): + data = [] + else: + data = [ + x.title + for x in ItemSuiviTag.query.filter( + ItemSuiviTag.title.like(f"{term}%"), + ItemSuiviTag.dept_id == g.scodoc_dept_id, + ).all() + ] + + return data diff --git a/app/models/__init__.py b/app/models/__init__.py index 82e8416ff..26ed712f0 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -128,9 +128,13 @@ class ScoDocModel(db.Model): def get_instance(cls, oid: int, accept_none=False): """Instance du modèle ou ou 404 (ou None si accept_none), cherche uniquement dans le département courant. - Ne fonctionne que si le modèle a un attribut dept_id. + + Ne fonctionne que si le modèle a un attribut dept_id + ou que l'attribut de classe _sco_dept_relations indique les jointures + à effectuer pour trouver le département. + Si accept_none, return None si l'id est invalide ou ne correspond - pas à une validation. + pas à une instance. Sinon lève 404 en cas d'erreur. """ if not isinstance(oid, int): try: diff --git a/app/models/etudiants.py b/app/models/etudiants.py index 18387a565..af2207df6 100644 --- a/app/models/etudiants.py +++ b/app/models/etudiants.py @@ -115,7 +115,12 @@ class Identite(models.ScoDocModel): cascade="all, delete", passive_deletes=True, ) - + itemsuivis = db.relationship( + "ItemSuivi", + backref="etudiant", + cascade="all, delete-orphan", + lazy="dynamic", + ) # Relations avec les assiduites et les justificatifs assiduites = db.relationship( "Assiduite", back_populates="etudiant", lazy="dynamic", cascade="all, delete" @@ -1118,8 +1123,39 @@ class ItemSuivi(models.ScoDocModel): _sco_dept_relations = ("Identite",) # accès au dept_id + tags = db.relationship( + "ItemSuiviTag", + secondary="itemsuivi_tags_assoc", + lazy=True, + backref=db.backref("items", lazy=True), + ) -class ItemSuiviTag(db.Model): + def to_dict(self, merge_tags=False): + """Représentation dictionnaire. + Si merge_tags, regroupe les tags sur une seule chaine, valeurs séparées par des virgules + """ + d = super().to_dict() + # Convertit les tags en liste de strings: + if merge_tags: + d["tags"] = ", ".join([tag.title for tag in self.tags]) + else: + d["tags"] = [tag.title for tag in self.tags] + # Ajoute date locale + d["item_date_dmy"] = self.item_date.strftime(scu.DATE_FMT) + return d + + def set_tags(self, tags: list[str]): + """Définit les tags de l'itemsuivi""" + self.tags = [] + for tag in tags: + tag_obj = ItemSuiviTag.query.filter_by(title=tag).first() + if tag_obj is None: + tag_obj = ItemSuiviTag(title=tag) + self.tags.append(tag_obj) + + +class ItemSuiviTag(models.ScoDocModel): + "Tag sur un itemsuivi" __tablename__ = "itemsuivi_tags" id = db.Column(db.Integer, primary_key=True) dept_id = db.Column(db.Integer, db.ForeignKey("departement.id"), index=True) @@ -1127,7 +1163,7 @@ class ItemSuiviTag(db.Model): title = db.Column(db.Text(), nullable=False, unique=True) -# Association tag <-> module +# Association tag <-> itemsuivi itemsuivi_tags_assoc = db.Table( "itemsuivi_tags_assoc", db.Column( diff --git a/app/scodoc/sco_debouche.py b/app/scodoc/sco_debouche.py index a5c97ab93..52e17e167 100644 --- a/app/scodoc/sco_debouche.py +++ b/app/scodoc/sco_debouche.py @@ -28,22 +28,15 @@ """ Rapport (table) avec dernier semestre fréquenté et débouché de chaque étudiant """ -import http from flask import g, render_template, request, url_for -from app import log from app.comp import res_sem from app.comp.res_compat import NotesTableCompat -from app.models import FormSemestre, Scolog +from app.models import Identite import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb -from app.scodoc.sco_exceptions import AccessDenied, ScoValueError from app.scodoc.gen_tables import GenTable -from app.scodoc import safehtml -from app.scodoc import sco_permissions_check from app.scodoc import sco_preferences -from app.scodoc import sco_tag_module -from app.scodoc import sco_etud import sco_version @@ -75,6 +68,7 @@ def report_debouche_date(start_year=None, fmt="html"): tab.base_url = f"{request.base_url}?start_year={start_year}" return tab.make_page( title="""

Débouchés étudiants

""", + page_title="Débouchés étudiants", fmt=fmt, with_html_headers=True, template="sco_page_dept.j2", @@ -115,70 +109,62 @@ def table_debouche_etudids(etudids, keep_numeric=True): """Rapport pour ces étudiants""" rows = [] # Recherche les débouchés: - itemsuivi_etuds = {etudid: itemsuivi_list_etud(etudid) for etudid in etudids} + # itemsuivi_etuds = {etudid: itemsuivi_list_etud(etudid) for etudid in etudids} all_tags = set() - for debouche in itemsuivi_etuds.values(): - if debouche: - for it in debouche: - all_tags.update(tag.strip() for tag in it["tags"].split(",")) - all_tags = tuple(sorted(all_tags)) - for etudid in etudids: - etud = sco_etud.get_etud_info(filled=True, etudid=etudid)[0] + etud = Identite.get_etud(etudid) + # collecte les tags + all_tags.update(tag.title for item in etud.itemsuivis for tag in item.tags) # retrouve le "dernier" semestre (au sens de la date de fin) - sems = etud["sems"] - es = [(s["date_fin_iso"], i) for i, s in enumerate(sems)] - imax = max(es)[1] - last_sem = sems[imax] - formsemestre = FormSemestre.query.get_or_404(last_sem["formsemestre_id"]) + formsemestres = etud.get_formsemestres() + dates_fin = [s.date_fin for s in formsemestres] + imax = dates_fin.index(max(dates_fin)) + formsemestre = formsemestres[imax] nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) row = { "etudid": etudid, - "civilite": etud["civilite"], - "nom": etud["nom"], - "prenom": etud["prenom"], + "civilite": etud.civilite, + "nom": etud.nom, + "prenom": etud.prenom, "_nom_target": url_for( "scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid ), "_prenom_target": url_for( "scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid ), - "_nom_td_attrs": 'id="%s" class="etudinfo"' % (etud["etudid"]), + "_nom_td_attrs": f'id="{etudid}" class="etudinfo"', # 'debouche' : etud['debouche'], "moy": scu.fmt_note(nt.get_etud_moy_gen(etudid), keep_numeric=keep_numeric), "rang": nt.get_etud_rang(etudid), "effectif": len(nt.T), - "semestre_id": last_sem["semestre_id"], - "semestre": last_sem["titre"], - "date_debut": last_sem["date_debut"], - "date_fin": last_sem["date_fin"], - "periode": "%s - %s" % (last_sem["mois_debut"], last_sem["mois_fin"]), - "sem_ident": "%s %s" - % (last_sem["date_debut_iso"], last_sem["titre"]), # utile pour tris + "semestre_id": formsemestre.semestre_id, + "semestre": formsemestre.titre, + "date_debut": formsemestre.date_debut, + "date_fin": formsemestre.date_fin, + "periode": f"{formsemestre.mois_debut()} - {formsemestre.mois_fin()}", + "sem_ident": f"{formsemestre.date_debut.isoformat()} {formsemestre.titre}", # utile pour tris } # recherche des débouchés - debouche = itemsuivi_etuds[etudid] # liste de plusieurs items - if debouche: + itemsuivis = etud.itemsuivis # liste de plusieurs items + if itemsuivis: if keep_numeric: # pour excel: row["debouche"] = "\n".join( - f"""{it["item_date"]}: {it["situation"]}""" for it in debouche + f"""{it.item_date.strftime(scu.DATE_FMT)}: {it.situation or ""}""" + for it in itemsuivis ) else: row["debouche"] = "
".join( [ - str(it["item_date"]) - + " : " - + it["situation"] - + " " - + it["tags"] - + "" - for it in debouche + f"""{it.item_date.strftime(scu.DATE_FMT)} : {it.situation or ""} + {', '.join( tag.title for tag in it.tags)} + """ + for it in itemsuivis ] ) - for it in debouche: - for tag in it["tags"].split(","): - tag = tag.strip() - row[f"tag_{tag}"] = tag + for it in itemsuivis: + for tag in it.tags: + tag_name = tag.title.strip() + row[f"tag_{tag_name}"] = tag_name else: row["debouche"] = "non renseigné" rows.append(row) @@ -236,177 +222,3 @@ def report_debouche_ask_date(msg: str) -> str: """, ) - - -# ---------------------------------------------------------------------------- -# -# Nouveau suivi des etudiants (nov 2017) -# -# ---------------------------------------------------------------------------- - - -_itemsuiviEditor = ndb.EditableTable( - "itemsuivi", - "itemsuivi_id", - ("itemsuivi_id", "etudid", "item_date", "situation"), - sortkey="item_date desc", - convert_null_outputs_to_empty=True, - output_formators={ - "situation": safehtml.html_to_safe_html, - "item_date": ndb.DateISOtoDMY, - }, - input_formators={"item_date": ndb.DateDMYtoISO}, -) - -_itemsuivi_create = _itemsuiviEditor.create -_itemsuivi_delete = _itemsuiviEditor.delete -_itemsuivi_list = _itemsuiviEditor.list -_itemsuivi_edit = _itemsuiviEditor.edit - - -class ItemSuiviTag(sco_tag_module.ScoTag): - """Les tags sur les items""" - - tag_table = "itemsuivi_tags" # table (tag_id, title) - assoc_table = "itemsuivi_tags_assoc" # table (tag_id, object_id) - obj_colname = "itemsuivi_id" # column name for object_id in assoc_table - - -def itemsuivi_get(cnx, itemsuivi_id, ignore_errors=False): - """get an item""" - items = _itemsuivi_list(cnx, {"itemsuivi_id": itemsuivi_id}) - if items: - return items[0] - elif not ignore_errors: - raise ScoValueError(f"Débouché: item inexistant ({itemsuivi_id})") - return None - - -def itemsuivi_suppress(itemsuivi_id): - """Suppression d'un item""" - if not sco_permissions_check.can_edit_suivi(): - raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") - cnx = ndb.GetDBConnexion() - item = itemsuivi_get(cnx, itemsuivi_id, ignore_errors=True) - if item: - _itemsuivi_delete(cnx, itemsuivi_id) - Scolog.logdb(method="itemsuivi_suppress", etudid=item["etudid"], commit=True) - log(f"suppressed itemsuivi {itemsuivi_id}") - return ("", 204) - - -def itemsuivi_create(etudid, item_date=None, situation="", fmt=None): - """Creation d'un item""" - if not sco_permissions_check.can_edit_suivi(): - raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") - cnx = ndb.GetDBConnexion() - itemsuivi_id = _itemsuivi_create( - cnx, args={"etudid": etudid, "item_date": item_date, "situation": situation} - ) - Scolog.logdb(method="itemsuivi_create", etudid=etudid, commit=True) - log("created itemsuivi %s for %s" % (itemsuivi_id, etudid)) - item = itemsuivi_get(cnx, itemsuivi_id) - if fmt == "json": - return scu.sendJSON(item) - return item - - -def itemsuivi_set_date(itemsuivi_id, item_date): - """set item date - item_date is a string dd/mm/yyyy - """ - if not sco_permissions_check.can_edit_suivi(): - raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") - # log('itemsuivi_set_date %s : %s' % (itemsuivi_id, item_date)) - cnx = ndb.GetDBConnexion() - item = itemsuivi_get(cnx, itemsuivi_id) - item["item_date"] = item_date - _itemsuivi_edit(cnx, item) - return ("", 204) - - -def itemsuivi_set_situation(obj, value): - """set situation""" - if not sco_permissions_check.can_edit_suivi(): - raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") - itemsuivi_id = obj - situation = value.strip("-_ \t") - # log('itemsuivi_set_situation %s : %s' % (itemsuivi_id, situation)) - cnx = ndb.GetDBConnexion() - item = itemsuivi_get(cnx, itemsuivi_id) - item["situation"] = situation - _itemsuivi_edit(cnx, item) - return situation or scu.IT_SITUATION_MISSING_STR - - -def itemsuivi_list_etud(etudid, fmt=None): - """Liste des items pour cet étudiant, avec tags""" - cnx = ndb.GetDBConnexion() - items = _itemsuivi_list(cnx, {"etudid": etudid}) - for it in items: - it["tags"] = ", ".join(itemsuivi_tag_list(it["itemsuivi_id"])) - if fmt == "json": - return scu.sendJSON(items) - return items - - -def itemsuivi_tag_list(itemsuivi_id): - """les noms de tags associés à cet item""" - r = ndb.SimpleDictFetch( - """SELECT t.title - FROM itemsuivi_tags_assoc a, itemsuivi_tags t - WHERE a.tag_id = t.id - AND a.itemsuivi_id = %(itemsuivi_id)s - """, - {"itemsuivi_id": itemsuivi_id}, - ) - return [x["title"] for x in r] - - -def itemsuivi_tag_search(term): - """List all used tag names (for auto-completion)""" - # restrict charset to avoid injections - if not scu.ALPHANUM_EXP.match(term): - data = [] - else: - r = ndb.SimpleDictFetch( - "SELECT title FROM itemsuivi_tags WHERE title LIKE %(term)s AND dept_id=%(dept_id)s", - { - "term": term + "%", - "dept_id": g.scodoc_dept_id, - }, - ) - data = [x["title"] for x in r] - - return scu.sendJSON(data) - - -def itemsuivi_tag_set(itemsuivi_id="", taglist=None): - """taglist may either be: - a string with tag names separated by commas ("un;deux") - or a list of strings (["un", "deux"]) - """ - if not sco_permissions_check.can_edit_suivi(): - raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") - if not taglist: - taglist = [] - elif isinstance(taglist, str): - taglist = taglist.split(",") - taglist = [t.strip() for t in taglist] - # log('itemsuivi_tag_set: itemsuivi_id=%s taglist=%s' % (itemsuivi_id, taglist)) - # Sanity check: - cnx = ndb.GetDBConnexion() - _ = itemsuivi_get(cnx, itemsuivi_id) - - newtags = set(taglist) - oldtags = set(itemsuivi_tag_list(itemsuivi_id)) - to_del = oldtags - newtags - to_add = newtags - oldtags - - # should be atomic, but it's not. - for tagname in to_add: - t = ItemSuiviTag(tagname, object_id=itemsuivi_id) - for tagname in to_del: - t = ItemSuiviTag(tagname) - t.remove_tag_from_object(itemsuivi_id) - return "", http.HTTPStatus.NO_CONTENT diff --git a/app/scodoc/sco_tag_module.py b/app/scodoc/sco_tag_module.py index e5f6a5d88..bc5fd03cf 100644 --- a/app/scodoc/sco_tag_module.py +++ b/app/scodoc/sco_tag_module.py @@ -262,6 +262,7 @@ def module_tag_set(module_id="", taglist=None): return scu.json_error(404, "invalid tag") # TODO code à moderniser (+ revoir classe ScoTag, utiliser modèle) + # TODO Voir ItemSuiviTag et api etud_suivi # Sanity check: mod_dict = sco_edit_module.module_list(args={"module_id": module_id}) diff --git a/app/static/js/etud_debouche.js b/app/static/js/etud_debouche.js index e5a8f6510..a3d06d8b4 100644 --- a/app/static/js/etud_debouche.js +++ b/app/static/js/etud_debouche.js @@ -16,9 +16,8 @@ function display_itemsuivis(active) { .off("click") .click(function (e) { e.preventDefault(); - $.post(SCO_URL + "itemsuivi_create", { + $.post(`${SCO_URL}../api/etudiant/${etudid}/itemsuivi/create`, { etudid: etudid, - fmt: "json", }).done(item_insert_new); return false; @@ -26,13 +25,13 @@ function display_itemsuivis(active) { } // add existing items $.get( - SCO_URL + "itemsuivi_list_etud", - { etudid: etudid, fmt: "json" }, + `${SCO_URL}../api/etudiant/${etudid}/itemsuivis`, + { }, function (L) { for (var i in L) { item_insert( - L[i]["itemsuivi_id"], - L[i]["item_date"], + L[i]["id"], + L[i]["item_date_dmy"], L[i]["situation"], L[i]["tags"], readonly @@ -49,7 +48,7 @@ function display_itemsuivis(active) { } function item_insert_new(it) { - item_insert(it.itemsuivi_id, it.item_date, it.situation, "", false); + item_insert(it.id, it.item_date, it.situation, "", false); } function item_insert(itemsuivi_id, item_date, situation, tags, readonly) { @@ -78,35 +77,36 @@ function item_nodes(itemsuivi_id, item_date, situation, tags, readonly) { var h = sel_mois; // situation - h += - '
' + - situation + - "
"; + h += `
${situation}
`; // tags: h += - '
"; + `
+ +
`; var nodes = $($.parseHTML('
  • ' + h + "
  • ")); var dp = nodes.find(".itemsuividatepicker"); dp.blur(function (e) { var date = this.value; - // console.log('selected text: ' + date); - $.post(SCO_URL + "itemsuivi_set_date", { - item_date: date, - itemsuivi_id: itemsuivi_id, - }); + if (date) { + $.post(`${SCO_URL}../api/etudiant/itemsuivi/${itemsuivi_id}/set_date`, { + date_dmy: date, + }); + } }); dp.datepicker({ onSelect: function (date, instance) { - // console.log('selected: ' + date + 'for itemsuivi_id ' + itemsuivi_id); - $.post(SCO_URL + "itemsuivi_set_date", { - item_date: date, - itemsuivi_id: itemsuivi_id, - }); + if (date) { + $.post(`${SCO_URL}../api/etudiant/itemsuivi/${itemsuivi_id}/set_date`, { + date_dmy: date, + }); + } }, showOn: "button", buttonImage: "/ScoDoc/static/icons/calendar_img.png", @@ -129,7 +129,8 @@ function item_nodes(itemsuivi_id, item_date, situation, tags, readonly) { initialTags: "", placeholder: "Tags...", onChange: function (field, editor, tags) { - $.post("itemsuivi_tag_set", { + let itemsuivi_id = field.data("itemsuivi_id"); + $.post(`${SCO_URL}../api/etudiant/itemsuivi/${itemsuivi_id}/tag`, { itemsuivi_id: itemsuivi_id, taglist: tags.join(), }); @@ -160,9 +161,20 @@ function Date2DMY(date) { return day + "/" + month + "/" + year; } -function itemsuivi_suppress(itemsuivi_id) { - $.post(SCO_URL + "itemsuivi_suppress", { itemsuivi_id: itemsuivi_id }); - // Clear items and rebuild: - $("ul.listdebouches li.itemsuivi").remove(); - display_itemsuivis(0); +async function itemsuivi_suppress(itemsuivi_id) { + const deleteUrl = `${SCO_URL}../api/etudiant/itemsuivi/${itemsuivi_id}/delete`; + + try { + const response = await fetch(deleteUrl, { + method: 'POST' + }); + + if (response.ok) { + // Clear items and rebuild: + $("ul.listdebouches li.itemsuivi").remove(); + display_itemsuivis(0); + } + } catch (error) { + console.error('Error deleting itemsuivi:', error); + } } diff --git a/app/views/scolar.py b/app/views/scolar.py index 68bab7b4c..59cdba472 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -719,46 +719,6 @@ sco_publish( ) -# Debouche / devenir etudiant -sco_publish( - "/itemsuivi_suppress", - sco_debouche.itemsuivi_suppress, - Permission.EtudChangeAdr, - methods=["GET", "POST"], -) -sco_publish( - "/itemsuivi_create", - sco_debouche.itemsuivi_create, - Permission.EtudChangeAdr, - methods=["GET", "POST"], -) -sco_publish( - "/itemsuivi_set_date", - sco_debouche.itemsuivi_set_date, - Permission.EtudChangeAdr, - methods=["GET", "POST"], -) -sco_publish( - "/itemsuivi_set_situation", - sco_debouche.itemsuivi_set_situation, - Permission.EtudChangeAdr, - methods=["GET", "POST"], -) -sco_publish( - "/itemsuivi_list_etud", sco_debouche.itemsuivi_list_etud, Permission.ScoView -) -sco_publish("/itemsuivi_tag_list", sco_debouche.itemsuivi_tag_list, Permission.ScoView) -sco_publish( - "/itemsuivi_tag_search", sco_debouche.itemsuivi_tag_search, Permission.ScoView -) -sco_publish( - "/itemsuivi_tag_set", - sco_debouche.itemsuivi_tag_set, - Permission.EtudChangeAdr, - methods=["GET", "POST"], -) - - @bp.route("/doAddAnnotation", methods=["GET", "POST"]) @scodoc @permission_required(Permission.EtudAddAnnotations)