From 4a7be6c221f2357d194bb3eb59648d609b61c1e6 Mon Sep 17 00:00:00 2001 From: georgievh Date: Tue, 30 Jun 2026 18:45:26 +0000 Subject: [PATCH 001/163] edited supervisorDepartment --- app/models/supervisorDepartment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/supervisorDepartment.py b/app/models/supervisorDepartment.py index 3585e1eb2..059712cc0 100644 --- a/app/models/supervisorDepartment.py +++ b/app/models/supervisorDepartment.py @@ -5,3 +5,4 @@ class SupervisorDepartment(baseModel): supervisor = ForeignKeyField(Supervisor, null=True) department = ForeignKeyField(Department) + banStatus = From 12d8d41764fd03ddc59c8421d63a770ac17f235f Mon Sep 17 00:00:00 2001 From: georgievh Date: Tue, 30 Jun 2026 18:45:55 +0000 Subject: [PATCH 002/163] edited supervisorDepartment --- app/models/supervisorDepartment.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/models/supervisorDepartment.py b/app/models/supervisorDepartment.py index 059712cc0..72a80ea6d 100644 --- a/app/models/supervisorDepartment.py +++ b/app/models/supervisorDepartment.py @@ -5,4 +5,12 @@ class SupervisorDepartment(baseModel): supervisor = ForeignKeyField(Supervisor, null=True) department = ForeignKeyField(Department) - banStatus = + banStatus = BooleanField(default=False) + isActive = BooleanField(default=False) + isCoordinator = BooleanField(default=False) + + @property + def isBanned(self): + return self.banStatus + + From a8684550b6260b90bf55507dda69b96868847796 Mon Sep 17 00:00:00 2001 From: feitsopb Date: Tue, 30 Jun 2026 19:15:25 +0000 Subject: [PATCH 003/163] added the position history file --- app/models/positionHistory.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 app/models/positionHistory.py diff --git a/app/models/positionHistory.py b/app/models/positionHistory.py new file mode 100644 index 000000000..f255dfbcb --- /dev/null +++ b/app/models/positionHistory.py @@ -0,0 +1,10 @@ +from app.models import * +from app.models.department import Department + +class PositionHistory(baseModel): + positioncode = PrimaryKeyField() + status = CharField() + WLS = IntegerField() + revisiondate = DateField() + Description = TextField() + Department = ForeignKeyField(Department) From 83c8c92e2fa28e5be183c8f09da4f8cdca317170 Mon Sep 17 00:00:00 2001 From: lolongaj Date: Tue, 30 Jun 2026 19:33:08 +0000 Subject: [PATCH 004/163] added the allocation model --- app/models/allocation.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 app/models/allocation.py diff --git a/app/models/allocation.py b/app/models/allocation.py new file mode 100644 index 000000000..ddd2084d7 --- /dev/null +++ b/app/models/allocation.py @@ -0,0 +1,19 @@ +from app.models import * +from app.models.department import Department +from app.models.supervisor import Supervisor +from app.models.term import Term + +class Allocation(baseModel): + termCode = ForeignKeyField(Term) + department = ForeignKeyField(Department) + isApproved = BooleanField(default=False) + approvedOn = DateField() + approvedBy = ForeignKeyField(Supervisor) + justification = TextField() + primary_10 = IntegerField() + primary_12 = IntegerField() + primary_15 = IntegerField() + primary_20 = IntegerField() + secondary_5 = IntegerField() + secondary_10 = IntegerField() + breakHours = IntegerField() From caad7d3733365f898f5031131bbdb07a8867e073 Mon Sep 17 00:00:00 2001 From: nahom70 Date: Tue, 30 Jun 2026 21:03:46 +0000 Subject: [PATCH 005/163] Added dummy data: weren't able to check if they work though --- database/demo_data.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/database/demo_data.py b/database/demo_data.py index 0557c9361..2d3ad1bdc 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -17,6 +17,8 @@ from app.models.laborStatusForm import LaborStatusForm from app.models.formHistory import FormHistory from app.models.notes import Notes +from app.models.positionHistory import PositionHistory # type: ignore + print("Inserting data for demo and testing purposes") @@ -609,3 +611,29 @@ ] Notes.insert_many(notes).on_conflict_replace().execute() print(" * laborOfficeNotes added") + + + +############################# +# Position History +############################# + +positionHistory = [ + { + "positioncode": 1, + "status": "Active", + "WLS":3, + "revisiondate" : "2020-01-01", + "Description": "This is a test data for position history code 1", + "Department" : "ACCT" + }, + { + "positioncode": 2, + "status": "Inactive", + "WLS":2, + "revisiondate" : "2023-01-01", + "Description": "This is a test data for position history code 2", + "Department" : "Computer Science" + }, +] +PositionHistory.insert_many(positionHistory).on_conflict_replace().execute() \ No newline at end of file From bea1a8c637863aa3720463af7f7180eaec488f34 Mon Sep 17 00:00:00 2001 From: Dayton Conwell Date: Tue, 30 Jun 2026 21:29:41 +0000 Subject: [PATCH 006/163] changed migrate_db.sh data to add PositionHistory, and added dummy data to demo_data.py --- database/demo_data.py | 13 +++++++++++++ database/migrate_db.sh | 1 + 2 files changed, 14 insertions(+) diff --git a/database/demo_data.py b/database/demo_data.py index 0557c9361..e55edb130 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -17,6 +17,9 @@ from app.models.laborStatusForm import LaborStatusForm from app.models.formHistory import FormHistory from app.models.notes import Notes +from app.models.allocation import Allocation +from app.models.positionHistory import PositionHistory +from app.models.supervisorDepartment import SupervisorDepartment print("Inserting data for demo and testing purposes") @@ -609,3 +612,13 @@ ] Notes.insert_many(notes).on_conflict_replace().execute() print(" * laborOfficeNotes added") +print(PositionHistory()) + +PositionHistory.insert([{ + "positioncode": "S61407", + "status": "Active", + "WLS": 1, + "revisiondate": f"{current_year}-04-01", + "Description": "Student Programmer", + "Department_id": 1 +}]).on_conflict_replace().execute() diff --git a/database/migrate_db.sh b/database/migrate_db.sh index f88c91f26..83f68a048 100755 --- a/database/migrate_db.sh +++ b/database/migrate_db.sh @@ -30,6 +30,7 @@ pem add app.models.supervisor.Supervisor pem add app.models.supervisorDepartment.SupervisorDepartment pem add app.models.studentLaborEvaluation.StudentLaborEvaluation pem add app.models.formSearchResult.FormSearchResult +pem add app.models.positionHistory.PositionHistory pem watch pem migrate From 2978b55ea3d277fc3a75e1a2ea12d7d58968a95f Mon Sep 17 00:00:00 2001 From: lolongaj Date: Tue, 30 Jun 2026 21:29:46 +0000 Subject: [PATCH 007/163] allocation table added --- database/demo_data.py | 22 ++++++++++++++++++++++ database/migrate_db.sh | 1 + 2 files changed, 23 insertions(+) diff --git a/database/demo_data.py b/database/demo_data.py index 0557c9361..34c80a3f5 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -17,6 +17,8 @@ from app.models.laborStatusForm import LaborStatusForm from app.models.formHistory import FormHistory from app.models.notes import Notes +from app.models.allocation import Allocation + print("Inserting data for demo and testing purposes") @@ -609,3 +611,23 @@ ] Notes.insert_many(notes).on_conflict_replace().execute() print(" * laborOfficeNotes added") + +allocation =[ + { + "termCode":f"{current_year}00", + "department": 3, + "isApproved": True, + "approvedOn": f"{current_year}-06-30", + "approvedBy": "B12365892", + "justification": "We just want it for fun", + "primary_10": 2, + "primary_12": 3, + "primary_15": 1, + "primary_20": 6, + "secondary_5": 2, + "secondary_10": 0, + "breakHours": 500 + } + ] +Allocation.insert_many(allocation).on_conflict_replace().execute() +print(" * allocation added") \ No newline at end of file diff --git a/database/migrate_db.sh b/database/migrate_db.sh index f88c91f26..5788fbead 100755 --- a/database/migrate_db.sh +++ b/database/migrate_db.sh @@ -30,6 +30,7 @@ pem add app.models.supervisor.Supervisor pem add app.models.supervisorDepartment.SupervisorDepartment pem add app.models.studentLaborEvaluation.StudentLaborEvaluation pem add app.models.formSearchResult.FormSearchResult +pem add app.models.allocation.Allocation pem watch pem migrate From 912f50f9fff9bdeea403b32c7a6abb34863f1122 Mon Sep 17 00:00:00 2001 From: georgievh Date: Tue, 30 Jun 2026 21:30:09 +0000 Subject: [PATCH 008/163] dummy allocations added --- database/demo_data.py | 123 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/database/demo_data.py b/database/demo_data.py index 0557c9361..d5eef179a 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -17,6 +17,10 @@ from app.models.laborStatusForm import LaborStatusForm from app.models.formHistory import FormHistory from app.models.notes import Notes +from app.models.allocation import Allocation +from app.models.positionHistory import PositionHistory +from app.models.supervisorDepartment import SupervisorDepartment + print("Inserting data for demo and testing purposes") @@ -515,6 +519,42 @@ "primaryCutOff": f"{current_year}-09-01", "adjustmentCutOff": f"{current_year}-09-01", }, + { + "termCode": f"{current_year-1}00", + "termName": f"AY {current_year-1}-{current_year}", + "termStart": f"{current_year-1}-08-01", + "termEnd": f"{current_year}-05-01", + "termState": 1, + "primaryCutOff": f"{current_year-1}-09-01", + "adjustmentCutOff": f"{current_year-1}-09-01", + }, + { + "termCode": f"{current_year-2}00", + "termName": f"AY {current_year-2}-{current_year-1}", + "termStart": f"{current_year-2}-08-01", + "termEnd": f"{current_year-1}-05-01", + "termState": 1, + "primaryCutOff": f"{current_year-2}-09-01", + "adjustmentCutOff": f"{current_year-2}-09-01", + }, + { + "termCode": f"{current_year-3}00", + "termName": f"AY {current_year-3}-{current_year-2}", + "termStart": f"{current_year-3}-08-01", + "termEnd": f"{current_year-2}-05-01", + "termState": 1, + "primaryCutOff": f"{current_year-3}-09-01", + "adjustmentCutOff": f"{current_year-3}-09-01", + }, + { + "termCode": f"{current_year-4}00", + "termName": f"AY {current_year-4}-{current_year-3}", + "termStart": f"{current_year-4}-08-01", + "termEnd": f"{current_year-3}-05-01", + "termState": 1, + "primaryCutOff": f"{current_year-4}-09-01", + "adjustmentCutOff": f"{current_year-4}-09-01", + }, { "termCode": f"{current_year}01", "termName": f"Thanksgiving Break {current_year}", @@ -609,3 +649,86 @@ ] Notes.insert_many(notes).on_conflict_replace().execute() print(" * laborOfficeNotes added") + +############################ +# Allocation Dummy Data: +########################### +allocations = [ + { + "termCode": 202200, + "department": "Computer Science", + "isApproved": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Downscaling due to decrease in student enrollment caused by current economic conditions", + "primary_10": 2, + "primary_12": 2, + "primary_15": 1, + "primary_20": 0, + "secondary_5": 1, + "secondary_10": 0, + "breakHours": 260, + }, + { + "termCode": 202300, + "department": "ETAD", + "isApproved": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Increase in student enrollment due to exodous from CS department", + "primary_10": 4, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 2, + "secondary_10": 0, + "breakHours": 750, + }, + { + "termCode": 202400, + "department": "Mathematics", + "isApproved": True, + "approvedOn": None, + "approvedBy": None, + "justification": "We are hiring more students to help with the increased workload in the department", + "primary_10": 5, + "primary_12": 6, + "primary_15": 4, + "primary_20": 1, + "secondary_5": 7, + "secondary_10": 0, + "breakHours": 550, + }, + { + "termCode": 202500, + "department": "Physics", + "isApproved": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Downscaling the number of students in the department due to budget cuts", + "primary_10": 4, + "primary_12": 5, + "primary_15": 0, + "primary_20": 0, + "secondary_5": 1, + "secondary_10": 0, + "breakHours": 300, + }, + { + "termCode": 202600, + "department": "Engineering Physics", + "isApproved": False, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, + + ] + +print("Data insertion complete. Check phpmyadmin to see if your changes are reflected") \ No newline at end of file From a61ff1d4cd6a8462dcf36b7743d3ceddeee0d46b Mon Sep 17 00:00:00 2001 From: ArtemKurasov Date: Tue, 30 Jun 2026 21:34:25 +0000 Subject: [PATCH 009/163] Successfully added dummy data for the SupervisorDepartment class --- database/demo_data.py | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/database/demo_data.py b/database/demo_data.py index 0557c9361..ed5c07c82 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -17,6 +17,7 @@ from app.models.laborStatusForm import LaborStatusForm from app.models.formHistory import FormHistory from app.models.notes import Notes +from app.models.supervisorDepartment import SupervisorDepartment print("Inserting data for demo and testing purposes") @@ -609,3 +610,54 @@ ] Notes.insert_many(notes).on_conflict_replace().execute() print(" * laborOfficeNotes added") + + + +############################## +# Departement Members +############################## + +department_members = [ + { + "supervisor": "B12361006", + "department": 1, + "banStatus": False, + "isActive": True, + "isCoordinator": True + }, + + { + "supervisor": "B12365892", + "department": 1, + "banStatus": True, + "isActive": True, + "isCoordinator": False + }, + + { + "supervisor": "B12365893", + "department": 1, + "banStatus": False, + "isActive": False, + "isCoordinator": False + }, + + { + "supervisor": "B00763721", + "department": 1, + "banStatus": False, + "isActive": True, + "isCoordinator": False + }, + + { + "supervisor": "B00841417", + "department": 1, + "banStatus": False, + "isActive": True, + "isCoordinator": True + } +] + +SupervisorDepartment.insert_many(department_members).on_conflict_replace().execute() +print(" * Department members added") \ No newline at end of file From cebf62e554b0563ec48d64b3ec824a8e4b0d49e8 Mon Sep 17 00:00:00 2001 From: BhushanSah Date: Wed, 1 Jul 2026 13:24:38 +0000 Subject: [PATCH 010/163] Inserted the demo data --- database/demo_data.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/database/demo_data.py b/database/demo_data.py index d5eef179a..a4296412e 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -658,8 +658,8 @@ "termCode": 202200, "department": "Computer Science", "isApproved": True, - "approvedOn": None, - "approvedBy": None, + "approvedOn": 2021-10-19, + "approvedBy": "Dr heggen", "justification": "Downscaling due to decrease in student enrollment caused by current economic conditions", "primary_10": 2, "primary_12": 2, @@ -673,8 +673,8 @@ "termCode": 202300, "department": "ETAD", "isApproved": True, - "approvedOn": None, - "approvedBy": None, + "approvedOn": 2022-11-12, + "approvedBy": "Dr Jan", "justification": "Increase in student enrollment due to exodous from CS department", "primary_10": 4, "primary_15": 7, @@ -687,8 +687,8 @@ "termCode": 202400, "department": "Mathematics", "isApproved": True, - "approvedOn": None, - "approvedBy": None, + "approvedOn": 2023-12-19, + "approvedBy": "Dr Barnard", "justification": "We are hiring more students to help with the increased workload in the department", "primary_10": 5, "primary_12": 6, @@ -702,8 +702,8 @@ "termCode": 202500, "department": "Physics", "isApproved": True, - "approvedOn": None, - "approvedBy": None, + "approvedOn": 2025-1-10, + "approvedBy": "Dr Hodge", "justification": "Downscaling the number of students in the department due to budget cuts", "primary_10": 4, "primary_12": 5, @@ -717,8 +717,8 @@ "termCode": 202600, "department": "Engineering Physics", "isApproved": False, - "approvedOn": None, - "approvedBy": None, + "approvedOn": 2025-10-19, + "approvedBy": "Dr wu", "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", "primary_10": 8, "primary_12": 10, @@ -730,5 +730,6 @@ }, ] +Allocation.insert_many(allocations).on_conflict_replace().execute() -print("Data insertion complete. Check phpmyadmin to see if your changes are reflected") \ No newline at end of file +print("Data insertion complete :)") \ No newline at end of file From 539efdee27ba153c9e1ab5d09a62fbe60a1b9af0 Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Wed, 1 Jul 2026 13:54:36 +0000 Subject: [PATCH 011/163] added a second round of demo data to the allocation --- database/demo_data.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/database/demo_data.py b/database/demo_data.py index 34c80a3f5..e3efef141 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -627,6 +627,21 @@ "secondary_5": 2, "secondary_10": 0, "breakHours": 500 + }, + { + "termCode":f"{current_year}00", + "department": 2, + "isApproved": False, + "approvedOn": f"{current_year}-06-20", + "approvedBy": "B00763721", + "justification": "We need it to lower the amount of allocations we have", + "primary_10": 1, + "primary_12": 2, + "primary_15": 5, + "primary_20": 2, + "secondary_5": 10, + "secondary_10": 0, + "breakHours": 1500 } ] Allocation.insert_many(allocation).on_conflict_replace().execute() From 6d58afdb3e687d532338231d09c4fc3b576c3fff Mon Sep 17 00:00:00 2001 From: Automation Date: Wed, 1 Jul 2026 13:56:19 +0000 Subject: [PATCH 012/163] We added more data for position history --- database/demo_data.py | 14 +++++++------- database/migrate_db.sh | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/database/demo_data.py b/database/demo_data.py index 2d3ad1bdc..90eb44817 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -17,8 +17,7 @@ from app.models.laborStatusForm import LaborStatusForm from app.models.formHistory import FormHistory from app.models.notes import Notes -from app.models.positionHistory import PositionHistory # type: ignore - +from app.models.positionHistory import PositionHistory print("Inserting data for demo and testing purposes") @@ -623,17 +622,18 @@ "positioncode": 1, "status": "Active", "WLS":3, - "revisiondate" : "2020-01-01", + "revisiondate" : f"{current_year}-01-01", "Description": "This is a test data for position history code 1", - "Department" : "ACCT" + "Department_id" : 2 + }, { "positioncode": 2, "status": "Inactive", "WLS":2, - "revisiondate" : "2023-01-01", + "revisiondate" : f"{current_year}-01-01", "Description": "This is a test data for position history code 2", - "Department" : "Computer Science" + "Department_id" : 1 }, ] -PositionHistory.insert_many(positionHistory).on_conflict_replace().execute() \ No newline at end of file +PositionHistory.insert_many(positionHistory).on_conflict_replace().execute() diff --git a/database/migrate_db.sh b/database/migrate_db.sh index f88c91f26..83f68a048 100755 --- a/database/migrate_db.sh +++ b/database/migrate_db.sh @@ -30,6 +30,7 @@ pem add app.models.supervisor.Supervisor pem add app.models.supervisorDepartment.SupervisorDepartment pem add app.models.studentLaborEvaluation.StudentLaborEvaluation pem add app.models.formSearchResult.FormSearchResult +pem add app.models.positionHistory.PositionHistory pem watch pem migrate From e670c2f37ecad6d092fa6dccde44fb2b928cefcb Mon Sep 17 00:00:00 2001 From: Dayton Conwell Date: Wed, 1 Jul 2026 14:22:52 +0000 Subject: [PATCH 013/163] fixed the demo_data to make it easier to merge, and fixed the positionhistory info to change the primary key field so position code shows --- app/models/positionHistory.py | 5 +++-- database/demo_data.py | 36 +++++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/app/models/positionHistory.py b/app/models/positionHistory.py index f255dfbcb..222441787 100644 --- a/app/models/positionHistory.py +++ b/app/models/positionHistory.py @@ -2,9 +2,10 @@ from app.models.department import Department class PositionHistory(baseModel): - positioncode = PrimaryKeyField() + positionID = PrimaryKeyField() + positioncode = CharField() status = CharField() WLS = IntegerField() revisiondate = DateField() - Description = TextField() + Description = TextField(default=None) Department = ForeignKeyField(Department) diff --git a/database/demo_data.py b/database/demo_data.py index e55edb130..4b27ff3e3 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -614,11 +614,31 @@ print(" * laborOfficeNotes added") print(PositionHistory()) -PositionHistory.insert([{ - "positioncode": "S61407", - "status": "Active", - "WLS": 1, - "revisiondate": f"{current_year}-04-01", - "Description": "Student Programmer", - "Department_id": 1 -}]).on_conflict_replace().execute() +PositionHistory.insert = [ + { + "positioncode": "S61407", + "status": "Active", + "WLS": 1, + "revisiondate": f"{current_year}-07-01", + "Description": "", + "Department_id": 1 + }, + { + + "positioncode": "S61408", + "status": "Active", + "WLS": 2, + "revisiondate": f"{current_year}-07-01", + "Description": "", + "Department_id": 1 + }, + { + "positioncode": "S61409", + "status": "Active", + "WLS": 3, + "revisiondate": f"{current_year}-07-01", + "Description": "", + "Department_id": 1 + } +] +positionHistory = PositionHistory.insert_many(PositionHistory.insert).on_conflict_replace().execute() \ No newline at end of file From 4c3f8758df9e36e2ebbeba0dbd9a8cae7095d4ca Mon Sep 17 00:00:00 2001 From: Dayton Conwell Date: Wed, 1 Jul 2026 14:40:50 +0000 Subject: [PATCH 014/163] fixed demo data to fit pre existing format --- database/demo_data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/demo_data.py b/database/demo_data.py index 4b27ff3e3..236f6444d 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -614,7 +614,7 @@ print(" * laborOfficeNotes added") print(PositionHistory()) -PositionHistory.insert = [ +positionhistory = [ { "positioncode": "S61407", "status": "Active", @@ -641,4 +641,4 @@ "Department_id": 1 } ] -positionHistory = PositionHistory.insert_many(PositionHistory.insert).on_conflict_replace().execute() \ No newline at end of file +PositionHistory.insert_many(positionhistory).on_conflict_replace().execute() \ No newline at end of file From 6666512ca20c6a7ea222faed977671ffcc9240a7 Mon Sep 17 00:00:00 2001 From: Automation Date: Wed, 1 Jul 2026 14:44:59 +0000 Subject: [PATCH 015/163] fixed formating --- app/models/positionHistory.py | 5 +++-- database/demo_data.py | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/models/positionHistory.py b/app/models/positionHistory.py index f255dfbcb..3fc1bd318 100644 --- a/app/models/positionHistory.py +++ b/app/models/positionHistory.py @@ -2,9 +2,10 @@ from app.models.department import Department class PositionHistory(baseModel): - positioncode = PrimaryKeyField() + positionID = PrimaryKeyField() + positioncode = CharField() status = CharField() WLS = IntegerField() revisiondate = DateField() - Description = TextField() + Description = TextField(default="None") Department = ForeignKeyField(Department) diff --git a/database/demo_data.py b/database/demo_data.py index 90eb44817..a6a316ae2 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -610,16 +610,16 @@ ] Notes.insert_many(notes).on_conflict_replace().execute() print(" * laborOfficeNotes added") - +print(PositionHistory()) ############################# # Position History ############################# -positionHistory = [ +positionhistory= [ { - "positioncode": 1, + "positioncode": "s6gjshs", "status": "Active", "WLS":3, "revisiondate" : f"{current_year}-01-01", @@ -636,4 +636,4 @@ "Department_id" : 1 }, ] -PositionHistory.insert_many(positionHistory).on_conflict_replace().execute() +PositionHistory.insert_many(positionhistory).on_conflict_replace().execute() From 0d517a961af1965f9cbd73f454c9cfad9236d93a Mon Sep 17 00:00:00 2001 From: Automation Date: Wed, 1 Jul 2026 14:47:13 +0000 Subject: [PATCH 016/163] fixed formating again --- app/models/positionHistory.py | 2 +- database/demo_data.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/positionHistory.py b/app/models/positionHistory.py index 3fc1bd318..222441787 100644 --- a/app/models/positionHistory.py +++ b/app/models/positionHistory.py @@ -7,5 +7,5 @@ class PositionHistory(baseModel): status = CharField() WLS = IntegerField() revisiondate = DateField() - Description = TextField(default="None") + Description = TextField(default=None) Department = ForeignKeyField(Department) diff --git a/database/demo_data.py b/database/demo_data.py index a6a316ae2..5269c53de 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -17,7 +17,10 @@ from app.models.laborStatusForm import LaborStatusForm from app.models.formHistory import FormHistory from app.models.notes import Notes -from app.models.positionHistory import PositionHistory +from app.models.positionHistory import PositionHistory +from app.models.allocation import Allocation +from app.models.positionHistory import PositionHistory +from app.models.supervisorDepartment import SupervisorDepartment print("Inserting data for demo and testing purposes") From e5869bbdfa0285fc26844afef2f69d3d4e84d72f Mon Sep 17 00:00:00 2001 From: Automation Date: Wed, 1 Jul 2026 14:49:48 +0000 Subject: [PATCH 017/163] fixed merge conflict --- database/demo_data.py | 61 ++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/database/demo_data.py b/database/demo_data.py index 5269c53de..1643d2447 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -620,23 +620,48 @@ # Position History ############################# -positionhistory= [ - { - "positioncode": "s6gjshs", - "status": "Active", - "WLS":3, - "revisiondate" : f"{current_year}-01-01", - "Description": "This is a test data for position history code 1", - "Department_id" : 2 +positionhistory = [ + { + "positioncode": "S61407", + "status": "Active", + "WLS": 1, + "revisiondate": f"{current_year}-07-01", + "Description": "", + "Department_id": 1 + }, + { + + "positioncode": "S61408", + "status": "Active", + "WLS": 2, + "revisiondate": f"{current_year}-07-01", + "Description": "", + "Department_id": 1 + }, + { + "positioncode": "S61409", + "status": "Active", + "WLS": 3, + "revisiondate": f"{current_year}-07-01", + "Description": "", + "Department_id": 1 + }, + { + "positioncode": "S61411", + "status": "Active", + "WLS":3, + "revisiondate" : f"{current_year}-01-01", + "Description": "This is a test data for position history code 1", + "Department_id" : 2 - }, - { - "positioncode": 2, - "status": "Inactive", - "WLS":2, - "revisiondate" : f"{current_year}-01-01", - "Description": "This is a test data for position history code 2", - "Department_id" : 1 - }, + }, + { + "positioncode": "S61410", + "status": "Inactive", + "WLS":2, + "revisiondate" : f"{current_year}-01-01", + "Description": "This is a test data for position history code 2", + "Department_id" : 1 + }, ] -PositionHistory.insert_many(positionhistory).on_conflict_replace().execute() +PositionHistory.insert_many(positionhistory).on_conflict_replace().execute() \ No newline at end of file From 49b5eac7080607a956abab4e65419da045cbc964 Mon Sep 17 00:00:00 2001 From: BhushanSah Date: Wed, 1 Jul 2026 14:55:29 +0000 Subject: [PATCH 018/163] Modified allocation --- app/models/allocation.py | 4 ++-- database/demo_data.py | 45 ++++++++++++++++++++-------------------- database/migrate_db.sh | 1 + 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/app/models/allocation.py b/app/models/allocation.py index ddd2084d7..75f9c828f 100644 --- a/app/models/allocation.py +++ b/app/models/allocation.py @@ -7,8 +7,8 @@ class Allocation(baseModel): termCode = ForeignKeyField(Term) department = ForeignKeyField(Department) isApproved = BooleanField(default=False) - approvedOn = DateField() - approvedBy = ForeignKeyField(Supervisor) + approvedOn = DateField(null =True) + approvedBy = ForeignKeyField(Supervisor, null =True) justification = TextField() primary_10 = IntegerField() primary_12 = IntegerField() diff --git a/database/demo_data.py b/database/demo_data.py index a4296412e..92d18557f 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -656,10 +656,10 @@ allocations = [ { "termCode": 202200, - "department": "Computer Science", - "isApproved": True, - "approvedOn": 2021-10-19, - "approvedBy": "Dr heggen", + "department": 3, + "isApproved": False, + "approvedOn": None, + "approvedBy": None, "justification": "Downscaling due to decrease in student enrollment caused by current economic conditions", "primary_10": 2, "primary_12": 2, @@ -670,13 +670,14 @@ "breakHours": 260, }, { - "termCode": 202300, - "department": "ETAD", - "isApproved": True, - "approvedOn": 2022-11-12, - "approvedBy": "Dr Jan", + "termCode": 202300, + "department": 2, + "isApproved": False, + "approvedOn": None, + "approvedBy": None, "justification": "Increase in student enrollment due to exodous from CS department", "primary_10": 4, + "primary_12": 2, "primary_15": 7, "primary_20": 4, "secondary_5": 2, @@ -685,10 +686,10 @@ }, { "termCode": 202400, - "department": "Mathematics", - "isApproved": True, - "approvedOn": 2023-12-19, - "approvedBy": "Dr Barnard", + "department": 1, + "isApproved": False, + "approvedOn": None, + "approvedBy": None, "justification": "We are hiring more students to help with the increased workload in the department", "primary_10": 5, "primary_12": 6, @@ -700,10 +701,10 @@ }, { "termCode": 202500, - "department": "Physics", - "isApproved": True, - "approvedOn": 2025-1-10, - "approvedBy": "Dr Hodge", + "department": 4, + "isApproved": False, + "approvedOn": None, + "approvedBy": None, "justification": "Downscaling the number of students in the department due to budget cuts", "primary_10": 4, "primary_12": 5, @@ -714,11 +715,11 @@ "breakHours": 300, }, { - "termCode": 202600, - "department": "Engineering Physics", - "isApproved": False, - "approvedOn": 2025-10-19, - "approvedBy": "Dr wu", + "termCode": 202500, + "department": 5, + "isApproved": False, + "approvedOn": None, + "approvedBy": None, "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", "primary_10": 8, "primary_12": 10, diff --git a/database/migrate_db.sh b/database/migrate_db.sh index f88c91f26..5788fbead 100755 --- a/database/migrate_db.sh +++ b/database/migrate_db.sh @@ -30,6 +30,7 @@ pem add app.models.supervisor.Supervisor pem add app.models.supervisorDepartment.SupervisorDepartment pem add app.models.studentLaborEvaluation.StudentLaborEvaluation pem add app.models.formSearchResult.FormSearchResult +pem add app.models.allocation.Allocation pem watch pem migrate From 30c5fe9d15d293e4a2b2bd912ff7d6b5e25c9d1b Mon Sep 17 00:00:00 2001 From: Dayton Conwell Date: Wed, 1 Jul 2026 15:04:58 +0000 Subject: [PATCH 019/163] fixed the format issue on demo data and made the composite key on positionhistory --- app/models/positionHistory.py | 4 ++-- database/demo_data.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/positionHistory.py b/app/models/positionHistory.py index 222441787..b8b834cc4 100644 --- a/app/models/positionHistory.py +++ b/app/models/positionHistory.py @@ -2,10 +2,10 @@ from app.models.department import Department class PositionHistory(baseModel): - positionID = PrimaryKeyField() positioncode = CharField() status = CharField() WLS = IntegerField() revisiondate = DateField() Description = TextField(default=None) - Department = ForeignKeyField(Department) + Department = ForeignKeyField(Department) +PositionHistory._meta.set_primary_key('positioncode_revisiondate_status', CompositeKey('positioncode', 'revisiondate', 'status')) diff --git a/database/demo_data.py b/database/demo_data.py index 7550d3e0d..65beebd14 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -662,6 +662,6 @@ "Description": "This is a test data for position history code 2", "Department_id" : 1 }, - } + ] PositionHistory.insert_many(positionhistory).on_conflict_replace().execute() \ No newline at end of file From 9b7e7786a71c90a1a3d89033d5bc7659492449ef Mon Sep 17 00:00:00 2001 From: Dayton Conwell Date: Wed, 1 Jul 2026 15:58:11 +0000 Subject: [PATCH 020/163] changed meta class in position history adn fixed identifiers in demo data --- app/models/positionHistory.py | 4 +++- database/demo_data.py | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/models/positionHistory.py b/app/models/positionHistory.py index b8b834cc4..399608a78 100644 --- a/app/models/positionHistory.py +++ b/app/models/positionHistory.py @@ -8,4 +8,6 @@ class PositionHistory(baseModel): revisiondate = DateField() Description = TextField(default=None) Department = ForeignKeyField(Department) -PositionHistory._meta.set_primary_key('positioncode_revisiondate_status', CompositeKey('positioncode', 'revisiondate', 'status')) + +class Meta: + primary_key = CompositeKey('positioncode', 'revisiondate', 'status') \ No newline at end of file diff --git a/database/demo_data.py b/database/demo_data.py index 65beebd14..1bc7e23f3 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -633,7 +633,7 @@ "positioncode": "S61408", "status": "Active", "WLS": 2, - "revisiondate": f"{current_year}-07-01", + "revisiondate": f"{current_year}-09-01", "Description": "", "Department_id": 1 }, @@ -650,8 +650,8 @@ "status": "Active", "WLS":3, "revisiondate" : f"{current_year}-01-01", - "Description": "This is a test data for position history code 1", - "Department_id" : 2 + "Description": "", + "Department_id" : 1 }, { @@ -659,7 +659,7 @@ "status": "Inactive", "WLS":2, "revisiondate" : f"{current_year}-01-01", - "Description": "This is a test data for position history code 2", + "Description": "", "Department_id" : 1 }, From a52eeca52cd0be83ba5faddc7629f77b3717bab5 Mon Sep 17 00:00:00 2001 From: Brian Ramsay Date: Thu, 2 Jul 2026 11:56:23 -0400 Subject: [PATCH 021/163] Add base for department portal --- app/controllers/main_routes/main_routes.py | 24 ++++++- app/static/css/base.css | 73 ++++++++++++++++++++++ app/static/js/departmentPortal.js | 6 ++ app/templates/main/departmentPortal.html | 27 ++++++++ app/templates/sidebar.html | 15 +++-- 5 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 app/static/js/departmentPortal.js create mode 100644 app/templates/main/departmentPortal.html diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index b3af06c9e..0a2f21e4b 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -1,5 +1,5 @@ from flask import render_template, request, json, redirect, url_for, send_file, g, flash, jsonify -from peewee import JOIN +from peewee import JOIN, DoesNotExist from functools import reduce import operator from app.models.department import Department @@ -47,6 +47,26 @@ def supervisorPortal(): currentUser = currentUser ) +@main_bp.route('/department', methods=['GET']) +@main_bp.route('/department/', methods=['GET']) +@main_bp.route('/department//', methods=['GET']) +def departmentPortal(org=None,account=None): + try: + dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) + except (NameError, DoesNotExist): + dept = None + + + + if g.currentUser.isLaborAdmin: + departments = list(Department.select().order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) + else: + departments = list(getDepartmentsForSupervisor(g.currentUser).order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) + + return render_template('main/departmentPortal.html', + departments = departments, + department = dept) + @main_bp.route('/supervisorPortal/addUserToDept', methods=['GET', 'POST']) def addUserToDept(): userDeptData = request.form @@ -113,4 +133,4 @@ def submitToBanner(formHistoryId): if save_form_status: return "Form successfully submitted to Banner.", 200 else: - return "Submitting to Banner failed.", 500 \ No newline at end of file + return "Submitting to Banner failed.", 500 diff --git a/app/static/css/base.css b/app/static/css/base.css index 916fb4db9..940f8d6e5 100755 --- a/app/static/css/base.css +++ b/app/static/css/base.css @@ -191,3 +191,76 @@ a { font-size:1.2em; z-index:999; } + +.card { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; +} + +.card-body { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1rem 1rem; +} + +.card-title { + margin-bottom: 0.5rem; + font-size: 1.25rem; + font-weight: 500; +} + +.card-subtitle { + margin-top: -0.25rem; + margin-bottom: 0; +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link + .card-link { + margin-left: 1rem; +} + +.card-header { + padding: 0.5rem 1rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} + +.card-footer { + padding: 0.5rem 1rem; + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); +} + +.card-img, .card-img-top { + width: 100%; +} + +.card-img-top { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} diff --git a/app/static/js/departmentPortal.js b/app/static/js/departmentPortal.js new file mode 100644 index 000000000..cb2023a3a --- /dev/null +++ b/app/static/js/departmentPortal.js @@ -0,0 +1,6 @@ +$(document).ready(function() { + $("#selectedDepartment").on("change",function() { + deptData = $(this).find('option:selected').data(); + window.location = `/department/${deptData.org}/${deptData.account}`; + }); +}); diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html new file mode 100644 index 000000000..8ee01838b --- /dev/null +++ b/app/templates/main/departmentPortal.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} + +{% block scripts %} +{{super()}} + +{% endblock %} + +{% block app_content %} +

