@outbuild-company/schedule-core 1.9.0 → 1.9.2
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 +18 -71
- package/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +395 -725
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -167
- package/dist/index.d.ts +0 -167
- package/dist/index.js +395 -725
- package/dist/index.js.map +1 -1
- package/package.json +2 -9
package/dist/index.js
CHANGED
|
@@ -399,16 +399,10 @@ var FIELD_REGISTRY = {
|
|
|
399
399
|
valueKind: "reference",
|
|
400
400
|
extract: (activity) => activity.calendarId === null ? null : String(activity.calendarId)
|
|
401
401
|
},
|
|
402
|
-
// Normalized to string like calendarId. It is stored as a number, so it used
|
|
403
|
-
// to reach compareValues through the numeric branch while its sibling
|
|
404
|
-
// reference went through the string one — the same field kind comparing two
|
|
405
|
-
// different ways. localeCompare with numeric:true keeps the digit ordering.
|
|
406
402
|
subcontractId: {
|
|
407
403
|
valueKind: "reference",
|
|
408
404
|
extract: (activity) => activity.subcontractId === null ? null : String(activity.subcontractId)
|
|
409
405
|
},
|
|
410
|
-
// Declared boolean, not enum: it is one, and saying so is what lets the enum
|
|
411
|
-
// branch demand an order without inventing one for true/false.
|
|
412
406
|
isCritical: {
|
|
413
407
|
valueKind: "boolean",
|
|
414
408
|
extract: (activity) => activity.isCritical
|
|
@@ -418,107 +412,6 @@ function getFieldDescriptor(field) {
|
|
|
418
412
|
return FIELD_REGISTRY[field] ?? null;
|
|
419
413
|
}
|
|
420
414
|
|
|
421
|
-
// src/internal/state/view-state.ts
|
|
422
|
-
function isRelativePlacementPinValid(activityId, pin, parentOf) {
|
|
423
|
-
const branchParentId = String(pin.branchParentId);
|
|
424
|
-
const currentParentId = String(parentOf(activityId) ?? "0");
|
|
425
|
-
if (currentParentId !== branchParentId) return false;
|
|
426
|
-
const referenceId = String(pin.referenceId);
|
|
427
|
-
return referenceId === branchParentId || String(parentOf(referenceId) ?? "0") === branchParentId;
|
|
428
|
-
}
|
|
429
|
-
var ViewStateStore = class {
|
|
430
|
-
checkedSet = /* @__PURE__ */ new Set();
|
|
431
|
-
hiddenSet = /* @__PURE__ */ new Set();
|
|
432
|
-
activeFilter = null;
|
|
433
|
-
activeOrder = null;
|
|
434
|
-
relativePlacementPins = /* @__PURE__ */ new Map();
|
|
435
|
-
isChecked(activityId) {
|
|
436
|
-
return this.checkedSet.has(activityId);
|
|
437
|
-
}
|
|
438
|
-
isVisible(activityId) {
|
|
439
|
-
return !this.hiddenSet.has(activityId);
|
|
440
|
-
}
|
|
441
|
-
hiddenIds() {
|
|
442
|
-
return [...this.hiddenSet];
|
|
443
|
-
}
|
|
444
|
-
getActiveFilter() {
|
|
445
|
-
return this.activeFilter;
|
|
446
|
-
}
|
|
447
|
-
setActiveFilter(nextFilter) {
|
|
448
|
-
this.activeFilter = nextFilter;
|
|
449
|
-
}
|
|
450
|
-
getActiveOrder() {
|
|
451
|
-
return this.activeOrder;
|
|
452
|
-
}
|
|
453
|
-
setActiveOrder(nextOrder) {
|
|
454
|
-
this.activeOrder = nextOrder;
|
|
455
|
-
}
|
|
456
|
-
setRelativePlacementPin(activityId, pin) {
|
|
457
|
-
this.relativePlacementPins.set(String(activityId), {
|
|
458
|
-
referenceId: String(pin.referenceId),
|
|
459
|
-
branchParentId: String(pin.branchParentId),
|
|
460
|
-
side: pin.side
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
getRelativePlacementPins() {
|
|
464
|
-
return this.relativePlacementPins;
|
|
465
|
-
}
|
|
466
|
-
restoreRelativePlacementPins(pins) {
|
|
467
|
-
this.relativePlacementPins = new Map(pins);
|
|
468
|
-
}
|
|
469
|
-
checkedIds() {
|
|
470
|
-
return [...this.checkedSet];
|
|
471
|
-
}
|
|
472
|
-
checkedCount() {
|
|
473
|
-
return this.checkedSet.size;
|
|
474
|
-
}
|
|
475
|
-
setChecked(activityId, nextChecked) {
|
|
476
|
-
if (nextChecked === this.checkedSet.has(activityId)) return false;
|
|
477
|
-
if (nextChecked) this.checkedSet.add(activityId);
|
|
478
|
-
else this.checkedSet.delete(activityId);
|
|
479
|
-
return true;
|
|
480
|
-
}
|
|
481
|
-
setVisible(activityId, nextVisible) {
|
|
482
|
-
if (nextVisible === !this.hiddenSet.has(activityId)) return false;
|
|
483
|
-
if (nextVisible) this.hiddenSet.delete(activityId);
|
|
484
|
-
else this.hiddenSet.add(activityId);
|
|
485
|
-
return true;
|
|
486
|
-
}
|
|
487
|
-
forget(activityId) {
|
|
488
|
-
this.checkedSet.delete(activityId);
|
|
489
|
-
this.hiddenSet.delete(activityId);
|
|
490
|
-
this.relativePlacementPins.delete(activityId);
|
|
491
|
-
for (const [pinnedId, pin] of this.relativePlacementPins) {
|
|
492
|
-
if (pin.referenceId === activityId) {
|
|
493
|
-
this.relativePlacementPins.delete(pinnedId);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
hydrate(seed2) {
|
|
498
|
-
this.checkedSet = new Set(seed2.checkedIds ?? []);
|
|
499
|
-
this.hiddenSet = new Set(seed2.hiddenIds ?? []);
|
|
500
|
-
this.activeFilter = null;
|
|
501
|
-
this.activeOrder = null;
|
|
502
|
-
this.relativePlacementPins = /* @__PURE__ */ new Map();
|
|
503
|
-
}
|
|
504
|
-
snapshot() {
|
|
505
|
-
return {
|
|
506
|
-
checked: new Set(this.checkedSet),
|
|
507
|
-
hidden: new Set(this.hiddenSet),
|
|
508
|
-
activeFilter: this.activeFilter,
|
|
509
|
-
activeOrder: this.activeOrder,
|
|
510
|
-
relativePlacementPins: new Map(this.relativePlacementPins)
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
restore(snapshot) {
|
|
514
|
-
this.checkedSet = new Set(snapshot.checked);
|
|
515
|
-
this.hiddenSet = new Set(snapshot.hidden);
|
|
516
|
-
this.activeFilter = snapshot.activeFilter;
|
|
517
|
-
this.activeOrder = snapshot.activeOrder;
|
|
518
|
-
this.relativePlacementPins = new Map(snapshot.relativePlacementPins);
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
|
|
522
415
|
// src/internal/filter/evaluate-filter.ts
|
|
523
416
|
function toTargetDate(value) {
|
|
524
417
|
if (value instanceof Date) return value;
|
|
@@ -645,7 +538,6 @@ function evaluateVisibleIds(input) {
|
|
|
645
538
|
function seedFilterProjection(input) {
|
|
646
539
|
const { activities, parentOf, filter, context } = input;
|
|
647
540
|
const matchedIds = /* @__PURE__ */ new Set();
|
|
648
|
-
const pinnedVisibleIds = /* @__PURE__ */ new Set();
|
|
649
541
|
const visibleReferenceCounts = /* @__PURE__ */ new Map();
|
|
650
542
|
const parentIds = /* @__PURE__ */ new Map();
|
|
651
543
|
const remainingChildren = /* @__PURE__ */ new Map();
|
|
@@ -666,35 +558,11 @@ function seedFilterProjection(input) {
|
|
|
666
558
|
}
|
|
667
559
|
return {
|
|
668
560
|
matchedIds,
|
|
669
|
-
pinnedVisibleIds,
|
|
670
561
|
visibleReferenceCounts,
|
|
671
562
|
parentIds,
|
|
672
563
|
remainingChildren
|
|
673
564
|
};
|
|
674
565
|
}
|
|
675
|
-
function applyRelativePlacementPins(seed2, pins) {
|
|
676
|
-
if (pins === void 0) return;
|
|
677
|
-
for (const [activityId, pin] of pins) {
|
|
678
|
-
const pinnedId = String(activityId);
|
|
679
|
-
const referenceId = String(pin.referenceId);
|
|
680
|
-
if (!seed2.parentIds.has(pinnedId) || !seed2.parentIds.has(referenceId) || !isRelativePlacementPinValid(
|
|
681
|
-
pinnedId,
|
|
682
|
-
pin,
|
|
683
|
-
(activityId2) => seed2.parentIds.get(activityId2) ?? null
|
|
684
|
-
) || (seed2.visibleReferenceCounts.get(referenceId) ?? 0) === 0) {
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
|
-
seed2.pinnedVisibleIds.add(pinnedId);
|
|
688
|
-
let currentId = pinnedId;
|
|
689
|
-
while (currentId !== null) {
|
|
690
|
-
seed2.visibleReferenceCounts.set(
|
|
691
|
-
currentId,
|
|
692
|
-
(seed2.visibleReferenceCounts.get(currentId) ?? 0) + 1
|
|
693
|
-
);
|
|
694
|
-
currentId = seed2.parentIds.get(currentId) ?? null;
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
566
|
function propagateVisibleReferenceCounts(seed2) {
|
|
699
567
|
const { visibleReferenceCounts, parentIds, remainingChildren } = seed2;
|
|
700
568
|
const pendingIds = [];
|
|
@@ -726,13 +594,11 @@ function collectVisibleIds(visibleReferenceCounts) {
|
|
|
726
594
|
function buildFilterProjection(input) {
|
|
727
595
|
const seed2 = seedFilterProjection(input);
|
|
728
596
|
propagateVisibleReferenceCounts(seed2);
|
|
729
|
-
applyRelativePlacementPins(seed2, input.relativePlacementPins);
|
|
730
597
|
const visibleIds = collectVisibleIds(seed2.visibleReferenceCounts);
|
|
731
598
|
return {
|
|
732
599
|
filter: input.filter,
|
|
733
600
|
context: input.context,
|
|
734
601
|
matchedIds: seed2.matchedIds,
|
|
735
|
-
pinnedVisibleIds: seed2.pinnedVisibleIds,
|
|
736
602
|
visibleIds,
|
|
737
603
|
visibleReferenceCounts: seed2.visibleReferenceCounts
|
|
738
604
|
};
|
|
@@ -790,8 +656,6 @@ var OPERATORS_BY_KIND = {
|
|
|
790
656
|
date: /* @__PURE__ */ new Set(["after", "before"]),
|
|
791
657
|
"id-array": /* @__PURE__ */ new Set(["someOf", "notSomeOf"]),
|
|
792
658
|
enum: /* @__PURE__ */ new Set(["someOf", "notSomeOf"]),
|
|
793
|
-
// Same membership operators as enum: splitting the kinds was about ordering,
|
|
794
|
-
// not about filtering, and these two filter exactly like an enum.
|
|
795
659
|
boolean: /* @__PURE__ */ new Set(["someOf", "notSomeOf"]),
|
|
796
660
|
reference: /* @__PURE__ */ new Set(["someOf", "notSomeOf"])
|
|
797
661
|
};
|
|
@@ -914,8 +778,7 @@ function resolveFilter(adapter, filter, hoursPerDay) {
|
|
|
914
778
|
activities,
|
|
915
779
|
parentOf: (activityId) => adapter.getParentId(activityId),
|
|
916
780
|
filter,
|
|
917
|
-
context: buildFilterContext(hoursPerDay)
|
|
918
|
-
relativePlacementPins: adapter.getRelativePlacementPins()
|
|
781
|
+
context: buildFilterContext(hoursPerDay)
|
|
919
782
|
});
|
|
920
783
|
return { visibleIds: projection.visibleIds, projection };
|
|
921
784
|
}
|
|
@@ -966,118 +829,25 @@ function normalizeParentKey(parent) {
|
|
|
966
829
|
|
|
967
830
|
// src/internal/hierarchy/visual-order.ts
|
|
968
831
|
var NOT_SET_SORT_VALUE = Number.MAX_SAFE_INTEGER;
|
|
969
|
-
|
|
970
|
-
function buildRelativePlacementPinIndex(adapter) {
|
|
971
|
-
const index = /* @__PURE__ */ new Map();
|
|
972
|
-
for (const [activityId, pin] of adapter.getRelativePlacementPins?.() ?? []) {
|
|
973
|
-
const pinnedId = String(activityId);
|
|
974
|
-
const referenceId = String(pin.referenceId);
|
|
975
|
-
if (adapter.getActivity(pinnedId) === null || adapter.getActivity(referenceId) === null || !isRelativePlacementPinValid(
|
|
976
|
-
pinnedId,
|
|
977
|
-
pin,
|
|
978
|
-
(activityId2) => adapter.getParentId(activityId2)
|
|
979
|
-
)) {
|
|
980
|
-
continue;
|
|
981
|
-
}
|
|
982
|
-
const targetParentId = String(pin.branchParentId);
|
|
983
|
-
const branchPins = index.get(targetParentId) ?? /* @__PURE__ */ new Map();
|
|
984
|
-
branchPins.set(pinnedId, pin);
|
|
985
|
-
index.set(targetParentId, branchPins);
|
|
986
|
-
}
|
|
987
|
-
return index;
|
|
988
|
-
}
|
|
989
|
-
function getChildrenInVisualOrder(parentId, adapter, pinIndex = buildRelativePlacementPinIndex(adapter)) {
|
|
832
|
+
function getChildrenInVisualOrder(parentId, adapter) {
|
|
990
833
|
const children = collectChildrenSnapshots(parentId, adapter);
|
|
991
834
|
const userOrder = adapter.getOrderComparator?.() ?? null;
|
|
992
835
|
children.sort(
|
|
993
836
|
userOrder === null ? compareActivitiesInVisualOrder : (a, b) => userOrder(a, b) || compareActivitiesInVisualOrder(a, b)
|
|
994
837
|
);
|
|
995
|
-
return
|
|
996
|
-
children.map((activity) => String(activity.id)),
|
|
997
|
-
parentId,
|
|
998
|
-
pinIndex.get(String(parentId)) ?? EMPTY_RELATIVE_PLACEMENT_PINS
|
|
999
|
-
);
|
|
1000
|
-
}
|
|
1001
|
-
function applyRelativePlacementPins2(orderedIds, parentId, pins) {
|
|
1002
|
-
const order = buildLinkedActivityOrder(orderedIds);
|
|
1003
|
-
for (const [activityId, pin] of pins) {
|
|
1004
|
-
const pinnedId = String(activityId);
|
|
1005
|
-
const referenceId = String(pin.referenceId);
|
|
1006
|
-
const isFirstChild = referenceId === String(parentId);
|
|
1007
|
-
if (!order.previous.has(pinnedId) || !isFirstChild && (!order.previous.has(referenceId) || pinnedId === referenceId)) {
|
|
1008
|
-
continue;
|
|
1009
|
-
}
|
|
1010
|
-
detachActivity(order, pinnedId);
|
|
1011
|
-
if (isFirstChild) insertActivityFirst(order, pinnedId);
|
|
1012
|
-
else insertActivityBeside(order, pinnedId, referenceId, pin.side);
|
|
1013
|
-
}
|
|
1014
|
-
return materializeActivityOrder(order);
|
|
1015
|
-
}
|
|
1016
|
-
function buildLinkedActivityOrder(orderedIds) {
|
|
1017
|
-
const previous = /* @__PURE__ */ new Map();
|
|
1018
|
-
const next = /* @__PURE__ */ new Map();
|
|
1019
|
-
for (let index = 0; index < orderedIds.length; index++) {
|
|
1020
|
-
const activityId = orderedIds[index];
|
|
1021
|
-
if (activityId === void 0) continue;
|
|
1022
|
-
previous.set(activityId, orderedIds[index - 1] ?? null);
|
|
1023
|
-
next.set(activityId, orderedIds[index + 1] ?? null);
|
|
1024
|
-
}
|
|
1025
|
-
return { previous, next, head: orderedIds[0] ?? null };
|
|
1026
|
-
}
|
|
1027
|
-
function detachActivity(order, activityId) {
|
|
1028
|
-
const before = order.previous.get(activityId) ?? null;
|
|
1029
|
-
const after = order.next.get(activityId) ?? null;
|
|
1030
|
-
if (before === null) order.head = after;
|
|
1031
|
-
else order.next.set(before, after);
|
|
1032
|
-
if (after !== null) order.previous.set(after, before);
|
|
1033
|
-
}
|
|
1034
|
-
function insertActivityFirst(order, activityId) {
|
|
1035
|
-
order.previous.set(activityId, null);
|
|
1036
|
-
order.next.set(activityId, order.head);
|
|
1037
|
-
if (order.head !== null) order.previous.set(order.head, activityId);
|
|
1038
|
-
order.head = activityId;
|
|
1039
|
-
}
|
|
1040
|
-
function insertActivityBeside(order, activityId, referenceId, side) {
|
|
1041
|
-
if (side === "before") {
|
|
1042
|
-
const before = order.previous.get(referenceId) ?? null;
|
|
1043
|
-
order.previous.set(activityId, before);
|
|
1044
|
-
order.next.set(activityId, referenceId);
|
|
1045
|
-
order.previous.set(referenceId, activityId);
|
|
1046
|
-
if (before === null) order.head = activityId;
|
|
1047
|
-
else order.next.set(before, activityId);
|
|
1048
|
-
return;
|
|
1049
|
-
}
|
|
1050
|
-
const after = order.next.get(referenceId) ?? null;
|
|
1051
|
-
order.previous.set(activityId, referenceId);
|
|
1052
|
-
order.next.set(activityId, after);
|
|
1053
|
-
order.next.set(referenceId, activityId);
|
|
1054
|
-
if (after !== null) order.previous.set(after, activityId);
|
|
1055
|
-
}
|
|
1056
|
-
function materializeActivityOrder(order) {
|
|
1057
|
-
const result = [];
|
|
1058
|
-
let activityId = order.head;
|
|
1059
|
-
while (activityId !== null) {
|
|
1060
|
-
result.push(activityId);
|
|
1061
|
-
activityId = order.next.get(activityId) ?? null;
|
|
1062
|
-
}
|
|
1063
|
-
return result;
|
|
838
|
+
return children.map((activity) => String(activity.id));
|
|
1064
839
|
}
|
|
1065
840
|
function iterateInVisualOrder(adapter) {
|
|
1066
841
|
const result = [];
|
|
1067
|
-
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
1068
842
|
const visit = (activity) => {
|
|
1069
843
|
result.push(activity);
|
|
1070
|
-
const childIds = getChildrenInVisualOrder(
|
|
1071
|
-
String(activity.id),
|
|
1072
|
-
adapter,
|
|
1073
|
-
pinIndex
|
|
1074
|
-
);
|
|
844
|
+
const childIds = getChildrenInVisualOrder(String(activity.id), adapter);
|
|
1075
845
|
for (const childId of childIds) {
|
|
1076
846
|
const child = adapter.getActivity(childId);
|
|
1077
847
|
if (child) visit(child);
|
|
1078
848
|
}
|
|
1079
849
|
};
|
|
1080
|
-
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter
|
|
850
|
+
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter);
|
|
1081
851
|
for (const rootId of rootIds) {
|
|
1082
852
|
const root = adapter.getActivity(rootId);
|
|
1083
853
|
if (root) visit(root);
|
|
@@ -1138,9 +908,8 @@ function setHas(set, id) {
|
|
|
1138
908
|
// src/dispatch/shared/collect-branch-order.ts
|
|
1139
909
|
function collectBranchOrder(adapter) {
|
|
1140
910
|
const branches = [];
|
|
1141
|
-
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
1142
911
|
const visit = (parentId) => {
|
|
1143
|
-
const childIds = getChildrenInVisualOrder(parentId, adapter
|
|
912
|
+
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
1144
913
|
if (childIds.length > 1) {
|
|
1145
914
|
branches.push({ parentId, childIds });
|
|
1146
915
|
}
|
|
@@ -1153,9 +922,8 @@ function collectBranchOrder(adapter) {
|
|
|
1153
922
|
}
|
|
1154
923
|
function collectBranchOrderForParents(adapter, parentIds) {
|
|
1155
924
|
const branches = [];
|
|
1156
|
-
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
1157
925
|
for (const parentId of parentIds) {
|
|
1158
|
-
const childIds = getChildrenInVisualOrder(parentId, adapter
|
|
926
|
+
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
1159
927
|
if (childIds.length > 1) branches.push({ parentId, childIds });
|
|
1160
928
|
}
|
|
1161
929
|
return branches;
|
|
@@ -1188,107 +956,61 @@ function dispatchSortSet(action, deps) {
|
|
|
1188
956
|
return { ok: true, changes };
|
|
1189
957
|
}
|
|
1190
958
|
|
|
1191
|
-
// src/columns
|
|
1192
|
-
var
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
// src/columns/tags/constants.ts
|
|
1237
|
-
var TAGS = "tags";
|
|
1238
|
-
|
|
1239
|
-
// src/columns/predecessors/constants.ts
|
|
1240
|
-
var CUSTOM_PREDECESSORS = "custom_predecessors";
|
|
1241
|
-
|
|
1242
|
-
// src/columns/successors/constants.ts
|
|
1243
|
-
var CUSTOM_SUCESSORS = "custom_sucessors";
|
|
1244
|
-
|
|
1245
|
-
// src/columns/real-work/constants.ts
|
|
1246
|
-
var REAL_WORK = "real_work";
|
|
1247
|
-
|
|
1248
|
-
// src/columns/real-cost/constants.ts
|
|
1249
|
-
var REAL_COST = "real_cost";
|
|
1250
|
-
|
|
1251
|
-
// src/columns/expected-progress/constants.ts
|
|
1252
|
-
var EXPECTED_PROGRESS = "expected_progress";
|
|
1253
|
-
|
|
1254
|
-
// src/columns/expected-progress-base/constants.ts
|
|
1255
|
-
var EXPECTED_PROGRESS_BASE = "expected_progress_base";
|
|
1256
|
-
|
|
1257
|
-
// src/columns/start-base/constants.ts
|
|
1258
|
-
var START_BASE = "start_base";
|
|
1259
|
-
|
|
1260
|
-
// src/columns/end-base/constants.ts
|
|
1261
|
-
var END_BASE = "end_base";
|
|
1262
|
-
|
|
1263
|
-
// src/columns/duration-base/constants.ts
|
|
1264
|
-
var DURATION_BASE = "duration_base";
|
|
1265
|
-
|
|
1266
|
-
// src/columns/cost-base/constants.ts
|
|
1267
|
-
var COST_BASE = "cost_base";
|
|
1268
|
-
|
|
1269
|
-
// src/columns/work-base/constants.ts
|
|
1270
|
-
var WORK_BASE = "work_base";
|
|
1271
|
-
|
|
1272
|
-
// src/columns/calendar-duration/constants.ts
|
|
1273
|
-
var CALENDAR_DURATION = "calendarDuration";
|
|
1274
|
-
|
|
1275
|
-
// src/columns/critical-path/constants.ts
|
|
1276
|
-
var IS_CRITICAL = "is_critical";
|
|
1277
|
-
var EARLY_START = "earlyStart";
|
|
1278
|
-
var EARLY_FINISH = "earlyFinish";
|
|
1279
|
-
var LATE_START = "lateStart";
|
|
1280
|
-
var LATE_FINISH = "lateFinish";
|
|
1281
|
-
var FREE_SLACK = "freeSlack";
|
|
1282
|
-
var TOTAL_SLACK = "totalSlack";
|
|
1283
|
-
|
|
1284
|
-
// src/columns/correlative-id/constants.ts
|
|
1285
|
-
var CORRELATIVE_ID = "correlative_id";
|
|
959
|
+
// src/constants/columns.ts
|
|
960
|
+
var EDITABLE = {
|
|
961
|
+
TEXT: "text",
|
|
962
|
+
DESCRIPTION: "description",
|
|
963
|
+
DURATION: "duration",
|
|
964
|
+
PROGRESS: "progress",
|
|
965
|
+
COST: "cost",
|
|
966
|
+
USED_COST: "used_cost",
|
|
967
|
+
HH_WORK_TIME: "hhWorkTime",
|
|
968
|
+
START_DATE: "start_date",
|
|
969
|
+
END_DATE: "end_date",
|
|
970
|
+
CONSTRAINT_TYPE: "constraint_type",
|
|
971
|
+
CONSTRAINT_DATE: "constraint_date",
|
|
972
|
+
CALENDAR_ID: "calendar_id",
|
|
973
|
+
CUSTOM_ID: "custom_id",
|
|
974
|
+
SUBCONTRACT_ID: "subcontractId",
|
|
975
|
+
RESPONSABLES: "responsables",
|
|
976
|
+
TAGS: "tags",
|
|
977
|
+
CUSTOM_PREDECESSORS: "custom_predecessors",
|
|
978
|
+
CUSTOM_SUCESSORS: "custom_sucessors"
|
|
979
|
+
};
|
|
980
|
+
var READ_ONLY = {
|
|
981
|
+
REAL_WORK: "real_work",
|
|
982
|
+
REAL_COST: "real_cost",
|
|
983
|
+
EXPECTED_PROGRESS: "expected_progress",
|
|
984
|
+
EXPECTED_PROGRESS_BASE: "expected_progress_base",
|
|
985
|
+
START_BASE: "start_base",
|
|
986
|
+
END_BASE: "end_base",
|
|
987
|
+
DURATION_BASE: "duration_base",
|
|
988
|
+
COST_BASE: "cost_base",
|
|
989
|
+
WORK_BASE: "work_base",
|
|
990
|
+
CALENDAR_DURATION: "calendarDuration",
|
|
991
|
+
IS_CRITICAL: "is_critical",
|
|
992
|
+
EARLY_START: "earlyStart",
|
|
993
|
+
EARLY_FINISH: "earlyFinish",
|
|
994
|
+
LATE_START: "lateStart",
|
|
995
|
+
LATE_FINISH: "lateFinish",
|
|
996
|
+
FREE_SLACK: "freeSlack",
|
|
997
|
+
TOTAL_SLACK: "totalSlack",
|
|
998
|
+
CORRELATIVE_ID: "correlative_id",
|
|
999
|
+
UNIQUE_CORRELATIVE_ID: "unique_correlative_id",
|
|
1000
|
+
PONDERATOR: "ponderator",
|
|
1001
|
+
STATUS: "status"
|
|
1002
|
+
};
|
|
1003
|
+
var COLUMN = { ...EDITABLE, ...READ_ONLY };
|
|
1286
1004
|
|
|
1287
|
-
// src/
|
|
1288
|
-
|
|
1005
|
+
// src/shared/assert-never.ts
|
|
1006
|
+
function assertNever(value, message) {
|
|
1007
|
+
throw new Error(message);
|
|
1008
|
+
}
|
|
1289
1009
|
|
|
1290
|
-
// src/
|
|
1291
|
-
|
|
1010
|
+
// src/autoscheduler/utils/cancellation.ts
|
|
1011
|
+
function createIsCurrent(id, getCurrentId) {
|
|
1012
|
+
return () => getCurrentId() === id;
|
|
1013
|
+
}
|
|
1292
1014
|
|
|
1293
1015
|
// src/types.ts
|
|
1294
1016
|
var WORK_TIME_DIRECTION = {
|
|
@@ -1307,71 +1029,8 @@ var STATUS = {
|
|
|
1307
1029
|
DOING: "Doing"
|
|
1308
1030
|
};
|
|
1309
1031
|
|
|
1310
|
-
// src/columns/status/constants.ts
|
|
1311
|
-
var STATUS_COLUMN = "status";
|
|
1312
|
-
var DEFAULT_STATUS_CRITERIA = "Baseline";
|
|
1313
|
-
function resolveStatusCriteria(value) {
|
|
1314
|
-
return value === "Actual" ? "Actual" : DEFAULT_STATUS_CRITERIA;
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
// src/constants/columns.ts
|
|
1318
|
-
var EDITABLE = {
|
|
1319
|
-
TEXT,
|
|
1320
|
-
DESCRIPTION,
|
|
1321
|
-
DURATION,
|
|
1322
|
-
PROGRESS,
|
|
1323
|
-
COST,
|
|
1324
|
-
USED_COST,
|
|
1325
|
-
HH_WORK_TIME,
|
|
1326
|
-
START_DATE,
|
|
1327
|
-
END_DATE,
|
|
1328
|
-
CONSTRAINT_TYPE,
|
|
1329
|
-
CONSTRAINT_DATE,
|
|
1330
|
-
CALENDAR_ID,
|
|
1331
|
-
CUSTOM_ID,
|
|
1332
|
-
SUBCONTRACT_ID,
|
|
1333
|
-
RESPONSABLES,
|
|
1334
|
-
TAGS,
|
|
1335
|
-
CUSTOM_PREDECESSORS,
|
|
1336
|
-
CUSTOM_SUCESSORS
|
|
1337
|
-
};
|
|
1338
|
-
var READ_ONLY = {
|
|
1339
|
-
REAL_WORK,
|
|
1340
|
-
REAL_COST,
|
|
1341
|
-
EXPECTED_PROGRESS,
|
|
1342
|
-
EXPECTED_PROGRESS_BASE,
|
|
1343
|
-
START_BASE,
|
|
1344
|
-
END_BASE,
|
|
1345
|
-
DURATION_BASE,
|
|
1346
|
-
COST_BASE,
|
|
1347
|
-
WORK_BASE,
|
|
1348
|
-
CALENDAR_DURATION,
|
|
1349
|
-
IS_CRITICAL,
|
|
1350
|
-
EARLY_START,
|
|
1351
|
-
EARLY_FINISH,
|
|
1352
|
-
LATE_START,
|
|
1353
|
-
LATE_FINISH,
|
|
1354
|
-
FREE_SLACK,
|
|
1355
|
-
TOTAL_SLACK,
|
|
1356
|
-
CORRELATIVE_ID,
|
|
1357
|
-
UNIQUE_CORRELATIVE_ID,
|
|
1358
|
-
PONDERATOR,
|
|
1359
|
-
STATUS: STATUS_COLUMN
|
|
1360
|
-
};
|
|
1361
|
-
var COLUMN = { ...EDITABLE, ...READ_ONLY };
|
|
1362
|
-
|
|
1363
|
-
// src/shared/assert-never.ts
|
|
1364
|
-
function assertNever(value, message) {
|
|
1365
|
-
throw new Error(message);
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
// src/autoscheduler/utils/cancellation.ts
|
|
1369
|
-
function createIsCurrent(id, getCurrentId) {
|
|
1370
|
-
return () => getCurrentId() === id;
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
1032
|
// src/constraints/index.ts
|
|
1374
|
-
var
|
|
1033
|
+
var CONSTRAINT_TYPE = {
|
|
1375
1034
|
ASAP: "asap",
|
|
1376
1035
|
ALAP: "alap",
|
|
1377
1036
|
SNET: "snet",
|
|
@@ -2288,7 +1947,7 @@ function processConstraints(activityIds, adapter, plans) {
|
|
|
2288
1947
|
const activity = adapter.getActivity(id);
|
|
2289
1948
|
if (!activity) continue;
|
|
2290
1949
|
const type = activity.constraintType;
|
|
2291
|
-
if (!type || type ===
|
|
1950
|
+
if (!type || type === CONSTRAINT_TYPE.ASAP || type === CONSTRAINT_TYPE.ALAP) {
|
|
2292
1951
|
continue;
|
|
2293
1952
|
}
|
|
2294
1953
|
const bounds = computeConstraintBounds(activity, adapter);
|
|
@@ -2337,14 +1996,14 @@ function validateMilestoneConstraint(activity, successorStart) {
|
|
|
2337
1996
|
const { constraintType, constraintDate } = activity;
|
|
2338
1997
|
if (!constraintType || !constraintDate) return successorStart;
|
|
2339
1998
|
switch (constraintType) {
|
|
2340
|
-
case
|
|
2341
|
-
case
|
|
1999
|
+
case CONSTRAINT_TYPE.MSO:
|
|
2000
|
+
case CONSTRAINT_TYPE.MFO:
|
|
2342
2001
|
return new Date(constraintDate);
|
|
2343
|
-
case
|
|
2344
|
-
case
|
|
2002
|
+
case CONSTRAINT_TYPE.SNET:
|
|
2003
|
+
case CONSTRAINT_TYPE.FNET:
|
|
2345
2004
|
return constraintDate > successorStart ? new Date(constraintDate) : successorStart;
|
|
2346
|
-
case
|
|
2347
|
-
case
|
|
2005
|
+
case CONSTRAINT_TYPE.SNLT:
|
|
2006
|
+
case CONSTRAINT_TYPE.FNLT:
|
|
2348
2007
|
return constraintDate < successorStart ? new Date(constraintDate) : successorStart;
|
|
2349
2008
|
default:
|
|
2350
2009
|
return successorStart;
|
|
@@ -2473,7 +2132,7 @@ async function asapPass(orderedIds, links, adapter, options, isCurrent, plans) {
|
|
|
2473
2132
|
});
|
|
2474
2133
|
plan.earliestSchedulingStart = linkStart;
|
|
2475
2134
|
plan.earliestSchedulingEnd = plan.endDate;
|
|
2476
|
-
} else if (activity.constraintType ===
|
|
2135
|
+
} else if (activity.constraintType === CONSTRAINT_TYPE.MSO) {
|
|
2477
2136
|
if (plan.earliestStart) {
|
|
2478
2137
|
plan.startDate = plan.earliestStart;
|
|
2479
2138
|
plan.endDate = plan.earliestEnd ?? adapter.calculateEndDate({
|
|
@@ -2482,7 +2141,7 @@ async function asapPass(orderedIds, links, adapter, options, isCurrent, plans) {
|
|
|
2482
2141
|
task: activity
|
|
2483
2142
|
});
|
|
2484
2143
|
}
|
|
2485
|
-
} else if (activity.constraintType ===
|
|
2144
|
+
} else if (activity.constraintType === CONSTRAINT_TYPE.MFO) {
|
|
2486
2145
|
if (plan.latestStart) {
|
|
2487
2146
|
plan.startDate = plan.latestStart;
|
|
2488
2147
|
plan.endDate = plan.latestEnd ?? adapter.calculateEndDate({
|
|
@@ -2508,7 +2167,7 @@ async function alapPass(reversedIds, links, asapPlans, adapter, _options, isCurr
|
|
|
2508
2167
|
const activityCount = allActivities.length;
|
|
2509
2168
|
const alapActivityIds = [];
|
|
2510
2169
|
for (const activity of allActivities) {
|
|
2511
|
-
if (activity.constraintType ===
|
|
2170
|
+
if (activity.constraintType === CONSTRAINT_TYPE.ALAP) {
|
|
2512
2171
|
alapActivityIds.push(activity.id);
|
|
2513
2172
|
}
|
|
2514
2173
|
}
|
|
@@ -2555,7 +2214,7 @@ async function alapPass(reversedIds, links, asapPlans, adapter, _options, isCurr
|
|
|
2555
2214
|
sliceStart = yieldResult.newSliceStart;
|
|
2556
2215
|
const activity = adapter.getActivity(activityId);
|
|
2557
2216
|
if (!activity) continue;
|
|
2558
|
-
if (activity.constraintType !==
|
|
2217
|
+
if (activity.constraintType !== CONSTRAINT_TYPE.ALAP) continue;
|
|
2559
2218
|
if (!activity.autoScheduling) continue;
|
|
2560
2219
|
if (activity.progress === COMPLETED_PROGRESS) continue;
|
|
2561
2220
|
if (isSummary(activity.type, adapter.getChildren(activityId).length > 0))
|
|
@@ -3064,9 +2723,7 @@ function applyLinkCreates(links, deps) {
|
|
|
3064
2723
|
break;
|
|
3065
2724
|
}
|
|
3066
2725
|
duplicateKeys.set(key, linkId);
|
|
3067
|
-
if (existingGraphHasCycle &&
|
|
3068
|
-
// SCC reachability only if corrupt cyclic schedules become measurable.
|
|
3069
|
-
wouldIntroduceCycle(edges, {
|
|
2726
|
+
if (existingGraphHasCycle && wouldIntroduceCycle(edges, {
|
|
3070
2727
|
source: operation.source,
|
|
3071
2728
|
target: operation.target
|
|
3072
2729
|
})) {
|
|
@@ -3544,7 +3201,7 @@ function widenScopeToAlapActivities(group, allLinks, adapter) {
|
|
|
3544
3201
|
const widenedAlapKeys = /* @__PURE__ */ new Set();
|
|
3545
3202
|
for (const activity of adapter.getAllActivities()) {
|
|
3546
3203
|
const activityKey = String(activity.id);
|
|
3547
|
-
const isOutOfComponentAlap = activity.constraintType ===
|
|
3204
|
+
const isOutOfComponentAlap = activity.constraintType === CONSTRAINT_TYPE.ALAP && !idSet.has(activityKey);
|
|
3548
3205
|
if (!isOutOfComponentAlap) continue;
|
|
3549
3206
|
widenedAlapKeys.add(activityKey);
|
|
3550
3207
|
idSet.add(activityKey);
|
|
@@ -3630,6 +3287,84 @@ function roundProgressPerLevel(value) {
|
|
|
3630
3287
|
return Number(value.toFixed(2));
|
|
3631
3288
|
}
|
|
3632
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
|
+
|
|
3633
3368
|
// src/columns/real-work/compute.ts
|
|
3634
3369
|
function computeLeafRealWork(workHours, progress) {
|
|
3635
3370
|
return (Number(workHours) || 0) * (Number(progress) || 0) / 100;
|
|
@@ -3745,16 +3480,8 @@ function recomputeParentFromChildren(parentId, adapter, progressMode = "freeze-w
|
|
|
3745
3480
|
adapter.setActivityField(parentId, "startDate", newStart);
|
|
3746
3481
|
adapter.setActivityField(parentId, "endDate", newEnd);
|
|
3747
3482
|
adapter.setActivityField(parentId, "durationHours", durationHours);
|
|
3748
|
-
|
|
3749
|
-
aggregate.weightedChildren
|
|
3750
|
-
);
|
|
3751
|
-
const shouldWriteProgress = progressMode !== "skip" && (progressRollup !== null || progressMode === "zero-when-no-contribution");
|
|
3752
|
-
if (shouldWriteProgress) {
|
|
3753
|
-
adapter.setActivityField(
|
|
3754
|
-
parentId,
|
|
3755
|
-
"progress",
|
|
3756
|
-
roundProgressPerLevel(progressRollup ?? 0)
|
|
3757
|
-
);
|
|
3483
|
+
if (progressMode !== "skip") {
|
|
3484
|
+
applyWeightedProgressRollup(parentId, aggregate.weightedChildren, adapter);
|
|
3758
3485
|
}
|
|
3759
3486
|
if (recomputeRealWork) {
|
|
3760
3487
|
adapter.setActivityField(parentId, "realWorkHours", aggregate.realWorkSum);
|
|
@@ -3777,10 +3504,10 @@ function collectParentIds(adapter) {
|
|
|
3777
3504
|
}
|
|
3778
3505
|
function computeDepths(ids, adapter) {
|
|
3779
3506
|
const depths = /* @__PURE__ */ new Map();
|
|
3780
|
-
for (const id of ids) depths.set(id,
|
|
3507
|
+
for (const id of ids) depths.set(id, depthOf2(id, adapter));
|
|
3781
3508
|
return depths;
|
|
3782
3509
|
}
|
|
3783
|
-
function
|
|
3510
|
+
function depthOf2(id, adapter) {
|
|
3784
3511
|
let depth = 0;
|
|
3785
3512
|
let current = id;
|
|
3786
3513
|
while (current && !isRootParent(current)) {
|
|
@@ -3906,7 +3633,7 @@ var descriptionPipeline = {
|
|
|
3906
3633
|
|
|
3907
3634
|
// src/columns/shared/activity-predicates.ts
|
|
3908
3635
|
function effectiveConstraintType(activity) {
|
|
3909
|
-
return activity.constraintType ??
|
|
3636
|
+
return activity.constraintType ?? CONSTRAINT_TYPE.ASAP;
|
|
3910
3637
|
}
|
|
3911
3638
|
var PROGRESS_COMPLETE = COMPLETED_PROGRESS;
|
|
3912
3639
|
function isCompletedActivity(activity) {
|
|
@@ -4263,6 +3990,7 @@ function buildAncestorRollupCascade(activity, newValue, hierarchy) {
|
|
|
4263
3990
|
const mutations = [];
|
|
4264
3991
|
for (const id of chain) {
|
|
4265
3992
|
const rollup = computeWeightedProgress(id, overlay, hierarchy);
|
|
3993
|
+
if (rollup === null) continue;
|
|
4266
3994
|
overlay.set(id, rollup);
|
|
4267
3995
|
mutations.push({
|
|
4268
3996
|
activityId: id,
|
|
@@ -4276,7 +4004,8 @@ function computeWeightedProgress(parentId, overlay, hierarchy) {
|
|
|
4276
4004
|
progress: overlay.has(child.id) ? overlay.get(child.id) : child.progress,
|
|
4277
4005
|
ponderator: child.ponderator ?? 0
|
|
4278
4006
|
}));
|
|
4279
|
-
|
|
4007
|
+
const rollup = computeWeightedProgressRollup(children);
|
|
4008
|
+
return rollup === null ? null : Number(rollup.toFixed(2));
|
|
4280
4009
|
}
|
|
4281
4010
|
function buildRecursiveTrackingEvents(activity, newValue) {
|
|
4282
4011
|
return [
|
|
@@ -4644,7 +4373,7 @@ function checkIsWorkingDay(newDate, activity, ctx) {
|
|
|
4644
4373
|
return null;
|
|
4645
4374
|
}
|
|
4646
4375
|
function detectEndDateConstraintWarning(activity, newEndDate) {
|
|
4647
|
-
const cannotViolateStartPin = effectiveConstraintType(activity) ===
|
|
4376
|
+
const cannotViolateStartPin = effectiveConstraintType(activity) === CONSTRAINT_TYPE.MSO;
|
|
4648
4377
|
if (cannotViolateStartPin) return void 0;
|
|
4649
4378
|
const projectedDate = pickProjectedDateForConstraint(
|
|
4650
4379
|
effectiveConstraintType(activity),
|
|
@@ -4694,7 +4423,7 @@ function calculateNewDuration(activity, newEndDate, ctx) {
|
|
|
4694
4423
|
|
|
4695
4424
|
// src/columns/constraint-type/constraint-type-pipeline.ts
|
|
4696
4425
|
var VALID_CONSTRAINT_TYPES = new Set(
|
|
4697
|
-
Object.values(
|
|
4426
|
+
Object.values(CONSTRAINT_TYPE)
|
|
4698
4427
|
);
|
|
4699
4428
|
var constraintTypePipeline = {
|
|
4700
4429
|
targetField: "constraintType",
|
|
@@ -5475,6 +5204,12 @@ function runExpectedProgressBase(state, now, defaultBaseCalendarId = null) {
|
|
|
5475
5204
|
return computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId);
|
|
5476
5205
|
}
|
|
5477
5206
|
|
|
5207
|
+
// src/columns/status/constants.ts
|
|
5208
|
+
var DEFAULT_STATUS_CRITERIA = "Baseline";
|
|
5209
|
+
function resolveStatusCriteria(value) {
|
|
5210
|
+
return value === "Actual" ? "Actual" : DEFAULT_STATUS_CRITERIA;
|
|
5211
|
+
}
|
|
5212
|
+
|
|
5478
5213
|
// src/columns/status/compute.ts
|
|
5479
5214
|
var roundToTwoDecimals = (value) => Math.round(value * 100) / 100;
|
|
5480
5215
|
function resolveExpectedForStatus(activity, criteria) {
|
|
@@ -5502,7 +5237,7 @@ function applyStatusPass(state, criteria) {
|
|
|
5502
5237
|
resolveExpectedForStatus(activity, criteria)
|
|
5503
5238
|
);
|
|
5504
5239
|
if (activity.status !== status) {
|
|
5505
|
-
setActivityFieldDynamic(state, id,
|
|
5240
|
+
setActivityFieldDynamic(state, id, COLUMN.STATUS, status);
|
|
5506
5241
|
changed.push(id);
|
|
5507
5242
|
}
|
|
5508
5243
|
});
|
|
@@ -9275,10 +9010,10 @@ var FreeFloat = class {
|
|
|
9275
9010
|
this.durationCache = /* @__PURE__ */ new Map();
|
|
9276
9011
|
}
|
|
9277
9012
|
getFreeFloat() {
|
|
9278
|
-
const
|
|
9013
|
+
const PROGRESS = Number(this.activity.progress);
|
|
9279
9014
|
const CONSTRAINT = this.getConstraintType();
|
|
9280
9015
|
this.calculateFreeFloatOfLink(CONSTRAINT);
|
|
9281
|
-
const activityFreeFloat =
|
|
9016
|
+
const activityFreeFloat = PROGRESS === 100 ? 0 : this.getFreeFloatBaseConstraint(CONSTRAINT);
|
|
9282
9017
|
return {
|
|
9283
9018
|
activityFreeFloat,
|
|
9284
9019
|
linksFreeFloat: this.linksFreeFloatObject
|
|
@@ -9437,11 +9172,11 @@ var FreeFloat = class {
|
|
|
9437
9172
|
};
|
|
9438
9173
|
}
|
|
9439
9174
|
calculateMsoMfo(constraint) {
|
|
9440
|
-
const
|
|
9175
|
+
const CONSTRAINT_DATE = this.activity.constraint_date || /* @__PURE__ */ new Date();
|
|
9441
9176
|
const calculation = this.forwardMap.get(this.activity.id);
|
|
9442
9177
|
const DATE_TO_CALCULATE = constraint === CONSTRAINT_TYPES.MSO ? calculation?.es : calculation?.ef;
|
|
9443
9178
|
const freeSlack = this.calculationWithCalendar(
|
|
9444
|
-
|
|
9179
|
+
CONSTRAINT_DATE,
|
|
9445
9180
|
DATE_TO_CALCULATE
|
|
9446
9181
|
);
|
|
9447
9182
|
return Math.max(0, this.parseHoursToDays(freeSlack));
|
|
@@ -10221,24 +9956,82 @@ function resolveDerivedPasses(action, autoSchedule, options) {
|
|
|
10221
9956
|
|
|
10222
9957
|
// src/dispatch/shared/post-mutation.ts
|
|
10223
9958
|
async function runPostMutation(deps, args) {
|
|
10224
|
-
const
|
|
9959
|
+
const progressInvalidation = resolveProgressInvalidation(deps.adapter);
|
|
9960
|
+
const passes = resolvePasses(args, progressInvalidation);
|
|
10225
9961
|
if (passes.has(DERIVED_PASS.AUTOSCHEDULE)) {
|
|
10226
9962
|
await refreshMutatedParentBounds(deps.adapter, args);
|
|
10227
9963
|
}
|
|
10228
9964
|
const schedule = passes.has(DERIVED_PASS.AUTOSCHEDULE) ? await runAutoschedule(deps, args.autoscheduleFrom) : emptySchedule();
|
|
10229
|
-
await rollUpParentBounds(
|
|
9965
|
+
await rollUpParentBounds(
|
|
9966
|
+
deps.adapter,
|
|
9967
|
+
args,
|
|
9968
|
+
schedule.scheduledIds,
|
|
9969
|
+
passes,
|
|
9970
|
+
progressInvalidation
|
|
9971
|
+
);
|
|
10230
9972
|
await runDerivedRecomputes(deps, passes, args.now);
|
|
10231
9973
|
return schedule;
|
|
10232
9974
|
}
|
|
10233
|
-
function resolvePasses(args) {
|
|
9975
|
+
function resolvePasses(args, progressInvalidation) {
|
|
10234
9976
|
const requested = args.autoscheduleFrom !== null;
|
|
10235
9977
|
const ran = !args.options.skipAutoSchedule && requested;
|
|
10236
9978
|
const passes = new Set(
|
|
10237
9979
|
resolveDerivedPasses(args.action, { ran }, args.options)
|
|
10238
9980
|
);
|
|
10239
|
-
if (args.recomputeParentProgress
|
|
9981
|
+
if (args.recomputeParentProgress || progressInvalidation.affectedParents.size > 0) {
|
|
9982
|
+
passes.add(DERIVED_PASS.PARENT_PROGRESS);
|
|
9983
|
+
}
|
|
10240
9984
|
return passes;
|
|
10241
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
|
+
}
|
|
10242
10035
|
async function runAutoschedule(deps, autoscheduleFrom) {
|
|
10243
10036
|
const options = autoscheduleFrom === "roots" ? {} : { triggerId: autoscheduleFrom };
|
|
10244
10037
|
const result = await deps.scheduler.schedule(options);
|
|
@@ -10266,18 +10059,36 @@ async function refreshMutatedParentBounds(adapter, args) {
|
|
|
10266
10059
|
if (mutated.size === 0) return;
|
|
10267
10060
|
await updateParentBoundsFromChildren(adapter, mutated, false);
|
|
10268
10061
|
}
|
|
10269
|
-
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
|
+
}
|
|
10270
10069
|
const dirty = args.collectDirty ? args.collectDirty(scheduledIds) : collectDirtyForStructural(args.recomputeParentsFrom, scheduledIds);
|
|
10070
|
+
for (const activityId of progressInvalidation.dirtySeeds) {
|
|
10071
|
+
dirty.add(activityId);
|
|
10072
|
+
}
|
|
10271
10073
|
await updateParentBoundsFromChildren(
|
|
10272
10074
|
adapter,
|
|
10273
10075
|
dirty,
|
|
10274
10076
|
passes.has(DERIVED_PASS.PARENT_PROGRESS),
|
|
10275
10077
|
{
|
|
10276
10078
|
recomputeRealWork: passes.has(DERIVED_PASS.REAL_WORK),
|
|
10277
|
-
progressMode:
|
|
10079
|
+
progressMode: "freeze-when-no-contribution"
|
|
10278
10080
|
}
|
|
10279
10081
|
);
|
|
10280
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
|
+
}
|
|
10281
10092
|
async function runDerivedRecomputes(deps, passes, now) {
|
|
10282
10093
|
if (passes.has(DERIVED_PASS.EXPECTED_PROGRESS) && now !== null) {
|
|
10283
10094
|
if (hasActiveBaseline(deps.adapter)) {
|
|
@@ -11504,9 +11315,8 @@ function buildParentMutations(input) {
|
|
|
11504
11315
|
if (wasPromotableLeaf) {
|
|
11505
11316
|
fields.type = PROMOTION_TARGET_TYPE;
|
|
11506
11317
|
if ((input.promotionSource ?? "create") === "create") {
|
|
11507
|
-
fields.constraintType =
|
|
11318
|
+
fields.constraintType = CONSTRAINT_TYPE.ASAP;
|
|
11508
11319
|
fields.constraintDate = null;
|
|
11509
|
-
fields.progress = 0;
|
|
11510
11320
|
}
|
|
11511
11321
|
}
|
|
11512
11322
|
return {
|
|
@@ -12645,8 +12455,6 @@ function dispatchSirSync(action, deps) {
|
|
|
12645
12455
|
id,
|
|
12646
12456
|
kind: "updated",
|
|
12647
12457
|
fields: { pendingRequestIds: { before, after } },
|
|
12648
|
-
// ISSUE-025: `after` must be the COMPLETE post-change entity; a partial
|
|
12649
|
-
// object crashes any consumer that projects the full snapshot.
|
|
12650
12458
|
after: structuredCloneActivity(updated)
|
|
12651
12459
|
};
|
|
12652
12460
|
return {
|
|
@@ -12661,60 +12469,6 @@ function dispatchSirSync(action, deps) {
|
|
|
12661
12469
|
};
|
|
12662
12470
|
}
|
|
12663
12471
|
|
|
12664
|
-
// src/propagations/upward/progress-rollup.ts
|
|
12665
|
-
function recomputeAllProgressRollup(adapter) {
|
|
12666
|
-
for (const parentId of parentsDeepestFirst(adapter)) {
|
|
12667
|
-
rollupParent(parentId, adapter);
|
|
12668
|
-
}
|
|
12669
|
-
}
|
|
12670
|
-
function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
|
|
12671
|
-
for (const parentId of parentIdsDeepestFirst) {
|
|
12672
|
-
rollupParent(parentId, adapter);
|
|
12673
|
-
}
|
|
12674
|
-
}
|
|
12675
|
-
function parentsDeepestFirst(adapter) {
|
|
12676
|
-
const parents = /* @__PURE__ */ new Set();
|
|
12677
|
-
adapter.forEachActivity((_activity, id) => {
|
|
12678
|
-
if (adapter.getChildren(id).length > 0) parents.add(id);
|
|
12679
|
-
});
|
|
12680
|
-
const depthById = /* @__PURE__ */ new Map();
|
|
12681
|
-
for (const id of parents) depthById.set(id, depthOf2(id, adapter));
|
|
12682
|
-
return [...parents].sort(
|
|
12683
|
-
(a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
|
|
12684
|
-
);
|
|
12685
|
-
}
|
|
12686
|
-
function depthOf2(id, adapter) {
|
|
12687
|
-
let depth = 0;
|
|
12688
|
-
let current = id;
|
|
12689
|
-
while (current && current !== "0") {
|
|
12690
|
-
if (!adapter.getActivity(current)) break;
|
|
12691
|
-
depth += 1;
|
|
12692
|
-
current = adapter.getParentId(current);
|
|
12693
|
-
}
|
|
12694
|
-
return depth;
|
|
12695
|
-
}
|
|
12696
|
-
function rollupParent(parentId, adapter) {
|
|
12697
|
-
const childIds = adapter.getChildren(parentId);
|
|
12698
|
-
if (childIds.length === 0) return;
|
|
12699
|
-
const children = [];
|
|
12700
|
-
for (const childId of childIds) {
|
|
12701
|
-
const child = adapter.getActivity(childId);
|
|
12702
|
-
if (!child) continue;
|
|
12703
|
-
children.push({
|
|
12704
|
-
progress: Number(child.progress ?? 0),
|
|
12705
|
-
ponderator: Number(child.ponderator ?? 0)
|
|
12706
|
-
});
|
|
12707
|
-
}
|
|
12708
|
-
const rollup = computeWeightedProgressRollup(children);
|
|
12709
|
-
if (rollup !== null) {
|
|
12710
|
-
adapter.setActivityField(
|
|
12711
|
-
parentId,
|
|
12712
|
-
COLUMN.PROGRESS,
|
|
12713
|
-
roundProgressPerLevel(rollup)
|
|
12714
|
-
);
|
|
12715
|
-
}
|
|
12716
|
-
}
|
|
12717
|
-
|
|
12718
12472
|
// src/dispatch/handlers/persistence-acknowledge.ts
|
|
12719
12473
|
function persistedOwnersOf(entities) {
|
|
12720
12474
|
const owners = /* @__PURE__ */ new Map();
|
|
@@ -13781,6 +13535,11 @@ async function dispatchActivitySetProgress(action, options, deps) {
|
|
|
13781
13535
|
const touchedIds = collectTouchedIds(action.activityId, changes);
|
|
13782
13536
|
const beforeSnap = await snapshotActivities(adapter, touchedIds);
|
|
13783
13537
|
applyFieldChanges(adapter, action.activityId, changes);
|
|
13538
|
+
setExplicitSummaryProgressFallbacks(
|
|
13539
|
+
action.activityId,
|
|
13540
|
+
action.newValue,
|
|
13541
|
+
adapter
|
|
13542
|
+
);
|
|
13784
13543
|
runPostProcessorsOnAdapter(
|
|
13785
13544
|
action.activityId,
|
|
13786
13545
|
changes.postProcessors ?? [],
|
|
@@ -17644,7 +17403,8 @@ var WriteCapture = class {
|
|
|
17644
17403
|
ops: [],
|
|
17645
17404
|
linkFieldCaptured: /* @__PURE__ */ new Set(),
|
|
17646
17405
|
correlativeBefore: /* @__PURE__ */ new Map(),
|
|
17647
|
-
scheduledBefore: /* @__PURE__ */ new Map()
|
|
17406
|
+
scheduledBefore: /* @__PURE__ */ new Map(),
|
|
17407
|
+
progressFallbackBefore: /* @__PURE__ */ new Map()
|
|
17648
17408
|
};
|
|
17649
17409
|
}
|
|
17650
17410
|
peek() {
|
|
@@ -17707,6 +17467,11 @@ var WriteCapture = class {
|
|
|
17707
17467
|
before: cloneLink(current)
|
|
17708
17468
|
});
|
|
17709
17469
|
}
|
|
17470
|
+
noteProgressFallback(activityId, current) {
|
|
17471
|
+
const journal = this._journal;
|
|
17472
|
+
if (!journal || journal.progressFallbackBefore.has(activityId)) return;
|
|
17473
|
+
journal.progressFallbackBefore.set(activityId, current);
|
|
17474
|
+
}
|
|
17710
17475
|
};
|
|
17711
17476
|
function cloneLink(link) {
|
|
17712
17477
|
return { ...link };
|
|
@@ -17876,11 +17641,83 @@ var HierarchyIndex = class {
|
|
|
17876
17641
|
}
|
|
17877
17642
|
};
|
|
17878
17643
|
|
|
17644
|
+
// src/internal/state/view-state.ts
|
|
17645
|
+
var ViewStateStore = class {
|
|
17646
|
+
checkedSet = /* @__PURE__ */ new Set();
|
|
17647
|
+
hiddenSet = /* @__PURE__ */ new Set();
|
|
17648
|
+
activeFilter = null;
|
|
17649
|
+
activeOrder = null;
|
|
17650
|
+
isChecked(activityId) {
|
|
17651
|
+
return this.checkedSet.has(activityId);
|
|
17652
|
+
}
|
|
17653
|
+
isVisible(activityId) {
|
|
17654
|
+
return !this.hiddenSet.has(activityId);
|
|
17655
|
+
}
|
|
17656
|
+
hiddenIds() {
|
|
17657
|
+
return [...this.hiddenSet];
|
|
17658
|
+
}
|
|
17659
|
+
getActiveFilter() {
|
|
17660
|
+
return this.activeFilter;
|
|
17661
|
+
}
|
|
17662
|
+
setActiveFilter(nextFilter) {
|
|
17663
|
+
this.activeFilter = nextFilter;
|
|
17664
|
+
}
|
|
17665
|
+
getActiveOrder() {
|
|
17666
|
+
return this.activeOrder;
|
|
17667
|
+
}
|
|
17668
|
+
setActiveOrder(nextOrder) {
|
|
17669
|
+
this.activeOrder = nextOrder;
|
|
17670
|
+
}
|
|
17671
|
+
checkedIds() {
|
|
17672
|
+
return [...this.checkedSet];
|
|
17673
|
+
}
|
|
17674
|
+
checkedCount() {
|
|
17675
|
+
return this.checkedSet.size;
|
|
17676
|
+
}
|
|
17677
|
+
setChecked(activityId, nextChecked) {
|
|
17678
|
+
if (nextChecked === this.checkedSet.has(activityId)) return false;
|
|
17679
|
+
if (nextChecked) this.checkedSet.add(activityId);
|
|
17680
|
+
else this.checkedSet.delete(activityId);
|
|
17681
|
+
return true;
|
|
17682
|
+
}
|
|
17683
|
+
setVisible(activityId, nextVisible) {
|
|
17684
|
+
if (nextVisible === !this.hiddenSet.has(activityId)) return false;
|
|
17685
|
+
if (nextVisible) this.hiddenSet.delete(activityId);
|
|
17686
|
+
else this.hiddenSet.add(activityId);
|
|
17687
|
+
return true;
|
|
17688
|
+
}
|
|
17689
|
+
forget(activityId) {
|
|
17690
|
+
this.checkedSet.delete(activityId);
|
|
17691
|
+
this.hiddenSet.delete(activityId);
|
|
17692
|
+
}
|
|
17693
|
+
hydrate(seed2) {
|
|
17694
|
+
this.checkedSet = new Set(seed2.checkedIds ?? []);
|
|
17695
|
+
this.hiddenSet = new Set(seed2.hiddenIds ?? []);
|
|
17696
|
+
this.activeFilter = null;
|
|
17697
|
+
this.activeOrder = null;
|
|
17698
|
+
}
|
|
17699
|
+
snapshot() {
|
|
17700
|
+
return {
|
|
17701
|
+
checked: new Set(this.checkedSet),
|
|
17702
|
+
hidden: new Set(this.hiddenSet),
|
|
17703
|
+
activeFilter: this.activeFilter,
|
|
17704
|
+
activeOrder: this.activeOrder
|
|
17705
|
+
};
|
|
17706
|
+
}
|
|
17707
|
+
restore(snapshot) {
|
|
17708
|
+
this.checkedSet = new Set(snapshot.checked);
|
|
17709
|
+
this.hiddenSet = new Set(snapshot.hidden);
|
|
17710
|
+
this.activeFilter = snapshot.activeFilter;
|
|
17711
|
+
this.activeOrder = snapshot.activeOrder;
|
|
17712
|
+
}
|
|
17713
|
+
};
|
|
17714
|
+
|
|
17879
17715
|
// src/internal/state/schedule-state.ts
|
|
17880
17716
|
var ScheduleState = class _ScheduleState {
|
|
17881
17717
|
_activities = /* @__PURE__ */ new Map();
|
|
17882
17718
|
_lastStartDate = /* @__PURE__ */ new Map();
|
|
17883
17719
|
_promotionSnapshot = /* @__PURE__ */ new Map();
|
|
17720
|
+
_progressFallback = /* @__PURE__ */ new Map();
|
|
17884
17721
|
_links = /* @__PURE__ */ new Map();
|
|
17885
17722
|
_outgoing = /* @__PURE__ */ new Map();
|
|
17886
17723
|
_incoming = /* @__PURE__ */ new Map();
|
|
@@ -17941,6 +17778,7 @@ var ScheduleState = class _ScheduleState {
|
|
|
17941
17778
|
cloneDomainValue(snapshot)
|
|
17942
17779
|
])
|
|
17943
17780
|
);
|
|
17781
|
+
fork._progressFallback = new Map(this._progressFallback);
|
|
17944
17782
|
fork._flags = cloneDomainValue(this._flags);
|
|
17945
17783
|
fork._filterProjection = cloneDomainValue(this._filterProjection);
|
|
17946
17784
|
return fork;
|
|
@@ -17994,6 +17832,17 @@ var ScheduleState = class _ScheduleState {
|
|
|
17994
17832
|
this._capturePromotionSnapshotOnce();
|
|
17995
17833
|
this._promotionSnapshot.set(String(activityId), snapshot);
|
|
17996
17834
|
}
|
|
17835
|
+
getProgressFallback(activityId) {
|
|
17836
|
+
return this._progressFallback.get(String(activityId)) ?? null;
|
|
17837
|
+
}
|
|
17838
|
+
setProgressFallback(activityId, value) {
|
|
17839
|
+
const key = String(activityId);
|
|
17840
|
+
const current = this._progressFallback.get(key) ?? null;
|
|
17841
|
+
if (Object.is(current, value)) return;
|
|
17842
|
+
this._writeCapture.noteProgressFallback(key, current);
|
|
17843
|
+
if (value === null) this._progressFallback.delete(key);
|
|
17844
|
+
else this._progressFallback.set(key, value);
|
|
17845
|
+
}
|
|
17997
17846
|
_capturePromotionSnapshotOnce() {
|
|
17998
17847
|
if (this._writeCapture.peek() === null) return;
|
|
17999
17848
|
if (this._promotionSnapshotBefore === null) {
|
|
@@ -18054,28 +17903,6 @@ var ScheduleState = class _ScheduleState {
|
|
|
18054
17903
|
this._viewState.setActiveOrder(nextOrder);
|
|
18055
17904
|
this.invalidateDerivedOrder();
|
|
18056
17905
|
}
|
|
18057
|
-
setRelativePlacementPin(activityId, pin) {
|
|
18058
|
-
this._viewState.setRelativePlacementPin(String(activityId), pin);
|
|
18059
|
-
this.invalidateVisualOrderIds();
|
|
18060
|
-
}
|
|
18061
|
-
getRelativePlacementPins() {
|
|
18062
|
-
return this._viewState.getRelativePlacementPins();
|
|
18063
|
-
}
|
|
18064
|
-
restoreRelativePlacementPins(pins) {
|
|
18065
|
-
this._viewState.restoreRelativePlacementPins(pins);
|
|
18066
|
-
this._filterProjection = null;
|
|
18067
|
-
this.invalidateVisualOrderIds();
|
|
18068
|
-
}
|
|
18069
|
-
/**
|
|
18070
|
-
* Rebuild-on-demand, memoized: at most one build per invalidation, never one
|
|
18071
|
-
* per comparison. getChildrenInVisualOrder asks for this once and then sorts a
|
|
18072
|
-
* whole sibling group with it, and collectBranchOrder walks every branch, so a
|
|
18073
|
-
* build per read would be thousands per dispatch.
|
|
18074
|
-
*
|
|
18075
|
-
* The factory reads hoursPerDay and the collation locale at build time, so a
|
|
18076
|
-
* rebuilt comparator always reflects the current context — that is what keeps
|
|
18077
|
-
* ordering and filtering from seeing two different hoursPerDay.
|
|
18078
|
-
*/
|
|
18079
17906
|
getOrderComparator() {
|
|
18080
17907
|
const activeOrder = this._viewState.getActiveOrder();
|
|
18081
17908
|
if (activeOrder === null) {
|
|
@@ -18086,12 +17913,6 @@ var ScheduleState = class _ScheduleState {
|
|
|
18086
17913
|
this._cache.orderComparator = this._buildOrderComparator(activeOrder);
|
|
18087
17914
|
return this._cache.orderComparator;
|
|
18088
17915
|
}
|
|
18089
|
-
/**
|
|
18090
|
-
* Both order caches, always together. The comparator decides the sequence, so
|
|
18091
|
-
* a rebuilt comparator with a surviving sequence would paint the old order.
|
|
18092
|
-
* invalidateVisualOrderIds stays separate on purpose: a structural change
|
|
18093
|
-
* moves rows without touching the rules, so the comparator is still valid.
|
|
18094
|
-
*/
|
|
18095
17916
|
invalidateDerivedOrder() {
|
|
18096
17917
|
this._cache.orderComparator = null;
|
|
18097
17918
|
this._cache.visualOrderIds = null;
|
|
@@ -18272,11 +18093,8 @@ var ScheduleState = class _ScheduleState {
|
|
|
18272
18093
|
const activity = this.getActivity(activityId);
|
|
18273
18094
|
if (activity) this._writeCapture.noteRemove(String(activityId), activity);
|
|
18274
18095
|
const key = String(activityId);
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
({ referenceId }) => referenceId === key
|
|
18278
|
-
);
|
|
18279
|
-
if (this._viewState.isChecked(key) || !this._viewState.isVisible(key) || relativePlacementPins.has(key) || hasDependentPin) {
|
|
18096
|
+
this.setProgressFallback(key, null);
|
|
18097
|
+
if (this._viewState.isChecked(key) || !this._viewState.isVisible(key)) {
|
|
18280
18098
|
this._captureViewStateOnce();
|
|
18281
18099
|
}
|
|
18282
18100
|
this._viewState.forget(key);
|
|
@@ -18300,7 +18118,13 @@ var ScheduleState = class _ScheduleState {
|
|
|
18300
18118
|
restoreFromCapture() {
|
|
18301
18119
|
const journal = this._writeCapture.peek();
|
|
18302
18120
|
if (!journal) return;
|
|
18303
|
-
const {
|
|
18121
|
+
const {
|
|
18122
|
+
ops,
|
|
18123
|
+
before,
|
|
18124
|
+
correlativeBefore,
|
|
18125
|
+
scheduledBefore,
|
|
18126
|
+
progressFallbackBefore
|
|
18127
|
+
} = journal;
|
|
18304
18128
|
this._undoLinkAdds(ops);
|
|
18305
18129
|
this._undoInserts(ops);
|
|
18306
18130
|
this._reInsertRemovedActivities(ops);
|
|
@@ -18309,6 +18133,7 @@ var ScheduleState = class _ScheduleState {
|
|
|
18309
18133
|
this._restoreCorrelatives(correlativeBefore);
|
|
18310
18134
|
this._restoreActivityFields(scheduledBefore);
|
|
18311
18135
|
this._restoreActivityFields(before);
|
|
18136
|
+
this._restoreProgressFallbacks(progressFallbackBefore);
|
|
18312
18137
|
if (this._viewStateBefore !== null) {
|
|
18313
18138
|
this._viewState.restore(this._viewStateBefore);
|
|
18314
18139
|
this._filterProjection = null;
|
|
@@ -18324,6 +18149,12 @@ var ScheduleState = class _ScheduleState {
|
|
|
18324
18149
|
this._cache.visualOrderIds = null;
|
|
18325
18150
|
this._hierarchy.markDirty();
|
|
18326
18151
|
}
|
|
18152
|
+
_restoreProgressFallbacks(before) {
|
|
18153
|
+
for (const [activityId, value] of before) {
|
|
18154
|
+
if (value === null) this._progressFallback.delete(activityId);
|
|
18155
|
+
else this._progressFallback.set(activityId, value);
|
|
18156
|
+
}
|
|
18157
|
+
}
|
|
18327
18158
|
_restoreCorrelatives(correlativeBefore) {
|
|
18328
18159
|
for (const [id, before] of correlativeBefore) {
|
|
18329
18160
|
const live = this._activities.get(id);
|
|
@@ -18537,15 +18368,15 @@ function buildHistoryChangeSet(changes) {
|
|
|
18537
18368
|
links: linksWithoutAfter
|
|
18538
18369
|
});
|
|
18539
18370
|
}
|
|
18540
|
-
function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks,
|
|
18371
|
+
function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks, progressFallbackBefore, progressFallbackAfter) {
|
|
18541
18372
|
return {
|
|
18542
18373
|
changeSet,
|
|
18543
18374
|
beforeSnap,
|
|
18544
18375
|
beforeLinks: resetDerivedLinkSnapshots(beforeLinks),
|
|
18545
18376
|
afterSnap,
|
|
18546
18377
|
afterLinks: resetDerivedLinkSnapshots(afterLinks),
|
|
18547
|
-
|
|
18548
|
-
|
|
18378
|
+
progressFallbackBefore,
|
|
18379
|
+
progressFallbackAfter
|
|
18549
18380
|
};
|
|
18550
18381
|
}
|
|
18551
18382
|
function resetDerivedLinkSnapshots(snapshots) {
|
|
@@ -18848,8 +18679,10 @@ function applyChangeSetSide(state, entry, side) {
|
|
|
18848
18679
|
);
|
|
18849
18680
|
}
|
|
18850
18681
|
}
|
|
18851
|
-
const
|
|
18852
|
-
|
|
18682
|
+
const progressFallbacks = side === "before" ? entry.progressFallbackBefore : entry.progressFallbackAfter;
|
|
18683
|
+
for (const [activityId, value] of progressFallbacks ?? []) {
|
|
18684
|
+
state.setProgressFallback(activityId, value);
|
|
18685
|
+
}
|
|
18853
18686
|
}
|
|
18854
18687
|
|
|
18855
18688
|
// src/dispatch/undo/undo-recorder.ts
|
|
@@ -20741,6 +20574,7 @@ async function runInitialPasses(deps) {
|
|
|
20741
20574
|
normalizeLoadedConstraintDates(state);
|
|
20742
20575
|
recomputeCanonicalRealWork(state);
|
|
20743
20576
|
if (skipAutoSchedule) {
|
|
20577
|
+
recomputeAllProgressRollup(state);
|
|
20744
20578
|
if (now) {
|
|
20745
20579
|
applyExpectedProgressLive(state, now);
|
|
20746
20580
|
applyStatusPass(state, sector.statusCriteria);
|
|
@@ -20752,6 +20586,7 @@ async function runInitialPasses(deps) {
|
|
|
20752
20586
|
normalizeMilestoneConstraintDatesForDisplay(state);
|
|
20753
20587
|
recomputeSkippedLeafEnds(state);
|
|
20754
20588
|
await updateParentBoundsFromChildren(state, void 0, false);
|
|
20589
|
+
recomputeAllProgressRollup(state);
|
|
20755
20590
|
if (now) {
|
|
20756
20591
|
applyExpectedProgressLive(state, now);
|
|
20757
20592
|
applyStatusPass(state, sector.statusCriteria);
|
|
@@ -21194,41 +21029,12 @@ function collectChangedActivities(changes, adapter) {
|
|
|
21194
21029
|
}
|
|
21195
21030
|
return activities;
|
|
21196
21031
|
}
|
|
21197
|
-
function changesAffectRelativePinProjection(changes, changedActivities, adapter, pins) {
|
|
21198
|
-
if (pins.size === 0) return false;
|
|
21199
|
-
if (changes.activities.some(
|
|
21200
|
-
(change) => change.kind === "created" && pins.has(String(change.id))
|
|
21201
|
-
)) {
|
|
21202
|
-
return true;
|
|
21203
|
-
}
|
|
21204
|
-
const referenceIds = new Set(
|
|
21205
|
-
[...pins.values()].map(({ referenceId }) => String(referenceId))
|
|
21206
|
-
);
|
|
21207
|
-
for (const activity of changedActivities) {
|
|
21208
|
-
let activityId = String(activity.id);
|
|
21209
|
-
while (activityId !== null) {
|
|
21210
|
-
if (referenceIds.has(activityId)) return true;
|
|
21211
|
-
activityId = adapter.getParentId(activityId);
|
|
21212
|
-
}
|
|
21213
|
-
}
|
|
21214
|
-
return false;
|
|
21215
|
-
}
|
|
21216
21032
|
function isCurrentFilterProjection(projection, filter, context) {
|
|
21217
21033
|
if (projection === null || projection.filter !== filter) return false;
|
|
21218
21034
|
const hasCurrentHours = projection.context.hoursPerDay === context.hoursPerDay;
|
|
21219
21035
|
const hasCurrentLocale = projection.context.locale === context.locale;
|
|
21220
21036
|
return hasCurrentHours && hasCurrentLocale;
|
|
21221
21037
|
}
|
|
21222
|
-
function relativePlacementPinsEqual(left, right) {
|
|
21223
|
-
if (left.size !== right.size) return false;
|
|
21224
|
-
for (const [activityId, pin] of left) {
|
|
21225
|
-
const other = right.get(activityId);
|
|
21226
|
-
if (other === void 0 || other.referenceId !== pin.referenceId || other.branchParentId !== pin.branchParentId || other.side !== pin.side) {
|
|
21227
|
-
return false;
|
|
21228
|
-
}
|
|
21229
|
-
}
|
|
21230
|
-
return true;
|
|
21231
|
-
}
|
|
21232
21038
|
var ScheduleCore = class _ScheduleCore {
|
|
21233
21039
|
_activityClipboard = { value: null };
|
|
21234
21040
|
_status = SCHEDULE_CORE_STATUS.READY;
|
|
@@ -21237,29 +21043,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21237
21043
|
_undo = new UndoRecorder();
|
|
21238
21044
|
_opQueue = Promise.resolve();
|
|
21239
21045
|
_scheduleRevision = 0;
|
|
21240
|
-
/**
|
|
21241
|
-
* Revision counting mutations that have been ADMITTED, whether or not they
|
|
21242
|
-
* have changed anything yet. `_scheduleRevision` counts the ones that
|
|
21243
|
-
* actually did.
|
|
21244
|
-
*
|
|
21245
|
-
* INVARIANT: `_pendingScheduleRevision >= _scheduleRevision`, and equality
|
|
21246
|
-
* means no mutation is in flight.
|
|
21247
|
-
*
|
|
21248
|
-
* The two exist separately because the useful instant and the knowable
|
|
21249
|
-
* instant are not the same one. A critical-path calculation becomes garbage
|
|
21250
|
-
* the moment the next mutation is admitted, but whether that mutation is
|
|
21251
|
-
* substantive is only knowable once its ChangeSet exists, which is hundreds
|
|
21252
|
-
* of milliseconds later at project scale. Measured live on a 12268-activity
|
|
21253
|
-
* project: the cancellation flag flipped 929 ms into a 930 ms calculation,
|
|
21254
|
-
* 812 into 812 and 785 into 785, because the job's apply block queues behind
|
|
21255
|
-
* the very dispatch whose completion cancels it. Cancellation and job end
|
|
21256
|
-
* were the same event, so every discarded job ran the whole calculation.
|
|
21257
|
-
*
|
|
21258
|
-
* Splitting the counter buys the early signal without moving the meaning of
|
|
21259
|
-
* `_scheduleRevision`, whose three readers (`isCriticalPathSettled`,
|
|
21260
|
-
* `createDateGesturePreview` and the job's own `isCurrent`) are all written
|
|
21261
|
-
* against "the state actually changed".
|
|
21262
|
-
*/
|
|
21263
21046
|
_pendingScheduleRevision = 0;
|
|
21264
21047
|
_criticalPathRevision = -1;
|
|
21265
21048
|
_activeCriticalPath = null;
|
|
@@ -21372,13 +21155,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21372
21155
|
this.assertReady();
|
|
21373
21156
|
return readAllActivities(this.coreRuntime.state);
|
|
21374
21157
|
}
|
|
21375
|
-
/**
|
|
21376
|
-
* Read del plan de indent (ISSUE-080): los padres destino DISTINTOS bajo los
|
|
21377
|
-
* que quedarían las actividades si se indentaran ahora. Es exactamente la
|
|
21378
|
-
* planificación que ejecuta el handler (`planIndentMoves`, autoridad única),
|
|
21379
|
-
* expuesta para que la frontera pueda correr el protocolo de conversión a
|
|
21380
|
-
* madre (chequeo backend + modal) ANTES de despachar. Solo lecturas.
|
|
21381
|
-
*/
|
|
21382
21158
|
getIndentTargetParentIds(activityIds) {
|
|
21383
21159
|
this.assertReady();
|
|
21384
21160
|
const plan = planIndentMoves(
|
|
@@ -21531,7 +21307,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21531
21307
|
this.assertReady();
|
|
21532
21308
|
return this._saveTracker.hasUnsavedChanges();
|
|
21533
21309
|
}
|
|
21534
|
-
/** Read-only revision; moves once per substantive mutation. */
|
|
21535
21310
|
getScheduleRevision() {
|
|
21536
21311
|
return this._scheduleRevision;
|
|
21537
21312
|
}
|
|
@@ -21577,24 +21352,10 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21577
21352
|
);
|
|
21578
21353
|
return workPromise;
|
|
21579
21354
|
}
|
|
21580
|
-
/**
|
|
21581
|
-
* Marks a mutation as admitted and invalidates the calculation in flight.
|
|
21582
|
-
*
|
|
21583
|
-
* Called BEFORE `_enqueue`, which is the point of the whole thing: the wait
|
|
21584
|
-
* in the operation queue is part of the window a running calculation wastes,
|
|
21585
|
-
* and it is the longest part of it when several mutations are already
|
|
21586
|
-
* queued.
|
|
21587
|
-
*
|
|
21588
|
-
* `dispatchChangesSchedulingState` is a pure function of the action, so this
|
|
21589
|
-
* decision needs no state and cannot be wrong about the action's nature. What
|
|
21590
|
-
* it cannot know yet is whether the mutation will produce anything, which is
|
|
21591
|
-
* what `_settleScheduleMutation` reconciles afterwards.
|
|
21592
|
-
*/
|
|
21593
21355
|
_beginScheduleMutation(action) {
|
|
21594
21356
|
if (!dispatchChangesSchedulingState(action)) return false;
|
|
21595
21357
|
return this._admitScheduleMutation();
|
|
21596
21358
|
}
|
|
21597
|
-
/** Undo and redo have no action to classify: reaching them IS the mutation. */
|
|
21598
21359
|
_admitScheduleMutation() {
|
|
21599
21360
|
this._pendingScheduleRevision++;
|
|
21600
21361
|
if (this._activeCriticalPath) {
|
|
@@ -21602,30 +21363,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21602
21363
|
}
|
|
21603
21364
|
return true;
|
|
21604
21365
|
}
|
|
21605
|
-
/**
|
|
21606
|
-
* Closes a mutation admitted by `_beginScheduleMutation`, on EVERY exit path.
|
|
21607
|
-
*
|
|
21608
|
-
* `changedState` false means the mutation was admitted and produced nothing
|
|
21609
|
-
* (rejected, non-substantive, or rolled back). The pending revision walks
|
|
21610
|
-
* back so the invariant holds and `isCriticalPathSettled` keeps telling the
|
|
21611
|
-
* truth, and the calculation this mutation killed for nothing is re-armed.
|
|
21612
|
-
*
|
|
21613
|
-
* The re-arm goes through the queue and that is not incidental. Started
|
|
21614
|
-
* outside it, the calculation would run immediately while the next queued
|
|
21615
|
-
* mutation is still waiting, and that mutation would kill it again on
|
|
21616
|
-
* admission: a cancel-and-restart treadmill burning a fresh project-wide deep
|
|
21617
|
-
* copy per lap. Inside the queue the restart cannot happen until the queue
|
|
21618
|
-
* drains, so at most one calculation is armed per settled mutation. The burst
|
|
21619
|
-
* scenario will NOT catch a regression here, because there every dispatch
|
|
21620
|
-
* succeeds and this path is never taken.
|
|
21621
|
-
*
|
|
21622
|
-
* It re-arms through `recomputeCriticalPath` rather than enqueueing the job
|
|
21623
|
-
* directly, because the queue slot must NOT await the job: the job's own
|
|
21624
|
-
* apply block needs a later slot on this same queue, so awaiting it from
|
|
21625
|
-
* inside a slot deadlocks the core. `recomputeCriticalPath` already has the
|
|
21626
|
-
* shape that returns the job's promise out of the slot instead of awaiting
|
|
21627
|
-
* it, and it keeps `_criticalPathReady` pointing at the live calculation.
|
|
21628
|
-
*/
|
|
21629
21366
|
_settleScheduleMutation(admitted, changedState) {
|
|
21630
21367
|
if (!admitted) return;
|
|
21631
21368
|
if (changedState) return;
|
|
@@ -21676,8 +21413,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21676
21413
|
dateFormat: this.coreRuntime.sector.dateFormat
|
|
21677
21414
|
});
|
|
21678
21415
|
const historyPolicy = getDispatchHistoryPolicy(action);
|
|
21679
|
-
const capturesRelativePlacementPins = action.kind === "activity-create" || action.kind === "activity-delete" || action.kind === "activity-batch" && action.mode === "replace";
|
|
21680
|
-
const relativePlacementPinsBefore = capturesRelativePlacementPins ? new Map(this.coreRuntime.state.getRelativePlacementPins()) : void 0;
|
|
21681
21416
|
const generatorSnapshot = [
|
|
21682
21417
|
this.coreRuntime.activityIdGenerator.snapshot(),
|
|
21683
21418
|
this.coreRuntime.linkIdGenerator.snapshot(),
|
|
@@ -21686,6 +21421,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21686
21421
|
this.coreRuntime.state.beginWriteCapture();
|
|
21687
21422
|
this.coreRuntime.customIdTracker.beginCustomIdTransaction();
|
|
21688
21423
|
let result;
|
|
21424
|
+
let progressFallbackBefore;
|
|
21689
21425
|
try {
|
|
21690
21426
|
result = await performDispatch(action, options, {
|
|
21691
21427
|
adapter: this.coreRuntime.state,
|
|
@@ -21706,6 +21442,10 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21706
21442
|
)?.id ?? null,
|
|
21707
21443
|
now: this.coreRuntime.clock ? endOfLocalDay(this.coreRuntime.clock()) : null
|
|
21708
21444
|
});
|
|
21445
|
+
const fallbackBefore = this.coreRuntime.state.peekWriteCapture()?.progressFallbackBefore;
|
|
21446
|
+
if (fallbackBefore && fallbackBefore.size > 0) {
|
|
21447
|
+
progressFallbackBefore = new Map(fallbackBefore);
|
|
21448
|
+
}
|
|
21709
21449
|
if (!result.ok) this._rollback(generatorSnapshot);
|
|
21710
21450
|
} catch (error) {
|
|
21711
21451
|
this._rollback(generatorSnapshot);
|
|
@@ -21714,17 +21454,17 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21714
21454
|
this.coreRuntime.state.endWriteCapture();
|
|
21715
21455
|
this.coreRuntime.customIdTracker.commitCustomIdTransaction();
|
|
21716
21456
|
}
|
|
21717
|
-
if (result.ok) this._recordRelativePlacementPin(action, result.changes);
|
|
21718
21457
|
if (result.ok && historyPolicy === "record" && changeSetIsSubstantive(result.changes)) {
|
|
21719
21458
|
const created = captureCreatedSnapshots(
|
|
21720
21459
|
this.coreRuntime.state,
|
|
21721
21460
|
result.changes
|
|
21722
21461
|
);
|
|
21723
|
-
const
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
|
|
21727
|
-
|
|
21462
|
+
const progressFallbackAfter = progressFallbackBefore ? new Map(
|
|
21463
|
+
Array.from(progressFallbackBefore.keys(), (activityId) => [
|
|
21464
|
+
activityId,
|
|
21465
|
+
this.coreRuntime.state.getProgressFallback(activityId)
|
|
21466
|
+
])
|
|
21467
|
+
) : void 0;
|
|
21728
21468
|
this._undo.record(
|
|
21729
21469
|
buildUndoEntry(
|
|
21730
21470
|
buildHistoryChangeSet(result.changes),
|
|
@@ -21732,8 +21472,8 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21732
21472
|
result.__beforeLinks,
|
|
21733
21473
|
created.afterSnap,
|
|
21734
21474
|
created.afterLinks,
|
|
21735
|
-
|
|
21736
|
-
|
|
21475
|
+
progressFallbackBefore,
|
|
21476
|
+
progressFallbackAfter
|
|
21737
21477
|
),
|
|
21738
21478
|
computeCoalesceKey(action),
|
|
21739
21479
|
Date.now()
|
|
@@ -21781,11 +21521,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21781
21521
|
return operation;
|
|
21782
21522
|
}
|
|
21783
21523
|
isCriticalPathSettled() {
|
|
21784
|
-
return this._criticalPathRevision === this._scheduleRevision &&
|
|
21785
|
-
// about to be stale. Without this term `whenCriticalPathSettled` would
|
|
21786
|
-
// spin: it would keep arming calculations that `isCurrent` kills on their
|
|
21787
|
-
// first check, each one paying the project-wide deep copy first.
|
|
21788
|
-
this._pendingScheduleRevision === this._scheduleRevision && this._activeCriticalPath === null;
|
|
21524
|
+
return this._criticalPathRevision === this._scheduleRevision && this._pendingScheduleRevision === this._scheduleRevision && this._activeCriticalPath === null;
|
|
21789
21525
|
}
|
|
21790
21526
|
async whenCriticalPathSettled() {
|
|
21791
21527
|
while (!this.isCriticalPathSettled()) {
|
|
@@ -21801,34 +21537,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21801
21537
|
const merged = this._reapplyViewState(result.changes);
|
|
21802
21538
|
return merged === null ? result : { ...result, changes: merged };
|
|
21803
21539
|
}
|
|
21804
|
-
_recordRelativePlacementPin(action, changes) {
|
|
21805
|
-
const state = this.coreRuntime.state;
|
|
21806
|
-
if (action.kind !== "activity-create") return;
|
|
21807
|
-
const referenceId = action.afterSiblingId ?? action.beforeSiblingId ?? (action.eventSource === "Creation button (+)" && action.parentId !== ROOT_PARENT_ID ? action.parentId : void 0);
|
|
21808
|
-
if (referenceId === void 0) return;
|
|
21809
|
-
const created = changes.activities.find(({ kind }) => kind === "created");
|
|
21810
|
-
if (created === void 0) return;
|
|
21811
|
-
state.setRelativePlacementPin(created.id, {
|
|
21812
|
-
referenceId,
|
|
21813
|
-
branchParentId: action.parentId,
|
|
21814
|
-
side: action.beforeSiblingId === void 0 ? "after" : "before"
|
|
21815
|
-
});
|
|
21816
|
-
}
|
|
21817
|
-
/**
|
|
21818
|
-
* The single place the two view-state passes are chained. Dispatch, undo and
|
|
21819
|
-
* redo all route through here: when this existed only inside the dispatch
|
|
21820
|
-
* path, undo and redo reapplied the filter and forgot the order, so an edit
|
|
21821
|
-
* that moved a row and was then undone left the row in its new position.
|
|
21822
|
-
*
|
|
21823
|
-
* The sequence between the passes is indifferent. Filter and order are
|
|
21824
|
-
* orthogonal projections over the same tree — the filter decides which rows
|
|
21825
|
-
* exist on screen and never reads the order; the order sequences every
|
|
21826
|
-
* sibling group from the hierarchy index and never reads visibility. Either
|
|
21827
|
-
* sequence produces the same ChangeSet.
|
|
21828
|
-
*
|
|
21829
|
-
* Both passes answer null while their state is inactive, so an unfiltered,
|
|
21830
|
-
* unsorted schedule pays two property reads.
|
|
21831
|
-
*/
|
|
21832
21540
|
_reapplyViewState(changes) {
|
|
21833
21541
|
const withFilter = this._reapplyActiveFilter(changes);
|
|
21834
21542
|
const sequenced = this._emitTouchedBranchOrder(withFilter ?? changes);
|
|
@@ -21838,24 +21546,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21838
21546
|
);
|
|
21839
21547
|
return withOrder ?? sequenced.changes ?? withFilter;
|
|
21840
21548
|
}
|
|
21841
|
-
/**
|
|
21842
|
-
* Emits `order` for the branches this mutation resequenced, when no user order
|
|
21843
|
-
* is active.
|
|
21844
|
-
*
|
|
21845
|
-
* The contract is that `order` reports a CHANGED SEQUENCE, not the presence of
|
|
21846
|
-
* a sort. Tying emission to the cause instead of the effect is what produced
|
|
21847
|
-
* the undo bug and, later, the reparent ones: without an active order a move,
|
|
21848
|
-
* an indent, an outdent or the undo of any of them rearranged rows and said
|
|
21849
|
-
* nothing, so an incremental consumer kept the old sequence. The undo of a
|
|
21850
|
-
* reparent was the worst of them — it carried neither `order` nor a single
|
|
21851
|
-
* correlativeId, so the position was not recoverable by any consumer.
|
|
21852
|
-
*
|
|
21853
|
-
* The touched branches are derived from the ChangeSet rather than accumulated
|
|
21854
|
-
* in the state: an entity whose parentId or correlativeId moved, plus the
|
|
21855
|
-
* parents of created and deleted rows, is exactly the set of branches whose
|
|
21856
|
-
* sequence can differ. That keeps this linear in the blast radius, adds
|
|
21857
|
-
* nothing to the write path, and cannot leak across dispatches.
|
|
21858
|
-
*/
|
|
21859
21549
|
_emitTouchedBranchOrder(changes) {
|
|
21860
21550
|
const adapter = this.coreRuntime.state;
|
|
21861
21551
|
const touchedParents = collectResequencedParents(
|
|
@@ -21872,15 +21562,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21872
21562
|
if (order.length === 0) return { changes: null, touchedParents };
|
|
21873
21563
|
return { changes: { ...changes, order }, touchedParents };
|
|
21874
21564
|
}
|
|
21875
|
-
/**
|
|
21876
|
-
* Re-sequences the grid after any mutation that could have changed a value the
|
|
21877
|
-
* active order sorts by. Ordering is a view over the data, so an edit that
|
|
21878
|
-
* moves a row past its sibling must move the row, exactly as the filter makes
|
|
21879
|
-
* a no-longer-matching row disappear.
|
|
21880
|
-
*
|
|
21881
|
-
* Production only re-sorts after a bar drag; diverging from that is a
|
|
21882
|
-
* deliberate product decision, not an oversight.
|
|
21883
|
-
*/
|
|
21884
21565
|
_reapplyActiveOrder(changes, resequencedParents) {
|
|
21885
21566
|
const adapter = this.coreRuntime.state;
|
|
21886
21567
|
if (adapter.getActiveOrder() === null) return null;
|
|
@@ -21915,22 +21596,15 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21915
21596
|
context
|
|
21916
21597
|
);
|
|
21917
21598
|
const changedActivities = changesRequireFilterProjectionRebuild(changes) ? null : collectChangedActivities(changes, adapter);
|
|
21918
|
-
const relativePlacementPins = adapter.getRelativePlacementPins();
|
|
21919
21599
|
let affectedIds;
|
|
21920
21600
|
let visibleIds;
|
|
21921
|
-
const needsProjectionRebuild = changedActivities === null || !projectionIsCurrent
|
|
21922
|
-
changes,
|
|
21923
|
-
changedActivities,
|
|
21924
|
-
adapter,
|
|
21925
|
-
relativePlacementPins
|
|
21926
|
-
);
|
|
21601
|
+
const needsProjectionRebuild = changedActivities === null || !projectionIsCurrent;
|
|
21927
21602
|
if (needsProjectionRebuild) {
|
|
21928
21603
|
const rebuiltProjection = buildFilterProjection({
|
|
21929
21604
|
activities: adapter.getAllActivities(),
|
|
21930
21605
|
parentOf: (activityId) => adapter.getParentId(activityId),
|
|
21931
21606
|
filter,
|
|
21932
|
-
context
|
|
21933
|
-
relativePlacementPins
|
|
21607
|
+
context
|
|
21934
21608
|
});
|
|
21935
21609
|
adapter.setFilterProjection(rebuiltProjection);
|
|
21936
21610
|
visibleIds = rebuiltProjection.visibleIds;
|
|
@@ -21986,11 +21660,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21986
21660
|
this.coreRuntime.baseCalendars
|
|
21987
21661
|
)
|
|
21988
21662
|
);
|
|
21989
|
-
const isCurrent = () => !cancellation.cancelled && this._status !== SCHEDULE_CORE_STATUS.DESTROYED && this._scheduleRevision === revision &&
|
|
21990
|
-
// garbage. Without this term the calculation only learns it is obsolete
|
|
21991
|
-
// when the mutation finishes, which measured live is the same instant the
|
|
21992
|
-
// job itself ends.
|
|
21993
|
-
this._pendingScheduleRevision === this._scheduleRevision;
|
|
21663
|
+
const isCurrent = () => !cancellation.cancelled && this._status !== SCHEDULE_CORE_STATUS.DESTROYED && this._scheduleRevision === revision && this._pendingScheduleRevision === this._scheduleRevision;
|
|
21994
21664
|
const promise = (async () => {
|
|
21995
21665
|
const calculatedFields = await computeCriticalPathFields(
|
|
21996
21666
|
isolatedState,
|
|
@@ -22340,6 +22010,6 @@ var CREATION_KIND = {
|
|
|
22340
22010
|
ROOT: "root"
|
|
22341
22011
|
};
|
|
22342
22012
|
|
|
22343
|
-
export { ACTIVITY_TYPE, CALENDAR_UNIT, COLUMN,
|
|
22013
|
+
export { ACTIVITY_TYPE, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, NEW_ACTIVITY_DEFAULTS, REJECTION_REASON, ROOT_PARENT_ID, SCHEDULE_CORE_STATUS, STATUS, ScheduleCore, WORK_TIME_DIRECTION, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, willRunCriticalPath, yieldToBrowser };
|
|
22344
22014
|
//# sourceMappingURL=index.js.map
|
|
22345
22015
|
//# sourceMappingURL=index.js.map
|