diff --git a/recopytex/dashboard/create_exam/app.py b/recopytex/dashboard/create_exam/app.py index bc42366..3a93744 100644 --- a/recopytex/dashboard/create_exam/app.py +++ b/recopytex/dashboard/create_exam/app.py @@ -5,13 +5,28 @@ import dash import dash_html_components as html import dash_core_components as dcc import dash_table -from datetime import date +from datetime import date, datetime import uuid import pandas as pd +import yaml from ...scripts.getconfig import config from ...config import NO_ST_COLUMNS from ..app import app +from ...scripts.exam import Exam + +QUESTION_COLUMNS = [ + {"id": "id", "name": "Question"}, + { + "id": "competence", + "name": "Competence", + "presentation": "dropdown", + }, + {"id": "theme", "name": "Domaine"}, + {"id": "comment", "name": "Commentaire"}, + {"id": "score_rate", "name": "Bareme"}, + {"id": "is_leveled", "name": "Est_nivele"}, +] def get_current_year_limit(): @@ -35,7 +50,8 @@ layout = html.Div( html.Header( children=[ html.H1("Création d'une évaluation"), - html.P("Dernière sauvegarde", id="lastsave"), + html.P("Pas encore de sauvegarde", id="is-saved"), + html.Button("Enregistrer dans csv", id="save-csv"), ], ), html.Main( @@ -118,7 +134,7 @@ layout = html.Div( def add_exercise(n_clicks, children): if n_clicks is None: return children - element_table = pd.DataFrame(columns=NO_ST_COLUMNS) + element_table = pd.DataFrame(columns=[c["id"] for c in QUESTION_COLUMNS]) element_table = element_table.append(pd.Series(name=0)) new_exercise = html.Div( children=[ @@ -127,12 +143,13 @@ def add_exercise(n_clicks, children): dcc.Input( id={"type": "exercice", "index": str(n_clicks)}, type="text", + value=f"Exercice {len(children)+1}", placeholder="Nom de l'exercice", className="exercise-name", ), html.Button( "X", - id={"type": "exercice", "index": str(n_clicks)}, + id={"type": "rm_exercice", "index": str(n_clicks)}, className="delete-exercise", ), ], @@ -140,18 +157,7 @@ def add_exercise(n_clicks, children): ), dash_table.DataTable( id={"type": "elements", "index": str(n_clicks)}, - columns=[ - {"id": "Question", "name": "Question"}, - { - "id": "Competence", - "name": "Competence", - "presentation": "dropdown", - }, - {"id": "Domaine", "name": "Domaine"}, - {"id": "Commentaire", "name": "Commentaire"}, - {"id": "Bareme", "name": "Bareme"}, - {"id": "Est_nivele", "name": "Est_nivele"}, - ], + columns=QUESTION_COLUMNS, data=element_table.to_dict("records"), editable=True, row_deletable=True, @@ -192,6 +198,7 @@ def add_exercise(n_clicks, children): {"type": "elements", "index": dash.dependencies.MATCH}, "data" ), ], + prevent_initial_call=True, ) def add_element(n_clicks, elements): if n_clicks is None or n_clicks < len(elements): @@ -202,8 +209,27 @@ def add_element(n_clicks, elements): return df.to_dict("records") +def exam_generalities(tribe, exam_name, date, term, exercices=[], elements=[]): + return [ + html.H1(f"{exam_name} pour les {tribe}"), + html.P(f"Fait le {date} (Trimestre {term})"), + ] + + +def exercise_summary(identifier, name, elements=[]): + df = pd.DataFrame.from_records(elements) + return html.Div( + [ + html.H2(name), + dash_table.DataTable( + columns=[{"id": c, "name": c} for c in df], data=elements + ), + ] + ) + + @app.callback( - dash.dependencies.Output("summary", "children"), + dash.dependencies.Output("exam_store", "data"), [ dash.dependencies.Input("tribe", "value"), dash.dependencies.Input("exam_name", "value"), @@ -212,13 +238,32 @@ def add_element(n_clicks, elements): dash.dependencies.Input( {"type": "exercice", "index": dash.dependencies.ALL}, "value" ), + dash.dependencies.Input( + {"type": "elements", "index": dash.dependencies.ALL}, "data" + ), ], + dash.dependencies.State({"type": "elements", "index": dash.dependencies.ALL}, "id"), ) -def display_summary(tribe, exam_name, date, term, exercices): - return html.Section( - children=[ - html.H1(f"{exam_name} pour les {tribe}"), - html.P(f"Fait le {date} (Trimestre {term})"), - ] - + [html.P(f"{value}") for (i, value) in enumerate(exercices)] - ) +def store_exam(tribe, exam_name, date, term, exercices, elements, elements_id): + exam = Exam(exam_name, tribe, date, term) + for (i, name) in enumerate(exercices): + ex_elements_id = [el for el in elements_id if el["index"] == str(i + 1)][0] + index = elements_id.index(ex_elements_id) + ex_elements = elements[index] + exam.add_exercise(name, ex_elements) + + print(yaml.dump(exam.to_dict())) + return exam.to_dict() + + +@app.callback( + dash.dependencies.Output("is-saved", "children"), + dash.dependencies.Input("save-csv", "n_clicks"), + dash.dependencies.State("exam_store", "data"), + prevent_initial_call=True, +) +def save_to_csv(n_clicks, data): + exam = Exam(**data) + csv = exam.path(".csv") + exam.write_csv() + return [f"Dernière sauvegarde {datetime.today()} dans {csv}"] diff --git a/recopytex/scripts/exam.py b/recopytex/scripts/exam.py index 1fcd0a3..212683f 100644 --- a/recopytex/scripts/exam.py +++ b/recopytex/scripts/exam.py @@ -4,22 +4,36 @@ from datetime import datetime from pathlib import Path from prompt_toolkit import HTML +from ..config import NO_ST_COLUMNS +import pandas as pd import yaml from .getconfig import config +def try_parsing_date(text, formats=["%Y-%m-%d", "%Y.%m.%d", "%Y/%m/%d"]): + for fmt in formats: + try: + return datetime.strptime(text[:10], fmt) + except ValueError: + pass + raise ValueError("no valid date format found") + + class Exam: def __init__(self, name, tribename, date, term, **kwrds): self._name = name self._tribename = tribename - try: - self._date = datetime.strptime(date, "%y%m%d") - except: - self._date = date + + self._date = try_parsing_date(date) self._term = term - self._exercises = {} + try: + kwrds["exercices"] + except KeyError: + self._exercises = {} + else: + self._exercises = kwrds["exercices"] @property def name(self): @@ -125,8 +139,21 @@ class Exam: def display(self, name): pass - def write(self): + def write_yaml(self): print(f"Sauvegarde temporaire dans {self.path('.yml')}") self.tribe_path.mkdir(exist_ok=True) with open(self.path(".yml"), "w") as f: f.write(yaml.dump(self.to_dict())) + + def write_csv(self): + rows = self.to_row() + + base_df = pd.DataFrame.from_dict(rows)[NO_ST_COLUMNS.keys()] + base_df.rename(columns=NO_ST_COLUMNS, inplace=True) + + students = pd.read_csv(self.tribe_student_path)["Nom"] + for student in students: + base_df[student] = "" + + self.tribe_path.mkdir(exist_ok=True) + base_df.to_csv(self.path(".csv"), index=False)