@outbuild-company/schedule-core 1.15.13 → 1.15.15
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 +414 -365
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +414 -365
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12764,258 +12764,6 @@ function normalizeActivityCreationOverrides(raw, hoursPerDay) {
|
|
|
12764
12764
|
};
|
|
12765
12765
|
}
|
|
12766
12766
|
|
|
12767
|
-
// src/dispatch/handlers/activity-create.ts
|
|
12768
|
-
async function createActivityCore(action, deps, opts = {}) {
|
|
12769
|
-
const { adapter, scheduler, sector, calendars, activityIdGen, uidGen } = deps;
|
|
12770
|
-
if (!opts.skipCacheInvalidation) scheduler.invalidateAllCaches();
|
|
12771
|
-
const target = validateCreateTarget(action, adapter);
|
|
12772
|
-
if (!target.ok) return target;
|
|
12773
|
-
const { parent, anchorSiblingId, isRoot } = target;
|
|
12774
|
-
const newId = resolveNewActivityId(
|
|
12775
|
-
action.activityId,
|
|
12776
|
-
adapter,
|
|
12777
|
-
activityIdGen,
|
|
12778
|
-
deps.isActivityIdReserved
|
|
12779
|
-
);
|
|
12780
|
-
const newUid = uidGen.next();
|
|
12781
|
-
const activityInput = {
|
|
12782
|
-
id: newId,
|
|
12783
|
-
parentId: isRoot ? null : action.parentId,
|
|
12784
|
-
sector: {
|
|
12785
|
-
id: sector.id,
|
|
12786
|
-
hoursPerDay: sector.hoursPerDay,
|
|
12787
|
-
defaultCalendar: findDefaultCalendarId(calendars)
|
|
12788
|
-
},
|
|
12789
|
-
numTasksInGantt: adapter.activityCount(),
|
|
12790
|
-
nextUniqueCorrelativeId: newUid,
|
|
12791
|
-
activityOverrides: action.overrides ?? {}
|
|
12792
|
-
};
|
|
12793
|
-
const created = buildNewActivity(activityInput, {
|
|
12794
|
-
getActivity: (id) => adapter.getActivity(id),
|
|
12795
|
-
calculateEndDate: (params) => adapter.calculateEndDate(params),
|
|
12796
|
-
getClosestWorkTime: (params) => adapter.getClosestWorkTime(params)
|
|
12797
|
-
});
|
|
12798
|
-
const newActivity = created.newTask;
|
|
12799
|
-
newActivity.realWorkHours = computeLeafRealWork(
|
|
12800
|
-
newActivity.workHours,
|
|
12801
|
-
newActivity.progress
|
|
12802
|
-
);
|
|
12803
|
-
assignCustomId(newActivity, action, deps, anchorSiblingId, parent, opts);
|
|
12804
|
-
const insertionCorrelativeId = opts.insertionCorrelativeId ?? computeInsertionCorrelativeId(
|
|
12805
|
-
adapter,
|
|
12806
|
-
isRoot ? ROOT_PARENT_ID : action.parentId,
|
|
12807
|
-
action.afterSiblingId,
|
|
12808
|
-
action.beforeSiblingId
|
|
12809
|
-
);
|
|
12810
|
-
newActivity.correlativeId = insertionCorrelativeId;
|
|
12811
|
-
const initialTouched = /* @__PURE__ */ new Set([newId]);
|
|
12812
|
-
if (parent) initialTouched.add(parent.id);
|
|
12813
|
-
const parentWasLeaf = parent !== null && adapter.getChildren(parent.id).length === 0;
|
|
12814
|
-
const parentCustomId = parentWasLeaf ? parent?.customId : null;
|
|
12815
|
-
const beforeSnap = opts.skipBeforeSnap ? /* @__PURE__ */ new Map() : await snapshotActivities(adapter, initialTouched);
|
|
12816
|
-
adapter.addActivity(newActivity);
|
|
12817
|
-
applyParentMutations(action, newId, parent, adapter, parentWasLeaf);
|
|
12818
|
-
if (parentCustomId) {
|
|
12819
|
-
deps.customIdTracker.releaseCustomId(parentCustomId);
|
|
12820
|
-
}
|
|
12821
|
-
if (!opts.skipRollupCascades) {
|
|
12822
|
-
recomputeHhCascadeForActivity(newId, adapter);
|
|
12823
|
-
recomputeUsedCostCascadeForActivity(newId, adapter);
|
|
12824
|
-
recomputeCostCascadeForActivity(newId, adapter);
|
|
12825
|
-
}
|
|
12826
|
-
const correlativeShifts = recomputeCorrelatives(
|
|
12827
|
-
adapter,
|
|
12828
|
-
newId,
|
|
12829
|
-
initialTouched,
|
|
12830
|
-
opts
|
|
12831
|
-
);
|
|
12832
|
-
return {
|
|
12833
|
-
ok: true,
|
|
12834
|
-
newId,
|
|
12835
|
-
parent,
|
|
12836
|
-
newActivity,
|
|
12837
|
-
beforeSnap,
|
|
12838
|
-
initialTouched,
|
|
12839
|
-
correlativeShifts
|
|
12840
|
-
};
|
|
12841
|
-
}
|
|
12842
|
-
function validateCreateTarget(action, adapter) {
|
|
12843
|
-
const isRoot = isRootParent(action.parentId);
|
|
12844
|
-
const parent = isRoot ? null : adapter.getActivity(action.parentId);
|
|
12845
|
-
if (!isRoot && !parent) {
|
|
12846
|
-
return { ok: false, reason: REJECTION_REASON.PARENT_NOT_FOUND };
|
|
12847
|
-
}
|
|
12848
|
-
const isParentFrozenBySir = parent !== null && isFrozen(parent);
|
|
12849
|
-
if (isParentFrozenBySir) {
|
|
12850
|
-
return { ok: false, reason: REJECTION_REASON.PARENT_FROZEN_BY_SIR };
|
|
12851
|
-
}
|
|
12852
|
-
const hasConflictingAnchors = action.afterSiblingId !== void 0 && action.beforeSiblingId !== void 0;
|
|
12853
|
-
if (hasConflictingAnchors) {
|
|
12854
|
-
return { ok: false, reason: REJECTION_REASON.ANCHOR_SIBLING_CONFLICT };
|
|
12855
|
-
}
|
|
12856
|
-
const anchorSiblingId = action.afterSiblingId ?? action.beforeSiblingId;
|
|
12857
|
-
const anchorError = validateAnchorSibling(
|
|
12858
|
-
action,
|
|
12859
|
-
adapter,
|
|
12860
|
-
isRoot,
|
|
12861
|
-
anchorSiblingId
|
|
12862
|
-
);
|
|
12863
|
-
if (anchorError) return anchorError;
|
|
12864
|
-
return { ok: true, parent, anchorSiblingId, isRoot };
|
|
12865
|
-
}
|
|
12866
|
-
function validateAnchorSibling(action, adapter, isRoot, anchorSiblingId) {
|
|
12867
|
-
if (anchorSiblingId === void 0) return null;
|
|
12868
|
-
const sibling = adapter.getActivity(anchorSiblingId);
|
|
12869
|
-
if (!sibling) {
|
|
12870
|
-
return { ok: false, reason: REJECTION_REASON.ANCHOR_SIBLING_NOT_FOUND };
|
|
12871
|
-
}
|
|
12872
|
-
const expectedSiblingParent = isRoot ? ROOT_PARENT_ID : action.parentId;
|
|
12873
|
-
const actualSiblingParent = sibling.parentId == null ? ROOT_PARENT_ID : String(sibling.parentId);
|
|
12874
|
-
if (actualSiblingParent !== expectedSiblingParent) {
|
|
12875
|
-
return { ok: false, reason: REJECTION_REASON.ANCHOR_SIBLING_WRONG_PARENT };
|
|
12876
|
-
}
|
|
12877
|
-
return null;
|
|
12878
|
-
}
|
|
12879
|
-
function resolveNewActivityId(explicitId, adapter, activityIdGen, isActivityIdReserved) {
|
|
12880
|
-
const nextAvailableId = () => {
|
|
12881
|
-
let candidate = activityIdGen.next();
|
|
12882
|
-
while (adapter.activityExists(candidate) || isActivityIdReserved(String(candidate))) {
|
|
12883
|
-
candidate = activityIdGen.next();
|
|
12884
|
-
}
|
|
12885
|
-
return candidate;
|
|
12886
|
-
};
|
|
12887
|
-
if (explicitId === void 0) return nextAvailableId();
|
|
12888
|
-
if (adapter.activityExists(explicitId) || isActivityIdReserved(String(explicitId))) {
|
|
12889
|
-
return nextAvailableId();
|
|
12890
|
-
}
|
|
12891
|
-
activityIdGen.bump(explicitId);
|
|
12892
|
-
return explicitId;
|
|
12893
|
-
}
|
|
12894
|
-
function readExplicitCustomId(action) {
|
|
12895
|
-
const value = action.overrides?.customId;
|
|
12896
|
-
return typeof value === "string" ? value : void 0;
|
|
12897
|
-
}
|
|
12898
|
-
function assignCustomId(newActivity, action, deps, anchorSiblingId, parent, opts) {
|
|
12899
|
-
const { adapter, customIdTracker } = deps;
|
|
12900
|
-
const explicit = readExplicitCustomId(action);
|
|
12901
|
-
if (explicit !== void 0) {
|
|
12902
|
-
if (explicit.length === 0) return;
|
|
12903
|
-
if (!customIdTracker.isCustomIdInUse(explicit)) {
|
|
12904
|
-
customIdTracker.registerCustomId(explicit);
|
|
12905
|
-
return;
|
|
12906
|
-
}
|
|
12907
|
-
}
|
|
12908
|
-
const customIdAnchorId = opts.customIdReferenceId ?? anchorSiblingId;
|
|
12909
|
-
const derivesFromAnchor = customIdAnchorId !== void 0;
|
|
12910
|
-
const referenceActivity = derivesFromAnchor ? adapter.getActivity(customIdAnchorId) : parent;
|
|
12911
|
-
newActivity.customId = customIdTracker.generateCustomIdForNewChild({
|
|
12912
|
-
activity: referenceActivity ?? {},
|
|
12913
|
-
useActivityCustomIdAsReference: derivesFromAnchor
|
|
12914
|
-
});
|
|
12915
|
-
}
|
|
12916
|
-
function applyParentMutations(action, newId, parent, adapter, parentWasLeaf) {
|
|
12917
|
-
if (!parent) return;
|
|
12918
|
-
const parentMutations = buildParentMutations({
|
|
12919
|
-
parentId: action.parentId,
|
|
12920
|
-
newChildId: newId,
|
|
12921
|
-
isCurrentlyLeaf: parentWasLeaf,
|
|
12922
|
-
getParent: (id) => adapter.getActivity(id) ?? null
|
|
12923
|
-
});
|
|
12924
|
-
if (!parentMutations) return;
|
|
12925
|
-
for (const [key, value] of Object.entries(parentMutations.fields)) {
|
|
12926
|
-
setActivityFieldDynamic(adapter, parentMutations.parentId, key, value);
|
|
12927
|
-
}
|
|
12928
|
-
if (parentMutations.promotionSnapshot) {
|
|
12929
|
-
adapter.setPromotionSnapshot(
|
|
12930
|
-
parentMutations.parentId,
|
|
12931
|
-
parentMutations.promotionSnapshot
|
|
12932
|
-
);
|
|
12933
|
-
}
|
|
12934
|
-
}
|
|
12935
|
-
function recomputeCorrelatives(adapter, newId, initialTouched, opts) {
|
|
12936
|
-
if (opts.skipCorrelativeRecompute) return [];
|
|
12937
|
-
const shifts = recomputeCorrelativeIds(adapter).filter(
|
|
12938
|
-
(shift) => shift.activityId !== String(newId)
|
|
12939
|
-
);
|
|
12940
|
-
for (const shift of shifts) initialTouched.add(shift.activityId);
|
|
12941
|
-
return shifts;
|
|
12942
|
-
}
|
|
12943
|
-
async function buildCreateChangeSet(adapter, action, coreResult, scheduledIds, hoursPerDay) {
|
|
12944
|
-
const { newId, newActivity, beforeSnap, initialTouched, correlativeShifts } = coreResult;
|
|
12945
|
-
const trackingEvent = {
|
|
12946
|
-
name: DISPATCH_TRACK_EVENT.ACTIVITY_CREATION,
|
|
12947
|
-
properties: {
|
|
12948
|
-
parent_id: action.parentId,
|
|
12949
|
-
activity_id: newId,
|
|
12950
|
-
created_duration: newActivity.durationHours
|
|
12951
|
-
}
|
|
12952
|
-
};
|
|
12953
|
-
if (action.eventSource !== void 0) {
|
|
12954
|
-
trackingEvent.properties.event_source = action.eventSource;
|
|
12955
|
-
}
|
|
12956
|
-
return assembleChangeSet(adapter, {
|
|
12957
|
-
source: action,
|
|
12958
|
-
beforeSnap,
|
|
12959
|
-
touchedIds: initialTouched,
|
|
12960
|
-
scheduledIds,
|
|
12961
|
-
correlativeShifts,
|
|
12962
|
-
trackingEvents: [trackingEvent]});
|
|
12963
|
-
}
|
|
12964
|
-
async function dispatchActivityCreate(action, options, deps) {
|
|
12965
|
-
const { adapter, scheduler, sector } = deps;
|
|
12966
|
-
const normalized2 = normalizeActivityCreationOverrides(
|
|
12967
|
-
action.overrides,
|
|
12968
|
-
sector.hoursPerDay
|
|
12969
|
-
);
|
|
12970
|
-
if (!normalized2.ok) return normalized2;
|
|
12971
|
-
const core = await createActivityCore(
|
|
12972
|
-
{ ...action, overrides: normalized2.value },
|
|
12973
|
-
deps
|
|
12974
|
-
);
|
|
12975
|
-
if (!core.ok) return core;
|
|
12976
|
-
const { newId } = core;
|
|
12977
|
-
const createdAutoScheduling = core.newActivity.autoScheduling;
|
|
12978
|
-
adapter.setActivityField(newId, "autoScheduling", false);
|
|
12979
|
-
let scheduleOutcome;
|
|
12980
|
-
try {
|
|
12981
|
-
scheduleOutcome = await runPostMutation(
|
|
12982
|
-
{
|
|
12983
|
-
adapter,
|
|
12984
|
-
scheduler,
|
|
12985
|
-
sector: deps.sector,
|
|
12986
|
-
defaultBaseCalendarId: deps.defaultBaseCalendarId
|
|
12987
|
-
},
|
|
12988
|
-
{
|
|
12989
|
-
action,
|
|
12990
|
-
autoscheduleFrom: newId,
|
|
12991
|
-
recomputeParentsFrom: [newId],
|
|
12992
|
-
preventSummaryTargetPullback: true,
|
|
12993
|
-
now: deps.now,
|
|
12994
|
-
options
|
|
12995
|
-
}
|
|
12996
|
-
);
|
|
12997
|
-
} finally {
|
|
12998
|
-
adapter.setActivityField(newId, "autoScheduling", createdAutoScheduling);
|
|
12999
|
-
}
|
|
13000
|
-
const { scheduledIds } = scheduleOutcome;
|
|
13001
|
-
const changeset = await buildCreateChangeSet(
|
|
13002
|
-
adapter,
|
|
13003
|
-
action,
|
|
13004
|
-
core,
|
|
13005
|
-
scheduledIds,
|
|
13006
|
-
sector.hoursPerDay
|
|
13007
|
-
);
|
|
13008
|
-
return { ok: true, changes: changeset };
|
|
13009
|
-
}
|
|
13010
|
-
function findDefaultCalendarId(calendars) {
|
|
13011
|
-
for (const calendar of calendars.values()) {
|
|
13012
|
-
if (calendar.is_default) return calendar.id;
|
|
13013
|
-
}
|
|
13014
|
-
const first = calendars.values().next();
|
|
13015
|
-
if (!first.done && first.value) return first.value.id;
|
|
13016
|
-
return "global";
|
|
13017
|
-
}
|
|
13018
|
-
|
|
13019
12767
|
// src/propagations/upward/recompute-rollup-cascades.ts
|
|
13020
12768
|
function recomputeRollupCascadesForParent(parentId, adapter) {
|
|
13021
12769
|
recomputeHhCascadeForParent(parentId, adapter);
|
|
@@ -13188,137 +12936,417 @@ async function dispatchActivityDelete(action, options, deps) {
|
|
|
13188
12936
|
for (const linkId of incidentLinkIds) {
|
|
13189
12937
|
adapter.removeLink(linkId);
|
|
13190
12938
|
}
|
|
13191
|
-
const viewStateChanges2 = captureDeletedViewState(adapter, toDelete);
|
|
13192
|
-
let removed = 0;
|
|
13193
|
-
for (const id of toDelete) {
|
|
13194
|
-
removed += 1;
|
|
13195
|
-
if (removed % DELETE_YIELD_EVERY_N === 0) await yieldToBrowser();
|
|
13196
|
-
adapter.removeActivity(id);
|
|
12939
|
+
const viewStateChanges2 = captureDeletedViewState(adapter, toDelete);
|
|
12940
|
+
let removed = 0;
|
|
12941
|
+
for (const id of toDelete) {
|
|
12942
|
+
removed += 1;
|
|
12943
|
+
if (removed % DELETE_YIELD_EVERY_N === 0) await yieldToBrowser();
|
|
12944
|
+
adapter.removeActivity(id);
|
|
12945
|
+
}
|
|
12946
|
+
for (const parentId of parentsToCheck) {
|
|
12947
|
+
const parent = adapter.getActivity(parentId);
|
|
12948
|
+
if (!parent) continue;
|
|
12949
|
+
applyParentNewActivitiesCleanup(parent, newActivitiesToDelete, adapter);
|
|
12950
|
+
const remainingChildren = adapter.getChildren(parentId);
|
|
12951
|
+
const demotion = buildParentDemotionMutations({
|
|
12952
|
+
parent,
|
|
12953
|
+
remainingChildIds: remainingChildren.map(String),
|
|
12954
|
+
defaultDurationHours: sector.hoursPerDay,
|
|
12955
|
+
promotionSnapshot: adapter.getPromotionSnapshot(parentId),
|
|
12956
|
+
computeEndDate: (startDate, durationHours) => adapter.calculateEndDate({ startDate, durationHours, task: parent }),
|
|
12957
|
+
idsRemoved: toDelete
|
|
12958
|
+
});
|
|
12959
|
+
if (!demotion) {
|
|
12960
|
+
recomputeSingleParentDisplayBounds(parentId, adapter);
|
|
12961
|
+
continue;
|
|
12962
|
+
}
|
|
12963
|
+
for (const [key, value] of Object.entries(demotion.fields)) {
|
|
12964
|
+
setActivityFieldDynamic(adapter, parentId, key, value);
|
|
12965
|
+
}
|
|
12966
|
+
if (parent.customId == null || parent.customId === "") {
|
|
12967
|
+
const previousSiblingId = findPrevSiblingHelper(parentId, adapter);
|
|
12968
|
+
const previousCustomId = previousSiblingId ? adapter.getActivity(previousSiblingId)?.customId : null;
|
|
12969
|
+
const generated = customIdTracker.generateCustomIdForRestoredChild(
|
|
12970
|
+
typeof previousCustomId === "string" && previousCustomId ? previousCustomId : null
|
|
12971
|
+
);
|
|
12972
|
+
adapter.setActivityField(
|
|
12973
|
+
parentId,
|
|
12974
|
+
ACTIVITY_PROPERTY.CUSTOM_ID,
|
|
12975
|
+
generated
|
|
12976
|
+
);
|
|
12977
|
+
}
|
|
12978
|
+
}
|
|
12979
|
+
for (const parentId of parentsToCheck) {
|
|
12980
|
+
recomputeRollupCascadesForParent(parentId, adapter);
|
|
12981
|
+
}
|
|
12982
|
+
const correlativeShifts = recomputeCorrelativeIds(adapter);
|
|
12983
|
+
const { scheduledIds } = await runPostMutation(
|
|
12984
|
+
{
|
|
12985
|
+
adapter,
|
|
12986
|
+
scheduler,
|
|
12987
|
+
sector: deps.sector,
|
|
12988
|
+
defaultBaseCalendarId: deps.defaultBaseCalendarId
|
|
12989
|
+
},
|
|
12990
|
+
{
|
|
12991
|
+
action,
|
|
12992
|
+
autoscheduleFrom: AUTOSCHEDULE_SCOPE.ROOTS,
|
|
12993
|
+
recomputeParentsFrom: parentsToCheck,
|
|
12994
|
+
now: deps.now,
|
|
12995
|
+
options
|
|
12996
|
+
}
|
|
12997
|
+
);
|
|
12998
|
+
const trackingEvent = {
|
|
12999
|
+
name: DISPATCH_TRACK_EVENT.ACTIVITY_DELETION,
|
|
13000
|
+
properties: {
|
|
13001
|
+
activity_ids: [...action.activityIds],
|
|
13002
|
+
cascade_count: toDelete.size
|
|
13003
|
+
}
|
|
13004
|
+
};
|
|
13005
|
+
if (action.eventSource !== void 0) {
|
|
13006
|
+
trackingEvent.properties.event_source = action.eventSource;
|
|
13007
|
+
}
|
|
13008
|
+
const beforeLinksByStringId = /* @__PURE__ */ new Map();
|
|
13009
|
+
for (const [id, l] of beforeLinks) beforeLinksByStringId.set(id, l);
|
|
13010
|
+
const deletedRowsSnap = /* @__PURE__ */ new Map();
|
|
13011
|
+
for (const id of toDelete) {
|
|
13012
|
+
const snap = beforeSnap.get(String(id));
|
|
13013
|
+
if (snap) deletedRowsSnap.set(String(id), snap);
|
|
13014
|
+
}
|
|
13015
|
+
const changes = await assembleChangeSet(adapter, {
|
|
13016
|
+
source: action,
|
|
13017
|
+
beforeSnap,
|
|
13018
|
+
touchedIds,
|
|
13019
|
+
scheduledIds,
|
|
13020
|
+
sirDetection: SIR_DETECTION_PHASE.AFTER_DIFF,
|
|
13021
|
+
links: buildLinkDeletions(beforeLinks),
|
|
13022
|
+
trackingEvents: [trackingEvent],
|
|
13023
|
+
hoursPerDay: sector.hoursPerDay,
|
|
13024
|
+
correlativeShifts
|
|
13025
|
+
});
|
|
13026
|
+
return {
|
|
13027
|
+
ok: true,
|
|
13028
|
+
changes: viewStateChanges2.length > 0 ? { ...changes, viewState: viewStateChanges2 } : changes,
|
|
13029
|
+
__beforeSnap: deletedRowsSnap,
|
|
13030
|
+
__beforeLinks: beforeLinksByStringId
|
|
13031
|
+
};
|
|
13032
|
+
}
|
|
13033
|
+
function applyParentNewActivitiesCleanup(parent, idsRemoved, adapter) {
|
|
13034
|
+
const cleanup = buildParentNewActivitiesCleanup({ parent, idsRemoved });
|
|
13035
|
+
if (!cleanup) return;
|
|
13036
|
+
for (const [key, value] of Object.entries(cleanup.fields)) {
|
|
13037
|
+
setActivityFieldDynamic(adapter, cleanup.parentId, key, value);
|
|
13038
|
+
}
|
|
13039
|
+
}
|
|
13040
|
+
function captureDeletedViewState(adapter, toDelete) {
|
|
13041
|
+
const changes = [];
|
|
13042
|
+
for (const id of toDelete) {
|
|
13043
|
+
const wasChecked = adapter.isChecked(id);
|
|
13044
|
+
const wasVisible = adapter.isVisible(id);
|
|
13045
|
+
if (!wasChecked && wasVisible) continue;
|
|
13046
|
+
changes.push({
|
|
13047
|
+
activityId: String(id),
|
|
13048
|
+
...wasChecked ? { checked: { before: true, after: false } } : {},
|
|
13049
|
+
...wasVisible ? {} : { visible: { before: false, after: true } }
|
|
13050
|
+
});
|
|
13051
|
+
}
|
|
13052
|
+
return changes;
|
|
13053
|
+
}
|
|
13054
|
+
function buildLinkDeletions(beforeLinks) {
|
|
13055
|
+
const out = [];
|
|
13056
|
+
for (const [id, before] of beforeLinks.entries()) {
|
|
13057
|
+
out.push({
|
|
13058
|
+
id,
|
|
13059
|
+
kind: ENTITY_CHANGE_KIND.DELETED,
|
|
13060
|
+
fields: {
|
|
13061
|
+
source: { before: String(before.source), after: void 0 },
|
|
13062
|
+
target: { before: String(before.target), after: void 0 },
|
|
13063
|
+
type: { before: before.type, after: void 0 },
|
|
13064
|
+
lag: { before: Number(before.lag), after: void 0 }
|
|
13065
|
+
},
|
|
13066
|
+
after: null
|
|
13067
|
+
});
|
|
13068
|
+
}
|
|
13069
|
+
return out;
|
|
13070
|
+
}
|
|
13071
|
+
|
|
13072
|
+
// src/dispatch/handlers/activity-create.ts
|
|
13073
|
+
async function createActivityCore(action, deps, opts = {}) {
|
|
13074
|
+
const { adapter, scheduler, sector, calendars, activityIdGen, uidGen } = deps;
|
|
13075
|
+
if (!opts.skipCacheInvalidation) scheduler.invalidateAllCaches();
|
|
13076
|
+
const target = validateCreateTarget(action, adapter);
|
|
13077
|
+
if (!target.ok) return target;
|
|
13078
|
+
const { parent, anchorSiblingId, isRoot } = target;
|
|
13079
|
+
const newId = resolveNewActivityId(
|
|
13080
|
+
action.activityId,
|
|
13081
|
+
adapter,
|
|
13082
|
+
activityIdGen,
|
|
13083
|
+
deps.isActivityIdReserved
|
|
13084
|
+
);
|
|
13085
|
+
const newUid = uidGen.next();
|
|
13086
|
+
const activityInput = {
|
|
13087
|
+
id: newId,
|
|
13088
|
+
parentId: isRoot ? null : action.parentId,
|
|
13089
|
+
sector: {
|
|
13090
|
+
id: sector.id,
|
|
13091
|
+
hoursPerDay: sector.hoursPerDay,
|
|
13092
|
+
defaultCalendar: findDefaultCalendarId(calendars)
|
|
13093
|
+
},
|
|
13094
|
+
numTasksInGantt: adapter.activityCount(),
|
|
13095
|
+
nextUniqueCorrelativeId: newUid,
|
|
13096
|
+
activityOverrides: action.overrides ?? {}
|
|
13097
|
+
};
|
|
13098
|
+
const created = buildNewActivity(activityInput, {
|
|
13099
|
+
getActivity: (id) => adapter.getActivity(id),
|
|
13100
|
+
calculateEndDate: (params) => adapter.calculateEndDate(params),
|
|
13101
|
+
getClosestWorkTime: (params) => adapter.getClosestWorkTime(params)
|
|
13102
|
+
});
|
|
13103
|
+
const newActivity = created.newTask;
|
|
13104
|
+
newActivity.realWorkHours = computeLeafRealWork(
|
|
13105
|
+
newActivity.workHours,
|
|
13106
|
+
newActivity.progress
|
|
13107
|
+
);
|
|
13108
|
+
assignCustomId(newActivity, action, deps, anchorSiblingId, parent, opts);
|
|
13109
|
+
const insertionCorrelativeId = opts.insertionCorrelativeId ?? computeInsertionCorrelativeId(
|
|
13110
|
+
adapter,
|
|
13111
|
+
isRoot ? ROOT_PARENT_ID : action.parentId,
|
|
13112
|
+
action.afterSiblingId,
|
|
13113
|
+
action.beforeSiblingId
|
|
13114
|
+
);
|
|
13115
|
+
newActivity.correlativeId = insertionCorrelativeId;
|
|
13116
|
+
const initialTouched = /* @__PURE__ */ new Set([newId]);
|
|
13117
|
+
if (parent) initialTouched.add(parent.id);
|
|
13118
|
+
const parentWasLeaf = parent !== null && adapter.getChildren(parent.id).length === 0;
|
|
13119
|
+
const parentCustomId = parentWasLeaf ? parent?.customId : null;
|
|
13120
|
+
const beforeSnap = opts.skipBeforeSnap ? /* @__PURE__ */ new Map() : await snapshotActivities(adapter, initialTouched);
|
|
13121
|
+
adapter.addActivity(newActivity);
|
|
13122
|
+
const removedParentLinks = parentWasLeaf ? removeIncidentLinks(parent.id, adapter) : /* @__PURE__ */ new Map();
|
|
13123
|
+
applyParentMutations(action, newId, parent, adapter, parentWasLeaf);
|
|
13124
|
+
if (parentCustomId) {
|
|
13125
|
+
deps.customIdTracker.releaseCustomId(parentCustomId);
|
|
13126
|
+
}
|
|
13127
|
+
if (!opts.skipRollupCascades) {
|
|
13128
|
+
recomputeHhCascadeForActivity(newId, adapter);
|
|
13129
|
+
recomputeUsedCostCascadeForActivity(newId, adapter);
|
|
13130
|
+
recomputeCostCascadeForActivity(newId, adapter);
|
|
13131
|
+
}
|
|
13132
|
+
const correlativeShifts = recomputeCorrelatives(
|
|
13133
|
+
adapter,
|
|
13134
|
+
newId,
|
|
13135
|
+
initialTouched,
|
|
13136
|
+
opts
|
|
13137
|
+
);
|
|
13138
|
+
return {
|
|
13139
|
+
ok: true,
|
|
13140
|
+
newId,
|
|
13141
|
+
parent,
|
|
13142
|
+
newActivity,
|
|
13143
|
+
beforeSnap,
|
|
13144
|
+
initialTouched,
|
|
13145
|
+
correlativeShifts,
|
|
13146
|
+
removedParentLinks
|
|
13147
|
+
};
|
|
13148
|
+
}
|
|
13149
|
+
function removeIncidentLinks(activityId, adapter) {
|
|
13150
|
+
const before = /* @__PURE__ */ new Map();
|
|
13151
|
+
const ids = /* @__PURE__ */ new Set([
|
|
13152
|
+
...adapter.getIncomingLinkIds(activityId),
|
|
13153
|
+
...adapter.getOutgoingLinkIds(activityId)
|
|
13154
|
+
]);
|
|
13155
|
+
for (const linkId of ids) {
|
|
13156
|
+
const link = adapter.getLink(linkId);
|
|
13157
|
+
if (!link) continue;
|
|
13158
|
+
before.set(String(linkId), { ...link });
|
|
13159
|
+
adapter.removeLink(linkId);
|
|
13160
|
+
}
|
|
13161
|
+
return before;
|
|
13162
|
+
}
|
|
13163
|
+
function validateCreateTarget(action, adapter) {
|
|
13164
|
+
const isRoot = isRootParent(action.parentId);
|
|
13165
|
+
const parent = isRoot ? null : adapter.getActivity(action.parentId);
|
|
13166
|
+
if (!isRoot && !parent) {
|
|
13167
|
+
return { ok: false, reason: REJECTION_REASON.PARENT_NOT_FOUND };
|
|
13168
|
+
}
|
|
13169
|
+
const isParentFrozenBySir = parent !== null && isFrozen(parent);
|
|
13170
|
+
if (isParentFrozenBySir) {
|
|
13171
|
+
return { ok: false, reason: REJECTION_REASON.PARENT_FROZEN_BY_SIR };
|
|
13172
|
+
}
|
|
13173
|
+
const hasConflictingAnchors = action.afterSiblingId !== void 0 && action.beforeSiblingId !== void 0;
|
|
13174
|
+
if (hasConflictingAnchors) {
|
|
13175
|
+
return { ok: false, reason: REJECTION_REASON.ANCHOR_SIBLING_CONFLICT };
|
|
13176
|
+
}
|
|
13177
|
+
const anchorSiblingId = action.afterSiblingId ?? action.beforeSiblingId;
|
|
13178
|
+
const anchorError = validateAnchorSibling(
|
|
13179
|
+
action,
|
|
13180
|
+
adapter,
|
|
13181
|
+
isRoot,
|
|
13182
|
+
anchorSiblingId
|
|
13183
|
+
);
|
|
13184
|
+
if (anchorError) return anchorError;
|
|
13185
|
+
return { ok: true, parent, anchorSiblingId, isRoot };
|
|
13186
|
+
}
|
|
13187
|
+
function validateAnchorSibling(action, adapter, isRoot, anchorSiblingId) {
|
|
13188
|
+
if (anchorSiblingId === void 0) return null;
|
|
13189
|
+
const sibling = adapter.getActivity(anchorSiblingId);
|
|
13190
|
+
if (!sibling) {
|
|
13191
|
+
return { ok: false, reason: REJECTION_REASON.ANCHOR_SIBLING_NOT_FOUND };
|
|
13192
|
+
}
|
|
13193
|
+
const expectedSiblingParent = isRoot ? ROOT_PARENT_ID : action.parentId;
|
|
13194
|
+
const actualSiblingParent = sibling.parentId == null ? ROOT_PARENT_ID : String(sibling.parentId);
|
|
13195
|
+
if (actualSiblingParent !== expectedSiblingParent) {
|
|
13196
|
+
return { ok: false, reason: REJECTION_REASON.ANCHOR_SIBLING_WRONG_PARENT };
|
|
13197
13197
|
}
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
|
|
13202
|
-
|
|
13203
|
-
|
|
13204
|
-
|
|
13205
|
-
remainingChildIds: remainingChildren.map(String),
|
|
13206
|
-
defaultDurationHours: sector.hoursPerDay,
|
|
13207
|
-
promotionSnapshot: adapter.getPromotionSnapshot(parentId),
|
|
13208
|
-
computeEndDate: (startDate, durationHours) => adapter.calculateEndDate({ startDate, durationHours, task: parent }),
|
|
13209
|
-
idsRemoved: toDelete
|
|
13210
|
-
});
|
|
13211
|
-
if (!demotion) {
|
|
13212
|
-
recomputeSingleParentDisplayBounds(parentId, adapter);
|
|
13213
|
-
continue;
|
|
13214
|
-
}
|
|
13215
|
-
for (const [key, value] of Object.entries(demotion.fields)) {
|
|
13216
|
-
setActivityFieldDynamic(adapter, parentId, key, value);
|
|
13198
|
+
return null;
|
|
13199
|
+
}
|
|
13200
|
+
function resolveNewActivityId(explicitId, adapter, activityIdGen, isActivityIdReserved) {
|
|
13201
|
+
const nextAvailableId = () => {
|
|
13202
|
+
let candidate = activityIdGen.next();
|
|
13203
|
+
while (adapter.activityExists(candidate) || isActivityIdReserved(String(candidate))) {
|
|
13204
|
+
candidate = activityIdGen.next();
|
|
13217
13205
|
}
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13227
|
-
|
|
13228
|
-
|
|
13206
|
+
return candidate;
|
|
13207
|
+
};
|
|
13208
|
+
if (explicitId === void 0) return nextAvailableId();
|
|
13209
|
+
if (adapter.activityExists(explicitId) || isActivityIdReserved(String(explicitId))) {
|
|
13210
|
+
return nextAvailableId();
|
|
13211
|
+
}
|
|
13212
|
+
activityIdGen.bump(explicitId);
|
|
13213
|
+
return explicitId;
|
|
13214
|
+
}
|
|
13215
|
+
function readExplicitCustomId(action) {
|
|
13216
|
+
const value = action.overrides?.customId;
|
|
13217
|
+
return typeof value === "string" ? value : void 0;
|
|
13218
|
+
}
|
|
13219
|
+
function assignCustomId(newActivity, action, deps, anchorSiblingId, parent, opts) {
|
|
13220
|
+
const { adapter, customIdTracker } = deps;
|
|
13221
|
+
const explicit = readExplicitCustomId(action);
|
|
13222
|
+
if (explicit !== void 0) {
|
|
13223
|
+
if (explicit.length === 0) return;
|
|
13224
|
+
if (!customIdTracker.isCustomIdInUse(explicit)) {
|
|
13225
|
+
customIdTracker.registerCustomId(explicit);
|
|
13226
|
+
return;
|
|
13229
13227
|
}
|
|
13230
13228
|
}
|
|
13231
|
-
|
|
13232
|
-
|
|
13229
|
+
const customIdAnchorId = opts.customIdReferenceId ?? anchorSiblingId;
|
|
13230
|
+
const derivesFromAnchor = customIdAnchorId !== void 0;
|
|
13231
|
+
const referenceActivity = derivesFromAnchor ? adapter.getActivity(customIdAnchorId) : parent;
|
|
13232
|
+
newActivity.customId = customIdTracker.generateCustomIdForNewChild({
|
|
13233
|
+
activity: referenceActivity ?? {},
|
|
13234
|
+
useActivityCustomIdAsReference: derivesFromAnchor
|
|
13235
|
+
});
|
|
13236
|
+
}
|
|
13237
|
+
function applyParentMutations(action, newId, parent, adapter, parentWasLeaf) {
|
|
13238
|
+
if (!parent) return;
|
|
13239
|
+
const parentMutations = buildParentMutations({
|
|
13240
|
+
parentId: action.parentId,
|
|
13241
|
+
newChildId: newId,
|
|
13242
|
+
isCurrentlyLeaf: parentWasLeaf,
|
|
13243
|
+
getParent: (id) => adapter.getActivity(id) ?? null
|
|
13244
|
+
});
|
|
13245
|
+
if (!parentMutations) return;
|
|
13246
|
+
for (const [key, value] of Object.entries(parentMutations.fields)) {
|
|
13247
|
+
setActivityFieldDynamic(adapter, parentMutations.parentId, key, value);
|
|
13233
13248
|
}
|
|
13234
|
-
|
|
13235
|
-
|
|
13236
|
-
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
recomputeParentsFrom: parentsToCheck,
|
|
13246
|
-
now: deps.now,
|
|
13247
|
-
options
|
|
13248
|
-
}
|
|
13249
|
+
if (parentMutations.promotionSnapshot) {
|
|
13250
|
+
adapter.setPromotionSnapshot(
|
|
13251
|
+
parentMutations.parentId,
|
|
13252
|
+
parentMutations.promotionSnapshot
|
|
13253
|
+
);
|
|
13254
|
+
}
|
|
13255
|
+
}
|
|
13256
|
+
function recomputeCorrelatives(adapter, newId, initialTouched, opts) {
|
|
13257
|
+
if (opts.skipCorrelativeRecompute) return [];
|
|
13258
|
+
const shifts = recomputeCorrelativeIds(adapter).filter(
|
|
13259
|
+
(shift) => shift.activityId !== String(newId)
|
|
13249
13260
|
);
|
|
13261
|
+
for (const shift of shifts) initialTouched.add(shift.activityId);
|
|
13262
|
+
return shifts;
|
|
13263
|
+
}
|
|
13264
|
+
async function buildCreateChangeSet(adapter, action, coreResult, scheduledIds, hoursPerDay) {
|
|
13265
|
+
const {
|
|
13266
|
+
newId,
|
|
13267
|
+
newActivity,
|
|
13268
|
+
beforeSnap,
|
|
13269
|
+
initialTouched,
|
|
13270
|
+
correlativeShifts,
|
|
13271
|
+
removedParentLinks
|
|
13272
|
+
} = coreResult;
|
|
13250
13273
|
const trackingEvent = {
|
|
13251
|
-
name: DISPATCH_TRACK_EVENT.
|
|
13274
|
+
name: DISPATCH_TRACK_EVENT.ACTIVITY_CREATION,
|
|
13252
13275
|
properties: {
|
|
13253
|
-
|
|
13254
|
-
|
|
13276
|
+
parent_id: action.parentId,
|
|
13277
|
+
activity_id: newId,
|
|
13278
|
+
created_duration: newActivity.durationHours
|
|
13255
13279
|
}
|
|
13256
13280
|
};
|
|
13257
13281
|
if (action.eventSource !== void 0) {
|
|
13258
13282
|
trackingEvent.properties.event_source = action.eventSource;
|
|
13259
13283
|
}
|
|
13260
|
-
|
|
13261
|
-
for (const [id, l] of beforeLinks) beforeLinksByStringId.set(id, l);
|
|
13262
|
-
const deletedRowsSnap = /* @__PURE__ */ new Map();
|
|
13263
|
-
for (const id of toDelete) {
|
|
13264
|
-
const snap = beforeSnap.get(String(id));
|
|
13265
|
-
if (snap) deletedRowsSnap.set(String(id), snap);
|
|
13266
|
-
}
|
|
13267
|
-
const changes = await assembleChangeSet(adapter, {
|
|
13284
|
+
return assembleChangeSet(adapter, {
|
|
13268
13285
|
source: action,
|
|
13269
13286
|
beforeSnap,
|
|
13270
|
-
touchedIds,
|
|
13287
|
+
touchedIds: initialTouched,
|
|
13271
13288
|
scheduledIds,
|
|
13272
|
-
|
|
13273
|
-
links: buildLinkDeletions(beforeLinks),
|
|
13289
|
+
correlativeShifts,
|
|
13274
13290
|
trackingEvents: [trackingEvent],
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13291
|
+
links: buildLinkDeletions(new Map(removedParentLinks))});
|
|
13292
|
+
}
|
|
13293
|
+
async function dispatchActivityCreate(action, options, deps) {
|
|
13294
|
+
const { adapter, scheduler, sector } = deps;
|
|
13295
|
+
const normalized2 = normalizeActivityCreationOverrides(
|
|
13296
|
+
action.overrides,
|
|
13297
|
+
sector.hoursPerDay
|
|
13298
|
+
);
|
|
13299
|
+
if (!normalized2.ok) return normalized2;
|
|
13300
|
+
const core = await createActivityCore(
|
|
13301
|
+
{ ...action, overrides: normalized2.value },
|
|
13302
|
+
deps
|
|
13303
|
+
);
|
|
13304
|
+
if (!core.ok) return core;
|
|
13305
|
+
const { newId } = core;
|
|
13306
|
+
const createdAutoScheduling = core.newActivity.autoScheduling;
|
|
13307
|
+
adapter.setActivityField(newId, "autoScheduling", false);
|
|
13308
|
+
let scheduleOutcome;
|
|
13309
|
+
try {
|
|
13310
|
+
scheduleOutcome = await runPostMutation(
|
|
13311
|
+
{
|
|
13312
|
+
adapter,
|
|
13313
|
+
scheduler,
|
|
13314
|
+
sector: deps.sector,
|
|
13315
|
+
defaultBaseCalendarId: deps.defaultBaseCalendarId
|
|
13316
|
+
},
|
|
13317
|
+
{
|
|
13318
|
+
action,
|
|
13319
|
+
autoscheduleFrom: newId,
|
|
13320
|
+
recomputeParentsFrom: [newId],
|
|
13321
|
+
preventSummaryTargetPullback: true,
|
|
13322
|
+
now: deps.now,
|
|
13323
|
+
options
|
|
13324
|
+
}
|
|
13325
|
+
);
|
|
13326
|
+
} finally {
|
|
13327
|
+
adapter.setActivityField(newId, "autoScheduling", createdAutoScheduling);
|
|
13328
|
+
}
|
|
13329
|
+
const { scheduledIds } = scheduleOutcome;
|
|
13330
|
+
const changeset = await buildCreateChangeSet(
|
|
13331
|
+
adapter,
|
|
13332
|
+
action,
|
|
13333
|
+
core,
|
|
13334
|
+
scheduledIds,
|
|
13335
|
+
sector.hoursPerDay
|
|
13336
|
+
);
|
|
13278
13337
|
return {
|
|
13279
13338
|
ok: true,
|
|
13280
|
-
changes:
|
|
13281
|
-
|
|
13282
|
-
__beforeLinks: beforeLinksByStringId
|
|
13339
|
+
changes: changeset,
|
|
13340
|
+
...core.removedParentLinks.size > 0 ? { __beforeLinks: new Map(core.removedParentLinks) } : {}
|
|
13283
13341
|
};
|
|
13284
13342
|
}
|
|
13285
|
-
function
|
|
13286
|
-
const
|
|
13287
|
-
|
|
13288
|
-
for (const [key, value] of Object.entries(cleanup.fields)) {
|
|
13289
|
-
setActivityFieldDynamic(adapter, cleanup.parentId, key, value);
|
|
13290
|
-
}
|
|
13291
|
-
}
|
|
13292
|
-
function captureDeletedViewState(adapter, toDelete) {
|
|
13293
|
-
const changes = [];
|
|
13294
|
-
for (const id of toDelete) {
|
|
13295
|
-
const wasChecked = adapter.isChecked(id);
|
|
13296
|
-
const wasVisible = adapter.isVisible(id);
|
|
13297
|
-
if (!wasChecked && wasVisible) continue;
|
|
13298
|
-
changes.push({
|
|
13299
|
-
activityId: String(id),
|
|
13300
|
-
...wasChecked ? { checked: { before: true, after: false } } : {},
|
|
13301
|
-
...wasVisible ? {} : { visible: { before: false, after: true } }
|
|
13302
|
-
});
|
|
13303
|
-
}
|
|
13304
|
-
return changes;
|
|
13305
|
-
}
|
|
13306
|
-
function buildLinkDeletions(beforeLinks) {
|
|
13307
|
-
const out = [];
|
|
13308
|
-
for (const [id, before] of beforeLinks.entries()) {
|
|
13309
|
-
out.push({
|
|
13310
|
-
id,
|
|
13311
|
-
kind: ENTITY_CHANGE_KIND.DELETED,
|
|
13312
|
-
fields: {
|
|
13313
|
-
source: { before: String(before.source), after: void 0 },
|
|
13314
|
-
target: { before: String(before.target), after: void 0 },
|
|
13315
|
-
type: { before: before.type, after: void 0 },
|
|
13316
|
-
lag: { before: Number(before.lag), after: void 0 }
|
|
13317
|
-
},
|
|
13318
|
-
after: null
|
|
13319
|
-
});
|
|
13343
|
+
function findDefaultCalendarId(calendars) {
|
|
13344
|
+
for (const calendar of calendars.values()) {
|
|
13345
|
+
if (calendar.is_default) return calendar.id;
|
|
13320
13346
|
}
|
|
13321
|
-
|
|
13347
|
+
const first = calendars.values().next();
|
|
13348
|
+
if (!first.done && first.value) return first.value.id;
|
|
13349
|
+
return "global";
|
|
13322
13350
|
}
|
|
13323
13351
|
|
|
13324
13352
|
// src/dispatch/handlers/activity-batch.ts
|
|
@@ -13361,6 +13389,14 @@ async function dispatchActivityBatch(action, options, deps) {
|
|
|
13361
13389
|
}
|
|
13362
13390
|
const created = await createPlannedActivities(action, plan.plan.items, deps);
|
|
13363
13391
|
if (!created.ok) return created;
|
|
13392
|
+
for (const [linkId, link] of created.removedParentLinks) {
|
|
13393
|
+
beforeLinks.set(linkId, link);
|
|
13394
|
+
appliedLinks.push({
|
|
13395
|
+
op: { kind: DISPATCH_LINK_OPERATION_KIND.DELETE, linkId },
|
|
13396
|
+
finalLinkId: linkId,
|
|
13397
|
+
rejected: null
|
|
13398
|
+
});
|
|
13399
|
+
}
|
|
13364
13400
|
const correlativeShifts = isSimpleRootAppend(action) ? [] : recomputeCorrelativeIds(deps.adapter);
|
|
13365
13401
|
const createdIdSet = new Set(
|
|
13366
13402
|
plan.plan.items.map((item) => String(item.activityId))
|
|
@@ -13435,8 +13471,8 @@ async function dispatchActivityBatch(action, options, deps) {
|
|
|
13435
13471
|
return {
|
|
13436
13472
|
ok: true,
|
|
13437
13473
|
changes: viewState.length > 0 ? { ...changes, viewState } : changes,
|
|
13438
|
-
...action.mode === ACTIVITY_BATCH_MODE.REPLACE ? {
|
|
13439
|
-
__beforeSnap: beforeSnap,
|
|
13474
|
+
...action.mode === ACTIVITY_BATCH_MODE.REPLACE || beforeLinks.size > 0 ? {
|
|
13475
|
+
...action.mode === ACTIVITY_BATCH_MODE.REPLACE ? { __beforeSnap: beforeSnap } : {},
|
|
13440
13476
|
__beforeLinks: stringKeyedLinks(beforeLinks)
|
|
13441
13477
|
} : {}
|
|
13442
13478
|
};
|
|
@@ -13711,6 +13747,7 @@ function interpolateCorrelative(left, right, position, count) {
|
|
|
13711
13747
|
}
|
|
13712
13748
|
async function createPlannedActivities(action, plannedItems, deps) {
|
|
13713
13749
|
const childrenByParent = /* @__PURE__ */ new Map();
|
|
13750
|
+
const removedParentLinks = /* @__PURE__ */ new Map();
|
|
13714
13751
|
const ready = [];
|
|
13715
13752
|
for (const item of plannedItems) {
|
|
13716
13753
|
if (item.parentBatchId === null) {
|
|
@@ -13741,6 +13778,9 @@ async function createPlannedActivities(action, plannedItems, deps) {
|
|
|
13741
13778
|
}
|
|
13742
13779
|
);
|
|
13743
13780
|
if (!core.ok) return core;
|
|
13781
|
+
for (const [linkId, link] of core.removedParentLinks) {
|
|
13782
|
+
removedParentLinks.set(linkId, link);
|
|
13783
|
+
}
|
|
13744
13784
|
for (const child of childrenByParent.get(item.input.batchId) ?? []) {
|
|
13745
13785
|
ready.push(child);
|
|
13746
13786
|
}
|
|
@@ -13757,7 +13797,7 @@ async function createPlannedActivities(action, plannedItems, deps) {
|
|
|
13757
13797
|
recomputedParents.add(String(parentId));
|
|
13758
13798
|
recomputeRollupCascadesForParent(parentId, deps.adapter);
|
|
13759
13799
|
}
|
|
13760
|
-
return { ok: true };
|
|
13800
|
+
return { ok: true, removedParentLinks };
|
|
13761
13801
|
}
|
|
13762
13802
|
function resolveActivityReference(reference, activityIdsByBatchId) {
|
|
13763
13803
|
if (typeof reference === "string") return reference;
|
|
@@ -16208,8 +16248,12 @@ async function dispatchCalendarReconcile(action, options, deps) {
|
|
|
16208
16248
|
if (!shouldReconcile(activity, deps)) continue;
|
|
16209
16249
|
const calendar = deps.ctx.calendars.getCalendar(activity.calendarId);
|
|
16210
16250
|
if (!calendar) continue;
|
|
16251
|
+
const startReference = calendar.isWorkTime(
|
|
16252
|
+
activity.startDate,
|
|
16253
|
+
CALENDAR_UNIT.HOUR
|
|
16254
|
+
) ? startOfUtcDay4(activity.startDate) : activity.startDate;
|
|
16211
16255
|
const startDate = calendar.getClosestWorkTime({
|
|
16212
|
-
date:
|
|
16256
|
+
date: startReference,
|
|
16213
16257
|
direction: WORK_TIME_DIRECTION.FUTURE,
|
|
16214
16258
|
unit: CALENDAR_UNIT.HOUR
|
|
16215
16259
|
});
|
|
@@ -16257,6 +16301,11 @@ function shouldReconcile(activity, deps) {
|
|
|
16257
16301
|
function sameInstant(first, second) {
|
|
16258
16302
|
return first.getTime() === second.getTime();
|
|
16259
16303
|
}
|
|
16304
|
+
function startOfUtcDay4(date2) {
|
|
16305
|
+
return new Date(
|
|
16306
|
+
Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())
|
|
16307
|
+
);
|
|
16308
|
+
}
|
|
16260
16309
|
|
|
16261
16310
|
// src/activity-copy-paste/policy.ts
|
|
16262
16311
|
var ACTIVITY_COPY_FIELDS = [
|