gantt-lib 0.64.1 → 0.71.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 +46 -11
- package/dist/core/scheduling/index.js.map +1 -1
- package/dist/core/scheduling/index.mjs +45 -11
- package/dist/core/scheduling/index.mjs.map +1 -1
- package/dist/{index-DMA7NbWe.d.mts → index-DlJm2l_7.d.mts} +16 -1
- package/dist/{index-DMA7NbWe.d.ts → index-DlJm2l_7.d.ts} +16 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +41 -3
- package/dist/index.d.ts +41 -3
- package/dist/index.js +404 -130
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +400 -130
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +10 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -499,6 +499,12 @@ init_dateMath();
|
|
|
499
499
|
|
|
500
500
|
// src/core/scheduling/dependencies.ts
|
|
501
501
|
init_dateMath();
|
|
502
|
+
function normalizePredecessorDates(predecessor, parseDateFn) {
|
|
503
|
+
const predStart = parseDateFn(predecessor.startDate);
|
|
504
|
+
const isMilestone = predecessor.type === "milestone";
|
|
505
|
+
const predEnd = isMilestone ? new Date(predStart.getTime() - DAY_MS) : parseDateFn(predecessor.endDate);
|
|
506
|
+
return { predStart, predEnd };
|
|
507
|
+
}
|
|
502
508
|
function getDependencyLag(dep) {
|
|
503
509
|
return Number.isFinite(dep.lag) ? dep.lag : 0;
|
|
504
510
|
}
|
|
@@ -774,8 +780,7 @@ function clampTaskRangeForIncomingFS(task, proposedStart, proposedEnd, allTasks,
|
|
|
774
780
|
if (!predecessor) {
|
|
775
781
|
continue;
|
|
776
782
|
}
|
|
777
|
-
const predecessorStart =
|
|
778
|
-
const predecessorEnd = parseDateOnly(predecessor.endDate);
|
|
783
|
+
const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(predecessor, parseDateOnly);
|
|
779
784
|
const predecessorDuration = getTaskDuration(
|
|
780
785
|
predecessorStart,
|
|
781
786
|
predecessorEnd,
|
|
@@ -811,8 +816,10 @@ function recalculateIncomingLags(task, newStartDate, newEndDate, allTasks, busin
|
|
|
811
816
|
if (!predecessor) {
|
|
812
817
|
return { ...dep, lag: getDependencyLag(dep) };
|
|
813
818
|
}
|
|
814
|
-
const predecessorStart =
|
|
815
|
-
|
|
819
|
+
const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(
|
|
820
|
+
predecessor,
|
|
821
|
+
(d) => new Date(d instanceof Date ? d.getTime() : `${String(d).split("T")[0]}T00:00:00.000Z`)
|
|
822
|
+
);
|
|
816
823
|
const nextLag = computeLagFromDates(
|
|
817
824
|
dep.type,
|
|
818
825
|
predecessorStart,
|
|
@@ -827,6 +834,12 @@ function recalculateIncomingLags(task, newStartDate, newEndDate, allTasks, busin
|
|
|
827
834
|
}
|
|
828
835
|
|
|
829
836
|
// src/core/scheduling/cascade.ts
|
|
837
|
+
function parseCascadeDateInput(date) {
|
|
838
|
+
if (date instanceof Date) {
|
|
839
|
+
return normalizeUTCDate(date);
|
|
840
|
+
}
|
|
841
|
+
return normalizeUTCDate(/* @__PURE__ */ new Date(`${date.split("T")[0]}T00:00:00.000Z`));
|
|
842
|
+
}
|
|
830
843
|
function getSuccessorChain(draggedTaskId, allTasks, linkTypes = ["FS"]) {
|
|
831
844
|
const successorMap = /* @__PURE__ */ new Map();
|
|
832
845
|
for (const task of allTasks) {
|
|
@@ -905,7 +918,21 @@ function cascadeByLinks(movedTaskId, newStart, newEnd, allTasks, skipChildCascad
|
|
|
905
918
|
const origStart = new Date(orig.startDate);
|
|
906
919
|
const origEnd = new Date(orig.endDate);
|
|
907
920
|
const duration = getTaskDuration(origStart, origEnd);
|
|
908
|
-
const
|
|
921
|
+
const currentTask = taskById.get(currentId);
|
|
922
|
+
const { predStart: normalizedPredStart, predEnd: normalizedPredEnd } = normalizePredecessorDates(
|
|
923
|
+
{
|
|
924
|
+
startDate: predStart,
|
|
925
|
+
endDate: predEnd,
|
|
926
|
+
type: currentTask.type
|
|
927
|
+
},
|
|
928
|
+
parseCascadeDateInput
|
|
929
|
+
);
|
|
930
|
+
const constraintDate = calculateSuccessorDate(
|
|
931
|
+
normalizedPredStart,
|
|
932
|
+
normalizedPredEnd,
|
|
933
|
+
dep.type,
|
|
934
|
+
getDependencyLag(dep)
|
|
935
|
+
);
|
|
909
936
|
let newSuccStart;
|
|
910
937
|
let newSuccEnd;
|
|
911
938
|
if (dep.type === "FS" || dep.type === "SS") {
|
|
@@ -1060,9 +1087,17 @@ function universalCascade(movedTask, newStart, newEnd, allTasks, businessDays =
|
|
|
1060
1087
|
if (!dep) continue;
|
|
1061
1088
|
const origStart = new Date(task.startDate);
|
|
1062
1089
|
const origEnd = new Date(task.endDate);
|
|
1090
|
+
const { predStart: normalizedPredStart, predEnd: normalizedPredEnd } = normalizePredecessorDates(
|
|
1091
|
+
{
|
|
1092
|
+
startDate: currStart,
|
|
1093
|
+
endDate: currEnd,
|
|
1094
|
+
type: currentOriginal.type
|
|
1095
|
+
},
|
|
1096
|
+
parseCascadeDateInput
|
|
1097
|
+
);
|
|
1063
1098
|
const constraintDate = calculateSuccessorDate(
|
|
1064
|
-
|
|
1065
|
-
|
|
1099
|
+
normalizedPredStart,
|
|
1100
|
+
normalizedPredEnd,
|
|
1066
1101
|
dep.type,
|
|
1067
1102
|
getDependencyLag(dep),
|
|
1068
1103
|
businessDays,
|
|
@@ -1279,8 +1314,7 @@ function recalculateTaskFromDependencies(taskId, snapshot, options) {
|
|
|
1279
1314
|
for (const dep of task.dependencies) {
|
|
1280
1315
|
const predecessor = snapshot.find((t) => t.id === dep.taskId);
|
|
1281
1316
|
if (!predecessor) continue;
|
|
1282
|
-
const predStart =
|
|
1283
|
-
const predEnd = parseDateOnly(predecessor.endDate);
|
|
1317
|
+
const { predStart, predEnd } = normalizePredecessorDates(predecessor, parseDateOnly);
|
|
1284
1318
|
const constraintDate = calculateSuccessorDate(
|
|
1285
1319
|
predStart,
|
|
1286
1320
|
predEnd,
|
|
@@ -1396,8 +1430,7 @@ function recalculateProjectSchedule(snapshot, options) {
|
|
|
1396
1430
|
if (!predecessor) {
|
|
1397
1431
|
continue;
|
|
1398
1432
|
}
|
|
1399
|
-
const predecessorStart =
|
|
1400
|
-
const predecessorEnd = parseDateOnly(predecessor.endDate);
|
|
1433
|
+
const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(predecessor, parseDateOnly);
|
|
1401
1434
|
const constraintDate = calculateSuccessorDate(
|
|
1402
1435
|
predecessorStart,
|
|
1403
1436
|
predecessorEnd,
|
|
@@ -1816,6 +1849,45 @@ var calculateTaskBar = (taskStartDate, taskEndDate, monthStart, dayWidth) => {
|
|
|
1816
1849
|
const width = Math.round((duration + 1) * dayWidth);
|
|
1817
1850
|
return { left, width };
|
|
1818
1851
|
};
|
|
1852
|
+
var calculateMilestoneGeometry = (taskDate, monthStart, dayWidth, size = 14) => {
|
|
1853
|
+
const { left, width } = calculateTaskBar(taskDate, taskDate, monthStart, dayWidth);
|
|
1854
|
+
const centerX = Math.round(left + width / 2);
|
|
1855
|
+
const halfSize = Math.round(size / 2);
|
|
1856
|
+
return {
|
|
1857
|
+
centerX,
|
|
1858
|
+
left: centerX - halfSize,
|
|
1859
|
+
right: centerX + halfSize,
|
|
1860
|
+
size
|
|
1861
|
+
};
|
|
1862
|
+
};
|
|
1863
|
+
var calculateMilestoneConnectionBounds = (dayLeft, dayWidth, size = 14) => {
|
|
1864
|
+
const halfDiagonal = Math.round(size / Math.SQRT2);
|
|
1865
|
+
const visualNudge = 2;
|
|
1866
|
+
return {
|
|
1867
|
+
left: dayLeft + halfDiagonal + visualNudge,
|
|
1868
|
+
right: dayLeft + dayWidth - halfDiagonal - visualNudge
|
|
1869
|
+
};
|
|
1870
|
+
};
|
|
1871
|
+
var resolveTaskHorizontalGeometry = (task, monthStart, dayWidth, override) => {
|
|
1872
|
+
const startDate = new Date(task.startDate);
|
|
1873
|
+
const endDate = new Date(task.endDate);
|
|
1874
|
+
if (task.type === "milestone") {
|
|
1875
|
+
const size = 14;
|
|
1876
|
+
if (override) {
|
|
1877
|
+
return calculateMilestoneConnectionBounds(override.left, dayWidth, size);
|
|
1878
|
+
}
|
|
1879
|
+
const bar2 = calculateTaskBar(startDate, startDate, monthStart, dayWidth);
|
|
1880
|
+
return calculateMilestoneConnectionBounds(bar2.left, dayWidth, size);
|
|
1881
|
+
}
|
|
1882
|
+
if (override) {
|
|
1883
|
+
return {
|
|
1884
|
+
left: override.left,
|
|
1885
|
+
right: override.left + override.width
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1888
|
+
const bar = calculateTaskBar(startDate, endDate, monthStart, dayWidth);
|
|
1889
|
+
return { left: bar.left, right: bar.left + bar.width };
|
|
1890
|
+
};
|
|
1819
1891
|
var pixelsToDate = (pixels, monthStart, dayWidth) => {
|
|
1820
1892
|
const days = Math.round(pixels / dayWidth);
|
|
1821
1893
|
return new Date(Date.UTC(
|
|
@@ -1919,6 +1991,9 @@ var calculateDependencyPath = (from, to, arrivesFromRight) => {
|
|
|
1919
1991
|
if (fy === ty) {
|
|
1920
1992
|
return `M ${fx} ${fy} H ${tx}`;
|
|
1921
1993
|
}
|
|
1994
|
+
if (fx === tx) {
|
|
1995
|
+
return `M ${fx} ${fy} V ${ty}`;
|
|
1996
|
+
}
|
|
1922
1997
|
const C = 2;
|
|
1923
1998
|
const goingDown = ty > fy;
|
|
1924
1999
|
const dirY = goingDown ? 1 : -1;
|
|
@@ -2026,6 +2101,37 @@ var isTaskExpired = (task, referenceDate = /* @__PURE__ */ new Date()) => {
|
|
|
2026
2101
|
return actualProgress < expectedProgress;
|
|
2027
2102
|
};
|
|
2028
2103
|
|
|
2104
|
+
// src/utils/taskType.ts
|
|
2105
|
+
init_dateUtils();
|
|
2106
|
+
var TASK_TYPE_DEFAULT = "task";
|
|
2107
|
+
function getTaskType(task) {
|
|
2108
|
+
return task.type ?? TASK_TYPE_DEFAULT;
|
|
2109
|
+
}
|
|
2110
|
+
function isMilestoneTask(task) {
|
|
2111
|
+
return getTaskType(task) === "milestone";
|
|
2112
|
+
}
|
|
2113
|
+
function normalizeMilestoneStartDate(startDateInput) {
|
|
2114
|
+
const parsedStartDate = parseUTCDate(startDateInput);
|
|
2115
|
+
if (startDateInput instanceof Date) {
|
|
2116
|
+
return new Date(Date.UTC(
|
|
2117
|
+
parsedStartDate.getUTCFullYear(),
|
|
2118
|
+
parsedStartDate.getUTCMonth(),
|
|
2119
|
+
parsedStartDate.getUTCDate()
|
|
2120
|
+
));
|
|
2121
|
+
}
|
|
2122
|
+
return parsedStartDate.toISOString().split("T")[0];
|
|
2123
|
+
}
|
|
2124
|
+
function normalizeTaskDatesForType(task) {
|
|
2125
|
+
if (!isMilestoneTask(task)) {
|
|
2126
|
+
return task;
|
|
2127
|
+
}
|
|
2128
|
+
const startDate = normalizeMilestoneStartDate(task.startDate);
|
|
2129
|
+
return {
|
|
2130
|
+
...task,
|
|
2131
|
+
endDate: startDate
|
|
2132
|
+
};
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2029
2135
|
// src/hooks/useTaskDrag.ts
|
|
2030
2136
|
import { useEffect, useRef, useState, useCallback } from "react";
|
|
2031
2137
|
|
|
@@ -2044,6 +2150,17 @@ function resolveDateRangeFromPixels(mode, left, width, monthStart, dayWidth, tas
|
|
|
2044
2150
|
monthStart.getUTCMonth(),
|
|
2045
2151
|
monthStart.getUTCDate() + rawEndOffset
|
|
2046
2152
|
));
|
|
2153
|
+
const isMilestone = task.type === "milestone";
|
|
2154
|
+
if (isMilestone) {
|
|
2155
|
+
const anchorDate = mode === "resize-right" ? rawEndDate : rawStartDate;
|
|
2156
|
+
if (businessDays && weekendPredicate) {
|
|
2157
|
+
const originalAnchor = mode === "resize-right" ? new Date(task.endDate) : new Date(task.startDate);
|
|
2158
|
+
const snapDirection2 = anchorDate.getTime() >= originalAnchor.getTime() ? 1 : -1;
|
|
2159
|
+
const alignedDate = alignToWorkingDay(anchorDate, snapDirection2, weekendPredicate);
|
|
2160
|
+
return { start: alignedDate, end: alignedDate };
|
|
2161
|
+
}
|
|
2162
|
+
return { start: anchorDate, end: anchorDate };
|
|
2163
|
+
}
|
|
2047
2164
|
if (!(businessDays && weekendPredicate)) {
|
|
2048
2165
|
return { start: rawStartDate, end: rawEndDate };
|
|
2049
2166
|
}
|
|
@@ -2134,8 +2251,10 @@ function handleGlobalMouseMove(e) {
|
|
|
2134
2251
|
const activeDrag = globalActiveDrag;
|
|
2135
2252
|
const { startX, initialLeft, initialWidth, mode, dayWidth, onProgress, allTasks } = activeDrag;
|
|
2136
2253
|
const deltaX = e.clientX - startX;
|
|
2254
|
+
const draggedTask = allTasks.find((t) => t.id === activeDrag.taskId);
|
|
2255
|
+
const effectiveWidth = draggedTask && isMilestoneTask(draggedTask) ? dayWidth : initialWidth;
|
|
2137
2256
|
let newLeft = initialLeft;
|
|
2138
|
-
let newWidth =
|
|
2257
|
+
let newWidth = effectiveWidth;
|
|
2139
2258
|
switch (mode) {
|
|
2140
2259
|
case "move":
|
|
2141
2260
|
newLeft = snapToGrid(initialLeft + deltaX, dayWidth);
|
|
@@ -2151,7 +2270,6 @@ function handleGlobalMouseMove(e) {
|
|
|
2151
2270
|
newWidth = Math.max(dayWidth, snappedWidth);
|
|
2152
2271
|
break;
|
|
2153
2272
|
}
|
|
2154
|
-
const draggedTask = allTasks.find((t) => t.id === activeDrag.taskId);
|
|
2155
2273
|
if (activeDrag.businessDays && activeDrag.weekendPredicate && draggedTask) {
|
|
2156
2274
|
const previewRange = clampDateRangeForIncomingFS(
|
|
2157
2275
|
draggedTask,
|
|
@@ -2193,6 +2311,9 @@ function handleGlobalMouseMove(e) {
|
|
|
2193
2311
|
newLeft = Math.round(alignedStartDay * dayWidth);
|
|
2194
2312
|
newWidth = Math.round((alignedEndDay - alignedStartDay + 1) * dayWidth);
|
|
2195
2313
|
}
|
|
2314
|
+
if (draggedTask && isMilestoneTask(draggedTask)) {
|
|
2315
|
+
newWidth = dayWidth;
|
|
2316
|
+
}
|
|
2196
2317
|
if (!activeDrag.disableConstraints && activeDrag.onCascadeProgress) {
|
|
2197
2318
|
const { dayWidth: dayWidth2, monthStart: mStart, taskId: dragId } = activeDrag;
|
|
2198
2319
|
const originalDraggedTask = draggedTask ?? allTasks.find((t) => t.id === dragId);
|
|
@@ -2229,7 +2350,8 @@ function handleGlobalMouseMove(e) {
|
|
|
2229
2350
|
};
|
|
2230
2351
|
})();
|
|
2231
2352
|
const previewStartDate = previewRange.start;
|
|
2232
|
-
const
|
|
2353
|
+
const isMilestone = originalDraggedTask ? isMilestoneTask(originalDraggedTask) : false;
|
|
2354
|
+
const previewEndDate = isMilestone ? previewRange.start : previewRange.end;
|
|
2233
2355
|
const movedTaskData = originalDraggedTask ?? { id: dragId, name: "", startDate: "", endDate: "" };
|
|
2234
2356
|
const cascadeResult = universalCascade(
|
|
2235
2357
|
{ ...movedTaskData, startDate: previewStartDate.toISOString(), endDate: previewEndDate.toISOString() },
|
|
@@ -2319,6 +2441,9 @@ var useTaskDrag = (options) => {
|
|
|
2319
2441
|
businessDays = true,
|
|
2320
2442
|
weekendPredicate
|
|
2321
2443
|
} = options;
|
|
2444
|
+
const rawHookTask = allTasks.find((t) => t.id === taskId);
|
|
2445
|
+
const hookTask = rawHookTask ? normalizeTaskDatesForType(rawHookTask) : void 0;
|
|
2446
|
+
const hookTaskIsMilestone = hookTask ? isMilestoneTask(hookTask) : false;
|
|
2322
2447
|
const isOwnerRef = useRef(false);
|
|
2323
2448
|
const effectiveLocked = locked || disableTaskDrag;
|
|
2324
2449
|
const [isDragging, setIsDragging] = useState(false);
|
|
@@ -2340,11 +2465,11 @@ var useTaskDrag = (options) => {
|
|
|
2340
2465
|
return Math.round((ms1 - ms2) / (1e3 * 60 * 60 * 24));
|
|
2341
2466
|
};
|
|
2342
2467
|
const startOffset = getUTCDayDifference2(initialStartDate, monthStart);
|
|
2343
|
-
const duration = getUTCDayDifference2(initialEndDate, initialStartDate);
|
|
2468
|
+
const duration = hookTaskIsMilestone ? 0 : getUTCDayDifference2(initialEndDate, initialStartDate);
|
|
2344
2469
|
const left = Math.round(startOffset * dayWidth);
|
|
2345
2470
|
const width = Math.round((duration + 1) * dayWidth);
|
|
2346
2471
|
return { left, width };
|
|
2347
|
-
}, [initialStartDate, initialEndDate, monthStart, dayWidth]);
|
|
2472
|
+
}, [initialStartDate, initialEndDate, monthStart, dayWidth, hookTaskIsMilestone]);
|
|
2348
2473
|
useEffect(() => {
|
|
2349
2474
|
if (isOwnerRef.current && globalActiveDrag) return;
|
|
2350
2475
|
const { left, width } = getInitialPosition();
|
|
@@ -2379,7 +2504,8 @@ var useTaskDrag = (options) => {
|
|
|
2379
2504
|
const handleComplete = useCallback((finalLeft, finalWidth, finalMode) => {
|
|
2380
2505
|
const wasOwner = isOwnerRef.current;
|
|
2381
2506
|
isOwnerRef.current = false;
|
|
2382
|
-
const
|
|
2507
|
+
const currentTaskRaw = allTasks.find((t) => t.id === taskId);
|
|
2508
|
+
const currentTask = currentTaskRaw ? normalizeTaskDatesForType(currentTaskRaw) : void 0;
|
|
2383
2509
|
const finalRange = currentTask ? clampDateRangeForIncomingFS(
|
|
2384
2510
|
currentTask,
|
|
2385
2511
|
resolveDateRangeFromPixels(
|
|
@@ -2413,7 +2539,7 @@ var useTaskDrag = (options) => {
|
|
|
2413
2539
|
};
|
|
2414
2540
|
})();
|
|
2415
2541
|
const newStartDate = finalRange.start;
|
|
2416
|
-
const newEndDate = finalRange.end;
|
|
2542
|
+
const newEndDate = currentTask && isMilestoneTask(currentTask) ? finalRange.start : finalRange.end;
|
|
2417
2543
|
setIsDragging(false);
|
|
2418
2544
|
setDragMode(null);
|
|
2419
2545
|
if (onDragStateChange) {
|
|
@@ -2425,6 +2551,23 @@ var useTaskDrag = (options) => {
|
|
|
2425
2551
|
});
|
|
2426
2552
|
}
|
|
2427
2553
|
if (wasOwner) {
|
|
2554
|
+
const startUnchanged = newStartDate.getTime() === Date.UTC(
|
|
2555
|
+
initialStartDate.getUTCFullYear(),
|
|
2556
|
+
initialStartDate.getUTCMonth(),
|
|
2557
|
+
initialStartDate.getUTCDate()
|
|
2558
|
+
);
|
|
2559
|
+
const baselineEndDate = hookTaskIsMilestone ? initialStartDate : initialEndDate;
|
|
2560
|
+
const endUnchanged = newEndDate.getTime() === Date.UTC(
|
|
2561
|
+
baselineEndDate.getUTCFullYear(),
|
|
2562
|
+
baselineEndDate.getUTCMonth(),
|
|
2563
|
+
baselineEndDate.getUTCDate()
|
|
2564
|
+
);
|
|
2565
|
+
if (startUnchanged && endUnchanged) {
|
|
2566
|
+
const { left, width } = getInitialPosition();
|
|
2567
|
+
setCurrentLeft(left);
|
|
2568
|
+
setCurrentWidth(width);
|
|
2569
|
+
return;
|
|
2570
|
+
}
|
|
2428
2571
|
if (!disableConstraints && onCascade && allTasks.length > 0) {
|
|
2429
2572
|
const draggedTaskData = currentTask;
|
|
2430
2573
|
const movedTask = {
|
|
@@ -2462,7 +2605,8 @@ var useTaskDrag = (options) => {
|
|
|
2462
2605
|
businessDays,
|
|
2463
2606
|
weekendPredicate,
|
|
2464
2607
|
initialStartDate,
|
|
2465
|
-
initialEndDate
|
|
2608
|
+
initialEndDate,
|
|
2609
|
+
hookTaskIsMilestone
|
|
2466
2610
|
]);
|
|
2467
2611
|
const handleCancel = useCallback(() => {
|
|
2468
2612
|
isOwnerRef.current = false;
|
|
@@ -2505,6 +2649,9 @@ var useTaskDrag = (options) => {
|
|
|
2505
2649
|
if (currentTask2 && isTaskParent(taskId, allTasks)) {
|
|
2506
2650
|
mode = "move";
|
|
2507
2651
|
}
|
|
2652
|
+
if (currentTask2 && isMilestoneTask(currentTask2)) {
|
|
2653
|
+
mode = "move";
|
|
2654
|
+
}
|
|
2508
2655
|
}
|
|
2509
2656
|
if (!mode) {
|
|
2510
2657
|
return;
|
|
@@ -2590,14 +2737,16 @@ var useTaskDrag = (options) => {
|
|
|
2590
2737
|
// src/components/TaskRow/TaskRow.tsx
|
|
2591
2738
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2592
2739
|
var arePropsEqual = (prevProps, nextProps) => {
|
|
2593
|
-
return prevProps.task.id === nextProps.task.id && prevProps.task.name === nextProps.task.name && prevProps.task.startDate === nextProps.task.startDate && prevProps.task.endDate === nextProps.task.endDate && prevProps.task.color === nextProps.task.color && prevProps.task.progress === nextProps.task.progress && prevProps.task.accepted === nextProps.task.accepted && prevProps.monthStart.getTime() === nextProps.monthStart.getTime() && prevProps.dayWidth === nextProps.dayWidth && prevProps.rowHeight === nextProps.rowHeight && prevProps.overridePosition?.left === nextProps.overridePosition?.left && prevProps.overridePosition?.width === nextProps.overridePosition?.width && prevProps.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints && prevProps.task.locked === nextProps.task.locked && prevProps.task.divider === nextProps.task.divider && prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks && prevProps.isFilterMatch === nextProps.isFilterMatch && prevProps.businessDays === nextProps.businessDays && prevProps.customDays === nextProps.customDays && prevProps.isWeekend === nextProps.isWeekend && prevProps.disableTaskDrag === nextProps.disableTaskDrag;
|
|
2740
|
+
return prevProps.task.id === nextProps.task.id && prevProps.task.name === nextProps.task.name && prevProps.task.startDate === nextProps.task.startDate && prevProps.task.endDate === nextProps.task.endDate && prevProps.task.type === nextProps.task.type && prevProps.task.color === nextProps.task.color && prevProps.task.progress === nextProps.task.progress && prevProps.task.accepted === nextProps.task.accepted && prevProps.monthStart.getTime() === nextProps.monthStart.getTime() && prevProps.dayWidth === nextProps.dayWidth && prevProps.rowHeight === nextProps.rowHeight && prevProps.overridePosition?.left === nextProps.overridePosition?.left && prevProps.overridePosition?.width === nextProps.overridePosition?.width && prevProps.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints && prevProps.task.locked === nextProps.task.locked && prevProps.task.divider === nextProps.task.divider && prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks && prevProps.isFilterMatch === nextProps.isFilterMatch && prevProps.businessDays === nextProps.businessDays && prevProps.customDays === nextProps.customDays && prevProps.isWeekend === nextProps.isWeekend && prevProps.disableTaskDrag === nextProps.disableTaskDrag;
|
|
2594
2741
|
};
|
|
2595
2742
|
var TaskRow = React2.memo(
|
|
2596
2743
|
({ task, monthStart, dayWidth, rowHeight, onTasksChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, onCascadeProgress, onCascade, divider, highlightExpiredTasks, isFilterMatch = false, businessDays, customDays, isWeekend: isWeekend3, disableTaskDrag = false }) => {
|
|
2597
2744
|
const defaultParentBarColor = "#782FC4";
|
|
2598
2745
|
const { divider: taskDivider } = task;
|
|
2599
|
-
const
|
|
2600
|
-
const
|
|
2746
|
+
const normalizedTask = useMemo2(() => normalizeTaskDatesForType(task), [task]);
|
|
2747
|
+
const milestone = useMemo2(() => isMilestoneTask(normalizedTask), [normalizedTask]);
|
|
2748
|
+
const taskStartDate = useMemo2(() => parseUTCDate(normalizedTask.startDate), [normalizedTask.startDate]);
|
|
2749
|
+
const taskEndDate = useMemo2(() => parseUTCDate(normalizedTask.endDate), [normalizedTask.endDate]);
|
|
2601
2750
|
const isParent = useMemo2(() => {
|
|
2602
2751
|
return allTasks ? isTaskParent(task.id, allTasks) : false;
|
|
2603
2752
|
}, [allTasks, task.id]);
|
|
@@ -2606,12 +2755,16 @@ var TaskRow = React2.memo(
|
|
|
2606
2755
|
}, [allTasks, task.id]);
|
|
2607
2756
|
const isExpired = useMemo2(() => {
|
|
2608
2757
|
if (!highlightExpiredTasks) return false;
|
|
2609
|
-
return isTaskExpired(
|
|
2610
|
-
}, [
|
|
2758
|
+
return isTaskExpired(normalizedTask);
|
|
2759
|
+
}, [normalizedTask.startDate, normalizedTask.endDate, normalizedTask.progress, highlightExpiredTasks]);
|
|
2611
2760
|
const { left, width } = useMemo2(
|
|
2612
2761
|
() => calculateTaskBar(taskStartDate, taskEndDate, monthStart, dayWidth),
|
|
2613
2762
|
[taskStartDate, taskEndDate, monthStart, dayWidth]
|
|
2614
2763
|
);
|
|
2764
|
+
const milestoneGeometry = useMemo2(
|
|
2765
|
+
() => calculateMilestoneGeometry(taskStartDate, monthStart, dayWidth),
|
|
2766
|
+
[taskStartDate, monthStart, dayWidth]
|
|
2767
|
+
);
|
|
2615
2768
|
const barColor = isExpired ? "var(--gantt-expired-color)" : task.color || "var(--gantt-task-bar-default-color)";
|
|
2616
2769
|
const progressWidth = useMemo2(() => {
|
|
2617
2770
|
if (task.progress === void 0 || task.progress <= 0) return 0;
|
|
@@ -2650,7 +2803,7 @@ var TaskRow = React2.memo(
|
|
|
2650
2803
|
}, [defaultParentBarColor, isExpired, isParent, progressWidth, barColor, progressColor, task.color]);
|
|
2651
2804
|
const handleDragEnd = (result) => {
|
|
2652
2805
|
const updatedTask = {
|
|
2653
|
-
...
|
|
2806
|
+
...normalizedTask,
|
|
2654
2807
|
startDate: result.startDate.toISOString(),
|
|
2655
2808
|
endDate: result.endDate.toISOString(),
|
|
2656
2809
|
...result.updatedDependencies !== void 0 && { dependencies: result.updatedDependencies }
|
|
@@ -2689,8 +2842,20 @@ var TaskRow = React2.memo(
|
|
|
2689
2842
|
});
|
|
2690
2843
|
const displayLeft = overridePosition?.left ?? (isDragging ? currentLeft : left);
|
|
2691
2844
|
const displayWidth = overridePosition?.width ?? (isDragging ? currentWidth : width);
|
|
2845
|
+
const displayMilestoneGeometry = useMemo2(() => {
|
|
2846
|
+
const centerX = Math.round(displayLeft + dayWidth / 2);
|
|
2847
|
+
const halfSize = Math.round(milestoneGeometry.size / 2);
|
|
2848
|
+
return {
|
|
2849
|
+
centerX,
|
|
2850
|
+
left: centerX - halfSize,
|
|
2851
|
+
right: centerX + halfSize,
|
|
2852
|
+
size: milestoneGeometry.size
|
|
2853
|
+
};
|
|
2854
|
+
}, [displayLeft, dayWidth, milestoneGeometry.size]);
|
|
2855
|
+
const visualLeft = milestone ? displayMilestoneGeometry.left : displayLeft;
|
|
2856
|
+
const visualWidth = milestone ? displayMilestoneGeometry.size : displayWidth;
|
|
2692
2857
|
const currentStartDate = isDragging ? pixelsToDate(displayLeft, monthStart, dayWidth) : taskStartDate;
|
|
2693
|
-
const currentEndDate = isDragging ? pixelsToDate(displayLeft + displayWidth - dayWidth, monthStart, dayWidth) : taskEndDate;
|
|
2858
|
+
const currentEndDate = isDragging ? milestone ? pixelsToDate(displayLeft, monthStart, dayWidth) : pixelsToDate(displayLeft + displayWidth - dayWidth, monthStart, dayWidth) : taskEndDate;
|
|
2694
2859
|
const dateRangeLabel = formatDateRangeLabel(currentStartDate, currentEndDate);
|
|
2695
2860
|
const durationDays = businessDays ? getBusinessDaysCount(currentStartDate, currentEndDate, weekendPredicate) : Math.round(
|
|
2696
2861
|
(currentEndDate.getTime() - currentStartDate.getTime()) / (1e3 * 60 * 60 * 24)
|
|
@@ -2705,9 +2870,9 @@ var TaskRow = React2.memo(
|
|
|
2705
2870
|
return `${count} \u0437\u0430\u0434\u0430\u0447`;
|
|
2706
2871
|
};
|
|
2707
2872
|
const estimatedTextWidth = isParent ? 120 : durationDays >= 10 ? 76 : 62;
|
|
2708
|
-
const showProgressInside = progressWidth > 0 && displayWidth > estimatedTextWidth;
|
|
2873
|
+
const showProgressInside = !milestone && progressWidth > 0 && displayWidth > estimatedTextWidth;
|
|
2709
2874
|
const MIN_DURATION_WIDTH = isParent ? 80 : 50;
|
|
2710
|
-
const showDurationInside = durationDays >= 2 && displayWidth > MIN_DURATION_WIDTH;
|
|
2875
|
+
const showDurationInside = !milestone && durationDays >= 2 && displayWidth > MIN_DURATION_WIDTH;
|
|
2711
2876
|
return /* @__PURE__ */ jsxs2(
|
|
2712
2877
|
"div",
|
|
2713
2878
|
{
|
|
@@ -2721,18 +2886,24 @@ var TaskRow = React2.memo(
|
|
|
2721
2886
|
"div",
|
|
2722
2887
|
{
|
|
2723
2888
|
"data-taskbar": true,
|
|
2724
|
-
className: `gantt-tr-taskBar ${isDragging ? "gantt-tr-dragging" : ""} ${task.locked ? "gantt-tr-locked" : ""} ${isParent ? "gantt-tr-parentBar" : ""}`,
|
|
2889
|
+
className: `gantt-tr-taskBar ${isDragging ? "gantt-tr-dragging" : ""} ${task.locked ? "gantt-tr-locked" : ""} ${isParent ? "gantt-tr-parentBar" : ""} ${milestone ? "gantt-tr-milestone" : ""}`,
|
|
2725
2890
|
style: {
|
|
2726
|
-
left: `${
|
|
2727
|
-
width: `${displayWidth}px`,
|
|
2891
|
+
left: `${visualLeft}px`,
|
|
2728
2892
|
...barStyle,
|
|
2729
|
-
|
|
2893
|
+
...milestone ? {
|
|
2894
|
+
height: `${displayMilestoneGeometry.size}px`,
|
|
2895
|
+
width: `${displayMilestoneGeometry.size}px`,
|
|
2896
|
+
padding: 0
|
|
2897
|
+
} : {
|
|
2898
|
+
width: `${visualWidth}px`,
|
|
2899
|
+
height: isParent ? "var(--gantt-parent-bar-height, 14px)" : "var(--gantt-task-bar-height)"
|
|
2900
|
+
},
|
|
2730
2901
|
cursor: dragHandleProps.style.cursor,
|
|
2731
2902
|
userSelect: dragHandleProps.style.userSelect
|
|
2732
2903
|
},
|
|
2733
2904
|
onMouseDown: dragHandleProps.onMouseDown,
|
|
2734
2905
|
children: [
|
|
2735
|
-
progressWidth > 0 && progressWidth < 100 && /* @__PURE__ */ jsx2(
|
|
2906
|
+
!milestone && progressWidth > 0 && progressWidth < 100 && /* @__PURE__ */ jsx2(
|
|
2736
2907
|
"div",
|
|
2737
2908
|
{
|
|
2738
2909
|
className: "gantt-tr-progressBar",
|
|
@@ -2745,13 +2916,13 @@ var TaskRow = React2.memo(
|
|
|
2745
2916
|
}
|
|
2746
2917
|
}
|
|
2747
2918
|
),
|
|
2748
|
-
!isParent && /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
|
|
2919
|
+
!isParent && !milestone && /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
|
|
2749
2920
|
showDurationInside && /* @__PURE__ */ jsx2("span", { className: "gantt-tr-taskDuration", children: isParent ? getChildCountLabel(childCount) : `${durationDays} \u0434` }),
|
|
2750
2921
|
progressWidth > 0 && showProgressInside && /* @__PURE__ */ jsxs2("span", { className: "gantt-tr-progressText", children: [
|
|
2751
2922
|
progressWidth,
|
|
2752
2923
|
"%"
|
|
2753
2924
|
] }),
|
|
2754
|
-
!isParent && /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
|
|
2925
|
+
!isParent && !milestone && /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
|
|
2755
2926
|
]
|
|
2756
2927
|
}
|
|
2757
2928
|
),
|
|
@@ -2760,7 +2931,7 @@ var TaskRow = React2.memo(
|
|
|
2760
2931
|
{
|
|
2761
2932
|
className: `gantt-tr-leftLabels ${task.locked ? "gantt-tr-leftLabels-locked" : ""}`,
|
|
2762
2933
|
style: {
|
|
2763
|
-
left: `${
|
|
2934
|
+
left: `${visualLeft}px`
|
|
2764
2935
|
},
|
|
2765
2936
|
children: /* @__PURE__ */ jsx2("span", { className: "gantt-tr-dateLabel gantt-tr-dateLabelLeft", children: dateRangeLabel })
|
|
2766
2937
|
}
|
|
@@ -2771,7 +2942,7 @@ var TaskRow = React2.memo(
|
|
|
2771
2942
|
className: "gantt-tr-lockIcon",
|
|
2772
2943
|
style: {
|
|
2773
2944
|
position: "absolute",
|
|
2774
|
-
left: `${
|
|
2945
|
+
left: `${visualLeft - 16}px`,
|
|
2775
2946
|
top: "50%",
|
|
2776
2947
|
transform: "translateY(-50%)",
|
|
2777
2948
|
width: "12px",
|
|
@@ -2791,11 +2962,11 @@ var TaskRow = React2.memo(
|
|
|
2791
2962
|
{
|
|
2792
2963
|
className: "gantt-tr-rightLabels",
|
|
2793
2964
|
style: {
|
|
2794
|
-
left: `${
|
|
2965
|
+
left: `${visualLeft + Math.max(visualWidth, 20) - Math.min(6, Math.max(visualWidth, 20) / 2) + 8}px`,
|
|
2795
2966
|
color: isParent ? task.color || defaultParentBarColor : barColor
|
|
2796
2967
|
},
|
|
2797
2968
|
children: [
|
|
2798
|
-
!showDurationInside && /* @__PURE__ */ jsx2("span", { className: "gantt-tr-externalDuration", children: isParent ? getChildCountLabel(childCount) : `${durationDays} \u0434` }),
|
|
2969
|
+
!showDurationInside && !milestone && /* @__PURE__ */ jsx2("span", { className: "gantt-tr-externalDuration", children: isParent ? getChildCountLabel(childCount) : `${durationDays} \u0434` }),
|
|
2799
2970
|
progressWidth > 0 && !showProgressInside && /* @__PURE__ */ jsxs2("span", { className: "gantt-tr-externalProgress", children: [
|
|
2800
2971
|
progressWidth,
|
|
2801
2972
|
"%"
|
|
@@ -3044,16 +3215,12 @@ var DependencyLines = React5.memo(({
|
|
|
3044
3215
|
const taskMap = new Map(tasksForPositions.map((t) => [t.id, t]));
|
|
3045
3216
|
const visibleTaskMap = new Map(tasks.map((t) => [t.id, t]));
|
|
3046
3217
|
tasks.forEach((task, index) => {
|
|
3047
|
-
const startDate = new Date(task.startDate);
|
|
3048
|
-
const endDate = new Date(task.endDate);
|
|
3049
|
-
const computed = calculateTaskBar(startDate, endDate, monthStart, dayWidth);
|
|
3050
3218
|
const override = dragOverrides?.get(task.id);
|
|
3051
|
-
const
|
|
3052
|
-
const resolvedWidth = override?.width ?? computed.width;
|
|
3219
|
+
const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);
|
|
3053
3220
|
indices.set(task.id, index);
|
|
3054
3221
|
positions.set(task.id, {
|
|
3055
|
-
left:
|
|
3056
|
-
right:
|
|
3222
|
+
left: computed.left,
|
|
3223
|
+
right: computed.right,
|
|
3057
3224
|
rowTop: index * rowHeight,
|
|
3058
3225
|
isVirtual: false
|
|
3059
3226
|
});
|
|
@@ -3067,15 +3234,11 @@ var DependencyLines = React5.memo(({
|
|
|
3067
3234
|
if (!visibleAncestor) continue;
|
|
3068
3235
|
const ancestorPosition = positions.get(visibleAncestor.id);
|
|
3069
3236
|
if (!ancestorPosition) continue;
|
|
3070
|
-
const startDate = new Date(task.startDate);
|
|
3071
|
-
const endDate = new Date(task.endDate);
|
|
3072
|
-
const computed = calculateTaskBar(startDate, endDate, monthStart, dayWidth);
|
|
3073
3237
|
const override = dragOverrides?.get(task.id);
|
|
3074
|
-
const
|
|
3075
|
-
const resolvedWidth = override?.width ?? computed.width;
|
|
3238
|
+
const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);
|
|
3076
3239
|
positions.set(task.id, {
|
|
3077
|
-
left:
|
|
3078
|
-
right:
|
|
3240
|
+
left: computed.left,
|
|
3241
|
+
right: computed.right,
|
|
3079
3242
|
rowTop: ancestorPosition.rowTop,
|
|
3080
3243
|
isVirtual: true
|
|
3081
3244
|
});
|
|
@@ -3091,6 +3254,7 @@ var DependencyLines = React5.memo(({
|
|
|
3091
3254
|
}, [tasks, allTasks]);
|
|
3092
3255
|
const lines = useMemo5(() => {
|
|
3093
3256
|
const tasksForEdges = allTasks ?? tasks;
|
|
3257
|
+
const taskMap = new Map(tasksForEdges.map((task) => [task.id, task]));
|
|
3094
3258
|
const edges = getAllDependencyEdges(tasksForEdges);
|
|
3095
3259
|
const lines2 = [];
|
|
3096
3260
|
for (const edge of edges) {
|
|
@@ -3101,9 +3265,11 @@ var DependencyLines = React5.memo(({
|
|
|
3101
3265
|
if (!predecessor || !successor) {
|
|
3102
3266
|
continue;
|
|
3103
3267
|
}
|
|
3268
|
+
const predecessorTask = taskMap.get(edge.predecessorId);
|
|
3269
|
+
const successorTask = taskMap.get(edge.successorId);
|
|
3104
3270
|
if (allTasks && collapsedParentIds.size > 0) {
|
|
3105
|
-
const
|
|
3106
|
-
if (areBothHiddenInSameParent(edge.predecessorId, edge.successorId, collapsedParentIds,
|
|
3271
|
+
const taskMap2 = new Map(allTasks.map((t) => [t.id, t]));
|
|
3272
|
+
if (areBothHiddenInSameParent(edge.predecessorId, edge.successorId, collapsedParentIds, taskMap2)) {
|
|
3107
3273
|
continue;
|
|
3108
3274
|
}
|
|
3109
3275
|
}
|
|
@@ -3123,11 +3289,18 @@ var DependencyLines = React5.memo(({
|
|
|
3123
3289
|
fromY = predecessor.rowTop + rowHeight - 10;
|
|
3124
3290
|
toY = successor.rowTop + 6;
|
|
3125
3291
|
}
|
|
3126
|
-
|
|
3292
|
+
let fromX = edge.type === "SS" || edge.type === "SF" ? predecessor.left : predecessor.right;
|
|
3127
3293
|
const toX = edge.type === "FF" || edge.type === "SF" ? successor.right : successor.left;
|
|
3294
|
+
const stackedMilestonesSameDay = Boolean(
|
|
3295
|
+
predecessorTask && successorTask && isMilestoneTask(predecessorTask) && isMilestoneTask(successorTask) && edge.lag === 0 && new Date(predecessorTask.startDate).toISOString().split("T")[0] === new Date(successorTask.startDate).toISOString().split("T")[0] && predecessor.rowTop !== successor.rowTop && edge.type === "FS"
|
|
3296
|
+
);
|
|
3297
|
+
const finalToX = stackedMilestonesSameDay ? Math.round(((predecessor.left + predecessor.right) / 2 + (successor.left + successor.right) / 2) / 2) : toX;
|
|
3298
|
+
if (stackedMilestonesSameDay) {
|
|
3299
|
+
fromX = finalToX;
|
|
3300
|
+
}
|
|
3128
3301
|
const arrivesFromRight = edge.type === "FF" || edge.type === "SF";
|
|
3129
3302
|
const from = { x: fromX, y: fromY };
|
|
3130
|
-
const to = { x:
|
|
3303
|
+
const to = { x: finalToX, y: toY };
|
|
3131
3304
|
const path = calculateDependencyPath(from, to, arrivesFromRight);
|
|
3132
3305
|
const hasCycle = cycleInfo.has(edge.predecessorId) || cycleInfo.has(edge.successorId);
|
|
3133
3306
|
lines2.push({
|
|
@@ -3136,7 +3309,7 @@ var DependencyLines = React5.memo(({
|
|
|
3136
3309
|
hasCycle,
|
|
3137
3310
|
lag: edge.lag,
|
|
3138
3311
|
fromX,
|
|
3139
|
-
toX,
|
|
3312
|
+
toX: finalToX,
|
|
3140
3313
|
fromY,
|
|
3141
3314
|
reverseOrder,
|
|
3142
3315
|
isVirtual
|
|
@@ -3149,6 +3322,7 @@ var DependencyLines = React5.memo(({
|
|
|
3149
3322
|
"svg",
|
|
3150
3323
|
{
|
|
3151
3324
|
className: "gantt-dependencies-svg",
|
|
3325
|
+
"data-testid": "dependency-lines-svg",
|
|
3152
3326
|
width: gridWidth,
|
|
3153
3327
|
height: svgHeight,
|
|
3154
3328
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -4147,7 +4321,7 @@ var DepChip = ({
|
|
|
4147
4321
|
const predecessor = taskById.get(dep.taskId);
|
|
4148
4322
|
if (!predecessor) return;
|
|
4149
4323
|
const predStart = parseUTCDate(predecessor.startDate);
|
|
4150
|
-
const predEnd = parseUTCDate(predecessor.endDate);
|
|
4324
|
+
const predEnd = predecessor.type === "milestone" ? predStart : parseUTCDate(predecessor.endDate);
|
|
4151
4325
|
const origStart = parseUTCDate(task.startDate);
|
|
4152
4326
|
const origEnd = parseUTCDate(task.endDate);
|
|
4153
4327
|
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
@@ -4398,7 +4572,8 @@ var TaskListRow = React9.memo(
|
|
|
4398
4572
|
canDemoteTask = true,
|
|
4399
4573
|
isLastChild = true,
|
|
4400
4574
|
nestingDepth = 0,
|
|
4401
|
-
|
|
4575
|
+
hasVisibleChildren = false,
|
|
4576
|
+
ancestorLineModes = [],
|
|
4402
4577
|
customDays,
|
|
4403
4578
|
isWeekend: isWeekend3,
|
|
4404
4579
|
businessDays,
|
|
@@ -4410,10 +4585,12 @@ var TaskListRow = React9.memo(
|
|
|
4410
4585
|
const editingName = editingColumnId === "name";
|
|
4411
4586
|
const editingDuration = editingColumnId === "duration";
|
|
4412
4587
|
const editingProgress = editingColumnId === "progress";
|
|
4588
|
+
const normalizedTask = useMemo7(() => normalizeTaskDatesForType(task), [task]);
|
|
4589
|
+
const isMilestone = useMemo7(() => isMilestoneTask(normalizedTask), [normalizedTask]);
|
|
4413
4590
|
const [nameValue, setNameValue] = useState4("");
|
|
4414
4591
|
const nameInputRef = useRef4(null);
|
|
4415
4592
|
const [durationValue, setDurationValue] = useState4(
|
|
4416
|
-
() => getInclusiveDurationDays(
|
|
4593
|
+
() => getInclusiveDurationDays(normalizedTask.startDate, normalizedTask.endDate)
|
|
4417
4594
|
);
|
|
4418
4595
|
const durationInputRef = useRef4(null);
|
|
4419
4596
|
const dependencySearchInputRef = useRef4(null);
|
|
@@ -4453,6 +4630,9 @@ var TaskListRow = React9.memo(
|
|
|
4453
4630
|
[businessDays, weekendPredicate]
|
|
4454
4631
|
);
|
|
4455
4632
|
const isCollapsed = collapsedParentIds.has(task.id);
|
|
4633
|
+
const getHierarchyLineColor = useCallback4((columnDepth) => {
|
|
4634
|
+
return columnDepth % 2 === 0 ? "var(--gantt-hierarchy-line-color)" : "#93c5fd";
|
|
4635
|
+
}, []);
|
|
4456
4636
|
const isPicking = selectingPredecessorFor != null;
|
|
4457
4637
|
const isSourceRow = isPicking && selectingPredecessorFor === task.id;
|
|
4458
4638
|
const [dependencySearchQuery, setDependencySearchQuery] = useState4("");
|
|
@@ -4614,14 +4794,14 @@ var TaskListRow = React9.memo(
|
|
|
4614
4794
|
e.stopPropagation();
|
|
4615
4795
|
durationConfirmedRef.current = false;
|
|
4616
4796
|
setDurationValue(
|
|
4617
|
-
getDuration(
|
|
4797
|
+
isMilestone ? 0 : getDuration(normalizedTask.startDate, normalizedTask.endDate)
|
|
4618
4798
|
);
|
|
4619
4799
|
setEditingColumnId("duration");
|
|
4620
4800
|
},
|
|
4621
|
-
[task.locked,
|
|
4801
|
+
[task.locked, normalizedTask.startDate, normalizedTask.endDate, getDuration, isMilestone]
|
|
4622
4802
|
);
|
|
4623
4803
|
const applyDurationChange = useCallback4((nextDuration) => {
|
|
4624
|
-
const normalizedDuration = Math.max(
|
|
4804
|
+
const normalizedDuration = Math.max(0, Math.round(nextDuration) || 0);
|
|
4625
4805
|
setDurationValue(normalizedDuration);
|
|
4626
4806
|
}, []);
|
|
4627
4807
|
const handleDurationSave = useCallback4(() => {
|
|
@@ -4629,19 +4809,26 @@ var TaskListRow = React9.memo(
|
|
|
4629
4809
|
durationConfirmedRef.current = false;
|
|
4630
4810
|
return;
|
|
4631
4811
|
}
|
|
4632
|
-
const
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
...task,
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4812
|
+
const rounded = Math.round(durationValue) || 0;
|
|
4813
|
+
if (isMilestone && rounded > 0) {
|
|
4814
|
+
onTasksChange?.([
|
|
4815
|
+
{ ...task, type: "task", endDate: getEndDate(task.startDate, rounded) }
|
|
4816
|
+
]);
|
|
4817
|
+
} else if (!isMilestone && rounded === 0) {
|
|
4818
|
+
onTasksChange?.([
|
|
4819
|
+
{ ...task, type: "milestone", endDate: task.startDate }
|
|
4820
|
+
]);
|
|
4821
|
+
} else if (!isMilestone && rounded > 0) {
|
|
4822
|
+
onTasksChange?.([
|
|
4823
|
+
{ ...task, endDate: getEndDate(task.startDate, rounded) }
|
|
4824
|
+
]);
|
|
4825
|
+
}
|
|
4639
4826
|
setEditingColumnId(null);
|
|
4640
|
-
}, [durationValue, task, onTasksChange, getEndDate]);
|
|
4827
|
+
}, [durationValue, task, onTasksChange, getEndDate, isMilestone]);
|
|
4641
4828
|
const handleDurationCancel = useCallback4(() => {
|
|
4642
|
-
setDurationValue(getDuration(
|
|
4829
|
+
setDurationValue(isMilestone ? 0 : getDuration(normalizedTask.startDate, normalizedTask.endDate));
|
|
4643
4830
|
setEditingColumnId(null);
|
|
4644
|
-
}, [
|
|
4831
|
+
}, [normalizedTask.startDate, normalizedTask.endDate, getDuration, isMilestone]);
|
|
4645
4832
|
const handleDurationAdjust = useCallback4(
|
|
4646
4833
|
(delta) => {
|
|
4647
4834
|
applyDurationChange(durationValue + delta);
|
|
@@ -4653,25 +4840,26 @@ var TaskListRow = React9.memo(
|
|
|
4653
4840
|
e.stopPropagation();
|
|
4654
4841
|
if (e.key === "Enter") {
|
|
4655
4842
|
durationConfirmedRef.current = true;
|
|
4656
|
-
const
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
endDate:
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4843
|
+
const rounded = Math.round(durationValue) || 0;
|
|
4844
|
+
if (isMilestone && rounded > 0) {
|
|
4845
|
+
onTasksChange?.([
|
|
4846
|
+
{ ...task, type: "task", endDate: getEndDate(task.startDate, rounded) }
|
|
4847
|
+
]);
|
|
4848
|
+
} else if (!isMilestone && rounded === 0) {
|
|
4849
|
+
onTasksChange?.([
|
|
4850
|
+
{ ...task, type: "milestone", endDate: task.startDate }
|
|
4851
|
+
]);
|
|
4852
|
+
} else if (!isMilestone && rounded > 0) {
|
|
4853
|
+
onTasksChange?.([
|
|
4854
|
+
{ ...task, endDate: getEndDate(task.startDate, rounded) }
|
|
4855
|
+
]);
|
|
4856
|
+
}
|
|
4669
4857
|
setEditingColumnId(null);
|
|
4670
4858
|
} else if (e.key === "Escape") {
|
|
4671
4859
|
handleDurationCancel();
|
|
4672
4860
|
}
|
|
4673
4861
|
},
|
|
4674
|
-
[durationValue, task, onTasksChange, handleDurationCancel, getEndDate]
|
|
4862
|
+
[durationValue, task, onTasksChange, handleDurationCancel, getEndDate, isMilestone]
|
|
4675
4863
|
);
|
|
4676
4864
|
const handleProgressClick = useCallback4(
|
|
4677
4865
|
(e) => {
|
|
@@ -4742,17 +4930,54 @@ var TaskListRow = React9.memo(
|
|
|
4742
4930
|
}
|
|
4743
4931
|
}, [editingProgress]);
|
|
4744
4932
|
useEffect4(() => {
|
|
4745
|
-
setDurationValue(getDuration(
|
|
4746
|
-
}, [
|
|
4933
|
+
setDurationValue(getDuration(normalizedTask.startDate, normalizedTask.endDate));
|
|
4934
|
+
}, [normalizedTask.startDate, normalizedTask.endDate, getDuration]);
|
|
4747
4935
|
useEffect4(() => {
|
|
4748
4936
|
if (editingDuration && durationInputRef.current) {
|
|
4749
4937
|
durationInputRef.current.focus();
|
|
4750
4938
|
durationInputRef.current.select();
|
|
4751
4939
|
}
|
|
4752
4940
|
}, [editingDuration]);
|
|
4941
|
+
const emitMilestoneDateChange = useCallback4((nextDateISO) => {
|
|
4942
|
+
const alignedDate = businessDays ? alignToWorkingDay(/* @__PURE__ */ new Date(`${nextDateISO}T00:00:00.000Z`), 1, weekendPredicate) : /* @__PURE__ */ new Date(`${nextDateISO}T00:00:00.000Z`);
|
|
4943
|
+
const clampedRange = clampTaskRangeForIncomingFS(
|
|
4944
|
+
task,
|
|
4945
|
+
alignedDate,
|
|
4946
|
+
alignedDate,
|
|
4947
|
+
allTasks,
|
|
4948
|
+
businessDays,
|
|
4949
|
+
weekendPredicate
|
|
4950
|
+
);
|
|
4951
|
+
const normalized = normalizeTaskDatesForType({
|
|
4952
|
+
...task,
|
|
4953
|
+
startDate: clampedRange.start.toISOString().split("T")[0],
|
|
4954
|
+
endDate: clampedRange.end.toISOString().split("T")[0]
|
|
4955
|
+
});
|
|
4956
|
+
const startDate = parseUTCDate(normalized.startDate);
|
|
4957
|
+
const endDate = parseUTCDate(normalized.endDate);
|
|
4958
|
+
onTasksChange?.([
|
|
4959
|
+
{
|
|
4960
|
+
...normalized,
|
|
4961
|
+
...task.dependencies && {
|
|
4962
|
+
dependencies: recalculateIncomingLags(
|
|
4963
|
+
task,
|
|
4964
|
+
startDate,
|
|
4965
|
+
endDate,
|
|
4966
|
+
allTasks,
|
|
4967
|
+
businessDays,
|
|
4968
|
+
weekendPredicate
|
|
4969
|
+
)
|
|
4970
|
+
}
|
|
4971
|
+
}
|
|
4972
|
+
]);
|
|
4973
|
+
}, [task, onTasksChange, allTasks, businessDays, weekendPredicate]);
|
|
4753
4974
|
const handleStartDateChange = useCallback4(
|
|
4754
4975
|
(newDateISO) => {
|
|
4755
4976
|
if (!newDateISO) return;
|
|
4977
|
+
if (isMilestone) {
|
|
4978
|
+
emitMilestoneDateChange(newDateISO);
|
|
4979
|
+
return;
|
|
4980
|
+
}
|
|
4756
4981
|
let nextEndISO;
|
|
4757
4982
|
const normalizedInputStart = businessDays ? alignToWorkingDay(/* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`), 1, weekendPredicate) : /* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`);
|
|
4758
4983
|
if (businessDays) {
|
|
@@ -4799,11 +5024,15 @@ var TaskListRow = React9.memo(
|
|
|
4799
5024
|
}
|
|
4800
5025
|
]);
|
|
4801
5026
|
},
|
|
4802
|
-
[task, onTasksChange, businessDays, getDuration, getEndDate, allTasks, weekendPredicate]
|
|
5027
|
+
[task, onTasksChange, businessDays, getDuration, getEndDate, allTasks, weekendPredicate, isMilestone, emitMilestoneDateChange]
|
|
4803
5028
|
);
|
|
4804
5029
|
const handleEndDateChange = useCallback4(
|
|
4805
5030
|
(newDateISO) => {
|
|
4806
5031
|
if (!newDateISO) return;
|
|
5032
|
+
if (isMilestone) {
|
|
5033
|
+
emitMilestoneDateChange(newDateISO);
|
|
5034
|
+
return;
|
|
5035
|
+
}
|
|
4807
5036
|
let nextStartISO;
|
|
4808
5037
|
const normalizedInputEnd = businessDays ? alignToWorkingDay(/* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`), -1, weekendPredicate) : /* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`);
|
|
4809
5038
|
if (businessDays) {
|
|
@@ -4850,7 +5079,7 @@ var TaskListRow = React9.memo(
|
|
|
4850
5079
|
}
|
|
4851
5080
|
]);
|
|
4852
5081
|
},
|
|
4853
|
-
[task, onTasksChange, businessDays, getDuration, weekendPredicate, allTasks]
|
|
5082
|
+
[task, onTasksChange, businessDays, getDuration, weekendPredicate, allTasks, isMilestone, emitMilestoneDateChange]
|
|
4854
5083
|
);
|
|
4855
5084
|
const handleRowClickInternal = useCallback4(() => {
|
|
4856
5085
|
onRowClick?.(task.id);
|
|
@@ -5121,8 +5350,8 @@ var TaskListRow = React9.memo(
|
|
|
5121
5350
|
},
|
|
5122
5351
|
[selectedChip?.successorId, selectedChip?.predecessorId, selectedChip?.linkType, onRemoveDependency, onChipSelect]
|
|
5123
5352
|
);
|
|
5124
|
-
const startDateISO = toISODate(
|
|
5125
|
-
const endDateISO = editingDuration ? getEndDate(
|
|
5353
|
+
const startDateISO = toISODate(normalizedTask.startDate);
|
|
5354
|
+
const endDateISO = editingDuration ? getEndDate(normalizedTask.startDate, durationValue) : toISODate(normalizedTask.endDate);
|
|
5126
5355
|
const numberCell = /* @__PURE__ */ jsxs9(
|
|
5127
5356
|
"div",
|
|
5128
5357
|
{
|
|
@@ -5152,23 +5381,41 @@ var TaskListRow = React9.memo(
|
|
|
5152
5381
|
const nameCell = /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
|
|
5153
5382
|
isChild && !editingName && /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
5154
5383
|
!isFilterHideMode && /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
5155
|
-
|
|
5156
|
-
(
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5384
|
+
ancestorLineModes.map(
|
|
5385
|
+
(mode, idx) => mode ? /* @__PURE__ */ jsxs9(React9.Fragment, { children: [
|
|
5386
|
+
/* @__PURE__ */ jsx12(
|
|
5387
|
+
"span",
|
|
5388
|
+
{
|
|
5389
|
+
"data-testid": `gantt-tl-ancestor-connector-${idx}`,
|
|
5390
|
+
style: {
|
|
5391
|
+
position: "absolute",
|
|
5392
|
+
left: `${idx * 20 + 9}px`,
|
|
5393
|
+
top: 0,
|
|
5394
|
+
height: mode === "half" ? `${rowHeight / 2}px` : `${rowHeight}px`,
|
|
5395
|
+
width: "1.5px",
|
|
5396
|
+
background: getHierarchyLineColor(idx),
|
|
5397
|
+
borderRadius: "1px",
|
|
5398
|
+
pointerEvents: "none"
|
|
5399
|
+
}
|
|
5168
5400
|
}
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5401
|
+
),
|
|
5402
|
+
mode === "half" && /* @__PURE__ */ jsx12(
|
|
5403
|
+
"span",
|
|
5404
|
+
{
|
|
5405
|
+
"data-testid": `gantt-tl-ancestor-connector-cap-${idx}`,
|
|
5406
|
+
style: {
|
|
5407
|
+
position: "absolute",
|
|
5408
|
+
left: `${idx * 20 + 9}px`,
|
|
5409
|
+
top: `${rowHeight / 2 - 0.75}px`,
|
|
5410
|
+
width: "5px",
|
|
5411
|
+
height: "1.5px",
|
|
5412
|
+
background: getHierarchyLineColor(idx),
|
|
5413
|
+
borderRadius: "1px",
|
|
5414
|
+
pointerEvents: "none"
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5417
|
+
)
|
|
5418
|
+
] }, idx) : null
|
|
5172
5419
|
),
|
|
5173
5420
|
nestingDepth > 0 && /* @__PURE__ */ jsx12(
|
|
5174
5421
|
"span",
|
|
@@ -5178,9 +5425,9 @@ var TaskListRow = React9.memo(
|
|
|
5178
5425
|
position: "absolute",
|
|
5179
5426
|
left: `${(nestingDepth - 1) * 20 + 9}px`,
|
|
5180
5427
|
top: 0,
|
|
5181
|
-
height: isLastChild ? `${rowHeight / 2}px` : `${rowHeight}px`,
|
|
5428
|
+
height: isLastChild && !hasVisibleChildren ? `${rowHeight / 2}px` : `${rowHeight}px`,
|
|
5182
5429
|
width: "1.5px",
|
|
5183
|
-
background:
|
|
5430
|
+
background: getHierarchyLineColor(nestingDepth - 1),
|
|
5184
5431
|
borderRadius: "1px",
|
|
5185
5432
|
pointerEvents: "none"
|
|
5186
5433
|
}
|
|
@@ -5195,7 +5442,7 @@ var TaskListRow = React9.memo(
|
|
|
5195
5442
|
top: `${rowHeight / 2 - 0.75}px`,
|
|
5196
5443
|
width: "8px",
|
|
5197
5444
|
height: "1.5px",
|
|
5198
|
-
background:
|
|
5445
|
+
background: getHierarchyLineColor(nestingDepth - 1),
|
|
5199
5446
|
borderRadius: "1px",
|
|
5200
5447
|
pointerEvents: "none"
|
|
5201
5448
|
}
|
|
@@ -5211,7 +5458,7 @@ var TaskListRow = React9.memo(
|
|
|
5211
5458
|
width: "4px",
|
|
5212
5459
|
height: "4px",
|
|
5213
5460
|
borderRadius: "50%",
|
|
5214
|
-
background:
|
|
5461
|
+
background: getHierarchyLineColor(nestingDepth - 1),
|
|
5215
5462
|
pointerEvents: "none"
|
|
5216
5463
|
}
|
|
5217
5464
|
}
|
|
@@ -5227,7 +5474,7 @@ var TaskListRow = React9.memo(
|
|
|
5227
5474
|
top: `${rowHeight / 2 + 7}px`,
|
|
5228
5475
|
height: `${rowHeight / 2 - 7}px`,
|
|
5229
5476
|
width: "1.5px",
|
|
5230
|
-
background:
|
|
5477
|
+
background: getHierarchyLineColor(nestingDepth),
|
|
5231
5478
|
borderRadius: "1px",
|
|
5232
5479
|
pointerEvents: "none"
|
|
5233
5480
|
}
|
|
@@ -5257,7 +5504,7 @@ var TaskListRow = React9.memo(
|
|
|
5257
5504
|
top: `${rowHeight / 2 + 7}px`,
|
|
5258
5505
|
height: `${rowHeight / 2 - 7}px`,
|
|
5259
5506
|
width: "1.5px",
|
|
5260
|
-
background:
|
|
5507
|
+
background: getHierarchyLineColor(nestingDepth),
|
|
5261
5508
|
borderRadius: "1px",
|
|
5262
5509
|
pointerEvents: "none"
|
|
5263
5510
|
}
|
|
@@ -5528,10 +5775,10 @@ var TaskListRow = React9.memo(
|
|
|
5528
5775
|
{
|
|
5529
5776
|
ref: durationInputRef,
|
|
5530
5777
|
type: "number",
|
|
5531
|
-
min:
|
|
5778
|
+
min: 0,
|
|
5532
5779
|
step: 1,
|
|
5533
5780
|
value: durationValue,
|
|
5534
|
-
onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) ||
|
|
5781
|
+
onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) || 0),
|
|
5535
5782
|
onBlur: handleDurationSave,
|
|
5536
5783
|
onKeyDown: handleDurationKeyDown,
|
|
5537
5784
|
className: "gantt-tl-number-input"
|
|
@@ -5592,14 +5839,11 @@ var TaskListRow = React9.memo(
|
|
|
5592
5839
|
]
|
|
5593
5840
|
}
|
|
5594
5841
|
),
|
|
5595
|
-
/* @__PURE__ */
|
|
5842
|
+
/* @__PURE__ */ jsx12(
|
|
5596
5843
|
"span",
|
|
5597
5844
|
{
|
|
5598
5845
|
style: editingDuration ? { visibility: "hidden", pointerEvents: "none" } : void 0,
|
|
5599
|
-
children:
|
|
5600
|
-
getDuration(task.startDate, task.endDate),
|
|
5601
|
-
"\u0434"
|
|
5602
|
-
]
|
|
5846
|
+
children: isMilestone ? "\u25C6" : `${getDuration(normalizedTask.startDate, normalizedTask.endDate)}\u0434`
|
|
5603
5847
|
}
|
|
5604
5848
|
)
|
|
5605
5849
|
]
|
|
@@ -6247,20 +6491,41 @@ var TaskList = ({
|
|
|
6247
6491
|
}
|
|
6248
6492
|
return last;
|
|
6249
6493
|
}, [visibleTasks]);
|
|
6250
|
-
const
|
|
6494
|
+
const visibleParentIds = useMemo8(() => {
|
|
6495
|
+
const parentIds = /* @__PURE__ */ new Set();
|
|
6496
|
+
for (const task of visibleTasks) {
|
|
6497
|
+
if (task.parentId) parentIds.add(task.parentId);
|
|
6498
|
+
}
|
|
6499
|
+
return parentIds;
|
|
6500
|
+
}, [visibleTasks]);
|
|
6501
|
+
const ancestorLineModesMap = useMemo8(() => {
|
|
6251
6502
|
const taskById = new Map(tasks.map((t) => [t.id, t]));
|
|
6503
|
+
const isDescendantOf = (taskId, ancestorId) => {
|
|
6504
|
+
let current = taskById.get(taskId);
|
|
6505
|
+
while (current?.parentId && taskById.has(current.parentId)) {
|
|
6506
|
+
if (current.parentId === ancestorId) return true;
|
|
6507
|
+
current = taskById.get(current.parentId);
|
|
6508
|
+
}
|
|
6509
|
+
return false;
|
|
6510
|
+
};
|
|
6252
6511
|
const map = /* @__PURE__ */ new Map();
|
|
6253
|
-
for (
|
|
6254
|
-
const
|
|
6512
|
+
for (let index = 0; index < visibleTasks.length; index++) {
|
|
6513
|
+
const task = visibleTasks[index];
|
|
6514
|
+
const ancestorIds = [];
|
|
6255
6515
|
let current = taskById.get(task.id);
|
|
6256
6516
|
while (current?.parentId && taskById.has(current.parentId)) {
|
|
6257
|
-
|
|
6517
|
+
ancestorIds.unshift(current.parentId);
|
|
6258
6518
|
current = taskById.get(current.parentId);
|
|
6259
6519
|
}
|
|
6260
|
-
|
|
6520
|
+
const ancestorsAboveParent = ancestorIds.slice(0, -1);
|
|
6521
|
+
const modes = ancestorsAboveParent.map((ancestorId) => {
|
|
6522
|
+
const hasLaterVisibleDescendant = visibleTasks.slice(index + 1).some((laterTask) => isDescendantOf(laterTask.id, ancestorId));
|
|
6523
|
+
return hasLaterVisibleDescendant ? "full" : "half";
|
|
6524
|
+
});
|
|
6525
|
+
map.set(task.id, modes);
|
|
6261
6526
|
}
|
|
6262
6527
|
return map;
|
|
6263
|
-
}, [tasks, visibleTasks
|
|
6528
|
+
}, [tasks, visibleTasks]);
|
|
6264
6529
|
const handleRowClick = useCallback5((taskId) => {
|
|
6265
6530
|
onTaskSelect?.(taskId);
|
|
6266
6531
|
}, [onTaskSelect]);
|
|
@@ -6805,7 +7070,8 @@ var TaskList = ({
|
|
|
6805
7070
|
canDemoteTask,
|
|
6806
7071
|
isLastChild: lastChildIds.has(task.id),
|
|
6807
7072
|
nestingDepth: nestingDepthMap.get(task.id) ?? 0,
|
|
6808
|
-
|
|
7073
|
+
hasVisibleChildren: visibleParentIds.has(task.id),
|
|
7074
|
+
ancestorLineModes: ancestorLineModesMap.get(task.id) ?? [],
|
|
6809
7075
|
customDays,
|
|
6810
7076
|
isWeekend: isWeekend3,
|
|
6811
7077
|
businessDays,
|
|
@@ -7543,6 +7809,8 @@ export {
|
|
|
7543
7809
|
calculateDependencyPath,
|
|
7544
7810
|
calculateGridLines,
|
|
7545
7811
|
calculateGridWidth,
|
|
7812
|
+
calculateMilestoneConnectionBounds,
|
|
7813
|
+
calculateMilestoneGeometry,
|
|
7546
7814
|
calculateMonthGridLines,
|
|
7547
7815
|
calculateOrthogonalPath,
|
|
7548
7816
|
calculateSuccessorDate,
|
|
@@ -7594,6 +7862,7 @@ export {
|
|
|
7594
7862
|
nameContains,
|
|
7595
7863
|
normalizeDependencyLag,
|
|
7596
7864
|
normalizeHierarchyTasks,
|
|
7865
|
+
normalizePredecessorDates,
|
|
7597
7866
|
normalizeTaskDates,
|
|
7598
7867
|
normalizeUTCDate,
|
|
7599
7868
|
not,
|
|
@@ -7609,6 +7878,7 @@ export {
|
|
|
7609
7878
|
removeDependenciesBetweenTasks,
|
|
7610
7879
|
resizeTaskWithCascade,
|
|
7611
7880
|
resolveDateRangeFromPixels,
|
|
7881
|
+
resolveTaskHorizontalGeometry,
|
|
7612
7882
|
shiftBusinessDayOffset,
|
|
7613
7883
|
subtractBusinessDays2 as subtractBusinessDays,
|
|
7614
7884
|
universalCascade,
|