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.mjs
CHANGED
|
@@ -2070,8 +2070,8 @@ function recalculateProjectSchedule(snapshot, options) {
|
|
|
2070
2070
|
}
|
|
2071
2071
|
}
|
|
2072
2072
|
const queue = snapshot.filter((task) => (indegree.get(task.id) ?? 0) === 0).map((task) => task.id);
|
|
2073
|
-
|
|
2074
|
-
const currentId = queue
|
|
2073
|
+
for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
|
|
2074
|
+
const currentId = queue[queueIndex];
|
|
2075
2075
|
for (const successorId of successorIdsByTask.get(currentId) ?? []) {
|
|
2076
2076
|
const nextIndegree = (indegree.get(successorId) ?? 0) - 1;
|
|
2077
2077
|
indegree.set(successorId, nextIndegree);
|
|
@@ -2122,7 +2122,13 @@ function recalculateProjectSchedule(snapshot, options) {
|
|
|
2122
2122
|
queue.push(successorId);
|
|
2123
2123
|
}
|
|
2124
2124
|
}
|
|
2125
|
-
const
|
|
2125
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
2126
|
+
for (const task of snapshot) if (task.parentId) {
|
|
2127
|
+
const children = childrenByParent.get(task.parentId) ?? [];
|
|
2128
|
+
children.push(task.id);
|
|
2129
|
+
childrenByParent.set(task.parentId, children);
|
|
2130
|
+
}
|
|
2131
|
+
const parentsByDepth = snapshot.filter((task) => childrenByParent.has(task.id)).map((task) => {
|
|
2126
2132
|
let depth = 0;
|
|
2127
2133
|
let current = task.parentId ? workingMap.get(task.parentId) : void 0;
|
|
2128
2134
|
while (current) {
|
|
@@ -2131,17 +2137,21 @@ function recalculateProjectSchedule(snapshot, options) {
|
|
|
2131
2137
|
}
|
|
2132
2138
|
return { taskId: task.id, depth };
|
|
2133
2139
|
}).sort((left, right) => right.depth - left.depth);
|
|
2134
|
-
const workingTasks = () => Array.from(workingMap.values());
|
|
2135
2140
|
for (const { taskId } of parentsByDepth) {
|
|
2136
2141
|
const parent = workingMap.get(taskId);
|
|
2137
2142
|
if (!parent || parent.locked) {
|
|
2138
2143
|
continue;
|
|
2139
2144
|
}
|
|
2140
|
-
|
|
2145
|
+
let startTime = Infinity, endTime = -Infinity;
|
|
2146
|
+
for (const childId of childrenByParent.get(taskId)) {
|
|
2147
|
+
const child = workingMap.get(childId);
|
|
2148
|
+
startTime = Math.min(startTime, new Date(child.startDate).getTime());
|
|
2149
|
+
endTime = Math.max(endTime, new Date(child.endDate).getTime());
|
|
2150
|
+
}
|
|
2141
2151
|
workingMap.set(taskId, {
|
|
2142
2152
|
...parent,
|
|
2143
|
-
startDate: toIsoDate(
|
|
2144
|
-
endDate: toIsoDate(
|
|
2153
|
+
startDate: toIsoDate(new Date(startTime)),
|
|
2154
|
+
endDate: toIsoDate(new Date(endTime))
|
|
2145
2155
|
});
|
|
2146
2156
|
}
|
|
2147
2157
|
return createChangedResult(snapshot, Array.from(workingMap.values()));
|
|
@@ -7567,6 +7577,7 @@ var DepChip = ({
|
|
|
7567
7577
|
weekendPredicate
|
|
7568
7578
|
}) => {
|
|
7569
7579
|
const [popoverOpen, setPopoverOpen] = useState6(false);
|
|
7580
|
+
const [typeMenuOpen, setTypeMenuOpen] = useState6(false);
|
|
7570
7581
|
const lagAbs = Math.abs(lag ?? 0);
|
|
7571
7582
|
const [inputAbs, setInputAbs] = useState6(lagAbs === 0 ? "" : String(lagAbs));
|
|
7572
7583
|
useEffect6(() => {
|
|
@@ -7688,6 +7699,69 @@ var DepChip = ({
|
|
|
7688
7699
|
const Icon = LINK_TYPE_ICONS[dep.type];
|
|
7689
7700
|
const depName = predecessorName ?? dep.taskId;
|
|
7690
7701
|
const effectiveLag = lag ?? 0;
|
|
7702
|
+
const handleTypeChange = useCallback6(
|
|
7703
|
+
(newType) => {
|
|
7704
|
+
if (newType === dep.type) return;
|
|
7705
|
+
if (!onTasksChange || !allTasks) return;
|
|
7706
|
+
if ((task.dependencies ?? []).some((d) => d.taskId === dep.taskId && d.type === newType)) return;
|
|
7707
|
+
const taskById = new Map(allTasks.map((t) => [t.id, t]));
|
|
7708
|
+
const predecessor = taskById.get(dep.taskId);
|
|
7709
|
+
if (!predecessor) return;
|
|
7710
|
+
const predStart = parseUTCDate(predecessor.startDate);
|
|
7711
|
+
const predEnd = predecessor.type === "milestone" ? predStart : parseUTCDate(predecessor.endDate);
|
|
7712
|
+
const origStart = parseUTCDate(task.startDate);
|
|
7713
|
+
const origEnd = parseUTCDate(task.endDate);
|
|
7714
|
+
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
7715
|
+
const normalizedLag = normalizeDependencyLag(
|
|
7716
|
+
newType,
|
|
7717
|
+
effectiveLag,
|
|
7718
|
+
predStart,
|
|
7719
|
+
predEnd,
|
|
7720
|
+
businessDays,
|
|
7721
|
+
weekendPredicate,
|
|
7722
|
+
task.type
|
|
7723
|
+
);
|
|
7724
|
+
const constraintDate = calculateSuccessorDate(
|
|
7725
|
+
predStart,
|
|
7726
|
+
predEnd,
|
|
7727
|
+
newType,
|
|
7728
|
+
normalizedLag,
|
|
7729
|
+
businessDays,
|
|
7730
|
+
weekendPredicate,
|
|
7731
|
+
task.type
|
|
7732
|
+
);
|
|
7733
|
+
let newStart, newEnd;
|
|
7734
|
+
if (newType === "FS" || newType === "SS") {
|
|
7735
|
+
newStart = constraintDate;
|
|
7736
|
+
if (businessDays) {
|
|
7737
|
+
const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);
|
|
7738
|
+
newEnd = addBusinessDays(constraintDate, businessDuration, weekendPredicate);
|
|
7739
|
+
} else {
|
|
7740
|
+
newEnd = new Date(constraintDate.getTime() + durationMs);
|
|
7741
|
+
}
|
|
7742
|
+
} else {
|
|
7743
|
+
newEnd = constraintDate;
|
|
7744
|
+
if (businessDays) {
|
|
7745
|
+
const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);
|
|
7746
|
+
newStart = subtractBusinessDays(constraintDate, businessDuration, weekendPredicate);
|
|
7747
|
+
} else {
|
|
7748
|
+
newStart = new Date(constraintDate.getTime() - durationMs);
|
|
7749
|
+
}
|
|
7750
|
+
}
|
|
7751
|
+
onTasksChange([
|
|
7752
|
+
{
|
|
7753
|
+
...task,
|
|
7754
|
+
startDate: newStart.toISOString().split("T")[0],
|
|
7755
|
+
endDate: newEnd.toISOString().split("T")[0],
|
|
7756
|
+
dependencies: (task.dependencies ?? []).map(
|
|
7757
|
+
(existingDep) => existingDep.taskId === dep.taskId && existingDep.type === dep.type ? { ...existingDep, type: newType, lag: normalizedLag } : existingDep
|
|
7758
|
+
)
|
|
7759
|
+
}
|
|
7760
|
+
]);
|
|
7761
|
+
onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: newType });
|
|
7762
|
+
},
|
|
7763
|
+
[dep.type, dep.taskId, task, allTasks, onTasksChange, businessDays, weekendPredicate, effectiveLag, onChipSelect, taskId]
|
|
7764
|
+
);
|
|
7691
7765
|
const actionVerb = dep.type === "FS" || dep.type === "SS" ? "\u043D\u0430\u0447\u0430\u0442\u044C" : "\u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C";
|
|
7692
7766
|
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";
|
|
7693
7767
|
let afterWhat;
|
|
@@ -7819,27 +7893,71 @@ var DepChip = ({
|
|
|
7819
7893
|
!disableDependencyEditing && /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
7820
7894
|
/* @__PURE__ */ jsx15("hr", { className: "gantt-tl-dep-edit-divider" }),
|
|
7821
7895
|
/* @__PURE__ */ jsxs10("div", { className: "gantt-tl-dep-edit-actions", children: [
|
|
7822
|
-
/* @__PURE__ */
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7896
|
+
/* @__PURE__ */ jsxs10(Popover, { open: typeMenuOpen, onOpenChange: setTypeMenuOpen, children: [
|
|
7897
|
+
/* @__PURE__ */ jsx15(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs10(
|
|
7898
|
+
"button",
|
|
7899
|
+
{
|
|
7900
|
+
type: "button",
|
|
7901
|
+
className: "gantt-tl-dep-edit-type-trigger",
|
|
7902
|
+
onClick: (e) => e.stopPropagation(),
|
|
7903
|
+
"aria-label": "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0438\u043F \u0441\u0432\u044F\u0437\u0438",
|
|
7904
|
+
title: "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0438\u043F \u0441\u0432\u044F\u0437\u0438",
|
|
7905
|
+
children: [
|
|
7906
|
+
/* @__PURE__ */ jsx15(Icon, {}),
|
|
7907
|
+
/* @__PURE__ */ jsx15("span", { children: LINK_TYPE_LABELS_RU2[dep.type] }),
|
|
7908
|
+
/* @__PURE__ */ jsx15("span", { className: "gantt-tl-dep-edit-type-caret", "aria-hidden": "true", children: "\u25BE" })
|
|
7909
|
+
]
|
|
7910
|
+
}
|
|
7911
|
+
) }),
|
|
7912
|
+
/* @__PURE__ */ jsx15(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ jsx15("div", { className: "gantt-tl-dep-type-menu", children: LINK_TYPE_ORDER.map((linkType) => {
|
|
7913
|
+
const TypeIcon = LINK_TYPE_ICONS[linkType];
|
|
7914
|
+
const isCurrent = linkType === dep.type;
|
|
7915
|
+
const isDuplicate = !isCurrent && (task.dependencies ?? []).some(
|
|
7916
|
+
(d) => d.taskId === dep.taskId && d.type === linkType
|
|
7917
|
+
);
|
|
7918
|
+
return /* @__PURE__ */ jsxs10(
|
|
7919
|
+
"button",
|
|
7920
|
+
{
|
|
7921
|
+
type: "button",
|
|
7922
|
+
className: `gantt-tl-dep-type-option${isCurrent ? " active" : ""}${isDuplicate ? " gantt-tl-dep-type-option-duplicate" : ""}`,
|
|
7923
|
+
disabled: isDuplicate,
|
|
7924
|
+
onClick: () => {
|
|
7925
|
+
handleTypeChange(linkType);
|
|
7926
|
+
setTypeMenuOpen(false);
|
|
7927
|
+
},
|
|
7928
|
+
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]}`,
|
|
7929
|
+
children: [
|
|
7930
|
+
/* @__PURE__ */ jsx15(TypeIcon, {}),
|
|
7931
|
+
/* @__PURE__ */ jsx15("span", { children: LINK_TYPE_LABELS_RU2[linkType] })
|
|
7932
|
+
]
|
|
7933
|
+
},
|
|
7934
|
+
linkType
|
|
7935
|
+
);
|
|
7936
|
+
}) }) })
|
|
7937
|
+
] }),
|
|
7938
|
+
/* @__PURE__ */ jsxs10("div", { className: "gantt-tl-dep-edit-actions-right", children: [
|
|
7939
|
+
/* @__PURE__ */ jsx15(
|
|
7940
|
+
"button",
|
|
7941
|
+
{
|
|
7942
|
+
type: "button",
|
|
7943
|
+
className: "gantt-tl-dep-edit-close",
|
|
7944
|
+
onClick: () => {
|
|
7945
|
+
setPopoverOpen(false);
|
|
7946
|
+
onChipSelectClear();
|
|
7947
|
+
},
|
|
7948
|
+
children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
|
|
7949
|
+
}
|
|
7950
|
+
),
|
|
7951
|
+
/* @__PURE__ */ jsx15(
|
|
7952
|
+
"button",
|
|
7953
|
+
{
|
|
7954
|
+
type: "button",
|
|
7955
|
+
className: "gantt-tl-dep-edit-delete",
|
|
7956
|
+
onClick: handleTrashClick,
|
|
7957
|
+
children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
|
|
7958
|
+
}
|
|
7959
|
+
)
|
|
7960
|
+
] })
|
|
7843
7961
|
] })
|
|
7844
7962
|
] })
|
|
7845
7963
|
] })
|
|
@@ -9345,7 +9463,7 @@ var TaskListRow = React11.memo(
|
|
|
9345
9463
|
{
|
|
9346
9464
|
className: "gantt-tl-dep-overflow-list",
|
|
9347
9465
|
onClick: (e) => e.stopPropagation(),
|
|
9348
|
-
children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ jsx15(
|
|
9466
|
+
children: chips.map(({ dep, lag, predecessorName }, chipIndex) => /* @__PURE__ */ jsx15(
|
|
9349
9467
|
DepChip,
|
|
9350
9468
|
{
|
|
9351
9469
|
lag,
|
|
@@ -9367,7 +9485,7 @@ var TaskListRow = React11.memo(
|
|
|
9367
9485
|
businessDays,
|
|
9368
9486
|
weekendPredicate
|
|
9369
9487
|
},
|
|
9370
|
-
`${dep.taskId}-${
|
|
9488
|
+
`${dep.taskId}-${chipIndex}`
|
|
9371
9489
|
))
|
|
9372
9490
|
}
|
|
9373
9491
|
) })
|
|
@@ -9395,7 +9513,8 @@ var TaskListRow = React11.memo(
|
|
|
9395
9513
|
onTasksChange,
|
|
9396
9514
|
businessDays,
|
|
9397
9515
|
weekendPredicate
|
|
9398
|
-
}
|
|
9516
|
+
},
|
|
9517
|
+
chips[0].dep.taskId
|
|
9399
9518
|
)
|
|
9400
9519
|
) : null,
|
|
9401
9520
|
!printDependencyLabels && !disableDependencyEditing && !isPicking && /* @__PURE__ */ jsx15(
|