Feat: exam creation page

This commit is contained in:
Bertrand Benjamin 2021-01-22 11:13:35 +01:00
parent b737612adb
commit e08e4a32a8
2 changed files with 103 additions and 31 deletions

View File

@ -5,13 +5,28 @@ import dash
import dash_html_components as html import dash_html_components as html
import dash_core_components as dcc import dash_core_components as dcc
import dash_table import dash_table
from datetime import date from datetime import date, datetime
import uuid import uuid
import pandas as pd import pandas as pd
import yaml
from ...scripts.getconfig import config from ...scripts.getconfig import config
from ...config import NO_ST_COLUMNS from ...config import NO_ST_COLUMNS
from ..app import app 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(): def get_current_year_limit():
@ -35,7 +50,8 @@ layout = html.Div(
html.Header( html.Header(
children=[ children=[
html.H1("Création d'une évaluation"), 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( html.Main(
@ -118,7 +134,7 @@ layout = html.Div(
def add_exercise(n_clicks, children): def add_exercise(n_clicks, children):
if n_clicks is None: if n_clicks is None:
return children 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)) element_table = element_table.append(pd.Series(name=0))
new_exercise = html.Div( new_exercise = html.Div(
children=[ children=[
@ -127,12 +143,13 @@ def add_exercise(n_clicks, children):
dcc.Input( dcc.Input(
id={"type": "exercice", "index": str(n_clicks)}, id={"type": "exercice", "index": str(n_clicks)},
type="text", type="text",
value=f"Exercice {len(children)+1}",
placeholder="Nom de l'exercice", placeholder="Nom de l'exercice",
className="exercise-name", className="exercise-name",
), ),
html.Button( html.Button(
"X", "X",
id={"type": "exercice", "index": str(n_clicks)}, id={"type": "rm_exercice", "index": str(n_clicks)},
className="delete-exercise", className="delete-exercise",
), ),
], ],
@ -140,18 +157,7 @@ def add_exercise(n_clicks, children):
), ),
dash_table.DataTable( dash_table.DataTable(
id={"type": "elements", "index": str(n_clicks)}, id={"type": "elements", "index": str(n_clicks)},
columns=[ columns=QUESTION_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"},
],
data=element_table.to_dict("records"), data=element_table.to_dict("records"),
editable=True, editable=True,
row_deletable=True, row_deletable=True,
@ -192,6 +198,7 @@ def add_exercise(n_clicks, children):
{"type": "elements", "index": dash.dependencies.MATCH}, "data" {"type": "elements", "index": dash.dependencies.MATCH}, "data"
), ),
], ],
prevent_initial_call=True,
) )
def add_element(n_clicks, elements): def add_element(n_clicks, elements):
if n_clicks is None or n_clicks < len(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") 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( @app.callback(
dash.dependencies.Output("summary", "children"), dash.dependencies.Output("exam_store", "data"),
[ [
dash.dependencies.Input("tribe", "value"), dash.dependencies.Input("tribe", "value"),
dash.dependencies.Input("exam_name", "value"), dash.dependencies.Input("exam_name", "value"),
@ -212,13 +238,32 @@ def add_element(n_clicks, elements):
dash.dependencies.Input( dash.dependencies.Input(
{"type": "exercice", "index": dash.dependencies.ALL}, "value" {"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): def store_exam(tribe, exam_name, date, term, exercices, elements, elements_id):
return html.Section( exam = Exam(exam_name, tribe, date, term)
children=[ for (i, name) in enumerate(exercices):
html.H1(f"{exam_name} pour les {tribe}"), ex_elements_id = [el for el in elements_id if el["index"] == str(i + 1)][0]
html.P(f"Fait le {date} (Trimestre {term})"), index = elements_id.index(ex_elements_id)
] ex_elements = elements[index]
+ [html.P(f"{value}") for (i, value) in enumerate(exercices)] 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}"]

View File

@ -4,22 +4,36 @@
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from prompt_toolkit import HTML from prompt_toolkit import HTML
from ..config import NO_ST_COLUMNS
import pandas as pd
import yaml import yaml
from .getconfig import config 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: class Exam:
def __init__(self, name, tribename, date, term, **kwrds): def __init__(self, name, tribename, date, term, **kwrds):
self._name = name self._name = name
self._tribename = tribename self._tribename = tribename
try:
self._date = datetime.strptime(date, "%y%m%d") self._date = try_parsing_date(date)
except:
self._date = date
self._term = term self._term = term
try:
kwrds["exercices"]
except KeyError:
self._exercises = {} self._exercises = {}
else:
self._exercises = kwrds["exercices"]
@property @property
def name(self): def name(self):
@ -125,8 +139,21 @@ class Exam:
def display(self, name): def display(self, name):
pass pass
def write(self): def write_yaml(self):
print(f"Sauvegarde temporaire dans {self.path('.yml')}") print(f"Sauvegarde temporaire dans {self.path('.yml')}")
self.tribe_path.mkdir(exist_ok=True) self.tribe_path.mkdir(exist_ok=True)
with open(self.path(".yml"), "w") as f: with open(self.path(".yml"), "w") as f:
f.write(yaml.dump(self.to_dict())) 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)