Feat: exam creation page
This commit is contained in:
parent
b737612adb
commit
e08e4a32a8
|
@ -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}"]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue