Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
dff58e0
Removed evaluation column from term management page
Jonimz Mar 16, 2026
ebe4036
Removed Evaluations column from term management table, including
Jonimz Mar 30, 2026
1ec26c2
Merge branch 'development' of https://github.com/BCStudentSoftwareDev…
JohnCox2211 Mar 31, 2026
3a158a7
Merge branch '522-remove-evaluation-buttons-from-term-management' of …
JohnCox2211 Mar 31, 2026
3d68c86
updated student labor evaluation form/controller/template after remov…
Jonimz Apr 8, 2026
4c65401
Remove midyear/final evaluation branching from student labor evaluation
Jonimz Apr 8, 2026
74b9422
Merge branch 'development' into 522-remove-evaluation-buttons-from-te…
Jonimz Apr 8, 2026
d94f939
Merge branch '522-remove-evaluation-buttons-from-term-management' of …
JohnCox2211 Apr 9, 2026
56ffec8
Add default boolean fields isFinalEvaluationOpen and isMidyearEvaluat…
Jonimz Apr 13, 2026
1450021
Remove unused evaluation status fields to match the database schema.
Jonimz May 2, 2026
6c03a95
Merge branch 'development' into 522-remove-evaluation-buttons-from-te…
MImran2002 Jun 12, 2026
d78a67f
removed extension"
MImran2002 Jun 12, 2026
2696bcd
Delete app/static/js/ckeditor/samples/toolbarconfigurator/lib/codemir…
MImran2002 Jun 12, 2026
d492600
Delete app/static/js/ckeditor/.DS_Store
MImran2002 Jun 12, 2026
f1e1f1c
Delete database/fix-fall-positions/.DS_Store
MImran2002 Jun 12, 2026
73b636a
Delete database/.DS_Store
MImran2002 Jun 12, 2026
207c7c8
removed unncessary files
MImran2002 Jun 12, 2026
297f32e
some backend functions remove for stud evals
MImran2002 Jun 12, 2026
41a8550
talked with Brian the model are kept to make sure data is not removed
MImran2002 Jun 12, 2026
353eed7
talked with Brian the model are kept to make sure data is not removed
MImran2002 Jun 12, 2026
d8540e8
make sure all the download button are working
MImran2002 Jun 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/admin_routes/allPendingForms.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ def downloadAllPendingForms():
additionalSpreadsheetFields=additionalSpreadsheetFields
)

return send_file(excel.relativePath, as_attachment=True, attachment_filename=excel.relativePath.split('/').pop())
return send_file(excel.relativePath, as_attachment=True, download_name=excel.relativePath.split('/').pop())

@admin.route('/admin/checkedForms', methods=['POST'])
def approved_and_denied_Forms():
Expand Down
19 changes: 0 additions & 19 deletions app/controllers/admin_routes/termManagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,22 +115,3 @@ def termStatusCheck():
except Exception as e:
print(e)
return jsonify({"Success": False})

@admin.route('/termManagement/manageEval', methods=['POST'])
def manageEval():
try:
rsp = eval(request.data.decode("utf-8")) # This fixes byte indices must be integers or slices error
if rsp:
term = Term.get(rsp['evalBtn'])
if rsp["isMidyear"]:
term.isMidyearEvaluationOpen = not term.isMidyearEvaluationOpen
term.isFinalEvaluationOpen = False
else:
term.isFinalEvaluationOpen = not term.isFinalEvaluationOpen
term.isMidyearEvaluationOpen = False
term.save()
flasherInfo = {'termChanged': term.termName}
return jsonify(flasherInfo)
except Exception as e:
print(e)
return jsonify({}, 500)
3 changes: 1 addition & 2 deletions app/controllers/main_routes/laborHistory.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,8 @@ def downloadFormHistory():
formSearchResults.searchType,
requestedLSFs=formHistories,
additionalSpreadsheetFields=[],
includeEvals=False
)
return send_file(excel.relativePath, mimetype='text/csv', as_attachment=True, attachment_filename=excel.relativePath.split('/').pop())
return send_file(excel.relativePath, mimetype='text/csv', as_attachment=True, download_name=excel.relativePath.split('/').pop())

