@outbuild-company/schedule-core 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +319 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +319 -128
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -942,6 +942,7 @@ declare class ScheduleCore {
|
|
|
942
942
|
isCriticalPathSettled(): boolean;
|
|
943
943
|
whenCriticalPathSettled(): Promise<void>;
|
|
944
944
|
private _withReappliedViewState;
|
|
945
|
+
private _recordRelativePlacementPin;
|
|
945
946
|
/**
|
|
946
947
|
* The single place the two view-state passes are chained. Dispatch, undo and
|
|
947
948
|
* redo all route through here: when this existed only inside the dispatch
|
package/dist/index.d.ts
CHANGED
|
@@ -942,6 +942,7 @@ declare class ScheduleCore {
|
|
|
942
942
|
isCriticalPathSettled(): boolean;
|
|
943
943
|
whenCriticalPathSettled(): Promise<void>;
|
|
944
944
|
private _withReappliedViewState;
|
|
945
|
+
private _recordRelativePlacementPin;
|
|
945
946
|
/**
|
|
946
947
|
* The single place the two view-state passes are chained. Dispatch, undo and
|
|
947
948
|
* redo all route through here: when this existed only inside the dispatch
|
package/dist/index.js
CHANGED
|
@@ -418,6 +418,107 @@ function getFieldDescriptor(field) {
|
|
|
418
418
|
return FIELD_REGISTRY[field] ?? null;
|
|
419
419
|
}
|
|
420
420
|
|
|
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
|
+
|
|
421
522
|
// src/internal/filter/evaluate-filter.ts
|
|
422
523
|
function toTargetDate(value) {
|
|
423
524
|
if (value instanceof Date) return value;
|
|
@@ -560,13 +661,8 @@ function seedFilterProjection(input) {
|
|
|
560
661
|
);
|
|
561
662
|
}
|
|
562
663
|
const isMatch = matchesFilter(activity, filter, context);
|
|
563
|
-
|
|
564
|
-
visibleReferenceCounts.set(
|
|
565
|
-
activityId,
|
|
566
|
-
(isMatch ? 1 : 0) + (isPinned ? 1 : 0)
|
|
567
|
-
);
|
|
664
|
+
visibleReferenceCounts.set(activityId, isMatch ? 1 : 0);
|
|
568
665
|
if (isMatch) matchedIds.add(activityId);
|
|
569
|
-
if (isPinned) pinnedVisibleIds.add(activityId);
|
|
570
666
|
}
|
|
571
667
|
return {
|
|
572
668
|
matchedIds,
|
|
@@ -576,6 +672,29 @@ function seedFilterProjection(input) {
|
|
|
576
672
|
remainingChildren
|
|
577
673
|
};
|
|
578
674
|
}
|
|
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
|
+
}
|
|
579
698
|
function propagateVisibleReferenceCounts(seed2) {
|
|
580
699
|
const { visibleReferenceCounts, parentIds, remainingChildren } = seed2;
|
|
581
700
|
const pendingIds = [];
|
|
@@ -607,6 +726,7 @@ function collectVisibleIds(visibleReferenceCounts) {
|
|
|
607
726
|
function buildFilterProjection(input) {
|
|
608
727
|
const seed2 = seedFilterProjection(input);
|
|
609
728
|
propagateVisibleReferenceCounts(seed2);
|
|
729
|
+
applyRelativePlacementPins(seed2, input.relativePlacementPins);
|
|
610
730
|
const visibleIds = collectVisibleIds(seed2.visibleReferenceCounts);
|
|
611
731
|
return {
|
|
612
732
|
filter: input.filter,
|
|
@@ -794,7 +914,8 @@ function resolveFilter(adapter, filter, hoursPerDay) {
|
|
|
794
914
|
activities,
|
|
795
915
|
parentOf: (activityId) => adapter.getParentId(activityId),
|
|
796
916
|
filter,
|
|
797
|
-
context: buildFilterContext(hoursPerDay)
|
|
917
|
+
context: buildFilterContext(hoursPerDay),
|
|
918
|
+
relativePlacementPins: adapter.getRelativePlacementPins()
|
|
798
919
|
});
|
|
799
920
|
return { visibleIds: projection.visibleIds, projection };
|
|
800
921
|
}
|
|
@@ -845,25 +966,118 @@ function normalizeParentKey(parent) {
|
|
|
845
966
|
|
|
846
967
|
// src/internal/hierarchy/visual-order.ts
|
|
847
968
|
var NOT_SET_SORT_VALUE = Number.MAX_SAFE_INTEGER;
|
|
848
|
-
|
|
969
|
+
var EMPTY_RELATIVE_PLACEMENT_PINS = /* @__PURE__ */ new Map();
|
|
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)) {
|
|
849
990
|
const children = collectChildrenSnapshots(parentId, adapter);
|
|
850
991
|
const userOrder = adapter.getOrderComparator?.() ?? null;
|
|
851
992
|
children.sort(
|
|
852
993
|
userOrder === null ? compareActivitiesInVisualOrder : (a, b) => userOrder(a, b) || compareActivitiesInVisualOrder(a, b)
|
|
853
994
|
);
|
|
854
|
-
return
|
|
995
|
+
return applyRelativePlacementPins2(
|
|
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;
|
|
855
1064
|
}
|
|
856
1065
|
function iterateInVisualOrder(adapter) {
|
|
857
1066
|
const result = [];
|
|
1067
|
+
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
858
1068
|
const visit = (activity) => {
|
|
859
1069
|
result.push(activity);
|
|
860
|
-
const childIds = getChildrenInVisualOrder(
|
|
1070
|
+
const childIds = getChildrenInVisualOrder(
|
|
1071
|
+
String(activity.id),
|
|
1072
|
+
adapter,
|
|
1073
|
+
pinIndex
|
|
1074
|
+
);
|
|
861
1075
|
for (const childId of childIds) {
|
|
862
1076
|
const child = adapter.getActivity(childId);
|
|
863
1077
|
if (child) visit(child);
|
|
864
1078
|
}
|
|
865
1079
|
};
|
|
866
|
-
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter);
|
|
1080
|
+
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter, pinIndex);
|
|
867
1081
|
for (const rootId of rootIds) {
|
|
868
1082
|
const root = adapter.getActivity(rootId);
|
|
869
1083
|
if (root) visit(root);
|
|
@@ -924,8 +1138,9 @@ function setHas(set, id) {
|
|
|
924
1138
|
// src/dispatch/shared/collect-branch-order.ts
|
|
925
1139
|
function collectBranchOrder(adapter) {
|
|
926
1140
|
const branches = [];
|
|
1141
|
+
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
927
1142
|
const visit = (parentId) => {
|
|
928
|
-
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
1143
|
+
const childIds = getChildrenInVisualOrder(parentId, adapter, pinIndex);
|
|
929
1144
|
if (childIds.length > 1) {
|
|
930
1145
|
branches.push({ parentId, childIds });
|
|
931
1146
|
}
|
|
@@ -938,8 +1153,9 @@ function collectBranchOrder(adapter) {
|
|
|
938
1153
|
}
|
|
939
1154
|
function collectBranchOrderForParents(adapter, parentIds) {
|
|
940
1155
|
const branches = [];
|
|
1156
|
+
const pinIndex = buildRelativePlacementPinIndex(adapter);
|
|
941
1157
|
for (const parentId of parentIds) {
|
|
942
|
-
const childIds = getChildrenInVisualOrder(parentId, adapter);
|
|
1158
|
+
const childIds = getChildrenInVisualOrder(parentId, adapter, pinIndex);
|
|
943
1159
|
if (childIds.length > 1) branches.push({ parentId, childIds });
|
|
944
1160
|
}
|
|
945
1161
|
return branches;
|
|
@@ -4084,8 +4300,8 @@ var costPipeline = {
|
|
|
4084
4300
|
}
|
|
4085
4301
|
return canEdit();
|
|
4086
4302
|
},
|
|
4087
|
-
parseInput(rawValue
|
|
4088
|
-
if (String(rawValue).trim() === "") return parsed(
|
|
4303
|
+
parseInput(rawValue) {
|
|
4304
|
+
if (String(rawValue).trim() === "") return parsed(0);
|
|
4089
4305
|
const numericValue = parseFloat(String(rawValue));
|
|
4090
4306
|
if (Number.isNaN(numericValue)) return parseError("not_a_number");
|
|
4091
4307
|
return parsed(numericValue);
|
|
@@ -4134,8 +4350,8 @@ var usedCostPipeline = {
|
|
|
4134
4350
|
}
|
|
4135
4351
|
return canEdit();
|
|
4136
4352
|
},
|
|
4137
|
-
parseInput(rawValue
|
|
4138
|
-
if (String(rawValue).trim() === "") return parsed(
|
|
4353
|
+
parseInput(rawValue) {
|
|
4354
|
+
if (String(rawValue).trim() === "") return parsed(0);
|
|
4139
4355
|
const numericValue = parseFloat(String(rawValue));
|
|
4140
4356
|
if (Number.isNaN(numericValue)) return parseError("not_a_number");
|
|
4141
4357
|
return parsed(numericValue);
|
|
@@ -17660,77 +17876,6 @@ var HierarchyIndex = class {
|
|
|
17660
17876
|
}
|
|
17661
17877
|
};
|
|
17662
17878
|
|
|
17663
|
-
// src/internal/state/view-state.ts
|
|
17664
|
-
var ViewStateStore = class {
|
|
17665
|
-
checkedSet = /* @__PURE__ */ new Set();
|
|
17666
|
-
hiddenSet = /* @__PURE__ */ new Set();
|
|
17667
|
-
activeFilter = null;
|
|
17668
|
-
activeOrder = null;
|
|
17669
|
-
isChecked(activityId) {
|
|
17670
|
-
return this.checkedSet.has(activityId);
|
|
17671
|
-
}
|
|
17672
|
-
isVisible(activityId) {
|
|
17673
|
-
return !this.hiddenSet.has(activityId);
|
|
17674
|
-
}
|
|
17675
|
-
hiddenIds() {
|
|
17676
|
-
return [...this.hiddenSet];
|
|
17677
|
-
}
|
|
17678
|
-
getActiveFilter() {
|
|
17679
|
-
return this.activeFilter;
|
|
17680
|
-
}
|
|
17681
|
-
setActiveFilter(nextFilter) {
|
|
17682
|
-
this.activeFilter = nextFilter;
|
|
17683
|
-
}
|
|
17684
|
-
getActiveOrder() {
|
|
17685
|
-
return this.activeOrder;
|
|
17686
|
-
}
|
|
17687
|
-
setActiveOrder(nextOrder) {
|
|
17688
|
-
this.activeOrder = nextOrder;
|
|
17689
|
-
}
|
|
17690
|
-
checkedIds() {
|
|
17691
|
-
return [...this.checkedSet];
|
|
17692
|
-
}
|
|
17693
|
-
checkedCount() {
|
|
17694
|
-
return this.checkedSet.size;
|
|
17695
|
-
}
|
|
17696
|
-
setChecked(activityId, nextChecked) {
|
|
17697
|
-
if (nextChecked === this.checkedSet.has(activityId)) return false;
|
|
17698
|
-
if (nextChecked) this.checkedSet.add(activityId);
|
|
17699
|
-
else this.checkedSet.delete(activityId);
|
|
17700
|
-
return true;
|
|
17701
|
-
}
|
|
17702
|
-
setVisible(activityId, nextVisible) {
|
|
17703
|
-
if (nextVisible === !this.hiddenSet.has(activityId)) return false;
|
|
17704
|
-
if (nextVisible) this.hiddenSet.delete(activityId);
|
|
17705
|
-
else this.hiddenSet.add(activityId);
|
|
17706
|
-
return true;
|
|
17707
|
-
}
|
|
17708
|
-
forget(activityId) {
|
|
17709
|
-
this.checkedSet.delete(activityId);
|
|
17710
|
-
this.hiddenSet.delete(activityId);
|
|
17711
|
-
}
|
|
17712
|
-
hydrate(seed2) {
|
|
17713
|
-
this.checkedSet = new Set(seed2.checkedIds ?? []);
|
|
17714
|
-
this.hiddenSet = new Set(seed2.hiddenIds ?? []);
|
|
17715
|
-
this.activeFilter = null;
|
|
17716
|
-
this.activeOrder = null;
|
|
17717
|
-
}
|
|
17718
|
-
snapshot() {
|
|
17719
|
-
return {
|
|
17720
|
-
checked: new Set(this.checkedSet),
|
|
17721
|
-
hidden: new Set(this.hiddenSet),
|
|
17722
|
-
activeFilter: this.activeFilter,
|
|
17723
|
-
activeOrder: this.activeOrder
|
|
17724
|
-
};
|
|
17725
|
-
}
|
|
17726
|
-
restore(snapshot) {
|
|
17727
|
-
this.checkedSet = new Set(snapshot.checked);
|
|
17728
|
-
this.hiddenSet = new Set(snapshot.hidden);
|
|
17729
|
-
this.activeFilter = snapshot.activeFilter;
|
|
17730
|
-
this.activeOrder = snapshot.activeOrder;
|
|
17731
|
-
}
|
|
17732
|
-
};
|
|
17733
|
-
|
|
17734
17879
|
// src/internal/state/schedule-state.ts
|
|
17735
17880
|
var ScheduleState = class _ScheduleState {
|
|
17736
17881
|
_activities = /* @__PURE__ */ new Map();
|
|
@@ -17909,6 +18054,18 @@ var ScheduleState = class _ScheduleState {
|
|
|
17909
18054
|
this._viewState.setActiveOrder(nextOrder);
|
|
17910
18055
|
this.invalidateDerivedOrder();
|
|
17911
18056
|
}
|
|
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
|
+
}
|
|
17912
18069
|
/**
|
|
17913
18070
|
* Rebuild-on-demand, memoized: at most one build per invalidation, never one
|
|
17914
18071
|
* per comparison. getChildrenInVisualOrder asks for this once and then sorts a
|
|
@@ -18115,10 +18272,14 @@ var ScheduleState = class _ScheduleState {
|
|
|
18115
18272
|
const activity = this.getActivity(activityId);
|
|
18116
18273
|
if (activity) this._writeCapture.noteRemove(String(activityId), activity);
|
|
18117
18274
|
const key = String(activityId);
|
|
18118
|
-
|
|
18275
|
+
const relativePlacementPins = this._viewState.getRelativePlacementPins();
|
|
18276
|
+
const hasDependentPin = [...relativePlacementPins.values()].some(
|
|
18277
|
+
({ referenceId }) => referenceId === key
|
|
18278
|
+
);
|
|
18279
|
+
if (this._viewState.isChecked(key) || !this._viewState.isVisible(key) || relativePlacementPins.has(key) || hasDependentPin) {
|
|
18119
18280
|
this._captureViewStateOnce();
|
|
18120
|
-
this._viewState.forget(key);
|
|
18121
18281
|
}
|
|
18282
|
+
this._viewState.forget(key);
|
|
18122
18283
|
this._activities.delete(activityId);
|
|
18123
18284
|
if (this._lastStartDate.has(String(activityId))) {
|
|
18124
18285
|
this._captureLastStartDateOnce();
|
|
@@ -18376,13 +18537,15 @@ function buildHistoryChangeSet(changes) {
|
|
|
18376
18537
|
links: linksWithoutAfter
|
|
18377
18538
|
});
|
|
18378
18539
|
}
|
|
18379
|
-
function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks) {
|
|
18540
|
+
function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks, relativePlacementPinsBefore, relativePlacementPinsAfter) {
|
|
18380
18541
|
return {
|
|
18381
18542
|
changeSet,
|
|
18382
18543
|
beforeSnap,
|
|
18383
18544
|
beforeLinks: resetDerivedLinkSnapshots(beforeLinks),
|
|
18384
18545
|
afterSnap,
|
|
18385
|
-
afterLinks: resetDerivedLinkSnapshots(afterLinks)
|
|
18546
|
+
afterLinks: resetDerivedLinkSnapshots(afterLinks),
|
|
18547
|
+
relativePlacementPinsBefore,
|
|
18548
|
+
relativePlacementPinsAfter
|
|
18386
18549
|
};
|
|
18387
18550
|
}
|
|
18388
18551
|
function resetDerivedLinkSnapshots(snapshots) {
|
|
@@ -18685,6 +18848,8 @@ function applyChangeSetSide(state, entry, side) {
|
|
|
18685
18848
|
);
|
|
18686
18849
|
}
|
|
18687
18850
|
}
|
|
18851
|
+
const pins = side === "before" ? entry.relativePlacementPinsBefore : entry.relativePlacementPinsAfter;
|
|
18852
|
+
if (pins !== void 0) state.restoreRelativePlacementPins(pins);
|
|
18688
18853
|
}
|
|
18689
18854
|
|
|
18690
18855
|
// src/dispatch/undo/undo-recorder.ts
|
|
@@ -21029,12 +21194,41 @@ function collectChangedActivities(changes, adapter) {
|
|
|
21029
21194
|
}
|
|
21030
21195
|
return activities;
|
|
21031
21196
|
}
|
|
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
|
+
}
|
|
21032
21216
|
function isCurrentFilterProjection(projection, filter, context) {
|
|
21033
21217
|
if (projection === null || projection.filter !== filter) return false;
|
|
21034
21218
|
const hasCurrentHours = projection.context.hoursPerDay === context.hoursPerDay;
|
|
21035
21219
|
const hasCurrentLocale = projection.context.locale === context.locale;
|
|
21036
21220
|
return hasCurrentHours && hasCurrentLocale;
|
|
21037
21221
|
}
|
|
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
|
+
}
|
|
21038
21232
|
var ScheduleCore = class _ScheduleCore {
|
|
21039
21233
|
_activityClipboard = { value: null };
|
|
21040
21234
|
_status = SCHEDULE_CORE_STATUS.READY;
|
|
@@ -21482,6 +21676,8 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21482
21676
|
dateFormat: this.coreRuntime.sector.dateFormat
|
|
21483
21677
|
});
|
|
21484
21678
|
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;
|
|
21485
21681
|
const generatorSnapshot = [
|
|
21486
21682
|
this.coreRuntime.activityIdGenerator.snapshot(),
|
|
21487
21683
|
this.coreRuntime.linkIdGenerator.snapshot(),
|
|
@@ -21518,18 +21714,26 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21518
21714
|
this.coreRuntime.state.endWriteCapture();
|
|
21519
21715
|
this.coreRuntime.customIdTracker.commitCustomIdTransaction();
|
|
21520
21716
|
}
|
|
21717
|
+
if (result.ok) this._recordRelativePlacementPin(action, result.changes);
|
|
21521
21718
|
if (result.ok && historyPolicy === "record" && changeSetIsSubstantive(result.changes)) {
|
|
21522
21719
|
const created = captureCreatedSnapshots(
|
|
21523
21720
|
this.coreRuntime.state,
|
|
21524
21721
|
result.changes
|
|
21525
21722
|
);
|
|
21723
|
+
const relativePlacementPinsAfter = capturesRelativePlacementPins ? new Map(this.coreRuntime.state.getRelativePlacementPins()) : void 0;
|
|
21724
|
+
const relativePlacementPinsChanged = relativePlacementPinsBefore !== void 0 && relativePlacementPinsAfter !== void 0 && !relativePlacementPinsEqual(
|
|
21725
|
+
relativePlacementPinsBefore,
|
|
21726
|
+
relativePlacementPinsAfter
|
|
21727
|
+
);
|
|
21526
21728
|
this._undo.record(
|
|
21527
21729
|
buildUndoEntry(
|
|
21528
21730
|
buildHistoryChangeSet(result.changes),
|
|
21529
21731
|
result.__beforeSnap,
|
|
21530
21732
|
result.__beforeLinks,
|
|
21531
21733
|
created.afterSnap,
|
|
21532
|
-
created.afterLinks
|
|
21734
|
+
created.afterLinks,
|
|
21735
|
+
relativePlacementPinsChanged ? relativePlacementPinsBefore : void 0,
|
|
21736
|
+
relativePlacementPinsChanged ? relativePlacementPinsAfter : void 0
|
|
21533
21737
|
),
|
|
21534
21738
|
computeCoalesceKey(action),
|
|
21535
21739
|
Date.now()
|
|
@@ -21597,6 +21801,19 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21597
21801
|
const merged = this._reapplyViewState(result.changes);
|
|
21598
21802
|
return merged === null ? result : { ...result, changes: merged };
|
|
21599
21803
|
}
|
|
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
|
+
}
|
|
21600
21817
|
/**
|
|
21601
21818
|
* The single place the two view-state passes are chained. Dispatch, undo and
|
|
21602
21819
|
* redo all route through here: when this existed only inside the dispatch
|
|
@@ -21619,39 +21836,7 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21619
21836
|
sequenced.changes ?? withFilter ?? changes,
|
|
21620
21837
|
sequenced.touchedParents
|
|
21621
21838
|
);
|
|
21622
|
-
|
|
21623
|
-
const finalChanges = reapplied ?? changes;
|
|
21624
|
-
const createdIds = finalChanges.activities.filter((change) => change.kind === "created").map((change) => String(change.id));
|
|
21625
|
-
if (createdIds.length === 0) return reapplied;
|
|
21626
|
-
const createdAndAncestors = new Set(createdIds);
|
|
21627
|
-
const filterProjection = this.coreRuntime.state.getFilterProjection();
|
|
21628
|
-
for (const createdId of createdIds) {
|
|
21629
|
-
if (filterProjection !== null) {
|
|
21630
|
-
filterProjection.pinnedVisibleIds.add(createdId);
|
|
21631
|
-
}
|
|
21632
|
-
let activityId = createdId;
|
|
21633
|
-
while (activityId !== null && activityId !== ROOT_PARENT_ID) {
|
|
21634
|
-
createdAndAncestors.add(activityId);
|
|
21635
|
-
if (filterProjection !== null) {
|
|
21636
|
-
filterProjection.visibleIds.add(activityId);
|
|
21637
|
-
filterProjection.visibleReferenceCounts.set(
|
|
21638
|
-
activityId,
|
|
21639
|
-
(filterProjection.visibleReferenceCounts.get(activityId) ?? 0) + 1
|
|
21640
|
-
);
|
|
21641
|
-
}
|
|
21642
|
-
activityId = this.coreRuntime.state.getParentId(activityId);
|
|
21643
|
-
}
|
|
21644
|
-
}
|
|
21645
|
-
const createdVisibility = applyVisibleSet(
|
|
21646
|
-
this.coreRuntime.state,
|
|
21647
|
-
createdAndAncestors,
|
|
21648
|
-
createdAndAncestors
|
|
21649
|
-
);
|
|
21650
|
-
if (createdVisibility.length === 0) return reapplied;
|
|
21651
|
-
return {
|
|
21652
|
-
...finalChanges,
|
|
21653
|
-
viewState: [...finalChanges.viewState ?? [], ...createdVisibility]
|
|
21654
|
-
};
|
|
21839
|
+
return withOrder ?? sequenced.changes ?? withFilter;
|
|
21655
21840
|
}
|
|
21656
21841
|
/**
|
|
21657
21842
|
* Emits `order` for the branches this mutation resequenced, when no user order
|
|
@@ -21730,16 +21915,22 @@ var ScheduleCore = class _ScheduleCore {
|
|
|
21730
21915
|
context
|
|
21731
21916
|
);
|
|
21732
21917
|
const changedActivities = changesRequireFilterProjectionRebuild(changes) ? null : collectChangedActivities(changes, adapter);
|
|
21918
|
+
const relativePlacementPins = adapter.getRelativePlacementPins();
|
|
21733
21919
|
let affectedIds;
|
|
21734
21920
|
let visibleIds;
|
|
21735
|
-
const needsProjectionRebuild = changedActivities === null || !projectionIsCurrent
|
|
21921
|
+
const needsProjectionRebuild = changedActivities === null || !projectionIsCurrent || changesAffectRelativePinProjection(
|
|
21922
|
+
changes,
|
|
21923
|
+
changedActivities,
|
|
21924
|
+
adapter,
|
|
21925
|
+
relativePlacementPins
|
|
21926
|
+
);
|
|
21736
21927
|
if (needsProjectionRebuild) {
|
|
21737
21928
|
const rebuiltProjection = buildFilterProjection({
|
|
21738
21929
|
activities: adapter.getAllActivities(),
|
|
21739
21930
|
parentOf: (activityId) => adapter.getParentId(activityId),
|
|
21740
21931
|
filter,
|
|
21741
21932
|
context,
|
|
21742
|
-
|
|
21933
|
+
relativePlacementPins
|
|
21743
21934
|
});
|
|
21744
21935
|
adapter.setFilterProjection(rebuiltProjection);
|
|
21745
21936
|
visibleIds = rebuiltProjection.visibleIds;
|