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