@blazeo.com/appointment-client 1.0.5 → 1.0.6
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/blazeo.com-appointment-client-1.0.6.tgz +0 -0
- package/dist/calendar/blazeoCalendarRelationMethods.d.ts +4 -36
- package/dist/calendar/blazeoCalendarRelationMethods.js +0 -1
- package/dist/calendar/buildUnifiedCalendarView.d.ts +31 -0
- package/dist/calendar/buildUnifiedCalendarView.js +265 -0
- package/dist/calendar/calendarCreation.d.ts +27 -0
- package/dist/calendar/calendarCreation.js +167 -0
- package/dist/calendar/calendarCreationFacade.d.ts +4 -13
- package/dist/calendar/calendarCreationFacade.js +3 -5
- package/dist/calendar/createCalendar.d.ts +67 -37
- package/dist/calendar/createCalendar.js +1 -3
- package/dist/calendar/fetchCalendarDetails.d.ts +73 -18
- package/dist/calendar/fetchCalendarDetails.js +192 -51
- package/dist/calendar/fetchCalendarWithOpeningHours.d.ts +34 -21
- package/dist/calendar/fetchCalendarWithOpeningHours.js +95 -75
- package/dist/calendar/getAllParticipantOpeningHours.d.ts +19 -0
- package/dist/calendar/getAllParticipantOpeningHours.js +17 -0
- package/dist/calendar/getOpeningHours.d.ts +5 -0
- package/dist/calendar/getOpeningHours.js +9 -0
- package/dist/calendar/getParticipantOpeningHours.d.ts +37 -0
- package/dist/calendar/getParticipantOpeningHours.js +43 -0
- package/dist/calendar/getParticipants.d.ts +4 -0
- package/dist/calendar/getParticipants.js +8 -0
- package/dist/calendar/mapCalendarBoToBlazeoSnapshot.d.ts +9 -9
- package/dist/calendar/mapCalendarBoToBlazeoSnapshot.js +43 -43
- package/dist/calendar/mapCalendarToBlazeoSnapshot.d.ts +22 -3
- package/dist/calendar/mapCalendarToBlazeoSnapshot.js +0 -1
- package/dist/config/applyBlazeoClientConfig.d.ts +2 -2
- package/dist/config/applyBlazeoClientConfig.js +13 -13
- package/dist/config/applyBlazeoDefaults.d.ts +0 -1
- package/dist/config/applyBlazeoDefaults.js +0 -1
- package/dist/config/blazeo.config.d.ts +10 -10
- package/dist/config/blazeo.config.js +10 -10
- package/dist/config/blazeoClientDefaults.d.ts +1 -2
- package/dist/config/blazeoClientDefaults.js +0 -1
- package/dist/config/initializeAppointmentClient.d.ts +4 -28
- package/dist/config/initializeAppointmentClient.js +5 -24
- package/dist/events/appointmentEventFacade.d.ts +55 -32
- package/dist/events/appointmentEventFacade.js +5 -10
- package/dist/events/mapAppointmentToEventSnapshot.d.ts +1 -4
- package/dist/events/mapAppointmentToEventSnapshot.js +0 -1
- package/dist/exampleData.d.ts +114 -10
- package/dist/exampleData.js +4 -5
- package/dist/facade/calendarCreationFacade.d.ts +39 -39
- package/dist/facade/calendarCreationFacade.js +95 -95
- package/dist/facade/mapCalendarBOToSnapshot.d.ts +9 -9
- package/dist/facade/mapCalendarBOToSnapshot.js +43 -43
- package/dist/facades/index.d.ts +11 -11
- package/dist/facades/index.js +11 -11
- package/dist/index.d.ts +23 -82
- package/dist/index.js +21 -33
- package/dist/models/CalendarRootModel.d.ts +36 -11
- package/dist/models/CalendarRootModel.js +22 -5
- package/dist/models/CalendarSlotModel.d.ts +8 -8
- package/dist/models/CalendarSlotModel.js +7 -7
- package/dist/models/EventModel.d.ts +10 -10
- package/dist/models/EventModel.js +9 -9
- package/dist/models/ParticipantModel.d.ts +8 -8
- package/dist/models/ParticipantModel.js +7 -7
- package/dist/models/index.d.ts +4 -4
- package/dist/models/index.js +4 -4
- package/dist/types/appointment.d.ts +27 -27
- package/dist/types/appointment.js +5 -5
- package/dist/types/calendar.d.ts +51 -51
- package/dist/types/calendar.js +5 -5
- package/dist/types/calendarBo.d.ts +61 -61
- package/dist/types/calendarBo.js +5 -5
- package/package.json +8 -2
- package/sample/build_error.txt +0 -0
- package/sample/demo.js +70 -0
- package/sample/package-lock.json +5 -2
- package/sample/package.json +3 -1
- package/sample/scripts/getInfoByCalendar.mjs +36 -0
- package/sample/scripts/getParticipantOpeningHours.mjs +48 -0
- package/sample/src/AllParticipantOpeningHoursTab.jsx +73 -0
- package/sample/src/App2.jsx +39 -2
- package/sample/src/BlazeoConnectionSettings.jsx +1 -1
- package/sample/src/FetchCalendarTab.jsx +70 -20
- package/sample/src/OpeningHoursTab.jsx +78 -0
- package/sample/src/ParticipantInfoTab.jsx +72 -0
- package/sample/src/ParticipantOpeningHoursTab.jsx +88 -0
- package/sample/src/ParticipantTab.jsx +2 -2
- package/src/calendar/blazeoCalendarRelationMethods.ts +19 -0
- package/src/calendar/buildUnifiedCalendarView.ts +322 -0
- package/src/calendar/calendarCreation.ts +179 -0
- package/src/calendar/createCalendar.ts +243 -0
- package/src/calendar/fetchCalendarDetails.ts +226 -0
- package/src/calendar/fetchCalendarWithOpeningHours.ts +99 -0
- package/src/calendar/getAllParticipantOpeningHours.ts +22 -0
- package/src/calendar/getOpeningHours.ts +10 -0
- package/src/calendar/getParticipantOpeningHours.ts +46 -0
- package/src/calendar/getParticipants.ts +9 -0
- package/src/calendar/mapCalendarToBlazeoSnapshot.ts +46 -0
- package/src/config/applyBlazeoDefaults.ts +13 -0
- package/src/config/blazeoClientDefaults.ts +11 -0
- package/src/config/initializeAppointmentClient.ts +18 -0
- package/src/events/appointmentEventFacade.ts +148 -0
- package/src/events/mapAppointmentToEventSnapshot.ts +65 -0
- package/src/exampleData.ts +79 -0
- package/src/index.ts +45 -0
- package/src/models/CalendarRootModel.ts +60 -0
- package/tsconfig.json +16 -0
- package/blazeo.com-appointment-client-1.0.5.tgz +0 -0
|
Binary file
|
|
@@ -1,40 +1,8 @@
|
|
|
1
|
-
import type { IStateTreeNode } from "mobx-state-tree";
|
|
2
|
-
/**
|
|
3
|
-
* Participant & opening-hour **save** APIs on a Blazeo `Calendar` MST node
|
|
4
|
-
* (`CalendarModel.create` from `@blazeo.com/calendar-client`).
|
|
5
|
-
*
|
|
6
|
-
* Source: `node_modules/@blazeo.com/calendar-client/dist/index.mjs` (Calendar model actions).
|
|
7
|
-
*
|
|
8
|
-
* | Instance method | Route | Notes |
|
|
9
|
-
* |-----------------|-------|--------|
|
|
10
|
-
* | `addParticipant(participantId)` | `GET /Calendar/Participant/Add` | Query: `calendar_id`, `participant_id` |
|
|
11
|
-
* | `removeParticipant(participantId)` | `GET /Calendar/Participant/Remove` | Remove participant from calendar |
|
|
12
|
-
* | `saveOpeningHour(payload)` | `POST /Calendar/Participant/Availability/OpeningHour/Save` | Single opening-hour row |
|
|
13
|
-
* | `saveOpeningHours(payload)` | `POST /Calendar/Participant/Availability/OpeningHours/Save` | Batch variant (same family) |
|
|
14
|
-
* | `getParticipantOpeningHours(params?)` | `GET /Calendar/Participant/OpeningHours/Get` | Read |
|
|
15
|
-
* | `removeParticipantOpeningHours(participantId)` | `GET /Calendar/Participant/OpeningHour/Remove` | Clear hours for participant |
|
|
16
|
-
*
|
|
17
|
-
* Alternative **static** helpers on `CalendarModel` (different flow): `createWithParticipants`,
|
|
18
|
-
* `editWithParticipants` — not used by `appointment-client` relation facade (we use create + `addParticipant`).
|
|
19
|
-
*/
|
|
20
|
-
export type BlazeoCalendarRelationResponse = {
|
|
21
|
-
status: string;
|
|
22
|
-
message?: string;
|
|
23
|
-
data?: unknown;
|
|
24
|
-
};
|
|
25
|
-
export type BlazeoCalendarForRelations = IStateTreeNode & {
|
|
26
|
-
readonly calendarId?: string;
|
|
27
|
-
addParticipant(participantId: string): Promise<BlazeoCalendarRelationResponse>;
|
|
28
|
-
removeParticipant(participantId: string): Promise<BlazeoCalendarRelationResponse>;
|
|
29
|
-
saveOpeningHour(payload: Record<string, unknown>): Promise<BlazeoCalendarRelationResponse>;
|
|
30
|
-
saveOpeningHours(payload: Record<string, unknown> | unknown[]): Promise<BlazeoCalendarRelationResponse>;
|
|
31
|
-
};
|
|
32
1
|
/** `GET /Calendar/Participant/Add` — attach `participantId` to this calendar. */
|
|
33
|
-
export declare function addParticipantToCalendar(calendar:
|
|
2
|
+
export declare function addParticipantToCalendar(calendar: any, participantId: string): any;
|
|
34
3
|
/** `GET /Calendar/Participant/Remove` */
|
|
35
|
-
export declare function removeParticipantFromCalendar(calendar:
|
|
4
|
+
export declare function removeParticipantFromCalendar(calendar: any, participantId: string): any;
|
|
36
5
|
/** `POST /Calendar/Participant/Availability/OpeningHour/Save` — one day/slot. */
|
|
37
|
-
export declare function saveCalendarOpeningHour(calendar:
|
|
6
|
+
export declare function saveCalendarOpeningHour(calendar: any, payload: any): any;
|
|
38
7
|
/** `POST /Calendar/Participant/Availability/OpeningHours/Save` — batch body (API-specific shape). */
|
|
39
|
-
export declare function saveCalendarOpeningHoursBatch(calendar:
|
|
40
|
-
//# sourceMappingURL=blazeoCalendarRelationMethods.d.ts.map
|
|
8
|
+
export declare function saveCalendarOpeningHoursBatch(calendar: any, payload: any): any;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface UnifiedCalendarMember {
|
|
2
|
+
id: number | string;
|
|
3
|
+
name: string;
|
|
4
|
+
email: string | null;
|
|
5
|
+
/** When API exposes status; otherwise derived from participant info flags. */
|
|
6
|
+
status: number | null;
|
|
7
|
+
/** Full row from Participants/GetInfo (plain object). */
|
|
8
|
+
participantInfo?: Record<string, unknown> | null;
|
|
9
|
+
}
|
|
10
|
+
export interface UnifiedParticipantWithHours extends UnifiedCalendarMember {
|
|
11
|
+
openingHours: UnifiedOpeningHourRow[];
|
|
12
|
+
}
|
|
13
|
+
export interface UnifiedOpeningHourRow {
|
|
14
|
+
member: number | string;
|
|
15
|
+
days: string[];
|
|
16
|
+
startHour: number;
|
|
17
|
+
startMinute: number;
|
|
18
|
+
endHour: number;
|
|
19
|
+
endMinute: number;
|
|
20
|
+
off: boolean;
|
|
21
|
+
}
|
|
22
|
+
export type UnifiedCalendarView = Record<string, unknown> & {
|
|
23
|
+
members: UnifiedCalendarMember[];
|
|
24
|
+
openingHours: UnifiedOpeningHourRow[];
|
|
25
|
+
participants?: UnifiedParticipantWithHours[];
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Build a consumer-friendly `{ id, name, members, openingHours }` shape where
|
|
29
|
+
* `openingHours[].member` references `members[].id`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildUnifiedCalendarView(calendarSnapshot: Record<string, any> | null, openingHoursRows: any[], participants: any[] | null | undefined, participantsInfo: any[] | null | undefined): UnifiedCalendarView | null;
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { getSnapshot, isStateTreeNode } from "mobx-state-tree";
|
|
2
|
+
const DAY_NAMES = ["SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"];
|
|
3
|
+
function pick(row, ...keys) {
|
|
4
|
+
if (row == null || typeof row !== "object")
|
|
5
|
+
return undefined;
|
|
6
|
+
for (const k of keys) {
|
|
7
|
+
if (row[k] !== undefined && row[k] !== null)
|
|
8
|
+
return row[k];
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
function toPlain(value) {
|
|
13
|
+
if (value == null)
|
|
14
|
+
return value;
|
|
15
|
+
if (isStateTreeNode(value))
|
|
16
|
+
return getSnapshot(value);
|
|
17
|
+
if (Array.isArray(value))
|
|
18
|
+
return value.map((x) => toPlain(x));
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function normParticipantKey(v) {
|
|
22
|
+
if (v == null)
|
|
23
|
+
return "";
|
|
24
|
+
return String(v).trim().toLowerCase();
|
|
25
|
+
}
|
|
26
|
+
function coerceMemberId(v) {
|
|
27
|
+
if (v == null || v === "")
|
|
28
|
+
return null;
|
|
29
|
+
if (typeof v === "number" && !Number.isNaN(v))
|
|
30
|
+
return v;
|
|
31
|
+
if (typeof v === "string") {
|
|
32
|
+
const t = v.trim();
|
|
33
|
+
if (/^\d+$/.test(t))
|
|
34
|
+
return Number(t);
|
|
35
|
+
return t;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Canonical member id used in both `members[].id` and `openingHours[].member`.
|
|
41
|
+
*/
|
|
42
|
+
function resolveParticipantMemberId(calPart) {
|
|
43
|
+
const n = pick(calPart, "id", "Id");
|
|
44
|
+
if (n != null && typeof n === "number" && !Number.isNaN(n))
|
|
45
|
+
return n;
|
|
46
|
+
const sid = pick(calPart, "participantId", "ParticipantId", "participant_id");
|
|
47
|
+
if (sid != null && String(sid).trim() !== "") {
|
|
48
|
+
const t = String(sid).trim();
|
|
49
|
+
if (/^\d+$/.test(t))
|
|
50
|
+
return Number(t);
|
|
51
|
+
return t;
|
|
52
|
+
}
|
|
53
|
+
return "";
|
|
54
|
+
}
|
|
55
|
+
function dayOrderIndex(d) {
|
|
56
|
+
const u = d.toUpperCase();
|
|
57
|
+
const i = DAY_NAMES.indexOf(u);
|
|
58
|
+
return i >= 0 ? i : 999;
|
|
59
|
+
}
|
|
60
|
+
/** Merge rows that share participant + time span + off into one row with combined `days`. */
|
|
61
|
+
function mergeOpeningHoursBySlot(rows) {
|
|
62
|
+
const map = new Map();
|
|
63
|
+
for (const r of rows) {
|
|
64
|
+
const key = [r.member, r.startHour, r.startMinute, r.endHour, r.endMinute, r.off].join("|");
|
|
65
|
+
const existing = map.get(key);
|
|
66
|
+
if (!existing) {
|
|
67
|
+
map.set(key, { ...r, days: [...r.days] });
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const set = new Set([...existing.days, ...r.days]);
|
|
71
|
+
existing.days = Array.from(set).sort((a, b) => dayOrderIndex(a) - dayOrderIndex(b));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
rows.length = 0;
|
|
75
|
+
rows.push(...map.values());
|
|
76
|
+
}
|
|
77
|
+
function normalizeDaysFromRow(row) {
|
|
78
|
+
const rawDays = pick(row, "days", "Days");
|
|
79
|
+
if (Array.isArray(rawDays)) {
|
|
80
|
+
return rawDays.map((d) => String(d).trim().toUpperCase()).filter(Boolean);
|
|
81
|
+
}
|
|
82
|
+
const dayNum = pick(row, "day", "Day");
|
|
83
|
+
if (dayNum != null && typeof dayNum === "number" && dayNum >= 0 && dayNum <= 6) {
|
|
84
|
+
return [DAY_NAMES[dayNum]];
|
|
85
|
+
}
|
|
86
|
+
const dayStr = pick(row, "dayName", "DayName", "dayOfWeek", "DayOfWeek");
|
|
87
|
+
if (dayStr != null && String(dayStr).trim() !== "") {
|
|
88
|
+
return [String(dayStr).trim().toUpperCase()];
|
|
89
|
+
}
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
function resolveOpeningHourMemberId(row, byParticipantKey, byCalendarParticipantKey) {
|
|
93
|
+
const calPartHook = pick(row, "calendarParticipantId", "CalendarParticipantId", "calendarparticipant_id");
|
|
94
|
+
if (calPartHook != null && String(calPartHook).trim() !== "") {
|
|
95
|
+
const ck = normParticipantKey(String(calPartHook));
|
|
96
|
+
if (byCalendarParticipantKey.has(ck))
|
|
97
|
+
return byCalendarParticipantKey.get(ck);
|
|
98
|
+
}
|
|
99
|
+
const pid = pick(row, "participantId", "ParticipantId", "participant_id");
|
|
100
|
+
if (pid != null && String(pid).trim() !== "") {
|
|
101
|
+
const k = normParticipantKey(String(pid));
|
|
102
|
+
if (byParticipantKey.has(k))
|
|
103
|
+
return byParticipantKey.get(k);
|
|
104
|
+
return coerceMemberId(pid);
|
|
105
|
+
}
|
|
106
|
+
const member = pick(row, "member", "Member");
|
|
107
|
+
if (member != null && typeof member === "object") {
|
|
108
|
+
const mid = coerceMemberId(pick(member, "id", "Id")) ??
|
|
109
|
+
coerceMemberId(pick(member, "participantId", "ParticipantId", "participant_id"));
|
|
110
|
+
if (mid != null)
|
|
111
|
+
return mid;
|
|
112
|
+
}
|
|
113
|
+
if (member != null && (typeof member === "number" || typeof member === "string")) {
|
|
114
|
+
const m = coerceMemberId(member);
|
|
115
|
+
if (m != null) {
|
|
116
|
+
const k = normParticipantKey(m);
|
|
117
|
+
if (byParticipantKey.has(k))
|
|
118
|
+
return byParticipantKey.get(k);
|
|
119
|
+
}
|
|
120
|
+
return m;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
function deriveMemberStatus(calPart, info) {
|
|
125
|
+
const direct = pick(calPart, "status", "Status") ?? pick(info ?? {}, "status", "Status");
|
|
126
|
+
if (direct != null && typeof direct === "number" && !Number.isNaN(direct))
|
|
127
|
+
return direct;
|
|
128
|
+
const approved = Boolean(pick(calPart, "isApproved", "IsApproved", "is_approved")) ||
|
|
129
|
+
Boolean(pick(info ?? {}, "isApproved", "IsApproved", "is_approved"));
|
|
130
|
+
if (approved)
|
|
131
|
+
return approved ? 1 : 0;
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Build a consumer-friendly `{ id, name, members, openingHours }` shape where
|
|
136
|
+
* `openingHours[].member` references `members[].id`.
|
|
137
|
+
*/
|
|
138
|
+
export function buildUnifiedCalendarView(calendarSnapshot, openingHoursRows, participants, participantsInfo) {
|
|
139
|
+
if (calendarSnapshot == null || typeof calendarSnapshot !== "object")
|
|
140
|
+
return null;
|
|
141
|
+
const calSnap = toPlain(calendarSnapshot);
|
|
142
|
+
const partsPlain = participants != null ? participants.map((p) => toPlain(p)) : [];
|
|
143
|
+
const infoPlain = participantsInfo != null ? participantsInfo.map((p) => toPlain(p)) : [];
|
|
144
|
+
const infoByPid = new Map();
|
|
145
|
+
for (const inf of infoPlain) {
|
|
146
|
+
const pid = inf?.participantId ?? inf?.ParticipantId ?? inf?.participant_id;
|
|
147
|
+
if (pid != null && String(pid).trim() !== "") {
|
|
148
|
+
infoByPid.set(normParticipantKey(String(pid)), inf);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const byParticipantKey = new Map();
|
|
152
|
+
const byCalendarParticipantKey = new Map();
|
|
153
|
+
const members = [];
|
|
154
|
+
if (partsPlain.length > 0) {
|
|
155
|
+
for (const cp of partsPlain) {
|
|
156
|
+
const memberId = resolveParticipantMemberId(cp);
|
|
157
|
+
const pidStr = pick(cp, "participantId", "ParticipantId", "participant_id") ?? "";
|
|
158
|
+
if (memberId === "" && (!pidStr || pidStr.trim() === ""))
|
|
159
|
+
continue;
|
|
160
|
+
const ik = normParticipantKey(pidStr || String(memberId));
|
|
161
|
+
const inf = ik ? infoByPid.get(ik) : undefined;
|
|
162
|
+
const participantInfoPlain = inf != null ? { ...toPlain(inf) } : null;
|
|
163
|
+
const alias = inf?.alias ?? inf?.Alias;
|
|
164
|
+
const name = typeof alias === "string" && alias.trim() !== ""
|
|
165
|
+
? alias.trim()
|
|
166
|
+
: pidStr && pidStr.trim() !== ""
|
|
167
|
+
? pidStr.trim()
|
|
168
|
+
: String(memberId);
|
|
169
|
+
const email = (inf?.email ?? inf?.Email ?? null);
|
|
170
|
+
const id = memberId === "" ? coerceMemberId(pidStr) ?? pidStr : memberId;
|
|
171
|
+
const calPartPk = pick(cp, "calendarParticipantId", "CalendarParticipantId", "calendarparticipant_id");
|
|
172
|
+
const calPartKey = calPartPk != null ? normParticipantKey(String(calPartPk)) : "";
|
|
173
|
+
if (calPartKey)
|
|
174
|
+
byCalendarParticipantKey.set(calPartKey, id);
|
|
175
|
+
const keyParticipant = ik || normParticipantKey(String(id));
|
|
176
|
+
if (keyParticipant) {
|
|
177
|
+
byParticipantKey.set(keyParticipant, id);
|
|
178
|
+
byParticipantKey.set(normParticipantKey(String(id)), id);
|
|
179
|
+
}
|
|
180
|
+
members.push({
|
|
181
|
+
id,
|
|
182
|
+
name,
|
|
183
|
+
email: email ?? null,
|
|
184
|
+
status: deriveMemberStatus(cp, inf),
|
|
185
|
+
participantInfo: participantInfoPlain,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else if (infoPlain.length > 0) {
|
|
190
|
+
for (const inf of infoPlain) {
|
|
191
|
+
const pid = inf?.participantId ?? inf?.ParticipantId ?? inf?.participant_id;
|
|
192
|
+
if (pid == null || String(pid).trim() === "")
|
|
193
|
+
continue;
|
|
194
|
+
const id = coerceMemberId(pid) ?? String(pid).trim();
|
|
195
|
+
const ik = normParticipantKey(String(pid));
|
|
196
|
+
const participantInfoPlain = { ...toPlain(inf) };
|
|
197
|
+
if (ik)
|
|
198
|
+
byParticipantKey.set(ik, id);
|
|
199
|
+
byParticipantKey.set(normParticipantKey(id), id);
|
|
200
|
+
const alias = inf.alias ?? inf.Alias ?? "";
|
|
201
|
+
const name = typeof alias === "string" && alias.trim() !== "" ? alias.trim() : String(pid);
|
|
202
|
+
const email = (inf.email ?? inf.Email ?? null);
|
|
203
|
+
members.push({
|
|
204
|
+
id,
|
|
205
|
+
name,
|
|
206
|
+
email: email ?? null,
|
|
207
|
+
status: deriveMemberStatus({}, inf),
|
|
208
|
+
participantInfo: participantInfoPlain,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const rawRows = Array.isArray(openingHoursRows) ? openingHoursRows : [];
|
|
213
|
+
const openingHours = [];
|
|
214
|
+
for (const raw of rawRows) {
|
|
215
|
+
const row = toPlain(raw);
|
|
216
|
+
let memberId = resolveOpeningHourMemberId(row, byParticipantKey, byCalendarParticipantKey);
|
|
217
|
+
if (memberId == null) {
|
|
218
|
+
const m = pick(row, "member", "Member");
|
|
219
|
+
memberId = typeof m === "number" || typeof m === "string" ? coerceMemberId(m) : null;
|
|
220
|
+
}
|
|
221
|
+
if (memberId == null)
|
|
222
|
+
continue;
|
|
223
|
+
const days = normalizeDaysFromRow(row);
|
|
224
|
+
const startHour = Number(pick(row, "startHour", "StartHour", "start_hour") ?? 0) || 0;
|
|
225
|
+
const startMinute = Number(pick(row, "startMinute", "StartMinute", "start_minute") ?? 0) || 0;
|
|
226
|
+
const endHour = Number(pick(row, "endHour", "EndHour", "end_hour") ?? 0) || 0;
|
|
227
|
+
const endMinute = Number(pick(row, "endMinute", "EndMinute", "end_minute") ?? 0) || 0;
|
|
228
|
+
const off = Boolean(pick(row, "off", "Off"));
|
|
229
|
+
openingHours.push({
|
|
230
|
+
member: memberId,
|
|
231
|
+
days,
|
|
232
|
+
startHour,
|
|
233
|
+
startMinute,
|
|
234
|
+
endHour,
|
|
235
|
+
endMinute,
|
|
236
|
+
off,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
mergeOpeningHoursBySlot(openingHours);
|
|
240
|
+
const view = {
|
|
241
|
+
...calSnap,
|
|
242
|
+
members,
|
|
243
|
+
openingHours,
|
|
244
|
+
participants: buildNestedParticipants(members, openingHours),
|
|
245
|
+
};
|
|
246
|
+
return view;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Groups opening hours into their respective participant objects.
|
|
250
|
+
*/
|
|
251
|
+
function buildNestedParticipants(members, openingHours) {
|
|
252
|
+
return members.map((m) => {
|
|
253
|
+
const hours = openingHours.filter((oh) => {
|
|
254
|
+
const mid = String(oh.member).trim().toLowerCase();
|
|
255
|
+
const pid = String(m.id).trim().toLowerCase();
|
|
256
|
+
return mid === pid;
|
|
257
|
+
});
|
|
258
|
+
// Remove the 'member' field from the nested opening hours as it's redundant.
|
|
259
|
+
const nestedHours = hours.map(({ member, ...rest }) => rest);
|
|
260
|
+
return {
|
|
261
|
+
...m,
|
|
262
|
+
openingHours: nestedHours,
|
|
263
|
+
};
|
|
264
|
+
});
|
|
265
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { deleteCalendarAsync } from "./createCalendar.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves Blazeo `participantId` for an opening-hour row: explicit `participantId`,
|
|
4
|
+
* matching `CalendarCreation.SaveOpeningHours`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveParticipantIdForOpeningHour(openingHour: any): string | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Orchestrates the same steps as Apex `CalendarCreation.CreateCalendarAsync`:
|
|
9
|
+
* save calendar (`POST /Calendar/Create`), then add participants, then save opening hours
|
|
10
|
+
* per day (`POST /Calendar/Participant/Availability/OpeningHour/Save`).
|
|
11
|
+
*/
|
|
12
|
+
export declare function createCalendarWithRelationsAsync(calendar: any, options?: any): Promise<any>;
|
|
13
|
+
/**
|
|
14
|
+
* Calendar body update, then same member + opening-hour saves as create (Apex-style follow-up).
|
|
15
|
+
* For member add/remove *diffs* against existing DB membership, use server-side Apex; this client
|
|
16
|
+
* only performs additive Blazeo calls matching the payload.
|
|
17
|
+
*/
|
|
18
|
+
export declare function updateCalendarWithRelationsAsync(calendar: any, options?: any): Promise<any>;
|
|
19
|
+
/**
|
|
20
|
+
* Aligned with `CalendarCreation`: create/update with members & opening hours,
|
|
21
|
+
* or delete calendar only.
|
|
22
|
+
*/
|
|
23
|
+
export declare class CalendarCreation {
|
|
24
|
+
static createWithRelationsAsync: typeof createCalendarWithRelationsAsync;
|
|
25
|
+
static updateWithRelationsAsync: typeof updateCalendarWithRelationsAsync;
|
|
26
|
+
static deleteCalendarAsync: typeof deleteCalendarAsync;
|
|
27
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { getSnapshot } from "mobx-state-tree";
|
|
2
|
+
import { addParticipantToCalendar, saveCalendarOpeningHour } from "./blazeoCalendarRelationMethods.js";
|
|
3
|
+
import { createCalendarAsync, updateCalendarAsync, deleteCalendarAsync } from "./createCalendar.js";
|
|
4
|
+
function isFailureStatus(res) {
|
|
5
|
+
return res.status !== "success" && res.status !== "Success";
|
|
6
|
+
}
|
|
7
|
+
function normalizeParticipantGuid(id) {
|
|
8
|
+
if (id == null || !String(id).trim())
|
|
9
|
+
return undefined;
|
|
10
|
+
return String(id).trim().replace(/^\{|\}$/g, "");
|
|
11
|
+
}
|
|
12
|
+
function newOpeningHourId() {
|
|
13
|
+
const c = globalThis.crypto;
|
|
14
|
+
if (c?.randomUUID)
|
|
15
|
+
return c.randomUUID();
|
|
16
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolves Blazeo `participantId` for an opening-hour row: explicit `participantId`,
|
|
20
|
+
* matching `CalendarCreation.SaveOpeningHours`.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveParticipantIdForOpeningHour(openingHour) {
|
|
23
|
+
const direct = normalizeParticipantGuid(openingHour.participantId);
|
|
24
|
+
if (direct)
|
|
25
|
+
return direct;
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
function effectiveCalendarId(calendarNode, input) {
|
|
29
|
+
const snap = getSnapshot(calendarNode);
|
|
30
|
+
const fromNode = snap.calendarId?.trim();
|
|
31
|
+
if (fromNode && fromNode !== "new")
|
|
32
|
+
return fromNode;
|
|
33
|
+
return (input.calendarId?.trim() || undefined);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Orchestrates the same steps as Apex `CalendarCreation.CreateCalendarAsync`:
|
|
37
|
+
* save calendar (`POST /Calendar/Create`), then add participants, then save opening hours
|
|
38
|
+
* per day (`POST /Calendar/Participant/Availability/OpeningHour/Save`).
|
|
39
|
+
*/
|
|
40
|
+
export async function createCalendarWithRelationsAsync(calendar, options = {}) {
|
|
41
|
+
const hasMembers = (calendar.members?.length ?? 0) > 0;
|
|
42
|
+
const hasHours = (calendar.openingHours?.length ?? 0) > 0;
|
|
43
|
+
if (!hasMembers && !hasHours) {
|
|
44
|
+
const r = await createCalendarAsync(calendar, options);
|
|
45
|
+
if (!r.ok)
|
|
46
|
+
return r;
|
|
47
|
+
return { ...r, membersAdded: 0, openingHoursSaved: 0 };
|
|
48
|
+
}
|
|
49
|
+
if (options.localOnly) {
|
|
50
|
+
const r = await createCalendarAsync(calendar, options);
|
|
51
|
+
if (!r.ok)
|
|
52
|
+
return r;
|
|
53
|
+
return { ...r, membersAdded: 0, openingHoursSaved: 0 };
|
|
54
|
+
}
|
|
55
|
+
const created = await createCalendarAsync(calendar, options);
|
|
56
|
+
if (!created.ok)
|
|
57
|
+
return created;
|
|
58
|
+
return runMembersAndOpeningHoursAfterCalendarSave(calendar, created.calendar, created);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* After calendar `create` or `update`, add members and opening hours (same order as Apex facade).
|
|
62
|
+
*/
|
|
63
|
+
async function runMembersAndOpeningHoursAfterCalendarSave(calendar, calendarNode, baseSuccess) {
|
|
64
|
+
const calendarIdStr = effectiveCalendarId(calendarNode, calendar);
|
|
65
|
+
if (!calendarIdStr) {
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
error: "Could not resolve calendar id after save. Ensure the API returned a calendar id.",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
let membersAdded = 0;
|
|
72
|
+
for (const m of calendar.members ?? []) {
|
|
73
|
+
const pid = normalizeParticipantGuid(m.id);
|
|
74
|
+
if (!pid) {
|
|
75
|
+
return {
|
|
76
|
+
ok: false,
|
|
77
|
+
error: `Member id ${m.id}: thirdPartyMemberId is required to add a participant.`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const res = await addParticipantToCalendar(calendarNode, pid);
|
|
81
|
+
if (isFailureStatus(res)) {
|
|
82
|
+
const msg = res.message ??
|
|
83
|
+
(typeof res.data === "string" ? res.data : undefined) ??
|
|
84
|
+
JSON.stringify(res);
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
error: `addParticipant failed for member ${m.id}: ${msg}`,
|
|
88
|
+
apiResponse: res,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
membersAdded += 1;
|
|
92
|
+
}
|
|
93
|
+
let openingHoursSaved = 0;
|
|
94
|
+
for (const oh of calendar.openingHours ?? []) {
|
|
95
|
+
const participantId = resolveParticipantIdForOpeningHour(oh);
|
|
96
|
+
if (!participantId) {
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
error: `Opening hour id ${oh.id}: participantId is required.`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
for (const day of oh.days ?? []) {
|
|
103
|
+
const payload = {
|
|
104
|
+
calendarId: calendarIdStr,
|
|
105
|
+
participantId,
|
|
106
|
+
day,
|
|
107
|
+
startHour: oh.startHour,
|
|
108
|
+
startMinute: oh.startMinute,
|
|
109
|
+
endHour: oh.endHour,
|
|
110
|
+
endMinute: oh.endMinute,
|
|
111
|
+
off: oh.off,
|
|
112
|
+
openingHourId: oh.openingHourId?.trim() || newOpeningHourId(),
|
|
113
|
+
};
|
|
114
|
+
const res = await saveCalendarOpeningHour(calendarNode, payload);
|
|
115
|
+
if (isFailureStatus(res)) {
|
|
116
|
+
const msg = res.message ??
|
|
117
|
+
(typeof res.data === "string" ? res.data : undefined) ??
|
|
118
|
+
JSON.stringify(res);
|
|
119
|
+
return {
|
|
120
|
+
ok: false,
|
|
121
|
+
error: `saveOpeningHour failed (opening hour ${oh.id}, day ${day}): ${msg}`,
|
|
122
|
+
apiResponse: res,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
openingHoursSaved += 1;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
...baseSuccess,
|
|
130
|
+
membersAdded,
|
|
131
|
+
openingHoursSaved,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Calendar body update, then same member + opening-hour saves as create (Apex-style follow-up).
|
|
136
|
+
* For member add/remove *diffs* against existing DB membership, use server-side Apex; this client
|
|
137
|
+
* only performs additive Blazeo calls matching the payload.
|
|
138
|
+
*/
|
|
139
|
+
export async function updateCalendarWithRelationsAsync(calendar, options = {}) {
|
|
140
|
+
const hasMembers = (calendar.members?.length ?? 0) > 0;
|
|
141
|
+
const hasHours = (calendar.openingHours?.length ?? 0) > 0;
|
|
142
|
+
if (!hasMembers && !hasHours) {
|
|
143
|
+
const r = await updateCalendarAsync(calendar, options);
|
|
144
|
+
if (!r.ok)
|
|
145
|
+
return r;
|
|
146
|
+
return { ...r, membersAdded: 0, openingHoursSaved: 0 };
|
|
147
|
+
}
|
|
148
|
+
if (options.localOnly) {
|
|
149
|
+
const r = await updateCalendarAsync(calendar, options);
|
|
150
|
+
if (!r.ok)
|
|
151
|
+
return r;
|
|
152
|
+
return { ...r, membersAdded: 0, openingHoursSaved: 0 };
|
|
153
|
+
}
|
|
154
|
+
const updated = await updateCalendarAsync(calendar, options);
|
|
155
|
+
if (!updated.ok)
|
|
156
|
+
return updated;
|
|
157
|
+
return runMembersAndOpeningHoursAfterCalendarSave(calendar, updated.calendar, updated);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Aligned with `CalendarCreation`: create/update with members & opening hours,
|
|
161
|
+
* or delete calendar only.
|
|
162
|
+
*/
|
|
163
|
+
export class CalendarCreation {
|
|
164
|
+
static createWithRelationsAsync = createCalendarWithRelationsAsync;
|
|
165
|
+
static updateWithRelationsAsync = updateCalendarWithRelationsAsync;
|
|
166
|
+
static deleteCalendarAsync = deleteCalendarAsync;
|
|
167
|
+
}
|
|
@@ -1,29 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { deleteCalendarAsync, type CreateCalendarOptions, type CreateCalendarResult, type CreateCalendarSuccess } from "./createCalendar.js";
|
|
1
|
+
import { deleteCalendarAsync } from "./createCalendar.js";
|
|
3
2
|
/**
|
|
4
3
|
* Resolves Blazeo `participantId` for an opening-hour row: explicit `participantId`,
|
|
5
4
|
* matching `CalendarCreationAPIFacade.SaveOpeningHours`.
|
|
6
5
|
*/
|
|
7
|
-
export declare function resolveParticipantIdForOpeningHour(openingHour:
|
|
8
|
-
export type CalendarWithRelationsSuccess = CreateCalendarSuccess & {
|
|
9
|
-
membersAdded: number;
|
|
10
|
-
openingHoursSaved: number;
|
|
11
|
-
};
|
|
12
|
-
export type CalendarWithRelationsResult = CalendarWithRelationsSuccess | Extract<CreateCalendarResult, {
|
|
13
|
-
ok: false;
|
|
14
|
-
}>;
|
|
6
|
+
export declare function resolveParticipantIdForOpeningHour(openingHour: any): string | undefined;
|
|
15
7
|
/**
|
|
16
8
|
* Orchestrates the same steps as Apex `CalendarCreationAPIFacade.CreateCalendarAsync`:
|
|
17
9
|
* save calendar (`POST /Calendar/Create`), then add participants, then save opening hours
|
|
18
10
|
* per day (`POST /Calendar/Participant/Availability/OpeningHour/Save`).
|
|
19
11
|
*/
|
|
20
|
-
export declare function createCalendarWithRelationsAsync(calendar:
|
|
12
|
+
export declare function createCalendarWithRelationsAsync(calendar: any, options?: any): Promise<any>;
|
|
21
13
|
/**
|
|
22
14
|
* Calendar body update, then same member + opening-hour saves as create (Apex-style follow-up).
|
|
23
15
|
* For member add/remove *diffs* against existing DB membership, use server-side Apex; this client
|
|
24
16
|
* only performs additive Blazeo calls matching the payload.
|
|
25
17
|
*/
|
|
26
|
-
export declare function updateCalendarWithRelationsAsync(calendar:
|
|
18
|
+
export declare function updateCalendarWithRelationsAsync(calendar: any, options?: any): Promise<any>;
|
|
27
19
|
/**
|
|
28
20
|
* Facade aligned with `CalendarCreationAPIFacade`: create/update with members & opening hours,
|
|
29
21
|
* or delete calendar only.
|
|
@@ -33,4 +25,3 @@ export declare class CalendarCreationFacade {
|
|
|
33
25
|
static updateWithRelationsAsync: typeof updateCalendarWithRelationsAsync;
|
|
34
26
|
static deleteCalendarAsync: typeof deleteCalendarAsync;
|
|
35
27
|
}
|
|
36
|
-
//# sourceMappingURL=calendarCreationFacade.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getSnapshot } from "mobx-state-tree";
|
|
2
|
-
import { addParticipantToCalendar, saveCalendarOpeningHour
|
|
3
|
-
import { createCalendarAsync, updateCalendarAsync, deleteCalendarAsync
|
|
2
|
+
import { addParticipantToCalendar, saveCalendarOpeningHour } from "./blazeoCalendarRelationMethods.js";
|
|
3
|
+
import { createCalendarAsync, updateCalendarAsync, deleteCalendarAsync } from "./createCalendar.js";
|
|
4
4
|
function isFailureStatus(res) {
|
|
5
5
|
return res.status !== "success" && res.status !== "Success";
|
|
6
6
|
}
|
|
@@ -30,8 +30,7 @@ function effectiveCalendarId(calendarNode, input) {
|
|
|
30
30
|
const fromNode = snap.calendarId?.trim();
|
|
31
31
|
if (fromNode && fromNode !== "new")
|
|
32
32
|
return fromNode;
|
|
33
|
-
return (input.calendarId?.trim() ||
|
|
34
|
-
undefined);
|
|
33
|
+
return (input.calendarId?.trim() || undefined);
|
|
35
34
|
}
|
|
36
35
|
/**
|
|
37
36
|
* Orchestrates the same steps as Apex `CalendarCreationAPIFacade.CreateCalendarAsync`:
|
|
@@ -166,4 +165,3 @@ export class CalendarCreationFacade {
|
|
|
166
165
|
static updateWithRelationsAsync = updateCalendarWithRelationsAsync;
|
|
167
166
|
static deleteCalendarAsync = deleteCalendarAsync;
|
|
168
167
|
}
|
|
169
|
-
//# sourceMappingURL=calendarCreationFacade.js.map
|