@main_bp.route('/laborHistory/modal/<statusKey>', methods=['GET'])
def populateModal(statusKey):
Expand Down
3 changes: 1 addition & 2 deletions app/controllers/main_routes/main_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,8 @@ def downloadSupervisorPortalResults():
formSearchResults.searchType,
requestedLSFs=formHistories,
additionalSpreadsheetFields=[],
includeEvals=False
)
return send_file(excel.relativePath, as_attachment=True, attachment_filename=excel.relativePath.split('/').pop())
return send_file(excel.relativePath, as_attachment=True, download_name=excel.relativePath.split('/').pop())

@main_bp.route('/supervisorPortal/liveSearch', methods=['GET'])
def SupervisorPortalSearch():
Expand Down
86 changes: 17 additions & 69 deletions app/controllers/main_routes/studentLaborEvaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,24 @@ class SLEForm(FlaskForm):

attendance = IntegerRangeField("Attendance", default = 15, render_kw={'class':'form-control slider'})
attendanceComments = TextAreaField("Comments about attendance:", [Length(max=65535)], render_kw={'class':'form-control'})
attendanceCommentsMidyear = TextAreaField("Attendance comments from Midyear :", render_kw={'class':'form-control', 'readonly': True})

accountability = IntegerRangeField("Accountability", default = 7, render_kw={'class':'form-control slider'})
accountabilityComments = TextAreaField("Comments about accountability:", [Length(max=65535)], render_kw={'class':'form-control'})
accountabilityCommentsMidyear = TextAreaField("Attendance comments from Midyear :", render_kw={'class':'form-control', 'readonly': True})

teamwork = IntegerRangeField("Teamwork", default = 7, render_kw={'class':'form-control slider'})
teamworkComments = TextAreaField("Comments about teamwork:", [Length(max=65535)], render_kw={'class':'form-control'})
teamworkCommentsMidyear = TextAreaField("Attendance comments from Midyear :", render_kw={'class':'form-control', 'readonly': True})

initiative = IntegerRangeField("Initiative", default = 7, render_kw={'class':'form-control slider'})
initiativeComments = TextAreaField("Comments about initiative:", [Length(max=65535)], render_kw={'class':'form-control'})
initiativeCommentsMidyear = TextAreaField("Attendance comments from Midyear :", render_kw={'class':'form-control', 'readonly': True})

respect = IntegerRangeField("Respect", default = 7, render_kw={'class':'form-control slider'})
respectComments = TextAreaField("Comments about respect:", [Length(max=65535)], render_kw={'class':'form-control'})
respectCommentsMidyear = TextAreaField("Attendance comments from Midyear :", render_kw={'class':'form-control', 'readonly': True})

learning = IntegerRangeField("Learning", default = 15, render_kw={'class':'form-control slider'})
learningComments = TextAreaField("Comments about learning:", [Length(max=65535)], render_kw={'class':'form-control'})
learningCommentsMidyear = TextAreaField("Attendance comments from Midyear :", render_kw={'class':'form-control', 'readonly': True})

jobSpecific = IntegerRangeField("Job Specific", default = 15, render_kw={'class':'form-control slider'})
jobSpecificComments = TextAreaField("Comments about this job, specifically:", [Length(max=65535)], render_kw={'class':'form-control'})
jobSpecificCommentsMidyear = TextAreaField("Attendance comments from Midyear :", render_kw={'class':'form-control', 'readonly': True})

transcriptComments = TextAreaField("Labor Transcript comments:", [Length(max=65535)], render_kw={'class':'form-control'})

Expand Down Expand Up @@ -73,30 +66,15 @@ def sle(statusKey):
return render_template('errors/403.html'), 403

