1
0
Fork 0
mirror of https://codeberg.org/Mo8it/AdvLabDB.git synced 2024-09-19 18:31:16 +00:00

Apply changes from the database

This commit is contained in:
Mo 2021-07-14 04:27:17 +02:00
parent bb1b6a86b2
commit 8178c72fe2
6 changed files with 113 additions and 125 deletions

View file

@ -27,9 +27,9 @@ from advlabdb.models import (
Semester, Semester,
Student, Student,
User, User,
Program,
) )
from advlabdb.utils import ( from advlabdb.utils import (
partFromLabelInUserActiveSemester,
randomPassword, randomPassword,
setUserActiveSemester, setUserActiveSemester,
userActiveSemester, userActiveSemester,
@ -100,12 +100,12 @@ class SemesterView(SecureModelView):
can_delete = False can_delete = False
can_view_details = True can_view_details = True
column_list = ["label", "parts"] column_list = ["label", "number", "parts"]
column_details_list = column_list + ["active_users"] column_details_list = column_list + ["active_users", "groups"]
form_columns = ["semester_label", "year", "transfer_parts", "transfer_assistants"] form_columns = ["label", "year", "transfer_parts", "transfer_assistants"]
form_extra_fields = { 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()]), "year": TextField("Year", validators=[DataRequired()]),
"transfer_parts": BooleanField( "transfer_parts": BooleanField(
"Transfer parts", "Transfer parts",
@ -121,7 +121,7 @@ class SemesterView(SecureModelView):
def create_model(self, form): def create_model(self, form):
try: 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.session.add(model)
self.on_model_change(form, model, True) self.on_model_change(form, model, True)
@ -137,7 +137,7 @@ class SemesterView(SecureModelView):
def after_model_change(self, form, model, is_created): def after_model_change(self, form, model, is_created):
admin.add_link( admin.add_link(
MenuLink( MenuLink(
name=model.label, name=model.repr(),
url=url_for("set_semester") + "?semester_id=" + str(model.id), url=url_for("set_semester") + "?semester_id=" + str(model.id),
category="Active semester", category="Active semester",
) )
@ -174,8 +174,8 @@ class SemesterView(SecureModelView):
class PartView(SecureModelView): class PartView(SecureModelView):
can_view_details = True can_view_details = True
column_details_list = ["label", "semester", "part_students", "groups"] column_details_list = ["program", "number", "semester", "part_students"]
form_columns = ["label", "semester"] form_columns = ["program", "number", "semester"]
def queryFilter(self): def queryFilter(self):
return Part.semester == userActiveSemester() return Part.semester == userActiveSemester()
@ -212,7 +212,7 @@ def partQueryFactory():
def groupQueryFactory(): 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])) markChoices = [(-1, "-")] + list(zip(range(16)[::-1], range(16)[::-1]))
@ -261,8 +261,7 @@ class PartStudentView(SecureModelView):
return form(get_form_data(), obj=obj) return form(get_form_data(), obj=obj)
def on_model_change(self, form, model, is_created): def on_model_change(self, form, model, is_created):
if model.group and model.part != model.group.part: PartStudent.check(model.group, model.group)
raise ModelViewException("Student's part and group's part do not match!")
def update_model(self, form, model): def update_model(self, form, model):
if form.final_part_mark.data == -1: if form.final_part_mark.data == -1:
@ -277,29 +276,21 @@ def partStudentsQueryFactory():
class GroupView(SecureModelView): class GroupView(SecureModelView):
class CreateForm(Form): class CreateForm(Form):
part = QuerySelectField( part_students = QuerySelectMultipleField(
"Part", "Part Students", query_factory=partStudentsQueryFactory, validators=[DataRequired()]
query_factory=partQueryFactory,
validators=[DataRequired()],
allow_blank=True,
blank_text="-",
) )
part_students = QuerySelectMultipleField("Part Students", query_factory=partStudentsQueryFactory)
class EditForm(CreateForm): form = CreateForm
part = None
form = EditForm column_list = ["number", "semester", "program", "part_students", "group_experiments"]
column_filters = ["number", "semester", "program"]
column_list = ["number", "part", "part_students", "group_experiments"]
column_filters = ["number", "part"]
def queryFilter(self): def queryFilter(self):
return Group.part_id.in_([part.id for part in userActiveSemester().parts]) return Group.semester == userActiveSemester()
def create_model(self, form): def create_model(self, form):
try: try:
model = Group.customInit(form.part.data, form.part_students.data) model = Group.customInit(form.part_students.data)
self.session.add(model) self.session.add(model)
self.on_model_change(form, model, True) self.on_model_change(form, model, True)
@ -313,19 +304,15 @@ class GroupView(SecureModelView):
return model return model
def update_model(self, form, 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) 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): class ExperimentView(SecureModelView):
can_view_details = True can_view_details = True
column_filters = ["active"] column_filters = ["active"]
column_list = ["label", "title", "active"] column_list = ["number", "program", "title", "active"]
column_details_list = column_list + [ column_details_list = column_list + [
"desciption", "desciption",
"wiki_link", "wiki_link",
@ -420,10 +407,7 @@ class GroupExperimentView(SecureModelView):
def queryFilter(self): def queryFilter(self):
return GroupExperiment.group_id.in_( return GroupExperiment.group_id.in_(
[ [group.id for group in Group.query.filter(Group.semester == userActiveSemester())]
group.id
for group in Group.query.filter(Group.part_id.in_([part.id for part in userActiveSemester().parts]))
]
) )
def create_model(self, form): def create_model(self, form):
@ -617,6 +601,11 @@ class ExperimentMarkView(SecureModelView):
self.session.rollback() 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(StudentView(Student, db.session))
admin.add_view(PartStudentView(PartStudent, db.session)) admin.add_view(PartStudentView(PartStudent, db.session))
admin.add_view(GroupView(Group, 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(ExperimentView(Experiment, db.session))
admin.add_view(SemesterExperimentView(SemesterExperiment, db.session)) admin.add_view(SemesterExperimentView(SemesterExperiment, db.session))
admin.add_view(AssistantView(Assistant, 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(PartView(Part, db.session))
admin.add_view(SemesterView(Semester, db.session)) admin.add_view(SemesterView(Semester, db.session))
admin.add_view(UserView(User, db.session)) admin.add_view(UserView(User, db.session))
@ -636,7 +626,7 @@ with app.app_context():
for semester in semesters: for semester in semesters:
admin.add_link( admin.add_link(
MenuLink( MenuLink(
name=semester.label, name=semester.repr(),
url=url_for("set_semester") + "?semester_id=" + str(semester.id), url=url_for("set_semester") + "?semester_id=" + str(semester.id),
category="Active semester", category="Active semester",
) )

View file

@ -1,6 +1,6 @@
{% extends "admin/model/create.html" %} {% extends "admin/model/create.html" %}
{% block body %} {% block body %}
User's active semester: {{userActiveSemester().label}} User's active semester: {{userActiveSemester().repr()}}
{{super()}} {{super()}}
{% endblock %} {% endblock %}

View file

@ -1,6 +1,6 @@
{% extends "admin/model/edit.html" %} {% extends "admin/model/edit.html" %}
{% block body %} {% block body %}
User's active semester: {{userActiveSemester().label}} User's active semester: {{userActiveSemester().repr()}}
{{super()}} {{super()}}
{% endblock %} {% endblock %}

View file

@ -1,7 +1,7 @@
{% extends "admin/index.html" %} {% extends "admin/index.html" %}
{% block body %} {% block body %}
User's active semester: {{userActiveSemester(flashWarning=True).label}} User's active semester: {{userActiveSemester(flashWarning=True).repr()}}
<h3>Welcome back, commander!</h3> <h3>Welcome back, commander!</h3>
{{super()}} {{super()}}
{% endblock %} {% endblock %}

View file

@ -1,6 +1,6 @@
{% extends "admin/model/list.html" %} {% extends "admin/model/list.html" %}
{% block body %} {% block body %}
User's active semester: {{userActiveSemester(flashWarning=True).label}} User's active semester: {{userActiveSemester(flashWarning=True).repr()}}
{{super()}} {{super()}}
{% endblock %} {% endblock %}

View file

@ -1,81 +1,79 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS --> <head>
<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"> <!-- Required meta tags -->
<!-- Fontawesome CSS --> <meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css" integrity="sha256-2H3fkXt6FEmrReK448mDVGKb3WW2ZZw35gI7vqHOE4Y=" crossorigin="anonymous"> <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 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">
{% if title %} <!-- Bootstrap CSS -->
<title>{{title}}</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css"
{% else %} integrity="sha256-nq7J0kse50upWdNiXRDsuGd/AkfaHz0hX8HgCUsCASY=" crossorigin="anonymous">
<title>AdvLabDB</title> <!-- Fontawesome CSS -->
{% endif %} <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css"
</head> integrity="sha256-2H3fkXt6FEmrReK448mDVGKb3WW2ZZw35gI7vqHOE4Y=" crossorigin="anonymous">
<body> <!-- Bootstrap Table CSS -->
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.18.2/dist/bootstrap-table.min.css"
<div class="container-fluid"> integrity="sha256-mypXFtMz9LOewBHR7iL9Ls3/eerooDeTAtLpo6gmTwU=" crossorigin="anonymous">
<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"> <title>AdvLabDB</title>
<span class="navbar-toggler-icon"></span> </head>
</button>
<div class="collapse navbar-collapse" id="navbar"> <body>
<ul class="navbar-nav"> <nav class="navbar navbar-expand-lg navbar-light bg-light">
{% for item in navbarItems(title) %}
<li class="nav-item">
{{item|safe}}
</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>
</nav>
<div class="container-fluid"> <div class="container-fluid">
<br> <a class="navbar-brand" href="{{url_for('index')}}">AdvLabDB</a>
{% with messages = get_flashed_messages(with_categories=True) %} <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar"
{% if messages %} aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
{% for category, message in messages %} <span class="navbar-toggler-icon"></span>
<div class="alert alert-{{category}}"> </button>
{{message}} <div class="collapse navbar-collapse" id="navbar">
</div> <ul class="navbar-nav">
{% endfor %} <li class="nav-item">
{% endif %} <a class="nav-link" href="{{url_for('security.login')}}">Login</a>
{% endwith %} </li>
</ul>
{% block content %}{% endblock content %} </div>
<br>
</div> </div>
</nav>
<div class="container-fluid">
<br>
{% with messages = get_flashed_messages(with_categories=True) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{category}}">
{{message}}
</div>
{% endfor %}
{% endif %}
{% endwith %}
<!-- jQuery JS --> {% block content %}{% endblock content %}
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script> <br>
<!-- Bootstrap Bundle with Popper --> </div>
<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 --> <!-- jQuery 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/jquery@3.6.0/dist/jquery.min.js"
<!-- Bootstrap Table Export extension JS --> integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" 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> <!-- Bootstrap Bundle with Popper -->
<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/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js"
<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> integrity="sha256-tfbRzZ36wuPoeUKXyuewrLOzcfgdO2ovc4ozuYRWMs4=" 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> <!-- Bootstrap Table JS -->
<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/bootstrap-table@1.18.2/dist/bootstrap-table.min.js"
{% block scripts %}{% endblock scripts %} integrity="sha256-8mXaKD8IdqCXwwzNpp/WHddQZi77Bin0cma5y1G+B9E=" crossorigin="anonymous"></script>
</body> <!-- Bootstrap Table Export extension JS -->
</html> <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>