2021-07-30 21:50:10 +00:00
from flask import flash
2022-02-23 18:37:09 +00:00
from flask_admin import expose
2021-07-30 22:12:37 +00:00
from flask_admin . contrib . sqla . fields import QuerySelectField , QuerySelectMultipleField
2022-02-23 19:36:29 +00:00
from flask_security import admin_change_password , current_user
2021-07-30 22:12:37 +00:00
from sqlalchemy import and_
2021-11-29 19:22:10 +00:00
from wtforms import BooleanField , Form , RadioField , SelectField , StringField
from wtforms . fields import DateField
2022-05-09 00:10:30 +00:00
from wtforms . validators import NumberRange , Optional
2021-07-30 00:50:49 +00:00
2022-05-08 19:26:25 +00:00
from . import assistantSpace , db
from . customClasses import SecureAssistantBaseView , SecureAssistantModelView
from . dependent_funs import (
2022-04-18 16:04:17 +00:00
flashRandomPassword ,
initActiveSemesterMenuLinks ,
userActiveSemester ,
)
2022-05-08 19:26:25 +00:00
from . exceptions import DataBaseException , ModelViewException
from . independent_funs import randomPassword
from . models import (
2022-04-11 23:44:53 +00:00
MAX_MARK ,
MIN_MARK ,
2021-07-30 00:50:49 +00:00
Appointment ,
Assistant ,
Experiment ,
ExperimentMark ,
Group ,
GroupExperiment ,
Part ,
PartStudent ,
2021-07-30 12:20:54 +00:00
Program ,
2021-07-30 00:50:49 +00:00
Role ,
Semester ,
2021-07-30 12:20:54 +00:00
SemesterExperiment ,
2021-07-30 00:50:49 +00:00
Student ,
User ,
)
2021-07-30 21:50:10 +00:00
class AssistantAppointmentView ( SecureAssistantModelView ) :
2022-02-24 00:28:09 +00:00
can_edit = True
2021-07-31 22:41:21 +00:00
column_list = [
" date " ,
" special " ,
" group_experiment.semester_experiment.experiment " ,
" group_experiment.group " ,
" group_experiment.group.part_students " ,
]
column_labels = {
" group_experiment.semester_experiment.experiment " : " Experiment " ,
" group_experiment.group " : " Group " ,
" group_experiment.group.part_students " : " Students " ,
}
2021-11-30 00:47:37 +00:00
column_editable_list = [
" date " ,
]
2022-02-24 00:28:09 +00:00
form_columns = column_editable_list
2021-07-30 21:50:10 +00:00
def queryFilter ( self ) :
return and_ (
Appointment . group_experiment . has (
GroupExperiment . semester_experiment . has ( SemesterExperiment . semester == userActiveSemester ( ) )
) ,
Appointment . assistant == current_user . assistant ,
)
class AssistantExperimentMarkView ( SecureAssistantModelView ) :
2022-02-24 00:28:09 +00:00
can_edit = True
2021-07-31 22:41:21 +00:00
column_list = [
" oral_mark " ,
" protocol_mark " ,
2021-08-29 16:15:14 +00:00
" final_experiment_mark " ,
2021-07-31 22:41:21 +00:00
" group_experiment.semester_experiment.experiment " ,
" part_student.student.first_name " ,
" part_student.student.last_name " ,
" part_student.group " ,
" part_student.student.uni_email " ,
" part_student.student.contact_email " ,
" part_student.part " ,
" assistant " ,
2022-02-27 18:30:28 +00:00
" admin " ,
2021-07-31 22:41:21 +00:00
]
column_labels = {
" group_experiment.semester_experiment.experiment " : " Experiment " ,
" part_student.student.first_name " : " First Name " ,
" part_student.student.last_name " : " Last Name " ,
" part_student.group " : " Group " ,
" part_student.student.uni_email " : " Uni Email " ,
" part_student.student.contact_email " : " Contact Email " ,
" part_student.part " : " Part " ,
}
column_descriptions = {
2022-04-11 23:44:53 +00:00
" oral_mark " : f " Between { MIN_MARK } and { MAX_MARK } " ,
" protocol_mark " : f " Between { MIN_MARK } and { MAX_MARK } " ,
2021-08-29 16:15:14 +00:00
" final_experiment_mark " : " Calculated automatically with oral and protocol marks and weightings " ,
2021-07-31 22:41:21 +00:00
" part_student.student.contact_email " : " The preferred contact email address if entered by the student " ,
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-07-31 22:41:21 +00:00
}
2021-11-30 00:47:37 +00:00
column_editable_list = [
" oral_mark " ,
" protocol_mark " ,
]
2022-02-24 00:28:09 +00:00
form_columns = column_editable_list
2021-07-30 21:50:10 +00:00
form_args = {
2022-04-11 23:44:53 +00:00
" oral_mark " : { " validators " : [ NumberRange ( MIN_MARK , MAX_MARK ) ] } ,
" protocol_mark " : { " validators " : [ NumberRange ( MIN_MARK , MAX_MARK ) ] } ,
2021-07-30 21:50:10 +00:00
}
2021-07-30 00:50:49 +00:00
2021-07-30 21:50:10 +00:00
column_default_sort = [ ( " oral_mark " , False ) , ( " protocol_mark " , False ) ]
2021-07-30 00:50:49 +00:00
2021-07-30 21:50:10 +00:00
def queryFilter ( self ) :
return ExperimentMark . group_experiment . has (
GroupExperiment . semester_experiment . has (
and_ (
SemesterExperiment . semester == userActiveSemester ( ) ,
SemesterExperiment . assistants . any ( Assistant . user == current_user ) ,
)
)
2021-07-30 00:50:49 +00:00
)
2021-08-21 21:08:32 +00:00
def update_model ( self , form , model ) :
2022-05-15 20:25:19 +00:00
if ( form . oral_mark is not None and form . oral_mark . data != model . oral_mark ) or (
form . protocol_mark is not None and form . protocol_mark . data != model . protocol_mark
2021-08-21 21:08:32 +00:00
) :
model . assistant = current_user . assistant
2021-07-30 00:50:49 +00:00
2022-05-15 20:25:19 +00:00
updateSuccessful = super ( ) . update_model ( form , model )
2021-07-30 00:50:49 +00:00
2021-08-21 21:08:32 +00:00
model . part_student . checkThenSetFinalPartMark ( )
2022-05-15 20:25:19 +00:00
return updateSuccessful
2021-08-21 21:08:32 +00:00
else :
# Nothing changed
return True
2021-07-30 00:50:49 +00:00
2021-07-30 21:50:10 +00:00
2021-11-30 00:47:37 +00:00
class AssistantUserView ( SecureAssistantModelView ) :
2022-02-23 19:36:29 +00:00
class EditForm ( Form ) :
2022-05-08 20:04:08 +00:00
phone_number = StringField (
" Phone Number " ,
validators = [ Optional ( ) ] ,
)
mobile_phone_number = StringField (
" Mobile Phone Number " ,
validators = [ Optional ( ) ] ,
)
2022-02-23 19:36:29 +00:00
2022-05-08 20:04:08 +00:00
building = StringField (
" Building " ,
validators = [ Optional ( ) ] ,
)
room = StringField (
" Room " ,
validators = [ Optional ( ) ] ,
)
2022-02-23 19:36:29 +00:00
2022-05-08 20:04:08 +00:00
generate_new_password = BooleanField (
" Generate new random password. For security reasons, it is not possible to manually enter a password. Please use a password manager like Bitwarden or KeepassXC to save the randomly generated password. " ,
default = False ,
)
2022-02-23 19:36:29 +00:00
can_edit = True
column_display_actions = True
2021-11-30 00:47:37 +00:00
column_sortable_list = [ ]
column_list = [
" email " ,
" phone_number " ,
" mobile_phone_number " ,
" building " ,
2022-02-23 19:36:29 +00:00
" room " ,
2021-11-30 00:47:37 +00:00
" assistant.semester_experiments " ,
]
column_labels = {
" assistant.semester_experiments " : " Semester Experiments " ,
}
def queryFilter ( self ) :
return User . id == current_user . id
2022-02-23 19:36:29 +00:00
def on_model_change ( self , form , model , is_created ) :
if form . generate_new_password . data :
password = randomPassword ( )
flashRandomPassword ( password )
admin_change_password ( model , password , notify = False ) # Password is automatically hashed with this function
2021-11-30 00:47:37 +00:00
2022-02-23 18:37:09 +00:00
class AssistantDocsView ( SecureAssistantBaseView ) :
2022-03-04 02:49:02 +00:00
@expose ( " / " )
2022-02-23 18:37:09 +00:00
def index ( self ) :
return self . render ( " docs/assistant.html " )
2021-07-30 21:50:10 +00:00
assistantSpace . add_view (
AssistantAppointmentView ( Appointment , db . session , endpoint = " assistant_appointment " , url = " appointment " )
)
2021-07-30 00:50:49 +00:00
assistantSpace . add_view (
2021-07-30 21:50:10 +00:00
AssistantExperimentMarkView ( ExperimentMark , db . session , endpoint = " assistant_experimentmark " , url = " experimentmark " )
2021-07-30 00:50:49 +00:00
)
2021-11-30 00:47:37 +00:00
assistantSpace . add_view ( AssistantUserView ( User , db . session , endpoint = " assistant_user " , url = " user " ) )
2022-02-23 18:37:09 +00:00
assistantSpace . add_view ( AssistantDocsView ( name = " Docs " , endpoint = " assistant_docs " , url = " docs " ) )
2021-07-30 22:12:37 +00:00
initActiveSemesterMenuLinks ( assistantSpace )