diff options
-rwxr-xr-x | package-lock.json | 18 | ||||
-rwxr-xr-x | package.json | 1 | ||||
-rwxr-xr-x | routes.js | 43 | ||||
-rwxr-xr-x | views/event.handlebars | 32 |
4 files changed, 93 insertions, 1 deletions
diff --git a/package-lock.json b/package-lock.json index 2e1d899..91e1ef5 100755 --- a/package-lock.json +++ b/package-lock.json @@ -2810,6 +2810,24 @@ "rrule": "2.4.1" } }, + "ical-generator": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/ical-generator/-/ical-generator-1.9.2.tgz", + "integrity": "sha512-z3OLKk/b9TbyOLKOIMpjLJ3u7gq/tXPNsH5uOz+Ai3sqn2kcpjFlZUafKrlduwZn3Xu3fV5WqZ2dddZFrhQTfg==", + "requires": { + "moment-timezone": "^0.5.27" + }, + "dependencies": { + "moment-timezone": { + "version": "0.5.27", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz", + "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==", + "requires": { + "moment": ">= 2.9.0" + } + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", diff --git a/package.json b/package.json index fff1c2d..04f8a15 100755 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "greenlock": "^2.6.7", "greenlock-express": "^2.6.7", "ical": "^0.6.0", + "ical-generator": "^1.9.2", "jimp": "^0.6.0", "jsonwebtoken": "^8.4.0", "marked": "^0.7.0", @@ -62,6 +62,11 @@ render_plain = function () { } const ical = require('ical'); +const icalGenerator = require('ical-generator'); +const cal = icalGenerator({ + domain: 'gath.io', + name: 'Gathio' +}); const sgMail = require('@sendgrid/mail'); @@ -408,6 +413,42 @@ router.get('/group/:eventGroupID', (req, res) => { }); }) +router.get('/exportevent/:eventID', (req, res) => { + Event.findOne({ + id: req.params.eventID + }) + .populate('eventGroup') + .then((event) => { + if (event) { + const icalEvent = cal.createEvent({ + start: moment.tz(event.start, event.timezone), + end: moment.tz(event.start, event.timezone), + timezone: event.timezone, + timestamp: moment(), + summary: event.name, + description: event.description, + organizer: { + name: event.hostName ? event.hostName : "Anonymous", + email: event.creatorEmail + }, + location: event.location, + url: 'https://gath.io/' + event.id + }); + + let string = cal.toString(); + console.log(string) + res.send(string); + } + }) + .catch((err) => { + addToLog("exportEvent", "error", "Attempt to export event " + req.params.eventID + " failed with error: " + err); + console.log(err) + res.status(404); + res.render('404', { url: req.url }); + return; + }); +}) + // BACKEND ROUTES //router.post('/login', @@ -529,7 +570,7 @@ router.post('/importevent', (req, res) => { image: '', creatorEmail: creatorEmail, url: '', - hostName: importedEventData.organizer ? importedEventData.organizer.params.CN : "", + hostName: importedEventData.organizer ? importedEventData.organizer.params.CN.replace(/["]+/g, '') : "", viewPassword: '', editPassword: '', editToken: editToken, diff --git a/views/event.handlebars b/views/event.handlebars index 4d0cf28..70c4018 100755 --- a/views/event.handlebars +++ b/views/event.handlebars @@ -45,6 +45,9 @@ <a href="http://www.google.com/calendar/event?action=TEMPLATE&dates={{parsedStart}}%2F{{parsedEnd}}&text={{escapedName}}&location={{parsedLocation}}&ctz={{timezone}}" class="eventInformationAction btn btn-outline-secondary btn-sm"> <i class="far fa-calendar-plus"></i> Add to Google Calendar </a> + <button type="button" id="exportICS" class="eventInformationAction btn btn-outline-secondary btn-sm" data-event-id="{{eventData.id}}"> + <i class="fas fa-download"></i> Export as ICS + </button> </li> {{#if eventHasHost}} <li> @@ -375,6 +378,29 @@ }) $(document).ready(function() { + // From https://davidwalsh.name/javascript-download + function downloadFile(data, fileName, type="text/plain") { + // Create an invisible A element + const a = document.createElement("a"); + a.style.display = "none"; + document.body.appendChild(a); + + // Set the HREF to a Blob representation of the data to be downloaded + a.href = window.URL.createObjectURL( + new Blob([data], { type }) + ); + + // Use download attribute to set set desired file name + a.setAttribute("download", fileName); + + // Trigger the download by simulating click + a.click(); + + // Cleanup + window.URL.revokeObjectURL(a.href); + document.body.removeChild(a); + } + $.uploadPreview({ input_field: "#image-upload", preview_box: "#image-preview", @@ -394,6 +420,12 @@ {{/if}} new ClipboardJS('#copyEventLink'); autosize($('textarea')); + $("#exportICS").click(function(){ + let eventID = $(this).attr('data-event-id'); + $.get('/exportevent/' + eventID, function(response) { + downloadFile(response, eventID + '.ics'); + }) + }) $("#copyEventLink").click(function(){ $(this).html('<i class="fas fa-copy"></i> Copied!'); setTimeout(function(){ $("#copyEventLink").html('<i class="fas fa-copy"></i> Copy');}, 5000); |