{% if department %} {{department.DEPT_NAME}} Portal {% else %} Choose a Department: {% endif %}

+ + +
+ + +
+{% endblock %} diff --git a/app/templates/sidebar.html b/app/templates/sidebar.html index 323b6b03b..1486f7de2 100644 --- a/app/templates/sidebar.html +++ b/app/templates/sidebar.html @@ -49,17 +49,24 @@

Labor History

{% if currentUser.supervisor %}
+ {% endif %} {% if currentUser.supervisor or (currentUser.student and currentUser.isLaborAdmin) %}
- -
+ +

New Labor Status Form

@@ -67,7 +74,7 @@

New Labor Status Form

{% endif %} {% if currentUser.supervisor or (currentUser.student and currentUser.isLaborAdmin) %}
-
+

Department Portal

From ba5a40b6175ba98a71bf487ab54b06dd349d620f Mon Sep 17 00:00:00 2001 From: Brian Ramsay Date: Thu, 2 Jul 2026 16:01:35 -0400 Subject: [PATCH 023/163] Add empty file for common routes --- app/controllers/main_routes/departmentPortal.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 app/controllers/main_routes/departmentPortal.py diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py new file mode 100644 index 000000000..351757701 --- /dev/null +++ b/app/controllers/main_routes/departmentPortal.py @@ -0,0 +1 @@ +from flask import render_template From 65c6b0338b29ec8f8267d7a2068672121b6957c0 Mon Sep 17 00:00:00 2001 From: feitsopb Date: Thu, 2 Jul 2026 20:27:51 +0000 Subject: [PATCH 024/163] added an HTML file for manage people added the main routes to the page --- .../main_routes/departmentPortal.py | 40 ++++++++++++++++++- app/templates/main/manageStaff.html | 12 ++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 app/templates/main/manageStaff.html diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py index 351757701..930347ae9 100644 --- a/app/controllers/main_routes/departmentPortal.py +++ b/app/controllers/main_routes/departmentPortal.py @@ -1 +1,39 @@ -from flask import render_template +from flask import render_template, request, json, redirect, url_for, send_file, g, flash, jsonify +from peewee import JOIN, DoesNotExist +from functools import reduce +import operator +from app.models.department import Department +from app.models.supervisor import Supervisor +from app.models.supervisorDepartment import SupervisorDepartment +from app.models.student import Student +from app.models.laborStatusForm import LaborStatusForm +from app.models.formHistory import FormHistory +from app.models.term import Term +from app.controllers.admin_routes.allPendingForms import checkAdjustment +from app.controllers.main_routes import main_bp +from app.logic.download import CSVMaker, saveFormSearchResult, retrieveFormSearchResult +from app.logic.search import getDepartmentsForSupervisor, searchPerson, searchSupervisorPortal +from app.login_manager import require_login, logout +from app.logic.getTableData import getDatatableData +from app.logic.banner import Banner + +@main_bp.route('/department/manage_staff', methods=['GET']) +@main_bp.route('/department/manage_staff/', methods=['GET']) +@main_bp.route('/department/manage_staff//', methods=['GET']) +def departmentPortal(org=None,account=None): + try: + dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) + except (NameError, DoesNotExist): + dept = None + + + + if g.currentUser.isLaborAdmin: + departments = list(Department.select().order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) + else: + departments = list(getDepartmentsForSupervisor(g.currentUser).order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) + + return render_template('main/departmentPortal.html', + departments = departments, + department = dept) + diff --git a/app/templates/main/manageStaff.html b/app/templates/main/manageStaff.html new file mode 100644 index 000000000..306282688 --- /dev/null +++ b/app/templates/main/manageStaff.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block scripts %} +{{super()}} + +{% endblock %} + +{% block app_content %} +

