Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple offering events #1282

Merged
merged 214 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from 200 commits
Commits
Show all changes
214 commits
Select commit Hold shift + click to select a range
dcd7fac
made modificaitons to the event.py and events.py in models and logic …
vungc Jun 17, 2024
36a97c6
html and js push
MImran2002 Jun 18, 2024
81724e3
modal toggle button created
MImran2002 Jun 18, 2024
37283b2
adding modal into the document
MImran2002 Jun 18, 2024
58e5a02
added new tests for isCustom and added isCustom in the lists
vungc Jun 19, 2024
49a2bd9
updated functions to resolve isCustom not existing - not solved
vungc Jun 19, 2024
8da1012
committing again
MImran2002 Jun 19, 2024
854b5f2
isCustom is passing in the tests, added isCustom in the dictionary in…
vungc Jun 19, 2024
a468a1d
tried to replicate the test for recurring events under test_deleteEve…
vungc Jun 19, 2024
93d151b
have done most of the modal ui
MImran2002 Jun 20, 2024
698b696
Merge branch 'imran-annaTraining' of https://github.com/BCStudentSoft…
MImran2002 Jun 20, 2024
c941ced
morning push
MImran2002 Jun 21, 2024
469c169
commented off all the function and chnages
MImran2002 Jun 24, 2024
1b5ef08
copied functions from recurring events to apply to custom events
vungc Jun 24, 2024
4382628
custom event modal
dixita9 Jun 24, 2024
5012037
figured out how to retrieve data from modal
dixita9 Jun 25, 2024
6f9d41c
created a loop to retriee the data from modal and store it in a list
vungc Jun 26, 2024
76be445
custom toggle fixed
dixita9 Jun 26, 2024
80721a7
fixed the toggle buttons to show custom event headings or recurring e…
vungc Jun 26, 2024
eb5d02a
Save button mostly fixed
dixita9 Jun 27, 2024
0825911
datepicker shows up when calendar icon is clicked for clones, but onl…
vungc Jun 27, 2024
2f49fb9
fixed the custom table display
dixita9 Jun 28, 2024
2ba7d62
Merge branch 'imran-annaTraining' of https://github.com/BCStudentSoft…
dixita9 Jun 28, 2024
a9b2d12
calendars on the modal are working now
vungc Jun 28, 2024
352d0aa
custom toggle fixed
dixita9 Jun 28, 2024
7882022
custom toggle fixed
dixita9 Jun 28, 2024
f4cd2f8
trash icons are working; clicking on it will delete its corresponding…
vungc Jun 28, 2024
aecd78d
added event name in front end
dixita9 Jun 30, 2024
f1ccb17
custom table completed
dixita9 Jul 1, 2024
451e9dd
hidden input created
dixita9 Jul 1, 2024
f188cb8
added for loop in the routes to create dictioanries for each of the m…
vungc Jul 1, 2024
1961404
chagned time displayed to be in 12hr format, cleaned up HTML and JS f…
vungc Jul 2, 2024
52b88e2
tried to debug the dicitoanry in the routes, still work in progress
vungc Jul 2, 2024
5e6e546
json error fixed
dixita9 Jul 2, 2024
7174329
data is saving to the databse
vungc Jul 2, 2024
a25977d
admin logs are working correctly now
dixita9 Jul 3, 2024
c4549d7
cleaned the debug statements in routes and modified the adminlog to d…
vungc Jul 3, 2024
0cc1de2
flash messages appear after tojson is added back on base.html, save b…
vungc Jul 8, 2024
168032c
modified customDict in routes to only update the different data
vungc Jul 8, 2024
b3e625d
changed the name of the custom events to multiple offering events
dixita9 Jul 9, 2024
fc9c1a9
added multiple offerings to some tests
dixita9 Jul 9, 2024
6b79ec5
added a test for saving multiple offering events
vungc Jul 10, 2024
1161a39
tests for multiple offerings completed
dixita9 Jul 10, 2024
c0d4bcc
pulled from development
dixita9 Jul 10, 2024
87a1cfa
modified trash can button to be similar to the
JohnCox2211 Jul 10, 2024
e6c430b
merged changes
dixita9 Jul 11, 2024
dab7918
made modificaitons to the event.py and events.py in models and logic …
vungc Jun 17, 2024
5f11a7b
html and js push
MImran2002 Jun 18, 2024
9fc5c07
modal toggle button created
MImran2002 Jun 18, 2024
7db26b1
adding modal into the document
MImran2002 Jun 18, 2024
9f04512
added new tests for isCustom and added isCustom in the lists
vungc Jun 19, 2024
c8ad996
updated functions to resolve isCustom not existing - not solved
vungc Jun 19, 2024
81a6bf7
committing again
MImran2002 Jun 19, 2024
80217a8
have done most of the modal ui
MImran2002 Jun 20, 2024
a1f0240
isCustom is passing in the tests, added isCustom in the dictionary in…
vungc Jun 19, 2024
7ab38d1
tried to replicate the test for recurring events under test_deleteEve…
vungc Jun 19, 2024
c32bd4c
morning push
MImran2002 Jun 21, 2024
9449dd6
commented off all the function and chnages
MImran2002 Jun 24, 2024
80048a1
copied functions from recurring events to apply to custom events
vungc Jun 24, 2024
e813adb
copied functions from recurring events to apply to custom events
vungc Jun 24, 2024
42f5bf1
custom event modal
dixita9 Jun 24, 2024
0d5c516
figured out how to retrieve data from modal
dixita9 Jun 25, 2024
d533689
created a loop to retriee the data from modal and store it in a list
vungc Jun 26, 2024
c7a6598
custom toggle fixed
dixita9 Jun 26, 2024
fe23641
fixed the toggle buttons to show custom event headings or recurring e…
vungc Jun 26, 2024
6a433ea
Save button mostly fixed
dixita9 Jun 27, 2024
e0381ab
fixed the custom table display
dixita9 Jun 28, 2024
5df4bab
datepicker shows up when calendar icon is clicked for clones, but onl…
vungc Jun 27, 2024
7d5222a
custom toggle fixed
dixita9 Jun 28, 2024
b3bd61a
calendars on the modal are working now
vungc Jun 28, 2024
f72d0ab
trash icons are working; clicking on it will delete its corresponding…
vungc Jun 28, 2024
0bdaa83
added event name in front end
dixita9 Jun 30, 2024
8e70823
custom table completed
dixita9 Jul 1, 2024
f718b9d
hidden input created
dixita9 Jul 1, 2024
98aa75e
added for loop in the routes to create dictioanries for each of the m…
vungc Jul 1, 2024
11cdf06
chagned time displayed to be in 12hr format, cleaned up HTML and JS f…
vungc Jul 2, 2024
caf33df
tried to debug the dicitoanry in the routes, still work in progress
vungc Jul 2, 2024
8c25dae
json error fixed
dixita9 Jul 2, 2024
ffd48ad
data is saving to the databse
vungc Jul 2, 2024
8bf0e12
admin logs are working correctly now
dixita9 Jul 3, 2024
24c2940
cleaned the debug statements in routes and modified the adminlog to d…
vungc Jul 3, 2024
5fbdacf
flash messages appear after tojson is added back on base.html, save b…
vungc Jul 8, 2024
d658073
modified customDict in routes to only update the different data
vungc Jul 8, 2024
25c4095
changed the name of the custom events to multiple offering events
dixita9 Jul 9, 2024
3747274
added multiple offerings to some tests
dixita9 Jul 9, 2024
a9049fe
added a test for saving multiple offering events
vungc Jul 10, 2024
2c140f6
tests for multiple offerings completed
dixita9 Jul 10, 2024
a1deee0
modified trash can button to be similar to the
JohnCox2211 Jul 10, 2024
f0bbae3
Formatted the add multiple event button to
JohnCox2211 Jul 10, 2024
8f4971b
Added css file for createEvent for button styling
JohnCox2211 Jul 10, 2024
d589ea0
html and js push
MImran2002 Jun 18, 2024
197cf33
modal toggle button created
MImran2002 Jun 18, 2024
b3ae4f7
adding modal into the document
MImran2002 Jun 18, 2024
edc4013
committing again
MImran2002 Jun 19, 2024
fbdcd9b
have done most of the modal ui
MImran2002 Jun 20, 2024
a1f05ac
morning push
MImran2002 Jun 21, 2024
2c7d144
commented off all the function and chnages
MImran2002 Jun 24, 2024
1473231
copied functions from recurring events to apply to custom events
vungc Jun 24, 2024
67995d7
figured out how to retrieve data from modal
dixita9 Jun 25, 2024
0a83a0a
created a loop to retriee the data from modal and store it in a list
vungc Jun 26, 2024
28cf415
fixed the toggle buttons to show custom event headings or recurring e…
vungc Jun 26, 2024
a5635fb
calendars on the modal are working now
vungc Jun 28, 2024
8830986
trash icons are working; clicking on it will delete its corresponding…
vungc Jun 28, 2024
119eef0
custom table completed
dixita9 Jul 1, 2024
c8f1497
chagned time displayed to be in 12hr format, cleaned up HTML and JS f…
vungc Jul 2, 2024
a267dba
tried to debug the dicitoanry in the routes, still work in progress
vungc Jul 2, 2024
3129576
json error fixed
dixita9 Jul 2, 2024
d9feeba
flash messages appear after tojson is added back on base.html, save b…
vungc Jul 8, 2024
bfc315c
changed the name of the custom events to multiple offering events
dixita9 Jul 9, 2024
af24738
made logging functions consistent with those in
JohnCox2211 Jul 11, 2024
8c930c9
resovled merge issues
JohnCox2211 Jul 11, 2024
be93f67
resolved merge issues
JohnCox2211 Jul 11, 2024
ab5e470
no more errorr
JohnCox2211 Jul 11, 2024
b0e86f6
Added date type to the date entry for default
JohnCox2211 Jul 11, 2024
89ff2bf
end of day commit, working on default date picker
JohnCox2211 Jul 11, 2024
d8c4554
TRYING TO PULL
JohnCox2211 Jul 12, 2024
a1092bc
Merge branch 'development' of https://github.com/BCStudentSoftwareDev…
dixita9 Jul 12, 2024
1d21c2e
cleaned create event page
dixita9 Jul 12, 2024
3502b55
removed dupe divs
JohnCox2211 Jul 12, 2024
93701b8
cleaned create event page
dixita9 Jul 12, 2024
e66ca49
removed dupe divs
JohnCox2211 Jul 12, 2024
82300ec
added required tags in modal
JohnCox2211 Jul 12, 2024
2cb1dce
Added function to make modal fields required. Need
JohnCox2211 Jul 12, 2024
5510b16
merged
dixita9 Jul 12, 2024
5c0ce83
Added a lil text notifier in the modal to tell the
JohnCox2211 Jul 12, 2024
2c69f20
Merge branch 'multipleOfferingJohn' of https://github.com/BCStudentSo…
dixita9 Jul 12, 2024
dad7979
designed the message flash for modal
dixita9 Jul 12, 2024
d3f27a0
added comments for tomorrow's work
dixita9 Jul 13, 2024
be64f54
fixed required inputs in modal: event name
dixita9 Jul 15, 2024
2e20e5d
Corrected spelling and centered text for the
JohnCox2211 Jul 15, 2024
987f4f3
main page name transfers to modal, working on
JohnCox2211 Jul 15, 2024
f20b94a
User can no longer select recurring event and
JohnCox2211 Jul 15, 2024
49ba915
All fields now required in the event modal
JohnCox2211 Jul 15, 2024
a1f08be
fixed modal notifier formatting
JohnCox2211 Jul 15, 2024
46e6a82
add animation to the modal notifier
JohnCox2211 Jul 16, 2024
7f1c6ef
removed unused function
JohnCox2211 Jul 16, 2024
c9b21ab
date formating in process
dixita9 Jul 16, 2024
76fa436
Merge branch 'multipleOfferingJohn' of https://github.com/BCStudentSo…
dixita9 Jul 16, 2024
50ef0bd
date format for modal table fixed
dixita9 Jul 16, 2024
7c68b47
date formating in process
dixita9 Jul 16, 2024
dc4703c
date format for modal table fixed
dixita9 Jul 16, 2024
32ed432
commiting to pull changes
JohnCox2211 Jul 16, 2024
57ec63e
added function back that git deemed useless for
JohnCox2211 Jul 16, 2024
5cd4c82
modified toggle switch logic, still not working
JohnCox2211 Jul 16, 2024
f946393
muliple offering and recurring toggle cannot be toggled at the same …
dixita9 Jul 16, 2024
a091fc9
toggle fixed and branches merged
dixita9 Jul 17, 2024
2875770
removed unncessary lines of code from toggle code
dixita9 Jul 17, 2024
1f4c81a
date formating in process
dixita9 Jul 16, 2024
6edc142
date format for modal table fixed
dixita9 Jul 16, 2024
cd11c8f
muliple offering and recurring toggle cannot be toggled at the same …
dixita9 Jul 16, 2024
c841946
removed unncessary lines of code from toggle code
dixita9 Jul 17, 2024
e02e090
fixed the code that git broke again
JohnCox2211 Jul 17, 2024
4874918
date picker fixed
dixita9 Jul 17, 2024
214c27b
removed dupe function that git decided it wanted
JohnCox2211 Jul 17, 2024
09aa60f
Merge branch 'multipleOfferingJohn' of https://github.com/BCStudentSo…
dixita9 Jul 17, 2024
44a759f
fixed dte picker
dixita9 Jul 17, 2024
0f8387a
fixed duplicate code
dixita9 Jul 17, 2024
fe7af93
fixed merge issues
dixita9 Jul 17, 2024
49178e8
removed more dupes
JohnCox2211 Jul 17, 2024
064083d
fixed end date
dixita9 Jul 17, 2024
60598b4
corrected HTML date formatting for editing event
JohnCox2211 Jul 17, 2024
fd0e1da
removed unused code and updated comments in
JohnCox2211 Jul 17, 2024
865fae6
No more error with saving events due to the date
JohnCox2211 Jul 17, 2024
df1ea6c
Merge branch 'multipleOfferingJohn' of https://github.com/BCStudentSo…
dixita9 Jul 17, 2024
3417737
edit button created
dixita9 Jul 17, 2024
bcbb297
added background colors to the event tables and
JohnCox2211 Jul 17, 2024
55c94ff
merged branch changes
JohnCox2211 Jul 17, 2024
6225086
made the padding spacing in the modal better
JohnCox2211 Jul 17, 2024
53f1479
fixed the functionality of edit button
dixita9 Jul 17, 2024
4c471f9
fixed multi event table date formatting causing
JohnCox2211 Jul 17, 2024
74f6c7f
fixed the functionality of edit button
dixita9 Jul 17, 2024
bfc2582
merged branch changes
JohnCox2211 Jul 17, 2024
3ab34ab
removed dupe code
JohnCox2211 Jul 17, 2024
1f2f8cb
removed dupe code again
JohnCox2211 Jul 18, 2024
1ecee70
changed comment placing, changed recurring and
JohnCox2211 Jul 18, 2024
3f5b4a6
Updated specified default JS code to be JQuery.
JohnCox2211 Jul 18, 2024
3d746ad
split a variable that would hold recurring event
JohnCox2211 Jul 18, 2024
65ae61f
red border added to the modl inputs that are empty, edit modal button…
dixita9 Jul 18, 2024
6ab4871
fixed the functionality of edit button
dixita9 Jul 17, 2024
2068eca
red border added to the modl inputs that are empty, edit modal button…
dixita9 Jul 18, 2024
3e18265
added background colors to the event tables and
JohnCox2211 Jul 17, 2024
b8302d2
merged branch changes
JohnCox2211 Jul 17, 2024
184c6b9
fixed the functionality of edit button
dixita9 Jul 17, 2024
579699e
merged branch changes
JohnCox2211 Jul 17, 2024
5d16c59
removed dupe code again
JohnCox2211 Jul 18, 2024
9463406
changed comment placing, changed recurring and
JohnCox2211 Jul 18, 2024
36b11e5
merged working branches
JohnCox2211 Jul 18, 2024
ca03b73
edit modal issue fixed
dixita9 Jul 19, 2024
0746935
removed unused function
JohnCox2211 Jul 19, 2024
e8b1aab
fixed the functionality of edit button
dixita9 Jul 17, 2024
94c4d3e
red border added to the modl inputs that are empty, edit modal button…
dixita9 Jul 18, 2024
13b2131
added back parenthesis that git removed
JohnCox2211 Jul 19, 2024
e483f9a
corrected variable names
JohnCox2211 Jul 22, 2024
06cf28b
now use saved event dates instead of getting new
JohnCox2211 Jul 22, 2024
04469e3
updated formatting for date correction
JohnCox2211 Jul 22, 2024
8d765da
Demo commit
Jul 23, 2024
b312cdd
checked for end time after start time
dixita9 Jul 23, 2024
6d7e894
Merge branch 'multipleOfferingJohn' of https://github.com/BCStudentSo…
dixita9 Jul 23, 2024
3342728
working fine
dixita9 Jul 24, 2024
a11c277
added red border to start time and end time
dixita9 Jul 24, 2024
222937f
Merge branch 'development' of https://github.com/BCStudentSoftwareDev…
dixita9 Jul 30, 2024
cb80ccd
Merged with Development
dixita9 Jul 30, 2024
137a18d
datepicker fixed
dixita9 Jul 30, 2024
10be44e
fixed footer
dixita9 Jul 30, 2024
19d73aa
fixed footer
dixita9 Jul 30, 2024
e32e7e0
Solved merge conflicts
Jul 31, 2024
fbffdc1
Save button was not appearing due to an issue in HTML, fixed.
Jul 31, 2024
e123e55
Centred Headings for Optional and Must Select
Jul 31, 2024
804c99e
Fixed modal footer issue
Jul 31, 2024
d70a9b0
merge conflict resloved. Footer works as expected. Save and Cancel fu…
Jul 31, 2024
785a9e2
Merge branch 'development' into MultipleOfferingEvents
BrianRamsay Jul 31, 2024
97b860e
Removed MultipleOffering id from delete function
Jul 31, 2024
3df0339
Merge branch 'MultipleOfferingEvents' of https://github.com/BCStudent…
Aug 1, 2024
5baf8c5
completed
dixita9 Aug 1, 2024
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
63 changes: 51 additions & 12 deletions app/controllers/admin/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
from app.logic.createLogs import createActivityLog
from app.logic.certification import getCertRequirements, updateCertRequirements
from app.logic.utils import selectSurroundingTerms, getFilesFromRequest, getRedirectTarget, setRedirectTarget
from app.logic.events import cancelEvent, deleteEvent, attemptSaveEvent, preprocessEventData, calculateRecurringEventFrequency, deleteEventAndAllFollowing, deleteAllRecurringEvents, getBonnerEvents,addEventView, getEventRsvpCount, copyRsvpToNewEvent, getCountdownToEvent
from app.logic.events import cancelEvent, deleteEvent, attemptSaveEvent, preprocessEventData, calculateRecurringEventFrequency, deleteEventAndAllFollowing, deleteAllRecurringEvents, getBonnerEvents,addEventView, getEventRsvpCount, copyRsvpToNewEvent, getCountdownToEvent, calculateNewMultipleOfferingId
from app.logic.events import cancelEvent, deleteEvent, attemptSaveEvent, preprocessEventData, calculateRecurringEventFrequency, deleteEventAndAllFollowing, deleteAllRecurringEvents, getBonnerEvents,addEventView, getEventRsvpCount, copyRsvpToNewEvent, getCountdownToEvent, calculateNewMultipleOfferingId
from app.logic.participants import getParticipationStatusForTrainings, checkUserRsvp
from app.logic.minor import getMinorInterest
from app.logic.fileHandler import FileHandler
Expand Down Expand Up @@ -66,6 +67,7 @@ def templateSelect():

