fullcalendar-google.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*!
  2. FullCalendar v5.11.3
  3. Docs & License: https://fullcalendar.io/
  4. (c) 2022 Adam Shaw
  5. */
  6. import { __assign } from 'tslib';
  7. import { identity, createPlugin, requestJson, addDays } from '@fullcalendar/common';
  8. // rename this file to options.ts like other packages?
  9. var OPTION_REFINERS = {
  10. googleCalendarApiKey: String,
  11. };
  12. var EVENT_SOURCE_REFINERS = {
  13. googleCalendarApiKey: String,
  14. googleCalendarId: String,
  15. googleCalendarApiBase: String,
  16. extraParams: identity,
  17. };
  18. // TODO: expose somehow
  19. var API_BASE = 'https://www.googleapis.com/calendar/v3/calendars';
  20. var eventSourceDef = {
  21. parseMeta: function (refined) {
  22. var googleCalendarId = refined.googleCalendarId;
  23. if (!googleCalendarId && refined.url) {
  24. googleCalendarId = parseGoogleCalendarId(refined.url);
  25. }
  26. if (googleCalendarId) {
  27. return {
  28. googleCalendarId: googleCalendarId,
  29. googleCalendarApiKey: refined.googleCalendarApiKey,
  30. googleCalendarApiBase: refined.googleCalendarApiBase,
  31. extraParams: refined.extraParams,
  32. };
  33. }
  34. return null;
  35. },
  36. fetch: function (arg, onSuccess, onFailure) {
  37. var _a = arg.context, dateEnv = _a.dateEnv, options = _a.options;
  38. var meta = arg.eventSource.meta;
  39. var apiKey = meta.googleCalendarApiKey || options.googleCalendarApiKey;
  40. if (!apiKey) {
  41. onFailure({
  42. message: 'Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/',
  43. });
  44. }
  45. else {
  46. var url = buildUrl(meta);
  47. // TODO: make DRY with json-feed-event-source
  48. var extraParams = meta.extraParams;
  49. var extraParamsObj = typeof extraParams === 'function' ? extraParams() : extraParams;
  50. var requestParams_1 = buildRequestParams(arg.range, apiKey, extraParamsObj, dateEnv);
  51. requestJson('GET', url, requestParams_1, function (body, xhr) {
  52. if (body.error) {
  53. onFailure({
  54. message: 'Google Calendar API: ' + body.error.message,
  55. errors: body.error.errors,
  56. xhr: xhr,
  57. });
  58. }
  59. else {
  60. onSuccess({
  61. rawEvents: gcalItemsToRawEventDefs(body.items, requestParams_1.timeZone),
  62. xhr: xhr,
  63. });
  64. }
  65. }, function (message, xhr) {
  66. onFailure({ message: message, xhr: xhr });
  67. });
  68. }
  69. },
  70. };
  71. function parseGoogleCalendarId(url) {
  72. var match;
  73. // detect if the ID was specified as a single string.
  74. // will match calendars like "asdf1234@calendar.google.com" in addition to person email calendars.
  75. if (/^[^/]+@([^/.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) {
  76. return url;
  77. }
  78. if ((match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^/]*)/.exec(url)) ||
  79. (match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^/]*)/.exec(url))) {
  80. return decodeURIComponent(match[1]);
  81. }
  82. return null;
  83. }
  84. function buildUrl(meta) {
  85. var apiBase = meta.googleCalendarApiBase;
  86. if (!apiBase) {
  87. apiBase = API_BASE;
  88. }
  89. return apiBase + '/' + encodeURIComponent(meta.googleCalendarId) + '/events';
  90. }
  91. function buildRequestParams(range, apiKey, extraParams, dateEnv) {
  92. var params;
  93. var startStr;
  94. var endStr;
  95. if (dateEnv.canComputeOffset) {
  96. // strings will naturally have offsets, which GCal needs
  97. startStr = dateEnv.formatIso(range.start);
  98. endStr = dateEnv.formatIso(range.end);
  99. }
  100. else {
  101. // when timezone isn't known, we don't know what the UTC offset should be, so ask for +/- 1 day
  102. // from the UTC day-start to guarantee we're getting all the events
  103. // (start/end will be UTC-coerced dates, so toISOString is okay)
  104. startStr = addDays(range.start, -1).toISOString();
  105. endStr = addDays(range.end, 1).toISOString();
  106. }
  107. params = __assign(__assign({}, (extraParams || {})), { key: apiKey, timeMin: startStr, timeMax: endStr, singleEvents: true, maxResults: 9999 });
  108. if (dateEnv.timeZone !== 'local') {
  109. params.timeZone = dateEnv.timeZone;
  110. }
  111. return params;
  112. }
  113. function gcalItemsToRawEventDefs(items, gcalTimezone) {
  114. return items.map(function (item) { return gcalItemToRawEventDef(item, gcalTimezone); });
  115. }
  116. function gcalItemToRawEventDef(item, gcalTimezone) {
  117. var url = item.htmlLink || null;
  118. // make the URLs for each event show times in the correct timezone
  119. if (url && gcalTimezone) {
  120. url = injectQsComponent(url, 'ctz=' + gcalTimezone);
  121. }
  122. return {
  123. id: item.id,
  124. title: item.summary,
  125. start: item.start.dateTime || item.start.date,
  126. end: item.end.dateTime || item.end.date,
  127. url: url,
  128. location: item.location,
  129. description: item.description,
  130. attachments: item.attachments || [],
  131. extendedProps: (item.extendedProperties || {}).shared || {},
  132. };
  133. }
  134. // Injects a string like "arg=value" into the querystring of a URL
  135. // TODO: move to a general util file?
  136. function injectQsComponent(url, component) {
  137. // inject it after the querystring but before the fragment
  138. return url.replace(/(\?.*?)?(#|$)/, function (whole, qs, hash) { return (qs ? qs + '&' : '?') + component + hash; });
  139. }
  140. var main = createPlugin({
  141. eventSourceDefs: [eventSourceDef],
  142. optionRefiners: OPTION_REFINERS,
  143. eventSourceRefiners: EVENT_SOURCE_REFINERS,
  144. });
  145. export default main;
  146. //# sourceMappingURL=main.js.map