gantt-lib 0.17.2 → 0.18.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.js +941 -444
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +948 -445
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +0 -40
- 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;
|
|
@@ -2887,18 +2889,49 @@ var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
|
2887
2889
|
var getInclusiveDurationDays = (startDate, endDate) => {
|
|
2888
2890
|
const start = parseUTCDate(startDate);
|
|
2889
2891
|
const end = parseUTCDate(endDate);
|
|
2890
|
-
return Math.max(
|
|
2892
|
+
return Math.max(
|
|
2893
|
+
1,
|
|
2894
|
+
Math.round((end.getTime() - start.getTime()) / DAY_MS2) + 1
|
|
2895
|
+
);
|
|
2891
2896
|
};
|
|
2892
2897
|
var getEndDateFromDuration = (startDate, durationDays) => {
|
|
2893
2898
|
const start = parseUTCDate(startDate);
|
|
2894
2899
|
return new Date(start.getTime() + (durationDays - 1) * DAY_MS2).toISOString().split("T")[0];
|
|
2895
2900
|
};
|
|
2896
|
-
var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2901
|
+
var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2902
|
+
"svg",
|
|
2903
|
+
{
|
|
2904
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2905
|
+
width: "12",
|
|
2906
|
+
height: "12",
|
|
2907
|
+
viewBox: "0 0 24 24",
|
|
2908
|
+
fill: "none",
|
|
2909
|
+
stroke: "currentColor",
|
|
2910
|
+
strokeWidth: "2",
|
|
2911
|
+
strokeLinecap: "round",
|
|
2912
|
+
strokeLinejoin: "round",
|
|
2913
|
+
children: [
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M3 6h18" }),
|
|
2916
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
2917
|
+
]
|
|
2918
|
+
}
|
|
2919
|
+
);
|
|
2920
|
+
var PlusIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2921
|
+
"svg",
|
|
2922
|
+
{
|
|
2923
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2924
|
+
width: "14",
|
|
2925
|
+
height: "14",
|
|
2926
|
+
viewBox: "0 0 24 24",
|
|
2927
|
+
fill: "none",
|
|
2928
|
+
stroke: "currentColor",
|
|
2929
|
+
strokeWidth: "2",
|
|
2930
|
+
strokeLinecap: "round",
|
|
2931
|
+
strokeLinejoin: "round",
|
|
2932
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M12 5v14M5 12h14" })
|
|
2933
|
+
}
|
|
2934
|
+
);
|
|
2902
2935
|
var DragHandleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "10", height: "14", viewBox: "0 0 10 14", fill: "currentColor", children: [
|
|
2903
2936
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "2", cy: "2", r: "1.5" }),
|
|
2904
2937
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "8", cy: "2", r: "1.5" }),
|
|
@@ -2907,51 +2940,94 @@ var DragHandleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg",
|
|
|
2907
2940
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "2", cy: "12", r: "1.5" }),
|
|
2908
2941
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "8", cy: "12", r: "1.5" })
|
|
2909
2942
|
] });
|
|
2910
|
-
var ChevronRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2943
|
+
var ChevronRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2944
|
+
"svg",
|
|
2945
|
+
{
|
|
2946
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2947
|
+
width: "14",
|
|
2948
|
+
height: "14",
|
|
2949
|
+
viewBox: "0 0 24 24",
|
|
2950
|
+
fill: "none",
|
|
2951
|
+
stroke: "currentColor",
|
|
2952
|
+
strokeWidth: "2",
|
|
2953
|
+
strokeLinecap: "round",
|
|
2954
|
+
strokeLinejoin: "round",
|
|
2955
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m9 18 6-6-6-6" })
|
|
2956
|
+
}
|
|
2957
|
+
);
|
|
2958
|
+
var ArrowLeft = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2959
|
+
"svg",
|
|
2960
|
+
{
|
|
2961
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2962
|
+
width: "16",
|
|
2963
|
+
height: "16",
|
|
2964
|
+
viewBox: "0 0 24 24",
|
|
2965
|
+
fill: "none",
|
|
2966
|
+
stroke: "currentColor",
|
|
2967
|
+
strokeWidth: "2",
|
|
2968
|
+
strokeLinecap: "round",
|
|
2969
|
+
strokeLinejoin: "round",
|
|
2970
|
+
children: [
|
|
2971
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m12 19-7-7 7-7" }),
|
|
2972
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M19 12H5" })
|
|
2973
|
+
]
|
|
2974
|
+
}
|
|
2975
|
+
);
|
|
2976
|
+
var ArrowRight = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2977
|
+
"svg",
|
|
2978
|
+
{
|
|
2979
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2980
|
+
width: "16",
|
|
2981
|
+
height: "16",
|
|
2982
|
+
viewBox: "0 0 24 24",
|
|
2983
|
+
fill: "none",
|
|
2984
|
+
stroke: "currentColor",
|
|
2985
|
+
strokeWidth: "2",
|
|
2986
|
+
strokeLinecap: "round",
|
|
2987
|
+
strokeLinejoin: "round",
|
|
2988
|
+
children: [
|
|
2989
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M5 12h14" }),
|
|
2990
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m12 5 7 7-7 7" })
|
|
2991
|
+
]
|
|
2992
|
+
}
|
|
2993
|
+
);
|
|
2916
2994
|
var HierarchyButton = ({
|
|
2917
2995
|
isChild,
|
|
2918
|
-
|
|
2919
|
-
rowIndex,
|
|
2996
|
+
rowIndex: _rowIndex,
|
|
2920
2997
|
onPromote,
|
|
2921
2998
|
onDemote
|
|
2922
2999
|
}) => {
|
|
2923
3000
|
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
|
-
|
|
3001
|
+
const canDemote = !!onDemote;
|
|
3002
|
+
if (!canPromote && !canDemote) return null;
|
|
3003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
3004
|
+
canPromote && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3005
|
+
"button",
|
|
3006
|
+
{
|
|
3007
|
+
type: "button",
|
|
3008
|
+
className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
|
|
3009
|
+
onClick: (e) => {
|
|
3010
|
+
e.stopPropagation();
|
|
3011
|
+
onPromote(e);
|
|
3012
|
+
},
|
|
3013
|
+
title: "\u041F\u043E\u0432\u044B\u0441\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
|
|
3014
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ArrowLeft, {})
|
|
3015
|
+
}
|
|
3016
|
+
),
|
|
3017
|
+
canDemote && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3018
|
+
"button",
|
|
3019
|
+
{
|
|
3020
|
+
type: "button",
|
|
3021
|
+
className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
|
|
3022
|
+
onClick: (e) => {
|
|
3023
|
+
e.stopPropagation();
|
|
3024
|
+
onDemote(e);
|
|
3025
|
+
},
|
|
3026
|
+
title: "\u041F\u043E\u043D\u0438\u0437\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
|
|
3027
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ArrowRight, {})
|
|
3028
|
+
}
|
|
3029
|
+
)
|
|
2944
3030
|
] });
|
|
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
3031
|
};
|
|
2956
3032
|
var DepChip = ({
|
|
2957
3033
|
lag,
|
|
@@ -2983,71 +3059,91 @@ var DepChip = ({
|
|
|
2983
3059
|
const nextOpen = !popoverOpen;
|
|
2984
3060
|
setPopoverOpen(nextOpen);
|
|
2985
3061
|
if (nextOpen) {
|
|
2986
|
-
onChipSelect?.({
|
|
3062
|
+
onChipSelect?.({
|
|
3063
|
+
successorId: taskId,
|
|
3064
|
+
predecessorId: dep.taskId,
|
|
3065
|
+
linkType: dep.type
|
|
3066
|
+
});
|
|
2987
3067
|
onScrollToTask?.(dep.taskId);
|
|
2988
3068
|
} else {
|
|
2989
3069
|
onChipSelect?.(null);
|
|
2990
3070
|
}
|
|
2991
3071
|
};
|
|
2992
|
-
const handleOpenChange = (0, import_react10.useCallback)(
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3072
|
+
const handleOpenChange = (0, import_react10.useCallback)(
|
|
3073
|
+
(open) => {
|
|
3074
|
+
setPopoverOpen(open);
|
|
3075
|
+
if (!open) {
|
|
3076
|
+
onChipSelect?.(null);
|
|
3077
|
+
}
|
|
3078
|
+
},
|
|
3079
|
+
[onChipSelect]
|
|
3080
|
+
);
|
|
2998
3081
|
const handleTrashClick = (e) => {
|
|
2999
3082
|
e.stopPropagation();
|
|
3000
3083
|
onRemoveDependency?.(taskId, dep.taskId, dep.type);
|
|
3001
3084
|
onChipSelectClear();
|
|
3002
3085
|
setPopoverOpen(false);
|
|
3003
3086
|
};
|
|
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
|
-
|
|
3087
|
+
const handleLagChange = (0, import_react10.useCallback)(
|
|
3088
|
+
(newLag) => {
|
|
3089
|
+
if (!onTasksChange || !allTasks) return;
|
|
3090
|
+
const taskById = new Map(allTasks.map((t) => [t.id, t]));
|
|
3091
|
+
const predecessor = taskById.get(dep.taskId);
|
|
3092
|
+
if (!predecessor) return;
|
|
3093
|
+
const predStart = parseUTCDate(predecessor.startDate);
|
|
3094
|
+
const predEnd = parseUTCDate(predecessor.endDate);
|
|
3095
|
+
const origStart = parseUTCDate(task.startDate);
|
|
3096
|
+
const origEnd = parseUTCDate(task.endDate);
|
|
3097
|
+
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
3098
|
+
const constraintDate = calculateSuccessorDate(
|
|
3099
|
+
predStart,
|
|
3100
|
+
predEnd,
|
|
3101
|
+
dep.type,
|
|
3102
|
+
newLag
|
|
3103
|
+
);
|
|
3104
|
+
let newStart, newEnd;
|
|
3105
|
+
if (dep.type === "FS" || dep.type === "SS") {
|
|
3106
|
+
newStart = constraintDate;
|
|
3107
|
+
newEnd = new Date(constraintDate.getTime() + durationMs);
|
|
3108
|
+
} else {
|
|
3109
|
+
newEnd = constraintDate;
|
|
3110
|
+
newStart = new Date(constraintDate.getTime() - durationMs);
|
|
3111
|
+
}
|
|
3112
|
+
onTasksChange([
|
|
3113
|
+
{
|
|
3114
|
+
...task,
|
|
3115
|
+
startDate: newStart.toISOString().split("T")[0],
|
|
3116
|
+
endDate: newEnd.toISOString().split("T")[0]
|
|
3117
|
+
}
|
|
3118
|
+
]);
|
|
3119
|
+
},
|
|
3120
|
+
[dep, task, allTasks, onTasksChange]
|
|
3121
|
+
);
|
|
3122
|
+
const handleInputCommit = (0, import_react10.useCallback)(
|
|
3123
|
+
(raw) => {
|
|
3124
|
+
if (raw === "") {
|
|
3125
|
+
handleLagChange(0);
|
|
3126
|
+
return;
|
|
3127
|
+
}
|
|
3128
|
+
const parsed = parseInt(raw, 10);
|
|
3129
|
+
const effectiveLag2 = lag ?? 0;
|
|
3130
|
+
if (isNaN(parsed)) {
|
|
3131
|
+
const abs = Math.abs(effectiveLag2);
|
|
3132
|
+
setInputAbs(abs === 0 ? "" : String(abs));
|
|
3133
|
+
return;
|
|
3134
|
+
}
|
|
3135
|
+
let newLag;
|
|
3136
|
+
if (parsed === 0) {
|
|
3137
|
+
newLag = 0;
|
|
3138
|
+
} else if (dep.type === "SF") {
|
|
3139
|
+
newLag = -Math.abs(parsed);
|
|
3140
|
+
} else {
|
|
3141
|
+
newLag = parsed;
|
|
3142
|
+
}
|
|
3143
|
+
if (newLag !== effectiveLag2) handleLagChange(newLag);
|
|
3144
|
+
},
|
|
3145
|
+
[lag, dep.type, handleLagChange]
|
|
3146
|
+
);
|
|
3051
3147
|
const Icon = LINK_TYPE_ICONS[dep.type];
|
|
3052
3148
|
const depName = predecessorName ?? dep.taskId;
|
|
3053
3149
|
const effectiveLag = lag ?? 0;
|
|
@@ -3086,67 +3182,92 @@ var DepChip = ({
|
|
|
3086
3182
|
]
|
|
3087
3183
|
}
|
|
3088
3184
|
) }),
|
|
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
|
-
|
|
3185
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3186
|
+
PopoverContent,
|
|
3187
|
+
{
|
|
3188
|
+
className: "gantt-tl-dep-edit-popover",
|
|
3189
|
+
portal: true,
|
|
3190
|
+
align: "start",
|
|
3191
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { onClick: (e) => e.stopPropagation(), children: [
|
|
3192
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "gantt-tl-dep-edit-task", children: task.name }),
|
|
3193
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-dep-edit-row", children: [
|
|
3194
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "gantt-tl-dep-edit-label", children: [
|
|
3195
|
+
actionVerb,
|
|
3196
|
+
preWord ? ` ${preWord}` : ""
|
|
3197
|
+
] }),
|
|
3198
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3199
|
+
"button",
|
|
3200
|
+
{
|
|
3201
|
+
type: "button",
|
|
3202
|
+
className: "gantt-tl-dep-edit-btn",
|
|
3203
|
+
onClick: () => handleLagChange(effectiveLag - 1),
|
|
3204
|
+
children: "\u2212"
|
|
3205
|
+
}
|
|
3206
|
+
),
|
|
3207
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3208
|
+
"input",
|
|
3209
|
+
{
|
|
3210
|
+
type: "number",
|
|
3211
|
+
className: "gantt-tl-dep-edit-input",
|
|
3212
|
+
value: inputAbs,
|
|
3213
|
+
placeholder: zeroPlaceholder,
|
|
3214
|
+
min: "0",
|
|
3215
|
+
onChange: (e) => setInputAbs(e.target.value),
|
|
3216
|
+
onFocus: (e) => e.target.select(),
|
|
3217
|
+
onBlur: (e) => handleInputCommit(e.target.value),
|
|
3218
|
+
onKeyDown: (e) => {
|
|
3219
|
+
if (e.key === "Enter") handleInputCommit(inputAbs);
|
|
3220
|
+
}
|
|
3221
|
+
}
|
|
3222
|
+
),
|
|
3223
|
+
!(dep.type === "SF" && effectiveLag === 0) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3224
|
+
"button",
|
|
3225
|
+
{
|
|
3226
|
+
type: "button",
|
|
3227
|
+
className: "gantt-tl-dep-edit-btn",
|
|
3228
|
+
onClick: () => handleLagChange(effectiveLag + 1),
|
|
3229
|
+
children: "+"
|
|
3230
|
+
}
|
|
3231
|
+
),
|
|
3232
|
+
effectiveLag !== 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u0434." }),
|
|
3233
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: afterWhat })
|
|
3234
|
+
] }),
|
|
3235
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "gantt-tl-dep-edit-pred", children: depName }),
|
|
3236
|
+
!disableDependencyEditing && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
3237
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("hr", { className: "gantt-tl-dep-edit-divider" }),
|
|
3238
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-dep-edit-actions", children: [
|
|
3239
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3240
|
+
"button",
|
|
3241
|
+
{
|
|
3242
|
+
type: "button",
|
|
3243
|
+
className: "gantt-tl-dep-edit-close",
|
|
3244
|
+
onClick: () => {
|
|
3245
|
+
setPopoverOpen(false);
|
|
3246
|
+
onChipSelectClear();
|
|
3247
|
+
},
|
|
3248
|
+
children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
|
|
3249
|
+
}
|
|
3250
|
+
),
|
|
3251
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3252
|
+
"button",
|
|
3253
|
+
{
|
|
3254
|
+
type: "button",
|
|
3255
|
+
className: "gantt-tl-dep-edit-delete",
|
|
3256
|
+
onClick: handleTrashClick,
|
|
3257
|
+
children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
|
|
3258
|
+
}
|
|
3259
|
+
)
|
|
3260
|
+
] })
|
|
3261
|
+
] })
|
|
3142
3262
|
] })
|
|
3143
|
-
|
|
3144
|
-
|
|
3263
|
+
}
|
|
3264
|
+
)
|
|
3145
3265
|
] });
|
|
3146
3266
|
};
|
|
3147
3267
|
var toISODate = (value) => {
|
|
3148
3268
|
if (value instanceof Date) return value.toISOString().split("T")[0];
|
|
3149
|
-
if (typeof value === "string" && value.includes("T"))
|
|
3269
|
+
if (typeof value === "string" && value.includes("T"))
|
|
3270
|
+
return value.split("T")[0];
|
|
3150
3271
|
return value;
|
|
3151
3272
|
};
|
|
3152
3273
|
var TaskListRow = import_react10.default.memo(
|
|
@@ -3183,13 +3304,17 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3183
3304
|
onToggleCollapse,
|
|
3184
3305
|
onPromoteTask,
|
|
3185
3306
|
onDemoteTask,
|
|
3186
|
-
isLastChild = true
|
|
3307
|
+
isLastChild = true,
|
|
3308
|
+
nestingDepth = 0,
|
|
3309
|
+
ancestorContinues = []
|
|
3187
3310
|
}) => {
|
|
3188
3311
|
const [editingName, setEditingName] = (0, import_react10.useState)(false);
|
|
3189
3312
|
const [nameValue, setNameValue] = (0, import_react10.useState)("");
|
|
3190
3313
|
const nameInputRef = (0, import_react10.useRef)(null);
|
|
3191
3314
|
const [editingDuration, setEditingDuration] = (0, import_react10.useState)(false);
|
|
3192
|
-
const [durationValue, setDurationValue] = (0, import_react10.useState)(
|
|
3315
|
+
const [durationValue, setDurationValue] = (0, import_react10.useState)(
|
|
3316
|
+
getInclusiveDurationDays(task.startDate, task.endDate)
|
|
3317
|
+
);
|
|
3193
3318
|
const durationInputRef = (0, import_react10.useRef)(null);
|
|
3194
3319
|
const [editingProgress, setEditingProgress] = (0, import_react10.useState)(false);
|
|
3195
3320
|
const [progressValue, setProgressValue] = (0, import_react10.useState)(0);
|
|
@@ -3199,11 +3324,16 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3199
3324
|
const durationConfirmedRef = (0, import_react10.useRef)(false);
|
|
3200
3325
|
const progressConfirmedRef = (0, import_react10.useRef)(false);
|
|
3201
3326
|
const autoEditedForRef = (0, import_react10.useRef)(null);
|
|
3202
|
-
const editTriggerRef = (0, import_react10.useRef)(
|
|
3327
|
+
const editTriggerRef = (0, import_react10.useRef)(
|
|
3328
|
+
"doubleclick"
|
|
3329
|
+
);
|
|
3203
3330
|
const [deletePending, setDeletePending] = (0, import_react10.useState)(false);
|
|
3204
3331
|
const deleteButtonRef = (0, import_react10.useRef)(null);
|
|
3205
3332
|
const isSelected = selectedTaskId === task.id;
|
|
3206
|
-
const isParent = (0, import_react10.useMemo)(
|
|
3333
|
+
const isParent = (0, import_react10.useMemo)(
|
|
3334
|
+
() => isTaskParent(task.id, allTasks),
|
|
3335
|
+
[task.id, allTasks]
|
|
3336
|
+
);
|
|
3207
3337
|
const isChild = task.parentId !== void 0;
|
|
3208
3338
|
const isCollapsed = collapsedParentIds.has(task.id);
|
|
3209
3339
|
const isPicking = selectingPredecessorFor != null;
|
|
@@ -3258,31 +3388,40 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3258
3388
|
setEditingName(true);
|
|
3259
3389
|
}
|
|
3260
3390
|
}, [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();
|
|
3391
|
+
const handleNameClick = (0, import_react10.useCallback)(
|
|
3392
|
+
(e) => {
|
|
3393
|
+
if (disableTaskNameEditing) return;
|
|
3394
|
+
e.stopPropagation();
|
|
3395
|
+
onRowClick?.(task.id);
|
|
3396
|
+
onScrollToTask?.(task.id);
|
|
3397
|
+
},
|
|
3398
|
+
[task.id, disableTaskNameEditing, onRowClick, onScrollToTask]
|
|
3399
|
+
);
|
|
3400
|
+
const handleNameDoubleClick = (0, import_react10.useCallback)(
|
|
3401
|
+
(e) => {
|
|
3402
|
+
if (disableTaskNameEditing) return;
|
|
3403
|
+
e.stopPropagation();
|
|
3279
3404
|
nameConfirmedRef.current = false;
|
|
3280
|
-
editTriggerRef.current = "
|
|
3405
|
+
editTriggerRef.current = "doubleclick";
|
|
3281
3406
|
setNameValue(task.name);
|
|
3282
3407
|
setEditingName(true);
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3408
|
+
},
|
|
3409
|
+
[task.name, disableTaskNameEditing]
|
|
3410
|
+
);
|
|
3411
|
+
const handleRowKeyDown = (0, import_react10.useCallback)(
|
|
3412
|
+
(e) => {
|
|
3413
|
+
if (editingProgress) return;
|
|
3414
|
+
if (!editingName && !disableTaskNameEditing && e.key === "F2") {
|
|
3415
|
+
e.preventDefault();
|
|
3416
|
+
nameConfirmedRef.current = false;
|
|
3417
|
+
editTriggerRef.current = "keypress";
|
|
3418
|
+
setNameValue(task.name);
|
|
3419
|
+
setEditingName(true);
|
|
3420
|
+
return;
|
|
3421
|
+
}
|
|
3422
|
+
},
|
|
3423
|
+
[editingName, disableTaskNameEditing, task.name]
|
|
3424
|
+
);
|
|
3286
3425
|
const handleNameSave = (0, import_react10.useCallback)(() => {
|
|
3287
3426
|
if (nameConfirmedRef.current) {
|
|
3288
3427
|
nameConfirmedRef.current = false;
|
|
@@ -3296,24 +3435,32 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3296
3435
|
const handleNameCancel = (0, import_react10.useCallback)(() => {
|
|
3297
3436
|
setEditingName(false);
|
|
3298
3437
|
}, []);
|
|
3299
|
-
const handleNameKeyDown = (0, import_react10.useCallback)(
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3438
|
+
const handleNameKeyDown = (0, import_react10.useCallback)(
|
|
3439
|
+
(e) => {
|
|
3440
|
+
if (e.key === "Enter") {
|
|
3441
|
+
nameConfirmedRef.current = true;
|
|
3442
|
+
if (nameValue.trim()) {
|
|
3443
|
+
onTasksChange?.([{ ...task, name: nameValue.trim() }]);
|
|
3444
|
+
}
|
|
3445
|
+
setEditingName(false);
|
|
3446
|
+
} else if (e.key === "Escape") {
|
|
3447
|
+
handleNameCancel();
|
|
3304
3448
|
}
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3449
|
+
},
|
|
3450
|
+
[nameValue, task, onTasksChange, handleNameCancel]
|
|
3451
|
+
);
|
|
3452
|
+
const handleDurationClick = (0, import_react10.useCallback)(
|
|
3453
|
+
(e) => {
|
|
3454
|
+
if (task.locked) return;
|
|
3455
|
+
e.stopPropagation();
|
|
3456
|
+
durationConfirmedRef.current = false;
|
|
3457
|
+
setDurationValue(
|
|
3458
|
+
getInclusiveDurationDays(task.startDate, task.endDate)
|
|
3459
|
+
);
|
|
3460
|
+
setEditingDuration(true);
|
|
3461
|
+
},
|
|
3462
|
+
[task.locked, task.startDate, task.endDate]
|
|
3463
|
+
);
|
|
3317
3464
|
const applyDurationChange = (0, import_react10.useCallback)((nextDuration) => {
|
|
3318
3465
|
const normalizedDuration = Math.max(1, Math.round(nextDuration) || 1);
|
|
3319
3466
|
setDurationValue(normalizedDuration);
|
|
@@ -3324,34 +3471,59 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3324
3471
|
return;
|
|
3325
3472
|
}
|
|
3326
3473
|
const normalizedDuration = Math.max(1, Math.round(durationValue) || 1);
|
|
3327
|
-
onTasksChange?.([
|
|
3474
|
+
onTasksChange?.([
|
|
3475
|
+
{
|
|
3476
|
+
...task,
|
|
3477
|
+
endDate: getEndDateFromDuration(task.startDate, normalizedDuration)
|
|
3478
|
+
}
|
|
3479
|
+
]);
|
|
3328
3480
|
setEditingDuration(false);
|
|
3329
3481
|
}, [durationValue, task, onTasksChange]);
|
|
3330
3482
|
const handleDurationCancel = (0, import_react10.useCallback)(() => {
|
|
3331
3483
|
setDurationValue(getInclusiveDurationDays(task.startDate, task.endDate));
|
|
3332
3484
|
setEditingDuration(false);
|
|
3333
3485
|
}, [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
|
-
|
|
3486
|
+
const handleDurationAdjust = (0, import_react10.useCallback)(
|
|
3487
|
+
(delta) => {
|
|
3488
|
+
applyDurationChange(durationValue + delta);
|
|
3489
|
+
},
|
|
3490
|
+
[applyDurationChange, durationValue]
|
|
3491
|
+
);
|
|
3492
|
+
const handleDurationKeyDown = (0, import_react10.useCallback)(
|
|
3493
|
+
(e) => {
|
|
3494
|
+
e.stopPropagation();
|
|
3495
|
+
if (e.key === "Enter") {
|
|
3496
|
+
durationConfirmedRef.current = true;
|
|
3497
|
+
const normalizedDuration = Math.max(
|
|
3498
|
+
1,
|
|
3499
|
+
Math.round(durationValue) || 1
|
|
3500
|
+
);
|
|
3501
|
+
onTasksChange?.([
|
|
3502
|
+
{
|
|
3503
|
+
...task,
|
|
3504
|
+
endDate: getEndDateFromDuration(
|
|
3505
|
+
task.startDate,
|
|
3506
|
+
normalizedDuration
|
|
3507
|
+
)
|
|
3508
|
+
}
|
|
3509
|
+
]);
|
|
3510
|
+
setEditingDuration(false);
|
|
3511
|
+
} else if (e.key === "Escape") {
|
|
3512
|
+
handleDurationCancel();
|
|
3513
|
+
}
|
|
3514
|
+
},
|
|
3515
|
+
[durationValue, task, onTasksChange, handleDurationCancel]
|
|
3516
|
+
);
|
|
3517
|
+
const handleProgressClick = (0, import_react10.useCallback)(
|
|
3518
|
+
(e) => {
|
|
3519
|
+
if (task.locked) return;
|
|
3520
|
+
e.stopPropagation();
|
|
3521
|
+
progressConfirmedRef.current = false;
|
|
3522
|
+
setProgressValue(task.progress ?? 0);
|
|
3523
|
+
setEditingProgress(true);
|
|
3524
|
+
},
|
|
3525
|
+
[task.progress, task.locked]
|
|
3526
|
+
);
|
|
3355
3527
|
const handleProgressSave = (0, import_react10.useCallback)(() => {
|
|
3356
3528
|
if (progressConfirmedRef.current) {
|
|
3357
3529
|
progressConfirmedRef.current = false;
|
|
@@ -3374,28 +3546,36 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3374
3546
|
setEditingProgress(false);
|
|
3375
3547
|
}, []);
|
|
3376
3548
|
const handleProgressAdjust = (0, import_react10.useCallback)((delta) => {
|
|
3377
|
-
setProgressValue(
|
|
3549
|
+
setProgressValue(
|
|
3550
|
+
(current) => Math.max(0, Math.min(100, current + delta))
|
|
3551
|
+
);
|
|
3378
3552
|
}, []);
|
|
3379
|
-
const handleProgressKeyDown = (0, import_react10.useCallback)(
|
|
3380
|
-
e
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3553
|
+
const handleProgressKeyDown = (0, import_react10.useCallback)(
|
|
3554
|
+
(e) => {
|
|
3555
|
+
e.stopPropagation();
|
|
3556
|
+
if (e.key === "Enter") {
|
|
3557
|
+
progressConfirmedRef.current = true;
|
|
3558
|
+
const clampedValue = Math.max(0, Math.min(100, progressValue));
|
|
3559
|
+
if ((clampedValue === 100 || clampedValue === 0) && isTaskParent(task.id, allTasks)) {
|
|
3560
|
+
const children = getChildren(task.id, allTasks);
|
|
3561
|
+
const updatedTasks = [
|
|
3562
|
+
{ ...task, progress: clampedValue },
|
|
3563
|
+
...children.map((child) => ({
|
|
3564
|
+
...child,
|
|
3565
|
+
progress: clampedValue
|
|
3566
|
+
}))
|
|
3567
|
+
];
|
|
3568
|
+
onTasksChange?.(updatedTasks);
|
|
3569
|
+
} else {
|
|
3570
|
+
onTasksChange?.([{ ...task, progress: clampedValue }]);
|
|
3571
|
+
}
|
|
3572
|
+
setEditingProgress(false);
|
|
3573
|
+
} else if (e.key === "Escape") {
|
|
3574
|
+
handleProgressCancel();
|
|
3393
3575
|
}
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
}
|
|
3398
|
-
}, [progressValue, task, onTasksChange, handleProgressCancel, allTasks]);
|
|
3576
|
+
},
|
|
3577
|
+
[progressValue, task, onTasksChange, handleProgressCancel, allTasks]
|
|
3578
|
+
);
|
|
3399
3579
|
(0, import_react10.useEffect)(() => {
|
|
3400
3580
|
if (editingProgress && progressInputRef.current) {
|
|
3401
3581
|
progressInputRef.current.focus();
|
|
@@ -3411,77 +3591,111 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3411
3591
|
durationInputRef.current.select();
|
|
3412
3592
|
}
|
|
3413
3593
|
}, [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
|
-
|
|
3594
|
+
const handleStartDateChange = (0, import_react10.useCallback)(
|
|
3595
|
+
(newDateISO) => {
|
|
3596
|
+
if (!newDateISO) return;
|
|
3597
|
+
const origStart = parseUTCDate(task.startDate);
|
|
3598
|
+
const origEnd = parseUTCDate(task.endDate);
|
|
3599
|
+
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
3600
|
+
const newStart = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
|
|
3601
|
+
const newEnd = new Date(newStart.getTime() + durationMs);
|
|
3602
|
+
const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(newDateISO, newEnd.toISOString().split("T")[0]);
|
|
3603
|
+
onTasksChange?.([
|
|
3604
|
+
{ ...task, startDate: normalizedStart, endDate: normalizedEnd }
|
|
3605
|
+
]);
|
|
3606
|
+
},
|
|
3607
|
+
[task, onTasksChange]
|
|
3608
|
+
);
|
|
3609
|
+
const handleEndDateChange = (0, import_react10.useCallback)(
|
|
3610
|
+
(newDateISO) => {
|
|
3611
|
+
if (!newDateISO) return;
|
|
3612
|
+
const origStart = parseUTCDate(task.startDate);
|
|
3613
|
+
const origEnd = parseUTCDate(task.endDate);
|
|
3614
|
+
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
3615
|
+
const newEnd = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
|
|
3616
|
+
const newStart = new Date(newEnd.getTime() - durationMs);
|
|
3617
|
+
const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(newStart.toISOString().split("T")[0], newDateISO);
|
|
3618
|
+
onTasksChange?.([
|
|
3619
|
+
{ ...task, startDate: normalizedStart, endDate: normalizedEnd }
|
|
3620
|
+
]);
|
|
3621
|
+
},
|
|
3622
|
+
[task, onTasksChange]
|
|
3623
|
+
);
|
|
3440
3624
|
const handleRowClickInternal = (0, import_react10.useCallback)(() => {
|
|
3441
3625
|
onRowClick?.(task.id);
|
|
3442
3626
|
}, [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
|
-
|
|
3627
|
+
const handleNumberClick = (0, import_react10.useCallback)(
|
|
3628
|
+
(e) => {
|
|
3629
|
+
e.stopPropagation();
|
|
3630
|
+
onRowClick?.(task.id);
|
|
3631
|
+
},
|
|
3632
|
+
[task.id, onRowClick]
|
|
3633
|
+
);
|
|
3634
|
+
const handleToggleCollapse = (0, import_react10.useCallback)(
|
|
3635
|
+
(e) => {
|
|
3636
|
+
e.stopPropagation();
|
|
3637
|
+
onToggleCollapse?.(task.id);
|
|
3638
|
+
},
|
|
3639
|
+
[task.id, onToggleCollapse]
|
|
3640
|
+
);
|
|
3641
|
+
const handlePromote = (0, import_react10.useCallback)(
|
|
3642
|
+
(e) => {
|
|
3643
|
+
e.stopPropagation();
|
|
3644
|
+
onPromoteTask?.(task.id);
|
|
3645
|
+
},
|
|
3646
|
+
[task.id, onPromoteTask]
|
|
3647
|
+
);
|
|
3648
|
+
const handleDemote = (0, import_react10.useCallback)(
|
|
3649
|
+
(e) => {
|
|
3650
|
+
e.stopPropagation();
|
|
3651
|
+
onDemoteTask?.(task.id, "");
|
|
3652
|
+
},
|
|
3653
|
+
[task.id, onDemoteTask]
|
|
3654
|
+
);
|
|
3655
|
+
const handleAddClick = (0, import_react10.useCallback)(
|
|
3656
|
+
(e) => {
|
|
3657
|
+
e.stopPropagation();
|
|
3658
|
+
onSetSelectingPredecessorFor?.(task.id);
|
|
3659
|
+
},
|
|
3660
|
+
[task.id, onSetSelectingPredecessorFor]
|
|
3661
|
+
);
|
|
3662
|
+
const handlePredecessorPick = (0, import_react10.useCallback)(
|
|
3663
|
+
(e) => {
|
|
3664
|
+
e.stopPropagation();
|
|
3665
|
+
if (!isPicking || isSourceRow) return;
|
|
3666
|
+
if (!selectingPredecessorFor || !activeLinkType) return;
|
|
3667
|
+
onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);
|
|
3668
|
+
},
|
|
3669
|
+
[
|
|
3670
|
+
isPicking,
|
|
3671
|
+
isSourceRow,
|
|
3672
|
+
selectingPredecessorFor,
|
|
3673
|
+
task.id,
|
|
3674
|
+
activeLinkType,
|
|
3675
|
+
onAddDependency
|
|
3676
|
+
]
|
|
3677
|
+
);
|
|
3678
|
+
const handleCancelPicking = (0, import_react10.useCallback)(
|
|
3679
|
+
(e) => {
|
|
3680
|
+
e.stopPropagation();
|
|
3681
|
+
onSetSelectingPredecessorFor?.(null);
|
|
3682
|
+
},
|
|
3683
|
+
[onSetSelectingPredecessorFor]
|
|
3684
|
+
);
|
|
3478
3685
|
const isSelectedPredecessor = selectedChip != null && selectedChip.predecessorId === task.id;
|
|
3479
|
-
const handleDeleteSelected = (0, import_react10.useCallback)(
|
|
3480
|
-
e
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3686
|
+
const handleDeleteSelected = (0, import_react10.useCallback)(
|
|
3687
|
+
(e) => {
|
|
3688
|
+
e.stopPropagation();
|
|
3689
|
+
if (!selectedChip) return;
|
|
3690
|
+
onRemoveDependency?.(
|
|
3691
|
+
selectedChip.successorId,
|
|
3692
|
+
selectedChip.predecessorId,
|
|
3693
|
+
selectedChip.linkType
|
|
3694
|
+
);
|
|
3695
|
+
onChipSelect?.(null);
|
|
3696
|
+
},
|
|
3697
|
+
[selectedChip, onRemoveDependency, onChipSelect]
|
|
3698
|
+
);
|
|
3485
3699
|
const startDateISO = toISODate(task.startDate);
|
|
3486
3700
|
const endDateISO = editingDuration ? getEndDateFromDuration(task.startDate, durationValue) : toISODate(task.endDate);
|
|
3487
3701
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
@@ -3534,13 +3748,78 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3534
3748
|
}
|
|
3535
3749
|
),
|
|
3536
3750
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
|
|
3537
|
-
isChild && !editingName && /* @__PURE__ */ (0, import_jsx_runtime12.
|
|
3751
|
+
isChild && !editingName && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
3752
|
+
ancestorContinues.map(
|
|
3753
|
+
(continues, idx) => continues ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3754
|
+
"span",
|
|
3755
|
+
{
|
|
3756
|
+
style: {
|
|
3757
|
+
position: "absolute",
|
|
3758
|
+
left: `${idx * 20 + 9}px`,
|
|
3759
|
+
top: 0,
|
|
3760
|
+
height: `${rowHeight}px`,
|
|
3761
|
+
width: "1.5px",
|
|
3762
|
+
background: "#d4bceb",
|
|
3763
|
+
borderRadius: "1px",
|
|
3764
|
+
pointerEvents: "none"
|
|
3765
|
+
}
|
|
3766
|
+
},
|
|
3767
|
+
idx
|
|
3768
|
+
) : null
|
|
3769
|
+
),
|
|
3770
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3771
|
+
"span",
|
|
3772
|
+
{
|
|
3773
|
+
style: {
|
|
3774
|
+
position: "absolute",
|
|
3775
|
+
left: `${(nestingDepth - 1) * 20 + 9}px`,
|
|
3776
|
+
top: 0,
|
|
3777
|
+
height: isLastChild ? `${rowHeight / 2}px` : `${rowHeight}px`,
|
|
3778
|
+
width: "1.5px",
|
|
3779
|
+
background: "#d4bceb",
|
|
3780
|
+
borderRadius: "1px",
|
|
3781
|
+
pointerEvents: "none"
|
|
3782
|
+
}
|
|
3783
|
+
}
|
|
3784
|
+
),
|
|
3785
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3786
|
+
"span",
|
|
3787
|
+
{
|
|
3788
|
+
style: {
|
|
3789
|
+
position: "absolute",
|
|
3790
|
+
left: `${(nestingDepth - 1) * 20 + 9}px`,
|
|
3791
|
+
top: `${rowHeight / 2 - 0.75}px`,
|
|
3792
|
+
width: "8px",
|
|
3793
|
+
height: "1.5px",
|
|
3794
|
+
background: "#d4bceb",
|
|
3795
|
+
borderRadius: "1px",
|
|
3796
|
+
pointerEvents: "none"
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
),
|
|
3800
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3801
|
+
"span",
|
|
3802
|
+
{
|
|
3803
|
+
style: {
|
|
3804
|
+
position: "absolute",
|
|
3805
|
+
left: `${(nestingDepth - 1) * 20 + 15}px`,
|
|
3806
|
+
top: `${rowHeight / 2 - 2}px`,
|
|
3807
|
+
width: "4px",
|
|
3808
|
+
height: "4px",
|
|
3809
|
+
borderRadius: "50%",
|
|
3810
|
+
background: "#d4bceb",
|
|
3811
|
+
pointerEvents: "none"
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
)
|
|
3815
|
+
] }),
|
|
3538
3816
|
isParent && !editingName && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3539
3817
|
"button",
|
|
3540
3818
|
{
|
|
3541
3819
|
type: "button",
|
|
3542
3820
|
className: `gantt-tl-collapse-btn ${isCollapsed ? "gantt-tl-collapse-btn-collapsed" : ""}`,
|
|
3543
3821
|
onClick: handleToggleCollapse,
|
|
3822
|
+
style: { left: `${nestingDepth * 20 + 4}px` },
|
|
3544
3823
|
"aria-label": isCollapsed ? "Expand children" : "Collapse children",
|
|
3545
3824
|
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronRightIcon, {})
|
|
3546
3825
|
}
|
|
@@ -3554,7 +3833,10 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3554
3833
|
onChange: (e) => setNameValue(e.target.value),
|
|
3555
3834
|
onBlur: handleNameSave,
|
|
3556
3835
|
onKeyDown: handleNameKeyDown,
|
|
3557
|
-
className:
|
|
3836
|
+
className: "gantt-tl-name-input",
|
|
3837
|
+
style: {
|
|
3838
|
+
paddingLeft: nestingDepth > 0 ? `${nestingDepth * 20 + 24}px` : void 0
|
|
3839
|
+
},
|
|
3558
3840
|
onClick: (e) => e.stopPropagation()
|
|
3559
3841
|
}
|
|
3560
3842
|
),
|
|
@@ -3564,14 +3846,15 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3564
3846
|
type: "button",
|
|
3565
3847
|
className: [
|
|
3566
3848
|
"gantt-tl-name-trigger",
|
|
3567
|
-
disableTaskNameEditing ? "gantt-tl-name-locked" : ""
|
|
3568
|
-
isParent ? "gantt-tl-name-trigger-parent" : "",
|
|
3569
|
-
isChild ? "gantt-tl-name-trigger-child" : ""
|
|
3849
|
+
disableTaskNameEditing ? "gantt-tl-name-locked" : ""
|
|
3570
3850
|
].filter(Boolean).join(" "),
|
|
3571
3851
|
title: task.name,
|
|
3572
3852
|
onClick: handleNameClick,
|
|
3573
3853
|
onDoubleClick: handleNameDoubleClick,
|
|
3574
|
-
style:
|
|
3854
|
+
style: {
|
|
3855
|
+
paddingLeft: nestingDepth > 0 ? `${nestingDepth * 20 + (isParent ? 26 : 8)}px` : isParent ? "26px" : void 0,
|
|
3856
|
+
...editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0
|
|
3857
|
+
},
|
|
3575
3858
|
children: task.name
|
|
3576
3859
|
}
|
|
3577
3860
|
),
|
|
@@ -3584,16 +3867,20 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3584
3867
|
onClick: (e) => {
|
|
3585
3868
|
e.stopPropagation();
|
|
3586
3869
|
const now = /* @__PURE__ */ new Date();
|
|
3587
|
-
const todayISO = new Date(
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3870
|
+
const todayISO = new Date(
|
|
3871
|
+
Date.UTC(
|
|
3872
|
+
now.getUTCFullYear(),
|
|
3873
|
+
now.getUTCMonth(),
|
|
3874
|
+
now.getUTCDate()
|
|
3875
|
+
)
|
|
3876
|
+
).toISOString().split("T")[0];
|
|
3877
|
+
const endISO = new Date(
|
|
3878
|
+
Date.UTC(
|
|
3879
|
+
now.getUTCFullYear(),
|
|
3880
|
+
now.getUTCMonth(),
|
|
3881
|
+
now.getUTCDate() + 7
|
|
3882
|
+
)
|
|
3883
|
+
).toISOString().split("T")[0];
|
|
3597
3884
|
const newTask = {
|
|
3598
3885
|
id: crypto.randomUUID(),
|
|
3599
3886
|
name: "\u041D\u043E\u0432\u0430\u044F \u0437\u0430\u0434\u0430\u0447\u0430",
|
|
@@ -3629,7 +3916,6 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3629
3916
|
HierarchyButton,
|
|
3630
3917
|
{
|
|
3631
3918
|
isChild,
|
|
3632
|
-
isParent,
|
|
3633
3919
|
rowIndex,
|
|
3634
3920
|
onPromote: onPromoteTask ? handlePromote : void 0,
|
|
3635
3921
|
onDemote: onDemoteTask ? handleDemote : void 0
|
|
@@ -3637,113 +3923,228 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3637
3923
|
)
|
|
3638
3924
|
] })
|
|
3639
3925
|
] }),
|
|
3640
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3641
|
-
|
|
3926
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3927
|
+
"div",
|
|
3642
3928
|
{
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3929
|
+
className: "gantt-tl-cell gantt-tl-cell-date",
|
|
3930
|
+
onClick: (e) => e.stopPropagation(),
|
|
3931
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3932
|
+
DatePicker,
|
|
3933
|
+
{
|
|
3934
|
+
value: startDateISO,
|
|
3935
|
+
onChange: handleStartDateChange,
|
|
3936
|
+
format: "dd.MM.yy",
|
|
3937
|
+
portal: true,
|
|
3938
|
+
disabled: task.locked
|
|
3939
|
+
}
|
|
3940
|
+
)
|
|
3648
3941
|
}
|
|
3649
|
-
)
|
|
3650
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3651
|
-
|
|
3942
|
+
),
|
|
3943
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3944
|
+
"div",
|
|
3652
3945
|
{
|
|
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,
|
|
3946
|
+
className: "gantt-tl-cell gantt-tl-cell-date",
|
|
3947
|
+
onClick: (e) => e.stopPropagation(),
|
|
3948
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3949
|
+
DatePicker,
|
|
3664
3950
|
{
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) || 1),
|
|
3671
|
-
onBlur: handleDurationSave,
|
|
3672
|
-
onKeyDown: handleDurationKeyDown,
|
|
3673
|
-
className: "gantt-tl-number-input"
|
|
3951
|
+
value: endDateISO,
|
|
3952
|
+
onChange: handleEndDateChange,
|
|
3953
|
+
format: "dd.MM.yy",
|
|
3954
|
+
portal: true,
|
|
3955
|
+
disabled: task.locked
|
|
3674
3956
|
}
|
|
3675
|
-
)
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3957
|
+
)
|
|
3958
|
+
}
|
|
3959
|
+
),
|
|
3960
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
3961
|
+
"div",
|
|
3962
|
+
{
|
|
3963
|
+
className: "gantt-tl-cell gantt-tl-cell-duration",
|
|
3964
|
+
onClick: handleDurationClick,
|
|
3965
|
+
children: [
|
|
3966
|
+
editingDuration && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
3967
|
+
"div",
|
|
3679
3968
|
{
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3969
|
+
className: "gantt-tl-number-editor",
|
|
3970
|
+
onClick: (e) => e.stopPropagation(),
|
|
3971
|
+
children: [
|
|
3972
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3973
|
+
Input,
|
|
3974
|
+
{
|
|
3975
|
+
ref: durationInputRef,
|
|
3976
|
+
type: "number",
|
|
3977
|
+
min: 1,
|
|
3978
|
+
step: 1,
|
|
3979
|
+
value: durationValue,
|
|
3980
|
+
onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) || 1),
|
|
3981
|
+
onBlur: handleDurationSave,
|
|
3982
|
+
onKeyDown: handleDurationKeyDown,
|
|
3983
|
+
className: "gantt-tl-number-input"
|
|
3984
|
+
}
|
|
3985
|
+
),
|
|
3986
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
|
|
3987
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3988
|
+
"button",
|
|
3989
|
+
{
|
|
3990
|
+
type: "button",
|
|
3991
|
+
className: "gantt-tl-number-stepper",
|
|
3992
|
+
tabIndex: -1,
|
|
3993
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
3994
|
+
onClick: () => handleDurationAdjust(1),
|
|
3995
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3996
|
+
"svg",
|
|
3997
|
+
{
|
|
3998
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3999
|
+
width: "10",
|
|
4000
|
+
height: "10",
|
|
4001
|
+
viewBox: "0 0 24 24",
|
|
4002
|
+
fill: "none",
|
|
4003
|
+
stroke: "currentColor",
|
|
4004
|
+
strokeWidth: "2",
|
|
4005
|
+
strokeLinecap: "round",
|
|
4006
|
+
strokeLinejoin: "round",
|
|
4007
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m18 15-6-6-6 6" })
|
|
4008
|
+
}
|
|
4009
|
+
)
|
|
4010
|
+
}
|
|
4011
|
+
),
|
|
4012
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4013
|
+
"button",
|
|
4014
|
+
{
|
|
4015
|
+
type: "button",
|
|
4016
|
+
className: "gantt-tl-number-stepper",
|
|
4017
|
+
tabIndex: -1,
|
|
4018
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4019
|
+
onClick: () => handleDurationAdjust(-1),
|
|
4020
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4021
|
+
"svg",
|
|
4022
|
+
{
|
|
4023
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4024
|
+
width: "10",
|
|
4025
|
+
height: "10",
|
|
4026
|
+
viewBox: "0 0 24 24",
|
|
4027
|
+
fill: "none",
|
|
4028
|
+
stroke: "currentColor",
|
|
4029
|
+
strokeWidth: "2",
|
|
4030
|
+
strokeLinecap: "round",
|
|
4031
|
+
strokeLinejoin: "round",
|
|
4032
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" })
|
|
4033
|
+
}
|
|
4034
|
+
)
|
|
4035
|
+
}
|
|
4036
|
+
)
|
|
4037
|
+
] })
|
|
4038
|
+
]
|
|
3686
4039
|
}
|
|
3687
4040
|
),
|
|
3688
4041
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3689
|
-
"
|
|
4042
|
+
"span",
|
|
3690
4043
|
{
|
|
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" }) })
|
|
4044
|
+
style: editingDuration ? { visibility: "hidden", pointerEvents: "none" } : void 0,
|
|
4045
|
+
children: getInclusiveDurationDays(task.startDate, task.endDate)
|
|
3697
4046
|
}
|
|
3698
4047
|
)
|
|
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",
|
|
4048
|
+
]
|
|
4049
|
+
}
|
|
4050
|
+
),
|
|
4051
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
4052
|
+
"div",
|
|
4053
|
+
{
|
|
4054
|
+
className: "gantt-tl-cell gantt-tl-cell-progress",
|
|
4055
|
+
onClick: handleProgressClick,
|
|
4056
|
+
children: [
|
|
4057
|
+
editingProgress && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
4058
|
+
"div",
|
|
3723
4059
|
{
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
4060
|
+
className: "gantt-tl-number-editor",
|
|
4061
|
+
onClick: (e) => e.stopPropagation(),
|
|
4062
|
+
children: [
|
|
4063
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4064
|
+
Input,
|
|
4065
|
+
{
|
|
4066
|
+
ref: progressInputRef,
|
|
4067
|
+
type: "number",
|
|
4068
|
+
min: 0,
|
|
4069
|
+
max: 100,
|
|
4070
|
+
step: 1,
|
|
4071
|
+
value: progressValue,
|
|
4072
|
+
onChange: (e) => setProgressValue(parseInt(e.target.value, 10) || 0),
|
|
4073
|
+
onBlur: handleProgressSave,
|
|
4074
|
+
onKeyDown: handleProgressKeyDown,
|
|
4075
|
+
className: "gantt-tl-number-input"
|
|
4076
|
+
}
|
|
4077
|
+
),
|
|
4078
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
|
|
4079
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4080
|
+
"button",
|
|
4081
|
+
{
|
|
4082
|
+
type: "button",
|
|
4083
|
+
className: "gantt-tl-number-stepper",
|
|
4084
|
+
tabIndex: -1,
|
|
4085
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4086
|
+
onClick: () => handleProgressAdjust(1),
|
|
4087
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4088
|
+
"svg",
|
|
4089
|
+
{
|
|
4090
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4091
|
+
width: "10",
|
|
4092
|
+
height: "10",
|
|
4093
|
+
viewBox: "0 0 24 24",
|
|
4094
|
+
fill: "none",
|
|
4095
|
+
stroke: "currentColor",
|
|
4096
|
+
strokeWidth: "2",
|
|
4097
|
+
strokeLinecap: "round",
|
|
4098
|
+
strokeLinejoin: "round",
|
|
4099
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m18 15-6-6-6 6" })
|
|
4100
|
+
}
|
|
4101
|
+
)
|
|
4102
|
+
}
|
|
4103
|
+
),
|
|
4104
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4105
|
+
"button",
|
|
4106
|
+
{
|
|
4107
|
+
type: "button",
|
|
4108
|
+
className: "gantt-tl-number-stepper",
|
|
4109
|
+
tabIndex: -1,
|
|
4110
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4111
|
+
onClick: () => handleProgressAdjust(-1),
|
|
4112
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4113
|
+
"svg",
|
|
4114
|
+
{
|
|
4115
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4116
|
+
width: "10",
|
|
4117
|
+
height: "10",
|
|
4118
|
+
viewBox: "0 0 24 24",
|
|
4119
|
+
fill: "none",
|
|
4120
|
+
stroke: "currentColor",
|
|
4121
|
+
strokeWidth: "2",
|
|
4122
|
+
strokeLinecap: "round",
|
|
4123
|
+
strokeLinejoin: "round",
|
|
4124
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" })
|
|
4125
|
+
}
|
|
4126
|
+
)
|
|
4127
|
+
}
|
|
4128
|
+
)
|
|
4129
|
+
] })
|
|
4130
|
+
]
|
|
3730
4131
|
}
|
|
3731
4132
|
),
|
|
3732
4133
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3733
|
-
"
|
|
4134
|
+
"span",
|
|
3734
4135
|
{
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
4136
|
+
style: editingProgress ? { visibility: "hidden", pointerEvents: "none" } : task.progress === 100 ? {
|
|
4137
|
+
backgroundColor: "#17c864",
|
|
4138
|
+
borderRadius: "4px",
|
|
4139
|
+
padding: "2px 4px",
|
|
4140
|
+
color: "#ffffff"
|
|
4141
|
+
} : void 0,
|
|
4142
|
+
children: task.progress ? Math.round(task.progress) === 100 ? "100" : `${Math.round(task.progress)}%` : "0%"
|
|
3741
4143
|
}
|
|
3742
4144
|
)
|
|
3743
|
-
]
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
] }),
|
|
4145
|
+
]
|
|
4146
|
+
}
|
|
4147
|
+
),
|
|
3747
4148
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3748
4149
|
"div",
|
|
3749
4150
|
{
|
|
@@ -3784,26 +4185,33 @@ var TaskListRow = import_react10.default.memo(
|
|
|
3784
4185
|
]
|
|
3785
4186
|
}
|
|
3786
4187
|
) }),
|
|
3787
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3788
|
-
|
|
4188
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4189
|
+
"div",
|
|
3789
4190
|
{
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
4191
|
+
className: "gantt-tl-dep-overflow-list",
|
|
4192
|
+
onClick: (e) => e.stopPropagation(),
|
|
4193
|
+
children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4194
|
+
DepChip,
|
|
4195
|
+
{
|
|
4196
|
+
lag,
|
|
4197
|
+
dep,
|
|
4198
|
+
taskId: task.id,
|
|
4199
|
+
predecessorName,
|
|
4200
|
+
selectedChip,
|
|
4201
|
+
disableDependencyEditing,
|
|
4202
|
+
onChipSelect,
|
|
4203
|
+
onRowClick,
|
|
4204
|
+
onScrollToTask,
|
|
4205
|
+
onRemoveDependency,
|
|
4206
|
+
onChipSelectClear: () => onChipSelect?.(null),
|
|
4207
|
+
task,
|
|
4208
|
+
allTasks,
|
|
4209
|
+
onTasksChange
|
|
4210
|
+
},
|
|
4211
|
+
`${dep.taskId}-${dep.type}`
|
|
4212
|
+
))
|
|
4213
|
+
}
|
|
4214
|
+
) })
|
|
3807
4215
|
] })
|
|
3808
4216
|
) : chips.length === 1 ? (
|
|
3809
4217
|
/* Single chip — unified DepChip */
|
|
@@ -4002,6 +4410,25 @@ var TaskList = ({
|
|
|
4002
4410
|
() => visibleTasks.length * rowHeight,
|
|
4003
4411
|
[visibleTasks.length, rowHeight]
|
|
4004
4412
|
);
|
|
4413
|
+
const nestingDepthMap = (0, import_react12.useMemo)(() => {
|
|
4414
|
+
const depthMap = /* @__PURE__ */ new Map();
|
|
4415
|
+
const taskById = new Map(tasks.map((t) => [t.id, t]));
|
|
4416
|
+
function getDepth(taskId) {
|
|
4417
|
+
if (depthMap.has(taskId)) return depthMap.get(taskId);
|
|
4418
|
+
const task = taskById.get(taskId);
|
|
4419
|
+
if (!task || !task.parentId || !taskById.has(task.parentId)) {
|
|
4420
|
+
depthMap.set(taskId, 0);
|
|
4421
|
+
return 0;
|
|
4422
|
+
}
|
|
4423
|
+
const depth = getDepth(task.parentId) + 1;
|
|
4424
|
+
depthMap.set(taskId, depth);
|
|
4425
|
+
return depth;
|
|
4426
|
+
}
|
|
4427
|
+
for (const task of tasks) {
|
|
4428
|
+
getDepth(task.id);
|
|
4429
|
+
}
|
|
4430
|
+
return depthMap;
|
|
4431
|
+
}, [tasks]);
|
|
4005
4432
|
const lastChildIds = (0, import_react12.useMemo)(() => {
|
|
4006
4433
|
const last = /* @__PURE__ */ new Set();
|
|
4007
4434
|
const seenParents = /* @__PURE__ */ new Set();
|
|
@@ -4014,6 +4441,20 @@ var TaskList = ({
|
|
|
4014
4441
|
}
|
|
4015
4442
|
return last;
|
|
4016
4443
|
}, [visibleTasks]);
|
|
4444
|
+
const ancestorContinuesMap = (0, import_react12.useMemo)(() => {
|
|
4445
|
+
const taskById = new Map(tasks.map((t) => [t.id, t]));
|
|
4446
|
+
const map = /* @__PURE__ */ new Map();
|
|
4447
|
+
for (const task of visibleTasks) {
|
|
4448
|
+
const continues = [];
|
|
4449
|
+
let current = taskById.get(task.id);
|
|
4450
|
+
while (current?.parentId && taskById.has(current.parentId)) {
|
|
4451
|
+
continues.unshift(!lastChildIds.has(current.id));
|
|
4452
|
+
current = taskById.get(current.parentId);
|
|
4453
|
+
}
|
|
4454
|
+
map.set(task.id, continues.slice(0, -1));
|
|
4455
|
+
}
|
|
4456
|
+
return map;
|
|
4457
|
+
}, [tasks, visibleTasks, lastChildIds]);
|
|
4017
4458
|
const handleRowClick = (0, import_react12.useCallback)((taskId) => {
|
|
4018
4459
|
onTaskSelect?.(taskId);
|
|
4019
4460
|
}, [onTaskSelect]);
|
|
@@ -4124,9 +4565,6 @@ var TaskList = ({
|
|
|
4124
4565
|
if (dropTarget.parentId === draggedTaskId) {
|
|
4125
4566
|
return false;
|
|
4126
4567
|
}
|
|
4127
|
-
if (dropTarget.parentId) {
|
|
4128
|
-
return false;
|
|
4129
|
-
}
|
|
4130
4568
|
const draggedTask = orderedTasks.find((t) => t.id === draggedTaskId);
|
|
4131
4569
|
if (!draggedTask) return true;
|
|
4132
4570
|
const descendants = getAllDescendants(draggedTaskId, orderedTasks);
|
|
@@ -4272,6 +4710,52 @@ var TaskList = ({
|
|
|
4272
4710
|
setIsCreating(false);
|
|
4273
4711
|
}, [onAdd]);
|
|
4274
4712
|
const handleCancelNewTask = (0, import_react12.useCallback)(() => setIsCreating(false), []);
|
|
4713
|
+
function getTaskDepth(task, tasks2) {
|
|
4714
|
+
if (!task) return 0;
|
|
4715
|
+
let depth = 0;
|
|
4716
|
+
let current = task;
|
|
4717
|
+
while (current) {
|
|
4718
|
+
if (!current.parentId) break;
|
|
4719
|
+
depth++;
|
|
4720
|
+
const parentId = current.parentId;
|
|
4721
|
+
current = tasks2.find((t) => t.id === parentId);
|
|
4722
|
+
}
|
|
4723
|
+
return depth;
|
|
4724
|
+
}
|
|
4725
|
+
const handleDemoteWrapper = (0, import_react12.useCallback)((taskId, _newParentId) => {
|
|
4726
|
+
const taskIndex = visibleTasks.findIndex((t) => t.id === taskId);
|
|
4727
|
+
const currentTask = visibleTasks[taskIndex];
|
|
4728
|
+
const currentDepth = getTaskDepth(currentTask, orderedTasks);
|
|
4729
|
+
if (taskIndex > 0) {
|
|
4730
|
+
for (let i = taskIndex - 1; i >= 0; i--) {
|
|
4731
|
+
const previousTask = visibleTasks[i];
|
|
4732
|
+
const previousDepth = getTaskDepth(previousTask, orderedTasks);
|
|
4733
|
+
if (previousDepth === currentDepth) {
|
|
4734
|
+
onDemoteTask?.(taskId, previousTask.id);
|
|
4735
|
+
return;
|
|
4736
|
+
}
|
|
4737
|
+
if (previousDepth < currentDepth) {
|
|
4738
|
+
break;
|
|
4739
|
+
}
|
|
4740
|
+
}
|
|
4741
|
+
return;
|
|
4742
|
+
}
|
|
4743
|
+
const demotedTask = orderedTasks.find((t) => t.id === taskId);
|
|
4744
|
+
if (!demotedTask) return;
|
|
4745
|
+
const newSectionTask = {
|
|
4746
|
+
id: crypto.randomUUID(),
|
|
4747
|
+
name: "\u041D\u043E\u0432\u044B\u0439 \u0440\u0430\u0437\u0434\u0435\u043B",
|
|
4748
|
+
startDate: demotedTask.startDate,
|
|
4749
|
+
endDate: demotedTask.endDate
|
|
4750
|
+
};
|
|
4751
|
+
const updatedTasks = [
|
|
4752
|
+
newSectionTask,
|
|
4753
|
+
...orderedTasks.map(
|
|
4754
|
+
(t) => t.id === taskId ? { ...t, parentId: newSectionTask.id } : t
|
|
4755
|
+
)
|
|
4756
|
+
];
|
|
4757
|
+
onReorder?.(updatedTasks, taskId, newSectionTask.id);
|
|
4758
|
+
}, [visibleTasks, orderedTasks, onDemoteTask, onReorder]);
|
|
4275
4759
|
const effectiveTaskListWidth = Math.max(taskListWidth, MIN_TASK_LIST_WIDTH);
|
|
4276
4760
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
4277
4761
|
"div",
|
|
@@ -4355,8 +4839,10 @@ var TaskList = ({
|
|
|
4355
4839
|
collapsedParentIds,
|
|
4356
4840
|
onToggleCollapse: handleToggleCollapse,
|
|
4357
4841
|
onPromoteTask,
|
|
4358
|
-
onDemoteTask,
|
|
4359
|
-
isLastChild: lastChildIds.has(task.id)
|
|
4842
|
+
onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
|
|
4843
|
+
isLastChild: lastChildIds.has(task.id),
|
|
4844
|
+
nestingDepth: nestingDepthMap.get(task.id) ?? 0,
|
|
4845
|
+
ancestorContinues: ancestorContinuesMap.get(task.id) ?? []
|
|
4360
4846
|
},
|
|
4361
4847
|
task.id
|
|
4362
4848
|
)) }),
|
|
@@ -4665,6 +5151,17 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4665
5151
|
}),
|
|
4666
5152
|
[scrollToToday, scrollToTask, handleCollapseAll, handleExpandAll]
|
|
4667
5153
|
);
|
|
5154
|
+
function getTaskDepth(taskId, tasks2) {
|
|
5155
|
+
let depth = 0;
|
|
5156
|
+
let current = tasks2.find((t) => t.id === taskId);
|
|
5157
|
+
while (current) {
|
|
5158
|
+
if (!current.parentId) break;
|
|
5159
|
+
depth++;
|
|
5160
|
+
const parentId = current.parentId;
|
|
5161
|
+
current = tasks2.find((t) => t.id === parentId);
|
|
5162
|
+
}
|
|
5163
|
+
return depth;
|
|
5164
|
+
}
|
|
4668
5165
|
const handlePromoteTask = (0, import_react13.useCallback)((taskId) => {
|
|
4669
5166
|
if (onPromoteTask) {
|
|
4670
5167
|
onPromoteTask(taskId);
|
|
@@ -4674,20 +5171,20 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4674
5171
|
if (!taskToPromote || !taskToPromote.parentId) {
|
|
4675
5172
|
return;
|
|
4676
5173
|
}
|
|
4677
|
-
const
|
|
4678
|
-
const
|
|
5174
|
+
const depth = getTaskDepth(taskId, tasks);
|
|
5175
|
+
const grandparentId = depth > 1 ? tasks.find((t) => t.id === taskToPromote.parentId)?.parentId : void 0;
|
|
5176
|
+
const currentParentId = taskToPromote.parentId;
|
|
5177
|
+
const siblings = tasks.filter((t) => t.parentId === currentParentId);
|
|
5178
|
+
const promotedTask = { ...taskToPromote, parentId: grandparentId };
|
|
4679
5179
|
if (siblings.length <= 1) {
|
|
4680
|
-
|
|
4681
|
-
onTasksChange?.([promotedTask2]);
|
|
5180
|
+
onTasksChange?.([promotedTask]);
|
|
4682
5181
|
return;
|
|
4683
5182
|
}
|
|
4684
|
-
const lastSiblingIndex = tasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId ===
|
|
5183
|
+
const lastSiblingIndex = tasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId === currentParentId).sort((a, b) => b.index - a.index)[0];
|
|
4685
5184
|
if (!lastSiblingIndex) {
|
|
4686
|
-
|
|
4687
|
-
onTasksChange?.([promotedTask2]);
|
|
5185
|
+
onTasksChange?.([promotedTask]);
|
|
4688
5186
|
return;
|
|
4689
5187
|
}
|
|
4690
|
-
const promotedTask = { ...taskToPromote, parentId: void 0 };
|
|
4691
5188
|
const reorderedTasks = normalizeHierarchyTasks([
|
|
4692
5189
|
...tasks.filter((t) => t.id !== taskId).slice(0, lastSiblingIndex.index + 1),
|
|
4693
5190
|
promotedTask,
|