@admin_bp.route('/eventTemplates/<templateid>/<programid>/create', methods=['GET','POST'])
def createEvent(templateid, programid):
savedEventsList = []
if not (g.current_user.isAdmin or g.current_user.isProgramManagerFor(programid)):
abort(403)

Expand Down Expand Up @@ -98,13 +100,31 @@ def createEvent(templateid, programid):
# Try to save the form
if request.method == "POST":
eventData.update(request.form.copy())
try:
savedEvents, validationErrorMessage = attemptSaveEvent(eventData, getFilesFromRequest(request))
if eventData.get('isMultipleOffering'):
multipleOfferingId = calculateNewMultipleOfferingId()

multipleOfferingData = json.loads(eventData.get('multipleOfferingData'))
for event in multipleOfferingData:
multipleOfferingDict = eventData.copy()
multipleOfferingDict.update({
'name': event['eventName'],
'startDate': event['eventDate'],
'timeStart': event['startTime'],
'timeEnd': event['endTime'],
'multipleOfferingId': multipleOfferingId
})
try:
savedEvents, validationErrorMessage = attemptSaveEvent(multipleOfferingDict, getFilesFromRequest(request))
savedEventsList.append(savedEvents)

except Exception as e:
print("Failed saving multi event", e)

except Exception as e:
print("Error saving event:", e)
savedEvents = False
validationErrorMessage = "Unknown Error Saving Event. Please try again"
else:
try:
savedEvents, validationErrorMessage = attemptSaveEvent(eventData, getFilesFromRequest(request))
except Exception as e:
print("Failed saving regular event", e)