sleForm = SLEForm()
existing_final_evaluation = StudentLaborEvaluation.get_or_none(formHistoryID = laborHistoryForm, is_midyear_evaluation = False, is_submitted = True)
existing_midyear_evaluation = StudentLaborEvaluation.get_or_none(formHistoryID = laborHistoryForm, is_midyear_evaluation = True, is_submitted = True)
existing_evaluation = (StudentLaborEvaluation.select()
.where(StudentLaborEvaluation.formHistoryID == laborHistoryForm, StudentLaborEvaluation.is_submitted == True)
.order_by(StudentLaborEvaluation.date_submitted.desc(nulls="LAST"), StudentLaborEvaluation.ID.desc())
.first())
existing_saved_evaluation = StudentLaborEvaluation.select().where(StudentLaborEvaluation.formHistoryID == laborHistoryForm, StudentLaborEvaluation.is_submitted == False)
if existing_saved_evaluation:
existing_saved_evaluation = existing_saved_evaluation[-1]

if not request.method == "POST": # Doesn't override submitted POST data!
if existing_midyear_evaluation: # TODO Or there's savedforlater data
sleForm.attendance.data = existing_midyear_evaluation.attendance_score
sleForm.accountability.data = existing_midyear_evaluation.accountability_score
sleForm.teamwork.data = existing_midyear_evaluation.teamwork_score
sleForm.initiative.data = existing_midyear_evaluation.initiative_score
sleForm.respect.data = existing_midyear_evaluation.respect_score
sleForm.learning.data = existing_midyear_evaluation.learning_score
sleForm.jobSpecific.data = existing_midyear_evaluation.jobSpecific_score

sleForm.attendanceCommentsMidyear.data = "Midyear comments: \n" + existing_midyear_evaluation.attendance_comment
sleForm.accountabilityCommentsMidyear.data = "Midyear comments: \n" + existing_midyear_evaluation.accountability_comment
sleForm.teamworkCommentsMidyear.data = "Midyear comments: \n" + existing_midyear_evaluation.teamwork_comment
sleForm.initiativeCommentsMidyear.data = "Midyear comments: \n" + existing_midyear_evaluation.initiative_comment
sleForm.respectCommentsMidyear.data = "Midyear comments: \n" + existing_midyear_evaluation.respect_comment
sleForm.learningCommentsMidyear.data = "Midyear comments: \n" + existing_midyear_evaluation.learning_comment
sleForm.jobSpecificCommentsMidyear.data = "Midyear comments: \n" + existing_midyear_evaluation.jobSpecific_comment

if existing_saved_evaluation:
sleForm.attendance.data = existing_saved_evaluation.attendance_score
sleForm.accountability.data = existing_saved_evaluation.accountability_score
Expand All @@ -115,48 +93,23 @@ def sle(statusKey):
sleForm.jobSpecificComments.data = existing_saved_evaluation.jobSpecific_comment
sleForm.transcriptComments.data = existing_saved_evaluation.transcript_comment


if not (laborHistoryForm.formID.termCode.isFinalEvaluationOpen or laborHistoryForm.formID.termCode.isMidyearEvaluationOpen) and not existing_final_evaluation and not existing_midyear_evaluation:
return render_template('errors/403.html'), 403

overall_score = 73 # The default value
if existing_final_evaluation:
overall_score = (existing_final_evaluation.attendance_score +
existing_final_evaluation.accountability_score +
existing_final_evaluation.teamwork_score +
existing_final_evaluation.initiative_score +
existing_final_evaluation.respect_score +
existing_final_evaluation.learning_score +
existing_final_evaluation.jobSpecific_score)
elif existing_midyear_evaluation:
overall_score = (existing_midyear_evaluation.attendance_score +
existing_midyear_evaluation.accountability_score +
existing_midyear_evaluation.teamwork_score +
existing_midyear_evaluation.initiative_score +
existing_midyear_evaluation.respect_score +
existing_midyear_evaluation.learning_score +
existing_midyear_evaluation.jobSpecific_score)
if existing_evaluation:
overall_score = (existing_evaluation.attendance_score +
existing_evaluation.accountability_score +
existing_evaluation.teamwork_score +
existing_evaluation.initiative_score +
existing_evaluation.respect_score +
existing_evaluation.learning_score +
existing_evaluation.jobSpecific_score)

if sleForm.validate_on_submit():
# Handling Booleanfields are tricky...
try:
submitAsFinal = True if request.form["submit_as_final"] else False
except BadRequestKeyError:
submitAsFinal = False

# First delete any temporarily saved data (is_submitted = False)
if not laborHistoryForm.formID.termCode.isMidyearEvaluationOpen: # Final eval
is_midyear_evaluation = False
elif submitAsFinal: # Midyear submitted as final
is_midyear_evaluation = False
else: # Midyear
is_midyear_evaluation = True
try:
sle = StudentLaborEvaluation.get(formHistoryID = laborHistoryForm, is_submitted = False, is_midyear_evaluation = is_midyear_evaluation)
sle = StudentLaborEvaluation.get(formHistoryID = laborHistoryForm, is_submitted = False)
sle.delete_instance()
except DoesNotExist:
pass
# Then, save the new record

studentLaborEvaluation = StudentLaborEvaluation.create(
formHistoryID = laborHistoryForm,
attendance_score = sleForm.attendance.data,
Expand All @@ -178,10 +131,7 @@ def sle(statusKey):
submitted_by = currentUser,
date_submitted = date.today()
)
if laborHistoryForm.formID.termCode.isMidyearEvaluationOpen and not submitAsFinal:
studentLaborEvaluation.is_midyear_evaluation = True
studentLaborEvaluation.save()
# Use first and last (so preferred name works)
msg = f"Thank you for submitting a labor evaluation for {laborHistoryForm.formID.studentSupervisee.FIRST_NAME} {laborHistoryForm.formID.studentSupervisee.LAST_NAME}!"
flash(msg, "success")
return redirect("/")
Expand All @@ -190,18 +140,16 @@ def sle(statusKey):
# Only approved evaluations get an SLE, so send them home.
return redirect("/")

if existing_final_evaluation and existing_final_evaluation.date_submitted:
submittedDate = existing_final_evaluation.date_submitted.strftime("%m-%d-%Y")
if existing_evaluation and existing_evaluation.date_submitted:
submittedDate = existing_evaluation.date_submitted.strftime("%m-%d-%Y")
else:
submittedDate = None

return render_template("main/studentLaborEvaluation.html",
form = sleForm,
laborHistoryForm = laborHistoryForm,
existing_final_evaluation = existing_final_evaluation,
existing_midyear_evaluation = existing_midyear_evaluation,
existing_evaluation = existing_evaluation,
date_submitted = submittedDate,
overall_score = overall_score,
isFinalEvaluationOpen = laborHistoryForm.formID.termCode.isFinalEvaluationOpen,
currentUser = currentUser
)
95 changes: 4 additions & 91 deletions app/logic/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,17 @@ class CSVMaker:
'''
Create the CSV for the download bottons
'''
def __init__(self, downloadName, requestedLSFs: ModelSelect, includeEvals = False, additionalSpreadsheetFields: list[str] = []):
def __init__(self, downloadName, requestedLSFs: ModelSelect, additionalSpreadsheetFields: list[str] = []):
self.relativePath = f'static/files/{downloadName}.csv'
self.completePath = 'app/' + self.relativePath
self.additionalSpreadsheetFields = (self._validateAdditionalSpreadsheetFields(additionalSpreadsheetFields))
self.formHistories = requestedLSFs
self.includeEvals = includeEvals
self.makeCSV()

@staticmethod
def _validateAdditionalSpreadsheetFields(additionalFields):
for additionalField in additionalFields:
if additionalField not in {'overloads', 'finalEvaluations', 'midYearEvaluations', 'allEvaluations'}:
if additionalField not in {'overloads', 'allEvaluations'}:
raise ValueError(f'Invalid spreadsheet fields: {additionalField}')
return additionalFields