{% if department %} {{department.DEPT_NAME}} Portal {% else %} Choose a Department: {% endif %}

+ + +{% endblock %} From 7c1adec948ec65c3f8251214bdff90de9877b59b Mon Sep 17 00:00:00 2001 From: BhushanSah Date: Thu, 2 Jul 2026 21:04:00 +0000 Subject: [PATCH 025/163] Added member card --- app/static/css/base.css | 32 ++++++++++ app/templates/main/departmentPortal.html | 80 ++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/app/static/css/base.css b/app/static/css/base.css index 940f8d6e5..9c5d8e2fb 100755 --- a/app/static/css/base.css +++ b/app/static/css/base.css @@ -264,3 +264,35 @@ a { border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } + + +.members-card .media { + margin-bottom: 18px; +} + +.members-card h4 { + margin-top: 18px; + margin-bottom: 4px; +} + +.members-card-icon { + display: inline-block; + width: 42px; + height: 42px; + line-height: 42px; + text-align: center; + border-radius: 50%; + background-color: #e8edf3; + color: #7c8ea1; + font-size: 18px; +} + +.members-card-cta { + position: relative; + display: inline-block; +} + +.members-card-btn { + border-radius: 20px; + padding: 8px 20px; +} diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 8ee01838b..6238bfe07 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -3,6 +3,8 @@ {% block scripts %} {{super()}} + {% endblock %} {% block app_content %} @@ -24,4 +26,82 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e

+ + +
+
+
+ +
+
+ +
+ +
+

+ Members +

+
+
+ +

Labor Coordinator

+

Dr. Jones

+ +

Supervisors

+

+ Dr. Heggen
+ Dr. Nakazawa +

+ +

+ + + View Details + + + +

+ +
+
+
{% endblock %} + + From cc07c972721e3107e01a9a81896e97f0ac71675b Mon Sep 17 00:00:00 2001 From: nahom70 Date: Thu, 2 Jul 2026 21:05:35 +0000 Subject: [PATCH 026/163] tried to add it --- app/templates/main/managepositions.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 app/templates/main/managepositions.html diff --git a/app/templates/main/managepositions.html b/app/templates/main/managepositions.html new file mode 100644 index 000000000..b78750533 --- /dev/null +++ b/app/templates/main/managepositions.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} + +{% block styles %} +{{super()}} + +{% endblock %} + +{% block scripts %} +{{super()}} + +{% endblock %} + +{% block app_content %} +

{{ department_name }}

+

Manage Positions

+ + +{% endblock %} \ No newline at end of file From 6bb3e689b95c263fd766bdf43b2a4c74228afb32 Mon Sep 17 00:00:00 2001 From: Dayton Conwell Date: Thu, 2 Jul 2026 21:06:38 +0000 Subject: [PATCH 027/163] some change --- app/templates/main/departmentPortal.html | 14 ++++++++++++++ app/templates/main/supervisorPortal.html | 2 +- database/reset_database.sh | 14 +++++++------- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 8ee01838b..18a6b9f64 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -8,6 +8,20 @@ {% block app_content %}

