@outbuild-company/schedule-core 1.1.1 → 1.1.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/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +1451 -1408
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -196
- package/dist/index.d.ts +39 -196
- package/dist/index.js +1452 -1406
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/dist/index.cjs
CHANGED
|
@@ -835,49 +835,63 @@ function appendToBucket(index, key, link) {
|
|
|
835
835
|
}
|
|
836
836
|
index.set(key, [link]);
|
|
837
837
|
}
|
|
838
|
-
function filterToChainEndpoints(leaves, adapter, linksByActivity) {
|
|
838
|
+
function filterToChainEndpoints(leaves, adapter, linksByActivity, selectSourceLinks) {
|
|
839
839
|
if (leaves.length <= 1) return leaves;
|
|
840
840
|
const leafSet = new Set(leaves.map(String));
|
|
841
841
|
const keptLeaves = [];
|
|
842
842
|
for (const leafId of leaves) {
|
|
843
|
-
if (!shouldSkipMidChainLeaf(
|
|
843
|
+
if (!shouldSkipMidChainLeaf(
|
|
844
|
+
leafId,
|
|
845
|
+
leafSet,
|
|
846
|
+
adapter,
|
|
847
|
+
linksByActivity,
|
|
848
|
+
selectSourceLinks
|
|
849
|
+
)) {
|
|
844
850
|
keptLeaves.push(leafId);
|
|
845
851
|
}
|
|
846
852
|
}
|
|
847
853
|
return keptLeaves.length > 0 ? keptLeaves : leaves;
|
|
848
854
|
}
|
|
849
|
-
function shouldSkipMidChainLeaf(leafId, leafSet, adapter, linksByActivity) {
|
|
855
|
+
function shouldSkipMidChainLeaf(leafId, leafSet, adapter, linksByActivity, selectSourceLinks) {
|
|
850
856
|
const leafKey = String(leafId);
|
|
851
857
|
const leafTask = adapter.getActivity(leafId);
|
|
852
858
|
if (!leafTask) return false;
|
|
853
859
|
if (leafTask.autoScheduling === false) return false;
|
|
854
860
|
const linksOnThis = linksByActivity.get(leafKey) ?? [];
|
|
855
861
|
for (const siblingLink of linksOnThis) {
|
|
856
|
-
if (
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
862
|
+
if (isMidChainConnection(
|
|
863
|
+
siblingLink,
|
|
864
|
+
leafKey,
|
|
865
|
+
leafTask,
|
|
866
|
+
leafSet,
|
|
867
|
+
adapter,
|
|
868
|
+
selectSourceLinks
|
|
869
|
+
))
|
|
863
870
|
return true;
|
|
864
|
-
}
|
|
865
871
|
}
|
|
866
872
|
return false;
|
|
867
873
|
}
|
|
874
|
+
function isMidChainConnection(link, leafKey, leafTask, leafSet, adapter, selectSourceLinks) {
|
|
875
|
+
if (isSelfLink(link)) return false;
|
|
876
|
+
const relevantDirection = selectSourceLinks ? String(link.source) === leafKey : String(link.target) === leafKey;
|
|
877
|
+
if (!relevantDirection) return false;
|
|
878
|
+
const otherId = otherEndOf(link, leafKey);
|
|
879
|
+
if (!leafSet.has(String(otherId))) return false;
|
|
880
|
+
const siblingTask = adapter.getActivity(otherId);
|
|
881
|
+
return Boolean(
|
|
882
|
+
siblingTask?.autoScheduling !== false && siblingTask && linkConnectsMidChain(link, leafTask, siblingTask)
|
|
883
|
+
);
|
|
884
|
+
}
|
|
868
885
|
function isSelfLink(link) {
|
|
869
886
|
return link.source === link.target;
|
|
870
887
|
}
|
|
871
888
|
function otherEndOf(link, knownEndKey) {
|
|
872
889
|
return String(link.source) === knownEndKey ? link.target : link.source;
|
|
873
890
|
}
|
|
874
|
-
function linkConnectsMidChain(link,
|
|
891
|
+
function linkConnectsMidChain(link, leafTask, siblingTask) {
|
|
875
892
|
const lag = link.lag ?? 0;
|
|
876
893
|
const absLag = Math.abs(lag);
|
|
877
|
-
|
|
878
|
-
if (link.target === otherId && absLag <= siblingTask.durationHours)
|
|
879
|
-
return true;
|
|
880
|
-
return false;
|
|
894
|
+
return String(link.target) === String(siblingTask.id) && absLag <= siblingTask.durationHours || String(link.target) === String(leafTask.id) && absLag <= leafTask.durationHours;
|
|
881
895
|
}
|
|
882
896
|
function expandParentLinks(links, adapter) {
|
|
883
897
|
const expanded = [];
|
|
@@ -886,115 +900,98 @@ function expandParentLinks(links, adapter) {
|
|
|
886
900
|
for (const link of links) {
|
|
887
901
|
const sourceIsSummary = isSummary2(link.source, adapter);
|
|
888
902
|
const targetIsSummary = isSummary2(link.target, adapter);
|
|
889
|
-
if (sourceIsSummary
|
|
890
|
-
if (targetIsSummary && isDescendantOf(link.source, link.target, adapter) || sourceIsSummary && isDescendantOf(link.target, link.source, adapter)) {
|
|
903
|
+
if (isInternalSummaryLink(link, sourceIsSummary, targetIsSummary, adapter))
|
|
891
904
|
continue;
|
|
892
|
-
}
|
|
893
905
|
if (!sourceIsSummary && !targetIsSummary) {
|
|
894
906
|
expanded.push(link);
|
|
895
907
|
continue;
|
|
896
908
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
chainEndpoints,
|
|
913
|
-
link,
|
|
914
|
-
link.target,
|
|
915
|
-
adapter,
|
|
916
|
-
virtualIdCounter
|
|
917
|
-
);
|
|
918
|
-
continue;
|
|
919
|
-
}
|
|
920
|
-
targetIds = keepBoundDefiningLeaves(chainEndpoints, true, adapter);
|
|
921
|
-
}
|
|
922
|
-
virtualIdCounter = pushExpandedLinks(
|
|
909
|
+
const sourceIds = expandedEndpoints(
|
|
910
|
+
link.source,
|
|
911
|
+
sourceIsSummary,
|
|
912
|
+
adapter,
|
|
913
|
+
linksByActivity,
|
|
914
|
+
true
|
|
915
|
+
);
|
|
916
|
+
const targetIds = expandedEndpoints(
|
|
917
|
+
link.target,
|
|
918
|
+
targetIsSummary,
|
|
919
|
+
adapter,
|
|
920
|
+
linksByActivity,
|
|
921
|
+
false
|
|
922
|
+
);
|
|
923
|
+
virtualIdCounter = pushOffsetPreservingLinks(
|
|
923
924
|
expanded,
|
|
924
925
|
sourceIds,
|
|
925
926
|
targetIds,
|
|
926
927
|
link,
|
|
928
|
+
adapter,
|
|
927
929
|
virtualIdCounter
|
|
928
930
|
);
|
|
929
931
|
}
|
|
930
932
|
return expanded;
|
|
931
933
|
}
|
|
932
|
-
function
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
934
|
+
function isInternalSummaryLink(link, sourceIsSummary, targetIsSummary, adapter) {
|
|
935
|
+
return targetIsSummary && isDescendantOf(link.source, link.target, adapter) || sourceIsSummary && isDescendantOf(link.target, link.source, adapter);
|
|
936
|
+
}
|
|
937
|
+
function expandedEndpoints(activityId, summary, adapter, linksByActivity, sourceSide) {
|
|
938
|
+
if (!summary) return [activityId];
|
|
939
|
+
return filterToChainEndpoints(
|
|
940
|
+
getLeafDescendants(activityId, adapter),
|
|
941
|
+
adapter,
|
|
942
|
+
linksByActivity,
|
|
943
|
+
sourceSide
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
function pushOffsetPreservingLinks(expanded, sourceIds, leafIds, originalLink, adapter, virtualIdCounter) {
|
|
937
947
|
const source = adapter.getActivity(originalLink.source);
|
|
948
|
+
const target = adapter.getActivity(originalLink.target);
|
|
949
|
+
const targetStart = target?.startDate;
|
|
950
|
+
const userLag = originalLink.lag ?? 0;
|
|
951
|
+
const sourceEndpointIsStart = originalLink.type === LINK_TYPE.START_TO_START || originalLink.type === LINK_TYPE.START_TO_FINISH;
|
|
952
|
+
const targetEndpointIsFinish = originalLink.type === LINK_TYPE.FINISH_TO_FINISH || originalLink.type === LINK_TYPE.START_TO_FINISH;
|
|
953
|
+
const sourceLag = sourceEndpointIsStart ? -(source?.durationHours ?? 0) : 0;
|
|
954
|
+
const targetLag = targetEndpointIsFinish ? -(target?.durationHours ?? 0) : 0;
|
|
938
955
|
let counter = virtualIdCounter;
|
|
939
956
|
for (const srcId of sourceIds) {
|
|
940
957
|
for (const tgtId of leafIds) {
|
|
941
958
|
if (String(srcId) === String(tgtId)) continue;
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
_trueLag: userLag + offTarget
|
|
957
|
-
});
|
|
959
|
+
expanded.push(
|
|
960
|
+
buildVirtualLink(
|
|
961
|
+
originalLink,
|
|
962
|
+
srcId,
|
|
963
|
+
tgtId,
|
|
964
|
+
counter,
|
|
965
|
+
sourceLag,
|
|
966
|
+
targetLag,
|
|
967
|
+
userLag,
|
|
968
|
+
source,
|
|
969
|
+
targetStart,
|
|
970
|
+
adapter
|
|
971
|
+
)
|
|
972
|
+
);
|
|
958
973
|
counter += 1;
|
|
959
974
|
}
|
|
960
975
|
}
|
|
961
976
|
return counter;
|
|
962
977
|
}
|
|
963
|
-
function
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
}
|
|
980
|
-
return kept.length > 0 ? kept : leaves;
|
|
981
|
-
}
|
|
982
|
-
function pushExpandedLinks(expanded, sourceIds, targetIds, originalLink, virtualIdCounter) {
|
|
983
|
-
let counter = virtualIdCounter;
|
|
984
|
-
for (const srcId of sourceIds) {
|
|
985
|
-
for (const tgtId of targetIds) {
|
|
986
|
-
if (String(srcId) === String(tgtId)) continue;
|
|
987
|
-
expanded.push({
|
|
988
|
-
id: `virtual_${originalLink.id}_${counter}`,
|
|
989
|
-
source: srcId,
|
|
990
|
-
target: tgtId,
|
|
991
|
-
type: originalLink.type,
|
|
992
|
-
lag: originalLink.lag
|
|
993
|
-
});
|
|
994
|
-
counter += 1;
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
return counter;
|
|
978
|
+
function buildVirtualLink(originalLink, sourceId, targetId, counter, sourceLag, targetLag, userLag, source, targetStart, adapter) {
|
|
979
|
+
const leaf = adapter.getActivity(targetId);
|
|
980
|
+
const offTarget = targetStart && leaf && source ? adapter.calculateDuration({
|
|
981
|
+
startDate: targetStart,
|
|
982
|
+
endDate: leaf.startDate,
|
|
983
|
+
task: source
|
|
984
|
+
}) : 0;
|
|
985
|
+
return {
|
|
986
|
+
id: `virtual_${originalLink.id}_${counter}`,
|
|
987
|
+
source: sourceId,
|
|
988
|
+
target: targetId,
|
|
989
|
+
type: originalLink.type,
|
|
990
|
+
lag: originalLink.lag,
|
|
991
|
+
_sourceLag: sourceLag,
|
|
992
|
+
_targetLag: targetLag,
|
|
993
|
+
_trueLag: userLag + offTarget
|
|
994
|
+
};
|
|
998
995
|
}
|
|
999
996
|
|
|
1000
997
|
// src/autoscheduler/utils/expanded-links-cache.ts
|
|
@@ -2260,12 +2257,6 @@ async function updateParentBoundsFromChildren(adapter, dirtyIds, recomputeProgre
|
|
|
2260
2257
|
recomputeRealWork: options.recomputeRealWork ?? false
|
|
2261
2258
|
});
|
|
2262
2259
|
}
|
|
2263
|
-
function recomputeParentBoundsSync(adapter, dirtyIds, recomputeProgress = true) {
|
|
2264
|
-
const parents = findAncestorsOfDirty(adapter, dirtyIds);
|
|
2265
|
-
for (const parentId of parents) {
|
|
2266
|
-
recomputeParentFromChildren(parentId, adapter, recomputeProgress);
|
|
2267
|
-
}
|
|
2268
|
-
}
|
|
2269
2260
|
function recomputeSingleParentDisplayBounds(parentId, adapter) {
|
|
2270
2261
|
recomputeParentFromChildren(parentId, adapter, false);
|
|
2271
2262
|
}
|
|
@@ -3766,6 +3757,7 @@ function buildActivityChanges(adapter, before, touched) {
|
|
|
3766
3757
|
}
|
|
3767
3758
|
const beforeSnap = before.get(id);
|
|
3768
3759
|
const diff = diffActivity(beforeSnap, afterSnap);
|
|
3760
|
+
if (beforeSnap && Object.keys(diff).length === 0) continue;
|
|
3769
3761
|
if (!beforeSnap) {
|
|
3770
3762
|
out.push({
|
|
3771
3763
|
id,
|
|
@@ -3919,6 +3911,77 @@ function computeExpectedProgressLive(rootIds, now, state) {
|
|
|
3919
3911
|
for (const activityId of rootIds) visit(activityId);
|
|
3920
3912
|
return changed;
|
|
3921
3913
|
}
|
|
3914
|
+
function applyExpectedProgressLive(state, now) {
|
|
3915
|
+
const rootIds = [];
|
|
3916
|
+
state.forEachActivity((activity, activityId) => {
|
|
3917
|
+
if (activity.parentId === null) rootIds.push(activityId);
|
|
3918
|
+
});
|
|
3919
|
+
computeExpectedProgressLive(rootIds, now, state);
|
|
3920
|
+
}
|
|
3921
|
+
|
|
3922
|
+
// src/propagations/shared/get-active-baseline.ts
|
|
3923
|
+
function getActiveBaseline(activity) {
|
|
3924
|
+
const points = activity?.baselinePoints;
|
|
3925
|
+
if (!Array.isArray(points) || points.length === 0) return null;
|
|
3926
|
+
return points.find((point) => point.isActiveVersion) ?? null;
|
|
3927
|
+
}
|
|
3928
|
+
|
|
3929
|
+
// src/columns/expected-progress-base/compute.ts
|
|
3930
|
+
var isProject2 = (a) => a.type === "project";
|
|
3931
|
+
var activeBaselineOf = (a) => getActiveBaseline(a);
|
|
3932
|
+
var leafExpected = (a, now, adapter, defaultBaseCalendarId) => {
|
|
3933
|
+
const base = activeBaselineOf(a);
|
|
3934
|
+
if (!base) return 0;
|
|
3935
|
+
const cal = (base.baseCalendarId != null ? adapter.getBaseCalendar(`${base.baseCalendarId}-base`) : null) ?? (defaultBaseCalendarId ? adapter.getBaseCalendar(defaultBaseCalendarId) : null);
|
|
3936
|
+
if (!cal) return 0;
|
|
3937
|
+
if (!base.startDate || !base.endDate) return 0;
|
|
3938
|
+
return expectedProgressFromBaseline(base.startDate, base.endDate, now, cal);
|
|
3939
|
+
};
|
|
3940
|
+
function computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId = null) {
|
|
3941
|
+
const changed = [];
|
|
3942
|
+
const writeIfChanged = (id, value) => {
|
|
3943
|
+
const a = adapter.getActivity(id);
|
|
3944
|
+
if (!a) return;
|
|
3945
|
+
if (a.expectedProgressBaseline !== value) {
|
|
3946
|
+
adapter.setActivityField(id, "expectedProgressBaseline", value);
|
|
3947
|
+
changed.push(id);
|
|
3948
|
+
}
|
|
3949
|
+
};
|
|
3950
|
+
const visit = (id) => {
|
|
3951
|
+
const a = adapter.getActivity(id);
|
|
3952
|
+
if (!a) return 0;
|
|
3953
|
+
if (!isProject2(a)) {
|
|
3954
|
+
const v2 = leafExpected(a, now, adapter, defaultBaseCalendarId);
|
|
3955
|
+
writeIfChanged(id, v2);
|
|
3956
|
+
return v2;
|
|
3957
|
+
}
|
|
3958
|
+
let acc = 0;
|
|
3959
|
+
for (const childId of adapter.getChildrenIds(id)) {
|
|
3960
|
+
const childBase = visit(childId);
|
|
3961
|
+
const child = adapter.getActivity(childId);
|
|
3962
|
+
const weight = typeof child?.ponderator === "number" ? child.ponderator : 0;
|
|
3963
|
+
acc += childBase * weight;
|
|
3964
|
+
}
|
|
3965
|
+
const v = acc / 100;
|
|
3966
|
+
writeIfChanged(id, v);
|
|
3967
|
+
return v;
|
|
3968
|
+
};
|
|
3969
|
+
for (const id of rootIds) visit(id);
|
|
3970
|
+
return changed;
|
|
3971
|
+
}
|
|
3972
|
+
function runExpectedProgressBase(state, now, defaultBaseCalendarId = null) {
|
|
3973
|
+
const adapter = {
|
|
3974
|
+
getChildrenIds: (parentId) => state.getChildren(String(parentId)).map((childId) => String(childId)),
|
|
3975
|
+
getActivity: (id) => state.getActivity(id),
|
|
3976
|
+
setActivityField: (id, field, value) => setActivityFieldDynamic(state, id, field, value),
|
|
3977
|
+
getBaseCalendar: (engineId) => state.calendarReader.getCalendar(engineId)
|
|
3978
|
+
};
|
|
3979
|
+
const rootIds = [];
|
|
3980
|
+
state.forEachActivity((activity, id) => {
|
|
3981
|
+
if (activity.parentId === null) rootIds.push(id);
|
|
3982
|
+
});
|
|
3983
|
+
return computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId);
|
|
3984
|
+
}
|
|
3922
3985
|
|
|
3923
3986
|
// src/columns/status/compute.ts
|
|
3924
3987
|
var roundToTwoDecimals = (value) => Math.round(value * 100) / 100;
|
|
@@ -3954,594 +4017,290 @@ function applyStatusPass(state, criteria) {
|
|
|
3954
4017
|
return changed;
|
|
3955
4018
|
}
|
|
3956
4019
|
|
|
3957
|
-
// src/
|
|
3958
|
-
|
|
3959
|
-
function
|
|
3960
|
-
const
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
function iterateInVisualOrder(adapter) {
|
|
3965
|
-
const result = [];
|
|
3966
|
-
const visit = (activity) => {
|
|
3967
|
-
result.push(activity);
|
|
3968
|
-
const childIds = getChildrenInVisualOrder(String(activity.id), adapter);
|
|
3969
|
-
for (const childId of childIds) {
|
|
3970
|
-
const child = adapter.getActivity(childId);
|
|
3971
|
-
if (child) visit(child);
|
|
3972
|
-
}
|
|
4020
|
+
// src/critical-path/legacy/shims/moment.js
|
|
4021
|
+
function moment(input) {
|
|
4022
|
+
const d = input instanceof Date ? new Date(input.getTime()) : input && typeof input === "object" && typeof input.valueOf === "function" ? new Date(input.valueOf()) : new Date(input);
|
|
4023
|
+
const accessor = (getUTC, setUTC) => (value) => {
|
|
4024
|
+
if (value === void 0) return d[getUTC]();
|
|
4025
|
+
d[setUTC](value);
|
|
4026
|
+
return api;
|
|
3973
4027
|
};
|
|
3974
|
-
const
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
4028
|
+
const api = {
|
|
4029
|
+
__isMomentShim: true,
|
|
4030
|
+
clone: () => moment(d),
|
|
4031
|
+
hours: accessor("getUTCHours", "setUTCHours"),
|
|
4032
|
+
minutes: accessor("getUTCMinutes", "setUTCMinutes"),
|
|
4033
|
+
seconds: accessor("getUTCSeconds", "setUTCSeconds"),
|
|
4034
|
+
milliseconds: accessor("getUTCMilliseconds", "setUTCMilliseconds"),
|
|
4035
|
+
valueOf: () => d.getTime(),
|
|
4036
|
+
toDate: () => new Date(d.getTime()),
|
|
4037
|
+
getTime: () => d.getTime()
|
|
4038
|
+
};
|
|
4039
|
+
return api;
|
|
3980
4040
|
}
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
for (let i = idx - 1; i >= 0; i--) {
|
|
3989
|
-
const candidateId = siblings[i];
|
|
3990
|
-
if (candidateId === void 0) continue;
|
|
3991
|
-
if (!setHas(selected, candidateId)) return candidateId;
|
|
4041
|
+
moment.isMoment = (x) => Boolean(x) && typeof x === "object" && x.__isMomentShim === true;
|
|
4042
|
+
var moment_default = moment;
|
|
4043
|
+
|
|
4044
|
+
// src/critical-path/legacy/helpers/isValidDate.js
|
|
4045
|
+
function isDate(obj) {
|
|
4046
|
+
if (obj && obj.constructor === Date) {
|
|
4047
|
+
return Boolean(obj.getFullYear && obj.getMonth && obj.getDate);
|
|
3992
4048
|
}
|
|
3993
|
-
return
|
|
4049
|
+
return false;
|
|
3994
4050
|
}
|
|
3995
|
-
function
|
|
3996
|
-
|
|
3997
|
-
if (!activity) return -1;
|
|
3998
|
-
const parentKey = parentKeyOf(activity);
|
|
3999
|
-
const siblings = getChildrenInVisualOrder(parentKey, adapter);
|
|
4000
|
-
return siblings.findIndex((id) => String(id) === String(taskId));
|
|
4051
|
+
function isValidDate2(obj) {
|
|
4052
|
+
return isDate(obj) && !isNaN(obj.getTime());
|
|
4001
4053
|
}
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
for (const id of childIds) {
|
|
4010
|
-
const snap = adapter.getActivity(id);
|
|
4011
|
-
if (snap) out.push(snap);
|
|
4054
|
+
|
|
4055
|
+
// src/critical-path/legacy/helpers/addDurationToDate.js
|
|
4056
|
+
function addDurationToDate(activityCalendar, date2, duration, activity) {
|
|
4057
|
+
if (!isValidDate2(new Date(date2))) {
|
|
4058
|
+
throw new Error(
|
|
4059
|
+
`Invalid date argument for calculateEndDate method. Date: ${date2}, Activity: ${JSON.stringify(activity)}`
|
|
4060
|
+
);
|
|
4012
4061
|
}
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
}
|
|
4021
|
-
function correlativeIdOf(activity) {
|
|
4022
|
-
const raw = activity.correlativeId;
|
|
4023
|
-
const n = typeof raw === "number" ? raw : Number(raw);
|
|
4024
|
-
return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
|
|
4025
|
-
}
|
|
4026
|
-
function parentKeyOf(activity) {
|
|
4027
|
-
const parentId = activity.parentId;
|
|
4028
|
-
if (parentId === null) return "0";
|
|
4029
|
-
return parentId;
|
|
4030
|
-
}
|
|
4031
|
-
function setHas(set, id) {
|
|
4032
|
-
if (set.has(id)) return true;
|
|
4033
|
-
return set.has(String(id));
|
|
4062
|
+
const dateToCalculate = date2;
|
|
4063
|
+
return activityCalendar.calculateEndDate({
|
|
4064
|
+
start_date: new Date(dateToCalculate),
|
|
4065
|
+
duration,
|
|
4066
|
+
unit: "hour",
|
|
4067
|
+
task: activity
|
|
4068
|
+
});
|
|
4034
4069
|
}
|
|
4035
4070
|
|
|
4036
|
-
// src/
|
|
4037
|
-
function
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4071
|
+
// src/critical-path/legacy/helpers/getNextWorkingHour.js
|
|
4072
|
+
function getNextWorkingHour(activityParams) {
|
|
4073
|
+
if (!isValidDate2(new Date(activityParams.dateBaseToCalculate))) {
|
|
4074
|
+
throw new Error("Invalid date argument for getClosestWorkTime method");
|
|
4075
|
+
}
|
|
4076
|
+
const { dateBaseToCalculate, activityCalendar, direction, activity } = activityParams;
|
|
4077
|
+
const newDate = activityCalendar.$gantt.getClosestWorkTime({
|
|
4078
|
+
date: new Date(dateBaseToCalculate),
|
|
4079
|
+
dir: direction,
|
|
4080
|
+
unit: "hour",
|
|
4081
|
+
task: activity
|
|
4042
4082
|
});
|
|
4043
|
-
|
|
4044
|
-
const stack = [];
|
|
4045
|
-
pushInReverseOrder(stack, roots);
|
|
4046
|
-
const shifts = [];
|
|
4047
|
-
let counter = 0;
|
|
4048
|
-
while (stack.length > 0) {
|
|
4049
|
-
const activity = stack.pop();
|
|
4050
|
-
if (activity.correlativeId !== counter) {
|
|
4051
|
-
const before = typeof activity.correlativeId === "number" ? activity.correlativeId : void 0;
|
|
4052
|
-
shifts.push({ activityId: String(activity.id), before });
|
|
4053
|
-
if (before !== void 0)
|
|
4054
|
-
adapter.noteCorrelativeBefore?.(String(activity.id), before);
|
|
4055
|
-
setCorrelativeId(activity, counter);
|
|
4056
|
-
}
|
|
4057
|
-
counter += 1;
|
|
4058
|
-
const children = collectChildrenSnapshots(String(activity.id), adapter);
|
|
4059
|
-
children.sort(byCorrelativeId);
|
|
4060
|
-
pushInReverseOrder(stack, children);
|
|
4061
|
-
}
|
|
4062
|
-
return shifts;
|
|
4063
|
-
}
|
|
4064
|
-
function pushInReverseOrder(stack, activities) {
|
|
4065
|
-
for (let i = activities.length - 1; i >= 0; i -= 1) {
|
|
4066
|
-
stack.push(activities[i]);
|
|
4067
|
-
}
|
|
4068
|
-
}
|
|
4069
|
-
function getCorrelativeId(activity) {
|
|
4070
|
-
const raw = activity.correlativeId;
|
|
4071
|
-
const n = typeof raw === "number" ? raw : Number(raw);
|
|
4072
|
-
return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
|
|
4073
|
-
}
|
|
4074
|
-
var byCorrelativeId = (a, b) => getCorrelativeId(a) - getCorrelativeId(b);
|
|
4075
|
-
function setCorrelativeId(activity, value) {
|
|
4076
|
-
activity.correlativeId = value;
|
|
4083
|
+
return newDate;
|
|
4077
4084
|
}
|
|
4078
4085
|
|
|
4079
|
-
// src/
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4086
|
+
// src/critical-path/legacy/helpers/filters.js
|
|
4087
|
+
var byFirstLevel = (activity) => {
|
|
4088
|
+
if (!activity) return false;
|
|
4089
|
+
return activity["$level"] === 1;
|
|
4090
|
+
};
|
|
4091
|
+
var filterByParentType = (activity) => activity.type === "project";
|
|
4092
|
+
var avoidSubproject = (activity) => activity["$level"] !== 0;
|
|
4093
|
+
var byTaskType = (activity) => activity.type === "task";
|
|
4094
|
+
var byTaskTypeAndMilestone = (activity) => activity.type === "task" || activity.type === "milestone";
|
|
4095
|
+
var filters_default = {
|
|
4096
|
+
byFirstLevel,
|
|
4097
|
+
filterByParentType,
|
|
4098
|
+
avoidSubproject,
|
|
4099
|
+
byTaskType,
|
|
4100
|
+
byTaskTypeAndMilestone
|
|
4101
|
+
};
|
|
4102
|
+
|
|
4103
|
+
// src/critical-path/legacy/constants/constraints.js
|
|
4104
|
+
var CONSTRAINT_TYPES = Object.freeze({
|
|
4105
|
+
MFO: "mfo",
|
|
4106
|
+
MSO: "mso",
|
|
4107
|
+
FNLT: "fnlt",
|
|
4108
|
+
FNET: "fnet",
|
|
4109
|
+
SNET: "snet",
|
|
4110
|
+
SNLT: "snlt",
|
|
4111
|
+
ALAP: "alap",
|
|
4112
|
+
ASAP: "asap"
|
|
4113
|
+
});
|
|
4114
|
+
|
|
4115
|
+
// src/critical-path/legacy/constants/linkTypes.js
|
|
4116
|
+
var LINK_TYPES = Object.freeze({
|
|
4117
|
+
FS: "fs",
|
|
4118
|
+
SS: "ss",
|
|
4119
|
+
FF: "ff",
|
|
4120
|
+
SF: "sf"
|
|
4121
|
+
});
|
|
4122
|
+
|
|
4123
|
+
// src/critical-path/legacy/constants/linkByCode.js
|
|
4124
|
+
function getLinkNameByCode(code) {
|
|
4125
|
+
const linkMap = {
|
|
4126
|
+
0: "fs",
|
|
4127
|
+
1: "ss",
|
|
4128
|
+
2: "ff",
|
|
4129
|
+
3: "sf"
|
|
4101
4130
|
};
|
|
4102
|
-
|
|
4103
|
-
return changedIds;
|
|
4131
|
+
return linkMap[Number(code)] || "sf";
|
|
4104
4132
|
}
|
|
4105
4133
|
|
|
4106
|
-
// src/
|
|
4107
|
-
|
|
4108
|
-
const {
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
if (now) {
|
|
4117
|
-
applyExpectedProgressLive(state, now);
|
|
4118
|
-
applyStatusPass(state, sector.statusCriteria);
|
|
4134
|
+
// src/critical-path/legacy/base/identifiers/secondLevelActivities.js
|
|
4135
|
+
function identifySecondLevelActivities(params) {
|
|
4136
|
+
const { gantt, pendingParentsWithNoLinks, calculations, linkProperty } = params;
|
|
4137
|
+
try {
|
|
4138
|
+
const subprojectsWithNoLinks = getSubprojectsWithNoLinks({
|
|
4139
|
+
gantt,
|
|
4140
|
+
pendingParentsWithNoLinks
|
|
4141
|
+
});
|
|
4142
|
+
if (subprojectsWithNoLinks.length === 0) {
|
|
4143
|
+
return /* @__PURE__ */ new Set();
|
|
4119
4144
|
}
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4145
|
+
const allChildrenFromParents = getAllChildrenFromParents({
|
|
4146
|
+
gantt,
|
|
4147
|
+
subprojectsWithNoLinks
|
|
4148
|
+
});
|
|
4149
|
+
const childrenThatCanBeCalculated = filterChildrenThatCanBeCalculated({
|
|
4150
|
+
gantt,
|
|
4151
|
+
childrenIds: allChildrenFromParents,
|
|
4152
|
+
linkProperty,
|
|
4153
|
+
getArrayOfLinkedActivities,
|
|
4154
|
+
calculations
|
|
4155
|
+
});
|
|
4156
|
+
return new Set(childrenThatCanBeCalculated.map((activity) => activity.id));
|
|
4157
|
+
} catch (e) {
|
|
4158
|
+
throw e;
|
|
4130
4159
|
}
|
|
4131
4160
|
}
|
|
4132
|
-
function
|
|
4133
|
-
const
|
|
4134
|
-
|
|
4135
|
-
if (activity.parentId === null) rootIds.push(activityId);
|
|
4136
|
-
});
|
|
4137
|
-
computeExpectedProgressLive(rootIds, now, state);
|
|
4161
|
+
function getSubprojectsWithNoLinks(params) {
|
|
4162
|
+
const { gantt, pendingParentsWithNoLinks } = params;
|
|
4163
|
+
return gantt.getTaskByTime().filter(filters_default.filterByParentType).filter((activity) => pendingParentsWithNoLinks.has(activity.id)).map((activity) => activity.id);
|
|
4138
4164
|
}
|
|
4139
|
-
function
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4165
|
+
function getAllChildrenFromParents(params) {
|
|
4166
|
+
const { gantt, subprojectsWithNoLinks } = params;
|
|
4167
|
+
const allChildrenSet = /* @__PURE__ */ new Set();
|
|
4168
|
+
for (const subprojectId of subprojectsWithNoLinks) {
|
|
4169
|
+
const childrenIds = gantt.getChildren(subprojectId);
|
|
4170
|
+
const validChildren = childrenIds.filter((childId) => {
|
|
4171
|
+
const childActivity = gantt.getTask(childId);
|
|
4172
|
+
const isTaskOrMilestone = filters_default.byTaskTypeAndMilestone(childActivity);
|
|
4173
|
+
const hasProgressLessThan100 = Number(childActivity.progress) < 100;
|
|
4174
|
+
return isTaskOrMilestone && hasProgressLessThan100;
|
|
4148
4175
|
});
|
|
4149
|
-
|
|
4176
|
+
validChildren.forEach((childId) => allChildrenSet.add(childId));
|
|
4177
|
+
}
|
|
4178
|
+
return [...allChildrenSet];
|
|
4150
4179
|
}
|
|
4151
|
-
function
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4180
|
+
function filterChildrenThatCanBeCalculated(params) {
|
|
4181
|
+
const {
|
|
4182
|
+
gantt,
|
|
4183
|
+
childrenIds,
|
|
4184
|
+
linkProperty,
|
|
4185
|
+
getArrayOfLinkedActivities: getArrayOfLinkedActivities3,
|
|
4186
|
+
calculations
|
|
4187
|
+
} = params;
|
|
4188
|
+
const calculableChildren = [];
|
|
4189
|
+
for (const childId of childrenIds) {
|
|
4190
|
+
const activity = gantt.getTask(childId);
|
|
4191
|
+
const links = activity[linkProperty] || [];
|
|
4192
|
+
const linkedActivities = getArrayOfLinkedActivities3({
|
|
4193
|
+
gantt,
|
|
4194
|
+
links,
|
|
4195
|
+
linkDirection: linkProperty === "$source" ? "target" : "source"
|
|
4158
4196
|
});
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
function normalizeLoadedConstraintDates(state) {
|
|
4162
|
-
state.forEachActivity((activity) => {
|
|
4163
|
-
const type = activity.constraintType;
|
|
4164
|
-
if (!type || !activity.constraintDate) return;
|
|
4165
|
-
const constraintDate = activity.constraintDate;
|
|
4166
|
-
if (activity.type === "milestone" && (constraintDate.getUTCHours() !== 0 || constraintDate.getUTCMinutes() !== 0)) {
|
|
4167
|
-
return;
|
|
4168
|
-
}
|
|
4169
|
-
const calendar = state.calendarReader.getCalendar(
|
|
4170
|
-
String(activity.calendarId)
|
|
4171
|
-
);
|
|
4172
|
-
if (!calendar) return;
|
|
4173
|
-
activity.constraintDate = normalizeConstraintDate(
|
|
4174
|
-
activity.constraintDate,
|
|
4175
|
-
calendar,
|
|
4176
|
-
type
|
|
4197
|
+
const isLinkedWithCalculatedOrSibling = linkedActivities.every(
|
|
4198
|
+
(linkedActivityId) => calculations.has(linkedActivityId)
|
|
4177
4199
|
);
|
|
4178
|
-
|
|
4200
|
+
if (isLinkedWithCalculatedOrSibling) {
|
|
4201
|
+
calculableChildren.push(activity);
|
|
4202
|
+
}
|
|
4203
|
+
}
|
|
4204
|
+
return calculableChildren;
|
|
4179
4205
|
}
|
|
4180
|
-
function
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
type
|
|
4193
|
-
);
|
|
4194
|
-
});
|
|
4206
|
+
function getArrayOfLinkedActivities(params) {
|
|
4207
|
+
const { gantt, links, linkDirection } = params;
|
|
4208
|
+
const linkedActivityIds = [];
|
|
4209
|
+
for (const linkId of links) {
|
|
4210
|
+
const link = gantt.getLink(linkId);
|
|
4211
|
+
if (!link) {
|
|
4212
|
+
continue;
|
|
4213
|
+
}
|
|
4214
|
+
const linkedActivityId = Number(link[linkDirection]);
|
|
4215
|
+
linkedActivityIds.push(linkedActivityId);
|
|
4216
|
+
}
|
|
4217
|
+
return linkedActivityIds;
|
|
4195
4218
|
}
|
|
4196
4219
|
|
|
4197
|
-
// src/
|
|
4198
|
-
function
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
var activeBaselineOf = (a) => getActiveBaseline(a);
|
|
4207
|
-
var leafExpected = (a, now, adapter, defaultBaseCalendarId) => {
|
|
4208
|
-
const base = activeBaselineOf(a);
|
|
4209
|
-
if (!base) return 0;
|
|
4210
|
-
const cal = (base.baseCalendarId != null ? adapter.getBaseCalendar(`${base.baseCalendarId}-base`) : null) ?? (defaultBaseCalendarId ? adapter.getBaseCalendar(defaultBaseCalendarId) : null);
|
|
4211
|
-
if (!cal) return 0;
|
|
4212
|
-
if (!base.startDate || !base.endDate) return 0;
|
|
4213
|
-
return expectedProgressFromBaseline(base.startDate, base.endDate, now, cal);
|
|
4214
|
-
};
|
|
4215
|
-
function computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId = null) {
|
|
4216
|
-
const changed = [];
|
|
4217
|
-
const writeIfChanged = (id, value) => {
|
|
4218
|
-
const a = adapter.getActivity(id);
|
|
4219
|
-
if (!a) return;
|
|
4220
|
-
if (a.expectedProgressBaseline !== value) {
|
|
4221
|
-
adapter.setActivityField(id, "expectedProgressBaseline", value);
|
|
4222
|
-
changed.push(id);
|
|
4223
|
-
}
|
|
4224
|
-
};
|
|
4225
|
-
const visit = (id) => {
|
|
4226
|
-
const a = adapter.getActivity(id);
|
|
4227
|
-
if (!a) return 0;
|
|
4228
|
-
if (!isProject2(a)) {
|
|
4229
|
-
const v2 = leafExpected(a, now, adapter, defaultBaseCalendarId);
|
|
4230
|
-
writeIfChanged(id, v2);
|
|
4231
|
-
return v2;
|
|
4220
|
+
// src/critical-path/legacy/base/identifiers/initialActivities.js
|
|
4221
|
+
function identifyInitialActivities({ gantt, linkProperty, direction }) {
|
|
4222
|
+
try {
|
|
4223
|
+
const chainStartActivities = getChainStartActivities(gantt, linkProperty);
|
|
4224
|
+
if (direction === "forward") {
|
|
4225
|
+
return {
|
|
4226
|
+
chainStartActivities,
|
|
4227
|
+
activitiesStartChainButChildrenOfLinkedParents: null
|
|
4228
|
+
};
|
|
4232
4229
|
}
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4230
|
+
if (direction === "backward") {
|
|
4231
|
+
return processBackwardActivities(
|
|
4232
|
+
chainStartActivities,
|
|
4233
|
+
gantt,
|
|
4234
|
+
linkProperty
|
|
4235
|
+
);
|
|
4239
4236
|
}
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
};
|
|
4244
|
-
for (const id of rootIds) visit(id);
|
|
4245
|
-
return changed;
|
|
4246
|
-
}
|
|
4247
|
-
function runExpectedProgressBase(state, now, defaultBaseCalendarId = null) {
|
|
4248
|
-
const adapter = {
|
|
4249
|
-
getChildrenIds: (parentId) => state.getChildren(String(parentId)).map((childId) => String(childId)),
|
|
4250
|
-
getActivity: (id) => state.getActivity(id),
|
|
4251
|
-
setActivityField: (id, field, value) => setActivityFieldDynamic(state, id, field, value),
|
|
4252
|
-
getBaseCalendar: (engineId) => state.calendarReader.getCalendar(engineId)
|
|
4253
|
-
};
|
|
4254
|
-
const rootIds = [];
|
|
4255
|
-
state.forEachActivity((activity, id) => {
|
|
4256
|
-
if (activity.parentId === null) rootIds.push(id);
|
|
4257
|
-
});
|
|
4258
|
-
return computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId);
|
|
4259
|
-
}
|
|
4260
|
-
|
|
4261
|
-
// src/critical-path/legacy/shims/moment.js
|
|
4262
|
-
function moment(input) {
|
|
4263
|
-
const d = input instanceof Date ? new Date(input.getTime()) : input && typeof input === "object" && typeof input.valueOf === "function" ? new Date(input.valueOf()) : new Date(input);
|
|
4264
|
-
const accessor = (getUTC, setUTC) => (value) => {
|
|
4265
|
-
if (value === void 0) return d[getUTC]();
|
|
4266
|
-
d[setUTC](value);
|
|
4267
|
-
return api;
|
|
4268
|
-
};
|
|
4269
|
-
const api = {
|
|
4270
|
-
__isMomentShim: true,
|
|
4271
|
-
clone: () => moment(d),
|
|
4272
|
-
hours: accessor("getUTCHours", "setUTCHours"),
|
|
4273
|
-
minutes: accessor("getUTCMinutes", "setUTCMinutes"),
|
|
4274
|
-
seconds: accessor("getUTCSeconds", "setUTCSeconds"),
|
|
4275
|
-
milliseconds: accessor("getUTCMilliseconds", "setUTCMilliseconds"),
|
|
4276
|
-
valueOf: () => d.getTime(),
|
|
4277
|
-
toDate: () => new Date(d.getTime()),
|
|
4278
|
-
getTime: () => d.getTime()
|
|
4279
|
-
};
|
|
4280
|
-
return api;
|
|
4281
|
-
}
|
|
4282
|
-
moment.isMoment = (x) => Boolean(x) && typeof x === "object" && x.__isMomentShim === true;
|
|
4283
|
-
var moment_default = moment;
|
|
4284
|
-
|
|
4285
|
-
// src/critical-path/legacy/helpers/isValidDate.js
|
|
4286
|
-
function isDate(obj) {
|
|
4287
|
-
if (obj && obj.constructor === Date) {
|
|
4288
|
-
return Boolean(obj.getFullYear && obj.getMonth && obj.getDate);
|
|
4237
|
+
} catch (e) {
|
|
4238
|
+
console.log("Critical Path", e);
|
|
4239
|
+
throw e;
|
|
4289
4240
|
}
|
|
4290
|
-
return false;
|
|
4291
|
-
}
|
|
4292
|
-
function isValidDate2(obj) {
|
|
4293
|
-
return isDate(obj) && !isNaN(obj.getTime());
|
|
4294
4241
|
}
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
function addDurationToDate(activityCalendar, date2, duration, activity) {
|
|
4298
|
-
if (!isValidDate2(new Date(date2))) {
|
|
4299
|
-
throw new Error(
|
|
4300
|
-
`Invalid date argument for calculateEndDate method. Date: ${date2}, Activity: ${JSON.stringify(activity)}`
|
|
4301
|
-
);
|
|
4302
|
-
}
|
|
4303
|
-
const dateToCalculate = date2;
|
|
4304
|
-
return activityCalendar.calculateEndDate({
|
|
4305
|
-
start_date: new Date(dateToCalculate),
|
|
4306
|
-
duration,
|
|
4307
|
-
unit: "hour",
|
|
4308
|
-
task: activity
|
|
4309
|
-
});
|
|
4242
|
+
function getChainStartActivities(gantt, linkProperty) {
|
|
4243
|
+
return gantt.getTaskByTime().filter(filters_default.avoidSubproject).filter(filters_default.byTaskTypeAndMilestone).filter((activity) => !activity[linkProperty].length);
|
|
4310
4244
|
}
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4245
|
+
function processBackwardActivities(chainStartActivities, gantt, linkProperty) {
|
|
4246
|
+
const withoutLinkedParents = [];
|
|
4247
|
+
const activitiesStartChainButChildrenOfLinkedParents = /* @__PURE__ */ new Set();
|
|
4248
|
+
chainStartActivities.forEach((activity) => {
|
|
4249
|
+
const parentId = Number(activity.parent);
|
|
4250
|
+
const parentActivity = gantt.getTask(parentId);
|
|
4251
|
+
if (!parentActivity) return;
|
|
4252
|
+
if (parentActivity[linkProperty].length > 0) {
|
|
4253
|
+
activitiesStartChainButChildrenOfLinkedParents.add(activity.id);
|
|
4254
|
+
} else if (parentActivity.constraint_type !== "fnlt") {
|
|
4255
|
+
withoutLinkedParents.push(activity);
|
|
4256
|
+
}
|
|
4323
4257
|
});
|
|
4324
|
-
return
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
// src/critical-path/legacy/helpers/filters.js
|
|
4328
|
-
var byFirstLevel = (activity) => {
|
|
4329
|
-
if (!activity) return false;
|
|
4330
|
-
return activity["$level"] === 1;
|
|
4331
|
-
};
|
|
4332
|
-
var filterByParentType = (activity) => activity.type === "project";
|
|
4333
|
-
var avoidSubproject = (activity) => activity["$level"] !== 0;
|
|
4334
|
-
var byTaskType = (activity) => activity.type === "task";
|
|
4335
|
-
var byTaskTypeAndMilestone = (activity) => activity.type === "task" || activity.type === "milestone";
|
|
4336
|
-
var filters_default = {
|
|
4337
|
-
byFirstLevel,
|
|
4338
|
-
filterByParentType,
|
|
4339
|
-
avoidSubproject,
|
|
4340
|
-
byTaskType,
|
|
4341
|
-
byTaskTypeAndMilestone
|
|
4342
|
-
};
|
|
4343
|
-
|
|
4344
|
-
// src/critical-path/legacy/constants/constraints.js
|
|
4345
|
-
var CONSTRAINT_TYPES = Object.freeze({
|
|
4346
|
-
MFO: "mfo",
|
|
4347
|
-
MSO: "mso",
|
|
4348
|
-
FNLT: "fnlt",
|
|
4349
|
-
FNET: "fnet",
|
|
4350
|
-
SNET: "snet",
|
|
4351
|
-
SNLT: "snlt",
|
|
4352
|
-
ALAP: "alap",
|
|
4353
|
-
ASAP: "asap"
|
|
4354
|
-
});
|
|
4355
|
-
|
|
4356
|
-
// src/critical-path/legacy/constants/linkTypes.js
|
|
4357
|
-
var LINK_TYPES = Object.freeze({
|
|
4358
|
-
FS: "fs",
|
|
4359
|
-
SS: "ss",
|
|
4360
|
-
FF: "ff",
|
|
4361
|
-
SF: "sf"
|
|
4362
|
-
});
|
|
4363
|
-
|
|
4364
|
-
// src/critical-path/legacy/constants/linkByCode.js
|
|
4365
|
-
function getLinkNameByCode(code) {
|
|
4366
|
-
const linkMap = {
|
|
4367
|
-
0: "fs",
|
|
4368
|
-
1: "ss",
|
|
4369
|
-
2: "ff",
|
|
4370
|
-
3: "sf"
|
|
4258
|
+
return {
|
|
4259
|
+
chainStartActivities: withoutLinkedParents,
|
|
4260
|
+
activitiesStartChainButChildrenOfLinkedParents
|
|
4371
4261
|
};
|
|
4372
|
-
return linkMap[Number(code)] || "sf";
|
|
4373
4262
|
}
|
|
4374
4263
|
|
|
4375
|
-
// src/critical-path/legacy/base/identifiers/
|
|
4376
|
-
function
|
|
4377
|
-
|
|
4264
|
+
// src/critical-path/legacy/base/identifiers/identifyParentsWithAndWithoutLinks.js
|
|
4265
|
+
function identifyParentsWithAndWithoutLinks({
|
|
4266
|
+
gantt,
|
|
4267
|
+
direction,
|
|
4268
|
+
linkProperty
|
|
4269
|
+
}) {
|
|
4378
4270
|
try {
|
|
4379
|
-
const
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
if (
|
|
4384
|
-
|
|
4271
|
+
const allParentActivities = getAllParentActivities(gantt);
|
|
4272
|
+
const parentsWithFullProgress = /* @__PURE__ */ new Set();
|
|
4273
|
+
const pendingParentsWithNoLinks = /* @__PURE__ */ new Set();
|
|
4274
|
+
const pendingParentsWithLinks = /* @__PURE__ */ new Set();
|
|
4275
|
+
if (direction === "backward") {
|
|
4276
|
+
const parentsWithFullProgressArray = getParentsWithFullProgress(allParentActivities);
|
|
4277
|
+
parentsWithFullProgressArray.forEach((activity) => {
|
|
4278
|
+
parentsWithFullProgress.add(activity.id);
|
|
4279
|
+
});
|
|
4385
4280
|
}
|
|
4386
|
-
const
|
|
4387
|
-
|
|
4388
|
-
|
|
4281
|
+
const parentsWithNoLinks = getParentsWithNoLinks(
|
|
4282
|
+
allParentActivities,
|
|
4283
|
+
direction,
|
|
4284
|
+
linkProperty
|
|
4285
|
+
);
|
|
4286
|
+
const difference = getDifference(allParentActivities, parentsWithNoLinks);
|
|
4287
|
+
parentsWithNoLinks.forEach((activity) => {
|
|
4288
|
+
pendingParentsWithNoLinks.add(activity.id);
|
|
4389
4289
|
});
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
childrenIds: allChildrenFromParents,
|
|
4393
|
-
linkProperty,
|
|
4394
|
-
getArrayOfLinkedActivities,
|
|
4395
|
-
calculations
|
|
4290
|
+
difference.forEach((activity) => {
|
|
4291
|
+
pendingParentsWithLinks.add(activity.id);
|
|
4396
4292
|
});
|
|
4397
|
-
return
|
|
4293
|
+
return {
|
|
4294
|
+
parentsWithFullProgress,
|
|
4295
|
+
pendingParentsWithNoLinks,
|
|
4296
|
+
pendingParentsWithLinks
|
|
4297
|
+
};
|
|
4398
4298
|
} catch (e) {
|
|
4399
4299
|
throw e;
|
|
4400
4300
|
}
|
|
4401
4301
|
}
|
|
4402
|
-
function
|
|
4403
|
-
|
|
4404
|
-
return gantt.getTaskByTime().filter(filters_default.filterByParentType).filter((activity) => pendingParentsWithNoLinks.has(activity.id)).map((activity) => activity.id);
|
|
4405
|
-
}
|
|
4406
|
-
function getAllChildrenFromParents(params) {
|
|
4407
|
-
const { gantt, subprojectsWithNoLinks } = params;
|
|
4408
|
-
const allChildrenSet = /* @__PURE__ */ new Set();
|
|
4409
|
-
for (const subprojectId of subprojectsWithNoLinks) {
|
|
4410
|
-
const childrenIds = gantt.getChildren(subprojectId);
|
|
4411
|
-
const validChildren = childrenIds.filter((childId) => {
|
|
4412
|
-
const childActivity = gantt.getTask(childId);
|
|
4413
|
-
const isTaskOrMilestone = filters_default.byTaskTypeAndMilestone(childActivity);
|
|
4414
|
-
const hasProgressLessThan100 = Number(childActivity.progress) < 100;
|
|
4415
|
-
return isTaskOrMilestone && hasProgressLessThan100;
|
|
4416
|
-
});
|
|
4417
|
-
validChildren.forEach((childId) => allChildrenSet.add(childId));
|
|
4418
|
-
}
|
|
4419
|
-
return [...allChildrenSet];
|
|
4420
|
-
}
|
|
4421
|
-
function filterChildrenThatCanBeCalculated(params) {
|
|
4422
|
-
const {
|
|
4423
|
-
gantt,
|
|
4424
|
-
childrenIds,
|
|
4425
|
-
linkProperty,
|
|
4426
|
-
getArrayOfLinkedActivities: getArrayOfLinkedActivities3,
|
|
4427
|
-
calculations
|
|
4428
|
-
} = params;
|
|
4429
|
-
const calculableChildren = [];
|
|
4430
|
-
for (const childId of childrenIds) {
|
|
4431
|
-
const activity = gantt.getTask(childId);
|
|
4432
|
-
const links = activity[linkProperty] || [];
|
|
4433
|
-
const linkedActivities = getArrayOfLinkedActivities3({
|
|
4434
|
-
gantt,
|
|
4435
|
-
links,
|
|
4436
|
-
linkDirection: linkProperty === "$source" ? "target" : "source"
|
|
4437
|
-
});
|
|
4438
|
-
const isLinkedWithCalculatedOrSibling = linkedActivities.every(
|
|
4439
|
-
(linkedActivityId) => calculations.has(linkedActivityId)
|
|
4440
|
-
);
|
|
4441
|
-
if (isLinkedWithCalculatedOrSibling) {
|
|
4442
|
-
calculableChildren.push(activity);
|
|
4443
|
-
}
|
|
4444
|
-
}
|
|
4445
|
-
return calculableChildren;
|
|
4446
|
-
}
|
|
4447
|
-
function getArrayOfLinkedActivities(params) {
|
|
4448
|
-
const { gantt, links, linkDirection } = params;
|
|
4449
|
-
const linkedActivityIds = [];
|
|
4450
|
-
for (const linkId of links) {
|
|
4451
|
-
const link = gantt.getLink(linkId);
|
|
4452
|
-
if (!link) {
|
|
4453
|
-
continue;
|
|
4454
|
-
}
|
|
4455
|
-
const linkedActivityId = Number(link[linkDirection]);
|
|
4456
|
-
linkedActivityIds.push(linkedActivityId);
|
|
4457
|
-
}
|
|
4458
|
-
return linkedActivityIds;
|
|
4459
|
-
}
|
|
4460
|
-
|
|
4461
|
-
// src/critical-path/legacy/base/identifiers/initialActivities.js
|
|
4462
|
-
function identifyInitialActivities({ gantt, linkProperty, direction }) {
|
|
4463
|
-
try {
|
|
4464
|
-
const chainStartActivities = getChainStartActivities(gantt, linkProperty);
|
|
4465
|
-
if (direction === "forward") {
|
|
4466
|
-
return {
|
|
4467
|
-
chainStartActivities,
|
|
4468
|
-
activitiesStartChainButChildrenOfLinkedParents: null
|
|
4469
|
-
};
|
|
4470
|
-
}
|
|
4471
|
-
if (direction === "backward") {
|
|
4472
|
-
return processBackwardActivities(
|
|
4473
|
-
chainStartActivities,
|
|
4474
|
-
gantt,
|
|
4475
|
-
linkProperty
|
|
4476
|
-
);
|
|
4477
|
-
}
|
|
4478
|
-
} catch (e) {
|
|
4479
|
-
console.log("Critical Path", e);
|
|
4480
|
-
throw e;
|
|
4481
|
-
}
|
|
4482
|
-
}
|
|
4483
|
-
function getChainStartActivities(gantt, linkProperty) {
|
|
4484
|
-
return gantt.getTaskByTime().filter(filters_default.avoidSubproject).filter(filters_default.byTaskTypeAndMilestone).filter((activity) => !activity[linkProperty].length);
|
|
4485
|
-
}
|
|
4486
|
-
function processBackwardActivities(chainStartActivities, gantt, linkProperty) {
|
|
4487
|
-
const withoutLinkedParents = [];
|
|
4488
|
-
const activitiesStartChainButChildrenOfLinkedParents = /* @__PURE__ */ new Set();
|
|
4489
|
-
chainStartActivities.forEach((activity) => {
|
|
4490
|
-
const parentId = Number(activity.parent);
|
|
4491
|
-
const parentActivity = gantt.getTask(parentId);
|
|
4492
|
-
if (!parentActivity) return;
|
|
4493
|
-
if (parentActivity[linkProperty].length > 0) {
|
|
4494
|
-
activitiesStartChainButChildrenOfLinkedParents.add(activity.id);
|
|
4495
|
-
} else if (parentActivity.constraint_type !== "fnlt") {
|
|
4496
|
-
withoutLinkedParents.push(activity);
|
|
4497
|
-
}
|
|
4498
|
-
});
|
|
4499
|
-
return {
|
|
4500
|
-
chainStartActivities: withoutLinkedParents,
|
|
4501
|
-
activitiesStartChainButChildrenOfLinkedParents
|
|
4502
|
-
};
|
|
4503
|
-
}
|
|
4504
|
-
|
|
4505
|
-
// src/critical-path/legacy/base/identifiers/identifyParentsWithAndWithoutLinks.js
|
|
4506
|
-
function identifyParentsWithAndWithoutLinks({
|
|
4507
|
-
gantt,
|
|
4508
|
-
direction,
|
|
4509
|
-
linkProperty
|
|
4510
|
-
}) {
|
|
4511
|
-
try {
|
|
4512
|
-
const allParentActivities = getAllParentActivities(gantt);
|
|
4513
|
-
const parentsWithFullProgress = /* @__PURE__ */ new Set();
|
|
4514
|
-
const pendingParentsWithNoLinks = /* @__PURE__ */ new Set();
|
|
4515
|
-
const pendingParentsWithLinks = /* @__PURE__ */ new Set();
|
|
4516
|
-
if (direction === "backward") {
|
|
4517
|
-
const parentsWithFullProgressArray = getParentsWithFullProgress(allParentActivities);
|
|
4518
|
-
parentsWithFullProgressArray.forEach((activity) => {
|
|
4519
|
-
parentsWithFullProgress.add(activity.id);
|
|
4520
|
-
});
|
|
4521
|
-
}
|
|
4522
|
-
const parentsWithNoLinks = getParentsWithNoLinks(
|
|
4523
|
-
allParentActivities,
|
|
4524
|
-
direction,
|
|
4525
|
-
linkProperty
|
|
4526
|
-
);
|
|
4527
|
-
const difference = getDifference(allParentActivities, parentsWithNoLinks);
|
|
4528
|
-
parentsWithNoLinks.forEach((activity) => {
|
|
4529
|
-
pendingParentsWithNoLinks.add(activity.id);
|
|
4530
|
-
});
|
|
4531
|
-
difference.forEach((activity) => {
|
|
4532
|
-
pendingParentsWithLinks.add(activity.id);
|
|
4533
|
-
});
|
|
4534
|
-
return {
|
|
4535
|
-
parentsWithFullProgress,
|
|
4536
|
-
pendingParentsWithNoLinks,
|
|
4537
|
-
pendingParentsWithLinks
|
|
4538
|
-
};
|
|
4539
|
-
} catch (e) {
|
|
4540
|
-
throw e;
|
|
4541
|
-
}
|
|
4542
|
-
}
|
|
4543
|
-
function getAllParentActivities(gantt) {
|
|
4544
|
-
return gantt.getTaskByTime().filter(filters_default.filterByParentType).filter(filters_default.avoidSubproject);
|
|
4302
|
+
function getAllParentActivities(gantt) {
|
|
4303
|
+
return gantt.getTaskByTime().filter(filters_default.filterByParentType).filter(filters_default.avoidSubproject);
|
|
4545
4304
|
}
|
|
4546
4305
|
function getParentsWithNoLinks(activities, direction, linkProperty) {
|
|
4547
4306
|
return activities.filter((activity) => {
|
|
@@ -9491,13 +9250,18 @@ var NON_SCHEDULING_INLINE_COLUMNS = /* @__PURE__ */ new Set([
|
|
|
9491
9250
|
COLUMN.SUBCONTRACT_ID,
|
|
9492
9251
|
COLUMN.TAGS
|
|
9493
9252
|
]);
|
|
9494
|
-
var
|
|
9253
|
+
var NON_SCHEDULING_KINDS = /* @__PURE__ */ new Set([
|
|
9495
9254
|
"selection-toggle",
|
|
9496
9255
|
"selection-replace",
|
|
9497
9256
|
"visibility-set",
|
|
9498
9257
|
"sir-sync",
|
|
9499
|
-
"activity-lookahead-sync"
|
|
9258
|
+
"activity-lookahead-sync",
|
|
9259
|
+
"persistence-acknowledge",
|
|
9260
|
+
"baseline-apply",
|
|
9261
|
+
"ponderator-criterion-set",
|
|
9262
|
+
"status-criteria-set"
|
|
9500
9263
|
]);
|
|
9264
|
+
var NO_STRUCTURAL_EXEMPTIONS = /* @__PURE__ */ new Set();
|
|
9501
9265
|
function editsOnlyNonSchedulingColumns(action) {
|
|
9502
9266
|
if (action.kind === "inline-edit") {
|
|
9503
9267
|
return NON_SCHEDULING_INLINE_COLUMNS.has(action.column);
|
|
@@ -9510,11 +9274,14 @@ function editsOnlyNonSchedulingColumns(action) {
|
|
|
9510
9274
|
return false;
|
|
9511
9275
|
}
|
|
9512
9276
|
function isSchedulingDispatch(action, structuralStaleKinds) {
|
|
9513
|
-
if (
|
|
9277
|
+
if (NON_SCHEDULING_KINDS.has(action.kind)) return false;
|
|
9514
9278
|
if (structuralStaleKinds.has(action.kind)) return false;
|
|
9515
9279
|
if (editsOnlyNonSchedulingColumns(action)) return false;
|
|
9516
9280
|
return true;
|
|
9517
9281
|
}
|
|
9282
|
+
function dispatchChangesSchedulingState(action) {
|
|
9283
|
+
return isSchedulingDispatch(action, NO_STRUCTURAL_EXEMPTIONS);
|
|
9284
|
+
}
|
|
9518
9285
|
function resolveRunCriticalPath(action) {
|
|
9519
9286
|
return isSchedulingDispatch(
|
|
9520
9287
|
action,
|
|
@@ -10233,26 +10000,21 @@ async function dispatchLinkBatch(operations, source, options, deps, deterministi
|
|
|
10233
10000
|
};
|
|
10234
10001
|
}
|
|
10235
10002
|
function pickAutoscheduleTrigger(applied, beforeLinks, adapter) {
|
|
10236
|
-
for (const
|
|
10237
|
-
if (
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
if (a.op.kind === "delete") {
|
|
10242
|
-
const snap = beforeLinks.get(a.op.linkId);
|
|
10243
|
-
if (snap) {
|
|
10244
|
-
return adapter.hasChildren(snap.target) ? "roots" : String(snap.target);
|
|
10245
|
-
}
|
|
10246
|
-
}
|
|
10247
|
-
if (a.op.kind === "update") {
|
|
10248
|
-
const link = adapter.getLink(a.op.linkId);
|
|
10249
|
-
if (link) {
|
|
10250
|
-
return adapter.hasChildren(link.target) ? "roots" : String(link.target);
|
|
10251
|
-
}
|
|
10252
|
-
}
|
|
10003
|
+
for (const operation of applied) {
|
|
10004
|
+
if (operation.rejected !== null) continue;
|
|
10005
|
+
const target = autoscheduleTarget(operation.op, beforeLinks, adapter);
|
|
10006
|
+
if (target !== null)
|
|
10007
|
+
return adapter.hasChildren(target) ? "roots" : String(target);
|
|
10253
10008
|
}
|
|
10254
10009
|
return null;
|
|
10255
10010
|
}
|
|
10011
|
+
function autoscheduleTarget(operation, beforeLinks, adapter) {
|
|
10012
|
+
if (operation.kind === "create") return operation.target;
|
|
10013
|
+
if (operation.kind === "delete") {
|
|
10014
|
+
return beforeLinks.get(operation.linkId)?.target ?? null;
|
|
10015
|
+
}
|
|
10016
|
+
return adapter.getLink(operation.linkId)?.target ?? null;
|
|
10017
|
+
}
|
|
10256
10018
|
function toLinkOperation(action, hoursPerDay) {
|
|
10257
10019
|
if (action.kind === "link-create") {
|
|
10258
10020
|
return {
|
|
@@ -10323,79 +10085,201 @@ var DISPATCH_TRACK_EVENT = {
|
|
|
10323
10085
|
ACTIVITY_OUTDENT: "schedule_activity_outdent"
|
|
10324
10086
|
};
|
|
10325
10087
|
|
|
10326
|
-
// src/
|
|
10327
|
-
|
|
10328
|
-
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
|
|
10332
|
-
|
|
10333
|
-
|
|
10088
|
+
// src/internal/hierarchy/visual-order.ts
|
|
10089
|
+
var NOT_SET_SORT_VALUE = Number.MAX_SAFE_INTEGER;
|
|
10090
|
+
function getChildrenInVisualOrder(parentId, adapter) {
|
|
10091
|
+
const children = collectChildrenSnapshots(parentId, adapter);
|
|
10092
|
+
children.sort(compareActivitiesInVisualOrder);
|
|
10093
|
+
return children.map((a) => String(a.id));
|
|
10094
|
+
}
|
|
10095
|
+
function iterateInVisualOrder(adapter) {
|
|
10096
|
+
const result = [];
|
|
10097
|
+
const visit = (activity) => {
|
|
10098
|
+
result.push(activity);
|
|
10099
|
+
const childIds = getChildrenInVisualOrder(String(activity.id), adapter);
|
|
10334
10100
|
for (const childId of childIds) {
|
|
10335
10101
|
const child = adapter.getActivity(childId);
|
|
10336
|
-
if (
|
|
10337
|
-
const hh = readNumber(child, ACTIVITY_PROPERTY.WORK_HOURS);
|
|
10338
|
-
const rw = readChildRealWork(childId, child, hh, adapter);
|
|
10339
|
-
hhSum += hh;
|
|
10340
|
-
rwSum += rw;
|
|
10102
|
+
if (child) visit(child);
|
|
10341
10103
|
}
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
|
|
10345
|
-
|
|
10346
|
-
);
|
|
10347
|
-
adapter.setActivityField(
|
|
10348
|
-
currentParentId,
|
|
10349
|
-
ACTIVITY_PROPERTY.REAL_WORK_HOURS,
|
|
10350
|
-
rwSum
|
|
10351
|
-
);
|
|
10352
|
-
const parentSnap = adapter.getActivity(currentParentId);
|
|
10353
|
-
if (!parentSnap) break;
|
|
10354
|
-
const grandParent = parentSnap.parentId;
|
|
10355
|
-
if (!grandParent || isRootParent(grandParent)) break;
|
|
10356
|
-
currentParentId = grandParent;
|
|
10104
|
+
};
|
|
10105
|
+
const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter);
|
|
10106
|
+
for (const rootId of rootIds) {
|
|
10107
|
+
const root = adapter.getActivity(rootId);
|
|
10108
|
+
if (root) visit(root);
|
|
10357
10109
|
}
|
|
10110
|
+
return result;
|
|
10358
10111
|
}
|
|
10359
|
-
function
|
|
10360
|
-
const activity = adapter.getActivity(
|
|
10361
|
-
if (!activity) return;
|
|
10362
|
-
const
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
|
|
10112
|
+
function findPreviousNonSelectedSibling(taskId, selected, adapter) {
|
|
10113
|
+
const activity = adapter.getActivity(taskId);
|
|
10114
|
+
if (!activity) return null;
|
|
10115
|
+
const parentKey = parentKeyOf(activity);
|
|
10116
|
+
const siblings = getChildrenInVisualOrder(parentKey, adapter);
|
|
10117
|
+
const idx = siblings.findIndex((id) => String(id) === String(taskId));
|
|
10118
|
+
if (idx <= 0) return null;
|
|
10119
|
+
for (let i = idx - 1; i >= 0; i--) {
|
|
10120
|
+
const candidateId = siblings[i];
|
|
10121
|
+
if (candidateId === void 0) continue;
|
|
10122
|
+
if (!setHas(selected, candidateId)) return candidateId;
|
|
10123
|
+
}
|
|
10124
|
+
return null;
|
|
10370
10125
|
}
|
|
10371
|
-
function
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
-
|
|
10375
|
-
);
|
|
10126
|
+
function visualIndexInParent(taskId, adapter) {
|
|
10127
|
+
const activity = adapter.getActivity(taskId);
|
|
10128
|
+
if (!activity) return -1;
|
|
10129
|
+
const parentKey = parentKeyOf(activity);
|
|
10130
|
+
const siblings = getChildrenInVisualOrder(parentKey, adapter);
|
|
10131
|
+
return siblings.findIndex((id) => String(id) === String(taskId));
|
|
10376
10132
|
}
|
|
10377
|
-
|
|
10378
|
-
|
|
10379
|
-
|
|
10380
|
-
|
|
10381
|
-
let currentParentId = String(startParentId);
|
|
10382
|
-
while (currentParentId !== null) {
|
|
10383
|
-
const childIds = adapter.getChildren(currentParentId);
|
|
10384
|
-
let sum = 0;
|
|
10385
|
-
for (const childId of childIds) {
|
|
10386
|
-
const child = adapter.getActivity(childId);
|
|
10387
|
-
if (!child) continue;
|
|
10388
|
-
sum += readNumber2(child, ACTIVITY_PROPERTY.USED_COST);
|
|
10389
|
-
}
|
|
10390
|
-
adapter.setActivityField(currentParentId, ACTIVITY_PROPERTY.USED_COST, sum);
|
|
10391
|
-
const parentSnap = adapter.getActivity(currentParentId);
|
|
10392
|
-
if (!parentSnap) break;
|
|
10393
|
-
const grandParent = parentSnap.parentId;
|
|
10394
|
-
if (!grandParent || isRootParent(grandParent)) break;
|
|
10395
|
-
currentParentId = grandParent;
|
|
10133
|
+
function collectChildrenSnapshots(parentId, adapter) {
|
|
10134
|
+
const key = String(parentId);
|
|
10135
|
+
if (key === "0") {
|
|
10136
|
+
return adapter.getAllActivities().filter((a) => a.parentId === null);
|
|
10396
10137
|
}
|
|
10138
|
+
const childIds = adapter.getChildren(parentId);
|
|
10139
|
+
const out = [];
|
|
10140
|
+
for (const id of childIds) {
|
|
10141
|
+
const snap = adapter.getActivity(id);
|
|
10142
|
+
if (snap) out.push(snap);
|
|
10143
|
+
}
|
|
10144
|
+
return out;
|
|
10397
10145
|
}
|
|
10398
|
-
function
|
|
10146
|
+
function compareActivitiesInVisualOrder(a, b) {
|
|
10147
|
+
const ac = correlativeIdOf(a);
|
|
10148
|
+
const bc = correlativeIdOf(b);
|
|
10149
|
+
if (ac !== bc) return ac - bc;
|
|
10150
|
+
return String(a.id).localeCompare(String(b.id));
|
|
10151
|
+
}
|
|
10152
|
+
function correlativeIdOf(activity) {
|
|
10153
|
+
const raw = activity.correlativeId;
|
|
10154
|
+
const n = typeof raw === "number" ? raw : Number(raw);
|
|
10155
|
+
return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
|
|
10156
|
+
}
|
|
10157
|
+
function parentKeyOf(activity) {
|
|
10158
|
+
const parentId = activity.parentId;
|
|
10159
|
+
if (parentId === null) return "0";
|
|
10160
|
+
return parentId;
|
|
10161
|
+
}
|
|
10162
|
+
function setHas(set, id) {
|
|
10163
|
+
if (set.has(id)) return true;
|
|
10164
|
+
return set.has(String(id));
|
|
10165
|
+
}
|
|
10166
|
+
|
|
10167
|
+
// src/internal/hierarchy/recompute-correlative-ids.ts
|
|
10168
|
+
function recomputeCorrelativeIds(adapter) {
|
|
10169
|
+
adapter.invalidateVisualOrderIds?.();
|
|
10170
|
+
const roots = [];
|
|
10171
|
+
adapter.forEachActivity((activity) => {
|
|
10172
|
+
if (isRootParent(activity.parentId)) roots.push(activity);
|
|
10173
|
+
});
|
|
10174
|
+
roots.sort(byCorrelativeId);
|
|
10175
|
+
const stack = [];
|
|
10176
|
+
pushInReverseOrder(stack, roots);
|
|
10177
|
+
const shifts = [];
|
|
10178
|
+
let counter = 0;
|
|
10179
|
+
while (stack.length > 0) {
|
|
10180
|
+
const activity = stack.pop();
|
|
10181
|
+
if (activity.correlativeId !== counter) {
|
|
10182
|
+
const before = typeof activity.correlativeId === "number" ? activity.correlativeId : void 0;
|
|
10183
|
+
shifts.push({ activityId: String(activity.id), before });
|
|
10184
|
+
if (before !== void 0)
|
|
10185
|
+
adapter.noteCorrelativeBefore?.(String(activity.id), before);
|
|
10186
|
+
setCorrelativeId(activity, counter);
|
|
10187
|
+
}
|
|
10188
|
+
counter += 1;
|
|
10189
|
+
const children = collectChildrenSnapshots(String(activity.id), adapter);
|
|
10190
|
+
children.sort(byCorrelativeId);
|
|
10191
|
+
pushInReverseOrder(stack, children);
|
|
10192
|
+
}
|
|
10193
|
+
return shifts;
|
|
10194
|
+
}
|
|
10195
|
+
function pushInReverseOrder(stack, activities) {
|
|
10196
|
+
for (let i = activities.length - 1; i >= 0; i -= 1) {
|
|
10197
|
+
stack.push(activities[i]);
|
|
10198
|
+
}
|
|
10199
|
+
}
|
|
10200
|
+
function getCorrelativeId(activity) {
|
|
10201
|
+
const raw = activity.correlativeId;
|
|
10202
|
+
const n = typeof raw === "number" ? raw : Number(raw);
|
|
10203
|
+
return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
|
|
10204
|
+
}
|
|
10205
|
+
var byCorrelativeId = (a, b) => getCorrelativeId(a) - getCorrelativeId(b);
|
|
10206
|
+
function setCorrelativeId(activity, value) {
|
|
10207
|
+
activity.correlativeId = value;
|
|
10208
|
+
}
|
|
10209
|
+
|
|
10210
|
+
// src/propagations/upward/recompute-hh-cascade.ts
|
|
10211
|
+
function recomputeHhCascadeForParent(startParentId, adapter) {
|
|
10212
|
+
if (!startParentId || startParentId === "0") return;
|
|
10213
|
+
let currentParentId = String(startParentId);
|
|
10214
|
+
while (currentParentId !== null) {
|
|
10215
|
+
const childIds = adapter.getChildren(currentParentId);
|
|
10216
|
+
let hhSum = 0;
|
|
10217
|
+
let rwSum = 0;
|
|
10218
|
+
for (const childId of childIds) {
|
|
10219
|
+
const child = adapter.getActivity(childId);
|
|
10220
|
+
if (!child) continue;
|
|
10221
|
+
const hh = readNumber(child, ACTIVITY_PROPERTY.WORK_HOURS);
|
|
10222
|
+
const rw = readChildRealWork(childId, child, hh, adapter);
|
|
10223
|
+
hhSum += hh;
|
|
10224
|
+
rwSum += rw;
|
|
10225
|
+
}
|
|
10226
|
+
adapter.setActivityField(
|
|
10227
|
+
currentParentId,
|
|
10228
|
+
ACTIVITY_PROPERTY.WORK_HOURS,
|
|
10229
|
+
hhSum
|
|
10230
|
+
);
|
|
10231
|
+
adapter.setActivityField(
|
|
10232
|
+
currentParentId,
|
|
10233
|
+
ACTIVITY_PROPERTY.REAL_WORK_HOURS,
|
|
10234
|
+
rwSum
|
|
10235
|
+
);
|
|
10236
|
+
const parentSnap = adapter.getActivity(currentParentId);
|
|
10237
|
+
if (!parentSnap) break;
|
|
10238
|
+
const grandParent = parentSnap.parentId;
|
|
10239
|
+
if (!grandParent || isRootParent(grandParent)) break;
|
|
10240
|
+
currentParentId = grandParent;
|
|
10241
|
+
}
|
|
10242
|
+
}
|
|
10243
|
+
function recomputeHhCascadeForActivity(activityId, adapter) {
|
|
10244
|
+
const activity = adapter.getActivity(activityId);
|
|
10245
|
+
if (!activity) return;
|
|
10246
|
+
const parentId = activity.parentId;
|
|
10247
|
+
if (!parentId || isRootParent(parentId)) return;
|
|
10248
|
+
recomputeHhCascadeForParent(parentId, adapter);
|
|
10249
|
+
}
|
|
10250
|
+
function readNumber(activity, key) {
|
|
10251
|
+
const v = activity[key];
|
|
10252
|
+
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
10253
|
+
return 0;
|
|
10254
|
+
}
|
|
10255
|
+
function readChildRealWork(childId, child, workHours, adapter) {
|
|
10256
|
+
return adapter.hasChildren(childId) ? readNumber(child, ACTIVITY_PROPERTY.REAL_WORK_HOURS) : computeLeafRealWork(
|
|
10257
|
+
workHours,
|
|
10258
|
+
readNumber(child, ACTIVITY_PROPERTY.PROGRESS)
|
|
10259
|
+
);
|
|
10260
|
+
}
|
|
10261
|
+
|
|
10262
|
+
// src/propagations/upward/recompute-used-cost-cascade.ts
|
|
10263
|
+
function recomputeUsedCostCascadeForParent(startParentId, adapter) {
|
|
10264
|
+
if (!startParentId || startParentId === "0") return;
|
|
10265
|
+
let currentParentId = String(startParentId);
|
|
10266
|
+
while (currentParentId !== null) {
|
|
10267
|
+
const childIds = adapter.getChildren(currentParentId);
|
|
10268
|
+
let sum = 0;
|
|
10269
|
+
for (const childId of childIds) {
|
|
10270
|
+
const child = adapter.getActivity(childId);
|
|
10271
|
+
if (!child) continue;
|
|
10272
|
+
sum += readNumber2(child, ACTIVITY_PROPERTY.USED_COST);
|
|
10273
|
+
}
|
|
10274
|
+
adapter.setActivityField(currentParentId, ACTIVITY_PROPERTY.USED_COST, sum);
|
|
10275
|
+
const parentSnap = adapter.getActivity(currentParentId);
|
|
10276
|
+
if (!parentSnap) break;
|
|
10277
|
+
const grandParent = parentSnap.parentId;
|
|
10278
|
+
if (!grandParent || isRootParent(grandParent)) break;
|
|
10279
|
+
currentParentId = grandParent;
|
|
10280
|
+
}
|
|
10281
|
+
}
|
|
10282
|
+
function recomputeUsedCostCascadeForActivity(activityId, adapter) {
|
|
10399
10283
|
const activity = adapter.getActivity(activityId);
|
|
10400
10284
|
if (!activity) return;
|
|
10401
10285
|
const parentId = activity.parentId;
|
|
@@ -10873,27 +10757,6 @@ function buildCreateChangeSet(adapter, action, coreResult, scheduledIds, hoursPe
|
|
|
10873
10757
|
scheduledBeforeImages: existingScheduledBeforeImages,
|
|
10874
10758
|
trackingEvents: [trackingEvent]});
|
|
10875
10759
|
}
|
|
10876
|
-
function createActivitySync(action, deps) {
|
|
10877
|
-
const result = createActivityCore(action, deps);
|
|
10878
|
-
if (!result.ok) {
|
|
10879
|
-
return { ok: false, reason: result.reason };
|
|
10880
|
-
}
|
|
10881
|
-
recomputeParentBoundsSync(deps.adapter, /* @__PURE__ */ new Set([result.newId]));
|
|
10882
|
-
const snapshot = deps.adapter.getActivity(result.newId);
|
|
10883
|
-
if (!snapshot) {
|
|
10884
|
-
throw new Error(
|
|
10885
|
-
`[ScheduleCore] createActivity: new activity ${result.newId} missing after commit`
|
|
10886
|
-
);
|
|
10887
|
-
}
|
|
10888
|
-
const changes = buildCreateChangeSet(
|
|
10889
|
-
deps.adapter,
|
|
10890
|
-
action,
|
|
10891
|
-
result,
|
|
10892
|
-
[],
|
|
10893
|
-
deps.sector.hoursPerDay
|
|
10894
|
-
);
|
|
10895
|
-
return { ok: true, activity: snapshot, changes };
|
|
10896
|
-
}
|
|
10897
10760
|
async function dispatchActivityCreate(action, options, deps) {
|
|
10898
10761
|
const { adapter, scheduler, sector } = deps;
|
|
10899
10762
|
const core = createActivityCore(action, deps);
|
|
@@ -12549,17 +12412,524 @@ function mergeBeforeSnapshots2(beforeSnap, ids, deps) {
|
|
|
12549
12412
|
for (const candidateId of ids) {
|
|
12550
12413
|
if (!beforeSnap.has(candidateId)) missing.add(candidateId);
|
|
12551
12414
|
}
|
|
12552
|
-
if (missing.size === 0) return;
|
|
12553
|
-
for (const [snappedId, snapshot] of snapshotActivities(
|
|
12415
|
+
if (missing.size === 0) return;
|
|
12416
|
+
for (const [snappedId, snapshot] of snapshotActivities(
|
|
12417
|
+
deps.adapter,
|
|
12418
|
+
missing
|
|
12419
|
+
)) {
|
|
12420
|
+
beforeSnap.set(snappedId, snapshot);
|
|
12421
|
+
}
|
|
12422
|
+
}
|
|
12423
|
+
|
|
12424
|
+
// src/dispatch/handlers/persistence-acknowledge.ts
|
|
12425
|
+
function assertValidAssignment(assignment, entityName, readCurrent, ownerByBackendId, seenIds, seenBackendIds) {
|
|
12426
|
+
const id = String(assignment.id);
|
|
12427
|
+
if (id.length === 0 || seenIds.has(id)) {
|
|
12428
|
+
throw new Error(
|
|
12429
|
+
`persistence-acknowledge: duplicate or empty ${entityName} id "${id}"`
|
|
12430
|
+
);
|
|
12431
|
+
}
|
|
12432
|
+
if (!Number.isSafeInteger(assignment.proplannerId) || assignment.proplannerId <= 0) {
|
|
12433
|
+
throw new Error(
|
|
12434
|
+
`persistence-acknowledge: invalid ${entityName} proplannerId ${String(assignment.proplannerId)}`
|
|
12435
|
+
);
|
|
12436
|
+
}
|
|
12437
|
+
if (seenBackendIds.has(assignment.proplannerId)) {
|
|
12438
|
+
throw new Error(
|
|
12439
|
+
`persistence-acknowledge: duplicate ${entityName} proplannerId ${String(assignment.proplannerId)}`
|
|
12440
|
+
);
|
|
12441
|
+
}
|
|
12442
|
+
const state = readCurrent(id);
|
|
12443
|
+
if (!state.exists) {
|
|
12444
|
+
throw new Error(
|
|
12445
|
+
`persistence-acknowledge: unknown ${entityName} id "${id}"`
|
|
12446
|
+
);
|
|
12447
|
+
}
|
|
12448
|
+
if (state.current !== null && state.current !== assignment.proplannerId) {
|
|
12449
|
+
throw new Error(
|
|
12450
|
+
`persistence-acknowledge: ${entityName} "${id}" already has proplannerId ${String(state.current)}`
|
|
12451
|
+
);
|
|
12452
|
+
}
|
|
12453
|
+
const existingOwner = ownerByBackendId.get(assignment.proplannerId);
|
|
12454
|
+
if (existingOwner !== void 0 && existingOwner !== id) {
|
|
12455
|
+
throw new Error(
|
|
12456
|
+
`persistence-acknowledge: ${entityName} proplannerId ${String(assignment.proplannerId)} already belongs to "${existingOwner}"`
|
|
12457
|
+
);
|
|
12458
|
+
}
|
|
12459
|
+
seenIds.add(id);
|
|
12460
|
+
seenBackendIds.add(assignment.proplannerId);
|
|
12461
|
+
}
|
|
12462
|
+
function assertValidAssignments(assignments, entityName, readCurrent, ownerByBackendId) {
|
|
12463
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
12464
|
+
const seenBackendIds = /* @__PURE__ */ new Set();
|
|
12465
|
+
for (const assignment of assignments) {
|
|
12466
|
+
assertValidAssignment(
|
|
12467
|
+
assignment,
|
|
12468
|
+
entityName,
|
|
12469
|
+
readCurrent,
|
|
12470
|
+
ownerByBackendId,
|
|
12471
|
+
seenIds,
|
|
12472
|
+
seenBackendIds
|
|
12473
|
+
);
|
|
12474
|
+
}
|
|
12475
|
+
}
|
|
12476
|
+
function dispatchPersistenceAcknowledge(action, deps) {
|
|
12477
|
+
const activities = action.activities ?? [];
|
|
12478
|
+
const links = action.links ?? [];
|
|
12479
|
+
const activityOwnerByBackendId = /* @__PURE__ */ new Map();
|
|
12480
|
+
for (const activity of deps.adapter.getAllActivities()) {
|
|
12481
|
+
if (activity.proplannerId != null) {
|
|
12482
|
+
activityOwnerByBackendId.set(activity.proplannerId, String(activity.id));
|
|
12483
|
+
}
|
|
12484
|
+
}
|
|
12485
|
+
const linkOwnerByBackendId = /* @__PURE__ */ new Map();
|
|
12486
|
+
for (const link of deps.adapter.getAllLinks()) {
|
|
12487
|
+
if (link.proplannerId != null) {
|
|
12488
|
+
linkOwnerByBackendId.set(link.proplannerId, String(link.id));
|
|
12489
|
+
}
|
|
12490
|
+
}
|
|
12491
|
+
assertValidAssignments(
|
|
12492
|
+
activities,
|
|
12493
|
+
"activity",
|
|
12494
|
+
(id) => {
|
|
12495
|
+
const activity = deps.adapter.getActivity(id);
|
|
12496
|
+
return {
|
|
12497
|
+
exists: activity !== null,
|
|
12498
|
+
current: activity?.proplannerId ?? null
|
|
12499
|
+
};
|
|
12500
|
+
},
|
|
12501
|
+
activityOwnerByBackendId
|
|
12502
|
+
);
|
|
12503
|
+
assertValidAssignments(
|
|
12504
|
+
links,
|
|
12505
|
+
"link",
|
|
12506
|
+
(id) => {
|
|
12507
|
+
const link = deps.adapter.getLink(id);
|
|
12508
|
+
return { exists: link !== null, current: link?.proplannerId ?? null };
|
|
12509
|
+
},
|
|
12510
|
+
linkOwnerByBackendId
|
|
12511
|
+
);
|
|
12512
|
+
const activityChanges = [];
|
|
12513
|
+
const linkChanges = [];
|
|
12514
|
+
deps.adapter.batchUpdate(() => {
|
|
12515
|
+
for (const assignment of activities) {
|
|
12516
|
+
const before = deps.adapter.getActivity(assignment.id);
|
|
12517
|
+
if (!before || before.proplannerId === assignment.proplannerId) continue;
|
|
12518
|
+
deps.adapter.setActivityField(
|
|
12519
|
+
assignment.id,
|
|
12520
|
+
"proplannerId",
|
|
12521
|
+
assignment.proplannerId
|
|
12522
|
+
);
|
|
12523
|
+
activityChanges.push({
|
|
12524
|
+
id: assignment.id,
|
|
12525
|
+
kind: "updated",
|
|
12526
|
+
fields: {
|
|
12527
|
+
proplannerId: {
|
|
12528
|
+
before: before.proplannerId,
|
|
12529
|
+
after: assignment.proplannerId
|
|
12530
|
+
}
|
|
12531
|
+
},
|
|
12532
|
+
after: { ...before, proplannerId: assignment.proplannerId }
|
|
12533
|
+
});
|
|
12534
|
+
}
|
|
12535
|
+
for (const assignment of links) {
|
|
12536
|
+
const before = deps.adapter.getLink(assignment.id);
|
|
12537
|
+
if (!before || before.proplannerId === assignment.proplannerId) continue;
|
|
12538
|
+
deps.adapter.setLinkProplannerId(assignment.id, assignment.proplannerId);
|
|
12539
|
+
linkChanges.push({
|
|
12540
|
+
id: assignment.id,
|
|
12541
|
+
kind: "updated",
|
|
12542
|
+
fields: {
|
|
12543
|
+
proplannerId: {
|
|
12544
|
+
before: before.proplannerId,
|
|
12545
|
+
after: assignment.proplannerId
|
|
12546
|
+
}
|
|
12547
|
+
},
|
|
12548
|
+
after: { ...before, proplannerId: assignment.proplannerId }
|
|
12549
|
+
});
|
|
12550
|
+
}
|
|
12551
|
+
});
|
|
12552
|
+
return {
|
|
12553
|
+
ok: true,
|
|
12554
|
+
changes: {
|
|
12555
|
+
source: action,
|
|
12556
|
+
activities: activityChanges,
|
|
12557
|
+
links: linkChanges,
|
|
12558
|
+
calendars: [],
|
|
12559
|
+
trackingEvents: []
|
|
12560
|
+
}
|
|
12561
|
+
};
|
|
12562
|
+
}
|
|
12563
|
+
|
|
12564
|
+
// src/baselines/normalize-baseline-point.ts
|
|
12565
|
+
function parseBaselineDate(value) {
|
|
12566
|
+
return typeof value === "string" && value.length > 0 ? parseBackendDate(value) : value instanceof Date ? value : null;
|
|
12567
|
+
}
|
|
12568
|
+
function parseFiniteNonNegative(value) {
|
|
12569
|
+
const numeric = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : Number.NaN;
|
|
12570
|
+
if (!Number.isFinite(numeric) || numeric < 0) return null;
|
|
12571
|
+
return numeric;
|
|
12572
|
+
}
|
|
12573
|
+
function normalizeBaselinePoint(point, reporter) {
|
|
12574
|
+
const durationDays = parseFiniteNonNegative(point.duration);
|
|
12575
|
+
const cost = parseFiniteNonNegative(point.cost);
|
|
12576
|
+
const workHours = parseFiniteNonNegative(point.hh_work);
|
|
12577
|
+
if (durationDays === null || cost === null || workHours === null) {
|
|
12578
|
+
reporter.warn(
|
|
12579
|
+
`[baseline] dropping point with non-finite/negative magnitude \u2014 duration=${JSON.stringify(point.duration)}, cost=${JSON.stringify(point.cost)}, hh_work=${JSON.stringify(point.hh_work)}`
|
|
12580
|
+
);
|
|
12581
|
+
return null;
|
|
12582
|
+
}
|
|
12583
|
+
return {
|
|
12584
|
+
startDate: parseBaselineDate(point.start_date),
|
|
12585
|
+
endDate: parseBaselineDate(point.end_date),
|
|
12586
|
+
durationDays,
|
|
12587
|
+
cost,
|
|
12588
|
+
workHours,
|
|
12589
|
+
versionId: typeof point.sectorbaselineversionId === "number" ? point.sectorbaselineversionId : null,
|
|
12590
|
+
isActiveVersion: Boolean(point.sectorbaselineversion?.active),
|
|
12591
|
+
isVisibleVersion: Boolean(point.sectorbaselineversion?.visible),
|
|
12592
|
+
baseCalendarId: point.baseCalendarId != null ? String(point.baseCalendarId) : null,
|
|
12593
|
+
hoursPerDay: typeof point.hoursPerDay === "number" ? point.hoursPerDay : null,
|
|
12594
|
+
hoursPerWeek: typeof point.hoursPerWeek === "number" ? point.hoursPerWeek : null
|
|
12595
|
+
};
|
|
12596
|
+
}
|
|
12597
|
+
|
|
12598
|
+
// src/baselines/apply-baseline-points.ts
|
|
12599
|
+
function applyBaselinePoints(adapter, points, reporter) {
|
|
12600
|
+
const idByProplanner = /* @__PURE__ */ new Map();
|
|
12601
|
+
adapter.forEachActivity((a, id) => {
|
|
12602
|
+
const pid = a.proplannerId;
|
|
12603
|
+
if (typeof pid === "number") idByProplanner.set(pid, id);
|
|
12604
|
+
});
|
|
12605
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
12606
|
+
for (const p of points) {
|
|
12607
|
+
const activityId = p.activityId;
|
|
12608
|
+
if (typeof activityId !== "number") continue;
|
|
12609
|
+
const coreId = idByProplanner.get(activityId);
|
|
12610
|
+
if (coreId === void 0) continue;
|
|
12611
|
+
const arr = grouped.get(coreId);
|
|
12612
|
+
if (arr) arr.push(p);
|
|
12613
|
+
else grouped.set(coreId, [p]);
|
|
12614
|
+
}
|
|
12615
|
+
const changed = [];
|
|
12616
|
+
for (const [coreId, group] of grouped) {
|
|
12617
|
+
adapter.setActivityField(
|
|
12618
|
+
coreId,
|
|
12619
|
+
"baselinePoints",
|
|
12620
|
+
group.map((point) => normalizeBaselinePoint(point, reporter)).filter((point) => point !== null)
|
|
12621
|
+
);
|
|
12622
|
+
changed.push(coreId);
|
|
12623
|
+
}
|
|
12624
|
+
adapter.forEachActivity((a, id) => {
|
|
12625
|
+
if (grouped.has(id)) return;
|
|
12626
|
+
const existing = a.baselinePoints;
|
|
12627
|
+
if (Array.isArray(existing) && existing.length > 0) {
|
|
12628
|
+
adapter.setActivityField(id, "baselinePoints", []);
|
|
12629
|
+
changed.push(id);
|
|
12630
|
+
}
|
|
12631
|
+
});
|
|
12632
|
+
return changed;
|
|
12633
|
+
}
|
|
12634
|
+
|
|
12635
|
+
// src/baselines/baseline-snapshot.ts
|
|
12636
|
+
function buildBaselineSnapshot(activity) {
|
|
12637
|
+
const active = getActiveBaseline(activity);
|
|
12638
|
+
if (!active) return null;
|
|
12639
|
+
return {
|
|
12640
|
+
startDate: active.startDate,
|
|
12641
|
+
endDate: active.endDate,
|
|
12642
|
+
durationDays: active.durationDays,
|
|
12643
|
+
cost: active.cost,
|
|
12644
|
+
workHours: active.workHours
|
|
12645
|
+
};
|
|
12646
|
+
}
|
|
12647
|
+
function emitBaselineSnapshotColumns(state) {
|
|
12648
|
+
const changed = [];
|
|
12649
|
+
state.forEachActivity((activity, id) => {
|
|
12650
|
+
const snapshot = buildBaselineSnapshot(activity);
|
|
12651
|
+
if (!snapshot) {
|
|
12652
|
+
if (activity.baselineSnapshot !== null) {
|
|
12653
|
+
state.setActivityField(id, "baselineSnapshot", null);
|
|
12654
|
+
changed.push(id);
|
|
12655
|
+
}
|
|
12656
|
+
return;
|
|
12657
|
+
}
|
|
12658
|
+
state.setActivityField(id, "baselineSnapshot", snapshot);
|
|
12659
|
+
changed.push(id);
|
|
12660
|
+
});
|
|
12661
|
+
return changed;
|
|
12662
|
+
}
|
|
12663
|
+
|
|
12664
|
+
// src/baselines/apply-baseline-overlay.ts
|
|
12665
|
+
function applyBaselineOverlay(state, points, now, reporter, defaultBaseCalendarId = null) {
|
|
12666
|
+
const changed = /* @__PURE__ */ new Set();
|
|
12667
|
+
for (const id of applyBaselinePoints(
|
|
12668
|
+
state,
|
|
12669
|
+
points,
|
|
12670
|
+
reporter
|
|
12671
|
+
)) {
|
|
12672
|
+
changed.add(id);
|
|
12673
|
+
}
|
|
12674
|
+
if (now) {
|
|
12675
|
+
for (const id of runExpectedProgressBase(state, now, defaultBaseCalendarId))
|
|
12676
|
+
changed.add(id);
|
|
12677
|
+
}
|
|
12678
|
+
for (const id of emitBaselineSnapshotColumns(state)) changed.add(id);
|
|
12679
|
+
for (const id of emitRealCost(state)) changed.add(id);
|
|
12680
|
+
return [...changed];
|
|
12681
|
+
}
|
|
12682
|
+
|
|
12683
|
+
// src/propagations/downward/recompute-ponderator-for-parent.ts
|
|
12684
|
+
function recomputePonderatorsForParent(parentId, criterion, adapter) {
|
|
12685
|
+
if (!parentId || parentId === "0") return;
|
|
12686
|
+
const childIds = adapter.getChildren(parentId);
|
|
12687
|
+
if (childIds.length === 0) return;
|
|
12688
|
+
const pesoById = /* @__PURE__ */ new Map();
|
|
12689
|
+
let denominator = 0;
|
|
12690
|
+
for (const childId of childIds) {
|
|
12691
|
+
const peso = criterionValue(String(childId), criterion, adapter);
|
|
12692
|
+
pesoById.set(String(childId), peso);
|
|
12693
|
+
denominator += peso;
|
|
12694
|
+
}
|
|
12695
|
+
const relationValue = denominator ? 100 / denominator : 0;
|
|
12696
|
+
for (const childId of childIds) {
|
|
12697
|
+
const child = adapter.getActivity(childId);
|
|
12698
|
+
if (!child) continue;
|
|
12699
|
+
const points = child.baselinePoints;
|
|
12700
|
+
const active = getActiveBaseline(child);
|
|
12701
|
+
if (active) {
|
|
12702
|
+
const peso = pesoById.get(String(childId)) ?? 0;
|
|
12703
|
+
adapter.setActivityField(
|
|
12704
|
+
childId,
|
|
12705
|
+
COLUMN.PONDERATOR,
|
|
12706
|
+
relationValue * peso
|
|
12707
|
+
);
|
|
12708
|
+
} else if (!Array.isArray(points) || points.length === 0) {
|
|
12709
|
+
adapter.setActivityField(childId, COLUMN.PONDERATOR, 0);
|
|
12710
|
+
}
|
|
12711
|
+
}
|
|
12712
|
+
}
|
|
12713
|
+
function criterionValue(childId, criterion, adapter) {
|
|
12714
|
+
const child = adapter.getActivity(childId);
|
|
12715
|
+
if (!child) return 0;
|
|
12716
|
+
const active = getActiveBaseline(child);
|
|
12717
|
+
if (!active) return 0;
|
|
12718
|
+
if (criterion === "COST") return toNumber(active.cost);
|
|
12719
|
+
if (criterion === "HH") return toNumber(active.workHours);
|
|
12720
|
+
const type = child.type;
|
|
12721
|
+
if (type === "project")
|
|
12722
|
+
return sumRecursiveBaselineDurationDays(childId, adapter);
|
|
12723
|
+
if (type === "milestone") return 0;
|
|
12724
|
+
return toNumber(active.durationDays);
|
|
12725
|
+
}
|
|
12726
|
+
function sumRecursiveBaselineDurationDays(activityId, adapter) {
|
|
12727
|
+
let sum = 0;
|
|
12728
|
+
for (const childId of adapter.getChildren(activityId)) {
|
|
12729
|
+
const child = adapter.getActivity(childId);
|
|
12730
|
+
if (!child) continue;
|
|
12731
|
+
const active = getActiveBaseline(child);
|
|
12732
|
+
if (!active) continue;
|
|
12733
|
+
const type = child.type;
|
|
12734
|
+
if (type === "project") {
|
|
12735
|
+
sum += sumRecursiveBaselineDurationDays(String(childId), adapter);
|
|
12736
|
+
} else if (type !== "milestone") {
|
|
12737
|
+
sum += toNumber(active.durationDays);
|
|
12738
|
+
}
|
|
12739
|
+
}
|
|
12740
|
+
return sum;
|
|
12741
|
+
}
|
|
12742
|
+
function toNumber(v) {
|
|
12743
|
+
const n = typeof v === "string" ? parseFloat(v) : v;
|
|
12744
|
+
return typeof n === "number" && Number.isFinite(n) ? n : 0;
|
|
12745
|
+
}
|
|
12746
|
+
|
|
12747
|
+
// src/propagations/downward/recompute-all-ponderators.ts
|
|
12748
|
+
function recomputeAllPonderators(criterion, adapter) {
|
|
12749
|
+
adapter.forEachActivity((_a, id) => {
|
|
12750
|
+
adapter.setActivityField(id, COLUMN.PONDERATOR, 0);
|
|
12751
|
+
});
|
|
12752
|
+
adapter.forEachActivity((_a, id) => {
|
|
12753
|
+
if (adapter.getChildren(id).length > 0) {
|
|
12754
|
+
recomputePonderatorsForParent(String(id), criterion, adapter);
|
|
12755
|
+
}
|
|
12756
|
+
});
|
|
12757
|
+
}
|
|
12758
|
+
|
|
12759
|
+
// src/propagations/upward/progress-rollup.ts
|
|
12760
|
+
function recomputeAllProgressRollup(adapter) {
|
|
12761
|
+
for (const parentId of parentsDeepestFirst(adapter)) {
|
|
12762
|
+
rollupParent(parentId, adapter);
|
|
12763
|
+
}
|
|
12764
|
+
}
|
|
12765
|
+
function parentsDeepestFirst(adapter) {
|
|
12766
|
+
const parents = /* @__PURE__ */ new Set();
|
|
12767
|
+
adapter.forEachActivity((_activity, id) => {
|
|
12768
|
+
if (adapter.getChildren(id).length > 0) parents.add(id);
|
|
12769
|
+
});
|
|
12770
|
+
const depthById = /* @__PURE__ */ new Map();
|
|
12771
|
+
for (const id of parents) depthById.set(id, depthOf2(id, adapter));
|
|
12772
|
+
return [...parents].sort(
|
|
12773
|
+
(a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
|
|
12774
|
+
);
|
|
12775
|
+
}
|
|
12776
|
+
function depthOf2(id, adapter) {
|
|
12777
|
+
let depth = 0;
|
|
12778
|
+
let current = id;
|
|
12779
|
+
while (current && current !== "0") {
|
|
12780
|
+
if (!adapter.getActivity(current)) break;
|
|
12781
|
+
depth += 1;
|
|
12782
|
+
current = adapter.getParentId(current);
|
|
12783
|
+
}
|
|
12784
|
+
return depth;
|
|
12785
|
+
}
|
|
12786
|
+
function rollupParent(parentId, adapter) {
|
|
12787
|
+
const childIds = adapter.getChildren(parentId);
|
|
12788
|
+
if (childIds.length === 0) return;
|
|
12789
|
+
const children = [];
|
|
12790
|
+
for (const childId of childIds) {
|
|
12791
|
+
const child = adapter.getActivity(childId);
|
|
12792
|
+
if (!child) continue;
|
|
12793
|
+
children.push({
|
|
12794
|
+
progress: Number(child.progress ?? 0),
|
|
12795
|
+
ponderator: Number(child.ponderator ?? 0)
|
|
12796
|
+
});
|
|
12797
|
+
}
|
|
12798
|
+
const rollup = computeWeightedProgressRollup(children);
|
|
12799
|
+
if (rollup !== null) {
|
|
12800
|
+
adapter.setActivityField(
|
|
12801
|
+
parentId,
|
|
12802
|
+
COLUMN.PROGRESS,
|
|
12803
|
+
roundProgressPerLevel(rollup)
|
|
12804
|
+
);
|
|
12805
|
+
}
|
|
12806
|
+
}
|
|
12807
|
+
|
|
12808
|
+
// src/dispatch/shared/baseline-weighted-fields.ts
|
|
12809
|
+
function recomputeBaselineWeightedFields(deps, criterion) {
|
|
12810
|
+
recomputeAllPonderators(criterion, deps.adapter);
|
|
12811
|
+
recomputeAllProgressRollup(deps.adapter);
|
|
12812
|
+
if (deps.now) {
|
|
12813
|
+
runExpectedProgressBase(
|
|
12814
|
+
deps.adapter,
|
|
12815
|
+
deps.now,
|
|
12816
|
+
deps.defaultBaseCalendarId ?? null
|
|
12817
|
+
);
|
|
12818
|
+
applyExpectedProgressLive(deps.adapter, deps.now);
|
|
12819
|
+
}
|
|
12820
|
+
emitRealCost(deps.adapter);
|
|
12821
|
+
if (deps.now) applyStatusPass(deps.adapter, deps.sector.statusCriteria);
|
|
12822
|
+
}
|
|
12823
|
+
|
|
12824
|
+
// src/dispatch/handlers/baseline-apply.ts
|
|
12825
|
+
function activeBaselineSignature(deps) {
|
|
12826
|
+
return JSON.stringify(
|
|
12827
|
+
deps.adapter.getAllIds().map((id) => {
|
|
12828
|
+
const point = deps.adapter.getActivity(id)?.baselinePoints.find((candidate) => candidate.isActiveVersion);
|
|
12829
|
+
return point ? [
|
|
12830
|
+
String(id),
|
|
12831
|
+
point.versionId,
|
|
12832
|
+
point.startDate?.getTime() ?? null,
|
|
12833
|
+
point.endDate?.getTime() ?? null,
|
|
12834
|
+
point.durationDays,
|
|
12835
|
+
point.cost,
|
|
12836
|
+
point.workHours,
|
|
12837
|
+
point.baseCalendarId,
|
|
12838
|
+
point.hoursPerDay,
|
|
12839
|
+
point.hoursPerWeek
|
|
12840
|
+
] : [String(id), null];
|
|
12841
|
+
})
|
|
12842
|
+
);
|
|
12843
|
+
}
|
|
12844
|
+
function dispatchBaselineApply(action, deps) {
|
|
12845
|
+
const beforeSnap = snapshotActivities(
|
|
12554
12846
|
deps.adapter,
|
|
12555
|
-
|
|
12556
|
-
)
|
|
12557
|
-
|
|
12847
|
+
new Set(deps.adapter.getAllIds())
|
|
12848
|
+
);
|
|
12849
|
+
const activeBaselineBefore = activeBaselineSignature(deps);
|
|
12850
|
+
const changedIds = applyBaselineOverlay(
|
|
12851
|
+
deps.adapter,
|
|
12852
|
+
action.points,
|
|
12853
|
+
deps.now,
|
|
12854
|
+
deps.reporter,
|
|
12855
|
+
deps.defaultBaseCalendarId ?? null
|
|
12856
|
+
);
|
|
12857
|
+
if (activeBaselineSignature(deps) !== activeBaselineBefore) {
|
|
12858
|
+
recomputeBaselineWeightedFields(
|
|
12859
|
+
deps,
|
|
12860
|
+
deps.sector.activityCreter ?? "DURATION"
|
|
12861
|
+
);
|
|
12558
12862
|
}
|
|
12863
|
+
return {
|
|
12864
|
+
ok: true,
|
|
12865
|
+
changes: assembleChangeSet(deps.adapter, {
|
|
12866
|
+
source: action,
|
|
12867
|
+
beforeSnap,
|
|
12868
|
+
touchedIds: changedIds,
|
|
12869
|
+
scheduledIds: [],
|
|
12870
|
+
hoursPerDay: deps.sector.hoursPerDay
|
|
12871
|
+
})
|
|
12872
|
+
};
|
|
12873
|
+
}
|
|
12874
|
+
|
|
12875
|
+
// src/dispatch/handlers/ponderator-criterion-set.ts
|
|
12876
|
+
function assertValidCriterion(value) {
|
|
12877
|
+
if (value === "DURATION" || value === "COST" || value === "HH") return;
|
|
12878
|
+
throw new Error(
|
|
12879
|
+
`ponderator-criterion-set: invalid criterion "${String(value)}"`
|
|
12880
|
+
);
|
|
12881
|
+
}
|
|
12882
|
+
function dispatchPonderatorCriterionSet(action, deps) {
|
|
12883
|
+
assertValidCriterion(action.criterion);
|
|
12884
|
+
const allIds = new Set(deps.adapter.getAllIds());
|
|
12885
|
+
const beforeSnap = snapshotActivities(deps.adapter, allIds);
|
|
12886
|
+
recomputeBaselineWeightedFields(deps, action.criterion);
|
|
12887
|
+
deps.sector.activityCreter = action.criterion;
|
|
12888
|
+
return {
|
|
12889
|
+
ok: true,
|
|
12890
|
+
changes: assembleChangeSet(deps.adapter, {
|
|
12891
|
+
source: action,
|
|
12892
|
+
beforeSnap,
|
|
12893
|
+
touchedIds: allIds,
|
|
12894
|
+
scheduledIds: [],
|
|
12895
|
+
hoursPerDay: deps.sector.hoursPerDay
|
|
12896
|
+
})
|
|
12897
|
+
};
|
|
12898
|
+
}
|
|
12899
|
+
|
|
12900
|
+
// src/dispatch/handlers/status-criteria-set.ts
|
|
12901
|
+
function dispatchStatusCriteriaSet(action, deps) {
|
|
12902
|
+
const resolved = resolveStatusCriteria(action.criteria);
|
|
12903
|
+
const allIds = new Set(deps.adapter.getAllIds());
|
|
12904
|
+
const beforeSnap = snapshotActivities(deps.adapter, allIds);
|
|
12905
|
+
const changedIds = applyStatusPass(deps.adapter, resolved);
|
|
12906
|
+
deps.sector.statusCriteria = resolved;
|
|
12907
|
+
return {
|
|
12908
|
+
ok: true,
|
|
12909
|
+
changes: assembleChangeSet(deps.adapter, {
|
|
12910
|
+
source: action,
|
|
12911
|
+
beforeSnap,
|
|
12912
|
+
touchedIds: changedIds,
|
|
12913
|
+
scheduledIds: [],
|
|
12914
|
+
hoursPerDay: deps.sector.hoursPerDay
|
|
12915
|
+
})
|
|
12916
|
+
};
|
|
12559
12917
|
}
|
|
12560
12918
|
|
|
12561
12919
|
// src/dispatch/dispatch.ts
|
|
12562
12920
|
async function dispatch(action, options, deps) {
|
|
12921
|
+
if (action.kind === "persistence-acknowledge") {
|
|
12922
|
+
return dispatchPersistenceAcknowledge(action, deps);
|
|
12923
|
+
}
|
|
12924
|
+
if (action.kind === "baseline-apply") {
|
|
12925
|
+
return dispatchBaselineApply(action, deps);
|
|
12926
|
+
}
|
|
12927
|
+
if (action.kind === "ponderator-criterion-set") {
|
|
12928
|
+
return dispatchPonderatorCriterionSet(action, deps);
|
|
12929
|
+
}
|
|
12930
|
+
if (action.kind === "status-criteria-set") {
|
|
12931
|
+
return dispatchStatusCriteriaSet(action, deps);
|
|
12932
|
+
}
|
|
12563
12933
|
if (action.kind === "link-create" || action.kind === "link-update" || action.kind === "link-delete") {
|
|
12564
12934
|
return dispatchLink(action, options, deps);
|
|
12565
12935
|
}
|
|
@@ -15723,6 +16093,18 @@ var HierarchyIndex = class {
|
|
|
15723
16093
|
arr.push(activity.id);
|
|
15724
16094
|
this._childrenByParent.set(key, arr);
|
|
15725
16095
|
}
|
|
16096
|
+
const compareIds = (left, right) => {
|
|
16097
|
+
const leftActivity = this.activities.get(left);
|
|
16098
|
+
const rightActivity = this.activities.get(right);
|
|
16099
|
+
if (!(leftActivity && rightActivity)) {
|
|
16100
|
+
return String(left).localeCompare(String(right));
|
|
16101
|
+
}
|
|
16102
|
+
return compareActivitiesInVisualOrder(leftActivity, rightActivity);
|
|
16103
|
+
};
|
|
16104
|
+
this._roots.sort(compareIds);
|
|
16105
|
+
for (const children of this._childrenByParent.values()) {
|
|
16106
|
+
children.sort(compareIds);
|
|
16107
|
+
}
|
|
15726
16108
|
}
|
|
15727
16109
|
};
|
|
15728
16110
|
|
|
@@ -16162,438 +16544,145 @@ var ScheduleState = class {
|
|
|
16162
16544
|
this._viewState.restore(this._viewStateBefore);
|
|
16163
16545
|
}
|
|
16164
16546
|
if (this._lastStartDateBefore !== null) {
|
|
16165
|
-
this._lastStartDate = this._lastStartDateBefore;
|
|
16166
|
-
}
|
|
16167
|
-
this._cache.ids = null;
|
|
16168
|
-
this._cache.visualOrderIds = null;
|
|
16169
|
-
this._hierarchy.markDirty();
|
|
16170
|
-
}
|
|
16171
|
-
_restoreCorrelatives(correlativeBefore) {
|
|
16172
|
-
for (const [id, before] of correlativeBefore) {
|
|
16173
|
-
const live = this._activities.get(id);
|
|
16174
|
-
if (live) live.correlativeId = before;
|
|
16175
|
-
}
|
|
16176
|
-
}
|
|
16177
|
-
_undoLinkAdds(ops) {
|
|
16178
|
-
for (const op of ops)
|
|
16179
|
-
if (op.kind === "link-add") this._detachLink(op.linkId);
|
|
16180
|
-
}
|
|
16181
|
-
_undoInserts(ops) {
|
|
16182
|
-
for (const op of ops)
|
|
16183
|
-
if (op.kind === "insert") this._activities.delete(op.activityId);
|
|
16184
|
-
}
|
|
16185
|
-
_reInsertRemovedActivities(ops) {
|
|
16186
|
-
for (const op of ops)
|
|
16187
|
-
if (op.kind === "remove") this._activities.set(op.activityId, op.before);
|
|
16188
|
-
}
|
|
16189
|
-
_reAddRemovedLinks(ops) {
|
|
16190
|
-
for (const op of ops)
|
|
16191
|
-
if (op.kind === "link-remove") this._attachLink(op.before);
|
|
16192
|
-
}
|
|
16193
|
-
_restoreLinkFields(ops) {
|
|
16194
|
-
for (const op of ops)
|
|
16195
|
-
if (op.kind === "link-field" && this._links.has(op.linkId))
|
|
16196
|
-
this._links.set(op.linkId, op.before);
|
|
16197
|
-
}
|
|
16198
|
-
_restoreActivityFields(before) {
|
|
16199
|
-
for (const [id, snapshot] of before) {
|
|
16200
|
-
const live = this._activities.get(id);
|
|
16201
|
-
if (live) this._restoreScalarFields(live, snapshot);
|
|
16202
|
-
}
|
|
16203
|
-
}
|
|
16204
|
-
_restoreScalarFields(live, before) {
|
|
16205
|
-
for (const key of Object.keys(live)) {
|
|
16206
|
-
if (!Object.hasOwn(before, key)) Reflect.deleteProperty(live, key);
|
|
16207
|
-
}
|
|
16208
|
-
for (const key of Object.keys(before)) {
|
|
16209
|
-
Reflect.set(live, key, Reflect.get(before, key));
|
|
16210
|
-
}
|
|
16211
|
-
}
|
|
16212
|
-
_attachLink(link) {
|
|
16213
|
-
this._links.set(String(link.id), { ...link });
|
|
16214
|
-
this._indexLink(link);
|
|
16215
|
-
}
|
|
16216
|
-
_detachLink(linkId) {
|
|
16217
|
-
const link = this.getLink(linkId);
|
|
16218
|
-
if (!link) return;
|
|
16219
|
-
this._links.delete(String(linkId));
|
|
16220
|
-
this._deindexLink(link);
|
|
16221
|
-
}
|
|
16222
|
-
};
|
|
16223
|
-
var EMPTY_LINK_IDS = [];
|
|
16224
|
-
function isMutableLinkField(field) {
|
|
16225
|
-
return field === LINK_PROPERTY.LAG || field === LINK_PROPERTY.TYPE;
|
|
16226
|
-
}
|
|
16227
|
-
function fieldAffectsVisualOrder(field) {
|
|
16228
|
-
return field === ACTIVITY_PROPERTY.PARENT || field === ACTIVITY_PROPERTY.CORRELATIVE_ID;
|
|
16229
|
-
}
|
|
16230
|
-
function detachLinkRef(refs, linkId) {
|
|
16231
|
-
return refs.filter((ref) => String(ref) !== String(linkId));
|
|
16232
|
-
}
|
|
16233
|
-
function pushLinkRef(map, key, linkId) {
|
|
16234
|
-
const refs = map.get(key);
|
|
16235
|
-
if (refs) refs.push(linkId);
|
|
16236
|
-
else map.set(key, [linkId]);
|
|
16237
|
-
}
|
|
16238
|
-
function buildFlags(snapshot) {
|
|
16239
|
-
const rawFlags = snapshot.runtimeFlags ?? {};
|
|
16240
|
-
return {
|
|
16241
|
-
isPasting: Boolean(rawFlags.isPasting),
|
|
16242
|
-
isBulkOperation: Boolean(rawFlags.isBulkOperation),
|
|
16243
|
-
dragWithMultiple: Boolean(rawFlags.dragWithMultiple),
|
|
16244
|
-
draggingSingleMilestone: Boolean(rawFlags.draggingSingleMilestone),
|
|
16245
|
-
creatingActivity: false,
|
|
16246
|
-
avoidAutoScheduleBeforeDrag: false,
|
|
16247
|
-
maxPerformance: Boolean(rawFlags.maxPerformance),
|
|
16248
|
-
allCheckedTaskIds: []
|
|
16249
|
-
};
|
|
16250
|
-
}
|
|
16251
|
-
|
|
16252
|
-
// src/init/read-api.ts
|
|
16253
|
-
function readActivity(state, id) {
|
|
16254
|
-
return state.getActivity(id);
|
|
16255
|
-
}
|
|
16256
|
-
function readAllActivities(state) {
|
|
16257
|
-
return state.getAllActivities();
|
|
16258
|
-
}
|
|
16259
|
-
function readAllIds(state) {
|
|
16260
|
-
return state.getAllIds().map(String);
|
|
16261
|
-
}
|
|
16262
|
-
function forEachActivityId(state, visit) {
|
|
16263
|
-
state.forEachActivity((_activity, id) => visit(id));
|
|
16264
|
-
}
|
|
16265
|
-
function readChildren(state, parentId) {
|
|
16266
|
-
const childIds = parentId === ROOT_PARENT_ID ? readChildrenIds(state, ROOT_PARENT_ID) : state.getChildren(parentId);
|
|
16267
|
-
const out = [];
|
|
16268
|
-
for (const id of childIds) {
|
|
16269
|
-
const snap = state.getActivity(id);
|
|
16270
|
-
if (snap) out.push(snap);
|
|
16271
|
-
}
|
|
16272
|
-
out.sort((a, b) => (a.correlativeId ?? 0) - (b.correlativeId ?? 0));
|
|
16273
|
-
return out;
|
|
16274
|
-
}
|
|
16275
|
-
function readChildrenIds(state, parentId) {
|
|
16276
|
-
const key = parentId;
|
|
16277
|
-
if (key === ROOT_PARENT_ID) {
|
|
16278
|
-
const roots = [];
|
|
16279
|
-
state.forEachActivity((activity, id) => {
|
|
16280
|
-
if (isRootParent(activity.parentId)) roots.push(id);
|
|
16281
|
-
});
|
|
16282
|
-
return roots;
|
|
16283
|
-
}
|
|
16284
|
-
return [...state.getChildren(key)].map(String);
|
|
16285
|
-
}
|
|
16286
|
-
function readSelectedActivityIds(state) {
|
|
16287
|
-
return state.checkedIds().map(String);
|
|
16288
|
-
}
|
|
16289
|
-
function readHasChild(state, parentId) {
|
|
16290
|
-
return state.getChildren(parentId).length > 0;
|
|
16291
|
-
}
|
|
16292
|
-
function readLink(state, id) {
|
|
16293
|
-
const l = state.getLink(id);
|
|
16294
|
-
return l ? snapshotToLink(l) : null;
|
|
16295
|
-
}
|
|
16296
|
-
function readAllLinks(state) {
|
|
16297
|
-
return state.getAllLinks().map((l) => snapshotToLink(l));
|
|
16298
|
-
}
|
|
16299
|
-
|
|
16300
|
-
// src/propagations/downward/recompute-ponderator-for-parent.ts
|
|
16301
|
-
function recomputePonderatorsForParent(parentId, criterion, adapter) {
|
|
16302
|
-
if (!parentId || parentId === "0") return;
|
|
16303
|
-
const childIds = adapter.getChildren(parentId);
|
|
16304
|
-
if (childIds.length === 0) return;
|
|
16305
|
-
const pesoById = /* @__PURE__ */ new Map();
|
|
16306
|
-
let denominator = 0;
|
|
16307
|
-
for (const childId of childIds) {
|
|
16308
|
-
const peso = criterionValue(String(childId), criterion, adapter);
|
|
16309
|
-
pesoById.set(String(childId), peso);
|
|
16310
|
-
denominator += peso;
|
|
16311
|
-
}
|
|
16312
|
-
const relationValue = denominator ? 100 / denominator : 0;
|
|
16313
|
-
for (const childId of childIds) {
|
|
16314
|
-
const child = adapter.getActivity(childId);
|
|
16315
|
-
if (!child) continue;
|
|
16316
|
-
const points = child.baselinePoints;
|
|
16317
|
-
const active = getActiveBaseline(child);
|
|
16318
|
-
if (active) {
|
|
16319
|
-
const peso = pesoById.get(String(childId)) ?? 0;
|
|
16320
|
-
adapter.setActivityField(
|
|
16321
|
-
childId,
|
|
16322
|
-
COLUMN.PONDERATOR,
|
|
16323
|
-
relationValue * peso
|
|
16324
|
-
);
|
|
16325
|
-
} else if (!Array.isArray(points) || points.length === 0) {
|
|
16326
|
-
adapter.setActivityField(childId, COLUMN.PONDERATOR, 0);
|
|
16327
|
-
}
|
|
16328
|
-
}
|
|
16329
|
-
}
|
|
16330
|
-
function criterionValue(childId, criterion, adapter) {
|
|
16331
|
-
const child = adapter.getActivity(childId);
|
|
16332
|
-
if (!child) return 0;
|
|
16333
|
-
const active = getActiveBaseline(child);
|
|
16334
|
-
if (!active) return 0;
|
|
16335
|
-
if (criterion === "COST") return toNumber(active.cost);
|
|
16336
|
-
if (criterion === "HH") return toNumber(active.workHours);
|
|
16337
|
-
const type = child.type;
|
|
16338
|
-
if (type === "project")
|
|
16339
|
-
return sumRecursiveBaselineDurationDays(childId, adapter);
|
|
16340
|
-
if (type === "milestone") return 0;
|
|
16341
|
-
return toNumber(active.durationDays);
|
|
16342
|
-
}
|
|
16343
|
-
function sumRecursiveBaselineDurationDays(activityId, adapter) {
|
|
16344
|
-
let sum = 0;
|
|
16345
|
-
for (const childId of adapter.getChildren(activityId)) {
|
|
16346
|
-
const child = adapter.getActivity(childId);
|
|
16347
|
-
if (!child) continue;
|
|
16348
|
-
const active = getActiveBaseline(child);
|
|
16349
|
-
if (!active) continue;
|
|
16350
|
-
const type = child.type;
|
|
16351
|
-
if (type === "project") {
|
|
16352
|
-
sum += sumRecursiveBaselineDurationDays(String(childId), adapter);
|
|
16353
|
-
} else if (type !== "milestone") {
|
|
16354
|
-
sum += toNumber(active.durationDays);
|
|
16355
|
-
}
|
|
16356
|
-
}
|
|
16357
|
-
return sum;
|
|
16358
|
-
}
|
|
16359
|
-
function toNumber(v) {
|
|
16360
|
-
const n = typeof v === "string" ? parseFloat(v) : v;
|
|
16361
|
-
return typeof n === "number" && Number.isFinite(n) ? n : 0;
|
|
16362
|
-
}
|
|
16363
|
-
|
|
16364
|
-
// src/propagations/downward/recompute-all-ponderators.ts
|
|
16365
|
-
function recomputeAllPonderators(criterion, adapter) {
|
|
16366
|
-
adapter.forEachActivity((_a, id) => {
|
|
16367
|
-
adapter.setActivityField(id, COLUMN.PONDERATOR, 0);
|
|
16368
|
-
});
|
|
16369
|
-
adapter.forEachActivity((_a, id) => {
|
|
16370
|
-
if (adapter.getChildren(id).length > 0) {
|
|
16371
|
-
recomputePonderatorsForParent(String(id), criterion, adapter);
|
|
16547
|
+
this._lastStartDate = this._lastStartDateBefore;
|
|
16372
16548
|
}
|
|
16373
|
-
|
|
16374
|
-
|
|
16375
|
-
|
|
16376
|
-
// src/propagations/upward/progress-rollup.ts
|
|
16377
|
-
function recomputeAllProgressRollup(adapter) {
|
|
16378
|
-
for (const parentId of parentsDeepestFirst(adapter)) {
|
|
16379
|
-
rollupParent(parentId, adapter);
|
|
16549
|
+
this._cache.ids = null;
|
|
16550
|
+
this._cache.visualOrderIds = null;
|
|
16551
|
+
this._hierarchy.markDirty();
|
|
16380
16552
|
}
|
|
16381
|
-
|
|
16382
|
-
|
|
16383
|
-
|
|
16384
|
-
|
|
16385
|
-
|
|
16386
|
-
});
|
|
16387
|
-
const depthById = /* @__PURE__ */ new Map();
|
|
16388
|
-
for (const id of parents) depthById.set(id, depthOf2(id, adapter));
|
|
16389
|
-
return [...parents].sort(
|
|
16390
|
-
(a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
|
|
16391
|
-
);
|
|
16392
|
-
}
|
|
16393
|
-
function depthOf2(id, adapter) {
|
|
16394
|
-
let depth = 0;
|
|
16395
|
-
let current = id;
|
|
16396
|
-
while (current && current !== "0") {
|
|
16397
|
-
if (!adapter.getActivity(current)) break;
|
|
16398
|
-
depth += 1;
|
|
16399
|
-
current = adapter.getParentId(current);
|
|
16553
|
+
_restoreCorrelatives(correlativeBefore) {
|
|
16554
|
+
for (const [id, before] of correlativeBefore) {
|
|
16555
|
+
const live = this._activities.get(id);
|
|
16556
|
+
if (live) live.correlativeId = before;
|
|
16557
|
+
}
|
|
16400
16558
|
}
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16404
|
-
const childIds = adapter.getChildren(parentId);
|
|
16405
|
-
if (childIds.length === 0) return;
|
|
16406
|
-
const children = [];
|
|
16407
|
-
for (const childId of childIds) {
|
|
16408
|
-
const child = adapter.getActivity(childId);
|
|
16409
|
-
if (!child) continue;
|
|
16410
|
-
children.push({
|
|
16411
|
-
progress: Number(child.progress ?? 0),
|
|
16412
|
-
ponderator: Number(child.ponderator ?? 0)
|
|
16413
|
-
});
|
|
16559
|
+
_undoLinkAdds(ops) {
|
|
16560
|
+
for (const op of ops)
|
|
16561
|
+
if (op.kind === "link-add") this._detachLink(op.linkId);
|
|
16414
16562
|
}
|
|
16415
|
-
|
|
16416
|
-
|
|
16417
|
-
|
|
16418
|
-
parentId,
|
|
16419
|
-
COLUMN.PROGRESS,
|
|
16420
|
-
roundProgressPerLevel(rollup)
|
|
16421
|
-
);
|
|
16563
|
+
_undoInserts(ops) {
|
|
16564
|
+
for (const op of ops)
|
|
16565
|
+
if (op.kind === "insert") this._activities.delete(op.activityId);
|
|
16422
16566
|
}
|
|
16423
|
-
|
|
16424
|
-
|
|
16425
|
-
|
|
16426
|
-
function parseBaselineDate(value) {
|
|
16427
|
-
return typeof value === "string" && value.length > 0 ? parseBackendDate(value) : value instanceof Date ? value : null;
|
|
16428
|
-
}
|
|
16429
|
-
function parseFiniteNonNegative(value) {
|
|
16430
|
-
const numeric = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : Number.NaN;
|
|
16431
|
-
if (!Number.isFinite(numeric) || numeric < 0) return null;
|
|
16432
|
-
return numeric;
|
|
16433
|
-
}
|
|
16434
|
-
function normalizeBaselinePoint(point, reporter) {
|
|
16435
|
-
const durationDays = parseFiniteNonNegative(point.duration);
|
|
16436
|
-
const cost = parseFiniteNonNegative(point.cost);
|
|
16437
|
-
const workHours = parseFiniteNonNegative(point.hh_work);
|
|
16438
|
-
if (durationDays === null || cost === null || workHours === null) {
|
|
16439
|
-
reporter.warn(
|
|
16440
|
-
`[baseline] dropping point with non-finite/negative magnitude \u2014 duration=${JSON.stringify(point.duration)}, cost=${JSON.stringify(point.cost)}, hh_work=${JSON.stringify(point.hh_work)}`
|
|
16441
|
-
);
|
|
16442
|
-
return null;
|
|
16567
|
+
_reInsertRemovedActivities(ops) {
|
|
16568
|
+
for (const op of ops)
|
|
16569
|
+
if (op.kind === "remove") this._activities.set(op.activityId, op.before);
|
|
16443
16570
|
}
|
|
16444
|
-
|
|
16445
|
-
|
|
16446
|
-
|
|
16447
|
-
durationDays,
|
|
16448
|
-
cost,
|
|
16449
|
-
workHours,
|
|
16450
|
-
versionId: typeof point.sectorbaselineversionId === "number" ? point.sectorbaselineversionId : null,
|
|
16451
|
-
isActiveVersion: Boolean(point.sectorbaselineversion?.active),
|
|
16452
|
-
baseCalendarId: point.baseCalendarId != null ? String(point.baseCalendarId) : null,
|
|
16453
|
-
hoursPerDay: typeof point.hoursPerDay === "number" ? point.hoursPerDay : null,
|
|
16454
|
-
hoursPerWeek: typeof point.hoursPerWeek === "number" ? point.hoursPerWeek : null
|
|
16455
|
-
};
|
|
16456
|
-
}
|
|
16457
|
-
|
|
16458
|
-
// src/baselines/apply-baseline-points.ts
|
|
16459
|
-
function applyBaselinePoints(adapter, points, reporter) {
|
|
16460
|
-
const idByProplanner = /* @__PURE__ */ new Map();
|
|
16461
|
-
adapter.forEachActivity((a, id) => {
|
|
16462
|
-
const pid = a.proplannerId;
|
|
16463
|
-
if (typeof pid === "number") idByProplanner.set(pid, id);
|
|
16464
|
-
});
|
|
16465
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
16466
|
-
for (const p of points) {
|
|
16467
|
-
const activityId = p.activityId;
|
|
16468
|
-
if (typeof activityId !== "number") continue;
|
|
16469
|
-
const coreId = idByProplanner.get(activityId);
|
|
16470
|
-
if (coreId === void 0) continue;
|
|
16471
|
-
const arr = grouped.get(coreId);
|
|
16472
|
-
if (arr) arr.push(p);
|
|
16473
|
-
else grouped.set(coreId, [p]);
|
|
16571
|
+
_reAddRemovedLinks(ops) {
|
|
16572
|
+
for (const op of ops)
|
|
16573
|
+
if (op.kind === "link-remove") this._attachLink(op.before);
|
|
16474
16574
|
}
|
|
16475
|
-
|
|
16476
|
-
|
|
16477
|
-
|
|
16478
|
-
|
|
16479
|
-
"baselinePoints",
|
|
16480
|
-
group.map((point) => normalizeBaselinePoint(point, reporter)).filter((point) => point !== null)
|
|
16481
|
-
);
|
|
16482
|
-
changed.push(coreId);
|
|
16575
|
+
_restoreLinkFields(ops) {
|
|
16576
|
+
for (const op of ops)
|
|
16577
|
+
if (op.kind === "link-field" && this._links.has(op.linkId))
|
|
16578
|
+
this._links.set(op.linkId, op.before);
|
|
16483
16579
|
}
|
|
16484
|
-
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
adapter.setActivityField(id, "baselinePoints", []);
|
|
16489
|
-
changed.push(id);
|
|
16580
|
+
_restoreActivityFields(before) {
|
|
16581
|
+
for (const [id, snapshot] of before) {
|
|
16582
|
+
const live = this._activities.get(id);
|
|
16583
|
+
if (live) this._restoreScalarFields(live, snapshot);
|
|
16490
16584
|
}
|
|
16491
|
-
}
|
|
16492
|
-
|
|
16585
|
+
}
|
|
16586
|
+
_restoreScalarFields(live, before) {
|
|
16587
|
+
for (const key of Object.keys(live)) {
|
|
16588
|
+
if (!Object.hasOwn(before, key)) Reflect.deleteProperty(live, key);
|
|
16589
|
+
}
|
|
16590
|
+
for (const key of Object.keys(before)) {
|
|
16591
|
+
Reflect.set(live, key, Reflect.get(before, key));
|
|
16592
|
+
}
|
|
16593
|
+
}
|
|
16594
|
+
_attachLink(link) {
|
|
16595
|
+
this._links.set(String(link.id), { ...link });
|
|
16596
|
+
this._indexLink(link);
|
|
16597
|
+
}
|
|
16598
|
+
_detachLink(linkId) {
|
|
16599
|
+
const link = this.getLink(linkId);
|
|
16600
|
+
if (!link) return;
|
|
16601
|
+
this._links.delete(String(linkId));
|
|
16602
|
+
this._deindexLink(link);
|
|
16603
|
+
}
|
|
16604
|
+
};
|
|
16605
|
+
var EMPTY_LINK_IDS = [];
|
|
16606
|
+
function isMutableLinkField(field) {
|
|
16607
|
+
return field === LINK_PROPERTY.LAG || field === LINK_PROPERTY.TYPE;
|
|
16493
16608
|
}
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16609
|
+
function fieldAffectsVisualOrder(field) {
|
|
16610
|
+
return field === ACTIVITY_PROPERTY.PARENT || field === ACTIVITY_PROPERTY.CORRELATIVE_ID;
|
|
16611
|
+
}
|
|
16612
|
+
function detachLinkRef(refs, linkId) {
|
|
16613
|
+
return refs.filter((ref) => String(ref) !== String(linkId));
|
|
16614
|
+
}
|
|
16615
|
+
function pushLinkRef(map, key, linkId) {
|
|
16616
|
+
const refs = map.get(key);
|
|
16617
|
+
if (refs) refs.push(linkId);
|
|
16618
|
+
else map.set(key, [linkId]);
|
|
16619
|
+
}
|
|
16620
|
+
function buildFlags(snapshot) {
|
|
16621
|
+
const rawFlags = snapshot.runtimeFlags ?? {};
|
|
16499
16622
|
return {
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
|
|
16504
|
-
|
|
16623
|
+
isPasting: Boolean(rawFlags.isPasting),
|
|
16624
|
+
isBulkOperation: Boolean(rawFlags.isBulkOperation),
|
|
16625
|
+
dragWithMultiple: Boolean(rawFlags.dragWithMultiple),
|
|
16626
|
+
draggingSingleMilestone: Boolean(rawFlags.draggingSingleMilestone),
|
|
16627
|
+
creatingActivity: false,
|
|
16628
|
+
avoidAutoScheduleBeforeDrag: false,
|
|
16629
|
+
maxPerformance: Boolean(rawFlags.maxPerformance),
|
|
16630
|
+
allCheckedTaskIds: []
|
|
16505
16631
|
};
|
|
16506
16632
|
}
|
|
16507
|
-
function emitBaselineSnapshotColumns(state) {
|
|
16508
|
-
const changed = [];
|
|
16509
|
-
state.forEachActivity((activity, id) => {
|
|
16510
|
-
const snapshot = buildBaselineSnapshot(activity);
|
|
16511
|
-
if (!snapshot) return;
|
|
16512
|
-
state.setActivityField(id, "baselineSnapshot", snapshot);
|
|
16513
|
-
changed.push(id);
|
|
16514
|
-
});
|
|
16515
|
-
return changed;
|
|
16516
|
-
}
|
|
16517
16633
|
|
|
16518
|
-
// src/
|
|
16519
|
-
function
|
|
16520
|
-
|
|
16521
|
-
const changed = /* @__PURE__ */ new Set();
|
|
16522
|
-
for (const id of applyBaselinePoints(
|
|
16523
|
-
state,
|
|
16524
|
-
points,
|
|
16525
|
-
reporter
|
|
16526
|
-
)) {
|
|
16527
|
-
changed.add(id);
|
|
16528
|
-
}
|
|
16529
|
-
if (now) {
|
|
16530
|
-
for (const id of runExpectedProgressBase(state, now, defaultBaseCalendarId))
|
|
16531
|
-
changed.add(id);
|
|
16532
|
-
}
|
|
16533
|
-
for (const id of emitBaselineSnapshotColumns(state)) changed.add(id);
|
|
16534
|
-
for (const id of emitRealCost(state)) changed.add(id);
|
|
16535
|
-
return [...changed];
|
|
16634
|
+
// src/shared/clone-domain-value.ts
|
|
16635
|
+
function cloneDomainValue(value) {
|
|
16636
|
+
return structuredClone(value);
|
|
16536
16637
|
}
|
|
16537
16638
|
|
|
16538
|
-
// src/init/
|
|
16539
|
-
function
|
|
16540
|
-
const
|
|
16541
|
-
return
|
|
16639
|
+
// src/init/read-api.ts
|
|
16640
|
+
function readActivity(state, id) {
|
|
16641
|
+
const activity = state.getActivity(id);
|
|
16642
|
+
return activity ? cloneDomainValue(activity) : null;
|
|
16542
16643
|
}
|
|
16543
|
-
function
|
|
16544
|
-
|
|
16545
|
-
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
16644
|
+
function readAllActivities(state) {
|
|
16645
|
+
return state.getAllActivities().map(cloneDomainValue);
|
|
16546
16646
|
}
|
|
16547
|
-
function
|
|
16548
|
-
|
|
16549
|
-
state.forEachActivity((a, id) => {
|
|
16550
|
-
before.set(id, readPonderator(a));
|
|
16551
|
-
});
|
|
16552
|
-
recomputeAllPonderators(criterion, state);
|
|
16553
|
-
const changed = [];
|
|
16554
|
-
state.forEachActivity((a, id) => {
|
|
16555
|
-
if (readPonderator(a) !== (before.get(id) ?? 0)) {
|
|
16556
|
-
changed.push(structuredCloneActivity(a));
|
|
16557
|
-
}
|
|
16558
|
-
});
|
|
16559
|
-
return changed;
|
|
16647
|
+
function readAllIds(state) {
|
|
16648
|
+
return state.getAllIds().map(String);
|
|
16560
16649
|
}
|
|
16561
|
-
function
|
|
16562
|
-
|
|
16563
|
-
state.forEachActivity((a, id) => {
|
|
16564
|
-
before.set(id, readProgress(a));
|
|
16565
|
-
});
|
|
16566
|
-
recomputeAllProgressRollup(state);
|
|
16567
|
-
const changed = [];
|
|
16568
|
-
state.forEachActivity((a, id) => {
|
|
16569
|
-
if (readProgress(a) !== (before.get(id) ?? 0)) {
|
|
16570
|
-
changed.push(structuredCloneActivity(a));
|
|
16571
|
-
}
|
|
16572
|
-
});
|
|
16573
|
-
return changed;
|
|
16650
|
+
function forEachActivityId(state, visit) {
|
|
16651
|
+
state.forEachActivity((_activity, id) => visit(id));
|
|
16574
16652
|
}
|
|
16575
|
-
function
|
|
16576
|
-
const
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
now,
|
|
16580
|
-
reporter,
|
|
16581
|
-
defaultBaseCalendarId
|
|
16582
|
-
);
|
|
16583
|
-
const changed = [];
|
|
16584
|
-
for (const id of changedIds) {
|
|
16653
|
+
function readChildren(state, parentId) {
|
|
16654
|
+
const childIds = parentId === ROOT_PARENT_ID ? readChildrenIds(state, ROOT_PARENT_ID) : state.getChildren(parentId);
|
|
16655
|
+
const out = [];
|
|
16656
|
+
for (const id of childIds) {
|
|
16585
16657
|
const snap = state.getActivity(id);
|
|
16586
|
-
if (snap)
|
|
16658
|
+
if (snap) out.push(cloneDomainValue(snap));
|
|
16659
|
+
}
|
|
16660
|
+
out.sort((a, b) => (a.correlativeId ?? 0) - (b.correlativeId ?? 0));
|
|
16661
|
+
return out;
|
|
16662
|
+
}
|
|
16663
|
+
function readChildrenIds(state, parentId) {
|
|
16664
|
+
const key = parentId;
|
|
16665
|
+
if (key === ROOT_PARENT_ID) {
|
|
16666
|
+
const roots = [];
|
|
16667
|
+
state.forEachActivity((activity, id) => {
|
|
16668
|
+
if (isRootParent(activity.parentId)) roots.push(id);
|
|
16669
|
+
});
|
|
16670
|
+
return roots;
|
|
16587
16671
|
}
|
|
16588
|
-
return
|
|
16672
|
+
return [...state.getChildren(key)].map(String);
|
|
16589
16673
|
}
|
|
16590
|
-
function
|
|
16591
|
-
|
|
16592
|
-
|
|
16593
|
-
|
|
16594
|
-
|
|
16595
|
-
|
|
16596
|
-
|
|
16674
|
+
function readSelectedActivityIds(state) {
|
|
16675
|
+
return state.checkedIds().map(String);
|
|
16676
|
+
}
|
|
16677
|
+
function readHasChild(state, parentId) {
|
|
16678
|
+
return state.getChildren(parentId).length > 0;
|
|
16679
|
+
}
|
|
16680
|
+
function readLink(state, id) {
|
|
16681
|
+
const l = state.getLink(id);
|
|
16682
|
+
return l ? snapshotToLink(l) : null;
|
|
16683
|
+
}
|
|
16684
|
+
function readAllLinks(state) {
|
|
16685
|
+
return state.getAllLinks().map((l) => snapshotToLink(l));
|
|
16597
16686
|
}
|
|
16598
16687
|
|
|
16599
16688
|
// src/internal/state/project-work-hours.ts
|
|
@@ -16703,8 +16792,12 @@ function mergeCoalesced(top, next) {
|
|
|
16703
16792
|
};
|
|
16704
16793
|
return buildUndoEntry(changeSet);
|
|
16705
16794
|
}
|
|
16706
|
-
function
|
|
16707
|
-
|
|
16795
|
+
function getDispatchHistoryPolicy(action) {
|
|
16796
|
+
if (action.kind === "persistence-acknowledge") return "clear-on-success";
|
|
16797
|
+
if (action.kind === "sir-sync" || action.kind === "activity-lookahead-sync" || action.kind === "baseline-apply" || action.kind === "ponderator-criterion-set" || action.kind === "status-criteria-set") {
|
|
16798
|
+
return "skip";
|
|
16799
|
+
}
|
|
16800
|
+
return "record";
|
|
16708
16801
|
}
|
|
16709
16802
|
function needsResync(entry) {
|
|
16710
16803
|
for (const change of entry.changeSet.activities) {
|
|
@@ -16971,6 +17064,7 @@ var UndoRecorder = class {
|
|
|
16971
17064
|
clear() {
|
|
16972
17065
|
this.undoStack.length = 0;
|
|
16973
17066
|
this.redoStack.length = 0;
|
|
17067
|
+
this.resetCoalesce();
|
|
16974
17068
|
}
|
|
16975
17069
|
};
|
|
16976
17070
|
|
|
@@ -18339,6 +18433,117 @@ function snapDemotedLeafTiming(state, activityId) {
|
|
|
18339
18433
|
state.setActivityField(activityId, ACTIVITY_PROPERTY.END_DATE, end);
|
|
18340
18434
|
}
|
|
18341
18435
|
|
|
18436
|
+
// src/propagations/upward/recompute-real-work.ts
|
|
18437
|
+
function recomputeCanonicalRealWork(state) {
|
|
18438
|
+
const rootIds = [];
|
|
18439
|
+
const changedIds = [];
|
|
18440
|
+
state.forEachActivity((activity, activityId) => {
|
|
18441
|
+
if (activity.parentId === null) rootIds.push(String(activityId));
|
|
18442
|
+
});
|
|
18443
|
+
const visit = (activityId) => {
|
|
18444
|
+
const activity = state.getActivity(activityId);
|
|
18445
|
+
if (!activity) return 0;
|
|
18446
|
+
const childIds = [...state.getChildren(activityId)];
|
|
18447
|
+
const realWork = childIds.length === 0 ? computeLeafRealWork(activity.workHours, activity.progress) : childIds.reduce(
|
|
18448
|
+
(total, childId) => total + visit(String(childId)),
|
|
18449
|
+
0
|
|
18450
|
+
);
|
|
18451
|
+
state.setActivityField(
|
|
18452
|
+
activityId,
|
|
18453
|
+
ACTIVITY_PROPERTY.REAL_WORK_HOURS,
|
|
18454
|
+
realWork
|
|
18455
|
+
);
|
|
18456
|
+
changedIds.push(activityId);
|
|
18457
|
+
return realWork;
|
|
18458
|
+
};
|
|
18459
|
+
for (const rootId of rootIds) visit(rootId);
|
|
18460
|
+
return changedIds;
|
|
18461
|
+
}
|
|
18462
|
+
|
|
18463
|
+
// src/init/initial-passes.ts
|
|
18464
|
+
async function runInitialPasses(deps) {
|
|
18465
|
+
const { state, sector, scheduler, skipAutoSchedule, now } = deps;
|
|
18466
|
+
recomputeCorrelativeIds(state);
|
|
18467
|
+
if (sector.updateDurationForPrimaveraEndDate) {
|
|
18468
|
+
recomputeDurationsFromDates(state);
|
|
18469
|
+
}
|
|
18470
|
+
normalizeLoadedConstraintDates(state);
|
|
18471
|
+
recomputeCanonicalRealWork(state);
|
|
18472
|
+
if (skipAutoSchedule) {
|
|
18473
|
+
if (now) {
|
|
18474
|
+
applyExpectedProgressLive(state, now);
|
|
18475
|
+
applyStatusPass(state, sector.statusCriteria);
|
|
18476
|
+
}
|
|
18477
|
+
return;
|
|
18478
|
+
}
|
|
18479
|
+
const result = await scheduler.schedule({});
|
|
18480
|
+
applyResults(state, result);
|
|
18481
|
+
normalizeMilestoneConstraintDatesForDisplay(state);
|
|
18482
|
+
recomputeSkippedLeafEnds(state);
|
|
18483
|
+
await updateParentBoundsFromChildren(state, void 0, false);
|
|
18484
|
+
if (now) {
|
|
18485
|
+
applyExpectedProgressLive(state, now);
|
|
18486
|
+
applyStatusPass(state, sector.statusCriteria);
|
|
18487
|
+
}
|
|
18488
|
+
}
|
|
18489
|
+
function recomputeSkippedLeafEnds(state) {
|
|
18490
|
+
state.forEachActivity((activity) => {
|
|
18491
|
+
if (activity.autoScheduling) return;
|
|
18492
|
+
if (!activity.startDate || activity.durationHours == null) return;
|
|
18493
|
+
if (state.getChildren(activity.id).length > 0) return;
|
|
18494
|
+
activity.endDate = state.calculateEndDate({
|
|
18495
|
+
startDate: activity.startDate,
|
|
18496
|
+
durationHours: activity.durationHours,
|
|
18497
|
+
task: activity
|
|
18498
|
+
});
|
|
18499
|
+
});
|
|
18500
|
+
}
|
|
18501
|
+
function recomputeDurationsFromDates(state) {
|
|
18502
|
+
state.forEachActivity((activity) => {
|
|
18503
|
+
if (!activity.startDate || !activity.endDate) return;
|
|
18504
|
+
activity.durationHours = state.calculateDuration({
|
|
18505
|
+
startDate: activity.startDate,
|
|
18506
|
+
endDate: activity.endDate,
|
|
18507
|
+
task: activity
|
|
18508
|
+
});
|
|
18509
|
+
});
|
|
18510
|
+
}
|
|
18511
|
+
function normalizeLoadedConstraintDates(state) {
|
|
18512
|
+
state.forEachActivity((activity) => {
|
|
18513
|
+
const type = activity.constraintType;
|
|
18514
|
+
if (!type || !activity.constraintDate) return;
|
|
18515
|
+
const constraintDate = activity.constraintDate;
|
|
18516
|
+
if (activity.type === "milestone" && (constraintDate.getUTCHours() !== 0 || constraintDate.getUTCMinutes() !== 0)) {
|
|
18517
|
+
return;
|
|
18518
|
+
}
|
|
18519
|
+
const calendar = state.calendarReader.getCalendar(
|
|
18520
|
+
String(activity.calendarId)
|
|
18521
|
+
);
|
|
18522
|
+
if (!calendar) return;
|
|
18523
|
+
activity.constraintDate = normalizeConstraintDate(
|
|
18524
|
+
activity.constraintDate,
|
|
18525
|
+
calendar,
|
|
18526
|
+
type
|
|
18527
|
+
);
|
|
18528
|
+
});
|
|
18529
|
+
}
|
|
18530
|
+
function normalizeMilestoneConstraintDatesForDisplay(state) {
|
|
18531
|
+
state.forEachActivity((activity) => {
|
|
18532
|
+
if (activity.type !== "milestone") return;
|
|
18533
|
+
const type = activity.constraintType;
|
|
18534
|
+
if (!type || !activity.constraintDate) return;
|
|
18535
|
+
const calendar = state.calendarReader.getCalendar(
|
|
18536
|
+
String(activity.calendarId)
|
|
18537
|
+
);
|
|
18538
|
+
if (!calendar) return;
|
|
18539
|
+
activity.constraintDate = normalizeConstraintDate(
|
|
18540
|
+
activity.constraintDate,
|
|
18541
|
+
calendar,
|
|
18542
|
+
type
|
|
18543
|
+
);
|
|
18544
|
+
});
|
|
18545
|
+
}
|
|
18546
|
+
|
|
18342
18547
|
// src/init/initialize-core.ts
|
|
18343
18548
|
var SCHEDULE_CORE_STATUS = {
|
|
18344
18549
|
READY: "ready",
|
|
@@ -18426,48 +18631,8 @@ function initializeCore(input) {
|
|
|
18426
18631
|
}
|
|
18427
18632
|
|
|
18428
18633
|
// src/init/schedule-core.ts
|
|
18429
|
-
function assertValidPersistenceAssignments(assignments, entityName, readCurrent, ownerByBackendId) {
|
|
18430
|
-
const seenIds = /* @__PURE__ */ new Set();
|
|
18431
|
-
const seenBackendIds = /* @__PURE__ */ new Set();
|
|
18432
|
-
for (const assignment of assignments) {
|
|
18433
|
-
const id = String(assignment.id);
|
|
18434
|
-
if (id.length === 0 || seenIds.has(id)) {
|
|
18435
|
-
throw new Error(
|
|
18436
|
-
`acknowledgePersistence: duplicate or empty ${entityName} id "${id}"`
|
|
18437
|
-
);
|
|
18438
|
-
}
|
|
18439
|
-
if (!Number.isSafeInteger(assignment.proplannerId) || assignment.proplannerId <= 0 || seenBackendIds.has(assignment.proplannerId)) {
|
|
18440
|
-
throw new Error(
|
|
18441
|
-
`acknowledgePersistence: invalid or duplicate ${entityName} proplannerId ${String(assignment.proplannerId)}`
|
|
18442
|
-
);
|
|
18443
|
-
}
|
|
18444
|
-
const state = readCurrent(id);
|
|
18445
|
-
if (!state.exists) {
|
|
18446
|
-
throw new Error(
|
|
18447
|
-
`acknowledgePersistence: unknown ${entityName} id "${id}"`
|
|
18448
|
-
);
|
|
18449
|
-
}
|
|
18450
|
-
if (state.current !== null && state.current !== assignment.proplannerId) {
|
|
18451
|
-
throw new Error(
|
|
18452
|
-
`acknowledgePersistence: ${entityName} "${id}" already has proplannerId ${String(state.current)}`
|
|
18453
|
-
);
|
|
18454
|
-
}
|
|
18455
|
-
const existingOwner = ownerByBackendId.get(assignment.proplannerId);
|
|
18456
|
-
if (existingOwner !== void 0 && existingOwner !== id) {
|
|
18457
|
-
throw new Error(
|
|
18458
|
-
`acknowledgePersistence: ${entityName} proplannerId ${String(assignment.proplannerId)} already belongs to "${existingOwner}"`
|
|
18459
|
-
);
|
|
18460
|
-
}
|
|
18461
|
-
seenIds.add(id);
|
|
18462
|
-
seenBackendIds.add(assignment.proplannerId);
|
|
18463
|
-
}
|
|
18464
|
-
}
|
|
18465
18634
|
var ScheduleCore = class {
|
|
18466
18635
|
_status = SCHEDULE_CORE_STATUS.READY;
|
|
18467
|
-
/** True while an async dispatch is suspended inside the write-capture window.
|
|
18468
|
-
* A sync facade mutation running in that gap would corrupt the in-flight
|
|
18469
|
-
* journal, so sync mutators refuse to run while it is set. */
|
|
18470
|
-
_dispatchInFlight = false;
|
|
18471
18636
|
coreRuntime;
|
|
18472
18637
|
_undo = new UndoRecorder();
|
|
18473
18638
|
_opQueue = Promise.resolve();
|
|
@@ -18518,7 +18683,7 @@ var ScheduleCore = class {
|
|
|
18518
18683
|
return this._status;
|
|
18519
18684
|
}
|
|
18520
18685
|
getSector() {
|
|
18521
|
-
return this.coreRuntime.sector;
|
|
18686
|
+
return cloneDomainValue(this.coreRuntime.sector);
|
|
18522
18687
|
}
|
|
18523
18688
|
getActivityView(id) {
|
|
18524
18689
|
this.assertReady();
|
|
@@ -18544,7 +18709,7 @@ var ScheduleCore = class {
|
|
|
18544
18709
|
this.assertReady();
|
|
18545
18710
|
const snapshot = this.coreRuntime.state.getActivity(activityId);
|
|
18546
18711
|
if (!snapshot) return null;
|
|
18547
|
-
return snapshot[property];
|
|
18712
|
+
return cloneDomainValue(snapshot[property]);
|
|
18548
18713
|
}
|
|
18549
18714
|
getAllIds() {
|
|
18550
18715
|
this.assertReady();
|
|
@@ -18571,7 +18736,7 @@ var ScheduleCore = class {
|
|
|
18571
18736
|
*/
|
|
18572
18737
|
getVisualOrderIds() {
|
|
18573
18738
|
this.assertReady();
|
|
18574
|
-
return this.coreRuntime.state.getVisualOrderIds();
|
|
18739
|
+
return [...this.coreRuntime.state.getVisualOrderIds()];
|
|
18575
18740
|
}
|
|
18576
18741
|
hasChild(parentId) {
|
|
18577
18742
|
this.assertReady();
|
|
@@ -18579,15 +18744,21 @@ var ScheduleCore = class {
|
|
|
18579
18744
|
}
|
|
18580
18745
|
getCalendar(id) {
|
|
18581
18746
|
this.assertReady();
|
|
18582
|
-
|
|
18747
|
+
const calendar = this.coreRuntime.calendars.get(id);
|
|
18748
|
+
return calendar ? cloneDomainValue(calendar) : null;
|
|
18583
18749
|
}
|
|
18584
18750
|
getAllCalendars() {
|
|
18585
18751
|
this.assertReady();
|
|
18586
|
-
return Array.from(
|
|
18752
|
+
return Array.from(
|
|
18753
|
+
this.coreRuntime.calendars.values(),
|
|
18754
|
+
(calendar) => cloneDomainValue(calendar)
|
|
18755
|
+
);
|
|
18587
18756
|
}
|
|
18588
18757
|
getBaseCalendars() {
|
|
18589
18758
|
this.assertReady();
|
|
18590
|
-
return this.coreRuntime.baseCalendars
|
|
18759
|
+
return this.coreRuntime.baseCalendars.map(
|
|
18760
|
+
(calendar) => cloneDomainValue(calendar)
|
|
18761
|
+
);
|
|
18591
18762
|
}
|
|
18592
18763
|
isCustomIdInUse(customId, currentCustomId = null) {
|
|
18593
18764
|
this.assertReady();
|
|
@@ -18604,184 +18775,9 @@ var ScheduleCore = class {
|
|
|
18604
18775
|
this.assertReady();
|
|
18605
18776
|
return this._saveTracker.modifiedLinks(this.getAllLinksView());
|
|
18606
18777
|
}
|
|
18607
|
-
markLinksPersisted() {
|
|
18608
|
-
this._saveTracker.snapshotLinks(this.getAllLinksView());
|
|
18609
|
-
}
|
|
18610
18778
|
getModifiedActivities() {
|
|
18611
18779
|
this.assertReady();
|
|
18612
|
-
return this._saveTracker.modifiedActivities(
|
|
18613
|
-
this.coreRuntime.state.getAllActivities()
|
|
18614
|
-
);
|
|
18615
|
-
}
|
|
18616
|
-
markActivitiesPersisted() {
|
|
18617
|
-
this._saveTracker.snapshotActivities(
|
|
18618
|
-
this.coreRuntime.state.getAllActivities()
|
|
18619
|
-
);
|
|
18620
|
-
}
|
|
18621
|
-
/**
|
|
18622
|
-
* Reconciles the backend identities returned by a successful schedule save.
|
|
18623
|
-
*
|
|
18624
|
-
* This is an application-boundary acknowledgement, not an editable schedule
|
|
18625
|
-
* gesture: it does not autoschedule, recompute, emit an undo entry, or invent
|
|
18626
|
-
* domain changes. Every assignment is validated before the first mutation so
|
|
18627
|
-
* a malformed/partial response cannot leave the core half-reconciled. Once
|
|
18628
|
-
* applied, the complete live graph becomes the new save-tracker baseline.
|
|
18629
|
-
*/
|
|
18630
|
-
acknowledgePersistence(acknowledgement) {
|
|
18631
|
-
this.assertReady();
|
|
18632
|
-
const activities = acknowledgement.activities ?? [];
|
|
18633
|
-
const links = acknowledgement.links ?? [];
|
|
18634
|
-
const activityOwnerByBackendId = /* @__PURE__ */ new Map();
|
|
18635
|
-
for (const activity of this.coreRuntime.state.getAllActivities()) {
|
|
18636
|
-
if (activity.proplannerId != null) {
|
|
18637
|
-
activityOwnerByBackendId.set(
|
|
18638
|
-
activity.proplannerId,
|
|
18639
|
-
String(activity.id)
|
|
18640
|
-
);
|
|
18641
|
-
}
|
|
18642
|
-
}
|
|
18643
|
-
const linkOwnerByBackendId = /* @__PURE__ */ new Map();
|
|
18644
|
-
for (const link of this.coreRuntime.state.getAllLinks()) {
|
|
18645
|
-
if (link.proplannerId != null) {
|
|
18646
|
-
linkOwnerByBackendId.set(link.proplannerId, String(link.id));
|
|
18647
|
-
}
|
|
18648
|
-
}
|
|
18649
|
-
assertValidPersistenceAssignments(
|
|
18650
|
-
activities,
|
|
18651
|
-
"activity",
|
|
18652
|
-
(id) => {
|
|
18653
|
-
const activity = this.coreRuntime.state.getActivity(id);
|
|
18654
|
-
return {
|
|
18655
|
-
exists: activity !== null,
|
|
18656
|
-
current: activity?.proplannerId ?? null
|
|
18657
|
-
};
|
|
18658
|
-
},
|
|
18659
|
-
activityOwnerByBackendId
|
|
18660
|
-
);
|
|
18661
|
-
assertValidPersistenceAssignments(
|
|
18662
|
-
links,
|
|
18663
|
-
"link",
|
|
18664
|
-
(id) => {
|
|
18665
|
-
const link = this.coreRuntime.state.getLink(id);
|
|
18666
|
-
return {
|
|
18667
|
-
exists: link !== null,
|
|
18668
|
-
current: link?.proplannerId ?? null
|
|
18669
|
-
};
|
|
18670
|
-
},
|
|
18671
|
-
linkOwnerByBackendId
|
|
18672
|
-
);
|
|
18673
|
-
this.coreRuntime.state.batchUpdate(() => {
|
|
18674
|
-
for (const assignment of activities) {
|
|
18675
|
-
this.coreRuntime.state.setActivityField(
|
|
18676
|
-
assignment.id,
|
|
18677
|
-
"proplannerId",
|
|
18678
|
-
assignment.proplannerId
|
|
18679
|
-
);
|
|
18680
|
-
}
|
|
18681
|
-
for (const assignment of links) {
|
|
18682
|
-
this.coreRuntime.state.setLinkProplannerId(
|
|
18683
|
-
assignment.id,
|
|
18684
|
-
assignment.proplannerId
|
|
18685
|
-
);
|
|
18686
|
-
}
|
|
18687
|
-
});
|
|
18688
|
-
this.markActivitiesPersisted();
|
|
18689
|
-
this.markLinksPersisted();
|
|
18690
|
-
}
|
|
18691
|
-
applyBaselines(points) {
|
|
18692
|
-
this.assertReady();
|
|
18693
|
-
const now = this.coreRuntime.clock ? endOfLocalDay(this.coreRuntime.clock()) : null;
|
|
18694
|
-
const defaultBaseCalendarId = this.coreRuntime.baseCalendars.find((calendar) => calendar.baseDefault)?.id ?? null;
|
|
18695
|
-
return applyBaselines(
|
|
18696
|
-
this.coreRuntime.state,
|
|
18697
|
-
this.coreRuntime.sector.hoursPerDay,
|
|
18698
|
-
points,
|
|
18699
|
-
now,
|
|
18700
|
-
this.coreRuntime.reporter,
|
|
18701
|
-
defaultBaseCalendarId
|
|
18702
|
-
);
|
|
18703
|
-
}
|
|
18704
|
-
/**
|
|
18705
|
-
* Whole-tree ponderator recompute (zeroes, then redistributes 100 within
|
|
18706
|
-
* each parent from its children's active baselines, weighted by `criterion`).
|
|
18707
|
-
* Returns the activities whose `ponderator` changed, for a prop-only repaint.
|
|
18708
|
-
* The base rollup (`applyBaselines`) depends on fresh ponderators, so callers
|
|
18709
|
-
* run this before it on a criterion change or baseline save.
|
|
18710
|
-
*/
|
|
18711
|
-
recomputeAllPonderators(criterion) {
|
|
18712
|
-
this.assertReady();
|
|
18713
|
-
return recomputeAllPonderators2(
|
|
18714
|
-
this.coreRuntime.state,
|
|
18715
|
-
this.coreRuntime.sector.hoursPerDay,
|
|
18716
|
-
criterion
|
|
18717
|
-
);
|
|
18718
|
-
}
|
|
18719
|
-
/**
|
|
18720
|
-
* Recompute the weighted-progress rollup of every parent, bottom-up.
|
|
18721
|
-
* Returns the activities whose `progress` changed, for a prop-only repaint.
|
|
18722
|
-
*/
|
|
18723
|
-
recomputeAllProgressRollup() {
|
|
18724
|
-
this.assertReady();
|
|
18725
|
-
return recomputeAllProgressRollup2(
|
|
18726
|
-
this.coreRuntime.state,
|
|
18727
|
-
this.coreRuntime.sector.hoursPerDay
|
|
18728
|
-
);
|
|
18729
|
-
}
|
|
18730
|
-
/**
|
|
18731
|
-
* Set the project's status criterion (the Baseline↔Actual toggle) and
|
|
18732
|
-
* recompute every activity's `status` against it. Stores the criterion so
|
|
18733
|
-
* future dispatches keep deriving status with it. Returns the activities
|
|
18734
|
-
* whose `status` changed, for a prop-only repaint.
|
|
18735
|
-
*/
|
|
18736
|
-
setStatusCriteria(criteria) {
|
|
18737
|
-
this.assertReady();
|
|
18738
|
-
const resolved = resolveStatusCriteria(criteria);
|
|
18739
|
-
this.coreRuntime.sector.statusCriteria = resolved;
|
|
18740
|
-
return recomputeStatus(
|
|
18741
|
-
this.coreRuntime.state,
|
|
18742
|
-
this.coreRuntime.sector.hoursPerDay,
|
|
18743
|
-
resolved
|
|
18744
|
-
);
|
|
18745
|
-
}
|
|
18746
|
-
allocateActivityId() {
|
|
18747
|
-
this.assertReady();
|
|
18748
|
-
return this.coreRuntime.activityIdGenerator.next();
|
|
18749
|
-
}
|
|
18750
|
-
createActivity(input) {
|
|
18751
|
-
this.assertReady();
|
|
18752
|
-
if (this._dispatchInFlight) {
|
|
18753
|
-
throw new Error(
|
|
18754
|
-
"[ScheduleCore] createActivity called during an in-flight dispatch"
|
|
18755
|
-
);
|
|
18756
|
-
}
|
|
18757
|
-
const action = { kind: "activity-create", ...input };
|
|
18758
|
-
this.coreRuntime.state.beginWriteCapture();
|
|
18759
|
-
this.coreRuntime.customIdTracker.beginCustomIdTransaction();
|
|
18760
|
-
let result;
|
|
18761
|
-
try {
|
|
18762
|
-
result = createActivitySync(action, {
|
|
18763
|
-
adapter: this.coreRuntime.state,
|
|
18764
|
-
scheduler: this.coreRuntime.scheduler,
|
|
18765
|
-
sector: this.coreRuntime.sector,
|
|
18766
|
-
calendars: this.coreRuntime.calendars,
|
|
18767
|
-
activityIdGen: this.coreRuntime.activityIdGenerator,
|
|
18768
|
-
uidGen: this.coreRuntime.uniqueCorrelativeIdGenerator,
|
|
18769
|
-
customIdTracker: this.coreRuntime.customIdTracker
|
|
18770
|
-
});
|
|
18771
|
-
if (!result.ok) this._rollback();
|
|
18772
|
-
} catch (error) {
|
|
18773
|
-
this._rollback();
|
|
18774
|
-
throw error;
|
|
18775
|
-
} finally {
|
|
18776
|
-
this.coreRuntime.state.endWriteCapture();
|
|
18777
|
-
this.coreRuntime.customIdTracker.commitCustomIdTransaction();
|
|
18778
|
-
}
|
|
18779
|
-
if (!result.ok) return result;
|
|
18780
|
-
return {
|
|
18781
|
-
ok: true,
|
|
18782
|
-
activity: result.activity,
|
|
18783
|
-
changes: result.changes
|
|
18784
|
-
};
|
|
18780
|
+
return this._saveTracker.modifiedActivities(this.coreRuntime.state.getAllActivities()).map(cloneDomainValue);
|
|
18785
18781
|
}
|
|
18786
18782
|
_enqueue(work) {
|
|
18787
18783
|
const workPromise = this._opQueue.then(work, work);
|
|
@@ -18801,10 +18797,9 @@ var ScheduleCore = class {
|
|
|
18801
18797
|
dateFormat: this.coreRuntime.sector.dateFormat,
|
|
18802
18798
|
inputUnit: options.inputUnit ?? "days"
|
|
18803
18799
|
});
|
|
18804
|
-
const
|
|
18800
|
+
const historyPolicy = getDispatchHistoryPolicy(action);
|
|
18805
18801
|
this.coreRuntime.state.beginWriteCapture();
|
|
18806
18802
|
this.coreRuntime.customIdTracker.beginCustomIdTransaction();
|
|
18807
|
-
this._dispatchInFlight = true;
|
|
18808
18803
|
let result;
|
|
18809
18804
|
try {
|
|
18810
18805
|
result = await dispatch(action, options, {
|
|
@@ -18817,6 +18812,7 @@ var ScheduleCore = class {
|
|
|
18817
18812
|
linkIdGen: this.coreRuntime.linkIdGenerator,
|
|
18818
18813
|
uidGen: this.coreRuntime.uniqueCorrelativeIdGenerator,
|
|
18819
18814
|
customIdTracker: this.coreRuntime.customIdTracker,
|
|
18815
|
+
reporter: this.coreRuntime.reporter,
|
|
18820
18816
|
defaultBaseCalendarId: this.coreRuntime.baseCalendars.find(
|
|
18821
18817
|
(calendar) => calendar.baseDefault
|
|
18822
18818
|
)?.id ?? null,
|
|
@@ -18827,11 +18823,10 @@ var ScheduleCore = class {
|
|
|
18827
18823
|
this._rollback();
|
|
18828
18824
|
throw error;
|
|
18829
18825
|
} finally {
|
|
18830
|
-
this._dispatchInFlight = false;
|
|
18831
18826
|
this.coreRuntime.state.endWriteCapture();
|
|
18832
18827
|
this.coreRuntime.customIdTracker.commitCustomIdTransaction();
|
|
18833
18828
|
}
|
|
18834
|
-
if (result.ok &&
|
|
18829
|
+
if (result.ok && historyPolicy === "record" && changeSetIsSubstantive(result.changes)) {
|
|
18835
18830
|
const created = captureCreatedSnapshots(
|
|
18836
18831
|
this.coreRuntime.state,
|
|
18837
18832
|
result.changes
|
|
@@ -18848,11 +18843,18 @@ var ScheduleCore = class {
|
|
|
18848
18843
|
Date.now()
|
|
18849
18844
|
);
|
|
18850
18845
|
}
|
|
18846
|
+
if (result.ok && historyPolicy === "clear-on-success") {
|
|
18847
|
+
this._saveTracker.snapshotActivities(
|
|
18848
|
+
this.coreRuntime.state.getAllActivities()
|
|
18849
|
+
);
|
|
18850
|
+
this._saveTracker.snapshotLinks(this.getAllLinksView());
|
|
18851
|
+
this._undo.clear();
|
|
18852
|
+
}
|
|
18851
18853
|
if (!result.ok) return result;
|
|
18852
|
-
if (changeSetIsSubstantive(result.changes)) {
|
|
18854
|
+
if (dispatchChangesSchedulingState(action) && changeSetIsSubstantive(result.changes)) {
|
|
18853
18855
|
this._recordScheduleMutation(options.skipCriticalPath !== true);
|
|
18854
18856
|
}
|
|
18855
|
-
return
|
|
18857
|
+
return cloneDomainValue(result);
|
|
18856
18858
|
}
|
|
18857
18859
|
/**
|
|
18858
18860
|
* Starts or joins the Critical Path calculation for the current schedule
|
|
@@ -18985,12 +18987,42 @@ var ScheduleCore = class {
|
|
|
18985
18987
|
}
|
|
18986
18988
|
return { changes };
|
|
18987
18989
|
}
|
|
18990
|
+
/**
|
|
18991
|
+
* Undo/Redo restores the user's historical mutation while retaining current
|
|
18992
|
+
* non-historical truth (for example a refreshed baseline). Re-derive every
|
|
18993
|
+
* value that depends on both so the restored model is immediately coherent.
|
|
18994
|
+
*/
|
|
18995
|
+
_recomputeAfterHistoryRestore() {
|
|
18996
|
+
const state = this.coreRuntime.state;
|
|
18997
|
+
recomputeAllProgressRollup(state);
|
|
18998
|
+
recomputeCanonicalRealWork(state);
|
|
18999
|
+
emitRealCost(state);
|
|
19000
|
+
if (this.coreRuntime.clock) {
|
|
19001
|
+
const now = endOfLocalDay(this.coreRuntime.clock());
|
|
19002
|
+
applyExpectedProgressLive(state, now);
|
|
19003
|
+
let hasActiveBaseline = false;
|
|
19004
|
+
state.forEachActivity((activity) => {
|
|
19005
|
+
hasActiveBaseline ||= getActiveBaseline(activity) !== null;
|
|
19006
|
+
});
|
|
19007
|
+
if (hasActiveBaseline) {
|
|
19008
|
+
runExpectedProgressBase(
|
|
19009
|
+
state,
|
|
19010
|
+
now,
|
|
19011
|
+
this.coreRuntime.baseCalendars.find(
|
|
19012
|
+
(calendar) => calendar.baseDefault
|
|
19013
|
+
)?.id ?? null
|
|
19014
|
+
);
|
|
19015
|
+
}
|
|
19016
|
+
applyStatusPass(state, this.coreRuntime.sector.statusCriteria);
|
|
19017
|
+
}
|
|
19018
|
+
}
|
|
18988
19019
|
undo() {
|
|
18989
19020
|
const operation = this._enqueue(async () => {
|
|
18990
19021
|
this.assertReady();
|
|
18991
19022
|
const entry = this._undo.takeUndo();
|
|
18992
19023
|
if (!entry) return null;
|
|
18993
19024
|
applyUndo(this.coreRuntime.state, entry);
|
|
19025
|
+
this._recomputeAfterHistoryRestore();
|
|
18994
19026
|
this._recordScheduleMutation(false);
|
|
18995
19027
|
if (needsResync(entry)) this._resyncCustomIdTrackerFromModel();
|
|
18996
19028
|
this._undo.pushRedo(entry);
|
|
@@ -19018,6 +19050,7 @@ var ScheduleCore = class {
|
|
|
19018
19050
|
const entry = this._undo.takeRedo();
|
|
19019
19051
|
if (!entry) return null;
|
|
19020
19052
|
applyRedo(this.coreRuntime.state, entry);
|
|
19053
|
+
this._recomputeAfterHistoryRestore();
|
|
19021
19054
|
this._recordScheduleMutation(false);
|
|
19022
19055
|
if (needsResync(entry)) this._resyncCustomIdTrackerFromModel();
|
|
19023
19056
|
this._undo.pushUndo(entry);
|
|
@@ -19039,15 +19072,20 @@ var ScheduleCore = class {
|
|
|
19039
19072
|
);
|
|
19040
19073
|
return operation;
|
|
19041
19074
|
}
|
|
19042
|
-
clearHistory() {
|
|
19043
|
-
this._undo.clear();
|
|
19044
|
-
}
|
|
19045
19075
|
canUndo() {
|
|
19046
19076
|
return this._undo.canUndo();
|
|
19047
19077
|
}
|
|
19048
19078
|
canRedo() {
|
|
19049
19079
|
return this._undo.canRedo();
|
|
19050
19080
|
}
|
|
19081
|
+
/**
|
|
19082
|
+
* Establishes a new persistence boundary without mutating schedule state.
|
|
19083
|
+
* Completed saves call this synchronously so neither prior undo entries nor
|
|
19084
|
+
* their redo branch can cross the persisted boundary.
|
|
19085
|
+
*/
|
|
19086
|
+
clearHistory() {
|
|
19087
|
+
this._undo.clear();
|
|
19088
|
+
}
|
|
19051
19089
|
undoDepth() {
|
|
19052
19090
|
return this._undo.undoDepth();
|
|
19053
19091
|
}
|
|
@@ -19133,6 +19171,10 @@ var DEFAULT_HOURS_PER_DAY = 8;
|
|
|
19133
19171
|
|
|
19134
19172
|
// src/dispatch/action-kinds.ts
|
|
19135
19173
|
var DISPATCH_ACTION_KIND = {
|
|
19174
|
+
PERSISTENCE_ACKNOWLEDGE: "persistence-acknowledge",
|
|
19175
|
+
BASELINE_APPLY: "baseline-apply",
|
|
19176
|
+
PONDERATOR_CRITERION_SET: "ponderator-criterion-set",
|
|
19177
|
+
STATUS_CRITERIA_SET: "status-criteria-set",
|
|
19136
19178
|
INLINE_EDIT: "inline-edit",
|
|
19137
19179
|
DATES_BATCH: "dates-batch",
|
|
19138
19180
|
BULK_EDIT: "bulk-edit",
|
|
@@ -19154,6 +19196,10 @@ var DISPATCH_ACTION_KIND = {
|
|
|
19154
19196
|
ACTIVITY_LOOKAHEAD_SYNC: "activity-lookahead-sync"
|
|
19155
19197
|
};
|
|
19156
19198
|
var KIND_CATALOG_COVERS_UNION = {
|
|
19199
|
+
[DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE]: true,
|
|
19200
|
+
[DISPATCH_ACTION_KIND.BASELINE_APPLY]: true,
|
|
19201
|
+
[DISPATCH_ACTION_KIND.PONDERATOR_CRITERION_SET]: true,
|
|
19202
|
+
[DISPATCH_ACTION_KIND.STATUS_CRITERIA_SET]: true,
|
|
19157
19203
|
[DISPATCH_ACTION_KIND.INLINE_EDIT]: true,
|
|
19158
19204
|
[DISPATCH_ACTION_KIND.DATES_BATCH]: true,
|
|
19159
19205
|
[DISPATCH_ACTION_KIND.BULK_EDIT]: true,
|
|
@@ -19202,7 +19248,6 @@ exports.REJECTION_REASON = REJECTION_REASON;
|
|
|
19202
19248
|
exports.ROOT_PARENT_ID = ROOT_PARENT_ID;
|
|
19203
19249
|
exports.ScheduleCore = ScheduleCore;
|
|
19204
19250
|
exports.WORK_TIME_DIRECTION = WORK_TIME_DIRECTION;
|
|
19205
|
-
exports.applyBaselinePoints = applyBaselinePoints;
|
|
19206
19251
|
exports.checkNoUpdatedLinks = checkNoUpdatedLinks;
|
|
19207
19252
|
exports.computeExpectedProgress = computeExpectedProgress;
|
|
19208
19253
|
exports.expectedProgressFromBaseline = expectedProgressFromBaseline;
|
|
@@ -19211,8 +19256,6 @@ exports.getUnsavedActivities = getUnsavedActivities;
|
|
|
19211
19256
|
exports.isRootParent = isRootParent;
|
|
19212
19257
|
exports.normalizeParentKey = normalizeParentKey;
|
|
19213
19258
|
exports.parseFromBackend = parseFromBackend;
|
|
19214
|
-
exports.recomputeAllPonderators = recomputeAllPonderators;
|
|
19215
|
-
exports.recomputeAllProgressRollup = recomputeAllProgressRollup;
|
|
19216
19259
|
exports.willRunCriticalPath = willRunCriticalPath;
|
|
19217
19260
|
exports.yieldToBrowser = yieldToBrowser;
|
|
19218
19261
|
//# sourceMappingURL=index.cjs.map
|