diff options
Diffstat (limited to 'public/js/fullcalendar/packages/icalendar/index.global.js')
-rw-r--r-- | public/js/fullcalendar/packages/icalendar/index.global.js | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/public/js/fullcalendar/packages/icalendar/index.global.js b/public/js/fullcalendar/packages/icalendar/index.global.js new file mode 100644 index 0000000..1c965f6 --- /dev/null +++ b/public/js/fullcalendar/packages/icalendar/index.global.js | |||
@@ -0,0 +1,225 @@ | |||
1 | /*! | ||
2 | FullCalendar iCalendar Plugin v6.1.17 | ||
3 | Docs & License: https://fullcalendar.io/docs/icalendar | ||
4 | (c) 2024 Adam Shaw | ||
5 | */ | ||
6 | FullCalendar.ICalendar = (function (exports, core, internal, ICAL) { | ||
7 | 'use strict'; | ||
8 | |||
9 | function _interopNamespace(e) { | ||
10 | if (e && e.__esModule) return e; | ||
11 | var n = Object.create(null); | ||
12 | if (e) { | ||
13 | Object.keys(e).forEach(function (k) { | ||
14 | if (k !== 'default') { | ||
15 | var d = Object.getOwnPropertyDescriptor(e, k); | ||
16 | Object.defineProperty(n, k, d.get ? d : { | ||
17 | enumerable: true, | ||
18 | get: function () { return e[k]; } | ||
19 | }); | ||
20 | } | ||
21 | }); | ||
22 | } | ||
23 | n["default"] = e; | ||
24 | return n; | ||
25 | } | ||
26 | |||
27 | var ICAL__namespace = /*#__PURE__*/_interopNamespace(ICAL); | ||
28 | |||
29 | /* eslint-disable */ | ||
30 | class IcalExpander { | ||
31 | constructor(opts) { | ||
32 | this.maxIterations = opts.maxIterations != null ? opts.maxIterations : 1000; | ||
33 | this.skipInvalidDates = opts.skipInvalidDates != null ? opts.skipInvalidDates : false; | ||
34 | this.jCalData = ICAL__namespace.parse(opts.ics); | ||
35 | this.component = new ICAL__namespace.Component(this.jCalData); | ||
36 | this.events = this.component.getAllSubcomponents('vevent').map(vevent => new ICAL__namespace.Event(vevent)); | ||
37 | if (this.skipInvalidDates) { | ||
38 | this.events = this.events.filter((evt) => { | ||
39 | try { | ||
40 | evt.startDate.toJSDate(); | ||
41 | evt.endDate.toJSDate(); | ||
42 | return true; | ||
43 | } | ||
44 | catch (err) { | ||
45 | // skipping events with invalid time | ||
46 | return false; | ||
47 | } | ||
48 | }); | ||
49 | } | ||
50 | } | ||
51 | between(after, before) { | ||
52 | function isEventWithinRange(startTime, endTime) { | ||
53 | return (!after || endTime >= after.getTime()) && | ||
54 | (!before || startTime <= before.getTime()); | ||
55 | } | ||
56 | function getTimes(eventOrOccurrence) { | ||
57 | const startTime = eventOrOccurrence.startDate.toJSDate().getTime(); | ||
58 | let endTime = eventOrOccurrence.endDate.toJSDate().getTime(); | ||
59 | // If it is an all day event, the end date is set to 00:00 of the next day | ||
60 | // So we need to make it be 23:59:59 to compare correctly with the given range | ||
61 | if (eventOrOccurrence.endDate.isDate && (endTime > startTime)) { | ||
62 | endTime -= 1; | ||
63 | } | ||
64 | return { startTime, endTime }; | ||
65 | } | ||
66 | const exceptions = []; | ||
67 | this.events.forEach((event) => { | ||
68 | if (event.isRecurrenceException()) | ||
69 | exceptions.push(event); | ||
70 | }); | ||
71 | const ret = { | ||
72 | events: [], | ||
73 | occurrences: [], | ||
74 | }; | ||
75 | this.events.filter(e => !e.isRecurrenceException()).forEach((event) => { | ||
76 | const exdates = []; | ||
77 | event.component.getAllProperties('exdate').forEach((exdateProp) => { | ||
78 | const exdate = exdateProp.getFirstValue(); | ||
79 | exdates.push(exdate.toJSDate().getTime()); | ||
80 | }); | ||
81 | // Recurring event is handled differently | ||
82 | if (event.isRecurring()) { | ||
83 | const iterator = event.iterator(); | ||
84 | let next; | ||
85 | let i = 0; | ||
86 | do { | ||
87 | i += 1; | ||
88 | next = iterator.next(); | ||
89 | if (next) { | ||
90 | const occurrence = event.getOccurrenceDetails(next); | ||
91 | const { startTime, endTime } = getTimes(occurrence); | ||
92 | const isOccurrenceExcluded = exdates.indexOf(startTime) !== -1; | ||
93 | // TODO check that within same day? | ||
94 | const exception = exceptions.find(ex => ex.uid === event.uid && ex.recurrenceId.toJSDate().getTime() === occurrence.startDate.toJSDate().getTime()); | ||
95 | // We have passed the max date, stop | ||
96 | if (before && startTime > before.getTime()) | ||
97 | break; | ||
98 | // Check that we are within our range | ||
99 | if (isEventWithinRange(startTime, endTime)) { | ||
100 | if (exception) { | ||
101 | ret.events.push(exception); | ||
102 | } | ||
103 | else if (!isOccurrenceExcluded) { | ||
104 | ret.occurrences.push(occurrence); | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | } while (next && (!this.maxIterations || i < this.maxIterations)); | ||
109 | return; | ||
110 | } | ||
111 | // Non-recurring event: | ||
112 | const { startTime, endTime } = getTimes(event); | ||
113 | if (isEventWithinRange(startTime, endTime)) | ||
114 | ret.events.push(event); | ||
115 | }); | ||
116 | return ret; | ||
117 | } | ||
118 | before(before) { | ||
119 | return this.between(undefined, before); | ||
120 | } | ||
121 | after(after) { | ||
122 | return this.between(after); | ||
123 | } | ||
124 | all() { | ||
125 | return this.between(); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | const eventSourceDef = { | ||
130 | parseMeta(refined) { | ||
131 | if (refined.url && refined.format === 'ics') { | ||
132 | return { | ||
133 | url: refined.url, | ||
134 | format: 'ics', | ||
135 | }; | ||
136 | } | ||
137 | return null; | ||
138 | }, | ||
139 | fetch(arg, successCallback, errorCallback) { | ||
140 | let meta = arg.eventSource.meta; | ||
141 | let { internalState } = meta; | ||
142 | /* | ||
143 | NOTE: isRefetch is a HACK. we would do the recurring-expanding in a separate plugin hook, | ||
144 | but we couldn't leverage built-in allDay-guessing, among other things. | ||
145 | */ | ||
146 | if (!internalState || arg.isRefetch) { | ||
147 | internalState = meta.internalState = { | ||
148 | response: null, | ||
149 | iCalExpanderPromise: fetch(meta.url, { method: 'GET' }).then((response) => { | ||
150 | return response.text().then((icsText) => { | ||
151 | internalState.response = response; | ||
152 | return new IcalExpander({ | ||
153 | ics: icsText, | ||
154 | skipInvalidDates: true, | ||
155 | }); | ||
156 | }); | ||
157 | }), | ||
158 | }; | ||
159 | } | ||
160 | internalState.iCalExpanderPromise.then((iCalExpander) => { | ||
161 | successCallback({ | ||
162 | rawEvents: expandICalEvents(iCalExpander, arg.range), | ||
163 | response: internalState.response, | ||
164 | }); | ||
165 | }, errorCallback); | ||
166 | }, | ||
167 | }; | ||
168 | function expandICalEvents(iCalExpander, range) { | ||
169 | // expand the range. because our `range` is timeZone-agnostic UTC | ||
170 | // or maybe because ical.js always produces dates in local time? i forget | ||
171 | let rangeStart = internal.addDays(range.start, -1); | ||
172 | let rangeEnd = internal.addDays(range.end, 1); | ||
173 | let iCalRes = iCalExpander.between(rangeStart, rangeEnd); // end inclusive. will give extra results | ||
174 | let expanded = []; | ||
175 | // TODO: instead of using startDate/endDate.toString to communicate allDay, | ||
176 | // we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing. | ||
177 | // single events | ||
178 | for (let iCalEvent of iCalRes.events) { | ||
179 | expanded.push(Object.assign(Object.assign({}, buildNonDateProps(iCalEvent)), { start: iCalEvent.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalEvent.endDate) | ||
180 | ? iCalEvent.endDate.toString() | ||
181 | : null })); | ||
182 | } | ||
183 | // recurring event instances | ||
184 | for (let iCalOccurence of iCalRes.occurrences) { | ||
185 | let iCalEvent = iCalOccurence.item; | ||
186 | expanded.push(Object.assign(Object.assign({}, buildNonDateProps(iCalEvent)), { start: iCalOccurence.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate) | ||
187 | ? iCalOccurence.endDate.toString() | ||
188 | : null })); | ||
189 | } | ||
190 | return expanded; | ||
191 | } | ||
192 | function buildNonDateProps(iCalEvent) { | ||
193 | return { | ||
194 | title: iCalEvent.summary, | ||
195 | url: extractEventUrl(iCalEvent), | ||
196 | extendedProps: { | ||
197 | location: iCalEvent.location, | ||
198 | organizer: iCalEvent.organizer, | ||
199 | description: iCalEvent.description, | ||
200 | }, | ||
201 | }; | ||
202 | } | ||
203 | function extractEventUrl(iCalEvent) { | ||
204 | let urlProp = iCalEvent.component.getFirstProperty('url'); | ||
205 | return urlProp ? urlProp.getFirstValue() : ''; | ||
206 | } | ||
207 | function specifiesEnd(iCalEvent) { | ||
208 | return Boolean(iCalEvent.component.getFirstProperty('dtend')) || | ||
209 | Boolean(iCalEvent.component.getFirstProperty('duration')); | ||
210 | } | ||
211 | |||
212 | var plugin = core.createPlugin({ | ||
213 | name: '@fullcalendar/icalendar', | ||
214 | eventSourceDefs: [eventSourceDef], | ||
215 | }); | ||
216 | |||
217 | core.globalPlugins.push(plugin); | ||
218 | |||
219 | exports["default"] = plugin; | ||
220 | |||
221 | Object.defineProperty(exports, '__esModule', { value: true }); | ||
222 | |||
223 | return exports; | ||
224 | |||
225 | })({}, FullCalendar, FullCalendar.Internal, ICAL); | ||