{% if department %} {{department.DEPT_NAME}} Portal {% else %} Choose a Department: {% endif %}

+
+
+
+ + + + + Current Allocation +
+


AY 26/27 15/20 POSITIONS

Break Hours 0 of 200 hrs

+ Go somewhere +
+
+
diff --git a/database/reset_database.sh b/database/reset_database.sh index 82f6cff53..ad6dbd91f 100755 --- a/database/reset_database.sh +++ b/database/reset_database.sh @@ -8,7 +8,7 @@ if [ "$1" != "test" ] && [ "$1" != "from-backup" ]; then fi cd database; - + PRODUCTION=0 if [ "`hostname`" == 'lsf.berea.edu' ]; then echo "DO NOT RUN THIS SCRIPT ON PRODUCTION UNLESS YOU REALLY REALLY KNOW WHAT YOU ARE DOING" @@ -22,12 +22,12 @@ if [ "$1" == "from-backup" ]; then fi echo "Dropping databases" -mysql -u root -proot --execute="DROP DATABASE \`lsf\`; DROP USER 'lsf_user';" -mysql -u root -proot --execute="DROP DATABASE \`UTE\`; DROP USER 'tracy_user';" +mysql -u root -proot --skip-ssl --execute="DROP DATABASE \`lsf\`; DROP USER 'lsf_user';" +mysql -u root -proot --skip-ssl --execute="DROP DATABASE \`UTE\`; DROP USER 'tracy_user';" echo "Recreating databases and users" -mysql -u root -proot --execute="CREATE DATABASE IF NOT EXISTS \`lsf\`; CREATE USER IF NOT EXISTS 'lsf_user'@'%' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'lsf_user'@'%';" -mysql -u root -proot --execute="CREATE DATABASE IF NOT EXISTS \`UTE\`; CREATE USER IF NOT EXISTS 'tracy_user'@'%' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'tracy_user'@'%';" +mysql -u root -proot --skip-ssl --execute="CREATE DATABASE IF NOT EXISTS \`lsf\`; CREATE USER IF NOT EXISTS 'lsf_user'@'%' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'lsf_user'@'%';" +mysql -u root -proot --skip-ssl --execute="CREATE DATABASE IF NOT EXISTS \`UTE\`; CREATE USER IF NOT EXISTS 'tracy_user'@'%' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'tracy_user'@'%';" cd database @@ -38,14 +38,14 @@ rm -rf migrations.json echo "Creating database objects" if [ $BACKUP -eq 1 ]; then echo " from backup" - mysql -u root -proot lsf < prod-backup.sql + mysql -u root -proot --skip-ssl lsf < prod-backup.sql else echo " empty" ./migrate_db.sh fi if [ $PRODUCTION -ne 1 ]; then - ./migrate_db_tracy.sh + ./migrate_db_tracy.sh fi rm -rf lsf_migrations From c29f01f461b8eb2a149605830f3506ea2caebde7 Mon Sep 17 00:00:00 2001 From: lolongaj Date: Thu, 2 Jul 2026 21:10:05 +0000 Subject: [PATCH 028/163] added 3 sample buttons to learn HTML --- app/templates/main/departmentPortal.html | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 8ee01838b..73f0c783c 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -4,7 +4,6 @@ {{super()}} {% endblock %} - {% block app_content %}

{% if department %} {{department.DEPT_NAME}} Portal {% else %} Choose a Department: {% endif %}

@@ -24,4 +23,23 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e

-{% endblock %} +
+
+
+

Positions

+

Student Programmer

+ View Details +
+
+
+

burrh

+
+
+
+

Positions

+

Student Programmer

+ View Details +
+
+
+{% endblock %}\ \ No newline at end of file From f706242d4eefb4f062aa62e4f85b996972cc9688 Mon Sep 17 00:00:00 2001 From: ArtemKurasov Date: Thu, 2 Jul 2026 21:37:05 +0000 Subject: [PATCH 029/163] Added the Manage Staff page --- app/controllers/main_routes/__init__.py | 1 + .../main_routes/departmentPortal.py | 8 +++--- app/templates/main/manageStaff.html | 25 +++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/app/controllers/main_routes/__init__.py b/app/controllers/main_routes/__init__.py index 54b32d3c5..da3323908 100755 --- a/app/controllers/main_routes/__init__.py +++ b/app/controllers/main_routes/__init__.py @@ -14,6 +14,7 @@ def injectGlobalData(): 'lastStaticUpdate': lastStaticUpdate} from app.controllers.main_routes import main_routes +from app.controllers.main_routes import departmentPortal from app.controllers.main_routes import laborStatusForm from app.controllers.main_routes import laborHistory from app.controllers.main_routes import alterLSF diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py index 930347ae9..df8dbbefc 100644 --- a/app/controllers/main_routes/departmentPortal.py +++ b/app/controllers/main_routes/departmentPortal.py @@ -20,7 +20,7 @@ @main_bp.route('/department/manage_staff', methods=['GET']) @main_bp.route('/department/manage_staff/', methods=['GET']) @main_bp.route('/department/manage_staff//', methods=['GET']) -def departmentPortal(org=None,account=None): +def manageStaff(org=None,account=None): try: dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) except (NameError, DoesNotExist): @@ -33,7 +33,9 @@ def departmentPortal(org=None,account=None): else: departments = list(getDepartmentsForSupervisor(g.currentUser).order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) - return render_template('main/departmentPortal.html', - departments = departments, + labor = [["Scott Heggen", 7, 11, 0], ["Brian Ramsey", 9, 10, 0], ["Bright Feitsop", 10, 20, 1], ["Artem Kurasov", 6, 7, 0]] + + return render_template('main/manageStaff.html', + staff = labor, department = dept) diff --git a/app/templates/main/manageStaff.html b/app/templates/main/manageStaff.html index 306282688..c5cfbdae5 100644 --- a/app/templates/main/manageStaff.html +++ b/app/templates/main/manageStaff.html @@ -7,6 +7,31 @@ {% block app_content %}

{% if department %} {{department.DEPT_NAME}} Portal {% else %} Choose a Department: {% endif %}

+

Manage Staff

+ +
+
+ + + +
+ + + + + + + + + {% for i in staff %} + + + + + + {% endfor %} +
NameSuperviseesAssign as Coordinator
{{ i[0] }} Primary: {{ i[1] }}
Secondary {{ i[2] }}
{{ i[3] }}
+
{% endblock %} From aa3a837d23f7543684ae0275dd86681ee63a0d0b Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Fri, 3 Jul 2026 13:17:42 +0000 Subject: [PATCH 030/163] uniform sizing for cards that scale with the screen and no cards when no department is selected --- app/templates/main/departmentPortal.html | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 73f0c783c..e31f476bf 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -23,15 +23,17 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e

-
-
+ +{% if department %} +
+

Positions

-

Student Programmer

+

{{department.ACCOUNT}}

View Details
-
+

burrh

@@ -42,4 +44,9 @@

Positions

+
+

aaaaaa

+
+{% endif %} + {% endblock %}\ \ No newline at end of file From d60b8e40977ee8df6bf0c7a70c0ca051b89c4b27 Mon Sep 17 00:00:00 2001 From: feitsopb Date: Fri, 3 Jul 2026 15:05:53 +0000 Subject: [PATCH 031/163] added an email symbol that opens in outlook --- app/templates/main/manageStaff.html | 32 +++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/app/templates/main/manageStaff.html b/app/templates/main/manageStaff.html index c5cfbdae5..ff39fd2d8 100644 --- a/app/templates/main/manageStaff.html +++ b/app/templates/main/manageStaff.html @@ -23,15 +23,29 @@

Manage Staff

Assign as Coordinator - {% for i in staff %} - - {{ i[0] }} - Primary: {{ i[1] }}
Secondary {{ i[2] }} - {{ i[3] }} - - {% endfor %} + + + {% for i in staff %} + + + {{ i[0] }} + + + {% if i[5] %} + Banned + {% endif %} + + + + Primary: {{ i[1] }}
+ Secondary: {{ i[2] }} + + + {{ i[3] }} + + {% endfor %} +
- -{% endblock %} +{% endblock %} \ No newline at end of file From 645e85ae93f8b743030a98a3160389194530c790 Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Fri, 3 Jul 2026 15:38:25 +0000 Subject: [PATCH 032/163] added a 10 position cap to the amount of visible positons --- app/controllers/main_routes/main_routes.py | 11 +++++++++-- app/templates/main/departmentPortal.html | 22 ++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index 0a2f21e4b..18c0f3963 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -16,6 +16,7 @@ from app.login_manager import require_login, logout from app.logic.getTableData import getDatatableData from app.logic.banner import Banner +from app.logic.tracy import Tracy @main_bp.route('/logout', methods=['GET']) def triggerLogout(): @@ -62,10 +63,16 @@ def departmentPortal(org=None,account=None): departments = list(Department.select().order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) else: departments = list(getDepartmentsForSupervisor(g.currentUser).order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) - + + pos = Tracy().getPositionsFromDepartment(org, account) + positions = [] + for i in pos: + positions.append(i.POSN_TITLE + "" + "(" + i.WLS + ")") + print(positions) return render_template('main/departmentPortal.html', departments = departments, - department = dept) + department = dept, + positions = positions) @main_bp.route('/supervisorPortal/addUserToDept', methods=['GET', 'POST']) def addUserToDept(): diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index e31f476bf..1f3e9e422 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -23,30 +23,36 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e

- + {% if department %}
-

Positions

+

that one thing

{{department.ACCOUNT}}

View Details
-
-

burrh

+
+
+

burrh

+

crazy interesting stuff here

+ View Details +

Positions

-

Student Programmer

+ {% for p in positions %} + {% if 10 > loop.index0 %} +

{{ p }}

+ {% endif %} + {% endfor %} View Details
-
-

aaaaaa

-
+ {% endif %} {% endblock %}\ \ No newline at end of file From d3c0b0401958ff6a147be8142468e92c68938acc Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Fri, 3 Jul 2026 15:40:44 +0000 Subject: [PATCH 033/163] removed an unecessary print statement from the main_routes.py --- app/controllers/main_routes/main_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index 18c0f3963..36bd7cb05 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -68,7 +68,7 @@ def departmentPortal(org=None,account=None): positions = [] for i in pos: positions.append(i.POSN_TITLE + "" + "(" + i.WLS + ")") - print(positions) + return render_template('main/departmentPortal.html', departments = departments, department = dept, From 09022bd1dee0d30dd432a1c3e962623195c45488 Mon Sep 17 00:00:00 2001 From: ArtemKurasov Date: Fri, 3 Jul 2026 17:10:05 +0000 Subject: [PATCH 034/163] Updated the Manage Staff table --- .../main_routes/departmentPortal.py | 4 +- app/templates/main/manageStaff.html | 44 ++++++++++++++----- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py index df8dbbefc..631a7eac3 100644 --- a/app/controllers/main_routes/departmentPortal.py +++ b/app/controllers/main_routes/departmentPortal.py @@ -33,9 +33,9 @@ def manageStaff(org=None,account=None): else: departments = list(getDepartmentsForSupervisor(g.currentUser).order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) - labor = [["Scott Heggen", 7, 11, 0], ["Brian Ramsey", 9, 10, 0], ["Bright Feitsop", 10, 20, 1], ["Artem Kurasov", 6, 7, 0]] + labor = [["Scott Heggen", 7, 11, 0, 1], ["Brian Ramsey", 9, 12, 0, 1], ["Bright Feitsop", 10, 20, 1, 0], ["Artem Kurasov", 6, 7, 0, 0]] return render_template('main/manageStaff.html', staff = labor, - department = dept) + department = "Computer Science") diff --git a/app/templates/main/manageStaff.html b/app/templates/main/manageStaff.html index ff39fd2d8..890f620fb 100644 --- a/app/templates/main/manageStaff.html +++ b/app/templates/main/manageStaff.html @@ -2,25 +2,31 @@ {% block scripts %} {{super()}} + + {% endblock %} {% block app_content %} -

{% if department %} {{department.DEPT_NAME}} Portal {% else %} Choose a Department: {% endif %}

-

Manage Staff

- -
-
+

{% if department %} Manage {{department.DEPT_NAME}} Staff {% else %} Manage Staff {% endif %}

+

-
+

+ +
+ + {% if currentUser.isLaborAdmin or currentUser.isLaborDepartmentStudent %} + + + {% endif %} @@ -29,10 +35,12 @@

Manage Staff

@@ -41,7 +49,23 @@

Manage Staff

