gantt-lib 0.17.2 → 0.19.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 +95 -3
- package/dist/index.d.ts +95 -3
- package/dist/index.js +1058 -470
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1063 -471
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +15 -44
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
"use strict";
|
|
2
4
|
"use client";
|
|
3
5
|
var __create = Object.create;
|
|
@@ -34,6 +36,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
34
36
|
// src/utils/dateUtils.ts
|
|
35
37
|
var dateUtils_exports = {};
|
|
36
38
|
__export(dateUtils_exports, {
|
|
39
|
+
createDateKey: () => createDateKey,
|
|
40
|
+
createIsWeekendPredicate: () => createIsWeekendPredicate,
|
|
37
41
|
formatDateLabel: () => formatDateLabel,
|
|
38
42
|
getDayOffset: () => getDayOffset,
|
|
39
43
|
getMonthBlocks: () => getMonthBlocks,
|
|
@@ -48,7 +52,7 @@ __export(dateUtils_exports, {
|
|
|
48
52
|
normalizeTaskDates: () => normalizeTaskDates,
|
|
49
53
|
parseUTCDate: () => parseUTCDate
|
|
50
54
|
});
|
|
51
|
-
var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, getMultiMonthDays, getMonthSpans, formatDateLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
|
|
55
|
+
var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, createDateKey, createIsWeekendPredicate, getMultiMonthDays, getMonthSpans, formatDateLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
|
|
52
56
|
var init_dateUtils = __esm({
|
|
53
57
|
"src/utils/dateUtils.ts"() {
|
|
54
58
|
"use strict";
|
|
@@ -105,6 +109,41 @@ var init_dateUtils = __esm({
|
|
|
105
109
|
const day = date.getUTCDay();
|
|
106
110
|
return day === 0 || day === 6;
|
|
107
111
|
};
|
|
112
|
+
createDateKey = (date) => {
|
|
113
|
+
return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;
|
|
114
|
+
};
|
|
115
|
+
createIsWeekendPredicate = (config) => {
|
|
116
|
+
const { weekends, workdays, isWeekend: customPredicate } = config;
|
|
117
|
+
if (customPredicate) {
|
|
118
|
+
return customPredicate;
|
|
119
|
+
}
|
|
120
|
+
if (workdays && workdays.length > 0) {
|
|
121
|
+
const workdaySet = new Set(workdays.map(createDateKey));
|
|
122
|
+
return (date) => {
|
|
123
|
+
const key = createDateKey(date);
|
|
124
|
+
if (workdaySet.has(key)) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
const dayOfWeek = date.getUTCDay();
|
|
128
|
+
return dayOfWeek === 0 || dayOfWeek === 6;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (weekends && weekends.length > 0) {
|
|
132
|
+
const weekendSet = new Set(weekends.map(createDateKey));
|
|
133
|
+
return (date) => {
|
|
134
|
+
const key = createDateKey(date);
|
|
135
|
+
if (weekendSet.has(key)) {
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
const dayOfWeek = date.getUTCDay();
|
|
139
|
+
return dayOfWeek === 0 || dayOfWeek === 6;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return (date) => {
|
|
143
|
+
const dayOfWeek = date.getUTCDay();
|
|
144
|
+
return dayOfWeek === 0 || dayOfWeek === 6;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
108
147
|
getMultiMonthDays = (tasks) => {
|
|
109
148
|
if (!tasks || tasks.length === 0) {
|
|
110
149
|
return getMonthDays(/* @__PURE__ */ new Date());
|
|
@@ -341,6 +380,8 @@ __export(index_exports, {
|
|
|
341
380
|
computeLagFromDates: () => computeLagFromDates,
|
|
342
381
|
computeParentDates: () => computeParentDates,
|
|
343
382
|
computeParentProgress: () => computeParentProgress,
|
|
383
|
+
createDateKey: () => createDateKey,
|
|
384
|
+
createIsWeekendPredicate: () => createIsWeekendPredicate,
|
|
344
385
|
detectCycles: () => detectCycles,
|
|
345
386
|
detectEdgeZone: () => detectEdgeZone,
|
|
346
387
|
findParentId: () => findParentId,
|
|
@@ -894,7 +935,8 @@ var TimeScaleHeader = ({
|
|
|
894
935
|
days,
|
|
895
936
|
dayWidth,
|
|
896
937
|
headerHeight,
|
|
897
|
-
viewMode = "day"
|
|
938
|
+
viewMode = "day",
|
|
939
|
+
isCustomWeekend
|
|
898
940
|
}) => {
|
|
899
941
|
const monthSpans = (0, import_react.useMemo)(() => getMonthSpans(days), [days]);
|
|
900
942
|
const rowHeight = headerHeight / 2;
|
|
@@ -1058,12 +1100,12 @@ var TimeScaleHeader = ({
|
|
|
1058
1100
|
) : (
|
|
1059
1101
|
// Day-view row 2: individual day numbers (existing code)
|
|
1060
1102
|
days.map((day, index) => {
|
|
1061
|
-
const
|
|
1103
|
+
const isWeekendDay = isCustomWeekend ? isCustomWeekend(day) : day.getUTCDay() === 0 || day.getUTCDay() === 6;
|
|
1062
1104
|
const prevDay = days[index - 1];
|
|
1063
|
-
const isMonthBoundary = index > 0 && prevDay && prevDay.
|
|
1105
|
+
const isMonthBoundary = index > 0 && prevDay && prevDay.getUTCMonth() !== day.getUTCMonth();
|
|
1064
1106
|
const now = /* @__PURE__ */ new Date();
|
|
1065
1107
|
const isTodayDate = day.getUTCFullYear() === now.getFullYear() && day.getUTCMonth() === now.getMonth() && day.getUTCDate() === now.getDate();
|
|
1066
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `gantt-tsh-dayCell ${
|
|
1108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `gantt-tsh-dayCell ${isWeekendDay ? "gantt-tsh-weekendDay" : ""} ${isTodayDate ? "gantt-tsh-today" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gantt-tsh-dayLabel", children: (0, import_date_fns.format)(day, "d") }) }, `day-${index}`);
|
|
1067
1109
|
})
|
|
1068
1110
|
)
|
|
1069
1111
|
}
|
|
@@ -1156,14 +1198,13 @@ var calculateGridLines = (dateRange, dayWidth) => {
|
|
|
1156
1198
|
}
|
|
1157
1199
|
return lines;
|
|
1158
1200
|
};
|
|
1159
|
-
var calculateWeekendBlocks = (dateRange, dayWidth) => {
|
|
1201
|
+
var calculateWeekendBlocks = (dateRange, dayWidth, isCustomWeekend) => {
|
|
1160
1202
|
const blocks = [];
|
|
1161
1203
|
let inWeekend = false;
|
|
1162
1204
|
let weekendStartIndex = -1;
|
|
1163
1205
|
for (let i = 0; i < dateRange.length; i++) {
|
|
1164
1206
|
const date = dateRange[i];
|
|
1165
|
-
const
|
|
1166
|
-
const isWeekend3 = dayOfWeek === 0 || dayOfWeek === 6;
|
|
1207
|
+
const isWeekend3 = isCustomWeekend ? isCustomWeekend(date) : date.getUTCDay() === 0 || date.getUTCDay() === 6;
|
|
1167
1208
|
if (isWeekend3 && !inWeekend) {
|
|
1168
1209
|
inWeekend = true;
|
|
1169
1210
|
weekendStartIndex = i;
|
|
@@ -1979,10 +2020,10 @@ var import_react5 = __toESM(require("react"));
|
|
|
1979
2020
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1980
2021
|
var arePropsEqual2 = (prevProps, nextProps) => {
|
|
1981
2022
|
return prevProps.dayWidth === nextProps.dayWidth && prevProps.dateRange.length === nextProps.dateRange.length && prevProps.totalHeight === nextProps.totalHeight && // skip re-render only when totalHeight unchanged
|
|
1982
|
-
prevProps.viewMode === nextProps.viewMode;
|
|
2023
|
+
prevProps.viewMode === nextProps.viewMode && prevProps.isCustomWeekend === nextProps.isCustomWeekend;
|
|
1983
2024
|
};
|
|
1984
2025
|
var GridBackground = import_react5.default.memo(
|
|
1985
|
-
({ dateRange, dayWidth, totalHeight, viewMode = "day" }) => {
|
|
2026
|
+
({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend }) => {
|
|
1986
2027
|
const weekGridLines = (0, import_react5.useMemo)(() => {
|
|
1987
2028
|
if (viewMode !== "week") return [];
|
|
1988
2029
|
return calculateWeekGridLines(dateRange, dayWidth);
|
|
@@ -1997,8 +2038,8 @@ var GridBackground = import_react5.default.memo(
|
|
|
1997
2038
|
}, [dateRange, dayWidth, viewMode]);
|
|
1998
2039
|
const weekendBlocks = (0, import_react5.useMemo)(() => {
|
|
1999
2040
|
if (viewMode === "week" || viewMode === "month") return [];
|
|
2000
|
-
return calculateWeekendBlocks(dateRange, dayWidth);
|
|
2001
|
-
}, [dateRange, dayWidth, viewMode]);
|
|
2041
|
+
return calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend);
|
|
2042
|
+
}, [dateRange, dayWidth, viewMode, isCustomWeekend]);
|
|
2002
2043
|
const gridWidth = (0, import_react5.useMemo)(() => {
|
|
2003
2044
|
return Math.round(dateRange.length * dayWidth);
|
|
2004
2045
|
}, [dateRange.length, dayWidth]);
|
|
@@ -2495,12 +2536,13 @@ var import_date_fns3 = require("date-fns");
|
|
|
2495
2536
|
var import_react8 = require("react");
|
|
2496
2537
|
var import_date_fns2 = require("date-fns");
|
|
2497
2538
|
var import_locale2 = require("date-fns/locale");
|
|
2539
|
+
init_dateUtils();
|
|
2498
2540
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2499
|
-
function getDayClassName(day, selected) {
|
|
2541
|
+
function getDayClassName(day, selected, isWeekendProp) {
|
|
2500
2542
|
const classes = ["gantt-day-btn"];
|
|
2501
2543
|
if (selected && (0, import_date_fns2.isSameDay)(day, selected)) classes.push("selected");
|
|
2502
2544
|
if ((0, import_date_fns2.isToday)(day)) classes.push("today");
|
|
2503
|
-
if ((0, import_date_fns2.isWeekend)(day)) classes.push("weekend");
|
|
2545
|
+
if (isWeekendProp ? isWeekendProp(day) : (0, import_date_fns2.isWeekend)(day)) classes.push("weekend");
|
|
2504
2546
|
if ((0, import_date_fns2.isBefore)(day, (0, import_date_fns2.startOfDay)(/* @__PURE__ */ new Date())) && !(0, import_date_fns2.isToday)(day)) classes.push("past");
|
|
2505
2547
|
return classes.join(" ");
|
|
2506
2548
|
}
|
|
@@ -2509,9 +2551,22 @@ var Calendar = ({
|
|
|
2509
2551
|
onSelect,
|
|
2510
2552
|
initialDate,
|
|
2511
2553
|
mode = "single",
|
|
2512
|
-
disabled = false
|
|
2554
|
+
disabled = false,
|
|
2555
|
+
isWeekend: isWeekendProp,
|
|
2556
|
+
weekends,
|
|
2557
|
+
workdays
|
|
2513
2558
|
}) => {
|
|
2514
2559
|
const scrollRef = (0, import_react8.useRef)(null);
|
|
2560
|
+
const derivedWeekendPredicate = (0, import_react8.useMemo)(() => {
|
|
2561
|
+
if (isWeekendProp) return isWeekendProp;
|
|
2562
|
+
if (weekends || workdays) {
|
|
2563
|
+
return createIsWeekendPredicate({
|
|
2564
|
+
weekends: weekends ?? [],
|
|
2565
|
+
workdays: workdays ?? []
|
|
2566
|
+
});
|
|
2567
|
+
}
|
|
2568
|
+
return void 0;
|
|
2569
|
+
}, [isWeekendProp, weekends, workdays]);
|
|
2515
2570
|
const initialMonth = (0, import_react8.useMemo)(
|
|
2516
2571
|
() => (0, import_date_fns2.startOfMonth)(initialDate ?? selected ?? /* @__PURE__ */ new Date()),
|
|
2517
2572
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -2565,11 +2620,13 @@ var Calendar = ({
|
|
|
2565
2620
|
const emptyDays = ((0, import_date_fns2.getDay)(firstDay) + 6) % 7;
|
|
2566
2621
|
const monthKey = (0, import_date_fns2.format)(month, "yyyy-MM");
|
|
2567
2622
|
const monthLabel = (0, import_date_fns2.format)(month, "LLLL yyyy", { locale: import_locale2.ru });
|
|
2623
|
+
const weekdayLabels = ["\u041F\u043D", "\u0412\u0442", "\u0421\u0440", "\u0427\u0442", "\u041F\u0442", "\u0421\u0431", "\u0412\u0441"];
|
|
2624
|
+
const weekdayHeaders = weekdayLabels.map((label, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "gantt-cal-weekday", children: label }, `wd-${i}`));
|
|
2568
2625
|
const emptyCells = Array.from({ length: emptyDays }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "gantt-cal-empty-day" }, `e-${i}`));
|
|
2569
2626
|
const dayCells = Array.from({ length: totalDays }, (_, i) => {
|
|
2570
2627
|
const dayNum = i + 1;
|
|
2571
|
-
const day = new Date(month.getFullYear(), month.getMonth(), dayNum);
|
|
2572
|
-
const className = getDayClassName(day, selected);
|
|
2628
|
+
const day = new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum));
|
|
2629
|
+
const className = getDayClassName(day, selected, derivedWeekendPredicate);
|
|
2573
2630
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2574
2631
|
"button",
|
|
2575
2632
|
{
|
|
@@ -2578,7 +2635,7 @@ var Calendar = ({
|
|
|
2578
2635
|
disabled,
|
|
2579
2636
|
onClick: () => {
|
|
2580
2637
|
if (!disabled && onSelect) {
|
|
2581
|
-
onSelect(new Date(month.getFullYear(), month.getMonth(), dayNum));
|
|
2638
|
+
onSelect(new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum)));
|
|
2582
2639
|
}
|
|
2583
2640
|
},
|
|
2584
2641
|
children: dayNum
|
|
@@ -2589,12 +2646,13 @@ var Calendar = ({
|
|
|
2589
2646
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "gantt-cal-month", "data-month": monthKey, children: [
|
|
2590
2647
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "gantt-cal-month-header", children: monthLabel }),
|
|
2591
2648
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "gantt-cal-month-days", children: [
|
|
2649
|
+
weekdayHeaders,
|
|
2592
2650
|
emptyCells,
|
|
2593
2651
|
dayCells
|
|
2594
2652
|
] })
|
|
2595
2653
|
] }, monthKey);
|
|
2596
2654
|
},
|
|
2597
|
-
[selected, onSelect, disabled]
|
|
2655
|
+
[selected, onSelect, disabled, derivedWeekendPredicate]
|
|
2598
2656
|
);
|
|
2599
2657
|
const renderedMonths = (0, import_react8.useMemo)(
|
|
2600
2658
|
() => months.map(renderMonth),
|
|
@@ -2618,7 +2676,10 @@ var DatePicker = ({
|
|
|
2618
2676
|
placeholder = "Pick a date",
|
|
2619
2677
|
portal = true,
|
|
2620
2678
|
className,
|
|
2621
|
-
disabled = false
|
|
2679
|
+
disabled = false,
|
|
2680
|
+
weekends,
|
|
2681
|
+
workdays,
|
|
2682
|
+
isWeekend: isWeekend3
|
|
2622
2683
|
}) => {
|
|
2623
2684
|
const [open, setOpen] = (0, import_react9.useState)(false);
|
|
2624
2685
|
const [inputValue, setInputValue] = (0, import_react9.useState)("");
|
|
@@ -2838,7 +2899,10 @@ var DatePicker = ({
|
|
|
2838
2899
|
mode: "single",
|
|
2839
2900
|
selected: selectedDate,
|
|
2840
2901
|
onSelect: handleCalendarSelect,
|
|
2841
|
-
initialDate: selectedDate
|
|
2902
|
+
initialDate: selectedDate,
|
|
2903
|
+
weekends,
|
|
2904
|
+
workdays,
|
|
2905
|
+
isWeekend: isWeekend3
|
|
2842
2906
|
}
|
|
2843
2907
|
)
|
|
2844
2908
|
]
|
|
@@ -2887,18 +2951,49 @@ var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
|
2887
2951
|
var getInclusiveDurationDays = (startDate, endDate) => {
|
|
2888
2952
|
const start = parseUTCDate(startDate);
|
|
2889
2953
|
const end = parseUTCDate(endDate);
|
|
2890
|
-
return Math.max(
|
|
2954
|
+
return Math.max(
|
|
2955
|
+
1,
|
|
2956
|
+
Math.round((end.getTime() - start.getTime()) / DAY_MS2) + 1
|
|
2957
|
+
);
|
|
2891
2958
|
};
|
|
2892
2959
|
var getEndDateFromDuration = (startDate, durationDays) => {
|
|
2893
2960
|
const start = parseUTCDate(startDate);
|
|
2894
2961
|
return new Date(start.getTime() + (durationDays - 1) * DAY_MS2).toISOString().split("T")[0];
|
|
2895
2962
|
};
|
|
2896
|
-
var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2963
|
+
var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2964
|
+
"svg",
|
|
2965
|
+
{
|
|
2966
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2967
|
+
width: "12",
|
|
2968
|
+
height: "12",
|
|
2969
|
+
viewBox: "0 0 24 24",
|
|
2970
|
+
fill: "none",
|
|
2971
|
+
stroke: "currentColor",
|
|
2972
|
+
strokeWidth: "2",
|
|
2973
|
+
strokeLinecap: "round",
|
|
2974
|
+
strokeLinejoin: "round",
|
|
2975
|
+
children: [
|
|
2976
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
|
|
2977
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M3 6h18" }),
|
|
2978
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
2979
|
+
]
|
|
2980
|
+
}
|
|
2981
|
+
);
|
|
2982
|
+
var PlusIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2983
|
+
"svg",
|
|
2984
|
+
{
|
|
2985
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2986
|
+
width: "14",
|
|
2987
|
+
height: "14",
|
|
2988
|
+
viewBox: "0 0 24 24",
|
|
2989
|
+
fill: "none",
|
|
2990
|
+
stroke: "currentColor",
|
|
2991
|
+
strokeWidth: "2",
|
|
2992
|
+
strokeLinecap: "round",
|
|
2993
|
+
strokeLinejoin: "round",
|
|
2994
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M12 5v14M5 12h14" })
|
|
2995
|
+
}
|
|
2996
|
+
);
|
|
2902
2997
|
var DragHandleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "10", height: "14", viewBox: "0 0 10 14", fill: "currentColor", children: [
|
|
2903
2998
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "2", cy: "2", r: "1.5" }),
|
|
2904
2999
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "8", cy: "2", r: "1.5" }),
|
|
@@ -2907,51 +3002,94 @@ var DragHandleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg",
|
|
|
2907
3002
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "2", cy: "12", r: "1.5" }),
|
|
2908
3003
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "8", cy: "12", r: "1.5" })
|
|
2909
3004
|
] });
|
|
2910
|
-
var ChevronRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
3005
|
+
var ChevronRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3006
|
+
"svg",
|
|
3007
|
+
{
|
|
3008
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3009
|
+
width: "14",
|
|
3010
|
+
height: "14",
|
|
3011
|
+
viewBox: "0 0 24 24",
|
|
3012
|
+
fill: "none",
|
|
3013
|
+
stroke: "currentColor",
|
|
3014
|
+
strokeWidth: "2",
|
|
3015
|
+
strokeLinecap: "round",
|
|
3016
|
+
strokeLinejoin: "round",
|
|
3017
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m9 18 6-6-6-6" })
|
|
3018
|
+
}
|
|
3019
|
+
);
|
|
3020
|
+
var ArrowLeft = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
3021
|
+
"svg",
|
|
3022
|
+
{
|
|
3023
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3024
|
+
width: "16",
|
|
3025
|
+
height: "16",
|
|
3026
|
+
viewBox: "0 0 24 24",
|
|
3027
|
+
fill: "none",
|
|
3028
|
+
stroke: "currentColor",
|
|
3029
|
+
strokeWidth: "2",
|
|
3030
|
+
strokeLinecap: "round",
|
|
3031
|
+
strokeLinejoin: "round",
|
|
3032
|
+
children: [
|
|
3033
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m12 19-7-7 7-7" }),
|
|
3034
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M19 12H5" })
|
|
3035
|
+
]
|
|
3036
|
+
}
|
|
3037
|
+
);
|
|
3038
|
+
var ArrowRight = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
3039
|
+
"svg",
|
|
3040
|
+
{
|
|
3041
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3042
|
+
width: "16",
|
|
3043
|
+
height: "16",
|
|
3044
|
+
viewBox: "0 0 24 24",
|
|
3045
|
+
fill: "none",
|
|
3046
|
+
stroke: "currentColor",
|
|
3047
|
+
strokeWidth: "2",
|
|
3048
|
+
strokeLinecap: "round",
|
|
3049
|
+
strokeLinejoin: "round",
|
|
3050
|
+
children: [
|
|
3051
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M5 12h14" }),
|
|
3052
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m12 5 7 7-7 7" })
|
|
3053
|
+
]
|
|
3054
|
+
}
|
|
3055
|
+
);
|
|
2916
3056
|
var HierarchyButton = ({
|
|
2917
3057
|
isChild,
|
|
2918
|
-
|
|
2919
|
-
rowIndex,
|
|
3058
|
+
rowIndex: _rowIndex,
|
|
2920
3059
|
onPromote,
|
|
2921
3060
|
onDemote
|
|
2922
3061
|
}) => {
|
|
2923
3062
|
const canPromote = isChild && onPromote;
|
|
2924
|
-
const canDemote =
|
|
2925
|
-
if (!canPromote && !canDemote)
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
3063
|
+
const canDemote = !!onDemote;
|
|
3064
|
+
if (!canPromote && !canDemote) return null;
|
|
3065
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
3066
|
+
canPromote && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3067
|
+
"button",
|
|
3068
|
+
{
|
|
3069
|
+
type: "button",
|
|
3070
|
+
className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
|
|
3071
|
+
onClick: (e) => {
|
|
3072
|
+
e.stopPropagation();
|
|
3073
|
+
onPromote(e);
|
|
3074
|
+
},
|
|
3075
|
+
title: "\u041F\u043E\u0432\u044B\u0441\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
|
|
3076
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ArrowLeft, {})
|
|
3077
|
+
}
|
|
3078
|
+
),
|
|
3079
|
+
canDemote && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3080
|
+
"button",
|
|
3081
|
+
{
|
|
3082
|
+
type: "button",
|
|
3083
|
+
className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
|
|
3084
|
+
onClick: (e) => {
|
|
3085
|
+
e.stopPropagation();
|
|
3086
|
+
onDemote(e);
|
|
3087
|
+
},
|
|
3088
|
+
title: "\u041F\u043E\u043D\u0438\u0437\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
|
|
3089
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ArrowRight, {})
|
|
3090
|
+
}
|
|
3091
|
+
)
|
|
2944
3092
|
] });
|
|
2945
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2946
|
-
"button",
|
|
2947
|
-
{
|
|
2948
|
-
type: "button",
|
|
2949
|
-
className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
|
|
2950
|
-
onClick: handleClick,
|
|
2951
|
-
title,
|
|
2952
|
-
children: canPromote ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ArrowLeft, {}) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ArrowRight, {})
|
|
2953
|
-
}
|
|
2954
|
-
);
|
|
2955
3093
|
};
|
|
2956
3094
|
var DepChip = ({
|
|
2957
3095
|
lag,
|
|
@@ -2983,71 +3121,91 @@ var DepChip = ({
|
|
|
2983
3121
|
const nextOpen = !popoverOpen;
|
|
2984
3122
|
setPopoverOpen(nextOpen);
|
|
2985
3123
|
if (nextOpen) {
|
|
2986
|
-
onChipSelect?.({
|
|
3124
|
+
onChipSelect?.({
|
|
3125
|
+
successorId: taskId,
|
|
3126
|
+
predecessorId: dep.taskId,
|
|
3127
|
+
linkType: dep.type
|
|
3128
|
+
});
|
|
2987
3129
|
onScrollToTask?.(dep.taskId);
|
|
2988
3130
|
} else {
|
|
2989
3131
|
onChipSelect?.(null);
|
|
2990
3132
|
}
|
|
2991
3133
|
};
|
|
2992
|
-
const handleOpenChange = (0, import_react10.useCallback)(
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3134
|
+
const handleOpenChange = (0, import_react10.useCallback)(
|
|
3135
|
+
(open) => {
|
|
3136
|
+
setPopoverOpen(open);
|
|
3137
|
+
if (!open) {
|
|
3138
|
+
onChipSelect?.(null);
|
|
3139
|
+
}
|
|
3140
|
+
},
|
|
3141
|
+
[onChipSelect]
|
|
3142
|
+
);
|
|
2998
3143
|
const handleTrashClick = (e) => {
|
|
2999
3144
|
e.stopPropagation();
|
|
3000
3145
|
onRemoveDependency?.(taskId, dep.taskId, dep.type);
|
|
3001
3146
|
onChipSelectClear();
|
|
3002
3147
|
setPopoverOpen(false);
|
|
3003
3148
|
};
|
|
3004
|
-
const handleLagChange = (0, import_react10.useCallback)(
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
newStart
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3149
|
+
const handleLagChange = (0, import_react10.useCallback)(
|
|
3150
|
+
(newLag) => {
|
|
3151
|
+
if (!onTasksChange || !allTasks) return;
|
|
3152
|
+
const taskById = new Map(allTasks.map((t) => [t.id, t]));
|
|
3153
|
+
const predecessor = taskById.get(dep.taskId);
|
|
3154
|
+
if (!predecessor) return;
|
|
3155
|
+
const predStart = parseUTCDate(predecessor.startDate);
|
|
3156
|
+
const predEnd = parseUTCDate(predecessor.endDate);
|
|
3157
|
+
const origStart = parseUTCDate(task.startDate);
|
|
3158
|
+
const origEnd = parseUTCDate(task.endDate);
|
|
3159
|
+
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
3160
|
+
const constraintDate = calculateSuccessorDate(
|
|
3161
|
+
predStart,
|
|
3162
|
+
predEnd,
|
|
3163
|
+
dep.type,
|
|
3164
|
+
newLag
|
|
3165
|
+
);
|
|
3166
|
+
let newStart, newEnd;
|
|
3167
|
+
if (dep.type === "FS" || dep.type === "SS") {
|
|
3168
|
+
newStart = constraintDate;
|
|
3169
|
+
newEnd = new Date(constraintDate.getTime() + durationMs);
|
|
3170
|
+
} else {
|
|
3171
|
+
newEnd = constraintDate;
|
|
3172
|
+
newStart = new Date(constraintDate.getTime() - durationMs);
|
|
3173
|
+
}
|
|
3174
|
+
onTasksChange([
|
|
3175
|
+
{
|
|
3176
|
+
...task,
|
|
3177
|
+
startDate: newStart.toISOString().split("T")[0],
|
|
3178
|
+
endDate: newEnd.toISOString().split("T")[0]
|
|
3179
|
+
}
|
|
3180
|
+
]);
|
|
3181
|
+
},
|
|
3182
|
+
[dep, task, allTasks, onTasksChange]
|
|
3183
|
+
);
|
|
3184
|
+
const handleInputCommit = (0, import_react10.useCallback)(
|
|
3185
|
+
(raw) => {
|
|
3186
|
+
if (raw === "") {
|
|
3187
|
+
handleLagChange(0);
|
|
3188
|
+
return;
|
|
3189
|
+
}
|
|
3190
|
+
const parsed = parseInt(raw, 10);
|
|
3191
|
+
const effectiveLag2 = lag ?? 0;
|
|
3192
|
+
if (isNaN(parsed)) {
|
|
3193
|
+
const abs = Math.abs(effectiveLag2);
|
|
3194
|
+
setInputAbs(abs === 0 ? "" : String(abs));
|
|
3195
|
+
return;
|
|
3196
|
+
}
|
|
3197
|
+
let newLag;
|
|
3198
|
+
if (parsed === 0) {
|
|
3199
|
+
newLag = 0;
|
|
3200
|
+
} else if (dep.type === "SF") {
|
|
3201
|
+
newLag = -Math.abs(parsed);
|
|
3202
|
+
} else {
|
|
3203
|
+
newLag = parsed;
|
|
3204
|
+
}
|
|
3205
|
+
if (newLag !== effectiveLag2) handleLagChange(newLag);
|
|
3206
|
+
},
|
|
3207
|
+
[lag, dep.type, handleLagChange]
|
|
3208
|
+
);
|
|
3051
3209
|
const Icon = LINK_TYPE_ICONS[dep.type];
|
|
3052
3210
|
const depName = predecessorName ?? dep.taskId;
|
|
3053
3211
|
const effectiveLag = lag ?? 0;
|
|
@@ -3086,67 +3244,92 @@ var DepChip = ({
|
|
|
3086
3244
|
]
|
|
3087
3245
|
}
|
|
3088
3246
|
) }),
|
|
3089
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3247
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3248
|
+
PopoverContent,
|
|
3249
|
+
{
|
|
3250
|
+
className: "gantt-tl-dep-edit-popover",
|
|
3251
|
+
portal: true,
|
|
3252
|
+
align: "start",
|
|
3253
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { onClick: (e) => e.stopPropagation(), children: [
|
|
3254
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "gantt-tl-dep-edit-task", children: task.name }),
|
|
3255
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-dep-edit-row", children: [
|
|
3256
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "gantt-tl-dep-edit-label", children: [
|
|
3257
|
+
actionVerb,
|
|
3258
|
+
preWord ? ` ${preWord}` : ""
|
|
3259
|
+
] }),
|
|
3260
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3261
|
+
"button",
|
|
3262
|
+
{
|
|
3263
|
+
type: "button",
|
|
3264
|
+
className: "gantt-tl-dep-edit-btn",
|
|
3265
|
+
onClick: () => handleLagChange(effectiveLag - 1),
|
|
3266
|
+
children: "\u2212"
|
|
3267
|
+
}
|
|
3268
|
+
),
|
|
3269
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3270
|
+
"input",
|
|
3271
|
+
{
|
|
3272
|
+
type: "number",
|
|
3273
|
+
className: "gantt-tl-dep-edit-input",
|
|
3274
|
+
value: inputAbs,
|
|
3275
|
+
placeholder: zeroPlaceholder,
|
|
3276
|
+
min: "0",
|
|
3277
|
+
onChange: (e) => setInputAbs(e.target.value),
|
|
3278
|
+
onFocus: (e) => e.target.select(),
|
|
3279
|
+
onBlur: (e) => handleInputCommit(e.target.value),
|
|
3280
|
+
onKeyDown: (e) => {
|
|
3281
|
+
if (e.key === "Enter") handleInputCommit(inputAbs);
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
),
|
|
3285
|
+
!(dep.type === "SF" && effectiveLag === 0) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3286
|
+
"button",
|
|
3287
|
+
{
|
|
3288
|
+
type: "button",
|
|
3289
|
+
className: "gantt-tl-dep-edit-btn",
|
|
3290
|
+
onClick: () => handleLagChange(effectiveLag + 1),
|
|
3291
|
+
children: "+"
|
|
3292
|
+
}
|
|
3293
|
+
),
|
|
3294
|
+
effectiveLag !== 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u0434." }),
|
|
3295
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: afterWhat })
|
|
3296
|
+
] }),
|
|
3297
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "gantt-tl-dep-edit-pred", children: depName }),
|
|
3298
|
+
!disableDependencyEditing && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
3299
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("hr", { className: "gantt-tl-dep-edit-divider" }),
|
|
3300
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-dep-edit-actions", children: [
|
|
3301
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3302
|
+
"button",
|
|
3303
|
+
{
|
|
3304
|
+
type: "button",
|
|
3305
|
+
className: "gantt-tl-dep-edit-close",
|
|
3306
|
+
onClick: () => {
|
|
3307
|
+
setPopoverOpen(false);
|
|
3308
|
+
onChipSelectClear();
|
|
3309
|
+
},
|
|
3310
|
+
children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
|
|
3311
|
+
}
|
|
3312
|
+
),
|
|
3313
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3314
|
+
"button",
|
|
3315
|
+
{
|
|
3316
|
+
type: "button",
|
|
3317
|
+
className: "gantt-tl-dep-edit-delete",
|
|
3318
|
+
onClick: handleTrashClick,
|
|
3319
|
+
children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
|
|
3320
|
+
}
|
|
3321
|
+
)
|
|
3322
|
+
] })
|
|
3323
|
+
] })
|
|
3142
3324
|
] })
|
|
3143
|
-
|
|
3144
|
-
|
|
3325
|
+
}
|
|
3326
|
+
)
|
|
3145
3327
|
] });
|
|
3146
3328
|
};
|
|
3147
3329
|
var toISODate = (value) => {
|
|
3148
3330
|
if (value instanceof Date) return value.toISOString().split("T")[0];
|
|
3149
|
-
if (typeof value === "string" && value.includes("T"))
|
|
3331
|
+
if (typeof value === "string" && value.includes("T"))
|
|
3332
|
+
return value.split("T")[0];
|
|
3150
3333
|
return value;
|
|
3151
3334
|
};
|
|
3152
3335
|
var TaskListRow = import_react10.default.memo(
|
|
@@ -3183,13 +3366,20 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3183
3366
|
onToggleCollapse,
|
|
3184
3367
|
onPromoteTask,
|
|
3185
3368
|
onDemoteTask,
|
|
3186
|
-
isLastChild = true
|
|
3369
|
+
isLastChild = true,
|
|
3370
|
+
nestingDepth = 0,
|
|
3371
|
+
ancestorContinues = [],
|
|
3372
|
+
weekends,
|
|
3373
|
+
workdays,
|
|
3374
|
+
isWeekend: isWeekend3
|
|
3187
3375
|
}) => {
|
|
3188
3376
|
const [editingName, setEditingName] = (0, import_react10.useState)(false);
|
|
3189
3377
|
const [nameValue, setNameValue] = (0, import_react10.useState)("");
|
|
3190
3378
|
const nameInputRef = (0, import_react10.useRef)(null);
|
|
3191
3379
|
const [editingDuration, setEditingDuration] = (0, import_react10.useState)(false);
|
|
3192
|
-
const [durationValue, setDurationValue] = (0, import_react10.useState)(
|
|
3380
|
+
const [durationValue, setDurationValue] = (0, import_react10.useState)(
|
|
3381
|
+
getInclusiveDurationDays(task.startDate, task.endDate)
|
|
3382
|
+
);
|
|
3193
3383
|
const durationInputRef = (0, import_react10.useRef)(null);
|
|
3194
3384
|
const [editingProgress, setEditingProgress] = (0, import_react10.useState)(false);
|
|
3195
3385
|
const [progressValue, setProgressValue] = (0, import_react10.useState)(0);
|
|
@@ -3199,11 +3389,16 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3199
3389
|
const durationConfirmedRef = (0, import_react10.useRef)(false);
|
|
3200
3390
|
const progressConfirmedRef = (0, import_react10.useRef)(false);
|
|
3201
3391
|
const autoEditedForRef = (0, import_react10.useRef)(null);
|
|
3202
|
-
const editTriggerRef = (0, import_react10.useRef)(
|
|
3392
|
+
const editTriggerRef = (0, import_react10.useRef)(
|
|
3393
|
+
"doubleclick"
|
|
3394
|
+
);
|
|
3203
3395
|
const [deletePending, setDeletePending] = (0, import_react10.useState)(false);
|
|
3204
3396
|
const deleteButtonRef = (0, import_react10.useRef)(null);
|
|
3205
3397
|
const isSelected = selectedTaskId === task.id;
|
|
3206
|
-
const isParent = (0, import_react10.useMemo)(
|
|
3398
|
+
const isParent = (0, import_react10.useMemo)(
|
|
3399
|
+
() => isTaskParent(task.id, allTasks),
|
|
3400
|
+
[task.id, allTasks]
|
|
3401
|
+
);
|
|
3207
3402
|
const isChild = task.parentId !== void 0;
|
|
3208
3403
|
const isCollapsed = collapsedParentIds.has(task.id);
|
|
3209
3404
|
const isPicking = selectingPredecessorFor != null;
|
|
@@ -3258,31 +3453,40 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3258
3453
|
setEditingName(true);
|
|
3259
3454
|
}
|
|
3260
3455
|
}, [editingTaskId, task.id, disableTaskNameEditing]);
|
|
3261
|
-
const handleNameClick = (0, import_react10.useCallback)(
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
}, [task.name, disableTaskNameEditing]);
|
|
3275
|
-
const handleRowKeyDown = (0, import_react10.useCallback)((e) => {
|
|
3276
|
-
if (editingProgress) return;
|
|
3277
|
-
if (!editingName && !disableTaskNameEditing && e.key === "F2") {
|
|
3278
|
-
e.preventDefault();
|
|
3456
|
+
const handleNameClick = (0, import_react10.useCallback)(
|
|
3457
|
+
(e) => {
|
|
3458
|
+
if (disableTaskNameEditing) return;
|
|
3459
|
+
e.stopPropagation();
|
|
3460
|
+
onRowClick?.(task.id);
|
|
3461
|
+
onScrollToTask?.(task.id);
|
|
3462
|
+
},
|
|
3463
|
+
[task.id, disableTaskNameEditing, onRowClick, onScrollToTask]
|
|
3464
|
+
);
|
|
3465
|
+
const handleNameDoubleClick = (0, import_react10.useCallback)(
|
|
3466
|
+
(e) => {
|
|
3467
|
+
if (disableTaskNameEditing) return;
|
|
3468
|
+
e.stopPropagation();
|
|
3279
3469
|
nameConfirmedRef.current = false;
|
|
3280
|
-
editTriggerRef.current = "
|
|
3470
|
+
editTriggerRef.current = "doubleclick";
|
|
3281
3471
|
setNameValue(task.name);
|
|
3282
3472
|
setEditingName(true);
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3473
|
+
},
|
|
3474
|
+
[task.name, disableTaskNameEditing]
|
|
3475
|
+
);
|
|
3476
|
+
const handleRowKeyDown = (0, import_react10.useCallback)(
|
|
3477
|
+
(e) => {
|
|
3478
|
+
if (editingProgress) return;
|
|
3479
|
+
if (!editingName && !disableTaskNameEditing && e.key === "F2") {
|
|
3480
|
+
e.preventDefault();
|
|
3481
|
+
nameConfirmedRef.current = false;
|
|
3482
|
+
editTriggerRef.current = "keypress";
|
|
3483
|
+
setNameValue(task.name);
|
|
3484
|
+
setEditingName(true);
|
|
3485
|
+
return;
|
|
3486
|
+
}
|
|
3487
|
+
},
|
|
3488
|
+
[editingName, disableTaskNameEditing, task.name]
|
|
3489
|
+
);
|
|
3286
3490
|
const handleNameSave = (0, import_react10.useCallback)(() => {
|
|
3287
3491
|
if (nameConfirmedRef.current) {
|
|
3288
3492
|
nameConfirmedRef.current = false;
|
|
@@ -3296,24 +3500,32 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3296
3500
|
const handleNameCancel = (0, import_react10.useCallback)(() => {
|
|
3297
3501
|
setEditingName(false);
|
|
3298
3502
|
}, []);
|
|
3299
|
-
const handleNameKeyDown = (0, import_react10.useCallback)(
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3503
|
+
const handleNameKeyDown = (0, import_react10.useCallback)(
|
|
3504
|
+
(e) => {
|
|
3505
|
+
if (e.key === "Enter") {
|
|
3506
|
+
nameConfirmedRef.current = true;
|
|
3507
|
+
if (nameValue.trim()) {
|
|
3508
|
+
onTasksChange?.([{ ...task, name: nameValue.trim() }]);
|
|
3509
|
+
}
|
|
3510
|
+
setEditingName(false);
|
|
3511
|
+
} else if (e.key === "Escape") {
|
|
3512
|
+
handleNameCancel();
|
|
3304
3513
|
}
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3514
|
+
},
|
|
3515
|
+
[nameValue, task, onTasksChange, handleNameCancel]
|
|
3516
|
+
);
|
|
3517
|
+
const handleDurationClick = (0, import_react10.useCallback)(
|
|
3518
|
+
(e) => {
|
|
3519
|
+
if (task.locked) return;
|
|
3520
|
+
e.stopPropagation();
|
|
3521
|
+
durationConfirmedRef.current = false;
|
|
3522
|
+
setDurationValue(
|
|
3523
|
+
getInclusiveDurationDays(task.startDate, task.endDate)
|
|
3524
|
+
);
|
|
3525
|
+
setEditingDuration(true);
|
|
3526
|
+
},
|
|
3527
|
+
[task.locked, task.startDate, task.endDate]
|
|
3528
|
+
);
|
|
3317
3529
|
const applyDurationChange = (0, import_react10.useCallback)((nextDuration) => {
|
|
3318
3530
|
const normalizedDuration = Math.max(1, Math.round(nextDuration) || 1);
|
|
3319
3531
|
setDurationValue(normalizedDuration);
|
|
@@ -3324,34 +3536,59 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3324
3536
|
return;
|
|
3325
3537
|
}
|
|
3326
3538
|
const normalizedDuration = Math.max(1, Math.round(durationValue) || 1);
|
|
3327
|
-
onTasksChange?.([
|
|
3539
|
+
onTasksChange?.([
|
|
3540
|
+
{
|
|
3541
|
+
...task,
|
|
3542
|
+
endDate: getEndDateFromDuration(task.startDate, normalizedDuration)
|
|
3543
|
+
}
|
|
3544
|
+
]);
|
|
3328
3545
|
setEditingDuration(false);
|
|
3329
3546
|
}, [durationValue, task, onTasksChange]);
|
|
3330
3547
|
const handleDurationCancel = (0, import_react10.useCallback)(() => {
|
|
3331
3548
|
setDurationValue(getInclusiveDurationDays(task.startDate, task.endDate));
|
|
3332
3549
|
setEditingDuration(false);
|
|
3333
3550
|
}, [task.startDate, task.endDate]);
|
|
3334
|
-
const handleDurationAdjust = (0, import_react10.useCallback)(
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3551
|
+
const handleDurationAdjust = (0, import_react10.useCallback)(
|
|
3552
|
+
(delta) => {
|
|
3553
|
+
applyDurationChange(durationValue + delta);
|
|
3554
|
+
},
|
|
3555
|
+
[applyDurationChange, durationValue]
|
|
3556
|
+
);
|
|
3557
|
+
const handleDurationKeyDown = (0, import_react10.useCallback)(
|
|
3558
|
+
(e) => {
|
|
3559
|
+
e.stopPropagation();
|
|
3560
|
+
if (e.key === "Enter") {
|
|
3561
|
+
durationConfirmedRef.current = true;
|
|
3562
|
+
const normalizedDuration = Math.max(
|
|
3563
|
+
1,
|
|
3564
|
+
Math.round(durationValue) || 1
|
|
3565
|
+
);
|
|
3566
|
+
onTasksChange?.([
|
|
3567
|
+
{
|
|
3568
|
+
...task,
|
|
3569
|
+
endDate: getEndDateFromDuration(
|
|
3570
|
+
task.startDate,
|
|
3571
|
+
normalizedDuration
|
|
3572
|
+
)
|
|
3573
|
+
}
|
|
3574
|
+
]);
|
|
3575
|
+
setEditingDuration(false);
|
|
3576
|
+
} else if (e.key === "Escape") {
|
|
3577
|
+
handleDurationCancel();
|
|
3578
|
+
}
|
|
3579
|
+
},
|
|
3580
|
+
[durationValue, task, onTasksChange, handleDurationCancel]
|
|
3581
|
+
);
|
|
3582
|
+
const handleProgressClick = (0, import_react10.useCallback)(
|
|
3583
|
+
(e) => {
|
|
3584
|
+
if (task.locked) return;
|
|
3585
|
+
e.stopPropagation();
|
|
3586
|
+
progressConfirmedRef.current = false;
|
|
3587
|
+
setProgressValue(task.progress ?? 0);
|
|
3588
|
+
setEditingProgress(true);
|
|
3589
|
+
},
|
|
3590
|
+
[task.progress, task.locked]
|
|
3591
|
+
);
|
|
3355
3592
|
const handleProgressSave = (0, import_react10.useCallback)(() => {
|
|
3356
3593
|
if (progressConfirmedRef.current) {
|
|
3357
3594
|
progressConfirmedRef.current = false;
|
|
@@ -3374,28 +3611,36 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3374
3611
|
setEditingProgress(false);
|
|
3375
3612
|
}, []);
|
|
3376
3613
|
const handleProgressAdjust = (0, import_react10.useCallback)((delta) => {
|
|
3377
|
-
setProgressValue(
|
|
3614
|
+
setProgressValue(
|
|
3615
|
+
(current) => Math.max(0, Math.min(100, current + delta))
|
|
3616
|
+
);
|
|
3378
3617
|
}, []);
|
|
3379
|
-
const handleProgressKeyDown = (0, import_react10.useCallback)(
|
|
3380
|
-
e
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3618
|
+
const handleProgressKeyDown = (0, import_react10.useCallback)(
|
|
3619
|
+
(e) => {
|
|
3620
|
+
e.stopPropagation();
|
|
3621
|
+
if (e.key === "Enter") {
|
|
3622
|
+
progressConfirmedRef.current = true;
|
|
3623
|
+
const clampedValue = Math.max(0, Math.min(100, progressValue));
|
|
3624
|
+
if ((clampedValue === 100 || clampedValue === 0) && isTaskParent(task.id, allTasks)) {
|
|
3625
|
+
const children = getChildren(task.id, allTasks);
|
|
3626
|
+
const updatedTasks = [
|
|
3627
|
+
{ ...task, progress: clampedValue },
|
|
3628
|
+
...children.map((child) => ({
|
|
3629
|
+
...child,
|
|
3630
|
+
progress: clampedValue
|
|
3631
|
+
}))
|
|
3632
|
+
];
|
|
3633
|
+
onTasksChange?.(updatedTasks);
|
|
3634
|
+
} else {
|
|
3635
|
+
onTasksChange?.([{ ...task, progress: clampedValue }]);
|
|
3636
|
+
}
|
|
3637
|
+
setEditingProgress(false);
|
|
3638
|
+
} else if (e.key === "Escape") {
|
|
3639
|
+
handleProgressCancel();
|
|
3393
3640
|
}
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
}
|
|
3398
|
-
}, [progressValue, task, onTasksChange, handleProgressCancel, allTasks]);
|
|
3641
|
+
},
|
|
3642
|
+
[progressValue, task, onTasksChange, handleProgressCancel, allTasks]
|
|
3643
|
+
);
|
|
3399
3644
|
(0, import_react10.useEffect)(() => {
|
|
3400
3645
|
if (editingProgress && progressInputRef.current) {
|
|
3401
3646
|
progressInputRef.current.focus();
|
|
@@ -3411,77 +3656,111 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3411
3656
|
durationInputRef.current.select();
|
|
3412
3657
|
}
|
|
3413
3658
|
}, [editingDuration]);
|
|
3414
|
-
const handleStartDateChange = (0, import_react10.useCallback)(
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
newDateISO,
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3659
|
+
const handleStartDateChange = (0, import_react10.useCallback)(
|
|
3660
|
+
(newDateISO) => {
|
|
3661
|
+
if (!newDateISO) return;
|
|
3662
|
+
const origStart = parseUTCDate(task.startDate);
|
|
3663
|
+
const origEnd = parseUTCDate(task.endDate);
|
|
3664
|
+
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
3665
|
+
const newStart = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
|
|
3666
|
+
const newEnd = new Date(newStart.getTime() + durationMs);
|
|
3667
|
+
const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(newDateISO, newEnd.toISOString().split("T")[0]);
|
|
3668
|
+
onTasksChange?.([
|
|
3669
|
+
{ ...task, startDate: normalizedStart, endDate: normalizedEnd }
|
|
3670
|
+
]);
|
|
3671
|
+
},
|
|
3672
|
+
[task, onTasksChange]
|
|
3673
|
+
);
|
|
3674
|
+
const handleEndDateChange = (0, import_react10.useCallback)(
|
|
3675
|
+
(newDateISO) => {
|
|
3676
|
+
if (!newDateISO) return;
|
|
3677
|
+
const origStart = parseUTCDate(task.startDate);
|
|
3678
|
+
const origEnd = parseUTCDate(task.endDate);
|
|
3679
|
+
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
3680
|
+
const newEnd = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
|
|
3681
|
+
const newStart = new Date(newEnd.getTime() - durationMs);
|
|
3682
|
+
const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(newStart.toISOString().split("T")[0], newDateISO);
|
|
3683
|
+
onTasksChange?.([
|
|
3684
|
+
{ ...task, startDate: normalizedStart, endDate: normalizedEnd }
|
|
3685
|
+
]);
|
|
3686
|
+
},
|
|
3687
|
+
[task, onTasksChange]
|
|
3688
|
+
);
|
|
3440
3689
|
const handleRowClickInternal = (0, import_react10.useCallback)(() => {
|
|
3441
3690
|
onRowClick?.(task.id);
|
|
3442
3691
|
}, [task.id, onRowClick]);
|
|
3443
|
-
const handleNumberClick = (0, import_react10.useCallback)(
|
|
3444
|
-
e
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
const
|
|
3465
|
-
e
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
onSetSelectingPredecessorFor
|
|
3477
|
-
|
|
3692
|
+
const handleNumberClick = (0, import_react10.useCallback)(
|
|
3693
|
+
(e) => {
|
|
3694
|
+
e.stopPropagation();
|
|
3695
|
+
onRowClick?.(task.id);
|
|
3696
|
+
},
|
|
3697
|
+
[task.id, onRowClick]
|
|
3698
|
+
);
|
|
3699
|
+
const handleToggleCollapse = (0, import_react10.useCallback)(
|
|
3700
|
+
(e) => {
|
|
3701
|
+
e.stopPropagation();
|
|
3702
|
+
onToggleCollapse?.(task.id);
|
|
3703
|
+
},
|
|
3704
|
+
[task.id, onToggleCollapse]
|
|
3705
|
+
);
|
|
3706
|
+
const handlePromote = (0, import_react10.useCallback)(
|
|
3707
|
+
(e) => {
|
|
3708
|
+
e.stopPropagation();
|
|
3709
|
+
onPromoteTask?.(task.id);
|
|
3710
|
+
},
|
|
3711
|
+
[task.id, onPromoteTask]
|
|
3712
|
+
);
|
|
3713
|
+
const handleDemote = (0, import_react10.useCallback)(
|
|
3714
|
+
(e) => {
|
|
3715
|
+
e.stopPropagation();
|
|
3716
|
+
onDemoteTask?.(task.id, "");
|
|
3717
|
+
},
|
|
3718
|
+
[task.id, onDemoteTask]
|
|
3719
|
+
);
|
|
3720
|
+
const handleAddClick = (0, import_react10.useCallback)(
|
|
3721
|
+
(e) => {
|
|
3722
|
+
e.stopPropagation();
|
|
3723
|
+
onSetSelectingPredecessorFor?.(task.id);
|
|
3724
|
+
},
|
|
3725
|
+
[task.id, onSetSelectingPredecessorFor]
|
|
3726
|
+
);
|
|
3727
|
+
const handlePredecessorPick = (0, import_react10.useCallback)(
|
|
3728
|
+
(e) => {
|
|
3729
|
+
e.stopPropagation();
|
|
3730
|
+
if (!isPicking || isSourceRow) return;
|
|
3731
|
+
if (!selectingPredecessorFor || !activeLinkType) return;
|
|
3732
|
+
onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);
|
|
3733
|
+
},
|
|
3734
|
+
[
|
|
3735
|
+
isPicking,
|
|
3736
|
+
isSourceRow,
|
|
3737
|
+
selectingPredecessorFor,
|
|
3738
|
+
task.id,
|
|
3739
|
+
activeLinkType,
|
|
3740
|
+
onAddDependency
|
|
3741
|
+
]
|
|
3742
|
+
);
|
|
3743
|
+
const handleCancelPicking = (0, import_react10.useCallback)(
|
|
3744
|
+
(e) => {
|
|
3745
|
+
e.stopPropagation();
|
|
3746
|
+
onSetSelectingPredecessorFor?.(null);
|
|
3747
|
+
},
|
|
3748
|
+
[onSetSelectingPredecessorFor]
|
|
3749
|
+
);
|
|
3478
3750
|
const isSelectedPredecessor = selectedChip != null && selectedChip.predecessorId === task.id;
|
|
3479
|
-
const handleDeleteSelected = (0, import_react10.useCallback)(
|
|
3480
|
-
e
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3751
|
+
const handleDeleteSelected = (0, import_react10.useCallback)(
|
|
3752
|
+
(e) => {
|
|
3753
|
+
e.stopPropagation();
|
|
3754
|
+
if (!selectedChip) return;
|
|
3755
|
+
onRemoveDependency?.(
|
|
3756
|
+
selectedChip.successorId,
|
|
3757
|
+
selectedChip.predecessorId,
|
|
3758
|
+
selectedChip.linkType
|
|
3759
|
+
);
|
|
3760
|
+
onChipSelect?.(null);
|
|
3761
|
+
},
|
|
3762
|
+
[selectedChip, onRemoveDependency, onChipSelect]
|
|
3763
|
+
);
|
|
3485
3764
|
const startDateISO = toISODate(task.startDate);
|
|
3486
3765
|
const endDateISO = editingDuration ? getEndDateFromDuration(task.startDate, durationValue) : toISODate(task.endDate);
|
|
3487
3766
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
@@ -3534,13 +3813,78 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3534
3813
|
}
|
|
3535
3814
|
),
|
|
3536
3815
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
|
|
3537
|
-
isChild && !editingName && /* @__PURE__ */ (0, import_jsx_runtime12.
|
|
3816
|
+
isChild && !editingName && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
3817
|
+
ancestorContinues.map(
|
|
3818
|
+
(continues, idx) => continues ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3819
|
+
"span",
|
|
3820
|
+
{
|
|
3821
|
+
style: {
|
|
3822
|
+
position: "absolute",
|
|
3823
|
+
left: `${idx * 20 + 9}px`,
|
|
3824
|
+
top: 0,
|
|
3825
|
+
height: `${rowHeight}px`,
|
|
3826
|
+
width: "1.5px",
|
|
3827
|
+
background: "#d4bceb",
|
|
3828
|
+
borderRadius: "1px",
|
|
3829
|
+
pointerEvents: "none"
|
|
3830
|
+
}
|
|
3831
|
+
},
|
|
3832
|
+
idx
|
|
3833
|
+
) : null
|
|
3834
|
+
),
|
|
3835
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3836
|
+
"span",
|
|
3837
|
+
{
|
|
3838
|
+
style: {
|
|
3839
|
+
position: "absolute",
|
|
3840
|
+
left: `${(nestingDepth - 1) * 20 + 9}px`,
|
|
3841
|
+
top: 0,
|
|
3842
|
+
height: isLastChild ? `${rowHeight / 2}px` : `${rowHeight}px`,
|
|
3843
|
+
width: "1.5px",
|
|
3844
|
+
background: "#d4bceb",
|
|
3845
|
+
borderRadius: "1px",
|
|
3846
|
+
pointerEvents: "none"
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
),
|
|
3850
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3851
|
+
"span",
|
|
3852
|
+
{
|
|
3853
|
+
style: {
|
|
3854
|
+
position: "absolute",
|
|
3855
|
+
left: `${(nestingDepth - 1) * 20 + 9}px`,
|
|
3856
|
+
top: `${rowHeight / 2 - 0.75}px`,
|
|
3857
|
+
width: "8px",
|
|
3858
|
+
height: "1.5px",
|
|
3859
|
+
background: "#d4bceb",
|
|
3860
|
+
borderRadius: "1px",
|
|
3861
|
+
pointerEvents: "none"
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
),
|
|
3865
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3866
|
+
"span",
|
|
3867
|
+
{
|
|
3868
|
+
style: {
|
|
3869
|
+
position: "absolute",
|
|
3870
|
+
left: `${(nestingDepth - 1) * 20 + 15}px`,
|
|
3871
|
+
top: `${rowHeight / 2 - 2}px`,
|
|
3872
|
+
width: "4px",
|
|
3873
|
+
height: "4px",
|
|
3874
|
+
borderRadius: "50%",
|
|
3875
|
+
background: "#d4bceb",
|
|
3876
|
+
pointerEvents: "none"
|
|
3877
|
+
}
|
|
3878
|
+
}
|
|
3879
|
+
)
|
|
3880
|
+
] }),
|
|
3538
3881
|
isParent && !editingName && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3539
3882
|
"button",
|
|
3540
3883
|
{
|
|
3541
3884
|
type: "button",
|
|
3542
3885
|
className: `gantt-tl-collapse-btn ${isCollapsed ? "gantt-tl-collapse-btn-collapsed" : ""}`,
|
|
3543
3886
|
onClick: handleToggleCollapse,
|
|
3887
|
+
style: { left: `${nestingDepth * 20 + 4}px` },
|
|
3544
3888
|
"aria-label": isCollapsed ? "Expand children" : "Collapse children",
|
|
3545
3889
|
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronRightIcon, {})
|
|
3546
3890
|
}
|
|
@@ -3554,7 +3898,10 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3554
3898
|
onChange: (e) => setNameValue(e.target.value),
|
|
3555
3899
|
onBlur: handleNameSave,
|
|
3556
3900
|
onKeyDown: handleNameKeyDown,
|
|
3557
|
-
className:
|
|
3901
|
+
className: "gantt-tl-name-input",
|
|
3902
|
+
style: {
|
|
3903
|
+
paddingLeft: nestingDepth > 0 ? `${nestingDepth * 20 + 24}px` : void 0
|
|
3904
|
+
},
|
|
3558
3905
|
onClick: (e) => e.stopPropagation()
|
|
3559
3906
|
}
|
|
3560
3907
|
),
|
|
@@ -3564,14 +3911,15 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3564
3911
|
type: "button",
|
|
3565
3912
|
className: [
|
|
3566
3913
|
"gantt-tl-name-trigger",
|
|
3567
|
-
disableTaskNameEditing ? "gantt-tl-name-locked" : ""
|
|
3568
|
-
isParent ? "gantt-tl-name-trigger-parent" : "",
|
|
3569
|
-
isChild ? "gantt-tl-name-trigger-child" : ""
|
|
3914
|
+
disableTaskNameEditing ? "gantt-tl-name-locked" : ""
|
|
3570
3915
|
].filter(Boolean).join(" "),
|
|
3571
3916
|
title: task.name,
|
|
3572
3917
|
onClick: handleNameClick,
|
|
3573
3918
|
onDoubleClick: handleNameDoubleClick,
|
|
3574
|
-
style:
|
|
3919
|
+
style: {
|
|
3920
|
+
paddingLeft: nestingDepth > 0 ? `${nestingDepth * 20 + (isParent ? 26 : 8)}px` : isParent ? "26px" : void 0,
|
|
3921
|
+
...editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0
|
|
3922
|
+
},
|
|
3575
3923
|
children: task.name
|
|
3576
3924
|
}
|
|
3577
3925
|
),
|
|
@@ -3584,16 +3932,20 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3584
3932
|
onClick: (e) => {
|
|
3585
3933
|
e.stopPropagation();
|
|
3586
3934
|
const now = /* @__PURE__ */ new Date();
|
|
3587
|
-
const todayISO = new Date(
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3935
|
+
const todayISO = new Date(
|
|
3936
|
+
Date.UTC(
|
|
3937
|
+
now.getUTCFullYear(),
|
|
3938
|
+
now.getUTCMonth(),
|
|
3939
|
+
now.getUTCDate()
|
|
3940
|
+
)
|
|
3941
|
+
).toISOString().split("T")[0];
|
|
3942
|
+
const endISO = new Date(
|
|
3943
|
+
Date.UTC(
|
|
3944
|
+
now.getUTCFullYear(),
|
|
3945
|
+
now.getUTCMonth(),
|
|
3946
|
+
now.getUTCDate() + 7
|
|
3947
|
+
)
|
|
3948
|
+
).toISOString().split("T")[0];
|
|
3597
3949
|
const newTask = {
|
|
3598
3950
|
id: crypto.randomUUID(),
|
|
3599
3951
|
name: "\u041D\u043E\u0432\u0430\u044F \u0437\u0430\u0434\u0430\u0447\u0430",
|
|
@@ -3629,7 +3981,6 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3629
3981
|
HierarchyButton,
|
|
3630
3982
|
{
|
|
3631
3983
|
isChild,
|
|
3632
|
-
isParent,
|
|
3633
3984
|
rowIndex,
|
|
3634
3985
|
onPromote: onPromoteTask ? handlePromote : void 0,
|
|
3635
3986
|
onDemote: onDemoteTask ? handleDemote : void 0
|
|
@@ -3637,113 +3988,234 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3637
3988
|
)
|
|
3638
3989
|
] })
|
|
3639
3990
|
] }),
|
|
3640
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3641
|
-
|
|
3991
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3992
|
+
"div",
|
|
3642
3993
|
{
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3994
|
+
className: "gantt-tl-cell gantt-tl-cell-date",
|
|
3995
|
+
onClick: (e) => e.stopPropagation(),
|
|
3996
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3997
|
+
DatePicker,
|
|
3998
|
+
{
|
|
3999
|
+
value: startDateISO,
|
|
4000
|
+
onChange: handleStartDateChange,
|
|
4001
|
+
format: "dd.MM.yy",
|
|
4002
|
+
portal: true,
|
|
4003
|
+
disabled: task.locked,
|
|
4004
|
+
weekends,
|
|
4005
|
+
workdays,
|
|
4006
|
+
isWeekend: isWeekend3
|
|
4007
|
+
}
|
|
4008
|
+
)
|
|
3648
4009
|
}
|
|
3649
|
-
)
|
|
3650
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3651
|
-
|
|
4010
|
+
),
|
|
4011
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4012
|
+
"div",
|
|
3652
4013
|
{
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
disabled: task.locked
|
|
3658
|
-
}
|
|
3659
|
-
) }),
|
|
3660
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-cell gantt-tl-cell-duration", onClick: handleDurationClick, children: [
|
|
3661
|
-
editingDuration && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-editor", onClick: (e) => e.stopPropagation(), children: [
|
|
3662
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3663
|
-
Input,
|
|
4014
|
+
className: "gantt-tl-cell gantt-tl-cell-date",
|
|
4015
|
+
onClick: (e) => e.stopPropagation(),
|
|
4016
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4017
|
+
DatePicker,
|
|
3664
4018
|
{
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
className: "gantt-tl-number-input"
|
|
4019
|
+
value: endDateISO,
|
|
4020
|
+
onChange: handleEndDateChange,
|
|
4021
|
+
format: "dd.MM.yy",
|
|
4022
|
+
portal: true,
|
|
4023
|
+
disabled: task.locked,
|
|
4024
|
+
weekends,
|
|
4025
|
+
workdays,
|
|
4026
|
+
isWeekend: isWeekend3
|
|
3674
4027
|
}
|
|
3675
|
-
)
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
4028
|
+
)
|
|
4029
|
+
}
|
|
4030
|
+
),
|
|
4031
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
4032
|
+
"div",
|
|
4033
|
+
{
|
|
4034
|
+
className: "gantt-tl-cell gantt-tl-cell-duration",
|
|
4035
|
+
onClick: handleDurationClick,
|
|
4036
|
+
children: [
|
|
4037
|
+
editingDuration && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
4038
|
+
"div",
|
|
3679
4039
|
{
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
4040
|
+
className: "gantt-tl-number-editor",
|
|
4041
|
+
onClick: (e) => e.stopPropagation(),
|
|
4042
|
+
children: [
|
|
4043
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4044
|
+
Input,
|
|
4045
|
+
{
|
|
4046
|
+
ref: durationInputRef,
|
|
4047
|
+
type: "number",
|
|
4048
|
+
min: 1,
|
|
4049
|
+
step: 1,
|
|
4050
|
+
value: durationValue,
|
|
4051
|
+
onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) || 1),
|
|
4052
|
+
onBlur: handleDurationSave,
|
|
4053
|
+
onKeyDown: handleDurationKeyDown,
|
|
4054
|
+
className: "gantt-tl-number-input"
|
|
4055
|
+
}
|
|
4056
|
+
),
|
|
4057
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
|
|
4058
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4059
|
+
"button",
|
|
4060
|
+
{
|
|
4061
|
+
type: "button",
|
|
4062
|
+
className: "gantt-tl-number-stepper",
|
|
4063
|
+
tabIndex: -1,
|
|
4064
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4065
|
+
onClick: () => handleDurationAdjust(1),
|
|
4066
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4067
|
+
"svg",
|
|
4068
|
+
{
|
|
4069
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4070
|
+
width: "10",
|
|
4071
|
+
height: "10",
|
|
4072
|
+
viewBox: "0 0 24 24",
|
|
4073
|
+
fill: "none",
|
|
4074
|
+
stroke: "currentColor",
|
|
4075
|
+
strokeWidth: "2",
|
|
4076
|
+
strokeLinecap: "round",
|
|
4077
|
+
strokeLinejoin: "round",
|
|
4078
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m18 15-6-6-6 6" })
|
|
4079
|
+
}
|
|
4080
|
+
)
|
|
4081
|
+
}
|
|
4082
|
+
),
|
|
4083
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4084
|
+
"button",
|
|
4085
|
+
{
|
|
4086
|
+
type: "button",
|
|
4087
|
+
className: "gantt-tl-number-stepper",
|
|
4088
|
+
tabIndex: -1,
|
|
4089
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4090
|
+
onClick: () => handleDurationAdjust(-1),
|
|
4091
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4092
|
+
"svg",
|
|
4093
|
+
{
|
|
4094
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4095
|
+
width: "10",
|
|
4096
|
+
height: "10",
|
|
4097
|
+
viewBox: "0 0 24 24",
|
|
4098
|
+
fill: "none",
|
|
4099
|
+
stroke: "currentColor",
|
|
4100
|
+
strokeWidth: "2",
|
|
4101
|
+
strokeLinecap: "round",
|
|
4102
|
+
strokeLinejoin: "round",
|
|
4103
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" })
|
|
4104
|
+
}
|
|
4105
|
+
)
|
|
4106
|
+
}
|
|
4107
|
+
)
|
|
4108
|
+
] })
|
|
4109
|
+
]
|
|
3686
4110
|
}
|
|
3687
4111
|
),
|
|
3688
4112
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3689
|
-
"
|
|
4113
|
+
"span",
|
|
3690
4114
|
{
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
tabIndex: -1,
|
|
3694
|
-
onMouseDown: (e) => e.preventDefault(),
|
|
3695
|
-
onClick: () => handleDurationAdjust(-1),
|
|
3696
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" }) })
|
|
4115
|
+
style: editingDuration ? { visibility: "hidden", pointerEvents: "none" } : void 0,
|
|
4116
|
+
children: getInclusiveDurationDays(task.startDate, task.endDate)
|
|
3697
4117
|
}
|
|
3698
4118
|
)
|
|
3699
|
-
]
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
min: 0,
|
|
3711
|
-
max: 100,
|
|
3712
|
-
step: 1,
|
|
3713
|
-
value: progressValue,
|
|
3714
|
-
onChange: (e) => setProgressValue(parseInt(e.target.value, 10) || 0),
|
|
3715
|
-
onBlur: handleProgressSave,
|
|
3716
|
-
onKeyDown: handleProgressKeyDown,
|
|
3717
|
-
className: "gantt-tl-number-input"
|
|
3718
|
-
}
|
|
3719
|
-
),
|
|
3720
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
|
|
3721
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3722
|
-
"button",
|
|
4119
|
+
]
|
|
4120
|
+
}
|
|
4121
|
+
),
|
|
4122
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
4123
|
+
"div",
|
|
4124
|
+
{
|
|
4125
|
+
className: "gantt-tl-cell gantt-tl-cell-progress",
|
|
4126
|
+
onClick: handleProgressClick,
|
|
4127
|
+
children: [
|
|
4128
|
+
editingProgress && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
4129
|
+
"div",
|
|
3723
4130
|
{
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
4131
|
+
className: "gantt-tl-number-editor",
|
|
4132
|
+
onClick: (e) => e.stopPropagation(),
|
|
4133
|
+
children: [
|
|
4134
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4135
|
+
Input,
|
|
4136
|
+
{
|
|
4137
|
+
ref: progressInputRef,
|
|
4138
|
+
type: "number",
|
|
4139
|
+
min: 0,
|
|
4140
|
+
max: 100,
|
|
4141
|
+
step: 1,
|
|
4142
|
+
value: progressValue,
|
|
4143
|
+
onChange: (e) => setProgressValue(parseInt(e.target.value, 10) || 0),
|
|
4144
|
+
onBlur: handleProgressSave,
|
|
4145
|
+
onKeyDown: handleProgressKeyDown,
|
|
4146
|
+
className: "gantt-tl-number-input"
|
|
4147
|
+
}
|
|
4148
|
+
),
|
|
4149
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
|
|
4150
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4151
|
+
"button",
|
|
4152
|
+
{
|
|
4153
|
+
type: "button",
|
|
4154
|
+
className: "gantt-tl-number-stepper",
|
|
4155
|
+
tabIndex: -1,
|
|
4156
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4157
|
+
onClick: () => handleProgressAdjust(1),
|
|
4158
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4159
|
+
"svg",
|
|
4160
|
+
{
|
|
4161
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4162
|
+
width: "10",
|
|
4163
|
+
height: "10",
|
|
4164
|
+
viewBox: "0 0 24 24",
|
|
4165
|
+
fill: "none",
|
|
4166
|
+
stroke: "currentColor",
|
|
4167
|
+
strokeWidth: "2",
|
|
4168
|
+
strokeLinecap: "round",
|
|
4169
|
+
strokeLinejoin: "round",
|
|
4170
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m18 15-6-6-6 6" })
|
|
4171
|
+
}
|
|
4172
|
+
)
|
|
4173
|
+
}
|
|
4174
|
+
),
|
|
4175
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4176
|
+
"button",
|
|
4177
|
+
{
|
|
4178
|
+
type: "button",
|
|
4179
|
+
className: "gantt-tl-number-stepper",
|
|
4180
|
+
tabIndex: -1,
|
|
4181
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4182
|
+
onClick: () => handleProgressAdjust(-1),
|
|
4183
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4184
|
+
"svg",
|
|
4185
|
+
{
|
|
4186
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4187
|
+
width: "10",
|
|
4188
|
+
height: "10",
|
|
4189
|
+
viewBox: "0 0 24 24",
|
|
4190
|
+
fill: "none",
|
|
4191
|
+
stroke: "currentColor",
|
|
4192
|
+
strokeWidth: "2",
|
|
4193
|
+
strokeLinecap: "round",
|
|
4194
|
+
strokeLinejoin: "round",
|
|
4195
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" })
|
|
4196
|
+
}
|
|
4197
|
+
)
|
|
4198
|
+
}
|
|
4199
|
+
)
|
|
4200
|
+
] })
|
|
4201
|
+
]
|
|
3730
4202
|
}
|
|
3731
4203
|
),
|
|
3732
4204
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3733
|
-
"
|
|
4205
|
+
"span",
|
|
3734
4206
|
{
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
4207
|
+
style: editingProgress ? { visibility: "hidden", pointerEvents: "none" } : task.progress === 100 ? {
|
|
4208
|
+
backgroundColor: "#17c864",
|
|
4209
|
+
borderRadius: "4px",
|
|
4210
|
+
padding: "2px 4px",
|
|
4211
|
+
color: "#ffffff"
|
|
4212
|
+
} : void 0,
|
|
4213
|
+
children: task.progress ? Math.round(task.progress) === 100 ? "100" : `${Math.round(task.progress)}%` : "0%"
|
|
3741
4214
|
}
|
|
3742
4215
|
)
|
|
3743
|
-
]
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
] }),
|
|
4216
|
+
]
|
|
4217
|
+
}
|
|
4218
|
+
),
|
|
3747
4219
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3748
4220
|
"div",
|
|
3749
4221
|
{
|
|
@@ -3784,26 +4256,33 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3784
4256
|
]
|
|
3785
4257
|
}
|
|
3786
4258
|
) }),
|
|
3787
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3788
|
-
|
|
4259
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4260
|
+
"div",
|
|
3789
4261
|
{
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
4262
|
+
className: "gantt-tl-dep-overflow-list",
|
|
4263
|
+
onClick: (e) => e.stopPropagation(),
|
|
4264
|
+
children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4265
|
+
DepChip,
|
|
4266
|
+
{
|
|
4267
|
+
lag,
|
|
4268
|
+
dep,
|
|
4269
|
+
taskId: task.id,
|
|
4270
|
+
predecessorName,
|
|
4271
|
+
selectedChip,
|
|
4272
|
+
disableDependencyEditing,
|
|
4273
|
+
onChipSelect,
|
|
4274
|
+
onRowClick,
|
|
4275
|
+
onScrollToTask,
|
|
4276
|
+
onRemoveDependency,
|
|
4277
|
+
onChipSelectClear: () => onChipSelect?.(null),
|
|
4278
|
+
task,
|
|
4279
|
+
allTasks,
|
|
4280
|
+
onTasksChange
|
|
4281
|
+
},
|
|
4282
|
+
`${dep.taskId}-${dep.type}`
|
|
4283
|
+
))
|
|
4284
|
+
}
|
|
4285
|
+
) })
|
|
3807
4286
|
] })
|
|
3808
4287
|
) : chips.length === 1 ? (
|
|
3809
4288
|
/* Single chip — unified DepChip */
|
|
@@ -3968,7 +4447,10 @@ var TaskList = ({
|
|
|
3968
4447
|
collapsedParentIds: externalCollapsedParentIds,
|
|
3969
4448
|
onToggleCollapse: externalOnToggleCollapse,
|
|
3970
4449
|
onPromoteTask,
|
|
3971
|
-
onDemoteTask
|
|
4450
|
+
onDemoteTask,
|
|
4451
|
+
weekends,
|
|
4452
|
+
workdays,
|
|
4453
|
+
isWeekend: isWeekend3
|
|
3972
4454
|
}) => {
|
|
3973
4455
|
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
|
|
3974
4456
|
const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
|
|
@@ -4002,6 +4484,25 @@ var TaskList = ({
|
|
|
4002
4484
|
() => visibleTasks.length * rowHeight,
|
|
4003
4485
|
[visibleTasks.length, rowHeight]
|
|
4004
4486
|
);
|
|
4487
|
+
const nestingDepthMap = (0, import_react12.useMemo)(() => {
|
|
4488
|
+
const depthMap = /* @__PURE__ */ new Map();
|
|
4489
|
+
const taskById = new Map(tasks.map((t) => [t.id, t]));
|
|
4490
|
+
function getDepth(taskId) {
|
|
4491
|
+
if (depthMap.has(taskId)) return depthMap.get(taskId);
|
|
4492
|
+
const task = taskById.get(taskId);
|
|
4493
|
+
if (!task || !task.parentId || !taskById.has(task.parentId)) {
|
|
4494
|
+
depthMap.set(taskId, 0);
|
|
4495
|
+
return 0;
|
|
4496
|
+
}
|
|
4497
|
+
const depth = getDepth(task.parentId) + 1;
|
|
4498
|
+
depthMap.set(taskId, depth);
|
|
4499
|
+
return depth;
|
|
4500
|
+
}
|
|
4501
|
+
for (const task of tasks) {
|
|
4502
|
+
getDepth(task.id);
|
|
4503
|
+
}
|
|
4504
|
+
return depthMap;
|
|
4505
|
+
}, [tasks]);
|
|
4005
4506
|
const lastChildIds = (0, import_react12.useMemo)(() => {
|
|
4006
4507
|
const last = /* @__PURE__ */ new Set();
|
|
4007
4508
|
const seenParents = /* @__PURE__ */ new Set();
|
|
@@ -4014,6 +4515,20 @@ var TaskList = ({
|
|
|
4014
4515
|
}
|
|
4015
4516
|
return last;
|
|
4016
4517
|
}, [visibleTasks]);
|
|
4518
|
+
const ancestorContinuesMap = (0, import_react12.useMemo)(() => {
|
|
4519
|
+
const taskById = new Map(tasks.map((t) => [t.id, t]));
|
|
4520
|
+
const map = /* @__PURE__ */ new Map();
|
|
4521
|
+
for (const task of visibleTasks) {
|
|
4522
|
+
const continues = [];
|
|
4523
|
+
let current = taskById.get(task.id);
|
|
4524
|
+
while (current?.parentId && taskById.has(current.parentId)) {
|
|
4525
|
+
continues.unshift(!lastChildIds.has(current.id));
|
|
4526
|
+
current = taskById.get(current.parentId);
|
|
4527
|
+
}
|
|
4528
|
+
map.set(task.id, continues.slice(0, -1));
|
|
4529
|
+
}
|
|
4530
|
+
return map;
|
|
4531
|
+
}, [tasks, visibleTasks, lastChildIds]);
|
|
4017
4532
|
const handleRowClick = (0, import_react12.useCallback)((taskId) => {
|
|
4018
4533
|
onTaskSelect?.(taskId);
|
|
4019
4534
|
}, [onTaskSelect]);
|
|
@@ -4124,9 +4639,6 @@ var TaskList = ({
|
|
|
4124
4639
|
if (dropTarget.parentId === draggedTaskId) {
|
|
4125
4640
|
return false;
|
|
4126
4641
|
}
|
|
4127
|
-
if (dropTarget.parentId) {
|
|
4128
|
-
return false;
|
|
4129
|
-
}
|
|
4130
4642
|
const draggedTask = orderedTasks.find((t) => t.id === draggedTaskId);
|
|
4131
4643
|
if (!draggedTask) return true;
|
|
4132
4644
|
const descendants = getAllDescendants(draggedTaskId, orderedTasks);
|
|
@@ -4272,6 +4784,52 @@ var TaskList = ({
|
|
|
4272
4784
|
setIsCreating(false);
|
|
4273
4785
|
}, [onAdd]);
|
|
4274
4786
|
const handleCancelNewTask = (0, import_react12.useCallback)(() => setIsCreating(false), []);
|
|
4787
|
+
function getTaskDepth(task, tasks2) {
|
|
4788
|
+
if (!task) return 0;
|
|
4789
|
+
let depth = 0;
|
|
4790
|
+
let current = task;
|
|
4791
|
+
while (current) {
|
|
4792
|
+
if (!current.parentId) break;
|
|
4793
|
+
depth++;
|
|
4794
|
+
const parentId = current.parentId;
|
|
4795
|
+
current = tasks2.find((t) => t.id === parentId);
|
|
4796
|
+
}
|
|
4797
|
+
return depth;
|
|
4798
|
+
}
|
|
4799
|
+
const handleDemoteWrapper = (0, import_react12.useCallback)((taskId, _newParentId) => {
|
|
4800
|
+
const taskIndex = visibleTasks.findIndex((t) => t.id === taskId);
|
|
4801
|
+
const currentTask = visibleTasks[taskIndex];
|
|
4802
|
+
const currentDepth = getTaskDepth(currentTask, orderedTasks);
|
|
4803
|
+
if (taskIndex > 0) {
|
|
4804
|
+
for (let i = taskIndex - 1; i >= 0; i--) {
|
|
4805
|
+
const previousTask = visibleTasks[i];
|
|
4806
|
+
const previousDepth = getTaskDepth(previousTask, orderedTasks);
|
|
4807
|
+
if (previousDepth === currentDepth) {
|
|
4808
|
+
onDemoteTask?.(taskId, previousTask.id);
|
|
4809
|
+
return;
|
|
4810
|
+
}
|
|
4811
|
+
if (previousDepth < currentDepth) {
|
|
4812
|
+
break;
|
|
4813
|
+
}
|
|
4814
|
+
}
|
|
4815
|
+
return;
|
|
4816
|
+
}
|
|
4817
|
+
const demotedTask = orderedTasks.find((t) => t.id === taskId);
|
|
4818
|
+
if (!demotedTask) return;
|
|
4819
|
+
const newSectionTask = {
|
|
4820
|
+
id: crypto.randomUUID(),
|
|
4821
|
+
name: "\u041D\u043E\u0432\u044B\u0439 \u0440\u0430\u0437\u0434\u0435\u043B",
|
|
4822
|
+
startDate: demotedTask.startDate,
|
|
4823
|
+
endDate: demotedTask.endDate
|
|
4824
|
+
};
|
|
4825
|
+
const updatedTasks = [
|
|
4826
|
+
newSectionTask,
|
|
4827
|
+
...orderedTasks.map(
|
|
4828
|
+
(t) => t.id === taskId ? { ...t, parentId: newSectionTask.id } : t
|
|
4829
|
+
)
|
|
4830
|
+
];
|
|
4831
|
+
onReorder?.(updatedTasks, taskId, newSectionTask.id);
|
|
4832
|
+
}, [visibleTasks, orderedTasks, onDemoteTask, onReorder]);
|
|
4275
4833
|
const effectiveTaskListWidth = Math.max(taskListWidth, MIN_TASK_LIST_WIDTH);
|
|
4276
4834
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
4277
4835
|
"div",
|
|
@@ -4355,8 +4913,13 @@ var TaskList = ({
|
|
|
4355
4913
|
collapsedParentIds,
|
|
4356
4914
|
onToggleCollapse: handleToggleCollapse,
|
|
4357
4915
|
onPromoteTask,
|
|
4358
|
-
onDemoteTask,
|
|
4359
|
-
isLastChild: lastChildIds.has(task.id)
|
|
4916
|
+
onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
|
|
4917
|
+
isLastChild: lastChildIds.has(task.id),
|
|
4918
|
+
nestingDepth: nestingDepthMap.get(task.id) ?? 0,
|
|
4919
|
+
ancestorContinues: ancestorContinuesMap.get(task.id) ?? [],
|
|
4920
|
+
weekends,
|
|
4921
|
+
workdays,
|
|
4922
|
+
isWeekend: isWeekend3
|
|
4360
4923
|
},
|
|
4361
4924
|
task.id
|
|
4362
4925
|
)) }),
|
|
@@ -4424,7 +4987,10 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4424
4987
|
onPromoteTask,
|
|
4425
4988
|
onDemoteTask,
|
|
4426
4989
|
enableAddTask = true,
|
|
4427
|
-
viewMode = "day"
|
|
4990
|
+
viewMode = "day",
|
|
4991
|
+
weekends,
|
|
4992
|
+
workdays,
|
|
4993
|
+
isWeekend: isWeekend3
|
|
4428
4994
|
}, ref) => {
|
|
4429
4995
|
const scrollContainerRef = (0, import_react13.useRef)(null);
|
|
4430
4996
|
const [selectedTaskId, setSelectedTaskId] = (0, import_react13.useState)(null);
|
|
@@ -4433,6 +4999,10 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4433
4999
|
const [collapsedParentIds, setCollapsedParentIds] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
|
|
4434
5000
|
const [editingTaskId, setEditingTaskId] = (0, import_react13.useState)(null);
|
|
4435
5001
|
const normalizedTasks = (0, import_react13.useMemo)(() => normalizeHierarchyTasks(tasks), [tasks]);
|
|
5002
|
+
const isCustomWeekend = (0, import_react13.useMemo)(
|
|
5003
|
+
() => createIsWeekendPredicate({ weekends, workdays, isWeekend: isWeekend3 }),
|
|
5004
|
+
[weekends, workdays, isWeekend3]
|
|
5005
|
+
);
|
|
4436
5006
|
const dateRange = (0, import_react13.useMemo)(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
|
|
4437
5007
|
const [validationResult, setValidationResult] = (0, import_react13.useState)(null);
|
|
4438
5008
|
const [cascadeOverrides, setCascadeOverrides] = (0, import_react13.useState)(/* @__PURE__ */ new Map());
|
|
@@ -4665,6 +5235,17 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4665
5235
|
}),
|
|
4666
5236
|
[scrollToToday, scrollToTask, handleCollapseAll, handleExpandAll]
|
|
4667
5237
|
);
|
|
5238
|
+
function getTaskDepth(taskId, tasks2) {
|
|
5239
|
+
let depth = 0;
|
|
5240
|
+
let current = tasks2.find((t) => t.id === taskId);
|
|
5241
|
+
while (current) {
|
|
5242
|
+
if (!current.parentId) break;
|
|
5243
|
+
depth++;
|
|
5244
|
+
const parentId = current.parentId;
|
|
5245
|
+
current = tasks2.find((t) => t.id === parentId);
|
|
5246
|
+
}
|
|
5247
|
+
return depth;
|
|
5248
|
+
}
|
|
4668
5249
|
const handlePromoteTask = (0, import_react13.useCallback)((taskId) => {
|
|
4669
5250
|
if (onPromoteTask) {
|
|
4670
5251
|
onPromoteTask(taskId);
|
|
@@ -4674,20 +5255,20 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4674
5255
|
if (!taskToPromote || !taskToPromote.parentId) {
|
|
4675
5256
|
return;
|
|
4676
5257
|
}
|
|
4677
|
-
const
|
|
4678
|
-
const
|
|
5258
|
+
const depth = getTaskDepth(taskId, tasks);
|
|
5259
|
+
const grandparentId = depth > 1 ? tasks.find((t) => t.id === taskToPromote.parentId)?.parentId : void 0;
|
|
5260
|
+
const currentParentId = taskToPromote.parentId;
|
|
5261
|
+
const siblings = tasks.filter((t) => t.parentId === currentParentId);
|
|
5262
|
+
const promotedTask = { ...taskToPromote, parentId: grandparentId };
|
|
4679
5263
|
if (siblings.length <= 1) {
|
|
4680
|
-
|
|
4681
|
-
onTasksChange?.([promotedTask2]);
|
|
5264
|
+
onTasksChange?.([promotedTask]);
|
|
4682
5265
|
return;
|
|
4683
5266
|
}
|
|
4684
|
-
const lastSiblingIndex = tasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId ===
|
|
5267
|
+
const lastSiblingIndex = tasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId === currentParentId).sort((a, b) => b.index - a.index)[0];
|
|
4685
5268
|
if (!lastSiblingIndex) {
|
|
4686
|
-
|
|
4687
|
-
onTasksChange?.([promotedTask2]);
|
|
5269
|
+
onTasksChange?.([promotedTask]);
|
|
4688
5270
|
return;
|
|
4689
5271
|
}
|
|
4690
|
-
const promotedTask = { ...taskToPromote, parentId: void 0 };
|
|
4691
5272
|
const reorderedTasks = normalizeHierarchyTasks([
|
|
4692
5273
|
...tasks.filter((t) => t.id !== taskId).slice(0, lastSiblingIndex.index + 1),
|
|
4693
5274
|
promotedTask,
|
|
@@ -4813,7 +5394,10 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4813
5394
|
collapsedParentIds,
|
|
4814
5395
|
onToggleCollapse: handleToggleCollapse,
|
|
4815
5396
|
onPromoteTask: onPromoteTask ?? handlePromoteTask,
|
|
4816
|
-
onDemoteTask: onDemoteTask ?? handleDemoteTask
|
|
5397
|
+
onDemoteTask: onDemoteTask ?? handleDemoteTask,
|
|
5398
|
+
weekends,
|
|
5399
|
+
workdays,
|
|
5400
|
+
isWeekend: isWeekend3
|
|
4817
5401
|
}
|
|
4818
5402
|
),
|
|
4819
5403
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
|
|
@@ -4823,7 +5407,8 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4823
5407
|
days: dateRange,
|
|
4824
5408
|
dayWidth,
|
|
4825
5409
|
headerHeight,
|
|
4826
|
-
viewMode
|
|
5410
|
+
viewMode,
|
|
5411
|
+
isCustomWeekend
|
|
4827
5412
|
}
|
|
4828
5413
|
) }),
|
|
4829
5414
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
@@ -4841,7 +5426,8 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4841
5426
|
dateRange,
|
|
4842
5427
|
dayWidth,
|
|
4843
5428
|
totalHeight: totalGridHeight,
|
|
4844
|
-
viewMode
|
|
5429
|
+
viewMode,
|
|
5430
|
+
isCustomWeekend
|
|
4845
5431
|
}
|
|
4846
5432
|
),
|
|
4847
5433
|
todayInRange && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
|
|
@@ -4956,6 +5542,8 @@ init_dateUtils();
|
|
|
4956
5542
|
computeLagFromDates,
|
|
4957
5543
|
computeParentDates,
|
|
4958
5544
|
computeParentProgress,
|
|
5545
|
+
createDateKey,
|
|
5546
|
+
createIsWeekendPredicate,
|
|
4959
5547
|
detectCycles,
|
|
4960
5548
|
detectEdgeZone,
|
|
4961
5549
|
findParentId,
|