/*! FullCalendar Resources Common Plugin v4.2.0 Docs & License: https://fullcalendar.io/scheduler (c) 2019 Adam Shaw */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : (global = global || self, factory(global.FullCalendarResourceCommon = {}, global.FullCalendar)); }(this, function (exports, core) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var ResourceDataAdder = /** @class */ (function () { function ResourceDataAdder() { this.filterResources = core.memoize(filterResources); } ResourceDataAdder.prototype.transform = function (viewProps, viewSpec, calendarProps, view) { if (viewSpec.class.needsResourceData) { return { resourceStore: this.filterResources(calendarProps.resourceStore, view.opt('filterResourcesWithEvents'), calendarProps.eventStore, calendarProps.dateProfile.activeRange), resourceEntityExpansions: calendarProps.resourceEntityExpansions }; } }; return ResourceDataAdder; }()); function filterResources(resourceStore, doFilterResourcesWithEvents, eventStore, activeRange) { if (doFilterResourcesWithEvents) { var instancesInRange = filterEventInstancesInRange(eventStore.instances, activeRange); var hasEvents_1 = computeHasEvents(instancesInRange, eventStore.defs); __assign(hasEvents_1, computeAncestorHasEvents(hasEvents_1, resourceStore)); return core.filterHash(resourceStore, function (resource, resourceId) { return hasEvents_1[resourceId]; }); } else { return resourceStore; } } function filterEventInstancesInRange(eventInstances, activeRange) { return core.filterHash(eventInstances, function (eventInstance) { return core.rangesIntersect(eventInstance.range, activeRange); }); } function computeHasEvents(eventInstances, eventDefs) { var hasEvents = {}; for (var instanceId in eventInstances) { var instance = eventInstances[instanceId]; for (var _i = 0, _a = eventDefs[instance.defId].resourceIds; _i < _a.length; _i++) { var resourceId = _a[_i]; hasEvents[resourceId] = true; } } return hasEvents; } /* mark resources as having events if any of their ancestors have them NOTE: resourceStore might not have all the resources that hasEvents{} has keyed */ function computeAncestorHasEvents(hasEvents, resourceStore) { var res = {}; for (var resourceId in hasEvents) { var resource = void 0; while ((resource = resourceStore[resourceId])) { resourceId = resource.parentId; // now functioning as the parentId if (resourceId) { res[resourceId] = true; } else { break; } } } return res; } // for when non-resource view should be given EventUi info (for event coloring/constraints based off of resource data) var ResourceEventConfigAdder = /** @class */ (function () { function ResourceEventConfigAdder() { this.buildResourceEventUis = core.memoizeOutput(buildResourceEventUis, core.isPropsEqual); this.injectResourceEventUis = core.memoize(injectResourceEventUis); } ResourceEventConfigAdder.prototype.transform = function (viewProps, viewSpec, calendarProps) { if (!viewSpec.class.needsResourceData) { // is a non-resource view? return { eventUiBases: this.injectResourceEventUis(viewProps.eventUiBases, viewProps.eventStore.defs, this.buildResourceEventUis(calendarProps.resourceStore)) }; } }; return ResourceEventConfigAdder; }()); function buildResourceEventUis(resourceStore) { return core.mapHash(resourceStore, function (resource) { return resource.ui; }); } function injectResourceEventUis(eventUiBases, eventDefs, resourceEventUis) { return core.mapHash(eventUiBases, function (eventUi, defId) { if (defId) { // not the '' key return injectResourceEventUi(eventUi, eventDefs[defId], resourceEventUis); } else { return eventUi; } }); } function injectResourceEventUi(origEventUi, eventDef, resourceEventUis) { var parts = []; // first resource takes precedence, which fights with the ordering of combineEventUis, thus the unshifts for (var _i = 0, _a = eventDef.resourceIds; _i < _a.length; _i++) { var resourceId = _a[_i]; if (resourceEventUis[resourceId]) { parts.unshift(resourceEventUis[resourceId]); } } parts.unshift(origEventUi); return core.combineEventUis(parts); } var RESOURCE_SOURCE_PROPS = { id: String }; var defs = []; var uid = 0; function registerResourceSourceDef(def) { defs.push(def); } function getResourceSourceDef(id) { return defs[id]; } function doesSourceIgnoreRange(source) { return Boolean(defs[source.sourceDefId].ignoreRange); } function parseResourceSource(input) { for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence var def = defs[i]; var meta = def.parseMeta(input); if (meta) { var res = parseResourceSourceProps((typeof input === 'object' && input) ? input : {}, meta, i); res._raw = input; return res; } } return null; } function parseResourceSourceProps(input, meta, sourceDefId) { var props = core.refineProps(input, RESOURCE_SOURCE_PROPS); props.sourceId = String(uid++); props.sourceDefId = sourceDefId; props.meta = meta; props.publicId = props.id; props.isFetching = false; props.latestFetchId = ''; props.fetchRange = null; delete props.id; return props; } function reduceResourceSource (source, action, dateProfile, calendar) { switch (action.type) { case 'INIT': return createSource(calendar.opt('resources'), calendar); case 'RESET_RESOURCE_SOURCE': return createSource(action.resourceSourceInput, calendar, true); case 'PREV': // TODO: how do we track all actions that affect dateProfile :( case 'NEXT': case 'SET_DATE': case 'SET_VIEW_TYPE': return handleRange(source, dateProfile.activeRange, calendar); case 'RECEIVE_RESOURCES': case 'RECEIVE_RESOURCE_ERROR': return receiveResponse(source, action.fetchId, action.fetchRange); case 'REFETCH_RESOURCES': return fetchSource(source, dateProfile.activeRange, calendar); default: return source; } } var uid$1 = 0; function createSource(input, calendar, forceFetch) { if (input) { var source = parseResourceSource(input); if (forceFetch || !calendar.opt('refetchResourcesOnNavigate')) { // because assumes handleRange will do it later source = fetchSource(source, null, calendar); } return source; } return null; } function handleRange(source, activeRange, calendar) { if (calendar.opt('refetchResourcesOnNavigate') && !doesSourceIgnoreRange(source) && (!source.fetchRange || !core.rangesEqual(source.fetchRange, activeRange))) { return fetchSource(source, activeRange, calendar); } else { return source; } } function fetchSource(source, fetchRange, calendar) { var sourceDef = getResourceSourceDef(source.sourceDefId); var fetchId = String(uid$1++); sourceDef.fetch({ resourceSource: source, calendar: calendar, range: fetchRange }, function (res) { // HACK // do before calling dispatch in case dispatch renders synchronously calendar.afterSizingTriggers._resourcesRendered = [null]; // fire once calendar.dispatch({ type: 'RECEIVE_RESOURCES', fetchId: fetchId, fetchRange: fetchRange, rawResources: res.rawResources }); }, function (error) { calendar.dispatch({ type: 'RECEIVE_RESOURCE_ERROR', fetchId: fetchId, fetchRange: fetchRange, error: error }); }); return __assign({}, source, { isFetching: true, latestFetchId: fetchId }); } function receiveResponse(source, fetchId, fetchRange) { if (fetchId === source.latestFetchId) { return __assign({}, source, { isFetching: false, fetchRange: fetchRange }); } return source; } var RESOURCE_PROPS = { id: String, title: String, parentId: String, businessHours: null, children: null, extendedProps: null }; var PRIVATE_ID_PREFIX = '_fc:'; var uid$2 = 0; /* needs a full store so that it can populate children too */ function parseResource(input, parentId, store, calendar) { if (parentId === void 0) { parentId = ''; } var leftovers0 = {}; var props = core.refineProps(input, RESOURCE_PROPS, {}, leftovers0); var leftovers1 = {}; var ui = core.processScopedUiProps('event', leftovers0, calendar, leftovers1); if (!props.id) { props.id = PRIVATE_ID_PREFIX + (uid$2++); } if (!props.parentId) { // give precedence to the parentId property props.parentId = parentId; } props.businessHours = props.businessHours ? core.parseBusinessHours(props.businessHours, calendar) : null; props.ui = ui; props.extendedProps = __assign({}, leftovers1, props.extendedProps); // help out ResourceApi from having user modify props Object.freeze(ui.classNames); Object.freeze(props.extendedProps); if (store[props.id]) ; else { store[props.id] = props; if (props.children) { for (var _i = 0, _a = props.children; _i < _a.length; _i++) { var childInput = _a[_i]; parseResource(childInput, props.id, store, calendar); } delete props.children; } } return props; } /* TODO: use this in more places */ function getPublicId(id) { if (id.indexOf(PRIVATE_ID_PREFIX) === 0) { return ''; } return id; } function reduceResourceStore (store, action, source, calendar) { switch (action.type) { case 'INIT': return {}; case 'RECEIVE_RESOURCES': return receiveRawResources(store, action.rawResources, action.fetchId, source, calendar); case 'ADD_RESOURCE': return addResource(store, action.resourceHash); case 'REMOVE_RESOURCE': return removeResource(store, action.resourceId); case 'SET_RESOURCE_PROP': return setResourceProp(store, action.resourceId, action.propName, action.propValue); case 'RESET_RESOURCES': // must make the calendar think each resource is a new object :/ return core.mapHash(store, function (resource) { return __assign({}, resource); }); default: return store; } } function receiveRawResources(existingStore, inputs, fetchId, source, calendar) { if (source.latestFetchId === fetchId) { var nextStore = {}; for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { var input = inputs_1[_i]; parseResource(input, '', nextStore, calendar); } return nextStore; } else { return existingStore; } } function addResource(existingStore, additions) { // TODO: warn about duplicate IDs return __assign({}, existingStore, additions); } function removeResource(existingStore, resourceId) { var newStore = __assign({}, existingStore); delete newStore[resourceId]; // promote children for (var childResourceId in newStore) { // a child, *maybe* but probably not if (newStore[childResourceId].parentId === resourceId) { newStore[childResourceId] = __assign({}, newStore[childResourceId], { parentId: '' }); } } return newStore; } function setResourceProp(existingStore, resourceId, name, value) { var _a, _b; var existingResource = existingStore[resourceId]; // TODO: sanitization if (existingResource) { return __assign({}, existingStore, (_a = {}, _a[resourceId] = __assign({}, existingResource, (_b = {}, _b[name] = value, _b)), _a)); } else { return existingStore; } } function reduceResourceEntityExpansions(expansions, action) { var _a; switch (action.type) { case 'INIT': return {}; case 'SET_RESOURCE_ENTITY_EXPANDED': return __assign({}, expansions, (_a = {}, _a[action.id] = action.isExpanded, _a)); default: return expansions; } } function resourcesReducers (state, action, calendar) { var resourceSource = reduceResourceSource(state.resourceSource, action, state.dateProfile, calendar); var resourceStore = reduceResourceStore(state.resourceStore, action, resourceSource, calendar); var resourceEntityExpansions = reduceResourceEntityExpansions(state.resourceEntityExpansions, action); return __assign({}, state, { resourceSource: resourceSource, resourceStore: resourceStore, resourceEntityExpansions: resourceEntityExpansions }); } var RESOURCE_RELATED_PROPS = { resourceId: String, resourceIds: function (items) { return (items || []).map(function (item) { return String(item); }); }, resourceEditable: Boolean }; function parseEventDef(def, props, leftovers) { var resourceRelatedProps = core.refineProps(props, RESOURCE_RELATED_PROPS, {}, leftovers); var resourceIds = resourceRelatedProps.resourceIds; if (resourceRelatedProps.resourceId) { resourceIds.push(resourceRelatedProps.resourceId); } def.resourceIds = resourceIds; def.resourceEditable = resourceRelatedProps.resourceEditable; } function massageEventDragMutation(eventMutation, hit0, hit1) { var resource0 = hit0.dateSpan.resourceId; var resource1 = hit1.dateSpan.resourceId; if (resource0 && resource1 && resource0 !== resource1) { eventMutation.resourceMutation = { matchResourceId: resource0, setResourceId: resource1 }; } } /* TODO: all this would be much easier if we were using a hash! */ function applyEventDefMutation(eventDef, mutation, calendar) { var resourceMutation = mutation.resourceMutation; if (resourceMutation && computeResourceEditable(eventDef, calendar)) { var index = eventDef.resourceIds.indexOf(resourceMutation.matchResourceId); if (index !== -1) { var resourceIds = eventDef.resourceIds.slice(); // copy resourceIds.splice(index, 1); // remove if (resourceIds.indexOf(resourceMutation.setResourceId) === -1) { // not already in there resourceIds.push(resourceMutation.setResourceId); // add } eventDef.resourceIds = resourceIds; } } } /* HACK TODO: use EventUi system instead of this */ function computeResourceEditable(eventDef, calendar) { var resourceEditable = eventDef.resourceEditable; if (resourceEditable == null) { var source = eventDef.sourceId && calendar.state.eventSources[eventDef.sourceId]; if (source) { resourceEditable = source.extendedProps.resourceEditable; // used the Source::extendedProps hack } if (resourceEditable == null) { resourceEditable = calendar.opt('eventResourceEditable'); if (resourceEditable == null) { resourceEditable = calendar.opt('editable'); // TODO: use defaults system instead } } } return resourceEditable; } function transformEventDrop(mutation, calendar) { var resourceMutation = mutation.resourceMutation; if (resourceMutation) { return { oldResource: calendar.getResourceById(resourceMutation.matchResourceId), newResource: calendar.getResourceById(resourceMutation.setResourceId) }; } else { return { oldResource: null, newResource: null }; } } function transformDateSelectionJoin(hit0, hit1) { var resourceId0 = hit0.dateSpan.resourceId; var resourceId1 = hit1.dateSpan.resourceId; if (resourceId0 && resourceId1) { if (hit0.component.allowAcrossResources === false && resourceId0 !== resourceId1) { return false; } else { return { resourceId: resourceId0 }; } } } var ResourceApi = /** @class */ (function () { function ResourceApi(calendar, rawResource) { this._calendar = calendar; this._resource = rawResource; } ResourceApi.prototype.setProp = function (name, value) { this._calendar.dispatch({ type: 'SET_RESOURCE_PROP', resourceId: this._resource.id, propName: name, propValue: value }); }; ResourceApi.prototype.remove = function () { this._calendar.dispatch({ type: 'REMOVE_RESOURCE', resourceId: this._resource.id }); }; ResourceApi.prototype.getParent = function () { var calendar = this._calendar; var parentId = this._resource.parentId; if (parentId) { return new ResourceApi(calendar, calendar.state.resourceSource[parentId]); } else { return null; } }; ResourceApi.prototype.getChildren = function () { var thisResourceId = this._resource.id; var calendar = this._calendar; var resourceStore = calendar.state.resourceStore; var childApis = []; for (var resourceId in resourceStore) { if (resourceStore[resourceId].parentId === thisResourceId) { childApis.push(new ResourceApi(calendar, resourceStore[resourceId])); } } return childApis; }; /* this is really inefficient! TODO: make EventApi::resourceIds a hash or keep an index in the Calendar's state */ ResourceApi.prototype.getEvents = function () { var thisResourceId = this._resource.id; var calendar = this._calendar; var _a = calendar.state.eventStore, defs = _a.defs, instances = _a.instances; var eventApis = []; for (var instanceId in instances) { var instance = instances[instanceId]; var def = defs[instance.defId]; if (def.resourceIds.indexOf(thisResourceId) !== -1) { // inefficient!!! eventApis.push(new core.EventApi(calendar, def, instance)); } } return eventApis; }; Object.defineProperty(ResourceApi.prototype, "id", { get: function () { return this._resource.id; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "title", { get: function () { return this._resource.title; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "eventConstraint", { get: function () { return this._resource.ui.constraints[0] || null; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "eventOverlap", { get: function () { return this._resource.ui.overlap; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "eventAllow", { get: function () { return this._resource.ui.allows[0] || null; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "eventBackgroundColor", { get: function () { return this._resource.ui.backgroundColor; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "eventBorderColor", { get: function () { return this._resource.ui.borderColor; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "eventTextColor", { get: function () { return this._resource.ui.textColor; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "eventClassNames", { // NOTE: user can't modify these because Object.freeze was called in event-def parsing get: function () { return this._resource.ui.classNames; }, enumerable: true, configurable: true }); Object.defineProperty(ResourceApi.prototype, "extendedProps", { get: function () { return this._resource.extendedProps; }, enumerable: true, configurable: true }); return ResourceApi; }()); core.Calendar.prototype.addResource = function (input, scrollTo) { var _a; if (scrollTo === void 0) { scrollTo = true; } var resourceHash; var resource; if (input instanceof ResourceApi) { resource = input._resource; resourceHash = (_a = {}, _a[resource.id] = resource, _a); } else { resourceHash = {}; resource = parseResource(input, '', resourceHash, this); } // HACK if (scrollTo) { this.component.view.addScroll({ forcedRowId: resource.id }); } this.dispatch({ type: 'ADD_RESOURCE', resourceHash: resourceHash }); return new ResourceApi(this, resource); }; core.Calendar.prototype.getResourceById = function (id) { id = String(id); if (this.state.resourceStore) { // guard against calendar with no resource functionality var rawResource = this.state.resourceStore[id]; if (rawResource) { return new ResourceApi(this, rawResource); } } return null; }; core.Calendar.prototype.getResources = function () { var resourceStore = this.state.resourceStore; var resourceApis = []; if (resourceStore) { // guard against calendar with no resource functionality for (var resourceId in resourceStore) { resourceApis.push(new ResourceApi(this, resourceStore[resourceId])); } } return resourceApis; }; core.Calendar.prototype.getTopLevelResources = function () { var resourceStore = this.state.resourceStore; var resourceApis = []; if (resourceStore) { // guard against calendar with no resource functionality for (var resourceId in resourceStore) { if (!resourceStore[resourceId].parentId) { resourceApis.push(new ResourceApi(this, resourceStore[resourceId])); } } } return resourceApis; }; core.Calendar.prototype.rerenderResources = function () { this.dispatch({ type: 'RESET_RESOURCES' }); }; core.Calendar.prototype.refetchResources = function () { this.dispatch({ type: 'REFETCH_RESOURCES' }); }; function transformDatePoint(dateSpan, calendar) { return dateSpan.resourceId ? { resource: calendar.getResourceById(dateSpan.resourceId) } : {}; } function transformDateSpan(dateSpan, calendar) { return dateSpan.resourceId ? { resource: calendar.getResourceById(dateSpan.resourceId) } : {}; } /* splits things BASED OFF OF which resources they are associated with. creates a '' entry which is when something has NO resource. */ var ResourceSplitter = /** @class */ (function (_super) { __extends(ResourceSplitter, _super); function ResourceSplitter() { return _super !== null && _super.apply(this, arguments) || this; } ResourceSplitter.prototype.getKeyInfo = function (props) { return __assign({ '': {} }, props.resourceStore // already has `ui` and `businessHours` keys! ); }; ResourceSplitter.prototype.getKeysForDateSpan = function (dateSpan) { return [dateSpan.resourceId || '']; }; ResourceSplitter.prototype.getKeysForEventDef = function (eventDef) { var resourceIds = eventDef.resourceIds; if (!resourceIds.length) { return ['']; } return resourceIds; }; return ResourceSplitter; }(core.Splitter)); function isPropsValidWithResources(props, calendar) { var splitter = new ResourceSplitter(); var sets = splitter.splitProps(__assign({}, props, { resourceStore: calendar.state.resourceStore })); for (var resourceId in sets) { var props_1 = sets[resourceId]; // merge in event data from the non-resource segment if (resourceId && sets['']) { // current segment is not the non-resource one, and there IS a non-resource one props_1 = __assign({}, props_1, { eventStore: core.mergeEventStores(sets[''].eventStore, props_1.eventStore), eventUiBases: __assign({}, sets[''].eventUiBases, props_1.eventUiBases) }); } if (!core.isPropsValid(props_1, calendar, { resourceId: resourceId }, filterConfig.bind(null, resourceId))) { return false; } } return true; } function filterConfig(resourceId, config) { return __assign({}, config, { constraints: filterConstraints(resourceId, config.constraints) }); } function filterConstraints(resourceId, constraints) { return constraints.map(function (constraint) { var defs = constraint.defs; if (defs) { // we are dealing with an EventStore // if any of the events define constraints to resources that are NOT this resource, // then this resource is unconditionally prohibited, which is what a `false` value does. for (var defId in defs) { var resourceIds = defs[defId].resourceIds; if (resourceIds.length && resourceIds.indexOf(resourceId) === -1) { // TODO: use a hash?!!! (for other reasons too) return false; } } } return constraint; }); } function transformExternalDef(dateSpan) { return dateSpan.resourceId ? { resourceId: dateSpan.resourceId } : {}; } function transformEventResizeJoin(hit0, hit1) { var component = hit0.component; if (component.allowAcrossResources === false && hit0.dateSpan.resourceId !== hit1.dateSpan.resourceId) { return false; } } core.EventApi.prototype.getResources = function () { var calendar = this._calendar; return this._def.resourceIds.map(function (resourceId) { return calendar.getResourceById(resourceId); }); }; core.EventApi.prototype.setResources = function (resources) { var resourceIds = []; // massage resources -> resourceIds for (var _i = 0, resources_1 = resources; _i < resources_1.length; _i++) { var resource = resources_1[_i]; var resourceId = null; if (typeof resource === 'string') { resourceId = resource; } else if (typeof resource === 'number') { resourceId = String(resource); } else if (resource instanceof ResourceApi) { resourceId = resource.id; // guaranteed to always have an ID. hmmm } else { console.warn('unknown resource type: ' + resource); } if (resourceId) { resourceIds.push(resourceId); } } this.mutate({ standardProps: { resourceIds: resourceIds } }); }; var RELEASE_DATE = '2019-06-02'; // for Scheduler var UPGRADE_WINDOW = 365 + 7; // days. 1 week leeway, for tz shift reasons too var LICENSE_INFO_URL = 'http://fullcalendar.io/scheduler/license/'; var PRESET_LICENSE_KEYS = [ 'GPL-My-Project-Is-Open-Source', 'CC-Attribution-NonCommercial-NoDerivatives' ]; var CSS = { position: 'absolute', 'z-index': 99999, bottom: '1px', left: '1px', background: '#eee', 'border-color': '#ddd', 'border-style': 'solid', 'border-width': '1px 1px 0 0', padding: '2px 4px', 'font-size': '12px', 'border-top-right-radius': '3px' }; function injectLicenseWarning(containerEl, calendar) { var key = calendar.opt('schedulerLicenseKey'); if (!isImmuneUrl(window.location.href) && !isValidKey(key)) { core.appendToElement(containerEl, '
'); } } /* This decryption is not meant to be bulletproof. Just a way to remind about an upgrade. */ function isValidKey(key) { if (PRESET_LICENSE_KEYS.indexOf(key) !== -1) { return true; } var parts = (key || '').match(/^(\d+)\-fcs\-(\d+)$/); if (parts && (parts[1].length === 10)) { var purchaseDate = new Date(parseInt(parts[2], 10) * 1000); var releaseDate = new Date(core.config.mockSchedulerReleaseDate || RELEASE_DATE); if (core.isValidDate(releaseDate)) { // token won't be replaced in dev mode var minPurchaseDate = core.addDays(releaseDate, -UPGRADE_WINDOW); if (minPurchaseDate < purchaseDate) { return true; } } } return false; } function isImmuneUrl(url) { return /\w+\:\/\/fullcalendar\.io\/|\/demos\/[\w-]+\.html$/.test(url); } var optionChangeHandlers = { resources: handleResources }; function handleResources(newSourceInput, calendar, deepEquals) { var oldSourceInput = calendar.state.resourceSource._raw; if (!deepEquals(oldSourceInput, newSourceInput)) { calendar.dispatch({ type: 'RESET_RESOURCE_SOURCE', resourceSourceInput: newSourceInput }); } } registerResourceSourceDef({ ignoreRange: true, parseMeta: function (raw) { if (Array.isArray(raw)) { return raw; } else if (Array.isArray(raw.resources)) { return raw.resources; } return null; }, fetch: function (arg, successCallback) { successCallback({ rawResources: arg.resourceSource.meta }); } }); registerResourceSourceDef({ parseMeta: function (raw) { if (typeof raw === 'function') { return raw; } else if (typeof raw.resources === 'function') { return raw.resources; } return null; }, fetch: function (arg, success, failure) { var dateEnv = arg.calendar.dateEnv; var func = arg.resourceSource.meta; var publicArg = {}; if (arg.range) { publicArg = { start: dateEnv.toDate(arg.range.start), end: dateEnv.toDate(arg.range.end), startStr: dateEnv.formatIso(arg.range.start), endStr: dateEnv.formatIso(arg.range.end), timeZone: dateEnv.timeZone }; } // TODO: make more dry with EventSourceFunc // TODO: accept a response? core.unpromisify(func.bind(null, publicArg), function (rawResources) { success({ rawResources: rawResources }); // needs an object response }, failure // send errorObj directly to failure callback ); } }); registerResourceSourceDef({ parseMeta: function (raw) { if (typeof raw === 'string') { raw = { url: raw }; } else if (!raw || typeof raw !== 'object' || !raw.url) { return null; } return { url: raw.url, method: (raw.method || 'GET').toUpperCase(), extraParams: raw.extraParams }; }, fetch: function (arg, successCallback, failureCallback) { var meta = arg.resourceSource.meta; var requestParams = buildRequestParams(meta, arg.range, arg.calendar); core.requestJson(meta.method, meta.url, requestParams, function (rawResources, xhr) { successCallback({ rawResources: rawResources, xhr: xhr }); }, function (message, xhr) { failureCallback({ message: message, xhr: xhr }); }); } }); // TODO: somehow consolidate with event json feed function buildRequestParams(meta, range, calendar) { var dateEnv = calendar.dateEnv; var startParam; var endParam; var timeZoneParam; var customRequestParams; var params = {}; if (range) { // startParam = meta.startParam // if (startParam == null) { startParam = calendar.opt('startParam'); // } // endParam = meta.endParam // if (endParam == null) { endParam = calendar.opt('endParam'); // } // timeZoneParam = meta.timeZoneParam // if (timeZoneParam == null) { timeZoneParam = calendar.opt('timeZoneParam'); // } params[startParam] = dateEnv.formatIso(range.start); params[endParam] = dateEnv.formatIso(range.end); if (dateEnv.timeZone !== 'local') { params[timeZoneParam] = dateEnv.timeZone; } } // retrieve any outbound GET/POST data from the options if (typeof meta.extraParams === 'function') { // supplied as a function that returns a key/value object customRequestParams = meta.extraParams(); } else { // probably supplied as a straight key/value object customRequestParams = meta.extraParams || {}; } __assign(params, customRequestParams); return params; } function buildResourceTextFunc(resourceTextSetting, calendar) { if (typeof resourceTextSetting === 'function') { return function (resource) { return resourceTextSetting(new ResourceApi(calendar, resource)); }; } else { return function (resource) { return resource.title || getPublicId(resource.id); }; } } var ResourceDayHeader = /** @class */ (function (_super) { __extends(ResourceDayHeader, _super); function ResourceDayHeader(context, parentEl) { var _this = _super.call(this, context) || this; _this.datesAboveResources = _this.opt('datesAboveResources'); _this.resourceTextFunc = buildResourceTextFunc(_this.opt('resourceText'), _this.calendar); parentEl.innerHTML = ''; // because might be nbsp parentEl.appendChild(_this.el = core.htmlToElement('