diff --git a/DB.drawio b/DB.drawio index 4acdbcd..ff2e47b 100644 --- a/DB.drawio +++ b/DB.drawio @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/advlabdb/models.py b/advlabdb/models.py index 2e62ff2..a697758 100644 --- a/advlabdb/models.py +++ b/advlabdb/models.py @@ -35,6 +35,7 @@ class PartStudent(db.Model): class Group(db.Model): id = db.Column(db.Integer, primary_key=True) number = db.Column(db.Integer, nullable=False) + part_id = db.Column(db.Integer, db.ForeignKey("part.id"), nullable=False) part_students = db.relationship("PartStudent", backref="group", lazy=True) group_experiments = db.relationship("GroupExperiment", backref="group", lazy=True) @@ -110,6 +111,7 @@ class Part(db.Model): semester_id = db.Column(db.Integer, db.ForeignKey("semester.id"), nullable=False) part_experiments = db.relationship("PartExperiment", backref="part", lazy=True) part_students = db.relationship("PartStudent", backref="part", lazy=True) + groups = db.relationship("Group", backref="part", lazy=True) class Semester(db.Model): diff --git a/advlabdb/routes.py b/advlabdb/routes.py index 3254936..95004d7 100644 --- a/advlabdb/routes.py +++ b/advlabdb/routes.py @@ -19,13 +19,13 @@ def students(): ["First name", "row.student.first_name"], ["Last name", "row.student.last_name"], ["Email", "row.student.email"], + ["GN", "row.group.number"], ["Bachelor thesis", "row.student.bachelor_thesis"], ["BT WG", "row.student.bachelor_thesis_work_group"], ["Note", "row.student.note"], - ["Parts", "[ps.part for ps in row.student.part_students]"], ["Final part mark", "row.final_part_mark"], - ["GN", "row.group.number"], - ["Experiemt marks", "row.experiment_marks"]] + ["Experiemt marks", "row.experiment_marks"], + ["Parts", "[ps.part for ps in row.student.part_students]"]] for part in parts: tablesLabels.append("Part " + part.label + ":") @@ -57,8 +57,24 @@ def assistants(): @app.route("/experiments") def experiments(): + semester = Semester.query.all()[-1] + parts = semester.parts + tables = [] + tablesLabels = [] + + headerAndDataList = [["Name", "row.experiment.name"], + ["Number", "row.number"], + ["Assistants", "row.assistants"], + ["Groups with this ex.", "[gEx.group.number for gEx in row.group_experiments]"]] + + for part in parts: + tablesLabels.append("Part " + part.label + ":") + tables.append(makeTable(headerAndDataList=headerAndDataList, + rows=part.part_experiments)) + page = "experiments" - return render_template(page + ".html", navbarItems=navbarItems(page)) + return render_template(page + ".html", navbarItems=navbarItems(page), + tables=tables, tablesLabels=tablesLabels) @app.route("/appointments") def appointments(): @@ -67,8 +83,25 @@ def appointments(): @app.route("/groups") def groups(): + semester = Semester.query.all()[-1] + parts = semester.parts + tables = [] + tablesLabels = [] + + headerAndDataList = [["Number", "row.number"], + ["Students", + "[ps.student.first_name + ' ' + ps.student.last_name for ps in row.part_students]"], + ["Experiments (appointments)", + "[str(gx.part_experiment.number) + ' (' + str([appointmentDate(a.date) for a in gx.appointments]) + ')' for gx in row.group_experiments]"]] + + for part in parts: + tablesLabels.append("Part " + part.label + ":") + tables.append(makeTable(headerAndDataList=headerAndDataList, + rows=part.groups)) + page = "groups" - return render_template(page + ".html", navbarItems=navbarItems(page)) + return render_template(page + ".html", navbarItems=navbarItems(page), + tables=tables, tablesLabels=tablesLabels) @app.route("/users") def users(): diff --git a/advlabdb/templates/experiments.html b/advlabdb/templates/experiments.html index 39e893d..f87c4aa 100644 --- a/advlabdb/templates/experiments.html +++ b/advlabdb/templates/experiments.html @@ -1,3 +1,11 @@ {% extends "layout.html" %} {% block content %} + +{% for table in tables %} +

{{tablesLabels[loop.index0]}}

+{{table|safe}} +{% else %} +No parts in this semster yet! +{% endfor %} + {% endblock content %} diff --git a/advlabdb/templates/groups.html b/advlabdb/templates/groups.html index 39e893d..f87c4aa 100644 --- a/advlabdb/templates/groups.html +++ b/advlabdb/templates/groups.html @@ -1,3 +1,11 @@ {% extends "layout.html" %} {% block content %} + +{% for table in tables %} +

{{tablesLabels[loop.index0]}}

+{{table|safe}} +{% else %} +No parts in this semster yet! +{% endfor %} + {% endblock content %} diff --git a/advlabdb/templates/layout.html b/advlabdb/templates/layout.html index ab067e5..b27dfe3 100644 --- a/advlabdb/templates/layout.html +++ b/advlabdb/templates/layout.html @@ -6,10 +6,11 @@ - + + + - - + {% if title %} {{title}} @@ -40,14 +41,14 @@ - + - + - - - - - + + + + + diff --git a/advlabdb/utils.py b/advlabdb/utils.py index ed1fd6e..ce339c4 100644 --- a/advlabdb/utils.py +++ b/advlabdb/utils.py @@ -11,7 +11,12 @@ def navbarItems(activePage): def makeTable(headerAndDataList, rows): def cellString(cell): - return str(cell).replace("<", " ").replace(">", " ") + cell = str(cell) + excludeChars = """<>"'[]""" + for c in excludeChars: + if c in cell: + cell = cell.replace(c, "") + return cell def td(cell): return "" + cellString(cell) + "" @@ -50,3 +55,6 @@ data-export-types="['json', 'xml', 'csv', 'txt', 'sql', 'pdf']">

''' return table + +def appointmentDate(date): + return date.strftime("%a %d.%m.%Y") diff --git a/testDB.py b/testDB.py index e78ef56..8402952 100644 --- a/testDB.py +++ b/testDB.py @@ -23,8 +23,8 @@ partb2 = Part(label="B/2", semester=sem) db.session.add(parta1) db.session.add(partb2) -g1 = Group(number=1) -g2 = Group(number=2) +g1 = Group(number=1, part=parta1) +g2 = Group(number=2, part=partb2) db.session.add(g1) db.session.add(g2)