mirror of
https://codeberg.org/Mo8it/AdvLabDB.git
synced 2024-12-20 23:41:20 +00:00
Apply changes from the database
This commit is contained in:
parent
bb1b6a86b2
commit
8178c72fe2
6 changed files with 113 additions and 125 deletions
|
@ -27,9 +27,9 @@ from advlabdb.models import (
|
|||
Semester,
|
||||
Student,
|
||||
User,
|
||||
Program,
|
||||
)
|
||||
from advlabdb.utils import (
|
||||
partFromLabelInUserActiveSemester,
|
||||
randomPassword,
|
||||
setUserActiveSemester,
|
||||
userActiveSemester,
|
||||
|
@ -100,12 +100,12 @@ class SemesterView(SecureModelView):
|
|||
can_delete = False
|
||||
can_view_details = True
|
||||
|
||||
column_list = ["label", "parts"]
|
||||
column_details_list = column_list + ["active_users"]
|
||||
form_columns = ["semester_label", "year", "transfer_parts", "transfer_assistants"]
|
||||
column_list = ["label", "number", "parts"]
|
||||
column_details_list = column_list + ["active_users", "groups"]
|
||||
form_columns = ["label", "year", "transfer_parts", "transfer_assistants"]
|
||||
|
||||
form_extra_fields = {
|
||||
"semester_label": RadioField("Semester", choices=["WS", "SS"], validators=[DataRequired()]),
|
||||
"label": RadioField("Semester", choices=["WS", "SS"], validators=[DataRequired()]),
|
||||
"year": TextField("Year", validators=[DataRequired()]),
|
||||
"transfer_parts": BooleanField(
|
||||
"Transfer parts",
|
||||
|
@ -121,7 +121,7 @@ class SemesterView(SecureModelView):
|
|||
|
||||
def create_model(self, form):
|
||||
try:
|
||||
model = Semester(label=form.semester_label.data + form.year.data)
|
||||
model = Semester(label=form.label.data, year=form.year.data)
|
||||
|
||||
self.session.add(model)
|
||||
self.on_model_change(form, model, True)
|
||||
|
@ -137,7 +137,7 @@ class SemesterView(SecureModelView):
|
|||
def after_model_change(self, form, model, is_created):
|
||||
admin.add_link(
|
||||
MenuLink(
|
||||
name=model.label,
|
||||
name=model.repr(),
|
||||
url=url_for("set_semester") + "?semester_id=" + str(model.id),
|
||||
category="Active semester",
|
||||
)
|
||||
|
@ -174,8 +174,8 @@ class SemesterView(SecureModelView):
|
|||
|
||||
class PartView(SecureModelView):
|
||||
can_view_details = True
|
||||
column_details_list = ["label", "semester", "part_students", "groups"]
|
||||
form_columns = ["label", "semester"]
|
||||
column_details_list = ["program", "number", "semester", "part_students"]
|
||||
form_columns = ["program", "number", "semester"]
|
||||
|
||||
def queryFilter(self):
|
||||
return Part.semester == userActiveSemester()
|
||||
|
@ -212,7 +212,7 @@ def partQueryFactory():
|
|||
|
||||
|
||||
def groupQueryFactory():
|
||||
return Group.query.filter(Group.part_id.in_([part.id for part in userActiveSemester().parts]))
|
||||
return Group.query.filter(Group.semester == userActiveSemester())
|
||||
|
||||
|
||||
markChoices = [(-1, "-")] + list(zip(range(16)[::-1], range(16)[::-1]))
|
||||
|
@ -261,8 +261,7 @@ class PartStudentView(SecureModelView):
|
|||
return form(get_form_data(), obj=obj)
|
||||
|
||||
def on_model_change(self, form, model, is_created):
|
||||
if model.group and model.part != model.group.part:
|
||||
raise ModelViewException("Student's part and group's part do not match!")
|
||||
PartStudent.check(model.group, model.group)
|
||||
|
||||
def update_model(self, form, model):
|
||||
if form.final_part_mark.data == -1:
|
||||
|
@ -277,29 +276,21 @@ def partStudentsQueryFactory():
|
|||
|
||||
class GroupView(SecureModelView):
|
||||
class CreateForm(Form):
|
||||
part = QuerySelectField(
|
||||
"Part",
|
||||
query_factory=partQueryFactory,
|
||||
validators=[DataRequired()],
|
||||
allow_blank=True,
|
||||
blank_text="-",
|
||||
part_students = QuerySelectMultipleField(
|
||||
"Part Students", query_factory=partStudentsQueryFactory, validators=[DataRequired()]
|
||||
)
|
||||
part_students = QuerySelectMultipleField("Part Students", query_factory=partStudentsQueryFactory)
|
||||
|
||||
class EditForm(CreateForm):
|
||||
part = None
|
||||
form = CreateForm
|
||||
|
||||
form = EditForm
|
||||
|
||||
column_list = ["number", "part", "part_students", "group_experiments"]
|
||||
column_filters = ["number", "part"]
|
||||
column_list = ["number", "semester", "program", "part_students", "group_experiments"]
|
||||
column_filters = ["number", "semester", "program"]
|
||||
|
||||
def queryFilter(self):
|
||||
return Group.part_id.in_([part.id for part in userActiveSemester().parts])
|
||||
return Group.semester == userActiveSemester()
|
||||
|
||||
def create_model(self, form):
|
||||
try:
|
||||
model = Group.customInit(form.part.data, form.part_students.data)
|
||||
model = Group.customInit(form.part_students.data)
|
||||
|
||||
self.session.add(model)
|
||||
self.on_model_change(form, model, True)
|
||||
|
@ -313,19 +304,15 @@ class GroupView(SecureModelView):
|
|||
return model
|
||||
|
||||
def update_model(self, form, model):
|
||||
Group.checkPartStudents(form.part_students.data)
|
||||
Group.check(form.part_students.data, model.program)
|
||||
|
||||
return super().update_model(form, model)
|
||||
|
||||
def create_form(self, obj=None):
|
||||
form = self.CreateForm
|
||||
return form(get_form_data(), obj=obj)
|
||||
|
||||
|
||||
class ExperimentView(SecureModelView):
|
||||
can_view_details = True
|
||||
column_filters = ["active"]
|
||||
column_list = ["label", "title", "active"]
|
||||
column_list = ["number", "program", "title", "active"]
|
||||
column_details_list = column_list + [
|
||||
"desciption",
|
||||
"wiki_link",
|
||||
|
@ -420,10 +407,7 @@ class GroupExperimentView(SecureModelView):
|
|||
|
||||
def queryFilter(self):
|
||||
return GroupExperiment.group_id.in_(
|
||||
[
|
||||
group.id
|
||||
for group in Group.query.filter(Group.part_id.in_([part.id for part in userActiveSemester().parts]))
|
||||
]
|
||||
[group.id for group in Group.query.filter(Group.semester == userActiveSemester())]
|
||||
)
|
||||
|
||||
def create_model(self, form):
|
||||
|
@ -617,6 +601,11 @@ class ExperimentMarkView(SecureModelView):
|
|||
self.session.rollback()
|
||||
|
||||
|
||||
class ProgramView(SecureModelView):
|
||||
column_list = ["label"]
|
||||
column_details_list = column_list + ["parts", "experiments", "groups"]
|
||||
|
||||
|
||||
admin.add_view(StudentView(Student, db.session))
|
||||
admin.add_view(PartStudentView(PartStudent, db.session))
|
||||
admin.add_view(GroupView(Group, db.session))
|
||||
|
@ -626,6 +615,7 @@ admin.add_view(ExperimentMarkView(ExperimentMark, db.session))
|
|||
admin.add_view(ExperimentView(Experiment, db.session))
|
||||
admin.add_view(SemesterExperimentView(SemesterExperiment, db.session))
|
||||
admin.add_view(AssistantView(Assistant, db.session))
|
||||
admin.add_view(ProgramView(Program, db.session))
|
||||
admin.add_view(PartView(Part, db.session))
|
||||
admin.add_view(SemesterView(Semester, db.session))
|
||||
admin.add_view(UserView(User, db.session))
|
||||
|
@ -636,7 +626,7 @@ with app.app_context():
|
|||
for semester in semesters:
|
||||
admin.add_link(
|
||||
MenuLink(
|
||||
name=semester.label,
|
||||
name=semester.repr(),
|
||||
url=url_for("set_semester") + "?semester_id=" + str(semester.id),
|
||||
category="Active semester",
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends "admin/model/create.html" %}
|
||||
|
||||
{% block body %}
|
||||
User's active semester: {{userActiveSemester().label}}
|
||||
User's active semester: {{userActiveSemester().repr()}}
|
||||
{{super()}}
|
||||
{% endblock %}
|
|
@ -1,6 +1,6 @@
|
|||
{% extends "admin/model/edit.html" %}
|
||||
|
||||
{% block body %}
|
||||
User's active semester: {{userActiveSemester().label}}
|
||||
User's active semester: {{userActiveSemester().repr()}}
|
||||
{{super()}}
|
||||
{% endblock %}
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/index.html" %}
|
||||
|
||||
{% block body %}
|
||||
User's active semester: {{userActiveSemester(flashWarning=True).label}}
|
||||
User's active semester: {{userActiveSemester(flashWarning=True).repr()}}
|
||||
<h3>Welcome back, commander!</h3>
|
||||
{{super()}}
|
||||
{% endblock %}
|
|
@ -1,6 +1,6 @@
|
|||
{% extends "admin/model/list.html" %}
|
||||
|
||||
{% block body %}
|
||||
User's active semester: {{userActiveSemester(flashWarning=True).label}}
|
||||
User's active semester: {{userActiveSemester(flashWarning=True).repr()}}
|
||||
{{super()}}
|
||||
{% endblock %}
|
|
@ -1,49 +1,37 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" integrity="sha256-nq7J0kse50upWdNiXRDsuGd/AkfaHz0hX8HgCUsCASY=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css"
|
||||
integrity="sha256-nq7J0kse50upWdNiXRDsuGd/AkfaHz0hX8HgCUsCASY=" crossorigin="anonymous">
|
||||
<!-- Fontawesome CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css" integrity="sha256-2H3fkXt6FEmrReK448mDVGKb3WW2ZZw35gI7vqHOE4Y=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css"
|
||||
integrity="sha256-2H3fkXt6FEmrReK448mDVGKb3WW2ZZw35gI7vqHOE4Y=" crossorigin="anonymous">
|
||||
<!-- Bootstrap Table CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.18.2/dist/bootstrap-table.min.css" integrity="sha256-mypXFtMz9LOewBHR7iL9Ls3/eerooDeTAtLpo6gmTwU=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.18.2/dist/bootstrap-table.min.css"
|
||||
integrity="sha256-mypXFtMz9LOewBHR7iL9Ls3/eerooDeTAtLpo6gmTwU=" crossorigin="anonymous">
|
||||
|
||||
{% if title %}
|
||||
<title>{{title}}</title>
|
||||
{% else %}
|
||||
<title>AdvLabDB</title>
|
||||
{% endif %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="{{url_for('index')}}">AdvLabDB</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar"
|
||||
aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbar">
|
||||
<ul class="navbar-nav">
|
||||
{% for item in navbarItems(title) %}
|
||||
<li class="nav-item">
|
||||
{{item|safe}}
|
||||
<a class="nav-link" href="{{url_for('security.login')}}">Login</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if current_user.is_authenticated %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Semester {{userActiveSemester().label}}
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
||||
{% for item in semesterDropDownItems() %}
|
||||
{{item|safe}}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -65,17 +53,27 @@
|
|||
</div>
|
||||
|
||||
<!-- jQuery JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"
|
||||
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
||||
<!-- Bootstrap Bundle with Popper -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" integrity="sha256-tfbRzZ36wuPoeUKXyuewrLOzcfgdO2ovc4ozuYRWMs4=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha256-tfbRzZ36wuPoeUKXyuewrLOzcfgdO2ovc4ozuYRWMs4=" crossorigin="anonymous"></script>
|
||||
<!-- Bootstrap Table JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.18.2/dist/bootstrap-table.min.js" integrity="sha256-8mXaKD8IdqCXwwzNpp/WHddQZi77Bin0cma5y1G+B9E=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.18.2/dist/bootstrap-table.min.js"
|
||||
integrity="sha256-8mXaKD8IdqCXwwzNpp/WHddQZi77Bin0cma5y1G+B9E=" crossorigin="anonymous"></script>
|
||||
<!-- Bootstrap Table Export extension JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.21/libs/FileSaver/FileSaver.min.js" integrity="sha256-S1CD3kZ9K/shgqLK8lnh6K5A/GQANjwwG+gLA1OL+Jg=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.21/libs/jsPDF/jspdf.min.js" integrity="sha256-B74p+AfarPBbH2e1zQiOJFDizKgXS2sPNkUsST4+cKA=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.21/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js" integrity="sha256-V3ovkrEpDyy74G52YBOG4TSBoC2sHkbbitBEp9/kZcY=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.21/tableExport.min.js" integrity="sha256-/VfFIAF4GLBN7iah7RFGi+zISoczKczfQTP4Dh4N0uw=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.18.2/dist/extensions/export/bootstrap-table-export.min.js" integrity="sha256-C4hVBAtUi42+NXYGkjgx4WD7lGG205ZVtcHo6UMIge8=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.21/libs/FileSaver/FileSaver.min.js"
|
||||
integrity="sha256-S1CD3kZ9K/shgqLK8lnh6K5A/GQANjwwG+gLA1OL+Jg=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.21/libs/jsPDF/jspdf.min.js"
|
||||
integrity="sha256-B74p+AfarPBbH2e1zQiOJFDizKgXS2sPNkUsST4+cKA=" crossorigin="anonymous"></script>
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.21/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js"
|
||||
integrity="sha256-V3ovkrEpDyy74G52YBOG4TSBoC2sHkbbitBEp9/kZcY=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.21/tableExport.min.js"
|
||||
integrity="sha256-/VfFIAF4GLBN7iah7RFGi+zISoczKczfQTP4Dh4N0uw=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.18.2/dist/extensions/export/bootstrap-table-export.min.js"
|
||||
integrity="sha256-C4hVBAtUi42+NXYGkjgx4WD7lGG205ZVtcHo6UMIge8=" crossorigin="anonymous"></script>
|
||||
{% block scripts %}{% endblock scripts %}
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in a new issue