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