if savedEvents:
rsvpcohorts = request.form.getlist("cohorts[]")
Expand All @@ -113,14 +133,32 @@ def createEvent(templateid, programid):
addBonnerCohortToRsvpLog(int(year), savedEvents[0].id)


noun = (eventData['isRecurring'] == 'on' and "Events" or "Event") # pluralize
noun = ((eventData.get('isRecurring') or eventData.get('isMultipleOffering')) and "Events" or "Event") # pluralize
flash(f"{noun} successfully created!", 'success')



if program:
if len(savedEvents) > 1:
if len(savedEvents) > 1 and eventData.get('isRecurring'):
createActivityLog(f"Created a recurring event, <a href=\"{url_for('admin.eventDisplay', eventId = savedEvents[0].id)}\">{savedEvents[0].name}</a>, for {program.programName}, with a start date of {datetime.strftime(eventData['startDate'], '%m/%d/%Y')}. The last event in the series will be on {datetime.strftime(savedEvents[-1].startDate, '%m/%d/%Y')}.")

elif len(savedEventsList) >= 1 and eventData.get('isMultipleOffering'):
modifiedSavedEvents = [item for sublist in savedEventsList for item in sublist]

event_dates = [event_data[0].startDate.strftime('%m/%d/%Y') for event_data in savedEventsList]

