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