From ad7b48e110c67aa57486d8eddecbea75011de61d Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Mon, 15 Apr 2024 17:53:02 +0200 Subject: [PATCH] =?UTF-8?q?Calendrier=20=C3=A9valuations:=20fix=20#875?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_cal.py | 256 ++++++------------ app/scodoc/sco_evaluations.py | 53 ++-- .../assiduites/pages/calendrier_assi_etud.j2 | 4 +- sco_version.py | 2 +- 4 files changed, 102 insertions(+), 213 deletions(-) diff --git a/app/scodoc/sco_cal.py b/app/scodoc/sco_cal.py index abb83740..ef88b70c 100644 --- a/app/scodoc/sco_cal.py +++ b/app/scodoc/sco_cal.py @@ -230,41 +230,41 @@ def next_iso_day(date): def YearTable( year, - events=[], + events_by_day: dict[str, list[dict]], firstmonth=9, lastmonth=7, - halfday=0, dayattributes="", - pad_width=8, ): + # Code simplifié en 2024: utilisé seulement pour calendrier évaluations """Generate a calendar table events = list of tuples (date, text, color, href [,halfday]) where date is a string in ISO format (yyyy-mm-dd) halfday is boolean (true: morning, false: afternoon) text = text to put in calendar (must be short, 1-5 cars) (optional) - if halfday, generate 2 cells per day (morning, afternoon) """ T = [ - '' + """
""" ] T.append("") month = firstmonth - while 1: + while True: T.append('") + T.append( + """ +
') - T.append(MonthTableHead(month)) + T.append(_month_table_head(month)) T.append( - MonthTableBody( + _month_table_body( month, year, - events, - halfday, + events_by_day, dayattributes, is_work_saturday(), - pad_width=pad_width, ) ) - T.append(MonthTableTail()) - T.append("
+ """ + ) if month == lastmonth: break month = month + 1 @@ -322,29 +322,32 @@ WEEKDAYCOLOR = GRAY1 WEEKENDCOLOR = GREEN3 -def MonthTableHead(month): +def _month_table_head(month): color = WHITE - return """ - \n""" % ( - color, - MONTHNAMES_ABREV[month - 1], - ) + return f"""
%s
+ + + \n""" -def MonthTableTail(): - return "
{MONTHNAMES_ABREV[month - 1]}
\n" - - -def MonthTableBody( - month, year, events=[], halfday=0, trattributes="", work_saturday=False, pad_width=8 -): +def _month_table_body( + month, + year, + events_by_day: dict[str, list[dict]], + trattributes="", + work_saturday=False, +) -> str: + """ + events : [event] + event = [ yyyy-mm-dd, legend, href, color, descr ] XXX + """ firstday, nbdays = calendar.monthrange(year, month) localtime = time.localtime() current_weeknum = time.strftime("%U", localtime) current_year = localtime[0] - T = [] + rows = [] # cherche date du lundi de la 1ere semaine de ce mois - monday = ddmmyyyy("1/%d/%d" % (month, year)) + monday = ddmmyyyy(f"1/{month}/{year}") while monday.weekday != 0: monday = monday.prev() @@ -353,158 +356,51 @@ def MonthTableBody( else: weekend = ("S", "D") - if not halfday: - for d in range(1, nbdays + 1): - weeknum = time.strftime( - "%U", time.strptime("%d/%d/%d" % (d, month, year), scu.DATE_FMT) - ) - day = DAYNAMES_ABREV[(firstday + d - 1) % 7] - if day in weekend: - bgcolor = WEEKENDCOLOR - weekclass = "wkend" - attrs = "" - else: - bgcolor = WEEKDAYCOLOR - weekclass = "wk" + str(monday).replace("/", "_") - attrs = trattributes - color = None - legend = "" - href = "" - descr = "" - # event this day ? - # each event is a tuple (date, text, color, href) - # where date is a string in ISO format (yyyy-mm-dd) - for ev in events: - ev_year = int(ev[0][:4]) - ev_month = int(ev[0][5:7]) - ev_day = int(ev[0][8:10]) - if year == ev_year and month == ev_month and ev_day == d: - if ev[1]: - legend = ev[1] - if ev[2]: - color = ev[2] - if ev[3]: - href = ev[3] - if len(ev) > 4 and ev[4]: - descr = ev[4] - # - cc = [] - if color is not None: - cc.append('' % color) - else: - cc.append('') - + for d in range(1, nbdays + 1): + weeknum = time.strftime( + "%U", time.strptime("%d/%d/%d" % (d, month, year), scu.DATE_FMT) + ) + day = DAYNAMES_ABREV[(firstday + d - 1) % 7] + if day in weekend: + bgcolor = WEEKENDCOLOR + weekclass = "wkend" + attrs = "" + else: + bgcolor = WEEKDAYCOLOR + weekclass = "wk" + str(monday).replace("/", "_") + attrs = trattributes + # events this day ? + events = events_by_day.get(f"{year}-{month:02}-{d:02}", []) + color = None + ev_txts = [] + for ev in events: + color = ev.get("color") + href = ev.get("href", "") + description = ev.get("description", "") if href: - href = 'href="%s"' % href - if descr: - descr = 'title="%s"' % html.escape(descr, quote=True) - if href or descr: - cc.append("" % (href, descr)) - - if legend or d == 1: - if pad_width is not None: - n = pad_width - len(legend) # pad to 8 cars - if n > 0: - legend = ( - " " * (n // 2) + legend + " " * ((n + 1) // 2) - ) + href = f'href="{href}"' + if description: + description = f"""title="{html.escape(description, quote=True)}" """ + if href or description: + ev_txts.append(f"""{ev.get("title", "")}""") else: - legend = " " # empty cell - cc.append(legend) - if href or descr: - cc.append("") - cc.append("") - cell = "".join(cc) - if day == "D": - monday = monday.next_day(7) - if ( - weeknum == current_weeknum - and current_year == year - and weekclass != "wkend" - ): - weekclass += " currentweek" - T.append( - '%d%s%s' - % (bgcolor, weekclass, attrs, d, day, cell) - ) - else: - # Calendar with 2 cells / day - for d in range(1, nbdays + 1): - weeknum = time.strftime( - "%U", time.strptime("%d/%d/%d" % (d, month, year), scu.DATE_FMT) - ) - day = DAYNAMES_ABREV[(firstday + d - 1) % 7] - if day in weekend: - bgcolor = WEEKENDCOLOR - weekclass = "wkend" - attrs = "" - else: - bgcolor = WEEKDAYCOLOR - weekclass = "wk" + str(monday).replace("/", "_") - attrs = trattributes - if ( - weeknum == current_weeknum - and current_year == year - and weekclass != "wkend" - ): - weeknum += " currentweek" + ev_txts.append(ev.get("title", " ")) + # + cc = [] + if color is not None: + cc.append(f'') + else: + cc.append('') - if day == "D": - monday = monday.next_day(7) - T.append( - '%d%s' - % (bgcolor, weekclass, attrs, d, day) - ) - cc = [] - for morning in (True, False): - color = None - legend = "" - href = "" - descr = "" - for ev in events: - ev_year = int(ev[0][:4]) - ev_month = int(ev[0][5:7]) - ev_day = int(ev[0][8:10]) - if ev[4] is not None: - ev_half = int(ev[4]) - else: - ev_half = 0 - if ( - year == ev_year - and month == ev_month - and ev_day == d - and morning == ev_half - ): - if ev[1]: - legend = ev[1] - if ev[2]: - color = ev[2] - if ev[3]: - href = ev[3] - if len(ev) > 5 and ev[5]: - descr = ev[5] - # - if color is not None: - cc.append('' % (color)) - else: - cc.append('') - if href: - href = 'href="%s"' % href - if descr: - descr = 'title="%s"' % html.escape(descr, quote=True) - if href or descr: - cc.append("" % (href, descr)) - if legend or d == 1: - n = 3 - len(legend) # pad to 3 cars - if n > 0: - legend = ( - " " * (n // 2) + legend + " " * ((n + 1) // 2) - ) - else: - legend = "   " # empty cell - cc.append(legend) - if href or descr: - cc.append("") - cc.append("\n") - T.append("".join(cc) + "") - return "\n".join(T) + cc.append(f"{', '.join(ev_txts)}") + cells = "".join(cc) + if day == "D": + monday = monday.next_day(7) + if weeknum == current_weeknum and current_year == year and weekclass != "wkend": + weekclass += " currentweek" + rows.append( + f""" + {d}{day}{cells}""" + ) + + return "\n".join(rows) diff --git a/app/scodoc/sco_evaluations.py b/app/scodoc/sco_evaluations.py index 0b6b0c62..ef2e8526 100644 --- a/app/scodoc/sco_evaluations.py +++ b/app/scodoc/sco_evaluations.py @@ -360,6 +360,7 @@ def do_evaluation_etat_in_mod(nt, modimpl: ModuleImpl): return etat +# View def formsemestre_evaluations_cal(formsemestre_id): """Page avec calendrier de toutes les evaluations de ce semestre""" formsemestre = FormSemestre.get_formsemestre(formsemestre_id) @@ -373,22 +374,17 @@ def formsemestre_evaluations_cal(formsemestre_id): color_futur = "#70E0FF" year = formsemestre.annee_scolaire() - events = {} # (day, halfday) : event + events_by_day = collections.defaultdict(list) # date_iso : event for e in evaluations: if e.date_debut is None: continue # éval. sans date - txt = e.moduleimpl.module.code or e.moduleimpl.module.abbrev or "éval." if e.date_debut == e.date_fin: - heure_debut_txt, heure_fin_txt = "?", "?" + heure_debut_txt, heure_fin_txt = "", "" else: heure_debut_txt = ( - e.date_debut.strftime(scu.TIME_FMT) if e.date_debut else "?" + e.date_debut.strftime(scu.TIME_FMT) if e.date_debut else "" ) - heure_fin_txt = e.date_fin.strftime(scu.TIME_FMT) if e.date_fin else "?" - - description = f"""{ - e.moduleimpl.module.titre - }, de {heure_debut_txt} à {heure_fin_txt}""" + heure_fin_txt = e.date_fin.strftime(scu.TIME_FMT) if e.date_fin else "" # Etat (notes completes) de l'évaluation: modimpl_result = nt.modimpls_results[e.moduleimpl.id] @@ -398,28 +394,27 @@ def formsemestre_evaluations_cal(formsemestre_id): color = color_incomplete if e.date_debut > datetime.datetime.now(scu.TIME_ZONE): color = color_futur - href = url_for( - "notes.moduleimpl_status", - scodoc_dept=g.scodoc_dept, - moduleimpl_id=e.moduleimpl_id, - ) day = e.date_debut.date().isoformat() # yyyy-mm-dd - event = events.get(day) - if not event: - events[day] = [day, txt, color, href, description, e.moduleimpl] - else: - if event[-1].id != e.moduleimpl.id: - # plusieurs evals de modules differents a la meme date - event[1] += ", " + txt - event[4] += ", " + description - if color == color_incomplete: - event[2] = color_incomplete - if color == color_futur: - event[2] = color_futur + event = { + "color": color, + "date_iso": day, + "title": e.moduleimpl.module.code or e.moduleimpl.module.abbrev or "éval.", + "description": f"""{e.description or e.moduleimpl.module.titre_str()}""" + + ( + f""" de {heure_debut_txt} à {heure_fin_txt}""" + if heure_debut_txt + else "" + ), + "href": url_for( + "notes.moduleimpl_status", + scodoc_dept=g.scodoc_dept, + moduleimpl_id=e.moduleimpl_id, + ), + "modimpl": e.moduleimpl, + } + events_by_day[day].append(event) - cal_html = sco_cal.YearTable( - year, events=list(events.values()), halfday=False, pad_width=None - ) + cal_html = sco_cal.YearTable(year, events_by_day=events_by_day) return f""" { diff --git a/app/templates/assiduites/pages/calendrier_assi_etud.j2 b/app/templates/assiduites/pages/calendrier_assi_etud.j2 index 99fa059b..3c3de3a4 100644 --- a/app/templates/assiduites/pages/calendrier_assi_etud.j2 +++ b/app/templates/assiduites/pages/calendrier_assi_etud.j2 @@ -51,8 +51,6 @@ Calendrier de l'assiduité
- Assiduité du -
{{jour.get_date()}} {{jour.generate_minitimeline() | safe}}
@@ -158,7 +156,7 @@ Calendrier de l'assiduité .calendrier { display: flex; - justify-content: start; + justify-content: center; overflow-x: scroll; border: 1px solid #444; border-radius: 12px; diff --git a/sco_version.py b/sco_version.py index d45b5339..57654dde 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.6.962" +SCOVERSION = "9.6.963" SCONAME = "ScoDoc"