gantt-lib 0.145.1 → 0.146.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/scheduling/index.js +17 -7
- package/dist/core/scheduling/index.js.map +1 -1
- package/dist/core/scheduling/index.mjs +17 -7
- package/dist/core/scheduling/index.mjs.map +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.js +150 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +150 -31
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +32 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2233,8 +2233,8 @@ function recalculateProjectSchedule(snapshot, options) {
|
|
|
2233
2233
|
}
|
|
2234
2234
|
}
|
|
2235
2235
|
const queue = snapshot.filter((task) => (indegree.get(task.id) ?? 0) === 0).map((task) => task.id);
|
|
2236
|
-
|
|
2237
|
-
const currentId = queue
|
|
2236
|
+
for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
|
|
2237
|
+
const currentId = queue[queueIndex];
|
|
2238
2238
|
for (const successorId of successorIdsByTask.get(currentId) ?? []) {
|
|
2239
2239
|
const nextIndegree = (indegree.get(successorId) ?? 0) - 1;
|
|
2240
2240
|
indegree.set(successorId, nextIndegree);
|
|
@@ -2285,7 +2285,13 @@ function recalculateProjectSchedule(snapshot, options) {
|
|
|
2285
2285
|
queue.push(successorId);
|
|
2286
2286
|
}
|
|
2287
2287
|
}
|
|
2288
|
-
const
|
|
2288
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
2289
|
+
for (const task of snapshot) if (task.parentId) {
|
|
2290
|
+
const children = childrenByParent.get(task.parentId) ?? [];
|
|
2291
|
+
children.push(task.id);
|
|
2292
|
+
childrenByParent.set(task.parentId, children);
|
|
2293
|
+
}
|
|
2294
|
+
const parentsByDepth = snapshot.filter((task) => childrenByParent.has(task.id)).map((task) => {
|
|
2289
2295
|
let depth = 0;
|
|
2290
2296
|
let current = task.parentId ? workingMap.get(task.parentId) : void 0;
|
|
2291
2297
|
while (current) {
|
|
@@ -2294,17 +2300,21 @@ function recalculateProjectSchedule(snapshot, options) {
|
|
|
2294
2300
|
}
|
|
2295
2301
|
return { taskId: task.id, depth };
|
|
2296
2302
|
}).sort((left, right) => right.depth - left.depth);
|
|
2297
|
-
const workingTasks = () => Array.from(workingMap.values());
|
|
2298
2303
|
for (const { taskId } of parentsByDepth) {
|
|
2299
2304
|
const parent = workingMap.get(taskId);
|
|
2300
2305
|
if (!parent || parent.locked) {
|
|
2301
2306
|
continue;
|
|
2302
2307
|
}
|
|
2303
|
-
|
|
2308
|
+
let startTime = Infinity, endTime = -Infinity;
|
|
2309
|
+
for (const childId of childrenByParent.get(taskId)) {
|
|
2310
|
+
const child = workingMap.get(childId);
|
|
2311
|
+
startTime = Math.min(startTime, new Date(child.startDate).getTime());
|
|
2312
|
+
endTime = Math.max(endTime, new Date(child.endDate).getTime());
|
|
2313
|
+
}
|
|
2304
2314
|
workingMap.set(taskId, {
|
|
2305
2315
|
...parent,
|
|
2306
|
-
startDate: toIsoDate(
|
|
2307
|
-
endDate: toIsoDate(
|
|
2316
|
+
startDate: toIsoDate(new Date(startTime)),
|
|
2317
|
+
endDate: toIsoDate(new Date(endTime))
|
|
2308
2318
|
});
|
|
2309
2319
|
}
|
|
2310
2320
|
return createChangedResult(snapshot, Array.from(workingMap.values()));
|
|
@@ -7706,6 +7716,7 @@ var DepChip = ({
|
|
|
7706
7716
|
weekendPredicate
|
|
7707
7717
|
}) => {
|
|
7708
7718
|
const [popoverOpen, setPopoverOpen] = (0, import_react12.useState)(false);
|
|
7719
|
+
const [typeMenuOpen, setTypeMenuOpen] = (0, import_react12.useState)(false);
|
|
7709
7720
|
const lagAbs = Math.abs(lag ?? 0);
|
|
7710
7721
|
const [inputAbs, setInputAbs] = (0, import_react12.useState)(lagAbs === 0 ? "" : String(lagAbs));
|
|
7711
7722
|
(0, import_react12.useEffect)(() => {
|
|
@@ -7827,6 +7838,69 @@ var DepChip = ({
|
|
|
7827
7838
|
const Icon = LINK_TYPE_ICONS[dep.type];
|
|
7828
7839
|
const depName = predecessorName ?? dep.taskId;
|
|
7829
7840
|
const effectiveLag = lag ?? 0;
|
|
7841
|
+
const handleTypeChange = (0, import_react12.useCallback)(
|
|
7842
|
+
(newType) => {
|
|
7843
|
+
if (newType === dep.type) return;
|
|
7844
|
+
if (!onTasksChange || !allTasks) return;
|
|
7845
|
+
if ((task.dependencies ?? []).some((d) => d.taskId === dep.taskId && d.type === newType)) return;
|
|
7846
|
+
const taskById = new Map(allTasks.map((t) => [t.id, t]));
|
|
7847
|
+
const predecessor = taskById.get(dep.taskId);
|
|
7848
|
+
if (!predecessor) return;
|
|
7849
|
+
const predStart = parseUTCDate(predecessor.startDate);
|
|
7850
|
+
const predEnd = predecessor.type === "milestone" ? predStart : parseUTCDate(predecessor.endDate);
|
|
7851
|
+
const origStart = parseUTCDate(task.startDate);
|
|
7852
|
+
const origEnd = parseUTCDate(task.endDate);
|
|
7853
|
+
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
7854
|
+
const normalizedLag = normalizeDependencyLag(
|
|
7855
|
+
newType,
|
|
7856
|
+
effectiveLag,
|
|
7857
|
+
predStart,
|
|
7858
|
+
predEnd,
|
|
7859
|
+
businessDays,
|
|
7860
|
+
weekendPredicate,
|
|
7861
|
+
task.type
|
|
7862
|
+
);
|
|
7863
|
+
const constraintDate = calculateSuccessorDate(
|
|
7864
|
+
predStart,
|
|
7865
|
+
predEnd,
|
|
7866
|
+
newType,
|
|
7867
|
+
normalizedLag,
|
|
7868
|
+
businessDays,
|
|
7869
|
+
weekendPredicate,
|
|
7870
|
+
task.type
|
|
7871
|
+
);
|
|
7872
|
+
let newStart, newEnd;
|
|
7873
|
+
if (newType === "FS" || newType === "SS") {
|
|
7874
|
+
newStart = constraintDate;
|
|
7875
|
+
if (businessDays) {
|
|
7876
|
+
const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);
|
|
7877
|
+
newEnd = addBusinessDays(constraintDate, businessDuration, weekendPredicate);
|
|
7878
|
+
} else {
|
|
7879
|
+
newEnd = new Date(constraintDate.getTime() + durationMs);
|
|
7880
|
+
}
|
|
7881
|
+
} else {
|
|
7882
|
+
newEnd = constraintDate;
|
|
7883
|
+
if (businessDays) {
|
|
7884
|
+
const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);
|
|
7885
|
+
newStart = subtractBusinessDays(constraintDate, businessDuration, weekendPredicate);
|
|
7886
|
+
} else {
|
|
7887
|
+
newStart = new Date(constraintDate.getTime() - durationMs);
|
|
7888
|
+
}
|
|
7889
|
+
}
|
|
7890
|
+
onTasksChange([
|
|
7891
|
+
{
|
|
7892
|
+
...task,
|
|
7893
|
+
startDate: newStart.toISOString().split("T")[0],
|
|
7894
|
+
endDate: newEnd.toISOString().split("T")[0],
|
|
7895
|
+
dependencies: (task.dependencies ?? []).map(
|
|
7896
|
+
(existingDep) => existingDep.taskId === dep.taskId && existingDep.type === dep.type ? { ...existingDep, type: newType, lag: normalizedLag } : existingDep
|
|
7897
|
+
)
|
|
7898
|
+
}
|
|
7899
|
+
]);
|
|
7900
|
+
onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: newType });
|
|
7901
|
+
},
|
|
7902
|
+
[dep.type, dep.taskId, task, allTasks, onTasksChange, businessDays, weekendPredicate, effectiveLag, onChipSelect, taskId]
|
|
7903
|
+
);
|
|
7830
7904
|
const actionVerb = dep.type === "FS" || dep.type === "SS" ? "\u043D\u0430\u0447\u0430\u0442\u044C" : "\u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C";
|
|
7831
7905
|
const zeroPlaceholder = dep.type === "SF" ? "\u0447\u0451\u0442\u043A\u043E" : dep.type === "FF" ? "\u0432\u043C\u0435\u0441\u0442\u0435" : dep.type === "SS" ? "\u0432\u043C\u0435\u0441\u0442\u0435" : "\u0441\u0440\u0430\u0437\u0443";
|
|
7832
7906
|
let afterWhat;
|
|
@@ -7958,27 +8032,71 @@ var DepChip = ({
|
|
|
7958
8032
|
!disableDependencyEditing && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
7959
8033
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { className: "gantt-tl-dep-edit-divider" }),
|
|
7960
8034
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "gantt-tl-dep-edit-actions", children: [
|
|
7961
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
8035
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Popover, { open: typeMenuOpen, onOpenChange: setTypeMenuOpen, children: [
|
|
8036
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
8037
|
+
"button",
|
|
8038
|
+
{
|
|
8039
|
+
type: "button",
|
|
8040
|
+
className: "gantt-tl-dep-edit-type-trigger",
|
|
8041
|
+
onClick: (e) => e.stopPropagation(),
|
|
8042
|
+
"aria-label": "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0438\u043F \u0441\u0432\u044F\u0437\u0438",
|
|
8043
|
+
title: "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0438\u043F \u0441\u0432\u044F\u0437\u0438",
|
|
8044
|
+
children: [
|
|
8045
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon, {}),
|
|
8046
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: LINK_TYPE_LABELS_RU2[dep.type] }),
|
|
8047
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-tl-dep-edit-type-caret", "aria-hidden": "true", children: "\u25BE" })
|
|
8048
|
+
]
|
|
8049
|
+
}
|
|
8050
|
+
) }),
|
|
8051
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "gantt-tl-dep-type-menu", children: LINK_TYPE_ORDER.map((linkType) => {
|
|
8052
|
+
const TypeIcon = LINK_TYPE_ICONS[linkType];
|
|
8053
|
+
const isCurrent = linkType === dep.type;
|
|
8054
|
+
const isDuplicate = !isCurrent && (task.dependencies ?? []).some(
|
|
8055
|
+
(d) => d.taskId === dep.taskId && d.type === linkType
|
|
8056
|
+
);
|
|
8057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
8058
|
+
"button",
|
|
8059
|
+
{
|
|
8060
|
+
type: "button",
|
|
8061
|
+
className: `gantt-tl-dep-type-option${isCurrent ? " active" : ""}${isDuplicate ? " gantt-tl-dep-type-option-duplicate" : ""}`,
|
|
8062
|
+
disabled: isDuplicate,
|
|
8063
|
+
onClick: () => {
|
|
8064
|
+
handleTypeChange(linkType);
|
|
8065
|
+
setTypeMenuOpen(false);
|
|
8066
|
+
},
|
|
8067
|
+
title: isDuplicate ? "\u0421\u0432\u044F\u0437\u044C \u0442\u0430\u043A\u043E\u0433\u043E \u0442\u0438\u043F\u0430 \u0443\u0436\u0435 \u0435\u0441\u0442\u044C" : `\u0422\u0438\u043F \u0441\u0432\u044F\u0437\u0438 ${LINK_TYPE_LABELS_RU2[linkType]}`,
|
|
8068
|
+
children: [
|
|
8069
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TypeIcon, {}),
|
|
8070
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: LINK_TYPE_LABELS_RU2[linkType] })
|
|
8071
|
+
]
|
|
8072
|
+
},
|
|
8073
|
+
linkType
|
|
8074
|
+
);
|
|
8075
|
+
}) }) })
|
|
8076
|
+
] }),
|
|
8077
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "gantt-tl-dep-edit-actions-right", children: [
|
|
8078
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8079
|
+
"button",
|
|
8080
|
+
{
|
|
8081
|
+
type: "button",
|
|
8082
|
+
className: "gantt-tl-dep-edit-close",
|
|
8083
|
+
onClick: () => {
|
|
8084
|
+
setPopoverOpen(false);
|
|
8085
|
+
onChipSelectClear();
|
|
8086
|
+
},
|
|
8087
|
+
children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
|
|
8088
|
+
}
|
|
8089
|
+
),
|
|
8090
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8091
|
+
"button",
|
|
8092
|
+
{
|
|
8093
|
+
type: "button",
|
|
8094
|
+
className: "gantt-tl-dep-edit-delete",
|
|
8095
|
+
onClick: handleTrashClick,
|
|
8096
|
+
children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
|
|
8097
|
+
}
|
|
8098
|
+
)
|
|
8099
|
+
] })
|
|
7982
8100
|
] })
|
|
7983
8101
|
] })
|
|
7984
8102
|
] })
|
|
@@ -9484,7 +9602,7 @@ var TaskListRow = import_react12.default.memo(
|
|
|
9484
9602
|
{
|
|
9485
9603
|
className: "gantt-tl-dep-overflow-list",
|
|
9486
9604
|
onClick: (e) => e.stopPropagation(),
|
|
9487
|
-
children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
9605
|
+
children: chips.map(({ dep, lag, predecessorName }, chipIndex) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
9488
9606
|
DepChip,
|
|
9489
9607
|
{
|
|
9490
9608
|
lag,
|
|
@@ -9506,7 +9624,7 @@ var TaskListRow = import_react12.default.memo(
|
|
|
9506
9624
|
businessDays,
|
|
9507
9625
|
weekendPredicate
|
|
9508
9626
|
},
|
|
9509
|
-
`${dep.taskId}-${
|
|
9627
|
+
`${dep.taskId}-${chipIndex}`
|
|
9510
9628
|
))
|
|
9511
9629
|
}
|
|
9512
9630
|
) })
|
|
@@ -9534,7 +9652,8 @@ var TaskListRow = import_react12.default.memo(
|
|
|
9534
9652
|
onTasksChange,
|
|
9535
9653
|
businessDays,
|
|
9536
9654
|
weekendPredicate
|
|
9537
|
-
}
|
|
9655
|
+
},
|
|
9656
|
+
chips[0].dep.taskId
|
|
9538
9657
|
)
|
|
9539
9658
|
) : null,
|
|
9540
9659
|
!printDependencyLabels && !disableDependencyEditing && !isPicking && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|