event_list = ', '.join(f"<a href=\"{url_for('admin.eventDisplay', eventId=event.id)}\">{event.name}</a>" for event in modifiedSavedEvents)

if len(modifiedSavedEvents) > 1:
#creates list of events created in a multiple series to display in the logs
event_list = ', '.join(event_list.split(', ')[:-1]) + f', and ' + event_list.split(', ')[-1]
#get last date and stick at the end after 'and' so that it reads like a sentence in admin log
last_event_date = event_dates[-1]
event_dates = ', '.join(event_dates[:-1]) + f', and {last_event_date}'

createActivityLog(f"Created events {event_list} for {program.programName}, with start dates of {event_dates}.")

else:
createActivityLog(f"Created <a href=\"{url_for('admin.eventDisplay', eventId = savedEvents[0].id)}\">{savedEvents[0].name}</a> for {program.programName}, with a start date of {datetime.strftime(eventData['startDate'], '%m/%d/%Y')}.")
createActivityLog(f"Created events <a href=\"{url_for('admin.eventDisplay', eventId = savedEvents[0].id)}\">{savedEvents[0].name}</a> for {program.programName}, with a start date of {datetime.strftime(eventData['startDate'], '%m/%d/%Y')}.")
else:
createActivityLog(f"Created a non-program event, <a href=\"{url_for('admin.eventDisplay', eventId = savedEvents[0].id)}\">{savedEvents[0].name}</a>, with a start date of {datetime.strftime(eventData['startDate'], '%m/%d/%Y')}.")

