@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.cjs
CHANGED
|
@@ -401,16 +401,10 @@ var FIELD_REGISTRY = {
|
|
|
401
401
|
valueKind: "reference",
|
|
402
402
|
extract: (activity) => activity.calendarId === null ? null : String(activity.calendarId)
|
|
403
403
|
},
|
|
404
|
-
// Normalized to string like calendarId. It is stored as a number, so it used
|
|
405
|
-
// to reach compareValues through the numeric branch while its sibling
|
|
406
|
-
// reference went through the string one — the same field kind comparing two
|
|
407
|
-
// different ways. localeCompare with numeric:true keeps the digit ordering.
|
|
408
404
|
subcontractId: {
|
|
409
405
|
valueKind: "reference",
|
|
410
406
|
extract: (activity) => activity.subcontractId === null ? null : String(activity.subcontractId)
|
|
411
407
|
},
|
|
412
|
-
// Declared boolean, not enum: it is one, and saying so is what lets the enum
|
|
413
|
-
// branch demand an order without inventing one for true/false.
|
|
414
408
|
isCritical: {
|
|
415
409
|
valueKind: "boolean",
|
|
416
410
|
extract: (activity) => activity.isCritical
|
|
@@ -420,107 +414,6 @@ function getFieldDescriptor(field) {
|
|
|
420
414
|
return FIELD_REGISTRY[field] ?? null;
|
|
421
415
|
}
|
|
422
416
|
|
|
423
|
-
// src/internal/state/view-state.ts
|
|
424
|
-
function isRelativePlacementPinValid(activityId, pin, parentOf) {
|
|
425
|
-
const branchParentId = String(pin.branchParentId);
|
|
426
|
-
const currentParentId = String(parentOf(activityId) ?? "0");
|
|
427
|
-
if (currentParentId !== branchParentId) return false;
|
|
428
|
-
const referenceId = String(pin.referenceId);
|
|
429
|
-
return referenceId === branchParentId || String(parentOf(referenceId) ?? "0") === branchParentId;
|
|
430
|
-
}
|
|
431
|
-
var ViewStateStore = class {
|
|
432
|
-
checkedSet = /* @__PURE__ */ new Set();
|
|
433
|
-
hiddenSet = /* @__PURE__ */ new Set();
|
|
434
|
-
activeFilter = null;
|
|
435
|
-
activeOrder = null;
|
|
436
|
-
relativePlacementPins = /* @__PURE__ */ new Map();
|
|
437
|
-
isChecked(activityId) {
|
|
438
|
-
return this.checkedSet.has(activityId);
|
|
439
|
-
}
|
|
440
|
-
isVisible(activityId) {
|
|
441
|
-
return !this.hiddenSet.has(activityId);
|
|
442
|
-
}
|
|
443
|
-
hiddenIds() {
|
|
444
|
-
return [...this.hiddenSet];
|
|
445
|
-
}
|
|
446
|
-
getActiveFilter() {
|
|
447
|
-
return this.activeFilter;
|
|
448
|
-
}
|
|
449
|
-
setActiveFilter(nextFilter) {
|
|
450
|
-
this.activeFilter = nextFilter;
|
|
451
|
-
}
|
|
452
|
-
getActiveOrder() {
|
|
453
|
-
return this.activeOrder;
|
|
454
|
-
}
|
|
455
|
-
setActiveOrder(nextOrder) {
|
|
456
|
-
this.activeOrder = nextOrder;
|
|
457
|
-
}
|
|
458
|
-
setRelativePlacementPin(activityId, pin) {
|
|
459
|
-
this.relativePlacementPins.set(String(activityId), {
|
|
460
|
-
referenceId: String(pin.referenceId),
|
|
461
|
-
branchParentId: String(pin.branchParentId),
|
|
462
|
-
side: pin.side
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
getRelativePlacementPins() {
|
|
466
|
-
return this.relativePlacementPins;
|
|
467
|
-
}
|
|
468
|
-
restoreRelativePlacementPins(pins) {
|
|
469
|
-
this.relativePlacementPins = new Map(pins);
|
|
470
|
-
}
|
|
471
|
-
checkedIds() {
|
|
472
|
-
return [...this.checkedSet];
|
|
473
|
-
}
|
|
474
|
-
checkedCount() {
|
|
475
|
-
return this.checkedSet.size;
|
|
476
|
-
}
|
|
477
|
-
setChecked(activityId, nextChecked) {
|
|
478
|
-
if (nextChecked === this.checkedSet.has(activityId)) return false;
|
|
479
|
-
if (nextChecked) this.checkedSet.add(activityId);
|
|
480
|
-
else this.checkedSet.delete(activityId);
|
|
481
|
-
return true;
|
|
482
|
-
}
|
|
483
|
-
setVisible(activityId, nextVisible) {
|
|
484
|
-
if (nextVisible === !this.hiddenSet.has(activityId)) return false;
|
|
485
|
-
if (nextVisible) this.hiddenSet.delete(activityId);
|
|
486
|
-
else this.hiddenSet.add(activityId);
|
|
487
|
-
return true;
|
|
488
|
-
}
|
|
489
|
-
forget(activityId) {
|
|
490
|
-
this.checkedSet.delete(activityId);
|
|
491
|
-
this.hiddenSet.delete(activityId);
|
|
492
|
-
this.relativePlacementPins.delete(activityId);
|
|
493
|
-
for (const [pinnedId, pin] of this.relativePlacementPins) {
|
|
494
|
-
if (pin.referenceId === activityId) {
|
|
495
|
-
this.relativePlacementPins.delete(pinnedId);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
hydrate(seed2) {
|
|
500
|
-
this.checkedSet = new Set(seed2.checkedIds ?? []);
|
|
501
|
-
this.hiddenSet = new Set(seed2.hiddenIds ?? []);
|
|
502
|
-
this.activeFilter = null;
|
|
503
|
-
this.activeOrder = null;
|
|
504
|
-
this.relativePlacementPins = /* @__PURE__ */ new Map();
|
|
505
|
-
}
|
|
506
|
-
snapshot() {
|
|
507
|
-
return {
|
|
508
|
-
checked: new Set(this.checkedSet),
|
|
509
|
-
hidden: new Set(this.hiddenSet),
|
|
510
|
-
activeFilter: this.activeFilter,
|
|
511
|
-
activeOrder: this.activeOrder,
|
|
512
|
-
relativePlacementPins: new Map(this.relativePlacementPins)
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
restore(snapshot) {
|
|
516
|
-
this.checkedSet = new Set(snapshot.checked);
|
|
517
|
-
this.hiddenSet = new Set(snapshot.hidden);
|
|
518
|
-
this.activeFilter = snapshot.activeFilter;
|
|
519
|
-
this.activeOrder = snapshot.activeOrder;
|
|
520
|
-
this.relativePlacementPins = new Map(snapshot.relativePlacementPins);
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
|
|
524
417
|
// src/internal/filter/evaluate-filter.ts
|
|
525
418
|
function toTargetDate(value) {
|
|
526
419
|
if (value instanceof Date) return value;
|
|
@@ -647,7 +540,6 @@ function evaluateVisibleIds(input) {
|
|
|
647
540
|
function seedFilterProjection(input) {
|
|
648
541
|
const { activities, parentOf, filter, context } = input;
|
|
649
542
|
const matchedIds = /* @__PURE__ */ new Set();
|
|
650
|
-
const pinnedVisibleIds = /* @__PURE__ */ new Set();
|
|
651
543
|
const visibleReferenceCounts = /* @__PURE__ */ new Map();
|
|
652
544
|
const parentIds = /* @__PURE__ */ new Map();
|
|
653
545
|
const remainingChildren = /* @__PURE__ */ new Map();
|
|
@@ -668,35 +560,11 @@ function seedFilterProjection(input) {
|
|
|
668
560
|
}
|
|
669
561
|
return {
|
|
670
562
|
matchedIds,
|
|
671
|
-
pinnedVisibleIds,
|
|
672
563
|
visibleReferenceCounts,
|
|
673
564
|
parentIds,
|
|
674
565
|
remainingChildren
|
|
675
566
|
};
|
|
676
567
|
}
|
|
677
|
-
function applyRelativePlacementPins(seed2, pins) {
|
|
678
|
-
if (pins === void 0) return;
|
|
679
|
-
for (const [activityId, pin] of pins) {
|
|
680
|
-
const pinnedId = String(activityId);
|
|
681
|
-
const referenceId = String(pin.referenceId);
|
|
682
|
-
if (!seed2.parentIds.has(pinnedId) || !seed2.parentIds.has(referenceId) || !isRelativePlacementPinValid(
|
|
683
|
-
pinnedId,
|
|
684
|
-
pin,
|
|
685
|
-
(activityId2) => seed2.parentIds.get(activityId2) ?? null
|
|
686
|
-
) || (seed2.visibleReferenceCounts.get(referenceId) ?? 0) === 0) {
|
|
687
|
-
continue;
|
|
688
|
-
}
|
|
689
|
-
seed2.pinnedVisibleIds.add(pinnedId);
|
|
690
|
-
let currentId = pinnedId;
|
|
691
|
-
while (currentId !== null) {
|
|
692
|
-
seed2.visibleReferenceCounts.set(
|
|
693
|
-
currentId,
|
|
694
|
-
(seed2.visibleReferenceCounts.get(currentId) ?? 0) + 1
|
|
695
|
-
);
|
|
696
|
-
currentId = seed2.parentIds.get(currentId) ?? null;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
568
|
function propagateVisibleReferenceCounts(seed2) {
|
|
701
569
|
const { visibleReferenceCounts, parentIds, remainingChildren } = seed2;
|
|
702
570
|
const pendingIds = [];
|
|
@@ -728,13 +596,11 @@ function collectVisibleIds(visibleReferenceCounts) {
|
|
|
728
596
|
function buildFilterProjection(input) {
|
|
729
597
|
const seed2 = seedFilterProjection(input);
|
|
730
598
|
propagateVisibleReferenceCounts(seed2);
|
|
731
|
-
applyRelativePlacementPins(seed2, input.relativePlacementPins);
|
|
732
599
|
const visibleIds = collectVisibleIds(seed2.visibleReferenceCounts);
|
|
733
600
|
return {
|
|
734
601
|
filter: input.filter,
|
|
735
602
|
context: input.context,
|
|
736
603
|
matchedIds: seed2.matchedIds,
|
|
737
|
-
pinnedVisibleIds: seed2.pinnedVisibleIds,
|
|
738
604
|
visibleIds,
|
|
739
605
|
visibleReferenceCounts: seed2.visibleReferenceCounts
|
|
740
606
|
};
|
|
@@ -792,8 +658,6 @@ var OPERATORS_BY_KIND = {
|
|
|
792
658
|
date: /* @__PURE__ */ new Set(["after", "before"]),
|
|
793
659
|
"id-array": /* @__PURE__ */ new Set(["someOf", "notSomeOf"]),
|
|
794
660
|
enum: /* @__PURE__ */ new Set(["someOf", "notSomeOf"]),
|
|
795
|
-
// Same membership operators as enum: splitting the kinds was about ordering,
|
|
796
|
-
// not about filtering, and these two filter exactly like an enum.
|
|
797
661
|
boolean: /* @__PURE__ */ new Set(["someOf", "notSomeOf"]),
|
|
798
662
|
reference: /* @__PURE__ */ new Set(["someOf", "notSomeOf"])
|
|
799
663
|
};
|
|
@@ -916,8 +780,7 @@ function resolveFilter(adapter, filter, hoursPerDay) {
|
|
|
916
780
|
activities,
|
|
917
781
|
parentOf: (activityId) => adapter.getParentId(activityId),
|
|
918
782
|
filter,
|
|
919
|
-
context: buildFilterContext(hoursPerDay)
|
|
920
|
-
relativePlacementPins: adapter.getRelativePlacementPins()
|
|
783
|
+
context: buildFilterContext(hoursPerDay)
|
|
921
784
|
});
|
|
922
785
|
return { visibleIds: projection.visibleIds, projection };
|
|
923
786
|
}
|
|
@@ -968,118 +831,25 @@ function normalizeParentKey(parent) {
|
|
|
968
831
|
|
|
969
832
|
// src/internal/hierarchy/visual-order.ts
|
|
970
833
|
var NOT_SET_SORT_VALUE = Number.MAX_SAFE_INTEGER;
|
|
971
|
-
|
|
972
|
-
function buildRelativePlacementPinIndex(adapter) {
|
|
973
|
-
const index = /* @__PURE__ */ new Map();
|
|
974
|
-
for (const [activityId, pin] of adapter.getRelativePlacementPins?.() ?? []) {
|
|
975
|
-
const pinnedId = String(activityId);
|
|
976
|
-
const referenceId = String(pin.referenceId);
|
|
977
|
-
if (adapter.getActivity(pinnedId) === null || adapter.getActivity(referenceId) === null || !isRelativePlacementPinValid(
|
|
978
|
-
pinnedId,
|
|
979
|
-
pin,
|
|
980
|
-
(activityId2) => adapter.getParentId(activityId2)
|
|
981
|
-
)) {
|
|
982
|
-
continue;
|
|
983
|
-
}
|
|
984
|
-
const targetParentId = String(pin.branchParentId);
|
|
985
|
-
const branchPins = index.get(targetParentId) ?? /* @__PURE__ */ new Map();
|
|
986
|
-
branchPins.set(pinnedId, pin);
|
|
987
|
-
index.set(targetParentId, branchPins);
|
|
988
|
-
}
|
|
989
|
-
return index;
|
|
990
|
-
}
|
|
991
|
-
function getChildrenInVisualOrder(parentId, adapter, pinIndex = buildRelativePlacementPinIndex(adapter)) {
|
|
834
|
+
function getChildrenInVisualOrder(parentId, adapter) {
|
|
992
835
|
const children = collectChildrenSnapshots(parentId, adapter);
|
|
993
836
|
const userOrder = adapter.getOrderComparator?.() ?? null;
|
|
994
837
|
children.sort(
|
|
995
838
|
userOrder === null ? compareActivitiesInVisualOrder : (a, b) => userOrder(a, b) || compareActivitiesInVisualOrder(a, b)
|
|
996
839
|
);
|
|
997
|
-
return
|
|
998
|
-
children.map((activity) => String(activity.id)),
|
|
999
|
-
parentId,
|
|
1000
|
-
pinIndex.get(String(parentId)) ?? EMPTY_RELATIVE_PLACEMENT_PINS
|
|
1001
|
-
);
|
|
1002
|
-
}
|
|
1003
|
-
function applyRelativePlacementPins2(orderedIds, parentId, pins) {
|
|
1004
|
-
const order = buildLinkedActivityOrder(orderedIds);
|
|
1005
|
-
for (const [activityId, pin] of pins) {
|
|
1006
|
-
const pinnedId = String(activityId);
|
|
1007
|
-
const referenceId = String(pin.referenceId);
|
|
1008
|
-
const isFirstChild = referenceId === String(parentId);
|
|
1009
|
-
if (!order.previous.has(pinnedId) || !isFirstChild && (!order.previous.has(referenceId) || pinnedId === referenceId)) {
|
|
1010
|
-
continue;
|
|
1011
|
-
}
|
|
1012
|
-
detachActivity(order, pinnedId);
|
|
1013
|
-
if (isFirstChild) insertActivityFirst(order, pinnedId);
|
|
1014
|
-
else insertActivityBeside(order, pinnedId, referenceId, pin.side);
|
|
1015
|
-
}
|
|
1016
|
-
return materializeActivityOrder(order);
|
|
1017
|
-
}
|
|
1018
|
-
function buildLinkedActivityOrder(orderedIds) {
|
|
1019
|
-
const previous = /* @__PURE__ */ new Map();
|
|
1020
|
-
const next = /* @__PURE__ */ new Map();
|
|
1021
|
-
for (let index = 0; index < orderedIds.length; index++) {
|
|
1022
|
-
const activityId = orderedIds[index];
|
|
1023
|
-
if (activityId === void 0) continue;
|
|
1024
|
-
previous.set(activityId, orderedIds[index - 1] ?? null);
|
|
1025
|
-
next.set(activityId, orderedIds[index + 1] ?? null);
|
|
1026
|
-
}
|
|
1027
|
-
return { previous, next, head: orderedIds[0] ?? null };
|
|
1028
|
-
}
|
|
1029
|
-
function detachActivity(order, activityId) {
|
|
1030
|
-
const before = order.previous.get(activityId) ?? null;
|
|
1031
|
-
const after = order.next.get(activityId) ?? null;
|
|
1032
|
-
if (before === null) order.head = after;
|
|
1033
|
-
else order.next.set(before, after);
|
|
1034
|
-
if (after !== null) order.previous.set(after, before);
|
|
1035
|
-
}
|
|
1036
|
-
function insertActivityFirst(order, activityId) {
|
|
1037
|
-
order.previous.set(activityId, null);
|
|
1038
|
-
order.next.set(activityId, order.head);
|
|
1039
|
-
if (order.head !== null) order.previous.set(order.head, activityId);
|
|
1040
|
-
order.head = activityId;
|
|
1041
|
-
}
|
|
1042
|
-
function insertActivityBeside(order, activityId, referenceId, side) {
|
|
1043
|
-
if (side === "before") {
|
|
1044
|
-
const before = order.previous.get(referenceId) ?? null;
|
|
1045
|
-
order.previous.set(activityId, before);
|
|
1046
|
-
order.next.set(activityId, referenceId);
|
|
1047
|
-
order.previous.set(referenceId, activityId);
|
|
1048
|
-
if (before === null) order.head = activityId;
|
|
1049
|
-
else order.next.set(before, activityId);
|
|
1050
|
-
return;
|
|
1051
|
-
}
|
|
1052
|
-
const after = order.next.get(referenceId) ?? null;
|
|
1053
|
-
order.previous.set(activityId, referenceId);
|
|
1054
|
-
order.next.set(activityId, after);
|
|
1055
|
-
order.next.set(referenceId, activityId);
|
|
1056
|
-
if (after !== null) order.previous.set(after, activityId);
|
|
1057
|
-
}
|
|
1058
|
-
function materializeActivityOrder(order) {
|
|
1059
|
-
const result = [];
|
|
1060
|
-
let activityId = order.head;
|
|
1061
|
-
while (activityId !== null) {
|
|
1062
|
-
result.push(activityId);
|
|
1063
|
-
activityId = order.next.get(activityId) ?? null;
|
|
1064
|
-
}
|
|
1065
|
-
return result;
|
|
840
|
+
return children.map((activity) => String(activity.id));
|
|
1066
841
|
}
|
|
1067
842
|
function iterateInVisualOrder(adapter) {
|
|
1068
843
|
const result = [];
|
|
1069
|
-
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
1070
844
|
const visit = (activity) => {
|
|
1071
845
|
result.push(activity);
|
|
1072
|
-
const childIds = getChildrenInVisualOrder(
|
|
1073
|
-
String(activity.id),
|
|
1074
|
-
adapter,
|
|
1075
|
-
pinIndex
|
|
1076
|
-
);
|
|
846
|
+
const childIds = getChildrenInVisualOrder(String(activity.id), adapter);
|
|
1077
847
|
for (const childId of childIds) {
|
|
1078
848
|
const child = adapter.getActivity(childId);
|
|
1079
849
|
if (child) visit(child);
|
|
1080
850
|
}
|
|
1081
851
|
};
|
|
1082
|
-
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter
|
|
852
|
+
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter);
|
|
1083
853
|
for (const rootId of rootIds) {
|
|
1084
854
|
const root = adapter.getActivity(rootId);
|
|
1085
855
|
if (root) visit(root);
|
|
@@ -1140,9 +910,8 @@ function setHas(set, id) {
|
|
|
1140
910
|
// src/dispatch/shared/collect-branch-order.ts
|
|
1141
911
|
function collectBranchOrder(adapter) {
|
|
1142
912
|
const branches = [];
|
|
1143
|
-
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
1144
913
|
const visit = (parentId) => {
|
|
1145
|
-
const childIds = getChildrenInVisualOrder(parentId, adapter
|
|
914
|
+
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
1146
915
|
if (childIds.length > 1) {
|
|
1147
916
|
branches.push({ parentId, childIds });
|
|
1148
917
|
}
|
|
@@ -1155,9 +924,8 @@ function collectBranchOrder(adapter) {
|
|
|
1155
924
|
}
|
|
1156
925
|
function collectBranchOrderForParents(adapter, parentIds) {
|
|
1157
926
|
const branches = [];
|
|
1158
|
-
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
1159
927
|
for (const parentId of parentIds) {
|
|
1160
|
-
const childIds = getChildrenInVisualOrder(parentId, adapter
|
|
928
|
+
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
1161
929
|
if (childIds.length > 1) branches.push({ parentId, childIds });
|
|
1162
930
|
}
|
|
1163
931
|
return branches;
|
|
@@ -1190,107 +958,61 @@ function dispatchSortSet(action, deps) {
|
|
|
1190
958
|
return { ok: true, changes };
|
|
1191
959
|
}
|
|
1192
960
|
|
|
1193
|
-
// src/columns
|
|
1194
|
-
var
|
|
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
|
-
|
|
1237
|
-
|
|
1238
|
-
// src/columns/tags/constants.ts
|
|
1239
|
-
var TAGS = "tags";
|
|
1240
|
-
|
|
1241
|
-
// src/columns/predecessors/constants.ts
|
|
1242
|
-
var CUSTOM_PREDECESSORS = "custom_predecessors";
|
|
1243
|
-
|
|
1244
|
-
// src/columns/successors/constants.ts
|
|
1245
|
-
var CUSTOM_SUCESSORS = "custom_sucessors";
|
|
1246
|
-
|
|
1247
|
-
// src/columns/real-work/constants.ts
|
|
1248
|
-
var REAL_WORK = "real_work";
|
|
1249
|
-
|
|
1250
|
-
// src/columns/real-cost/constants.ts
|
|
1251
|
-
var REAL_COST = "real_cost";
|
|
1252
|
-
|
|
1253
|
-
// src/columns/expected-progress/constants.ts
|
|
1254
|
-
var EXPECTED_PROGRESS = "expected_progress";
|
|
1255
|
-
|
|
1256
|
-
// src/columns/expected-progress-base/constants.ts
|
|
1257
|
-
var EXPECTED_PROGRESS_BASE = "expected_progress_base";
|
|
1258
|
-
|
|
1259
|
-
// src/columns/start-base/constants.ts
|
|
1260
|
-
var START_BASE = "start_base";
|
|
1261
|
-
|
|
1262
|
-
// src/columns/end-base/constants.ts
|
|
1263
|
-
var END_BASE = "end_base";
|
|
1264
|
-
|
|
1265
|
-
// src/columns/duration-base/constants.ts
|
|
1266
|
-
var DURATION_BASE = "duration_base";
|
|
1267
|
-
|
|
1268
|
-
// src/columns/cost-base/constants.ts
|
|
1269
|
-
var COST_BASE = "cost_base";
|
|
1270
|
-
|
|
1271
|
-
// src/columns/work-base/constants.ts
|
|
1272
|
-
var WORK_BASE = "work_base";
|
|
1273
|
-
|
|
1274
|
-
// src/columns/calendar-duration/constants.ts
|
|
1275
|
-
var CALENDAR_DURATION = "calendarDuration";
|
|
1276
|
-
|
|
1277
|
-
// src/columns/critical-path/constants.ts
|
|
1278
|
-
var IS_CRITICAL = "is_critical";
|
|
1279
|
-
var EARLY_START = "earlyStart";
|
|
1280
|
-
var EARLY_FINISH = "earlyFinish";
|
|
1281
|
-
var LATE_START = "lateStart";
|
|
1282
|
-
var LATE_FINISH = "lateFinish";
|
|
1283
|
-
var FREE_SLACK = "freeSlack";
|
|
1284
|
-
var TOTAL_SLACK = "totalSlack";
|
|
1285
|
-
|
|
1286
|
-
// src/columns/correlative-id/constants.ts
|
|
1287
|
-
var CORRELATIVE_ID = "correlative_id";
|
|
961
|
+
// src/constants/columns.ts
|
|
962
|
+
var EDITABLE = {
|
|
963
|
+
TEXT: "text",
|
|
964
|
+
DESCRIPTION: "description",
|
|
965
|
+
DURATION: "duration",
|
|
966
|
+
PROGRESS: "progress",
|
|
967
|
+
COST: "cost",
|
|
968
|
+
USED_COST: "used_cost",
|
|
969
|
+
HH_WORK_TIME: "hhWorkTime",
|
|
970
|
+
START_DATE: "start_date",
|
|
971
|
+
END_DATE: "end_date",
|
|
972
|
+
CONSTRAINT_TYPE: "constraint_type",
|
|
973
|
+
CONSTRAINT_DATE: "constraint_date",
|
|
974
|
+
CALENDAR_ID: "calendar_id",
|
|
975
|
+
CUSTOM_ID: "custom_id",
|
|
976
|
+
SUBCONTRACT_ID: "subcontractId",
|
|
977
|
+
RESPONSABLES: "responsables",
|
|
978
|
+
TAGS: "tags",
|
|
979
|
+
CUSTOM_PREDECESSORS: "custom_predecessors",
|
|
980
|
+
CUSTOM_SUCESSORS: "custom_sucessors"
|
|
981
|
+
};
|
|
982
|
+
var READ_ONLY = {
|
|
983
|
+
REAL_WORK: "real_work",
|
|
984
|
+
REAL_COST: "real_cost",
|
|
985
|
+
EXPECTED_PROGRESS: "expected_progress",
|
|
986
|
+
EXPECTED_PROGRESS_BASE: "expected_progress_base",
|
|
987
|
+
START_BASE: "start_base",
|
|
988
|
+
END_BASE: "end_base",
|
|
989
|
+
DURATION_BASE: "duration_base",
|
|
990
|
+
COST_BASE: "cost_base",
|
|
991
|
+
WORK_BASE: "work_base",
|
|
992
|
+
CALENDAR_DURATION: "calendarDuration",
|
|
993
|
+
IS_CRITICAL: "is_critical",
|
|
994
|
+
EARLY_START: "earlyStart",
|
|
995
|
+
EARLY_FINISH: "earlyFinish",
|
|
996
|
+
LATE_START: "lateStart",
|
|
997
|
+
LATE_FINISH: "lateFinish",
|
|
998
|
+
FREE_SLACK: "freeSlack",
|
|
999
|
+
TOTAL_SLACK: "totalSlack",
|
|
1000
|
+
CORRELATIVE_ID: "correlative_id",
|
|
1001
|
+
UNIQUE_CORRELATIVE_ID: "unique_correlative_id",
|
|
1002
|
+
PONDERATOR: "ponderator",
|
|
1003
|
+
STATUS: "status"
|
|
1004
|
+
};
|
|
1005
|
+
var COLUMN = { ...EDITABLE, ...READ_ONLY };
|
|
1288
1006
|
|
|
1289
|
-
// src/
|
|
1290
|
-
|
|
1007
|
+
// src/shared/assert-never.ts
|
|
1008
|
+
function assertNever(value, message) {
|
|
1009
|
+
throw new Error(message);
|
|
1010
|
+
}
|
|
1291
1011
|
|
|
1292
|
-
// src/
|
|
1293
|
-
|
|
1012
|
+
// src/autoscheduler/utils/cancellation.ts
|
|
1013
|
+
function createIsCurrent(id, getCurrentId) {
|
|
1014
|
+
return () => getCurrentId() === id;
|
|
1015
|
+
}
|
|
1294
1016
|
|
|
1295
1017
|
// src/types.ts
|
|
1296
1018
|
var WORK_TIME_DIRECTION = {
|
|
@@ -1309,71 +1031,8 @@ var STATUS = {
|
|
|
1309
1031
|
DOING: "Doing"
|
|
1310
1032
|
};
|
|
1311
1033
|
|
|
1312
|
-
// src/columns/status/constants.ts
|
|
1313
|
-
var STATUS_COLUMN = "status";
|
|
1314
|
-
var DEFAULT_STATUS_CRITERIA = "Baseline";
|
|
1315
|
-
function resolveStatusCriteria(value) {
|
|
1316
|
-
return value === "Actual" ? "Actual" : DEFAULT_STATUS_CRITERIA;
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
// src/constants/columns.ts
|
|
1320
|
-
var EDITABLE = {
|
|
1321
|
-
TEXT,
|
|
1322
|
-
DESCRIPTION,
|
|
1323
|
-
DURATION,
|
|
1324
|
-
PROGRESS,
|
|
1325
|
-
COST,
|
|
1326
|
-
USED_COST,
|
|
1327
|
-
HH_WORK_TIME,
|
|
1328
|
-
START_DATE,
|
|
1329
|
-
END_DATE,
|
|
1330
|
-
CONSTRAINT_TYPE,
|
|
1331
|
-
CONSTRAINT_DATE,
|
|
1332
|
-
CALENDAR_ID,
|
|
1333
|
-
CUSTOM_ID,
|
|
1334
|
-
SUBCONTRACT_ID,
|
|
1335
|
-
RESPONSABLES,
|
|
1336
|
-
TAGS,
|
|
1337
|
-
CUSTOM_PREDECESSORS,
|
|
1338
|
-
CUSTOM_SUCESSORS
|
|
1339
|
-
};
|
|
1340
|
-
var READ_ONLY = {
|
|
1341
|
-
REAL_WORK,
|
|
1342
|
-
REAL_COST,
|
|
1343
|
-
EXPECTED_PROGRESS,
|
|
1344
|
-
EXPECTED_PROGRESS_BASE,
|
|
1345
|
-
START_BASE,
|
|
1346
|
-
END_BASE,
|
|
1347
|
-
DURATION_BASE,
|
|
1348
|
-
COST_BASE,
|
|
1349
|
-
WORK_BASE,
|
|
1350
|
-
CALENDAR_DURATION,
|
|
1351
|
-
IS_CRITICAL,
|
|
1352
|
-
EARLY_START,
|
|
1353
|
-
EARLY_FINISH,
|
|
1354
|
-
LATE_START,
|
|
1355
|
-
LATE_FINISH,
|
|
1356
|
-
FREE_SLACK,
|
|
1357
|
-
TOTAL_SLACK,
|
|
1358
|
-
CORRELATIVE_ID,
|
|
1359
|
-
UNIQUE_CORRELATIVE_ID,
|
|
1360
|
-
PONDERATOR,
|
|
1361
|
-
STATUS: STATUS_COLUMN
|
|
1362
|
-
};
|
|
1363
|
-
var COLUMN = { ...EDITABLE, ...READ_ONLY };
|
|
1364
|
-
|
|
1365
|
-
// src/shared/assert-never.ts
|
|
1366
|
-
function assertNever(value, message) {
|
|
1367
|
-
throw new Error(message);
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
// src/autoscheduler/utils/cancellation.ts
|
|
1371
|
-
function createIsCurrent(id, getCurrentId) {
|
|
1372
|
-
return () => getCurrentId() === id;
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
1034
|
// src/constraints/index.ts
|
|
1376
|
-
var
|
|
1035
|
+
var CONSTRAINT_TYPE = {
|
|
1377
1036
|
ASAP: "asap",
|
|
1378
1037
|
ALAP: "alap",
|
|
1379
1038
|
SNET: "snet",
|
|
@@ -2290,7 +1949,7 @@ function processConstraints(activityIds, adapter, plans) {
|
|
|
2290
1949
|
const activity = adapter.getActivity(id);
|
|
2291
1950
|
if (!activity) continue;
|
|
2292
1951
|
const type = activity.constraintType;
|
|
2293
|
-
if (!type || type ===
|
|
1952
|
+
if (!type || type === CONSTRAINT_TYPE.ASAP || type === CONSTRAINT_TYPE.ALAP) {
|
|
2294
1953
|
continue;
|
|
2295
1954
|
}
|
|
2296
1955
|
const bounds = computeConstraintBounds(activity, adapter);
|
|
@@ -2339,14 +1998,14 @@ function validateMilestoneConstraint(activity, successorStart) {
|
|
|
2339
1998
|
const { constraintType, constraintDate } = activity;
|
|
2340
1999
|
if (!constraintType || !constraintDate) return successorStart;
|
|
2341
2000
|
switch (constraintType) {
|
|
2342
|
-
case
|
|
2343
|
-
case
|
|
2001
|
+
case CONSTRAINT_TYPE.MSO:
|
|
2002
|
+
case CONSTRAINT_TYPE.MFO:
|
|
2344
2003
|
return new Date(constraintDate);
|
|
2345
|
-
case
|
|
2346
|
-
case
|
|
2004
|
+
case CONSTRAINT_TYPE.SNET:
|
|
2005
|
+
case CONSTRAINT_TYPE.FNET:
|
|
2347
2006
|
return constraintDate > successorStart ? new Date(constraintDate) : successorStart;
|
|
2348
|
-
case
|
|
2349
|
-
case
|
|
2007
|
+
case CONSTRAINT_TYPE.SNLT:
|
|
2008
|
+
case CONSTRAINT_TYPE.FNLT:
|
|
2350
2009
|
return constraintDate < successorStart ? new Date(constraintDate) : successorStart;
|
|
2351
2010
|
default:
|
|
2352
2011
|
return successorStart;
|
|
@@ -2475,7 +2134,7 @@ async function asapPass(orderedIds, links, adapter, options, isCurrent, plans) {
|
|
|
2475
2134
|
});
|
|
2476
2135
|
plan.earliestSchedulingStart = linkStart;
|
|
2477
2136
|
plan.earliestSchedulingEnd = plan.endDate;
|
|
2478
|
-
} else if (activity.constraintType ===
|
|
2137
|
+
} else if (activity.constraintType === CONSTRAINT_TYPE.MSO) {
|
|
2479
2138
|
if (plan.earliestStart) {
|
|
2480
2139
|
plan.startDate = plan.earliestStart;
|
|
2481
2140
|
plan.endDate = plan.earliestEnd ?? adapter.calculateEndDate({
|
|
@@ -2484,7 +2143,7 @@ async function asapPass(orderedIds, links, adapter, options, isCurrent, plans) {
|
|
|
2484
2143
|
task: activity
|
|
2485
2144
|
});
|
|
2486
2145
|
}
|
|
2487
|
-
} else if (activity.constraintType ===
|
|
2146
|
+
} else if (activity.constraintType === CONSTRAINT_TYPE.MFO) {
|
|
2488
2147
|
if (plan.latestStart) {
|
|
2489
2148
|
plan.startDate = plan.latestStart;
|
|
2490
2149
|
plan.endDate = plan.latestEnd ?? adapter.calculateEndDate({
|
|
@@ -2510,7 +2169,7 @@ async function alapPass(reversedIds, links, asapPlans, adapter, _options, isCurr
|
|
|
2510
2169
|
const activityCount = allActivities.length;
|
|
2511
2170
|
const alapActivityIds = [];
|
|
2512
2171
|
for (const activity of allActivities) {
|
|
2513
|
-
if (activity.constraintType ===
|
|
2172
|
+
if (activity.constraintType === CONSTRAINT_TYPE.ALAP) {
|
|
2514
2173
|
alapActivityIds.push(activity.id);
|
|
2515
2174
|
}
|
|
2516
2175
|
}
|
|
@@ -2557,7 +2216,7 @@ async function alapPass(reversedIds, links, asapPlans, adapter, _options, isCurr
|
|
|
2557
2216
|
sliceStart = yieldResult.newSliceStart;
|
|
2558
2217
|
const activity = adapter.getActivity(activityId);
|
|
2559
2218
|
if (!activity) continue;
|
|
2560
|
-
if (activity.constraintType !==
|
|
2219
|
+
if (activity.constraintType !== CONSTRAINT_TYPE.ALAP) continue;
|
|
2561
2220
|
if (!activity.autoScheduling) continue;
|
|
2562
2221
|
if (activity.progress === COMPLETED_PROGRESS) continue;
|
|
2563
2222
|
if (isSummary(activity.type, adapter.getChildren(activityId).length > 0))
|
|
@@ -3066,9 +2725,7 @@ function applyLinkCreates(links, deps) {
|
|
|
3066
2725
|
break;
|
|
3067
2726
|
}
|
|
3068
2727
|
duplicateKeys.set(key, linkId);
|
|
3069
|
-
if (existingGraphHasCycle &&
|
|
3070
|
-
// SCC reachability only if corrupt cyclic schedules become measurable.
|
|
3071
|
-
wouldIntroduceCycle(edges, {
|
|
2728
|
+
if (existingGraphHasCycle && wouldIntroduceCycle(edges, {
|
|
3072
2729
|
source: operation.source,
|
|
3073
2730
|
target: operation.target
|
|
3074
2731
|
})) {
|
|
@@ -3546,7 +3203,7 @@ function widenScopeToAlapActivities(group, allLinks, adapter) {
|
|
|
3546
3203
|
const widenedAlapKeys = /* @__PURE__ */ new Set();
|
|
3547
3204
|
for (const activity of adapter.getAllActivities()) {
|
|
3548
3205
|
const activityKey = String(activity.id);
|
|
3549
|
-
const isOutOfComponentAlap = activity.constraintType ===
|
|
3206
|
+
const isOutOfComponentAlap = activity.constraintType === CONSTRAINT_TYPE.ALAP && !idSet.has(activityKey);
|
|
3550
3207
|
if (!isOutOfComponentAlap) continue;
|
|
3551
3208
|
widenedAlapKeys.add(activityKey);
|
|
3552
3209
|
idSet.add(activityKey);
|
|
@@ -3632,6 +3289,84 @@ function roundProgressPerLevel(value) {
|
|
|
3632
3289
|
return Number(value.toFixed(2));
|
|
3633
3290
|
}
|
|
3634
3291
|
|
|
3292
|
+
// src/propagations/upward/progress-rollup.ts
|
|
3293
|
+
function recomputeAllProgressRollup(adapter) {
|
|
3294
|
+
for (const parentId of parentsDeepestFirst(adapter)) {
|
|
3295
|
+
rollupParent(parentId, adapter);
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
|
|
3299
|
+
for (const parentId of parentIdsDeepestFirst) {
|
|
3300
|
+
rollupParent(parentId, adapter);
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
function parentsDeepestFirst(adapter) {
|
|
3304
|
+
const parents = /* @__PURE__ */ new Set();
|
|
3305
|
+
adapter.forEachActivity((_activity, id) => {
|
|
3306
|
+
if (adapter.getChildren(id).length > 0) parents.add(id);
|
|
3307
|
+
});
|
|
3308
|
+
const depthById = /* @__PURE__ */ new Map();
|
|
3309
|
+
for (const id of parents) depthById.set(id, depthOf(id, adapter));
|
|
3310
|
+
return [...parents].sort(
|
|
3311
|
+
(a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
|
|
3312
|
+
);
|
|
3313
|
+
}
|
|
3314
|
+
function depthOf(id, adapter) {
|
|
3315
|
+
let depth = 0;
|
|
3316
|
+
let current = id;
|
|
3317
|
+
while (current && current !== "0") {
|
|
3318
|
+
if (!adapter.getActivity(current)) break;
|
|
3319
|
+
depth += 1;
|
|
3320
|
+
current = adapter.getParentId(current);
|
|
3321
|
+
}
|
|
3322
|
+
return depth;
|
|
3323
|
+
}
|
|
3324
|
+
function rollupParent(parentId, adapter) {
|
|
3325
|
+
const childIds = adapter.getChildren(parentId);
|
|
3326
|
+
if (childIds.length === 0) return;
|
|
3327
|
+
const children = [];
|
|
3328
|
+
for (const childId of childIds) {
|
|
3329
|
+
const child = adapter.getActivity(childId);
|
|
3330
|
+
if (!child) continue;
|
|
3331
|
+
children.push({
|
|
3332
|
+
progress: Number(child.progress ?? 0),
|
|
3333
|
+
ponderator: Number(child.ponderator ?? 0)
|
|
3334
|
+
});
|
|
3335
|
+
}
|
|
3336
|
+
applyWeightedProgressRollup(parentId, children, adapter);
|
|
3337
|
+
}
|
|
3338
|
+
function applyWeightedProgressRollup(parentId, children, adapter) {
|
|
3339
|
+
const parent = adapter.getActivity(parentId);
|
|
3340
|
+
if (!parent) return;
|
|
3341
|
+
const rollup = computeWeightedProgressRollup(children);
|
|
3342
|
+
if (rollup === null) {
|
|
3343
|
+
const fallback = adapter.getProgressFallback(parentId);
|
|
3344
|
+
if (fallback !== null) {
|
|
3345
|
+
adapter.setActivityField(parentId, COLUMN.PROGRESS, fallback);
|
|
3346
|
+
}
|
|
3347
|
+
return;
|
|
3348
|
+
}
|
|
3349
|
+
if (adapter.getProgressFallback(parentId) === null) {
|
|
3350
|
+
adapter.setProgressFallback(parentId, Number(parent.progress ?? 0));
|
|
3351
|
+
}
|
|
3352
|
+
adapter.setActivityField(
|
|
3353
|
+
parentId,
|
|
3354
|
+
COLUMN.PROGRESS,
|
|
3355
|
+
roundProgressPerLevel(rollup)
|
|
3356
|
+
);
|
|
3357
|
+
}
|
|
3358
|
+
function setExplicitSummaryProgressFallbacks(activityId, progress, adapter) {
|
|
3359
|
+
const pending = [activityId];
|
|
3360
|
+
while (pending.length > 0) {
|
|
3361
|
+
const currentId = pending.pop();
|
|
3362
|
+
if (currentId === void 0) continue;
|
|
3363
|
+
const children = adapter.getChildren(currentId);
|
|
3364
|
+
if (children.length === 0) continue;
|
|
3365
|
+
adapter.setProgressFallback(currentId, progress);
|
|
3366
|
+
pending.push(...children);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
|
|
3635
3370
|
// src/columns/real-work/compute.ts
|
|
3636
3371
|
function computeLeafRealWork(workHours, progress) {
|
|
3637
3372
|
return (Number(workHours) || 0) * (Number(progress) || 0) / 100;
|
|
@@ -3747,16 +3482,8 @@ function recomputeParentFromChildren(parentId, adapter, progressMode = "freeze-w
|
|
|
3747
3482
|
adapter.setActivityField(parentId, "startDate", newStart);
|
|
3748
3483
|
adapter.setActivityField(parentId, "endDate", newEnd);
|
|
3749
3484
|
adapter.setActivityField(parentId, "durationHours", durationHours);
|
|
3750
|
-
|
|
3751
|
-
aggregate.weightedChildren
|
|
3752
|
-
);
|
|
3753
|
-
const shouldWriteProgress = progressMode !== "skip" && (progressRollup !== null || progressMode === "zero-when-no-contribution");
|
|
3754
|
-
if (shouldWriteProgress) {
|
|
3755
|
-
adapter.setActivityField(
|
|
3756
|
-
parentId,
|
|
3757
|
-
"progress",
|
|
3758
|
-
roundProgressPerLevel(progressRollup ?? 0)
|
|
3759
|
-
);
|
|
3485
|
+
if (progressMode !== "skip") {
|
|
3486
|
+
applyWeightedProgressRollup(parentId, aggregate.weightedChildren, adapter);
|
|
3760
3487
|
}
|
|
3761
3488
|
if (recomputeRealWork) {
|
|
3762
3489
|
adapter.setActivityField(parentId, "realWorkHours", aggregate.realWorkSum);
|
|
@@ -3779,10 +3506,10 @@ function collectParentIds(adapter) {
|
|
|
3779
3506
|
}
|
|
3780
3507
|
function computeDepths(ids, adapter) {
|
|
3781
3508
|
const depths = /* @__PURE__ */ new Map();
|
|
3782
|
-
for (const id of ids) depths.set(id,
|
|
3509
|
+
for (const id of ids) depths.set(id, depthOf2(id, adapter));
|
|
3783
3510
|
return depths;
|
|
3784
3511
|
}
|
|
3785
|
-
function
|
|
3512
|
+
function depthOf2(id, adapter) {
|
|
3786
3513
|
let depth = 0;
|
|
3787
3514
|
let current = id;
|
|
3788
3515
|
while (current && !isRootParent(current)) {
|
|
@@ -3908,7 +3635,7 @@ var descriptionPipeline = {
|
|
|
3908
3635
|
|
|
3909
3636
|
// src/columns/shared/activity-predicates.ts
|
|
3910
3637
|
function effectiveConstraintType(activity) {
|
|
3911
|
-
return activity.constraintType ??
|
|
3638
|
+
return activity.constraintType ?? CONSTRAINT_TYPE.ASAP;
|
|
3912
3639
|
}
|
|
3913
3640
|
var PROGRESS_COMPLETE = COMPLETED_PROGRESS;
|
|
3914
3641
|
function isCompletedActivity(activity) {
|
|
@@ -4265,6 +3992,7 @@ function buildAncestorRollupCascade(activity, newValue, hierarchy) {
|
|
|
4265
3992
|
const mutations = [];
|
|
4266
3993
|
for (const id of chain) {
|
|
4267
3994
|
const rollup = computeWeightedProgress(id, overlay, hierarchy);
|
|
3995
|
+
if (rollup === null) continue;
|
|
4268
3996
|
overlay.set(id, rollup);
|
|
4269
3997
|
mutations.push({
|
|
4270
3998
|
activityId: id,
|
|
@@ -4278,7 +4006,8 @@ function computeWeightedProgress(parentId, overlay, hierarchy) {
|
|
|
4278
4006
|
progress: overlay.has(child.id) ? overlay.get(child.id) : child.progress,
|
|
4279
4007
|
ponderator: child.ponderator ?? 0
|
|
4280
4008
|
}));
|
|
4281
|
-
|
|
4009
|
+
const rollup = computeWeightedProgressRollup(children);
|
|
4010
|
+
return rollup === null ? null : Number(rollup.toFixed(2));
|
|
4282
4011
|
}
|
|
4283
4012
|
function buildRecursiveTrackingEvents(activity, newValue) {
|
|
4284
4013
|
return [
|
|
@@ -4646,7 +4375,7 @@ function checkIsWorkingDay(newDate, activity, ctx) {
|
|
|
4646
4375
|
return null;
|
|
4647
4376
|
}
|
|
4648
4377
|
function detectEndDateConstraintWarning(activity, newEndDate) {
|
|
4649
|
-
const cannotViolateStartPin = effectiveConstraintType(activity) ===
|
|
4378
|
+
const cannotViolateStartPin = effectiveConstraintType(activity) === CONSTRAINT_TYPE.MSO;
|
|
4650
4379
|
if (cannotViolateStartPin) return void 0;
|
|
4651
4380
|
const projectedDate = pickProjectedDateForConstraint(
|
|
4652
4381
|
effectiveConstraintType(activity),
|
|
@@ -4696,7 +4425,7 @@ function calculateNewDuration(activity, newEndDate, ctx) {
|
|
|
4696
4425
|
|
|
4697
4426
|
// src/columns/constraint-type/constraint-type-pipeline.ts
|
|
4698
4427
|
var VALID_CONSTRAINT_TYPES = new Set(
|
|
4699
|
-
Object.values(
|
|
4428
|
+
Object.values(CONSTRAINT_TYPE)
|
|
4700
4429
|
);
|
|
4701
4430
|
var constraintTypePipeline = {
|
|
4702
4431
|
targetField: "constraintType",
|
|
@@ -5477,6 +5206,12 @@ function runExpectedProgressBase(state, now, defaultBaseCalendarId = null) {
|
|
|
5477
5206
|
return computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId);
|
|
5478
5207
|
}
|
|
5479
5208
|
|
|
5209
|
+
// src/columns/status/constants.ts
|
|
5210
|
+
var DEFAULT_STATUS_CRITERIA = "Baseline";
|
|
5211
|
+
function resolveStatusCriteria(value) {
|
|
5212
|
+
return value === "Actual" ? "Actual" : DEFAULT_STATUS_CRITERIA;
|
|
5213
|
+
}
|
|
5214
|
+
|
|
5480
5215
|
// src/columns/status/compute.ts
|
|
5481
5216
|
var roundToTwoDecimals = (value) => Math.round(value * 100) / 100;
|
|
5482
5217
|
function resolveExpectedForStatus(activity, criteria) {
|
|
@@ -5504,7 +5239,7 @@ function applyStatusPass(state, criteria) {
|
|
|
5504
5239
|
resolveExpectedForStatus(activity, criteria)
|
|
5505
5240
|
);
|
|
5506
5241
|
if (activity.status !== status) {
|
|
5507
|
-
setActivityFieldDynamic(state, id,
|
|
5242
|
+
setActivityFieldDynamic(state, id, COLUMN.STATUS, status);
|
|
5508
5243
|
changed.push(id);
|
|
5509
5244
|
}
|
|
5510
5245
|
});
|
|
@@ -9277,10 +9012,10 @@ var FreeFloat = class {
|
|
|
9277
9012
|
this.durationCache = /* @__PURE__ */ new Map();
|
|
9278
9013
|
}
|
|
9279
9014
|
getFreeFloat() {
|
|
9280
|
-
const
|
|
9015
|
+
const PROGRESS = Number(this.activity.progress);
|
|
9281
9016
|
const CONSTRAINT = this.getConstraintType();
|
|
9282
9017
|
this.calculateFreeFloatOfLink(CONSTRAINT);
|
|
9283
|
-
const activityFreeFloat =
|
|
9018
|
+
const activityFreeFloat = PROGRESS === 100 ? 0 : this.getFreeFloatBaseConstraint(CONSTRAINT);
|
|
9284
9019
|
return {
|
|
9285
9020
|
activityFreeFloat,
|
|
9286
9021
|
linksFreeFloat: this.linksFreeFloatObject
|
|
@@ -9439,11 +9174,11 @@ var FreeFloat = class {
|
|
|
9439
9174
|
};
|
|
9440
9175
|
}
|
|
9441
9176
|
calculateMsoMfo(constraint) {
|
|
9442
|
-
const
|
|
9177
|
+
const CONSTRAINT_DATE = this.activity.constraint_date || /* @__PURE__ */ new Date();
|
|
9443
9178
|
const calculation = this.forwardMap.get(this.activity.id);
|
|
9444
9179
|
const DATE_TO_CALCULATE = constraint === CONSTRAINT_TYPES.MSO ? calculation?.es : calculation?.ef;
|
|
9445
9180
|
const freeSlack = this.calculationWithCalendar(
|
|
9446
|
-
|
|
9181
|
+
CONSTRAINT_DATE,
|
|
9447
9182
|
DATE_TO_CALCULATE
|
|
9448
9183
|
);
|
|
9449
9184
|
return Math.max(0, this.parseHoursToDays(freeSlack));
|
|
@@ -10223,24 +9958,82 @@ function resolveDerivedPasses(action, autoSchedule, options) {
|
|
|
10223
9958
|
|
|
10224
9959
|
// src/dispatch/shared/post-mutation.ts
|
|
10225
9960
|
async function runPostMutation(deps, args) {
|
|
10226
|
-
const
|
|
9961
|
+
const progressInvalidation = resolveProgressInvalidation(deps.adapter);
|
|
9962
|
+
const passes = resolvePasses(args, progressInvalidation);
|
|
10227
9963
|
if (passes.has(DERIVED_PASS.AUTOSCHEDULE)) {
|
|
10228
9964
|
await refreshMutatedParentBounds(deps.adapter, args);
|
|
10229
9965
|
}
|
|
10230
9966
|
const schedule = passes.has(DERIVED_PASS.AUTOSCHEDULE) ? await runAutoschedule(deps, args.autoscheduleFrom) : emptySchedule();
|
|
10231
|
-
await rollUpParentBounds(
|
|
9967
|
+
await rollUpParentBounds(
|
|
9968
|
+
deps.adapter,
|
|
9969
|
+
args,
|
|
9970
|
+
schedule.scheduledIds,
|
|
9971
|
+
passes,
|
|
9972
|
+
progressInvalidation
|
|
9973
|
+
);
|
|
10232
9974
|
await runDerivedRecomputes(deps, passes, args.now);
|
|
10233
9975
|
return schedule;
|
|
10234
9976
|
}
|
|
10235
|
-
function resolvePasses(args) {
|
|
9977
|
+
function resolvePasses(args, progressInvalidation) {
|
|
10236
9978
|
const requested = args.autoscheduleFrom !== null;
|
|
10237
9979
|
const ran = !args.options.skipAutoSchedule && requested;
|
|
10238
9980
|
const passes = new Set(
|
|
10239
9981
|
resolveDerivedPasses(args.action, { ran }, args.options)
|
|
10240
9982
|
);
|
|
10241
|
-
if (args.recomputeParentProgress
|
|
9983
|
+
if (args.recomputeParentProgress || progressInvalidation.affectedParents.size > 0) {
|
|
9984
|
+
passes.add(DERIVED_PASS.PARENT_PROGRESS);
|
|
9985
|
+
}
|
|
10242
9986
|
return passes;
|
|
10243
9987
|
}
|
|
9988
|
+
function resolveProgressInvalidation(adapter) {
|
|
9989
|
+
const affectedParents = /* @__PURE__ */ new Set();
|
|
9990
|
+
const dirtySeeds = /* @__PURE__ */ new Set();
|
|
9991
|
+
const journal = adapter.peekWriteCapture();
|
|
9992
|
+
if (!journal) return { affectedParents, dirtySeeds };
|
|
9993
|
+
const affectParent = (parentId) => {
|
|
9994
|
+
if (parentId === null || isRootParent(parentId)) return;
|
|
9995
|
+
const normalized2 = String(parentId);
|
|
9996
|
+
affectedParents.add(normalized2);
|
|
9997
|
+
const childId = adapter.getChildren(normalized2)[0];
|
|
9998
|
+
if (childId !== void 0) dirtySeeds.add(childId);
|
|
9999
|
+
};
|
|
10000
|
+
collectStructuralProgressInvalidations(adapter, journal.ops, affectParent);
|
|
10001
|
+
collectFieldProgressInvalidations(
|
|
10002
|
+
adapter,
|
|
10003
|
+
journal.before,
|
|
10004
|
+
dirtySeeds,
|
|
10005
|
+
affectParent
|
|
10006
|
+
);
|
|
10007
|
+
return { affectedParents, dirtySeeds };
|
|
10008
|
+
}
|
|
10009
|
+
function collectStructuralProgressInvalidations(adapter, operations, affectParent) {
|
|
10010
|
+
for (const operation of operations) {
|
|
10011
|
+
if (operation.kind === "insert") {
|
|
10012
|
+
const inserted = adapter.getActivity(operation.activityId);
|
|
10013
|
+
if (inserted) affectParent(inserted.parentId);
|
|
10014
|
+
} else if (operation.kind === "remove") {
|
|
10015
|
+
affectParent(operation.before.parentId);
|
|
10016
|
+
}
|
|
10017
|
+
}
|
|
10018
|
+
}
|
|
10019
|
+
function collectFieldProgressInvalidations(adapter, beforeById, dirtySeeds, affectParent) {
|
|
10020
|
+
for (const [activityId, before] of beforeById) {
|
|
10021
|
+
const after = adapter.getActivity(activityId);
|
|
10022
|
+
if (!after) continue;
|
|
10023
|
+
const progressChanged = !Object.is(before.progress, after.progress);
|
|
10024
|
+
const ponderatorChanged = !Object.is(before.ponderator, after.ponderator);
|
|
10025
|
+
const parentChanged = !Object.is(before.parentId, after.parentId);
|
|
10026
|
+
if (progressChanged || ponderatorChanged) {
|
|
10027
|
+
affectParent(after.parentId);
|
|
10028
|
+
dirtySeeds.add(String(activityId));
|
|
10029
|
+
}
|
|
10030
|
+
if (parentChanged) {
|
|
10031
|
+
affectParent(before.parentId);
|
|
10032
|
+
affectParent(after.parentId);
|
|
10033
|
+
dirtySeeds.add(String(activityId));
|
|
10034
|
+
}
|
|
10035
|
+
}
|
|
10036
|
+
}
|
|
10244
10037
|
async function runAutoschedule(deps, autoscheduleFrom) {
|
|
10245
10038
|
const options = autoscheduleFrom === "roots" ? {} : { triggerId: autoscheduleFrom };
|
|
10246
10039
|
const result = await deps.scheduler.schedule(options);
|
|
@@ -10268,18 +10061,36 @@ async function refreshMutatedParentBounds(adapter, args) {
|
|
|
10268
10061
|
if (mutated.size === 0) return;
|
|
10269
10062
|
await updateParentBoundsFromChildren(adapter, mutated, false);
|
|
10270
10063
|
}
|
|
10271
|
-
async function rollUpParentBounds(adapter, args, scheduledIds, passes) {
|
|
10064
|
+
async function rollUpParentBounds(adapter, args, scheduledIds, passes, progressInvalidation) {
|
|
10065
|
+
if (passes.has(DERIVED_PASS.PARENT_PROGRESS)) {
|
|
10066
|
+
restoreDemotedProgressFallbacks(
|
|
10067
|
+
adapter,
|
|
10068
|
+
progressInvalidation.affectedParents
|
|
10069
|
+
);
|
|
10070
|
+
}
|
|
10272
10071
|
const dirty = args.collectDirty ? args.collectDirty(scheduledIds) : collectDirtyForStructural(args.recomputeParentsFrom, scheduledIds);
|
|
10072
|
+
for (const activityId of progressInvalidation.dirtySeeds) {
|
|
10073
|
+
dirty.add(activityId);
|
|
10074
|
+
}
|
|
10273
10075
|
await updateParentBoundsFromChildren(
|
|
10274
10076
|
adapter,
|
|
10275
10077
|
dirty,
|
|
10276
10078
|
passes.has(DERIVED_PASS.PARENT_PROGRESS),
|
|
10277
10079
|
{
|
|
10278
10080
|
recomputeRealWork: passes.has(DERIVED_PASS.REAL_WORK),
|
|
10279
|
-
progressMode:
|
|
10081
|
+
progressMode: "freeze-when-no-contribution"
|
|
10280
10082
|
}
|
|
10281
10083
|
);
|
|
10282
10084
|
}
|
|
10085
|
+
function restoreDemotedProgressFallbacks(adapter, affectedParents) {
|
|
10086
|
+
for (const parentId of affectedParents) {
|
|
10087
|
+
if (adapter.hasChildren(parentId)) continue;
|
|
10088
|
+
const fallback = adapter.getProgressFallback(parentId);
|
|
10089
|
+
if (fallback === null) continue;
|
|
10090
|
+
adapter.setActivityField(parentId, "progress", fallback);
|
|
10091
|
+
adapter.setProgressFallback(parentId, null);
|
|
10092
|
+
}
|
|
10093
|
+
}
|
|
10283
10094
|
async function runDerivedRecomputes(deps, passes, now) {
|
|
10284
10095
|
if (passes.has(DERIVED_PASS.EXPECTED_PROGRESS) && now !== null) {
|
|
10285
10096
|
if (hasActiveBaseline(deps.adapter)) {
|
|
@@ -11506,9 +11317,8 @@ function buildParentMutations(input) {
|
|
|
11506
11317
|
if (wasPromotableLeaf) {
|
|
11507
11318
|
fields.type = PROMOTION_TARGET_TYPE;
|
|
11508
11319
|
if ((input.promotionSource ?? "create") === "create") {
|
|
11509
|
-
fields.constraintType =
|
|
11320
|
+
fields.constraintType = CONSTRAINT_TYPE.ASAP;
|
|
11510
11321
|
fields.constraintDate = null;
|
|
11511
|
-
fields.progress = 0;
|
|
11512
11322
|
}
|
|
11513
11323
|
}
|
|
11514
11324
|
return {
|
|
@@ -12647,8 +12457,6 @@ function dispatchSirSync(action, deps) {
|
|
|
12647
12457
|
id,
|
|
12648
12458
|
kind: "updated",
|
|
12649
12459
|
fields: { pendingRequestIds: { before, after } },
|
|
12650
|
-
// ISSUE-025: `after` must be the COMPLETE post-change entity; a partial
|
|
12651
|
-
// object crashes any consumer that projects the full snapshot.
|
|
12652
12460
|
after: structuredCloneActivity(updated)
|
|
12653
12461
|
};
|
|
12654
12462
|
return {
|
|
@@ -12663,60 +12471,6 @@ function dispatchSirSync(action, deps) {
|
|
|
12663
12471
|
};
|
|
12664
12472
|
}
|
|
12665
12473
|
|
|
12666
|
-
// src/propagations/upward/progress-rollup.ts
|
|
12667
|
-
function recomputeAllProgressRollup(adapter) {
|
|
12668
|
-
for (const parentId of parentsDeepestFirst(adapter)) {
|
|
12669
|
-
rollupParent(parentId, adapter);
|
|
12670
|
-
}
|
|
12671
|
-
}
|
|
12672
|
-
function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
|
|
12673
|
-
for (const parentId of parentIdsDeepestFirst) {
|
|
12674
|
-
rollupParent(parentId, adapter);
|
|
12675
|
-
}
|
|
12676
|
-
}
|
|
12677
|
-
function parentsDeepestFirst(adapter) {
|
|
12678
|
-
const parents = /* @__PURE__ */ new Set();
|
|
12679
|
-
adapter.forEachActivity((_activity, id) => {
|
|
12680
|
-
if (adapter.getChildren(id).length > 0) parents.add(id);
|
|
12681
|
-
});
|
|
12682
|
-
const depthById = /* @__PURE__ */ new Map();
|
|
12683
|
-
for (const id of parents) depthById.set(id, depthOf2(id, adapter));
|
|
12684
|
-
return [...parents].sort(
|
|
12685
|
-
(a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
|
|
12686
|
-
);
|
|
12687
|
-
}
|
|
12688
|
-
function depthOf2(id, adapter) {
|
|
12689
|
-
let depth = 0;
|
|
12690
|
-
let current = id;
|
|
12691
|
-
while (current && current !== "0") {
|
|
12692
|
-
if (!adapter.getActivity(current)) break;
|
|
12693
|
-
depth += 1;
|
|
12694
|
-
current = adapter.getParentId(current);
|
|
12695
|
-
}
|
|
12696
|
-
return depth;
|
|
12697
|
-
}
|
|
12698
|
-
function rollupParent(parentId, adapter) {
|
|
12699
|
-
const childIds = adapter.getChildren(parentId);
|
|
12700
|
-
if (childIds.length === 0) return;
|
|
12701
|
-
const children = [];
|
|
12702
|
-
for (const childId of childIds) {
|
|
12703
|
-
const child = adapter.getActivity(childId);
|
|
12704
|
-
if (!child) continue;
|
|
12705
|
-
children.push({
|
|
12706
|
-
progress: Number(child.progress ?? 0),
|
|
12707
|
-
ponderator: Number(child.ponderator ?? 0)
|
|
12708
|
-
});
|
|
12709
|
-
}
|
|
12710
|
-
const rollup = computeWeightedProgressRollup(children);
|
|
12711
|
-
if (rollup !== null) {
|
|
12712
|
-
adapter.setActivityField(
|
|
12713
|
-
parentId,
|
|
12714
|
-
COLUMN.PROGRESS,
|
|
12715
|
-
roundProgressPerLevel(rollup)
|
|
12716
|
-
);
|
|
12717
|
-
}
|
|
12718
|
-
}
|
|
12719
|
-
|
|
12720
12474
|
// src/dispatch/handlers/persistence-acknowledge.ts
|
|
12721
12475
|
function persistedOwnersOf(entities) {
|
|
12722
12476
|
const owners = /* @__PURE__ */ new Map();
|
|
@@ -13783,6 +13537,11 @@ async function dispatchActivitySetProgress(action, options, deps) {
|
|
|
13783
13537
|
const touchedIds = collectTouchedIds(action.activityId, changes);
|
|
13784
13538
|
const beforeSnap = await snapshotActivities(adapter, touchedIds);
|
|
13785
13539
|
applyFieldChanges(adapter, action.activityId, changes);
|
|
13540
|
+
setExplicitSummaryProgressFallbacks(
|
|
13541
|
+
action.activityId,
|
|
13542
|
+
action.newValue,
|
|
13543
|
+
adapter
|
|
13544
|
+
);
|
|
13786
13545
|
runPostProcessorsOnAdapter(
|
|
13787
13546
|
action.activityId,
|
|
13788
13547
|
changes.postProcessors ?? [],
|
|
@@ -17646,7 +17405,8 @@ var WriteCapture = class {
|
|
|
17646
17405
|
ops: [],
|
|
17647
17406
|
linkFieldCaptured: /* @__PURE__ */ new Set(),
|
|
17648
17407
|
correlativeBefore: /* @__PURE__ */ new Map(),
|
|
17649
|
-
scheduledBefore: /* @__PURE__ */ new Map()
|
|
17408
|
+
scheduledBefore: /* @__PURE__ */ new Map(),
|
|
17409
|
+
progressFallbackBefore: /* @__PURE__ */ new Map()
|
|
17650
17410
|
};
|
|
17651
17411
|
}
|
|
17652
17412
|
peek() {
|
|
@@ -17709,6 +17469,11 @@ var WriteCapture = class {
|
|
|
17709
17469
|
before: cloneLink(current)
|
|
17710
17470
|
});
|
|
17711
17471
|
}
|
|
17472
|
+
noteProgressFallback(activityId, current) {
|
|
17473
|
+
const journal = this._journal;
|
|
17474
|
+
if (!journal || journal.progressFallbackBefore.has(activityId)) return;
|
|
17475
|
+
journal.progressFallbackBefore.set(activityId, current);
|
|
17476
|
+
}
|
|
17712
17477
|
};
|
|
17713
17478
|
function cloneLink(link) {
|
|
17714
17479
|
return { ...link };
|
|
@@ -17878,11 +17643,83 @@ var HierarchyIndex = class {
|
|
|
17878
17643
|
}
|
|
17879
17644
|
};
|
|
17880
17645
|
|
|
17646
|
+
// src/internal/state/view-state.ts
|
|
17647
|
+
var ViewStateStore = class {
|
|
17648
|
+
checkedSet = /* @__PURE__ */ new Set();
|
|
17649
|
+
hiddenSet = /* @__PURE__ */ new Set();
|
|
17650
|
+
activeFilter = null;
|
|
17651
|
+
activeOrder = null;
|
|
17652
|
+
isChecked(activityId) {
|
|
17653
|
+
return this.checkedSet.has(activityId);
|
|
17654
|
+
}
|
|
17655
|
+
isVisible(activityId) {
|
|
17656
|
+
return !this.hiddenSet.has(activityId);
|
|
17657
|
+
}
|
|
17658
|
+
hiddenIds() {
|
|
17659
|
+
return [...this.hiddenSet];
|
|
17660
|
+
}
|
|
17661
|
+
getActiveFilter() {
|
|
17662
|
+
return this.activeFilter;
|
|
17663
|
+
}
|
|
17664
|
+
setActiveFilter(nextFilter) {
|
|
17665
|
+
this.activeFilter = nextFilter;
|
|
17666
|
+
}
|
|
17667
|
+
getActiveOrder() {
|
|
17668
|
+
return this.activeOrder;
|
|
17669
|
+
}
|
|
17670
|
+
setActiveOrder(nextOrder) {
|
|
17671
|
+
this.activeOrder = nextOrder;
|
|
17672
|
+
}
|
|
17673
|
+
checkedIds() {
|
|
17674
|
+
return [...this.checkedSet];
|
|
17675
|
+
}
|
|
17676
|
+
checkedCount() {
|
|
17677
|
+
return this.checkedSet.size;
|
|
17678
|
+
}
|
|
17679
|
+
setChecked(activityId, nextChecked) {
|
|
17680
|
+
if (nextChecked === this.checkedSet.has(activityId)) return false;
|
|
17681
|
+
if (nextChecked) this.checkedSet.add(activityId);
|
|
17682
|
+
else this.checkedSet.delete(activityId);
|
|
17683
|
+
return true;
|
|
17684
|
+
}
|
|
17685
|
+
setVisible(activityId, nextVisible) {
|
|
17686
|
+
if (nextVisible === !this.hiddenSet.has(activityId)) return false;
|
|
17687
|
+
if (nextVisible) this.hiddenSet.delete(activityId);
|
|
17688
|
+
else this.hiddenSet.add(activityId);
|
|
17689
|
+
return true;
|
|
17690
|
+
}
|
|
17691
|
+
forget(activityId) {
|
|
17692
|
+
this.checkedSet.delete(activityId);
|
|
17693
|
+
this.hiddenSet.delete(activityId);
|
|
17694
|
+
}
|
|
17695
|
+
hydrate(seed2) {
|
|
17696
|
+
this.checkedSet = new Set(seed2.checkedIds ?? []);
|
|
17697
|
+
this.hiddenSet = new Set(seed2.hiddenIds ?? []);
|
|
17698
|
+
this.activeFilter = null;
|
|
17699
|
+
this.activeOrder = null;
|
|
17700
|
+
}
|
|
17701
|
+
snapshot() {
|
|
17702
|
+
return {
|
|
17703
|
+
checked: new Set(this.checkedSet),
|
|
17704
|
+
hidden: new Set(this.hiddenSet),
|
|
17705
|
+
activeFilter: this.activeFilter,
|
|
17706
|
+
activeOrder: this.activeOrder
|
|
17707
|
+
};
|
|
17708
|
+
}
|
|
17709
|
+
restore(snapshot) {
|
|
17710
|
+
this.checkedSet = new Set(snapshot.checked);
|
|
17711
|
+
this.hiddenSet = new Set(snapshot.hidden);
|
|
17712
|
+
this.activeFilter = snapshot.activeFilter;
|
|
17713
|
+
this.activeOrder = snapshot.activeOrder;
|
|
17714
|
+
}
|
|
17715
|
+
};
|
|
17716
|
+
|
|
17881
17717
|
// src/internal/state/schedule-state.ts
|
|
17882
17718
|
var ScheduleState = class _ScheduleState {
|
|
17883
17719
|
_activities = /* @__PURE__ */ new Map();
|
|
17884
17720
|
_lastStartDate = /* @__PURE__ */ new Map();
|
|
17885
17721
|
_promotionSnapshot = /* @__PURE__ */ new Map();
|
|
17722
|
+
_progressFallback = /* @__PURE__ */ new Map();
|
|
17886
17723
|
_links = /* @__PURE__ */ new Map();
|
|
17887
17724
|
_outgoing = /* @__PURE__ */ new Map();
|
|
17888
17725
|
_incoming = /* @__PURE__ */ new Map();
|
|
@@ -17943,6 +17780,7 @@ var ScheduleState = class _ScheduleState {
|
|
|
17943
17780
|
cloneDomainValue(snapshot)
|
|
17944
17781
|
])
|
|
17945
17782
|
);
|
|
17783
|
+
fork._progressFallback = new Map(this._progressFallback);
|
|
17946
17784
|
fork._flags = cloneDomainValue(this._flags);
|
|
17947
17785
|
fork._filterProjection = cloneDomainValue(this._filterProjection);
|
|
17948
17786
|
return fork;
|
|
@@ -17996,6 +17834,17 @@ var ScheduleState = class _ScheduleState {
|
|
|
17996
17834
|
this._capturePromotionSnapshotOnce();
|
|
17997
17835
|
this._promotionSnapshot.set(String(activityId), snapshot);
|
|
17998
17836
|
}
|
|
17837
|
+
getProgressFallback(activityId) {
|
|
17838
|
+
return this._progressFallback.get(String(activityId)) ?? null;
|
|
17839
|
+
}
|
|
17840
|
+
setProgressFallback(activityId, value) {
|
|
17841
|
+
const key = String(activityId);
|
|
17842
|
+
const current = this._progressFallback.get(key) ?? null;
|
|
17843
|
+
if (Object.is(current, value)) return;
|
|
17844
|
+
this._writeCapture.noteProgressFallback(key, current);
|
|
17845
|
+
if (value === null) this._progressFallback.delete(key);
|
|
17846
|
+
else this._progressFallback.set(key, value);
|
|
17847
|
+
}
|
|
17999
17848
|
_capturePromotionSnapshotOnce() {
|
|
18000
17849
|
if (this._writeCapture.peek() === null) return;
|
|
18001
17850
|
if (this._promotionSnapshotBefore === null) {
|
|
@@ -18056,28 +17905,6 @@ var ScheduleState = class _ScheduleState {
|
|
|
18056
17905
|
this._viewState.setActiveOrder(nextOrder);
|
|
18057
17906
|
this.invalidateDerivedOrder();
|
|
18058
17907
|
}
|
|
18059
|
-
setRelativePlacementPin(activityId, pin) {
|
|
18060
|
-
this._viewState.setRelativePlacementPin(String(activityId), pin);
|
|
18061
|
-
this.invalidateVisualOrderIds();
|
|
18062
|
-
}
|
|
18063
|
-
getRelativePlacementPins() {
|
|
18064
|
-
return this._viewState.getRelativePlacementPins();
|
|
18065
|
-
}
|
|
18066
|
-
restoreRelativePlacementPins(pins) {
|
|
18067
|
-
this._viewState.restoreRelativePlacementPins(pins);
|
|
18068
|
-
this._filterProjection = null;
|
|
18069
|
-
this.invalidateVisualOrderIds();
|
|
18070
|
-
}
|
|
18071
|
-
/**
|
|
18072
|
-
* Rebuild-on-demand, memoized: at most one build per invalidation, never one
|
|
18073
|
-
* per comparison. getChildrenInVisualOrder asks for this once and then sorts a
|
|
18074
|
-
* whole sibling group with it, and collectBranchOrder walks every branch, so a
|
|
18075
|
-
* build per read would be thousands per dispatch.
|
|
18076
|
-
*
|
|
18077
|
-
* The factory reads hoursPerDay and the collation locale at build time, so a
|
|
18078
|
-
* rebuilt comparator always reflects the current context — that is what keeps
|
|
18079
|
-
* ordering and filtering from seeing two different hoursPerDay.
|
|
18080
|
-
*/
|
|
18081
17908
|
getOrderComparator() {
|
|
18082
17909
|
const activeOrder = this._viewState.getActiveOrder();
|
|
18083
17910
|
if (activeOrder === null) {
|
|
@@ -18088,12 +17915,6 @@ var ScheduleState = class _ScheduleState {
|
|
|
18088
17915
|
this._cache.orderComparator = this._buildOrderComparator(activeOrder);
|
|
18089
17916
|
return this._cache.orderComparator;
|
|
18090
17917
|
}
|
|
18091
|
-
/**
|
|
18092
|
-
* Both order caches, always together. The comparator decides the sequence, so
|
|
18093
|
-
* a rebuilt comparator with a surviving sequence would paint the old order.
|
|
18094
|
-
* invalidateVisualOrderIds stays separate on purpose: a structural change
|
|
18095
|
-
* moves rows without touching the rules, so the comparator is still valid.
|
|
18096
|
-
*/
|
|
18097
17918
|
invalidateDerivedOrder() {
|
|
18098
17919
|
this._cache.orderComparator = null;
|
|
18099
17920
|
this._cache.visualOrderIds = null;
|
|
@@ -18274,11 +18095,8 @@ var ScheduleState = class _ScheduleState {
|
|
|
18274
18095
|
const activity = this.getActivity(activityId);
|
|
18275
18096
|
if (activity) this._writeCapture.noteRemove(String(activityId), activity);
|
|
18276
18097
|
const key = String(activityId);
|
|
18277
|
-
|
|
18278
|
-
|
|
18279
|
-
({ referenceId }) => referenceId === key
|
|
18280
|
-
);
|
|
18281
|
-
if (this._viewState.isChecked(key) || !this._viewState.isVisible(key) || relativePlacementPins.has(key) || hasDependentPin) {
|
|
18098
|
+
this.setProgressFallback(key, null);
|
|
18099
|
+
if (this._viewState.isChecked(key) || !this._viewState.isVisible(key)) {
|
|
18282
18100
|
this._captureViewStateOnce();
|
|
18283
18101
|
}
|
|
18284
18102
|
this._viewState.forget(key);
|
|
@@ -18302,7 +18120,13 @@ var ScheduleState = class _ScheduleState {
|
|
|
18302
18120
|
restoreFromCapture() {
|
|
18303
18121
|
const journal = this._writeCapture.peek();
|
|
18304
18122
|
if (!journal) return;
|
|
18305
|
-
const {
|
|
18123
|
+
const {
|
|
18124
|
+
ops,
|
|
18125
|
+
before,
|
|
18126
|
+
correlativeBefore,
|
|
18127
|
+
scheduledBefore,
|
|
18128
|
+
progressFallbackBefore
|
|
18129
|
+
} = journal;
|
|
18306
18130
|
this._undoLinkAdds(ops);
|
|
18307
18131
|
this._undoInserts(ops);
|
|
18308
18132
|
this._reInsertRemovedActivities(ops);
|
|
@@ -18311,6 +18135,7 @@ var ScheduleState = class _ScheduleState {
|
|
|
18311
18135
|
this._restoreCorrelatives(correlativeBefore);
|
|
18312
18136
|
this._restoreActivityFields(scheduledBefore);
|
|
18313
18137
|
this._restoreActivityFields(before);
|
|
18138
|
+
this._restoreProgressFallbacks(progressFallbackBefore);
|
|
18314
18139
|
if (this._viewStateBefore !== null) {
|
|
18315
18140
|
this._viewState.restore(this._viewStateBefore);
|
|
18316
18141
|
this._filterProjection = null;
|
|
@@ -18326,6 +18151,12 @@ var ScheduleState = class _ScheduleState {
|
|
|
18326
18151
|
this._cache.visualOrderIds = null;
|
|
18327
18152
|
this._hierarchy.markDirty();
|
|
18328
18153
|
}
|
|
18154
|
+
_restoreProgressFallbacks(before) {
|
|
18155
|
+
for (const [activityId, value] of before) {
|
|
18156
|
+
if (value === null) this._progressFallback.delete(activityId);
|
|
18157
|
+
else this._progressFallback.set(activityId, value);
|
|
18158
|
+
}
|
|
18159
|
+
}
|
|
18329
18160
|
_restoreCorrelatives(correlativeBefore) {
|
|
18330
18161
|
for (const [id, before] of correlativeBefore) {
|
|
18331
18162
|
const live = this._activities.get(id);
|
|
@@ -18539,15 +18370,15 @@ function buildHistoryChangeSet(changes) {
|
|
|
18539
18370
|
links: linksWithoutAfter
|
|
18540
18371
|
});
|
|
18541
18372
|
}
|
|
18542
|
-
function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks,
|
|
18373
|
+
function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks, progressFallbackBefore, progressFallbackAfter) {
|
|
18543
18374
|
return {
|
|
18544
18375
|
changeSet,
|
|
18545
18376
|
beforeSnap,
|
|
18546
18377
|
beforeLinks: resetDerivedLinkSnapshots(beforeLinks),
|
|
18547
18378
|
afterSnap,
|
|
18548
18379
|
afterLinks: resetDerivedLinkSnapshots(afterLinks),
|
|
18549
|
-
|
|
18550
|
-
|
|
18380
|
+
progressFallbackBefore,
|
|
18381
|
+
progressFallbackAfter
|
|
18551
18382
|
};
|
|
18552
18383
|
}
|
|
18553
18384
|
function resetDerivedLinkSnapshots(snapshots) {
|
|
@@ -18850,8 +18681,10 @@ function applyChangeSetSide(state, entry, side) {
|
|
|
18850
18681
|
);
|
|
18851
18682
|
}
|
|
18852
18683
|
}
|
|
18853
|
-
const
|
|
18854
|
-
|
|
18684
|
+
const progressFallbacks = side === "before" ? entry.progressFallbackBefore : entry.progressFallbackAfter;
|
|
18685
|
+
for (const [activityId, value] of progressFallbacks ?? []) {
|
|
18686
|
+
state.setProgressFallback(activityId, value);
|
|
18687
|
+
}
|
|
18855
18688
|
}
|
|
18856
18689
|
|
|
18857
18690
|
// src/dispatch/undo/undo-recorder.ts
|
|
@@ -20743,6 +20576,7 @@ async function runInitialPasses(deps) {
|
|
|
20743
20576
|
normalizeLoadedConstraintDates(state);
|
|
20744
20577
|
recomputeCanonicalRealWork(state);
|
|
20745
20578
|
if (skipAutoSchedule) {
|
|
20579
|
+
recomputeAllProgressRollup(state);
|
|
20746
20580
|
if (now) {
|
|
20747
20581
|
applyExpectedProgressLive(state, now);
|
|
20748
20582
|
applyStatusPass(state, sector.statusCriteria);
|
|
@@ -20754,6 +20588,7 @@ async function runInitialPasses(deps) {
|
|
|
20754
20588
|
normalizeMilestoneConstraintDatesForDisplay(state);
|
|
20755
20589
|
recomputeSkippedLeafEnds(state);
|
|
20756
20590
|
await updateParentBoundsFromChildren(state, void 0, false);
|
|
20591
|
+
recomputeAllProgressRollup(state);
|
|
20757
20592
|
if (now) {
|
|
20758
20593
|
applyExpectedProgressLive(state, now);
|
|
20759
20594
|
applyStatusPass(state, sector.statusCriteria);
|
|
@@ -21196,41 +21031,12 @@ function collectChangedActivities(changes, adapter) {
|
|
|
21196
21031
|
}
|
|
21197
21032
|
return activities;
|
|
21198
21033
|
}
|
|
21199
|
-
function changesAffectRelativePinProjection(changes, changedActivities, adapter, pins) {
|
|
21200
|
-
if (pins.size === 0) return false;
|
|
21201
|
-
if (changes.activities.some(
|
|
21202
|
-
(change) => change.kind === "created" && pins.has(String(change.id))
|
|
21203
|
-
)) {
|
|
21204
|
-
return true;
|
|
21205
|
-
}
|
|
21206
|
-
const referenceIds = new Set(
|
|
21207
|
-
[...pins.values()].map(({ referenceId }) => String(referenceId))
|
|
21208
|
-
);
|
|
21209
|
-
for (const activity of changedActivities) {
|
|
21210
|
-
let activityId = String(activity.id);
|
|
21211
|
-
while (activityId !== null) {
|
|
21212
|
-
if (referenceIds.has(activityId)) return true;
|
|
21213
|
-
activityId = adapter.getParentId(activityId);
|
|
21214
|
-
}
|
|
21215
|
-
}
|
|
21216
|
-
return false;
|
|
21217
|
-
}
|
|
21218
21034
|
function isCurrentFilterProjection(projection, filter, context) {
|
|
21219
21035
|
if (projection === null || projection.filter !== filter) return false;
|
|
21220
21036
|
const hasCurrentHours = projection.context.hoursPerDay === context.hoursPerDay;
|
|
21221
21037
|
const hasCurrentLocale = projection.context.locale === context.locale;
|
|
21222
21038
|
return hasCurrentHours && hasCurrentLocale;
|
|
21223
21039
|
}
|
|
21224
|
-
function relativePlacementPinsEqual(left, right) {
|
|
21225
|
-
if (left.size !== right.size) return false;
|
|
21226
|
-
for (const [activityId, pin] of left) {
|
|
21227
|
-
const other = right.get(activityId);
|
|
21228
|
-
if (other === void 0 || other.referenceId !== pin.referenceId || other.branchParentId !== pin.branchParentId || other.side !== pin.side) {
|
|
21229
|
-
return false;
|
|
21230
|
-
}
|
|
21231
|
-
}
|
|
21232
|
-
return true;
|
|
21233
|
-
}
|
|
21234
21040
|
var ScheduleCore = class _ScheduleCore {
|
|
21235
21041
|
_activityClipboard = { value: null };
|
|
21236
21042
|
_status = SCHEDULE_CORE_STATUS.READY;
|
|
@@ -21239,29 +21045,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21239
21045
|
_undo = new UndoRecorder();
|
|
21240
21046
|
_opQueue = Promise.resolve();
|
|
21241
21047
|
_scheduleRevision = 0;
|
|
21242
|
-
/**
|
|
21243
|
-
* Revision counting mutations that have been ADMITTED, whether or not they
|
|
21244
|
-
* have changed anything yet. `_scheduleRevision` counts the ones that
|
|
21245
|
-
* actually did.
|
|
21246
|
-
*
|
|
21247
|
-
* INVARIANT: `_pendingScheduleRevision >= _scheduleRevision`, and equality
|
|
21248
|
-
* means no mutation is in flight.
|
|
21249
|
-
*
|
|
21250
|
-
* The two exist separately because the useful instant and the knowable
|
|
21251
|
-
* instant are not the same one. A critical-path calculation becomes garbage
|
|
21252
|
-
* the moment the next mutation is admitted, but whether that mutation is
|
|
21253
|
-
* substantive is only knowable once its ChangeSet exists, which is hundreds
|
|
21254
|
-
* of milliseconds later at project scale. Measured live on a 12268-activity
|
|
21255
|
-
* project: the cancellation flag flipped 929 ms into a 930 ms calculation,
|
|
21256
|
-
* 812 into 812 and 785 into 785, because the job's apply block queues behind
|
|
21257
|
-
* the very dispatch whose completion cancels it. Cancellation and job end
|
|
21258
|
-
* were the same event, so every discarded job ran the whole calculation.
|
|
21259
|
-
*
|
|
21260
|
-
* Splitting the counter buys the early signal without moving the meaning of
|
|
21261
|
-
* `_scheduleRevision`, whose three readers (`isCriticalPathSettled`,
|
|
21262
|
-
* `createDateGesturePreview` and the job's own `isCurrent`) are all written
|
|
21263
|
-
* against "the state actually changed".
|
|
21264
|
-
*/
|
|
21265
21048
|
_pendingScheduleRevision = 0;
|
|
21266
21049
|
_criticalPathRevision = -1;
|
|
21267
21050
|
_activeCriticalPath = null;
|
|
@@ -21374,13 +21157,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21374
21157
|
this.assertReady();
|
|
21375
21158
|
return readAllActivities(this.coreRuntime.state);
|
|
21376
21159
|
}
|
|
21377
|
-
/**
|
|
21378
|
-
* Read del plan de indent (ISSUE-080): los padres destino DISTINTOS bajo los
|
|
21379
|
-
* que quedarían las actividades si se indentaran ahora. Es exactamente la
|
|
21380
|
-
* planificación que ejecuta el handler (`planIndentMoves`, autoridad única),
|
|
21381
|
-
* expuesta para que la frontera pueda correr el protocolo de conversión a
|
|
21382
|
-
* madre (chequeo backend + modal) ANTES de despachar. Solo lecturas.
|
|
21383
|
-
*/
|
|
21384
21160
|
getIndentTargetParentIds(activityIds) {
|
|
21385
21161
|
this.assertReady();
|
|
21386
21162
|
const plan = planIndentMoves(
|
|
@@ -21533,7 +21309,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21533
21309
|
this.assertReady();
|
|
21534
21310
|
return this._saveTracker.hasUnsavedChanges();
|
|
21535
21311
|
}
|
|
21536
|
-
/** Read-only revision; moves once per substantive mutation. */
|
|
21537
21312
|
getScheduleRevision() {
|
|
21538
21313
|
return this._scheduleRevision;
|
|
21539
21314
|
}
|
|
@@ -21579,24 +21354,10 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21579
21354
|
);
|
|
21580
21355
|
return workPromise;
|
|
21581
21356
|
}
|
|
21582
|
-
/**
|
|
21583
|
-
* Marks a mutation as admitted and invalidates the calculation in flight.
|
|
21584
|
-
*
|
|
21585
|
-
* Called BEFORE `_enqueue`, which is the point of the whole thing: the wait
|
|
21586
|
-
* in the operation queue is part of the window a running calculation wastes,
|
|
21587
|
-
* and it is the longest part of it when several mutations are already
|
|
21588
|
-
* queued.
|
|
21589
|
-
*
|
|
21590
|
-
* `dispatchChangesSchedulingState` is a pure function of the action, so this
|
|
21591
|
-
* decision needs no state and cannot be wrong about the action's nature. What
|
|
21592
|
-
* it cannot know yet is whether the mutation will produce anything, which is
|
|
21593
|
-
* what `_settleScheduleMutation` reconciles afterwards.
|
|
21594
|
-
*/
|
|
21595
21357
|
_beginScheduleMutation(action) {
|
|
21596
21358
|
if (!dispatchChangesSchedulingState(action)) return false;
|
|
21597
21359
|
return this._admitScheduleMutation();
|
|
21598
21360
|
}
|
|
21599
|
-
/** Undo and redo have no action to classify: reaching them IS the mutation. */
|
|
21600
21361
|
_admitScheduleMutation() {
|
|
21601
21362
|
this._pendingScheduleRevision++;
|
|
21602
21363
|
if (this._activeCriticalPath) {
|
|
@@ -21604,30 +21365,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21604
21365
|
}
|
|
21605
21366
|
return true;
|
|
21606
21367
|
}
|
|
21607
|
-
/**
|
|
21608
|
-
* Closes a mutation admitted by `_beginScheduleMutation`, on EVERY exit path.
|
|
21609
|
-
*
|
|
21610
|
-
* `changedState` false means the mutation was admitted and produced nothing
|
|
21611
|
-
* (rejected, non-substantive, or rolled back). The pending revision walks
|
|
21612
|
-
* back so the invariant holds and `isCriticalPathSettled` keeps telling the
|
|
21613
|
-
* truth, and the calculation this mutation killed for nothing is re-armed.
|
|
21614
|
-
*
|
|
21615
|
-
* The re-arm goes through the queue and that is not incidental. Started
|
|
21616
|
-
* outside it, the calculation would run immediately while the next queued
|
|
21617
|
-
* mutation is still waiting, and that mutation would kill it again on
|
|
21618
|
-
* admission: a cancel-and-restart treadmill burning a fresh project-wide deep
|
|
21619
|
-
* copy per lap. Inside the queue the restart cannot happen until the queue
|
|
21620
|
-
* drains, so at most one calculation is armed per settled mutation. The burst
|
|
21621
|
-
* scenario will NOT catch a regression here, because there every dispatch
|
|
21622
|
-
* succeeds and this path is never taken.
|
|
21623
|
-
*
|
|
21624
|
-
* It re-arms through `recomputeCriticalPath` rather than enqueueing the job
|
|
21625
|
-
* directly, because the queue slot must NOT await the job: the job's own
|
|
21626
|
-
* apply block needs a later slot on this same queue, so awaiting it from
|
|
21627
|
-
* inside a slot deadlocks the core. `recomputeCriticalPath` already has the
|
|
21628
|
-
* shape that returns the job's promise out of the slot instead of awaiting
|
|
21629
|
-
* it, and it keeps `_criticalPathReady` pointing at the live calculation.
|
|
21630
|
-
*/
|
|
21631
21368
|
_settleScheduleMutation(admitted, changedState) {
|
|
21632
21369
|
if (!admitted) return;
|
|
21633
21370
|
if (changedState) return;
|
|
@@ -21678,8 +21415,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21678
21415
|
dateFormat: this.coreRuntime.sector.dateFormat
|
|
21679
21416
|
});
|
|
21680
21417
|
const historyPolicy = getDispatchHistoryPolicy(action);
|
|
21681
|
-
const capturesRelativePlacementPins = action.kind === "activity-create" || action.kind === "activity-delete" || action.kind === "activity-batch" && action.mode === "replace";
|
|
21682
|
-
const relativePlacementPinsBefore = capturesRelativePlacementPins ? new Map(this.coreRuntime.state.getRelativePlacementPins()) : void 0;
|
|
21683
21418
|
const generatorSnapshot = [
|
|
21684
21419
|
this.coreRuntime.activityIdGenerator.snapshot(),
|
|
21685
21420
|
this.coreRuntime.linkIdGenerator.snapshot(),
|
|
@@ -21688,6 +21423,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21688
21423
|
this.coreRuntime.state.beginWriteCapture();
|
|
21689
21424
|
this.coreRuntime.customIdTracker.beginCustomIdTransaction();
|
|
21690
21425
|
let result;
|
|
21426
|
+
let progressFallbackBefore;
|
|
21691
21427
|
try {
|
|
21692
21428
|
result = await performDispatch(action, options, {
|
|
21693
21429
|
adapter: this.coreRuntime.state,
|
|
@@ -21708,6 +21444,10 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21708
21444
|
)?.id ?? null,
|
|
21709
21445
|
now: this.coreRuntime.clock ? endOfLocalDay(this.coreRuntime.clock()) : null
|
|
21710
21446
|
});
|
|
21447
|
+
const fallbackBefore = this.coreRuntime.state.peekWriteCapture()?.progressFallbackBefore;
|
|
21448
|
+
if (fallbackBefore && fallbackBefore.size > 0) {
|
|
21449
|
+
progressFallbackBefore = new Map(fallbackBefore);
|
|
21450
|
+
}
|
|
21711
21451
|
if (!result.ok) this._rollback(generatorSnapshot);
|
|
21712
21452
|
} catch (error) {
|
|
21713
21453
|
this._rollback(generatorSnapshot);
|
|
@@ -21716,17 +21456,17 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21716
21456
|
this.coreRuntime.state.endWriteCapture();
|
|
21717
21457
|
this.coreRuntime.customIdTracker.commitCustomIdTransaction();
|
|
21718
21458
|
}
|
|
21719
|
-
if (result.ok) this._recordRelativePlacementPin(action, result.changes);
|
|
21720
21459
|
if (result.ok && historyPolicy === "record" && changeSetIsSubstantive(result.changes)) {
|
|
21721
21460
|
const created = captureCreatedSnapshots(
|
|
21722
21461
|
this.coreRuntime.state,
|
|
21723
21462
|
result.changes
|
|
21724
21463
|
);
|
|
21725
|
-
const
|
|
21726
|
-
|
|
21727
|
-
|
|
21728
|
-
|
|
21729
|
-
|
|
21464
|
+
const progressFallbackAfter = progressFallbackBefore ? new Map(
|
|
21465
|
+
Array.from(progressFallbackBefore.keys(), (activityId) => [
|
|
21466
|
+
activityId,
|
|
21467
|
+
this.coreRuntime.state.getProgressFallback(activityId)
|
|
21468
|
+
])
|
|
21469
|
+
) : void 0;
|
|
21730
21470
|
this._undo.record(
|
|
21731
21471
|
buildUndoEntry(
|
|
21732
21472
|
buildHistoryChangeSet(result.changes),
|
|
@@ -21734,8 +21474,8 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21734
21474
|
result.__beforeLinks,
|
|
21735
21475
|
created.afterSnap,
|
|
21736
21476
|
created.afterLinks,
|
|
21737
|
-
|
|
21738
|
-
|
|
21477
|
+
progressFallbackBefore,
|
|
21478
|
+
progressFallbackAfter
|
|
21739
21479
|
),
|
|
21740
21480
|
computeCoalesceKey(action),
|
|
21741
21481
|
Date.now()
|
|
@@ -21783,11 +21523,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21783
21523
|
return operation;
|
|
21784
21524
|
}
|
|
21785
21525
|
isCriticalPathSettled() {
|
|
21786
|
-
return this._criticalPathRevision === this._scheduleRevision &&
|
|
21787
|
-
// about to be stale. Without this term `whenCriticalPathSettled` would
|
|
21788
|
-
// spin: it would keep arming calculations that `isCurrent` kills on their
|
|
21789
|
-
// first check, each one paying the project-wide deep copy first.
|
|
21790
|
-
this._pendingScheduleRevision === this._scheduleRevision && this._activeCriticalPath === null;
|
|
21526
|
+
return this._criticalPathRevision === this._scheduleRevision && this._pendingScheduleRevision === this._scheduleRevision && this._activeCriticalPath === null;
|
|
21791
21527
|
}
|
|
21792
21528
|
async whenCriticalPathSettled() {
|
|
21793
21529
|
while (!this.isCriticalPathSettled()) {
|
|
@@ -21803,34 +21539,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21803
21539
|
const merged = this._reapplyViewState(result.changes);
|
|
21804
21540
|
return merged === null ? result : { ...result, changes: merged };
|
|
21805
21541
|
}
|
|
21806
|
-
_recordRelativePlacementPin(action, changes) {
|
|
21807
|
-
const state = this.coreRuntime.state;
|
|
21808
|
-
if (action.kind !== "activity-create") return;
|
|
21809
|
-
const referenceId = action.afterSiblingId ?? action.beforeSiblingId ?? (action.eventSource === "Creation button (+)" && action.parentId !== ROOT_PARENT_ID ? action.parentId : void 0);
|
|
21810
|
-
if (referenceId === void 0) return;
|
|
21811
|
-
const created = changes.activities.find(({ kind }) => kind === "created");
|
|
21812
|
-
if (created === void 0) return;
|
|
21813
|
-
state.setRelativePlacementPin(created.id, {
|
|
21814
|
-
referenceId,
|
|
21815
|
-
branchParentId: action.parentId,
|
|
21816
|
-
side: action.beforeSiblingId === void 0 ? "after" : "before"
|
|
21817
|
-
});
|
|
21818
|
-
}
|
|
21819
|
-
/**
|
|
21820
|
-
* The single place the two view-state passes are chained. Dispatch, undo and
|
|
21821
|
-
* redo all route through here: when this existed only inside the dispatch
|
|
21822
|
-
* path, undo and redo reapplied the filter and forgot the order, so an edit
|
|
21823
|
-
* that moved a row and was then undone left the row in its new position.
|
|
21824
|
-
*
|
|
21825
|
-
* The sequence between the passes is indifferent. Filter and order are
|
|
21826
|
-
* orthogonal projections over the same tree — the filter decides which rows
|
|
21827
|
-
* exist on screen and never reads the order; the order sequences every
|
|
21828
|
-
* sibling group from the hierarchy index and never reads visibility. Either
|
|
21829
|
-
* sequence produces the same ChangeSet.
|
|
21830
|
-
*
|
|
21831
|
-
* Both passes answer null while their state is inactive, so an unfiltered,
|
|
21832
|
-
* unsorted schedule pays two property reads.
|
|
21833
|
-
*/
|
|
21834
21542
|
_reapplyViewState(changes) {
|
|
21835
21543
|
const withFilter = this._reapplyActiveFilter(changes);
|
|
21836
21544
|
const sequenced = this._emitTouchedBranchOrder(withFilter ?? changes);
|
|
@@ -21840,24 +21548,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21840
21548
|
);
|
|
21841
21549
|
return withOrder ?? sequenced.changes ?? withFilter;
|
|
21842
21550
|
}
|
|
21843
|
-
/**
|
|
21844
|
-
* Emits `order` for the branches this mutation resequenced, when no user order
|
|
21845
|
-
* is active.
|
|
21846
|
-
*
|
|
21847
|
-
* The contract is that `order` reports a CHANGED SEQUENCE, not the presence of
|
|
21848
|
-
* a sort. Tying emission to the cause instead of the effect is what produced
|
|
21849
|
-
* the undo bug and, later, the reparent ones: without an active order a move,
|
|
21850
|
-
* an indent, an outdent or the undo of any of them rearranged rows and said
|
|
21851
|
-
* nothing, so an incremental consumer kept the old sequence. The undo of a
|
|
21852
|
-
* reparent was the worst of them — it carried neither `order` nor a single
|
|
21853
|
-
* correlativeId, so the position was not recoverable by any consumer.
|
|
21854
|
-
*
|
|
21855
|
-
* The touched branches are derived from the ChangeSet rather than accumulated
|
|
21856
|
-
* in the state: an entity whose parentId or correlativeId moved, plus the
|
|
21857
|
-
* parents of created and deleted rows, is exactly the set of branches whose
|
|
21858
|
-
* sequence can differ. That keeps this linear in the blast radius, adds
|
|
21859
|
-
* nothing to the write path, and cannot leak across dispatches.
|
|
21860
|
-
*/
|
|
21861
21551
|
_emitTouchedBranchOrder(changes) {
|
|
21862
21552
|
const adapter = this.coreRuntime.state;
|
|
21863
21553
|
const touchedParents = collectResequencedParents(
|
|
@@ -21874,15 +21564,6 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21874
21564
|
if (order.length === 0) return { changes: null, touchedParents };
|
|
21875
21565
|
return { changes: { ...changes, order }, touchedParents };
|
|
21876
21566
|
}
|
|
21877
|
-
/**
|
|
21878
|
-
* Re-sequences the grid after any mutation that could have changed a value the
|
|
21879
|
-
* active order sorts by. Ordering is a view over the data, so an edit that
|
|
21880
|
-
* moves a row past its sibling must move the row, exactly as the filter makes
|
|
21881
|
-
* a no-longer-matching row disappear.
|
|
21882
|
-
*
|
|
21883
|
-
* Production only re-sorts after a bar drag; diverging from that is a
|
|
21884
|
-
* deliberate product decision, not an oversight.
|
|
21885
|
-
*/
|
|
21886
21567
|
_reapplyActiveOrder(changes, resequencedParents) {
|
|
21887
21568
|
const adapter = this.coreRuntime.state;
|
|
21888
21569
|
if (adapter.getActiveOrder() === null) return null;
|
|
@@ -21917,22 +21598,15 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21917
21598
|
context
|
|
21918
21599
|
);
|
|
21919
21600
|
const changedActivities = changesRequireFilterProjectionRebuild(changes) ? null : collectChangedActivities(changes, adapter);
|
|
21920
|
-
const relativePlacementPins = adapter.getRelativePlacementPins();
|
|
21921
21601
|
let affectedIds;
|
|
21922
21602
|
let visibleIds;
|
|
21923
|
-
const needsProjectionRebuild = changedActivities === null || !projectionIsCurrent
|
|
21924
|
-
changes,
|
|
21925
|
-
changedActivities,
|
|
21926
|
-
adapter,
|
|
21927
|
-
relativePlacementPins
|
|
21928
|
-
);
|
|
21603
|
+
const needsProjectionRebuild = changedActivities === null || !projectionIsCurrent;
|
|
21929
21604
|
if (needsProjectionRebuild) {
|
|
21930
21605
|
const rebuiltProjection = buildFilterProjection({
|
|
21931
21606
|
activities: adapter.getAllActivities(),
|
|
21932
21607
|
parentOf: (activityId) => adapter.getParentId(activityId),
|
|
21933
21608
|
filter,
|
|
21934
|
-
context
|
|
21935
|
-
relativePlacementPins
|
|
21609
|
+
context
|
|
21936
21610
|
});
|
|
21937
21611
|
adapter.setFilterProjection(rebuiltProjection);
|
|
21938
21612
|
visibleIds = rebuiltProjection.visibleIds;
|
|
@@ -21988,11 +21662,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21988
21662
|
this.coreRuntime.baseCalendars
|
|
21989
21663
|
)
|
|
21990
21664
|
);
|
|
21991
|
-
const isCurrent = () => !cancellation.cancelled && this._status !== SCHEDULE_CORE_STATUS.DESTROYED && this._scheduleRevision === revision &&
|
|
21992
|
-
// garbage. Without this term the calculation only learns it is obsolete
|
|
21993
|
-
// when the mutation finishes, which measured live is the same instant the
|
|
21994
|
-
// job itself ends.
|
|
21995
|
-
this._pendingScheduleRevision === this._scheduleRevision;
|
|
21665
|
+
const isCurrent = () => !cancellation.cancelled && this._status !== SCHEDULE_CORE_STATUS.DESTROYED && this._scheduleRevision === revision && this._pendingScheduleRevision === this._scheduleRevision;
|
|
21996
21666
|
const promise = (async () => {
|
|
21997
21667
|
const calculatedFields = await computeCriticalPathFields(
|
|
21998
21668
|
isolatedState,
|
|
@@ -22345,7 +22015,7 @@ var CREATION_KIND = {
|
|
|
22345
22015
|
exports.ACTIVITY_TYPE = ACTIVITY_TYPE;
|
|
22346
22016
|
exports.CALENDAR_UNIT = CALENDAR_UNIT;
|
|
22347
22017
|
exports.COLUMN = COLUMN;
|
|
22348
|
-
exports.CONSTRAINT_TYPE =
|
|
22018
|
+
exports.CONSTRAINT_TYPE = CONSTRAINT_TYPE;
|
|
22349
22019
|
exports.CONSTRAINT_TYPE_TO_LABEL = CONSTRAINT_TYPE_TO_LABEL;
|
|
22350
22020
|
exports.CREATION_KIND = CREATION_KIND;
|
|
22351
22021
|
exports.DEFAULT_HOURS_PER_DAY = DEFAULT_HOURS_PER_DAY;
|