Secondary: {{ i[2] }} - + + + {% if currentUser.isLaborAdmin or currentUser.isLaborDepartmentStudent %} + + + {% endif %} + {% endfor %} From 426e2e7153a77388ee03284c5fedb0fbc402137e Mon Sep 17 00:00:00 2001 From: ArtemKurasov Date: Fri, 3 Jul 2026 18:00:19 +0000 Subject: [PATCH 035/163] Added a hover indicator for names on the Manage Staff table --- app/controllers/main_routes/departmentPortal.py | 2 +- app/templates/main/manageStaff.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py index 631a7eac3..be78113f7 100644 --- a/app/controllers/main_routes/departmentPortal.py +++ b/app/controllers/main_routes/departmentPortal.py @@ -33,7 +33,7 @@ def manageStaff(org=None,account=None): else: departments = list(getDepartmentsForSupervisor(g.currentUser).order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) - labor = [["Scott Heggen", 7, 11, 0, 1], ["Brian Ramsey", 9, 12, 0, 1], ["Bright Feitsop", 10, 20, 1, 0], ["Artem Kurasov", 6, 7, 0, 0]] + labor = [["Scott Heggen", 7, 11, 0, 1, "B0010201"], ["Brian Ramsay", 9, 12, 0, 1, "B0011251"], ["Bright Feitsop", 10, 20, 1, 0, "B023241"], ["Artem Kurasov", 6, 7, 0, 0, "B1110201"]] return render_template('main/manageStaff.html', staff = labor, diff --git a/app/templates/main/manageStaff.html b/app/templates/main/manageStaff.html index 890f620fb..1df4b5853 100644 --- a/app/templates/main/manageStaff.html +++ b/app/templates/main/manageStaff.html @@ -34,7 +34,7 @@

{% if department %} Manage {{department.DEPT_NAME}} Staf {% for i in staff %}

Name Supervisees Assign as CoordinatorStatusRemove Staff
{{ i[0] }} - + + +
- {% if i[5] %} - Banned + {% if i[4] %} + Banned {% endif %}
{{ i[3] }} + + + {% if not i[4] %} + + {% else %} + + {% endif %} + + +
- {{ i[0] }} + {{ i[0] }}
From dfa597131f5dc3ca3529c442cf3c6ab83696ce35 Mon Sep 17 00:00:00 2001 From: nyabutoa Date: Fri, 3 Jul 2026 19:11:32 +0000 Subject: [PATCH 036/163] we added some things and the table we hard coded some information in there but we will be connecting it soon to tracy and get actaul information --- app/controllers/main_routes/main_routes.py | 25 ++++- app/templates/main/departmentPortal.html | 2 +- app/templates/main/managepositions.html | 117 +++++++++++++++++++-- 3 files changed, 132 insertions(+), 12 deletions(-) diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index 36bd7cb05..527244cb6 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -52,9 +52,12 @@ def supervisorPortal(): @main_bp.route('/department/', methods=['GET']) @main_bp.route('/department//', methods=['GET']) def departmentPortal(org=None,account=None): - try: - dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) - except (NameError, DoesNotExist): + if org and account: + try: + dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) + except (NameError, DoesNotExist): + dept = None + else: dept = None @@ -69,11 +72,25 @@ def departmentPortal(org=None,account=None): for i in pos: positions.append(i.POSN_TITLE + "" + "(" + i.WLS + ")") - return render_template('main/departmentPortal.html', + return render_template('main/departmentPortal.html', departments = departments, department = dept, positions = positions) +@main_bp.route('/department///managepositions', methods=['GET']) +def managePositions(org, account): + try: + dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) + except DoesNotExist: + return render_template('errors/404.html'), 404 + + positions = Tracy().getPositionsFromDepartment(org, account) + + return render_template('main/managepositions.html', + department = dept, + department_name = dept.DEPT_NAME, + positions = positions) + @main_bp.route('/supervisorPortal/addUserToDept', methods=['GET', 'POST']) def addUserToDept(): userDeptData = request.form diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 1f3e9e422..a00a298b2 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -48,7 +48,7 @@

Positions

{{ p }}

{% endif %} {% endfor %} - View Details + View Details diff --git a/app/templates/main/managepositions.html b/app/templates/main/managepositions.html index b78750533..9c38e7f52 100644 --- a/app/templates/main/managepositions.html +++ b/app/templates/main/managepositions.html @@ -2,17 +2,120 @@ {% block styles %} {{super()}} - + {% endblock %} {% block scripts %} {{super()}} - + {% endblock %} {% block app_content %} -

{{ department_name }}

-

Manage Positions

- - -{% endblock %} \ No newline at end of file +
+

{{ department_name }}

+
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Position (WSL)Position CodeStatusLast Revision DateView Position DescriptionEdit Position Description
TA (3)S85405 + + Active + + 01/01/2024 + + + +
Co-Lead TA (4)S89123 + + Requested + + 01/01/2024 + + + +
Lead TA (4)S89123 + + Inactive + + 01/01/2024 + + + +
+
+

+ Total Positions: + 3 +

+
+{% endblock %} From 693191bfd9161858047801e2b8555bd58f8dc1ae Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Fri, 3 Jul 2026 20:31:48 +0000 Subject: [PATCH 037/163] got the first card added from Dayton's branch --- app/templates/main/departmentPortal.html | 32 ++++++++++-------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 86a15e6ce..fa226dca7 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -7,19 +7,6 @@ {% block app_content %}

{% if department %} {{department.DEPT_NAME}} Portal {% else %} Choose a Department: {% endif %}

-
-
-
- - - - - Current Allocation -
-


AY 26/27 15/20 POSITIONS

Break Hours 0 of 200 hrs

- Go somewhere -
-
@@ -40,13 +27,20 @@
{% if department %}
-
-
-

that one thing

-

{{department.ACCOUNT}}

- View Details -
+ +
+
+
+ + + + + Current Allocation +
+


AY 26/27 15/20 POSITIONS

Break Hours 0 of 200 hrs

+ Go somewhere
+

burrh

From 1bb8c18f69e2779e29ba9a654b49c61d50073547 Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Fri, 3 Jul 2026 21:23:04 +0000 Subject: [PATCH 038/163] added real people into the members card, its wrong and gives us everyone --- app/controllers/main_routes/main_routes.py | 10 +++++++++- app/templates/main/departmentPortal.html | 17 +++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index 36bd7cb05..17fa6f2a2 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -69,10 +69,18 @@ def departmentPortal(org=None,account=None): for i in pos: positions.append(i.POSN_TITLE + "" + "(" + i.WLS + ")") + staff = Tracy().getSupervisors() + supervisors = [] + + for i in staff: + if i.DEPT_NAME == Department.DEPT_NAME: + supervisors.append(i.FIRST_NAME + " " + i.LAST_NAME + " (" + i.EMAIL + ")") + return render_template('main/departmentPortal.html', departments = departments, department = dept, - positions = positions) + positions = positions, + supervisors = supervisors) @main_bp.route('/supervisorPortal/addUserToDept', methods=['GET', 'POST']) def addUserToDept(): diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index a221f7160..bc3710bd7 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -45,7 +45,6 @@
-
@@ -53,22 +52,23 @@
-

Members

- -

Labor Coordinator

+

Labor Coordinator(s)

Dr. Jones

Supervisors

-

- Dr. Heggen
- Dr. Nakazawa -

+ {% for s in supervisors %} + {% if 3 > loop.index0 %} +

{{ s }}

+ {% elif 4 > loop.index0 %} +

and {{ supervisors | length}} more...

+ {% endif %} + {% endfor %}
+

Positions

From 570293cd85765f94156eb5df14910194de151804 Mon Sep 17 00:00:00 2001 From: BhushanSah Date: Mon, 6 Jul 2026 13:00:41 +0000 Subject: [PATCH 039/163] Updated the members card --- database/reset_database.sh.bak | 67 ++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 database/reset_database.sh.bak diff --git a/database/reset_database.sh.bak b/database/reset_database.sh.bak new file mode 100644 index 000000000..82f6cff53 --- /dev/null +++ b/database/reset_database.sh.bak @@ -0,0 +1,67 @@ +#!/bin/bash + +## Check if argument was passed in +if [ "$1" != "test" ] && [ "$1" != "from-backup" ]; then + echo "You must specify which data set you want to restore" + echo "Usage: ./reset_database.sh [test|from-backup]" + exit 1; +fi + +cd database; + +PRODUCTION=0 +if [ "`hostname`" == 'lsf.berea.edu' ]; then + echo "DO NOT RUN THIS SCRIPT ON PRODUCTION UNLESS YOU REALLY REALLY KNOW WHAT YOU ARE DOING" + PRODUCTION=1 + exit 1 +fi + +BACKUP=0 +if [ "$1" == "from-backup" ]; then + BACKUP=1 +fi + +echo "Dropping databases" +mysql -u root -proot --execute="DROP DATABASE \`lsf\`; DROP USER 'lsf_user';" +mysql -u root -proot --execute="DROP DATABASE \`UTE\`; DROP USER 'tracy_user';" + +echo "Recreating databases and users" +mysql -u root -proot --execute="CREATE DATABASE IF NOT EXISTS \`lsf\`; CREATE USER IF NOT EXISTS 'lsf_user'@'%' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'lsf_user'@'%';" +mysql -u root -proot --execute="CREATE DATABASE IF NOT EXISTS \`UTE\`; CREATE USER IF NOT EXISTS 'tracy_user'@'%' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'tracy_user'@'%';" + +cd database + +rm -rf lsf_migrations +rm -rf tracy_migrations +rm -rf migrations.json + +echo "Creating database objects" +if [ $BACKUP -eq 1 ]; then + echo " from backup" + mysql -u root -proot lsf < prod-backup.sql +else + echo " empty" + ./migrate_db.sh +fi + +if [ $PRODUCTION -ne 1 ]; then + ./migrate_db_tracy.sh +fi + +rm -rf lsf_migrations +rm -rf tracy_migrations +rm -rf migrations.json + +# Adding data we need in all environments, unless we are restoring from backup +if [ $BACKUP -ne 1 ]; then + python3 base_data.py +else + echo "You have imported the production DB backup. You probably want to enable real Tracy access as well. Set FLASK_ENV to staging or production." +fi + +# Adding fake data for non-prod, set up admins for prod +if [ $PRODUCTION -eq 1 ]; then + FLASK_ENV=production python3 add_admins.py +elif [ $BACKUP -ne 1 ]; then + python3 demo_data.py +fi From 3f6aa594d26c04ff25ded1fb935925cfa7b99e46 Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Mon, 6 Jul 2026 13:17:24 +0000 Subject: [PATCH 040/163] changed the button from members to blue --- app/templates/main/departmentPortal.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index bc3710bd7..fd29a2ec3 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -53,15 +53,15 @@
-

+

Members -

+

Labor Coordinator(s)

Dr. Jones

-

Supervisors

+

Supervisors

{% for s in supervisors %} {% if 3 > loop.index0 %}

{{ s }}

@@ -72,8 +72,8 @@

Supervisors

From 77e9714189a8ed1a1c0105470fcbc7944edd4af8 Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Mon, 6 Jul 2026 13:25:46 +0000 Subject: [PATCH 041/163] added the bottom border and centered the button --- app/templates/main/departmentPortal.html | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index fd29a2ec3..33f82f747 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -78,17 +78,19 @@

Supervisors

-
-
-

Positions

- {% for p in positions %} - {% if 10 > loop.index0 %} -

{{ p }}

- {% endif %} - {% endfor %} - View Details -
+
+
+

Positions

+ {% for p in positions %} + {% if 10 > loop.index0 %} +

{{ p }}

+ {% endif %} + {% endfor %}
+ +
{% endif %} From abcd951f493146b284bae8c55717d8c598dc0862 Mon Sep 17 00:00:00 2001 From: rukwashai Date: Mon, 6 Jul 2026 09:57:32 -0400 Subject: [PATCH 042/163] Add real data to the Current Allocation card - New Allocation model (department, term, totalPositions, totalBreakHours) - Register Allocation in migrate_db.sh - Seed demo allocation rows per department in demo_data.py - departmentPortal route now queries Allocation for the selected dept and open term, and computes positions/break-hours used from LaborStatusForm - Template renders real allocation data instead of hardcoded placeholder text --- app/controllers/main_routes/main_routes.py | 23 +++++++++++++++++++--- app/models/allocation.py | 9 +++++++++ app/templates/main/departmentPortal.html | 9 +++++++-- database/demo_data.py | 15 ++++++++++++++ database/migrate_db.sh | 1 + 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 app/models/allocation.py diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index 17fa6f2a2..3dd3fa40b 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -1,8 +1,9 @@ from flask import render_template, request, json, redirect, url_for, send_file, g, flash, jsonify -from peewee import JOIN, DoesNotExist +from peewee import JOIN, DoesNotExist, fn from functools import reduce import operator from app.models.department import Department +from app.models.allocation import Allocation from app.models.supervisor import Supervisor from app.models.supervisorDepartment import SupervisorDepartment from app.models.student import Student @@ -76,11 +77,27 @@ def departmentPortal(org=None,account=None): if i.DEPT_NAME == Department.DEPT_NAME: supervisors.append(i.FIRST_NAME + " " + i.LAST_NAME + " (" + i.EMAIL + ")") - return render_template('main/departmentPortal.html', + allocation = None + positionsUsed = 0 + breakHoursUsed = 0 + if dept and g.openTerm: + allocation = Allocation.get_or_none(Allocation.department == dept, Allocation.term == g.openTerm) + usage = (LaborStatusForm + .select(fn.COUNT(LaborStatusForm.laborStatusFormID).alias('positionCount'), + fn.SUM(LaborStatusForm.contractHours).alias('hoursSum')) + .where(LaborStatusForm.department == dept, LaborStatusForm.termCode == g.openTerm) + .get()) + positionsUsed = usage.positionCount or 0 + breakHoursUsed = usage.hoursSum or 0 + + return render_template('main/departmentPortal.html', departments = departments, department = dept, positions = positions, - supervisors = supervisors) + supervisors = supervisors, + allocation = allocation, + positionsUsed = positionsUsed, + breakHoursUsed = breakHoursUsed) @main_bp.route('/supervisorPortal/addUserToDept', methods=['GET', 'POST']) def addUserToDept(): diff --git a/app/models/allocation.py b/app/models/allocation.py new file mode 100644 index 000000000..f67b61e3e --- /dev/null +++ b/app/models/allocation.py @@ -0,0 +1,9 @@ +from app.models import * +from app.models.department import Department +from app.models.term import Term + +class Allocation(baseModel): + department = ForeignKeyField(Department, on_delete="cascade") + term = ForeignKeyField(Term, on_delete="cascade") + totalPositions = IntegerField() + totalBreakHours = IntegerField() diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index fd29a2ec3..d77f22f8e 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -39,8 +39,13 @@
Current Allocation
-


AY 26/27 15/20 POSITIONS

Break Hours 0 of 200 hrs

- Go somewhere + {% if allocation %} +


{{allocation.term.termName}} {{positionsUsed}}/{{allocation.totalPositions}} POSITIONS +

Break Hours {{breakHoursUsed}} of {{allocation.totalBreakHours}} hrs

+ {% else %} +


No allocation set for this term.

