Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b34ffd9
Changes other Events to Celts Labor with the events that are marked L…
PuskarC Jul 18, 2025
155d374
'Student-Led Services' renamed to 'Volunteer Opportunities'
PuskarC Jul 18, 2025
2c8b9e0
Changed Student led service and its all occurence to Volunteer Opport…
PuskarC Jul 18, 2025
e7b03bb
Fixed the Training and Education and Engagement tabs so that it exclu…
PuskarC Jul 18, 2025
4137e76
'Volunteer Opportunities" now only show events with the isService fl…
bakobagassas Jul 21, 2025
202c81f
solved the testing issue
bakobagassas Jul 21, 2025
ef90ec2
solved second testing issue
bakobagassas Jul 21, 2025
ee29e09
implemeted all requested changes from PR comments
bakobagassas Jul 29, 2025
d9bafe6
Merge branch 'development' into Celts-Labor
bakobagassas Jul 29, 2025
4f03722
Merge branch 'development' into Celts-Labor
bakobagassas Jul 29, 2025
eef03e2
Merge branch 'development' into Celts-Labor
bakobagassas Sep 2, 2025
a78fce1
Merge branch 'development' into Celts-Labor
Karina-Agliullova Sep 15, 2025
751af30
Merge branch 'development' into Celts-Labor
esw0624 Oct 29, 2025
b622f9b
Merge branch 'development' into Celts-Labor
bakobagassas Nov 5, 2025
082024b
started implementing requested changes for celts labor tab
bakobagassas Nov 6, 2025
946c6ed
Merge branch 'Celts-Labor' of https://github.com/BCStudentSoftwareDev…
bakobagassas Nov 6, 2025
d585ac9
Fixed the error on getting into the Event List
esw0624 Nov 10, 2025
e86719f
rewinded, fixed broken page and some logic issues. Still need to chec…
bakobagassas Nov 11, 2025
262dcd4
Labor events are not showing up in engagement and training
bakobagassas Nov 11, 2025
dfddb03
removed re-annotation
bakobagassas Nov 18, 2025
1cfc46b
Pushing Test Code
esw0624 Nov 18, 2025
0e1cb1c
Volunteer opp. in programs
bakobagassas Nov 18, 2025
86c7fda
landing page
bakobagassas Nov 18, 2025
f22fa65
Vol. Opp. and landing page thing
bakobagassas Nov 20, 2025
77db936
Fixed the issue with the engagement tab
bakobagassas Nov 20, 2025
4f5de80
Implemented logic for when a student has a labor position with celts.
bakobagassas Nov 21, 2025
340c523
Merge branch 'development' into Celts-Labor
BrianRamsay Nov 24, 2025
349bd0c
Merge branch 'development' into Celts-Labor
BrianRamsay Nov 24, 2025
17bea25
fixed syntax errors
bakobagassas Nov 24, 2025
50286e7
Merge branch 'Celts-Labor' of https://github.com/BCStudentSoftwareDev…
bakobagassas Nov 24, 2025
b2ff1f7
fixed landing page failing test
bakobagassas Nov 24, 2025
1ede70c
Fixed error with hasCurrentCeltsLabor
bakobagassas Nov 24, 2025
b819c24
Fixed event test failure!! no more tests failing (hopefully)
bakobagassas Nov 24, 2025
14e77c0
importing term
bakobagassas Nov 25, 2025
32563e2
Pulling
esw0624 Nov 25, 2025
67e1ab7
Merging remote branch
esw0624 Nov 25, 2025
e5de7b3
commiting changes
esw0624 Nov 25, 2025
9d7cc81
term import
bakobagassas Nov 25, 2025
3188bb2
corrected syntax that had been mysteriously changed
bakobagassas Nov 25, 2025
a912c38
backup alter the table
bakobagassas Nov 25, 2025
f29576b
Fixing Event List Crashing when invalid term ID is selected
esw0624 Nov 25, 2025
b9cbb16
Fixed mismatching and misssing events from backup (tested in developm…
bakobagassas Nov 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 23 additions & 20 deletions app/controllers/main/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from app.models.courseInstructor import CourseInstructor
from app.models.backgroundCheckType import BackgroundCheckType

from app.logic.events import getUpcomingEventsForUser, getParticipatedEventsForUser, getTrainingEvents, getEventRsvpCountsForTerm, getUpcomingStudentLedCount, getStudentLedEvents, getBonnerEvents, getOtherEvents, getEngagementEvents
from app.logic.events import getUpcomingEventsForUser, getParticipatedEventsForUser, getTrainingEvents, getEventRsvpCountsForTerm, getUpcomingVolunteerOpportunitiesCount, getVolunteerOpportunities, getBonnerEvents, getCeltsLabor, getEngagementEvents
from app.logic.transcript import *
from app.logic.loginManager import logout
from app.logic.searchUsers import searchUsers
Expand Down Expand Up @@ -69,7 +69,7 @@ def landingPage():
def goToEventsList(programID):
return {"activeTab": getActiveEventTab(programID)}

@main_bp.route('/eventsList/<selectedTerm>', methods=['GET'], defaults={'activeTab': "studentLedEvents", 'programID': 0})
@main_bp.route('/eventsList/<selectedTerm>', methods=['GET'], defaults={'activeTab': "volunteerOpportunities", 'programID': 0})
@main_bp.route('/eventsList/<selectedTerm>/<activeTab>', methods=['GET'], defaults={'programID': 0})
@main_bp.route('/eventsList/<selectedTerm>/<activeTab>/<programID>', methods=['GET'])
def events(selectedTerm, activeTab, programID):
Expand All @@ -82,36 +82,40 @@ def events(selectedTerm, activeTab, programID):
participantRSVP = EventRsvp.select(EventRsvp, Event).join(Event).where(EventRsvp.user == g.current_user)
rsvpedEventsID = [event.event.id for event in participantRSVP]

term: Term = Term.get_by_id(currentTerm)
if isinstance(currentTerm, Term):
term = currentTerm
else:
term = Term.get_or_none(Term.id == currentTerm)
if term is None:
term = Term.get(Term.isCurrentTerm == True)

currentEventRsvpAmount = getEventRsvpCountsForTerm(term)
studentLedEvents = getStudentLedEvents(term)
countUpcomingStudentLedEvents = getUpcomingStudentLedCount(term, currentTime)
volunteerOpportunities = getVolunteerOpportunities(term)
countUpcomingVolunteerOpportunities = getUpcomingVolunteerOpportunitiesCount(term, currentTime)
trainingEvents = getTrainingEvents(term, g.current_user)
engagementEvents = getEngagementEvents(term)
bonnerEvents = getBonnerEvents(term)
otherEvents = getOtherEvents(term)
celtsLabor = getCeltsLabor(term)

managersProgramDict = getManagerProgramDict(g.current_user)

# Fetch toggle state from session
toggleState = request.args.get('toggleState', 'unchecked')

# compile all student led events into one list
# compile all volunteer opportunitiesevents into one list
studentEvents = []
for studentEvent in studentLedEvents.values():
for studentEvent in volunteerOpportunities.values():
studentEvents += studentEvent # add all contents of studentEvent to the studentEvents list

# Get the count of all term events for each category to display in the event list page.
studentLedEventsCount: int = len(studentEvents)
volunteerOpportunitiesCount: int = len(studentEvents)
trainingEventsCount: int = len(trainingEvents)
engagementEventsCount: int = len(engagementEvents)
bonnerEventsCount: int = len(bonnerEvents)
otherEventsCount: int = len(otherEvents)
celtsLaborCount: int = len(celtsLabor)

# gets only upcoming events to display in indicators
if (toggleState == 'unchecked'):
studentLedEventsCount: int = sum(list(countUpcomingStudentLedEvents.values()))
for event in trainingEvents:
if event.isPastEnd:
trainingEventsCount -= 1
Expand All @@ -121,28 +125,27 @@ def events(selectedTerm, activeTab, programID):
for event in bonnerEvents:
if event.isPastEnd:
bonnerEventsCount -= 1
for event in otherEvents:
for event in celtsLabor:
if event.isPastEnd:
otherEventsCount -= 1

celtsLaborCount -= 1
# Handle ajax request for Event category header number notifiers and toggle
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
return jsonify({
"studentLedEventsCount": studentLedEventsCount,
"volunteerOpportunitiesCount": volunteerOpportunitiesCount,
"trainingEventsCount": trainingEventsCount,
"engagementEventsCount": engagementEventsCount,
"bonnerEventsCount": bonnerEventsCount,
"otherEventsCount": otherEventsCount,
"celtsLaborCount": celtsLaborCount,
"toggleStatus": toggleState
})

return render_template("/events/eventList.html",
selectedTerm = term,
studentLedEvents = studentLedEvents,
volunteerOpportunities = volunteerOpportunities,
trainingEvents = trainingEvents,
engagementEvents = engagementEvents,
bonnerEvents = bonnerEvents,
otherEvents = otherEvents,
celtsLabor = celtsLabor,
listOfTerms = listOfTerms,
rsvpedEventsID = rsvpedEventsID,
currentEventRsvpAmount = currentEventRsvpAmount,
Expand All @@ -151,7 +154,7 @@ def events(selectedTerm, activeTab, programID):
activeTab = activeTab,
programID = int(programID),
managersProgramDict = managersProgramDict,
countUpcomingStudentLedEvents = countUpcomingStudentLedEvents,
countUpcomingVolunteerOpportunities = countUpcomingVolunteerOpportunities,
toggleState = toggleState,
)

Expand Down
87 changes: 45 additions & 42 deletions app/logic/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,45 +224,55 @@ def saveEventToDb(newEventData, renewedEvent = False):
eventRecords.append(eventRecord)
return eventRecords

def getStudentLedEvents(term):
studentLedEvents = list(Event.select(Event, Program)
def getVolunteerOpportunities(term):
volunteerOpportunities = list(Event.select(Event, Program)
.join(Program)
.where(Program.isStudentLed,
Event.term == term, Event.deletionDate == None)
.where((Event.term == term) &
(Event.deletionDate.is_null(True)) &
(Event.isService == True) &
((Event.isLaborOnly == False) | Event.isLaborOnly.is_null(True))
)
.order_by(Event.startDate, Event.timeStart)
.execute())

programs = {}

for event in studentLedEvents:
for event in volunteerOpportunities:
programs.setdefault(event.program, []).append(event)

return programs

def getEngagementEvents(term):
engagementEvents = list(Event.select(Event, Program)
.join(Program)
.where(Event.isEngagement,
.where(Event.isEngagement, Event.isLaborOnly == False,
Event.term == term, Event.deletionDate == None)
.order_by(Event.startDate, Event.timeStart)
.execute())
return engagementEvents

def getUpcomingStudentLedCount(term, currentTime):
def getUpcomingVolunteerOpportunitiesCount(term, currentTime):
"""
Return a count of all upcoming events for each student led program.
Return a count of all upcoming events for each volunteer opportunitiesprogram.
"""

upcomingCount = (Program.select(Program.id, fn.COUNT(Event.id).alias("eventCount"))
.join(Event, on=(Program.id == Event.program_id))
.where(Program.isStudentLed,
Event.term == term, Event.deletionDate == None,
(Event.startDate > currentTime) | ((Event.startDate == currentTime) & (Event.timeEnd >= currentTime)),
Event.isCanceled == False)
.group_by(Program.id))

programCountDict = {}
upcomingCount = (
Program
.select(Program.id, fn.COUNT(Event.id).alias("eventCount"))
.join(Event, on=(Program.id == Event.program_id))
.where(
(Event.term == term) &
(Event.deletionDate.is_null(True)) &
(Event.isService == True) &
((Event.isLaborOnly == False) | Event.isLaborOnly.is_null(True)) &
((Event.startDate > currentTime) |
((Event.startDate == currentTime) & (Event.timeEnd >= currentTime))) &
(Event.isCanceled == False)
)
.group_by(Program.id)
)

programCountDict = {}
for programCount in upcomingCount:
programCountDict[programCount.id] = programCount.eventCount
return programCountDict
Expand All @@ -279,7 +289,7 @@ def getTrainingEvents(term, user):
"""
trainingQuery = (Event.select(Event).distinct()
.join(Program, JOIN.LEFT_OUTER)
.where(Event.isTraining == True,
.where(Event.isTraining == True, Event.isLaborOnly == False,
Event.term == term, Event.deletionDate == None)
.order_by(Event.isAllVolunteerTraining.desc(), Event.startDate, Event.timeStart))

Expand All @@ -290,36 +300,29 @@ def getTrainingEvents(term, user):
return list(trainingQuery.execute())

def getBonnerEvents(term):
bonnerScholarsEvents = list(Event.select(Event, Program.id.alias("program_id"))
.join(Program)
.where(Program.isBonnerScholars,
Event.term == term, Event.deletionDate == None)
.order_by(Event.startDate, Event.timeStart)
.execute())
bonnerScholarsEvents = list(
Event.select(Event, Program.id.alias("program_id"))
.join(Program)
.where(
Program.isBonnerScholars, Event.isTraining == False, Event.isEngagement == False, Event.isService == False,
Event.term == term,
Event.deletionDate == None
)
.order_by(Event.startDate, Event.timeStart)
.execute()
)
return bonnerScholarsEvents

def getOtherEvents(term):
def getCeltsLabor(term):
"""

Get the list of the events not caught by other functions to be displayed in
the Other Events section of the Events List page.
:return: A list of Other Event objects
Labor tab: events explicitly marked as Labor Only.
"""
# Gets all events that are not associated with a program and are not trainings
# Gets all events that have a program but don't fit anywhere

otherEvents = list(Event.select(Event, Program)
.join(Program, JOIN.LEFT_OUTER)
.where(Event.term == term, Event.deletionDate == None,
Event.isTraining == False,
Event.isAllVolunteerTraining == False,
((Program.isOtherCeltsSponsored) |
((Program.isStudentLed == False) &
(Program.isBonnerScholars == False))))
celtsLabor = list(Event.select()
.join(Program, JOIN.LEFT_OUTER, on=(Event.program == Program.id))
.where(Event.term == term, Event.deletionDate == None, Event.isLaborOnly == True)
.order_by(Event.startDate, Event.timeStart, Event.id)
.execute())

return otherEvents
return celtsLabor

def getUpcomingEventsForUser(user, asOf=datetime.now(), program=None):
"""
Expand Down
17 changes: 11 additions & 6 deletions app/logic/landingPage.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,16 @@ def getManagerProgramDict(user):
managerProgramDict[row.program]["managers"] = f'{managerProgramDict[row.program]["managers"]}, {row.user.firstName} {row.user.lastName}'
return managerProgramDict

def getActiveEventTab(programID):
program = Program.get_by_id(programID)
if program.isBonnerScholars:
def getActiveEventTab(programID=None, explicit_tab=None):
if explicit_tab:
return explicit_tab
if programID is None:
return "celtsLabor"
try:
program = Program.get_by_id(programID)
except Program.DoesNotExist:
return "celtsLabor"
if getattr(program, "isBonnerScholars", False):
return "bonnerScholarsEvents"
elif program.isStudentLed:
return "studentLedEvents"
else:
return "otherEvents"
return "celtsLabor"
1 change: 0 additions & 1 deletion app/models/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class Program(baseModel):
bereaUrl = TextField(null=True)
programDescription = TextField()
partner = CharField(null=True)
isStudentLed = BooleanField(default=False)
isBonnerScholars = BooleanField(default=False)
isOtherCeltsSponsored = BooleanField(default=False)
contactName = CharField(null=True,default='')
Expand Down
10 changes: 9 additions & 1 deletion app/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,15 @@ def isBonnerScholar(self):
self._bsCache = BonnerCohort.select().where(BonnerCohort.user == self).exists()

return self._bsCache


@property
def hasCurrentCeltsLabor(self):
if self._bsCache is None:
from app.models.celtsLabor import CeltsLabor
from app.models.term import Term
self._bsCache = CeltsLabor.select().where(CeltsLabor.user == self, CeltsLabor.term.isCurrent == True).exists()
return self._bsCache

@property
def fullName(self):
return f"{self.firstName} {self.lastName}"
Expand Down
8 changes: 4 additions & 4 deletions app/static/js/eventList.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,21 @@ function updateIndicatorCounts(isChecked){
toggleState: isChecked ? "checked" : "unchecked",
},
success: function(eventsCount) {
const studentLedEventsCount = Number(eventsCount.studentLedEventsCount);
const volunteerOpportunitiesCount = Number(eventsCount.volunteerOpportunitiesCount);
const trainingEventsCount = Number(eventsCount.trainingEventsCount);
const engagementEventsCount = Number(eventsCount.engagementEventsCount);
const bonnerEventsCount = Number(eventsCount.bonnerEventsCount);
const otherEventsCount = Number(eventsCount.otherEventsCount);
const celtsLaborCount = Number(eventsCount.celtsLaborCount);
const toggleStatus = eventsCount.toggleStatus;

$("#viewPastEventsToggle").prop(toggleStatus, true);

// use ternary operators to populate the tab with a number if there are events, and clear the count if there are none
studentLedEventsCount > 0 ? $("#studentLedEvents").html(`Student-Led Services (${studentLedEventsCount})`) : $("#studentLedEvents").html(`Student-Led Services`)
volunteerOpportunitiesCount > 0 ? $("#volunteerOpportunities").html(`Volunteer Opportunities (${volunteerOpportunitiesCount})`) : $("#volunteerOpportunities").html(`Volunteer Opportunities`)
trainingEventsCount > 0 ? $("#trainingEvents").html(`Trainings (${trainingEventsCount})`) : $("#trainingEvents").html(`Trainings`)
engagementEventsCount > 0 ? $("#engagementEvents").html(`Education and Engagement (${engagementEventsCount})`) : $("#engagementEvents").html('Education and Engagement')
bonnerEventsCount > 0 ? $("#bonnerScholarsEvents").html(`Bonner Scholars (${bonnerEventsCount})`) : $("#bonnerScholarsEvents").html(`Bonner Scholars`)
otherEventsCount > 0 ? $("#otherEvents").html(`Other Events (${otherEventsCount})`) : $("#otherEvents").html(`Other Events`)
celtsLaborCount > 0 ? $("#celtsLabor").html(`Celts Labor (${celtsLaborCount})`) : $("#celtsLabor").html(`Celts Labor`)
},
error: function(request, status, error) {
console.log(status,error);
Expand Down
2 changes: 1 addition & 1 deletion app/static/js/landingPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ $(document).ready(function(){
url: "/goToEventsList/"+programID,
type: "GET",
success: function(response) {
if (response.activeTab === "studentLedEvents"){
if (response.activeTab === "volunteerOpportunities"){
window.location.href += "eventsList/"+term+"/"+response.activeTab+"/"+programID
} else {
window.location.href += "eventsList/"+term+"/"+response.activeTab
Expand Down
Loading