@outbuild-company/schedule-core 1.9.1 → 1.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +427 -134
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -6
- package/dist/index.d.ts +60 -6
- package/dist/index.js +427 -134
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3289,6 +3289,84 @@ function roundProgressPerLevel(value) {
|
|
|
3289
3289
|
return Number(value.toFixed(2));
|
|
3290
3290
|
}
|
|
3291
3291
|
|
|
3292
|
+
// src/propagations/upward/progress-rollup.ts
|
|
3293
|
+
function recomputeAllProgressRollup(adapter) {
|
|
3294
|
+
for (const parentId of parentsDeepestFirst(adapter)) {
|
|
3295
|
+
rollupParent(parentId, adapter);
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
|
|
3299
|
+
for (const parentId of parentIdsDeepestFirst) {
|
|
3300
|
+
rollupParent(parentId, adapter);
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
function parentsDeepestFirst(adapter) {
|
|
3304
|
+
const parents = /* @__PURE__ */ new Set();
|
|
3305
|
+
adapter.forEachActivity((_activity, id) => {
|
|
3306
|
+
if (adapter.getChildren(id).length > 0) parents.add(id);
|
|
3307
|
+
});
|
|
3308
|
+
const depthById = /* @__PURE__ */ new Map();
|
|
3309
|
+
for (const id of parents) depthById.set(id, depthOf(id, adapter));
|
|
3310
|
+
return [...parents].sort(
|
|
3311
|
+
(a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
|
|
3312
|
+
);
|
|
3313
|
+
}
|
|
3314
|
+
function depthOf(id, adapter) {
|
|
3315
|
+
let depth = 0;
|
|
3316
|
+
let current = id;
|
|
3317
|
+
while (current && current !== "0") {
|
|
3318
|
+
if (!adapter.getActivity(current)) break;
|
|
3319
|
+
depth += 1;
|
|
3320
|
+
current = adapter.getParentId(current);
|
|
3321
|
+
}
|
|
3322
|
+
return depth;
|
|
3323
|
+
}
|
|
3324
|
+
function rollupParent(parentId, adapter) {
|
|
3325
|
+
const childIds = adapter.getChildren(parentId);
|
|
3326
|
+
if (childIds.length === 0) return;
|
|
3327
|
+
const children = [];
|
|
3328
|
+
for (const childId of childIds) {
|
|
3329
|
+
const child = adapter.getActivity(childId);
|
|
3330
|
+
if (!child) continue;
|
|
3331
|
+
children.push({
|
|
3332
|
+
progress: Number(child.progress ?? 0),
|
|
3333
|
+
ponderator: Number(child.ponderator ?? 0)
|
|
3334
|
+
});
|
|
3335
|
+
}
|
|
3336
|
+
applyWeightedProgressRollup(parentId, children, adapter);
|
|
3337
|
+
}
|
|
3338
|
+
function applyWeightedProgressRollup(parentId, children, adapter) {
|
|
3339
|
+
const parent = adapter.getActivity(parentId);
|
|
3340
|
+
if (!parent) return;
|
|
3341
|
+
const rollup = computeWeightedProgressRollup(children);
|
|
3342
|
+
if (rollup === null) {
|
|
3343
|
+
const fallback = adapter.getProgressFallback(parentId);
|
|
3344
|
+
if (fallback !== null) {
|
|
3345
|
+
adapter.setActivityField(parentId, COLUMN.PROGRESS, fallback);
|
|
3346
|
+
}
|
|
3347
|
+
return;
|
|
3348
|
+
}
|
|
3349
|
+
if (adapter.getProgressFallback(parentId) === null) {
|
|
3350
|
+
adapter.setProgressFallback(parentId, Number(parent.progress ?? 0));
|
|
3351
|
+
}
|
|
3352
|
+
adapter.setActivityField(
|
|
3353
|
+
parentId,
|
|
3354
|
+
COLUMN.PROGRESS,
|
|
3355
|
+
roundProgressPerLevel(rollup)
|
|
3356
|
+
);
|
|
3357
|
+
}
|
|
3358
|
+
function setExplicitSummaryProgressFallbacks(activityId, progress, adapter) {
|
|
3359
|
+
const pending = [activityId];
|
|
3360
|
+
while (pending.length > 0) {
|
|
3361
|
+
const currentId = pending.pop();
|
|
3362
|
+
if (currentId === void 0) continue;
|
|
3363
|
+
const children = adapter.getChildren(currentId);
|
|
3364
|
+
if (children.length === 0) continue;
|
|
3365
|
+
adapter.setProgressFallback(currentId, progress);
|
|
3366
|
+
pending.push(...children);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
|
|
3292
3370
|
// src/columns/real-work/compute.ts
|
|
3293
3371
|
function computeLeafRealWork(workHours, progress) {
|
|
3294
3372
|
return (Number(workHours) || 0) * (Number(progress) || 0) / 100;
|
|
@@ -3404,16 +3482,8 @@ function recomputeParentFromChildren(parentId, adapter, progressMode = "freeze-w
|
|
|
3404
3482
|
adapter.setActivityField(parentId, "startDate", newStart);
|
|
3405
3483
|
adapter.setActivityField(parentId, "endDate", newEnd);
|
|
3406
3484
|
adapter.setActivityField(parentId, "durationHours", durationHours);
|
|
3407
|
-
|
|
3408
|
-
aggregate.weightedChildren
|
|
3409
|
-
);
|
|
3410
|
-
const shouldWriteProgress = progressMode !== "skip" && (progressRollup !== null || progressMode === "zero-when-no-contribution");
|
|
3411
|
-
if (shouldWriteProgress) {
|
|
3412
|
-
adapter.setActivityField(
|
|
3413
|
-
parentId,
|
|
3414
|
-
"progress",
|
|
3415
|
-
roundProgressPerLevel(progressRollup ?? 0)
|
|
3416
|
-
);
|
|
3485
|
+
if (progressMode !== "skip") {
|
|
3486
|
+
applyWeightedProgressRollup(parentId, aggregate.weightedChildren, adapter);
|
|
3417
3487
|
}
|
|
3418
3488
|
if (recomputeRealWork) {
|
|
3419
3489
|
adapter.setActivityField(parentId, "realWorkHours", aggregate.realWorkSum);
|
|
@@ -3436,10 +3506,10 @@ function collectParentIds(adapter) {
|
|
|
3436
3506
|
}
|
|
3437
3507
|
function computeDepths(ids, adapter) {
|
|
3438
3508
|
const depths = /* @__PURE__ */ new Map();
|
|
3439
|
-
for (const id of ids) depths.set(id,
|
|
3509
|
+
for (const id of ids) depths.set(id, depthOf2(id, adapter));
|
|
3440
3510
|
return depths;
|
|
3441
3511
|
}
|
|
3442
|
-
function
|
|
3512
|
+
function depthOf2(id, adapter) {
|
|
3443
3513
|
let depth = 0;
|
|
3444
3514
|
let current = id;
|
|
3445
3515
|
while (current && !isRootParent(current)) {
|
|
@@ -3922,6 +3992,7 @@ function buildAncestorRollupCascade(activity, newValue, hierarchy) {
|
|
|
3922
3992
|
const mutations = [];
|
|
3923
3993
|
for (const id of chain) {
|
|
3924
3994
|
const rollup = computeWeightedProgress(id, overlay, hierarchy);
|
|
3995
|
+
if (rollup === null) continue;
|
|
3925
3996
|
overlay.set(id, rollup);
|
|
3926
3997
|
mutations.push({
|
|
3927
3998
|
activityId: id,
|
|
@@ -3935,7 +4006,8 @@ function computeWeightedProgress(parentId, overlay, hierarchy) {
|
|
|
3935
4006
|
progress: overlay.has(child.id) ? overlay.get(child.id) : child.progress,
|
|
3936
4007
|
ponderator: child.ponderator ?? 0
|
|
3937
4008
|
}));
|
|
3938
|
-
|
|
4009
|
+
const rollup = computeWeightedProgressRollup(children);
|
|
4010
|
+
return rollup === null ? null : Number(rollup.toFixed(2));
|
|
3939
4011
|
}
|
|
3940
4012
|
function buildRecursiveTrackingEvents(activity, newValue) {
|
|
3941
4013
|
return [
|
|
@@ -9886,24 +9958,82 @@ function resolveDerivedPasses(action, autoSchedule, options) {
|
|
|
9886
9958
|
|
|
9887
9959
|
// src/dispatch/shared/post-mutation.ts
|
|
9888
9960
|
async function runPostMutation(deps, args) {
|
|
9889
|
-
const
|
|
9961
|
+
const progressInvalidation = resolveProgressInvalidation(deps.adapter);
|
|
9962
|
+
const passes = resolvePasses(args, progressInvalidation);
|
|
9890
9963
|
if (passes.has(DERIVED_PASS.AUTOSCHEDULE)) {
|
|
9891
9964
|
await refreshMutatedParentBounds(deps.adapter, args);
|
|
9892
9965
|
}
|
|
9893
9966
|
const schedule = passes.has(DERIVED_PASS.AUTOSCHEDULE) ? await runAutoschedule(deps, args.autoscheduleFrom) : emptySchedule();
|
|
9894
|
-
await rollUpParentBounds(
|
|
9967
|
+
await rollUpParentBounds(
|
|
9968
|
+
deps.adapter,
|
|
9969
|
+
args,
|
|
9970
|
+
schedule.scheduledIds,
|
|
9971
|
+
passes,
|
|
9972
|
+
progressInvalidation
|
|
9973
|
+
);
|
|
9895
9974
|
await runDerivedRecomputes(deps, passes, args.now);
|
|
9896
9975
|
return schedule;
|
|
9897
9976
|
}
|
|
9898
|
-
function resolvePasses(args) {
|
|
9977
|
+
function resolvePasses(args, progressInvalidation) {
|
|
9899
9978
|
const requested = args.autoscheduleFrom !== null;
|
|
9900
9979
|
const ran = !args.options.skipAutoSchedule && requested;
|
|
9901
9980
|
const passes = new Set(
|
|
9902
9981
|
resolveDerivedPasses(args.action, { ran }, args.options)
|
|
9903
9982
|
);
|
|
9904
|
-
if (args.recomputeParentProgress
|
|
9983
|
+
if (args.recomputeParentProgress || progressInvalidation.affectedParents.size > 0) {
|
|
9984
|
+
passes.add(DERIVED_PASS.PARENT_PROGRESS);
|
|
9985
|
+
}
|
|
9905
9986
|
return passes;
|
|
9906
9987
|
}
|
|
9988
|
+
function resolveProgressInvalidation(adapter) {
|
|
9989
|
+
const affectedParents = /* @__PURE__ */ new Set();
|
|
9990
|
+
const dirtySeeds = /* @__PURE__ */ new Set();
|
|
9991
|
+
const journal = adapter.peekWriteCapture();
|
|
9992
|
+
if (!journal) return { affectedParents, dirtySeeds };
|
|
9993
|
+
const affectParent = (parentId) => {
|
|
9994
|
+
if (parentId === null || isRootParent(parentId)) return;
|
|
9995
|
+
const normalized2 = String(parentId);
|
|
9996
|
+
affectedParents.add(normalized2);
|
|
9997
|
+
const childId = adapter.getChildren(normalized2)[0];
|
|
9998
|
+
if (childId !== void 0) dirtySeeds.add(childId);
|
|
9999
|
+
};
|
|
10000
|
+
collectStructuralProgressInvalidations(adapter, journal.ops, affectParent);
|
|
10001
|
+
collectFieldProgressInvalidations(
|
|
10002
|
+
adapter,
|
|
10003
|
+
journal.before,
|
|
10004
|
+
dirtySeeds,
|
|
10005
|
+
affectParent
|
|
10006
|
+
);
|
|
10007
|
+
return { affectedParents, dirtySeeds };
|
|
10008
|
+
}
|
|
10009
|
+
function collectStructuralProgressInvalidations(adapter, operations, affectParent) {
|
|
10010
|
+
for (const operation of operations) {
|
|
10011
|
+
if (operation.kind === "insert") {
|
|
10012
|
+
const inserted = adapter.getActivity(operation.activityId);
|
|
10013
|
+
if (inserted) affectParent(inserted.parentId);
|
|
10014
|
+
} else if (operation.kind === "remove") {
|
|
10015
|
+
affectParent(operation.before.parentId);
|
|
10016
|
+
}
|
|
10017
|
+
}
|
|
10018
|
+
}
|
|
10019
|
+
function collectFieldProgressInvalidations(adapter, beforeById, dirtySeeds, affectParent) {
|
|
10020
|
+
for (const [activityId, before] of beforeById) {
|
|
10021
|
+
const after = adapter.getActivity(activityId);
|
|
10022
|
+
if (!after) continue;
|
|
10023
|
+
const progressChanged = !Object.is(before.progress, after.progress);
|
|
10024
|
+
const ponderatorChanged = !Object.is(before.ponderator, after.ponderator);
|
|
10025
|
+
const parentChanged = !Object.is(before.parentId, after.parentId);
|
|
10026
|
+
if (progressChanged || ponderatorChanged) {
|
|
10027
|
+
affectParent(after.parentId);
|
|
10028
|
+
dirtySeeds.add(String(activityId));
|
|
10029
|
+
}
|
|
10030
|
+
if (parentChanged) {
|
|
10031
|
+
affectParent(before.parentId);
|
|
10032
|
+
affectParent(after.parentId);
|
|
10033
|
+
dirtySeeds.add(String(activityId));
|
|
10034
|
+
}
|
|
10035
|
+
}
|
|
10036
|
+
}
|
|
9907
10037
|
async function runAutoschedule(deps, autoscheduleFrom) {
|
|
9908
10038
|
const options = autoscheduleFrom === "roots" ? {} : { triggerId: autoscheduleFrom };
|
|
9909
10039
|
const result = await deps.scheduler.schedule(options);
|
|
@@ -9931,18 +10061,36 @@ async function refreshMutatedParentBounds(adapter, args) {
|
|
|
9931
10061
|
if (mutated.size === 0) return;
|
|
9932
10062
|
await updateParentBoundsFromChildren(adapter, mutated, false);
|
|
9933
10063
|
}
|
|
9934
|
-
async function rollUpParentBounds(adapter, args, scheduledIds, passes) {
|
|
10064
|
+
async function rollUpParentBounds(adapter, args, scheduledIds, passes, progressInvalidation) {
|
|
10065
|
+
if (passes.has(DERIVED_PASS.PARENT_PROGRESS)) {
|
|
10066
|
+
restoreDemotedProgressFallbacks(
|
|
10067
|
+
adapter,
|
|
10068
|
+
progressInvalidation.affectedParents
|
|
10069
|
+
);
|
|
10070
|
+
}
|
|
9935
10071
|
const dirty = args.collectDirty ? args.collectDirty(scheduledIds) : collectDirtyForStructural(args.recomputeParentsFrom, scheduledIds);
|
|
10072
|
+
for (const activityId of progressInvalidation.dirtySeeds) {
|
|
10073
|
+
dirty.add(activityId);
|
|
10074
|
+
}
|
|
9936
10075
|
await updateParentBoundsFromChildren(
|
|
9937
10076
|
adapter,
|
|
9938
10077
|
dirty,
|
|
9939
10078
|
passes.has(DERIVED_PASS.PARENT_PROGRESS),
|
|
9940
10079
|
{
|
|
9941
10080
|
recomputeRealWork: passes.has(DERIVED_PASS.REAL_WORK),
|
|
9942
|
-
progressMode:
|
|
10081
|
+
progressMode: "freeze-when-no-contribution"
|
|
9943
10082
|
}
|
|
9944
10083
|
);
|
|
9945
10084
|
}
|
|
10085
|
+
function restoreDemotedProgressFallbacks(adapter, affectedParents) {
|
|
10086
|
+
for (const parentId of affectedParents) {
|
|
10087
|
+
if (adapter.hasChildren(parentId)) continue;
|
|
10088
|
+
const fallback = adapter.getProgressFallback(parentId);
|
|
10089
|
+
if (fallback === null) continue;
|
|
10090
|
+
adapter.setActivityField(parentId, "progress", fallback);
|
|
10091
|
+
adapter.setProgressFallback(parentId, null);
|
|
10092
|
+
}
|
|
10093
|
+
}
|
|
9946
10094
|
async function runDerivedRecomputes(deps, passes, now) {
|
|
9947
10095
|
if (passes.has(DERIVED_PASS.EXPECTED_PROGRESS) && now !== null) {
|
|
9948
10096
|
if (hasActiveBaseline(deps.adapter)) {
|
|
@@ -11171,7 +11319,6 @@ function buildParentMutations(input) {
|
|
|
11171
11319
|
if ((input.promotionSource ?? "create") === "create") {
|
|
11172
11320
|
fields.constraintType = CONSTRAINT_TYPE.ASAP;
|
|
11173
11321
|
fields.constraintDate = null;
|
|
11174
|
-
fields.progress = 0;
|
|
11175
11322
|
}
|
|
11176
11323
|
}
|
|
11177
11324
|
return {
|
|
@@ -12324,60 +12471,6 @@ function dispatchSirSync(action, deps) {
|
|
|
12324
12471
|
};
|
|
12325
12472
|
}
|
|
12326
12473
|
|
|
12327
|
-
// src/propagations/upward/progress-rollup.ts
|
|
12328
|
-
function recomputeAllProgressRollup(adapter) {
|
|
12329
|
-
for (const parentId of parentsDeepestFirst(adapter)) {
|
|
12330
|
-
rollupParent(parentId, adapter);
|
|
12331
|
-
}
|
|
12332
|
-
}
|
|
12333
|
-
function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
|
|
12334
|
-
for (const parentId of parentIdsDeepestFirst) {
|
|
12335
|
-
rollupParent(parentId, adapter);
|
|
12336
|
-
}
|
|
12337
|
-
}
|
|
12338
|
-
function parentsDeepestFirst(adapter) {
|
|
12339
|
-
const parents = /* @__PURE__ */ new Set();
|
|
12340
|
-
adapter.forEachActivity((_activity, id) => {
|
|
12341
|
-
if (adapter.getChildren(id).length > 0) parents.add(id);
|
|
12342
|
-
});
|
|
12343
|
-
const depthById = /* @__PURE__ */ new Map();
|
|
12344
|
-
for (const id of parents) depthById.set(id, depthOf2(id, adapter));
|
|
12345
|
-
return [...parents].sort(
|
|
12346
|
-
(a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
|
|
12347
|
-
);
|
|
12348
|
-
}
|
|
12349
|
-
function depthOf2(id, adapter) {
|
|
12350
|
-
let depth = 0;
|
|
12351
|
-
let current = id;
|
|
12352
|
-
while (current && current !== "0") {
|
|
12353
|
-
if (!adapter.getActivity(current)) break;
|
|
12354
|
-
depth += 1;
|
|
12355
|
-
current = adapter.getParentId(current);
|
|
12356
|
-
}
|
|
12357
|
-
return depth;
|
|
12358
|
-
}
|
|
12359
|
-
function rollupParent(parentId, adapter) {
|
|
12360
|
-
const childIds = adapter.getChildren(parentId);
|
|
12361
|
-
if (childIds.length === 0) return;
|
|
12362
|
-
const children = [];
|
|
12363
|
-
for (const childId of childIds) {
|
|
12364
|
-
const child = adapter.getActivity(childId);
|
|
12365
|
-
if (!child) continue;
|
|
12366
|
-
children.push({
|
|
12367
|
-
progress: Number(child.progress ?? 0),
|
|
12368
|
-
ponderator: Number(child.ponderator ?? 0)
|
|
12369
|
-
});
|
|
12370
|
-
}
|
|
12371
|
-
const rollup = computeWeightedProgressRollup(children);
|
|
12372
|
-
if (rollup !== null) {
|
|
12373
|
-
adapter.setActivityField(
|
|
12374
|
-
parentId,
|
|
12375
|
-
COLUMN.PROGRESS,
|
|
12376
|
-
roundProgressPerLevel(rollup)
|
|
12377
|
-
);
|
|
12378
|
-
}
|
|
12379
|
-
}
|
|
12380
|
-
|
|
12381
12474
|
// src/dispatch/handlers/persistence-acknowledge.ts
|
|
12382
12475
|
function persistedOwnersOf(entities) {
|
|
12383
12476
|
const owners = /* @__PURE__ */ new Map();
|
|
@@ -12450,28 +12543,6 @@ function assertValidAssignments(assignments, entityName, readCurrent, ownerByBac
|
|
|
12450
12543
|
);
|
|
12451
12544
|
}
|
|
12452
12545
|
}
|
|
12453
|
-
function assertValidReconciledProgress(entries, deps) {
|
|
12454
|
-
const seen = /* @__PURE__ */ new Set();
|
|
12455
|
-
for (const entry of entries) {
|
|
12456
|
-
const id = String(entry.activityId);
|
|
12457
|
-
if (id.length === 0 || seen.has(id)) {
|
|
12458
|
-
throw new Error(
|
|
12459
|
-
`persistence-acknowledge: duplicate or empty reconciled activity id "${id}"`
|
|
12460
|
-
);
|
|
12461
|
-
}
|
|
12462
|
-
if (!Number.isFinite(entry.progress) || entry.progress < 0 || entry.progress > 100) {
|
|
12463
|
-
throw new Error(
|
|
12464
|
-
`persistence-acknowledge: invalid reconciled progress ${String(entry.progress)} for "${id}"`
|
|
12465
|
-
);
|
|
12466
|
-
}
|
|
12467
|
-
if (!deps.adapter.getActivity(id)) {
|
|
12468
|
-
throw new Error(
|
|
12469
|
-
`persistence-acknowledge: unknown reconciled activity id "${id}"`
|
|
12470
|
-
);
|
|
12471
|
-
}
|
|
12472
|
-
seen.add(id);
|
|
12473
|
-
}
|
|
12474
|
-
}
|
|
12475
12546
|
async function applyReconciledProgress(entries, deps) {
|
|
12476
12547
|
const progressToApply = entries.filter((entry) => {
|
|
12477
12548
|
const current = deps.adapter.getActivity(String(entry.activityId));
|
|
@@ -12502,19 +12573,25 @@ async function applyReconciledProgress(entries, deps) {
|
|
|
12502
12573
|
async function dispatchPersistenceAcknowledge(action, deps) {
|
|
12503
12574
|
const activities = action.activities ?? [];
|
|
12504
12575
|
const links = action.links ?? [];
|
|
12505
|
-
const reconciledProgress = action.reconciledProgress ?? [];
|
|
12506
|
-
assertValidReconciledProgress(reconciledProgress, deps);
|
|
12507
12576
|
const currentActivities = deps.adapter.getAllActivities();
|
|
12508
12577
|
const currentLinks = deps.adapter.getAllLinks();
|
|
12509
|
-
const
|
|
12510
|
-
const
|
|
12578
|
+
const checkpointActivities = action.checkpoint?.activities ?? currentActivities;
|
|
12579
|
+
const checkpointLinks = action.checkpoint?.links ?? currentLinks;
|
|
12580
|
+
const checkpointActivityById = new Map(
|
|
12581
|
+
checkpointActivities.map((activity) => [String(activity.id), activity])
|
|
12582
|
+
);
|
|
12583
|
+
const checkpointLinkById = new Map(
|
|
12584
|
+
checkpointLinks.map((link) => [String(link.id), link])
|
|
12585
|
+
);
|
|
12586
|
+
const activityOwnerByBackendId = persistedOwnersOf(checkpointActivities);
|
|
12587
|
+
const linkOwnerByBackendId = persistedOwnersOf(checkpointLinks);
|
|
12511
12588
|
assertValidAssignments(
|
|
12512
12589
|
activities,
|
|
12513
12590
|
"activity",
|
|
12514
12591
|
(id) => {
|
|
12515
|
-
const activity =
|
|
12592
|
+
const activity = checkpointActivityById.get(id);
|
|
12516
12593
|
return {
|
|
12517
|
-
exists: activity !==
|
|
12594
|
+
exists: activity !== void 0,
|
|
12518
12595
|
current: activity?.proplannerId ?? null
|
|
12519
12596
|
};
|
|
12520
12597
|
},
|
|
@@ -12524,17 +12601,21 @@ async function dispatchPersistenceAcknowledge(action, deps) {
|
|
|
12524
12601
|
links,
|
|
12525
12602
|
"link",
|
|
12526
12603
|
(id) => {
|
|
12527
|
-
const link =
|
|
12528
|
-
return {
|
|
12604
|
+
const link = checkpointLinkById.get(id);
|
|
12605
|
+
return {
|
|
12606
|
+
exists: link !== void 0,
|
|
12607
|
+
current: link?.proplannerId ?? null
|
|
12608
|
+
};
|
|
12529
12609
|
},
|
|
12530
12610
|
linkOwnerByBackendId
|
|
12531
12611
|
);
|
|
12532
|
-
assertAllNewEntitiesAcknowledged(
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12536
|
-
deps
|
|
12612
|
+
assertAllNewEntitiesAcknowledged(
|
|
12613
|
+
checkpointActivities,
|
|
12614
|
+
activities,
|
|
12615
|
+
"activity"
|
|
12537
12616
|
);
|
|
12617
|
+
assertAllNewEntitiesAcknowledged(checkpointLinks, links, "link");
|
|
12618
|
+
const activityChanges = [];
|
|
12538
12619
|
const linkChanges = [];
|
|
12539
12620
|
deps.adapter.batchUpdate(() => {
|
|
12540
12621
|
for (const assignment of activities) {
|
|
@@ -13444,6 +13525,11 @@ async function dispatchActivitySetProgress(action, options, deps) {
|
|
|
13444
13525
|
const touchedIds = collectTouchedIds(action.activityId, changes);
|
|
13445
13526
|
const beforeSnap = await snapshotActivities(adapter, touchedIds);
|
|
13446
13527
|
applyFieldChanges(adapter, action.activityId, changes);
|
|
13528
|
+
setExplicitSummaryProgressFallbacks(
|
|
13529
|
+
action.activityId,
|
|
13530
|
+
action.newValue,
|
|
13531
|
+
adapter
|
|
13532
|
+
);
|
|
13447
13533
|
runPostProcessorsOnAdapter(
|
|
13448
13534
|
action.activityId,
|
|
13449
13535
|
changes.postProcessors ?? [],
|
|
@@ -17307,7 +17393,8 @@ var WriteCapture = class {
|
|
|
17307
17393
|
ops: [],
|
|
17308
17394
|
linkFieldCaptured: /* @__PURE__ */ new Set(),
|
|
17309
17395
|
correlativeBefore: /* @__PURE__ */ new Map(),
|
|
17310
|
-
scheduledBefore: /* @__PURE__ */ new Map()
|
|
17396
|
+
scheduledBefore: /* @__PURE__ */ new Map(),
|
|
17397
|
+
progressFallbackBefore: /* @__PURE__ */ new Map()
|
|
17311
17398
|
};
|
|
17312
17399
|
}
|
|
17313
17400
|
peek() {
|
|
@@ -17370,6 +17457,11 @@ var WriteCapture = class {
|
|
|
17370
17457
|
before: cloneLink(current)
|
|
17371
17458
|
});
|
|
17372
17459
|
}
|
|
17460
|
+
noteProgressFallback(activityId, current) {
|
|
17461
|
+
const journal = this._journal;
|
|
17462
|
+
if (!journal || journal.progressFallbackBefore.has(activityId)) return;
|
|
17463
|
+
journal.progressFallbackBefore.set(activityId, current);
|
|
17464
|
+
}
|
|
17373
17465
|
};
|
|
17374
17466
|
function cloneLink(link) {
|
|
17375
17467
|
return { ...link };
|
|
@@ -17615,6 +17707,7 @@ var ScheduleState = class _ScheduleState {
|
|
|
17615
17707
|
_activities = /* @__PURE__ */ new Map();
|
|
17616
17708
|
_lastStartDate = /* @__PURE__ */ new Map();
|
|
17617
17709
|
_promotionSnapshot = /* @__PURE__ */ new Map();
|
|
17710
|
+
_progressFallback = /* @__PURE__ */ new Map();
|
|
17618
17711
|
_links = /* @__PURE__ */ new Map();
|
|
17619
17712
|
_outgoing = /* @__PURE__ */ new Map();
|
|
17620
17713
|
_incoming = /* @__PURE__ */ new Map();
|
|
@@ -17675,6 +17768,7 @@ var ScheduleState = class _ScheduleState {
|
|
|
17675
17768
|
cloneDomainValue(snapshot)
|
|
17676
17769
|
])
|
|
17677
17770
|
);
|
|
17771
|
+
fork._progressFallback = new Map(this._progressFallback);
|
|
17678
17772
|
fork._flags = cloneDomainValue(this._flags);
|
|
17679
17773
|
fork._filterProjection = cloneDomainValue(this._filterProjection);
|
|
17680
17774
|
return fork;
|
|
@@ -17728,6 +17822,17 @@ var ScheduleState = class _ScheduleState {
|
|
|
17728
17822
|
this._capturePromotionSnapshotOnce();
|
|
17729
17823
|
this._promotionSnapshot.set(String(activityId), snapshot);
|
|
17730
17824
|
}
|
|
17825
|
+
getProgressFallback(activityId) {
|
|
17826
|
+
return this._progressFallback.get(String(activityId)) ?? null;
|
|
17827
|
+
}
|
|
17828
|
+
setProgressFallback(activityId, value) {
|
|
17829
|
+
const key = String(activityId);
|
|
17830
|
+
const current = this._progressFallback.get(key) ?? null;
|
|
17831
|
+
if (Object.is(current, value)) return;
|
|
17832
|
+
this._writeCapture.noteProgressFallback(key, current);
|
|
17833
|
+
if (value === null) this._progressFallback.delete(key);
|
|
17834
|
+
else this._progressFallback.set(key, value);
|
|
17835
|
+
}
|
|
17731
17836
|
_capturePromotionSnapshotOnce() {
|
|
17732
17837
|
if (this._writeCapture.peek() === null) return;
|
|
17733
17838
|
if (this._promotionSnapshotBefore === null) {
|
|
@@ -17978,6 +18083,7 @@ var ScheduleState = class _ScheduleState {
|
|
|
17978
18083
|
const activity = this.getActivity(activityId);
|
|
17979
18084
|
if (activity) this._writeCapture.noteRemove(String(activityId), activity);
|
|
17980
18085
|
const key = String(activityId);
|
|
18086
|
+
this.setProgressFallback(key, null);
|
|
17981
18087
|
if (this._viewState.isChecked(key) || !this._viewState.isVisible(key)) {
|
|
17982
18088
|
this._captureViewStateOnce();
|
|
17983
18089
|
}
|
|
@@ -18002,7 +18108,13 @@ var ScheduleState = class _ScheduleState {
|
|
|
18002
18108
|
restoreFromCapture() {
|
|
18003
18109
|
const journal = this._writeCapture.peek();
|
|
18004
18110
|
if (!journal) return;
|
|
18005
|
-
const {
|
|
18111
|
+
const {
|
|
18112
|
+
ops,
|
|
18113
|
+
before,
|
|
18114
|
+
correlativeBefore,
|
|
18115
|
+
scheduledBefore,
|
|
18116
|
+
progressFallbackBefore
|
|
18117
|
+
} = journal;
|
|
18006
18118
|
this._undoLinkAdds(ops);
|
|
18007
18119
|
this._undoInserts(ops);
|
|
18008
18120
|
this._reInsertRemovedActivities(ops);
|
|
@@ -18011,6 +18123,7 @@ var ScheduleState = class _ScheduleState {
|
|
|
18011
18123
|
this._restoreCorrelatives(correlativeBefore);
|
|
18012
18124
|
this._restoreActivityFields(scheduledBefore);
|
|
18013
18125
|
this._restoreActivityFields(before);
|
|
18126
|
+
this._restoreProgressFallbacks(progressFallbackBefore);
|
|
18014
18127
|
if (this._viewStateBefore !== null) {
|
|
18015
18128
|
this._viewState.restore(this._viewStateBefore);
|
|
18016
18129
|
this._filterProjection = null;
|
|
@@ -18026,6 +18139,12 @@ var ScheduleState = class _ScheduleState {
|
|
|
18026
18139
|
this._cache.visualOrderIds = null;
|
|
18027
18140
|
this._hierarchy.markDirty();
|
|
18028
18141
|
}
|
|
18142
|
+
_restoreProgressFallbacks(before) {
|
|
18143
|
+
for (const [activityId, value] of before) {
|
|
18144
|
+
if (value === null) this._progressFallback.delete(activityId);
|
|
18145
|
+
else this._progressFallback.set(activityId, value);
|
|
18146
|
+
}
|
|
18147
|
+
}
|
|
18029
18148
|
_restoreCorrelatives(correlativeBefore) {
|
|
18030
18149
|
for (const [id, before] of correlativeBefore) {
|
|
18031
18150
|
const live = this._activities.get(id);
|
|
@@ -18239,13 +18358,15 @@ function buildHistoryChangeSet(changes) {
|
|
|
18239
18358
|
links: linksWithoutAfter
|
|
18240
18359
|
});
|
|
18241
18360
|
}
|
|
18242
|
-
function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks) {
|
|
18361
|
+
function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks, progressFallbackBefore, progressFallbackAfter) {
|
|
18243
18362
|
return {
|
|
18244
18363
|
changeSet,
|
|
18245
18364
|
beforeSnap,
|
|
18246
18365
|
beforeLinks: resetDerivedLinkSnapshots(beforeLinks),
|
|
18247
18366
|
afterSnap,
|
|
18248
|
-
afterLinks: resetDerivedLinkSnapshots(afterLinks)
|
|
18367
|
+
afterLinks: resetDerivedLinkSnapshots(afterLinks),
|
|
18368
|
+
progressFallbackBefore,
|
|
18369
|
+
progressFallbackAfter
|
|
18249
18370
|
};
|
|
18250
18371
|
}
|
|
18251
18372
|
function resetDerivedLinkSnapshots(snapshots) {
|
|
@@ -18308,7 +18429,9 @@ function mergeCoalesced(top, next) {
|
|
|
18308
18429
|
return buildUndoEntry(changeSet);
|
|
18309
18430
|
}
|
|
18310
18431
|
function getDispatchHistoryPolicy(action) {
|
|
18311
|
-
if (action.kind === "persistence-acknowledge")
|
|
18432
|
+
if (action.kind === "persistence-acknowledge") {
|
|
18433
|
+
return "checkpoint-on-success";
|
|
18434
|
+
}
|
|
18312
18435
|
if (action.kind === "sir-sync" || action.kind === "activity-lookahead-sync" || action.kind === "baseline-apply" || action.kind === "ponderator-criterion-set" || action.kind === "status-criteria-set" || action.kind === "activity-clipboard-clear" || action.kind === "activity-copy" || action.kind === "selection-toggle" || action.kind === "selection-replace" || action.kind === "visibility-set" || action.kind === "filter-set" || action.kind === "sort-set") {
|
|
18313
18436
|
return "skip";
|
|
18314
18437
|
}
|
|
@@ -18548,6 +18671,10 @@ function applyChangeSetSide(state, entry, side) {
|
|
|
18548
18671
|
);
|
|
18549
18672
|
}
|
|
18550
18673
|
}
|
|
18674
|
+
const progressFallbacks = side === "before" ? entry.progressFallbackBefore : entry.progressFallbackAfter;
|
|
18675
|
+
for (const [activityId, value] of progressFallbacks ?? []) {
|
|
18676
|
+
state.setProgressFallback(activityId, value);
|
|
18677
|
+
}
|
|
18551
18678
|
}
|
|
18552
18679
|
|
|
18553
18680
|
// src/dispatch/undo/undo-recorder.ts
|
|
@@ -18560,22 +18687,25 @@ var UndoRecorder = class _UndoRecorder {
|
|
|
18560
18687
|
maxDepth;
|
|
18561
18688
|
undoStack = [];
|
|
18562
18689
|
redoStack = [];
|
|
18690
|
+
sequence = 0;
|
|
18563
18691
|
_lastKey = null;
|
|
18564
18692
|
_lastTime = 0;
|
|
18565
18693
|
fork() {
|
|
18566
18694
|
const fork = new _UndoRecorder(this.maxDepth);
|
|
18567
18695
|
fork.undoStack.push(...cloneDomainValue(this.undoStack));
|
|
18568
18696
|
fork.redoStack.push(...cloneDomainValue(this.redoStack));
|
|
18697
|
+
fork.sequence = this.sequence;
|
|
18569
18698
|
fork._lastKey = this._lastKey;
|
|
18570
18699
|
fork._lastTime = this._lastTime;
|
|
18571
18700
|
return fork;
|
|
18572
18701
|
}
|
|
18573
18702
|
record(entry, coalesceKey = null, now = 0) {
|
|
18574
18703
|
const top = this.undoStack[this.undoStack.length - 1];
|
|
18575
|
-
if (coalesceKey != null && coalesceKey === this._lastKey && now - this._lastTime <= COALESCE_WINDOW_MS && top !== void 0 && canCoalesce(top, entry)) {
|
|
18576
|
-
|
|
18704
|
+
if (coalesceKey != null && coalesceKey === this._lastKey && now - this._lastTime <= COALESCE_WINDOW_MS && top !== void 0 && canCoalesce(top.entry, entry)) {
|
|
18705
|
+
top.entry = mergeCoalesced(top.entry, entry);
|
|
18706
|
+
top.touchedAt = this.touch();
|
|
18577
18707
|
} else {
|
|
18578
|
-
this.undoStack.push(entry);
|
|
18708
|
+
this.undoStack.push({ entry, touchedAt: this.touch() });
|
|
18579
18709
|
if (this.undoStack.length > this.maxDepth) {
|
|
18580
18710
|
this.undoStack.splice(0, this.undoStack.length - this.maxDepth);
|
|
18581
18711
|
}
|
|
@@ -18588,16 +18718,16 @@ var UndoRecorder = class _UndoRecorder {
|
|
|
18588
18718
|
this._lastKey = null;
|
|
18589
18719
|
}
|
|
18590
18720
|
takeUndo() {
|
|
18591
|
-
return this.undoStack.pop() ?? null;
|
|
18721
|
+
return this.undoStack.pop()?.entry ?? null;
|
|
18592
18722
|
}
|
|
18593
18723
|
takeRedo() {
|
|
18594
|
-
return this.redoStack.pop() ?? null;
|
|
18724
|
+
return this.redoStack.pop()?.entry ?? null;
|
|
18595
18725
|
}
|
|
18596
18726
|
pushRedo(entry) {
|
|
18597
|
-
this.redoStack.push(entry);
|
|
18727
|
+
this.redoStack.push({ entry, touchedAt: this.touch() });
|
|
18598
18728
|
}
|
|
18599
18729
|
pushUndo(entry) {
|
|
18600
|
-
this.undoStack.push(entry);
|
|
18730
|
+
this.undoStack.push({ entry, touchedAt: this.touch() });
|
|
18601
18731
|
}
|
|
18602
18732
|
canUndo() {
|
|
18603
18733
|
return this.undoStack.length > 0;
|
|
@@ -18608,11 +18738,64 @@ var UndoRecorder = class _UndoRecorder {
|
|
|
18608
18738
|
undoDepth() {
|
|
18609
18739
|
return this.undoStack.length;
|
|
18610
18740
|
}
|
|
18741
|
+
capturePersistenceBoundary() {
|
|
18742
|
+
this.resetCoalesce();
|
|
18743
|
+
return this.sequence;
|
|
18744
|
+
}
|
|
18745
|
+
discardThrough(boundary) {
|
|
18746
|
+
this.removeEntriesThrough(this.undoStack, boundary);
|
|
18747
|
+
this.removeEntriesThrough(this.redoStack, boundary);
|
|
18748
|
+
this.resetCoalesce();
|
|
18749
|
+
}
|
|
18750
|
+
applyPersistedIdentities(activities, links) {
|
|
18751
|
+
const activityIds = new Map(
|
|
18752
|
+
activities.map(({ id, proplannerId }) => [String(id), proplannerId])
|
|
18753
|
+
);
|
|
18754
|
+
const linkIds = new Map(
|
|
18755
|
+
links.map(({ id, proplannerId }) => [String(id), proplannerId])
|
|
18756
|
+
);
|
|
18757
|
+
for (const stored of [...this.undoStack, ...this.redoStack]) {
|
|
18758
|
+
stored.entry = this.withPersistedIdentities(
|
|
18759
|
+
stored.entry,
|
|
18760
|
+
activityIds,
|
|
18761
|
+
linkIds
|
|
18762
|
+
);
|
|
18763
|
+
}
|
|
18764
|
+
}
|
|
18611
18765
|
clear() {
|
|
18612
18766
|
this.undoStack.length = 0;
|
|
18613
18767
|
this.redoStack.length = 0;
|
|
18614
18768
|
this.resetCoalesce();
|
|
18615
18769
|
}
|
|
18770
|
+
touch() {
|
|
18771
|
+
this.sequence += 1;
|
|
18772
|
+
return this.sequence;
|
|
18773
|
+
}
|
|
18774
|
+
removeEntriesThrough(stack, boundary) {
|
|
18775
|
+
const retained = stack.filter(({ touchedAt }) => touchedAt > boundary);
|
|
18776
|
+
stack.splice(0, stack.length, ...retained);
|
|
18777
|
+
}
|
|
18778
|
+
withPersistedIdentities(entry, activityIds, linkIds) {
|
|
18779
|
+
const patchActivities = (snapshots) => snapshots === void 0 ? void 0 : new Map(
|
|
18780
|
+
Array.from(snapshots, ([id, activity]) => [
|
|
18781
|
+
id,
|
|
18782
|
+
activityIds.has(id) ? { ...activity, proplannerId: activityIds.get(id) } : activity
|
|
18783
|
+
])
|
|
18784
|
+
);
|
|
18785
|
+
const patchLinks = (snapshots) => snapshots === void 0 ? void 0 : new Map(
|
|
18786
|
+
Array.from(snapshots, ([id, link]) => [
|
|
18787
|
+
id,
|
|
18788
|
+
linkIds.has(id) ? { ...link, proplannerId: linkIds.get(id) } : link
|
|
18789
|
+
])
|
|
18790
|
+
);
|
|
18791
|
+
return {
|
|
18792
|
+
...entry,
|
|
18793
|
+
beforeSnap: patchActivities(entry.beforeSnap),
|
|
18794
|
+
afterSnap: patchActivities(entry.afterSnap),
|
|
18795
|
+
beforeLinks: patchLinks(entry.beforeLinks),
|
|
18796
|
+
afterLinks: patchLinks(entry.afterLinks)
|
|
18797
|
+
};
|
|
18798
|
+
}
|
|
18616
18799
|
};
|
|
18617
18800
|
|
|
18618
18801
|
// src/dispatch/shared/resequenced-parents.ts
|
|
@@ -18770,10 +18953,12 @@ function snapshotFieldValue(field, value) {
|
|
|
18770
18953
|
return value;
|
|
18771
18954
|
}
|
|
18772
18955
|
function activityChangedSince(current, saved) {
|
|
18773
|
-
|
|
18774
|
-
|
|
18775
|
-
|
|
18776
|
-
return
|
|
18956
|
+
return changedPersistableActivityFields(current, saved).length > 0;
|
|
18957
|
+
}
|
|
18958
|
+
function changedPersistableActivityFields(current, saved) {
|
|
18959
|
+
return PERSISTABLE_ACTIVITY_FIELDS.filter(
|
|
18960
|
+
(field) => !fieldEquals(field, current[field], saved[field])
|
|
18961
|
+
);
|
|
18777
18962
|
}
|
|
18778
18963
|
function fieldEquals(field, currentValue, savedValue) {
|
|
18779
18964
|
if (DATE_FIELDS2.has(field)) return dateEquals(currentValue, savedValue);
|
|
@@ -18882,11 +19067,60 @@ var SaveTracker = class _SaveTracker {
|
|
|
18882
19067
|
}
|
|
18883
19068
|
this.initialized = true;
|
|
18884
19069
|
}
|
|
18885
|
-
acknowledge(activities, links) {
|
|
19070
|
+
acknowledge(activities, links, activityIdentities = [], linkIdentities = [], currentActivities, currentLinks) {
|
|
18886
19071
|
if (!this.trackingEnabled) return;
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
|
|
19072
|
+
const activityIds = new Map(
|
|
19073
|
+
activityIdentities.map(({ id, proplannerId }) => [
|
|
19074
|
+
String(id),
|
|
19075
|
+
proplannerId
|
|
19076
|
+
])
|
|
19077
|
+
);
|
|
19078
|
+
const linkIds = new Map(
|
|
19079
|
+
linkIdentities.map(({ id, proplannerId }) => [String(id), proplannerId])
|
|
19080
|
+
);
|
|
19081
|
+
const persistedActivities = activities.map((activity) => ({
|
|
19082
|
+
...activity,
|
|
19083
|
+
proplannerId: activityIds.get(String(activity.id)) ?? activity.proplannerId
|
|
19084
|
+
}));
|
|
19085
|
+
const persistedLinks = links.map((link) => {
|
|
19086
|
+
const proplannerId = linkIds.get(String(link.id));
|
|
19087
|
+
return proplannerId === void 0 ? { ...link } : { ...link, proplannerId };
|
|
19088
|
+
});
|
|
19089
|
+
assertValidPersistedIdentities(persistedActivities, persistedLinks);
|
|
19090
|
+
this.snapshotActivities(persistedActivities);
|
|
19091
|
+
this.snapshotLinks(persistedLinks);
|
|
19092
|
+
if (!currentActivities || !currentLinks) return;
|
|
19093
|
+
const currentActivityById = new Map(
|
|
19094
|
+
currentActivities.map((activity) => [String(activity.id), activity])
|
|
19095
|
+
);
|
|
19096
|
+
const currentLinkById = new Map(
|
|
19097
|
+
currentLinks.map((link) => [String(link.id), link])
|
|
19098
|
+
);
|
|
19099
|
+
for (const activity of persistedActivities) {
|
|
19100
|
+
const activityId = String(activity.id);
|
|
19101
|
+
if (this.activityIsDirty(
|
|
19102
|
+
activityId,
|
|
19103
|
+
currentActivityById.get(activityId) ?? null
|
|
19104
|
+
)) {
|
|
19105
|
+
this.dirtyActivityIds.add(activityId);
|
|
19106
|
+
}
|
|
19107
|
+
}
|
|
19108
|
+
for (const activity of currentActivities) {
|
|
19109
|
+
const activityId = String(activity.id);
|
|
19110
|
+
if (this.activityIsDirty(activityId, activity)) {
|
|
19111
|
+
this.dirtyActivityIds.add(activityId);
|
|
19112
|
+
}
|
|
19113
|
+
}
|
|
19114
|
+
for (const link of persistedLinks) {
|
|
19115
|
+
const linkId = String(link.id);
|
|
19116
|
+
if (this.linkIsDirty(linkId, currentLinkById.get(linkId) ?? null)) {
|
|
19117
|
+
this.dirtyLinkIds.add(linkId);
|
|
19118
|
+
}
|
|
19119
|
+
}
|
|
19120
|
+
for (const link of currentLinks) {
|
|
19121
|
+
const linkId = String(link.id);
|
|
19122
|
+
if (this.linkIsDirty(linkId, link)) this.dirtyLinkIds.add(linkId);
|
|
19123
|
+
}
|
|
18890
19124
|
}
|
|
18891
19125
|
snapshotActivities(activities) {
|
|
18892
19126
|
if (!this.trackingEnabled) return;
|
|
@@ -19070,6 +19304,21 @@ var SaveTracker = class _SaveTracker {
|
|
|
19070
19304
|
}
|
|
19071
19305
|
return modified;
|
|
19072
19306
|
}
|
|
19307
|
+
modifiedActivityFields(getActivity) {
|
|
19308
|
+
const result = /* @__PURE__ */ new Map();
|
|
19309
|
+
if (!this.trackingEnabled || !this.initialized) return result;
|
|
19310
|
+
for (const activityId of this.dirtyActivityIds) {
|
|
19311
|
+
const current = getActivity(activityId);
|
|
19312
|
+
const saved = this.activitiesAtLastSave.get(activityId);
|
|
19313
|
+
if (!current || !saved) continue;
|
|
19314
|
+
const fields = changedPersistableActivityFields(
|
|
19315
|
+
current,
|
|
19316
|
+
saved.persistable
|
|
19317
|
+
);
|
|
19318
|
+
if (fields.length > 0) result.set(activityId, fields);
|
|
19319
|
+
}
|
|
19320
|
+
return result;
|
|
19321
|
+
}
|
|
19073
19322
|
modifiedLinks(getLink) {
|
|
19074
19323
|
if (!this.trackingEnabled || !this.initialized) return [];
|
|
19075
19324
|
const modified = [];
|
|
@@ -20439,6 +20688,7 @@ async function runInitialPasses(deps) {
|
|
|
20439
20688
|
normalizeLoadedConstraintDates(state);
|
|
20440
20689
|
recomputeCanonicalRealWork(state);
|
|
20441
20690
|
if (skipAutoSchedule) {
|
|
20691
|
+
recomputeAllProgressRollup(state);
|
|
20442
20692
|
if (now) {
|
|
20443
20693
|
applyExpectedProgressLive(state, now);
|
|
20444
20694
|
applyStatusPass(state, sector.statusCriteria);
|
|
@@ -20450,6 +20700,7 @@ async function runInitialPasses(deps) {
|
|
|
20450
20700
|
normalizeMilestoneConstraintDatesForDisplay(state);
|
|
20451
20701
|
recomputeSkippedLeafEnds(state);
|
|
20452
20702
|
await updateParentBoundsFromChildren(state, void 0, false);
|
|
20703
|
+
recomputeAllProgressRollup(state);
|
|
20453
20704
|
if (now) {
|
|
20454
20705
|
applyExpectedProgressLive(state, now);
|
|
20455
20706
|
applyStatusPass(state, sector.statusCriteria);
|
|
@@ -21160,6 +21411,14 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21160
21411
|
(activityId) => this.coreRuntime.state.getActivity(activityId)
|
|
21161
21412
|
).map(cloneDomainValue);
|
|
21162
21413
|
}
|
|
21414
|
+
getModifiedActivityFields() {
|
|
21415
|
+
this.assertReady();
|
|
21416
|
+
return cloneDomainValue(
|
|
21417
|
+
this._saveTracker.modifiedActivityFields(
|
|
21418
|
+
(activityId) => this.coreRuntime.state.getActivity(activityId)
|
|
21419
|
+
)
|
|
21420
|
+
);
|
|
21421
|
+
}
|
|
21163
21422
|
getNewActivities() {
|
|
21164
21423
|
this.assertReady();
|
|
21165
21424
|
return this._saveTracker.newActivities(
|
|
@@ -21173,6 +21432,10 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21173
21432
|
getScheduleRevision() {
|
|
21174
21433
|
return this._scheduleRevision;
|
|
21175
21434
|
}
|
|
21435
|
+
capturePersistenceHistoryBoundary() {
|
|
21436
|
+
this.assertReady();
|
|
21437
|
+
return this._undo.capturePersistenceBoundary();
|
|
21438
|
+
}
|
|
21176
21439
|
getCanonicalDigest() {
|
|
21177
21440
|
this.assertReady();
|
|
21178
21441
|
const byId = (left, right) => String(left.id).localeCompare(String(right.id));
|
|
@@ -21284,6 +21547,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21284
21547
|
this.coreRuntime.state.beginWriteCapture();
|
|
21285
21548
|
this.coreRuntime.customIdTracker.beginCustomIdTransaction();
|
|
21286
21549
|
let result;
|
|
21550
|
+
let progressFallbackBefore;
|
|
21287
21551
|
try {
|
|
21288
21552
|
result = await performDispatch(action, options, {
|
|
21289
21553
|
adapter: this.coreRuntime.state,
|
|
@@ -21304,6 +21568,10 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21304
21568
|
)?.id ?? null,
|
|
21305
21569
|
now: this.coreRuntime.clock ? endOfLocalDay(this.coreRuntime.clock()) : null
|
|
21306
21570
|
});
|
|
21571
|
+
const fallbackBefore = this.coreRuntime.state.peekWriteCapture()?.progressFallbackBefore;
|
|
21572
|
+
if (fallbackBefore && fallbackBefore.size > 0) {
|
|
21573
|
+
progressFallbackBefore = new Map(fallbackBefore);
|
|
21574
|
+
}
|
|
21307
21575
|
if (!result.ok) this._rollback(generatorSnapshot);
|
|
21308
21576
|
} catch (error) {
|
|
21309
21577
|
this._rollback(generatorSnapshot);
|
|
@@ -21317,25 +21585,50 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21317
21585
|
this.coreRuntime.state,
|
|
21318
21586
|
result.changes
|
|
21319
21587
|
);
|
|
21588
|
+
const progressFallbackAfter = progressFallbackBefore ? new Map(
|
|
21589
|
+
Array.from(progressFallbackBefore.keys(), (activityId) => [
|
|
21590
|
+
activityId,
|
|
21591
|
+
this.coreRuntime.state.getProgressFallback(activityId)
|
|
21592
|
+
])
|
|
21593
|
+
) : void 0;
|
|
21320
21594
|
this._undo.record(
|
|
21321
21595
|
buildUndoEntry(
|
|
21322
21596
|
buildHistoryChangeSet(result.changes),
|
|
21323
21597
|
result.__beforeSnap,
|
|
21324
21598
|
result.__beforeLinks,
|
|
21325
21599
|
created.afterSnap,
|
|
21326
|
-
created.afterLinks
|
|
21600
|
+
created.afterLinks,
|
|
21601
|
+
progressFallbackBefore,
|
|
21602
|
+
progressFallbackAfter
|
|
21327
21603
|
),
|
|
21328
21604
|
computeCoalesceKey(action),
|
|
21329
21605
|
Date.now()
|
|
21330
21606
|
);
|
|
21331
21607
|
}
|
|
21332
21608
|
if (result.ok) {
|
|
21333
|
-
if (historyPolicy === "
|
|
21609
|
+
if (historyPolicy === "checkpoint-on-success") {
|
|
21610
|
+
if (action.kind !== "persistence-acknowledge") {
|
|
21611
|
+
throw new Error(
|
|
21612
|
+
"checkpoint-on-success requires persistence acknowledge"
|
|
21613
|
+
);
|
|
21614
|
+
}
|
|
21615
|
+
const currentActivities = this.coreRuntime.state.getAllActivities();
|
|
21616
|
+
const currentLinks = this.coreRuntime.state.getAllLinks();
|
|
21617
|
+
const checkpoint = action.checkpoint;
|
|
21618
|
+
const boundary = checkpoint?.historyBoundary ?? this._undo.capturePersistenceBoundary();
|
|
21334
21619
|
this._saveTracker.acknowledge(
|
|
21335
|
-
|
|
21336
|
-
|
|
21620
|
+
checkpoint?.activities ?? currentActivities,
|
|
21621
|
+
checkpoint?.links ?? currentLinks,
|
|
21622
|
+
action.activities,
|
|
21623
|
+
action.links,
|
|
21624
|
+
currentActivities,
|
|
21625
|
+
currentLinks
|
|
21626
|
+
);
|
|
21627
|
+
this._undo.discardThrough(boundary);
|
|
21628
|
+
this._undo.applyPersistedIdentities(
|
|
21629
|
+
action.activities ?? [],
|
|
21630
|
+
action.links ?? []
|
|
21337
21631
|
);
|
|
21338
|
-
this._undo.clear();
|
|
21339
21632
|
} else if (action.kind === "activity-lookahead-sync" && action.acknowledgePersistedLookahead === true) {
|
|
21340
21633
|
this._saveTracker.acknowledgePersistedLookahead(
|
|
21341
21634
|
result.changes.activities,
|