Expand Down Expand Up @@ -187,7 +225,8 @@ def renewEvent(eventId):
'location': formData['location'],
'startDate': f'{formData["startDate"][-4:]}-{formData["startDate"][0:-5]}',
'endDate': f'{formData["endDate"][-4:]}-{formData["endDate"][0:-5]}',
'isRecurring': bool(priorEvent['recurringId'])
'isRecurring': bool(priorEvent['recurringId']),
'isMultipleOffering': bool(priorEvent['multipleOffeirngId']),
})
newEvent, message = attemptSaveEvent(newEventDict, renewedEvent = True)
if message:
Expand Down
62 changes: 51 additions & 11 deletions app/logic/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,35 +67,40 @@ def deleteEvent(eventId):

event.delete_instance(recursive = True, delete_nullable = True)


def deleteEventAndAllFollowing(eventId):
"""
Deletes a recurring event and all the recurring events after it.
Modified to also apply to the case of events with multiple offerings
"""
event = Event.get_or_none(Event.id == eventId)
if event:
if event.recurringId:
if event.recurringId or event.multipleOfferingId:
recurringId = event.recurringId
recurringSeries = list(Event.select().where((Event.recurringId == recurringId) & (Event.startDate >= event.startDate)))
multipleOfferingId = event.multipleOfferingId
recurringSeries = list(Event.select().where((Event.recurringId == recurringId or Event.multipleOfferingId== multipleOfferingId) & (Event.startDate >= event.startDate)))
for seriesEvent in recurringSeries:
seriesEvent.delete_instance(recursive = True)

