@outbuild-company/schedule-core 1.10.4 → 1.12.0
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 +91 -162
- package/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +1692 -795
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1556 -191
- package/dist/index.d.ts +1556 -191
- package/dist/index.js +1669 -796
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,679 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var WORK_TIME_DIRECTION = {
|
|
3
|
+
FUTURE: "future",
|
|
4
|
+
PAST: "past"
|
|
5
|
+
};
|
|
6
|
+
var CALENDAR_UNIT = {
|
|
7
|
+
HOUR: "hour",
|
|
8
|
+
DAY: "day"
|
|
9
|
+
};
|
|
10
|
+
var ACTIVITY_PONDERATOR_CRITERION = {
|
|
11
|
+
DURATION: "DURATION",
|
|
12
|
+
COST: "COST",
|
|
13
|
+
WORK_HOURS: "HH"
|
|
14
|
+
};
|
|
15
|
+
var STATUS_CRITERIA = {
|
|
16
|
+
BASELINE: "Baseline",
|
|
17
|
+
ACTUAL: "Actual"
|
|
18
|
+
};
|
|
19
|
+
var STATUS = {
|
|
20
|
+
DONE: "Done",
|
|
21
|
+
OVERDUE: "Overdue",
|
|
22
|
+
ADVANCEMENT: "Advancement",
|
|
23
|
+
WAITING: "Waiting",
|
|
24
|
+
DOING: "Doing"
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// src/constraints/index.ts
|
|
28
|
+
var CONSTRAINT_TYPE = {
|
|
29
|
+
ASAP: "asap",
|
|
30
|
+
ALAP: "alap",
|
|
31
|
+
SNET: "snet",
|
|
32
|
+
SNLT: "snlt",
|
|
33
|
+
FNET: "fnet",
|
|
34
|
+
FNLT: "fnlt",
|
|
35
|
+
MSO: "mso",
|
|
36
|
+
MFO: "mfo"
|
|
37
|
+
};
|
|
38
|
+
var VIOLATION_RULES = {
|
|
39
|
+
mso: () => true,
|
|
40
|
+
mfo: () => true,
|
|
41
|
+
snlt: (constraint, projected) => constraint < projected,
|
|
42
|
+
snet: (constraint, projected) => constraint > projected,
|
|
43
|
+
fnlt: (constraint, projected) => constraint < projected,
|
|
44
|
+
fnet: (constraint, projected) => constraint > projected
|
|
45
|
+
};
|
|
46
|
+
function checkConstraintViolation(constraintType, constraintDate, projectedDate) {
|
|
47
|
+
if (!constraintDate) return { violated: false };
|
|
48
|
+
const rule = VIOLATION_RULES[constraintType];
|
|
49
|
+
if (!rule) return { violated: false };
|
|
50
|
+
if (rule(constraintDate, projectedDate)) {
|
|
51
|
+
return { violated: true, constraintType, constraintDate };
|
|
52
|
+
}
|
|
53
|
+
return { violated: false };
|
|
54
|
+
}
|
|
55
|
+
var START_BASED_CONSTRAINTS = /* @__PURE__ */ new Set([
|
|
56
|
+
"mso",
|
|
57
|
+
"snet",
|
|
58
|
+
"snlt"
|
|
59
|
+
]);
|
|
60
|
+
function pickProjectedDateForConstraint(constraintType, projectedStart, projectedEnd) {
|
|
61
|
+
return START_BASED_CONSTRAINTS.has(constraintType) ? projectedStart : projectedEnd;
|
|
62
|
+
}
|
|
63
|
+
function buildConstraintNotification(constraintType, constraintDate, projectedDate) {
|
|
64
|
+
return {
|
|
65
|
+
type: "constraint",
|
|
66
|
+
messageKey: "constraint_violation",
|
|
67
|
+
data: {
|
|
68
|
+
constraintType,
|
|
69
|
+
constraintDate,
|
|
70
|
+
...projectedDate ? { projectedDate } : {}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
var CONSTRAINT_CASES = {
|
|
75
|
+
snet: { startOfDay: true, direction: WORK_TIME_DIRECTION.FUTURE },
|
|
76
|
+
snlt: { startOfDay: true, direction: WORK_TIME_DIRECTION.PAST },
|
|
77
|
+
fnet: { startOfDay: false, direction: WORK_TIME_DIRECTION.FUTURE },
|
|
78
|
+
fnlt: { startOfDay: false, direction: WORK_TIME_DIRECTION.PAST },
|
|
79
|
+
mso: { startOfDay: true, direction: WORK_TIME_DIRECTION.FUTURE },
|
|
80
|
+
mfo: { startOfDay: false, direction: WORK_TIME_DIRECTION.PAST }
|
|
81
|
+
};
|
|
82
|
+
var startOfUtcDay = (d) => new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
|
|
83
|
+
var addUtcDays = (d, n) => new Date(d.getTime() + n * 864e5);
|
|
84
|
+
var sameUtcDay = (a, b) => a.getUTCFullYear() === b.getUTCFullYear() && a.getUTCMonth() === b.getUTCMonth() && a.getUTCDate() === b.getUTCDate();
|
|
85
|
+
function getEffectiveConstraintDate(activity, adapter) {
|
|
86
|
+
if (!activity.constraintDate || !activity.constraintType) return null;
|
|
87
|
+
const config = CONSTRAINT_CASES[activity.constraintType];
|
|
88
|
+
if (!config) return activity.constraintDate;
|
|
89
|
+
const cd = activity.constraintDate;
|
|
90
|
+
const firstWorkOfDay = adapter.getClosestWorkTime({
|
|
91
|
+
date: startOfUtcDay(cd),
|
|
92
|
+
dir: WORK_TIME_DIRECTION.FUTURE,
|
|
93
|
+
task: activity
|
|
94
|
+
});
|
|
95
|
+
if (sameUtcDay(firstWorkOfDay, cd)) {
|
|
96
|
+
if (cd.getTime() !== startOfUtcDay(cd).getTime()) return cd;
|
|
97
|
+
if (config.startOfDay) return firstWorkOfDay;
|
|
98
|
+
return adapter.getClosestWorkTime({
|
|
99
|
+
date: addUtcDays(startOfUtcDay(cd), 1),
|
|
100
|
+
dir: WORK_TIME_DIRECTION.PAST,
|
|
101
|
+
task: activity
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const effectiveMidnight = startOfUtcDay(
|
|
105
|
+
adapter.getClosestWorkTime({
|
|
106
|
+
date: cd,
|
|
107
|
+
dir: config.direction,
|
|
108
|
+
task: activity
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
if (config.startOfDay) {
|
|
112
|
+
return adapter.getClosestWorkTime({
|
|
113
|
+
date: effectiveMidnight,
|
|
114
|
+
dir: WORK_TIME_DIRECTION.FUTURE,
|
|
115
|
+
task: activity
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return adapter.getClosestWorkTime({
|
|
119
|
+
date: addUtcDays(effectiveMidnight, 1),
|
|
120
|
+
dir: WORK_TIME_DIRECTION.PAST,
|
|
121
|
+
task: activity
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function computeConstraintBounds(activity, adapter) {
|
|
125
|
+
const empty = {
|
|
126
|
+
earliestStart: null,
|
|
127
|
+
latestStart: null,
|
|
128
|
+
earliestEnd: null,
|
|
129
|
+
latestEnd: null
|
|
130
|
+
};
|
|
131
|
+
const type = activity.constraintType;
|
|
132
|
+
if (!type || type === "asap" || type === "alap") return empty;
|
|
133
|
+
const constraintDate = getEffectiveConstraintDate(activity, adapter);
|
|
134
|
+
if (!constraintDate) return empty;
|
|
135
|
+
const endFromStart = (start) => adapter.calculateEndDate({
|
|
136
|
+
startDate: start,
|
|
137
|
+
durationHours: activity.durationHours,
|
|
138
|
+
task: activity
|
|
139
|
+
});
|
|
140
|
+
const startFromEnd = (end) => adapter.calculateEndDate({
|
|
141
|
+
startDate: end,
|
|
142
|
+
durationHours: -activity.durationHours,
|
|
143
|
+
task: activity
|
|
144
|
+
});
|
|
145
|
+
switch (type) {
|
|
146
|
+
case "snet":
|
|
147
|
+
return {
|
|
148
|
+
earliestStart: constraintDate,
|
|
149
|
+
latestStart: null,
|
|
150
|
+
earliestEnd: endFromStart(constraintDate),
|
|
151
|
+
latestEnd: null
|
|
152
|
+
};
|
|
153
|
+
case "snlt":
|
|
154
|
+
return {
|
|
155
|
+
earliestStart: null,
|
|
156
|
+
latestStart: constraintDate,
|
|
157
|
+
earliestEnd: null,
|
|
158
|
+
latestEnd: endFromStart(constraintDate)
|
|
159
|
+
};
|
|
160
|
+
case "fnet":
|
|
161
|
+
return {
|
|
162
|
+
earliestStart: startFromEnd(constraintDate),
|
|
163
|
+
latestStart: null,
|
|
164
|
+
earliestEnd: constraintDate,
|
|
165
|
+
latestEnd: null
|
|
166
|
+
};
|
|
167
|
+
case "fnlt":
|
|
168
|
+
return {
|
|
169
|
+
earliestStart: null,
|
|
170
|
+
latestStart: startFromEnd(constraintDate),
|
|
171
|
+
earliestEnd: null,
|
|
172
|
+
latestEnd: constraintDate
|
|
173
|
+
};
|
|
174
|
+
case "mso": {
|
|
175
|
+
const end = endFromStart(constraintDate);
|
|
176
|
+
return {
|
|
177
|
+
earliestStart: constraintDate,
|
|
178
|
+
latestStart: constraintDate,
|
|
179
|
+
earliestEnd: end,
|
|
180
|
+
latestEnd: end
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
case "mfo": {
|
|
184
|
+
const start = startFromEnd(constraintDate);
|
|
185
|
+
return {
|
|
186
|
+
earliestStart: start,
|
|
187
|
+
latestStart: start,
|
|
188
|
+
earliestEnd: constraintDate,
|
|
189
|
+
latestEnd: constraintDate
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
default:
|
|
193
|
+
return empty;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function isStartWithinBounds(start, bounds) {
|
|
197
|
+
if (bounds.earliestStart && start < bounds.earliestStart) return false;
|
|
198
|
+
if (bounds.latestStart && start > bounds.latestStart) return false;
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
function clampStartToBounds(candidate, bounds) {
|
|
202
|
+
if (bounds.latestStart && candidate > bounds.latestStart) {
|
|
203
|
+
return bounds.latestStart;
|
|
204
|
+
}
|
|
205
|
+
if (bounds.earliestStart && candidate < bounds.earliestStart) {
|
|
206
|
+
return bounds.earliestStart;
|
|
207
|
+
}
|
|
208
|
+
return candidate;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// src/autoscheduler/types.ts
|
|
212
|
+
var LINK_TYPE = {
|
|
213
|
+
FINISH_TO_START: "0",
|
|
214
|
+
START_TO_START: "1",
|
|
215
|
+
FINISH_TO_FINISH: "2",
|
|
216
|
+
START_TO_FINISH: "3"
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// src/constants/columns.ts
|
|
220
|
+
var EDITABLE = {
|
|
221
|
+
TEXT: "text",
|
|
222
|
+
DESCRIPTION: "description",
|
|
223
|
+
DURATION: "duration",
|
|
224
|
+
PROGRESS: "progress",
|
|
225
|
+
COST: "cost",
|
|
226
|
+
USED_COST: "used_cost",
|
|
227
|
+
HH_WORK_TIME: "hhWorkTime",
|
|
228
|
+
START_DATE: "start_date",
|
|
229
|
+
END_DATE: "end_date",
|
|
230
|
+
CONSTRAINT_TYPE: "constraint_type",
|
|
231
|
+
CONSTRAINT_DATE: "constraint_date",
|
|
232
|
+
CALENDAR_ID: "calendar_id",
|
|
233
|
+
CUSTOM_ID: "custom_id",
|
|
234
|
+
SUBCONTRACT_ID: "subcontractId",
|
|
235
|
+
RESPONSABLES: "responsables",
|
|
236
|
+
TAGS: "tags",
|
|
237
|
+
CUSTOM_PREDECESSORS: "custom_predecessors",
|
|
238
|
+
CUSTOM_SUCESSORS: "custom_sucessors"
|
|
239
|
+
};
|
|
240
|
+
var READ_ONLY = {
|
|
241
|
+
REAL_WORK: "real_work",
|
|
242
|
+
REAL_COST: "real_cost",
|
|
243
|
+
EXPECTED_PROGRESS: "expected_progress",
|
|
244
|
+
EXPECTED_PROGRESS_BASE: "expected_progress_base",
|
|
245
|
+
START_BASE: "start_base",
|
|
246
|
+
END_BASE: "end_base",
|
|
247
|
+
DURATION_BASE: "duration_base",
|
|
248
|
+
COST_BASE: "cost_base",
|
|
249
|
+
WORK_BASE: "work_base",
|
|
250
|
+
CALENDAR_DURATION: "calendarDuration",
|
|
251
|
+
IS_CRITICAL: "is_critical",
|
|
252
|
+
EARLY_START: "earlyStart",
|
|
253
|
+
EARLY_FINISH: "earlyFinish",
|
|
254
|
+
LATE_START: "lateStart",
|
|
255
|
+
LATE_FINISH: "lateFinish",
|
|
256
|
+
FREE_SLACK: "freeSlack",
|
|
257
|
+
TOTAL_SLACK: "totalSlack",
|
|
258
|
+
CORRELATIVE_ID: "correlative_id",
|
|
259
|
+
UNIQUE_CORRELATIVE_ID: "unique_correlative_id",
|
|
260
|
+
PONDERATOR: "ponderator",
|
|
261
|
+
STATUS: "status"
|
|
262
|
+
};
|
|
263
|
+
var COLUMN = { ...EDITABLE, ...READ_ONLY };
|
|
264
|
+
|
|
265
|
+
// src/autoscheduler/links/types.ts
|
|
266
|
+
var LINK_OPERATION_KIND = {
|
|
267
|
+
CREATE: "create",
|
|
268
|
+
UPDATE: "update",
|
|
269
|
+
DELETE: "delete"
|
|
270
|
+
};
|
|
271
|
+
var LINK_REJECTION_REASON = {
|
|
272
|
+
SELF_LINK: "self-link",
|
|
273
|
+
CYCLE: "cycle",
|
|
274
|
+
DUPLICATE: "duplicate",
|
|
275
|
+
ACTIVITY_MISSING: "activity-missing",
|
|
276
|
+
LINK_MISSING: "link-missing",
|
|
277
|
+
HIERARCHY_LINK: "hierarchy-link"
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// src/dispatch/action-kinds.ts
|
|
281
|
+
var DISPATCH_ACTION_KIND = {
|
|
282
|
+
ACTIVITY_CLIPBOARD_CLEAR: "activity-clipboard-clear",
|
|
283
|
+
ACTIVITY_COPY: "activity-copy",
|
|
284
|
+
CALENDAR_RECONCILE: "calendar-reconcile",
|
|
285
|
+
ACTIVITY_PASTE_COPIED: "activity-paste-copied",
|
|
286
|
+
PERSISTENCE_ACKNOWLEDGE: "persistence-acknowledge",
|
|
287
|
+
BASELINE_APPLY: "baseline-apply",
|
|
288
|
+
PONDERATOR_CRITERION_SET: "ponderator-criterion-set",
|
|
289
|
+
STATUS_CRITERIA_SET: "status-criteria-set",
|
|
290
|
+
INLINE_EDIT: "inline-edit",
|
|
291
|
+
DATES_BATCH: "dates-batch",
|
|
292
|
+
BULK_EDIT: "bulk-edit",
|
|
293
|
+
LINK_CREATE: "link-create",
|
|
294
|
+
LINK_UPDATE: "link-update",
|
|
295
|
+
LINK_DELETE: "link-delete",
|
|
296
|
+
LINKS_BATCH: "links-batch",
|
|
297
|
+
ACTIVITY_CREATE: "activity-create",
|
|
298
|
+
ACTIVITY_DELETE: "activity-delete",
|
|
299
|
+
ACTIVITY_MOVE: "activity-move",
|
|
300
|
+
ACTIVITY_INDENT: "activity-indent",
|
|
301
|
+
ACTIVITY_OUTDENT: "activity-outdent",
|
|
302
|
+
ACTIVITY_SET_PROGRESS: "activity-set-progress",
|
|
303
|
+
SELECTION_TOGGLE: "selection-toggle",
|
|
304
|
+
SELECTION_REPLACE: "selection-replace",
|
|
305
|
+
VISIBILITY_SET: "visibility-set",
|
|
306
|
+
FILTER_SET: "filter-set",
|
|
307
|
+
SORT_SET: "sort-set",
|
|
308
|
+
SIR_SYNC: "sir-sync",
|
|
309
|
+
ACTIVITY_LOOKAHEAD_SYNC: "activity-lookahead-sync"
|
|
310
|
+
};
|
|
311
|
+
var ACTIVITY_BATCH_ACTION_KIND = "activity-batch";
|
|
312
|
+
var DISPATCH_LINK_OPERATION_KIND = LINK_OPERATION_KIND;
|
|
313
|
+
var DISPATCH_ACTION_KINDS = Object.values(DISPATCH_ACTION_KIND);
|
|
314
|
+
|
|
315
|
+
// src/propagations/shared/get-active-baseline.ts
|
|
316
|
+
function getActiveBaseline(activity) {
|
|
317
|
+
const points = activity?.baselinePoints;
|
|
318
|
+
if (!Array.isArray(points) || points.length === 0) return null;
|
|
319
|
+
return points.find((point) => point.isActiveVersion) ?? null;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// src/api/types.ts
|
|
323
|
+
var ACTIVITY_FIELD = {
|
|
324
|
+
NAME: "name",
|
|
325
|
+
DESCRIPTION: "description",
|
|
326
|
+
DURATION_DAYS: "durationDays",
|
|
327
|
+
PROGRESS: "progress",
|
|
328
|
+
COST: "cost",
|
|
329
|
+
USED_COST: "usedCost",
|
|
330
|
+
WORK_HOURS: "workHours",
|
|
331
|
+
START_DATE: "startDate",
|
|
332
|
+
END_DATE: "endDate",
|
|
333
|
+
CONSTRAINT_TYPE: "constraintType",
|
|
334
|
+
CONSTRAINT_DATE: "constraintDate",
|
|
335
|
+
CALENDAR_ID: "calendarId",
|
|
336
|
+
CUSTOM_ID: "customId",
|
|
337
|
+
SUBCONTRACT_ID: "subcontractId",
|
|
338
|
+
RESPONSABLE_IDS: "responsableIds",
|
|
339
|
+
TAG_IDS: "tagIds"
|
|
340
|
+
};
|
|
341
|
+
var ACTIVITY_DATE_EDGE = {
|
|
342
|
+
START: "start",
|
|
343
|
+
END: "end"
|
|
344
|
+
};
|
|
345
|
+
var LINK_RELATIONSHIP = {
|
|
346
|
+
FINISH_TO_START: "finish-to-start",
|
|
347
|
+
START_TO_START: "start-to-start",
|
|
348
|
+
FINISH_TO_FINISH: "finish-to-finish",
|
|
349
|
+
START_TO_FINISH: "start-to-finish"
|
|
350
|
+
};
|
|
351
|
+
var LINK_BATCH_OPERATION_KIND = {
|
|
352
|
+
CREATE: "create",
|
|
353
|
+
UPDATE: "update",
|
|
354
|
+
REMOVE: "remove"
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
// src/api/activity-fields.ts
|
|
358
|
+
var ACTIVITY_EDIT_COLUMNS = {
|
|
359
|
+
[ACTIVITY_FIELD.NAME]: COLUMN.TEXT,
|
|
360
|
+
[ACTIVITY_FIELD.DESCRIPTION]: COLUMN.DESCRIPTION,
|
|
361
|
+
[ACTIVITY_FIELD.DURATION_DAYS]: COLUMN.DURATION,
|
|
362
|
+
[ACTIVITY_FIELD.PROGRESS]: COLUMN.PROGRESS,
|
|
363
|
+
[ACTIVITY_FIELD.COST]: COLUMN.COST,
|
|
364
|
+
[ACTIVITY_FIELD.USED_COST]: COLUMN.USED_COST,
|
|
365
|
+
[ACTIVITY_FIELD.WORK_HOURS]: COLUMN.HH_WORK_TIME,
|
|
366
|
+
[ACTIVITY_FIELD.START_DATE]: COLUMN.START_DATE,
|
|
367
|
+
[ACTIVITY_FIELD.END_DATE]: COLUMN.END_DATE,
|
|
368
|
+
[ACTIVITY_FIELD.CONSTRAINT_TYPE]: COLUMN.CONSTRAINT_TYPE,
|
|
369
|
+
[ACTIVITY_FIELD.CONSTRAINT_DATE]: COLUMN.CONSTRAINT_DATE,
|
|
370
|
+
[ACTIVITY_FIELD.CALENDAR_ID]: COLUMN.CALENDAR_ID,
|
|
371
|
+
[ACTIVITY_FIELD.CUSTOM_ID]: COLUMN.CUSTOM_ID,
|
|
372
|
+
[ACTIVITY_FIELD.SUBCONTRACT_ID]: COLUMN.SUBCONTRACT_ID,
|
|
373
|
+
[ACTIVITY_FIELD.RESPONSABLE_IDS]: COLUMN.RESPONSABLES,
|
|
374
|
+
[ACTIVITY_FIELD.TAG_IDS]: COLUMN.TAGS
|
|
375
|
+
};
|
|
376
|
+
function activityEditToColumnEdit(activityId, edit) {
|
|
377
|
+
return {
|
|
378
|
+
activityId,
|
|
379
|
+
column: ACTIVITY_EDIT_COLUMNS[edit.field],
|
|
380
|
+
newValue: edit.value
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/api/schedule-api.ts
|
|
385
|
+
var LINK_TYPES = {
|
|
386
|
+
[LINK_RELATIONSHIP.FINISH_TO_START]: LINK_TYPE.FINISH_TO_START,
|
|
387
|
+
[LINK_RELATIONSHIP.START_TO_START]: LINK_TYPE.START_TO_START,
|
|
388
|
+
[LINK_RELATIONSHIP.FINISH_TO_FINISH]: LINK_TYPE.FINISH_TO_FINISH,
|
|
389
|
+
[LINK_RELATIONSHIP.START_TO_FINISH]: LINK_TYPE.START_TO_FINISH
|
|
390
|
+
};
|
|
391
|
+
function linkType(relationship) {
|
|
392
|
+
return LINK_TYPES[relationship];
|
|
393
|
+
}
|
|
394
|
+
function batchLink(operation) {
|
|
395
|
+
if (operation.kind === LINK_BATCH_OPERATION_KIND.CREATE) {
|
|
396
|
+
return {
|
|
397
|
+
kind: DISPATCH_LINK_OPERATION_KIND.CREATE,
|
|
398
|
+
source: operation.sourceId,
|
|
399
|
+
target: operation.targetId,
|
|
400
|
+
type: linkType(operation.relationship),
|
|
401
|
+
...operation.lagDays === void 0 ? {} : { lag: operation.lagDays },
|
|
402
|
+
...operation.linkId === void 0 ? {} : { linkId: operation.linkId }
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
if (operation.kind === LINK_BATCH_OPERATION_KIND.UPDATE) {
|
|
406
|
+
return {
|
|
407
|
+
kind: DISPATCH_LINK_OPERATION_KIND.UPDATE,
|
|
408
|
+
linkId: operation.linkId,
|
|
409
|
+
...operation.relationship === void 0 ? {} : { type: linkType(operation.relationship) },
|
|
410
|
+
...operation.lagDays === void 0 ? {} : { lag: operation.lagDays }
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
if (operation.kind === LINK_BATCH_OPERATION_KIND.REMOVE) {
|
|
414
|
+
return {
|
|
415
|
+
kind: DISPATCH_LINK_OPERATION_KIND.DELETE,
|
|
416
|
+
linkId: operation.linkId
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
return operation;
|
|
420
|
+
}
|
|
421
|
+
function activityDateColumn(edge) {
|
|
422
|
+
if (edge === ACTIVITY_DATE_EDGE.START) return COLUMN.START_DATE;
|
|
423
|
+
if (edge === ACTIVITY_DATE_EDGE.END) return COLUMN.END_DATE;
|
|
424
|
+
return edge;
|
|
425
|
+
}
|
|
426
|
+
function activityBatch(input) {
|
|
427
|
+
return {
|
|
428
|
+
kind: ACTIVITY_BATCH_ACTION_KIND,
|
|
429
|
+
mode: input.mode,
|
|
430
|
+
items: input.items,
|
|
431
|
+
links: input.links.map((link) => ({
|
|
432
|
+
source: link.source,
|
|
433
|
+
target: link.target,
|
|
434
|
+
type: linkType(link.relationship),
|
|
435
|
+
...link.lagDays === void 0 ? {} : { lag: link.lagDays },
|
|
436
|
+
...link.linkId === void 0 ? {} : { linkId: link.linkId }
|
|
437
|
+
})),
|
|
438
|
+
...input.eventSource === void 0 ? {} : { eventSource: input.eventSource }
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
function createActivitiesApi(engine) {
|
|
442
|
+
return {
|
|
443
|
+
get: (id) => engine.getActivityView(id),
|
|
444
|
+
list: () => engine.getAllActivitiesView(),
|
|
445
|
+
ids: () => engine.getAllIds(),
|
|
446
|
+
forEachId: (visit) => engine.forEachActivityId(visit),
|
|
447
|
+
property: (id, property) => engine.getProperty(id, property),
|
|
448
|
+
children: (parentId) => engine.getChildrenView(parentId),
|
|
449
|
+
childIds: (parentId) => engine.getChildrenIds(parentId),
|
|
450
|
+
hasChildren: (parentId) => engine.hasChild(parentId),
|
|
451
|
+
indentTargetParentIds: (ids) => engine.getIndentTargetParentIds(ids),
|
|
452
|
+
isCustomIdInUse: (customId, currentCustomId) => engine.isCustomIdInUse(customId, currentCustomId ?? null),
|
|
453
|
+
create: (input, options) => engine.dispatch(
|
|
454
|
+
{ ...input, kind: DISPATCH_ACTION_KIND.ACTIVITY_CREATE },
|
|
455
|
+
options
|
|
456
|
+
),
|
|
457
|
+
applyBatch: (input, options) => engine.applyActivityBatch(activityBatch(input), options),
|
|
458
|
+
editInline: (activityId, edit, options) => engine.dispatch(
|
|
459
|
+
{
|
|
460
|
+
...activityEditToColumnEdit(activityId, edit),
|
|
461
|
+
kind: DISPATCH_ACTION_KIND.INLINE_EDIT
|
|
462
|
+
},
|
|
463
|
+
options
|
|
464
|
+
),
|
|
465
|
+
applyDragBatch: (edits, options) => engine.dispatch(
|
|
466
|
+
{
|
|
467
|
+
kind: DISPATCH_ACTION_KIND.DATES_BATCH,
|
|
468
|
+
edits: edits.map((edit) => ({
|
|
469
|
+
activityId: edit.activityId,
|
|
470
|
+
column: activityDateColumn(edit.edge),
|
|
471
|
+
newValue: edit.value
|
|
472
|
+
}))
|
|
473
|
+
},
|
|
474
|
+
options
|
|
475
|
+
),
|
|
476
|
+
editFields: (edits, options) => engine.dispatch(
|
|
477
|
+
{
|
|
478
|
+
kind: DISPATCH_ACTION_KIND.BULK_EDIT,
|
|
479
|
+
edits: edits.map(
|
|
480
|
+
(edit) => activityEditToColumnEdit(edit.activityId, edit)
|
|
481
|
+
)
|
|
482
|
+
},
|
|
483
|
+
options
|
|
484
|
+
),
|
|
485
|
+
remove: (activityIds, context = {}) => engine.dispatch({
|
|
486
|
+
...context,
|
|
487
|
+
kind: DISPATCH_ACTION_KIND.ACTIVITY_DELETE,
|
|
488
|
+
activityIds
|
|
489
|
+
}),
|
|
490
|
+
move: (input, options) => engine.dispatch(
|
|
491
|
+
{ ...input, kind: DISPATCH_ACTION_KIND.ACTIVITY_MOVE },
|
|
492
|
+
options
|
|
493
|
+
),
|
|
494
|
+
indent: (activityIds, context = {}) => engine.dispatch({
|
|
495
|
+
...context,
|
|
496
|
+
kind: DISPATCH_ACTION_KIND.ACTIVITY_INDENT,
|
|
497
|
+
activityIds
|
|
498
|
+
}),
|
|
499
|
+
outdent: (activityIds, context = {}) => engine.dispatch({
|
|
500
|
+
...context,
|
|
501
|
+
kind: DISPATCH_ACTION_KIND.ACTIVITY_OUTDENT,
|
|
502
|
+
activityIds
|
|
503
|
+
}),
|
|
504
|
+
setProgress: (activityId, progress, context = {}) => engine.dispatch({
|
|
505
|
+
...context,
|
|
506
|
+
kind: DISPATCH_ACTION_KIND.ACTIVITY_SET_PROGRESS,
|
|
507
|
+
activityId,
|
|
508
|
+
newValue: progress
|
|
509
|
+
}),
|
|
510
|
+
copy: (context = {}) => engine.dispatch({ ...context, kind: DISPATCH_ACTION_KIND.ACTIVITY_COPY }),
|
|
511
|
+
paste: (afterSiblingId, context = {}) => engine.dispatch({
|
|
512
|
+
...context,
|
|
513
|
+
kind: DISPATCH_ACTION_KIND.ACTIVITY_PASTE_COPIED,
|
|
514
|
+
destination: { afterSiblingId }
|
|
515
|
+
}),
|
|
516
|
+
clearClipboard: (context = {}) => engine.dispatch({
|
|
517
|
+
...context,
|
|
518
|
+
kind: DISPATCH_ACTION_KIND.ACTIVITY_CLIPBOARD_CLEAR
|
|
519
|
+
}),
|
|
520
|
+
lookaheadSync: (input) => engine.dispatch({
|
|
521
|
+
...input,
|
|
522
|
+
kind: DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC
|
|
523
|
+
}),
|
|
524
|
+
createDateGesturePreview: (gesture) => engine.createDateGesturePreview(gesture)
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
function createLinksApi(engine) {
|
|
528
|
+
return {
|
|
529
|
+
get: (id) => engine.getLinkView(id),
|
|
530
|
+
list: () => engine.getAllLinksView(),
|
|
531
|
+
forActivity: (activityId) => engine.getLinksForActivityView(activityId),
|
|
532
|
+
create: (input, options) => engine.dispatch(
|
|
533
|
+
{
|
|
534
|
+
kind: DISPATCH_ACTION_KIND.LINK_CREATE,
|
|
535
|
+
source: input.sourceId,
|
|
536
|
+
target: input.targetId,
|
|
537
|
+
type: linkType(input.relationship),
|
|
538
|
+
...input.lagDays === void 0 ? {} : { lag: input.lagDays },
|
|
539
|
+
...input.linkId === void 0 ? {} : { linkId: input.linkId }
|
|
540
|
+
},
|
|
541
|
+
options
|
|
542
|
+
),
|
|
543
|
+
update: (linkId, patch, options) => engine.dispatch(
|
|
544
|
+
{
|
|
545
|
+
kind: DISPATCH_ACTION_KIND.LINK_UPDATE,
|
|
546
|
+
linkId,
|
|
547
|
+
...patch.relationship === void 0 ? {} : { type: linkType(patch.relationship) },
|
|
548
|
+
...patch.lagDays === void 0 ? {} : { lag: patch.lagDays }
|
|
549
|
+
},
|
|
550
|
+
options
|
|
551
|
+
),
|
|
552
|
+
remove: (linkId, options) => engine.dispatch(
|
|
553
|
+
{ kind: DISPATCH_ACTION_KIND.LINK_DELETE, linkId },
|
|
554
|
+
options
|
|
555
|
+
),
|
|
556
|
+
batch: (operations, options) => engine.dispatch(
|
|
557
|
+
{
|
|
558
|
+
kind: DISPATCH_ACTION_KIND.LINKS_BATCH,
|
|
559
|
+
operations: operations.map(batchLink)
|
|
560
|
+
},
|
|
561
|
+
options
|
|
562
|
+
)
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
function createScheduleNamespaces(engine) {
|
|
566
|
+
const applyBaselinePoints2 = (points, options) => engine.dispatch(
|
|
567
|
+
{ kind: DISPATCH_ACTION_KIND.BASELINE_APPLY, points },
|
|
568
|
+
options
|
|
569
|
+
);
|
|
570
|
+
return {
|
|
571
|
+
activities: createActivitiesApi(engine),
|
|
572
|
+
links: createLinksApi(engine),
|
|
573
|
+
calendars: {
|
|
574
|
+
get: (id) => engine.getCalendar(id),
|
|
575
|
+
list: () => engine.getAllCalendars(),
|
|
576
|
+
listBase: () => engine.getBaseCalendars(),
|
|
577
|
+
projectWorkHours: () => engine.getProjectWorkHours(),
|
|
578
|
+
reconcile: (options) => engine.dispatch(
|
|
579
|
+
{ kind: DISPATCH_ACTION_KIND.CALENDAR_RECONCILE },
|
|
580
|
+
options
|
|
581
|
+
)
|
|
582
|
+
},
|
|
583
|
+
selection: {
|
|
584
|
+
ids: () => engine.getSelectedActivityIds(),
|
|
585
|
+
toggle: ({ checked, ...input }) => engine.dispatch({
|
|
586
|
+
...input,
|
|
587
|
+
kind: DISPATCH_ACTION_KIND.SELECTION_TOGGLE,
|
|
588
|
+
isChecked: checked
|
|
589
|
+
}),
|
|
590
|
+
replace: (activityIds, context = {}) => engine.dispatch({
|
|
591
|
+
...context,
|
|
592
|
+
kind: DISPATCH_ACTION_KIND.SELECTION_REPLACE,
|
|
593
|
+
activityIds
|
|
594
|
+
})
|
|
595
|
+
},
|
|
596
|
+
view: {
|
|
597
|
+
hiddenActivityIds: () => engine.getHiddenActivityIds(),
|
|
598
|
+
visibleActivityIds: () => engine.getVisibleActivityIds(),
|
|
599
|
+
visualOrderIds: () => engine.getVisualOrderIds(),
|
|
600
|
+
filter: () => engine.getActiveFilter(),
|
|
601
|
+
setFilter: (input) => engine.dispatch({ ...input, kind: DISPATCH_ACTION_KIND.FILTER_SET }),
|
|
602
|
+
order: () => engine.getActiveOrder(),
|
|
603
|
+
setOrder: (rules, context = {}) => engine.dispatch({
|
|
604
|
+
...context,
|
|
605
|
+
kind: DISPATCH_ACTION_KIND.SORT_SET,
|
|
606
|
+
rules
|
|
607
|
+
}),
|
|
608
|
+
setVisibility: (activityIds, context = {}) => engine.dispatch({
|
|
609
|
+
...context,
|
|
610
|
+
kind: DISPATCH_ACTION_KIND.VISIBILITY_SET,
|
|
611
|
+
visibleIds: activityIds
|
|
612
|
+
}),
|
|
613
|
+
setStatusCriteria: (criteria, options) => engine.dispatch(
|
|
614
|
+
{ kind: DISPATCH_ACTION_KIND.STATUS_CRITERIA_SET, criteria },
|
|
615
|
+
options
|
|
616
|
+
)
|
|
617
|
+
},
|
|
618
|
+
baselines: {
|
|
619
|
+
refresh: applyBaselinePoints2,
|
|
620
|
+
setVisibility: applyBaselinePoints2,
|
|
621
|
+
setPonderatorCriterion: (criterion, options) => engine.dispatch(
|
|
622
|
+
{ kind: DISPATCH_ACTION_KIND.PONDERATOR_CRITERION_SET, criterion },
|
|
623
|
+
options
|
|
624
|
+
),
|
|
625
|
+
activeFor: (activity) => getActiveBaseline(activity)
|
|
626
|
+
},
|
|
627
|
+
impactRequests: {
|
|
628
|
+
sync: (input) => engine.dispatch({ ...input, kind: DISPATCH_ACTION_KIND.SIR_SYNC })
|
|
629
|
+
},
|
|
630
|
+
persistence: {
|
|
631
|
+
hasChanges: () => engine.hasUnsavedChanges(),
|
|
632
|
+
modifiedActivities: () => engine.getModifiedActivities(),
|
|
633
|
+
modifiedActivityFields: () => engine.getModifiedActivityFields(),
|
|
634
|
+
newActivities: () => engine.getNewActivities(),
|
|
635
|
+
deletedActivities: () => engine.getDeletedActivitiesSinceLastSave(),
|
|
636
|
+
modifiedLinks: () => engine.getModifiedLinks(),
|
|
637
|
+
newLinks: () => engine.getNewLinks(),
|
|
638
|
+
deletedLinks: () => engine.getDeletedLinksSinceLastSave(),
|
|
639
|
+
captureHistoryBoundary: () => engine.capturePersistenceHistoryBoundary(),
|
|
640
|
+
readSnapshot: () => ({
|
|
641
|
+
activities: engine.getAllActivitiesView(),
|
|
642
|
+
links: engine.getAllLinksView(),
|
|
643
|
+
historyBoundary: engine.capturePersistenceHistoryBoundary()
|
|
644
|
+
}),
|
|
645
|
+
acknowledge: (checkpoint) => engine.dispatch({
|
|
646
|
+
kind: DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE,
|
|
647
|
+
checkpoint
|
|
648
|
+
})
|
|
649
|
+
},
|
|
650
|
+
history: {
|
|
651
|
+
undo: (options) => engine.undo(options),
|
|
652
|
+
redo: (options) => engine.redo(options),
|
|
653
|
+
canUndo: () => engine.canUndo(),
|
|
654
|
+
canRedo: () => engine.canRedo(),
|
|
655
|
+
clear: () => engine.clearHistory(),
|
|
656
|
+
depth: () => engine.undoDepth()
|
|
657
|
+
},
|
|
658
|
+
projection: {
|
|
659
|
+
changeSetFrom: (source) => engine.createProjectionChangeSetFrom(source)
|
|
660
|
+
},
|
|
661
|
+
criticalPath: {
|
|
662
|
+
get ready() {
|
|
663
|
+
return engine.criticalPathReady;
|
|
664
|
+
},
|
|
665
|
+
recompute: () => engine.recomputeCriticalPath(),
|
|
666
|
+
isSettled: () => engine.isCriticalPathSettled(),
|
|
667
|
+
whenSettled: () => engine.whenCriticalPathSettled()
|
|
668
|
+
},
|
|
669
|
+
diagnostics: {
|
|
670
|
+
auditEffectiveGraph: () => engine.auditEffectiveGraph(),
|
|
671
|
+
revision: () => engine.getScheduleRevision(),
|
|
672
|
+
canonicalDigest: () => engine.getCanonicalDigest()
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
1
677
|
// src/shared/queue.ts
|
|
2
678
|
var Queue = class {
|
|
3
679
|
items = [];
|
|
@@ -247,23 +923,105 @@ function dispatchVisibilitySet(action, deps) {
|
|
|
247
923
|
return { ok: true, changes };
|
|
248
924
|
}
|
|
249
925
|
|
|
926
|
+
// src/autoscheduler/constants.ts
|
|
927
|
+
var ACTIVITY_TYPE = {
|
|
928
|
+
TASK: "task",
|
|
929
|
+
PROJECT: "project",
|
|
930
|
+
MILESTONE: "milestone"
|
|
931
|
+
};
|
|
932
|
+
var TIMING = {
|
|
933
|
+
YIELD_SLICE_MS: 8
|
|
934
|
+
};
|
|
935
|
+
|
|
936
|
+
// src/internal/filter/types.ts
|
|
937
|
+
var FILTER_VALUE_KIND = {
|
|
938
|
+
STRING: "string",
|
|
939
|
+
NUMBER: "number",
|
|
940
|
+
DATE: "date",
|
|
941
|
+
ID_ARRAY: "id-array",
|
|
942
|
+
ENUM: "enum",
|
|
943
|
+
BOOLEAN: "boolean",
|
|
944
|
+
REFERENCE: "reference"
|
|
945
|
+
};
|
|
946
|
+
var FILTER_FIELD = {
|
|
947
|
+
NAME: "name",
|
|
948
|
+
DESCRIPTION: "description",
|
|
949
|
+
CUSTOM_ID: "customId",
|
|
950
|
+
CORRELATIVE_ID: "correlativeId",
|
|
951
|
+
UNIQUE_CORRELATIVE_ID: "uniqueCorrelativeId",
|
|
952
|
+
PROGRESS: "progress",
|
|
953
|
+
DURATION_DAYS: "durationDays",
|
|
954
|
+
CALENDAR_DURATION: "calendarDuration",
|
|
955
|
+
COST: "cost",
|
|
956
|
+
USED_COST: "usedCost",
|
|
957
|
+
REAL_COST: "realCost",
|
|
958
|
+
WORK_HOURS: "workHours",
|
|
959
|
+
REAL_WORK_HOURS: "realWorkHours",
|
|
960
|
+
PONDERATOR: "ponderator",
|
|
961
|
+
FREE_SLACK_DAYS: "freeSlackDays",
|
|
962
|
+
TOTAL_SLACK_DAYS: "totalSlackDays",
|
|
963
|
+
EXPECTED_PROGRESS_BASELINE: "expectedProgressBaseline",
|
|
964
|
+
BASELINE_DURATION_DAYS: "baselineDurationDays",
|
|
965
|
+
BASELINE_COST: "baselineCost",
|
|
966
|
+
BASELINE_WORK_HOURS: "baselineWorkHours",
|
|
967
|
+
EXPECTED_PROGRESS: "expectedProgress",
|
|
968
|
+
START_DATE: "startDate",
|
|
969
|
+
END_DATE: "endDate",
|
|
970
|
+
CONSTRAINT_DATE: "constraintDate",
|
|
971
|
+
BASELINE_START_DATE: "baselineStartDate",
|
|
972
|
+
BASELINE_END_DATE: "baselineEndDate",
|
|
973
|
+
EARLY_START: "earlyStart",
|
|
974
|
+
EARLY_FINISH: "earlyFinish",
|
|
975
|
+
LATE_START: "lateStart",
|
|
976
|
+
LATE_FINISH: "lateFinish",
|
|
977
|
+
RESPONSABLE_IDS: "responsableIds",
|
|
978
|
+
TAG_IDS: "tagIds",
|
|
979
|
+
STATUS: "status",
|
|
980
|
+
CONSTRAINT_TYPE: "constraintType",
|
|
981
|
+
CALENDAR_ID: "calendarId",
|
|
982
|
+
SUBCONTRACT_ID: "subcontractId",
|
|
983
|
+
IS_CRITICAL: "isCritical"
|
|
984
|
+
};
|
|
985
|
+
var FILTER_OPERATOR = {
|
|
986
|
+
INCLUDES: "includes",
|
|
987
|
+
NOT_INCLUDES: "notIncludes",
|
|
988
|
+
IS: "is",
|
|
989
|
+
IS_NOT: "isNot",
|
|
990
|
+
EQUALS: "equals",
|
|
991
|
+
NOT_EQUALS: "notEquals",
|
|
992
|
+
GREATER_THAN: "greaterThan",
|
|
993
|
+
LESS_THAN: "lessThan",
|
|
994
|
+
GREATER_OR_EQUAL: "greaterOrEqual",
|
|
995
|
+
LESS_OR_EQUAL: "lessOrEqual",
|
|
996
|
+
AFTER: "after",
|
|
997
|
+
BEFORE: "before",
|
|
998
|
+
BETWEEN: "between",
|
|
999
|
+
SOME_OF: "someOf",
|
|
1000
|
+
NOT_SOME_OF: "notSomeOf"
|
|
1001
|
+
};
|
|
1002
|
+
var FILTER_LOGIC = {
|
|
1003
|
+
AND: "and",
|
|
1004
|
+
OR: "or"
|
|
1005
|
+
};
|
|
1006
|
+
|
|
250
1007
|
// src/internal/filter/field-registry.ts
|
|
1008
|
+
var BASELINE_EXPECTED_PROGRESS_PRECISION = 2;
|
|
251
1009
|
var STATUS_ORDER = [
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
1010
|
+
STATUS.WAITING,
|
|
1011
|
+
STATUS.DONE,
|
|
1012
|
+
STATUS.DOING,
|
|
1013
|
+
STATUS.OVERDUE,
|
|
1014
|
+
STATUS.ADVANCEMENT
|
|
257
1015
|
];
|
|
258
1016
|
var CONSTRAINT_TYPE_ORDER = [
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
1017
|
+
CONSTRAINT_TYPE.MFO,
|
|
1018
|
+
CONSTRAINT_TYPE.MSO,
|
|
1019
|
+
CONSTRAINT_TYPE.SNLT,
|
|
1020
|
+
CONSTRAINT_TYPE.SNET,
|
|
1021
|
+
CONSTRAINT_TYPE.ALAP,
|
|
1022
|
+
CONSTRAINT_TYPE.ASAP,
|
|
1023
|
+
CONSTRAINT_TYPE.FNET,
|
|
1024
|
+
CONSTRAINT_TYPE.FNLT
|
|
267
1025
|
];
|
|
268
1026
|
var MILLISECONDS_PER_DAY = 1e3 * 60 * 60 * 24;
|
|
269
1027
|
function toDays(hours, hoursPerDay) {
|
|
@@ -285,131 +1043,161 @@ function calendarDaySpan(startDate, endDate) {
|
|
|
285
1043
|
return Math.floor((endDay - startDay) / MILLISECONDS_PER_DAY) + 1;
|
|
286
1044
|
}
|
|
287
1045
|
var FIELD_REGISTRY = {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
1046
|
+
[FILTER_FIELD.NAME]: {
|
|
1047
|
+
valueKind: FILTER_VALUE_KIND.STRING,
|
|
1048
|
+
extract: (activity) => activity.name
|
|
1049
|
+
},
|
|
1050
|
+
[FILTER_FIELD.DESCRIPTION]: {
|
|
1051
|
+
valueKind: FILTER_VALUE_KIND.STRING,
|
|
291
1052
|
extract: (activity) => activity.description
|
|
292
1053
|
},
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
1054
|
+
[FILTER_FIELD.CUSTOM_ID]: {
|
|
1055
|
+
valueKind: FILTER_VALUE_KIND.STRING,
|
|
1056
|
+
extract: (activity) => activity.customId
|
|
1057
|
+
},
|
|
1058
|
+
[FILTER_FIELD.CORRELATIVE_ID]: {
|
|
1059
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
296
1060
|
extract: (activity) => activity.correlativeId
|
|
297
1061
|
},
|
|
298
|
-
|
|
299
|
-
valueKind:
|
|
1062
|
+
[FILTER_FIELD.UNIQUE_CORRELATIVE_ID]: {
|
|
1063
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
300
1064
|
extract: (activity) => {
|
|
301
1065
|
const value = Number(activity.uniqueCorrelativeId);
|
|
302
1066
|
return Number.isFinite(value) ? value : null;
|
|
303
1067
|
}
|
|
304
1068
|
},
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
1069
|
+
[FILTER_FIELD.PROGRESS]: {
|
|
1070
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
1071
|
+
extract: (activity) => activity.progress
|
|
1072
|
+
},
|
|
1073
|
+
[FILTER_FIELD.DURATION_DAYS]: {
|
|
1074
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
308
1075
|
extract: (activity, context) => toDays(activity.durationHours, context.hoursPerDay)
|
|
309
1076
|
},
|
|
310
|
-
|
|
311
|
-
valueKind:
|
|
312
|
-
extract: (activity) => activity.type ===
|
|
1077
|
+
[FILTER_FIELD.CALENDAR_DURATION]: {
|
|
1078
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
1079
|
+
extract: (activity) => activity.type === ACTIVITY_TYPE.MILESTONE ? 0 : calendarDaySpan(activity.startDate, activity.endDate)
|
|
1080
|
+
},
|
|
1081
|
+
[FILTER_FIELD.COST]: {
|
|
1082
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
1083
|
+
extract: (activity) => activity.cost
|
|
1084
|
+
},
|
|
1085
|
+
[FILTER_FIELD.USED_COST]: {
|
|
1086
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
1087
|
+
extract: (activity) => activity.usedCost
|
|
313
1088
|
},
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
valueKind:
|
|
1089
|
+
[FILTER_FIELD.REAL_COST]: {
|
|
1090
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
1091
|
+
extract: (activity) => activity.realCost
|
|
1092
|
+
},
|
|
1093
|
+
[FILTER_FIELD.WORK_HOURS]: {
|
|
1094
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
1095
|
+
extract: (activity) => activity.workHours
|
|
1096
|
+
},
|
|
1097
|
+
[FILTER_FIELD.REAL_WORK_HOURS]: {
|
|
1098
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
320
1099
|
extract: (activity) => activity.realWorkHours
|
|
321
1100
|
},
|
|
322
|
-
|
|
323
|
-
valueKind:
|
|
1101
|
+
[FILTER_FIELD.PONDERATOR]: {
|
|
1102
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
324
1103
|
extract: (activity) => activity.ponderator
|
|
325
1104
|
},
|
|
326
|
-
|
|
327
|
-
valueKind:
|
|
1105
|
+
[FILTER_FIELD.FREE_SLACK_DAYS]: {
|
|
1106
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
328
1107
|
extract: (activity, context) => toDays(activity.freeSlackHours, context.hoursPerDay)
|
|
329
1108
|
},
|
|
330
|
-
|
|
331
|
-
valueKind:
|
|
1109
|
+
[FILTER_FIELD.TOTAL_SLACK_DAYS]: {
|
|
1110
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
332
1111
|
extract: (activity, context) => toDays(
|
|
333
1112
|
activity.criticalPath?.totalSlackHours ?? null,
|
|
334
1113
|
context.hoursPerDay
|
|
335
1114
|
)
|
|
336
1115
|
},
|
|
337
|
-
|
|
338
|
-
valueKind:
|
|
339
|
-
equalityPrecision:
|
|
1116
|
+
[FILTER_FIELD.EXPECTED_PROGRESS_BASELINE]: {
|
|
1117
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
1118
|
+
equalityPrecision: BASELINE_EXPECTED_PROGRESS_PRECISION,
|
|
340
1119
|
extract: (activity) => activity.expectedProgressBaseline
|
|
341
1120
|
},
|
|
342
|
-
|
|
343
|
-
valueKind:
|
|
1121
|
+
[FILTER_FIELD.EXPECTED_PROGRESS]: {
|
|
1122
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
344
1123
|
extract: (activity) => activity.expectedProgress
|
|
345
1124
|
},
|
|
346
|
-
|
|
347
|
-
valueKind:
|
|
1125
|
+
[FILTER_FIELD.BASELINE_DURATION_DAYS]: {
|
|
1126
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
348
1127
|
extract: (activity) => activity.baselineSnapshot?.durationDays ?? null
|
|
349
1128
|
},
|
|
350
|
-
|
|
351
|
-
valueKind:
|
|
1129
|
+
[FILTER_FIELD.BASELINE_COST]: {
|
|
1130
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
352
1131
|
extract: (activity) => activity.baselineSnapshot?.cost ?? null
|
|
353
1132
|
},
|
|
354
|
-
|
|
355
|
-
valueKind:
|
|
1133
|
+
[FILTER_FIELD.BASELINE_WORK_HOURS]: {
|
|
1134
|
+
valueKind: FILTER_VALUE_KIND.NUMBER,
|
|
356
1135
|
extract: (activity) => activity.baselineSnapshot?.workHours ?? null
|
|
357
1136
|
},
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
1137
|
+
[FILTER_FIELD.START_DATE]: {
|
|
1138
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
1139
|
+
extract: (activity) => activity.startDate
|
|
1140
|
+
},
|
|
1141
|
+
[FILTER_FIELD.END_DATE]: {
|
|
1142
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
1143
|
+
extract: (activity) => activity.endDate
|
|
1144
|
+
},
|
|
1145
|
+
[FILTER_FIELD.CONSTRAINT_DATE]: {
|
|
1146
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
362
1147
|
extract: (activity) => activity.constraintDate
|
|
363
1148
|
},
|
|
364
|
-
|
|
365
|
-
valueKind:
|
|
1149
|
+
[FILTER_FIELD.BASELINE_START_DATE]: {
|
|
1150
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
366
1151
|
extract: (activity) => activity.baselineSnapshot?.startDate ?? null
|
|
367
1152
|
},
|
|
368
|
-
|
|
369
|
-
valueKind:
|
|
1153
|
+
[FILTER_FIELD.BASELINE_END_DATE]: {
|
|
1154
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
370
1155
|
extract: (activity) => activity.baselineSnapshot?.endDate ?? null
|
|
371
1156
|
},
|
|
372
|
-
|
|
373
|
-
valueKind:
|
|
1157
|
+
[FILTER_FIELD.EARLY_START]: {
|
|
1158
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
374
1159
|
extract: (activity) => activity.criticalPath?.earlyStart ?? null
|
|
375
1160
|
},
|
|
376
|
-
|
|
377
|
-
valueKind:
|
|
1161
|
+
[FILTER_FIELD.EARLY_FINISH]: {
|
|
1162
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
378
1163
|
extract: (activity) => activity.criticalPath?.earlyFinish ?? null
|
|
379
1164
|
},
|
|
380
|
-
|
|
381
|
-
valueKind:
|
|
1165
|
+
[FILTER_FIELD.LATE_START]: {
|
|
1166
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
382
1167
|
extract: (activity) => activity.criticalPath?.lateStart ?? null
|
|
383
1168
|
},
|
|
384
|
-
|
|
385
|
-
valueKind:
|
|
1169
|
+
[FILTER_FIELD.LATE_FINISH]: {
|
|
1170
|
+
valueKind: FILTER_VALUE_KIND.DATE,
|
|
386
1171
|
extract: (activity) => activity.criticalPath?.lateFinish ?? null
|
|
387
1172
|
},
|
|
388
|
-
|
|
389
|
-
valueKind:
|
|
1173
|
+
[FILTER_FIELD.RESPONSABLE_IDS]: {
|
|
1174
|
+
valueKind: FILTER_VALUE_KIND.ID_ARRAY,
|
|
390
1175
|
extract: (activity) => activity.responsableIds
|
|
391
1176
|
},
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
1177
|
+
[FILTER_FIELD.TAG_IDS]: {
|
|
1178
|
+
valueKind: FILTER_VALUE_KIND.ID_ARRAY,
|
|
1179
|
+
extract: (activity) => activity.tagIds
|
|
1180
|
+
},
|
|
1181
|
+
[FILTER_FIELD.STATUS]: {
|
|
1182
|
+
valueKind: FILTER_VALUE_KIND.ENUM,
|
|
395
1183
|
order: STATUS_ORDER,
|
|
396
1184
|
extract: (activity) => activity.status
|
|
397
1185
|
},
|
|
398
|
-
|
|
399
|
-
valueKind:
|
|
1186
|
+
[FILTER_FIELD.CONSTRAINT_TYPE]: {
|
|
1187
|
+
valueKind: FILTER_VALUE_KIND.ENUM,
|
|
400
1188
|
order: CONSTRAINT_TYPE_ORDER,
|
|
401
1189
|
extract: (activity) => activity.constraintType
|
|
402
1190
|
},
|
|
403
|
-
|
|
404
|
-
valueKind:
|
|
1191
|
+
[FILTER_FIELD.CALENDAR_ID]: {
|
|
1192
|
+
valueKind: FILTER_VALUE_KIND.REFERENCE,
|
|
405
1193
|
extract: (activity) => activity.calendarId === null ? null : String(activity.calendarId)
|
|
406
1194
|
},
|
|
407
|
-
|
|
408
|
-
valueKind:
|
|
1195
|
+
[FILTER_FIELD.SUBCONTRACT_ID]: {
|
|
1196
|
+
valueKind: FILTER_VALUE_KIND.REFERENCE,
|
|
409
1197
|
extract: (activity) => activity.subcontractId === null ? null : String(activity.subcontractId)
|
|
410
1198
|
},
|
|
411
|
-
|
|
412
|
-
valueKind:
|
|
1199
|
+
[FILTER_FIELD.IS_CRITICAL]: {
|
|
1200
|
+
valueKind: FILTER_VALUE_KIND.BOOLEAN,
|
|
413
1201
|
extract: (activity) => activity.isCritical
|
|
414
1202
|
}
|
|
415
1203
|
};
|
|
@@ -430,27 +1218,31 @@ function utcDayMs(date2) {
|
|
|
430
1218
|
}
|
|
431
1219
|
function matchString(value, target, operator) {
|
|
432
1220
|
const isAbsent = value === null;
|
|
433
|
-
if (operator ===
|
|
1221
|
+
if (operator === FILTER_OPERATOR.INCLUDES) {
|
|
434
1222
|
return !isAbsent && String(value).toLowerCase().includes(target.toLowerCase());
|
|
435
1223
|
}
|
|
436
|
-
if (operator ===
|
|
1224
|
+
if (operator === FILTER_OPERATOR.NOT_INCLUDES) {
|
|
437
1225
|
return isAbsent || !String(value).toLowerCase().includes(target.toLowerCase());
|
|
438
1226
|
}
|
|
439
|
-
if (operator ===
|
|
440
|
-
|
|
1227
|
+
if (operator === FILTER_OPERATOR.IS) {
|
|
1228
|
+
return !isAbsent && String(value) === target;
|
|
1229
|
+
}
|
|
1230
|
+
if (operator === FILTER_OPERATOR.IS_NOT) {
|
|
1231
|
+
return isAbsent || String(value) !== target;
|
|
1232
|
+
}
|
|
441
1233
|
return false;
|
|
442
1234
|
}
|
|
443
1235
|
function matchNumber(value, target, operator, equalityPrecision) {
|
|
444
1236
|
if (value === null || typeof value !== "number") {
|
|
445
|
-
return operator ===
|
|
1237
|
+
return operator === FILTER_OPERATOR.NOT_EQUALS;
|
|
446
1238
|
}
|
|
447
1239
|
const equalityValue = equalityPrecision === void 0 ? value : Number(value.toFixed(equalityPrecision));
|
|
448
|
-
if (operator ===
|
|
449
|
-
if (operator ===
|
|
450
|
-
if (operator ===
|
|
451
|
-
if (operator ===
|
|
452
|
-
if (operator ===
|
|
453
|
-
if (operator ===
|
|
1240
|
+
if (operator === FILTER_OPERATOR.EQUALS) return equalityValue === target;
|
|
1241
|
+
if (operator === FILTER_OPERATOR.NOT_EQUALS) return equalityValue !== target;
|
|
1242
|
+
if (operator === FILTER_OPERATOR.GREATER_THAN) return value > target;
|
|
1243
|
+
if (operator === FILTER_OPERATOR.LESS_THAN) return value < target;
|
|
1244
|
+
if (operator === FILTER_OPERATOR.GREATER_OR_EQUAL) return value >= target;
|
|
1245
|
+
if (operator === FILTER_OPERATOR.LESS_OR_EQUAL) return value <= target;
|
|
454
1246
|
return false;
|
|
455
1247
|
}
|
|
456
1248
|
function matchNumberBetween(value, minimum, maximum) {
|
|
@@ -460,8 +1252,8 @@ function matchDate(value, target, operator) {
|
|
|
460
1252
|
if (!(value instanceof Date)) return false;
|
|
461
1253
|
const valueDay = utcDayMs(value);
|
|
462
1254
|
const targetDay = utcDayMs(target);
|
|
463
|
-
if (operator ===
|
|
464
|
-
if (operator ===
|
|
1255
|
+
if (operator === FILTER_OPERATOR.AFTER) return valueDay > targetDay;
|
|
1256
|
+
if (operator === FILTER_OPERATOR.BEFORE) return valueDay < targetDay;
|
|
465
1257
|
return false;
|
|
466
1258
|
}
|
|
467
1259
|
function matchDateBetween(value, minimum, maximum) {
|
|
@@ -472,14 +1264,14 @@ function matchDateBetween(value, minimum, maximum) {
|
|
|
472
1264
|
function matchIdArray(value, allowed, operator) {
|
|
473
1265
|
const ids = Array.isArray(value) ? value : [];
|
|
474
1266
|
const intersects = ids.some((id) => allowed.has(String(id)));
|
|
475
|
-
if (operator ===
|
|
476
|
-
if (operator ===
|
|
1267
|
+
if (operator === FILTER_OPERATOR.SOME_OF) return intersects;
|
|
1268
|
+
if (operator === FILTER_OPERATOR.NOT_SOME_OF) return !intersects;
|
|
477
1269
|
return false;
|
|
478
1270
|
}
|
|
479
1271
|
function matchEnum(value, allowed, operator) {
|
|
480
1272
|
const isMember = value !== null && allowed.has(String(value));
|
|
481
|
-
if (operator ===
|
|
482
|
-
if (operator ===
|
|
1273
|
+
if (operator === FILTER_OPERATOR.SOME_OF) return isMember;
|
|
1274
|
+
if (operator === FILTER_OPERATOR.NOT_SOME_OF) return !isMember;
|
|
483
1275
|
return false;
|
|
484
1276
|
}
|
|
485
1277
|
function toAllowedSet(value) {
|
|
@@ -491,15 +1283,15 @@ function matchCriterion(activity, criterion, context) {
|
|
|
491
1283
|
if (descriptor === null) return false;
|
|
492
1284
|
const value = descriptor.extract(activity, context);
|
|
493
1285
|
const { operator } = criterion;
|
|
494
|
-
if (operator ===
|
|
495
|
-
if (descriptor.valueKind ===
|
|
1286
|
+
if (operator === FILTER_OPERATOR.BETWEEN) {
|
|
1287
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.NUMBER) {
|
|
496
1288
|
return matchNumberBetween(
|
|
497
1289
|
value,
|
|
498
1290
|
Number(criterion.value),
|
|
499
1291
|
Number(criterion.valueTo)
|
|
500
1292
|
);
|
|
501
1293
|
}
|
|
502
|
-
if (descriptor.valueKind ===
|
|
1294
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.DATE) {
|
|
503
1295
|
return matchDateBetween(
|
|
504
1296
|
value,
|
|
505
1297
|
toTargetDate(criterion.value),
|
|
@@ -508,10 +1300,10 @@ function matchCriterion(activity, criterion, context) {
|
|
|
508
1300
|
}
|
|
509
1301
|
return false;
|
|
510
1302
|
}
|
|
511
|
-
if (descriptor.valueKind ===
|
|
1303
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.STRING) {
|
|
512
1304
|
return matchString(value, String(criterion.value), operator);
|
|
513
1305
|
}
|
|
514
|
-
if (descriptor.valueKind ===
|
|
1306
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.NUMBER) {
|
|
515
1307
|
return matchNumber(
|
|
516
1308
|
value,
|
|
517
1309
|
Number(criterion.value),
|
|
@@ -519,17 +1311,17 @@ function matchCriterion(activity, criterion, context) {
|
|
|
519
1311
|
descriptor.equalityPrecision
|
|
520
1312
|
);
|
|
521
1313
|
}
|
|
522
|
-
if (descriptor.valueKind ===
|
|
1314
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.DATE) {
|
|
523
1315
|
return matchDate(value, toTargetDate(criterion.value), operator);
|
|
524
1316
|
}
|
|
525
|
-
if (descriptor.valueKind ===
|
|
1317
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.ID_ARRAY) {
|
|
526
1318
|
return matchIdArray(value, toAllowedSet(criterion.value), operator);
|
|
527
1319
|
}
|
|
528
1320
|
return matchEnum(value, toAllowedSet(criterion.value), operator);
|
|
529
1321
|
}
|
|
530
1322
|
function matchesCriteria(activity, filter, context) {
|
|
531
1323
|
if (filter.criteria.length === 0) return true;
|
|
532
|
-
if (filter.logic ===
|
|
1324
|
+
if (filter.logic === FILTER_LOGIC.OR) {
|
|
533
1325
|
return filter.criteria.some(
|
|
534
1326
|
(criterion) => matchCriterion(activity, criterion, context)
|
|
535
1327
|
);
|
|
@@ -684,36 +1476,62 @@ function buildFilterContext(hoursPerDay) {
|
|
|
684
1476
|
}
|
|
685
1477
|
|
|
686
1478
|
// src/internal/filter/validate.ts
|
|
1479
|
+
var FILTER_REJECTION_REASON = {
|
|
1480
|
+
UNKNOWN_FIELD: "unknown_field",
|
|
1481
|
+
UNKNOWN_OPERATOR: "unknown_operator",
|
|
1482
|
+
INVALID_VALUE: "invalid_value"
|
|
1483
|
+
};
|
|
687
1484
|
var OPERATORS_BY_KIND = {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
"lessThan",
|
|
694
|
-
"greaterOrEqual",
|
|
695
|
-
"lessOrEqual",
|
|
696
|
-
"between"
|
|
1485
|
+
[FILTER_VALUE_KIND.STRING]: /* @__PURE__ */ new Set([
|
|
1486
|
+
FILTER_OPERATOR.INCLUDES,
|
|
1487
|
+
FILTER_OPERATOR.NOT_INCLUDES,
|
|
1488
|
+
FILTER_OPERATOR.IS,
|
|
1489
|
+
FILTER_OPERATOR.IS_NOT
|
|
697
1490
|
]),
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
1491
|
+
[FILTER_VALUE_KIND.NUMBER]: /* @__PURE__ */ new Set([
|
|
1492
|
+
FILTER_OPERATOR.EQUALS,
|
|
1493
|
+
FILTER_OPERATOR.NOT_EQUALS,
|
|
1494
|
+
FILTER_OPERATOR.GREATER_THAN,
|
|
1495
|
+
FILTER_OPERATOR.LESS_THAN,
|
|
1496
|
+
FILTER_OPERATOR.GREATER_OR_EQUAL,
|
|
1497
|
+
FILTER_OPERATOR.LESS_OR_EQUAL,
|
|
1498
|
+
FILTER_OPERATOR.BETWEEN
|
|
1499
|
+
]),
|
|
1500
|
+
[FILTER_VALUE_KIND.DATE]: /* @__PURE__ */ new Set([
|
|
1501
|
+
FILTER_OPERATOR.AFTER,
|
|
1502
|
+
FILTER_OPERATOR.BEFORE,
|
|
1503
|
+
FILTER_OPERATOR.BETWEEN
|
|
1504
|
+
]),
|
|
1505
|
+
[FILTER_VALUE_KIND.ID_ARRAY]: /* @__PURE__ */ new Set([
|
|
1506
|
+
FILTER_OPERATOR.SOME_OF,
|
|
1507
|
+
FILTER_OPERATOR.NOT_SOME_OF
|
|
1508
|
+
]),
|
|
1509
|
+
[FILTER_VALUE_KIND.ENUM]: /* @__PURE__ */ new Set([
|
|
1510
|
+
FILTER_OPERATOR.SOME_OF,
|
|
1511
|
+
FILTER_OPERATOR.NOT_SOME_OF
|
|
1512
|
+
]),
|
|
1513
|
+
[FILTER_VALUE_KIND.BOOLEAN]: /* @__PURE__ */ new Set([
|
|
1514
|
+
FILTER_OPERATOR.SOME_OF,
|
|
1515
|
+
FILTER_OPERATOR.NOT_SOME_OF
|
|
1516
|
+
]),
|
|
1517
|
+
[FILTER_VALUE_KIND.REFERENCE]: /* @__PURE__ */ new Set([
|
|
1518
|
+
FILTER_OPERATOR.SOME_OF,
|
|
1519
|
+
FILTER_OPERATOR.NOT_SOME_OF
|
|
1520
|
+
])
|
|
703
1521
|
};
|
|
704
1522
|
function normalizeDateRange(value) {
|
|
705
1523
|
if (value === void 0) return { ok: true, dateRange: void 0 };
|
|
706
1524
|
if (typeof value !== "object" || value === null) {
|
|
707
|
-
return { ok: false, reason:
|
|
1525
|
+
return { ok: false, reason: FILTER_REJECTION_REASON.INVALID_VALUE };
|
|
708
1526
|
}
|
|
709
1527
|
const { start, end } = value;
|
|
710
1528
|
if (!(start instanceof Date) || !(end instanceof Date)) {
|
|
711
|
-
return { ok: false, reason:
|
|
1529
|
+
return { ok: false, reason: FILTER_REJECTION_REASON.INVALID_VALUE };
|
|
712
1530
|
}
|
|
713
1531
|
const startTime = start.getTime();
|
|
714
1532
|
const endTime = end.getTime();
|
|
715
1533
|
if (!Number.isFinite(startTime) || !Number.isFinite(endTime) || startTime > endTime) {
|
|
716
|
-
return { ok: false, reason:
|
|
1534
|
+
return { ok: false, reason: FILTER_REJECTION_REASON.INVALID_VALUE };
|
|
717
1535
|
}
|
|
718
1536
|
return {
|
|
719
1537
|
ok: true,
|
|
@@ -722,30 +1540,32 @@ function normalizeDateRange(value) {
|
|
|
722
1540
|
}
|
|
723
1541
|
function normalizeCriterion(criterion) {
|
|
724
1542
|
const descriptor = getFieldDescriptor(criterion.field);
|
|
725
|
-
if (descriptor === null)
|
|
1543
|
+
if (descriptor === null) {
|
|
1544
|
+
return { ok: false, reason: FILTER_REJECTION_REASON.UNKNOWN_FIELD };
|
|
1545
|
+
}
|
|
726
1546
|
if (!OPERATORS_BY_KIND[descriptor.valueKind].has(criterion.operator)) {
|
|
727
|
-
return { ok: false, reason:
|
|
1547
|
+
return { ok: false, reason: FILTER_REJECTION_REASON.UNKNOWN_OPERATOR };
|
|
728
1548
|
}
|
|
729
|
-
if (criterion.operator ===
|
|
1549
|
+
if (criterion.operator === FILTER_OPERATOR.BETWEEN) {
|
|
730
1550
|
return normalizeBetweenCriterion(criterion, descriptor.valueKind);
|
|
731
1551
|
}
|
|
732
|
-
if (descriptor.valueKind ===
|
|
1552
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.NUMBER) {
|
|
733
1553
|
const value = normalizeNumberValue(criterion.value);
|
|
734
|
-
return value === null ? { ok: false, reason:
|
|
1554
|
+
return value === null ? { ok: false, reason: FILTER_REJECTION_REASON.INVALID_VALUE } : {
|
|
735
1555
|
ok: true,
|
|
736
1556
|
criterion: { ...criterion, value }
|
|
737
1557
|
};
|
|
738
1558
|
}
|
|
739
|
-
if (descriptor.valueKind ===
|
|
1559
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.DATE) {
|
|
740
1560
|
const value = normalizeDateValue(criterion.value);
|
|
741
|
-
return value === null ? { ok: false, reason:
|
|
1561
|
+
return value === null ? { ok: false, reason: FILTER_REJECTION_REASON.INVALID_VALUE } : {
|
|
742
1562
|
ok: true,
|
|
743
1563
|
criterion: { ...criterion, value }
|
|
744
1564
|
};
|
|
745
1565
|
}
|
|
746
1566
|
const rejection = validateValueForKind(criterion, descriptor.valueKind);
|
|
747
1567
|
if (rejection !== null) return { ok: false, reason: rejection };
|
|
748
|
-
if (descriptor.valueKind ===
|
|
1568
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.BOOLEAN) {
|
|
749
1569
|
return {
|
|
750
1570
|
ok: true,
|
|
751
1571
|
criterion: {
|
|
@@ -754,7 +1574,7 @@ function normalizeCriterion(criterion) {
|
|
|
754
1574
|
}
|
|
755
1575
|
};
|
|
756
1576
|
}
|
|
757
|
-
if (descriptor.valueKind ===
|
|
1577
|
+
if (descriptor.valueKind === FILTER_VALUE_KIND.ID_ARRAY || descriptor.valueKind === FILTER_VALUE_KIND.ENUM || descriptor.valueKind === FILTER_VALUE_KIND.REFERENCE) {
|
|
758
1578
|
return {
|
|
759
1579
|
ok: true,
|
|
760
1580
|
criterion: {
|
|
@@ -770,41 +1590,41 @@ function normalizeCriterion(criterion) {
|
|
|
770
1590
|
return { ok: true, criterion };
|
|
771
1591
|
}
|
|
772
1592
|
function normalizeBetweenCriterion(criterion, valueKind) {
|
|
773
|
-
if (valueKind ===
|
|
1593
|
+
if (valueKind === FILTER_VALUE_KIND.NUMBER) {
|
|
774
1594
|
const value = normalizeNumberValue(criterion.value);
|
|
775
1595
|
const valueTo = normalizeNumberValue(criterion.valueTo);
|
|
776
1596
|
if (value === null || valueTo === null || value > valueTo) {
|
|
777
|
-
return { ok: false, reason:
|
|
1597
|
+
return { ok: false, reason: FILTER_REJECTION_REASON.INVALID_VALUE };
|
|
778
1598
|
}
|
|
779
1599
|
return {
|
|
780
1600
|
ok: true,
|
|
781
1601
|
criterion: { ...criterion, value, valueTo }
|
|
782
1602
|
};
|
|
783
1603
|
}
|
|
784
|
-
if (valueKind ===
|
|
1604
|
+
if (valueKind === FILTER_VALUE_KIND.DATE) {
|
|
785
1605
|
const value = normalizeDateValue(criterion.value);
|
|
786
1606
|
const valueTo = normalizeDateValue(criterion.valueTo);
|
|
787
1607
|
if (value === null || valueTo === null || value.getTime() > valueTo.getTime()) {
|
|
788
|
-
return { ok: false, reason:
|
|
1608
|
+
return { ok: false, reason: FILTER_REJECTION_REASON.INVALID_VALUE };
|
|
789
1609
|
}
|
|
790
1610
|
return {
|
|
791
1611
|
ok: true,
|
|
792
1612
|
criterion: { ...criterion, value, valueTo }
|
|
793
1613
|
};
|
|
794
1614
|
}
|
|
795
|
-
return { ok: false, reason:
|
|
1615
|
+
return { ok: false, reason: FILTER_REJECTION_REASON.UNKNOWN_OPERATOR };
|
|
796
1616
|
}
|
|
797
1617
|
function validateValueForKind(criterion, valueKind) {
|
|
798
1618
|
const { value } = criterion;
|
|
799
|
-
if (valueKind ===
|
|
800
|
-
return Array.isArray(value) && value.every((item) => typeof item === "boolean") ? null :
|
|
1619
|
+
if (valueKind === FILTER_VALUE_KIND.BOOLEAN) {
|
|
1620
|
+
return Array.isArray(value) && value.every((item) => typeof item === "boolean") ? null : FILTER_REJECTION_REASON.INVALID_VALUE;
|
|
801
1621
|
}
|
|
802
|
-
if (valueKind ===
|
|
1622
|
+
if (valueKind === FILTER_VALUE_KIND.ID_ARRAY || valueKind === FILTER_VALUE_KIND.ENUM || valueKind === FILTER_VALUE_KIND.REFERENCE) {
|
|
803
1623
|
return Array.isArray(value) && value.every(
|
|
804
1624
|
(item) => typeof item === "string" || typeof item === "number"
|
|
805
|
-
) ? null :
|
|
1625
|
+
) ? null : FILTER_REJECTION_REASON.INVALID_VALUE;
|
|
806
1626
|
}
|
|
807
|
-
if (Array.isArray(value)) return
|
|
1627
|
+
if (Array.isArray(value)) return FILTER_REJECTION_REASON.INVALID_VALUE;
|
|
808
1628
|
return null;
|
|
809
1629
|
}
|
|
810
1630
|
function normalizeNumberValue(value) {
|
|
@@ -852,455 +1672,198 @@ function resolveFilter(adapter, filter, hoursPerDay) {
|
|
|
852
1672
|
});
|
|
853
1673
|
return { visibleIds: projection.visibleIds, projection };
|
|
854
1674
|
}
|
|
855
|
-
function dispatchFilterSet(action, deps) {
|
|
856
|
-
const { adapter, hoursPerDay } = deps;
|
|
857
|
-
const criteria = [];
|
|
858
|
-
for (const criterion of action.criteria) {
|
|
859
|
-
const result = normalizeCriterion(criterion);
|
|
860
|
-
if (!result.ok) return { ok: false, reason: result.reason };
|
|
861
|
-
criteria.push(result.criterion);
|
|
862
|
-
}
|
|
863
|
-
const rangeResult = normalizeDateRange(action.dateRange);
|
|
864
|
-
if (!rangeResult.ok) return { ok: false, reason: rangeResult.reason };
|
|
865
|
-
const filter = cloneDomainValue(
|
|
866
|
-
rangeResult.dateRange === void 0 ? { criteria, logic: action.logic } : {
|
|
867
|
-
criteria,
|
|
868
|
-
logic: action.logic,
|
|
869
|
-
dateRange: rangeResult.dateRange
|
|
870
|
-
}
|
|
871
|
-
);
|
|
872
|
-
adapter.setActiveFilter(isEmptyFilter(filter) ? null : filter);
|
|
873
|
-
const { visibleIds, projection } = resolveFilter(
|
|
874
|
-
adapter,
|
|
875
|
-
filter,
|
|
876
|
-
hoursPerDay
|
|
877
|
-
);
|
|
878
|
-
adapter.setFilterProjection(projection);
|
|
879
|
-
const viewState = applyVisibleSet(adapter, visibleIds);
|
|
880
|
-
const changes = {
|
|
881
|
-
source: action,
|
|
882
|
-
activities: [],
|
|
883
|
-
links: [],
|
|
884
|
-
calendars: [],
|
|
885
|
-
trackingEvents: [],
|
|
886
|
-
viewState
|
|
887
|
-
};
|
|
888
|
-
return { ok: true, changes };
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
// src/internal/hierarchy/root-parent.ts
|
|
892
|
-
var ROOT_PARENT_ID = "0";
|
|
893
|
-
var ROOT_PROJECT_CORRELATIVE_ID = 0;
|
|
894
|
-
function isRootParent(parent) {
|
|
895
|
-
return parent == null || parent === 0 || parent === ROOT_PARENT_ID;
|
|
896
|
-
}
|
|
897
|
-
function normalizeParentKey(parent) {
|
|
898
|
-
return isRootParent(parent) ? ROOT_PARENT_ID : String(parent);
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
// src/internal/hierarchy/visual-order.ts
|
|
902
|
-
var NOT_SET_SORT_VALUE = Number.MAX_SAFE_INTEGER;
|
|
903
|
-
function getChildrenInVisualOrder(parentId, adapter) {
|
|
904
|
-
const children = collectChildrenSnapshots(parentId, adapter);
|
|
905
|
-
const userOrder = adapter.getOrderComparator?.() ?? null;
|
|
906
|
-
children.sort(
|
|
907
|
-
userOrder === null ? compareActivitiesInVisualOrder : (a, b) => userOrder(a, b) || compareActivitiesInVisualOrder(a, b)
|
|
908
|
-
);
|
|
909
|
-
return children.map((activity) => String(activity.id));
|
|
910
|
-
}
|
|
911
|
-
function iterateInVisualOrder(adapter) {
|
|
912
|
-
const result = [];
|
|
913
|
-
const visit = (activity) => {
|
|
914
|
-
result.push(activity);
|
|
915
|
-
const childIds = getChildrenInVisualOrder(String(activity.id), adapter);
|
|
916
|
-
for (const childId of childIds) {
|
|
917
|
-
const child = adapter.getActivity(childId);
|
|
918
|
-
if (child) visit(child);
|
|
919
|
-
}
|
|
920
|
-
};
|
|
921
|
-
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter);
|
|
922
|
-
for (const rootId of rootIds) {
|
|
923
|
-
const root = adapter.getActivity(rootId);
|
|
924
|
-
if (root) visit(root);
|
|
925
|
-
}
|
|
926
|
-
return result;
|
|
927
|
-
}
|
|
928
|
-
function findPreviousNonSelectedSibling(taskId, selected, adapter) {
|
|
929
|
-
const activity = adapter.getActivity(taskId);
|
|
930
|
-
if (!activity) return null;
|
|
931
|
-
const parentKey = parentKeyOf(activity);
|
|
932
|
-
const siblings = getChildrenInVisualOrder(parentKey, adapter);
|
|
933
|
-
const idx = siblings.findIndex((id) => String(id) === String(taskId));
|
|
934
|
-
if (idx <= 0) return null;
|
|
935
|
-
for (let i = idx - 1; i >= 0; i--) {
|
|
936
|
-
const candidateId = siblings[i];
|
|
937
|
-
if (candidateId === void 0) continue;
|
|
938
|
-
if (!setHas(selected, candidateId)) return candidateId;
|
|
939
|
-
}
|
|
940
|
-
return null;
|
|
941
|
-
}
|
|
942
|
-
function visualIndexInParent(taskId, adapter) {
|
|
943
|
-
const activity = adapter.getActivity(taskId);
|
|
944
|
-
if (!activity) return -1;
|
|
945
|
-
const parentKey = parentKeyOf(activity);
|
|
946
|
-
const siblings = getChildrenInVisualOrder(parentKey, adapter);
|
|
947
|
-
return siblings.findIndex((id) => String(id) === String(taskId));
|
|
948
|
-
}
|
|
949
|
-
function collectChildrenSnapshots(parentId, adapter) {
|
|
950
|
-
const childIds = String(parentId) === ROOT_PARENT_ID ? adapter.getRootIds?.() ?? adapter.getChildren(ROOT_PARENT_ID) : adapter.getChildren(parentId);
|
|
951
|
-
const out = [];
|
|
952
|
-
for (const id of childIds) {
|
|
953
|
-
const snap = adapter.getActivity(id);
|
|
954
|
-
if (snap) out.push(snap);
|
|
955
|
-
}
|
|
956
|
-
return out;
|
|
957
|
-
}
|
|
958
|
-
function compareActivitiesInVisualOrder(a, b) {
|
|
959
|
-
const ac = correlativeIdOf(a);
|
|
960
|
-
const bc = correlativeIdOf(b);
|
|
961
|
-
if (ac !== bc) return ac - bc;
|
|
962
|
-
return String(a.id).localeCompare(String(b.id));
|
|
963
|
-
}
|
|
964
|
-
function correlativeIdOf(activity) {
|
|
965
|
-
const raw = activity.correlativeId;
|
|
966
|
-
const n = typeof raw === "number" ? raw : Number(raw);
|
|
967
|
-
return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
|
|
968
|
-
}
|
|
969
|
-
function parentKeyOf(activity) {
|
|
970
|
-
const parentId = activity.parentId;
|
|
971
|
-
if (parentId === null) return "0";
|
|
972
|
-
return parentId;
|
|
973
|
-
}
|
|
974
|
-
function setHas(set, id) {
|
|
975
|
-
if (set.has(id)) return true;
|
|
976
|
-
return set.has(String(id));
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
// src/dispatch/shared/collect-branch-order.ts
|
|
980
|
-
function collectBranchOrder(adapter) {
|
|
981
|
-
const branches = [];
|
|
982
|
-
const visit = (parentId) => {
|
|
983
|
-
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
984
|
-
if (childIds.length > 1) {
|
|
985
|
-
branches.push({ parentId, childIds });
|
|
986
|
-
}
|
|
987
|
-
for (const childId of childIds) {
|
|
988
|
-
visit(childId);
|
|
989
|
-
}
|
|
990
|
-
};
|
|
991
|
-
visit(ROOT_PARENT_ID);
|
|
992
|
-
return branches;
|
|
993
|
-
}
|
|
994
|
-
function collectBranchOrderForParents(adapter, parentIds) {
|
|
995
|
-
const branches = [];
|
|
996
|
-
for (const parentId of parentIds) {
|
|
997
|
-
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
998
|
-
if (childIds.length > 1) branches.push({ parentId, childIds });
|
|
999
|
-
}
|
|
1000
|
-
return branches;
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
// src/dispatch/order.ts
|
|
1004
|
-
function validateRule(rule) {
|
|
1005
|
-
if (getFieldDescriptor(rule.field) === null) return "unknown_field";
|
|
1006
|
-
if (rule.direction !== "asc" && rule.direction !== "desc") {
|
|
1007
|
-
return "unknown_operator";
|
|
1008
|
-
}
|
|
1009
|
-
return null;
|
|
1010
|
-
}
|
|
1011
|
-
function dispatchSortSet(action, deps) {
|
|
1012
|
-
const { adapter } = deps;
|
|
1013
|
-
for (const rule of action.rules) {
|
|
1014
|
-
const rejection = validateRule(rule);
|
|
1015
|
-
if (rejection !== null) return { ok: false, reason: rejection };
|
|
1016
|
-
}
|
|
1017
|
-
const order = action.rules.length === 0 ? null : cloneDomainValue({ rules: action.rules });
|
|
1018
|
-
adapter.setActiveOrder(order);
|
|
1019
|
-
const changes = {
|
|
1020
|
-
source: action,
|
|
1021
|
-
activities: [],
|
|
1022
|
-
links: [],
|
|
1023
|
-
calendars: [],
|
|
1024
|
-
trackingEvents: [],
|
|
1025
|
-
order: collectBranchOrder(adapter)
|
|
1026
|
-
};
|
|
1027
|
-
return { ok: true, changes };
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
// src/constants/columns.ts
|
|
1031
|
-
var EDITABLE = {
|
|
1032
|
-
TEXT: "text",
|
|
1033
|
-
DESCRIPTION: "description",
|
|
1034
|
-
DURATION: "duration",
|
|
1035
|
-
PROGRESS: "progress",
|
|
1036
|
-
COST: "cost",
|
|
1037
|
-
USED_COST: "used_cost",
|
|
1038
|
-
HH_WORK_TIME: "hhWorkTime",
|
|
1039
|
-
START_DATE: "start_date",
|
|
1040
|
-
END_DATE: "end_date",
|
|
1041
|
-
CONSTRAINT_TYPE: "constraint_type",
|
|
1042
|
-
CONSTRAINT_DATE: "constraint_date",
|
|
1043
|
-
CALENDAR_ID: "calendar_id",
|
|
1044
|
-
CUSTOM_ID: "custom_id",
|
|
1045
|
-
SUBCONTRACT_ID: "subcontractId",
|
|
1046
|
-
RESPONSABLES: "responsables",
|
|
1047
|
-
TAGS: "tags",
|
|
1048
|
-
CUSTOM_PREDECESSORS: "custom_predecessors",
|
|
1049
|
-
CUSTOM_SUCESSORS: "custom_sucessors"
|
|
1050
|
-
};
|
|
1051
|
-
var READ_ONLY = {
|
|
1052
|
-
REAL_WORK: "real_work",
|
|
1053
|
-
REAL_COST: "real_cost",
|
|
1054
|
-
EXPECTED_PROGRESS: "expected_progress",
|
|
1055
|
-
EXPECTED_PROGRESS_BASE: "expected_progress_base",
|
|
1056
|
-
START_BASE: "start_base",
|
|
1057
|
-
END_BASE: "end_base",
|
|
1058
|
-
DURATION_BASE: "duration_base",
|
|
1059
|
-
COST_BASE: "cost_base",
|
|
1060
|
-
WORK_BASE: "work_base",
|
|
1061
|
-
CALENDAR_DURATION: "calendarDuration",
|
|
1062
|
-
IS_CRITICAL: "is_critical",
|
|
1063
|
-
EARLY_START: "earlyStart",
|
|
1064
|
-
EARLY_FINISH: "earlyFinish",
|
|
1065
|
-
LATE_START: "lateStart",
|
|
1066
|
-
LATE_FINISH: "lateFinish",
|
|
1067
|
-
FREE_SLACK: "freeSlack",
|
|
1068
|
-
TOTAL_SLACK: "totalSlack",
|
|
1069
|
-
CORRELATIVE_ID: "correlative_id",
|
|
1070
|
-
UNIQUE_CORRELATIVE_ID: "unique_correlative_id",
|
|
1071
|
-
PONDERATOR: "ponderator",
|
|
1072
|
-
STATUS: "status"
|
|
1073
|
-
};
|
|
1074
|
-
var COLUMN = { ...EDITABLE, ...READ_ONLY };
|
|
1075
|
-
|
|
1076
|
-
// src/shared/assert-never.ts
|
|
1077
|
-
function assertNever(value, message) {
|
|
1078
|
-
throw new Error(message);
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
// src/autoscheduler/utils/cancellation.ts
|
|
1082
|
-
function createIsCurrent(id, getCurrentId) {
|
|
1083
|
-
return () => getCurrentId() === id;
|
|
1675
|
+
function dispatchFilterSet(action, deps) {
|
|
1676
|
+
const { adapter, hoursPerDay } = deps;
|
|
1677
|
+
const criteria = [];
|
|
1678
|
+
for (const criterion of action.criteria) {
|
|
1679
|
+
const result = normalizeCriterion(criterion);
|
|
1680
|
+
if (!result.ok) return { ok: false, reason: result.reason };
|
|
1681
|
+
criteria.push(result.criterion);
|
|
1682
|
+
}
|
|
1683
|
+
const rangeResult = normalizeDateRange(action.dateRange);
|
|
1684
|
+
if (!rangeResult.ok) return { ok: false, reason: rangeResult.reason };
|
|
1685
|
+
const filter = cloneDomainValue(
|
|
1686
|
+
rangeResult.dateRange === void 0 ? { criteria, logic: action.logic } : {
|
|
1687
|
+
criteria,
|
|
1688
|
+
logic: action.logic,
|
|
1689
|
+
dateRange: rangeResult.dateRange
|
|
1690
|
+
}
|
|
1691
|
+
);
|
|
1692
|
+
adapter.setActiveFilter(isEmptyFilter(filter) ? null : filter);
|
|
1693
|
+
const { visibleIds, projection } = resolveFilter(
|
|
1694
|
+
adapter,
|
|
1695
|
+
filter,
|
|
1696
|
+
hoursPerDay
|
|
1697
|
+
);
|
|
1698
|
+
adapter.setFilterProjection(projection);
|
|
1699
|
+
const viewState = applyVisibleSet(adapter, visibleIds);
|
|
1700
|
+
const changes = {
|
|
1701
|
+
source: action,
|
|
1702
|
+
activities: [],
|
|
1703
|
+
links: [],
|
|
1704
|
+
calendars: [],
|
|
1705
|
+
trackingEvents: [],
|
|
1706
|
+
viewState
|
|
1707
|
+
};
|
|
1708
|
+
return { ok: true, changes };
|
|
1084
1709
|
}
|
|
1085
1710
|
|
|
1086
|
-
// src/types.ts
|
|
1087
|
-
var
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
};
|
|
1091
|
-
var CALENDAR_UNIT = {
|
|
1092
|
-
HOUR: "hour",
|
|
1093
|
-
DAY: "day"
|
|
1094
|
-
};
|
|
1095
|
-
var STATUS = {
|
|
1096
|
-
DONE: "Done",
|
|
1097
|
-
OVERDUE: "Overdue",
|
|
1098
|
-
ADVANCEMENT: "Advancement",
|
|
1099
|
-
WAITING: "Waiting",
|
|
1100
|
-
DOING: "Doing"
|
|
1711
|
+
// src/internal/order/types.ts
|
|
1712
|
+
var ORDER_DIRECTION = {
|
|
1713
|
+
ASCENDING: "asc",
|
|
1714
|
+
DESCENDING: "desc"
|
|
1101
1715
|
};
|
|
1102
1716
|
|
|
1103
|
-
// src/
|
|
1104
|
-
var
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
SNLT: "snlt",
|
|
1109
|
-
FNET: "fnet",
|
|
1110
|
-
FNLT: "fnlt",
|
|
1111
|
-
MSO: "mso",
|
|
1112
|
-
MFO: "mfo"
|
|
1113
|
-
};
|
|
1114
|
-
var VIOLATION_RULES = {
|
|
1115
|
-
mso: () => true,
|
|
1116
|
-
mfo: () => true,
|
|
1117
|
-
snlt: (constraint, projected) => constraint < projected,
|
|
1118
|
-
snet: (constraint, projected) => constraint > projected,
|
|
1119
|
-
fnlt: (constraint, projected) => constraint < projected,
|
|
1120
|
-
fnet: (constraint, projected) => constraint > projected
|
|
1121
|
-
};
|
|
1122
|
-
function checkConstraintViolation(constraintType, constraintDate, projectedDate) {
|
|
1123
|
-
if (!constraintDate) return { violated: false };
|
|
1124
|
-
const rule = VIOLATION_RULES[constraintType];
|
|
1125
|
-
if (!rule) return { violated: false };
|
|
1126
|
-
if (rule(constraintDate, projectedDate)) {
|
|
1127
|
-
return { violated: true, constraintType, constraintDate };
|
|
1128
|
-
}
|
|
1129
|
-
return { violated: false };
|
|
1717
|
+
// src/internal/hierarchy/root-parent.ts
|
|
1718
|
+
var ROOT_PARENT_ID = "0";
|
|
1719
|
+
var ROOT_PROJECT_CORRELATIVE_ID = 0;
|
|
1720
|
+
function isRootParent(parent) {
|
|
1721
|
+
return parent == null || parent === 0 || parent === ROOT_PARENT_ID;
|
|
1130
1722
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
"snet",
|
|
1134
|
-
"snlt"
|
|
1135
|
-
]);
|
|
1136
|
-
function pickProjectedDateForConstraint(constraintType, projectedStart, projectedEnd) {
|
|
1137
|
-
return START_BASED_CONSTRAINTS.has(constraintType) ? projectedStart : projectedEnd;
|
|
1723
|
+
function normalizeParentKey(parent) {
|
|
1724
|
+
return isRootParent(parent) ? ROOT_PARENT_ID : String(parent);
|
|
1138
1725
|
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1726
|
+
|
|
1727
|
+
// src/internal/hierarchy/visual-order.ts
|
|
1728
|
+
var NOT_SET_SORT_VALUE = Number.MAX_SAFE_INTEGER;
|
|
1729
|
+
function getChildrenInVisualOrder(parentId, adapter) {
|
|
1730
|
+
const children = collectChildrenSnapshots(parentId, adapter);
|
|
1731
|
+
const userOrder = adapter.getOrderComparator?.() ?? null;
|
|
1732
|
+
children.sort(
|
|
1733
|
+
userOrder === null ? compareActivitiesInVisualOrder : (a, b) => userOrder(a, b) || compareActivitiesInVisualOrder(a, b)
|
|
1734
|
+
);
|
|
1735
|
+
return children.map((activity) => String(activity.id));
|
|
1736
|
+
}
|
|
1737
|
+
function iterateInVisualOrder(adapter) {
|
|
1738
|
+
const result = [];
|
|
1739
|
+
const visit = (activity) => {
|
|
1740
|
+
result.push(activity);
|
|
1741
|
+
const childIds = getChildrenInVisualOrder(String(activity.id), adapter);
|
|
1742
|
+
for (const childId of childIds) {
|
|
1743
|
+
const child = adapter.getActivity(childId);
|
|
1744
|
+
if (child) visit(child);
|
|
1147
1745
|
}
|
|
1148
1746
|
};
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
fnet: { startOfDay: false, direction: WORK_TIME_DIRECTION.FUTURE },
|
|
1154
|
-
fnlt: { startOfDay: false, direction: WORK_TIME_DIRECTION.PAST },
|
|
1155
|
-
mso: { startOfDay: true, direction: WORK_TIME_DIRECTION.FUTURE },
|
|
1156
|
-
mfo: { startOfDay: false, direction: WORK_TIME_DIRECTION.PAST }
|
|
1157
|
-
};
|
|
1158
|
-
var startOfUtcDay = (d) => new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
|
|
1159
|
-
var addUtcDays = (d, n) => new Date(d.getTime() + n * 864e5);
|
|
1160
|
-
var sameUtcDay = (a, b) => a.getUTCFullYear() === b.getUTCFullYear() && a.getUTCMonth() === b.getUTCMonth() && a.getUTCDate() === b.getUTCDate();
|
|
1161
|
-
function getEffectiveConstraintDate(activity, adapter) {
|
|
1162
|
-
if (!activity.constraintDate || !activity.constraintType) return null;
|
|
1163
|
-
const config = CONSTRAINT_CASES[activity.constraintType];
|
|
1164
|
-
if (!config) return activity.constraintDate;
|
|
1165
|
-
const cd = activity.constraintDate;
|
|
1166
|
-
const firstWorkOfDay = adapter.getClosestWorkTime({
|
|
1167
|
-
date: startOfUtcDay(cd),
|
|
1168
|
-
dir: WORK_TIME_DIRECTION.FUTURE,
|
|
1169
|
-
task: activity
|
|
1170
|
-
});
|
|
1171
|
-
if (sameUtcDay(firstWorkOfDay, cd)) {
|
|
1172
|
-
if (cd.getTime() !== startOfUtcDay(cd).getTime()) return cd;
|
|
1173
|
-
if (config.startOfDay) return firstWorkOfDay;
|
|
1174
|
-
return adapter.getClosestWorkTime({
|
|
1175
|
-
date: addUtcDays(startOfUtcDay(cd), 1),
|
|
1176
|
-
dir: WORK_TIME_DIRECTION.PAST,
|
|
1177
|
-
task: activity
|
|
1178
|
-
});
|
|
1747
|
+
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter);
|
|
1748
|
+
for (const rootId of rootIds) {
|
|
1749
|
+
const root = adapter.getActivity(rootId);
|
|
1750
|
+
if (root) visit(root);
|
|
1179
1751
|
}
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
);
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1752
|
+
return result;
|
|
1753
|
+
}
|
|
1754
|
+
function findPreviousNonSelectedSibling(taskId, selected, adapter) {
|
|
1755
|
+
const activity = adapter.getActivity(taskId);
|
|
1756
|
+
if (!activity) return null;
|
|
1757
|
+
const parentKey = parentKeyOf(activity);
|
|
1758
|
+
const siblings = getChildrenInVisualOrder(parentKey, adapter);
|
|
1759
|
+
const idx = siblings.findIndex((id) => String(id) === String(taskId));
|
|
1760
|
+
if (idx <= 0) return null;
|
|
1761
|
+
for (let i = idx - 1; i >= 0; i--) {
|
|
1762
|
+
const candidateId = siblings[i];
|
|
1763
|
+
if (candidateId === void 0) continue;
|
|
1764
|
+
if (!setHas(selected, candidateId)) return candidateId;
|
|
1193
1765
|
}
|
|
1194
|
-
return
|
|
1195
|
-
date: addUtcDays(effectiveMidnight, 1),
|
|
1196
|
-
dir: WORK_TIME_DIRECTION.PAST,
|
|
1197
|
-
task: activity
|
|
1198
|
-
});
|
|
1766
|
+
return null;
|
|
1199
1767
|
}
|
|
1200
|
-
function
|
|
1201
|
-
const
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
const
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
return {
|
|
1245
|
-
earliestStart: null,
|
|
1246
|
-
latestStart: startFromEnd(constraintDate),
|
|
1247
|
-
earliestEnd: null,
|
|
1248
|
-
latestEnd: constraintDate
|
|
1249
|
-
};
|
|
1250
|
-
case "mso": {
|
|
1251
|
-
const end = endFromStart(constraintDate);
|
|
1252
|
-
return {
|
|
1253
|
-
earliestStart: constraintDate,
|
|
1254
|
-
latestStart: constraintDate,
|
|
1255
|
-
earliestEnd: end,
|
|
1256
|
-
latestEnd: end
|
|
1257
|
-
};
|
|
1768
|
+
function visualIndexInParent(taskId, adapter) {
|
|
1769
|
+
const activity = adapter.getActivity(taskId);
|
|
1770
|
+
if (!activity) return -1;
|
|
1771
|
+
const parentKey = parentKeyOf(activity);
|
|
1772
|
+
const siblings = getChildrenInVisualOrder(parentKey, adapter);
|
|
1773
|
+
return siblings.findIndex((id) => String(id) === String(taskId));
|
|
1774
|
+
}
|
|
1775
|
+
function collectChildrenSnapshots(parentId, adapter) {
|
|
1776
|
+
const childIds = String(parentId) === ROOT_PARENT_ID ? adapter.getRootIds?.() ?? adapter.getChildren(ROOT_PARENT_ID) : adapter.getChildren(parentId);
|
|
1777
|
+
const out = [];
|
|
1778
|
+
for (const id of childIds) {
|
|
1779
|
+
const snap = adapter.getActivity(id);
|
|
1780
|
+
if (snap) out.push(snap);
|
|
1781
|
+
}
|
|
1782
|
+
return out;
|
|
1783
|
+
}
|
|
1784
|
+
function compareActivitiesInVisualOrder(a, b) {
|
|
1785
|
+
const ac = correlativeIdOf(a);
|
|
1786
|
+
const bc = correlativeIdOf(b);
|
|
1787
|
+
if (ac !== bc) return ac - bc;
|
|
1788
|
+
return String(a.id).localeCompare(String(b.id));
|
|
1789
|
+
}
|
|
1790
|
+
function correlativeIdOf(activity) {
|
|
1791
|
+
const raw = activity.correlativeId;
|
|
1792
|
+
const n = typeof raw === "number" ? raw : Number(raw);
|
|
1793
|
+
return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
|
|
1794
|
+
}
|
|
1795
|
+
function parentKeyOf(activity) {
|
|
1796
|
+
const parentId = activity.parentId;
|
|
1797
|
+
if (parentId === null) return "0";
|
|
1798
|
+
return parentId;
|
|
1799
|
+
}
|
|
1800
|
+
function setHas(set, id) {
|
|
1801
|
+
if (set.has(id)) return true;
|
|
1802
|
+
return set.has(String(id));
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
// src/dispatch/shared/collect-branch-order.ts
|
|
1806
|
+
function collectBranchOrder(adapter) {
|
|
1807
|
+
const branches = [];
|
|
1808
|
+
const visit = (parentId) => {
|
|
1809
|
+
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
1810
|
+
if (childIds.length > 1) {
|
|
1811
|
+
branches.push({ parentId, childIds });
|
|
1258
1812
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
return {
|
|
1262
|
-
earliestStart: start,
|
|
1263
|
-
latestStart: start,
|
|
1264
|
-
earliestEnd: constraintDate,
|
|
1265
|
-
latestEnd: constraintDate
|
|
1266
|
-
};
|
|
1813
|
+
for (const childId of childIds) {
|
|
1814
|
+
visit(childId);
|
|
1267
1815
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1816
|
+
};
|
|
1817
|
+
visit(ROOT_PARENT_ID);
|
|
1818
|
+
return branches;
|
|
1271
1819
|
}
|
|
1272
|
-
function
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1820
|
+
function collectBranchOrderForParents(adapter, parentIds) {
|
|
1821
|
+
const branches = [];
|
|
1822
|
+
for (const parentId of parentIds) {
|
|
1823
|
+
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
1824
|
+
if (childIds.length > 1) branches.push({ parentId, childIds });
|
|
1825
|
+
}
|
|
1826
|
+
return branches;
|
|
1276
1827
|
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1828
|
+
|
|
1829
|
+
// src/dispatch/order.ts
|
|
1830
|
+
function validateRule(rule) {
|
|
1831
|
+
if (getFieldDescriptor(rule.field) === null) {
|
|
1832
|
+
return FILTER_REJECTION_REASON.UNKNOWN_FIELD;
|
|
1280
1833
|
}
|
|
1281
|
-
if (
|
|
1282
|
-
return
|
|
1834
|
+
if (rule.direction !== ORDER_DIRECTION.ASCENDING && rule.direction !== ORDER_DIRECTION.DESCENDING) {
|
|
1835
|
+
return FILTER_REJECTION_REASON.UNKNOWN_OPERATOR;
|
|
1283
1836
|
}
|
|
1284
|
-
return
|
|
1837
|
+
return null;
|
|
1838
|
+
}
|
|
1839
|
+
function dispatchSortSet(action, deps) {
|
|
1840
|
+
const { adapter } = deps;
|
|
1841
|
+
for (const rule of action.rules) {
|
|
1842
|
+
const rejection = validateRule(rule);
|
|
1843
|
+
if (rejection !== null) return { ok: false, reason: rejection };
|
|
1844
|
+
}
|
|
1845
|
+
const order = action.rules.length === 0 ? null : cloneDomainValue({ rules: action.rules });
|
|
1846
|
+
adapter.setActiveOrder(order);
|
|
1847
|
+
const changes = {
|
|
1848
|
+
source: action,
|
|
1849
|
+
activities: [],
|
|
1850
|
+
links: [],
|
|
1851
|
+
calendars: [],
|
|
1852
|
+
trackingEvents: [],
|
|
1853
|
+
order: collectBranchOrder(adapter)
|
|
1854
|
+
};
|
|
1855
|
+
return { ok: true, changes };
|
|
1285
1856
|
}
|
|
1286
1857
|
|
|
1287
|
-
// src/
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
FINISH_TO_FINISH: "2",
|
|
1292
|
-
START_TO_FINISH: "3"
|
|
1293
|
-
};
|
|
1858
|
+
// src/shared/assert-never.ts
|
|
1859
|
+
function assertNever(value, message) {
|
|
1860
|
+
throw new Error(message);
|
|
1861
|
+
}
|
|
1294
1862
|
|
|
1295
|
-
// src/autoscheduler/
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
MILESTONE: "milestone"
|
|
1300
|
-
};
|
|
1301
|
-
var TIMING = {
|
|
1302
|
-
YIELD_SLICE_MS: 8
|
|
1303
|
-
};
|
|
1863
|
+
// src/autoscheduler/utils/cancellation.ts
|
|
1864
|
+
function createIsCurrent(id, getCurrentId) {
|
|
1865
|
+
return () => getCurrentId() === id;
|
|
1866
|
+
}
|
|
1304
1867
|
|
|
1305
1868
|
// src/shared/timing.ts
|
|
1306
1869
|
var isNode = typeof window === "undefined";
|
|
@@ -1815,9 +2378,10 @@ function findConnectedGroupForTrigger(triggerId, links) {
|
|
|
1815
2378
|
}
|
|
1816
2379
|
|
|
1817
2380
|
// src/constants/progress.ts
|
|
2381
|
+
var NOT_STARTED_PROGRESS = 0;
|
|
1818
2382
|
var COMPLETED_PROGRESS = 100;
|
|
1819
2383
|
function isAutoSchedulingEnabledForProgress(progress) {
|
|
1820
|
-
return progress ===
|
|
2384
|
+
return progress === NOT_STARTED_PROGRESS;
|
|
1821
2385
|
}
|
|
1822
2386
|
|
|
1823
2387
|
// src/autoscheduler/engine/link-calculator.ts
|
|
@@ -2759,11 +3323,11 @@ function corruptActivityIds(edges) {
|
|
|
2759
3323
|
// src/autoscheduler/links/apply-link-operation.ts
|
|
2760
3324
|
function applyLinkOperation(op, deps) {
|
|
2761
3325
|
switch (op.kind) {
|
|
2762
|
-
case
|
|
3326
|
+
case LINK_OPERATION_KIND.CREATE:
|
|
2763
3327
|
return applyCreate(op, deps);
|
|
2764
|
-
case
|
|
3328
|
+
case LINK_OPERATION_KIND.UPDATE:
|
|
2765
3329
|
return applyLinkUpdate(op, deps.port);
|
|
2766
|
-
case
|
|
3330
|
+
case LINK_OPERATION_KIND.DELETE:
|
|
2767
3331
|
return applyDelete(op, deps);
|
|
2768
3332
|
}
|
|
2769
3333
|
}
|
|
@@ -2781,15 +3345,24 @@ function applyLinkCreates(links, deps) {
|
|
|
2781
3345
|
let rejected = null;
|
|
2782
3346
|
for (const { operation, linkId } of links) {
|
|
2783
3347
|
if (String(operation.source) === String(operation.target)) {
|
|
2784
|
-
rejected = {
|
|
3348
|
+
rejected = {
|
|
3349
|
+
applied: false,
|
|
3350
|
+
rejected: LINK_REJECTION_REASON.SELF_LINK
|
|
3351
|
+
};
|
|
2785
3352
|
break;
|
|
2786
3353
|
}
|
|
2787
3354
|
if (!deps.port.getActivity(operation.source) || !deps.port.getActivity(operation.target)) {
|
|
2788
|
-
rejected = {
|
|
3355
|
+
rejected = {
|
|
3356
|
+
applied: false,
|
|
3357
|
+
rejected: LINK_REJECTION_REASON.ACTIVITY_MISSING
|
|
3358
|
+
};
|
|
2789
3359
|
break;
|
|
2790
3360
|
}
|
|
2791
3361
|
if (isSummaryHierarchyLink(operation.source, operation.target, deps.port)) {
|
|
2792
|
-
rejected = {
|
|
3362
|
+
rejected = {
|
|
3363
|
+
applied: false,
|
|
3364
|
+
rejected: LINK_REJECTION_REASON.HIERARCHY_LINK
|
|
3365
|
+
};
|
|
2793
3366
|
break;
|
|
2794
3367
|
}
|
|
2795
3368
|
const key = linkKey(operation);
|
|
@@ -2797,7 +3370,7 @@ function applyLinkCreates(links, deps) {
|
|
|
2797
3370
|
if (duplicateId !== void 0) {
|
|
2798
3371
|
rejected = {
|
|
2799
3372
|
applied: false,
|
|
2800
|
-
rejected:
|
|
3373
|
+
rejected: LINK_REJECTION_REASON.DUPLICATE,
|
|
2801
3374
|
linkId: duplicateId
|
|
2802
3375
|
};
|
|
2803
3376
|
break;
|
|
@@ -2807,12 +3380,12 @@ function applyLinkCreates(links, deps) {
|
|
|
2807
3380
|
source: operation.source,
|
|
2808
3381
|
target: operation.target
|
|
2809
3382
|
})) {
|
|
2810
|
-
return { applied: false, rejected:
|
|
3383
|
+
return { applied: false, rejected: LINK_REJECTION_REASON.CYCLE };
|
|
2811
3384
|
}
|
|
2812
3385
|
edges.push({ source: operation.source, target: operation.target });
|
|
2813
3386
|
}
|
|
2814
3387
|
if (!existingGraphHasCycle && hasDirectedCycle(edges)) {
|
|
2815
|
-
return { applied: false, rejected:
|
|
3388
|
+
return { applied: false, rejected: LINK_REJECTION_REASON.CYCLE };
|
|
2816
3389
|
}
|
|
2817
3390
|
if (rejected) return rejected;
|
|
2818
3391
|
const proposedLinks = [
|
|
@@ -2833,7 +3406,7 @@ function applyLinkCreates(links, deps) {
|
|
|
2833
3406
|
proposedLinks
|
|
2834
3407
|
});
|
|
2835
3408
|
if (!effectiveVerdict.ok) {
|
|
2836
|
-
return { applied: false, rejected:
|
|
3409
|
+
return { applied: false, rejected: LINK_REJECTION_REASON.CYCLE };
|
|
2837
3410
|
}
|
|
2838
3411
|
for (const { operation, linkId } of links) {
|
|
2839
3412
|
const preserved = deps.preserved?.get(linkId);
|
|
@@ -2858,20 +3431,30 @@ function linkKey(link) {
|
|
|
2858
3431
|
function applyCreate(op, deps) {
|
|
2859
3432
|
const { port } = deps;
|
|
2860
3433
|
if (String(op.source) === String(op.target)) {
|
|
2861
|
-
return { applied: false, rejected:
|
|
3434
|
+
return { applied: false, rejected: LINK_REJECTION_REASON.SELF_LINK };
|
|
2862
3435
|
}
|
|
2863
3436
|
const src = port.getActivity(op.source);
|
|
2864
3437
|
const tgt = port.getActivity(op.target);
|
|
2865
3438
|
if (!src || !tgt) {
|
|
2866
|
-
return {
|
|
3439
|
+
return {
|
|
3440
|
+
applied: false,
|
|
3441
|
+
rejected: LINK_REJECTION_REASON.ACTIVITY_MISSING
|
|
3442
|
+
};
|
|
2867
3443
|
}
|
|
2868
3444
|
if (isSummaryHierarchyLink(op.source, op.target, port)) {
|
|
2869
|
-
return {
|
|
3445
|
+
return {
|
|
3446
|
+
applied: false,
|
|
3447
|
+
rejected: LINK_REJECTION_REASON.HIERARCHY_LINK
|
|
3448
|
+
};
|
|
2870
3449
|
}
|
|
2871
3450
|
const existingLinks = port.getAllLinks();
|
|
2872
3451
|
for (const l of existingLinks) {
|
|
2873
3452
|
if (String(l.source) === String(op.source) && String(l.target) === String(op.target) && l.type === op.type) {
|
|
2874
|
-
return {
|
|
3453
|
+
return {
|
|
3454
|
+
applied: false,
|
|
3455
|
+
rejected: LINK_REJECTION_REASON.DUPLICATE,
|
|
3456
|
+
linkId: l.id
|
|
3457
|
+
};
|
|
2875
3458
|
}
|
|
2876
3459
|
}
|
|
2877
3460
|
const asEdges = existingLinks.map((l) => ({
|
|
@@ -2879,7 +3462,7 @@ function applyCreate(op, deps) {
|
|
|
2879
3462
|
target: l.target
|
|
2880
3463
|
}));
|
|
2881
3464
|
if (wouldIntroduceCycle(asEdges, { source: op.source, target: op.target })) {
|
|
2882
|
-
return { applied: false, rejected:
|
|
3465
|
+
return { applied: false, rejected: LINK_REJECTION_REASON.CYCLE };
|
|
2883
3466
|
}
|
|
2884
3467
|
const id = (deps.newLinkId ?? defaultNewLinkId)();
|
|
2885
3468
|
const link = {
|
|
@@ -2897,14 +3480,16 @@ function applyCreate(op, deps) {
|
|
|
2897
3480
|
proposedLinks: [...existingLinks, link]
|
|
2898
3481
|
});
|
|
2899
3482
|
if (!effectiveVerdict.ok) {
|
|
2900
|
-
return { applied: false, rejected:
|
|
3483
|
+
return { applied: false, rejected: LINK_REJECTION_REASON.CYCLE };
|
|
2901
3484
|
}
|
|
2902
3485
|
port.addLink(link);
|
|
2903
3486
|
return { applied: true, linkId: id };
|
|
2904
3487
|
}
|
|
2905
3488
|
function applyLinkUpdate(op, port) {
|
|
2906
3489
|
const link = port.getLink(op.linkId);
|
|
2907
|
-
if (!link)
|
|
3490
|
+
if (!link) {
|
|
3491
|
+
return { applied: false, rejected: LINK_REJECTION_REASON.LINK_MISSING };
|
|
3492
|
+
}
|
|
2908
3493
|
if (op.lag !== void 0) port.setLinkField(op.linkId, "lag", op.lag);
|
|
2909
3494
|
if (op.type !== void 0) port.setLinkField(op.linkId, "type", op.type);
|
|
2910
3495
|
return { applied: true, linkId: op.linkId };
|
|
@@ -2912,7 +3497,9 @@ function applyLinkUpdate(op, port) {
|
|
|
2912
3497
|
function applyDelete(op, deps) {
|
|
2913
3498
|
const { port } = deps;
|
|
2914
3499
|
const link = port.getLink(op.linkId);
|
|
2915
|
-
if (!link)
|
|
3500
|
+
if (!link) {
|
|
3501
|
+
return { applied: false, rejected: LINK_REJECTION_REASON.LINK_MISSING };
|
|
3502
|
+
}
|
|
2916
3503
|
port.removeLink(op.linkId);
|
|
2917
3504
|
return { applied: true, linkId: op.linkId };
|
|
2918
3505
|
}
|
|
@@ -3104,8 +3691,8 @@ var currentImpl = {
|
|
|
3104
3691
|
};
|
|
3105
3692
|
|
|
3106
3693
|
// src/autoscheduler/date-math/types.ts
|
|
3107
|
-
function pickDatesForLinkType(source, target,
|
|
3108
|
-
switch (
|
|
3694
|
+
function pickDatesForLinkType(source, target, linkType2) {
|
|
3695
|
+
switch (linkType2) {
|
|
3109
3696
|
case "0":
|
|
3110
3697
|
return { sourceDate: source.endDate, targetDate: target.startDate };
|
|
3111
3698
|
case "1":
|
|
@@ -4848,13 +5435,34 @@ function findPipelineForColumn(columnName) {
|
|
|
4848
5435
|
return COLUMN_PIPELINES.get(columnName);
|
|
4849
5436
|
}
|
|
4850
5437
|
|
|
5438
|
+
// src/dispatch/types.ts
|
|
5439
|
+
var ACTIVITY_BATCH_MODE = {
|
|
5440
|
+
APPEND: "append",
|
|
5441
|
+
REPLACE: "replace"
|
|
5442
|
+
};
|
|
5443
|
+
var SCHEDULE_EFFECT_KIND = {
|
|
5444
|
+
SIR_AUTO_REJECT: "sir-auto-reject"
|
|
5445
|
+
};
|
|
5446
|
+
var SIR_AUTO_REJECT_REASON = {
|
|
5447
|
+
DATE_CHANGED: "date_changed",
|
|
5448
|
+
ACTIVITY_DELETED: "activity_deleted"
|
|
5449
|
+
};
|
|
5450
|
+
var CONSTRAINT_WARNING_KIND = {
|
|
5451
|
+
VIOLATION: "constraint_violation"
|
|
5452
|
+
};
|
|
5453
|
+
var CHANGE_SET_SOURCE_KIND = {
|
|
5454
|
+
INIT: "init",
|
|
5455
|
+
UNDO: "undo",
|
|
5456
|
+
REDO: "redo"
|
|
5457
|
+
};
|
|
5458
|
+
|
|
4851
5459
|
// src/dispatch/shared/constraint-warnings.ts
|
|
4852
5460
|
function toConstraintWarning(activityId, notification) {
|
|
4853
5461
|
if (!notification || notification.type !== "constraint") return null;
|
|
4854
5462
|
const data = notification.data;
|
|
4855
5463
|
if (!data?.constraintType || !data.constraintDate) return null;
|
|
4856
5464
|
return {
|
|
4857
|
-
kind:
|
|
5465
|
+
kind: CONSTRAINT_WARNING_KIND.VIOLATION,
|
|
4858
5466
|
activityId,
|
|
4859
5467
|
constraintType: data.constraintType,
|
|
4860
5468
|
constraintDate: data.constraintDate,
|
|
@@ -5230,13 +5838,6 @@ function applyExpectedProgressLive(state, now) {
|
|
|
5230
5838
|
computeExpectedProgressLive(rootIds, now, state);
|
|
5231
5839
|
}
|
|
5232
5840
|
|
|
5233
|
-
// src/propagations/shared/get-active-baseline.ts
|
|
5234
|
-
function getActiveBaseline(activity) {
|
|
5235
|
-
const points = activity?.baselinePoints;
|
|
5236
|
-
if (!Array.isArray(points) || points.length === 0) return null;
|
|
5237
|
-
return points.find((point) => point.isActiveVersion) ?? null;
|
|
5238
|
-
}
|
|
5239
|
-
|
|
5240
5841
|
// src/columns/expected-progress-base/compute.ts
|
|
5241
5842
|
var isProject2 = (a) => a.type === "project";
|
|
5242
5843
|
var activeBaselineOf = (a) => getActiveBaseline(a);
|
|
@@ -5295,15 +5896,15 @@ function runExpectedProgressBase(state, now, defaultBaseCalendarId = null) {
|
|
|
5295
5896
|
}
|
|
5296
5897
|
|
|
5297
5898
|
// src/columns/status/constants.ts
|
|
5298
|
-
var DEFAULT_STATUS_CRITERIA =
|
|
5899
|
+
var DEFAULT_STATUS_CRITERIA = STATUS_CRITERIA.BASELINE;
|
|
5299
5900
|
function resolveStatusCriteria(value) {
|
|
5300
|
-
return value ===
|
|
5901
|
+
return value === STATUS_CRITERIA.ACTUAL ? STATUS_CRITERIA.ACTUAL : DEFAULT_STATUS_CRITERIA;
|
|
5301
5902
|
}
|
|
5302
5903
|
|
|
5303
5904
|
// src/columns/status/compute.ts
|
|
5304
5905
|
var roundToTwoDecimals = (value) => Math.round(value * 100) / 100;
|
|
5305
5906
|
function resolveExpectedForStatus(activity, criteria) {
|
|
5306
|
-
const value = criteria ===
|
|
5907
|
+
const value = criteria === STATUS_CRITERIA.BASELINE ? activity.expectedProgressBaseline : activity.expectedProgress;
|
|
5307
5908
|
return value ?? void 0;
|
|
5308
5909
|
}
|
|
5309
5910
|
function deriveActivityStatus(progress, expectedProgress) {
|
|
@@ -5430,7 +6031,7 @@ var CONSTRAINT_TYPES = Object.freeze({
|
|
|
5430
6031
|
});
|
|
5431
6032
|
|
|
5432
6033
|
// src/critical-path/legacy/constants/linkTypes.js
|
|
5433
|
-
var
|
|
6034
|
+
var LINK_TYPES2 = Object.freeze({
|
|
5434
6035
|
FS: "fs",
|
|
5435
6036
|
SS: "ss",
|
|
5436
6037
|
FF: "ff",
|
|
@@ -5718,13 +6319,13 @@ function getMaxEarlyStartSet(arrayCalculatedLinks) {
|
|
|
5718
6319
|
|
|
5719
6320
|
// src/critical-path/legacy/base/parents-calculations/helpers.js
|
|
5720
6321
|
function mutateDate({
|
|
5721
|
-
linkType,
|
|
6322
|
+
linkType: linkType2,
|
|
5722
6323
|
lag,
|
|
5723
6324
|
predecessorTime,
|
|
5724
6325
|
activityCalendar,
|
|
5725
6326
|
activity
|
|
5726
6327
|
}) {
|
|
5727
|
-
if (
|
|
6328
|
+
if (linkType2 === LINK_TYPES2.FS && lag === 0) {
|
|
5728
6329
|
return getNextWorkingHour({
|
|
5729
6330
|
activityCalendar,
|
|
5730
6331
|
direction: "future",
|
|
@@ -5733,7 +6334,7 @@ function mutateDate({
|
|
|
5733
6334
|
} else {
|
|
5734
6335
|
return mutateTheDateToFutureOrPastInBaseRestriction(
|
|
5735
6336
|
predecessorTime,
|
|
5736
|
-
|
|
6337
|
+
linkType2,
|
|
5737
6338
|
activityCalendar,
|
|
5738
6339
|
activity
|
|
5739
6340
|
);
|
|
@@ -5760,10 +6361,10 @@ function calculateRestrictionSnet({
|
|
|
5760
6361
|
return { es, ef };
|
|
5761
6362
|
}
|
|
5762
6363
|
function mutateTheDateToFutureOrPastInBaseRestriction(dateBaseToCalculate, restrictionOfLink, activityCalendar, activity) {
|
|
5763
|
-
if (![
|
|
6364
|
+
if (![LINK_TYPES2.FS, LINK_TYPES2.SS, LINK_TYPES2.FF].includes(restrictionOfLink)) {
|
|
5764
6365
|
return dateBaseToCalculate;
|
|
5765
6366
|
}
|
|
5766
|
-
let constraintThatGoToNextWorkingHour = [
|
|
6367
|
+
let constraintThatGoToNextWorkingHour = [LINK_TYPES2.FS, LINK_TYPES2.SS];
|
|
5767
6368
|
let direction = constraintThatGoToNextWorkingHour.includes(restrictionOfLink) ? "future" : "past";
|
|
5768
6369
|
return getNextWorkingHour({
|
|
5769
6370
|
dateBaseToCalculate,
|
|
@@ -5803,18 +6404,18 @@ var CalculateForwardParentsWithLinks = class {
|
|
|
5803
6404
|
const calculations = [];
|
|
5804
6405
|
for (const linkedActivity of this.linkedActivitiesData) {
|
|
5805
6406
|
const linkTypeCode = linkedActivity.linkType;
|
|
5806
|
-
const
|
|
6407
|
+
const linkType2 = getLinkNameByCode(linkTypeCode);
|
|
5807
6408
|
const lag = linkedActivity.linkLag;
|
|
5808
6409
|
const predecessorEs = linkedActivity.es;
|
|
5809
6410
|
const predecessorEf = linkedActivity.ef;
|
|
5810
6411
|
let calculation = null;
|
|
5811
|
-
if (
|
|
6412
|
+
if (linkType2 === "ss") {
|
|
5812
6413
|
calculation = this.calculateSSLink({ lag, predecessorEs });
|
|
5813
|
-
} else if (
|
|
6414
|
+
} else if (linkType2 === "ff") {
|
|
5814
6415
|
calculation = this.calculateFFLink({ lag, predecessorEf });
|
|
5815
|
-
} else if (
|
|
6416
|
+
} else if (linkType2 === "fs") {
|
|
5816
6417
|
calculation = this.calculateFSLink({ lag, predecessorEf });
|
|
5817
|
-
} else if (
|
|
6418
|
+
} else if (linkType2 === "sf") {
|
|
5818
6419
|
calculation = this.calculateSFLink({
|
|
5819
6420
|
lag,
|
|
5820
6421
|
predecessorEs,
|
|
@@ -5983,7 +6584,7 @@ var CalculateBackwardParentsLinks = class {
|
|
|
5983
6584
|
}
|
|
5984
6585
|
const calculationsFromLinks = [];
|
|
5985
6586
|
for (let linkedActivity of this.linkedActivitiesData) {
|
|
5986
|
-
const
|
|
6587
|
+
const linkType2 = getLinkNameByCode(linkedActivity.linkType);
|
|
5987
6588
|
if (linkedActivity.type === "task" && Number(linkedActivity.progress) > 0) {
|
|
5988
6589
|
continue;
|
|
5989
6590
|
}
|
|
@@ -5993,7 +6594,7 @@ var CalculateBackwardParentsLinks = class {
|
|
|
5993
6594
|
const lag = linkedActivity.linkLag;
|
|
5994
6595
|
let sucessorLs = linkedActivity.ls;
|
|
5995
6596
|
let sucessorLf = linkedActivity.lf;
|
|
5996
|
-
if (
|
|
6597
|
+
if (linkType2 === "ss") {
|
|
5997
6598
|
const valuesToDoCalculation = {
|
|
5998
6599
|
lag,
|
|
5999
6600
|
workTime: sucessorLs,
|
|
@@ -6003,7 +6604,7 @@ var CalculateBackwardParentsLinks = class {
|
|
|
6003
6604
|
let { ls, lf } = this.calculateSSLink(valuesToDoCalculation);
|
|
6004
6605
|
calculationsFromLinks.push({ ls, lf });
|
|
6005
6606
|
}
|
|
6006
|
-
if (
|
|
6607
|
+
if (linkType2 === "ff") {
|
|
6007
6608
|
const valuesToDoCalculation = {
|
|
6008
6609
|
lag,
|
|
6009
6610
|
workTime: sucessorLf,
|
|
@@ -6013,7 +6614,7 @@ var CalculateBackwardParentsLinks = class {
|
|
|
6013
6614
|
let { ls, lf } = this.calculateFFLink(valuesToDoCalculation);
|
|
6014
6615
|
calculationsFromLinks.push({ ls, lf });
|
|
6015
6616
|
}
|
|
6016
|
-
if (
|
|
6617
|
+
if (linkType2 === "fs") {
|
|
6017
6618
|
const valuesToDoCalculation = {
|
|
6018
6619
|
lag,
|
|
6019
6620
|
workTime: sucessorLs,
|
|
@@ -6023,7 +6624,7 @@ var CalculateBackwardParentsLinks = class {
|
|
|
6023
6624
|
let { ls, lf } = this.calculateFsLink(valuesToDoCalculation);
|
|
6024
6625
|
calculationsFromLinks.push({ ls, lf });
|
|
6025
6626
|
}
|
|
6026
|
-
if (
|
|
6627
|
+
if (linkType2 === "sf") {
|
|
6027
6628
|
const valuesToDoCalculation = {
|
|
6028
6629
|
lag,
|
|
6029
6630
|
workTime: sucessorLf,
|
|
@@ -7213,7 +7814,7 @@ var LinksRulesCalculationsMethods = class {
|
|
|
7213
7814
|
}
|
|
7214
7815
|
return this.calculatedActivities.get(Number(activity));
|
|
7215
7816
|
}
|
|
7216
|
-
calculateSucessorTimes(predecessorTime, esDataCalculation, efDataCalculation = 0, lag, restrictionOfLink =
|
|
7817
|
+
calculateSucessorTimes(predecessorTime, esDataCalculation, efDataCalculation = 0, lag, restrictionOfLink = LINK_TYPES2.FS) {
|
|
7217
7818
|
const activityCalendar = this.gantt.getCalendar(
|
|
7218
7819
|
this.referenceActivity.calendar_id
|
|
7219
7820
|
);
|
|
@@ -7227,7 +7828,7 @@ var LinksRulesCalculationsMethods = class {
|
|
|
7227
7828
|
let ef = null;
|
|
7228
7829
|
const isAMilestone = this.referenceActivity.type === "milestone";
|
|
7229
7830
|
if (!isAMilestone) {
|
|
7230
|
-
if (restrictionOfLink ===
|
|
7831
|
+
if (restrictionOfLink === LINK_TYPES2.FS && lag === 0) {
|
|
7231
7832
|
dateBaseToCalculate = getNextWorkingHour({
|
|
7232
7833
|
dateBaseToCalculate,
|
|
7233
7834
|
activityCalendar,
|
|
@@ -7242,7 +7843,7 @@ var LinksRulesCalculationsMethods = class {
|
|
|
7242
7843
|
);
|
|
7243
7844
|
}
|
|
7244
7845
|
}
|
|
7245
|
-
if ([
|
|
7846
|
+
if ([LINK_TYPES2.FF, LINK_TYPES2.SF].includes(restrictionOfLink)) {
|
|
7246
7847
|
ef = addDurationToDate(
|
|
7247
7848
|
activityCalendar,
|
|
7248
7849
|
dateBaseToCalculate,
|
|
@@ -7296,7 +7897,7 @@ var LinksRulesCalculationsMethods = class {
|
|
|
7296
7897
|
esDataCalculation,
|
|
7297
7898
|
efDataCalculation,
|
|
7298
7899
|
lag,
|
|
7299
|
-
|
|
7900
|
+
LINK_TYPES2.SS
|
|
7300
7901
|
);
|
|
7301
7902
|
}
|
|
7302
7903
|
calculateFF(link) {
|
|
@@ -7310,7 +7911,7 @@ var LinksRulesCalculationsMethods = class {
|
|
|
7310
7911
|
esDataCalculation,
|
|
7311
7912
|
efDataCalculation,
|
|
7312
7913
|
lag,
|
|
7313
|
-
|
|
7914
|
+
LINK_TYPES2.FF
|
|
7314
7915
|
);
|
|
7315
7916
|
}
|
|
7316
7917
|
calculateFS(link) {
|
|
@@ -7324,7 +7925,7 @@ var LinksRulesCalculationsMethods = class {
|
|
|
7324
7925
|
esDataCalculation,
|
|
7325
7926
|
efDataCalculation,
|
|
7326
7927
|
lag,
|
|
7327
|
-
|
|
7928
|
+
LINK_TYPES2.FS
|
|
7328
7929
|
);
|
|
7329
7930
|
}
|
|
7330
7931
|
calculateSF(link) {
|
|
@@ -7338,14 +7939,14 @@ var LinksRulesCalculationsMethods = class {
|
|
|
7338
7939
|
esDataCalculation,
|
|
7339
7940
|
efDataCalculation,
|
|
7340
7941
|
lag,
|
|
7341
|
-
|
|
7942
|
+
LINK_TYPES2.SF
|
|
7342
7943
|
);
|
|
7343
7944
|
}
|
|
7344
7945
|
mutateTheDateToFutureOrPastInBaseRestriction(dateBaseToCalculate, restrictionOfLink, activityCalendar) {
|
|
7345
|
-
if (![
|
|
7946
|
+
if (![LINK_TYPES2.FS, LINK_TYPES2.SS, LINK_TYPES2.FF].includes(restrictionOfLink)) {
|
|
7346
7947
|
return dateBaseToCalculate;
|
|
7347
7948
|
}
|
|
7348
|
-
const constraintThatGoToNextWorkingHour = [
|
|
7949
|
+
const constraintThatGoToNextWorkingHour = [LINK_TYPES2.FS, LINK_TYPES2.SS];
|
|
7349
7950
|
const direction = constraintThatGoToNextWorkingHour.includes(
|
|
7350
7951
|
restrictionOfLink
|
|
7351
7952
|
) ? "future" : "past";
|
|
@@ -7880,7 +8481,7 @@ var CalculationsGenericMethods = class {
|
|
|
7880
8481
|
}
|
|
7881
8482
|
return this.calculatedActivities.get(activity);
|
|
7882
8483
|
}
|
|
7883
|
-
calculateSuccessorTimes(sucessorTime, lsDataCalculation, lfDataCalculation = 0, lag, type =
|
|
8484
|
+
calculateSuccessorTimes(sucessorTime, lsDataCalculation, lfDataCalculation = 0, lag, type = LINK_TYPES2.FS) {
|
|
7884
8485
|
let activityCalendar = this.gantt.getCalendar(this.activity.calendar_id);
|
|
7885
8486
|
if (!activityCalendar) {
|
|
7886
8487
|
throw new Error(
|
|
@@ -7912,19 +8513,19 @@ var CalculationsGenericMethods = class {
|
|
|
7912
8513
|
lfDataCalculation,
|
|
7913
8514
|
isMilestone
|
|
7914
8515
|
};
|
|
7915
|
-
if (type ===
|
|
8516
|
+
if (type === LINK_TYPES2.FS) {
|
|
7916
8517
|
let { ls, lf } = this.calculateFsLink(valuesToDoCalculation);
|
|
7917
8518
|
return { ls, lf };
|
|
7918
8519
|
}
|
|
7919
|
-
if (type ===
|
|
8520
|
+
if (type === LINK_TYPES2.FF) {
|
|
7920
8521
|
let { ls, lf } = this.calculateFFLink(valuesToDoCalculation);
|
|
7921
8522
|
return { ls, lf };
|
|
7922
8523
|
}
|
|
7923
|
-
if (type ===
|
|
8524
|
+
if (type === LINK_TYPES2.SS) {
|
|
7924
8525
|
let { ls, lf } = this.calculateSSlink(valuesToDoCalculation);
|
|
7925
8526
|
return { ls, lf };
|
|
7926
8527
|
}
|
|
7927
|
-
if (type ===
|
|
8528
|
+
if (type === LINK_TYPES2.SF) {
|
|
7928
8529
|
let { ls, lf } = this.calculateSFLink(valuesToDoCalculation);
|
|
7929
8530
|
return { ls, lf };
|
|
7930
8531
|
}
|
|
@@ -7939,7 +8540,7 @@ var CalculationsGenericMethods = class {
|
|
|
7939
8540
|
lsDataForCalculation,
|
|
7940
8541
|
lfDataForCalculation,
|
|
7941
8542
|
lag,
|
|
7942
|
-
|
|
8543
|
+
LINK_TYPES2.SS
|
|
7943
8544
|
);
|
|
7944
8545
|
}
|
|
7945
8546
|
calculateFF(link, constraint) {
|
|
@@ -7956,7 +8557,7 @@ var CalculationsGenericMethods = class {
|
|
|
7956
8557
|
lsDataForCalculation,
|
|
7957
8558
|
lfDataForCalculation,
|
|
7958
8559
|
lag,
|
|
7959
|
-
|
|
8560
|
+
LINK_TYPES2.FF
|
|
7960
8561
|
);
|
|
7961
8562
|
}
|
|
7962
8563
|
calculateFS(link, constraint) {
|
|
@@ -7974,7 +8575,7 @@ var CalculationsGenericMethods = class {
|
|
|
7974
8575
|
lsDataForCalculation,
|
|
7975
8576
|
lfDataForCalculation,
|
|
7976
8577
|
lag,
|
|
7977
|
-
|
|
8578
|
+
LINK_TYPES2.FS
|
|
7978
8579
|
);
|
|
7979
8580
|
}
|
|
7980
8581
|
calculateSF(link, getFromForward = false) {
|
|
@@ -7987,7 +8588,7 @@ var CalculationsGenericMethods = class {
|
|
|
7987
8588
|
lsDataForCalculation,
|
|
7988
8589
|
lfDataForCalculation,
|
|
7989
8590
|
lag,
|
|
7990
|
-
|
|
8591
|
+
LINK_TYPES2.SF
|
|
7991
8592
|
);
|
|
7992
8593
|
}
|
|
7993
8594
|
getEarlyStartFromForwardPath(link) {
|
|
@@ -9175,7 +9776,7 @@ var FreeFloat = class {
|
|
|
9175
9776
|
}
|
|
9176
9777
|
return constraint_type;
|
|
9177
9778
|
}
|
|
9178
|
-
getDatesFromSucessorAndPredecessor(
|
|
9779
|
+
getDatesFromSucessorAndPredecessor(linkType2, constraint, sucessor) {
|
|
9179
9780
|
const isSuscessorAlap = sucessor.constraint_type === CONSTRAINT_TYPES.ALAP;
|
|
9180
9781
|
const constraintData = this.getSucessorAndPredecessorDates({
|
|
9181
9782
|
constraint,
|
|
@@ -9185,8 +9786,8 @@ var FreeFloat = class {
|
|
|
9185
9786
|
});
|
|
9186
9787
|
let sucessorDateToCalculate = /* @__PURE__ */ new Date();
|
|
9187
9788
|
let predecessorDateToCalculate = /* @__PURE__ */ new Date();
|
|
9188
|
-
sucessorDateToCalculate = constraintData[
|
|
9189
|
-
predecessorDateToCalculate = constraintData[
|
|
9789
|
+
sucessorDateToCalculate = constraintData[linkType2].sucessor;
|
|
9790
|
+
predecessorDateToCalculate = constraintData[linkType2].predecessor;
|
|
9190
9791
|
return {
|
|
9191
9792
|
sucessorDateToCalculate,
|
|
9192
9793
|
predecessorDateToCalculate
|
|
@@ -10358,10 +10959,10 @@ function detectSirAutoReject(beforeSnap, adapter, touchedIds) {
|
|
|
10358
10959
|
if (adapter.getActivity(id) != null) continue;
|
|
10359
10960
|
for (const pending of pendingRequestIds) {
|
|
10360
10961
|
effects.push({
|
|
10361
|
-
kind:
|
|
10962
|
+
kind: SCHEDULE_EFFECT_KIND.SIR_AUTO_REJECT,
|
|
10362
10963
|
activityId: id,
|
|
10363
10964
|
sirId: pending,
|
|
10364
|
-
reason:
|
|
10965
|
+
reason: SIR_AUTO_REJECT_REASON.ACTIVITY_DELETED
|
|
10365
10966
|
});
|
|
10366
10967
|
}
|
|
10367
10968
|
}
|
|
@@ -10802,11 +11403,57 @@ async function dispatchInlineEdit(action, options, deps) {
|
|
|
10802
11403
|
}
|
|
10803
11404
|
|
|
10804
11405
|
// src/dispatch/handlers/link.ts
|
|
11406
|
+
var LINK_TYPE_VALUES = new Set(Object.values(LINK_TYPE));
|
|
11407
|
+
function isValidLinkType(value) {
|
|
11408
|
+
return typeof value === "string" && LINK_TYPE_VALUES.has(value);
|
|
11409
|
+
}
|
|
11410
|
+
function hasOwn(value, property) {
|
|
11411
|
+
return Object.hasOwn(value, property);
|
|
11412
|
+
}
|
|
11413
|
+
function validateLinkAction(action) {
|
|
11414
|
+
if (action.kind === DISPATCH_ACTION_KIND.LINK_CREATE) {
|
|
11415
|
+
if (!isValidLinkType(action.type)) {
|
|
11416
|
+
return REJECTION_REASON.INVALID_LINK_TYPE;
|
|
11417
|
+
}
|
|
11418
|
+
return action.lag === void 0 || Number.isFinite(action.lag) ? null : REJECTION_REASON.INVALID_LINK_LAG;
|
|
11419
|
+
}
|
|
11420
|
+
if (action.kind === DISPATCH_ACTION_KIND.LINK_UPDATE) {
|
|
11421
|
+
if (hasOwn(action, "type") && !isValidLinkType(action.type)) {
|
|
11422
|
+
return REJECTION_REASON.INVALID_LINK_TYPE;
|
|
11423
|
+
}
|
|
11424
|
+
if (hasOwn(action, "lag") && !Number.isFinite(action.lag)) {
|
|
11425
|
+
return REJECTION_REASON.INVALID_LINK_LAG;
|
|
11426
|
+
}
|
|
11427
|
+
}
|
|
11428
|
+
return null;
|
|
11429
|
+
}
|
|
11430
|
+
function validateLinkBatchOperation(operation) {
|
|
11431
|
+
if (operation.kind === DISPATCH_LINK_OPERATION_KIND.CREATE) {
|
|
11432
|
+
if (!isValidLinkType(operation.type)) {
|
|
11433
|
+
return REJECTION_REASON.INVALID_LINK_TYPE;
|
|
11434
|
+
}
|
|
11435
|
+
return operation.lag === void 0 || Number.isFinite(operation.lag) ? null : REJECTION_REASON.INVALID_LINK_LAG;
|
|
11436
|
+
}
|
|
11437
|
+
if (operation.kind === DISPATCH_LINK_OPERATION_KIND.UPDATE) {
|
|
11438
|
+
if (hasOwn(operation, "type") && !isValidLinkType(operation.type)) {
|
|
11439
|
+
return REJECTION_REASON.INVALID_LINK_TYPE;
|
|
11440
|
+
}
|
|
11441
|
+
return !hasOwn(operation, "lag") || Number.isFinite(operation.lag) ? null : REJECTION_REASON.INVALID_LINK_LAG;
|
|
11442
|
+
}
|
|
11443
|
+
return operation.kind === DISPATCH_LINK_OPERATION_KIND.DELETE ? null : REJECTION_REASON.INVALID_VALUE;
|
|
11444
|
+
}
|
|
11445
|
+
function validateLinkBatch(operations) {
|
|
11446
|
+
for (const operation of operations) {
|
|
11447
|
+
const error = validateLinkBatchOperation(operation);
|
|
11448
|
+
if (error !== null) return error;
|
|
11449
|
+
}
|
|
11450
|
+
return null;
|
|
11451
|
+
}
|
|
10805
11452
|
function collectBatchContext(operations, adapter) {
|
|
10806
11453
|
const activityIds = /* @__PURE__ */ new Set();
|
|
10807
11454
|
const links = /* @__PURE__ */ new Map();
|
|
10808
11455
|
for (const operation of operations) {
|
|
10809
|
-
if (operation.kind ===
|
|
11456
|
+
if (operation.kind === DISPATCH_LINK_OPERATION_KIND.CREATE) {
|
|
10810
11457
|
activityIds.add(String(operation.source));
|
|
10811
11458
|
activityIds.add(String(operation.target));
|
|
10812
11459
|
continue;
|
|
@@ -10821,7 +11468,7 @@ function collectBatchContext(operations, adapter) {
|
|
|
10821
11468
|
}
|
|
10822
11469
|
function applyBatchOperations(operations, adapter, linkIdGen, deterministicIds) {
|
|
10823
11470
|
return operations.map((operation, index) => {
|
|
10824
|
-
const deterministicId = operation.kind ===
|
|
11471
|
+
const deterministicId = operation.kind === DISPATCH_LINK_OPERATION_KIND.CREATE ? deterministicIds?.get(index) : void 0;
|
|
10825
11472
|
const result = applyLinkOperation(operation, {
|
|
10826
11473
|
port: adapter,
|
|
10827
11474
|
newLinkId: deterministicId ? () => deterministicId : linkIdGen.next
|
|
@@ -10829,7 +11476,7 @@ function applyBatchOperations(operations, adapter, linkIdGen, deterministicIds)
|
|
|
10829
11476
|
return {
|
|
10830
11477
|
op: operation,
|
|
10831
11478
|
finalLinkId: result.applied ? result.linkId : null,
|
|
10832
|
-
rejected: result.applied ? null : result.rejected ??
|
|
11479
|
+
rejected: result.applied ? null : result.rejected ?? REJECTION_REASON.INVALID
|
|
10833
11480
|
};
|
|
10834
11481
|
});
|
|
10835
11482
|
}
|
|
@@ -10837,25 +11484,19 @@ function stringKeyedLinkSnapshots(links) {
|
|
|
10837
11484
|
return new Map([...links].map(([id, link]) => [String(id), link]));
|
|
10838
11485
|
}
|
|
10839
11486
|
async function dispatchLink(action, options, deps) {
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
if (type !== void 0 && !Object.values(LINK_TYPE).some((t) => t === type)) {
|
|
10843
|
-
return { ok: false, reason: REJECTION_REASON.INVALID_LINK_TYPE };
|
|
10844
|
-
}
|
|
10845
|
-
const lag = action.lag;
|
|
10846
|
-
if (lag !== void 0 && !Number.isFinite(lag)) {
|
|
10847
|
-
return { ok: false, reason: REJECTION_REASON.INVALID_LINK_LAG };
|
|
10848
|
-
}
|
|
10849
|
-
}
|
|
11487
|
+
const validationError = validateLinkAction(action);
|
|
11488
|
+
if (validationError !== null) return { ok: false, reason: validationError };
|
|
10850
11489
|
return dispatchLinkBatch(
|
|
10851
11490
|
[toLinkOperation(action, deps.sector.hoursPerDay)],
|
|
10852
11491
|
action,
|
|
10853
11492
|
options,
|
|
10854
11493
|
deps,
|
|
10855
|
-
action.kind ===
|
|
11494
|
+
action.kind === DISPATCH_ACTION_KIND.LINK_CREATE && action.linkId ? /* @__PURE__ */ new Map([[0, action.linkId]]) : void 0
|
|
10856
11495
|
);
|
|
10857
11496
|
}
|
|
10858
11497
|
async function dispatchLinksBatch(action, options, deps) {
|
|
11498
|
+
const validationError = validateLinkBatch(action.operations);
|
|
11499
|
+
if (validationError !== null) return { ok: false, reason: validationError };
|
|
10859
11500
|
const { hoursPerDay } = deps.sector;
|
|
10860
11501
|
const operations = action.operations.map(
|
|
10861
11502
|
(op) => batchOpToLinkOperation(op, hoursPerDay)
|
|
@@ -10866,7 +11507,9 @@ async function dispatchLinksBatch(action, options, deps) {
|
|
|
10866
11507
|
function collectDeterministicIds(operations) {
|
|
10867
11508
|
const ids = /* @__PURE__ */ new Map();
|
|
10868
11509
|
operations.forEach((op, index) => {
|
|
10869
|
-
if (op.kind ===
|
|
11510
|
+
if (op.kind === DISPATCH_LINK_OPERATION_KIND.CREATE && op.linkId) {
|
|
11511
|
+
ids.set(index, op.linkId);
|
|
11512
|
+
}
|
|
10870
11513
|
});
|
|
10871
11514
|
return ids.size > 0 ? ids : void 0;
|
|
10872
11515
|
}
|
|
@@ -10891,24 +11534,24 @@ function resolveDeterministicIds(deterministicIds, deps) {
|
|
|
10891
11534
|
return resolved;
|
|
10892
11535
|
}
|
|
10893
11536
|
function batchOpToLinkOperation(op, hoursPerDay) {
|
|
10894
|
-
if (op.kind ===
|
|
11537
|
+
if (op.kind === DISPATCH_LINK_OPERATION_KIND.CREATE) {
|
|
10895
11538
|
return {
|
|
10896
|
-
kind:
|
|
11539
|
+
kind: DISPATCH_LINK_OPERATION_KIND.CREATE,
|
|
10897
11540
|
source: op.source,
|
|
10898
11541
|
target: op.target,
|
|
10899
11542
|
type: op.type,
|
|
10900
11543
|
lag: lagDaysToHours(op.lag ?? 0, hoursPerDay)
|
|
10901
11544
|
};
|
|
10902
11545
|
}
|
|
10903
|
-
if (op.kind ===
|
|
11546
|
+
if (op.kind === DISPATCH_LINK_OPERATION_KIND.UPDATE) {
|
|
10904
11547
|
return {
|
|
10905
|
-
kind:
|
|
11548
|
+
kind: DISPATCH_LINK_OPERATION_KIND.UPDATE,
|
|
10906
11549
|
linkId: op.linkId,
|
|
10907
11550
|
type: op.type,
|
|
10908
11551
|
lag: op.lag === void 0 ? void 0 : lagDaysToHours(op.lag, hoursPerDay)
|
|
10909
11552
|
};
|
|
10910
11553
|
}
|
|
10911
|
-
return { kind:
|
|
11554
|
+
return { kind: DISPATCH_LINK_OPERATION_KIND.DELETE, linkId: op.linkId };
|
|
10912
11555
|
}
|
|
10913
11556
|
async function dispatchLinkBatch(operations, source, options, deps, deterministicIds) {
|
|
10914
11557
|
const { adapter, scheduler, sector, linkIdGen } = deps;
|
|
@@ -10924,7 +11567,7 @@ async function dispatchLinkBatch(operations, source, options, deps, deterministi
|
|
|
10924
11567
|
linkIdGen,
|
|
10925
11568
|
resolveDeterministicIds(deterministicIds, deps)
|
|
10926
11569
|
);
|
|
10927
|
-
if (operations.length === 1 && applied[0] && applied[0].rejected !== null && source.kind !==
|
|
11570
|
+
if (operations.length === 1 && applied[0] && applied[0].rejected !== null && source.kind !== DISPATCH_ACTION_KIND.INLINE_EDIT) {
|
|
10928
11571
|
return { ok: false, reason: applied[0].rejected };
|
|
10929
11572
|
}
|
|
10930
11573
|
const triggerId = pickAutoscheduleTrigger(applied, beforeLinks, adapter);
|
|
@@ -10980,31 +11623,36 @@ function pickAutoscheduleTrigger(applied, beforeLinks, adapter) {
|
|
|
10980
11623
|
return null;
|
|
10981
11624
|
}
|
|
10982
11625
|
function autoscheduleTarget(operation, beforeLinks, adapter) {
|
|
10983
|
-
if (operation.kind ===
|
|
10984
|
-
|
|
11626
|
+
if (operation.kind === DISPATCH_LINK_OPERATION_KIND.CREATE) {
|
|
11627
|
+
return operation.target;
|
|
11628
|
+
}
|
|
11629
|
+
if (operation.kind === DISPATCH_LINK_OPERATION_KIND.DELETE) {
|
|
10985
11630
|
return beforeLinks.get(operation.linkId)?.target ?? null;
|
|
10986
11631
|
}
|
|
10987
11632
|
return adapter.getLink(operation.linkId)?.target ?? null;
|
|
10988
11633
|
}
|
|
10989
11634
|
function toLinkOperation(action, hoursPerDay) {
|
|
10990
|
-
if (action.kind ===
|
|
11635
|
+
if (action.kind === DISPATCH_ACTION_KIND.LINK_CREATE) {
|
|
10991
11636
|
return {
|
|
10992
|
-
kind:
|
|
11637
|
+
kind: DISPATCH_LINK_OPERATION_KIND.CREATE,
|
|
10993
11638
|
source: action.source,
|
|
10994
11639
|
target: action.target,
|
|
10995
11640
|
type: action.type,
|
|
10996
|
-
lag: lagDaysToHours(action.lag, hoursPerDay)
|
|
11641
|
+
lag: lagDaysToHours(action.lag ?? 0, hoursPerDay)
|
|
10997
11642
|
};
|
|
10998
11643
|
}
|
|
10999
|
-
if (action.kind ===
|
|
11644
|
+
if (action.kind === DISPATCH_ACTION_KIND.LINK_UPDATE) {
|
|
11000
11645
|
return {
|
|
11001
|
-
kind:
|
|
11646
|
+
kind: DISPATCH_LINK_OPERATION_KIND.UPDATE,
|
|
11002
11647
|
linkId: action.linkId,
|
|
11003
11648
|
type: action.type,
|
|
11004
11649
|
lag: action.lag === void 0 ? void 0 : lagDaysToHours(action.lag, hoursPerDay)
|
|
11005
11650
|
};
|
|
11006
11651
|
}
|
|
11007
|
-
return {
|
|
11652
|
+
return {
|
|
11653
|
+
kind: DISPATCH_LINK_OPERATION_KIND.DELETE,
|
|
11654
|
+
linkId: action.linkId
|
|
11655
|
+
};
|
|
11008
11656
|
}
|
|
11009
11657
|
async function dispatchInlineEditLinks(action, options, deps) {
|
|
11010
11658
|
const { adapter, sector } = deps;
|
|
@@ -12130,16 +12778,16 @@ async function dispatchActivityBatch(action, options, deps) {
|
|
|
12130
12778
|
if (validationError) return { ok: false, reason: validationError };
|
|
12131
12779
|
const plan = buildBatchPlan(action, deps);
|
|
12132
12780
|
if (!plan.ok) return plan;
|
|
12133
|
-
const existingActivityIds = action.mode ===
|
|
12134
|
-
const beforeSnap = action.mode ===
|
|
12135
|
-
const beforeLinks = action.mode ===
|
|
12136
|
-
const viewState = action.mode ===
|
|
12781
|
+
const existingActivityIds = action.mode === ACTIVITY_BATCH_MODE.REPLACE ? new Set(deps.adapter.getAllIds().map((id) => String(id))) : /* @__PURE__ */ new Set();
|
|
12782
|
+
const beforeSnap = action.mode === ACTIVITY_BATCH_MODE.REPLACE ? await snapshotActivities(deps.adapter, existingActivityIds) : /* @__PURE__ */ new Map();
|
|
12783
|
+
const beforeLinks = action.mode === ACTIVITY_BATCH_MODE.REPLACE ? snapshotAllLinks(deps) : /* @__PURE__ */ new Map();
|
|
12784
|
+
const viewState = action.mode === ACTIVITY_BATCH_MODE.REPLACE ? captureDeletedViewState(deps.adapter, existingActivityIds) : [];
|
|
12137
12785
|
deps.scheduler.invalidateAllCaches();
|
|
12138
12786
|
const appliedLinks = [];
|
|
12139
|
-
if (action.mode ===
|
|
12787
|
+
if (action.mode === ACTIVITY_BATCH_MODE.REPLACE) {
|
|
12140
12788
|
for (const linkId of beforeLinks.keys()) {
|
|
12141
12789
|
const deleted = applyLinkOperation(
|
|
12142
|
-
{ kind:
|
|
12790
|
+
{ kind: DISPATCH_LINK_OPERATION_KIND.DELETE, linkId },
|
|
12143
12791
|
{ port: deps.adapter }
|
|
12144
12792
|
);
|
|
12145
12793
|
if (!deleted.applied) {
|
|
@@ -12149,7 +12797,7 @@ async function dispatchActivityBatch(action, options, deps) {
|
|
|
12149
12797
|
};
|
|
12150
12798
|
}
|
|
12151
12799
|
appliedLinks.push({
|
|
12152
|
-
op: { kind:
|
|
12800
|
+
op: { kind: DISPATCH_LINK_OPERATION_KIND.DELETE, linkId },
|
|
12153
12801
|
finalLinkId: linkId,
|
|
12154
12802
|
rejected: null
|
|
12155
12803
|
});
|
|
@@ -12171,7 +12819,7 @@ async function dispatchActivityBatch(action, options, deps) {
|
|
|
12171
12819
|
const existingCorrelativeShifts = correlativeShifts.filter(
|
|
12172
12820
|
(shift) => !createdIdSet.has(shift.activityId)
|
|
12173
12821
|
);
|
|
12174
|
-
const touchedIds = action.mode ===
|
|
12822
|
+
const touchedIds = action.mode === ACTIVITY_BATCH_MODE.REPLACE ? new Set(existingActivityIds) : /* @__PURE__ */ new Set();
|
|
12175
12823
|
foldCorrelativeShifts(
|
|
12176
12824
|
deps.adapter,
|
|
12177
12825
|
correlativeShifts,
|
|
@@ -12184,11 +12832,11 @@ async function dispatchActivityBatch(action, options, deps) {
|
|
|
12184
12832
|
}
|
|
12185
12833
|
const linkCreates = plan.plan.links.map((link) => ({
|
|
12186
12834
|
operation: {
|
|
12187
|
-
kind:
|
|
12835
|
+
kind: DISPATCH_LINK_OPERATION_KIND.CREATE,
|
|
12188
12836
|
source: link.source,
|
|
12189
12837
|
target: link.target,
|
|
12190
12838
|
type: link.type,
|
|
12191
|
-
lag: lagDaysToHours(link.lag, deps.sector.hoursPerDay)
|
|
12839
|
+
lag: lagDaysToHours(link.lag ?? 0, deps.sector.hoursPerDay)
|
|
12192
12840
|
},
|
|
12193
12841
|
linkId: link.linkId
|
|
12194
12842
|
}));
|
|
@@ -12233,19 +12881,19 @@ async function dispatchActivityBatch(action, options, deps) {
|
|
|
12233
12881
|
links: buildLinkChangesForBatch(appliedLinks, beforeLinks, deps.adapter),
|
|
12234
12882
|
hoursPerDay: deps.sector.hoursPerDay,
|
|
12235
12883
|
correlativeShifts: existingCorrelativeShifts,
|
|
12236
|
-
...action.mode ===
|
|
12884
|
+
...action.mode === ACTIVITY_BATCH_MODE.REPLACE ? { sirDetection: "after-diff" } : {}
|
|
12237
12885
|
});
|
|
12238
12886
|
return {
|
|
12239
12887
|
ok: true,
|
|
12240
12888
|
changes: viewState.length > 0 ? { ...changes, viewState } : changes,
|
|
12241
|
-
...action.mode ===
|
|
12889
|
+
...action.mode === ACTIVITY_BATCH_MODE.REPLACE ? {
|
|
12242
12890
|
__beforeSnap: beforeSnap,
|
|
12243
12891
|
__beforeLinks: stringKeyedLinks(beforeLinks)
|
|
12244
12892
|
} : {}
|
|
12245
12893
|
};
|
|
12246
12894
|
}
|
|
12247
12895
|
function validateBatch(action, deps) {
|
|
12248
|
-
if (action.mode !==
|
|
12896
|
+
if (action.mode !== ACTIVITY_BATCH_MODE.APPEND && action.mode !== ACTIVITY_BATCH_MODE.REPLACE) {
|
|
12249
12897
|
return REJECTION_REASON.INVALID;
|
|
12250
12898
|
}
|
|
12251
12899
|
const batchIds = /* @__PURE__ */ new Set();
|
|
@@ -12260,7 +12908,7 @@ function validateBatch(action, deps) {
|
|
|
12260
12908
|
}
|
|
12261
12909
|
if (item.activityId !== void 0) {
|
|
12262
12910
|
const activityId = String(item.activityId);
|
|
12263
|
-
if (activityId.length === 0 || activityId ===
|
|
12911
|
+
if (activityId.length === 0 || activityId === ROOT_PARENT_ID || explicitActivityIds.has(activityId)) {
|
|
12264
12912
|
return REJECTION_REASON.INVALID;
|
|
12265
12913
|
}
|
|
12266
12914
|
explicitActivityIds.add(activityId);
|
|
@@ -12274,8 +12922,11 @@ function validateBatch(action, deps) {
|
|
|
12274
12922
|
if (hasParentCycle(action.items)) return REJECTION_REASON.INVALID;
|
|
12275
12923
|
const explicitLinkIds = /* @__PURE__ */ new Set();
|
|
12276
12924
|
for (const link of action.links) {
|
|
12277
|
-
if (!Object.values(LINK_TYPE).includes(link.type)
|
|
12278
|
-
return
|
|
12925
|
+
if (!Object.values(LINK_TYPE).includes(link.type)) {
|
|
12926
|
+
return REJECTION_REASON.INVALID_LINK_TYPE;
|
|
12927
|
+
}
|
|
12928
|
+
if (link.lag !== void 0 && !Number.isFinite(link.lag)) {
|
|
12929
|
+
return REJECTION_REASON.INVALID_LINK_LAG;
|
|
12279
12930
|
}
|
|
12280
12931
|
if (!validReference(link.source, false, action.mode, batchIds, deps) || !validReference(link.target, false, action.mode, batchIds, deps)) {
|
|
12281
12932
|
return REJECTION_REASON.ACTIVITY_NOT_FOUND;
|
|
@@ -12292,8 +12943,8 @@ function validateBatch(action, deps) {
|
|
|
12292
12943
|
}
|
|
12293
12944
|
function validReference(reference, allowRoot, mode, batchIds, deps) {
|
|
12294
12945
|
if (typeof reference === "string") {
|
|
12295
|
-
if (reference ===
|
|
12296
|
-
return mode ===
|
|
12946
|
+
if (reference === ROOT_PARENT_ID) return allowRoot;
|
|
12947
|
+
return mode === ACTIVITY_BATCH_MODE.APPEND && deps.adapter.getActivity(String(reference)) !== null;
|
|
12297
12948
|
}
|
|
12298
12949
|
return reference !== null && reference.batchId.length > 0 && batchIds.has(reference.batchId);
|
|
12299
12950
|
}
|
|
@@ -12388,32 +13039,32 @@ function buildBatchPlan(action, deps) {
|
|
|
12388
13039
|
source,
|
|
12389
13040
|
target,
|
|
12390
13041
|
type: link.type,
|
|
12391
|
-
lag: link.lag,
|
|
13042
|
+
lag: link.lag ?? 0,
|
|
12392
13043
|
linkId
|
|
12393
13044
|
});
|
|
12394
13045
|
}
|
|
12395
13046
|
return { ok: true, plan: { items, links } };
|
|
12396
13047
|
}
|
|
12397
13048
|
function resolvePlannedActivityId(explicitId, mode, plannedIds, deps) {
|
|
12398
|
-
const explicitIsAvailable = explicitId !== void 0 && (mode ===
|
|
13049
|
+
const explicitIsAvailable = explicitId !== void 0 && (mode === ACTIVITY_BATCH_MODE.REPLACE || deps.adapter.getActivity(explicitId) === null && !deps.isActivityIdReserved(String(explicitId))) && !plannedIds.has(String(explicitId));
|
|
12399
13050
|
if (explicitIsAvailable) {
|
|
12400
13051
|
deps.activityIdGen.bump(explicitId);
|
|
12401
13052
|
return explicitId;
|
|
12402
13053
|
}
|
|
12403
13054
|
let candidate = deps.activityIdGen.next();
|
|
12404
|
-
while (plannedIds.has(String(candidate)) || mode ===
|
|
13055
|
+
while (plannedIds.has(String(candidate)) || mode === ACTIVITY_BATCH_MODE.APPEND && (deps.adapter.getActivity(candidate) !== null || deps.isActivityIdReserved(String(candidate)))) {
|
|
12405
13056
|
candidate = deps.activityIdGen.next();
|
|
12406
13057
|
}
|
|
12407
13058
|
return candidate;
|
|
12408
13059
|
}
|
|
12409
13060
|
function resolvePlannedLinkId(explicitId, mode, plannedIds, deps) {
|
|
12410
|
-
const explicitIsAvailable = explicitId !== void 0 && (mode ===
|
|
13061
|
+
const explicitIsAvailable = explicitId !== void 0 && (mode === ACTIVITY_BATCH_MODE.REPLACE || deps.adapter.getLink(explicitId) === null && !deps.isLinkIdReserved(String(explicitId))) && !plannedIds.has(String(explicitId));
|
|
12411
13062
|
if (explicitIsAvailable) {
|
|
12412
13063
|
deps.linkIdGen.bump(explicitId);
|
|
12413
13064
|
return explicitId;
|
|
12414
13065
|
}
|
|
12415
13066
|
let candidate = deps.linkIdGen.next();
|
|
12416
|
-
while (plannedIds.has(String(candidate)) || mode ===
|
|
13067
|
+
while (plannedIds.has(String(candidate)) || mode === ACTIVITY_BATCH_MODE.APPEND && (deps.adapter.getLink(candidate) !== null || deps.isLinkIdReserved(String(candidate)))) {
|
|
12417
13068
|
candidate = deps.linkIdGen.next();
|
|
12418
13069
|
}
|
|
12419
13070
|
return candidate;
|
|
@@ -12440,7 +13091,7 @@ function planInsertionCorrelatives(action, activityIdsByBatchId, deps) {
|
|
|
12440
13091
|
const parentKey = String(parentId);
|
|
12441
13092
|
let plan = plansByParent.get(parentKey);
|
|
12442
13093
|
if (!plan) {
|
|
12443
|
-
const existing = action.mode ===
|
|
13094
|
+
const existing = action.mode === ACTIVITY_BATCH_MODE.REPLACE || typeof item.parent !== "string" && activityIdsByBatchId.has(item.parent.batchId) ? [] : collectSiblings(deps.adapter, parentKey).sort((left, right) => {
|
|
12444
13095
|
const diff = readCorrelativeId(left) - readCorrelativeId(right);
|
|
12445
13096
|
return diff || String(left.id).localeCompare(String(right.id));
|
|
12446
13097
|
}).map((activity) => String(activity.id));
|
|
@@ -12493,8 +13144,8 @@ function planInsertionCorrelatives(action, activityIdsByBatchId, deps) {
|
|
|
12493
13144
|
return result;
|
|
12494
13145
|
}
|
|
12495
13146
|
function isSimpleRootAppend(action) {
|
|
12496
|
-
return action.mode ===
|
|
12497
|
-
(item) => item.parent ===
|
|
13147
|
+
return action.mode === ACTIVITY_BATCH_MODE.APPEND && action.items.every(
|
|
13148
|
+
(item) => item.parent === ROOT_PARENT_ID && item.index === void 0
|
|
12498
13149
|
);
|
|
12499
13150
|
}
|
|
12500
13151
|
function activityCorrelative(activityId, deps) {
|
|
@@ -12525,6 +13176,7 @@ async function createPlannedActivities(action, plannedItems, deps) {
|
|
|
12525
13176
|
const item = ready[index];
|
|
12526
13177
|
const core = await createActivityCore(
|
|
12527
13178
|
{
|
|
13179
|
+
kind: DISPATCH_ACTION_KIND.ACTIVITY_CREATE,
|
|
12528
13180
|
parentId: item.parentId,
|
|
12529
13181
|
activityId: item.activityId,
|
|
12530
13182
|
overrides: item.overrides,
|
|
@@ -12550,7 +13202,9 @@ async function createPlannedActivities(action, plannedItems, deps) {
|
|
|
12550
13202
|
const recomputedParents = /* @__PURE__ */ new Set();
|
|
12551
13203
|
for (let index = ready.length - 1; index >= 0; index -= 1) {
|
|
12552
13204
|
const parentId = ready[index].parentId;
|
|
12553
|
-
if (parentId ===
|
|
13205
|
+
if (parentId === ROOT_PARENT_ID || recomputedParents.has(String(parentId))) {
|
|
13206
|
+
continue;
|
|
13207
|
+
}
|
|
12554
13208
|
recomputedParents.add(String(parentId));
|
|
12555
13209
|
recomputeRollupCascadesForParent(parentId, deps.adapter);
|
|
12556
13210
|
}
|
|
@@ -13702,7 +14356,13 @@ async function dispatchActivitySetProgress(action, options, deps) {
|
|
|
13702
14356
|
}
|
|
13703
14357
|
|
|
13704
14358
|
// src/dispatch/handlers/dates-batch.ts
|
|
14359
|
+
function isDateColumn(column) {
|
|
14360
|
+
return column === COLUMN.START_DATE || column === COLUMN.END_DATE;
|
|
14361
|
+
}
|
|
13705
14362
|
async function dispatchDatesBatch(action, options, deps) {
|
|
14363
|
+
if (action.edits.some((edit) => !isDateColumn(edit.column))) {
|
|
14364
|
+
return { ok: false, reason: REJECTION_REASON.INVALID_VALUE };
|
|
14365
|
+
}
|
|
13706
14366
|
const { adapter, scheduler, sector } = deps;
|
|
13707
14367
|
const verdicts = [];
|
|
13708
14368
|
const beforeSnap = /* @__PURE__ */ new Map();
|
|
@@ -14219,7 +14879,7 @@ function applyBaselineOverlay(state, points, now, reporter, defaultBaseCalendarI
|
|
|
14219
14879
|
|
|
14220
14880
|
// src/propagations/downward/recompute-ponderator-for-parent.ts
|
|
14221
14881
|
function recomputePonderatorsForParent(parentId, criterion, adapter) {
|
|
14222
|
-
if (!parentId || parentId ===
|
|
14882
|
+
if (!parentId || parentId === ROOT_PARENT_ID) return;
|
|
14223
14883
|
const childIds = adapter.getChildren(parentId);
|
|
14224
14884
|
if (childIds.length === 0) return;
|
|
14225
14885
|
const pesoById = /* @__PURE__ */ new Map();
|
|
@@ -14252,12 +14912,16 @@ function criterionValue(childId, criterion, adapter) {
|
|
|
14252
14912
|
if (!child) return 0;
|
|
14253
14913
|
const active = getActiveBaseline(child);
|
|
14254
14914
|
if (!active) return 0;
|
|
14255
|
-
if (criterion ===
|
|
14256
|
-
|
|
14257
|
-
|
|
14258
|
-
if (
|
|
14915
|
+
if (criterion === ACTIVITY_PONDERATOR_CRITERION.COST) {
|
|
14916
|
+
return toNumber(active.cost);
|
|
14917
|
+
}
|
|
14918
|
+
if (criterion === ACTIVITY_PONDERATOR_CRITERION.WORK_HOURS) {
|
|
14919
|
+
return toNumber(active.workHours);
|
|
14920
|
+
}
|
|
14921
|
+
const { type } = child;
|
|
14922
|
+
if (type === ACTIVITY_TYPE.PROJECT)
|
|
14259
14923
|
return sumRecursiveBaselineDurationDays(childId, adapter);
|
|
14260
|
-
if (type ===
|
|
14924
|
+
if (type === ACTIVITY_TYPE.MILESTONE) return 0;
|
|
14261
14925
|
return toNumber(active.durationDays);
|
|
14262
14926
|
}
|
|
14263
14927
|
function sumRecursiveBaselineDurationDays(activityId, adapter) {
|
|
@@ -14267,10 +14931,10 @@ function sumRecursiveBaselineDurationDays(activityId, adapter) {
|
|
|
14267
14931
|
if (!child) continue;
|
|
14268
14932
|
const active = getActiveBaseline(child);
|
|
14269
14933
|
if (!active) continue;
|
|
14270
|
-
const type = child
|
|
14271
|
-
if (type ===
|
|
14934
|
+
const { type } = child;
|
|
14935
|
+
if (type === ACTIVITY_TYPE.PROJECT) {
|
|
14272
14936
|
sum += sumRecursiveBaselineDurationDays(String(childId), adapter);
|
|
14273
|
-
} else if (type !==
|
|
14937
|
+
} else if (type !== ACTIVITY_TYPE.MILESTONE) {
|
|
14274
14938
|
sum += toNumber(active.durationDays);
|
|
14275
14939
|
}
|
|
14276
14940
|
}
|
|
@@ -14345,7 +15009,7 @@ async function dispatchBaselineApply(action, deps) {
|
|
|
14345
15009
|
if (activeBaselineSignature(deps) !== activeBaselineBefore) {
|
|
14346
15010
|
recomputeBaselineWeightedFields(
|
|
14347
15011
|
deps,
|
|
14348
|
-
deps.sector.activityCreter ??
|
|
15012
|
+
deps.sector.activityCreter ?? ACTIVITY_PONDERATOR_CRITERION.DURATION
|
|
14349
15013
|
);
|
|
14350
15014
|
}
|
|
14351
15015
|
return {
|
|
@@ -14361,14 +15025,15 @@ async function dispatchBaselineApply(action, deps) {
|
|
|
14361
15025
|
}
|
|
14362
15026
|
|
|
14363
15027
|
// src/dispatch/handlers/ponderator-criterion-set.ts
|
|
14364
|
-
function
|
|
14365
|
-
|
|
14366
|
-
|
|
14367
|
-
`ponderator-criterion-set: invalid criterion "${String(value)}"`
|
|
15028
|
+
function isValidCriterion(value) {
|
|
15029
|
+
return Object.values(ACTIVITY_PONDERATOR_CRITERION).includes(
|
|
15030
|
+
value
|
|
14368
15031
|
);
|
|
14369
15032
|
}
|
|
14370
15033
|
async function dispatchPonderatorCriterionSet(action, deps) {
|
|
14371
|
-
|
|
15034
|
+
if (!isValidCriterion(action.criterion)) {
|
|
15035
|
+
return { ok: false, reason: REJECTION_REASON.INVALID_VALUE };
|
|
15036
|
+
}
|
|
14372
15037
|
const allIds = new Set(deps.adapter.getAllIds());
|
|
14373
15038
|
const beforeSnap = await snapshotActivities(deps.adapter, allIds);
|
|
14374
15039
|
recomputeBaselineWeightedFields(deps, action.criterion);
|
|
@@ -14404,6 +15069,64 @@ async function dispatchStatusCriteriaSet(action, deps) {
|
|
|
14404
15069
|
};
|
|
14405
15070
|
}
|
|
14406
15071
|
|
|
15072
|
+
// src/dispatch/handlers/calendar-reconcile.ts
|
|
15073
|
+
async function dispatchCalendarReconcile(action, options, deps) {
|
|
15074
|
+
const beforeSnap = /* @__PURE__ */ new Map();
|
|
15075
|
+
const touchedIds = /* @__PURE__ */ new Set();
|
|
15076
|
+
for (const activity of deps.adapter.getAllActivities()) {
|
|
15077
|
+
if (!shouldReconcile(activity, deps)) continue;
|
|
15078
|
+
const calendar = deps.ctx.calendars.getCalendar(activity.calendarId);
|
|
15079
|
+
if (!calendar) continue;
|
|
15080
|
+
const startDate = calendar.getClosestWorkTime({
|
|
15081
|
+
date: activity.startDate,
|
|
15082
|
+
direction: WORK_TIME_DIRECTION.FUTURE,
|
|
15083
|
+
unit: CALENDAR_UNIT.HOUR
|
|
15084
|
+
});
|
|
15085
|
+
const endDate = calendar.calculateEndDate(
|
|
15086
|
+
startDate,
|
|
15087
|
+
activity.durationHours
|
|
15088
|
+
);
|
|
15089
|
+
if (sameInstant(startDate, activity.startDate) && sameInstant(endDate, activity.endDate)) {
|
|
15090
|
+
continue;
|
|
15091
|
+
}
|
|
15092
|
+
const activityId = String(activity.id);
|
|
15093
|
+
beforeSnap.set(activityId, structuredCloneActivity(activity));
|
|
15094
|
+
touchedIds.add(activityId);
|
|
15095
|
+
deps.adapter.setActivityFields(activityId, { startDate, endDate });
|
|
15096
|
+
}
|
|
15097
|
+
const { scheduledIds } = await runPostMutation(
|
|
15098
|
+
{
|
|
15099
|
+
adapter: deps.adapter,
|
|
15100
|
+
scheduler: deps.scheduler,
|
|
15101
|
+
sector: deps.sector,
|
|
15102
|
+
defaultBaseCalendarId: deps.defaultBaseCalendarId
|
|
15103
|
+
},
|
|
15104
|
+
{
|
|
15105
|
+
action,
|
|
15106
|
+
autoscheduleFrom: "roots",
|
|
15107
|
+
recomputeParentsFrom: touchedIds,
|
|
15108
|
+
now: deps.now,
|
|
15109
|
+
options
|
|
15110
|
+
}
|
|
15111
|
+
);
|
|
15112
|
+
return {
|
|
15113
|
+
ok: true,
|
|
15114
|
+
changes: await assembleChangeSet(deps.adapter, {
|
|
15115
|
+
source: action,
|
|
15116
|
+
beforeSnap,
|
|
15117
|
+
touchedIds,
|
|
15118
|
+
scheduledIds,
|
|
15119
|
+
hoursPerDay: deps.sector.hoursPerDay
|
|
15120
|
+
})
|
|
15121
|
+
};
|
|
15122
|
+
}
|
|
15123
|
+
function shouldReconcile(activity, deps) {
|
|
15124
|
+
return activity.progress === 0 && !isSummary(activity.type, deps.adapter.hasChildren(activity.id));
|
|
15125
|
+
}
|
|
15126
|
+
function sameInstant(first, second) {
|
|
15127
|
+
return first.getTime() === second.getTime();
|
|
15128
|
+
}
|
|
15129
|
+
|
|
14407
15130
|
// src/activity-copy-paste/policy.ts
|
|
14408
15131
|
var ACTIVITY_COPY_FIELDS = [
|
|
14409
15132
|
"name",
|
|
@@ -14613,6 +15336,9 @@ async function performDispatch(action, options, deps) {
|
|
|
14613
15336
|
clipboard: deps.activityClipboard
|
|
14614
15337
|
});
|
|
14615
15338
|
}
|
|
15339
|
+
if (action.kind === "calendar-reconcile") {
|
|
15340
|
+
return dispatchCalendarReconcile(action, options, deps);
|
|
15341
|
+
}
|
|
14616
15342
|
if (action.kind === "activity-clipboard-clear") {
|
|
14617
15343
|
return dispatchActivityClipboardClear(action, deps.activityClipboard);
|
|
14618
15344
|
}
|
|
@@ -18533,7 +19259,7 @@ function captureCreatedSnapshots(state, changeSet) {
|
|
|
18533
19259
|
return { afterSnap, afterLinks };
|
|
18534
19260
|
}
|
|
18535
19261
|
function computeCoalesceKey(action) {
|
|
18536
|
-
if (action.kind !==
|
|
19262
|
+
if (action.kind !== DISPATCH_ACTION_KIND.INLINE_EDIT) return null;
|
|
18537
19263
|
if (!NON_SCHEDULING_INLINE_COLUMNS.has(action.column)) return null;
|
|
18538
19264
|
return `inline-edit:${String(action.activityId)}:${action.column}`;
|
|
18539
19265
|
}
|
|
@@ -18568,10 +19294,10 @@ function mergeCoalesced(top, next) {
|
|
|
18568
19294
|
return buildUndoEntry(changeSet);
|
|
18569
19295
|
}
|
|
18570
19296
|
function getDispatchHistoryPolicy(action) {
|
|
18571
|
-
if (action.kind ===
|
|
19297
|
+
if (action.kind === DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE) {
|
|
18572
19298
|
return "checkpoint-on-success";
|
|
18573
19299
|
}
|
|
18574
|
-
if (action.kind ===
|
|
19300
|
+
if (action.kind === DISPATCH_ACTION_KIND.SIR_SYNC || action.kind === DISPATCH_ACTION_KIND.CALENDAR_RECONCILE || action.kind === DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC || action.kind === DISPATCH_ACTION_KIND.BASELINE_APPLY || action.kind === DISPATCH_ACTION_KIND.PONDERATOR_CRITERION_SET || action.kind === DISPATCH_ACTION_KIND.STATUS_CRITERIA_SET || action.kind === DISPATCH_ACTION_KIND.ACTIVITY_CLIPBOARD_CLEAR || action.kind === DISPATCH_ACTION_KIND.ACTIVITY_COPY || action.kind === DISPATCH_ACTION_KIND.SELECTION_TOGGLE || action.kind === DISPATCH_ACTION_KIND.SELECTION_REPLACE || action.kind === DISPATCH_ACTION_KIND.VISIBILITY_SET || action.kind === DISPATCH_ACTION_KIND.FILTER_SET || action.kind === DISPATCH_ACTION_KIND.SORT_SET) {
|
|
18575
19301
|
return "skip";
|
|
18576
19302
|
}
|
|
18577
19303
|
return "record";
|
|
@@ -18659,7 +19385,9 @@ function buildInverseChangeSet(state, entry, side) {
|
|
|
18659
19385
|
(change) => side === "before" ? invertViewStateChange(change) : change
|
|
18660
19386
|
);
|
|
18661
19387
|
return {
|
|
18662
|
-
source: {
|
|
19388
|
+
source: {
|
|
19389
|
+
kind: side === "before" ? CHANGE_SET_SOURCE_KIND.UNDO : CHANGE_SET_SOURCE_KIND.REDO
|
|
19390
|
+
},
|
|
18663
19391
|
activities,
|
|
18664
19392
|
links,
|
|
18665
19393
|
calendars: [],
|
|
@@ -19494,7 +20222,7 @@ var WORKING_DAY_TRUE_VALUES = /* @__PURE__ */ new Set([
|
|
|
19494
20222
|
"1",
|
|
19495
20223
|
"true"
|
|
19496
20224
|
]);
|
|
19497
|
-
var DEFAULT_ACTIVITY_CRETER =
|
|
20225
|
+
var DEFAULT_ACTIVITY_CRETER = ACTIVITY_PONDERATOR_CRITERION.DURATION;
|
|
19498
20226
|
var DEFAULT_CONSTRAINT_TYPE = "asap";
|
|
19499
20227
|
var CONSTRAINT_LABEL_MAP = {
|
|
19500
20228
|
ASAP: "asap",
|
|
@@ -20001,12 +20729,12 @@ function linkIdAsNumber(link) {
|
|
|
20001
20729
|
function parseActivityCreter(raw) {
|
|
20002
20730
|
if (typeof raw !== "string") return DEFAULT_ACTIVITY_CRETER;
|
|
20003
20731
|
switch (raw.toUpperCase()) {
|
|
20004
|
-
case
|
|
20005
|
-
return
|
|
20006
|
-
case
|
|
20007
|
-
return
|
|
20008
|
-
case
|
|
20009
|
-
return
|
|
20732
|
+
case ACTIVITY_PONDERATOR_CRITERION.DURATION:
|
|
20733
|
+
return ACTIVITY_PONDERATOR_CRITERION.DURATION;
|
|
20734
|
+
case ACTIVITY_PONDERATOR_CRITERION.COST:
|
|
20735
|
+
return ACTIVITY_PONDERATOR_CRITERION.COST;
|
|
20736
|
+
case ACTIVITY_PONDERATOR_CRITERION.WORK_HOURS:
|
|
20737
|
+
return ACTIVITY_PONDERATOR_CRITERION.WORK_HOURS;
|
|
20010
20738
|
default:
|
|
20011
20739
|
return DEFAULT_ACTIVITY_CRETER;
|
|
20012
20740
|
}
|
|
@@ -20733,8 +21461,8 @@ function compareByRule(rule, context) {
|
|
|
20733
21461
|
const valueB = descriptor.extract(b, context);
|
|
20734
21462
|
const missing = compareMissing(isMissing(valueA), isMissing(valueB));
|
|
20735
21463
|
if (missing !== null) return missing;
|
|
20736
|
-
const result = descriptor.valueKind ===
|
|
20737
|
-
return rule.direction ===
|
|
21464
|
+
const result = descriptor.valueKind === FILTER_VALUE_KIND.ENUM ? enumRank(valueA, descriptor.order) - enumRank(valueB, descriptor.order) : compareValues(valueA, valueB, context.locale);
|
|
21465
|
+
return rule.direction === ORDER_DIRECTION.DESCENDING ? -result : result;
|
|
20738
21466
|
};
|
|
20739
21467
|
}
|
|
20740
21468
|
function buildComparator(order, context) {
|
|
@@ -21105,7 +21833,7 @@ function viewStateChanges(target, source) {
|
|
|
21105
21833
|
function createProjectionChangeSet(target, source) {
|
|
21106
21834
|
const orderChanged = serializeCanonicalSchedule(target.order) !== serializeCanonicalSchedule(source.order);
|
|
21107
21835
|
return {
|
|
21108
|
-
source: { kind:
|
|
21836
|
+
source: { kind: CHANGE_SET_SOURCE_KIND.INIT },
|
|
21109
21837
|
activities: entityChanges(target.activities, source.activities),
|
|
21110
21838
|
links: entityChanges(target.links, source.links),
|
|
21111
21839
|
calendars: entityChanges(target.calendars, source.calendars),
|
|
@@ -21117,6 +21845,11 @@ function createProjectionChangeSet(target, source) {
|
|
|
21117
21845
|
}
|
|
21118
21846
|
|
|
21119
21847
|
// src/propagations/upward/date-gesture-preview.ts
|
|
21848
|
+
var DATE_GESTURE_KIND = {
|
|
21849
|
+
MOVE: "move",
|
|
21850
|
+
RESIZE_START: "resize-start",
|
|
21851
|
+
RESIZE_END: "resize-end"
|
|
21852
|
+
};
|
|
21120
21853
|
var emptyFormula = () => ({
|
|
21121
21854
|
constantStart: null,
|
|
21122
21855
|
variableStartOffset: null,
|
|
@@ -21128,7 +21861,7 @@ var max = (left, right) => left === null ? right : Math.max(left, right);
|
|
|
21128
21861
|
function createDateGesturePreview(adapter, gesture, assertCurrent) {
|
|
21129
21862
|
const participantIds = [
|
|
21130
21863
|
...new Set(
|
|
21131
|
-
gesture.kind ===
|
|
21864
|
+
gesture.kind === DATE_GESTURE_KIND.MOVE ? gesture.activityIds.map(String) : [String(gesture.activityId)]
|
|
21132
21865
|
)
|
|
21133
21866
|
];
|
|
21134
21867
|
if (participantIds.length === 0) {
|
|
@@ -21157,14 +21890,14 @@ function createDateGesturePreview(adapter, gesture, assertCurrent) {
|
|
|
21157
21890
|
}
|
|
21158
21891
|
function buildParticipantFormulas(adapter, gesture, participantIds) {
|
|
21159
21892
|
const formulas = /* @__PURE__ */ new Map();
|
|
21160
|
-
const anchorId = gesture.kind ===
|
|
21893
|
+
const anchorId = gesture.kind === DATE_GESTURE_KIND.MOVE ? String(gesture.anchorActivityId) : null;
|
|
21161
21894
|
const anchor = anchorId === null ? null : requireLeafActivity(adapter, anchorId);
|
|
21162
21895
|
if (anchorId !== null && !participantIds.includes(anchorId)) {
|
|
21163
21896
|
throw new Error("[ScheduleCore] move anchor is not a participant");
|
|
21164
21897
|
}
|
|
21165
21898
|
for (const activityId of participantIds) {
|
|
21166
21899
|
const activity = requireLeafActivity(adapter, activityId);
|
|
21167
|
-
if (gesture.kind ===
|
|
21900
|
+
if (gesture.kind === DATE_GESTURE_KIND.MOVE) {
|
|
21168
21901
|
const anchorStart = anchor.startDate.getTime();
|
|
21169
21902
|
formulas.set(activityId, {
|
|
21170
21903
|
constantStart: null,
|
|
@@ -21172,7 +21905,7 @@ function buildParticipantFormulas(adapter, gesture, participantIds) {
|
|
|
21172
21905
|
constantEnd: null,
|
|
21173
21906
|
variableEndOffset: activity.endDate.getTime() - anchorStart
|
|
21174
21907
|
});
|
|
21175
|
-
} else if (gesture.kind ===
|
|
21908
|
+
} else if (gesture.kind === DATE_GESTURE_KIND.RESIZE_START) {
|
|
21176
21909
|
formulas.set(activityId, {
|
|
21177
21910
|
constantStart: null,
|
|
21178
21911
|
variableStartOffset: 0,
|
|
@@ -21263,7 +21996,7 @@ function evaluateEnd(formula, proposedEdgeTimeMs) {
|
|
|
21263
21996
|
// src/init/schedule-core.ts
|
|
21264
21997
|
var FORK_SOURCE = /* @__PURE__ */ Symbol("ScheduleCore.fork.source");
|
|
21265
21998
|
function acknowledgesPersistence(action) {
|
|
21266
|
-
return action.kind ===
|
|
21999
|
+
return action.kind === DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE || action.kind === DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC && action.acknowledgePersistedLookahead === true;
|
|
21267
22000
|
}
|
|
21268
22001
|
function changesRequireFilterProjectionRebuild(changes) {
|
|
21269
22002
|
for (const change of changes.activities) {
|
|
@@ -21289,6 +22022,30 @@ function isCurrentFilterProjection(projection, filter, context) {
|
|
|
21289
22022
|
return hasCurrentHours && hasCurrentLocale;
|
|
21290
22023
|
}
|
|
21291
22024
|
var ScheduleCore = class _ScheduleCore {
|
|
22025
|
+
/** Activity reads and mutations. */
|
|
22026
|
+
activities;
|
|
22027
|
+
/** Dependency-link reads and mutations. */
|
|
22028
|
+
links;
|
|
22029
|
+
/** Calendar reads and reconciliation. */
|
|
22030
|
+
calendars;
|
|
22031
|
+
/** Core-owned activity selection. */
|
|
22032
|
+
selection;
|
|
22033
|
+
/** Visibility, filtering, and order projection. */
|
|
22034
|
+
view;
|
|
22035
|
+
/** Baseline overlays and selection. */
|
|
22036
|
+
baselines;
|
|
22037
|
+
/** Pending impact-request synchronization. */
|
|
22038
|
+
impactRequests;
|
|
22039
|
+
/** External persistence tracking; no storage I/O is performed. */
|
|
22040
|
+
persistence;
|
|
22041
|
+
/** Undo and redo history. */
|
|
22042
|
+
history;
|
|
22043
|
+
/** Cross-instance projection change sets. */
|
|
22044
|
+
projection;
|
|
22045
|
+
/** Critical-path job lifecycle. */
|
|
22046
|
+
criticalPath;
|
|
22047
|
+
/** Effective-graph, revision, and digest diagnostics. */
|
|
22048
|
+
diagnostics;
|
|
21292
22049
|
_activityClipboard = { value: null };
|
|
21293
22050
|
_status = SCHEDULE_CORE_STATUS.READY;
|
|
21294
22051
|
coreRuntime;
|
|
@@ -21300,6 +22057,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21300
22057
|
_criticalPathRevision = -1;
|
|
21301
22058
|
_activeCriticalPath = null;
|
|
21302
22059
|
constructor(input) {
|
|
22060
|
+
Object.assign(this, createScheduleNamespaces(this));
|
|
21303
22061
|
if (FORK_SOURCE in input) {
|
|
21304
22062
|
this._isFork = true;
|
|
21305
22063
|
const source = input[FORK_SOURCE];
|
|
@@ -21365,9 +22123,21 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21365
22123
|
const waitForCriticalPathOnLoad = input.criticalPathOnLoad === true;
|
|
21366
22124
|
this._ready = waitForCriticalPathOnLoad ? this._criticalPathReady.then(() => void 0) : this._initPromise;
|
|
21367
22125
|
}
|
|
22126
|
+
/**
|
|
22127
|
+
* Resolves after initialization, and after initial critical path when
|
|
22128
|
+
* `criticalPathOnLoad` is enabled.
|
|
22129
|
+
*/
|
|
21368
22130
|
get ready() {
|
|
21369
22131
|
return this._ready;
|
|
21370
22132
|
}
|
|
22133
|
+
/**
|
|
22134
|
+
* Creates an isolated schedule with copied state, history, and generators.
|
|
22135
|
+
*
|
|
22136
|
+
* The fork runs the same mutation logic but disables dirty tracking:
|
|
22137
|
+
* `persistence.hasChanges()` stays false and all dirty collections stay
|
|
22138
|
+
* empty. It cannot acknowledge persistence and is never merged automatically.
|
|
22139
|
+
* @returns A ready isolated schedule.
|
|
22140
|
+
*/
|
|
21371
22141
|
fork() {
|
|
21372
22142
|
return this._enqueue(async () => {
|
|
21373
22143
|
await this._ready;
|
|
@@ -21377,19 +22147,48 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21377
22147
|
});
|
|
21378
22148
|
});
|
|
21379
22149
|
}
|
|
22150
|
+
/**
|
|
22151
|
+
* Tracks the critical-path job current when this property is read.
|
|
22152
|
+
*
|
|
22153
|
+
* Later automatic work, including undo or redo recomputation, can replace
|
|
22154
|
+
* the promise returned by subsequent reads. Use `whenSettled()` to wait for
|
|
22155
|
+
* the current schedule revision.
|
|
22156
|
+
* Apply a non-null `changes` value to the consumer-owned projection.
|
|
22157
|
+
*/
|
|
21380
22158
|
get criticalPathReady() {
|
|
21381
22159
|
return this._criticalPathReady;
|
|
21382
22160
|
}
|
|
22161
|
+
/**
|
|
22162
|
+
* Current lifecycle health; `ready` can be observed before initialization
|
|
22163
|
+
* finishes, so await {@link ScheduleCore.ready} before normal use.
|
|
22164
|
+
*/
|
|
21383
22165
|
get status() {
|
|
21384
22166
|
return this._status;
|
|
21385
22167
|
}
|
|
22168
|
+
/**
|
|
22169
|
+
* Reads a defensive sector metadata snapshot without a readiness guard.
|
|
22170
|
+
*
|
|
22171
|
+
* @returns Cloned metadata, including values available after destruction.
|
|
22172
|
+
*/
|
|
21386
22173
|
getSector() {
|
|
21387
22174
|
return cloneDomainValue(this.coreRuntime.sector);
|
|
21388
22175
|
}
|
|
22176
|
+
/**
|
|
22177
|
+
* Reads a defensive activity snapshot from a ready schedule.
|
|
22178
|
+
*
|
|
22179
|
+
* @param id - Canonical activity ID.
|
|
22180
|
+
* @returns The activity, or `null` when absent.
|
|
22181
|
+
*/
|
|
21389
22182
|
getActivityView(id) {
|
|
21390
22183
|
this.assertReady();
|
|
21391
22184
|
return readActivity(this.coreRuntime.state, id);
|
|
21392
22185
|
}
|
|
22186
|
+
/**
|
|
22187
|
+
* Creates a read-only date prediction bound to the current revision.
|
|
22188
|
+
*
|
|
22189
|
+
* @param gesture - Move or resize gesture to preview.
|
|
22190
|
+
* @returns A preview that throws after schedule state changes.
|
|
22191
|
+
*/
|
|
21393
22192
|
createDateGesturePreview(gesture) {
|
|
21394
22193
|
this.assertReady();
|
|
21395
22194
|
const revision = this._scheduleRevision;
|
|
@@ -21400,10 +22199,16 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21400
22199
|
}
|
|
21401
22200
|
});
|
|
21402
22201
|
}
|
|
22202
|
+
/** @returns Defensive snapshots of every activity in the ready schedule. */
|
|
21403
22203
|
getAllActivitiesView() {
|
|
21404
22204
|
this.assertReady();
|
|
21405
22205
|
return readAllActivities(this.coreRuntime.state);
|
|
21406
22206
|
}
|
|
22207
|
+
/**
|
|
22208
|
+
* Computes the unique parent IDs allowed by the current indent plan.
|
|
22209
|
+
*
|
|
22210
|
+
* @param activityIds - Activities considered for indentation.
|
|
22211
|
+
*/
|
|
21407
22212
|
getIndentTargetParentIds(activityIds) {
|
|
21408
22213
|
this.assertReady();
|
|
21409
22214
|
const plan = planIndentMoves(
|
|
@@ -21414,14 +22219,30 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21414
22219
|
...new Set(plan.allowedMoves.map((move) => String(move.newParentId)))
|
|
21415
22220
|
];
|
|
21416
22221
|
}
|
|
22222
|
+
/**
|
|
22223
|
+
* Reads defensive direct-child snapshots in correlative order.
|
|
22224
|
+
*
|
|
22225
|
+
* @param parentId - Parent activity ID, or the root ID.
|
|
22226
|
+
*/
|
|
21417
22227
|
getChildrenView(parentId) {
|
|
21418
22228
|
this.assertReady();
|
|
21419
22229
|
return readChildren(this.coreRuntime.state, parentId);
|
|
21420
22230
|
}
|
|
22231
|
+
/**
|
|
22232
|
+
* Reads a defensive link snapshot.
|
|
22233
|
+
*
|
|
22234
|
+
* @param id - Canonical link ID.
|
|
22235
|
+
* @returns The link, or `null` when absent. Stored lag is in working hours.
|
|
22236
|
+
*/
|
|
21421
22237
|
getLinkView(id) {
|
|
21422
22238
|
this.assertReady();
|
|
21423
22239
|
return readLink(this.coreRuntime.state, id);
|
|
21424
22240
|
}
|
|
22241
|
+
/**
|
|
22242
|
+
* Reads unique incoming and outgoing link snapshots for an activity.
|
|
22243
|
+
*
|
|
22244
|
+
* @param activityId - Activity whose links should be read.
|
|
22245
|
+
*/
|
|
21425
22246
|
getLinksForActivityView(activityId) {
|
|
21426
22247
|
this.assertReady();
|
|
21427
22248
|
const state = this.coreRuntime.state;
|
|
@@ -21437,10 +22258,12 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21437
22258
|
for (const linkId of state.getIncomingLinkIds(activityId)) append(linkId);
|
|
21438
22259
|
return links;
|
|
21439
22260
|
}
|
|
22261
|
+
/** @returns Defensive snapshots of every link; stored lag is in working hours. */
|
|
21440
22262
|
getAllLinksView() {
|
|
21441
22263
|
this.assertReady();
|
|
21442
22264
|
return readAllLinks(this.coreRuntime.state);
|
|
21443
22265
|
}
|
|
22266
|
+
/** @returns Counts and circular components from the effective dependency graph. */
|
|
21444
22267
|
auditEffectiveGraph() {
|
|
21445
22268
|
this.assertReady();
|
|
21446
22269
|
const state = this.coreRuntime.state;
|
|
@@ -21461,58 +22284,90 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21461
22284
|
largestComponentSize
|
|
21462
22285
|
};
|
|
21463
22286
|
}
|
|
22287
|
+
/**
|
|
22288
|
+
* Reads and clones one activity property.
|
|
22289
|
+
*
|
|
22290
|
+
* @param activityId - Canonical activity ID.
|
|
22291
|
+
* @param property - Property to read.
|
|
22292
|
+
* @returns The cloned value, or `null` when the activity is absent.
|
|
22293
|
+
*/
|
|
21464
22294
|
getProperty(activityId, property) {
|
|
21465
22295
|
this.assertReady();
|
|
21466
22296
|
const snapshot = this.coreRuntime.state.getActivity(activityId);
|
|
21467
22297
|
if (!snapshot) return null;
|
|
21468
22298
|
return cloneDomainValue(snapshot[property]);
|
|
21469
22299
|
}
|
|
22300
|
+
/** @returns A read-only snapshot of all current activity IDs. */
|
|
21470
22301
|
getAllIds() {
|
|
21471
22302
|
this.assertReady();
|
|
21472
22303
|
return readAllIds(this.coreRuntime.state);
|
|
21473
22304
|
}
|
|
22305
|
+
/**
|
|
22306
|
+
* Visits each current activity ID without exposing mutable state.
|
|
22307
|
+
*
|
|
22308
|
+
* @param visit - Callback invoked once per current ID.
|
|
22309
|
+
*/
|
|
21474
22310
|
forEachActivityId(visit) {
|
|
21475
22311
|
this.assertReady();
|
|
21476
22312
|
forEachActivityId(this.coreRuntime.state, visit);
|
|
21477
22313
|
}
|
|
22314
|
+
/**
|
|
22315
|
+
* Reads direct child IDs in visual order.
|
|
22316
|
+
*
|
|
22317
|
+
* @param parentId - Parent activity ID, or the root ID.
|
|
22318
|
+
*/
|
|
21478
22319
|
getChildrenIds(parentId) {
|
|
21479
22320
|
this.assertReady();
|
|
21480
22321
|
return readChildrenIds(this.coreRuntime.state, parentId);
|
|
21481
22322
|
}
|
|
22323
|
+
/** @returns A defensive snapshot of selected activity IDs. */
|
|
21482
22324
|
getSelectedActivityIds() {
|
|
21483
22325
|
this.assertReady();
|
|
21484
22326
|
return readSelectedActivityIds(this.coreRuntime.state);
|
|
21485
22327
|
}
|
|
22328
|
+
/** @returns A defensive snapshot of explicitly hidden activity IDs. */
|
|
21486
22329
|
getHiddenActivityIds() {
|
|
21487
22330
|
this.assertReady();
|
|
21488
22331
|
return this.coreRuntime.state.hiddenIds().map(String);
|
|
21489
22332
|
}
|
|
22333
|
+
/** @returns A defensive snapshot of activity IDs not currently hidden. */
|
|
21490
22334
|
getVisibleActivityIds() {
|
|
21491
22335
|
this.assertReady();
|
|
21492
22336
|
const hiddenIds = new Set(this.coreRuntime.state.hiddenIds().map(String));
|
|
21493
22337
|
return this.coreRuntime.state.getAllIds().map(String).filter((activityId) => !hiddenIds.has(activityId));
|
|
21494
22338
|
}
|
|
22339
|
+
/** @returns A defensive active-filter snapshot, or `null`. */
|
|
21495
22340
|
getActiveFilter() {
|
|
21496
22341
|
this.assertReady();
|
|
21497
22342
|
return cloneDomainValue(this.coreRuntime.state.getActiveFilter());
|
|
21498
22343
|
}
|
|
22344
|
+
/** @returns A defensive active-order snapshot, or `null`. */
|
|
21499
22345
|
getActiveOrder() {
|
|
21500
22346
|
this.assertReady();
|
|
21501
22347
|
return cloneDomainValue(this.coreRuntime.state.getActiveOrder());
|
|
21502
22348
|
}
|
|
22349
|
+
/** @returns Activity IDs in the current projected traversal order. */
|
|
21503
22350
|
getVisualOrderIds() {
|
|
21504
22351
|
this.assertReady();
|
|
21505
22352
|
return [...this.coreRuntime.state.getVisualOrderIds()];
|
|
21506
22353
|
}
|
|
22354
|
+
/** @returns Whether the parent currently has a direct child. */
|
|
21507
22355
|
hasChild(parentId) {
|
|
21508
22356
|
this.assertReady();
|
|
21509
22357
|
return readHasChild(this.coreRuntime.state, parentId);
|
|
21510
22358
|
}
|
|
22359
|
+
/**
|
|
22360
|
+
* Reads a defensive schedule-calendar snapshot.
|
|
22361
|
+
*
|
|
22362
|
+
* @param id - Canonical calendar ID.
|
|
22363
|
+
* @returns The calendar, or `null` when absent.
|
|
22364
|
+
*/
|
|
21511
22365
|
getCalendar(id) {
|
|
21512
22366
|
this.assertReady();
|
|
21513
22367
|
const calendar = this.coreRuntime.calendars.get(id);
|
|
21514
22368
|
return calendar ? cloneDomainValue(calendar) : null;
|
|
21515
22369
|
}
|
|
22370
|
+
/** @returns Defensive snapshots of every schedule calendar. */
|
|
21516
22371
|
getAllCalendars() {
|
|
21517
22372
|
this.assertReady();
|
|
21518
22373
|
return Array.from(
|
|
@@ -21520,12 +22375,19 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21520
22375
|
(calendar) => cloneDomainValue(calendar)
|
|
21521
22376
|
);
|
|
21522
22377
|
}
|
|
22378
|
+
/** @returns Defensive snapshots of every base calendar. */
|
|
21523
22379
|
getBaseCalendars() {
|
|
21524
22380
|
this.assertReady();
|
|
21525
22381
|
return this.coreRuntime.baseCalendars.map(
|
|
21526
22382
|
(calendar) => cloneDomainValue(calendar)
|
|
21527
22383
|
);
|
|
21528
22384
|
}
|
|
22385
|
+
/**
|
|
22386
|
+
* Checks custom-ID uniqueness while optionally excluding the current value.
|
|
22387
|
+
*
|
|
22388
|
+
* @param customId - Candidate custom ID.
|
|
22389
|
+
* @param currentCustomId - Existing value to ignore, or `null`.
|
|
22390
|
+
*/
|
|
21529
22391
|
isCustomIdInUse(customId, currentCustomId = null) {
|
|
21530
22392
|
this.assertReady();
|
|
21531
22393
|
return this.coreRuntime.customIdTracker.isCustomIdInUse(
|
|
@@ -21533,24 +22395,29 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21533
22395
|
currentCustomId
|
|
21534
22396
|
);
|
|
21535
22397
|
}
|
|
22398
|
+
/** @returns The default calendar's earliest start/latest end, or `null`. */
|
|
21536
22399
|
getProjectWorkHours() {
|
|
21537
22400
|
this.assertReady();
|
|
21538
22401
|
return computeProjectWorkHours(this.coreRuntime.calendars.values());
|
|
21539
22402
|
}
|
|
22403
|
+
/** @returns Defensive snapshots of modified persisted links; no I/O occurs. */
|
|
21540
22404
|
getModifiedLinks() {
|
|
21541
22405
|
this.assertReady();
|
|
21542
22406
|
return this._saveTracker.modifiedLinks((linkId) => this.coreRuntime.state.getLink(linkId)).map(cloneDomainValue);
|
|
21543
22407
|
}
|
|
22408
|
+
/** @returns Defensive snapshots of not-yet-persisted links; no I/O occurs. */
|
|
21544
22409
|
getNewLinks() {
|
|
21545
22410
|
this.assertReady();
|
|
21546
22411
|
return this._saveTracker.newLinks((linkId) => this.coreRuntime.state.getLink(linkId)).map(cloneDomainValue);
|
|
21547
22412
|
}
|
|
22413
|
+
/** @returns Defensive snapshots of modified persisted activities; no I/O occurs. */
|
|
21548
22414
|
getModifiedActivities() {
|
|
21549
22415
|
this.assertReady();
|
|
21550
22416
|
return this._saveTracker.modifiedActivities(
|
|
21551
22417
|
(activityId) => this.coreRuntime.state.getActivity(activityId)
|
|
21552
22418
|
).map(cloneDomainValue);
|
|
21553
22419
|
}
|
|
22420
|
+
/** @returns Modified persisted fields grouped by activity ID; no I/O occurs. */
|
|
21554
22421
|
getModifiedActivityFields() {
|
|
21555
22422
|
this.assertReady();
|
|
21556
22423
|
return cloneDomainValue(
|
|
@@ -21559,23 +22426,28 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21559
22426
|
)
|
|
21560
22427
|
);
|
|
21561
22428
|
}
|
|
22429
|
+
/** @returns Defensive snapshots of not-yet-persisted activities; no I/O occurs. */
|
|
21562
22430
|
getNewActivities() {
|
|
21563
22431
|
this.assertReady();
|
|
21564
22432
|
return this._saveTracker.newActivities(
|
|
21565
22433
|
(activityId) => this.coreRuntime.state.getActivity(activityId)
|
|
21566
22434
|
).map(cloneDomainValue);
|
|
21567
22435
|
}
|
|
22436
|
+
/** @returns Whether tracked state differs from the acknowledged save baseline. */
|
|
21568
22437
|
hasUnsavedChanges() {
|
|
21569
22438
|
this.assertReady();
|
|
21570
22439
|
return this._saveTracker.hasUnsavedChanges();
|
|
21571
22440
|
}
|
|
22441
|
+
/** @returns The monotonic scheduling revision without a readiness guard. */
|
|
21572
22442
|
getScheduleRevision() {
|
|
21573
22443
|
return this._scheduleRevision;
|
|
21574
22444
|
}
|
|
22445
|
+
/** @returns The undo-history boundary for an external save checkpoint. */
|
|
21575
22446
|
capturePersistenceHistoryBoundary() {
|
|
21576
22447
|
this.assertReady();
|
|
21577
22448
|
return this._undo.capturePersistenceBoundary();
|
|
21578
22449
|
}
|
|
22450
|
+
/** @returns A deterministic serialization digest of canonical schedule state. */
|
|
21579
22451
|
getCanonicalDigest() {
|
|
21580
22452
|
this.assertReady();
|
|
21581
22453
|
const byId = (left, right) => String(left.id).localeCompare(String(right.id));
|
|
@@ -21587,6 +22459,13 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21587
22459
|
baseCalendars: [...this.getBaseCalendars()].sort(byId)
|
|
21588
22460
|
});
|
|
21589
22461
|
}
|
|
22462
|
+
/**
|
|
22463
|
+
* Produces changes that transform a projection of `source` into this schedule.
|
|
22464
|
+
*
|
|
22465
|
+
* Both schedules must be ready. Neither instance is mutated or merged.
|
|
22466
|
+
* @param source - Schedule currently represented by the consumer projection.
|
|
22467
|
+
* @returns A complete consumer projection change set.
|
|
22468
|
+
*/
|
|
21590
22469
|
createProjectionChangeSetFrom(source) {
|
|
21591
22470
|
this.assertReady();
|
|
21592
22471
|
source.assertReady();
|
|
@@ -21600,12 +22479,14 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21600
22479
|
});
|
|
21601
22480
|
return createProjectionChangeSet(projectionOf(this), projectionOf(source));
|
|
21602
22481
|
}
|
|
22482
|
+
/** @returns Deleted persisted activity identities since the last save. */
|
|
21603
22483
|
getDeletedActivitiesSinceLastSave() {
|
|
21604
22484
|
this.assertReady();
|
|
21605
22485
|
return this._saveTracker.deletedActivities(
|
|
21606
22486
|
(activityId) => this.coreRuntime.state.getActivity(activityId)
|
|
21607
22487
|
).map(cloneDomainValue);
|
|
21608
22488
|
}
|
|
22489
|
+
/** @returns Deleted persisted link identities since the last save. */
|
|
21609
22490
|
getDeletedLinksSinceLastSave() {
|
|
21610
22491
|
this.assertReady();
|
|
21611
22492
|
return this._saveTracker.deletedLinks((linkId) => this.coreRuntime.state.getLink(linkId)).map(cloneDomainValue);
|
|
@@ -21645,10 +22526,27 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21645
22526
|
);
|
|
21646
22527
|
});
|
|
21647
22528
|
}
|
|
22529
|
+
/**
|
|
22530
|
+
* Serializes and applies one public command to core-owned state.
|
|
22531
|
+
*
|
|
22532
|
+
* @param action - Public command. Activity-batch commands use
|
|
22533
|
+
* {@link ScheduleCore.applyActivityBatch} instead.
|
|
22534
|
+
* @param options - Per-operation autoschedule and critical-path controls.
|
|
22535
|
+
* @returns The complete dispatch result unchanged, including change sets,
|
|
22536
|
+
* verdicts, effects, tracking events, and warnings when present.
|
|
22537
|
+
*/
|
|
21648
22538
|
async dispatch(action, options = {}) {
|
|
21649
22539
|
const admitted = this._beginScheduleMutation(action);
|
|
21650
22540
|
return this._enqueue(() => this._dispatchInner(action, options, admitted));
|
|
21651
22541
|
}
|
|
22542
|
+
/**
|
|
22543
|
+
* Serializes and applies an activity creation batch.
|
|
22544
|
+
*
|
|
22545
|
+
* @param action - Append/replace batch using working-day link lags and
|
|
22546
|
+
* activity-creation overrides. Dispatch converts lags to stored hours.
|
|
22547
|
+
* @param options - Per-operation autoschedule and critical-path controls.
|
|
22548
|
+
* @returns The complete dispatch result unchanged.
|
|
22549
|
+
*/
|
|
21652
22550
|
async applyActivityBatch(action, options = {}) {
|
|
21653
22551
|
const admitted = this._beginScheduleMutation(action);
|
|
21654
22552
|
return this._enqueue(() => this._dispatchInner(action, options, admitted));
|
|
@@ -21747,7 +22645,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21747
22645
|
}
|
|
21748
22646
|
if (result.ok) {
|
|
21749
22647
|
if (historyPolicy === "checkpoint-on-success") {
|
|
21750
|
-
if (action.kind !==
|
|
22648
|
+
if (action.kind !== DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE) {
|
|
21751
22649
|
throw new Error(
|
|
21752
22650
|
"checkpoint-on-success requires persistence acknowledge"
|
|
21753
22651
|
);
|
|
@@ -21769,7 +22667,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21769
22667
|
action.activities ?? [],
|
|
21770
22668
|
action.links ?? []
|
|
21771
22669
|
);
|
|
21772
|
-
} else if (action.kind ===
|
|
22670
|
+
} else if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC && action.acknowledgePersistedLookahead === true) {
|
|
21773
22671
|
this._saveTracker.acknowledgePersistedLookahead(
|
|
21774
22672
|
result.changes.activities,
|
|
21775
22673
|
(activityId) => this.coreRuntime.state.getActivity(activityId)
|
|
@@ -21796,6 +22694,12 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21796
22694
|
}
|
|
21797
22695
|
return { result: toPublicDispatchResult(result), changedState: false };
|
|
21798
22696
|
}
|
|
22697
|
+
/**
|
|
22698
|
+
* Queues critical-path calculation for the current revision.
|
|
22699
|
+
*
|
|
22700
|
+
* @returns A complete projection update, or `null` when already current,
|
|
22701
|
+
* destroyed, or superseded.
|
|
22702
|
+
*/
|
|
21799
22703
|
recomputeCriticalPath() {
|
|
21800
22704
|
const operation = this._enqueue(async () => ({
|
|
21801
22705
|
job: this._startCriticalPathForCurrentRevision()
|
|
@@ -21803,9 +22707,11 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21803
22707
|
this._criticalPathReady = operation;
|
|
21804
22708
|
return operation;
|
|
21805
22709
|
}
|
|
22710
|
+
/** @returns Whether no mutation or calculation remains for the current revision. */
|
|
21806
22711
|
isCriticalPathSettled() {
|
|
21807
22712
|
return this._criticalPathRevision === this._scheduleRevision && this._pendingScheduleRevision === this._scheduleRevision && this._activeCriticalPath === null;
|
|
21808
22713
|
}
|
|
22714
|
+
/** Resolves after repeatedly recomputing until the current revision is settled. */
|
|
21809
22715
|
async whenCriticalPathSettled() {
|
|
21810
22716
|
while (!this.isCriticalPathSettled()) {
|
|
21811
22717
|
await this.recomputeCriticalPath();
|
|
@@ -21813,7 +22719,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21813
22719
|
}
|
|
21814
22720
|
_withReappliedViewState(action, result) {
|
|
21815
22721
|
if (!result.ok) return result;
|
|
21816
|
-
if (action.kind ===
|
|
22722
|
+
if (action.kind === DISPATCH_ACTION_KIND.VISIBILITY_SET) {
|
|
21817
22723
|
this.coreRuntime.state.setFilterProjection(null);
|
|
21818
22724
|
}
|
|
21819
22725
|
if (!reappliesViewState(action)) return result;
|
|
@@ -21972,7 +22878,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21972
22878
|
);
|
|
21973
22879
|
}
|
|
21974
22880
|
changes = await assembleChangeSet(this.coreRuntime.state, {
|
|
21975
|
-
source: { kind:
|
|
22881
|
+
source: { kind: CHANGE_SET_SOURCE_KIND.INIT },
|
|
21976
22882
|
beforeSnap: /* @__PURE__ */ new Map(),
|
|
21977
22883
|
touchedIds: [],
|
|
21978
22884
|
scheduledIds: [],
|
|
@@ -21998,6 +22904,13 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21998
22904
|
void promise.then(clearIfActive, clearIfActive);
|
|
21999
22905
|
return promise;
|
|
22000
22906
|
}
|
|
22907
|
+
/**
|
|
22908
|
+
* Applies the latest inverse operation through the serialized queue.
|
|
22909
|
+
*
|
|
22910
|
+
* @param options - Optional depth guard and critical-path suppression.
|
|
22911
|
+
* @returns The complete projection change set, or `null` when unavailable or
|
|
22912
|
+
* when the expected depth does not match.
|
|
22913
|
+
*/
|
|
22001
22914
|
undo(options = {}) {
|
|
22002
22915
|
const admitted = this._admitScheduleMutation();
|
|
22003
22916
|
let changedState = false;
|
|
@@ -22053,6 +22966,12 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
22053
22966
|
return this._reapplyViewState(changes) ?? changes;
|
|
22054
22967
|
}
|
|
22055
22968
|
}
|
|
22969
|
+
/**
|
|
22970
|
+
* Reapplies the latest undone operation through the serialized queue.
|
|
22971
|
+
*
|
|
22972
|
+
* @param options - Optional critical-path suppression.
|
|
22973
|
+
* @returns The complete projection change set, or `null` when unavailable.
|
|
22974
|
+
*/
|
|
22056
22975
|
redo(options = {}) {
|
|
22057
22976
|
const admitted = this._admitScheduleMutation();
|
|
22058
22977
|
let changedState = false;
|
|
@@ -22103,15 +23022,19 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
22103
23022
|
);
|
|
22104
23023
|
return this._reapplyViewState(changes) ?? changes;
|
|
22105
23024
|
}
|
|
23025
|
+
/** @returns Whether an undo entry is available; readiness is not required. */
|
|
22106
23026
|
canUndo() {
|
|
22107
23027
|
return this._undo.canUndo();
|
|
22108
23028
|
}
|
|
23029
|
+
/** @returns Whether a redo entry is available; readiness is not required. */
|
|
22109
23030
|
canRedo() {
|
|
22110
23031
|
return this._undo.canRedo();
|
|
22111
23032
|
}
|
|
23033
|
+
/** Clears undo and redo history without changing schedule state. */
|
|
22112
23034
|
clearHistory() {
|
|
22113
23035
|
this._undo.clear();
|
|
22114
23036
|
}
|
|
23037
|
+
/** @returns Current undo depth; readiness is not required. */
|
|
22115
23038
|
undoDepth() {
|
|
22116
23039
|
return this._undo.undoDepth();
|
|
22117
23040
|
}
|
|
@@ -22121,6 +23044,10 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
22121
23044
|
this.coreRuntime.state.getAllActivities()
|
|
22122
23045
|
);
|
|
22123
23046
|
}
|
|
23047
|
+
/**
|
|
23048
|
+
* Cancels active critical-path work, clears caches, and permanently destroys
|
|
23049
|
+
* this instance. Guarded reads and operations throw afterward.
|
|
23050
|
+
*/
|
|
22124
23051
|
destroy() {
|
|
22125
23052
|
if (this._activeCriticalPath) {
|
|
22126
23053
|
this._activeCriticalPath.cancellation.cancelled = true;
|
|
@@ -22173,6 +23100,13 @@ function toPublicDispatchResult(result) {
|
|
|
22173
23100
|
return publicResult;
|
|
22174
23101
|
}
|
|
22175
23102
|
|
|
23103
|
+
// src/api/create-schedule.ts
|
|
23104
|
+
async function createSchedule(input) {
|
|
23105
|
+
const schedule = new ScheduleCore(input);
|
|
23106
|
+
await schedule.ready;
|
|
23107
|
+
return schedule;
|
|
23108
|
+
}
|
|
23109
|
+
|
|
22176
23110
|
// src/boundary/save/unsaved.ts
|
|
22177
23111
|
var getUnsavedActivities = (activities = []) => (activities ?? []).filter((activity) => !activity.proplannerId);
|
|
22178
23112
|
|
|
@@ -22191,67 +23125,6 @@ var CONSTRAINT_TYPE_TO_LABEL = {
|
|
|
22191
23125
|
// src/constants/workday.ts
|
|
22192
23126
|
var DEFAULT_HOURS_PER_DAY = 8;
|
|
22193
23127
|
|
|
22194
|
-
// src/dispatch/action-kinds.ts
|
|
22195
|
-
var DISPATCH_ACTION_KIND = {
|
|
22196
|
-
ACTIVITY_CLIPBOARD_CLEAR: "activity-clipboard-clear",
|
|
22197
|
-
ACTIVITY_COPY: "activity-copy",
|
|
22198
|
-
ACTIVITY_PASTE_COPIED: "activity-paste-copied",
|
|
22199
|
-
PERSISTENCE_ACKNOWLEDGE: "persistence-acknowledge",
|
|
22200
|
-
BASELINE_APPLY: "baseline-apply",
|
|
22201
|
-
PONDERATOR_CRITERION_SET: "ponderator-criterion-set",
|
|
22202
|
-
STATUS_CRITERIA_SET: "status-criteria-set",
|
|
22203
|
-
INLINE_EDIT: "inline-edit",
|
|
22204
|
-
DATES_BATCH: "dates-batch",
|
|
22205
|
-
BULK_EDIT: "bulk-edit",
|
|
22206
|
-
LINK_CREATE: "link-create",
|
|
22207
|
-
LINK_UPDATE: "link-update",
|
|
22208
|
-
LINK_DELETE: "link-delete",
|
|
22209
|
-
LINKS_BATCH: "links-batch",
|
|
22210
|
-
ACTIVITY_CREATE: "activity-create",
|
|
22211
|
-
ACTIVITY_DELETE: "activity-delete",
|
|
22212
|
-
ACTIVITY_MOVE: "activity-move",
|
|
22213
|
-
ACTIVITY_INDENT: "activity-indent",
|
|
22214
|
-
ACTIVITY_OUTDENT: "activity-outdent",
|
|
22215
|
-
ACTIVITY_SET_PROGRESS: "activity-set-progress",
|
|
22216
|
-
SELECTION_TOGGLE: "selection-toggle",
|
|
22217
|
-
SELECTION_REPLACE: "selection-replace",
|
|
22218
|
-
VISIBILITY_SET: "visibility-set",
|
|
22219
|
-
FILTER_SET: "filter-set",
|
|
22220
|
-
SORT_SET: "sort-set",
|
|
22221
|
-
SIR_SYNC: "sir-sync",
|
|
22222
|
-
ACTIVITY_LOOKAHEAD_SYNC: "activity-lookahead-sync"
|
|
22223
|
-
};
|
|
22224
|
-
var KIND_CATALOG_COVERS_UNION = {
|
|
22225
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_CLIPBOARD_CLEAR]: true,
|
|
22226
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_COPY]: true,
|
|
22227
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_PASTE_COPIED]: true,
|
|
22228
|
-
[DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE]: true,
|
|
22229
|
-
[DISPATCH_ACTION_KIND.BASELINE_APPLY]: true,
|
|
22230
|
-
[DISPATCH_ACTION_KIND.PONDERATOR_CRITERION_SET]: true,
|
|
22231
|
-
[DISPATCH_ACTION_KIND.STATUS_CRITERIA_SET]: true,
|
|
22232
|
-
[DISPATCH_ACTION_KIND.INLINE_EDIT]: true,
|
|
22233
|
-
[DISPATCH_ACTION_KIND.DATES_BATCH]: true,
|
|
22234
|
-
[DISPATCH_ACTION_KIND.BULK_EDIT]: true,
|
|
22235
|
-
[DISPATCH_ACTION_KIND.LINK_CREATE]: true,
|
|
22236
|
-
[DISPATCH_ACTION_KIND.LINK_UPDATE]: true,
|
|
22237
|
-
[DISPATCH_ACTION_KIND.LINK_DELETE]: true,
|
|
22238
|
-
[DISPATCH_ACTION_KIND.LINKS_BATCH]: true,
|
|
22239
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_CREATE]: true,
|
|
22240
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_DELETE]: true,
|
|
22241
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_MOVE]: true,
|
|
22242
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_INDENT]: true,
|
|
22243
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_OUTDENT]: true,
|
|
22244
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_SET_PROGRESS]: true,
|
|
22245
|
-
[DISPATCH_ACTION_KIND.SELECTION_TOGGLE]: true,
|
|
22246
|
-
[DISPATCH_ACTION_KIND.SELECTION_REPLACE]: true,
|
|
22247
|
-
[DISPATCH_ACTION_KIND.VISIBILITY_SET]: true,
|
|
22248
|
-
[DISPATCH_ACTION_KIND.FILTER_SET]: true,
|
|
22249
|
-
[DISPATCH_ACTION_KIND.SORT_SET]: true,
|
|
22250
|
-
[DISPATCH_ACTION_KIND.SIR_SYNC]: true,
|
|
22251
|
-
[DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC]: true
|
|
22252
|
-
};
|
|
22253
|
-
var DISPATCH_ACTION_KINDS = Object.keys(KIND_CATALOG_COVERS_UNION);
|
|
22254
|
-
|
|
22255
23128
|
// src/creation/creation-kinds.ts
|
|
22256
23129
|
var CREATION_KIND = {
|
|
22257
23130
|
CHILD: "child",
|
|
@@ -22260,6 +23133,6 @@ var CREATION_KIND = {
|
|
|
22260
23133
|
ROOT: "root"
|
|
22261
23134
|
};
|
|
22262
23135
|
|
|
22263
|
-
export { ACTIVITY_TYPE, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, NEW_ACTIVITY_DEFAULTS, REJECTION_REASON, ROOT_PARENT_ID, SCHEDULE_CORE_STATUS, STATUS, ScheduleCore, WORK_TIME_DIRECTION, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, willRunCriticalPath, yieldToBrowser };
|
|
23136
|
+
export { ACTIVITY_BATCH_ACTION_KIND, ACTIVITY_BATCH_MODE, ACTIVITY_DATE_EDGE, ACTIVITY_FIELD, ACTIVITY_PONDERATOR_CRITERION, ACTIVITY_TYPE, CALENDAR_UNIT, CHANGE_SET_SOURCE_KIND, COLUMN, COMPLETED_PROGRESS, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CONSTRAINT_WARNING_KIND, CREATION_KIND, DATE_GESTURE_KIND, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_LINK_OPERATION_KIND, DISPATCH_TRACK_EVENT, FILTER_FIELD, FILTER_LOGIC, FILTER_OPERATOR, FILTER_REJECTION_REASON, FILTER_VALUE_KIND, LINK_BATCH_OPERATION_KIND, LINK_CODE_TO_TYPE, LINK_REJECTION_REASON, LINK_RELATIONSHIP, LINK_TYPE, LINK_TYPE_CODE, NEW_ACTIVITY_DEFAULTS, NOT_STARTED_PROGRESS, ORDER_DIRECTION, REJECTION_REASON, ROOT_PARENT_ID, SCHEDULE_CORE_STATUS, SCHEDULE_EFFECT_KIND, SIR_AUTO_REJECT_REASON, STATUS, STATUS_CRITERIA, ScheduleCore, WORK_TIME_DIRECTION, checkNoUpdatedLinks, computeExpectedProgress, createSchedule, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, willRunCriticalPath, yieldToBrowser };
|
|
22264
23137
|
//# sourceMappingURL=index.js.map
|
|
22265
23138
|
//# sourceMappingURL=index.js.map
|