@dimescheduler/setup 0.1.2 → 0.1.3
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/README.md +8 -8
- package/dist/bundle-5KNZSFFQ.js +10 -0
- package/dist/chunk-VHT6HO3N.js +863 -0
- package/dist/index.js +205 -448
- package/package.json +11 -7
|
@@ -0,0 +1,863 @@
|
|
|
1
|
+
// src/core/compile/bundle.ts
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import { dirname, resolve } from "path";
|
|
4
|
+
import JSON5 from "json5";
|
|
5
|
+
|
|
6
|
+
// src/core/types.ts
|
|
7
|
+
function isProfileDocument(doc) {
|
|
8
|
+
return typeof doc === "object" && doc !== null && doc.type === "profile";
|
|
9
|
+
}
|
|
10
|
+
function isUsersDocument(doc) {
|
|
11
|
+
return typeof doc === "object" && doc !== null && doc.type === "users";
|
|
12
|
+
}
|
|
13
|
+
function isLayoutsDocument(doc) {
|
|
14
|
+
return typeof doc === "object" && doc !== null && doc.type === "layouts";
|
|
15
|
+
}
|
|
16
|
+
function isBundleDocument(doc) {
|
|
17
|
+
return typeof doc === "object" && doc !== null && doc.type === "bundle";
|
|
18
|
+
}
|
|
19
|
+
function isDocumentReference(item) {
|
|
20
|
+
return "$ref" in item;
|
|
21
|
+
}
|
|
22
|
+
function detectDocumentType(doc) {
|
|
23
|
+
if (typeof doc !== "object" || doc === null) return null;
|
|
24
|
+
const type = doc.type;
|
|
25
|
+
if (type === "profile" || type === "users" || type === "layouts" || type === "bundle") {
|
|
26
|
+
return type;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/core/compile/merge.ts
|
|
32
|
+
function hasConflicts(a, b, key) {
|
|
33
|
+
const aKeys = new Set(a.map((item) => item[key]));
|
|
34
|
+
return b.some((item) => aKeys.has(item[key]));
|
|
35
|
+
}
|
|
36
|
+
function mergeLayouts(existing, incoming, strategy = "append") {
|
|
37
|
+
if (strategy === "replace") {
|
|
38
|
+
return [...incoming];
|
|
39
|
+
}
|
|
40
|
+
if (strategy === "error" && hasConflicts(existing, incoming, "code")) {
|
|
41
|
+
const existingCodes = new Set(existing.map((l) => l.code));
|
|
42
|
+
const conflicts = incoming.filter((l) => existingCodes.has(l.code)).map((l) => l.code);
|
|
43
|
+
throw new Error(`Layout code conflict detected: ${conflicts.join(", ")}`);
|
|
44
|
+
}
|
|
45
|
+
const merged = [...existing];
|
|
46
|
+
for (const layout of incoming) {
|
|
47
|
+
const existingIndex = merged.findIndex((l) => l.code === layout.code);
|
|
48
|
+
if (existingIndex >= 0) {
|
|
49
|
+
merged[existingIndex] = layout;
|
|
50
|
+
} else {
|
|
51
|
+
merged.push(layout);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return merged;
|
|
55
|
+
}
|
|
56
|
+
function mergeUsers(existing, incoming, strategy = "append") {
|
|
57
|
+
if (strategy === "replace") {
|
|
58
|
+
return [...incoming];
|
|
59
|
+
}
|
|
60
|
+
if (strategy === "error" && hasConflicts(existing, incoming, "email")) {
|
|
61
|
+
const existingEmails = new Set(existing.map((u) => u.email));
|
|
62
|
+
const conflicts = incoming.filter((u) => existingEmails.has(u.email)).map((u) => u.email);
|
|
63
|
+
throw new Error(`User email conflict detected: ${conflicts.join(", ")}`);
|
|
64
|
+
}
|
|
65
|
+
const merged = [...existing];
|
|
66
|
+
for (const user of incoming) {
|
|
67
|
+
const existingIndex = merged.findIndex((u) => u.email === user.email);
|
|
68
|
+
if (existingIndex >= 0) {
|
|
69
|
+
merged[existingIndex] = user;
|
|
70
|
+
} else {
|
|
71
|
+
merged.push(user);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return merged;
|
|
75
|
+
}
|
|
76
|
+
function deepMerge(target, source) {
|
|
77
|
+
const result = { ...target };
|
|
78
|
+
for (const key of Object.keys(source)) {
|
|
79
|
+
const sourceValue = source[key];
|
|
80
|
+
const targetValue = result[key];
|
|
81
|
+
if (sourceValue === void 0) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (Array.isArray(sourceValue)) {
|
|
85
|
+
if (Array.isArray(targetValue)) {
|
|
86
|
+
result[key] = [...targetValue, ...sourceValue];
|
|
87
|
+
} else {
|
|
88
|
+
result[key] = [...sourceValue];
|
|
89
|
+
}
|
|
90
|
+
} else if (typeof sourceValue === "object" && sourceValue !== null && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) {
|
|
91
|
+
result[key] = deepMerge(
|
|
92
|
+
targetValue,
|
|
93
|
+
sourceValue
|
|
94
|
+
);
|
|
95
|
+
} else {
|
|
96
|
+
result[key] = sourceValue;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
function setPath(obj, path, value) {
|
|
102
|
+
const parts = path.split(".");
|
|
103
|
+
let current = obj;
|
|
104
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
105
|
+
const part = parts[i];
|
|
106
|
+
if (!(part in current) || typeof current[part] !== "object" || current[part] === null) {
|
|
107
|
+
current[part] = {};
|
|
108
|
+
}
|
|
109
|
+
current = current[part];
|
|
110
|
+
}
|
|
111
|
+
const lastPart = parts[parts.length - 1];
|
|
112
|
+
if (Array.isArray(value) && Array.isArray(current[lastPart])) {
|
|
113
|
+
current[lastPart] = [...current[lastPart], ...value];
|
|
114
|
+
} else if (typeof value === "object" && value !== null && !Array.isArray(value) && typeof current[lastPart] === "object" && current[lastPart] !== null && !Array.isArray(current[lastPart])) {
|
|
115
|
+
current[lastPart] = deepMerge(
|
|
116
|
+
current[lastPart],
|
|
117
|
+
value
|
|
118
|
+
);
|
|
119
|
+
} else {
|
|
120
|
+
current[lastPart] = value;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function applyMergeOverrides(doc, mergeOverrides) {
|
|
124
|
+
const result = JSON.parse(JSON.stringify(doc));
|
|
125
|
+
for (const [path, value] of Object.entries(mergeOverrides)) {
|
|
126
|
+
setPath(result, path, value);
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/core/compile/mappers.ts
|
|
132
|
+
var SNAP_MODE_MAP = {
|
|
133
|
+
"none": 1,
|
|
134
|
+
"off": 1,
|
|
135
|
+
"5min": 2,
|
|
136
|
+
"5minutes": 2,
|
|
137
|
+
"10min": 3,
|
|
138
|
+
"10minutes": 3,
|
|
139
|
+
"15min": 4,
|
|
140
|
+
"15minutes": 4,
|
|
141
|
+
"30min": 5,
|
|
142
|
+
"30minutes": 5,
|
|
143
|
+
"halfhour": 5,
|
|
144
|
+
"1hour": 6,
|
|
145
|
+
"1h": 6,
|
|
146
|
+
"hour": 6,
|
|
147
|
+
"12hours": 7,
|
|
148
|
+
"12h": 7,
|
|
149
|
+
"1day": 8,
|
|
150
|
+
"1d": 8,
|
|
151
|
+
"day": 8,
|
|
152
|
+
"2hours": 9,
|
|
153
|
+
"2h": 9,
|
|
154
|
+
"4hours": 10,
|
|
155
|
+
"4h": 10,
|
|
156
|
+
// Numeric string mappings
|
|
157
|
+
"1": 1,
|
|
158
|
+
"2": 2,
|
|
159
|
+
"3": 3,
|
|
160
|
+
"4": 4,
|
|
161
|
+
"5": 5,
|
|
162
|
+
"6": 6,
|
|
163
|
+
"7": 7,
|
|
164
|
+
"8": 8,
|
|
165
|
+
"9": 9,
|
|
166
|
+
"10": 10
|
|
167
|
+
};
|
|
168
|
+
function mapSnapMode(mode) {
|
|
169
|
+
if (mode === void 0 || mode === null) return 6;
|
|
170
|
+
return SNAP_MODE_MAP[String(mode).toLowerCase()] ?? 6;
|
|
171
|
+
}
|
|
172
|
+
var RANGE_MODE_MAP = {
|
|
173
|
+
"day": 1,
|
|
174
|
+
"days": 1,
|
|
175
|
+
"hours": 1,
|
|
176
|
+
"week": 2,
|
|
177
|
+
"weeks": 2,
|
|
178
|
+
"month": 3,
|
|
179
|
+
"months": 3,
|
|
180
|
+
"custom": 4,
|
|
181
|
+
// Numeric string mappings
|
|
182
|
+
"1": 1,
|
|
183
|
+
"2": 2,
|
|
184
|
+
"3": 3,
|
|
185
|
+
"4": 4
|
|
186
|
+
};
|
|
187
|
+
function mapRangeMode(mode) {
|
|
188
|
+
if (mode === void 0 || mode === null) return 2;
|
|
189
|
+
return RANGE_MODE_MAP[String(mode).toLowerCase()] ?? 2;
|
|
190
|
+
}
|
|
191
|
+
var START_MODE_MAP = {
|
|
192
|
+
"today": 1,
|
|
193
|
+
"absolute": 1,
|
|
194
|
+
"startofweek": 2,
|
|
195
|
+
"relative": 2,
|
|
196
|
+
"startofmonth": 3,
|
|
197
|
+
"todayoffset": 4,
|
|
198
|
+
// Numeric string mappings
|
|
199
|
+
"1": 1,
|
|
200
|
+
"2": 2,
|
|
201
|
+
"3": 3,
|
|
202
|
+
"4": 4
|
|
203
|
+
};
|
|
204
|
+
function mapStartMode(mode) {
|
|
205
|
+
if (mode === void 0 || mode === null) return 2;
|
|
206
|
+
return START_MODE_MAP[String(mode).toLowerCase().replace(/\s+/g, "")] ?? 2;
|
|
207
|
+
}
|
|
208
|
+
function mapUnitOfDistance(unit) {
|
|
209
|
+
if (!unit) return "Kilometers";
|
|
210
|
+
const v = unit.toLowerCase();
|
|
211
|
+
if (["km", "kilometer", "kilometers"].includes(v)) return "Kilometers";
|
|
212
|
+
if (["mi", "mile", "miles"].includes(v)) return "Miles";
|
|
213
|
+
return unit;
|
|
214
|
+
}
|
|
215
|
+
var COMPONENT_TO_GL = {
|
|
216
|
+
// Friendly names (user-facing DSL names)
|
|
217
|
+
"openTasks": "openTasksGridComponent",
|
|
218
|
+
"planningBoard": "schedulerComponent",
|
|
219
|
+
"map": "mapComponent",
|
|
220
|
+
"indicators": "categoriesComponent",
|
|
221
|
+
"resourceFilters": "filterComponent",
|
|
222
|
+
"plannedTasks": "plannedTasksGridComponent",
|
|
223
|
+
"details": "propertygridComponent",
|
|
224
|
+
"datePicker": "datePickerComponent",
|
|
225
|
+
"gantt": "ganttComponent",
|
|
226
|
+
"capacity": "capacityComponent",
|
|
227
|
+
"routeSequence": "routeSequenceComponent",
|
|
228
|
+
"notifications": "notificationsComponent",
|
|
229
|
+
// Internal names (for backwards compatibility)
|
|
230
|
+
"mapComponent": "mapComponent",
|
|
231
|
+
"plannedTasksGridComponent": "plannedTasksGridComponent",
|
|
232
|
+
"propertygridComponent": "propertygridComponent",
|
|
233
|
+
"datePickerComponent": "datePickerComponent",
|
|
234
|
+
"ganttComponent": "ganttComponent",
|
|
235
|
+
"capacityComponent": "capacityComponent",
|
|
236
|
+
"routeSequenceComponent": "routeSequenceComponent",
|
|
237
|
+
"notificationsComponent": "notificationsComponent"
|
|
238
|
+
};
|
|
239
|
+
function componentToGlName(name) {
|
|
240
|
+
return COMPONENT_TO_GL[name] ?? name;
|
|
241
|
+
}
|
|
242
|
+
var VIEW_PRESET_MAP = {
|
|
243
|
+
"day": "1",
|
|
244
|
+
"1": "1",
|
|
245
|
+
"week": "2",
|
|
246
|
+
"2": "2",
|
|
247
|
+
"workweek": "3",
|
|
248
|
+
"workWeek": "3",
|
|
249
|
+
"work_week": "3",
|
|
250
|
+
"3": "3",
|
|
251
|
+
"month": "4",
|
|
252
|
+
"4": "4"
|
|
253
|
+
};
|
|
254
|
+
function mapViewPreset(value) {
|
|
255
|
+
if (value === void 0 || value === null) return "2";
|
|
256
|
+
const v = String(value).toLowerCase().replace(/[\s_-]+/g, "");
|
|
257
|
+
return VIEW_PRESET_MAP[v] ?? String(value);
|
|
258
|
+
}
|
|
259
|
+
var ROW_HEIGHT_MAP = {
|
|
260
|
+
"1row": 25,
|
|
261
|
+
"1rows": 25,
|
|
262
|
+
"1": 25,
|
|
263
|
+
"25": 25,
|
|
264
|
+
"2rows": 38,
|
|
265
|
+
"2row": 38,
|
|
266
|
+
"2": 38,
|
|
267
|
+
"38": 38,
|
|
268
|
+
"3rows": 50,
|
|
269
|
+
"3row": 50,
|
|
270
|
+
"3": 50,
|
|
271
|
+
"50": 50,
|
|
272
|
+
"4rows": 63,
|
|
273
|
+
"4row": 63,
|
|
274
|
+
"4": 63,
|
|
275
|
+
"63": 63
|
|
276
|
+
};
|
|
277
|
+
function mapRowHeight(value) {
|
|
278
|
+
if (value === void 0 || value === null) return 38;
|
|
279
|
+
const v = String(value).toLowerCase().replace(/[\s_-]+/g, "");
|
|
280
|
+
if (ROW_HEIGHT_MAP[v] !== void 0) return ROW_HEIGHT_MAP[v];
|
|
281
|
+
const parsed = parseInt(String(value), 10);
|
|
282
|
+
return isNaN(parsed) ? 38 : parsed;
|
|
283
|
+
}
|
|
284
|
+
function mapRouteProfile(value) {
|
|
285
|
+
if (!value || value === "default") return "car";
|
|
286
|
+
return value;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/core/compile/goldenLayout.ts
|
|
290
|
+
function workspaceNodeToGL(node) {
|
|
291
|
+
const gl = { type: node.type };
|
|
292
|
+
if ("width" in node && node.width !== void 0) {
|
|
293
|
+
gl.width = node.width;
|
|
294
|
+
}
|
|
295
|
+
if ("height" in node && node.height !== void 0) {
|
|
296
|
+
gl.height = node.height;
|
|
297
|
+
}
|
|
298
|
+
if (node.type === "row" || node.type === "column" || node.type === "stack") {
|
|
299
|
+
gl.isClosable = true;
|
|
300
|
+
gl.reorderEnabled = true;
|
|
301
|
+
gl.title = "";
|
|
302
|
+
if ("content" in node && node.content) {
|
|
303
|
+
gl.content = node.content.map(workspaceNodeToGL);
|
|
304
|
+
}
|
|
305
|
+
if (node.type === "stack") {
|
|
306
|
+
gl.activeItemIndex = 0;
|
|
307
|
+
}
|
|
308
|
+
return gl;
|
|
309
|
+
}
|
|
310
|
+
if (node.type === "component") {
|
|
311
|
+
const compName = componentToGlName(node.component);
|
|
312
|
+
if (compName) {
|
|
313
|
+
gl.componentName = compName;
|
|
314
|
+
}
|
|
315
|
+
if (node.title !== void 0) {
|
|
316
|
+
gl.title = node.title;
|
|
317
|
+
}
|
|
318
|
+
gl.isClosable = true;
|
|
319
|
+
gl.reorderEnabled = true;
|
|
320
|
+
const compState = {};
|
|
321
|
+
const compId = node.id;
|
|
322
|
+
if (compId) {
|
|
323
|
+
gl.id = compId;
|
|
324
|
+
compState.id = compId;
|
|
325
|
+
} else if (compName === "schedulerComponent") {
|
|
326
|
+
gl.id = "schedulerContainer";
|
|
327
|
+
compState.id = "scheduler";
|
|
328
|
+
}
|
|
329
|
+
if (compName === "datePickerComponent" && compId) {
|
|
330
|
+
compState.wrapperId = compId;
|
|
331
|
+
}
|
|
332
|
+
if (Object.keys(compState).length > 0) {
|
|
333
|
+
gl.componentState = compState;
|
|
334
|
+
}
|
|
335
|
+
return gl;
|
|
336
|
+
}
|
|
337
|
+
return gl;
|
|
338
|
+
}
|
|
339
|
+
function detectRootType(workspace) {
|
|
340
|
+
if (workspace.length === 0) return "row";
|
|
341
|
+
let heightCount = 0;
|
|
342
|
+
let widthCount = 0;
|
|
343
|
+
for (const node of workspace) {
|
|
344
|
+
if ("height" in node && node.height !== void 0) heightCount++;
|
|
345
|
+
if ("width" in node && node.width !== void 0) widthCount++;
|
|
346
|
+
}
|
|
347
|
+
if (heightCount > widthCount) {
|
|
348
|
+
return "column";
|
|
349
|
+
}
|
|
350
|
+
return "row";
|
|
351
|
+
}
|
|
352
|
+
function workspaceToGoldenLayout(workspace) {
|
|
353
|
+
const rootType = detectRootType(workspace);
|
|
354
|
+
return {
|
|
355
|
+
settings: {
|
|
356
|
+
hasHeaders: true,
|
|
357
|
+
constrainDragToContainer: false,
|
|
358
|
+
reorderEnabled: true,
|
|
359
|
+
selectionEnabled: true,
|
|
360
|
+
popoutWholeStack: false,
|
|
361
|
+
blockedPopoutsThrowError: true,
|
|
362
|
+
closePopoutsOnUnload: true,
|
|
363
|
+
showPopoutIcon: false,
|
|
364
|
+
showMaximiseIcon: true,
|
|
365
|
+
showCloseIcon: true,
|
|
366
|
+
responsiveMode: "onload",
|
|
367
|
+
tabOverlapAllowance: 0,
|
|
368
|
+
reorderOnTabMenuClick: true,
|
|
369
|
+
tabControlOffset: 10
|
|
370
|
+
},
|
|
371
|
+
dimensions: {
|
|
372
|
+
borderWidth: 5,
|
|
373
|
+
borderGrabWidth: 15,
|
|
374
|
+
minItemHeight: 10,
|
|
375
|
+
minItemWidth: 10,
|
|
376
|
+
headerHeight: 20,
|
|
377
|
+
dragProxyWidth: 300,
|
|
378
|
+
dragProxyHeight: 200
|
|
379
|
+
},
|
|
380
|
+
labels: {
|
|
381
|
+
close: "Close",
|
|
382
|
+
maximise: "Maximize",
|
|
383
|
+
minimise: "Minimize",
|
|
384
|
+
popout: "open in new window",
|
|
385
|
+
popin: "pop in",
|
|
386
|
+
tabDropdown: "Additional Tabs"
|
|
387
|
+
},
|
|
388
|
+
content: [
|
|
389
|
+
{
|
|
390
|
+
type: rootType,
|
|
391
|
+
isClosable: true,
|
|
392
|
+
reorderEnabled: true,
|
|
393
|
+
title: "",
|
|
394
|
+
content: workspace.map(workspaceNodeToGL)
|
|
395
|
+
}
|
|
396
|
+
],
|
|
397
|
+
isClosable: true,
|
|
398
|
+
reorderEnabled: true,
|
|
399
|
+
title: "",
|
|
400
|
+
openPopouts: [],
|
|
401
|
+
maximisedItemId: null
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// src/core/compile/layoutBuilders/base.ts
|
|
406
|
+
function buildBaseLayoutState(layout, gridName) {
|
|
407
|
+
const columns = (layout.columns || []).filter((c) => c.property).map((c) => ({ dataIndex: c.property }));
|
|
408
|
+
const sorters = (layout.sorters || []).filter((s) => s.property && s.direction).map((s) => ({ direction: s.direction, property: s.property }));
|
|
409
|
+
let grouper;
|
|
410
|
+
if (layout.grouper && layout.grouper.property && layout.grouper.direction) {
|
|
411
|
+
grouper = {
|
|
412
|
+
root: "data",
|
|
413
|
+
property: layout.grouper.property,
|
|
414
|
+
direction: layout.grouper.direction,
|
|
415
|
+
id: layout.grouper.id || layout.grouper.property
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
const filters = (layout.filters || []).map((f) => ({
|
|
419
|
+
operator: f.operator || "like",
|
|
420
|
+
value: f.value || "",
|
|
421
|
+
property: f.property,
|
|
422
|
+
exactMatch: f.exactMatch ?? false
|
|
423
|
+
}));
|
|
424
|
+
const pageSize = layout.pageSize !== void 0 ? typeof layout.pageSize === "number" ? layout.pageSize : parseInt(String(layout.pageSize), 10) : 50;
|
|
425
|
+
const state = {
|
|
426
|
+
columns,
|
|
427
|
+
storeState: grouper ? { grouper } : {},
|
|
428
|
+
filters,
|
|
429
|
+
Id: layout.id || gridName,
|
|
430
|
+
pageSize: isNaN(pageSize) ? 50 : pageSize
|
|
431
|
+
};
|
|
432
|
+
if (sorters.length > 0) {
|
|
433
|
+
state.sorters = sorters;
|
|
434
|
+
}
|
|
435
|
+
if (layout.default) {
|
|
436
|
+
state.default = true;
|
|
437
|
+
}
|
|
438
|
+
if (layout.name) {
|
|
439
|
+
state.name = layout.name;
|
|
440
|
+
}
|
|
441
|
+
return state;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/core/compile/layoutBuilders/scheduler.ts
|
|
445
|
+
function buildSchedulerLayoutState(layout, gridName) {
|
|
446
|
+
const base = buildBaseLayoutState(layout, gridName);
|
|
447
|
+
const lockedGridWidth = layout.lockedGridWidth || layout.resourcesGridWidth || null;
|
|
448
|
+
const fitToScreen = typeof layout.fitToScreen === "boolean" ? layout.fitToScreen : layout.fitToScreen === "true";
|
|
449
|
+
const ignoreCalendars = typeof layout.ignoreCalendars === "boolean" ? layout.ignoreCalendars : layout.ignoreCalendars === "true";
|
|
450
|
+
return {
|
|
451
|
+
...base,
|
|
452
|
+
viewPreset: layout.viewPreset !== void 0 ? mapViewPreset(layout.viewPreset) : null,
|
|
453
|
+
lockedGridWidth,
|
|
454
|
+
fitToScreen,
|
|
455
|
+
rowHeight: mapRowHeight(layout.rowHeight),
|
|
456
|
+
ignoreCalendars
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/core/compile/layoutBuilders/capacity.ts
|
|
461
|
+
function buildCapacityLayoutState(layout, gridName) {
|
|
462
|
+
const base = buildBaseLayoutState(layout, gridName);
|
|
463
|
+
const state = { ...base };
|
|
464
|
+
if (layout.viewLayoutType !== void 0) state.viewLayoutType = layout.viewLayoutType;
|
|
465
|
+
if (layout.startRowGroupsCollapsed !== void 0) state.startRowGroupsCollapsed = layout.startRowGroupsCollapsed;
|
|
466
|
+
if (layout.startColGroupsCollapsed !== void 0) state.startColGroupsCollapsed = layout.startColGroupsCollapsed;
|
|
467
|
+
if (layout.enableColumnSort !== void 0) state.enableColumnSort = layout.enableColumnSort;
|
|
468
|
+
if (layout.expandedItems !== void 0) state.expandedItems = layout.expandedItems;
|
|
469
|
+
if (layout.matrix !== void 0) state.matrix = layout.matrix;
|
|
470
|
+
if (layout.pivotcolumns !== void 0) state.pivotcolumns = layout.pivotcolumns;
|
|
471
|
+
if (layout.collapsed !== void 0) state.collapsed = layout.collapsed;
|
|
472
|
+
return state;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// src/core/compile/layoutBuilders/gantt.ts
|
|
476
|
+
function buildGanttLayoutState(layout, gridName) {
|
|
477
|
+
const base = buildBaseLayoutState(layout, gridName);
|
|
478
|
+
const state = { ...base };
|
|
479
|
+
if (layout.viewPreset !== void 0) {
|
|
480
|
+
state.viewPreset = mapViewPreset(layout.viewPreset);
|
|
481
|
+
}
|
|
482
|
+
return state;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// src/core/compile/layoutBuilders/grid.ts
|
|
486
|
+
function buildGridLayoutState(layout, gridName) {
|
|
487
|
+
const base = buildBaseLayoutState(layout, gridName);
|
|
488
|
+
const state = { ...base };
|
|
489
|
+
if (layout.hideEmptyRows !== void 0) {
|
|
490
|
+
state.hideEmptyRows = layout.hideEmptyRows;
|
|
491
|
+
}
|
|
492
|
+
return state;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// src/core/compile/layoutBuilders/index.ts
|
|
496
|
+
function buildLayoutState(layout, gridName) {
|
|
497
|
+
const context = layout.context;
|
|
498
|
+
switch (context) {
|
|
499
|
+
case "scheduler":
|
|
500
|
+
return buildSchedulerLayoutState(layout, gridName);
|
|
501
|
+
case "pivotGrid":
|
|
502
|
+
return buildCapacityLayoutState(layout, gridName);
|
|
503
|
+
case "gantt":
|
|
504
|
+
return buildGanttLayoutState(layout, gridName);
|
|
505
|
+
case "unplannedTasksGrid":
|
|
506
|
+
case "plannedTasksGrid":
|
|
507
|
+
case "notificationsGrid":
|
|
508
|
+
case "detailsGrid":
|
|
509
|
+
case "routeSequenceGrid":
|
|
510
|
+
return buildGridLayoutState(layout, gridName);
|
|
511
|
+
default:
|
|
512
|
+
return buildBaseLayoutState(layout, gridName);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// src/core/compile/layoutBuilder.ts
|
|
517
|
+
function collectLayouts(layouts) {
|
|
518
|
+
return layouts.map((layout) => {
|
|
519
|
+
const gridName = layout.id || layout.code;
|
|
520
|
+
return {
|
|
521
|
+
context: layout.context,
|
|
522
|
+
grid: gridName,
|
|
523
|
+
value: buildLayoutState(layout, gridName),
|
|
524
|
+
name: layout.name || layout.code,
|
|
525
|
+
code: layout.code,
|
|
526
|
+
componentId: gridName,
|
|
527
|
+
default: layout.default ?? false,
|
|
528
|
+
public: layout.shared?.public ?? false,
|
|
529
|
+
userGroup: layout.shared?.userGroup
|
|
530
|
+
};
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
function buildLayoutDtos(layouts) {
|
|
534
|
+
if (!layouts || layouts.length === 0) return [];
|
|
535
|
+
return collectLayouts(layouts).map((L) => ({
|
|
536
|
+
context: L.context,
|
|
537
|
+
grid: L.grid,
|
|
538
|
+
value: JSON.stringify(L.value),
|
|
539
|
+
default: L.default,
|
|
540
|
+
public: L.public,
|
|
541
|
+
userGroup: L.userGroup,
|
|
542
|
+
isOwner: true,
|
|
543
|
+
isNew: true,
|
|
544
|
+
name: L.name,
|
|
545
|
+
code: L.code
|
|
546
|
+
}));
|
|
547
|
+
}
|
|
548
|
+
var PANEL_COMPONENTS = /* @__PURE__ */ new Set([
|
|
549
|
+
"planningBoard",
|
|
550
|
+
"scheduler",
|
|
551
|
+
"openTasks",
|
|
552
|
+
"tasks",
|
|
553
|
+
"plannedTasks",
|
|
554
|
+
"details",
|
|
555
|
+
"gantt",
|
|
556
|
+
"indicators",
|
|
557
|
+
"categories",
|
|
558
|
+
"capacity",
|
|
559
|
+
"pivot",
|
|
560
|
+
"notifications",
|
|
561
|
+
"routeSequence"
|
|
562
|
+
]);
|
|
563
|
+
function buildProfileLayoutDtos(workspace, profileCode) {
|
|
564
|
+
if (!workspace || workspace.length === 0) return [];
|
|
565
|
+
const profileLayouts = [];
|
|
566
|
+
function traverse(nodes) {
|
|
567
|
+
for (const node of nodes) {
|
|
568
|
+
if (node.type === "row" || node.type === "column" || node.type === "stack") {
|
|
569
|
+
if ("content" in node && node.content) {
|
|
570
|
+
traverse(node.content);
|
|
571
|
+
}
|
|
572
|
+
} else if (node.type === "component") {
|
|
573
|
+
if (node.layoutRef) {
|
|
574
|
+
const refs = Array.isArray(node.layoutRef) ? node.layoutRef : [node.layoutRef];
|
|
575
|
+
const needsPanel = PANEL_COMPONENTS.has(node.component);
|
|
576
|
+
for (const code of refs) {
|
|
577
|
+
profileLayouts.push({
|
|
578
|
+
profileCode,
|
|
579
|
+
layoutCode: code,
|
|
580
|
+
default: true,
|
|
581
|
+
public: false,
|
|
582
|
+
name: node.id ? needsPanel ? `${node.id}_panel` : node.id : ""
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
traverse(workspace);
|
|
590
|
+
return profileLayouts;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// src/core/compile/profile.ts
|
|
594
|
+
var SNAP_MODE_VALUE = {
|
|
595
|
+
1: 0,
|
|
596
|
+
// none
|
|
597
|
+
2: 3e5,
|
|
598
|
+
// 5 min
|
|
599
|
+
3: 6e5,
|
|
600
|
+
// 10 min
|
|
601
|
+
4: 9e5,
|
|
602
|
+
// 15 min
|
|
603
|
+
5: 18e5,
|
|
604
|
+
// 30 min
|
|
605
|
+
6: 36e5,
|
|
606
|
+
// 1 hour
|
|
607
|
+
7: 432e5,
|
|
608
|
+
// 12 hours
|
|
609
|
+
8: 864e5,
|
|
610
|
+
// 1 day
|
|
611
|
+
9: 72e5,
|
|
612
|
+
// 2 hours
|
|
613
|
+
10: 144e5
|
|
614
|
+
// 4 hours
|
|
615
|
+
};
|
|
616
|
+
function getSnapMode(snapInterval) {
|
|
617
|
+
if (!snapInterval) return void 0;
|
|
618
|
+
if (typeof snapInterval === "string") return snapInterval;
|
|
619
|
+
return snapInterval.mode;
|
|
620
|
+
}
|
|
621
|
+
function getSnapValue(snapInterval, snapMode) {
|
|
622
|
+
if (typeof snapInterval === "object" && snapInterval?.value !== void 0 && snapInterval.value !== null) {
|
|
623
|
+
return snapInterval.value;
|
|
624
|
+
}
|
|
625
|
+
return SNAP_MODE_VALUE[snapMode] ?? 36e5;
|
|
626
|
+
}
|
|
627
|
+
function compileProfileDocument(doc) {
|
|
628
|
+
const profile = doc.payload;
|
|
629
|
+
const theme = profile.theme || { color: "default", scheme: "sdtd" };
|
|
630
|
+
const shared = profile.shared || { global: false, userGroup: "" };
|
|
631
|
+
const route = profile.route || {
|
|
632
|
+
profile: "default",
|
|
633
|
+
calculateRoutes: true,
|
|
634
|
+
showSequenceIndicators: true,
|
|
635
|
+
unitOfDistance: "km"
|
|
636
|
+
};
|
|
637
|
+
const planning = profile.planning || {
|
|
638
|
+
snapInterval: { mode: "1hour", value: 0 },
|
|
639
|
+
range: { mode: "week", value: 0 },
|
|
640
|
+
start: { mode: "startOfWeek", value: 2 },
|
|
641
|
+
hours: { start: 8, end: 18 }
|
|
642
|
+
};
|
|
643
|
+
const workspace = profile.workspace;
|
|
644
|
+
const goldenLayout = workspace && workspace.length > 0 ? workspaceToGoldenLayout(workspace) : null;
|
|
645
|
+
const layouts = [];
|
|
646
|
+
const profileLayouts = buildProfileLayoutDtos(workspace, profile.code || "");
|
|
647
|
+
const snapMode = mapSnapMode(getSnapMode(planning.snapInterval));
|
|
648
|
+
const snapValue = getSnapValue(planning.snapInterval, snapMode);
|
|
649
|
+
return {
|
|
650
|
+
id: "profile",
|
|
651
|
+
payload: {
|
|
652
|
+
profiles: [{
|
|
653
|
+
name: profile.name || "",
|
|
654
|
+
code: profile.code || "",
|
|
655
|
+
color: theme.color || "default",
|
|
656
|
+
theme: theme.scheme || "sdtd",
|
|
657
|
+
public: shared.global ?? false,
|
|
658
|
+
userGroup: shared.userGroup || "",
|
|
659
|
+
snapMode,
|
|
660
|
+
snapValue,
|
|
661
|
+
rangeMode: mapRangeMode(planning.range?.mode),
|
|
662
|
+
rangeValue: planning.range?.value ?? null,
|
|
663
|
+
startMode: mapStartMode(planning.start?.mode),
|
|
664
|
+
startValue: planning.start?.value ?? null,
|
|
665
|
+
startTime: planning.hours?.start ?? 8,
|
|
666
|
+
endTime: planning.hours?.end ?? 18,
|
|
667
|
+
unitOfDistance: mapUnitOfDistance(route.unitOfDistance),
|
|
668
|
+
autoRouteCalculation: route.calculateRoutes ?? true,
|
|
669
|
+
showSequenceIndicators: route.showSequenceIndicators ?? true,
|
|
670
|
+
routeProfile: mapRouteProfile(route.profile),
|
|
671
|
+
layout: goldenLayout ? JSON.stringify(goldenLayout) : ""
|
|
672
|
+
}],
|
|
673
|
+
layouts,
|
|
674
|
+
profileLayouts,
|
|
675
|
+
owner: doc.owner,
|
|
676
|
+
notificationEmail: doc.notificationEmail
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// src/core/compile/users.ts
|
|
682
|
+
function compileUsersDocument(doc) {
|
|
683
|
+
return {
|
|
684
|
+
id: "users",
|
|
685
|
+
payload: {
|
|
686
|
+
users: doc.payload,
|
|
687
|
+
owner: doc.owner,
|
|
688
|
+
notificationEmail: doc.notificationEmail
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// src/core/compile/layouts.ts
|
|
694
|
+
function compileLayoutsDocument(doc) {
|
|
695
|
+
return {
|
|
696
|
+
id: "layouts",
|
|
697
|
+
payload: {
|
|
698
|
+
layouts: buildLayoutDtos(doc.payload),
|
|
699
|
+
owner: doc.owner,
|
|
700
|
+
notificationEmail: doc.notificationEmail
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// src/core/compile/bundle.ts
|
|
706
|
+
async function resolveBundle(bundle, basePath) {
|
|
707
|
+
const result = {
|
|
708
|
+
profiles: [],
|
|
709
|
+
users: [],
|
|
710
|
+
layouts: []
|
|
711
|
+
};
|
|
712
|
+
const strategy = bundle.mergeStrategy ?? {};
|
|
713
|
+
for (const item of bundle.documents) {
|
|
714
|
+
let doc;
|
|
715
|
+
if (isDocumentReference(item)) {
|
|
716
|
+
const refPath = resolve(dirname(basePath), item.$ref);
|
|
717
|
+
const content = await readFile(refPath, "utf-8");
|
|
718
|
+
const parsed = JSON5.parse(content);
|
|
719
|
+
if (!isProfileDocument(parsed) && !isUsersDocument(parsed) && !isLayoutsDocument(parsed)) {
|
|
720
|
+
throw new Error(`Referenced document at ${item.$ref} is not a valid document type (profile, users, or layouts)`);
|
|
721
|
+
}
|
|
722
|
+
doc = parsed;
|
|
723
|
+
if (item.$merge) {
|
|
724
|
+
doc = applyMergeOverrides(doc, item.$merge);
|
|
725
|
+
}
|
|
726
|
+
} else if (isProfileDocument(item) || isUsersDocument(item) || isLayoutsDocument(item)) {
|
|
727
|
+
doc = item;
|
|
728
|
+
} else {
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
if (isProfileDocument(doc)) {
|
|
732
|
+
result.profiles.push(doc);
|
|
733
|
+
} else if (isUsersDocument(doc)) {
|
|
734
|
+
result.users = mergeUsers(result.users, doc.payload ?? [], strategy.users);
|
|
735
|
+
} else if (isLayoutsDocument(doc)) {
|
|
736
|
+
result.layouts = mergeLayouts(result.layouts, doc.payload ?? [], strategy.layouts);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return result;
|
|
740
|
+
}
|
|
741
|
+
async function compileBundleDocument(bundle, basePath) {
|
|
742
|
+
const resolved = await resolveBundle(bundle, basePath);
|
|
743
|
+
const payloads = [];
|
|
744
|
+
const strategy = bundle.mergeStrategy ?? {};
|
|
745
|
+
if (resolved.profiles.length > 0) {
|
|
746
|
+
let profilesForCompile;
|
|
747
|
+
if (strategy.profiles === "error" && resolved.profiles.length > 1) {
|
|
748
|
+
throw new Error(`Multiple profiles found in bundle and mergeStrategy.profiles is 'error'`);
|
|
749
|
+
} else if (strategy.profiles === "first-wins") {
|
|
750
|
+
profilesForCompile = [resolved.profiles[0]];
|
|
751
|
+
} else {
|
|
752
|
+
profilesForCompile = [resolved.profiles[resolved.profiles.length - 1]];
|
|
753
|
+
}
|
|
754
|
+
for (const profile of profilesForCompile) {
|
|
755
|
+
payloads.push(compileProfileDocument(profile));
|
|
756
|
+
}
|
|
757
|
+
if (resolved.layouts.length > 0) {
|
|
758
|
+
const layoutsDoc = {
|
|
759
|
+
type: "layouts",
|
|
760
|
+
payload: resolved.layouts
|
|
761
|
+
};
|
|
762
|
+
payloads.push(compileLayoutsDocument(layoutsDoc));
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (resolved.profiles.length === 0) {
|
|
766
|
+
if (resolved.users.length > 0) {
|
|
767
|
+
const usersDoc = {
|
|
768
|
+
type: "users",
|
|
769
|
+
payload: resolved.users
|
|
770
|
+
};
|
|
771
|
+
payloads.push(compileUsersDocument(usersDoc));
|
|
772
|
+
}
|
|
773
|
+
if (resolved.layouts.length > 0) {
|
|
774
|
+
const layoutsDoc = {
|
|
775
|
+
type: "layouts",
|
|
776
|
+
payload: resolved.layouts
|
|
777
|
+
};
|
|
778
|
+
payloads.push(compileLayoutsDocument(layoutsDoc));
|
|
779
|
+
}
|
|
780
|
+
} else {
|
|
781
|
+
if (resolved.users.length > 0) {
|
|
782
|
+
const usersDoc = {
|
|
783
|
+
type: "users",
|
|
784
|
+
payload: resolved.users
|
|
785
|
+
};
|
|
786
|
+
payloads.push(compileUsersDocument(usersDoc));
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
return {
|
|
790
|
+
id: "bundle",
|
|
791
|
+
payloads
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
function compileBundleDocumentSync(bundle) {
|
|
795
|
+
for (const item of bundle.documents) {
|
|
796
|
+
if (isDocumentReference(item)) {
|
|
797
|
+
throw new Error("Bundle contains $ref items. Use compileBundleDocument (async) instead.");
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
const result = {
|
|
801
|
+
profiles: [],
|
|
802
|
+
users: [],
|
|
803
|
+
layouts: []
|
|
804
|
+
};
|
|
805
|
+
const strategy = bundle.mergeStrategy ?? {};
|
|
806
|
+
for (const item of bundle.documents) {
|
|
807
|
+
if (isProfileDocument(item)) {
|
|
808
|
+
result.profiles.push(item);
|
|
809
|
+
} else if (isUsersDocument(item)) {
|
|
810
|
+
result.users = mergeUsers(result.users, item.payload ?? [], strategy.users);
|
|
811
|
+
} else if (isLayoutsDocument(item)) {
|
|
812
|
+
result.layouts = mergeLayouts(result.layouts, item.payload ?? [], strategy.layouts);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
const payloads = [];
|
|
816
|
+
if (result.profiles.length > 0) {
|
|
817
|
+
let profilesForCompile;
|
|
818
|
+
if (strategy.profiles === "error" && result.profiles.length > 1) {
|
|
819
|
+
throw new Error(`Multiple profiles found in bundle and mergeStrategy.profiles is 'error'`);
|
|
820
|
+
} else if (strategy.profiles === "first-wins") {
|
|
821
|
+
profilesForCompile = [result.profiles[0]];
|
|
822
|
+
} else {
|
|
823
|
+
profilesForCompile = [result.profiles[result.profiles.length - 1]];
|
|
824
|
+
}
|
|
825
|
+
for (const profile of profilesForCompile) {
|
|
826
|
+
payloads.push(compileProfileDocument(profile));
|
|
827
|
+
}
|
|
828
|
+
if (result.layouts.length > 0) {
|
|
829
|
+
payloads.push(compileLayoutsDocument({ type: "layouts", payload: result.layouts }));
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
if (result.profiles.length === 0) {
|
|
833
|
+
if (result.users.length > 0) {
|
|
834
|
+
payloads.push(compileUsersDocument({ type: "users", payload: result.users }));
|
|
835
|
+
}
|
|
836
|
+
if (result.layouts.length > 0) {
|
|
837
|
+
payloads.push(compileLayoutsDocument({ type: "layouts", payload: result.layouts }));
|
|
838
|
+
}
|
|
839
|
+
} else {
|
|
840
|
+
if (result.users.length > 0) {
|
|
841
|
+
payloads.push(compileUsersDocument({ type: "users", payload: result.users }));
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
return {
|
|
845
|
+
id: "bundle",
|
|
846
|
+
payloads
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
export {
|
|
851
|
+
isProfileDocument,
|
|
852
|
+
isUsersDocument,
|
|
853
|
+
isLayoutsDocument,
|
|
854
|
+
isBundleDocument,
|
|
855
|
+
isDocumentReference,
|
|
856
|
+
detectDocumentType,
|
|
857
|
+
compileProfileDocument,
|
|
858
|
+
compileUsersDocument,
|
|
859
|
+
compileLayoutsDocument,
|
|
860
|
+
resolveBundle,
|
|
861
|
+
compileBundleDocument,
|
|
862
|
+
compileBundleDocumentSync
|
|
863
|
+
};
|