def deleteAllRecurringEvents(eventId):
"""
Deletes all recurring events.
Modified to also apply for events with multiple offerings
"""
event = Event.get_or_none(Event.id == eventId)
if event:
if event.recurringId:
if event.recurringId or event.multipleOfferingId:
recurringId = event.recurringId
allRecurringEvents = list(Event.select().where(Event.recurringId == recurringId))
MultipleOfferingId = event.multipleOfferingId
allRecurringEvents = list(Event.select().where(Event.recurringId == recurringId or Event.multipleOfferingId == MultipleOfferingId))
for aRecurringEvent in allRecurringEvents:
aRecurringEvent.delete_instance(recursive = True)


def attemptSaveEvent(eventData, attachmentFiles = None, renewedEvent = False):
"""
Tries to save an event to the database:
Checks that the event data is valid and if it is it continus to saves the new
Checks that the event data is valid and if it is, it continues to save the new
event to the database and adds files if there are any.
If it is not valid it will return a validation error.

Expand All @@ -107,6 +112,7 @@ def attemptSaveEvent(eventData, attachmentFiles = None, renewedEvent = False):
# automatically changed from "" to 0
if eventData["rsvpLimit"] == "":
eventData["rsvpLimit"] = None

newEventData = preprocessEventData(eventData)

isValid, validationErrorMessage = validateNewEventData(newEventData)
Expand Down Expand Up @@ -136,17 +142,26 @@ def saveEventToDb(newEventData, renewedEvent = False):

eventsToCreate = []
recurringSeriesId = None
multipleSeriesId = None
if (isNewEvent and newEventData['isRecurring']) and not renewedEvent:
eventsToCreate = calculateRecurringEventFrequency(newEventData)
recurringSeriesId = calculateNewrecurringId()

#temporarily applying the append for single events for now to tests
elif(isNewEvent and newEventData['isMultipleOffering']) and not renewedEvent:
eventsToCreate.append({'name': f"{newEventData['name']}",
'date':newEventData['startDate'],
"week":1})
multipleSeriesId = newEventData['multipleOfferingId']

else:
eventsToCreate.append({'name': f"{newEventData['name']}",
'date':newEventData['startDate'],
"week":1})
if renewedEvent:
recurringSeriesId = newEventData.get('recurringId')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't handle the multiple offering case here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, that append happens in both cases, so we should make the conditional for isMultipleOffering only be around the code that depends on the condition.

eventRecords = []
for eventInstance in eventsToCreate:
for eventInstance in eventsToCreate:
with mainDB.atomic():

eventData = {
Expand All @@ -172,6 +187,7 @@ def saveEventToDb(newEventData, renewedEvent = False):
if isNewEvent:
eventData['program'] = newEventData['program']
eventData['recurringId'] = recurringSeriesId
eventData['multipleOfferingId'] = multipleSeriesId
eventData["isAllVolunteerTraining"] = newEventData['isAllVolunteerTraining']
eventRecord = Event.create(**eventData)
else:
Expand Down Expand Up @@ -296,14 +312,18 @@ def getUpcomingEventsForUser(user, asOf=datetime.now(), program=None):

events_list = []
shown_recurring_event_list = []
shown_multiple_offering_event_list = []

# removes all recurring events except for the next upcoming one
for event in events:
if event.recurringId:
if event.recurringId or event.multipleOfferingId:
if not event.isCanceled:
if event.recurringId not in shown_recurring_event_list:
events_list.append(event)
shown_recurring_event_list.append(event.recurringId)
if event.multipleOfferingId not in shown_multiple_offering_event_list:
events_list.append(event)
shown_multiple_offering_event_list.append(event.multipleOfferingId)
else:
if not event.isCanceled:
events_list.append(event)
Expand Down Expand Up @@ -344,7 +364,7 @@ def validateNewEventData(data):
Returns 3 values: (boolean success, the validation error message, the data object)
"""

