gantt-lib 0.78.0 → 0.80.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/{index-CZzZrxn-.d.mts → index-DAfJyZbj.d.mts} +14 -1
- package/dist/{index-CZzZrxn-.d.ts → index-DAfJyZbj.d.ts} +14 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +20 -5
- package/dist/index.d.ts +20 -5
- package/dist/index.js +305 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +317 -62
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +245 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3137,7 +3137,7 @@ var arePropsEqual2 = (prevProps, nextProps) => {
|
|
|
3137
3137
|
prevProps.viewMode === nextProps.viewMode && prevProps.isCustomWeekend === nextProps.isCustomWeekend;
|
|
3138
3138
|
};
|
|
3139
3139
|
var GridBackground = import_react5.default.memo(
|
|
3140
|
-
({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend }) => {
|
|
3140
|
+
({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend, className, showWeekendBlocks = true, showGridLines = true }) => {
|
|
3141
3141
|
const weekGridLines = (0, import_react5.useMemo)(() => {
|
|
3142
3142
|
if (viewMode !== "week") return [];
|
|
3143
3143
|
return calculateWeekGridLines(dateRange, dayWidth);
|
|
@@ -3160,13 +3160,13 @@ var GridBackground = import_react5.default.memo(
|
|
|
3160
3160
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
3161
3161
|
"div",
|
|
3162
3162
|
{
|
|
3163
|
-
className: "gantt-gb-gridBackground",
|
|
3163
|
+
className: ["gantt-gb-gridBackground", className].filter(Boolean).join(" "),
|
|
3164
3164
|
style: {
|
|
3165
3165
|
width: `${gridWidth}px`,
|
|
3166
3166
|
height: `${totalHeight}px`
|
|
3167
3167
|
},
|
|
3168
3168
|
children: [
|
|
3169
|
-
weekendBlocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3169
|
+
showWeekendBlocks && weekendBlocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3170
3170
|
"div",
|
|
3171
3171
|
{
|
|
3172
3172
|
className: "gantt-gb-weekendBlock",
|
|
@@ -3177,7 +3177,7 @@ var GridBackground = import_react5.default.memo(
|
|
|
3177
3177
|
},
|
|
3178
3178
|
`weekend-${index}`
|
|
3179
3179
|
)),
|
|
3180
|
-
viewMode === "week" ? (
|
|
3180
|
+
showGridLines && (viewMode === "week" ? (
|
|
3181
3181
|
// Week-view: one line per week column boundary
|
|
3182
3182
|
weekGridLines.map((line, index) => {
|
|
3183
3183
|
const lineClass = line.isMonthStart ? "gantt-gb-monthSeparator" : "gantt-gb-weekSeparator";
|
|
@@ -3218,7 +3218,7 @@ var GridBackground = import_react5.default.memo(
|
|
|
3218
3218
|
`gridline-${index}`
|
|
3219
3219
|
);
|
|
3220
3220
|
})
|
|
3221
|
-
)
|
|
3221
|
+
))
|
|
3222
3222
|
]
|
|
3223
3223
|
}
|
|
3224
3224
|
);
|
|
@@ -3489,6 +3489,25 @@ var DependencyLines = import_react6.default.memo(({
|
|
|
3489
3489
|
}
|
|
3490
3490
|
)
|
|
3491
3491
|
}
|
|
3492
|
+
),
|
|
3493
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3494
|
+
"marker",
|
|
3495
|
+
{
|
|
3496
|
+
id: "arrowhead-hover",
|
|
3497
|
+
markerWidth: "8",
|
|
3498
|
+
markerHeight: "6",
|
|
3499
|
+
markerUnits: "userSpaceOnUse",
|
|
3500
|
+
refX: "7",
|
|
3501
|
+
refY: "3",
|
|
3502
|
+
orient: "auto",
|
|
3503
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3504
|
+
"polygon",
|
|
3505
|
+
{
|
|
3506
|
+
points: "0 0, 8 3, 0 6",
|
|
3507
|
+
fill: "var(--gantt-dependency-hover-color, #ef4444)"
|
|
3508
|
+
}
|
|
3509
|
+
)
|
|
3510
|
+
}
|
|
3492
3511
|
)
|
|
3493
3512
|
] }),
|
|
3494
3513
|
lines.map(({ id, path, hasCycle, lag, fromX, toX, fromY, reverseOrder, isVirtual }) => {
|
|
@@ -3503,14 +3522,23 @@ var DependencyLines = import_react6.default.memo(({
|
|
|
3503
3522
|
else markerEnd = "url(#arrowhead)";
|
|
3504
3523
|
const lagColor = isSelected ? "#ef4444" : hasCycle ? "var(--gantt-dependency-cycle-color, #ef4444)" : "var(--gantt-dependency-line-color, #666666)";
|
|
3505
3524
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react6.default.Fragment, { children: [
|
|
3506
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3525
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("g", { className: "gantt-dependency-line", children: [
|
|
3526
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3527
|
+
"path",
|
|
3528
|
+
{
|
|
3529
|
+
d: path,
|
|
3530
|
+
className: "gantt-dependency-hit-area"
|
|
3531
|
+
}
|
|
3532
|
+
),
|
|
3533
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3534
|
+
"path",
|
|
3535
|
+
{
|
|
3536
|
+
d: path,
|
|
3537
|
+
className: pathClassName,
|
|
3538
|
+
markerEnd
|
|
3539
|
+
}
|
|
3540
|
+
)
|
|
3541
|
+
] }),
|
|
3514
3542
|
lag !== 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3515
3543
|
"text",
|
|
3516
3544
|
{
|
|
@@ -4560,12 +4588,20 @@ var DepChip = ({
|
|
|
4560
4588
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
4561
4589
|
"span",
|
|
4562
4590
|
{
|
|
4563
|
-
className: `gantt-tl-dep-chip${isSelected ? " gantt-tl-dep-chip-selected" : ""}`,
|
|
4591
|
+
className: `gantt-tl-dep-chip-with-number${isSelected ? " gantt-tl-dep-chip-with-number-selected" : ""}`,
|
|
4564
4592
|
onClick: handleClick,
|
|
4565
|
-
|
|
4593
|
+
"aria-label": `[${LINK_TYPE_LABELS_RU[dep.type]}] ${formatTaskNumberLabel(predecessorTaskNumber)}${depName}`,
|
|
4566
4594
|
children: [
|
|
4567
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4568
|
-
|
|
4595
|
+
predecessorTaskNumber && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-dep-chip-task-number", children: predecessorTaskNumber }),
|
|
4596
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-dep-chip", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, {}) }),
|
|
4597
|
+
effectiveLag !== 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-dep-chip-lag", children: effectiveLag > 0 ? `+${effectiveLag}` : `${effectiveLag}` }),
|
|
4598
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "gantt-tl-dep-chip-tooltip", role: "tooltip", children: [
|
|
4599
|
+
"[",
|
|
4600
|
+
LINK_TYPE_LABELS_RU[dep.type],
|
|
4601
|
+
"] ",
|
|
4602
|
+
formatTaskNumberLabel(predecessorTaskNumber),
|
|
4603
|
+
depName
|
|
4604
|
+
] })
|
|
4569
4605
|
]
|
|
4570
4606
|
}
|
|
4571
4607
|
) }),
|
|
@@ -6410,7 +6446,7 @@ var BUILT_IN_COLUMN_WIDTHS = {
|
|
|
6410
6446
|
endDate: 90,
|
|
6411
6447
|
duration: 60,
|
|
6412
6448
|
progress: 50,
|
|
6413
|
-
dependencies:
|
|
6449
|
+
dependencies: 128,
|
|
6414
6450
|
actions: 80
|
|
6415
6451
|
};
|
|
6416
6452
|
function createBuiltInColumns(opts) {
|
|
@@ -7411,6 +7447,33 @@ var calculateConflictInfo = (parsedItems) => {
|
|
|
7411
7447
|
}
|
|
7412
7448
|
return result;
|
|
7413
7449
|
};
|
|
7450
|
+
var countConflictOverlaps = (items) => {
|
|
7451
|
+
const conflictsByItemId = new Map(items.map((item) => [item.itemId, item.conflictsWith]));
|
|
7452
|
+
const visited = /* @__PURE__ */ new Set();
|
|
7453
|
+
let overlapCount = 0;
|
|
7454
|
+
for (const item of items) {
|
|
7455
|
+
if (visited.has(item.itemId) || item.conflictsWith.length === 0) {
|
|
7456
|
+
continue;
|
|
7457
|
+
}
|
|
7458
|
+
const stack = [item.itemId];
|
|
7459
|
+
let componentSize = 0;
|
|
7460
|
+
while (stack.length > 0) {
|
|
7461
|
+
const itemId = stack.pop();
|
|
7462
|
+
if (visited.has(itemId)) {
|
|
7463
|
+
continue;
|
|
7464
|
+
}
|
|
7465
|
+
visited.add(itemId);
|
|
7466
|
+
componentSize += 1;
|
|
7467
|
+
for (const conflictId of conflictsByItemId.get(itemId) ?? []) {
|
|
7468
|
+
if (!visited.has(conflictId)) {
|
|
7469
|
+
stack.push(conflictId);
|
|
7470
|
+
}
|
|
7471
|
+
}
|
|
7472
|
+
}
|
|
7473
|
+
overlapCount += Math.max(0, componentSize - 1);
|
|
7474
|
+
}
|
|
7475
|
+
return overlapCount;
|
|
7476
|
+
};
|
|
7414
7477
|
var layoutResourceTimelineItems = (resources, options) => {
|
|
7415
7478
|
const rows = [];
|
|
7416
7479
|
const items = [];
|
|
@@ -7470,7 +7533,7 @@ var layoutResourceTimelineItems = (resources, options) => {
|
|
|
7470
7533
|
}
|
|
7471
7534
|
const laneCount = Math.max(1, laneEndDays.length);
|
|
7472
7535
|
const resourceRowHeight = laneCount * options.laneHeight;
|
|
7473
|
-
const conflictCount = laidOutItems
|
|
7536
|
+
const conflictCount = countConflictOverlaps(laidOutItems);
|
|
7474
7537
|
const row = {
|
|
7475
7538
|
resource,
|
|
7476
7539
|
resourceId: resource.id,
|
|
@@ -7715,7 +7778,8 @@ var DEFAULT_ROW_HEADER_WIDTH = 240;
|
|
|
7715
7778
|
var DEFAULT_RESOURCE_ROW_GAP = 8;
|
|
7716
7779
|
var ITEM_OUTER_VERTICAL_INSET = 2;
|
|
7717
7780
|
var ITEM_INNER_VERTICAL_INSET = 1;
|
|
7718
|
-
var
|
|
7781
|
+
var ITEM_START_HORIZONTAL_INSET = 2;
|
|
7782
|
+
var ITEM_END_HORIZONTAL_INSET = 1;
|
|
7719
7783
|
var isValidDate = (date) => !Number.isNaN(date.getTime());
|
|
7720
7784
|
var collectValidItems = (resources) => {
|
|
7721
7785
|
return resources.flatMap(
|
|
@@ -7737,12 +7801,18 @@ var getVisualItemGeometry = (geometry, laneIndex, laneCount) => {
|
|
|
7737
7801
|
const topInset = laneIndex === 0 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7738
7802
|
const bottomInset = laneIndex === laneCount - 1 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7739
7803
|
return {
|
|
7740
|
-
left: geometry.left +
|
|
7804
|
+
left: geometry.left + ITEM_START_HORIZONTAL_INSET,
|
|
7741
7805
|
top: geometry.top + topInset,
|
|
7742
|
-
width: Math.max(
|
|
7806
|
+
width: Math.max(1, geometry.width - ITEM_START_HORIZONTAL_INSET - ITEM_END_HORIZONTAL_INSET),
|
|
7743
7807
|
height: Math.max(0, geometry.height - topInset - bottomInset)
|
|
7744
7808
|
};
|
|
7745
7809
|
};
|
|
7810
|
+
var formatOverlapCount = (count) => {
|
|
7811
|
+
const mod10 = count % 10;
|
|
7812
|
+
const mod100 = count % 100;
|
|
7813
|
+
const word = mod10 === 1 && mod100 !== 11 ? "\u043D\u0430\u043B\u043E\u0436\u0435\u043D\u0438\u0435" : mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14) ? "\u043D\u0430\u043B\u043E\u0436\u0435\u043D\u0438\u044F" : "\u043D\u0430\u043B\u043E\u0436\u0435\u043D\u0438\u0439";
|
|
7814
|
+
return `${count} ${word}`;
|
|
7815
|
+
};
|
|
7746
7816
|
var getWeekendOverlaySegments = (startDate, endDate, dayWidth, weekendPredicate) => {
|
|
7747
7817
|
const segments2 = [];
|
|
7748
7818
|
const current = new Date(Date.UTC(startDate.getUTCFullYear(), startDate.getUTCMonth(), startDate.getUTCDate()));
|
|
@@ -7785,7 +7855,143 @@ var getRangeOverlaySegments = (itemStartDate, ranges, dayWidth) => {
|
|
|
7785
7855
|
};
|
|
7786
7856
|
});
|
|
7787
7857
|
};
|
|
7858
|
+
var clampOverlaySegments = (segments2, maxWidth) => segments2.flatMap((segment) => {
|
|
7859
|
+
const left = Math.max(0, Math.min(segment.left, maxWidth));
|
|
7860
|
+
const right = Math.max(left, Math.min(segment.left + segment.width, maxWidth));
|
|
7861
|
+
const width = right - left;
|
|
7862
|
+
return width > 0 ? [{ left, width }] : [];
|
|
7863
|
+
});
|
|
7788
7864
|
var getDurationValue = (startDate, endDate, businessDays, weekendPredicate) => businessDays ? getBusinessDaysCount(startDate, endDate, weekendPredicate) : Math.max(1, Math.round((endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1e3)) + 1);
|
|
7865
|
+
var ResourceHeader = ({
|
|
7866
|
+
resource,
|
|
7867
|
+
resourceId,
|
|
7868
|
+
conflictCount,
|
|
7869
|
+
height,
|
|
7870
|
+
paddingBottom,
|
|
7871
|
+
menuCommands
|
|
7872
|
+
}) => {
|
|
7873
|
+
const [menuOpen, setMenuOpen] = (0, import_react14.useState)(false);
|
|
7874
|
+
const visibleCommands = (0, import_react14.useMemo)(
|
|
7875
|
+
() => menuCommands.filter((command) => command.isVisible?.(resource) ?? true),
|
|
7876
|
+
[menuCommands, resource]
|
|
7877
|
+
);
|
|
7878
|
+
const hasMenu = visibleCommands.length > 0;
|
|
7879
|
+
const handleCommandClick = (command, event) => {
|
|
7880
|
+
event.stopPropagation();
|
|
7881
|
+
if (command.closeOnSelect !== false) {
|
|
7882
|
+
setMenuOpen(false);
|
|
7883
|
+
}
|
|
7884
|
+
command.onSelect(resource);
|
|
7885
|
+
};
|
|
7886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7887
|
+
"div",
|
|
7888
|
+
{
|
|
7889
|
+
className: `gantt-resourceTimeline-resourceHeader${menuOpen ? " gantt-resourceTimeline-resourceHeaderMenuOpen" : ""}`,
|
|
7890
|
+
"data-resource-row-id": resourceId,
|
|
7891
|
+
style: {
|
|
7892
|
+
height: `${height}px`,
|
|
7893
|
+
paddingBottom: `${paddingBottom}px`
|
|
7894
|
+
},
|
|
7895
|
+
children: [
|
|
7896
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-resourceName", children: resource.name }),
|
|
7897
|
+
conflictCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7898
|
+
"span",
|
|
7899
|
+
{
|
|
7900
|
+
className: "gantt-resourceTimeline-conflictBadge",
|
|
7901
|
+
"aria-label": formatOverlapCount(conflictCount),
|
|
7902
|
+
title: formatOverlapCount(conflictCount),
|
|
7903
|
+
children: conflictCount
|
|
7904
|
+
}
|
|
7905
|
+
),
|
|
7906
|
+
hasMenu && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Popover, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
7907
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7908
|
+
"button",
|
|
7909
|
+
{
|
|
7910
|
+
className: "gantt-resourceTimeline-resourceMenuButton",
|
|
7911
|
+
type: "button",
|
|
7912
|
+
"aria-label": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0440\u0435\u0441\u0443\u0440\u0441\u0430",
|
|
7913
|
+
onClick: (event) => {
|
|
7914
|
+
event.stopPropagation();
|
|
7915
|
+
setMenuOpen((open) => !open);
|
|
7916
|
+
},
|
|
7917
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { "aria-hidden": "true", children: "\u22EE" })
|
|
7918
|
+
}
|
|
7919
|
+
) }),
|
|
7920
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverContent, { className: "gantt-resourceTimeline-resourceMenu", portal: true, align: "end", children: visibleCommands.map((command) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7921
|
+
"button",
|
|
7922
|
+
{
|
|
7923
|
+
type: "button",
|
|
7924
|
+
className: `gantt-resourceTimeline-resourceMenuItem${command.danger ? " gantt-resourceTimeline-resourceMenuItemDanger" : ""}`,
|
|
7925
|
+
disabled: command.isDisabled?.(resource) ?? false,
|
|
7926
|
+
onClick: (event) => handleCommandClick(command, event),
|
|
7927
|
+
children: [
|
|
7928
|
+
command.icon,
|
|
7929
|
+
command.label
|
|
7930
|
+
]
|
|
7931
|
+
},
|
|
7932
|
+
command.id
|
|
7933
|
+
)) })
|
|
7934
|
+
] })
|
|
7935
|
+
]
|
|
7936
|
+
}
|
|
7937
|
+
);
|
|
7938
|
+
};
|
|
7939
|
+
var NewResourceRow = ({ height, onConfirm, onCancel }) => {
|
|
7940
|
+
const [nameValue, setNameValue] = (0, import_react14.useState)("");
|
|
7941
|
+
const inputRef = (0, import_react14.useRef)(null);
|
|
7942
|
+
const confirmedRef = (0, import_react14.useRef)(false);
|
|
7943
|
+
(0, import_react14.useEffect)(() => {
|
|
7944
|
+
inputRef.current?.focus();
|
|
7945
|
+
inputRef.current?.select();
|
|
7946
|
+
}, []);
|
|
7947
|
+
const handleCancel = () => {
|
|
7948
|
+
confirmedRef.current = true;
|
|
7949
|
+
onCancel();
|
|
7950
|
+
};
|
|
7951
|
+
const handleConfirm = () => {
|
|
7952
|
+
const name = nameValue.trim();
|
|
7953
|
+
if (!name) {
|
|
7954
|
+
handleCancel();
|
|
7955
|
+
return;
|
|
7956
|
+
}
|
|
7957
|
+
confirmedRef.current = true;
|
|
7958
|
+
onConfirm(name);
|
|
7959
|
+
};
|
|
7960
|
+
const handleKeyDown = (event) => {
|
|
7961
|
+
if (event.key === "Enter") {
|
|
7962
|
+
handleConfirm();
|
|
7963
|
+
} else if (event.key === "Escape") {
|
|
7964
|
+
handleCancel();
|
|
7965
|
+
}
|
|
7966
|
+
};
|
|
7967
|
+
const handleBlur = () => {
|
|
7968
|
+
if (!confirmedRef.current) {
|
|
7969
|
+
handleConfirm();
|
|
7970
|
+
}
|
|
7971
|
+
};
|
|
7972
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7973
|
+
"div",
|
|
7974
|
+
{
|
|
7975
|
+
className: "gantt-resourceTimeline-resourceHeader gantt-resourceTimeline-resourceHeaderNew",
|
|
7976
|
+
style: {
|
|
7977
|
+
height: `${height}px`,
|
|
7978
|
+
paddingBottom: `${DEFAULT_RESOURCE_ROW_GAP}px`
|
|
7979
|
+
},
|
|
7980
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7981
|
+
Input,
|
|
7982
|
+
{
|
|
7983
|
+
ref: inputRef,
|
|
7984
|
+
value: nameValue,
|
|
7985
|
+
onChange: (event) => setNameValue(event.target.value),
|
|
7986
|
+
onKeyDown: handleKeyDown,
|
|
7987
|
+
onBlur: handleBlur,
|
|
7988
|
+
placeholder: "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430",
|
|
7989
|
+
className: "gantt-resourceTimeline-resourceInput"
|
|
7990
|
+
}
|
|
7991
|
+
)
|
|
7992
|
+
}
|
|
7993
|
+
);
|
|
7994
|
+
};
|
|
7789
7995
|
function ResourceTimelineChart({
|
|
7790
7996
|
resources,
|
|
7791
7997
|
dayWidth = DEFAULT_DAY_WIDTH,
|
|
@@ -7803,11 +8009,15 @@ function ResourceTimelineChart({
|
|
|
7803
8009
|
renderItem,
|
|
7804
8010
|
getItemClassName,
|
|
7805
8011
|
onResourceItemClick,
|
|
7806
|
-
onResourceItemMove
|
|
8012
|
+
onResourceItemMove,
|
|
8013
|
+
onAddResource,
|
|
8014
|
+
enableAddResource = true,
|
|
8015
|
+
resourceMenuCommands = []
|
|
7807
8016
|
}) {
|
|
7808
8017
|
const scrollContainerRef = (0, import_react14.useRef)(null);
|
|
7809
8018
|
const gridRef = (0, import_react14.useRef)(null);
|
|
7810
8019
|
const panStateRef = (0, import_react14.useRef)(null);
|
|
8020
|
+
const [isCreatingResource, setIsCreatingResource] = (0, import_react14.useState)(false);
|
|
7811
8021
|
const validItems = (0, import_react14.useMemo)(() => collectValidItems(resources), [resources]);
|
|
7812
8022
|
const dateRange = (0, import_react14.useMemo)(() => getMultiMonthDays(validItems), [validItems]);
|
|
7813
8023
|
const monthStart = (0, import_react14.useMemo)(() => {
|
|
@@ -7842,6 +8052,18 @@ function ResourceTimelineChart({
|
|
|
7842
8052
|
}
|
|
7843
8053
|
return map;
|
|
7844
8054
|
}, [layout.items]);
|
|
8055
|
+
const canAddResource = enableAddResource && Boolean(onAddResource);
|
|
8056
|
+
const resourceAddRowHeight = laneHeight + DEFAULT_RESOURCE_ROW_GAP;
|
|
8057
|
+
const displayTotalHeight = layout.totalHeight + (canAddResource ? resourceAddRowHeight : 0);
|
|
8058
|
+
const handleConfirmNewResource = (0, import_react14.useCallback)((name) => {
|
|
8059
|
+
onAddResource?.({
|
|
8060
|
+
id: crypto.randomUUID(),
|
|
8061
|
+
name,
|
|
8062
|
+
items: []
|
|
8063
|
+
});
|
|
8064
|
+
setIsCreatingResource(false);
|
|
8065
|
+
}, [onAddResource]);
|
|
8066
|
+
const handleCancelNewResource = (0, import_react14.useCallback)(() => setIsCreatingResource(false), []);
|
|
7845
8067
|
const { preview, startDrag } = useResourceItemDrag({
|
|
7846
8068
|
dayWidth,
|
|
7847
8069
|
monthStart,
|
|
@@ -7936,28 +8158,34 @@ function ResourceTimelineChart({
|
|
|
7936
8158
|
style: { height: `${headerHeight}px` }
|
|
7937
8159
|
}
|
|
7938
8160
|
),
|
|
7939
|
-
layout.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime15.
|
|
7940
|
-
|
|
8161
|
+
layout.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8162
|
+
ResourceHeader,
|
|
7941
8163
|
{
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
children: [
|
|
7949
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-resourceName", children: row.resource.name }),
|
|
7950
|
-
row.conflictCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7951
|
-
"span",
|
|
7952
|
-
{
|
|
7953
|
-
className: "gantt-resourceTimeline-conflictBadge",
|
|
7954
|
-
"aria-label": `${row.conflictCount} \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u043E\u0432`,
|
|
7955
|
-
children: row.conflictCount
|
|
7956
|
-
}
|
|
7957
|
-
)
|
|
7958
|
-
]
|
|
8164
|
+
resource: row.resource,
|
|
8165
|
+
resourceId: row.resourceId,
|
|
8166
|
+
conflictCount: row.conflictCount,
|
|
8167
|
+
height: row.resourceRowHeight + DEFAULT_RESOURCE_ROW_GAP,
|
|
8168
|
+
paddingBottom: DEFAULT_RESOURCE_ROW_GAP,
|
|
8169
|
+
menuCommands: resourceMenuCommands
|
|
7959
8170
|
},
|
|
7960
8171
|
row.resourceId
|
|
8172
|
+
)),
|
|
8173
|
+
canAddResource && (isCreatingResource ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8174
|
+
NewResourceRow,
|
|
8175
|
+
{
|
|
8176
|
+
height: resourceAddRowHeight,
|
|
8177
|
+
onConfirm: handleConfirmNewResource,
|
|
8178
|
+
onCancel: handleCancelNewResource
|
|
8179
|
+
}
|
|
8180
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8181
|
+
"button",
|
|
8182
|
+
{
|
|
8183
|
+
className: "gantt-resourceTimeline-addResourceButton",
|
|
8184
|
+
type: "button",
|
|
8185
|
+
style: { height: `${resourceAddRowHeight}px` },
|
|
8186
|
+
onClick: () => setIsCreatingResource(true),
|
|
8187
|
+
children: "+ \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0440\u0435\u0441\u0443\u0440\u0441"
|
|
8188
|
+
}
|
|
7961
8189
|
))
|
|
7962
8190
|
]
|
|
7963
8191
|
}
|
|
@@ -7983,14 +8211,14 @@ function ResourceTimelineChart({
|
|
|
7983
8211
|
{
|
|
7984
8212
|
ref: gridRef,
|
|
7985
8213
|
className: "gantt-resourceTimeline-grid",
|
|
7986
|
-
style: { width: `${gridWidth}px`, height: `${
|
|
8214
|
+
style: { width: `${gridWidth}px`, height: `${displayTotalHeight}px` },
|
|
7987
8215
|
children: [
|
|
7988
8216
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7989
8217
|
GridBackground_default,
|
|
7990
8218
|
{
|
|
7991
8219
|
dateRange,
|
|
7992
8220
|
dayWidth,
|
|
7993
|
-
totalHeight:
|
|
8221
|
+
totalHeight: displayTotalHeight,
|
|
7994
8222
|
viewMode,
|
|
7995
8223
|
isCustomWeekend: weekendPredicate
|
|
7996
8224
|
}
|
|
@@ -8008,6 +8236,17 @@ function ResourceTimelineChart({
|
|
|
8008
8236
|
},
|
|
8009
8237
|
row.resourceId
|
|
8010
8238
|
)),
|
|
8239
|
+
canAddResource && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8240
|
+
"div",
|
|
8241
|
+
{
|
|
8242
|
+
className: "gantt-resourceTimeline-row gantt-resourceTimeline-rowNew",
|
|
8243
|
+
"data-resource-add-row": "true",
|
|
8244
|
+
style: {
|
|
8245
|
+
top: `${layout.totalHeight}px`,
|
|
8246
|
+
height: `${resourceAddRowHeight}px`
|
|
8247
|
+
}
|
|
8248
|
+
}
|
|
8249
|
+
),
|
|
8011
8250
|
Array.from(itemsByResourceId.values()).flatMap(
|
|
8012
8251
|
(resourceItems) => resourceItems.map((layoutItem) => {
|
|
8013
8252
|
const customClassName = getItemClassName?.(layoutItem.item);
|
|
@@ -8033,11 +8272,17 @@ function ResourceTimelineChart({
|
|
|
8033
8272
|
}, layoutItem.laneIndex, laneCount);
|
|
8034
8273
|
const overlayStartDate = isDraggingItem ? preview.startDate : layoutItem.startDate;
|
|
8035
8274
|
const overlayEndDate = isDraggingItem ? preview.endDate : layoutItem.endDate;
|
|
8036
|
-
const weekendOverlaySegments = businessDays ?
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8275
|
+
const weekendOverlaySegments = businessDays ? clampOverlaySegments(
|
|
8276
|
+
getWeekendOverlaySegments(overlayStartDate, overlayEndDate, dayWidth, weekendPredicate),
|
|
8277
|
+
itemGeometry.width
|
|
8278
|
+
) : [];
|
|
8279
|
+
const conflictOverlaySegments = clampOverlaySegments(
|
|
8280
|
+
getRangeOverlaySegments(
|
|
8281
|
+
overlayStartDate,
|
|
8282
|
+
isDraggingItem ? [] : layoutItem.conflictRanges,
|
|
8283
|
+
dayWidth
|
|
8284
|
+
),
|
|
8285
|
+
itemGeometry.width
|
|
8041
8286
|
);
|
|
8042
8287
|
const durationValue = getDurationValue(
|
|
8043
8288
|
overlayStartDate,
|
|
@@ -8056,6 +8301,7 @@ function ResourceTimelineChart({
|
|
|
8056
8301
|
{
|
|
8057
8302
|
className,
|
|
8058
8303
|
"data-resource-item-id": layoutItem.itemId,
|
|
8304
|
+
"data-resource-item-tooltip": layoutItem.item.title,
|
|
8059
8305
|
onMouseDown: (event) => startDrag(event, layoutItem),
|
|
8060
8306
|
onClick: () => onResourceItemClick?.(layoutItem.item),
|
|
8061
8307
|
onKeyDown: (event) => {
|
|
@@ -9192,7 +9438,16 @@ Button.displayName = "Button";
|
|
|
9192
9438
|
var and = (...predicates) => (task) => predicates.every((p) => p(task));
|
|
9193
9439
|
var or = (...predicates) => (task) => predicates.some((p) => p(task));
|
|
9194
9440
|
var not = (predicate) => (task) => !predicate(task);
|
|
9195
|
-
var withoutDeps = () => (task) =>
|
|
9441
|
+
var withoutDeps = (options = {}) => (task) => {
|
|
9442
|
+
if (!task) return false;
|
|
9443
|
+
if (options.onlyChildren && !task.parentId) return false;
|
|
9444
|
+
if (options.onlyLeafTasks) {
|
|
9445
|
+
const isParent = (options.tasks ?? []).some((candidate) => candidate.parentId === task.id);
|
|
9446
|
+
const isRegularTask = task.type == null || task.type === "task";
|
|
9447
|
+
if (isParent || !isRegularTask) return false;
|
|
9448
|
+
}
|
|
9449
|
+
return !task.dependencies || task.dependencies.length === 0;
|
|
9450
|
+
};
|
|
9196
9451
|
var expired = (referenceDate = /* @__PURE__ */ new Date()) => (task) => isTaskExpired(task, referenceDate);
|
|
9197
9452
|
var inDateRange = (rangeStart, rangeEnd) => (task) => {
|
|
9198
9453
|
if (!task) return false;
|