{{evt.details}}
+ @@ -205,4 +225,26 @@ export default { margin-top: 1em; padding-top: 1em; } +.c-detail-links { + display: flex; + justify-content: center; + flex-direction: column; + flex-flow: row wrap; + list-style-type: none; + gap: 5px; + /* on safari empty tags collapse, on chrome they take up space. + this helps keep things consistent */ + margin: 1em 0; + padding-inline-start: 0px; + + /* copied from main.css eventlink */ + li { + border-right: 1px solid var(--page-text); + padding-right: 5px; + &:last-child { + border-right: none; + } + } +} + \ No newline at end of file diff --git a/cal/src/calHelpers.js b/cal/src/calHelpers.js index 222fb8e6..6abadde9 100644 --- a/cal/src/calHelpers.js +++ b/cal/src/calHelpers.js @@ -54,6 +54,36 @@ export default { return friendlyTime(time) + suffix; }, + // duplicated from calendars helpers + getAddToGoogleLink(event) { + const googleCalUrl = new URL('https://www.google.com/calendar/render'); + + const startDate = dayjs(`${event.date} ${event.time}`).toISOString(); + const duration = event.duration ?? 60; // Google requires a duration and defaults to 60 minutes anyway + const endDate = dayjs(startDate).add(dayjs.duration({ 'minute': duration })).toISOString(); + /** + * Matches anything that is not a word or whitespace + * @example + * "2025-05-21T16:30:00.000Z".replace(regex, '') // 20250521T163000000Z + */ + const regex = /[^\w\s]/gi; + + // Remove colons and periods for Google Calendar URL (2025-05-21T16:30:00.000Z => 20250521T163000000Z) + const calendarDates = `${startDate.replace(regex, '')}/${endDate.replace(regex, '')}`; + + googleCalUrl.search = new URLSearchParams({ + action: "TEMPLATE", + text: `shift2Bikes: ${event.title}`, + location: event.address, + details: `${event.details}\n\n${event.shareable}`, + dates: calendarDates, + sf: true, // ?? + output: 'xml' + }); + + return googleCalUrl.toString(); + }, + // https://jasonwatmore.com/vanilla-js-slugify-a-string-in-javascript // might want the server to do this; but fine for now. slugify(evt) { diff --git a/cal/src/eventDetails.js b/cal/src/eventDetails.js index 04018ca8..4b10a19e 100644 --- a/cal/src/eventDetails.js +++ b/cal/src/eventDetails.js @@ -50,7 +50,6 @@ function buildShortcuts(evt, fullPath) { }; }, addevent: "/addevent/", - export: `/api/ics.php?id=${evt.id}`, // hide share till its ready // see also the ShortcutButton // this might depend on platform or sussing out capabilities. diff --git a/cal/src/siteConfig.js b/cal/src/siteConfig.js index 9ab9300a..fc18acc9 100644 --- a/cal/src/siteConfig.js +++ b/cal/src/siteConfig.js @@ -7,9 +7,11 @@ import siteInfo from 'extras/siteInfo.json' import dayjs from 'dayjs' import advancedFormat from 'dayjs/plugin/advancedFormat' import customParseFormat from 'dayjs/plugin/customParseFormat' +import duration from 'dayjs/plugin/duration' dayjs.extend(advancedFormat); dayjs.extend(customParseFormat); +dayjs.extend(duration); // the calendar part of the menu has links to the pages we are already on // so those are unneeded. diff --git a/cal/src/support/dataPool.js b/cal/src/support/dataPool.js index 6013d2bf..de0e345c 100644 --- a/cal/src/support/dataPool.js +++ b/cal/src/support/dataPool.js @@ -9,6 +9,7 @@ const API_BASE_URL = window.location.origin; // const API_BASE_URL = "https://api.shift2bikes.org"; const API_EVENTS_URL = new URL(`/api/events.php`, API_BASE_URL); const API_SEARCH_URL = new URL(`/api/search.php`, API_BASE_URL); +const API_ICS_URL = new URL('/api/ics.php', API_BASE_URL); // cache the most recent range. // useful for front-end development where browser caching is disable. @@ -73,7 +74,13 @@ export default { const data = await resp.json(); // data => { events: [], pagination: {} } mungeEvents(data.events); return data; - } + }, + // fix: this isn't nice as a method of data pool + // make an endpoints file of some sort that dataPool uses. + // ( and then have callers of this use that file directly ) + getExportURL(id) { + return buildUrl(API_ICS_URL, {id}); + }, } // change dates into dayjs; and sort.