if 'on' in [data['isFoodProvided'], data['isRsvpRequired'], data['isTraining'], data['isService'], data['isRecurring']]:
if 'on' in [data['isFoodProvided'], data['isRsvpRequired'], data['isTraining'], data['isService'], data['isRecurring'], data['isMultipleOffering']]:
return (False, "Raw form data passed to validate method. Preprocess first.")

if data['isRecurring'] and data['endDate'] < data['startDate']:
Expand Down Expand Up @@ -386,6 +406,15 @@ def calculateNewrecurringId():
return recurringId + 1
else:
return 1
def calculateNewMultipleOfferingId():
"""
Gets the highest recurring Id so that a new recurring Id can be assigned
"""
multipleOfferingId = Event.select(fn.MAX(Event.multipleOfferingId)).scalar()
if multipleOfferingId:
return multipleOfferingId + 1
else:
return 1

def getPreviousRecurringEventData(recurringId):
"""
Expand All @@ -397,6 +426,16 @@ def getPreviousRecurringEventData(recurringId):
.where(Event.recurringId==recurringId))
return previousEventVolunteers

def getPreviousMultipleOfferingEventData(multipleOfferingId):
"""
Joins the User db table and Event Participant db table so that we can get the information of a participant if they attended an event
"""
previousEventVolunteers = (User.select(User).distinct()
.join(EventParticipant)
.join(Event)
.where(Event.multipleOfferingId == multipleOfferingId))
return previousEventVolunteers

def calculateRecurringEventFrequency(event):
"""
Calculate the events to create based on a recurring event start and end date. Takes a
Expand All @@ -411,6 +450,7 @@ def calculateRecurringEventFrequency(event):

