gantt-task-react-v 1.3.6 → 1.4.1
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/gantt-task-react.es.js +271 -77
- package/dist/gantt-task-react.umd.js +271 -77
- package/dist/types/public-types.d.ts +10 -0
- package/package.json +1 -1
|
@@ -4688,9 +4688,9 @@ const getStartAndEnd = (containerEl, property, cellSize) => {
|
|
|
4688
4688
|
const scrollValue = property === "scrollLeft" ? el.scrollLeft : el.scrollTop;
|
|
4689
4689
|
const maxScrollValue = property === "scrollLeft" ? el.scrollWidth : el.scrollHeight;
|
|
4690
4690
|
const fullValue = property === "scrollLeft" ? el.clientWidth : el.clientHeight;
|
|
4691
|
-
const firstIndex = Math.max(0, Math.floor(scrollValue / cellSize));
|
|
4692
4691
|
const visibleCount = Math.max(1, Math.ceil(fullValue / cellSize));
|
|
4693
4692
|
const overscan = Math.min(100, Math.max(10, Math.ceil(visibleCount * 0.5)));
|
|
4693
|
+
const firstIndex = Math.max(0, Math.floor(scrollValue / cellSize) - overscan);
|
|
4694
4694
|
const lastIndex = Math.floor((scrollValue + fullValue) / cellSize) + overscan;
|
|
4695
4695
|
const isStartOfScroll = scrollValue < DELTA;
|
|
4696
4696
|
const isEndOfScroll = scrollValue + fullValue > maxScrollValue - DELTA;
|
|
@@ -5536,6 +5536,37 @@ const TaskListTableHeadersDefaultInner = ({
|
|
|
5536
5536
|
canMoveTasks,
|
|
5537
5537
|
onColumnResizeStart
|
|
5538
5538
|
}) => {
|
|
5539
|
+
const pinnedStyles = useMemo(() => {
|
|
5540
|
+
const result = {};
|
|
5541
|
+
let leftOffset = 0;
|
|
5542
|
+
if (canMoveTasks) {
|
|
5543
|
+
leftOffset = 24;
|
|
5544
|
+
}
|
|
5545
|
+
for (let i = 0; i < columns.length; i++) {
|
|
5546
|
+
if (columns[i].pinned === "left") {
|
|
5547
|
+
result[i] = {
|
|
5548
|
+
position: "sticky",
|
|
5549
|
+
left: leftOffset,
|
|
5550
|
+
zIndex: 2,
|
|
5551
|
+
backgroundColor: "var(--gantt-table-header-background-color, #fff)"
|
|
5552
|
+
};
|
|
5553
|
+
leftOffset += columns[i].width;
|
|
5554
|
+
}
|
|
5555
|
+
}
|
|
5556
|
+
let rightOffset = 0;
|
|
5557
|
+
for (let i = columns.length - 1; i >= 0; i--) {
|
|
5558
|
+
if (columns[i].pinned === "right") {
|
|
5559
|
+
result[i] = {
|
|
5560
|
+
position: "sticky",
|
|
5561
|
+
right: rightOffset,
|
|
5562
|
+
zIndex: 2,
|
|
5563
|
+
backgroundColor: "var(--gantt-table-header-background-color, #fff)"
|
|
5564
|
+
};
|
|
5565
|
+
rightOffset += columns[i].width;
|
|
5566
|
+
}
|
|
5567
|
+
}
|
|
5568
|
+
return result;
|
|
5569
|
+
}, [columns, canMoveTasks]);
|
|
5539
5570
|
return /* @__PURE__ */ jsx(
|
|
5540
5571
|
"div",
|
|
5541
5572
|
{
|
|
@@ -5572,7 +5603,8 @@ const TaskListTableHeadersDefaultInner = ({
|
|
|
5572
5603
|
className: styles$h.ganttTable_HeaderItem,
|
|
5573
5604
|
style: {
|
|
5574
5605
|
minWidth: width,
|
|
5575
|
-
maxWidth: width
|
|
5606
|
+
maxWidth: width,
|
|
5607
|
+
...pinnedStyles[index2]
|
|
5576
5608
|
},
|
|
5577
5609
|
children: [
|
|
5578
5610
|
title,
|
|
@@ -10135,6 +10167,37 @@ const TaskListTableRowInner = forwardRef(
|
|
|
10135
10167
|
}
|
|
10136
10168
|
return classNames.join(" ");
|
|
10137
10169
|
}, [isCut2, moveOverPosition, isOverlay2, isDragging]);
|
|
10170
|
+
const pinnedStyles = useMemo(() => {
|
|
10171
|
+
const result = {};
|
|
10172
|
+
let leftOffset = 0;
|
|
10173
|
+
if (moveHandleProps || !isOverlay2 && task.type !== "project" && task.id !== "no-project-asigned") {
|
|
10174
|
+
leftOffset = 24;
|
|
10175
|
+
}
|
|
10176
|
+
for (let i = 0; i < columns.length; i++) {
|
|
10177
|
+
if (columns[i].pinned === "left") {
|
|
10178
|
+
result[i] = {
|
|
10179
|
+
position: "sticky",
|
|
10180
|
+
left: leftOffset,
|
|
10181
|
+
zIndex: 1,
|
|
10182
|
+
backgroundColor: "inherit"
|
|
10183
|
+
};
|
|
10184
|
+
leftOffset += columns[i].width;
|
|
10185
|
+
}
|
|
10186
|
+
}
|
|
10187
|
+
let rightOffset = 0;
|
|
10188
|
+
for (let i = columns.length - 1; i >= 0; i--) {
|
|
10189
|
+
if (columns[i].pinned === "right") {
|
|
10190
|
+
result[i] = {
|
|
10191
|
+
position: "sticky",
|
|
10192
|
+
right: rightOffset,
|
|
10193
|
+
zIndex: 1,
|
|
10194
|
+
backgroundColor: "inherit"
|
|
10195
|
+
};
|
|
10196
|
+
rightOffset += columns[i].width;
|
|
10197
|
+
}
|
|
10198
|
+
}
|
|
10199
|
+
return result;
|
|
10200
|
+
}, [columns, moveHandleProps, isOverlay2, task.type, task.id]);
|
|
10138
10201
|
return /* @__PURE__ */ jsxs(
|
|
10139
10202
|
"div",
|
|
10140
10203
|
{
|
|
@@ -10156,7 +10219,8 @@ const TaskListTableRowInner = forwardRef(
|
|
|
10156
10219
|
className: styles$f.taskListCell,
|
|
10157
10220
|
style: {
|
|
10158
10221
|
minWidth: width,
|
|
10159
|
-
maxWidth: width
|
|
10222
|
+
maxWidth: width,
|
|
10223
|
+
...pinnedStyles[index2]
|
|
10160
10224
|
},
|
|
10161
10225
|
children: /* @__PURE__ */ jsx(Component, { data: columnData })
|
|
10162
10226
|
},
|
|
@@ -13062,6 +13126,12 @@ const TaskGanttContentInner = (props) => {
|
|
|
13062
13126
|
const tasksRes = [];
|
|
13063
13127
|
const arrowsRes = [];
|
|
13064
13128
|
const selectedTasksRes = [];
|
|
13129
|
+
const taskById = /* @__PURE__ */ new Map();
|
|
13130
|
+
mapGlobalRowIndexToTask.forEach((task) => {
|
|
13131
|
+
if (task.type !== "empty") {
|
|
13132
|
+
taskById.set(task.id, task);
|
|
13133
|
+
}
|
|
13134
|
+
});
|
|
13065
13135
|
const addedSelectedTasks = {};
|
|
13066
13136
|
const addedDependencies = {};
|
|
13067
13137
|
for (let index2 = start; index2 <= end; ++index2) {
|
|
@@ -13115,19 +13185,73 @@ const TaskGanttContentInner = (props) => {
|
|
|
13115
13185
|
const safeProgressWidth = isNaN(progressWidth) || !isFinite(progressWidth) ? 0 : Math.max(progressWidth, 0);
|
|
13116
13186
|
const safeInnerX1 = isNaN(innerX1) || !isFinite(innerX1) ? 0 : innerX1;
|
|
13117
13187
|
const safeInnerX2 = isNaN(innerX2) || !isFinite(innerX2) ? safeInnerX1 + safeWidth : innerX2;
|
|
13118
|
-
|
|
13188
|
+
tasksRes.push(
|
|
13189
|
+
/* @__PURE__ */ jsx(
|
|
13190
|
+
"svg",
|
|
13191
|
+
{
|
|
13192
|
+
id: task.id,
|
|
13193
|
+
className: `${styles$4.TaskItemWrapper} TaskItemWrapper`,
|
|
13194
|
+
x: Math.max(safeContainerX + (additionalLeftSpace || 0), 0),
|
|
13195
|
+
y: safeLevelY,
|
|
13196
|
+
width: Math.max(safeContainerWidth, 0),
|
|
13197
|
+
height: fullRowHeight,
|
|
13198
|
+
children: /* @__PURE__ */ jsx(
|
|
13199
|
+
TaskItem,
|
|
13200
|
+
{
|
|
13201
|
+
movingAction: taskBarMovingAction(task),
|
|
13202
|
+
allowMoveTaskBar,
|
|
13203
|
+
hasChildren: checkHasChildren(task, childTasksMap),
|
|
13204
|
+
progressWidth: safeProgressWidth,
|
|
13205
|
+
progressX: rtl ? safeInnerX2 : safeInnerX1,
|
|
13206
|
+
onSelectTaskOnMouseDown: selectTaskOnMouseDown,
|
|
13207
|
+
task,
|
|
13208
|
+
taskYOffset,
|
|
13209
|
+
width: safeWidth,
|
|
13210
|
+
x1: safeInnerX1,
|
|
13211
|
+
x2: safeInnerX2,
|
|
13212
|
+
distances,
|
|
13213
|
+
taskHeight,
|
|
13214
|
+
taskHalfHeight,
|
|
13215
|
+
isProgressChangeable: (t) => isProgressChangeable(t) && !waitCommitTasks,
|
|
13216
|
+
isDateChangeable: (t) => isDateChangeable(t) && !waitCommitTasks,
|
|
13217
|
+
isRelationChangeable: (t) => isRelationChangeable(t) && !waitCommitTasks,
|
|
13218
|
+
authorizedRelations,
|
|
13219
|
+
ganttRelationEvent,
|
|
13220
|
+
canDelete: !task.isDisabled && !waitCommitTasks,
|
|
13221
|
+
onDoubleClick,
|
|
13222
|
+
onClick,
|
|
13223
|
+
onEventStart: onTaskBarDragStart,
|
|
13224
|
+
onTooltipTask,
|
|
13225
|
+
onRelationStart: onTaskBarRelationStart,
|
|
13226
|
+
isSelected: Boolean(selectedIdsMirror[taskId]),
|
|
13227
|
+
isCritical,
|
|
13228
|
+
rtl,
|
|
13229
|
+
onDeleteTask,
|
|
13230
|
+
renderCustomLabel,
|
|
13231
|
+
viewMode,
|
|
13232
|
+
showProgress,
|
|
13233
|
+
progressColor
|
|
13234
|
+
}
|
|
13235
|
+
)
|
|
13236
|
+
},
|
|
13237
|
+
key2
|
|
13238
|
+
)
|
|
13239
|
+
);
|
|
13119
13240
|
if (task.comparisonDates && comparisonDates) {
|
|
13120
13241
|
const safeComparisonX = isNaN(comparisonDates.x) || !isFinite(comparisonDates.x) ? 0 : comparisonDates.x;
|
|
13121
|
-
const
|
|
13122
|
-
const
|
|
13123
|
-
const
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
comparisonBarElement = /* @__PURE__ */ jsx(
|
|
13128
|
-
"g",
|
|
13242
|
+
const safeComparisonY = isNaN(comparisonDates.y) || !isFinite(comparisonDates.y) ? safeLevelY : comparisonDates.y;
|
|
13243
|
+
const safeComparisonWidth = isNaN(comparisonDates.width) || !isFinite(comparisonDates.width) ? 0 : Math.max(comparisonDates.width, 0);
|
|
13244
|
+
const safeComparisonHeight = isNaN(comparisonDates.height) || !isFinite(comparisonDates.height) ? 0 : Math.max(comparisonDates.height, 0);
|
|
13245
|
+
tasksRes.push(
|
|
13246
|
+
/* @__PURE__ */ jsx(
|
|
13247
|
+
"svg",
|
|
13129
13248
|
{
|
|
13130
|
-
|
|
13249
|
+
id: task.id + "_comparison",
|
|
13250
|
+
className: "TaskItemWrapperComparison",
|
|
13251
|
+
x: Math.max(safeComparisonX + (additionalLeftSpace || 0), 0),
|
|
13252
|
+
y: safeComparisonY,
|
|
13253
|
+
width: safeComparisonWidth,
|
|
13254
|
+
height: safeComparisonHeight * 2,
|
|
13131
13255
|
children: /* @__PURE__ */ jsx(
|
|
13132
13256
|
BarComparison,
|
|
13133
13257
|
{
|
|
@@ -13139,70 +13263,16 @@ const TaskGanttContentInner = (props) => {
|
|
|
13139
13263
|
height: safeComparisonHeight,
|
|
13140
13264
|
width: safeComparisonWidth,
|
|
13141
13265
|
borderHeight: distances.barComparisonTaskBorderHeight,
|
|
13142
|
-
yOffset:
|
|
13266
|
+
yOffset: distances.barComparisonTaskYOffset,
|
|
13143
13267
|
task,
|
|
13144
13268
|
onTooltipTask
|
|
13145
13269
|
}
|
|
13146
13270
|
)
|
|
13147
|
-
}
|
|
13148
|
-
|
|
13149
|
-
|
|
13271
|
+
},
|
|
13272
|
+
key2 + "_comparison"
|
|
13273
|
+
)
|
|
13274
|
+
);
|
|
13150
13275
|
}
|
|
13151
|
-
tasksRes.push(
|
|
13152
|
-
/* @__PURE__ */ jsxs(
|
|
13153
|
-
"svg",
|
|
13154
|
-
{
|
|
13155
|
-
id: task.id,
|
|
13156
|
-
className: `${styles$4.TaskItemWrapper} TaskItemWrapper`,
|
|
13157
|
-
x: Math.max(safeContainerX + (additionalLeftSpace || 0), 0),
|
|
13158
|
-
y: safeLevelY,
|
|
13159
|
-
width: Math.max(safeContainerWidth, 0),
|
|
13160
|
-
height: fullRowHeight,
|
|
13161
|
-
children: [
|
|
13162
|
-
/* @__PURE__ */ jsx(
|
|
13163
|
-
TaskItem,
|
|
13164
|
-
{
|
|
13165
|
-
movingAction: taskBarMovingAction(task),
|
|
13166
|
-
allowMoveTaskBar,
|
|
13167
|
-
hasChildren: checkHasChildren(task, childTasksMap),
|
|
13168
|
-
progressWidth: safeProgressWidth,
|
|
13169
|
-
progressX: rtl ? safeInnerX2 : safeInnerX1,
|
|
13170
|
-
onSelectTaskOnMouseDown: selectTaskOnMouseDown,
|
|
13171
|
-
task,
|
|
13172
|
-
taskYOffset,
|
|
13173
|
-
width: safeWidth,
|
|
13174
|
-
x1: safeInnerX1,
|
|
13175
|
-
x2: safeInnerX2,
|
|
13176
|
-
distances,
|
|
13177
|
-
taskHeight,
|
|
13178
|
-
taskHalfHeight,
|
|
13179
|
-
isProgressChangeable: (t) => isProgressChangeable(t) && !waitCommitTasks,
|
|
13180
|
-
isDateChangeable: (t) => isDateChangeable(t) && !waitCommitTasks,
|
|
13181
|
-
isRelationChangeable: (t) => isRelationChangeable(t) && !waitCommitTasks,
|
|
13182
|
-
authorizedRelations,
|
|
13183
|
-
ganttRelationEvent,
|
|
13184
|
-
canDelete: !task.isDisabled && !waitCommitTasks,
|
|
13185
|
-
onDoubleClick,
|
|
13186
|
-
onClick,
|
|
13187
|
-
onEventStart: onTaskBarDragStart,
|
|
13188
|
-
onTooltipTask,
|
|
13189
|
-
onRelationStart: onTaskBarRelationStart,
|
|
13190
|
-
isSelected: Boolean(selectedIdsMirror[taskId]),
|
|
13191
|
-
isCritical,
|
|
13192
|
-
rtl,
|
|
13193
|
-
onDeleteTask,
|
|
13194
|
-
renderCustomLabel,
|
|
13195
|
-
viewMode,
|
|
13196
|
-
showProgress,
|
|
13197
|
-
progressColor
|
|
13198
|
-
}
|
|
13199
|
-
),
|
|
13200
|
-
comparisonBarElement
|
|
13201
|
-
]
|
|
13202
|
-
},
|
|
13203
|
-
key2
|
|
13204
|
-
)
|
|
13205
|
-
);
|
|
13206
13276
|
const addedDependenciesAtLevel = addedDependencies[comparisonLevel] || {};
|
|
13207
13277
|
if (!addedDependencies[comparisonLevel]) {
|
|
13208
13278
|
addedDependencies[comparisonLevel] = addedDependenciesAtLevel;
|
|
@@ -13356,6 +13426,93 @@ const TaskGanttContentInner = (props) => {
|
|
|
13356
13426
|
);
|
|
13357
13427
|
}
|
|
13358
13428
|
}
|
|
13429
|
+
const renderedTop = start * fullRowHeight;
|
|
13430
|
+
const renderedBottom = (end + 1) * fullRowHeight;
|
|
13431
|
+
for (const [comparisonLevel, dependenciesByLevel] of dependencyMap) {
|
|
13432
|
+
let addedDependenciesAtLevel = addedDependencies[comparisonLevel];
|
|
13433
|
+
if (!addedDependenciesAtLevel) {
|
|
13434
|
+
addedDependenciesAtLevel = {};
|
|
13435
|
+
addedDependencies[comparisonLevel] = addedDependenciesAtLevel;
|
|
13436
|
+
}
|
|
13437
|
+
const criticalPathOnLevel = criticalPaths ? criticalPaths.get(comparisonLevel) : void 0;
|
|
13438
|
+
for (const [taskId, dependencies] of dependenciesByLevel) {
|
|
13439
|
+
let addedDependenciesAtTask = addedDependenciesAtLevel[taskId];
|
|
13440
|
+
if (!addedDependenciesAtTask) {
|
|
13441
|
+
addedDependenciesAtTask = {};
|
|
13442
|
+
addedDependenciesAtLevel[taskId] = addedDependenciesAtTask;
|
|
13443
|
+
}
|
|
13444
|
+
const targetTask = taskById.get(taskId);
|
|
13445
|
+
if (!targetTask)
|
|
13446
|
+
continue;
|
|
13447
|
+
const criticalPathForTask = criticalPathOnLevel ? criticalPathOnLevel.dependencies.get(taskId) : void 0;
|
|
13448
|
+
dependencies.filter(({ source }) => {
|
|
13449
|
+
if (addedDependenciesAtTask[source.id])
|
|
13450
|
+
return false;
|
|
13451
|
+
if (!visibleTasksMirror[source.id])
|
|
13452
|
+
return false;
|
|
13453
|
+
return true;
|
|
13454
|
+
}).forEach(
|
|
13455
|
+
({
|
|
13456
|
+
containerHeight,
|
|
13457
|
+
containerY,
|
|
13458
|
+
innerFromY,
|
|
13459
|
+
innerToY,
|
|
13460
|
+
ownTarget,
|
|
13461
|
+
source,
|
|
13462
|
+
sourceTarget
|
|
13463
|
+
}) => {
|
|
13464
|
+
if (containerY + containerHeight < renderedTop || containerY > renderedBottom) {
|
|
13465
|
+
return;
|
|
13466
|
+
}
|
|
13467
|
+
addedDependenciesAtTask[source.id] = true;
|
|
13468
|
+
const isCritical = criticalPathForTask ? criticalPathForTask.has(source.id) : false;
|
|
13469
|
+
const { x1: fromX1, x2: fromX2 } = getTaskCoordinates2(source);
|
|
13470
|
+
const { x1: targetX1, x2: targetX2 } = getTaskCoordinates2(targetTask);
|
|
13471
|
+
const safeFromX1 = isNaN(fromX1) || !isFinite(fromX1) ? 0 : fromX1;
|
|
13472
|
+
const safeFromX2 = isNaN(fromX2) || !isFinite(fromX2) ? safeFromX1 + 10 : fromX2;
|
|
13473
|
+
const safeTargetX1 = isNaN(targetX1) || !isFinite(targetX1) ? 0 : targetX1;
|
|
13474
|
+
const safeTargetX2 = isNaN(targetX2) || !isFinite(targetX2) ? safeTargetX1 + 10 : targetX2;
|
|
13475
|
+
const cX = Math.min(safeFromX1, safeTargetX1) - DELTA_RELATION_WIDTH;
|
|
13476
|
+
const cW = Math.max(safeFromX2, safeTargetX2) - cX + DELTA_RELATION_WIDTH;
|
|
13477
|
+
const safeCX = isNaN(cX) || !isFinite(cX) ? 0 : cX;
|
|
13478
|
+
const safeCW = isNaN(cW) || !isFinite(cW) ? 100 : Math.max(cW, 0);
|
|
13479
|
+
arrowsRes.push(
|
|
13480
|
+
/* @__PURE__ */ jsx(
|
|
13481
|
+
"svg",
|
|
13482
|
+
{
|
|
13483
|
+
x: Math.max(safeCX + (additionalLeftSpace || 0), 0),
|
|
13484
|
+
y: containerY,
|
|
13485
|
+
width: safeCW,
|
|
13486
|
+
height: containerHeight,
|
|
13487
|
+
children: /* @__PURE__ */ jsx(
|
|
13488
|
+
Arrow,
|
|
13489
|
+
{
|
|
13490
|
+
distances,
|
|
13491
|
+
taskFrom: source,
|
|
13492
|
+
targetFrom: sourceTarget,
|
|
13493
|
+
fromX1: safeFromX1 - safeCX,
|
|
13494
|
+
fromX2: safeFromX2 - safeCX,
|
|
13495
|
+
fromY: innerFromY,
|
|
13496
|
+
taskTo: targetTask,
|
|
13497
|
+
targetTo: ownTarget,
|
|
13498
|
+
toX1: safeTargetX1 - safeCX,
|
|
13499
|
+
toX2: safeTargetX2 - safeCX,
|
|
13500
|
+
toY: innerToY,
|
|
13501
|
+
fullRowHeight,
|
|
13502
|
+
taskHeight,
|
|
13503
|
+
isCritical,
|
|
13504
|
+
rtl,
|
|
13505
|
+
onArrowDoubleClick
|
|
13506
|
+
}
|
|
13507
|
+
)
|
|
13508
|
+
},
|
|
13509
|
+
`Arrow from ${source.id} to ${taskId} on ${comparisonLevel}`
|
|
13510
|
+
)
|
|
13511
|
+
);
|
|
13512
|
+
}
|
|
13513
|
+
);
|
|
13514
|
+
}
|
|
13515
|
+
}
|
|
13359
13516
|
return [tasksRes, arrowsRes, selectedTasksRes];
|
|
13360
13517
|
}, [
|
|
13361
13518
|
viewMode,
|
|
@@ -13860,12 +14017,10 @@ const countTaskCoordinates = (task, taskToRowIndexMap, startDate, viewMode, rtl,
|
|
|
13860
14017
|
);
|
|
13861
14018
|
cx1 = isNaN(cx1) || !isFinite(cx1) ? x1 : cx1;
|
|
13862
14019
|
cx2 = isNaN(cx2) || !isFinite(cx2) ? x2 : cx2;
|
|
13863
|
-
const comparisonWidth = Math.max(Math.abs(cx2 - cx1), 3);
|
|
13864
|
-
const comparisonX = Math.min(cx1, cx2);
|
|
13865
14020
|
comparisonDates = {
|
|
13866
|
-
x:
|
|
14021
|
+
x: cx1,
|
|
13867
14022
|
y: y + taskHeight,
|
|
13868
|
-
width:
|
|
14023
|
+
width: Math.max(cx2 - cx1, 0),
|
|
13869
14024
|
height: barComparisonTaskHeight
|
|
13870
14025
|
};
|
|
13871
14026
|
}
|
|
@@ -19059,7 +19214,8 @@ const Gantt = (props) => {
|
|
|
19059
19214
|
todayLabel = "Today",
|
|
19060
19215
|
dataDateLabel = "Data Date",
|
|
19061
19216
|
showProgress = true,
|
|
19062
|
-
progressColor
|
|
19217
|
+
progressColor,
|
|
19218
|
+
scrollToTaskId
|
|
19063
19219
|
} = props;
|
|
19064
19220
|
const ganttSVGRef = useRef(null);
|
|
19065
19221
|
const wrapperRef = useRef(null);
|
|
@@ -19367,6 +19523,44 @@ const Gantt = (props) => {
|
|
|
19367
19523
|
},
|
|
19368
19524
|
[mapTaskToCoordinates, setScrollXProgrammatically]
|
|
19369
19525
|
);
|
|
19526
|
+
const prevScrollToTaskIdRef = useRef(void 0);
|
|
19527
|
+
useEffect(() => {
|
|
19528
|
+
if (!scrollToTaskId || scrollToTaskId === prevScrollToTaskIdRef.current) {
|
|
19529
|
+
return;
|
|
19530
|
+
}
|
|
19531
|
+
prevScrollToTaskIdRef.current = scrollToTaskId;
|
|
19532
|
+
for (const [comparisonLevel, levelMap] of tasksMap) {
|
|
19533
|
+
const task = levelMap.get(scrollToTaskId);
|
|
19534
|
+
if (!task || task.type === "empty") {
|
|
19535
|
+
continue;
|
|
19536
|
+
}
|
|
19537
|
+
const { x1 } = getTaskCoordinates(task, mapTaskToCoordinates);
|
|
19538
|
+
setScrollXProgrammatically(Math.max(0, x1 - 100));
|
|
19539
|
+
const rowIndexMap = taskToRowIndexMap.get(comparisonLevel);
|
|
19540
|
+
if (rowIndexMap) {
|
|
19541
|
+
const rowIndex = rowIndexMap.get(scrollToTaskId);
|
|
19542
|
+
if (typeof rowIndex === "number") {
|
|
19543
|
+
const targetScrollY = rowIndex * fullRowHeight - ganttHeight / 2 + fullRowHeight / 2;
|
|
19544
|
+
setScrollYProgrammatically(
|
|
19545
|
+
Math.max(0, Math.min(targetScrollY, ganttFullHeight - ganttHeight))
|
|
19546
|
+
);
|
|
19547
|
+
}
|
|
19548
|
+
}
|
|
19549
|
+
selectTask(scrollToTaskId);
|
|
19550
|
+
break;
|
|
19551
|
+
}
|
|
19552
|
+
}, [
|
|
19553
|
+
scrollToTaskId,
|
|
19554
|
+
tasksMap,
|
|
19555
|
+
mapTaskToCoordinates,
|
|
19556
|
+
taskToRowIndexMap,
|
|
19557
|
+
fullRowHeight,
|
|
19558
|
+
ganttHeight,
|
|
19559
|
+
ganttFullHeight,
|
|
19560
|
+
setScrollXProgrammatically,
|
|
19561
|
+
setScrollYProgrammatically,
|
|
19562
|
+
selectTask
|
|
19563
|
+
]);
|
|
19370
19564
|
const { contextMenu, handleCloseContextMenu, handleOpenContextMenu } = useContextMenu(wrapperRef, scrollToTask);
|
|
19371
19565
|
const [ganttContextMenu, setGanttContextMenu] = useState({
|
|
19372
19566
|
task: null,
|
|
@@ -4705,9 +4705,9 @@
|
|
|
4705
4705
|
const scrollValue = property === "scrollLeft" ? el.scrollLeft : el.scrollTop;
|
|
4706
4706
|
const maxScrollValue = property === "scrollLeft" ? el.scrollWidth : el.scrollHeight;
|
|
4707
4707
|
const fullValue = property === "scrollLeft" ? el.clientWidth : el.clientHeight;
|
|
4708
|
-
const firstIndex = Math.max(0, Math.floor(scrollValue / cellSize));
|
|
4709
4708
|
const visibleCount = Math.max(1, Math.ceil(fullValue / cellSize));
|
|
4710
4709
|
const overscan = Math.min(100, Math.max(10, Math.ceil(visibleCount * 0.5)));
|
|
4710
|
+
const firstIndex = Math.max(0, Math.floor(scrollValue / cellSize) - overscan);
|
|
4711
4711
|
const lastIndex = Math.floor((scrollValue + fullValue) / cellSize) + overscan;
|
|
4712
4712
|
const isStartOfScroll = scrollValue < DELTA;
|
|
4713
4713
|
const isEndOfScroll = scrollValue + fullValue > maxScrollValue - DELTA;
|
|
@@ -5553,6 +5553,37 @@
|
|
|
5553
5553
|
canMoveTasks,
|
|
5554
5554
|
onColumnResizeStart
|
|
5555
5555
|
}) => {
|
|
5556
|
+
const pinnedStyles = React.useMemo(() => {
|
|
5557
|
+
const result = {};
|
|
5558
|
+
let leftOffset = 0;
|
|
5559
|
+
if (canMoveTasks) {
|
|
5560
|
+
leftOffset = 24;
|
|
5561
|
+
}
|
|
5562
|
+
for (let i = 0; i < columns.length; i++) {
|
|
5563
|
+
if (columns[i].pinned === "left") {
|
|
5564
|
+
result[i] = {
|
|
5565
|
+
position: "sticky",
|
|
5566
|
+
left: leftOffset,
|
|
5567
|
+
zIndex: 2,
|
|
5568
|
+
backgroundColor: "var(--gantt-table-header-background-color, #fff)"
|
|
5569
|
+
};
|
|
5570
|
+
leftOffset += columns[i].width;
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
let rightOffset = 0;
|
|
5574
|
+
for (let i = columns.length - 1; i >= 0; i--) {
|
|
5575
|
+
if (columns[i].pinned === "right") {
|
|
5576
|
+
result[i] = {
|
|
5577
|
+
position: "sticky",
|
|
5578
|
+
right: rightOffset,
|
|
5579
|
+
zIndex: 2,
|
|
5580
|
+
backgroundColor: "var(--gantt-table-header-background-color, #fff)"
|
|
5581
|
+
};
|
|
5582
|
+
rightOffset += columns[i].width;
|
|
5583
|
+
}
|
|
5584
|
+
}
|
|
5585
|
+
return result;
|
|
5586
|
+
}, [columns, canMoveTasks]);
|
|
5556
5587
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5557
5588
|
"div",
|
|
5558
5589
|
{
|
|
@@ -5589,7 +5620,8 @@
|
|
|
5589
5620
|
className: styles$h.ganttTable_HeaderItem,
|
|
5590
5621
|
style: {
|
|
5591
5622
|
minWidth: width,
|
|
5592
|
-
maxWidth: width
|
|
5623
|
+
maxWidth: width,
|
|
5624
|
+
...pinnedStyles[index2]
|
|
5593
5625
|
},
|
|
5594
5626
|
children: [
|
|
5595
5627
|
title,
|
|
@@ -10152,6 +10184,37 @@
|
|
|
10152
10184
|
}
|
|
10153
10185
|
return classNames.join(" ");
|
|
10154
10186
|
}, [isCut2, moveOverPosition, isOverlay2, isDragging]);
|
|
10187
|
+
const pinnedStyles = React.useMemo(() => {
|
|
10188
|
+
const result = {};
|
|
10189
|
+
let leftOffset = 0;
|
|
10190
|
+
if (moveHandleProps || !isOverlay2 && task.type !== "project" && task.id !== "no-project-asigned") {
|
|
10191
|
+
leftOffset = 24;
|
|
10192
|
+
}
|
|
10193
|
+
for (let i = 0; i < columns.length; i++) {
|
|
10194
|
+
if (columns[i].pinned === "left") {
|
|
10195
|
+
result[i] = {
|
|
10196
|
+
position: "sticky",
|
|
10197
|
+
left: leftOffset,
|
|
10198
|
+
zIndex: 1,
|
|
10199
|
+
backgroundColor: "inherit"
|
|
10200
|
+
};
|
|
10201
|
+
leftOffset += columns[i].width;
|
|
10202
|
+
}
|
|
10203
|
+
}
|
|
10204
|
+
let rightOffset = 0;
|
|
10205
|
+
for (let i = columns.length - 1; i >= 0; i--) {
|
|
10206
|
+
if (columns[i].pinned === "right") {
|
|
10207
|
+
result[i] = {
|
|
10208
|
+
position: "sticky",
|
|
10209
|
+
right: rightOffset,
|
|
10210
|
+
zIndex: 1,
|
|
10211
|
+
backgroundColor: "inherit"
|
|
10212
|
+
};
|
|
10213
|
+
rightOffset += columns[i].width;
|
|
10214
|
+
}
|
|
10215
|
+
}
|
|
10216
|
+
return result;
|
|
10217
|
+
}, [columns, moveHandleProps, isOverlay2, task.type, task.id]);
|
|
10155
10218
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10156
10219
|
"div",
|
|
10157
10220
|
{
|
|
@@ -10173,7 +10236,8 @@
|
|
|
10173
10236
|
className: styles$f.taskListCell,
|
|
10174
10237
|
style: {
|
|
10175
10238
|
minWidth: width,
|
|
10176
|
-
maxWidth: width
|
|
10239
|
+
maxWidth: width,
|
|
10240
|
+
...pinnedStyles[index2]
|
|
10177
10241
|
},
|
|
10178
10242
|
children: /* @__PURE__ */ jsxRuntime.jsx(Component, { data: columnData })
|
|
10179
10243
|
},
|
|
@@ -13079,6 +13143,12 @@
|
|
|
13079
13143
|
const tasksRes = [];
|
|
13080
13144
|
const arrowsRes = [];
|
|
13081
13145
|
const selectedTasksRes = [];
|
|
13146
|
+
const taskById = /* @__PURE__ */ new Map();
|
|
13147
|
+
mapGlobalRowIndexToTask.forEach((task) => {
|
|
13148
|
+
if (task.type !== "empty") {
|
|
13149
|
+
taskById.set(task.id, task);
|
|
13150
|
+
}
|
|
13151
|
+
});
|
|
13082
13152
|
const addedSelectedTasks = {};
|
|
13083
13153
|
const addedDependencies = {};
|
|
13084
13154
|
for (let index2 = start; index2 <= end; ++index2) {
|
|
@@ -13132,19 +13202,73 @@
|
|
|
13132
13202
|
const safeProgressWidth = isNaN(progressWidth) || !isFinite(progressWidth) ? 0 : Math.max(progressWidth, 0);
|
|
13133
13203
|
const safeInnerX1 = isNaN(innerX1) || !isFinite(innerX1) ? 0 : innerX1;
|
|
13134
13204
|
const safeInnerX2 = isNaN(innerX2) || !isFinite(innerX2) ? safeInnerX1 + safeWidth : innerX2;
|
|
13135
|
-
|
|
13205
|
+
tasksRes.push(
|
|
13206
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13207
|
+
"svg",
|
|
13208
|
+
{
|
|
13209
|
+
id: task.id,
|
|
13210
|
+
className: `${styles$4.TaskItemWrapper} TaskItemWrapper`,
|
|
13211
|
+
x: Math.max(safeContainerX + (additionalLeftSpace || 0), 0),
|
|
13212
|
+
y: safeLevelY,
|
|
13213
|
+
width: Math.max(safeContainerWidth, 0),
|
|
13214
|
+
height: fullRowHeight,
|
|
13215
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13216
|
+
TaskItem,
|
|
13217
|
+
{
|
|
13218
|
+
movingAction: taskBarMovingAction(task),
|
|
13219
|
+
allowMoveTaskBar,
|
|
13220
|
+
hasChildren: checkHasChildren(task, childTasksMap),
|
|
13221
|
+
progressWidth: safeProgressWidth,
|
|
13222
|
+
progressX: rtl ? safeInnerX2 : safeInnerX1,
|
|
13223
|
+
onSelectTaskOnMouseDown: selectTaskOnMouseDown,
|
|
13224
|
+
task,
|
|
13225
|
+
taskYOffset,
|
|
13226
|
+
width: safeWidth,
|
|
13227
|
+
x1: safeInnerX1,
|
|
13228
|
+
x2: safeInnerX2,
|
|
13229
|
+
distances,
|
|
13230
|
+
taskHeight,
|
|
13231
|
+
taskHalfHeight,
|
|
13232
|
+
isProgressChangeable: (t) => isProgressChangeable(t) && !waitCommitTasks,
|
|
13233
|
+
isDateChangeable: (t) => isDateChangeable(t) && !waitCommitTasks,
|
|
13234
|
+
isRelationChangeable: (t) => isRelationChangeable(t) && !waitCommitTasks,
|
|
13235
|
+
authorizedRelations,
|
|
13236
|
+
ganttRelationEvent,
|
|
13237
|
+
canDelete: !task.isDisabled && !waitCommitTasks,
|
|
13238
|
+
onDoubleClick,
|
|
13239
|
+
onClick,
|
|
13240
|
+
onEventStart: onTaskBarDragStart,
|
|
13241
|
+
onTooltipTask,
|
|
13242
|
+
onRelationStart: onTaskBarRelationStart,
|
|
13243
|
+
isSelected: Boolean(selectedIdsMirror[taskId]),
|
|
13244
|
+
isCritical,
|
|
13245
|
+
rtl,
|
|
13246
|
+
onDeleteTask,
|
|
13247
|
+
renderCustomLabel,
|
|
13248
|
+
viewMode,
|
|
13249
|
+
showProgress,
|
|
13250
|
+
progressColor
|
|
13251
|
+
}
|
|
13252
|
+
)
|
|
13253
|
+
},
|
|
13254
|
+
key2
|
|
13255
|
+
)
|
|
13256
|
+
);
|
|
13136
13257
|
if (task.comparisonDates && comparisonDates) {
|
|
13137
13258
|
const safeComparisonX = isNaN(comparisonDates.x) || !isFinite(comparisonDates.x) ? 0 : comparisonDates.x;
|
|
13138
|
-
const
|
|
13139
|
-
const
|
|
13140
|
-
const
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
comparisonBarElement = /* @__PURE__ */ jsxRuntime.jsx(
|
|
13145
|
-
"g",
|
|
13259
|
+
const safeComparisonY = isNaN(comparisonDates.y) || !isFinite(comparisonDates.y) ? safeLevelY : comparisonDates.y;
|
|
13260
|
+
const safeComparisonWidth = isNaN(comparisonDates.width) || !isFinite(comparisonDates.width) ? 0 : Math.max(comparisonDates.width, 0);
|
|
13261
|
+
const safeComparisonHeight = isNaN(comparisonDates.height) || !isFinite(comparisonDates.height) ? 0 : Math.max(comparisonDates.height, 0);
|
|
13262
|
+
tasksRes.push(
|
|
13263
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13264
|
+
"svg",
|
|
13146
13265
|
{
|
|
13147
|
-
|
|
13266
|
+
id: task.id + "_comparison",
|
|
13267
|
+
className: "TaskItemWrapperComparison",
|
|
13268
|
+
x: Math.max(safeComparisonX + (additionalLeftSpace || 0), 0),
|
|
13269
|
+
y: safeComparisonY,
|
|
13270
|
+
width: safeComparisonWidth,
|
|
13271
|
+
height: safeComparisonHeight * 2,
|
|
13148
13272
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13149
13273
|
BarComparison,
|
|
13150
13274
|
{
|
|
@@ -13156,70 +13280,16 @@
|
|
|
13156
13280
|
height: safeComparisonHeight,
|
|
13157
13281
|
width: safeComparisonWidth,
|
|
13158
13282
|
borderHeight: distances.barComparisonTaskBorderHeight,
|
|
13159
|
-
yOffset:
|
|
13283
|
+
yOffset: distances.barComparisonTaskYOffset,
|
|
13160
13284
|
task,
|
|
13161
13285
|
onTooltipTask
|
|
13162
13286
|
}
|
|
13163
13287
|
)
|
|
13164
|
-
}
|
|
13165
|
-
|
|
13166
|
-
|
|
13288
|
+
},
|
|
13289
|
+
key2 + "_comparison"
|
|
13290
|
+
)
|
|
13291
|
+
);
|
|
13167
13292
|
}
|
|
13168
|
-
tasksRes.push(
|
|
13169
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
13170
|
-
"svg",
|
|
13171
|
-
{
|
|
13172
|
-
id: task.id,
|
|
13173
|
-
className: `${styles$4.TaskItemWrapper} TaskItemWrapper`,
|
|
13174
|
-
x: Math.max(safeContainerX + (additionalLeftSpace || 0), 0),
|
|
13175
|
-
y: safeLevelY,
|
|
13176
|
-
width: Math.max(safeContainerWidth, 0),
|
|
13177
|
-
height: fullRowHeight,
|
|
13178
|
-
children: [
|
|
13179
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13180
|
-
TaskItem,
|
|
13181
|
-
{
|
|
13182
|
-
movingAction: taskBarMovingAction(task),
|
|
13183
|
-
allowMoveTaskBar,
|
|
13184
|
-
hasChildren: checkHasChildren(task, childTasksMap),
|
|
13185
|
-
progressWidth: safeProgressWidth,
|
|
13186
|
-
progressX: rtl ? safeInnerX2 : safeInnerX1,
|
|
13187
|
-
onSelectTaskOnMouseDown: selectTaskOnMouseDown,
|
|
13188
|
-
task,
|
|
13189
|
-
taskYOffset,
|
|
13190
|
-
width: safeWidth,
|
|
13191
|
-
x1: safeInnerX1,
|
|
13192
|
-
x2: safeInnerX2,
|
|
13193
|
-
distances,
|
|
13194
|
-
taskHeight,
|
|
13195
|
-
taskHalfHeight,
|
|
13196
|
-
isProgressChangeable: (t) => isProgressChangeable(t) && !waitCommitTasks,
|
|
13197
|
-
isDateChangeable: (t) => isDateChangeable(t) && !waitCommitTasks,
|
|
13198
|
-
isRelationChangeable: (t) => isRelationChangeable(t) && !waitCommitTasks,
|
|
13199
|
-
authorizedRelations,
|
|
13200
|
-
ganttRelationEvent,
|
|
13201
|
-
canDelete: !task.isDisabled && !waitCommitTasks,
|
|
13202
|
-
onDoubleClick,
|
|
13203
|
-
onClick,
|
|
13204
|
-
onEventStart: onTaskBarDragStart,
|
|
13205
|
-
onTooltipTask,
|
|
13206
|
-
onRelationStart: onTaskBarRelationStart,
|
|
13207
|
-
isSelected: Boolean(selectedIdsMirror[taskId]),
|
|
13208
|
-
isCritical,
|
|
13209
|
-
rtl,
|
|
13210
|
-
onDeleteTask,
|
|
13211
|
-
renderCustomLabel,
|
|
13212
|
-
viewMode,
|
|
13213
|
-
showProgress,
|
|
13214
|
-
progressColor
|
|
13215
|
-
}
|
|
13216
|
-
),
|
|
13217
|
-
comparisonBarElement
|
|
13218
|
-
]
|
|
13219
|
-
},
|
|
13220
|
-
key2
|
|
13221
|
-
)
|
|
13222
|
-
);
|
|
13223
13293
|
const addedDependenciesAtLevel = addedDependencies[comparisonLevel] || {};
|
|
13224
13294
|
if (!addedDependencies[comparisonLevel]) {
|
|
13225
13295
|
addedDependencies[comparisonLevel] = addedDependenciesAtLevel;
|
|
@@ -13373,6 +13443,93 @@
|
|
|
13373
13443
|
);
|
|
13374
13444
|
}
|
|
13375
13445
|
}
|
|
13446
|
+
const renderedTop = start * fullRowHeight;
|
|
13447
|
+
const renderedBottom = (end + 1) * fullRowHeight;
|
|
13448
|
+
for (const [comparisonLevel, dependenciesByLevel] of dependencyMap) {
|
|
13449
|
+
let addedDependenciesAtLevel = addedDependencies[comparisonLevel];
|
|
13450
|
+
if (!addedDependenciesAtLevel) {
|
|
13451
|
+
addedDependenciesAtLevel = {};
|
|
13452
|
+
addedDependencies[comparisonLevel] = addedDependenciesAtLevel;
|
|
13453
|
+
}
|
|
13454
|
+
const criticalPathOnLevel = criticalPaths ? criticalPaths.get(comparisonLevel) : void 0;
|
|
13455
|
+
for (const [taskId, dependencies] of dependenciesByLevel) {
|
|
13456
|
+
let addedDependenciesAtTask = addedDependenciesAtLevel[taskId];
|
|
13457
|
+
if (!addedDependenciesAtTask) {
|
|
13458
|
+
addedDependenciesAtTask = {};
|
|
13459
|
+
addedDependenciesAtLevel[taskId] = addedDependenciesAtTask;
|
|
13460
|
+
}
|
|
13461
|
+
const targetTask = taskById.get(taskId);
|
|
13462
|
+
if (!targetTask)
|
|
13463
|
+
continue;
|
|
13464
|
+
const criticalPathForTask = criticalPathOnLevel ? criticalPathOnLevel.dependencies.get(taskId) : void 0;
|
|
13465
|
+
dependencies.filter(({ source }) => {
|
|
13466
|
+
if (addedDependenciesAtTask[source.id])
|
|
13467
|
+
return false;
|
|
13468
|
+
if (!visibleTasksMirror[source.id])
|
|
13469
|
+
return false;
|
|
13470
|
+
return true;
|
|
13471
|
+
}).forEach(
|
|
13472
|
+
({
|
|
13473
|
+
containerHeight,
|
|
13474
|
+
containerY,
|
|
13475
|
+
innerFromY,
|
|
13476
|
+
innerToY,
|
|
13477
|
+
ownTarget,
|
|
13478
|
+
source,
|
|
13479
|
+
sourceTarget
|
|
13480
|
+
}) => {
|
|
13481
|
+
if (containerY + containerHeight < renderedTop || containerY > renderedBottom) {
|
|
13482
|
+
return;
|
|
13483
|
+
}
|
|
13484
|
+
addedDependenciesAtTask[source.id] = true;
|
|
13485
|
+
const isCritical = criticalPathForTask ? criticalPathForTask.has(source.id) : false;
|
|
13486
|
+
const { x1: fromX1, x2: fromX2 } = getTaskCoordinates2(source);
|
|
13487
|
+
const { x1: targetX1, x2: targetX2 } = getTaskCoordinates2(targetTask);
|
|
13488
|
+
const safeFromX1 = isNaN(fromX1) || !isFinite(fromX1) ? 0 : fromX1;
|
|
13489
|
+
const safeFromX2 = isNaN(fromX2) || !isFinite(fromX2) ? safeFromX1 + 10 : fromX2;
|
|
13490
|
+
const safeTargetX1 = isNaN(targetX1) || !isFinite(targetX1) ? 0 : targetX1;
|
|
13491
|
+
const safeTargetX2 = isNaN(targetX2) || !isFinite(targetX2) ? safeTargetX1 + 10 : targetX2;
|
|
13492
|
+
const cX = Math.min(safeFromX1, safeTargetX1) - DELTA_RELATION_WIDTH;
|
|
13493
|
+
const cW = Math.max(safeFromX2, safeTargetX2) - cX + DELTA_RELATION_WIDTH;
|
|
13494
|
+
const safeCX = isNaN(cX) || !isFinite(cX) ? 0 : cX;
|
|
13495
|
+
const safeCW = isNaN(cW) || !isFinite(cW) ? 100 : Math.max(cW, 0);
|
|
13496
|
+
arrowsRes.push(
|
|
13497
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13498
|
+
"svg",
|
|
13499
|
+
{
|
|
13500
|
+
x: Math.max(safeCX + (additionalLeftSpace || 0), 0),
|
|
13501
|
+
y: containerY,
|
|
13502
|
+
width: safeCW,
|
|
13503
|
+
height: containerHeight,
|
|
13504
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13505
|
+
Arrow,
|
|
13506
|
+
{
|
|
13507
|
+
distances,
|
|
13508
|
+
taskFrom: source,
|
|
13509
|
+
targetFrom: sourceTarget,
|
|
13510
|
+
fromX1: safeFromX1 - safeCX,
|
|
13511
|
+
fromX2: safeFromX2 - safeCX,
|
|
13512
|
+
fromY: innerFromY,
|
|
13513
|
+
taskTo: targetTask,
|
|
13514
|
+
targetTo: ownTarget,
|
|
13515
|
+
toX1: safeTargetX1 - safeCX,
|
|
13516
|
+
toX2: safeTargetX2 - safeCX,
|
|
13517
|
+
toY: innerToY,
|
|
13518
|
+
fullRowHeight,
|
|
13519
|
+
taskHeight,
|
|
13520
|
+
isCritical,
|
|
13521
|
+
rtl,
|
|
13522
|
+
onArrowDoubleClick
|
|
13523
|
+
}
|
|
13524
|
+
)
|
|
13525
|
+
},
|
|
13526
|
+
`Arrow from ${source.id} to ${taskId} on ${comparisonLevel}`
|
|
13527
|
+
)
|
|
13528
|
+
);
|
|
13529
|
+
}
|
|
13530
|
+
);
|
|
13531
|
+
}
|
|
13532
|
+
}
|
|
13376
13533
|
return [tasksRes, arrowsRes, selectedTasksRes];
|
|
13377
13534
|
}, [
|
|
13378
13535
|
viewMode,
|
|
@@ -13877,12 +14034,10 @@
|
|
|
13877
14034
|
);
|
|
13878
14035
|
cx1 = isNaN(cx1) || !isFinite(cx1) ? x1 : cx1;
|
|
13879
14036
|
cx2 = isNaN(cx2) || !isFinite(cx2) ? x2 : cx2;
|
|
13880
|
-
const comparisonWidth = Math.max(Math.abs(cx2 - cx1), 3);
|
|
13881
|
-
const comparisonX = Math.min(cx1, cx2);
|
|
13882
14037
|
comparisonDates = {
|
|
13883
|
-
x:
|
|
14038
|
+
x: cx1,
|
|
13884
14039
|
y: y + taskHeight,
|
|
13885
|
-
width:
|
|
14040
|
+
width: Math.max(cx2 - cx1, 0),
|
|
13886
14041
|
height: barComparisonTaskHeight
|
|
13887
14042
|
};
|
|
13888
14043
|
}
|
|
@@ -19076,7 +19231,8 @@
|
|
|
19076
19231
|
todayLabel = "Today",
|
|
19077
19232
|
dataDateLabel = "Data Date",
|
|
19078
19233
|
showProgress = true,
|
|
19079
|
-
progressColor
|
|
19234
|
+
progressColor,
|
|
19235
|
+
scrollToTaskId
|
|
19080
19236
|
} = props;
|
|
19081
19237
|
const ganttSVGRef = React.useRef(null);
|
|
19082
19238
|
const wrapperRef = React.useRef(null);
|
|
@@ -19384,6 +19540,44 @@
|
|
|
19384
19540
|
},
|
|
19385
19541
|
[mapTaskToCoordinates, setScrollXProgrammatically]
|
|
19386
19542
|
);
|
|
19543
|
+
const prevScrollToTaskIdRef = React.useRef(void 0);
|
|
19544
|
+
React.useEffect(() => {
|
|
19545
|
+
if (!scrollToTaskId || scrollToTaskId === prevScrollToTaskIdRef.current) {
|
|
19546
|
+
return;
|
|
19547
|
+
}
|
|
19548
|
+
prevScrollToTaskIdRef.current = scrollToTaskId;
|
|
19549
|
+
for (const [comparisonLevel, levelMap] of tasksMap) {
|
|
19550
|
+
const task = levelMap.get(scrollToTaskId);
|
|
19551
|
+
if (!task || task.type === "empty") {
|
|
19552
|
+
continue;
|
|
19553
|
+
}
|
|
19554
|
+
const { x1 } = getTaskCoordinates(task, mapTaskToCoordinates);
|
|
19555
|
+
setScrollXProgrammatically(Math.max(0, x1 - 100));
|
|
19556
|
+
const rowIndexMap = taskToRowIndexMap.get(comparisonLevel);
|
|
19557
|
+
if (rowIndexMap) {
|
|
19558
|
+
const rowIndex = rowIndexMap.get(scrollToTaskId);
|
|
19559
|
+
if (typeof rowIndex === "number") {
|
|
19560
|
+
const targetScrollY = rowIndex * fullRowHeight - ganttHeight / 2 + fullRowHeight / 2;
|
|
19561
|
+
setScrollYProgrammatically(
|
|
19562
|
+
Math.max(0, Math.min(targetScrollY, ganttFullHeight - ganttHeight))
|
|
19563
|
+
);
|
|
19564
|
+
}
|
|
19565
|
+
}
|
|
19566
|
+
selectTask(scrollToTaskId);
|
|
19567
|
+
break;
|
|
19568
|
+
}
|
|
19569
|
+
}, [
|
|
19570
|
+
scrollToTaskId,
|
|
19571
|
+
tasksMap,
|
|
19572
|
+
mapTaskToCoordinates,
|
|
19573
|
+
taskToRowIndexMap,
|
|
19574
|
+
fullRowHeight,
|
|
19575
|
+
ganttHeight,
|
|
19576
|
+
ganttFullHeight,
|
|
19577
|
+
setScrollXProgrammatically,
|
|
19578
|
+
setScrollYProgrammatically,
|
|
19579
|
+
selectTask
|
|
19580
|
+
]);
|
|
19387
19581
|
const { contextMenu, handleCloseContextMenu, handleOpenContextMenu } = useContextMenu(wrapperRef, scrollToTask);
|
|
19388
19582
|
const [ganttContextMenu, setGanttContextMenu] = React.useState({
|
|
19389
19583
|
task: null,
|
|
@@ -368,6 +368,11 @@ export interface GanttProps {
|
|
|
368
368
|
* Custom color for progress bars. If not provided, theme progress colors are used.
|
|
369
369
|
*/
|
|
370
370
|
progressColor?: string;
|
|
371
|
+
/**
|
|
372
|
+
* When set (or changed), the gantt will scroll to reveal and select this task.
|
|
373
|
+
* Set to a task id to scroll both horizontally and vertically to that task.
|
|
374
|
+
*/
|
|
375
|
+
scrollToTaskId?: TaskId;
|
|
371
376
|
}
|
|
372
377
|
export interface GanttTaskBarActions {
|
|
373
378
|
allowMoveTaskBar?: (action: TaskBarMoveAction, task: RenderTask) => boolean;
|
|
@@ -397,6 +402,11 @@ export type Column = {
|
|
|
397
402
|
width: number;
|
|
398
403
|
title?: ReactNode;
|
|
399
404
|
canResize?: boolean;
|
|
405
|
+
/**
|
|
406
|
+
* Pin column to the left or right side of the table.
|
|
407
|
+
* Pinned columns stay visible while scrolling horizontally.
|
|
408
|
+
*/
|
|
409
|
+
pinned?: "left" | "right";
|
|
400
410
|
};
|
|
401
411
|
export type OnResizeColumn = (nextColumns: readonly Column[], columnIndex: number, deltaWidth: number) => void;
|
|
402
412
|
export type ChangeAction = {
|
package/package.json
CHANGED