From 9d3da3563ce13d54673cfa3468911caeb4836741 Mon Sep 17 00:00:00 2001 From: lowercasename Date: Sat, 14 Sep 2019 10:08:09 +0100 Subject: Functionality to limit number of attendees --- app.js | 24 ++++++++++++++++-- models/Event.js | 3 +++ public/css/style.css | 17 +++++++++++++ routes.js | 14 ++++++++++- views/event.handlebars | 37 +++++++++++++++++++++++++-- views/partials/editeventmodal.handlebars | 32 ++++++++++++++++-------- views/partials/neweventform.handlebars | 43 ++++++++++++++++++++++++++++---- 7 files changed, 150 insertions(+), 20 deletions(-) diff --git a/app.js b/app.js index 9a82abe..a8d2889 100755 --- a/app.js +++ b/app.js @@ -16,8 +16,28 @@ const app = express(); // View engine // - -app.engine('handlebars', hbs({defaultLayout: 'main'})); +hbsInstance = hbs.create({ + defaultLayout: 'main', + partialsDir: ['views/partials/'], + helpers: { + plural: function(number, text) { + var singular = number === 1; + // If no text parameter was given, just return a conditional s. + if (typeof text !== 'string') return singular ? '' : 's'; + // Split with regex into group1/group2 or group1(group3) + var match = text.match(/^([^()\/]+)(?:\/(.+))?(?:\((\w+)\))?/); + // If no match, just append a conditional s. + if (!match) return text + (singular ? '' : 's'); + // We have a good match, so fire away + return singular && match[1] // Singular case + || + match[2] // Plural case: 'bagel/bagels' --> bagels + || + match[1] + (match[3] || 's'); // Plural case: 'bagel(s)' or 'bagel' --> bagels + } + } +}); +app.engine('handlebars', hbsInstance.engine); app.set('view engine', 'handlebars'); // Static files // diff --git a/models/Event.js b/models/Event.js index 90c8117..43af171 100755 --- a/models/Event.js +++ b/models/Event.js @@ -155,6 +155,9 @@ const EventSchema = new mongoose.Schema({ default: true }, attendees: [Attendees], + maxAttendees: { + type: Number + }, comments: [CommentSchema] }); diff --git a/public/css/style.css b/public/css/style.css index 43d9997..122c6ad 100755 --- a/public/css/style.css +++ b/public/css/style.css @@ -292,6 +292,23 @@ body, html { margin-top: 0.5rem; } +#maxAttendeesContainer { + display: none; +} +#maxAttendeesCheckboxContainer { + display: none; +} + +.edit-buttons { + text-align: right; +} + +@media (max-width: 1199.98px) { + .edit-buttons { + text-align: left; + } +} + @media (min-width: 577px) { #sidebar { border-right: 2px solid #e0e0e0; diff --git a/routes.js b/routes.js index fde1b86..4e665ba 100755 --- a/routes.js +++ b/routes.js @@ -244,6 +244,13 @@ router.get('/:eventID', (req, res) => { } } let eventAttendees = event.attendees.sort((a,b) => (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0)); + let spotsRemaining, noMoreSpots; + if (event.maxAttendees) { + spotsRemaining = event.maxAttendees - eventAttendees.length; + if (spotsRemaining <= 0) { + noMoreSpots = true; + } + } let metadata = { title: event.name, description: marked(event.description, { renderer: render_plain()}).split(" ").splice(0,40).join(" ").trim(), @@ -256,6 +263,8 @@ router.get('/:eventID', (req, res) => { escapedName: escapedName, eventData: event, eventAttendees: eventAttendees, + spotsRemaining: spotsRemaining, + noMoreSpots: noMoreSpots, eventStartISO: eventStartISO, eventEndISO: eventEndISO, parsedLocation: parsedLocation, @@ -334,6 +343,7 @@ router.post('/newevent', (req, res) => { usersCanAttend: req.body.joinCheckbox ? true : false, showUsersList: req.body.guestlistCheckbox ? true : false, usersCanComment: req.body.interactionCheckbox ? true : false, + maxAttendees: req.body.maxAttendees, firstLoad: true }); event.save() @@ -470,7 +480,9 @@ router.post('/editevent/:eventID/:editToken', (req, res) => { image: eventImageFilename, usersCanAttend: req.body.joinCheckbox ? true : false, showUsersList: req.body.guestlistCheckbox ? true : false, - usersCanComment: req.body.interactionCheckbox ? true : false + usersCanComment: req.body.interactionCheckbox ? true : false, + maxAttendees: req.body.maxAttendeesCheckbox ? req.body.maxAttendees : null, + } Event.findOneAndUpdate({id: req.params.eventID}, updatedEvent, function(err, raw) { if (err) { diff --git a/views/event.handlebars b/views/event.handlebars index fdbc7cf..a4d714d 100755 --- a/views/event.handlebars +++ b/views/event.handlebars @@ -8,7 +8,7 @@