+ {% endif %} + View Details diff --git a/database/demo_data.py b/database/demo_data.py index 0557c9361..1bb4c3b6a 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -530,6 +530,21 @@ Term.insert_many(terms).on_conflict_replace().execute() print(f" * terms for {current_year}-{current_year+1} added") +############################# +# Allocation +############################# +from app.models.allocation import Allocation + +allocations = [ + {"department": 1, "term": f"{current_year}00", "totalPositions": 20, "totalBreakHours": 200}, + {"department": 2, "term": f"{current_year}00", "totalPositions": 12, "totalBreakHours": 150}, + {"department": 3, "term": f"{current_year}00", "totalPositions": 15, "totalBreakHours": 180}, + {"department": 4, "term": f"{current_year}00", "totalPositions": 10, "totalBreakHours": 100}, + {"department": 5, "term": f"{current_year}00", "totalPositions": 20, "totalBreakHours": 200}, +] +Allocation.insert_many(allocations).on_conflict_replace().execute() +print(" * allocations added") + ############################# # Create a Pending Labor Status Form ############################# diff --git a/database/migrate_db.sh b/database/migrate_db.sh index f88c91f26..472aab283 100755 --- a/database/migrate_db.sh +++ b/database/migrate_db.sh @@ -16,6 +16,7 @@ pem add app.models.laborStatusForm.LaborStatusForm pem add app.models.laborReleaseForm.LaborReleaseForm pem add app.models.term.Term pem add app.models.department.Department +pem add app.models.allocation.Allocation pem add app.models.emailTemplate.EmailTemplate pem add app.models.formHistory.FormHistory pem add app.models.adjustedForm.AdjustedForm From 6c52ca9eb6d46a7acd83413a7716254c9b8b7df0 Mon Sep 17 00:00:00 2001 From: BhushanSah Date: Mon, 6 Jul 2026 14:08:08 +0000 Subject: [PATCH 043/163] fixedgit add app/controllers/main_routes/main_routes.py Now current dept show the supervisor of current department only --- app/controllers/main_routes/main_routes.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index 17fa6f2a2..a10c46cc8 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -56,9 +56,7 @@ def departmentPortal(org=None,account=None): dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) except (NameError, DoesNotExist): dept = None - - - + if g.currentUser.isLaborAdmin: departments = list(Department.select().order_by(Department.isActive.desc(), Department.DEPT_NAME.asc())) else: @@ -73,7 +71,8 @@ def departmentPortal(org=None,account=None): supervisors = [] for i in staff: - if i.DEPT_NAME == Department.DEPT_NAME: + print(f"org= {org},----- account= {account}") + if i.ORG == org: supervisors.append(i.FIRST_NAME + " " + i.LAST_NAME + " (" + i.EMAIL + ")") return render_template('main/departmentPortal.html', From cdabc2a68f6047bbc892c313cc7d4bcd004c9054 Mon Sep 17 00:00:00 2001 From: Dayton Conwell Date: Mon, 6 Jul 2026 14:14:20 +0000 Subject: [PATCH 044/163] added changes to format with all 3 cards --- app/templates/main/departmentPortal.html | 37 +++++++++++++++++------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index bc3710bd7..78fda0498 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -30,19 +30,34 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e {% if department %}
-
+
-
- - - - - Current Allocation -
-


AY 26/27 15/20 POSITIONS

Break Hours 0 of 200 hrs

- Go somewhere +
+
+ + + +
+
+

+ Current Allocation +

+
+
+

AY 26/27      15 / 20 Positions

+

Break Hours      0 of 200 Hrs.

-
+ + + +
From ea79ff6ebb275ccbf8c1f02350653583a80a428a Mon Sep 17 00:00:00 2001 From: fritzj2 Date: Mon, 6 Jul 2026 14:28:55 +0000 Subject: [PATCH 045/163] unordered list now bullets elements, icon is in the top right, and round corners --- app/templates/main/departmentPortal.html | 29 ++++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 33f82f747..0487d8138 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -28,9 +28,9 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e

{% if department %} -
+
-
+
@@ -44,7 +44,7 @@
-
+
@@ -78,14 +78,29 @@

Supervisors

-
+
-

Positions

+
+
+

Positions

+
+
+ +
+ +
+
    {% for p in positions %} - {% if 10 > loop.index0 %} -

    {{ p }}

    + {% if 7 > loop.index0 %} +
  • {{ p }}
  • + {% elif 8 == loop.index0 %} +

and {{ positions | length}} more...

{% endif %} {% endfor %} + +
diff --git a/database/demo_data.py b/database/demo_data.py index 1bb4c3b6a..0557c9361 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -530,21 +530,6 @@ Term.insert_many(terms).on_conflict_replace().execute() print(f" * terms for {current_year}-{current_year+1} added") -############################# -# Allocation -############################# -from app.models.allocation import Allocation - -allocations = [ - {"department": 1, "term": f"{current_year}00", "totalPositions": 20, "totalBreakHours": 200}, - {"department": 2, "term": f"{current_year}00", "totalPositions": 12, "totalBreakHours": 150}, - {"department": 3, "term": f"{current_year}00", "totalPositions": 15, "totalBreakHours": 180}, - {"department": 4, "term": f"{current_year}00", "totalPositions": 10, "totalBreakHours": 100}, - {"department": 5, "term": f"{current_year}00", "totalPositions": 20, "totalBreakHours": 200}, -] -Allocation.insert_many(allocations).on_conflict_replace().execute() -print(" * allocations added") - ############################# # Create a Pending Labor Status Form ############################# diff --git a/database/migrate_db.sh b/database/migrate_db.sh index 472aab283..f88c91f26 100755 --- a/database/migrate_db.sh +++ b/database/migrate_db.sh @@ -16,7 +16,6 @@ pem add app.models.laborStatusForm.LaborStatusForm pem add app.models.laborReleaseForm.LaborReleaseForm pem add app.models.term.Term pem add app.models.department.Department -pem add app.models.allocation.Allocation pem add app.models.emailTemplate.EmailTemplate pem add app.models.formHistory.FormHistory pem add app.models.adjustedForm.AdjustedForm From c1ffd5738b7dbf7b0ef2a829b91bc942acced7c9 Mon Sep 17 00:00:00 2001 From: BhushanSah Date: Mon, 6 Jul 2026 14:59:05 +0000 Subject: [PATCH 047/163] fixed supervisor for members card --- app/controllers/main_routes/main_routes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index a10c46cc8..62ad00b7f 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -71,7 +71,6 @@ def departmentPortal(org=None,account=None): supervisors = [] for i in staff: - print(f"org= {org},----- account= {account}") if i.ORG == org: supervisors.append(i.FIRST_NAME + " " + i.LAST_NAME + " (" + i.EMAIL + ")") From 725ce6aa4a89db39417930ca714bdadf88eb8aa2 Mon Sep 17 00:00:00 2001 From: nahom70 Date: Mon, 6 Jul 2026 15:15:30 +0000 Subject: [PATCH 048/163] polished the UI --- app/static/css/managepositions.css | 15 +++++++ app/templates/main/managepositions.html | 52 ++++++++++++------------- 2 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 app/static/css/managepositions.css diff --git a/app/static/css/managepositions.css b/app/static/css/managepositions.css new file mode 100644 index 000000000..9c40bbe38 --- /dev/null +++ b/app/static/css/managepositions.css @@ -0,0 +1,15 @@ +.width-12{ + width:12%; +} + +*{ + /* outline:solid 1px lime; */ + margin:0; + padding:0; + box-sizing:border-box; +} + +.department-header{ + padding:1%; + margin-top:-20px; +} \ No newline at end of file diff --git a/app/templates/main/managepositions.html b/app/templates/main/managepositions.html index 9c38e7f52..8cea7d3ef 100644 --- a/app/templates/main/managepositions.html +++ b/app/templates/main/managepositions.html @@ -2,7 +2,7 @@ {% block styles %} {{super()}} - + {% endblock %} {% block scripts %} @@ -11,39 +11,37 @@ {% endblock %} {% block app_content %} -
-

{{ department_name }}

+
+

{{ department_name }}