if event['endDate'] == event['startDate']:
raise Exception("This event is not a recurring event")

return [ {'name': f"{event['name']} Week {counter+1}",
'date': event['startDate'] + timedelta(days=7*counter),
"week": counter+1}
Expand All @@ -427,7 +467,7 @@ def preprocessEventData(eventData):
- Look up matching certification requirement if necessary
"""
## Process checkboxes
eventCheckBoxes = ['isFoodProvided', 'isRsvpRequired', 'isService', 'isTraining', 'isRecurring', 'isAllVolunteerTraining']
eventCheckBoxes = ['isFoodProvided', 'isRsvpRequired', 'isService', 'isTraining', 'isRecurring', 'isMultipleOffering', 'isAllVolunteerTraining']

for checkBox in eventCheckBoxes:
if checkBox not in eventData:
Expand All @@ -445,7 +485,7 @@ def preprocessEventData(eventData):
elif not isinstance(eventData[eventDate], date):
eventData[eventDate] = ''

# If we aren't recurring, all of our events are single-day
# If we aren't recurring, all of our events are single-day or mutliple offerings, which also have the same start and end date
if not eventData['isRecurring']:
eventData['endDate'] = eventData['startDate']

Expand Down Expand Up @@ -595,4 +635,4 @@ def copyRsvpToNewEvent(priorEvent, newEvent):
newRsvp.save()
numRsvps = len(rsvpInfo)
if numRsvps:
createRsvpLog(newEvent, f"Copied {numRsvps} Rsvps from {priorEvent['name']} to {newEvent.name}")
createRsvpLog(newEvent, f"Copied {numRsvps} Rsvps from {priorEvent['name']} to {newEvent.name}")
7 changes: 6 additions & 1 deletion app/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Event(baseModel):
startDate = DateField()
endDate = DateField(null=True)
recurringId = IntegerField(null=True)
multipleOfferingId = IntegerField(null=True)
contactEmail = CharField(null=True)
contactName = CharField(null=True)
program = ForeignKeyField(Program)
Expand Down Expand Up @@ -50,6 +51,10 @@ def isFirstRecurringEvent(self):
firstRecurringEvent = Event.select().where(Event.recurringId==self.recurringId).order_by(Event.id).get()
return firstRecurringEvent.id == self.id

@property
def isMultipleOffering(self):
return bool(self.multipleOfferingId)

@property
def relativeTime(self):
relativeTime = datetime.combine(self.startDate, self.timeStart) - datetime.now()
Expand All @@ -69,4 +74,4 @@ def relativeTime(self):
else:
return f"happening now"



43 changes: 43 additions & 0 deletions app/static/css/createEvent.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.addMultipleBtn{
border-radius: 5px;
margin-left: auto;
margin-right: auto;
}

.deleteRow{
border-radius: 5px;
position:relative;
top: 12px;
}
.invalidFeedback {
display: none;
color: #dc3545;
font-size: 0.875rem;
border: 1px solid darkred;
padding: 0.75rem 1.25rem;
margin-bottom: 10px;
border-radius: 0.25rem;
background-color: #f8d7da;
margin-top: 25px;
left: 50%; /* Position the header at 50% of the viewport width */
transform: translateX(-50%);
text-align: center;
position: fixed;
z-index: 10;
animation: flash 6s forwards;
}

@keyframes flash {
0%, 89.9% {
opacity: 1;
}
90%, 100% {
opacity: 0;
}
}
.border-red {
border: 2px solid red;
}
.divStripes {
background-color: #fff
}
Loading