gantt-lib 0.60.1 → 0.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/scheduling/index.d.mts +1 -1
- package/dist/core/scheduling/index.d.ts +1 -1
- package/dist/core/scheduling/index.js +372 -56
- package/dist/core/scheduling/index.js.map +1 -1
- package/dist/core/scheduling/index.mjs +368 -56
- package/dist/core/scheduling/index.mjs.map +1 -1
- package/dist/{index-CliEEiHA.d.mts → index-BlUshzVg.d.mts} +107 -21
- package/dist/{index-CliEEiHA.d.ts → index-BlUshzVg.d.ts} +107 -21
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +414 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +408 -69
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export { D as DAY_MS, a as DependencyError, L as LinkType, T as Task,
|
|
1
|
+
export { D as DAY_MS, a as DependencyError, L as LinkType, Y as ScheduleCommandOptions, Z as ScheduleCommandResult, _ as ScheduleDependency, $ as ScheduleTask, a0 as ScheduleTaskUpdate, T as Task, a1 as TaskDependency, V as ValidationResult, a2 as addBusinessDays, e as alignToWorkingDay, f as areTasksHierarchicallyRelated, g as buildAdjacencyList, h as buildTaskRangeFromEnd, i as buildTaskRangeFromStart, j as calculateSuccessorDate, k as cascadeByLinks, l as clampDateRangeForIncomingFS, m as clampTaskRangeForIncomingFS, n as computeLagFromDates, o as computeParentDates, p as computeParentProgress, q as detectCycles, r as findParentId, s as getAllDependencyEdges, t as getAllDescendants, u as getBusinessDayOffset, a3 as getBusinessDaysCount, v as getChildren, w as getDependencyLag, x as getSuccessorChain, y as getTaskDuration, z as getTransitiveCascadeChain, A as isAncestorTask, B as isTaskParent, C as moveTaskRange, E as moveTaskWithCascade, F as normalizeDependencyLag, H as normalizeUTCDate, I as parseDateOnly, J as recalculateIncomingLags, K as recalculateProjectSchedule, N as recalculateTaskFromDependencies, O as reflowTasksOnModeSwitch, P as removeDependenciesBetweenTasks, Q as resizeTaskWithCascade, R as resolveDateRangeFromPixels, S as shiftBusinessDayOffset, a4 as subtractBusinessDays, U as universalCascade, X as validateDependencies } from '../../index-BlUshzVg.mjs';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { D as DAY_MS, a as DependencyError, L as LinkType, T as Task,
|
|
1
|
+
export { D as DAY_MS, a as DependencyError, L as LinkType, Y as ScheduleCommandOptions, Z as ScheduleCommandResult, _ as ScheduleDependency, $ as ScheduleTask, a0 as ScheduleTaskUpdate, T as Task, a1 as TaskDependency, V as ValidationResult, a2 as addBusinessDays, e as alignToWorkingDay, f as areTasksHierarchicallyRelated, g as buildAdjacencyList, h as buildTaskRangeFromEnd, i as buildTaskRangeFromStart, j as calculateSuccessorDate, k as cascadeByLinks, l as clampDateRangeForIncomingFS, m as clampTaskRangeForIncomingFS, n as computeLagFromDates, o as computeParentDates, p as computeParentProgress, q as detectCycles, r as findParentId, s as getAllDependencyEdges, t as getAllDescendants, u as getBusinessDayOffset, a3 as getBusinessDaysCount, v as getChildren, w as getDependencyLag, x as getSuccessorChain, y as getTaskDuration, z as getTransitiveCascadeChain, A as isAncestorTask, B as isTaskParent, C as moveTaskRange, E as moveTaskWithCascade, F as normalizeDependencyLag, H as normalizeUTCDate, I as parseDateOnly, J as recalculateIncomingLags, K as recalculateProjectSchedule, N as recalculateTaskFromDependencies, O as reflowTasksOnModeSwitch, P as removeDependenciesBetweenTasks, Q as resizeTaskWithCascade, R as resolveDateRangeFromPixels, S as shiftBusinessDayOffset, a4 as subtractBusinessDays, U as universalCascade, X as validateDependencies } from '../../index-BlUshzVg.js';
|
|
@@ -48,12 +48,16 @@ __export(scheduling_exports, {
|
|
|
48
48
|
isAncestorTask: () => isAncestorTask,
|
|
49
49
|
isTaskParent: () => isTaskParent,
|
|
50
50
|
moveTaskRange: () => moveTaskRange,
|
|
51
|
+
moveTaskWithCascade: () => moveTaskWithCascade,
|
|
51
52
|
normalizeDependencyLag: () => normalizeDependencyLag,
|
|
52
53
|
normalizeUTCDate: () => normalizeUTCDate,
|
|
53
54
|
parseDateOnly: () => parseDateOnly,
|
|
54
55
|
recalculateIncomingLags: () => recalculateIncomingLags,
|
|
56
|
+
recalculateProjectSchedule: () => recalculateProjectSchedule,
|
|
57
|
+
recalculateTaskFromDependencies: () => recalculateTaskFromDependencies,
|
|
55
58
|
reflowTasksOnModeSwitch: () => reflowTasksOnModeSwitch,
|
|
56
59
|
removeDependenciesBetweenTasks: () => removeDependenciesBetweenTasks,
|
|
60
|
+
resizeTaskWithCascade: () => resizeTaskWithCascade,
|
|
57
61
|
resolveDateRangeFromPixels: () => resolveDateRangeFromPixels,
|
|
58
62
|
shiftBusinessDayOffset: () => shiftBusinessDayOffset,
|
|
59
63
|
subtractBusinessDays: () => subtractBusinessDays,
|
|
@@ -485,62 +489,6 @@ function recalculateIncomingLags(task, newStartDate, newEndDate, allTasks, busin
|
|
|
485
489
|
return { ...dep, lag: nextLag };
|
|
486
490
|
});
|
|
487
491
|
}
|
|
488
|
-
function resolveDateRangeFromPixels(mode, left, width, monthStart, dayWidth, task, businessDays, weekendPredicate) {
|
|
489
|
-
const dayOffset = Math.round(left / dayWidth);
|
|
490
|
-
const rawStartDate = new Date(Date.UTC(
|
|
491
|
-
monthStart.getUTCFullYear(),
|
|
492
|
-
monthStart.getUTCMonth(),
|
|
493
|
-
monthStart.getUTCDate() + dayOffset
|
|
494
|
-
));
|
|
495
|
-
const rawEndOffset = dayOffset + Math.round(width / dayWidth) - 1;
|
|
496
|
-
const rawEndDate = new Date(Date.UTC(
|
|
497
|
-
monthStart.getUTCFullYear(),
|
|
498
|
-
monthStart.getUTCMonth(),
|
|
499
|
-
monthStart.getUTCDate() + rawEndOffset
|
|
500
|
-
));
|
|
501
|
-
if (!(businessDays && weekendPredicate)) {
|
|
502
|
-
return { start: rawStartDate, end: rawEndDate };
|
|
503
|
-
}
|
|
504
|
-
if (mode === "move") {
|
|
505
|
-
const originalStart2 = new Date(task.startDate);
|
|
506
|
-
const snapDirection2 = rawStartDate.getTime() >= originalStart2.getTime() ? 1 : -1;
|
|
507
|
-
return moveTaskRange(
|
|
508
|
-
task.startDate,
|
|
509
|
-
task.endDate,
|
|
510
|
-
rawStartDate,
|
|
511
|
-
true,
|
|
512
|
-
weekendPredicate,
|
|
513
|
-
snapDirection2
|
|
514
|
-
);
|
|
515
|
-
}
|
|
516
|
-
if (mode === "resize-right") {
|
|
517
|
-
const fixedStart = new Date(task.startDate);
|
|
518
|
-
const originalEnd = new Date(task.endDate);
|
|
519
|
-
const snapDirection2 = rawEndDate.getTime() >= originalEnd.getTime() ? 1 : -1;
|
|
520
|
-
const alignedEnd = alignToWorkingDay(rawEndDate, snapDirection2, weekendPredicate);
|
|
521
|
-
const duration2 = Math.max(1, getBusinessDaysCount(fixedStart, alignedEnd, weekendPredicate));
|
|
522
|
-
return buildTaskRangeFromStart(fixedStart, duration2, true, weekendPredicate);
|
|
523
|
-
}
|
|
524
|
-
const fixedEnd = new Date(task.endDate);
|
|
525
|
-
const originalStart = new Date(task.startDate);
|
|
526
|
-
const snapDirection = rawStartDate.getTime() >= originalStart.getTime() ? 1 : -1;
|
|
527
|
-
const alignedStart = alignToWorkingDay(rawStartDate, snapDirection, weekendPredicate);
|
|
528
|
-
const duration = Math.max(1, getBusinessDaysCount(alignedStart, fixedEnd, weekendPredicate));
|
|
529
|
-
return buildTaskRangeFromEnd(fixedEnd, duration, true, weekendPredicate);
|
|
530
|
-
}
|
|
531
|
-
function clampDateRangeForIncomingFS(task, range, allTasks, mode, businessDays, weekendPredicate) {
|
|
532
|
-
if (mode === "resize-right") {
|
|
533
|
-
return range;
|
|
534
|
-
}
|
|
535
|
-
return clampTaskRangeForIncomingFS(
|
|
536
|
-
task,
|
|
537
|
-
range.start,
|
|
538
|
-
range.end,
|
|
539
|
-
allTasks,
|
|
540
|
-
businessDays,
|
|
541
|
-
weekendPredicate
|
|
542
|
-
);
|
|
543
|
-
}
|
|
544
492
|
|
|
545
493
|
// src/core/scheduling/cascade.ts
|
|
546
494
|
function getSuccessorChain(draggedTaskId, allTasks, linkTypes = ["FS"]) {
|
|
@@ -857,6 +805,312 @@ function reflowTasksOnModeSwitch(sourceTasks, toBusinessDays, weekendPredicate)
|
|
|
857
805
|
return tasks;
|
|
858
806
|
}
|
|
859
807
|
|
|
808
|
+
// src/core/scheduling/execute.ts
|
|
809
|
+
function toIsoDate(date) {
|
|
810
|
+
return date.toISOString().split("T")[0];
|
|
811
|
+
}
|
|
812
|
+
function createChangedResult(snapshot, nextTasks) {
|
|
813
|
+
const originalById = new Map(snapshot.map((task) => [task.id, task]));
|
|
814
|
+
const changedTasks = nextTasks.filter((task) => JSON.stringify(originalById.get(task.id)) !== JSON.stringify(task));
|
|
815
|
+
return {
|
|
816
|
+
changedTasks,
|
|
817
|
+
changedIds: changedTasks.map((task) => task.id)
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function moveTaskWithCascade(taskId, newStart, snapshot, options) {
|
|
821
|
+
const task = snapshot.find((t) => t.id === taskId);
|
|
822
|
+
if (!task) {
|
|
823
|
+
return { changedTasks: [], changedIds: [] };
|
|
824
|
+
}
|
|
825
|
+
const businessDays = options?.businessDays ?? false;
|
|
826
|
+
const weekendPredicate = options?.weekendPredicate;
|
|
827
|
+
const newRange = moveTaskRange(
|
|
828
|
+
task.startDate,
|
|
829
|
+
task.endDate,
|
|
830
|
+
newStart,
|
|
831
|
+
businessDays,
|
|
832
|
+
weekendPredicate
|
|
833
|
+
);
|
|
834
|
+
const updatedDependencies = recalculateIncomingLags(
|
|
835
|
+
task,
|
|
836
|
+
newRange.start,
|
|
837
|
+
newRange.end,
|
|
838
|
+
snapshot,
|
|
839
|
+
businessDays,
|
|
840
|
+
weekendPredicate
|
|
841
|
+
);
|
|
842
|
+
const movedTask = {
|
|
843
|
+
...task,
|
|
844
|
+
startDate: newRange.start.toISOString().split("T")[0],
|
|
845
|
+
endDate: newRange.end.toISOString().split("T")[0],
|
|
846
|
+
dependencies: updatedDependencies
|
|
847
|
+
};
|
|
848
|
+
if (options?.skipCascade) {
|
|
849
|
+
return {
|
|
850
|
+
changedTasks: [movedTask],
|
|
851
|
+
changedIds: [movedTask.id]
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
const cascadeResult = universalCascade(
|
|
855
|
+
movedTask,
|
|
856
|
+
newRange.start,
|
|
857
|
+
newRange.end,
|
|
858
|
+
snapshot,
|
|
859
|
+
businessDays,
|
|
860
|
+
weekendPredicate
|
|
861
|
+
);
|
|
862
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
863
|
+
resultMap.set(movedTask.id, movedTask);
|
|
864
|
+
for (const t of cascadeResult) {
|
|
865
|
+
resultMap.set(t.id, t);
|
|
866
|
+
}
|
|
867
|
+
const changedTasks = Array.from(resultMap.values());
|
|
868
|
+
return {
|
|
869
|
+
changedTasks,
|
|
870
|
+
changedIds: changedTasks.map((t) => t.id)
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
function resizeTaskWithCascade(taskId, anchor, newDate, snapshot, options) {
|
|
874
|
+
const task = snapshot.find((t) => t.id === taskId);
|
|
875
|
+
if (!task) {
|
|
876
|
+
return { changedTasks: [], changedIds: [] };
|
|
877
|
+
}
|
|
878
|
+
const businessDays = options?.businessDays ?? false;
|
|
879
|
+
const weekendPredicate = options?.weekendPredicate;
|
|
880
|
+
const originalStart = parseDateOnly(task.startDate);
|
|
881
|
+
const originalEnd = parseDateOnly(task.endDate);
|
|
882
|
+
let newRange;
|
|
883
|
+
if (anchor === "end") {
|
|
884
|
+
newRange = { start: originalStart, end: newDate };
|
|
885
|
+
} else {
|
|
886
|
+
newRange = { start: newDate, end: originalEnd };
|
|
887
|
+
}
|
|
888
|
+
const updatedDependencies = recalculateIncomingLags(
|
|
889
|
+
task,
|
|
890
|
+
newRange.start,
|
|
891
|
+
newRange.end,
|
|
892
|
+
snapshot,
|
|
893
|
+
businessDays,
|
|
894
|
+
weekendPredicate
|
|
895
|
+
);
|
|
896
|
+
const resizedTask = {
|
|
897
|
+
...task,
|
|
898
|
+
startDate: newRange.start.toISOString().split("T")[0],
|
|
899
|
+
endDate: newRange.end.toISOString().split("T")[0],
|
|
900
|
+
dependencies: updatedDependencies
|
|
901
|
+
};
|
|
902
|
+
if (options?.skipCascade) {
|
|
903
|
+
return {
|
|
904
|
+
changedTasks: [resizedTask],
|
|
905
|
+
changedIds: [resizedTask.id]
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
const cascadeResult = universalCascade(
|
|
909
|
+
resizedTask,
|
|
910
|
+
newRange.start,
|
|
911
|
+
newRange.end,
|
|
912
|
+
snapshot,
|
|
913
|
+
businessDays,
|
|
914
|
+
weekendPredicate
|
|
915
|
+
);
|
|
916
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
917
|
+
resultMap.set(resizedTask.id, resizedTask);
|
|
918
|
+
for (const t of cascadeResult) {
|
|
919
|
+
resultMap.set(t.id, t);
|
|
920
|
+
}
|
|
921
|
+
const changedTasks = Array.from(resultMap.values());
|
|
922
|
+
return {
|
|
923
|
+
changedTasks,
|
|
924
|
+
changedIds: changedTasks.map((t) => t.id)
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
function recalculateTaskFromDependencies(taskId, snapshot, options) {
|
|
928
|
+
const task = snapshot.find((t) => t.id === taskId);
|
|
929
|
+
if (!task) {
|
|
930
|
+
return { changedTasks: [], changedIds: [] };
|
|
931
|
+
}
|
|
932
|
+
const businessDays = options?.businessDays ?? false;
|
|
933
|
+
const weekendPredicate = options?.weekendPredicate;
|
|
934
|
+
if (!task.dependencies || task.dependencies.length === 0) {
|
|
935
|
+
return {
|
|
936
|
+
changedTasks: [task],
|
|
937
|
+
changedIds: [task.id]
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
let constrainedStart = null;
|
|
941
|
+
let constrainedEnd = null;
|
|
942
|
+
for (const dep of task.dependencies) {
|
|
943
|
+
const predecessor = snapshot.find((t) => t.id === dep.taskId);
|
|
944
|
+
if (!predecessor) continue;
|
|
945
|
+
const predStart = parseDateOnly(predecessor.startDate);
|
|
946
|
+
const predEnd = parseDateOnly(predecessor.endDate);
|
|
947
|
+
const constraintDate = calculateSuccessorDate(
|
|
948
|
+
predStart,
|
|
949
|
+
predEnd,
|
|
950
|
+
dep.type,
|
|
951
|
+
getDependencyLag(dep),
|
|
952
|
+
businessDays,
|
|
953
|
+
weekendPredicate
|
|
954
|
+
);
|
|
955
|
+
const duration = getTaskDuration(
|
|
956
|
+
parseDateOnly(task.startDate),
|
|
957
|
+
parseDateOnly(task.endDate),
|
|
958
|
+
businessDays,
|
|
959
|
+
weekendPredicate
|
|
960
|
+
);
|
|
961
|
+
let range;
|
|
962
|
+
if (dep.type === "FS" || dep.type === "SS") {
|
|
963
|
+
range = buildTaskRangeFromStart(constraintDate, duration, businessDays, weekendPredicate);
|
|
964
|
+
} else {
|
|
965
|
+
range = buildTaskRangeFromEnd(constraintDate, duration, businessDays, weekendPredicate);
|
|
966
|
+
}
|
|
967
|
+
if (!constrainedStart || range.start.getTime() > constrainedStart.getTime()) {
|
|
968
|
+
constrainedStart = range.start;
|
|
969
|
+
constrainedEnd = range.end;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
if (!constrainedStart || !constrainedEnd) {
|
|
973
|
+
return {
|
|
974
|
+
changedTasks: [task],
|
|
975
|
+
changedIds: [task.id]
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
const updatedDependencies = recalculateIncomingLags(
|
|
979
|
+
task,
|
|
980
|
+
constrainedStart,
|
|
981
|
+
constrainedEnd,
|
|
982
|
+
snapshot,
|
|
983
|
+
businessDays,
|
|
984
|
+
weekendPredicate
|
|
985
|
+
);
|
|
986
|
+
const recalculatedTask = {
|
|
987
|
+
...task,
|
|
988
|
+
startDate: constrainedStart.toISOString().split("T")[0],
|
|
989
|
+
endDate: constrainedEnd.toISOString().split("T")[0],
|
|
990
|
+
dependencies: updatedDependencies
|
|
991
|
+
};
|
|
992
|
+
if (options?.skipCascade) {
|
|
993
|
+
return {
|
|
994
|
+
changedTasks: [recalculatedTask],
|
|
995
|
+
changedIds: [recalculatedTask.id]
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
const cascadeResult = universalCascade(
|
|
999
|
+
recalculatedTask,
|
|
1000
|
+
constrainedStart,
|
|
1001
|
+
constrainedEnd,
|
|
1002
|
+
snapshot,
|
|
1003
|
+
businessDays,
|
|
1004
|
+
weekendPredicate
|
|
1005
|
+
);
|
|
1006
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
1007
|
+
resultMap.set(recalculatedTask.id, recalculatedTask);
|
|
1008
|
+
for (const t of cascadeResult) {
|
|
1009
|
+
resultMap.set(t.id, t);
|
|
1010
|
+
}
|
|
1011
|
+
const changedTasks = Array.from(resultMap.values());
|
|
1012
|
+
return {
|
|
1013
|
+
changedTasks,
|
|
1014
|
+
changedIds: changedTasks.map((t) => t.id)
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
function recalculateProjectSchedule(snapshot, options) {
|
|
1018
|
+
const businessDays = options?.businessDays ?? false;
|
|
1019
|
+
const weekendPredicate = options?.weekendPredicate;
|
|
1020
|
+
const workingMap = new Map(snapshot.map((task) => [task.id, { ...task }]));
|
|
1021
|
+
const indegree = /* @__PURE__ */ new Map();
|
|
1022
|
+
const successorIdsByTask = /* @__PURE__ */ new Map();
|
|
1023
|
+
for (const task of snapshot) {
|
|
1024
|
+
indegree.set(task.id, 0);
|
|
1025
|
+
successorIdsByTask.set(task.id, []);
|
|
1026
|
+
}
|
|
1027
|
+
for (const task of snapshot) {
|
|
1028
|
+
for (const dep of task.dependencies ?? []) {
|
|
1029
|
+
if (!workingMap.has(dep.taskId)) {
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
indegree.set(task.id, (indegree.get(task.id) ?? 0) + 1);
|
|
1033
|
+
successorIdsByTask.get(dep.taskId)?.push(task.id);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
const queue = snapshot.filter((task) => (indegree.get(task.id) ?? 0) === 0).map((task) => task.id);
|
|
1037
|
+
while (queue.length > 0) {
|
|
1038
|
+
const currentId = queue.shift();
|
|
1039
|
+
for (const successorId of successorIdsByTask.get(currentId) ?? []) {
|
|
1040
|
+
const nextIndegree = (indegree.get(successorId) ?? 0) - 1;
|
|
1041
|
+
indegree.set(successorId, nextIndegree);
|
|
1042
|
+
if (nextIndegree !== 0) {
|
|
1043
|
+
continue;
|
|
1044
|
+
}
|
|
1045
|
+
const currentTask = workingMap.get(successorId);
|
|
1046
|
+
if (!currentTask || currentTask.locked || !currentTask.dependencies?.length) {
|
|
1047
|
+
queue.push(successorId);
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
const duration = getTaskDuration(
|
|
1051
|
+
parseDateOnly(currentTask.startDate),
|
|
1052
|
+
parseDateOnly(currentTask.endDate),
|
|
1053
|
+
businessDays,
|
|
1054
|
+
weekendPredicate
|
|
1055
|
+
);
|
|
1056
|
+
let constrainedRange = null;
|
|
1057
|
+
for (const dep of currentTask.dependencies) {
|
|
1058
|
+
const predecessor = workingMap.get(dep.taskId);
|
|
1059
|
+
if (!predecessor) {
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
1062
|
+
const predecessorStart = parseDateOnly(predecessor.startDate);
|
|
1063
|
+
const predecessorEnd = parseDateOnly(predecessor.endDate);
|
|
1064
|
+
const constraintDate = calculateSuccessorDate(
|
|
1065
|
+
predecessorStart,
|
|
1066
|
+
predecessorEnd,
|
|
1067
|
+
dep.type,
|
|
1068
|
+
getDependencyLag(dep),
|
|
1069
|
+
businessDays,
|
|
1070
|
+
weekendPredicate
|
|
1071
|
+
);
|
|
1072
|
+
const candidateRange = dep.type === "FS" || dep.type === "SS" ? buildTaskRangeFromStart(constraintDate, duration, businessDays, weekendPredicate) : buildTaskRangeFromEnd(constraintDate, duration, businessDays, weekendPredicate);
|
|
1073
|
+
if (!constrainedRange || candidateRange.start.getTime() > constrainedRange.start.getTime() || candidateRange.start.getTime() === constrainedRange.start.getTime() && candidateRange.end.getTime() > constrainedRange.end.getTime()) {
|
|
1074
|
+
constrainedRange = candidateRange;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
if (!constrainedRange) {
|
|
1078
|
+
queue.push(successorId);
|
|
1079
|
+
continue;
|
|
1080
|
+
}
|
|
1081
|
+
workingMap.set(successorId, {
|
|
1082
|
+
...currentTask,
|
|
1083
|
+
startDate: toIsoDate(constrainedRange.start),
|
|
1084
|
+
endDate: toIsoDate(constrainedRange.end)
|
|
1085
|
+
});
|
|
1086
|
+
queue.push(successorId);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
const parentsByDepth = snapshot.filter((task) => isTaskParent(task.id, snapshot)).map((task) => {
|
|
1090
|
+
let depth = 0;
|
|
1091
|
+
let current = task.parentId ? workingMap.get(task.parentId) : void 0;
|
|
1092
|
+
while (current) {
|
|
1093
|
+
depth++;
|
|
1094
|
+
current = current.parentId ? workingMap.get(current.parentId) : void 0;
|
|
1095
|
+
}
|
|
1096
|
+
return { taskId: task.id, depth };
|
|
1097
|
+
}).sort((left, right) => right.depth - left.depth);
|
|
1098
|
+
const workingTasks = () => Array.from(workingMap.values());
|
|
1099
|
+
for (const { taskId } of parentsByDepth) {
|
|
1100
|
+
const parent = workingMap.get(taskId);
|
|
1101
|
+
if (!parent || parent.locked) {
|
|
1102
|
+
continue;
|
|
1103
|
+
}
|
|
1104
|
+
const { startDate, endDate } = computeParentDates(taskId, workingTasks());
|
|
1105
|
+
workingMap.set(taskId, {
|
|
1106
|
+
...parent,
|
|
1107
|
+
startDate: toIsoDate(startDate),
|
|
1108
|
+
endDate: toIsoDate(endDate)
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
return createChangedResult(snapshot, Array.from(workingMap.values()));
|
|
1112
|
+
}
|
|
1113
|
+
|
|
860
1114
|
// src/core/scheduling/validation.ts
|
|
861
1115
|
function buildAdjacencyList(tasks) {
|
|
862
1116
|
const graph = /* @__PURE__ */ new Map();
|
|
@@ -955,6 +1209,64 @@ function validateDependencies(tasks) {
|
|
|
955
1209
|
errors
|
|
956
1210
|
};
|
|
957
1211
|
}
|
|
1212
|
+
|
|
1213
|
+
// src/adapters/scheduling/drag.ts
|
|
1214
|
+
function resolveDateRangeFromPixels(mode, left, width, monthStart, dayWidth, task, businessDays, weekendPredicate) {
|
|
1215
|
+
const dayOffset = Math.round(left / dayWidth);
|
|
1216
|
+
const rawStartDate = new Date(Date.UTC(
|
|
1217
|
+
monthStart.getUTCFullYear(),
|
|
1218
|
+
monthStart.getUTCMonth(),
|
|
1219
|
+
monthStart.getUTCDate() + dayOffset
|
|
1220
|
+
));
|
|
1221
|
+
const rawEndOffset = dayOffset + Math.round(width / dayWidth) - 1;
|
|
1222
|
+
const rawEndDate = new Date(Date.UTC(
|
|
1223
|
+
monthStart.getUTCFullYear(),
|
|
1224
|
+
monthStart.getUTCMonth(),
|
|
1225
|
+
monthStart.getUTCDate() + rawEndOffset
|
|
1226
|
+
));
|
|
1227
|
+
if (!(businessDays && weekendPredicate)) {
|
|
1228
|
+
return { start: rawStartDate, end: rawEndDate };
|
|
1229
|
+
}
|
|
1230
|
+
if (mode === "move") {
|
|
1231
|
+
const originalStart2 = new Date(task.startDate);
|
|
1232
|
+
const snapDirection2 = rawStartDate.getTime() >= originalStart2.getTime() ? 1 : -1;
|
|
1233
|
+
return moveTaskRange(
|
|
1234
|
+
task.startDate,
|
|
1235
|
+
task.endDate,
|
|
1236
|
+
rawStartDate,
|
|
1237
|
+
true,
|
|
1238
|
+
weekendPredicate,
|
|
1239
|
+
snapDirection2
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
if (mode === "resize-right") {
|
|
1243
|
+
const fixedStart = new Date(task.startDate);
|
|
1244
|
+
const originalEnd = new Date(task.endDate);
|
|
1245
|
+
const snapDirection2 = rawEndDate.getTime() >= originalEnd.getTime() ? 1 : -1;
|
|
1246
|
+
const alignedEnd = alignToWorkingDay(rawEndDate, snapDirection2, weekendPredicate);
|
|
1247
|
+
const duration2 = Math.max(1, getBusinessDaysCount(fixedStart, alignedEnd, weekendPredicate));
|
|
1248
|
+
return buildTaskRangeFromStart(fixedStart, duration2, true, weekendPredicate);
|
|
1249
|
+
}
|
|
1250
|
+
const fixedEnd = new Date(task.endDate);
|
|
1251
|
+
const originalStart = new Date(task.startDate);
|
|
1252
|
+
const snapDirection = rawStartDate.getTime() >= originalStart.getTime() ? 1 : -1;
|
|
1253
|
+
const alignedStart = alignToWorkingDay(rawStartDate, snapDirection, weekendPredicate);
|
|
1254
|
+
const duration = Math.max(1, getBusinessDaysCount(alignedStart, fixedEnd, weekendPredicate));
|
|
1255
|
+
return buildTaskRangeFromEnd(fixedEnd, duration, true, weekendPredicate);
|
|
1256
|
+
}
|
|
1257
|
+
function clampDateRangeForIncomingFS(task, range, allTasks, mode, businessDays, weekendPredicate) {
|
|
1258
|
+
if (mode === "resize-right") {
|
|
1259
|
+
return range;
|
|
1260
|
+
}
|
|
1261
|
+
return clampTaskRangeForIncomingFS(
|
|
1262
|
+
task,
|
|
1263
|
+
range.start,
|
|
1264
|
+
range.end,
|
|
1265
|
+
allTasks,
|
|
1266
|
+
businessDays,
|
|
1267
|
+
weekendPredicate
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
958
1270
|
// Annotate the CommonJS export names for ESM import in node:
|
|
959
1271
|
0 && (module.exports = {
|
|
960
1272
|
DAY_MS,
|
|
@@ -985,12 +1297,16 @@ function validateDependencies(tasks) {
|
|
|
985
1297
|
isAncestorTask,
|
|
986
1298
|
isTaskParent,
|
|
987
1299
|
moveTaskRange,
|
|
1300
|
+
moveTaskWithCascade,
|
|
988
1301
|
normalizeDependencyLag,
|
|
989
1302
|
normalizeUTCDate,
|
|
990
1303
|
parseDateOnly,
|
|
991
1304
|
recalculateIncomingLags,
|
|
1305
|
+
recalculateProjectSchedule,
|
|
1306
|
+
recalculateTaskFromDependencies,
|
|
992
1307
|
reflowTasksOnModeSwitch,
|
|
993
1308
|
removeDependenciesBetweenTasks,
|
|
1309
|
+
resizeTaskWithCascade,
|
|
994
1310
|
resolveDateRangeFromPixels,
|
|
995
1311
|
shiftBusinessDayOffset,
|
|
996
1312
|
subtractBusinessDays,
|