{{eventData.name}}

{{#if editingEnabled}} -
+
@@ -102,11 +102,20 @@
Attendees {{#if eventAttendees}}({{eventAttendees.length}}){{/if}}
- + {{#unless noMoreSpots}} + + {{/unless}}
+ {{#if eventData.maxAttendees}} + {{#if noMoreSpots}} +
This event is at capacity.
+ {{else}} +
{{spotsRemaining}} {{plural spotsRemaining "spot(s)"}} remaining - add yourself now!
+ {{/if}} + {{/if}} {{#if eventAttendees}}
    {{#each eventAttendees}} @@ -384,6 +393,30 @@ setTimeout(function(){ $("#copyEventLink").html(' Copy');}, 5000); }) $(".daysToDeletion").html(moment("{{eventEndISO}}").add(7, 'days').fromNow()); + if ($("#joinCheckbox").is(':checked')){ + $("#maxAttendeesCheckboxContainer").css("display","flex"); + } + $("#maxAttendeesCheckbox").on("click", function() { + if ($(this).is(':checked')) { + $("#maxAttendeesContainer").slideDown('fast').css("display","flex"); + $("#maxAttendees").attr("data-validation-optional","false"); + } + else { + $("#maxAttendeesContainer").slideUp('fast'); + $("#maxAttendees").attr("data-validation-optional","true").val("").removeClass('is-valid is-invalid'); + } + }); + $("#joinCheckbox").on("click", function() { + if ($(this).is(':checked')) { + $("#maxAttendeesCheckboxContainer").slideDown('fast').css("display","flex"); + } + else { + $("#maxAttendeesCheckboxContainer").slideUp('fast'); + $("#maxAttendeesCheckbox").prop("checked",false); + $("#maxAttendeesContainer").slideUp('fast'); + $("#maxAttendees").attr("data-validation-optional","true").val("").removeClass('is-valid is-invalid'); + } + }); }); diff --git a/views/partials/editeventmodal.handlebars b/views/partials/editeventmodal.handlebars index ceb172b..68c8f80 100644 --- a/views/partials/editeventmodal.handlebars +++ b/views/partials/editeventmodal.handlebars @@ -7,7 +7,7 @@
-
+
- +
@@ -71,20 +71,32 @@
Options
+
+ + +
- +
-
- - -
+
+ + +
+
+ +
+ +
+
-
\ No newline at end of file +
diff --git a/views/partials/neweventform.handlebars b/views/partials/neweventform.handlebars index bf6d0ed..51d1695 100755 --- a/views/partials/neweventform.handlebars +++ b/views/partials/neweventform.handlebars @@ -25,7 +25,7 @@
- +
@@ -80,20 +80,32 @@
Options
+
+ + +
-
- -
+
+ +
+ +
+
@@ -114,5 +126,26 @@ no_label: false }); autosize($('textarea')); + $("#maxAttendeesCheckbox").on("click", function() { + if ($(this).is(':checked')) { + $("#maxAttendeesContainer").slideDown('fast').css("display","flex"); + $("#maxAttendees").attr("data-validation-optional","false"); + } + else { + $("#maxAttendeesContainer").slideUp('fast'); + $("#maxAttendees").attr("data-validation-optional","true").val("").removeClass('is-valid is-invalid'); + } + }); + $("#joinCheckbox").on("click", function() { + if ($(this).is(':checked')) { + $("#maxAttendeesCheckboxContainer").slideDown('fast').css("display","flex"); + } + else { + $("#maxAttendeesCheckboxContainer").slideUp('fast'); + $("#maxAttendeesCheckbox").prop("checked",false); + $("#maxAttendeesContainer").slideUp('fast'); + $("#maxAttendees").attr("data-validation-optional","true").val("").removeClass('is-valid is-invalid'); + } + }); }); -- cgit v1.2.3