-
+
{% if department %} {{department.DEPT_NAME}} Portal {% e
- {% if department %}
@@ -41,81 +40,13 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e

-
-
-
-
- - - -
- -
-

- Members -

-
-
-

{% if laborCoordinators|length <= 1 %} Labor Coordinator {% else %} Labor Coordinators{% endif %}

- {% if laborCoordinators %} - {% for coordinator in laborCoordinators %} -

- {{ coordinator.name }} - - {% if coordinator.email %} - - - - {% endif %} -

- {% endfor %} - {% else %} -

None assigned. Add one?

- - - {% endif %} - - -

{% if supervisors|length <= 1 %} Supervisor{% else %} Supervisors{% endif %}

- - {% if supervisors %} - {% for s in supervisors[:3] %} -

- {{ s.name }} +

- {% if s.email %} - - - - - {% endif %} -

- {% endfor %} - - {% if supervisors|length > 3 %} -

and {{ supervisors|length - 3 }} more...

- {% endif %} - - {% elif not laborCoordinators and currentUser.isLaborAdmin %} -

No active supervisors assigned. Add one?

- {% else %} -

No active supervisors assigned.

- {% endif %} - -
- - -
+

Insert Members Card Here

+ +
@@ -134,7 +65,8 @@

Positions

    - {% for p in positions[:7] %} + {% for p in positions %} + {% if 7 > loop.index0 %} {% if p == "No active positions in this department" %}
  • {{ p }}

    @@ -144,10 +76,12 @@

    Positions

    {{ p }}
  • {% endif %} - {% endfor %} - {% if positions| length >7 %} + + {% elif 7 == loop.index0 %}

and {{ (positions | length) - 7}} more...

{% endif %} + {% endfor %} +

-
-
-
+
+ +
diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 173adb3d2..8ee01838b 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -3,7 +3,6 @@ {% block scripts %} {{super()}} - {% endblock %} {% block app_content %} @@ -25,72 +24,4 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e

- - {% if department %} -
-
- -
-

Insert Allocations Card Here

- -
- -
- -
-
- -

Insert Members Card Here

- -
- -
- -
-
-
-
-
- -
-
-

Positions

-
- -
-
    - {% for p in positions %} - {% if 7 > loop.index0 %} - {% if p == "No active positions in this department" %} -
  • -

    {{ p }}

    -
  • - {% else %} -
  • - {{ p }} -
  • - {% endif %} - - {% elif 7 == loop.index0 %} -

and {{ (positions | length) - 7}} more...

- {% endif %} - {% endfor %} - - -
- -
-
-
- -{% endif %} - {% endblock %} diff --git a/database/demo_data.py b/database/demo_data.py index 1311a7487..de6047624 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -750,119 +750,50 @@ # Position History ############################# -positionhistory = [ +positionHistory = [ { - "positionTitle": "Student Programmer", "positionCode": "S61407", "status": "Active", "wls": 1, - "revisionDate": f"2026-07-01", + "revisionDate": f"2025-07-01", "description": "", "department": 1 }, { - "positionTitle": "Research Associate", + "positionCode": "S61408", "status": "Active", "wls": 2, - "revisionDate": f"2026-09-01", + "revisionDate": f"2025-09-01", "description": "", "department": 1 }, { - "positionTitle": "Labor Workers", "positionCode": "S61409", "status": "Active", "wls": 3, - "revisionDate": f"2026-07-01", + "revisionDate": f"2025-07-01", "description": "", "department": 1 }, { - "positionTitle": "Teaching Associate", "positionCode": "S61411", "status": "Active", "wls":3, - "revisionDate" : f"2026-01-01", + "revisionDate" : f"2025-01-01", "description": "", "department" : 1 - }, - { - "positionTitle": "Teaching Associate", + }, + { "positionCode": "S61410", "status": "Inactive", "wls":2, - "revisionDate" : f"2026-01-01", - "description": "", - "department" : 3 - }, - { - "positionTitle": "Teaching Associate", - "positionCode": "S61410", - "status": "Active", - "wls":2, - "revisionDate" : f"2026-03-29", - "description": "", - "department" : 3 - }, - { - "positionTitle": "DUMMY POSITION", - "positionCode": "S12345", - "status": "Active", - "wls":3, - "revisionDate" : f"2026-01-23", - "description": "", - "department" : 1 - }, - { - "positionTitle": "Junior Data Analyst", - "positionCode": "S39568", - "status": "Active", - "wls":4, - "revisionDate" : f"2026-01-31", - "description": "", - "department" : 1 - }, - { - "positionTitle": "Student Manager", - "positionCode": "S74933", - "status": "Active", - "wls":5, - "revisionDate" : f"2026-04-01", - "description": "", - "department" : 1 - }, - { - "positionTitle": "IT Technician", - "positionCode": "S94932", - "status": "Active", - "wls":6, - "revisionDate" : f"2026-05-03", - "description": "", - "department" : 1 - }, - { - "positionTitle": "Human code generator", - "positionCode": "S22222", - "status": "Active", - "wls":1, - "revisionDate" : f"2026-05-03", + "revisionDate" : f"2025-01-01", "description": "", "department" : 1 - }, - { - "positionTitle": "Senior Software Engineer", - "positionCode": "S00000", - "status": "Active", - "wls":6, - "revisionDate" : f"2026-05-03", - "description": "", - "department" : 1 - } - + }, - ] -PositionHistory.insert_many(positionhistory).on_conflict_replace().execute() +PositionHistory.insert_many(positionHistory).on_conflict_replace().execute() print(" * position history added") \ No newline at end of file diff --git a/setup.sh b/setup.sh index c4e43d652..895e43b98 100755 --- a/setup.sh +++ b/setup.sh @@ -39,13 +39,3 @@ export FLASK_APP=app.py # app entry point export APP_ENV=development # default export FLASK_RUN_PORT=8080 # For consistency (python app.py vs flask run) export FLASK_RUN_HOST=0.0.0.0 # To allow external routing to the application - -# Fix symbolic link inside database directory -if ! [ -L "database/app" ]; then - echo "Fixing symlink to app in database directory" - cd database - rm app - ln -s ../app - cd .. -fi - From dad0a4903db54e8e2ccb9c2878145da83d0785e2 Mon Sep 17 00:00:00 2001 From: kurasova Date: Mon, 20 Jul 2026 14:49:24 -0400 Subject: [PATCH 156/163] Reverted the merges --- app/controllers/main_routes/__init__.py | 1 + .../main_routes/departmentPortal.py | 245 +++++++++++++++++- app/controllers/main_routes/main_routes.py | 50 ++-- app/logic/tracy.py | 8 + app/models/supervisor.py | 9 +- app/static/css/managemembers.css | 154 +++++++++++ app/static/css/managepositions.css | 15 ++ app/static/js/addSupervisorsToDepartment.js | 31 --- app/static/js/manageMembers.js | 223 ++++++++++++++++ app/templates/main/departmentPortal.html | 134 ++++++++++ app/templates/main/manageMembers.html | 128 +++++++++ app/templates/main/managepositions.html | 90 +++++++ app/templates/main/supervisorPortal.html | 2 +- database/demo_data.py | 243 ++++++++++++++++- database/reset_database.sh | 4 +- database/reset_database.sh.bak | 67 +++++ db_test.py | 4 +- 17 files changed, 1341 insertions(+), 67 deletions(-) create mode 100644 app/static/css/managemembers.css create mode 100644 app/static/css/managepositions.css create mode 100644 app/static/js/manageMembers.js create mode 100644 app/templates/main/manageMembers.html create mode 100644 app/templates/main/managepositions.html create mode 100644 database/reset_database.sh.bak diff --git a/app/controllers/main_routes/__init__.py b/app/controllers/main_routes/__init__.py index 54b32d3c5..da3323908 100755 --- a/app/controllers/main_routes/__init__.py +++ b/app/controllers/main_routes/__init__.py @@ -14,6 +14,7 @@ def injectGlobalData(): 'lastStaticUpdate': lastStaticUpdate} from app.controllers.main_routes import main_routes +from app.controllers.main_routes import departmentPortal from app.controllers.main_routes import laborStatusForm from app.controllers.main_routes import laborHistory from app.controllers.main_routes import alterLSF diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py index 351757701..353287e0f 100644 --- a/app/controllers/main_routes/departmentPortal.py +++ b/app/controllers/main_routes/departmentPortal.py @@ -1 +1,244 @@ -from flask import render_template +import re +from datetime import date +from flask import render_template, request, json, redirect, session, url_for, send_file, g, flash, jsonify +from peewee import JOIN, DoesNotExist, fn, Case +from functools import reduce +import operator +from app.logic.tracy import Tracy +from app.logic.userInsertFunctions import createSupervisorFromTracy +from app.models.department import Department +from app.models.supervisor import Supervisor +from app.models.supervisorDepartment import SupervisorDepartment +from app.models.student import Student +from app.models.laborStatusForm import LaborStatusForm +from app.models.formHistory import FormHistory +from app.models.laborReleaseForm import LaborReleaseForm +from app.models.term import Term +from app.controllers.admin_routes.allPendingForms import checkAdjustment +from app.controllers.main_routes import main_bp +from app.logic.download import CSVMaker, saveFormSearchResult, retrieveFormSearchResult +from app.logic.search import getDepartmentsForSupervisor, searchPerson, searchSupervisorPortal +from app.login_manager import require_login, logout +from app.logic.getTableData import getDatatableData +from app.logic.banner import Banner +from flask import abort +from app.logic.search import limitSearchByUserDepartment, studentDbToDict, usernameFromEmail + + + +@main_bp.route('/department///members', methods=['GET']) +def manageStaff(org=None,account=None): + try: + dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) + session['current_department_id'] = dept.departmentID + session['current_department'] = dept.DEPT_NAME + except (NameError, DoesNotExist): + dept = None + abort(404) + + members = list( + SupervisorDepartment. + select( + SupervisorDepartment, + Supervisor + ).where( + SupervisorDepartment.department == dept + ).join( + Supervisor + ).dicts() + ) + + today = date.today() + released_forms = ( + FormHistory + .select(FormHistory.formID) + .join( + LaborReleaseForm, + on=(FormHistory.releaseForm == LaborReleaseForm.laborReleaseFormID) + ) + .where( + (FormHistory.historyType == "Labor Release Form") & + (FormHistory.status == "Approved") & + (LaborReleaseForm.releaseDate <= today) + ) + ) + + # Conditions for the supervisee counts. Expired and released positions do + # not contribute to any of the four totals. + active_primaries = ( + (LaborStatusForm.jobType == 'Primary') & + (LaborStatusForm.studentConfirmation == True) & + (LaborStatusForm.endDate >= today) + ) + pending_primaries = ( + (LaborStatusForm.jobType == 'Primary') & + (LaborStatusForm.studentConfirmation.is_null(True)) & + (LaborStatusForm.endDate >= today) + ) + active_secondaries = ( + (LaborStatusForm.jobType == 'Secondary') & + (LaborStatusForm.studentConfirmation == True) & + (LaborStatusForm.endDate >= today) + ) + pending_secondaries = ( + (LaborStatusForm.jobType == 'Secondary') & + (LaborStatusForm.studentConfirmation.is_null(True)) & + (LaborStatusForm.endDate >= today) + ) + + + student_count = list( + LaborStatusForm. + select( + fn.SUM(Case(None, ((active_primaries, 1),), 0)).alias("active_primary_positions"), + fn.SUM(Case(None, ((pending_primaries, 1),), 0)).alias("pending_primary_positions"), + fn.SUM(Case(None, ((active_secondaries, 1),), 0)).alias("active_secondary_positions"), + fn.SUM(Case(None, ((pending_secondaries, 1),), 0)).alias("pending_secondary_positions"), + LaborStatusForm.department, + LaborStatusForm.supervisor + ).where( + (LaborStatusForm.department == dept) & + (LaborStatusForm.laborStatusFormID.not_in(released_forms)) + ).group_by( + LaborStatusForm.department, + LaborStatusForm.supervisor + ).dicts() + ) + + counts = {(row["department"], row["supervisor"]): row for row in student_count} + + for member in members: + + key = (member["department"], member["supervisor"]) + row = counts.get(key, {}) + + member["active_primary_positions"] = row.get("active_primary_positions", 0) + member["pending_primary_positions"] = row.get("pending_primary_positions", 0) + member["active_secondary_positions"] = row.get("active_secondary_positions", 0) + member["pending_secondary_positions"] = row.get("pending_secondary_positions", 0) + + return render_template('main/manageMembers.html', + members = members, + department = dept) + + +def supervisorsDbToDict(supervisor): + """ + Given a supervisor object it will return a mapped Dict with supervisor data. + """ + dbToDict = {'username': usernameFromEmail(supervisor.EMAIL.strip()), + 'firstName': supervisor.FIRST_NAME.strip(), + 'lastName': supervisor.LAST_NAME.strip(), + 'bnumber': supervisor.ID.strip(), + 'department': supervisor.DEPT_NAME.strip(), + 'type': 'Supervisor'} + return dbToDict + + +# search student table and STUDATA for student results +@main_bp.route('/members/search/', methods=['GET']) +def add_member(query=None): + currentUser = require_login() + accessAllowed = currentUser and (currentUser.supervisor or currentUser.isLaborAdmin) + if not accessAllowed: + return render_template('errors/403.html'), 403 + + recorded_supervisors = [] # supervisors recorded in the database + current_supervisors = [] # supervisors from Tracy + query = query.strip() + + current_department = session.get('current_department') + + # bnumber search + if re.match(r'[Bb]\d+', query): + recorded_supervisors = list(map(supervisorsDbToDict, Supervisor.select().where(Supervisor.ID % "{}%".format(query.upper())).where(Supervisor.DEPT_NAME != current_department))) + current_supervisors = [ + s for s in map(supervisorsDbToDict, Tracy().getSupervisorsFromUserInput(query)) + if s.get('department') != current_department + ] + + + # name search + else: + if " " not in query: + search = query.upper() + "%" + results = Supervisor.select().where(Supervisor.DEPT_NAME != current_department).where(Supervisor.preferred_name ** search | Supervisor.legal_name ** search | Supervisor.LAST_NAME ** search) + else: + search = query.upper().split() + first_query = search[0] + "%" + last_query = search[-1] + "%" + results = Supervisor.select().where(Supervisor.DEPT_NAME != current_department).where((Supervisor.preferred_name ** first_query | Supervisor.legal_name ** first_query) & Supervisor.LAST_NAME ** last_query) + + recorded_supervisors = list(map(supervisorsDbToDict, results)) + current_supervisors = [ + s for s in map(supervisorsDbToDict, Tracy().getSupervisorsFromUserInput(query)) + if s.get('department') != current_department + ] + + # combine lists, remove duplicates, and then sort + supervisors = list({v['bnumber']:v for v in (current_supervisors + recorded_supervisors)}.values()) + supervisors = sorted(supervisors, key=lambda f: f['firstName'] + f['lastName']) + + return jsonify(supervisors) + + +@main_bp.route('/members/coordinator_switch', methods=['POST']) +def coordinator_switch(): + data = request.get_json() + supervisor_id = data.get("supervisorID") + is_coordinator = data.get("isCoordinator") + + member = SupervisorDepartment.get(SupervisorDepartment.supervisor == supervisor_id) + member.isCoordinator = is_coordinator + member.save() + + return "", 200 + + +@main_bp.route('/members/ban_switch', methods=['POST']) +def ban_switch(): + data = request.get_json() + supervisor_id = data.get("supervisorID") + + member = Supervisor.get(Supervisor.ID == supervisor_id) + + member.isBanned = not member.isBanned + member.save() + + return "", 200 + + +@main_bp.route('/members/remove', methods=['DELETE']) +def remove_member(): + data = request.get_json() + supervisor_id = data.get("supervisorID") + + member = SupervisorDepartment.get( + (SupervisorDepartment.supervisor == supervisor_id) & + (SupervisorDepartment.department == session['current_department_id']) + ) + member.delete_instance() + + return "", 200 + + + +@main_bp.route('/members/add', methods=['GET', 'POST']) +def addUserToDept(): + userDeptData = request.form + supervisorDeptRecord = SupervisorDepartment.get_or_none(supervisor = userDeptData['supervisorID'], department = userDeptData['departmentID']) + try: + if supervisorDeptRecord: + return "False" + + else: + supervisorID = userDeptData['supervisorID'] + if not Supervisor.get_or_none(Supervisor.ID == supervisorID): + createSupervisorFromTracy(bnumber=supervisorID) + + SupervisorDepartment.create(supervisor=supervisorID, department=userDeptData['departmentID']) + return "True" + + except Exception as e: + print(f'Could not add user to department: {e}') + return "", 500 \ No newline at end of file diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index 0a2f21e4b..d43df38c1 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -16,6 +16,10 @@ from app.login_manager import require_login, logout from app.logic.getTableData import getDatatableData from app.logic.banner import Banner +from app.logic.tracy import Tracy +from app.logic.userInsertFunctions import createSupervisorFromTracy +from app.models.positionHistory import PositionHistory + @main_bp.route('/logout', methods=['GET']) def triggerLogout(): @@ -51,10 +55,14 @@ def supervisorPortal(): @main_bp.route('/department/', methods=['GET']) @main_bp.route('/department//', methods=['GET']) def departmentPortal(org=None,account=None): - try: - dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) - except (NameError, DoesNotExist): + if org and account: + try: + dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) + except (NameError, DoesNotExist): + dept = None + else: dept = None + @@ -65,23 +73,27 @@ def departmentPortal(org=None,account=None): return render_template('main/departmentPortal.html', departments = departments, - department = dept) - -@main_bp.route('/supervisorPortal/addUserToDept', methods=['GET', 'POST']) -def addUserToDept(): - userDeptData = request.form - supervisorDeptRecord = SupervisorDepartment.get_or_none(supervisor = userDeptData['supervisorID'], department = userDeptData['departmentID']) + department = dept, + supervisors = supervisors, + laborCoordinators=laborCoordinators, + currentUser=g.currentUser, + positions = positionsList, + posUrl = posUrl) + +@main_bp.route('/department///positions', methods=['GET']) +def managePositions(org, account): try: - if supervisorDeptRecord: - return "False" - - else: - SupervisorDepartment.create(supervisor=userDeptData['supervisorID'], department=userDeptData['departmentID']) - return "True" - - except Exception as e: - print(f'Could not add user to department: {e}') - return "", 500 + dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) + except DoesNotExist: + return render_template('errors/404.html'), 404 + + positions = Tracy().getPositionsFromDepartment(org, account) + print(positions) + return render_template('main/managepositions.html', + department = dept, + department_name = dept.DEPT_NAME, + positions = positions + ) @main_bp.route('/supervisorPortal/download', methods=['POST']) def downloadSupervisorPortalResults(): diff --git a/app/logic/tracy.py b/app/logic/tracy.py index cd0ecf50a..027cd9fd5 100644 --- a/app/logic/tracy.py +++ b/app/logic/tracy.py @@ -142,6 +142,14 @@ def getStudentsFromBNumberSearch(self, bnum_part: str): students = STUDATA.query.filter(STUDATA.ID.like(bnum_search)).all() return students + def getSupervisorsFromBNumberSearch(self, bnum_part: str): + """ + Return a list of supervisors searching by bnumber + """ + bnum_search = bnum_part.strip().upper() + "%" + supervisors = STUSTAFF.query.filter(STUSTAFF.ID.like(bnum_search)).all() + return supervisors + def checkStudentOrSupervisor(self, username: str): """ Checks if the username belongs to a student or supervisor diff --git a/app/models/supervisor.py b/app/models/supervisor.py index e16d43282..3f9d3608e 100644 --- a/app/models/supervisor.py +++ b/app/models/supervisor.py @@ -13,10 +13,11 @@ class Supervisor(baseModel): ORG = CharField(null=True) DEPT_NAME = CharField(null=True) - legal_name = CharField(null=True) - preferred_name = CharField(null=True) - isActive = BooleanField(default=False) - isBanned = BooleanField(default=False) + legal_name = CharField(null=True) + preferred_name = CharField(null=True) + isActive = BooleanField(default=False) + isBanned = BooleanField(default=False) + @property diff --git a/app/static/css/managemembers.css b/app/static/css/managemembers.css new file mode 100644 index 000000000..3384fddc6 --- /dev/null +++ b/app/static/css/managemembers.css @@ -0,0 +1,154 @@ +/*styles for column alignment in the data table*/ +.centered-header { + text-align: center !important; +} + +.centered-cell { + vertical-align: middle !important; +} + +/* The add-member search bar*/ +#add-member { + display: flex; + justify-content: center; + gap: 0px; + height: 20px; + margin-bottom: 30px; +} + + +@media (min-width: 767px) { + #add-member{ + display: flex; + justify-content: flex-end; + gap: 0px; + /*margin-bottom: -20px;*/ + } +} + + +/* The switch container */ +.switch { + position: relative; + display: inline-block; + width: 31.25px; + height: 16.25px; + vertical-align: middle; +} + +/* Hide default HTML checkbox */ +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +/* The slider track */ +.slider { + position: absolute; + cursor: pointer; + top: 0; left: 0; right: 0; bottom: 0; + background-color: #ccc !important; + transition: .4s; +} + +/* The slider knob */ +.slider:before { + position: absolute; + content: ""; + height: 11.25px; + width: 11.25px; + left: 2.5px; + bottom: 2.5px; + background-color: white !important; + transition: .4s; +} + +/* Checked state track color */ +input:checked + .slider { + background-color: #337ab7 !important; /* Bootstrap 3 Primary Color */ +} + +/* Checked state knob movement */ +input:checked + .slider:before { + transform: translateX(15px) !important; +} + +/* Rounded slider track and knob */ +.slider.round { + border-radius: 21.25px; +} +.slider.round:before { + border-radius: 50%; +} + +/* Optional label spacing */ +.switch-label { + margin-left: 6.25px; + vertical-align: middle; + font-weight: bold; +} + +/* hover indicator */ +a.hover-indicator { + text-decoration: none !important; + position: relative; + border-bottom: 1px dotted #000; + color: #000000; +} + +a.hover-indicator:visited, +a.hover-indicator:link, +a.hover-indicator:hover, +a.hover-indicator:active { + color: #000000; +} + +[class*="hover-indicator"]:after { + content: attr(aria-label); + display: none; + position: absolute; + top: 110%; + left: 10px; + z-index: 5000; + pointer-events: none; + padding: 8px 10px; + line-height: 15px; + white-space: nowrap; + text-decoration: none !important; + text-indent: 0; + overflow: visible; + font-size: .9em; + font-weight: normal; + -webkit-border-radius: 2px; + border-radius: 2px; + -webkit-box-shadow: 1px 2px 6px rgba(0,0,0,0.3); + box-shadow: 1px 2px 6px rgba(0,0,0,0.3); + background-color: #FFFFFF; + color: #000000; +} + +[class*="hover-indicator"]:hover:after, [class*="hover_indicator"]:focus:after { + display: block; + color: #000000; +} + +/*a "banned" badge displayed under the name of a banned department member*/ +.isbanned-badge { + position: relative; + display: inline-block; + margin-top: 3px; + padding: 2px 6px; + background: red; + color: white !important; + border-radius: 10px; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.3px; + line-height: 1.2; +} + +/* switches inside the data table */ +.table-switch { + top: 10px; +} \ No newline at end of file diff --git a/app/static/css/managepositions.css b/app/static/css/managepositions.css new file mode 100644 index 000000000..9c40bbe38 --- /dev/null +++ b/app/static/css/managepositions.css @@ -0,0 +1,15 @@ +.width-12{ + width:12%; +} + +*{ + /* outline:solid 1px lime; */ + margin:0; + padding:0; + box-sizing:border-box; +} + +.department-header{ + padding:1%; + margin-top:-20px; +} \ No newline at end of file diff --git a/app/static/js/addSupervisorsToDepartment.js b/app/static/js/addSupervisorsToDepartment.js index 16c3f1d85..e69de29bb 100644 --- a/app/static/js/addSupervisorsToDepartment.js +++ b/app/static/js/addSupervisorsToDepartment.js @@ -1,31 +0,0 @@ -function addSupervisorToDepartment(supervisorID, departmentID, callback=() => {}) { - return $.ajax({ - method: "POST", - url: `/supervisorPortal/addUserToDept`, - data: {"supervisorID": supervisorID, "departmentID": departmentID}, - success: function(response) { - if (response == "True") { - msgFlash("Supervisor has been added to department.", "success") - clearDropdowns() - } else { - msgFlash("Supervisor is already a member of this department.", "warning") - clearDropdowns() - } - if (callback){ - callback() - } - }, - error: function() { - msgFlash("Failed to add supervisor, please try again.", "fail") - clearDropdowns() - }, - }) - -} - -function clearDropdowns(){ - $('select.selectpicker').each(function() { - $(`#${this.id} option:eq(0)`).prop("selected", true); - $(`#${this.id}`).selectpicker("refresh"); - }); -}; \ No newline at end of file diff --git a/app/static/js/manageMembers.js b/app/static/js/manageMembers.js new file mode 100644 index 000000000..18055e1a1 --- /dev/null +++ b/app/static/js/manageMembers.js @@ -0,0 +1,223 @@ +$(document).ready(function() { + + $('#searchBoxContainer').children('.dropdown, .bootstrap-select, .form-control').addClass('open') + $('[type="search"], .form-control').focus(); + + $('#manageMembers').DataTable({ + 'columnDefs': [{ + 'targets': '.no-sorting', + 'orderable': false + }], // hide sort icon on header of first column + 'aaSorting': [ + [0, 'asc'] + ], // start to sort data in second column + searching: false, + pageLength: 10, + language: { + lengthMenu: " _MENU_ entries per page" + }, + //dom: '<"top"l>rt<"bottom"p><"clear">' + }); + + $(document).on("click", ".assign-coordinator", function() { + + let memberName = $(this).data("member-name"); + let supervisorID = $(this).data("supervisor"); + let isChecked = $(this).is(":checked"); + + $.ajax({ + url: "/members/coordinator_switch", + data: JSON.stringify({supervisorID: supervisorID, isCoordinator: isChecked}), + type: "POST", + contentType: "application/json", + success: function() { + if (isChecked) { + $("#flash_container").html("
" + memberName + " has been assigned as a coordinator.
"); + $("#flasher").delay(3000).fadeOut(); + } else { + $("#flash_container").html("
" + memberName + " is no longer a coordinator.
"); + $("#flasher").delay(3000).fadeOut(); + } + + }, + error: function() {console.log("An error has occured.");} + }) + + + }); + + $(document).on("click", ".member-status-btn", function() { + + let button = $(this); + let ban_badge = $(this).closest("tr").find(".isbanned-badge"); + + let memberName = button.data("member-name"); + let supervisorID = button.data("supervisor"); + + let banStatus = button.val(); + let isBanned = banStatus === "Banned" ? true : false; + + let quote = String.fromCharCode(39); + + let category; + + $.ajax({ + url: "/members/ban_switch", + data: JSON.stringify({supervisorID: supervisorID, isBanned: isBanned}), + type: "POST", + contentType: "application/json", + success: function() { + if (!isBanned) { + category = "danger"; + button.removeClass("btn-danger").addClass("btn-success"); + button.text("Unban"); + button.val("Banned"); + ban_badge.css("visibility", "visible"); + } else { + category = "success"; + button.removeClass("btn-success").addClass("btn-danger"); + button.html("  Ban  "); + button.val("Unbanned"); + ban_badge.css("visibility", "hidden"); + } + + $("#flash_container").html("
The status for " + memberName + " has been set to " + quote + banStatus + quote + ".
"); + $("#flasher").delay(3000).fadeOut(); + + }, + error: function() {console.log("An error has occured.");} + }) + }); + + $(document).on("click", ".remove-member", function() { + + let redButton = $(this); + let row = $(this).closest("tr"); + + let memberName = redButton.data("member-name"); + let supervisorID = redButton.data("supervisor"); + + $.ajax({ + url: "/members/remove", + data: JSON.stringify({supervisorID: supervisorID}), + type: "DELETE", + contentType: "application/json", + success: function() { + $("#flash_container").html("
" + memberName + " has been removed from the department.
"); + $("#flasher").delay(3000).fadeOut(); + row.remove(); + }, + error: function() {console.log("An error has occured.");} + }) + }); +}) + +// Creates a dom fragment from html, rather than having to add dom elements +// https://love2dev.com/blog/inserting-html-using-createdocumentfragment-instead-of-using-jquery/ +function createFragment(htmlStr) { + let frag = document.createDocumentFragment(), temp = document.createElement('div'); + temp.innerHTML = htmlStr; + while(temp.firstChild) { frag.appendChild(temp.firstChild); } + return frag; +} + +// highlight search string. doesn't actually check for last name and first name, just highlights what we find +$.fn.selectpicker.Constructor.DEFAULTS.whiteList.mark = []; +function highlight(htmlStr, query) { + query = query.trim().split(" "); + for(i = 0; i < query.length; i++) { + htmlStr = htmlStr.replace(new RegExp(query[i], "gi"), function(match) { return `${match}`; }); + } + return htmlStr; +} + +let typeTimer; + +$('#search').selectpicker('refresh'); +$('.dropdown-menu .bs-searchbox input').on('keyup', function (e) { + // ignore arrow keys + if (e.keyCode == '40' || e.keyCode == '38') return; + + // wait a little longer for bnumber typing + keyInterval = 200 + if (e.keyCode >= 48 && e.keyCode <= 57) { + keyInterval = 500 + } + + // don't search for every key (especially relevant for bnumber) + clearTimeout(typeTimer) + typeTimer = setTimeout(function() { sendQuery(e.target.value); }, keyInterval) +}); + +$('#search').on('changed.bs.select', function () { + let supervisorID = $(this).val(); + let departmentID = $(this).data('department-id'); + + if (!supervisorID || !departmentID) return; + + addSupervisorToDepartment(supervisorID, departmentID, function() { + window.location.reload(); + }); +}); + +// We load the options returned into an html string and then add them to the selectpicker at the end, to save A LOT of time. +function sendQuery(search_str) { + $("#search").empty(); + $('#search').selectpicker("refresh"); + if (search_str.length >= 3) { + $.ajax({ + type: "GET", + url: "/members/search/" + encodeURIComponent(search_str), + contentType: 'application/json', + success: function(response) { + let optionString = "" + for (let key = 0; key < response.length; key++) { + let username = response[key]['username']; + let bnumber = response[key]['bnumber']; + let firstName = response[key]['firstName']; + let lastName = response[key]['lastName']; + let type = response[key]['type']; + if (type == "Supervisor") { + choice_text = bnumber + ': ' + firstName + ' ' + lastName; + highlighted_text = highlight(choice_text, search_str) + `${username}`; + optionString += ``; + } + } + $("#search").append(createFragment(optionString)) + $('#search').selectpicker("refresh"); + } + }); + } +} + +function addSupervisorToDepartment(supervisorID, departmentID, callback=() => {}) { + return $.ajax({ + method: "POST", + url: `/members/add`, + data: {"supervisorID": supervisorID, "departmentID": departmentID}, + success: function(response) { + if (response == "True") { + msgFlash("Supervisor has been added to department.", "success") + clearDropdowns(); + } else { + msgFlash("Supervisor is already a member of this department.", "warning") + clearDropdowns(); + } + if (callback){ + callback(); + } + }, + error: function() { + msgFlash("Failed to add supervisor, please try again.", "fail") + clearDropdowns(); + }, + }) + +} + +function clearDropdowns(){ + $('select.selectpicker').each(function() { + $(`#${this.id} option:eq(0)`).prop("selected", true); + $(`#${this.id}`).selectpicker("refresh"); + }); +}; \ No newline at end of file diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index 8ee01838b..0b9a6134d 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -24,4 +24,138 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e

+ + + {% if department %} +
+
+ +
+

Insert Allocations Card Here

+ +
+ +
+ +
+
+
+
+
+ + + +
+ +
+

+ Members +

+
+
+

{% if laborCoordinators|length <= 1 %} Labor Coordinator {% else %} Labor Coordinators{% endif %}

+ {% if laborCoordinators %} + {% for coordinator in laborCoordinators %} +

+ {{ coordinator.name }} + + {% if coordinator.email %} + + + + {% endif %} +

+ {% endfor %} + {% else %} +

None assigned. Add one?

+ + + {% endif %} + + +

{% if supervisors|length <= 1 %} Supervisor{% else %} Supervisors{% endif %}

+ + {% if supervisors %} + {% for s in supervisors[:3] %} +

+ {{ s.name }} + + {% if s.email %} + + + + + {% endif %} +

+ {% endfor %} + + {% if supervisors|length > 3 %} +

and {{ supervisors|length - 3 }} more...

+ {% endif %} + + {% elif not laborCoordinators and currentUser.isLaborAdmin %} +

No active supervisors assigned. Add one?

+ {% else %} +

No active supervisors assigned.

+ {% endif %} + +
+ + +
+ +
+ +
+
+
+
+
+ +
+
+

Positions

+
+ +
+
    + {% for p in positions[:7] %} + {% if p == "No active positions in this department" %} +
  • +

    {{ p }}

    +
  • + {% else %} +
  • + {{ p }} +
  • + {% endif %} + {% endfor %} + {% if positions| length >7 %} +

and {{ (positions | length) - 7}} more...

+ {% endif %} + +
+ +
+
+
+ +{% endif %} + {% endblock %} diff --git a/app/templates/main/manageMembers.html b/app/templates/main/manageMembers.html new file mode 100644 index 000000000..8d9758fee --- /dev/null +++ b/app/templates/main/manageMembers.html @@ -0,0 +1,128 @@ +{% extends "base.html" %} + +{% block styles %} +{{super()}} + + + {% endblock %} + +{% block scripts %} +{{super()}} + + + +{% endblock %} + +{% block app_content %} +

{% if department %} Manage {{department.DEPT_NAME}} Members {% else %} Manage Members {% endif %}

+

Academic Year: 2026-2027

+ +

+ +
+ Click to Skip +
+
+ +
+
+
+ +
+ + + + + + + + {% if currentUser.isLaborAdmin or currentUser.isLaborDepartmentStudent %} + + + {% endif %} + + + + + {% for i in members %} + + + + + + + + {% if currentUser.isLaborAdmin or currentUser.isLaborDepartmentStudent %} + + + {% endif %} + + + {% endfor %} + +
NameSuperviseesAssign CoordinatorChange StatusRemove Member
+ {{ i['legal_name'] + " " + i['LAST_NAME']}} + + +
+ +
+ {% if (i['active_primary_positions'] == 0 and i['active_secondary_positions'] == 0) and (i['pending_primary_positions'] == 0 and i['pending_secondary_positions'] == 0) %} + None + {% else %} + Primary: {{i['active_primary_positions']}} active, {{i['pending_primary_positions']}} pending
+ Secondary: {{i['active_secondary_positions']}} active, {{i['pending_secondary_positions']}} pending + {% endif %} +
+
+
+ + +
+
+
+
+ {% if not i['isBanned'] %} + + {% else %} + + {% endif %} +
+
+
+ +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/main/managepositions.html b/app/templates/main/managepositions.html new file mode 100644 index 000000000..f61558a37 --- /dev/null +++ b/app/templates/main/managepositions.html @@ -0,0 +1,90 @@ +{% extends "base.html" %} + +{% block styles %} +{{super()}} + +{% endblock %} + +{% block scripts %} +{{super()}} + +{% endblock %} + +{% block app_content %} +
+

{{ department_name }}

+
+ +
+ + + +
+ + + + + + + + + + + + + + + {% for position in positions %} + + + + + + + + + {% endfor %} + +
Position (WSL)Position CodeStatusLast Revision DateView Position DescriptionEdit Position Description
{{position.POSN_TITLE}} ({{position.WLS}}){{position.POSN_CODE}} +

+ Active +

+
01/01/2024 + + + +
+
+

+ Total Positions: + {{ positions|length }} +

+
+ +{% endblock %} diff --git a/app/templates/main/supervisorPortal.html b/app/templates/main/supervisorPortal.html index 78383566c..3ab521a54 100644 --- a/app/templates/main/supervisorPortal.html +++ b/app/templates/main/supervisorPortal.html @@ -227,7 +227,7 @@

Form Search


-
+