2022-02-13 18:58:05 +00:00
from pathlib import Path
2022-03-02 00:56:42 +00:00
from flask import flash , redirect , request , url_for , has_request_context
2022-02-13 18:58:05 +00:00
from flask_admin import expose
2021-07-30 12:20:54 +00:00
from flask_admin . contrib . sqla . fields import QuerySelectField , QuerySelectMultipleField
2022-02-27 18:30:28 +00:00
from flask_admin . contrib . sqla . filters import FilterEqual
2021-07-30 12:20:54 +00:00
from flask_admin . helpers import get_form_data
2021-06-02 21:43:41 +00:00
from flask_admin . menu import MenuLink
2021-07-01 14:38:37 +00:00
from flask_admin . model . template import EndpointLinkRowAction
2021-07-30 12:20:54 +00:00
from flask_security import admin_change_password , current_user , hash_password
2022-02-13 18:58:05 +00:00
from flask_wtf import FlaskForm
from flask_wtf . file import FileAllowed , FileField , FileRequired
from sqlalchemy import and_ , func , or_
from werkzeug . utils import secure_filename
2022-02-27 16:43:31 +00:00
from wtforms import Form
from wtforms . fields import (
BooleanField ,
DateField ,
DecimalField ,
IntegerField ,
RadioField ,
SelectField ,
StringField ,
)
2021-07-30 22:12:37 +00:00
from wtforms . validators import URL , DataRequired , Email , NumberRange , Optional
2021-04-24 10:05:58 +00:00
2021-07-30 22:12:37 +00:00
from advlabdb import adminSpace , app , assistantSpace , db , user_datastore
2021-06-01 23:56:49 +00:00
from advlabdb . configUtils import getConfig
2022-02-13 18:58:05 +00:00
from advlabdb . customClasses import SecureAdminBaseView , SecureAdminModelView
from advlabdb . database_import import importFromFile
2021-07-30 12:20:54 +00:00
from advlabdb . exceptions import DataBaseException , ModelViewException
2021-06-02 21:43:41 +00:00
from advlabdb . models import (
Appointment ,
Assistant ,
Experiment ,
ExperimentMark ,
Group ,
GroupExperiment ,
Part ,
PartStudent ,
2021-07-30 12:20:54 +00:00
Program ,
2021-06-02 21:43:41 +00:00
Role ,
Semester ,
2021-07-30 12:20:54 +00:00
SemesterExperiment ,
2021-06-02 21:43:41 +00:00
Student ,
User ,
2022-03-01 21:23:30 +00:00
Admin ,
2021-06-02 21:43:41 +00:00
)
2021-07-30 22:12:37 +00:00
from advlabdb . utils import (
2022-02-23 19:36:29 +00:00
flashRandomPassword ,
2021-07-30 22:12:37 +00:00
initActiveSemesterMenuLinks ,
randomPassword ,
setUserActiveSemester ,
userActiveSemester ,
)
2021-06-02 21:43:41 +00:00
2021-04-26 19:31:15 +00:00
2021-08-15 23:15:19 +00:00
def semesterExperimentQueryFactory ( ) :
return SemesterExperiment . query . filter ( SemesterExperiment . semester == userActiveSemester ( ) )
2021-07-30 00:03:44 +00:00
class UserView ( SecureAdminModelView ) :
2021-07-29 18:55:22 +00:00
class CreateForm ( Form ) :
def roleQueryFactory ( ) :
return Role . query
def semesterQueryFactory ( ) :
return Semester . query
2021-07-29 22:46:36 +00:00
def activeSemesterDefault ( ) :
return userActiveSemester ( )
2021-11-29 19:22:10 +00:00
email = StringField ( " Email " , validators = [ DataRequired ( ) , Email ( ) ] )
2021-07-29 18:55:22 +00:00
roles = QuerySelectMultipleField (
" Roles " ,
query_factory = roleQueryFactory ,
validators = [ DataRequired ( ) ] ,
default = [ Role . query . filter ( Role . name == " assistant " ) . first ( ) ] ,
)
2021-08-15 23:15:19 +00:00
2021-11-29 19:22:10 +00:00
first_name = StringField ( " First Name " , validators = [ DataRequired ( ) ] )
last_name = StringField ( " Last Name " , validators = [ DataRequired ( ) ] )
phone_number = StringField ( " Phone Number " )
mobile_phone_number = StringField ( " Mobile Phone Number " )
building = StringField ( " Building " )
2022-02-23 19:36:29 +00:00
room = StringField ( " Room " )
2021-08-15 23:15:19 +00:00
semester_experiments = QuerySelectMultipleField (
" Semester Experiments " ,
query_factory = semesterExperimentQueryFactory ,
allow_blank = True ,
blank_text = " - " ,
description = " Only needed if the user has the assistant role " ,
)
2021-07-29 18:55:22 +00:00
active = BooleanField ( " Active " , default = True )
active_semester = QuerySelectField (
" Active Semester " ,
query_factory = semesterQueryFactory ,
allow_blank = True ,
blank_text = " - " ,
2021-07-29 22:46:36 +00:00
default = activeSemesterDefault ,
2021-08-16 21:47:04 +00:00
description = " Not fixed and users (including assistants) can change it. " ,
2021-07-29 18:55:22 +00:00
)
class EditForm ( CreateForm ) :
2021-08-15 23:15:19 +00:00
semester_experiments = None
2021-07-29 18:55:22 +00:00
generate_new_password = BooleanField ( " Generate new random password " , default = False )
form = EditForm
2021-07-29 18:03:41 +00:00
can_view_details = True
2021-11-30 00:41:18 +00:00
column_list = [
" first_name " ,
" last_name " ,
" email " ,
" active " ,
" roles " ,
" assistant " ,
" active_semester " ,
]
2021-08-15 23:15:19 +00:00
column_details_list = column_list + [
" phone_number " ,
" mobile_phone_number " ,
" building " ,
2022-02-23 19:36:29 +00:00
" room " ,
2021-08-15 23:15:19 +00:00
" create_datetime " ,
" update_datetime " ,
]
2021-11-30 00:41:18 +00:00
column_searchable_list = [
" first_name " ,
" last_name " ,
" email " ,
]
2022-03-02 00:56:42 +00:00
column_filters = (
2021-11-30 00:41:18 +00:00
" active " ,
" active_semester " ,
2022-03-02 00:56:42 +00:00
)
2021-11-30 00:41:18 +00:00
column_editable_list = [
" active " ,
]
2021-04-27 21:28:47 +00:00
2021-07-29 18:55:22 +00:00
def create_form ( self , obj = None ) :
form = self . CreateForm
return form ( get_form_data ( ) , obj = obj )
2021-04-24 10:05:58 +00:00
def create_model ( self , form ) :
2021-07-29 22:24:10 +00:00
try :
password = randomPassword ( )
hashedPassword = hash_password ( password )
2021-04-24 10:05:58 +00:00
2021-07-29 22:24:10 +00:00
email = form . email . data . lower ( )
2021-04-24 10:05:58 +00:00
2021-07-29 22:24:10 +00:00
roles = [ role . name for role in form . roles . data ]
2021-04-24 10:05:58 +00:00
2021-07-29 15:37:15 +00:00
model = user_datastore . create_user (
2021-08-15 23:15:19 +00:00
email = email ,
password = hashedPassword ,
roles = roles ,
first_name = form . first_name . data ,
last_name = form . last_name . data ,
phone_number = form . phone_number . data ,
mobile_phone_number = form . mobile_phone_number . data ,
building = form . building . data ,
2022-02-23 19:36:29 +00:00
room = form . room . data ,
2021-08-15 23:15:19 +00:00
active = form . active . data ,
active_semester = form . active_semester . data ,
2021-07-29 15:37:15 +00:00
)
2021-06-30 19:58:57 +00:00
self . on_model_change ( form , model , True )
2021-06-08 23:07:02 +00:00
self . session . commit ( )
except Exception as ex :
2021-07-11 12:27:00 +00:00
flash ( str ( ex ) , " error " )
2021-06-08 23:07:02 +00:00
self . session . rollback ( )
else :
flash (
2021-08-21 21:18:55 +00:00
f " { email } registered with roles: { ' , ' . join ( [ role . name for role in model . roles ] ) } . " ,
2021-06-08 23:07:02 +00:00
category = " success " ,
)
2021-07-29 18:55:22 +00:00
2022-02-23 19:36:29 +00:00
flashRandomPassword ( password )
2021-07-29 18:55:22 +00:00
self . after_model_change ( form , model , True )
2021-06-08 23:07:02 +00:00
return model
2021-04-24 10:05:58 +00:00
2021-06-09 00:22:37 +00:00
def on_model_delete ( self , model ) :
if model == current_user :
2021-07-13 23:58:35 +00:00
raise ModelViewException ( " Tried to delete yourself as user! " )
2021-06-09 00:22:37 +00:00
def on_model_change ( self , form , model , is_created ) :
2021-07-29 22:24:10 +00:00
if not is_created :
2021-11-30 00:41:18 +00:00
if model == current_user :
if not form . active . data :
2022-02-13 18:58:05 +00:00
raise ModelViewException ( " Tried to deactivate yourself as user! " )
2021-11-30 00:41:18 +00:00
if not model . has_role ( " admin " ) :
raise ModelViewException ( " Tried to remove your admin role! " )
2021-06-09 00:22:37 +00:00
2021-07-30 13:14:35 +00:00
if hasattr ( form , " generate_new_password " ) and form . generate_new_password . data :
2021-07-29 22:24:10 +00:00
password = randomPassword ( )
UserView . flashPassword ( password )
2021-07-29 18:55:22 +00:00
2021-07-29 22:24:10 +00:00
admin_change_password (
model , password , notify = False
2022-02-23 19:36:29 +00:00
) # Password is automatically hashed with this function
2021-07-29 18:55:22 +00:00
2021-08-21 21:18:55 +00:00
if model . has_role ( " assistant " ) and not model . assistant :
2021-08-21 21:21:39 +00:00
semester_experiments = form . semester_experiments . data if form . semester_experiments else [ ]
2021-08-21 21:18:55 +00:00
assistant = Assistant ( user = model , semester_experiments = semester_experiments )
self . session . add ( assistant )
2022-02-27 18:30:28 +00:00
if model . has_role ( " admin " ) and not model . admin :
admin = Admin ( user = model )
self . session . add ( admin )
2021-04-24 10:05:58 +00:00
2021-07-30 00:03:44 +00:00
class RoleView ( SecureAdminModelView ) :
2021-06-09 00:22:37 +00:00
can_create = False
can_edit = False
can_delete = False
column_display_actions = False
2021-08-16 21:47:04 +00:00
can_export = False
can_set_page_size = False
2021-06-09 00:22:37 +00:00
2021-11-30 00:41:18 +00:00
column_list = [
" name " ,
" description " ,
" permissions " ,
" update_datetime " ,
]
2021-04-24 10:05:58 +00:00
2021-04-24 11:38:03 +00:00
2021-07-30 00:03:44 +00:00
class SemesterView ( SecureAdminModelView ) :
2021-07-29 14:27:15 +00:00
class CreateForm ( Form ) :
2021-07-29 22:40:21 +00:00
def labelDefault ( ) :
if userActiveSemester ( ) . label == " WS " :
return " SS "
else :
return " WS "
def yearDefault ( ) :
activeSemester = userActiveSemester ( )
if activeSemester . label == " WS " :
return activeSemester . year + 1
else :
return activeSemester . year
label = RadioField ( " Semester " , choices = [ " WS " , " SS " ] , validators = [ DataRequired ( ) ] , default = labelDefault )
2021-11-29 19:22:10 +00:00
year = StringField ( " Year " , validators = [ DataRequired ( ) ] , default = yearDefault )
2021-07-29 14:27:15 +00:00
transfer_parts = BooleanField (
2021-07-01 14:38:37 +00:00
" Transfer parts " ,
2021-07-01 21:17:09 +00:00
description = " This option transfers the parts you have in your current active semester. Make sure that your semester is the last semester before creating a new one (recommended)! " ,
2021-06-25 23:59:21 +00:00
default = True ,
2021-07-29 14:27:15 +00:00
)
transfer_assistants = BooleanField (
2021-07-01 14:38:37 +00:00
" Transfer Assistants " ,
2022-02-13 18:58:05 +00:00
description = " This option transfers assistants of your active semester to active experiments in the new semester. Make sure that your semester is the last semester before creating a new one (recommended)! Active experiments are transferred anyway. If you do not want an experiment to be transferred, set it to inactive before creating the new semester. Experiments which are switched to active before creating the new semester will be created in the new semester without assistants. It is important to check the assistants of all experiments after creating a new semester. " ,
2021-07-01 14:38:37 +00:00
default = True ,
2021-07-29 14:27:15 +00:00
)
form = CreateForm
can_edit = False
can_delete = False
can_view_details = True
2021-11-30 00:41:18 +00:00
column_list = [
" label " ,
" year " ,
" parts " ,
]
column_details_list = column_list + [
" semester_experiments " ,
" active_users " ,
" groups " ,
]
column_searchable_list = [
" label " ,
" year " ,
]
2021-04-24 11:38:03 +00:00
2021-07-29 22:24:10 +00:00
def customCreateModel ( self , form ) :
2021-11-29 19:22:10 +00:00
return Semester . customInitFromOldSemester (
2021-07-29 22:24:10 +00:00
label = form . label . data ,
year = form . year . data ,
oldSemester = userActiveSemester ( ) ,
transferParts = form . transfer_parts . data ,
transferAssistants = form . transfer_assistants . data ,
)
2021-06-08 23:07:02 +00:00
2021-07-30 22:12:37 +00:00
def addMenuLink ( space , newSemester ) :
2022-03-02 00:56:42 +00:00
categoryText = " Active semester "
link = MenuLink (
name = newSemester . repr ( ) ,
url = url_for ( " set_semester " ) + " ?semester_id= " + str ( newSemester . id ) ,
category = categoryText ,
2021-06-25 23:59:21 +00:00
)
2022-03-02 00:56:42 +00:00
category = self . _menu_categories . get ( categoryText )
link . parent = category
category . _children . insert ( 0 , link )
2021-07-30 22:12:37 +00:00
def after_model_change ( self , form , model , is_created ) :
setUserActiveSemester ( model . id )
SemesterView . addMenuLink ( adminSpace , model )
SemesterView . addMenuLink ( assistantSpace , model )
2021-04-24 11:38:03 +00:00
2021-07-29 22:24:10 +00:00
def programQueryFactory ( ) :
return Program . query
2021-07-30 00:03:44 +00:00
class PartView ( SecureAdminModelView ) :
2021-04-24 11:38:03 +00:00
can_view_details = True
2021-07-28 22:58:50 +00:00
2021-07-29 14:27:15 +00:00
column_sortable_list = [ ]
2021-11-30 00:41:18 +00:00
column_list = [
" program " ,
" number " ,
" semester " ,
]
column_details_list = column_list + [
" part_students " ,
]
form_columns = [
" program " ,
" number " ,
]
2021-07-29 22:24:10 +00:00
form_extra_fields = {
" program " : QuerySelectField (
" Program " , query_factory = programQueryFactory , validators = [ DataRequired ( ) ] , allow_blank = True , blank_text = " - "
)
}
2021-04-24 11:38:03 +00:00
2021-07-12 14:42:11 +00:00
def queryFilter ( self ) :
2021-07-13 01:37:00 +00:00
return Part . semester == userActiveSemester ( )
2021-06-10 01:14:30 +00:00
2021-07-29 22:24:10 +00:00
def customCreateModel ( self , form ) :
return Part ( program = form . program . data , number = form . number . data , semester = userActiveSemester ( ) )
2021-04-27 13:50:03 +00:00
2021-07-30 00:03:44 +00:00
class StudentView ( SecureAdminModelView ) :
2021-04-26 19:31:15 +00:00
can_view_details = True
2021-06-30 19:58:57 +00:00
2021-11-30 00:41:18 +00:00
column_list = [
" student_number " ,
" first_name " ,
" last_name " ,
" uni_email " ,
" contact_email " ,
" part_students " ,
]
column_descriptions = {
" contact_email " : " The preferred contact email address if entered by the student " ,
}
column_details_list = column_list + [
" bachelor_thesis " ,
" bachelor_thesis_work_group " ,
" note " ,
]
2021-06-30 19:58:57 +00:00
2021-11-30 00:41:18 +00:00
column_sortable_list = [
" student_number " ,
" first_name " ,
" last_name " ,
]
column_searchable_list = column_sortable_list + [
" uni_email " ,
" contact_email " ,
]
2021-06-30 19:58:57 +00:00
2021-11-30 00:41:18 +00:00
form_excluded_columns = [
" part_students " ,
]
2021-04-26 22:26:11 +00:00
2021-04-27 21:28:47 +00:00
form_args = {
2021-05-14 16:53:15 +00:00
" uni_email " : { " validators " : [ Email ( ) ] } ,
" contact_email " : { " validators " : [ Email ( ) ] } ,
2021-04-27 21:28:47 +00:00
}
2021-07-01 14:38:37 +00:00
column_extra_row_actions = [
EndpointLinkRowAction (
" glyphicon glyphicon-time " ,
id_arg = " flt1_0 " ,
title = " Experiments history " ,
endpoint = " experimentmark.index_view " ,
)
]
2021-06-10 01:14:30 +00:00
2021-07-12 14:42:11 +00:00
def partQueryFactory ( ) :
2021-07-30 13:14:35 +00:00
return Part . query . filter ( Part . semester == userActiveSemester ( ) )
2021-06-10 01:14:30 +00:00
2021-07-12 14:42:11 +00:00
def groupQueryFactory ( ) :
2021-07-14 02:27:17 +00:00
return Group . query . filter ( Group . semester == userActiveSemester ( ) )
2021-07-01 11:12:43 +00:00
2022-03-02 00:56:42 +00:00
def partFilterOptions ( ) :
if has_request_context ( ) :
parts = Part . query . filter ( Part . semester == userActiveSemester ( ) )
return ( ( part . id , f " { part . program . repr ( ) } { part . number } " ) for part in parts )
else :
return
2021-07-30 00:03:44 +00:00
class PartStudentView ( SecureAdminModelView ) :
2022-03-02 00:56:42 +00:00
@expose ( " / " )
def index_view ( self ) :
# To update filter options
self . _refresh_filters_cache ( )
return super ( ) . index_view ( )
class PartFilter ( FilterEqual ) :
def get_options ( self , view ) :
return partFilterOptions ( )
def apply ( self , query , value , alias = None ) :
return query . filter ( self . column . part_id == int ( value ) )
2021-06-30 19:58:57 +00:00
class CreateForm ( Form ) :
2021-07-12 14:42:11 +00:00
def studentQueryFactory ( ) :
return Student . query
2021-04-26 22:26:11 +00:00
2021-06-30 19:58:57 +00:00
student = QuerySelectField (
2021-07-13 01:37:00 +00:00
" Student " ,
query_factory = studentQueryFactory ,
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
2021-06-30 19:58:57 +00:00
)
part = QuerySelectField (
2021-07-13 01:37:00 +00:00
" Part " ,
query_factory = partQueryFactory ,
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
)
group = QuerySelectField (
" Group " ,
query_factory = groupQueryFactory ,
allow_blank = True ,
blank_text = " - " ,
2021-06-30 19:58:57 +00:00
)
2021-04-26 22:26:11 +00:00
2021-06-30 19:58:57 +00:00
class EditForm ( CreateForm ) :
student = None
part = None
2021-06-08 23:07:02 +00:00
2021-06-30 19:58:57 +00:00
form = EditForm
2021-06-08 23:07:02 +00:00
2021-11-30 00:41:18 +00:00
column_list = [
" student " ,
" part " ,
" group " ,
" final_part_mark " ,
" experiment_marks " ,
]
2021-08-18 23:29:09 +00:00
2022-03-02 00:56:42 +00:00
column_filters = (
PartFilter ( PartStudent , " Part " ) ,
" student.student_number " ,
" student.first_name " ,
" student.last_name " ,
" group.number " ,
" experiment_marks " ,
)
2021-04-26 19:31:15 +00:00
2021-07-12 14:42:11 +00:00
def queryFilter ( self ) :
2021-07-30 13:14:35 +00:00
return PartStudent . part . has ( Part . semester == userActiveSemester ( ) )
2021-07-12 14:42:11 +00:00
2021-06-30 19:58:57 +00:00
def create_form ( self , obj = None ) :
form = self . CreateForm
return form ( get_form_data ( ) , obj = obj )
2021-04-27 21:28:47 +00:00
2021-06-30 19:58:57 +00:00
def on_model_change ( self , form , model , is_created ) :
2021-07-29 19:13:49 +00:00
PartStudent . check ( model . group , model . part )
2021-04-27 21:28:47 +00:00
2021-04-27 13:50:03 +00:00
2021-07-29 21:18:24 +00:00
def partStudentQueryFactory ( ) :
2021-07-30 13:14:35 +00:00
return PartStudent . query . filter ( PartStudent . part . has ( Part . semester == userActiveSemester ( ) ) )
2021-07-13 01:37:00 +00:00
2021-07-30 00:03:44 +00:00
class GroupView ( SecureAdminModelView ) :
2022-03-02 00:56:42 +00:00
@expose ( " / " )
def index_view ( self ) :
# To update filter options
self . _refresh_filters_cache ( )
return super ( ) . index_view ( )
class ProgramFilter ( FilterEqual ) :
def get_options ( self , view ) :
programs = Program . query
return ( ( program . id , program . repr ( ) ) for program in programs )
def apply ( self , query , value , alias = None ) :
return query . filter ( self . column . program_id == int ( value ) )
2021-08-18 18:11:40 +00:00
def formFactory ( is_created , group ) :
if is_created :
2021-06-30 19:58:57 +00:00
2021-07-29 21:18:24 +00:00
def query_factory ( ) :
return partStudentQueryFactory ( ) . filter ( PartStudent . group == None )
else :
def query_factory ( ) :
2021-08-18 18:06:18 +00:00
return partStudentQueryFactory ( ) . filter (
or_ (
and_ ( PartStudent . group == None , PartStudent . part . has ( Part . program == group . program ) ) ,
PartStudent . group == group ,
)
)
2021-07-29 21:18:24 +00:00
class CustomForm ( Form ) :
part_students = QuerySelectMultipleField (
2021-08-16 21:32:46 +00:00
" Part Students " ,
query_factory = query_factory ,
validators = [ DataRequired ( ) ] ,
description = " The part students have to be in the same program! " ,
2021-07-29 21:18:24 +00:00
)
return CustomForm
2021-06-30 19:58:57 +00:00
2021-11-30 00:41:18 +00:00
column_list = [
" number " ,
" program " ,
" part_students " ,
" group_experiments " ,
]
2022-03-02 00:56:42 +00:00
column_filters = (
ProgramFilter ( Group , " Program " ) ,
2021-11-30 00:41:18 +00:00
" number " ,
2022-03-02 00:56:42 +00:00
)
2021-06-30 19:58:57 +00:00
2021-07-12 14:42:11 +00:00
def queryFilter ( self ) :
2021-07-14 02:27:17 +00:00
return Group . semester == userActiveSemester ( )
2021-07-12 14:42:11 +00:00
2021-07-29 22:24:10 +00:00
def customCreateModel ( self , form ) :
return Group . customInit ( form . part_students . data )
2021-06-30 19:58:57 +00:00
2021-07-29 21:18:24 +00:00
def create_form ( self , obj = None ) :
2021-08-18 18:11:40 +00:00
form = GroupView . formFactory ( is_created = True , group = None )
2021-07-29 21:18:24 +00:00
return form ( get_form_data ( ) , obj = obj )
def edit_form ( self , obj = None ) :
2021-08-18 18:11:40 +00:00
form = GroupView . formFactory ( is_created = False , group = obj )
2021-07-29 21:18:24 +00:00
return form ( get_form_data ( ) , obj = obj )
2021-06-07 15:15:10 +00:00
2021-07-30 00:03:44 +00:00
class ExperimentView ( SecureAdminModelView ) :
2021-06-21 16:07:18 +00:00
can_view_details = True
2021-07-28 22:58:50 +00:00
2022-03-02 00:56:42 +00:00
column_filters = ( " active " , )
2021-11-30 00:41:18 +00:00
column_list = [
" number " ,
" program " ,
" title " ,
" active " ,
]
column_descriptions = {
" active " : " Active experiments are present in new semesters " ,
}
2021-07-10 23:49:39 +00:00
column_details_list = column_list + [
2021-07-28 11:59:41 +00:00
" description " ,
2021-07-10 23:49:39 +00:00
" wiki_link " ,
" building " ,
2022-02-23 19:36:29 +00:00
" room " ,
2021-07-10 23:49:39 +00:00
" responsibility " ,
" duration_in_days " ,
" semester_experiments " ,
]
2021-06-21 16:26:38 +00:00
2021-08-16 21:32:46 +00:00
form_columns = column_details_list . copy ( )
form_columns . remove ( " semester_experiments " )
2021-11-30 00:41:18 +00:00
column_editable_list = [
" active " ,
]
2021-07-13 16:41:00 +00:00
2021-08-16 21:32:46 +00:00
form_args = {
" wiki_link " : { " validators " : [ URL ( ) ] } ,
}
2021-07-29 21:37:18 +00:00
form_extra_fields = {
" program " : QuerySelectField (
" Program " , query_factory = programQueryFactory , validators = [ DataRequired ( ) ] , allow_blank = True , blank_text = " - "
)
}
2021-07-13 16:41:00 +00:00
2021-06-21 16:26:38 +00:00
2021-07-28 22:31:43 +00:00
def assistantQueryFactory ( ) :
2021-07-30 13:14:35 +00:00
return Assistant . query . filter ( Assistant . user . has ( User . active == True ) )
2021-07-28 22:31:43 +00:00
2021-07-30 00:03:44 +00:00
class SemesterExperimentView ( SecureAdminModelView ) :
2021-07-28 22:31:43 +00:00
class CreateForm ( Form ) :
def experimentQueryFactory ( ) :
return Experiment . query . filter ( Experiment . active == True )
experiment = QuerySelectField (
" Experiment " ,
query_factory = experimentQueryFactory ,
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
)
2022-02-27 16:43:31 +00:00
oral_weighting = DecimalField (
" Oral weighting " ,
validators = [ DataRequired ( ) , NumberRange ( min = 0 , max = 1 ) ] ,
default = 0.5 ,
description = " Between 0 and 1 " ,
places = 2 ,
)
protocol_weighting = DecimalField (
" Protocol weighting " ,
validators = [ DataRequired ( ) , NumberRange ( min = 0 , max = 1 ) ] ,
default = 0.5 ,
description = " Between 0 and 1. Oral and protocol weightings have to add to 1! Both are rounded to 2 decimal digits. " ,
places = 2 ,
)
final_weighting = DecimalField (
" Final weighting " ,
validators = [ DataRequired ( ) , NumberRange ( min = 0 , max = 1 ) ] ,
default = 1.0 ,
description = " Between 0 and 1 " ,
places = 2 ,
)
2021-07-28 22:31:43 +00:00
assistants = QuerySelectMultipleField ( " Assistants " , query_factory = assistantQueryFactory )
form = CreateForm
can_view_details = True
2021-11-30 00:41:18 +00:00
column_list = [
" experiment " ,
" assistants " ,
" semester " ,
]
column_details_list = column_list + [
2022-02-27 16:43:31 +00:00
" oral_weighting " ,
" protocol_weighting " ,
" final_weighting " ,
2021-11-30 00:41:18 +00:00
" group_experiments " ,
]
2022-03-02 00:56:42 +00:00
column_filters = ( " experiment " , )
2021-06-21 16:26:38 +00:00
2021-07-12 14:42:11 +00:00
def queryFilter ( self ) :
return SemesterExperiment . semester == userActiveSemester ( )
2021-06-21 16:07:18 +00:00
2021-07-29 22:24:10 +00:00
def customCreateModel ( self , form ) :
return SemesterExperiment (
2022-02-27 16:43:31 +00:00
semester = userActiveSemester ( ) ,
oral_weighting = form . oral_weighting . data ,
protocol_weighting = form . protocol_weighting . data ,
final_weighting = form . final_weighting . data ,
experiment = form . experiment . data ,
assistants = form . assistants . data ,
2021-07-29 22:24:10 +00:00
)
2021-07-28 22:31:43 +00:00
2022-02-27 16:43:31 +00:00
def on_model_change ( self , form , model , is_created ) :
model . checkAndRoundWeightings ( )
2021-06-21 16:07:18 +00:00
2021-07-30 00:03:44 +00:00
class AssistantView ( SecureAdminModelView ) :
2021-07-29 15:37:15 +00:00
def assistantUserQueryFactory ( ) :
return User . query . filter ( User . roles . any ( Role . name == " assistant " ) )
2021-06-24 17:24:14 +00:00
can_view_details = True
2021-07-28 22:58:50 +00:00
2021-11-30 00:41:18 +00:00
column_list = [
" user.first_name " ,
" user.last_name " ,
" user " ,
" semester_experiments " ,
]
2021-07-01 11:12:43 +00:00
column_details_list = column_list + [
2021-08-15 23:15:19 +00:00
" user.phone_number " ,
" user.mobile_phone_number " ,
" user.building " ,
2022-02-23 19:36:29 +00:00
" user.room " ,
2021-07-01 11:12:43 +00:00
" appointments " ,
" experiment_marks " ,
]
2021-11-30 00:41:18 +00:00
column_searchable_list = [
" user.first_name " ,
" user.last_name " ,
" user.email " ,
]
2022-03-02 00:56:42 +00:00
column_filters = ( " user.active " , )
2021-11-30 00:41:18 +00:00
form_excluded_columns = [
" experiment_marks " ,
" appointments " ,
]
2021-07-29 15:37:15 +00:00
form_extra_fields = {
" user " : QuerySelectField (
" User " ,
query_factory = assistantUserQueryFactory ,
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
2021-08-15 23:15:19 +00:00
) ,
" semester_experiments " : QuerySelectMultipleField (
" Semester Experiments " ,
query_factory = semesterExperimentQueryFactory ,
allow_blank = True ,
blank_text = " - " ,
) ,
2021-07-29 15:37:15 +00:00
}
2021-06-24 17:24:14 +00:00
2022-03-01 21:23:30 +00:00
# TODO: Add AdminView
2021-07-12 14:42:11 +00:00
assistantBlankText = " Auto assign if experiment has only one assistant "
2022-03-02 00:56:42 +00:00
def experimentFilterOptions ( ) :
activeExperiments = Experiment . query . filter ( Experiment . active == True )
return (
(
f " { activeExperiment . number } , { activeExperiment . program . id } " ,
f " { activeExperiment . number } { activeExperiment . program . repr ( ) } " ,
)
for activeExperiment in activeExperiments
)
2021-07-30 00:03:44 +00:00
class GroupExperimentView ( SecureAdminModelView ) :
2022-03-01 21:23:30 +00:00
@expose ( " / " )
def index_view ( self ) :
# To update filter options
self . _refresh_filters_cache ( )
return super ( ) . index_view ( )
class ExperimentFilter ( FilterEqual ) :
def get_options ( self , view ) :
2022-03-02 00:56:42 +00:00
return experimentFilterOptions ( )
2022-03-01 21:23:30 +00:00
def apply ( self , query , value , alias = None ) :
values = value . split ( " , " )
experimentNumber = int ( values [ 0 ] )
programId = int ( values [ 1 ] )
return query . filter (
self . column . semester_experiment . has (
SemesterExperiment . experiment . has ( Experiment . program_id == programId )
) ,
self . column . semester_experiment . has (
SemesterExperiment . experiment . has ( Experiment . number == experimentNumber )
) ,
)
2021-07-01 11:12:43 +00:00
class CreateForm ( Form ) :
group = QuerySelectField (
2021-07-13 01:37:00 +00:00
" Group " ,
query_factory = groupQueryFactory ,
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
2021-07-01 11:12:43 +00:00
)
2021-07-01 12:41:20 +00:00
semester_experiment = QuerySelectField (
" Semester Experiment " ,
query_factory = semesterExperimentQueryFactory ,
2021-07-01 11:12:43 +00:00
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
)
2021-08-16 21:32:46 +00:00
appointment1_date = DateField (
" Appointment-1 Date " ,
validators = [ Optional ( ) ] ,
description = " Set if you already want to add an appointment. Otherwise, leave it blank and you can do it later under the Appointment tab. " ,
)
2021-07-12 14:42:11 +00:00
appointment1_special = BooleanField ( " Appointment-1 Special " , default = False )
2021-07-01 11:12:43 +00:00
appointment1_assistant = QuerySelectField (
2021-07-01 14:38:37 +00:00
" Appointment-1 Assistant " ,
2021-07-01 11:12:43 +00:00
query_factory = assistantQueryFactory ,
allow_blank = True ,
blank_text = assistantBlankText ,
)
2021-08-16 21:32:46 +00:00
appointment2_date = DateField (
" Appointment-2 Date " , validators = [ Optional ( ) ] , description = " Add a second appointment (see above). "
)
2021-07-12 14:42:11 +00:00
appointment2_special = BooleanField ( " Appointment-2 Special " , default = False )
2021-07-01 11:12:43 +00:00
appointment2_assistant = QuerySelectField (
2021-07-01 14:38:37 +00:00
" Appointment-2 Assistant " ,
2021-07-01 11:12:43 +00:00
query_factory = assistantQueryFactory ,
allow_blank = True ,
blank_text = assistantBlankText ,
)
form = CreateForm
2021-07-01 14:38:37 +00:00
can_edit = False
2021-07-28 22:31:43 +00:00
2021-11-30 00:41:18 +00:00
column_list = [
" group " ,
" semester_experiment " ,
" appointments " ,
" experiment_marks " ,
]
2022-03-02 00:56:42 +00:00
column_filters = (
2022-03-01 21:23:30 +00:00
ExperimentFilter ( GroupExperiment , " Experiment " ) ,
2022-03-02 00:56:42 +00:00
" group.number " ,
2021-11-30 00:41:18 +00:00
" appointments " ,
2022-03-02 00:56:42 +00:00
" experiment_marks " ,
)
2021-06-24 17:39:26 +00:00
2021-07-12 14:42:11 +00:00
def queryFilter ( self ) :
2021-07-30 13:14:35 +00:00
return GroupExperiment . group . has ( Group . semester == userActiveSemester ( ) )
2021-07-12 11:06:44 +00:00
2021-07-29 22:24:10 +00:00
def customCreateModel ( self , form ) :
return GroupExperiment . customInit ( semester_experiment = form . semester_experiment . data , group = form . group . data )
2021-07-01 17:43:59 +00:00
2021-07-29 22:24:10 +00:00
def on_model_change ( self , form , model , is_created ) :
if is_created :
2021-07-12 12:48:29 +00:00
for date , special , assistant in zip (
2021-07-01 17:43:59 +00:00
[ form . appointment1_date . data , form . appointment2_date . data ] ,
[ form . appointment1_special . data , form . appointment2_special . data ] ,
[ form . appointment1_assistant . data , form . appointment2_assistant . data ] ,
) :
2021-07-12 12:48:29 +00:00
if date :
2021-09-11 13:25:13 +00:00
appointment = Appointment . customInit (
date = date , special = special , group_experiment = model , assistant = assistant
)
2021-07-01 17:43:59 +00:00
self . session . add ( appointment )
2021-07-29 22:24:10 +00:00
def after_model_change ( self , form , model , is_created ) :
if is_created :
2021-07-01 20:20:34 +00:00
if model . appointments :
flash ( f " Appointments { model . appointments } added. " , " success " )
2021-07-01 17:43:59 +00:00
2021-06-24 17:39:26 +00:00
2021-07-12 14:42:11 +00:00
def groupExperimentQueryFactory ( ) :
return GroupExperiment . query . filter (
2021-07-30 13:14:35 +00:00
GroupExperiment . semester_experiment . has ( SemesterExperiment . semester == userActiveSemester ( ) )
2021-07-12 14:42:11 +00:00
)
2022-03-02 00:56:42 +00:00
def assistantFilterOptions ( ) :
assistants = Assistant . query . filter ( Assistant . user . has ( User . active == True ) )
return ( ( assistant . id , assistant . repr ( ) ) for assistant in assistants )
2021-07-30 00:03:44 +00:00
class AppointmentView ( SecureAdminModelView ) :
2022-03-02 00:56:42 +00:00
@expose ( " / " )
def index_view ( self ) :
# To update filter options
self . _refresh_filters_cache ( )
return super ( ) . index_view ( )
class ExperimentFilter ( FilterEqual ) :
def get_options ( self , view ) :
return experimentFilterOptions ( )
def apply ( self , query , value , alias = None ) :
values = value . split ( " , " )
experimentNumber = int ( values [ 0 ] )
programId = int ( values [ 1 ] )
return query . filter (
self . column . group_experiment . has (
GroupExperiment . semester_experiment . has (
SemesterExperiment . experiment . has ( Experiment . program_id == programId )
)
) ,
self . column . group_experiment . has (
GroupExperiment . semester_experiment . has (
SemesterExperiment . experiment . has ( Experiment . number == experimentNumber )
)
) ,
)
class AssistantFilter ( FilterEqual ) :
def get_options ( self , view ) :
return assistantFilterOptions ( )
def apply ( self , query , value , alias = None ) :
return query . filter ( self . column . assistant_id == int ( value ) )
2021-07-12 14:42:11 +00:00
class CreateForm ( Form ) :
group_experiment = QuerySelectField (
2021-07-13 01:37:00 +00:00
" Group Experiment " ,
query_factory = groupExperimentQueryFactory ,
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
2021-07-12 14:42:11 +00:00
)
date = DateField ( " Date " , validators = [ DataRequired ( ) ] )
special = BooleanField ( " Special " , default = False )
assistant = QuerySelectField (
" Assistant " ,
query_factory = assistantQueryFactory ,
allow_blank = True ,
blank_text = assistantBlankText ,
)
form = CreateForm
2022-03-02 00:56:42 +00:00
column_filters = (
ExperimentFilter ( Appointment , " Experiment " ) ,
AssistantFilter ( Appointment , " Assistant " ) ,
" group_experiment.group " ,
2021-07-13 19:49:44 +00:00
" date " ,
" special " ,
2022-03-02 00:56:42 +00:00
)
2021-11-30 00:41:18 +00:00
column_editable_list = [
" date " ,
" special " ,
]
2021-07-12 14:42:11 +00:00
def queryFilter ( self ) :
2021-07-30 13:14:35 +00:00
return Appointment . group_experiment . has (
GroupExperiment . semester_experiment . has ( SemesterExperiment . semester == userActiveSemester ( ) )
2021-07-12 14:42:11 +00:00
)
2021-07-29 22:24:10 +00:00
def customCreateModel ( self , form ) :
return Appointment . customInit (
2021-09-11 13:25:13 +00:00
date = form . date . data ,
special = form . special . data ,
group_experiment = form . group_experiment . data ,
assistant = form . assistant . data ,
2021-07-29 22:24:10 +00:00
)
2021-07-12 14:42:11 +00:00
def update_model ( self , form , model ) :
2021-07-30 21:50:10 +00:00
if not form . date or not form . special : # For editables
return super ( ) . update_model ( form , model )
2021-07-12 14:42:11 +00:00
try :
2021-07-30 21:50:10 +00:00
model . customUpdate ( form . date . data , form . special . data , form . assistant . data , form . group_experiment . data )
2021-07-12 14:42:11 +00:00
self . on_model_change ( form , model , False )
self . session . commit ( )
except Exception as ex :
flash ( str ( ex ) , " error " )
self . session . rollback ( )
return False
else :
self . after_model_change ( form , model , False )
return True
2021-07-01 11:12:43 +00:00
2021-07-30 00:03:44 +00:00
class ExperimentMarkView ( SecureAdminModelView ) :
2022-02-27 18:30:28 +00:00
@expose ( " / " )
def index_view ( self ) :
# To update filter options
self . _refresh_filters_cache ( )
return super ( ) . index_view ( )
2021-07-01 14:38:37 +00:00
2022-02-27 18:30:28 +00:00
class StudentFilter ( FilterEqual ) :
2021-07-01 14:38:37 +00:00
def validate ( self , value ) :
if Student . query . get ( value ) :
return True
else :
return False
2022-03-02 00:56:42 +00:00
def apply ( self , query , value , alias = None ) :
return query . filter ( self . column . part_student . has ( PartStudent . student_id == int ( value ) ) )
2022-02-27 18:30:28 +00:00
class AssistantFilter ( FilterEqual ) :
def get_options ( self , view ) :
2022-03-02 00:56:42 +00:00
return assistantFilterOptions ( )
2022-02-27 18:30:28 +00:00
2022-03-01 21:23:30 +00:00
def apply ( self , query , value , alias = None ) :
2022-03-02 00:56:42 +00:00
return query . filter ( self . column . assistant_id == int ( value ) )
2022-03-01 21:23:30 +00:00
class AdminFilter ( FilterEqual ) :
def get_options ( self , view ) :
2022-03-02 00:56:42 +00:00
admins = Admin . query . filter ( Admin . user . has ( User . active == True ) )
2022-03-01 21:23:30 +00:00
return ( ( admin . id , admin . repr ( ) ) for admin in admins )
def apply ( self , query , value , alias = None ) :
2022-03-02 00:56:42 +00:00
return query . filter ( self . column . admin_id == int ( value ) )
class ExperimentFilter ( FilterEqual ) :
def get_options ( self , view ) :
return experimentFilterOptions ( )
def apply ( self , query , value , alias = None ) :
values = value . split ( " , " )
experimentNumber = int ( values [ 0 ] )
programId = int ( values [ 1 ] )
return query . filter (
self . column . group_experiment . has (
GroupExperiment . semester_experiment . has (
SemesterExperiment . experiment . has ( Experiment . program_id == programId )
)
) ,
self . column . group_experiment . has (
GroupExperiment . semester_experiment . has (
SemesterExperiment . experiment . has ( Experiment . number == experimentNumber )
)
) ,
)
class ProgramFilter ( FilterEqual ) :
def get_options ( self , view ) :
programs = Program . query
return ( ( program . id , program . repr ( ) ) for program in programs )
def apply ( self , query , value , alias = None ) :
return query . filter ( self . column . part_student . has ( PartStudent . part . has ( Part . program_id == int ( value ) ) ) )
class PartFilter ( FilterEqual ) :
def get_options ( self , view ) :
return partFilterOptions ( )
def apply ( self , query , value , alias = None ) :
return query . filter ( self . column . part_student . has ( PartStudent . part_id == int ( value ) ) )
class SemesterFilter ( FilterEqual ) :
def get_options ( self , view ) :
semesters = Semester . query . order_by ( Semester . id . desc ( ) )
return ( ( semester . id , semester . repr ( ) ) for semester in semesters )
def apply ( self , query , value , alias = None ) :
return query . filter (
self . column . group_experiment . has (
GroupExperiment . semester_experiment . has ( SemesterExperiment . semester_id == int ( value ) )
)
)
2022-03-01 21:23:30 +00:00
2021-07-13 00:50:15 +00:00
class CreateForm ( Form ) :
part_student = QuerySelectField (
" Part Student " ,
2021-07-29 21:18:24 +00:00
query_factory = partStudentQueryFactory ,
2021-07-13 00:50:15 +00:00
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
)
group_experiment = QuerySelectField (
" Group Experiment " ,
query_factory = groupExperimentQueryFactory ,
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
)
2021-08-21 20:58:23 +00:00
class EditForm ( Form ) :
oral_mark = IntegerField (
" Oral Mark " ,
validators = [ NumberRange ( min = 0 , max = 15 ) , Optional ( ) ] ,
description = " Between 0 and 15 " ,
)
protocol_mark = IntegerField (
" Protocol Mark " ,
validators = [ NumberRange ( min = 0 , max = 15 ) , Optional ( ) ] ,
description = " Between 0 and 15 " ,
)
2021-07-13 00:50:15 +00:00
2021-08-21 20:58:23 +00:00
form = EditForm
2021-08-18 17:39:21 +00:00
2021-08-16 21:32:46 +00:00
column_descriptions = {
" oral_mark " : " Between 0 and 15 " ,
" protocol_mark " : " Between 0 and 15 " ,
2021-08-29 16:15:14 +00:00
" final_experiment_mark " : " Calculated automatically with oral and protocol marks and weightings " ,
2022-02-27 18:30:28 +00:00
" assistant " : " The last assistant who edited the mark " ,
" admin " : " The last admin who edited the mark " ,
2021-08-16 21:32:46 +00:00
}
2022-03-02 00:56:42 +00:00
column_filters = (
StudentFilter ( ExperimentMark , " Student / ID " ) ,
SemesterFilter ( ExperimentMark , " Semester " ) ,
AssistantFilter ( ExperimentMark , " Assistant " ) ,
AdminFilter ( ExperimentMark , " Admin " ) ,
ExperimentFilter ( ExperimentMark , " Experiment " ) ,
ProgramFilter ( ExperimentMark , " Program " ) ,
PartFilter ( ExperimentMark , " Part " ) ,
2021-07-30 21:42:20 +00:00
" group_experiment.group " ,
2021-08-29 16:15:14 +00:00
" oral_mark " ,
" protocol_mark " ,
" final_experiment_mark " ,
2022-03-02 00:56:42 +00:00
)
2021-07-30 21:42:20 +00:00
column_default_sort = [ ( " oral_mark " , False ) , ( " protocol_mark " , False ) ]
2021-07-13 00:50:15 +00:00
2021-07-31 23:03:27 +00:00
"""
2022-02-13 18:58:05 +00:00
# Deactivated for the experiments history of a student.
2021-07-30 21:42:20 +00:00
def queryFilter ( self ) :
2021-07-30 13:14:35 +00:00
return ExperimentMark . group_experiment . has (
GroupExperiment . semester_experiment . has ( SemesterExperiment . semester == userActiveSemester ( ) )
2021-07-13 00:50:15 +00:00
)
2021-07-31 23:03:27 +00:00
"""
2021-07-13 00:50:15 +00:00
2021-08-21 20:58:23 +00:00
def create_form ( self , obj = None ) :
form = self . CreateForm
return form ( get_form_data ( ) , obj = obj )
2021-08-18 17:39:21 +00:00
def customCreateModel ( self , form ) :
return ExperimentMark . customInit (
part_student = form . part_student . data , group_experiment = form . group_experiment . data
)
2021-08-18 17:07:56 +00:00
def update_model ( self , form , model ) :
if ( form . oral_mark and form . oral_mark . data != model . oral_mark ) or (
form . protocol_mark and form . protocol_mark . data != model . protocol_mark
) :
2022-02-27 18:30:28 +00:00
model . admin = current_user . admin
2021-08-18 17:07:56 +00:00
2021-08-18 23:29:09 +00:00
ret = super ( ) . update_model ( form , model )
model . part_student . checkThenSetFinalPartMark ( )
return ret
else :
# Nothing changed
return True
2021-08-18 17:07:56 +00:00
2021-07-01 14:38:37 +00:00
2021-07-30 00:03:44 +00:00
class ProgramView ( SecureAdminModelView ) :
2021-07-28 23:04:58 +00:00
can_view_details = True
2021-11-30 00:41:18 +00:00
column_list = [
" label " ,
]
form_excluded_columns = [
" parts " ,
" experiments " ,
" groups " ,
]
2021-07-28 23:04:58 +00:00
column_details_list = column_list + form_excluded_columns
2021-07-14 02:27:17 +00:00
2021-09-11 18:53:11 +00:00
class ImportView ( SecureAdminBaseView ) :
class FileForm ( FlaskForm ) :
file = FileField (
label = " Import file " ,
validators = [ FileRequired ( ) , FileAllowed ( [ " txt " ] , " Only txt files are allowed! " ) ] ,
description = " The import file has to be a text file (with .txt at the end) encoded in UTF-8. It has to strictly follow the required format. " ,
)
2022-02-23 23:08:14 +00:00
@expose ( methods = ( " GET " , " POST " ) )
2021-09-11 18:53:11 +00:00
def index ( self ) :
form = ImportView . FileForm ( )
if form . validate_on_submit ( ) :
f = form . file . data
filename = secure_filename ( f . filename )
2022-01-13 01:25:31 +00:00
directory = " db/import_files "
2021-09-11 18:53:11 +00:00
Path ( directory ) . mkdir ( exist_ok = True )
filePath = directory + f " / { filename } "
f . save ( filePath )
try :
importFromFile ( filePath )
except Exception as exc :
flash ( str ( exc ) , " error " )
return redirect ( url_for ( " index " ) )
return self . render ( " import.html " , form = form )
2022-02-23 18:37:09 +00:00
class DocsView ( SecureAdminBaseView ) :
2022-02-23 23:08:14 +00:00
@expose ( )
2022-02-23 18:37:09 +00:00
def index ( self ) :
return self . render ( " docs/admin.html " )
2021-07-30 00:03:44 +00:00
adminSpace . add_view ( StudentView ( Student , db . session ) )
adminSpace . add_view ( PartStudentView ( PartStudent , db . session ) )
adminSpace . add_view ( GroupView ( Group , db . session ) )
adminSpace . add_view ( GroupExperimentView ( GroupExperiment , db . session ) )
adminSpace . add_view ( AppointmentView ( Appointment , db . session ) )
adminSpace . add_view ( ExperimentMarkView ( ExperimentMark , db . session ) )
adminSpace . add_view ( ExperimentView ( Experiment , db . session ) )
adminSpace . add_view ( SemesterExperimentView ( SemesterExperiment , db . session ) )
adminSpace . add_view ( SemesterView ( Semester , db . session ) )
2021-08-15 23:15:19 +00:00
adminSpace . add_view ( PartView ( Part , db . session ) )
adminSpace . add_view ( AssistantView ( Assistant , db . session ) )
2021-07-30 00:03:44 +00:00
adminSpace . add_view ( UserView ( User , db . session ) )
adminSpace . add_view ( RoleView ( Role , db . session ) )
2021-08-15 23:15:19 +00:00
adminSpace . add_view ( ProgramView ( Program , db . session ) )
2021-09-11 18:53:11 +00:00
adminSpace . add_view ( ImportView ( name = " Import " ) )
2022-02-23 18:37:09 +00:00
adminSpace . add_view ( DocsView ( name = " Docs " ) )
2021-04-18 23:33:46 +00:00
2021-07-30 22:12:37 +00:00
initActiveSemesterMenuLinks ( adminSpace )