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