@sprucelabs/spruce-calendar-components 20.11.1 → 21.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/.spruce/errors/errors.types.d.ts +122 -0
- package/build/.spruce/errors/errors.types.js +4 -0
- package/build/.spruce/errors/options.types.d.ts +28 -0
- package/build/.spruce/errors/options.types.js +2 -0
- package/build/constants.d.ts +5 -0
- package/build/constants.js +9 -0
- package/build/errors/SpruceError.d.ts +5 -0
- package/build/errors/SpruceError.js +45 -0
- package/build/esm/.spruce/errors/errors.types.d.ts +122 -0
- package/build/esm/.spruce/errors/errors.types.js +3 -0
- package/build/esm/.spruce/errors/options.types.d.ts +28 -0
- package/build/esm/.spruce/errors/options.types.js +1 -0
- package/build/esm/constants.d.ts +5 -0
- package/build/esm/constants.js +6 -0
- package/build/esm/errors/SpruceError.d.ts +5 -0
- package/build/esm/errors/SpruceError.js +39 -0
- package/build/esm/index-module.d.ts +30 -0
- package/build/esm/index-module.js +7 -0
- package/build/esm/skillViewControllers/Root.svc.d.ts +73 -0
- package/build/esm/skillViewControllers/Root.svc.js +404 -0
- package/build/esm/stores/RemotePreferencesStore.d.ts +26 -0
- package/build/esm/stores/RemotePreferencesStore.js +85 -0
- package/build/esm/toolBelt/CalendarToolTestFactory.d.ts +5 -0
- package/build/esm/toolBelt/CalendarToolTestFactory.js +28 -0
- package/build/esm/toolBelt/states/PrerequisitesToolBeltState.d.ts +37 -0
- package/build/esm/toolBelt/states/PrerequisitesToolBeltState.js +190 -0
- package/build/esm/toolBelt/states/RootToolBeltState.d.ts +37 -0
- package/build/esm/toolBelt/states/RootToolBeltState.js +122 -0
- package/build/esm/toolBelt/states/makeEventTyped.d.ts +2 -0
- package/build/esm/toolBelt/states/makeEventTyped.js +8 -0
- package/build/esm/types/calendar.types.d.ts +10 -0
- package/build/esm/utilities/CalendarEventManager.d.ts +72 -0
- package/build/esm/utilities/CalendarEventManager.js +321 -0
- package/build/esm/utilities/CalendarPeopleManager.d.ts +56 -0
- package/build/esm/utilities/CalendarPeopleManager.js +182 -0
- package/build/esm/utilities/calendarShiftGenerator.d.ts +8 -0
- package/build/esm/utilities/calendarShiftGenerator.js +24 -0
- package/build/esm/viewControllers/CalendarSelectTool.vc.d.ts +28 -0
- package/build/esm/viewControllers/CalendarSelectTool.vc.js +103 -0
- package/build/esm/viewControllers/DateSelectCard.vc.d.ts +29 -0
- package/build/esm/viewControllers/DateSelectCard.vc.js +77 -0
- package/build/esm/viewControllers/PersonSelectTool.vc.d.ts +36 -0
- package/build/esm/viewControllers/PersonSelectTool.vc.js +156 -0
- package/build/esm/viewControllers/SelectUpdateRepeatingStrategyCard.vc.d.ts +18 -0
- package/build/esm/viewControllers/SelectUpdateRepeatingStrategyCard.vc.js +85 -0
- package/build/index-module.d.ts +30 -0
- package/build/index-module.js +32 -0
- package/build/skillViewControllers/Root.svc.d.ts +73 -0
- package/build/skillViewControllers/Root.svc.js +359 -0
- package/build/stores/RemotePreferencesStore.d.ts +26 -0
- package/build/stores/RemotePreferencesStore.js +67 -0
- package/build/toolBelt/CalendarToolTestFactory.d.ts +5 -0
- package/build/toolBelt/CalendarToolTestFactory.js +34 -0
- package/build/toolBelt/states/PrerequisitesToolBeltState.d.ts +37 -0
- package/build/toolBelt/states/PrerequisitesToolBeltState.js +172 -0
- package/build/toolBelt/states/RootToolBeltState.d.ts +37 -0
- package/build/toolBelt/states/RootToolBeltState.js +113 -0
- package/build/toolBelt/states/makeEventTyped.d.ts +2 -0
- package/build/toolBelt/states/makeEventTyped.js +14 -0
- package/build/types/calendar.types.d.ts +10 -0
- package/build/utilities/CalendarEventManager.d.ts +72 -0
- package/build/utilities/CalendarEventManager.js +279 -0
- package/build/utilities/CalendarPeopleManager.d.ts +56 -0
- package/build/utilities/CalendarPeopleManager.js +163 -0
- package/build/utilities/calendarShiftGenerator.d.ts +8 -0
- package/build/utilities/calendarShiftGenerator.js +26 -0
- package/build/viewControllers/CalendarSelectTool.vc.d.ts +28 -0
- package/build/viewControllers/CalendarSelectTool.vc.js +93 -0
- package/build/viewControllers/DateSelectCard.vc.d.ts +29 -0
- package/build/viewControllers/DateSelectCard.vc.js +69 -0
- package/build/viewControllers/PersonSelectTool.vc.d.ts +36 -0
- package/build/viewControllers/PersonSelectTool.vc.js +140 -0
- package/build/viewControllers/SelectUpdateRepeatingStrategyCard.vc.d.ts +18 -0
- package/build/viewControllers/SelectUpdateRepeatingStrategyCard.vc.js +88 -0
- package/package.json +99 -26
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { calendarEventSchema, } from '@sprucelabs/heartwood-view-controllers';
|
|
11
|
+
import { assertOptions, normalizeSchemaValues } from '@sprucelabs/schema';
|
|
12
|
+
import SpruceError from '../errors/SpruceError.js';
|
|
13
|
+
import calendarShiftGenerator from './calendarShiftGenerator.js';
|
|
14
|
+
import draftEventGenerator from './draftGenerator.js';
|
|
15
|
+
export class CalendarEventManager {
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.allEvents = [];
|
|
18
|
+
this.inclusiveCalendarIds = [];
|
|
19
|
+
this.hasVcForEventTypeBeenLoaded = {};
|
|
20
|
+
this.shouldIgnoreNextContextUpdate = false;
|
|
21
|
+
this.calendars = [];
|
|
22
|
+
this.shouldUpdateContextOnNextSave = true;
|
|
23
|
+
const { calendarVc, events, remoteVc, sm, askForUpdateStrategy, dates, preferences, } = assertOptions(options, [
|
|
24
|
+
'calendarVc',
|
|
25
|
+
'events',
|
|
26
|
+
'remoteVc',
|
|
27
|
+
'sm',
|
|
28
|
+
'askForUpdateStrategy',
|
|
29
|
+
'dates',
|
|
30
|
+
'preferences',
|
|
31
|
+
]);
|
|
32
|
+
this.calendarVc = calendarVc;
|
|
33
|
+
this.events = events;
|
|
34
|
+
this.remoteVc = remoteVc;
|
|
35
|
+
this.sm = sm;
|
|
36
|
+
this.prefs = preferences;
|
|
37
|
+
this.dates = dates;
|
|
38
|
+
this.askForUpdateStrategy = askForUpdateStrategy;
|
|
39
|
+
this.calendarVc.setRemoteStore(this.events);
|
|
40
|
+
}
|
|
41
|
+
get calendarIds() {
|
|
42
|
+
return this.calendars.map((c) => c.id);
|
|
43
|
+
}
|
|
44
|
+
get visibleCalendarIds() {
|
|
45
|
+
var _a;
|
|
46
|
+
return (_a = this.prefs.getVisibleCalendarIds()) !== null && _a !== void 0 ? _a : this.calendars.map((c) => c.id);
|
|
47
|
+
}
|
|
48
|
+
replaceEventsInRange(events, startMs, endMs) {
|
|
49
|
+
this.calendarVc.replaceEventsInRange(events.filter((e) => this.isCalendarSelected(e.calendarId)), startMs, endMs);
|
|
50
|
+
this.allEvents = this.allEvents.filter((e) => events.findIndex((event) => event.id === e.id) === -1 &&
|
|
51
|
+
!(e.startDateTimeMs >= startMs && e.startDateTimeMs <= endMs));
|
|
52
|
+
this.allEvents.push(...events);
|
|
53
|
+
this.refreshShifts();
|
|
54
|
+
}
|
|
55
|
+
refreshShifts() {
|
|
56
|
+
const inclusiveEvents = this.allEvents.filter((e) => this.inclusiveCalendarIds.indexOf(e.calendarId) > -1);
|
|
57
|
+
const shifts = calendarShiftGenerator.generateFromEvents(inclusiveEvents);
|
|
58
|
+
this.calendarVc.setShifts([...shifts]);
|
|
59
|
+
}
|
|
60
|
+
isCalendarSelected(calendarId) {
|
|
61
|
+
return this.visibleCalendarIds.indexOf(calendarId) > -1;
|
|
62
|
+
}
|
|
63
|
+
doesCalenderExist(calendarId) {
|
|
64
|
+
return this.calendars.findIndex((c) => c.id === calendarId) > -1;
|
|
65
|
+
}
|
|
66
|
+
getAllEvents() {
|
|
67
|
+
return this.allEvents;
|
|
68
|
+
}
|
|
69
|
+
getCalendars() {
|
|
70
|
+
return this.calendars;
|
|
71
|
+
}
|
|
72
|
+
addDraftEvent(event) {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
this.calendarVc.selectEvent(event.id);
|
|
75
|
+
this.allEvents.push(event);
|
|
76
|
+
yield this.updateEventInContext(event);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
silentlySwapEvent(oldId, event) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
const events = this.getAllEvents().filter((e) => e.id !== oldId);
|
|
82
|
+
this.allEvents = [...events, event];
|
|
83
|
+
yield this.updateEventInContext(event);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
handleDropEvent(id, updates) {
|
|
87
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
+
const event = Object.assign(Object.assign({}, this.calendarVc.getEvent(id)), updates);
|
|
89
|
+
const pass = yield this.optionallyAskForUpdateRepeatingStrategy(event);
|
|
90
|
+
if (pass) {
|
|
91
|
+
yield this.saveEvent(event);
|
|
92
|
+
}
|
|
93
|
+
return pass;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
reset() {
|
|
97
|
+
var _a;
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
void this.setEventInContext(undefined);
|
|
100
|
+
(_a = this.events) === null || _a === void 0 ? void 0 : _a.clearCalendarId();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
restoreEventToDraftOnStateLoadError() {
|
|
104
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
105
|
+
const updated = yield this.updateEventInContext({
|
|
106
|
+
timeBlocks: draftEventGenerator.generateTimeBlocks(),
|
|
107
|
+
calendarId: undefined,
|
|
108
|
+
eventTypeSlug: undefined,
|
|
109
|
+
});
|
|
110
|
+
this.updateEvent(updated.id, updated);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
getVisibleCalendarIds() {
|
|
114
|
+
return this.visibleCalendarIds;
|
|
115
|
+
}
|
|
116
|
+
removeEvent(id) {
|
|
117
|
+
var _a;
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
this.allEvents = this.allEvents.filter((e) => e.id !== id);
|
|
120
|
+
const event = this.calendarVc.getEvent(id);
|
|
121
|
+
this.calendarVc.removeEvent(id);
|
|
122
|
+
try {
|
|
123
|
+
yield this.events.cancelEvent(event.id);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
console.error((_a = err.stack) !== null && _a !== void 0 ? _a : err.message);
|
|
127
|
+
this.calendarVc.addEvent(Object.assign(Object.assign({}, event), { error: err }));
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
makeCalendarVisible(calendarId) {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
this.assertValidCalendarId(calendarId);
|
|
134
|
+
this.calendarVc.mixinEvents(this.allEvents.filter((e) => e.calendarId === calendarId));
|
|
135
|
+
const visibleCalendarIds = [...this.visibleCalendarIds];
|
|
136
|
+
visibleCalendarIds.push(calendarId);
|
|
137
|
+
yield this.prefs.setVisibleCalendarIds(visibleCalendarIds);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
makeCalendarHidden(calendarId) {
|
|
141
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
142
|
+
this.assertValidCalendarId(calendarId);
|
|
143
|
+
const visibleCalendarIds = this.visibleCalendarIds.filter((id) => id !== calendarId);
|
|
144
|
+
for (const event of this.allEvents) {
|
|
145
|
+
if (event.calendarId === calendarId &&
|
|
146
|
+
this.calendarVc.hasEvent(event.id)) {
|
|
147
|
+
this.calendarVc.removeEvent(event.id);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
yield this.prefs.setVisibleCalendarIds(visibleCalendarIds);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
updateEvent(id, updates) {
|
|
154
|
+
var _a;
|
|
155
|
+
this.calendarVc.updateEvent(id, updates);
|
|
156
|
+
const idx = this.allEvents.findIndex((e) => e.id === id);
|
|
157
|
+
this.allEvents[idx] = Object.assign(Object.assign({}, this.allEvents[idx]), updates);
|
|
158
|
+
this.refreshShifts();
|
|
159
|
+
if (this.shouldUpdateContextOnNextSave &&
|
|
160
|
+
((_a = this.sm.getContext().event) === null || _a === void 0 ? void 0 : _a.id) === id) {
|
|
161
|
+
this.shouldIgnoreNextContextUpdate = true;
|
|
162
|
+
void this.updateEventInContext(updates);
|
|
163
|
+
}
|
|
164
|
+
this.shouldUpdateContextOnNextSave = true;
|
|
165
|
+
}
|
|
166
|
+
loadEvents(startDate, endDate, peopleIds) {
|
|
167
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
168
|
+
const events = yield this.events.getSchedules({
|
|
169
|
+
calendarIds: this.calendarIds,
|
|
170
|
+
startDate,
|
|
171
|
+
endDate,
|
|
172
|
+
peopleIds,
|
|
173
|
+
});
|
|
174
|
+
this.replaceEventsInRange(events, startDate, endDate);
|
|
175
|
+
if (!this.eventTypes) {
|
|
176
|
+
this.eventTypes = yield this.events.loadEventTypes();
|
|
177
|
+
}
|
|
178
|
+
yield Promise.all(events.map((e) => __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
var _a;
|
|
180
|
+
const type = (_a = this.eventTypes) === null || _a === void 0 ? void 0 : _a.find((t) => t.slug === e.eventTypeSlug);
|
|
181
|
+
if (type === null || type === void 0 ? void 0 : type.viewControllerId) {
|
|
182
|
+
yield this.setupVcForEventType(type.viewControllerId, type.slug);
|
|
183
|
+
}
|
|
184
|
+
})));
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
setCalendarVisibility(calendarId, shouldBeVisible) {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
if (shouldBeVisible) {
|
|
190
|
+
yield this.makeCalendarVisible(calendarId);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
yield this.makeCalendarHidden(calendarId);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
setupVcForEventType(vcId, typeSlug) {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
if (this.hasVcForEventTypeBeenLoaded[vcId]) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
this.hasVcForEventTypeBeenLoaded[vcId] = true;
|
|
203
|
+
yield this.remoteVc.fetchRemoteController(vcId);
|
|
204
|
+
this.calendarVc.setControllerForEventType(typeSlug, vcId);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
assertValidCalendarId(calendarId) {
|
|
208
|
+
if (!this.doesCalenderExist(calendarId)) {
|
|
209
|
+
throw new SpruceError({
|
|
210
|
+
code: 'CALENDAR_NOT_FOUND',
|
|
211
|
+
calendarIds: [calendarId],
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
updateEventInContext(updates) {
|
|
216
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
217
|
+
const { event } = this.sm.getContext();
|
|
218
|
+
const updated = Object.assign(Object.assign(Object.assign({}, event), updates), { isBusy: false });
|
|
219
|
+
yield this.setEventInContext(updated);
|
|
220
|
+
return updated;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
setEventInContext(newEvent, options) {
|
|
224
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
225
|
+
this.shouldIgnoreNextContextUpdate =
|
|
226
|
+
(options === null || options === void 0 ? void 0 : options.shouldHandleDidUpdateContext) !== false;
|
|
227
|
+
yield this.sm.updateContext({
|
|
228
|
+
event: newEvent,
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
selectEvent(eventId) {
|
|
233
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
234
|
+
const lastSelected = this.calendarVc.getSelectedEvent();
|
|
235
|
+
const event = this.calendarVc.getEvent(eventId);
|
|
236
|
+
this.calendarVc.selectEvent(event.id);
|
|
237
|
+
if ((lastSelected === null || lastSelected === void 0 ? void 0 : lastSelected.id) !== event.id) {
|
|
238
|
+
yield this.setEventInContext(event);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
load() {
|
|
243
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
+
yield this.sm.on('will-update-context', this.handleWillUpdateContext.bind(this));
|
|
245
|
+
yield this.sm.on('did-update-context', this.handleDidUpdateContext.bind(this));
|
|
246
|
+
yield this.loadCalendars();
|
|
247
|
+
this.inclusiveCalendarIds = this.calendars
|
|
248
|
+
.filter((c) => c.availableTimeSlotBehavior === 'include')
|
|
249
|
+
.map((c) => c.id);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
loadCalendars() {
|
|
253
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
254
|
+
this.calendars = yield this.events.loadCalendars();
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
handleWillUpdateContext(options) {
|
|
258
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
+
const { event: originalEvent } = options.current;
|
|
260
|
+
const { event } = options.updates;
|
|
261
|
+
let pass = true;
|
|
262
|
+
if ((event === null || event === void 0 ? void 0 : event.id) &&
|
|
263
|
+
(originalEvent === null || originalEvent === void 0 ? void 0 : originalEvent.id) === (event === null || event === void 0 ? void 0 : event.id) &&
|
|
264
|
+
!this.shouldIgnoreNextContextUpdate) {
|
|
265
|
+
pass = yield this.optionallyAskForUpdateRepeatingStrategy(event);
|
|
266
|
+
}
|
|
267
|
+
return {
|
|
268
|
+
shouldAllowUpdates: pass,
|
|
269
|
+
};
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
handleDidUpdateContext() {
|
|
273
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
274
|
+
if (this.shouldIgnoreNextContextUpdate) {
|
|
275
|
+
this.shouldIgnoreNextContextUpdate = false;
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const { event } = this.sm.getContext();
|
|
279
|
+
if (event === null || event === void 0 ? void 0 : event.id) {
|
|
280
|
+
this.shouldUpdateContextOnNextSave = false;
|
|
281
|
+
yield this.saveEvent(event);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
saveEvent(event) {
|
|
286
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
287
|
+
try {
|
|
288
|
+
const cleaned = normalizeSchemaValues(calendarEventSchema, Object.assign({}, event), {});
|
|
289
|
+
this.updateEvent(event.id, Object.assign(Object.assign({}, cleaned), { dateToUpdate: this.dateToUpdate, shouldUpdateAllEventsGoingForward: this.shouldUpdateAllEventsGoingForward }));
|
|
290
|
+
}
|
|
291
|
+
catch (err) {
|
|
292
|
+
console.error('Updating event in context from root failed because:\n\n', err);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
optionallyAskForUpdateRepeatingStrategy(event) {
|
|
297
|
+
var _a;
|
|
298
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
299
|
+
const cleaned = normalizeSchemaValues(calendarEventSchema, event, {});
|
|
300
|
+
if (((_a = cleaned.totalInRepeating) !== null && _a !== void 0 ? _a : 0) > 1) {
|
|
301
|
+
let strategy = yield this.askForUpdateStrategy(cleaned);
|
|
302
|
+
if (strategy === 'cancel') {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
else if (strategy === 'only-this-one') {
|
|
306
|
+
this.dateToUpdate = this.dates.getStartOfDay(event.startDateTimeMs);
|
|
307
|
+
this.shouldUpdateAllEventsGoingForward = false;
|
|
308
|
+
}
|
|
309
|
+
else if (strategy === 'all-going-forward') {
|
|
310
|
+
this.dateToUpdate = this.dates.getStartOfDay(event.startDateTimeMs);
|
|
311
|
+
this.shouldUpdateAllEventsGoingForward = true;
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
this.dateToUpdate = undefined;
|
|
315
|
+
this.shouldUpdateAllEventsGoingForward = false;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return true;
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { MercuryClient } from '@sprucelabs/mercury-client';
|
|
2
|
+
import { AbstractEventEmitter } from '@sprucelabs/mercury-event-emitter';
|
|
3
|
+
import { CalendarPerson } from '../skillViewControllers/Root.svc';
|
|
4
|
+
import RemotePreferencesStore from '../stores/RemotePreferencesStore';
|
|
5
|
+
import { CalendarEvent } from '../types/calendar.types';
|
|
6
|
+
import CalendarViewController from '../viewControllers/Calendar.vc';
|
|
7
|
+
import { PersonMode } from '../viewControllers/PersonSelectTool.vc';
|
|
8
|
+
export default class CalendarPeopleManager extends AbstractEventEmitter<PeopleContract> {
|
|
9
|
+
private connectToApi;
|
|
10
|
+
private prefs;
|
|
11
|
+
private client;
|
|
12
|
+
private loggedInPerson?;
|
|
13
|
+
private locationId;
|
|
14
|
+
private organizationId;
|
|
15
|
+
private team;
|
|
16
|
+
private getVisibleEvents;
|
|
17
|
+
constructor(options: PeopleManagerOptions);
|
|
18
|
+
load(options: {
|
|
19
|
+
loggedInPerson?: CalendarPerson | null;
|
|
20
|
+
locationId: string;
|
|
21
|
+
organizationId: string;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
private loadTeam;
|
|
24
|
+
getVisiblePeople(): CalendarPerson[];
|
|
25
|
+
private teammateById;
|
|
26
|
+
getTeam(): import("@sprucelabs/mercury-types").SpruceSchemas.Spruce.v2020_07_22.Person[];
|
|
27
|
+
getLoggedInPerson(): import("@sprucelabs/mercury-types").SpruceSchemas.HeartwoodViewControllers.v2021_02_11.CalendarPerson | undefined;
|
|
28
|
+
protected getVisiblePeopleIds(): string[];
|
|
29
|
+
private getSavedVisiblePeopleIds;
|
|
30
|
+
getVisibilityMode(): PersonMode;
|
|
31
|
+
setVisibilityMode(mode: PersonMode): Promise<void>;
|
|
32
|
+
private setVisibilityToMe;
|
|
33
|
+
private setVisibleToWorking;
|
|
34
|
+
private getWorkingPeopleIds;
|
|
35
|
+
private getWorkingPeople;
|
|
36
|
+
protected setVisiblePeopleIds(visible: string[], options?: SetVisiblePeolpeOptions): Promise<void>;
|
|
37
|
+
setPersonVisibility(id: string, shouldBeVisible: boolean): Promise<void>;
|
|
38
|
+
private emitDidUpdate;
|
|
39
|
+
}
|
|
40
|
+
export interface PeopleManagerOptions {
|
|
41
|
+
connectToApi: () => Promise<MercuryClient>;
|
|
42
|
+
preferences: RemotePreferencesStore;
|
|
43
|
+
calendarVc: PeopleManagerCalendarVc;
|
|
44
|
+
getVisibleEvents: () => CalendarEvent[];
|
|
45
|
+
}
|
|
46
|
+
export declare type PeopleManagerCalendarVc = Pick<CalendarViewController, 'addPerson' | 'getPeople' | 'removePerson' | 'setPeople'>;
|
|
47
|
+
declare const peopleContract: {
|
|
48
|
+
eventSignatures: {
|
|
49
|
+
'did-update': {};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
declare type PeopleContract = typeof peopleContract;
|
|
53
|
+
export interface SetVisiblePeolpeOptions {
|
|
54
|
+
shouldForceEmitDidChange?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { AbstractEventEmitter } from '@sprucelabs/mercury-event-emitter';
|
|
11
|
+
import { buildEventContract } from '@sprucelabs/mercury-types';
|
|
12
|
+
import { assertOptions } from '@sprucelabs/schema';
|
|
13
|
+
import { EMPLOYED_BASE_ROLES } from '@sprucelabs/spruce-core-schemas';
|
|
14
|
+
import SpruceError from '../errors/SpruceError.js';
|
|
15
|
+
export default class CalendarPeopleManager extends AbstractEventEmitter {
|
|
16
|
+
constructor(options) {
|
|
17
|
+
super(peopleContract);
|
|
18
|
+
this.team = [];
|
|
19
|
+
const { connectToApi, preferences, getVisibleEvents } = assertOptions(options, ['connectToApi', 'preferences', 'calendarVc', 'getVisibleEvents']);
|
|
20
|
+
this.connectToApi = connectToApi;
|
|
21
|
+
this.prefs = preferences;
|
|
22
|
+
this.getVisibleEvents = getVisibleEvents;
|
|
23
|
+
}
|
|
24
|
+
load(options) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const { loggedInPerson, organizationId, locationId } = options !== null && options !== void 0 ? options : {};
|
|
27
|
+
this.client = yield this.connectToApi();
|
|
28
|
+
this.loggedInPerson = loggedInPerson !== null && loggedInPerson !== void 0 ? loggedInPerson : undefined;
|
|
29
|
+
this.organizationId = organizationId;
|
|
30
|
+
this.locationId = locationId;
|
|
31
|
+
yield this.loadTeam();
|
|
32
|
+
if (this.getVisiblePeople().length === 0 && this.loggedInPerson) {
|
|
33
|
+
yield this.setVisiblePeopleIds([this.loggedInPerson.id]);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
loadTeam() {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
const [{ people }] = yield this.client.emitAndFlattenResponses('list-people::v2020_12_25', {
|
|
40
|
+
target: {
|
|
41
|
+
locationId: this.locationId,
|
|
42
|
+
organizationId: this.organizationId,
|
|
43
|
+
},
|
|
44
|
+
payload: {
|
|
45
|
+
roleBases: EMPLOYED_BASE_ROLES.map((r) => r.slug),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
this.team = people;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
getVisiblePeople() {
|
|
52
|
+
return this.getVisiblePeopleIds()
|
|
53
|
+
.map((i) => {
|
|
54
|
+
try {
|
|
55
|
+
return this.teammateById(i);
|
|
56
|
+
// eslint-disable-next-line no-empty
|
|
57
|
+
}
|
|
58
|
+
catch (_a) { }
|
|
59
|
+
return null;
|
|
60
|
+
})
|
|
61
|
+
.filter((t) => !!t);
|
|
62
|
+
}
|
|
63
|
+
teammateById(id) {
|
|
64
|
+
var _a;
|
|
65
|
+
const teammate = (_a = this.team) === null || _a === void 0 ? void 0 : _a.find((t) => t.id === id);
|
|
66
|
+
if (!teammate) {
|
|
67
|
+
throw new SpruceError({
|
|
68
|
+
code: 'PERSON_NOT_FOUND',
|
|
69
|
+
personId: id,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return teammate;
|
|
73
|
+
}
|
|
74
|
+
getTeam() {
|
|
75
|
+
return this.team;
|
|
76
|
+
}
|
|
77
|
+
getLoggedInPerson() {
|
|
78
|
+
return this.loggedInPerson;
|
|
79
|
+
}
|
|
80
|
+
getVisiblePeopleIds() {
|
|
81
|
+
var _a;
|
|
82
|
+
if (this.getVisibilityMode() === 'working') {
|
|
83
|
+
return this.getWorkingPeopleIds();
|
|
84
|
+
}
|
|
85
|
+
return (_a = this.getSavedVisiblePeopleIds()) !== null && _a !== void 0 ? _a : [];
|
|
86
|
+
}
|
|
87
|
+
getSavedVisiblePeopleIds() {
|
|
88
|
+
return this.prefs.getVisiblePeopleIds();
|
|
89
|
+
}
|
|
90
|
+
getVisibilityMode() {
|
|
91
|
+
var _a;
|
|
92
|
+
return (_a = this.prefs.getVisiblePeopleMode()) !== null && _a !== void 0 ? _a : 'me';
|
|
93
|
+
}
|
|
94
|
+
setVisibilityMode(mode) {
|
|
95
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
if (this.getVisibilityMode() === mode) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
yield this.prefs.setVisiblePeopleMode(mode);
|
|
100
|
+
if (mode === 'me' && this.loggedInPerson) {
|
|
101
|
+
yield this.setVisibilityToMe();
|
|
102
|
+
}
|
|
103
|
+
else if (mode === 'working') {
|
|
104
|
+
yield this.setVisibleToWorking();
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
setVisibilityToMe() {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
if (this.loggedInPerson) {
|
|
111
|
+
yield this.setVisiblePeopleIds([this.loggedInPerson.id], {
|
|
112
|
+
shouldForceEmitDidChange: true,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
setVisibleToWorking() {
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
const ids = this.getWorkingPeopleIds();
|
|
120
|
+
yield this.setVisiblePeopleIds(ids);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
getWorkingPeopleIds() {
|
|
124
|
+
return this.getWorkingPeople().map((i) => i.id);
|
|
125
|
+
}
|
|
126
|
+
getWorkingPeople() {
|
|
127
|
+
const events = this.getVisibleEvents();
|
|
128
|
+
let ids = events.map((e) => e.target.personId);
|
|
129
|
+
ids = ids.filter((id, idx) => ids.indexOf(id) === idx);
|
|
130
|
+
return ids
|
|
131
|
+
.map((id) => {
|
|
132
|
+
try {
|
|
133
|
+
return this.teammateById(id);
|
|
134
|
+
// eslint-disable-next-line no-empty
|
|
135
|
+
}
|
|
136
|
+
catch (_a) { }
|
|
137
|
+
return false;
|
|
138
|
+
})
|
|
139
|
+
.filter((p) => !!p);
|
|
140
|
+
}
|
|
141
|
+
setVisiblePeopleIds(visible, options) {
|
|
142
|
+
var _a;
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
const { shouldForceEmitDidChange } = options !== null && options !== void 0 ? options : {};
|
|
145
|
+
const newVisibile = visible.filter((id, idx) => visible.indexOf(id) === idx);
|
|
146
|
+
const oldVisible = (_a = this.getSavedVisiblePeopleIds()) !== null && _a !== void 0 ? _a : [];
|
|
147
|
+
const newKey = newVisibile.join('');
|
|
148
|
+
const oldKey = oldVisible.join('');
|
|
149
|
+
const didChange = newKey !== oldKey;
|
|
150
|
+
if (didChange) {
|
|
151
|
+
yield this.prefs.setVisiblePeopleIds(newVisibile);
|
|
152
|
+
}
|
|
153
|
+
if (didChange || shouldForceEmitDidChange) {
|
|
154
|
+
yield this.emitDidUpdate();
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
setPersonVisibility(id, shouldBeVisible) {
|
|
159
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
160
|
+
const person = this.teammateById(id);
|
|
161
|
+
let selected = [...this.getVisiblePeopleIds()];
|
|
162
|
+
if (shouldBeVisible) {
|
|
163
|
+
selected.push(person.id);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
selected = selected.filter((i) => i !== id);
|
|
167
|
+
}
|
|
168
|
+
yield this.setVisibilityMode('custom');
|
|
169
|
+
yield this.setVisiblePeopleIds(selected);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
emitDidUpdate() {
|
|
173
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
yield this.emit('did-update');
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const peopleContract = buildEventContract({
|
|
179
|
+
eventSignatures: {
|
|
180
|
+
'did-update': {},
|
|
181
|
+
},
|
|
182
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SpruceSchemas } from '@sprucelabs/heartwood-view-controllers';
|
|
2
|
+
export declare type CalendarShift = SpruceSchemas.HeartwoodViewControllers.v2021_02_11.CalendarShift;
|
|
3
|
+
import { EventForShift } from '../types/calendar.types';
|
|
4
|
+
declare const calendarShiftGenerator: {
|
|
5
|
+
generateFromEvent(event: EventForShift): CalendarShift[];
|
|
6
|
+
generateFromEvents(events: EventForShift[]): CalendarShift[];
|
|
7
|
+
};
|
|
8
|
+
export default calendarShiftGenerator;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const calendarShiftGenerator = {
|
|
2
|
+
generateFromEvent(event) {
|
|
3
|
+
let time = event.startDateTimeMs;
|
|
4
|
+
return event.timeBlocks.map((timeBlock, idx) => {
|
|
5
|
+
const end = time + timeBlock.durationMinutes * 60 * 1000;
|
|
6
|
+
const shift = {
|
|
7
|
+
id: event.id + '-' + idx,
|
|
8
|
+
startDateTimeMs: time,
|
|
9
|
+
endDateTimeMs: end,
|
|
10
|
+
personId: event.target.personId,
|
|
11
|
+
};
|
|
12
|
+
time = end;
|
|
13
|
+
return shift;
|
|
14
|
+
});
|
|
15
|
+
},
|
|
16
|
+
generateFromEvents(events) {
|
|
17
|
+
const shifts = events.reduce((shifts, event) => {
|
|
18
|
+
shifts.push(...this.generateFromEvent(event));
|
|
19
|
+
return shifts;
|
|
20
|
+
}, []);
|
|
21
|
+
return shifts;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
export default calendarShiftGenerator;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AbstractViewController, ActiveRecordCardViewController, Scope, SpruceSchemas, ViewControllerOptions } from '@sprucelabs/heartwood-view-controllers';
|
|
2
|
+
import { CalendarEventManager } from '../utilities/CalendarEventManager';
|
|
3
|
+
export default class CalendarSelectCardViewController extends AbstractViewController<Card> {
|
|
4
|
+
static id: string;
|
|
5
|
+
private isLoaded;
|
|
6
|
+
private activeVc;
|
|
7
|
+
private events;
|
|
8
|
+
private selectedCalendarIds;
|
|
9
|
+
private changePromise?;
|
|
10
|
+
constructor(options: ViewControllerOptions & CalendarSelectCardOptions);
|
|
11
|
+
private CalendarListVc;
|
|
12
|
+
private renderCalendarRow;
|
|
13
|
+
waitForChanges(): Promise<void>;
|
|
14
|
+
getActiveRecordCardVc(): ActiveRecordCardViewController;
|
|
15
|
+
getListVc(): import("@sprucelabs/heartwood-view-controllers").ListViewController;
|
|
16
|
+
getIsLoaded(): boolean;
|
|
17
|
+
getSelectedCalendarIds(): string[];
|
|
18
|
+
load(options: {
|
|
19
|
+
scope: Scope;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
render(): SpruceSchemas.HeartwoodViewControllers.v2021_02_11.Card;
|
|
22
|
+
}
|
|
23
|
+
declare type Card = SpruceSchemas.HeartwoodViewControllers.v2021_02_11.Card;
|
|
24
|
+
export declare type CalendarVisibilityToggleHandler = (calendarId: string, isVisible: boolean) => any;
|
|
25
|
+
export interface CalendarSelectCardOptions {
|
|
26
|
+
events: CalendarEventManager;
|
|
27
|
+
}
|
|
28
|
+
export {};
|