Expand Down Expand Up @@ -74,24 +73,6 @@ def makeCSV(self):
'Supervisor Email',
'Supervisor Notes'
])
if self.includeEvals:
headers.extend(['SLE Type',
'SLE Attendance',
'SLE Attendance Comments',
'SLE Accountability',
'SLE Accountability Comments',
'SLE Teamwork',
'SLE Teamwork Comments',
'SLE Initiative',
'SLE Initiative Comments',
'SLE Respect',
'SLE Respect Comments',
'SLE Learning',
'SLE Learning Comments',
'SLE Job Specific',
'SLE Job Specific Comments',
'SLE Overall Score'
])

if 'overloads' in self.additionalSpreadsheetFields:
headers.extend(['Student Overload Reason',
Expand All @@ -109,22 +90,7 @@ def makeCSV(self):

for form in self.formHistories:
row = self.addPrimaryData(form)
if self.includeEvals:
evalRows = self.addEvaluationData(form.formHistoryID)
if len(evalRows) == 0:
self.filewriter.writerow(row)
elif len(evalRows) == 1:
row.extend(evalRows[0])
self.filewriter.writerow(row)
else:
row.extend(evalRows[0])
self.filewriter.writerow(row)
for evaluation in evalRows[1:]:
row = [""] * 17
row.extend(evaluation)
self.filewriter.writerow(row)

elif 'overloads' in self.additionalSpreadsheetFields:
if 'overloads' in self.additionalSpreadsheetFields:
row = self.addOverloadData(form, row)
self.filewriter.writerow(row)
else:
Expand Down Expand Up @@ -178,57 +144,4 @@ def addOverloadData(self, form, rowData):

return rowData


def addEvaluationData(self, formID):
'''
Adds data for SLE
'''
multipleRows = []
if "finalEvaluations" in self.additionalSpreadsheetFields:
finalEvaluation = StudentLaborEvaluation.get_or_none(StudentLaborEvaluation.formHistoryID == formID, StudentLaborEvaluation.is_midyear_evaluation == 0, StudentLaborEvaluation.is_submitted == True)
if finalEvaluation:
multipleRows.append(self.insertEvaluationData(finalEvaluation, "Final"))
elif "midYearEvaluations" in self.additionalSpreadsheetFields:
midyearEvaluation = StudentLaborEvaluation.get_or_none(StudentLaborEvaluation.formHistoryID == formID, StudentLaborEvaluation.is_midyear_evaluation == 1, StudentLaborEvaluation.is_submitted == True)
if midyearEvaluation:
multipleRows.append(self.insertEvaluationData(midyearEvaluation, "Midyear"))
elif self.includeEvals == True:
anyEvaluation = StudentLaborEvaluation.select().where(StudentLaborEvaluation.formHistoryID == formID, StudentLaborEvaluation.is_submitted == True)
if anyEvaluation:
for evaluation in anyEvaluation:
multipleRows.append(self.insertEvaluationData(evaluation, "Midyear" if evaluation.is_midyear_evaluation else "Final"))
else:
return []

return multipleRows

def insertEvaluationData(self, evaluation, evalType):
'''
Helper function for self.addEvaluationData(); Adds individual row's SLE data
'''
tableRow = []
tableRow.extend([ evalType,
evaluation.attendance_score,
evaluation.attendance_comment,
evaluation.accountability_score,
evaluation.accountability_comment,
evaluation.teamwork_score,
evaluation.teamwork_comment,
evaluation.initiative_score,
evaluation.initiative_comment,
evaluation.respect_score,
evaluation.respect_comment,
evaluation.learning_score,
evaluation.learning_comment,
evaluation.jobSpecific_score,
evaluation.jobSpecific_comment
])
tableRow.append(evaluation.attendance_score +
evaluation.accountability_score +
evaluation.teamwork_score +
evaluation.initiative_score +
evaluation.respect_score +
evaluation.learning_score +
evaluation.jobSpecific_score
)
return tableRow

Loading