-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Events: Added "add to calendar" actions to each event item (#318)
* set up logs to test new description parser * Resolved bug in #309 * Started making progress on fix/281 * Added sliding effect and clipboard interaction * Move copy to clipboard button to right side * Update clipboard.svelte * Renamed icon to CopyLinkIcon * Made toast animation one dimensional * Added "event event summary" action * Added highlight effects to toasts per path * Fixed lint error, unused import * Added "event event summary" action * Update event-item.svelte * Added path metadata to toast notification * Removed unused import * Added copy google calendar button to action bar * Update event-item.svelte * Added Google, Office 365, Outlook, and Yahoo! calendar links * Ran formatter * Ran `npm audit fix` * Forked [`calendar-link`](https://github.com/AnandChowdhary/calendar-link#readme) * Update calendar-link.ts * Update calendar-link.ts * Uninstalled unused dependency calendar-link * Removed bloaty action buttons * moved calendar-link internal lib to lib root * updated lint errors from removing action buttons * Created separate summary and title properties in AcmEvent interface
- Loading branch information
1 parent
8a7f1a4
commit 6e751ac
Showing
14 changed files
with
632 additions
and
149 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# `calendar-link` | ||
|
||
## Credit | ||
|
||
- Demo: <https://anandchowdhary.github.io/calendar-link/> | ||
- Repository: <https://github.com/AnandChowdhary/calendar-link> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import dayjs from 'dayjs'; | ||
import utc from 'dayjs/plugin/utc.js'; | ||
import { stringify } from 'query-string'; | ||
|
||
import type { CalendarEvent, NormalizedCalendarEvent, Google, Outlook, Yahoo } from './interfaces'; | ||
import { TimeFormats } from './utils'; | ||
|
||
dayjs.extend(utc); | ||
|
||
function formatTimes( | ||
{ startUtc, endUtc }: NormalizedCalendarEvent, | ||
dateTimeFormat: keyof typeof TimeFormats | ||
): { start: string; end: string } { | ||
const format = TimeFormats[dateTimeFormat]; | ||
return { start: startUtc.format(format), end: endUtc.format(format) }; | ||
} | ||
|
||
export function eventify(event: CalendarEvent): NormalizedCalendarEvent { | ||
const { start, end, duration, ...rest } = event; | ||
const startUtc = dayjs(start).utc(); | ||
const endUtc = end | ||
? dayjs(end).utc() | ||
: (() => { | ||
if (event.allDay) { | ||
return startUtc.add(1, 'day'); | ||
} | ||
if (duration && duration.length == 2) { | ||
const value = Number(duration[0]); | ||
const unit = duration[1]; | ||
return startUtc.add(value, unit); | ||
} | ||
return dayjs().utc(); | ||
})(); | ||
return { | ||
...rest, | ||
startUtc, | ||
endUtc, | ||
}; | ||
} | ||
|
||
export function google(calendarEvent: CalendarEvent): string { | ||
const event = eventify(calendarEvent); | ||
const { start, end } = formatTimes(event, event.allDay ? 'allDay' : 'dateTimeUTC'); | ||
const details: Google = { | ||
action: 'TEMPLATE', | ||
text: event.title, | ||
details: event.description, | ||
location: event.location, | ||
trp: event.busy, | ||
dates: start + '/' + end, | ||
}; | ||
if (event.guests && event.guests.length) { | ||
details.add = event.guests.join(); | ||
} | ||
return `https://calendar.google.com/calendar/render?${stringify(details)}`; | ||
} | ||
|
||
export function outlook(calendarEvent: CalendarEvent): string { | ||
const event = eventify(calendarEvent); | ||
const { start, end } = formatTimes(event, 'dateTimeWithOffset'); | ||
const details: Outlook = { | ||
path: '/calendar/action/compose', | ||
rru: 'addevent', | ||
startdt: start, | ||
enddt: end, | ||
subject: event.title, | ||
body: event.description, | ||
location: event.location, | ||
allday: event.allDay || false, | ||
}; | ||
return `https://outlook.live.com/calendar/0/deeplink/compose?${stringify(details)}`; | ||
} | ||
|
||
export function office365(calendarEvent: CalendarEvent): string { | ||
const event = eventify(calendarEvent); | ||
const { start, end } = formatTimes(event, 'dateTimeWithOffset'); | ||
const details: Outlook = { | ||
path: '/calendar/action/compose', | ||
rru: 'addevent', | ||
startdt: start, | ||
enddt: end, | ||
subject: event.title, | ||
body: event.description, | ||
location: event.location, | ||
allday: event.allDay || false, | ||
}; | ||
return `https://outlook.office.com/calendar/0/deeplink/compose?${stringify(details)}`; | ||
} | ||
|
||
export function yahoo(calendarEvent: CalendarEvent): string { | ||
const event = eventify(calendarEvent); | ||
const { start, end } = formatTimes(event, event.allDay ? 'allDay' : 'dateTimeUTC'); | ||
const details: Yahoo = { | ||
v: 60, | ||
title: event.title, | ||
st: start, | ||
et: end, | ||
desc: event.description, | ||
in_loc: event.location, | ||
dur: event.allDay ? 'allday' : false, | ||
}; | ||
return `https://calendar.yahoo.com/?${stringify(details)}`; | ||
} | ||
|
||
export function ics(calendarEvent: CalendarEvent): string { | ||
const event = eventify(calendarEvent); | ||
const formattedDescription: string = (event.description || '') | ||
.replace(/,/gm, ',') | ||
.replace(/;/gm, ';') | ||
.replace(/\n/gm, '\\n') | ||
.replace(/(\\n)[\s\t]+/gm, '\\n'); | ||
|
||
const formattedLocation: string = (event.location || '') | ||
.replace(/,/gm, ',') | ||
.replace(/;/gm, ';') | ||
.replace(/\n/gm, '\\n') | ||
.replace(/(\\n)[\s\t]+/gm, '\\n'); | ||
|
||
const { start, end } = formatTimes(event, event.allDay ? 'allDay' : 'dateTimeUTC'); | ||
const calendarChunks = [ | ||
{ | ||
key: 'BEGIN', | ||
value: 'VCALENDAR', | ||
}, | ||
{ | ||
key: 'VERSION', | ||
value: '2.0', | ||
}, | ||
{ | ||
key: 'BEGIN', | ||
value: 'VEVENT', | ||
}, | ||
{ | ||
key: 'URL', | ||
value: event.url, | ||
}, | ||
{ | ||
key: 'DTSTART', | ||
value: start, | ||
}, | ||
{ | ||
key: 'DTEND', | ||
value: end, | ||
}, | ||
{ | ||
key: 'SUMMARY', | ||
value: event.title, | ||
}, | ||
{ | ||
key: 'DESCRIPTION', | ||
value: formattedDescription, | ||
}, | ||
{ | ||
key: 'LOCATION', | ||
value: formattedLocation, | ||
}, | ||
{ | ||
key: 'END', | ||
value: 'VEVENT', | ||
}, | ||
{ | ||
key: 'END', | ||
value: 'VCALENDAR', | ||
}, | ||
]; | ||
|
||
let calendarUrl = ''; | ||
|
||
calendarChunks.forEach((chunk) => { | ||
if (chunk.value) { | ||
calendarUrl += `${chunk.key}:${encodeURIComponent(`${chunk.value}\n`)}`; | ||
} | ||
}); | ||
|
||
return `data:text/calendar;charset=utf8,${calendarUrl}`; | ||
} | ||
|
||
export type { CalendarEvent }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './calendar-link'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import type dayjs from 'dayjs'; | ||
|
||
interface CalendarEvent { | ||
title: string; | ||
start: Date; | ||
end?: Date; | ||
duration?: [number, dayjs.UnitType]; | ||
allDay?: boolean; | ||
description?: string; | ||
location?: string; | ||
busy?: boolean; | ||
guests?: string[]; | ||
url?: string; | ||
} | ||
|
||
interface NormalizedCalendarEvent extends Omit<CalendarEvent, 'start' | 'end' | 'duration'> { | ||
startUtc: dayjs.Dayjs; | ||
endUtc: dayjs.Dayjs; | ||
} | ||
|
||
interface Google extends Record<string, string | boolean | number | undefined> { | ||
action: string; | ||
text: string; | ||
dates: string; | ||
details?: string; | ||
location?: string; | ||
trp?: boolean; | ||
sprop?: string; | ||
add?: string; | ||
src?: string; | ||
recur?: string; | ||
} | ||
|
||
interface Outlook extends Record<string, string | boolean | number | undefined> { | ||
path: string; | ||
rru: string; | ||
startdt: string; | ||
enddt: string; | ||
subject: string; | ||
allday?: boolean; | ||
body?: string; | ||
location?: string; | ||
} | ||
|
||
interface Yahoo extends Record<string, string | boolean | number | undefined> { | ||
v: number; | ||
title: string; | ||
st: string; | ||
et: string; | ||
desc?: string; | ||
in_loc?: string; | ||
} | ||
|
||
export type { CalendarEvent, NormalizedCalendarEvent, Outlook, Yahoo, Google }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const TimeFormats = { | ||
dateTimeWithOffset: 'YYYY-MM-DD[T]HH:mm:ssZ', | ||
dateTimeUTC: 'YYYYMMDD[T]HHmmss[Z]', | ||
allDay: 'YYYYMMDD', | ||
}; |
Oops, something went wrong.
6e751ac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs: