gantt-lib 0.142.2 → 0.143.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/index.css.map +1 -1
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +383 -176
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +611 -404
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +36 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4773,6 +4773,7 @@ function createTaskPreviewPositionStore() {
|
|
|
4773
4773
|
}
|
|
4774
4774
|
function createActivityPreviewStore() {
|
|
4775
4775
|
let overridesByTask = /* @__PURE__ */ new Map();
|
|
4776
|
+
let draggedRange;
|
|
4776
4777
|
const listenersByTaskId = /* @__PURE__ */ new Map();
|
|
4777
4778
|
function notify(taskIds) {
|
|
4778
4779
|
for (const taskId of taskIds) {
|
|
@@ -4793,6 +4794,16 @@ function createActivityPreviewStore() {
|
|
|
4793
4794
|
}
|
|
4794
4795
|
};
|
|
4795
4796
|
},
|
|
4797
|
+
getActivityRange(taskId, activityId) {
|
|
4798
|
+
return draggedRange?.taskId === taskId && draggedRange.activityId === activityId ? draggedRange : void 0;
|
|
4799
|
+
},
|
|
4800
|
+
setActivityRange(taskId, activityId, range) {
|
|
4801
|
+
if (draggedRange?.taskId === taskId && draggedRange.activityId === activityId && draggedRange.startDate.getTime() === range.startDate.getTime() && draggedRange.endDate.getTime() === range.endDate.getTime()) return;
|
|
4802
|
+
const changed = /* @__PURE__ */ new Set([taskId]);
|
|
4803
|
+
if (draggedRange) changed.add(draggedRange.taskId);
|
|
4804
|
+
draggedRange = { taskId, activityId, ...range };
|
|
4805
|
+
notify(changed);
|
|
4806
|
+
},
|
|
4796
4807
|
getTaskOverrides(taskId) {
|
|
4797
4808
|
return overridesByTask.get(taskId);
|
|
4798
4809
|
},
|
|
@@ -4813,10 +4824,10 @@ function createActivityPreviewStore() {
|
|
|
4813
4824
|
notify(changedTaskIds);
|
|
4814
4825
|
},
|
|
4815
4826
|
clear() {
|
|
4816
|
-
if (overridesByTask.size === 0)
|
|
4817
|
-
return;
|
|
4818
|
-
}
|
|
4827
|
+
if (overridesByTask.size === 0 && !draggedRange) return;
|
|
4819
4828
|
const changedTaskIds = new Set(overridesByTask.keys());
|
|
4829
|
+
if (draggedRange) changedTaskIds.add(draggedRange.taskId);
|
|
4830
|
+
draggedRange = void 0;
|
|
4820
4831
|
overridesByTask = /* @__PURE__ */ new Map();
|
|
4821
4832
|
notify(changedTaskIds);
|
|
4822
4833
|
}
|
|
@@ -5162,13 +5173,6 @@ var TaskRow = import_react3.default.memo(
|
|
|
5162
5173
|
const activityDragStart = (0, import_react3.useRef)(null);
|
|
5163
5174
|
const activityConstraintRef = (0, import_react3.useRef)(null);
|
|
5164
5175
|
const [activityBlockedBy, setActivityBlockedBy] = (0, import_react3.useState)(null);
|
|
5165
|
-
const visibleActivitySegments = (0, import_react3.useMemo)(() => {
|
|
5166
|
-
if (!activityLayout) return [];
|
|
5167
|
-
const window2 = horizontalWindow;
|
|
5168
|
-
if (!window2) return activityLayout.segments;
|
|
5169
|
-
const draggedId = activityDrag?.id;
|
|
5170
|
-
return activityLayout.segments.filter((segment) => segment.id === draggedId || segment.left <= window2.endPx && segment.left + segment.width >= window2.startPx);
|
|
5171
|
-
}, [activityLayout, horizontalWindow, activityDrag?.id]);
|
|
5172
5176
|
const subscribeActivityOverrides = (0, import_react3.useCallback)(
|
|
5173
5177
|
(listener) => activityPreviewStore?.subscribeTask(task.id, listener) ?? (() => {
|
|
5174
5178
|
}),
|
|
@@ -5183,6 +5187,15 @@ var TaskRow = import_react3.default.memo(
|
|
|
5183
5187
|
getActivityOverridesSnapshot,
|
|
5184
5188
|
() => void 0
|
|
5185
5189
|
);
|
|
5190
|
+
const visibleActivitySegments = (0, import_react3.useMemo)(() => {
|
|
5191
|
+
if (!activityLayout) return [];
|
|
5192
|
+
if (!horizontalWindow) return activityLayout.segments;
|
|
5193
|
+
return activityLayout.segments.filter((segment) => {
|
|
5194
|
+
if (segment.id === activityDrag?.id) return true;
|
|
5195
|
+
const left2 = segment.left + (activityOverrides?.get(segment.id) ?? 0) * dayWidth;
|
|
5196
|
+
return left2 <= horizontalWindow.endPx && left2 + segment.width >= horizontalWindow.startPx;
|
|
5197
|
+
});
|
|
5198
|
+
}, [activityLayout, horizontalWindow, activityDrag?.id, activityOverrides, dayWidth]);
|
|
5186
5199
|
const subscribeActivityBlock = (0, import_react3.useCallback)(
|
|
5187
5200
|
(listener) => activityBlockStore?.subscribeTask(task.id, listener) ?? (() => {
|
|
5188
5201
|
}),
|
|
@@ -5308,6 +5321,11 @@ var TaskRow = import_react3.default.memo(
|
|
|
5308
5321
|
});
|
|
5309
5322
|
}
|
|
5310
5323
|
publishChainPreview(activityDrag.id, activityDrag.mode, clamped);
|
|
5324
|
+
const sourceActivity = task.activities?.find((activity) => activity.id === activityDrag.id);
|
|
5325
|
+
if (sourceActivity) activityPreviewStore?.setActivityRange?.(task.id, activityDrag.id, {
|
|
5326
|
+
startDate: shiftActivityDay(sourceActivity.startDate, activityDrag.mode === "resize-right" ? 0 : clamped),
|
|
5327
|
+
endDate: shiftActivityDay(sourceActivity.endDate, activityDrag.mode === "resize-left" ? 0 : clamped)
|
|
5328
|
+
});
|
|
5311
5329
|
};
|
|
5312
5330
|
const onUp = () => {
|
|
5313
5331
|
activityPreviewStore?.clear();
|
|
@@ -5413,6 +5431,53 @@ var TaskRow = import_react3.default.memo(
|
|
|
5413
5431
|
}
|
|
5414
5432
|
return { left: segment.left, width: segment.width + activityDrag.dayDelta * dayWidth };
|
|
5415
5433
|
};
|
|
5434
|
+
const activityLinks = (0, import_react3.useMemo)(() => {
|
|
5435
|
+
const gaps = [];
|
|
5436
|
+
const elbows = [];
|
|
5437
|
+
if (!showActivityLinks || !renderActivities || !activityLayout) return { gaps, elbows };
|
|
5438
|
+
const activities = task.activities ?? [];
|
|
5439
|
+
const segmentById = new Map(activityLayout.segments.map((segment) => [segment.id, segment]));
|
|
5440
|
+
const visibleIds = new Set(visibleActivitySegments.map((segment) => segment.id));
|
|
5441
|
+
const laneTopY = (lane) => activityTopOffset + lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2;
|
|
5442
|
+
const liveRect = (segment) => {
|
|
5443
|
+
const geometry = liveActivityGeometry(segment);
|
|
5444
|
+
const chainDelta = activityOverrides?.get(segment.id) ?? 0;
|
|
5445
|
+
const left2 = geometry.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
|
|
5446
|
+
return { left: left2, right: left2 + geometry.width };
|
|
5447
|
+
};
|
|
5448
|
+
for (let index = 0; index < activities.length - 1; index += 1) {
|
|
5449
|
+
const predecessor = segmentById.get(activities[index].id);
|
|
5450
|
+
const successor = segmentById.get(activities[index + 1].id);
|
|
5451
|
+
if (!predecessor || !successor) continue;
|
|
5452
|
+
if (!visibleIds.has(predecessor.id) || !visibleIds.has(successor.id)) continue;
|
|
5453
|
+
const lag = activities[index + 1].lag ?? 0;
|
|
5454
|
+
const predRect = liveRect(predecessor);
|
|
5455
|
+
const succRect = liveRect(successor);
|
|
5456
|
+
if (predecessor.lane === successor.lane && succRect.left >= predRect.right) {
|
|
5457
|
+
const width2 = succRect.left - predRect.right;
|
|
5458
|
+
if (width2 >= 1) {
|
|
5459
|
+
gaps.push({ key: `${predecessor.id}->${successor.id}`, left: predRect.right, width: width2, lane: predecessor.lane, lag });
|
|
5460
|
+
}
|
|
5461
|
+
continue;
|
|
5462
|
+
}
|
|
5463
|
+
const predecessorLaneTop = laneTopY(predecessor.lane);
|
|
5464
|
+
const successorLaneTop = laneTopY(successor.lane);
|
|
5465
|
+
const sameLane = predecessor.lane === successor.lane;
|
|
5466
|
+
const reverseOrder = !sameLane && successorLaneTop < predecessorLaneTop;
|
|
5467
|
+
const fromY = reverseOrder ? predecessorLaneTop + 6 : predecessorLaneTop + ACTIVITY_LANE_BAR_HEIGHT - 6;
|
|
5468
|
+
const toY = reverseOrder ? successorLaneTop + ACTIVITY_LANE_BAR_HEIGHT - 6 : successorLaneTop + (sameLane ? ACTIVITY_LANE_STEP : 0) + 6;
|
|
5469
|
+
const fromX = predRect.right;
|
|
5470
|
+
const toX = succRect.left;
|
|
5471
|
+
elbows.push({
|
|
5472
|
+
key: `${predecessor.id}->${successor.id}`,
|
|
5473
|
+
d: calculateDependencyPath({ x: fromX, y: fromY }, { x: toX, y: toY }, false),
|
|
5474
|
+
lagX: toX - 14,
|
|
5475
|
+
lagY: reverseOrder ? fromY - 4 : fromY + 12,
|
|
5476
|
+
lag
|
|
5477
|
+
});
|
|
5478
|
+
}
|
|
5479
|
+
return { gaps, elbows };
|
|
5480
|
+
}, [showActivityLinks, renderActivities, activityLayout, visibleActivitySegments, activityTopOffset, activityOverrides, activityDrag, dayWidth, task.activities]);
|
|
5416
5481
|
const activityTipData = (0, import_react3.useMemo)(() => {
|
|
5417
5482
|
if (!activityTipId || !task.activities) return null;
|
|
5418
5483
|
const activity = task.activities.find((item) => item.id === activityTipId);
|
|
@@ -5484,72 +5549,121 @@ var TaskRow = import_react3.default.memo(
|
|
|
5484
5549
|
}
|
|
5485
5550
|
}
|
|
5486
5551
|
),
|
|
5487
|
-
renderActivities && activityLayout && /* @__PURE__ */ (0, import_jsx_runtime2.
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
"data-activity-id": segment.id,
|
|
5503
|
-
className: `gantt-tr-activityBar${isDraggingActivity ? " gantt-tr-activityBar-dragging" : ""}${isBlockingActivity ? " gantt-tr-activityBar-blocking" : ""}${isAtLimit ? " gantt-tr-activityBar-atLimit" : ""}${isActiveActivity ? " gantt-tr-activityBar-active" : ""}${isDimmed ? " gantt-tr-activityBar-dimmed" : ""}${isChainHighlighted ? " gantt-tr-activityBar-chain" : ""}${activityDragEnabled ? "" : " gantt-tr-activityBar-locked"}`,
|
|
5504
|
-
style: {
|
|
5505
|
-
left: `${liveLeft}px`,
|
|
5506
|
-
width: `${live.width}px`,
|
|
5507
|
-
top: `${activityTopOffset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2}px`,
|
|
5508
|
-
height: `${ACTIVITY_LANE_BAR_HEIGHT}px`,
|
|
5509
|
-
backgroundColor: segment.color || "var(--gantt-task-bar-default-color)"
|
|
5510
|
-
},
|
|
5511
|
-
onMouseDown: (event) => {
|
|
5512
|
-
if (!activityDragEnabled) return;
|
|
5513
|
-
const activationKey = activityOwnerKey(task.id, segment.id);
|
|
5514
|
-
const isActive = activityActivationStore?.getActiveKey() === activationKey;
|
|
5515
|
-
if (activationVisualEnabled && !isActive) {
|
|
5516
|
-
activityActivationStore?.setActiveKey(activationKey);
|
|
5552
|
+
renderActivities && activityLayout && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gantt-tr-activityLanes", children: [
|
|
5553
|
+
activityLinks.elbows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "gantt-tr-activityLinksSvg", width: "100%", height: "100%", "aria-hidden": "true", children: [
|
|
5554
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("marker", { id: "arrowhead", markerWidth: "8", markerHeight: "6", markerUnits: "userSpaceOnUse", refX: "7", refY: "3", orient: "auto", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polygon", { points: "0 0, 8 3, 0 6", fill: "var(--gantt-dependency-line-color, #666666)" }) }) }),
|
|
5555
|
+
activityLinks.elbows.map((link) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
|
|
5556
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { className: "gantt-dependency-path", d: link.d, markerEnd: "url(#arrowhead)" }),
|
|
5557
|
+
showActivityLag && link.lag !== 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
5558
|
+
"text",
|
|
5559
|
+
{
|
|
5560
|
+
className: "gantt-dependency-lag-label",
|
|
5561
|
+
x: link.lagX,
|
|
5562
|
+
y: link.lagY,
|
|
5563
|
+
textAnchor: "middle",
|
|
5564
|
+
fontSize: "10",
|
|
5565
|
+
fill: "var(--gantt-dependency-line-color, #666666)",
|
|
5566
|
+
children: link.lag > 0 ? `+${link.lag}` : `${link.lag}`
|
|
5517
5567
|
}
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5568
|
+
)
|
|
5569
|
+
] }, link.key))
|
|
5570
|
+
] }),
|
|
5571
|
+
visibleActivitySegments.map((segment) => {
|
|
5572
|
+
const live = liveActivityGeometry(segment);
|
|
5573
|
+
const chainDelta = activityOverrides?.get(segment.id) ?? 0;
|
|
5574
|
+
const activityProgress = segment.progress === void 0 ? 0 : Math.min(100, Math.max(0, Math.round(segment.progress)));
|
|
5575
|
+
const liveLeft = live.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
|
|
5576
|
+
const isDraggingActivity = activityDrag?.id === segment.id;
|
|
5577
|
+
const isBlockingActivity = blockedActivityIds?.has(segment.id) ?? false;
|
|
5578
|
+
const isAtLimit = isDraggingActivity && activityBlockedBy !== null;
|
|
5579
|
+
const isActiveActivity = activationVisualEnabled && activeActivityKey === activityOwnerKey(task.id, segment.id);
|
|
5580
|
+
const isSameWorkType = activeWork !== null && (segment.id === activeWork.id || activeWork.name !== null && segment.name === activeWork.name);
|
|
5581
|
+
const isDimmed = dimOthers && activeWork !== null && !isSameWorkType;
|
|
5582
|
+
const isChainHighlighted = highlightChain && activeWork !== null && isSameWorkType;
|
|
5583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
5584
|
+
"div",
|
|
5585
|
+
{
|
|
5586
|
+
"data-activity-id": segment.id,
|
|
5587
|
+
className: `gantt-tr-activityBar${isDraggingActivity ? " gantt-tr-activityBar-dragging" : ""}${isBlockingActivity ? " gantt-tr-activityBar-blocking" : ""}${isAtLimit ? " gantt-tr-activityBar-atLimit" : ""}${isActiveActivity ? " gantt-tr-activityBar-active" : ""}${isDimmed ? " gantt-tr-activityBar-dimmed" : ""}${isChainHighlighted ? " gantt-tr-activityBar-chain" : ""}${activityDragEnabled ? "" : " gantt-tr-activityBar-locked"}`,
|
|
5588
|
+
style: {
|
|
5589
|
+
left: `${liveLeft}px`,
|
|
5590
|
+
width: `${live.width}px`,
|
|
5591
|
+
top: `${activityTopOffset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2}px`,
|
|
5592
|
+
height: `${ACTIVITY_LANE_BAR_HEIGHT}px`,
|
|
5593
|
+
backgroundColor: segment.color || "var(--gantt-task-bar-default-color)"
|
|
5594
|
+
},
|
|
5595
|
+
onMouseDown: (event) => {
|
|
5596
|
+
if (!activityDragEnabled) return;
|
|
5597
|
+
const activationKey = activityOwnerKey(task.id, segment.id);
|
|
5598
|
+
const isActive = activityActivationStore?.getActiveKey() === activationKey;
|
|
5599
|
+
if (activationVisualEnabled && !isActive) {
|
|
5600
|
+
activityActivationStore?.setActiveKey(activationKey);
|
|
5601
|
+
}
|
|
5602
|
+
if (activityClickToDrag && !isActive) return;
|
|
5603
|
+
const target = event.target;
|
|
5604
|
+
const mode = target.closest(".gantt-tr-resizeHandleLeft") ? "resize-left" : target.closest(".gantt-tr-resizeHandleRight") ? "resize-right" : "move";
|
|
5605
|
+
handleActivityPointerDown(segment, mode)(event);
|
|
5606
|
+
},
|
|
5607
|
+
onMouseEnter: (event) => {
|
|
5608
|
+
if (activityDrag || activityDragOwner?.get()) return;
|
|
5609
|
+
setActivityTipPosition(anchorActivityTip(event.currentTarget.getBoundingClientRect()));
|
|
5610
|
+
setActivityTipId(segment.id);
|
|
5611
|
+
},
|
|
5612
|
+
onMouseLeave: () => {
|
|
5613
|
+
if (!activityDrag) {
|
|
5614
|
+
setActivityTipId((current) => current === segment.id ? null : current);
|
|
5615
|
+
activityTipAnchor.current = null;
|
|
5616
|
+
setActivityTipPosition(null);
|
|
5617
|
+
}
|
|
5618
|
+
},
|
|
5619
|
+
children: [
|
|
5620
|
+
activityProgress > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
5621
|
+
"span",
|
|
5622
|
+
{
|
|
5623
|
+
className: "gantt-tr-activityProgress",
|
|
5624
|
+
style: { width: `${activityProgress}%` }
|
|
5625
|
+
}
|
|
5626
|
+
),
|
|
5627
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gantt-tr-activityName", style: { color: activityTextColor(segment.color) }, children: segment.name }),
|
|
5628
|
+
activityDragEnabled && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
5629
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
|
|
5630
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
|
|
5631
|
+
] })
|
|
5632
|
+
]
|
|
5527
5633
|
},
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5634
|
+
segment.id
|
|
5635
|
+
);
|
|
5636
|
+
}),
|
|
5637
|
+
activityLinks.gaps.map((gap) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react3.default.Fragment, { children: [
|
|
5638
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
5639
|
+
"span",
|
|
5640
|
+
{
|
|
5641
|
+
className: "gantt-tr-activityLink",
|
|
5642
|
+
"aria-hidden": "true",
|
|
5643
|
+
style: {
|
|
5644
|
+
left: `${gap.left}px`,
|
|
5645
|
+
width: `${gap.width}px`,
|
|
5646
|
+
top: `${activityTopOffset + gap.lane * ACTIVITY_LANE_STEP + ACTIVITY_LANE_STEP / 2}px`
|
|
5533
5647
|
}
|
|
5534
|
-
}
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
)
|
|
5552
|
-
|
|
5648
|
+
}
|
|
5649
|
+
),
|
|
5650
|
+
showActivityLag && gap.lag > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
5651
|
+
"span",
|
|
5652
|
+
{
|
|
5653
|
+
className: "gantt-tr-activityLag",
|
|
5654
|
+
title: `\u0417\u0430\u0437\u043E\u0440 ${gap.lag} \u0434`,
|
|
5655
|
+
style: {
|
|
5656
|
+
left: `${gap.left + gap.width - 14}px`,
|
|
5657
|
+
top: `${activityTopOffset + gap.lane * ACTIVITY_LANE_STEP + ACTIVITY_LANE_STEP / 2}px`
|
|
5658
|
+
},
|
|
5659
|
+
children: [
|
|
5660
|
+
"+",
|
|
5661
|
+
gap.lag
|
|
5662
|
+
]
|
|
5663
|
+
}
|
|
5664
|
+
)
|
|
5665
|
+
] }, gap.key))
|
|
5666
|
+
] }),
|
|
5553
5667
|
!renderActivities && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
5554
5668
|
"div",
|
|
5555
5669
|
{
|
|
@@ -6122,6 +6236,74 @@ function areBothHiddenInSameParent(predecessorId, successorId, collapsedParentId
|
|
|
6122
6236
|
return predVisibleAncestor.id === succVisibleAncestor.id;
|
|
6123
6237
|
}
|
|
6124
6238
|
var EMPTY_COLLAPSED_PARENT_IDS = /* @__PURE__ */ new Set();
|
|
6239
|
+
var DependencyLineView = import_react7.default.memo(function DependencyLineView2({
|
|
6240
|
+
line,
|
|
6241
|
+
hovered,
|
|
6242
|
+
selected,
|
|
6243
|
+
showLag,
|
|
6244
|
+
markerPrefix,
|
|
6245
|
+
onLineHover,
|
|
6246
|
+
onLineLeave,
|
|
6247
|
+
onDependencyClick
|
|
6248
|
+
}) {
|
|
6249
|
+
const { id, predecessorId, successorId, linkType, path, hasCycle, lag, toX, fromY, reverseOrder, isVirtual, isCoupling } = line;
|
|
6250
|
+
const interactive = !isCoupling && onDependencyClick !== void 0;
|
|
6251
|
+
let pathClassName = "gantt-dependency-path";
|
|
6252
|
+
if (selected) pathClassName += " gantt-dependency-selected";
|
|
6253
|
+
else if (hasCycle) pathClassName += " gantt-dependency-cycle";
|
|
6254
|
+
else if (line.isCritical) pathClassName += " gantt-dependency-critical";
|
|
6255
|
+
if (isVirtual && !selected) pathClassName += " gantt-dependency-virtual";
|
|
6256
|
+
let markerEnd;
|
|
6257
|
+
if (hovered) markerEnd = `url(#${markerPrefix}-arrowhead-hover)`;
|
|
6258
|
+
else if (selected) markerEnd = `url(#${markerPrefix}-arrowhead-selected)`;
|
|
6259
|
+
else if (hasCycle) markerEnd = `url(#${markerPrefix}-arrowhead-cycle)`;
|
|
6260
|
+
else if (line.isCritical) markerEnd = `url(#${markerPrefix}-arrowhead-critical)`;
|
|
6261
|
+
else markerEnd = `url(#${markerPrefix}-arrowhead)`;
|
|
6262
|
+
const lagColor = selected ? "#ef4444" : hasCycle ? "var(--gantt-dependency-cycle-color, #ef4444)" : line.isCritical ? "var(--gantt-critical-path-color, #dc2626)" : "var(--gantt-dependency-line-color, #666666)";
|
|
6263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react7.default.Fragment, { children: [
|
|
6264
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
6265
|
+
"g",
|
|
6266
|
+
{
|
|
6267
|
+
className: `gantt-dependency-line${interactive ? "" : " gantt-dependency-line-static"}${hovered && interactive ? " gantt-dependency-line-hovered" : ""}`,
|
|
6268
|
+
onPointerEnter: interactive ? () => onLineHover(id) : void 0,
|
|
6269
|
+
onPointerLeave: interactive ? () => onLineLeave(id) : void 0,
|
|
6270
|
+
onClick: interactive ? (event) => {
|
|
6271
|
+
event.stopPropagation();
|
|
6272
|
+
onDependencyClick?.({
|
|
6273
|
+
predecessorId,
|
|
6274
|
+
successorId,
|
|
6275
|
+
linkType,
|
|
6276
|
+
x: toX,
|
|
6277
|
+
y: reverseOrder ? fromY - 4 : fromY + 12
|
|
6278
|
+
});
|
|
6279
|
+
} : void 0,
|
|
6280
|
+
role: interactive ? "button" : void 0,
|
|
6281
|
+
"aria-label": interactive ? `\u0421\u0432\u044F\u0437\u044C ${linkType}` : void 0,
|
|
6282
|
+
children: isCoupling ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: toX - 4.5, y1: fromY, x2: toX + 4.5, y2: fromY, className: `${pathClassName} gantt-dependency-coupling` }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
6283
|
+
interactive && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: path, className: "gantt-dependency-hit-area" }),
|
|
6284
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: path, className: pathClassName, markerEnd })
|
|
6285
|
+
] })
|
|
6286
|
+
}
|
|
6287
|
+
),
|
|
6288
|
+
showLag && lag !== 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
6289
|
+
"text",
|
|
6290
|
+
{
|
|
6291
|
+
className: "gantt-dependency-lag-label",
|
|
6292
|
+
x: lag < 0 ? toX + 14 : toX - 14,
|
|
6293
|
+
y: reverseOrder ? fromY - 4 : fromY + 12,
|
|
6294
|
+
textAnchor: "middle",
|
|
6295
|
+
fontSize: "10",
|
|
6296
|
+
fill: lagColor,
|
|
6297
|
+
children: lag > 0 ? `+${lag}` : `${lag}`
|
|
6298
|
+
}
|
|
6299
|
+
)
|
|
6300
|
+
] });
|
|
6301
|
+
}, (prev, next) => (
|
|
6302
|
+
// Сравнение по значению, а не по ссылке линии: пересчёт геометрии на каждом
|
|
6303
|
+
// бакете вертикальной прокрутки создаёт новые объекты линий с той же
|
|
6304
|
+
// геометрией — пере-рендерить их нельзя, иначе пан дёргается.
|
|
6305
|
+
prev.line.id === next.line.id && prev.line.predecessorId === next.line.predecessorId && prev.line.successorId === next.line.successorId && prev.line.linkType === next.line.linkType && prev.line.path === next.line.path && prev.line.hasCycle === next.line.hasCycle && prev.line.lag === next.line.lag && prev.line.toX === next.line.toX && prev.line.fromY === next.line.fromY && prev.line.reverseOrder === next.line.reverseOrder && prev.line.isVirtual === next.line.isVirtual && prev.line.isCritical === next.line.isCritical && prev.line.isCoupling === next.line.isCoupling && prev.hovered === next.hovered && prev.selected === next.selected && prev.showLag === next.showLag && prev.markerPrefix === next.markerPrefix && prev.onLineHover === next.onLineHover && prev.onLineLeave === next.onLineLeave && prev.onDependencyClick === next.onDependencyClick
|
|
6306
|
+
));
|
|
6125
6307
|
var DependencyLines = import_react7.default.memo(({
|
|
6126
6308
|
tasks,
|
|
6127
6309
|
allTasks,
|
|
@@ -6137,6 +6319,7 @@ var DependencyLines = import_react7.default.memo(({
|
|
|
6137
6319
|
dragOverrides,
|
|
6138
6320
|
selectedDep,
|
|
6139
6321
|
criticalTaskIds,
|
|
6322
|
+
cycleTaskIds,
|
|
6140
6323
|
showLag = true,
|
|
6141
6324
|
activityEndpoints = false,
|
|
6142
6325
|
businessDays = true,
|
|
@@ -6147,13 +6330,16 @@ var DependencyLines = import_react7.default.memo(({
|
|
|
6147
6330
|
const markerPrefix = `gantt-dependency-${(0, import_react7.useId)().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
6148
6331
|
const markerId = (kind) => `${markerPrefix}-${kind}`;
|
|
6149
6332
|
const [hoveredLineId, setHoveredLineId] = (0, import_react7.useState)(null);
|
|
6333
|
+
const handleLineHover = (0, import_react7.useCallback)((id) => setHoveredLineId(id), []);
|
|
6334
|
+
const handleLineLeave = (0, import_react7.useCallback)((id) => setHoveredLineId((current) => current === id ? null : current), []);
|
|
6150
6335
|
const tasksForPositions = allTasks ?? tasks;
|
|
6336
|
+
const geometryTasks = activityEndpoints ? tasksForPositions : tasks;
|
|
6151
6337
|
const { taskPositions, taskIndices, hiddenTaskIds } = (0, import_react7.useMemo)(() => {
|
|
6152
6338
|
const positions = /* @__PURE__ */ new Map();
|
|
6153
6339
|
const indices = /* @__PURE__ */ new Map();
|
|
6154
6340
|
const hidden = /* @__PURE__ */ new Set();
|
|
6155
6341
|
const taskMap = new Map(tasksForPositions.map((t) => [t.id, t]));
|
|
6156
|
-
|
|
6342
|
+
geometryTasks.forEach((task, index) => {
|
|
6157
6343
|
const override = dragOverrides?.get(task.id);
|
|
6158
6344
|
const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);
|
|
6159
6345
|
const rowIndex = rowIndexByTaskId?.get(task.id) ?? index;
|
|
@@ -6209,18 +6395,19 @@ var DependencyLines = import_react7.default.memo(({
|
|
|
6209
6395
|
}
|
|
6210
6396
|
}
|
|
6211
6397
|
return { taskPositions: positions, taskIndices: indices, hiddenTaskIds: hidden };
|
|
6212
|
-
}, [
|
|
6398
|
+
}, [geometryTasks, tasksForPositions, allTasks, collapsedParentIds, monthStart, dayWidth, rowHeight, rowTops, rowHeights, dragOverrides, rowIndexByTaskId]);
|
|
6213
6399
|
const tasksForCycleDetection = allTasks ?? tasks;
|
|
6214
6400
|
const cycleInfo = (0, import_react7.useMemo)(() => {
|
|
6401
|
+
if (cycleTaskIds) return cycleTaskIds;
|
|
6215
6402
|
const result = detectCycles(tasksForCycleDetection);
|
|
6216
|
-
const
|
|
6217
|
-
return
|
|
6218
|
-
}, [tasksForCycleDetection]);
|
|
6403
|
+
const detectedCycleIds = new Set(result.cyclePath || []);
|
|
6404
|
+
return detectedCycleIds;
|
|
6405
|
+
}, [tasksForCycleDetection, cycleTaskIds]);
|
|
6219
6406
|
const lines = (0, import_react7.useMemo)(() => {
|
|
6220
|
-
const tasksForEdges = allTasks ??
|
|
6407
|
+
const tasksForEdges = allTasks ?? geometryTasks;
|
|
6221
6408
|
const taskMap = new Map(tasksForEdges.map((task) => [task.id, task]));
|
|
6222
6409
|
const positionedTaskIds = Array.from(taskPositions.keys());
|
|
6223
|
-
const renderedTaskIdSet = new Set(
|
|
6410
|
+
const renderedTaskIdSet = new Set(geometryTasks.map((t) => t.id));
|
|
6224
6411
|
const lines2 = [];
|
|
6225
6412
|
for (const successorId of positionedTaskIds) {
|
|
6226
6413
|
const successorTaskForEdges = taskMap.get(successorId);
|
|
@@ -6315,16 +6502,20 @@ var DependencyLines = import_react7.default.memo(({
|
|
|
6315
6502
|
}
|
|
6316
6503
|
}
|
|
6317
6504
|
return lines2;
|
|
6318
|
-
}, [
|
|
6505
|
+
}, [geometryTasks, allTasks, taskPositions, taskIndices, cycleInfo, collapsedParentIds, criticalTaskIds, activityEndpoints]);
|
|
6319
6506
|
const visibleLines = (0, import_react7.useMemo)(() => {
|
|
6320
|
-
|
|
6321
|
-
return lines.filter((line) =>
|
|
6322
|
-
|
|
6507
|
+
const renderedIds = activityEndpoints ? new Set(tasks.map((task) => task.id)) : void 0;
|
|
6508
|
+
return lines.filter((line) => {
|
|
6509
|
+
if (renderedIds && !renderedIds.has(line.predecessorId) && !renderedIds.has(line.successorId)) return false;
|
|
6510
|
+
return !horizontalWindow || Math.max(line.fromX, line.toX) >= horizontalWindow.startPx && Math.min(line.fromX, line.toX) <= horizontalWindow.endPx;
|
|
6511
|
+
});
|
|
6512
|
+
}, [lines, activityEndpoints, tasks, horizontalWindow?.startPx, horizontalWindow?.endPx]);
|
|
6323
6513
|
const svgHeight = totalHeight ?? tasks.length * rowHeight;
|
|
6514
|
+
const interactive = onDependencyClick !== void 0;
|
|
6324
6515
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
6325
6516
|
"svg",
|
|
6326
6517
|
{
|
|
6327
|
-
className: "gantt-dependencies-svg"
|
|
6518
|
+
className: `gantt-dependencies-svg${interactive ? "" : " gantt-dependencies-svg-static"}`,
|
|
6328
6519
|
"data-testid": "dependency-lines-svg",
|
|
6329
6520
|
width: gridWidth,
|
|
6330
6521
|
height: svgHeight,
|
|
@@ -6427,63 +6618,22 @@ var DependencyLines = import_react7.default.memo(({
|
|
|
6427
6618
|
}
|
|
6428
6619
|
)
|
|
6429
6620
|
] }),
|
|
6430
|
-
visibleLines.map((
|
|
6431
|
-
const
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
6447
|
-
"g",
|
|
6448
|
-
{
|
|
6449
|
-
className: `gantt-dependency-line${isHovered ? " gantt-dependency-line-hovered" : ""}`,
|
|
6450
|
-
onPointerEnter: () => setHoveredLineId(id),
|
|
6451
|
-
onPointerLeave: () => setHoveredLineId((current) => current === id ? null : current),
|
|
6452
|
-
onClick: (event) => {
|
|
6453
|
-
event.stopPropagation();
|
|
6454
|
-
onDependencyClick?.({
|
|
6455
|
-
predecessorId,
|
|
6456
|
-
successorId,
|
|
6457
|
-
linkType,
|
|
6458
|
-
x: toX,
|
|
6459
|
-
y: reverseOrder ? fromY - 4 : fromY + 12
|
|
6460
|
-
});
|
|
6461
|
-
},
|
|
6462
|
-
role: "button",
|
|
6463
|
-
"aria-label": `\u0421\u0432\u044F\u0437\u044C ${linkType}`,
|
|
6464
|
-
children: isCoupling ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
6465
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("title", { children: "\u041F\u043E\u0441\u043B\u0435 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F \xB7 \u0431\u0435\u0437 \u043B\u0430\u0433\u0430" }),
|
|
6466
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("circle", { cx: toX, cy: fromY, r: 12, className: "gantt-dependency-coupling-hit-area" }),
|
|
6467
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("circle", { cx: toX, cy: fromY, r: 4, className: `${pathClassName} gantt-dependency-coupling` })
|
|
6468
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
6469
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: path, className: "gantt-dependency-hit-area" }),
|
|
6470
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: path, className: pathClassName, markerEnd })
|
|
6471
|
-
] })
|
|
6472
|
-
}
|
|
6473
|
-
),
|
|
6474
|
-
showLag && lag !== 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
6475
|
-
"text",
|
|
6476
|
-
{
|
|
6477
|
-
className: "gantt-dependency-lag-label",
|
|
6478
|
-
x: lag < 0 ? toX + 14 : toX - 14,
|
|
6479
|
-
y: reverseOrder ? fromY - 4 : fromY + 12,
|
|
6480
|
-
textAnchor: "middle",
|
|
6481
|
-
fontSize: "10",
|
|
6482
|
-
fill: lagColor,
|
|
6483
|
-
children: lag > 0 ? `+${lag}` : `${lag}`
|
|
6484
|
-
}
|
|
6485
|
-
)
|
|
6486
|
-
] }, id);
|
|
6621
|
+
visibleLines.map((line) => {
|
|
6622
|
+
const isSelected = selectedDep != null && line.id === `${selectedDep.predecessorId}-${selectedDep.successorId}-${selectedDep.linkType}`;
|
|
6623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
6624
|
+
DependencyLineView,
|
|
6625
|
+
{
|
|
6626
|
+
line,
|
|
6627
|
+
hovered: hoveredLineId === line.id,
|
|
6628
|
+
selected: isSelected,
|
|
6629
|
+
showLag,
|
|
6630
|
+
markerPrefix,
|
|
6631
|
+
onLineHover: handleLineHover,
|
|
6632
|
+
onLineLeave: handleLineLeave,
|
|
6633
|
+
onDependencyClick
|
|
6634
|
+
},
|
|
6635
|
+
line.id
|
|
6636
|
+
);
|
|
6487
6637
|
})
|
|
6488
6638
|
]
|
|
6489
6639
|
}
|
|
@@ -6496,6 +6646,14 @@ var DependencyLines_default = DependencyLines;
|
|
|
6496
6646
|
var import_react8 = require("react");
|
|
6497
6647
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
6498
6648
|
var activityKey = (taskId, activityId) => JSON.stringify([taskId, activityId]);
|
|
6649
|
+
var sameDependencies = (left, right) => {
|
|
6650
|
+
if (left === right) return true;
|
|
6651
|
+
if (!left || !right || left.length !== right.length) return false;
|
|
6652
|
+
return left.every((dep, index) => {
|
|
6653
|
+
const other = right[index];
|
|
6654
|
+
return dep.taskId === other.taskId && dep.type === other.type && dep.lag === other.lag && dep.hidden === other.hidden;
|
|
6655
|
+
});
|
|
6656
|
+
};
|
|
6499
6657
|
function ActivityDependencyLines(props) {
|
|
6500
6658
|
const { tasks, dependencies, monthStart, dayWidth, previewStore } = props;
|
|
6501
6659
|
const [previewVersion, refresh] = (0, import_react8.useReducer)((value) => value + 1, 0);
|
|
@@ -6503,15 +6661,29 @@ function ActivityDependencyLines(props) {
|
|
|
6503
6661
|
const cleanups = tasks.filter((task) => task.activities?.length).map((task) => previewStore?.subscribeTask(task.id, refresh));
|
|
6504
6662
|
return () => cleanups.forEach((cleanup) => cleanup?.());
|
|
6505
6663
|
}, [tasks, previewStore]);
|
|
6664
|
+
const cycleTaskIds = (0, import_react8.useMemo)(() => {
|
|
6665
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
6666
|
+
for (const edge of dependencies) {
|
|
6667
|
+
const id = activityKey(edge.successorTaskId, edge.successorActivityId);
|
|
6668
|
+
const values = incoming.get(id) ?? [];
|
|
6669
|
+
values.push({ taskId: activityKey(edge.predecessorTaskId, edge.predecessorActivityId), type: edge.type, lag: edge.lag ?? 0 });
|
|
6670
|
+
incoming.set(id, values);
|
|
6671
|
+
}
|
|
6672
|
+
const nodes = tasks.flatMap((task) => (task.activities ?? []).map((activity) => ({ id: activityKey(task.id, activity.id), name: activity.name, startDate: activity.startDate, endDate: activity.endDate, dependencies: incoming.get(activityKey(task.id, activity.id)) })));
|
|
6673
|
+
return new Set(detectCycles(nodes).cyclePath ?? []);
|
|
6674
|
+
}, [tasks, dependencies]);
|
|
6675
|
+
const layoutCacheRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
|
|
6506
6676
|
const layout = (0, import_react8.useMemo)(() => {
|
|
6507
|
-
const flattened = [],
|
|
6677
|
+
const flattened = [], tops = [], heights = [];
|
|
6678
|
+
const nodesByTaskId = /* @__PURE__ */ new Map();
|
|
6508
6679
|
const indices = /* @__PURE__ */ new Map();
|
|
6509
6680
|
const neededRows = /* @__PURE__ */ new Set();
|
|
6510
6681
|
const incoming = /* @__PURE__ */ new Map();
|
|
6511
6682
|
const selected = props.highlight ? new Set(props.highlight.activities.map((activity) => activityKey(activity.taskId, activity.activityId))) : void 0;
|
|
6512
6683
|
const highlightMode = props.highlight?.mode ?? "chain";
|
|
6513
6684
|
for (const edge of dependencies) {
|
|
6514
|
-
|
|
6685
|
+
const isCrossRow = edge.predecessorTaskId !== edge.successorTaskId;
|
|
6686
|
+
if (isCrossRow && !props.highlight) continue;
|
|
6515
6687
|
if (selected) {
|
|
6516
6688
|
const fromSelected = selected.has(activityKey(edge.predecessorTaskId, edge.predecessorActivityId));
|
|
6517
6689
|
const toSelected = selected.has(activityKey(edge.successorTaskId, edge.successorActivityId));
|
|
@@ -6524,33 +6696,75 @@ function ActivityDependencyLines(props) {
|
|
|
6524
6696
|
neededRows.add(edge.successorTaskId);
|
|
6525
6697
|
const id = activityKey(edge.successorTaskId, edge.successorActivityId);
|
|
6526
6698
|
const values = incoming.get(id) ?? [];
|
|
6527
|
-
values.push({ taskId: activityKey(edge.predecessorTaskId, edge.predecessorActivityId), type: edge.type, lag: edge.lag });
|
|
6699
|
+
values.push({ taskId: activityKey(edge.predecessorTaskId, edge.predecessorActivityId), type: edge.type, lag: edge.lag ?? 0 });
|
|
6528
6700
|
incoming.set(id, values);
|
|
6529
6701
|
}
|
|
6702
|
+
const monthStartMs = monthStart.getTime();
|
|
6703
|
+
const cache = layoutCacheRef.current;
|
|
6530
6704
|
for (const task of tasks) {
|
|
6531
6705
|
if (!neededRows.has(task.id)) continue;
|
|
6532
6706
|
const row = props.rowIndexByTaskId.get(task.id);
|
|
6533
6707
|
if (row === void 0 || !task.activities?.length) continue;
|
|
6534
6708
|
const height = props.rowHeights[row] ?? props.rowHeight;
|
|
6535
6709
|
if (height < props.rowHeight) continue;
|
|
6536
|
-
const
|
|
6537
|
-
const
|
|
6538
|
-
|
|
6539
|
-
for (const activity of
|
|
6540
|
-
const
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6710
|
+
const activities = task.activities;
|
|
6711
|
+
const overrides = previewStore?.getTaskOverrides(task.id);
|
|
6712
|
+
let range;
|
|
6713
|
+
for (const activity of activities) {
|
|
6714
|
+
const current = previewStore?.getActivityRange?.(task.id, activity.id);
|
|
6715
|
+
if (current) {
|
|
6716
|
+
range = current;
|
|
6717
|
+
break;
|
|
6718
|
+
}
|
|
6719
|
+
}
|
|
6720
|
+
let entry = cache.get(task.id);
|
|
6721
|
+
const reusable = entry && entry.activities === activities && entry.monthStartMs === monthStartMs && entry.dayWidth === dayWidth && entry.overrides === overrides && entry.range === range && entry.nodes.length === activities.length && entry.nodes.every((node, index) => node.name === activities[index].name && node.startDate === activities[index].startDate && node.endDate === activities[index].endDate && sameDependencies(node.dependencies, incoming.get(node.id)));
|
|
6722
|
+
if (!entry || !reusable) {
|
|
6723
|
+
const liveActivities = activities.map((activity) => {
|
|
6724
|
+
const activityRange = previewStore?.getActivityRange?.(task.id, activity.id);
|
|
6725
|
+
if (activityRange) return { ...activity, startDate: activityRange.startDate, endDate: activityRange.endDate };
|
|
6726
|
+
const delta = overrides?.get(activity.id) ?? 0;
|
|
6727
|
+
if (delta === 0) return activity;
|
|
6728
|
+
return { ...activity, startDate: shiftActivityDate(activity.startDate, delta), endDate: shiftActivityDate(activity.endDate, delta) };
|
|
6729
|
+
});
|
|
6730
|
+
const packed = computeActivityLanes(liveActivities, monthStart, dayWidth);
|
|
6731
|
+
const lanes = new Map(packed.segments.map((segment) => [segment.id, segment.lane]));
|
|
6732
|
+
const rawIds = liveActivities.map((activity) => activity.id);
|
|
6733
|
+
const nodes = liveActivities.map((activity) => ({
|
|
6734
|
+
id: activityKey(task.id, activity.id),
|
|
6735
|
+
name: activity.name,
|
|
6736
|
+
startDate: activity.startDate,
|
|
6737
|
+
endDate: activity.endDate,
|
|
6738
|
+
dependencies: incoming.get(activityKey(task.id, activity.id))
|
|
6739
|
+
}));
|
|
6740
|
+
entry = { activities, monthStartMs, dayWidth, overrides, range, laneCount: packed.laneCount, lanes, rawIds, nodes };
|
|
6741
|
+
cache.set(task.id, entry);
|
|
6742
|
+
}
|
|
6743
|
+
const offset = Math.max(0, (height - entry.laneCount * ACTIVITY_LANE_STEP) / 2);
|
|
6744
|
+
nodesByTaskId.set(task.id, entry.nodes);
|
|
6745
|
+
entry.nodes.forEach((node, nodeIndex) => {
|
|
6746
|
+
const lane = entry.lanes.get(entry.rawIds[nodeIndex]) ?? 0;
|
|
6747
|
+
const index = flattened.length;
|
|
6544
6748
|
flattened.push(node);
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
tops.push((props.rowTops[row] ?? row * props.rowHeight) + offset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2);
|
|
6749
|
+
indices.set(node.id, index);
|
|
6750
|
+
tops.push((props.rowTops[row] ?? row * props.rowHeight) + offset + lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2);
|
|
6548
6751
|
heights.push(ACTIVITY_LANE_BAR_HEIGHT);
|
|
6549
|
-
}
|
|
6752
|
+
});
|
|
6753
|
+
}
|
|
6754
|
+
for (const taskId of cache.keys()) {
|
|
6755
|
+
if (!nodesByTaskId.has(taskId)) cache.delete(taskId);
|
|
6550
6756
|
}
|
|
6551
|
-
return { flattened,
|
|
6552
|
-
}, [tasks, dependencies, props.highlight, monthStart, dayWidth, props.rowIndexByTaskId, props.rowTops, props.rowHeights, props.rowHeight,
|
|
6553
|
-
|
|
6757
|
+
return { flattened, nodesByTaskId, indices, tops, heights };
|
|
6758
|
+
}, [tasks, dependencies, props.highlight, monthStart, dayWidth, props.rowIndexByTaskId, props.rowTops, props.rowHeights, props.rowHeight, previewStore, previewVersion]);
|
|
6759
|
+
const rendered = (0, import_react8.useMemo)(() => {
|
|
6760
|
+
const nodes = [];
|
|
6761
|
+
for (const taskId of props.renderedTaskIds) {
|
|
6762
|
+
const rowNodes = layout.nodesByTaskId.get(taskId);
|
|
6763
|
+
if (rowNodes) nodes.push(...rowNodes);
|
|
6764
|
+
}
|
|
6765
|
+
return nodes;
|
|
6766
|
+
}, [layout, props.renderedTaskIds]);
|
|
6767
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DependencyLines, { tasks: rendered, allTasks: layout.flattened, monthStart, dayWidth, rowHeight: ACTIVITY_LANE_BAR_HEIGHT, gridWidth: props.gridWidth, totalHeight: props.totalHeight, rowIndexByTaskId: layout.indices, rowTops: layout.tops, rowHeights: layout.heights, horizontalWindow: props.horizontalWindow, showLag: props.showLag, cycleTaskIds, activityEndpoints: true });
|
|
6554
6768
|
}
|
|
6555
6769
|
|
|
6556
6770
|
// src/components/DependencyCreationOverlay/DependencyCreationOverlay.tsx
|
|
@@ -15442,17 +15656,6 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15442
15656
|
onTaskDateChangeModeChange: externalOnTaskDateChangeModeChange,
|
|
15443
15657
|
printDependencyLabels = false
|
|
15444
15658
|
} = props;
|
|
15445
|
-
const resolvedActivityDependencies = (0, import_react20.useMemo)(() => {
|
|
15446
|
-
if (activityDependencies !== void 0) return activityDependencies;
|
|
15447
|
-
return tasks.flatMap((task) => (task.activities ?? []).slice(1).map((successor, index) => ({
|
|
15448
|
-
predecessorTaskId: task.id,
|
|
15449
|
-
predecessorActivityId: task.activities[index].id,
|
|
15450
|
-
successorTaskId: task.id,
|
|
15451
|
-
successorActivityId: successor.id,
|
|
15452
|
-
type: "FS",
|
|
15453
|
-
lag: successor.lag ?? 0
|
|
15454
|
-
})));
|
|
15455
|
-
}, [tasks, activityDependencies]);
|
|
15456
15659
|
const dayWidth = !isTableMatrixMode ? props.dayWidth ?? 40 : 40;
|
|
15457
15660
|
const criticalPathMode = !isTableMatrixMode && !isPlanFactMode ? props.criticalPathMode : void 0;
|
|
15458
15661
|
const onSubtreeScaleResult = !isTableMatrixMode && !isPlanFactMode ? props.onSubtreeScaleResult : void 0;
|
|
@@ -16359,7 +16562,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16359
16562
|
}
|
|
16360
16563
|
}
|
|
16361
16564
|
return Array.from(indices).sort((left, right) => left - right);
|
|
16362
|
-
}, [compositeRowLayout, forceFullRenderForPrint, forcedRenderedTaskIds, scrollViewport, visibleTaskIndexMap, visibleTasks.length]);
|
|
16565
|
+
}, [compositeRowLayout, forceFullRenderForPrint, forcedRenderedTaskIds, scrollViewport.scrollTop, scrollViewport.viewportHeight, visibleTaskIndexMap, visibleTasks.length]);
|
|
16363
16566
|
const visiblePlanFactDateIndices = (0, import_react20.useMemo)(() => {
|
|
16364
16567
|
if (forceFullRenderForPrint) {
|
|
16365
16568
|
return void 0;
|
|
@@ -16673,6 +16876,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16673
16876
|
if (document.activeElement instanceof HTMLElement) {
|
|
16674
16877
|
document.activeElement.blur();
|
|
16675
16878
|
}
|
|
16879
|
+
container.setAttribute("data-panning", "true");
|
|
16676
16880
|
container.style.cursor = "grabbing";
|
|
16677
16881
|
e.preventDefault();
|
|
16678
16882
|
}, [activityActivationStore]);
|
|
@@ -16710,7 +16914,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16710
16914
|
}
|
|
16711
16915
|
panStateRef.current = null;
|
|
16712
16916
|
const container = scrollContainerRef.current;
|
|
16713
|
-
if (container)
|
|
16917
|
+
if (container) {
|
|
16918
|
+
container.removeAttribute("data-panning");
|
|
16919
|
+
container.style.cursor = "";
|
|
16920
|
+
}
|
|
16714
16921
|
};
|
|
16715
16922
|
window.addEventListener("mousemove", handlePanMove);
|
|
16716
16923
|
window.addEventListener("mouseup", handlePanEnd);
|
|
@@ -16929,7 +17136,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16929
17136
|
onHoverEnd: () => setActiveTimelineTooltip(null)
|
|
16930
17137
|
}
|
|
16931
17138
|
),
|
|
16932
|
-
showActivityLinks &&
|
|
17139
|
+
showActivityLinks && activityDependencies !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ActivityDependencyLines, { tasks: previewVisibleTasks, renderedTaskIds: renderedTaskIdsRef.current, dependencies: activityDependencies, highlight: activityDependencyHighlight, monthStart, dayWidth, rowHeight: effectiveRowHeight, gridWidth: renderGridWidth, totalHeight: totalGridHeight, rowIndexByTaskId: visibleTaskIndexMap, rowTops: compositeRowLayout.tops, rowHeights: compositeRowLayout.heights, showLag: showActivityLag, previewStore: activityPreviewStore, horizontalWindow }),
|
|
16933
17140
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
16934
17141
|
DependencyLines_default,
|
|
16935
17142
|
{
|
|
@@ -17072,10 +17279,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
17072
17279
|
activityActivationStore,
|
|
17073
17280
|
activityClickToDrag,
|
|
17074
17281
|
activityActivationMode,
|
|
17075
|
-
showActivityLinks:
|
|
17282
|
+
showActivityLinks: showActivityLinks && activityDependencies === void 0,
|
|
17076
17283
|
showActivityLag,
|
|
17077
17284
|
activityTooltip,
|
|
17078
|
-
horizontalWindow,
|
|
17285
|
+
horizontalWindow: forceFullRenderForPrint ? void 0 : horizontalWindow,
|
|
17079
17286
|
onCascadeProgress: handleCascadeProgress,
|
|
17080
17287
|
onCascade: handleCascade,
|
|
17081
17288
|
onScheduleIntent,
|