v2.5.2
This commit is contained in:
2
.sync
2
.sync
@@ -1 +1 @@
|
|||||||
913b95b49f0d253d50d6b3461c48aaa9facb7ba2
|
b33bea9b4d106757875dab25dada246fc8d8864a
|
||||||
|
|||||||
@@ -2,54 +2,54 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.narrow {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.narrow {
|
||||||
background-color: #676a81;
|
background-color: #676a81;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
height: 10px !important;
|
height: 10px !important;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
border: 1px solid #63667a;
|
border: 1px solid #63667a;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.narrow .wx-progress-percent {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.narrow .wx-progress-percent {
|
||||||
background-color: #1a2630;
|
background-color: #1a2630;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.narrow .wx-link {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.narrow .wx-link {
|
||||||
background-color: #384047;
|
background-color: #384047;
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.narrow .wx-link .wx-inner {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.narrow .wx-link .wx-inner {
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.round {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.round {
|
||||||
background-color: #ffeb3b;
|
background-color: #ffeb3b;
|
||||||
border: 1px solid #ffeb3b;
|
border: 1px solid #ffeb3b;
|
||||||
color: #384047;
|
color: #384047;
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.round .wx-progress-percent {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.round .wx-progress-percent {
|
||||||
background-color: #ffc107;
|
background-color: #ffc107;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.round .wx-progress-wrapper {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.round .wx-progress-wrapper {
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.progress {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.progress {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: var(--wx-color-font);
|
color: var(--wx-color-font);
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
border: 1px solid #00bcd4;
|
border: 1px solid #00bcd4;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.progress .wx-progress-percent {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.progress .wx-progress-percent {
|
||||||
background-color: #00bcd4;
|
background-color: #00bcd4;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.progress .wx-progress-wrapper {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.progress .wx-progress-wrapper {
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.urgent {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.urgent {
|
||||||
background-color: #f49a82;
|
background-color: #f49a82;
|
||||||
border: 1px solid #f45e36;
|
border: 1px solid #f45e36;
|
||||||
}
|
}
|
||||||
.demo.wx-I1glfWSB > .wx-gantt .wx-bar.wx-task.urgent .wx-progress-percent {
|
.demo.wx-I1glfWSB .wx-gantt .wx-bar.wx-task.urgent .wx-progress-percent {
|
||||||
background-color: #f45e36;
|
background-color: #f45e36;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { getTypedData, taskTypes } from '../data';
|
import { getTypedData, taskTypes } from '../data';
|
||||||
import { Gantt, Editor } from '../../src/';
|
import { Gantt, Editor, ContextMenu } from '../../src/';
|
||||||
import './GanttTaskTypes.css';
|
import './GanttTaskTypes.css';
|
||||||
|
|
||||||
function GanttTaskTypes(props) {
|
function GanttTaskTypes(props) {
|
||||||
@@ -11,6 +11,7 @@ function GanttTaskTypes(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wx-I1glfWSB demo">
|
<div className="wx-I1glfWSB demo">
|
||||||
|
<ContextMenu api={api}>
|
||||||
<Gantt
|
<Gantt
|
||||||
init={setApi}
|
init={setApi}
|
||||||
{...skinSettings}
|
{...skinSettings}
|
||||||
@@ -19,6 +20,7 @@ function GanttTaskTypes(props) {
|
|||||||
scales={data.scales}
|
scales={data.scales}
|
||||||
taskTypes={taskTypes}
|
taskTypes={taskTypes}
|
||||||
/>
|
/>
|
||||||
|
</ContextMenu>
|
||||||
{api && <Editor api={api} />}
|
{api && <Editor api={api} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
11
demos/cases/ProExport.css
Normal file
11
demos/cases/ProExport.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
.rselect {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
.wx-gantt .myMarker {
|
||||||
|
background-color: rgba(255, 84, 84, 0.77);
|
||||||
|
}
|
||||||
|
.gtcell {
|
||||||
|
position: relative;
|
||||||
|
height: calc(100% - 48px);
|
||||||
|
border-top: var(--wx-gantt-border);
|
||||||
|
}
|
||||||
199
demos/cases/ProExport.jsx
Normal file
199
demos/cases/ProExport.jsx
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
import { getData } from '../data';
|
||||||
|
import { Gantt, version } from '../../src/';
|
||||||
|
import { Toolbar, registerToolbarItem } from '@svar-ui/react-toolbar';
|
||||||
|
import { Switch, RichSelect, Segmented } from '@svar-ui/react-core';
|
||||||
|
import { Calendar } from '@svar-ui/gantt-store';
|
||||||
|
import './ProExport.css';
|
||||||
|
|
||||||
|
registerToolbarItem('switch', Switch);
|
||||||
|
registerToolbarItem('segmented', Segmented);
|
||||||
|
registerToolbarItem('richselect', RichSelect);
|
||||||
|
|
||||||
|
export default function ProExport({ skinSettings }) {
|
||||||
|
|
||||||
|
const [size, setSize] = useState('auto');
|
||||||
|
const [fit, setFit] = useState(true);
|
||||||
|
const [api, setApi] = useState();
|
||||||
|
const [config, setConfig] = useState('basic');
|
||||||
|
|
||||||
|
const data = useMemo(() => {
|
||||||
|
const advanced = config === 'advanced';
|
||||||
|
return getData(null, {
|
||||||
|
splitTasks: advanced,
|
||||||
|
baselines: advanced,
|
||||||
|
unscheduledTasks: advanced,
|
||||||
|
});
|
||||||
|
}, [config]);
|
||||||
|
|
||||||
|
const items = useMemo(() => {
|
||||||
|
return [
|
||||||
|
{ text: 'Page size' },
|
||||||
|
{
|
||||||
|
id: 'size',
|
||||||
|
comp: 'richselect',
|
||||||
|
css: 'rselect',
|
||||||
|
value: size,
|
||||||
|
options: [
|
||||||
|
{ id: 'auto', label: 'Auto' },
|
||||||
|
{ id: 'a4-landscape', label: 'A4 Landscape' },
|
||||||
|
{ id: 'a4', label: 'A4 Portrait' },
|
||||||
|
{ id: 'a3-landscape', label: 'A3 Landscape' },
|
||||||
|
{ id: 'a3', label: 'A3 Portrait' },
|
||||||
|
],
|
||||||
|
handler: () => {},
|
||||||
|
},
|
||||||
|
{ text: 'Fit to page' },
|
||||||
|
{
|
||||||
|
id: 'fit',
|
||||||
|
comp: 'switch',
|
||||||
|
value: fit,
|
||||||
|
handler: () => {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'export-pdf',
|
||||||
|
comp: 'button',
|
||||||
|
text: 'To PDF',
|
||||||
|
handler: () => exportOthers('pdf'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'export-png',
|
||||||
|
comp: 'button',
|
||||||
|
text: 'To PNG',
|
||||||
|
handler: () => exportOthers('png'),
|
||||||
|
},
|
||||||
|
{ comp: 'separator' },
|
||||||
|
{
|
||||||
|
id: 'export-xlsx',
|
||||||
|
comp: 'button',
|
||||||
|
text: 'To XLSX',
|
||||||
|
handler: () => exportExcel(false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'export-xlsx-chart',
|
||||||
|
comp: 'button',
|
||||||
|
text: 'To XLSX with Chart',
|
||||||
|
handler: () => exportExcel(true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'export-mspx',
|
||||||
|
comp: 'button',
|
||||||
|
text: 'To MS Project (XML)',
|
||||||
|
handler: () => exportOthers('mspx'),
|
||||||
|
},
|
||||||
|
{ comp: 'spacer' },
|
||||||
|
{
|
||||||
|
id: 'config',
|
||||||
|
comp: 'segmented',
|
||||||
|
value: config,
|
||||||
|
options: [
|
||||||
|
{ id: 'basic', label: 'Basic' },
|
||||||
|
{ id: 'advanced', label: 'Advanced' },
|
||||||
|
],
|
||||||
|
handler: () => {},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}, [size, fit, config, api]);
|
||||||
|
|
||||||
|
const markers = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
start: new Date(2026, 3, 8),
|
||||||
|
text: 'Approval of strategy',
|
||||||
|
css: 'myMarker',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const calendar = useMemo(() => new Calendar(), []);
|
||||||
|
|
||||||
|
function handleClick({ item }) {
|
||||||
|
const parts = item.id.split('-');
|
||||||
|
if (parts[0] === 'export') {
|
||||||
|
if (parts[1] === 'xlsx') {
|
||||||
|
exportExcel(parts[2] === 'chart');
|
||||||
|
} else {
|
||||||
|
exportOthers(parts[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = 'https://export.svar.dev/gantt/' + version;
|
||||||
|
|
||||||
|
function exportExcel(visual) {
|
||||||
|
api.exec('export-data', {
|
||||||
|
url,
|
||||||
|
format: 'xlsx',
|
||||||
|
excel: {
|
||||||
|
columns: visual
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
id: 'text',
|
||||||
|
header: 'Task name',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: null,
|
||||||
|
sheetNames: ['Tasks', 'Links'],
|
||||||
|
dateFormat: 'yyyy-mmm-dd',
|
||||||
|
visual,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportOthers(format) {
|
||||||
|
const parts = size.split('-');
|
||||||
|
const props = {
|
||||||
|
size: parts[0],
|
||||||
|
landscape: parts[1] === 'landscape',
|
||||||
|
fitSize: fit && size != 'auto',
|
||||||
|
styles: '.wx-gantt .myMarker{ background-color: rgba(255, 84, 84, 0.77);',
|
||||||
|
};
|
||||||
|
api.exec('export-data', {
|
||||||
|
url,
|
||||||
|
format,
|
||||||
|
pdf: props,
|
||||||
|
png: props,
|
||||||
|
ganttConfig: {
|
||||||
|
cellWidth: 30,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChange({ item, value }) {
|
||||||
|
if (item.id === 'size') setSize(value);
|
||||||
|
else if (item.id === 'fit') setFit(value);
|
||||||
|
else if (item.id === 'config') setConfig(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Toolbar items={items} onClick={handleClick} onChange={handleChange} />
|
||||||
|
<div className="gtcell">
|
||||||
|
{config === 'basic' ? (
|
||||||
|
<Gantt
|
||||||
|
init={setApi}
|
||||||
|
{...skinSettings}
|
||||||
|
tasks={data.tasks}
|
||||||
|
links={data.links}
|
||||||
|
scales={data.scales}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Gantt
|
||||||
|
init={setApi}
|
||||||
|
baselines={true}
|
||||||
|
splitTasks={true}
|
||||||
|
unscheduledTasks={true}
|
||||||
|
markers={markers}
|
||||||
|
calendar={calendar}
|
||||||
|
{...skinSettings}
|
||||||
|
tasks={data.tasks}
|
||||||
|
links={data.links}
|
||||||
|
scales={data.scales}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
5
demos/cases/ProMSProject.css
Normal file
5
demos/cases/ProMSProject.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.gtcell {
|
||||||
|
position: relative;
|
||||||
|
height: calc(100% - 48px);
|
||||||
|
border-top: var(--wx-gantt-border);
|
||||||
|
}
|
||||||
60
demos/cases/ProMSProject.jsx
Normal file
60
demos/cases/ProMSProject.jsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { getData } from "../data";
|
||||||
|
import { Gantt } from "../../src";
|
||||||
|
import { Toolbar, registerToolbarItem } from "@wx/react-toolbar";
|
||||||
|
import UploadButton from "../custom/UploadButton";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
|
import './ProMSProject.css';
|
||||||
|
|
||||||
|
registerToolbarItem("upload", UploadButton);
|
||||||
|
export default function ProMSProject({ skinSettings }) {
|
||||||
|
const data = getData();
|
||||||
|
const [api, setApi] = useState();
|
||||||
|
|
||||||
|
const handleClick = useCallback(({ item }) => {
|
||||||
|
if (item.id === "export") {
|
||||||
|
api.exec("export-data", { format: "mspx" });
|
||||||
|
}
|
||||||
|
}, [api]);
|
||||||
|
|
||||||
|
const importMSProject = useCallback(() => {
|
||||||
|
const file = document.getElementById("import-file").files[0];
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = e => {
|
||||||
|
const xml = e.target.result;
|
||||||
|
api.exec("import-data", {
|
||||||
|
data: xml,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
}, [api]);
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
id: "export",
|
||||||
|
comp: "button",
|
||||||
|
text: "Download MS Project XML",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "import",
|
||||||
|
comp: "upload",
|
||||||
|
text: "Upload MS Project XML",
|
||||||
|
onChange: importMSProject,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Toolbar items={items} onClick={handleClick} />
|
||||||
|
<div className="gtcell">
|
||||||
|
<Gantt
|
||||||
|
init={setApi}
|
||||||
|
{...skinSettings}
|
||||||
|
tasks={data.tasks}
|
||||||
|
links={data.links}
|
||||||
|
scales={data.scales}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,109 +1,28 @@
|
|||||||
import { useMemo, useCallback, useRef } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { useStoreLater } from '@svar-ui/lib-react';
|
|
||||||
import { getData } from '../data';
|
import { getData } from '../data';
|
||||||
import {
|
import {
|
||||||
Gantt,
|
Gantt,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
Editor,
|
Editor,
|
||||||
getEditorItems,
|
} from '../../src/';
|
||||||
defaultTaskTypes,
|
|
||||||
} from '../../src';
|
|
||||||
|
|
||||||
export default function SummariesConvert({ skinSettings }) {
|
export default function SummariesConvert({ skinSettings }) {
|
||||||
const data = useMemo(() => getData(), []);
|
const data = useMemo(() => getData(), []);
|
||||||
const gApi = useRef(null);
|
const [api, setApi] = useState();
|
||||||
|
|
||||||
const toSummary = useCallback(
|
|
||||||
(id, self) => {
|
|
||||||
const api = gApi.current;
|
|
||||||
if (!api) return;
|
|
||||||
const task = api.getTask(id);
|
|
||||||
if (!self) id = task.parent;
|
|
||||||
|
|
||||||
if (id && task.type !== 'summary') {
|
|
||||||
api.exec('update-task', {
|
|
||||||
id,
|
|
||||||
task: { type: 'summary' },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[gApi],
|
|
||||||
);
|
|
||||||
|
|
||||||
const toTask = useCallback(
|
|
||||||
(id) => {
|
|
||||||
const api = gApi.current;
|
|
||||||
if (!api) return;
|
|
||||||
const obj = api.getTask(id);
|
|
||||||
if (obj && !obj.data?.length) {
|
|
||||||
api.exec('update-task', {
|
|
||||||
id,
|
|
||||||
task: { type: 'task' },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[gApi],
|
|
||||||
);
|
|
||||||
|
|
||||||
const init = useCallback(
|
|
||||||
(api) => {
|
|
||||||
gApi.current = api;
|
|
||||||
|
|
||||||
api.getState().tasks.forEach((task) => {
|
|
||||||
if (task.data?.length) {
|
|
||||||
toSummary(task.id, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
api.on('add-task', ({ id, mode }) => {
|
|
||||||
if (mode === 'child') toSummary(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
api.on('move-task', ({ id, source, mode, inProgress }) => {
|
|
||||||
if (inProgress) return;
|
|
||||||
if (mode == 'child') toSummary(id);
|
|
||||||
else toTask(source);
|
|
||||||
});
|
|
||||||
|
|
||||||
api.on('delete-task', ({ source }) => {
|
|
||||||
toTask(source);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[toSummary, toTask],
|
|
||||||
);
|
|
||||||
|
|
||||||
const activeTaskId = useStoreLater(gApi.current, 'activeTask');
|
|
||||||
|
|
||||||
const items = useMemo(() => {
|
|
||||||
const api = gApi.current;
|
|
||||||
const task = activeTaskId ? api?.getTask(activeTaskId) : null;
|
|
||||||
if (task) {
|
|
||||||
return getEditorItems().map((item) => {
|
|
||||||
item = { ...item };
|
|
||||||
if (item.comp === 'select' && item.key === 'type') {
|
|
||||||
item.options =
|
|
||||||
task.type !== 'summary'
|
|
||||||
? defaultTaskTypes.filter((t) => t.id !== 'summary')
|
|
||||||
: [];
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}, [activeTaskId, gApi.current]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wx-TEIogFEZ gt-cell">
|
<div className="wx-TEIogFEZ gt-cell">
|
||||||
<ContextMenu api={gApi.current}>
|
<ContextMenu api={api}>
|
||||||
<Gantt
|
<Gantt
|
||||||
init={init}
|
init={setApi}
|
||||||
{...skinSettings}
|
{...skinSettings}
|
||||||
tasks={data.tasks}
|
tasks={data.tasks}
|
||||||
links={data.links}
|
links={data.links}
|
||||||
scales={data.scales}
|
scales={data.scales}
|
||||||
|
summary={{ autoConvert: true }}
|
||||||
/>
|
/>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
{gApi.current && <Editor api={gApi.current} items={items} />}
|
{api && <Editor api={api} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,131 +1,29 @@
|
|||||||
import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
|
import { useState, useMemo } from 'react';
|
||||||
import { getData } from '../data';
|
import { getData } from '../data';
|
||||||
import { Gantt, Editor, getEditorItems, ContextMenu } from '../../src';
|
import { Gantt, Editor, ContextMenu } from '../../src';
|
||||||
import './ProSummariesProgress.css';
|
|
||||||
|
|
||||||
function SummariesProgress({ skinSettings }) {
|
function SummariesProgress({ skinSettings }) {
|
||||||
const data = useMemo(() => getData(), []);
|
const data = useMemo(() => getData(), []);
|
||||||
const tasks = data.tasks;
|
const { tasks, links, scales } = data;
|
||||||
|
|
||||||
const [api, setApi] = useState();
|
const [api, setApi] = useState();
|
||||||
|
|
||||||
const dayDiff = (next, prev) => {
|
|
||||||
const d = (next - prev) / 1000 / 60 / 60 / 24;
|
|
||||||
return Math.ceil(Math.abs(d));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The formula of calculation is ∑d*p / ∑d , where "d" is task duration in days,
|
|
||||||
* "p" is the task progress and "∑" stands for a sum of all loaded tasks
|
|
||||||
*/
|
|
||||||
function getSummaryProgress(id) {
|
|
||||||
const [totalProgress, totalDuration] = collectProgressFromKids(id);
|
|
||||||
const res = totalProgress / totalDuration;
|
|
||||||
return isNaN(res) ? 0 : Math.round(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
function collectProgressFromKids(id) {
|
|
||||||
let totalProgress = 0,
|
|
||||||
totalDuration = 0;
|
|
||||||
const kids = api.getTask(id).data;
|
|
||||||
|
|
||||||
kids?.forEach((kid) => {
|
|
||||||
let duration = 0;
|
|
||||||
if (kid.type !== 'milestone' && kid.type !== 'summary') {
|
|
||||||
duration = kid.duration || dayDiff(kid.end, kid.start);
|
|
||||||
totalDuration += duration;
|
|
||||||
totalProgress += duration * kid.progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [p, d] = collectProgressFromKids(kid.id);
|
|
||||||
totalProgress += p;
|
|
||||||
totalDuration += d;
|
|
||||||
});
|
|
||||||
return [totalProgress, totalDuration];
|
|
||||||
}
|
|
||||||
|
|
||||||
function recalcSummaryProgress(id, self) {
|
|
||||||
const { tasks } = api.getState();
|
|
||||||
const task = api.getTask(id);
|
|
||||||
|
|
||||||
if (task.type != 'milestone') {
|
|
||||||
const summary =
|
|
||||||
self && task.type === 'summary' ? id : tasks.getSummaryId(id);
|
|
||||||
|
|
||||||
if (summary) {
|
|
||||||
const progress = getSummaryProgress(summary);
|
|
||||||
api.exec('update-task', {
|
|
||||||
id: summary,
|
|
||||||
task: { progress },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const recalcRef = useRef(null);
|
|
||||||
recalcRef.current = recalcSummaryProgress;
|
|
||||||
|
|
||||||
const init = useCallback((api) => {
|
|
||||||
setApi(api);
|
|
||||||
// auto progress calculations
|
|
||||||
api.on('add-task', ({ id }) => {
|
|
||||||
recalcRef.current(id);
|
|
||||||
});
|
|
||||||
api.on('update-task', ({ id }) => {
|
|
||||||
recalcRef.current(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
api.on('delete-task', ({ source }) => {
|
|
||||||
recalcRef.current(source, true);
|
|
||||||
});
|
|
||||||
api.on('copy-task', ({ id }) => {
|
|
||||||
recalcRef.current(id);
|
|
||||||
});
|
|
||||||
api.on('move-task', ({ id, source, inProgress }) => {
|
|
||||||
if (inProgress) return;
|
|
||||||
|
|
||||||
if (api.getTask(id).parent != source) recalcRef.current(source, true);
|
|
||||||
recalcRef.current(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wx-OeNgRLo4 wrapper">
|
<>
|
||||||
<ContextMenu api={api}>
|
<ContextMenu api={api}>
|
||||||
<div className="wx-OeNgRLo4 gt-cell">
|
|
||||||
<Gantt
|
<Gantt
|
||||||
{...skinSettings}
|
{...skinSettings}
|
||||||
init={init}
|
init={setApi}
|
||||||
tasks={tasks}
|
tasks={tasks}
|
||||||
links={data.links}
|
links={links}
|
||||||
scales={data.scales}
|
scales={scales}
|
||||||
cellWidth={30}
|
cellWidth={30}
|
||||||
|
summary={{ autoProgress: true }}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
{api && <ConfiguredEditor api={api} />}
|
{api && <Editor api={api} />}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConfiguredEditor({ api }) {
|
|
||||||
const [editorItems, setEditorItems] = useState(getEditorItems());
|
|
||||||
|
|
||||||
// disabling progress slider for summary tasks
|
|
||||||
api.on('show-editor', ({ id }) => {
|
|
||||||
if (id) {
|
|
||||||
const type = api.getTask(id).type;
|
|
||||||
setEditorItems(
|
|
||||||
getEditorItems().map((ed) => ({
|
|
||||||
...ed,
|
|
||||||
...(ed.key == 'progress' && {
|
|
||||||
config: { disabled: type === 'summary' },
|
|
||||||
}),
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return <Editor api={api} items={editorItems} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SummariesProgress;
|
export default SummariesProgress;
|
||||||
|
|||||||
@@ -17,28 +17,25 @@ function DemoExplorerContent({
|
|||||||
}) {
|
}) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [skin, setSkin] = useState(skins[0].id);
|
const [skin, setSkin] = useState(skins[0].id);
|
||||||
const [title, setTitle] = useState('');
|
|
||||||
const [githubLink, setGithubLink] = useState('');
|
|
||||||
const [show, setShow] = useState(true);
|
const [show, setShow] = useState(true);
|
||||||
|
|
||||||
|
const currentPath = window.location.hash.slice(1);
|
||||||
|
const parts = currentPath.split('/');
|
||||||
|
const currentPage = `/${parts[1]}/:skin`;
|
||||||
|
const matched = links.find((a) => a[0] === currentPage);
|
||||||
|
const title = matched ? matched[1] : '';
|
||||||
const baseLink =
|
const baseLink =
|
||||||
'https://github.com/svar-widgets/react-' +
|
'https://github.com/svar-widgets/react-' +
|
||||||
productTag +
|
productTag +
|
||||||
'/tree/main/demos/cases/';
|
'/tree/main/demos/cases/';
|
||||||
|
|
||||||
|
const name = matched ? (matched[3] || matched[1]) : '';
|
||||||
|
const githubLink = `${baseLink}${name}.jsx`;
|
||||||
|
|
||||||
const handleRouteChange = useCallback((path) => {
|
const handleRouteChange = useCallback((path) => {
|
||||||
const parts = path.split('/');
|
const parts = path.split('/');
|
||||||
const page = parts[1];
|
|
||||||
const newSkin = parts[2];
|
const newSkin = parts[2];
|
||||||
setSkin(newSkin);
|
setSkin(newSkin);
|
||||||
|
|
||||||
const targetPage = `/${page}/:skin`;
|
|
||||||
const matched = links.find((a) => a[0] === targetPage);
|
|
||||||
if (matched) {
|
|
||||||
setTitle(matched[1]);
|
|
||||||
const name = matched[3] || matched[1];
|
|
||||||
setGithubLink(`${baseLink}${name}.jsx`);
|
|
||||||
}
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSkinChange = ({ value }) => {
|
const handleSkinChange = ({ value }) => {
|
||||||
|
|||||||
14
demos/custom/UbloadButton.css
Normal file
14
demos/custom/UbloadButton.css
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
.button {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 5px 16px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #f2f2f7;
|
||||||
|
color: #2c2f3c;
|
||||||
|
}
|
||||||
|
:global(.wx-willow-dark-theme .button) {
|
||||||
|
background-color: #384047;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
35
demos/custom/UploadButton.jsx
Normal file
35
demos/custom/UploadButton.jsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import React, { useRef } from 'react';
|
||||||
|
import './UbloadButton.css';
|
||||||
|
|
||||||
|
function UploadButton({ text, onChange }) {
|
||||||
|
|
||||||
|
const fileInput = useRef(null);
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
fileInput.current?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChange() {
|
||||||
|
if (onChange) {
|
||||||
|
onChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button className="button" onClick={handleClick}>
|
||||||
|
{text}
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
ref={fileInput}
|
||||||
|
id="import-file"
|
||||||
|
type="file"
|
||||||
|
accept=".xml"
|
||||||
|
onChange={handleChange}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UploadButton;
|
||||||
@@ -53,7 +53,7 @@ const tasks = [
|
|||||||
base_start: new Date(2026, 3, 2),
|
base_start: new Date(2026, 3, 2),
|
||||||
base_end: new Date(2026, 3, 16),
|
base_end: new Date(2026, 3, 16),
|
||||||
text: 'Project planning',
|
text: 'Project planning',
|
||||||
progress: 30,
|
progress: 40,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -76,7 +76,7 @@ const tasks = [
|
|||||||
start: new Date(2026, 3, 5),
|
start: new Date(2026, 3, 5),
|
||||||
duration: 2,
|
duration: 2,
|
||||||
text: 'Discussions',
|
text: 'Discussions',
|
||||||
progress: 100,
|
progress: 72,
|
||||||
parent: 1,
|
parent: 1,
|
||||||
type: 'task',
|
type: 'task',
|
||||||
details: 'Team discussions on project strategies.',
|
details: 'Team discussions on project strategies.',
|
||||||
@@ -139,7 +139,7 @@ const tasks = [
|
|||||||
base_start: new Date(2026, 3, 2),
|
base_start: new Date(2026, 3, 2),
|
||||||
base_end: new Date(2026, 3, 12),
|
base_end: new Date(2026, 3, 12),
|
||||||
text: 'Project management',
|
text: 'Project management',
|
||||||
progress: 10,
|
progress: 8,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -191,7 +191,7 @@ const tasks = [
|
|||||||
base_start: new Date(2026, 3, 9),
|
base_start: new Date(2026, 3, 9),
|
||||||
base_end: new Date(2026, 3, 30),
|
base_end: new Date(2026, 3, 30),
|
||||||
text: 'Development',
|
text: 'Development',
|
||||||
progress: 30,
|
progress: 2,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -202,7 +202,7 @@ const tasks = [
|
|||||||
start: new Date(2026, 3, 9),
|
start: new Date(2026, 3, 9),
|
||||||
duration: 6,
|
duration: 6,
|
||||||
text: 'Prototyping',
|
text: 'Prototyping',
|
||||||
progress: 3,
|
progress: 7,
|
||||||
parent: 3,
|
parent: 3,
|
||||||
type: 'task',
|
type: 'task',
|
||||||
assigned: 3,
|
assigned: 3,
|
||||||
@@ -233,7 +233,7 @@ const tasks = [
|
|||||||
base_start: new Date(2026, 3, 9),
|
base_start: new Date(2026, 3, 9),
|
||||||
base_end: new Date(2026, 4, 3),
|
base_end: new Date(2026, 4, 3),
|
||||||
text: 'Testing',
|
text: 'Testing',
|
||||||
progress: 3,
|
progress: 4,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -244,7 +244,7 @@ const tasks = [
|
|||||||
start: new Date(2026, 3, 9),
|
start: new Date(2026, 3, 9),
|
||||||
duration: 4,
|
duration: 4,
|
||||||
text: 'Testing prototype',
|
text: 'Testing prototype',
|
||||||
progress: 3,
|
progress: 24,
|
||||||
parent: 4,
|
parent: 4,
|
||||||
type: 'task',
|
type: 'task',
|
||||||
assigned: 4,
|
assigned: 4,
|
||||||
@@ -300,7 +300,7 @@ const calendarTasks = [
|
|||||||
//start: new Date(2026, 3, 2),
|
//start: new Date(2026, 3, 2),
|
||||||
//end: new Date(2026, 3, 18),
|
//end: new Date(2026, 3, 18),
|
||||||
text: 'Project planning',
|
text: 'Project planning',
|
||||||
progress: 30,
|
progress: 40,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -323,7 +323,7 @@ const calendarTasks = [
|
|||||||
start: new Date(2026, 3, 7),
|
start: new Date(2026, 3, 7),
|
||||||
duration: 2,
|
duration: 2,
|
||||||
text: 'Discussions',
|
text: 'Discussions',
|
||||||
progress: 100,
|
progress: 72,
|
||||||
parent: 1,
|
parent: 1,
|
||||||
type: 'task',
|
type: 'task',
|
||||||
details: 'Team discussions on project strategies.',
|
details: 'Team discussions on project strategies.',
|
||||||
@@ -386,7 +386,7 @@ const calendarTasks = [
|
|||||||
//start: new Date(2026, 3, 2),
|
//start: new Date(2026, 3, 2),
|
||||||
//end: new Date(2026, 3, 14),
|
//end: new Date(2026, 3, 14),
|
||||||
text: 'Project management',
|
text: 'Project management',
|
||||||
progress: 10,
|
progress: 8,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -437,7 +437,7 @@ const calendarTasks = [
|
|||||||
//start: new Date(2026, 3, 9),
|
//start: new Date(2026, 3, 9),
|
||||||
//end: new Date(2026, 4, 8),
|
//end: new Date(2026, 4, 8),
|
||||||
text: 'Development',
|
text: 'Development',
|
||||||
progress: 30,
|
progress: 2,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -448,7 +448,7 @@ const calendarTasks = [
|
|||||||
start: new Date(2026, 3, 13),
|
start: new Date(2026, 3, 13),
|
||||||
duration: 4,
|
duration: 4,
|
||||||
text: 'Prototyping',
|
text: 'Prototyping',
|
||||||
progress: 3,
|
progress: 7,
|
||||||
parent: 3,
|
parent: 3,
|
||||||
type: 'task',
|
type: 'task',
|
||||||
assigned: 3,
|
assigned: 3,
|
||||||
@@ -479,7 +479,7 @@ const calendarTasks = [
|
|||||||
//start: new Date(2026, 3, 9),
|
//start: new Date(2026, 3, 9),
|
||||||
//end: new Date(2026, 4, 13),
|
//end: new Date(2026, 4, 13),
|
||||||
text: 'Testing',
|
text: 'Testing',
|
||||||
progress: 3,
|
progress: 4,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -490,7 +490,7 @@ const calendarTasks = [
|
|||||||
start: new Date(2026, 3, 17),
|
start: new Date(2026, 3, 17),
|
||||||
duration: 4,
|
duration: 4,
|
||||||
text: 'Testing prototype',
|
text: 'Testing prototype',
|
||||||
progress: 3,
|
progress: 24,
|
||||||
parent: 4,
|
parent: 4,
|
||||||
type: 'task',
|
type: 'task',
|
||||||
assigned: 4,
|
assigned: 4,
|
||||||
@@ -608,11 +608,6 @@ const links = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const scales = [
|
|
||||||
{ unit: 'month', step: 1, format: '%F %Y' },
|
|
||||||
{ unit: 'day', step: 1, format: '%j', css: dayStyle },
|
|
||||||
];
|
|
||||||
|
|
||||||
const tasksHour = [
|
const tasksHour = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -773,7 +768,7 @@ const critTasks = [
|
|||||||
start: new Date(2026, 3, 5),
|
start: new Date(2026, 3, 5),
|
||||||
end: new Date(2026, 3, 7),
|
end: new Date(2026, 3, 7),
|
||||||
text: 'Discussions',
|
text: 'Discussions',
|
||||||
progress: 100,
|
progress: 72,
|
||||||
type: 'task',
|
type: 'task',
|
||||||
open: true,
|
open: true,
|
||||||
details: 'Team discussions on project strategies.',
|
details: 'Team discussions on project strategies.',
|
||||||
@@ -828,7 +823,7 @@ const critTasks = [
|
|||||||
start: new Date(2026, 3, 2),
|
start: new Date(2026, 3, 2),
|
||||||
end: new Date(2026, 3, 12),
|
end: new Date(2026, 3, 12),
|
||||||
text: 'Project management 1',
|
text: 'Project management 1',
|
||||||
progress: 10,
|
progress: 8,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -882,7 +877,7 @@ const critTasks = [
|
|||||||
start: new Date(2026, 3, 2),
|
start: new Date(2026, 3, 2),
|
||||||
end: new Date(2026, 3, 12),
|
end: new Date(2026, 3, 12),
|
||||||
text: 'Project management 2',
|
text: 'Project management 2',
|
||||||
progress: 10,
|
progress: 8,
|
||||||
parent: 0,
|
parent: 0,
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
open: true,
|
open: true,
|
||||||
@@ -1014,6 +1009,11 @@ function addDays(d, n) {
|
|||||||
return new Date(new Date(d).setDate(d.getDate() + n));
|
return new Date(new Date(d).setDate(d.getDate() + n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const scales = [
|
||||||
|
{ unit: 'month', step: 1, format: '%F %Y' },
|
||||||
|
{ unit: 'day', step: 1, format: '%j', css: dayStyle },
|
||||||
|
];
|
||||||
|
|
||||||
const datasets = {
|
const datasets = {
|
||||||
day: { tasks, links, scales },
|
day: { tasks, links, scales },
|
||||||
hour: { tasks: tasksHour, links: linksHour, scales: scalesHour },
|
hour: { tasks: tasksHour, links: linksHour, scales: scalesHour },
|
||||||
@@ -1021,16 +1021,6 @@ const datasets = {
|
|||||||
calendar: { tasks: calendarTasks, links, scales },
|
calendar: { tasks: calendarTasks, links, scales },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const taskTypes = [
|
|
||||||
{ id: 'task', label: 'Task' },
|
|
||||||
{ id: 'summary', label: 'Summary task' },
|
|
||||||
{ id: 'milestone', label: 'Milestone' },
|
|
||||||
{ id: 'urgent', label: 'Urgent' },
|
|
||||||
{ id: 'narrow', label: 'Narrow' },
|
|
||||||
{ id: 'progress', label: 'Progress' },
|
|
||||||
{ id: 'round', label: 'Rounded' },
|
|
||||||
];
|
|
||||||
|
|
||||||
export function getData(name, config) {
|
export function getData(name, config) {
|
||||||
const data = datasets[name || 'day'];
|
const data = datasets[name || 'day'];
|
||||||
|
|
||||||
@@ -1070,6 +1060,16 @@ export function getData(name, config) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const taskTypes = [
|
||||||
|
{ id: 'task', label: 'Task' },
|
||||||
|
{ id: 'summary', label: 'Summary task' },
|
||||||
|
{ id: 'milestone', label: 'Milestone' },
|
||||||
|
{ id: 'urgent', label: 'Urgent' },
|
||||||
|
{ id: 'narrow', label: 'Narrow' },
|
||||||
|
{ id: 'progress', label: 'Progress' },
|
||||||
|
{ id: 'round', label: 'Rounded' },
|
||||||
|
];
|
||||||
|
|
||||||
export function getTypedData() {
|
export function getTypedData() {
|
||||||
const t = tasks.map((task, i) => {
|
const t = tasks.map((task, i) => {
|
||||||
const res = { ...task };
|
const res = { ...task };
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ export const links = [
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'/backend-provider-batch/:skin',
|
'/backend-provider-batch/:skin',
|
||||||
'Saving to backend (batch)',
|
'Saving to backend: batch request',
|
||||||
GanttBatchProvider,
|
GanttBatchProvider,
|
||||||
'GanttBatchProvider',
|
'GanttBatchProvider',
|
||||||
],
|
],
|
||||||
|
|||||||
141
package-lock.json
generated
141
package-lock.json
generated
@@ -1,25 +1,25 @@
|
|||||||
{
|
{
|
||||||
"name": "@svar-ui/react-gantt",
|
"name": "@svar-ui/react-gantt",
|
||||||
"version": "2.4.5",
|
"version": "2.5.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@svar-ui/react-gantt",
|
"name": "@svar-ui/react-gantt",
|
||||||
"version": "2.4.5",
|
"version": "2.5.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/gantt-data-provider": "2.4.4",
|
"@svar-ui/gantt-data-provider": "2.5.1",
|
||||||
"@svar-ui/gantt-locales": "2.4.4",
|
"@svar-ui/gantt-locales": "2.5.1",
|
||||||
"@svar-ui/gantt-store": "2.4.4",
|
"@svar-ui/gantt-store": "2.5.1",
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/lib-react": "1.2.2",
|
"@svar-ui/lib-react": "1.2.2",
|
||||||
"@svar-ui/lib-state": "1.9.6",
|
"@svar-ui/lib-state": "1.9.6",
|
||||||
"@svar-ui/react-core": "2.4.1",
|
"@svar-ui/react-core": "2.4.3",
|
||||||
"@svar-ui/react-editor": "2.4.1",
|
"@svar-ui/react-editor": "2.4.3",
|
||||||
"@svar-ui/react-grid": "2.4.1",
|
"@svar-ui/react-grid": "2.5.1",
|
||||||
"@svar-ui/react-menu": "2.4.1",
|
"@svar-ui/react-menu": "2.4.3",
|
||||||
"@svar-ui/react-toolbar": "2.4.1"
|
"@svar-ui/react-toolbar": "2.4.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "18.2.66",
|
"@types/react": "18.2.66",
|
||||||
@@ -1345,24 +1345,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/gantt-data-provider": {
|
"node_modules/@svar-ui/gantt-data-provider": {
|
||||||
"version": "2.4.4",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/gantt-data-provider/-/gantt-data-provider-2.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/gantt-data-provider/-/gantt-data-provider-2.5.1.tgz",
|
||||||
"integrity": "sha512-Jngj0P75STm6cdNqG3mHBcIBq4OWa4eqRLQjgv09xONhx9rYXn9xOOFIyPpyxaeKY9wKr2+H6Z+dhOrJfBg3pA==",
|
"integrity": "sha512-aBn01tezBRlX5mrvf2lhnBTO1VuXEyPa9a2bKi/qhNBJ5F943EBx2utijC7dVbPKPQvIDU8Iq+utUqLjshOgHQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/lib-data-provider": "1.7.1"
|
"@svar-ui/lib-data-provider": "1.7.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/gantt-locales": {
|
"node_modules/@svar-ui/gantt-locales": {
|
||||||
"version": "2.4.4",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/gantt-locales/-/gantt-locales-2.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/gantt-locales/-/gantt-locales-2.5.1.tgz",
|
||||||
"integrity": "sha512-cVXxoA+4cRMGuzKUC6TKM/A9RysxSlL2BJ6F5kx3VzLNzpKAytDWNRp5j+2QPLBqjtcc/KF5Ha2lEUOW2qc2EA==",
|
"integrity": "sha512-6E3qO4wh/+3o5WZPaPTyMt95AeKt9j3nMsmaemEBZEYeLRV67HP0cTUJHFdqrr3aTRkwhPyc0Xym7QZw8OMdSw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/gantt-store": {
|
"node_modules/@svar-ui/gantt-store": {
|
||||||
"version": "2.4.4",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/gantt-store/-/gantt-store-2.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/gantt-store/-/gantt-store-2.5.1.tgz",
|
||||||
"integrity": "sha512-AioX4ndXz17xvK9nw4qlUJ4PWnHZ3mEylIxAE3KqQZtc1CG6HfjPdfZghMR6sGaYhztNNPaeRoEIiQOk0ageyQ==",
|
"integrity": "sha512-8G66oNpFq2GIy5BtOZ1c07ppK5NTbJldUPBosS5Rgf2wbN5OhjNThGdMYoE0y9kXPBVdjHYVZVef3hd0b/pUkQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/lib-state": "1.9.6",
|
"@svar-ui/lib-state": "1.9.6",
|
||||||
@@ -1370,24 +1370,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/grid-data-provider": {
|
"node_modules/@svar-ui/grid-data-provider": {
|
||||||
"version": "2.4.0",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/grid-data-provider/-/grid-data-provider-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/grid-data-provider/-/grid-data-provider-2.5.0.tgz",
|
||||||
"integrity": "sha512-Rm0Zbwj3/ZZLTdpmJXX/lGKafL2sqZuikOh/8KXNty7RXjx6WqryjaAkX6t0cl8lnhPjV/awC4R4+uYRW4UbEQ==",
|
"integrity": "sha512-jI7cPJ9f+ozUoT9IYwHG8coeGvICp6iGI3F4IOLcJ7Hb0/NGaRwz1l0EIt7GjNeJodEIlbpdUZhfbIPSfErx6Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/lib-data-provider": "1.7.1"
|
"@svar-ui/lib-data-provider": "1.7.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/grid-locales": {
|
"node_modules/@svar-ui/grid-locales": {
|
||||||
"version": "2.4.0",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/grid-locales/-/grid-locales-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/grid-locales/-/grid-locales-2.5.0.tgz",
|
||||||
"integrity": "sha512-UnhsQYzDAplMES08QXupa7/1BdBXyCujnTuQaIKZcDf/PGRiSFo3I3iNCk6UdJ5Tnj4si9CqB8/wcIp2YyAHSg==",
|
"integrity": "sha512-xzNE0IRFCeu0KyMNI1CT40sHU5YrvlyWiYk0sMNvUGnC7n+5wfdWeRdAILeZkwXjM4keCl8qhUfTPiMpVYyyGw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/grid-store": {
|
"node_modules/@svar-ui/grid-store": {
|
||||||
"version": "2.4.0",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/grid-store/-/grid-store-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/grid-store/-/grid-store-2.5.0.tgz",
|
||||||
"integrity": "sha512-GJyVC+5G+aA8EfcoKMwrHVP2/OK7bUUbp9ofyZTGUAyuXO9tkxRnfquvk+nTA1ybOfbFCY8rSsJTEHYcgXQCTw==",
|
"integrity": "sha512-Y5x+M5HANyohP7xExIPFzyMCtf5ABVbEwfac/Q7eY5UPUq2eUszfHgqn1YmyV5F7s+YpIXpD0Ed4kMW7MoaEIg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
@@ -1425,9 +1425,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/react-comments": {
|
"node_modules/@svar-ui/react-comments": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/react-comments/-/react-comments-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/react-comments/-/react-comments-2.4.3.tgz",
|
||||||
"integrity": "sha512-zliH0x74guyS3dk/e+wh00t3tFBTaL+j9wMw34PDqkKBiBAOKRUuNhTT7nNRYSnqb1xr7RnHtqMdYhTYelueAg==",
|
"integrity": "sha512-hwx3g0LPIBIBbO/YniLvNRaSwxlC/J0Uo2h2BK5N/FszwcBwruYkHBcXI0CEGpJltEaWHYKeO1hF0U5D2SzeBQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/comments-locales": "2.4.0",
|
"@svar-ui/comments-locales": "2.4.0",
|
||||||
@@ -1435,8 +1435,8 @@
|
|||||||
"@svar-ui/lib-data-provider": "1.7.1",
|
"@svar-ui/lib-data-provider": "1.7.1",
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/lib-state": "1.9.6",
|
"@svar-ui/lib-state": "1.9.6",
|
||||||
"@svar-ui/react-core": "2.4.1",
|
"@svar-ui/react-core": "2.4.3",
|
||||||
"@svar-ui/react-menu": "2.4.1"
|
"@svar-ui/react-menu": "2.4.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18",
|
"react": ">=18",
|
||||||
@@ -1444,9 +1444,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/react-core": {
|
"node_modules/@svar-ui/react-core": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/react-core/-/react-core-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/react-core/-/react-core-2.4.3.tgz",
|
||||||
"integrity": "sha512-lEB12BuBt3xq+68vWPM4K3CUFaDbvy5ZCyIIRXLBxmeeu8IIlVkSrDvPFQ0fUn05+mB3JzXxQx1SjKd2Ic90Tg==",
|
"integrity": "sha512-ufyK48znpYyV+99mb0e44u4aoZN/D/aQxCy58z4xmNWJmQvPFhCu+5QVwnodh9BUbmRp8OHAQjugBAF1eL1doQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/core-locales": "^2.4.0",
|
"@svar-ui/core-locales": "^2.4.0",
|
||||||
@@ -1459,18 +1459,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/react-editor": {
|
"node_modules/@svar-ui/react-editor": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/react-editor/-/react-editor-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/react-editor/-/react-editor-2.4.3.tgz",
|
||||||
"integrity": "sha512-kcxywPxQ821z/8mmAuIJmd1M6mQr/iRdzDD5qEbBqBL1KEASC5a2KCOTfuiKdykYJVgVfqCcQDCd/TyO5NzkYQ==",
|
"integrity": "sha512-cAd7ASRoezGaMdPXQ7EuuKHYRNOr60OOqPvP2gmn+j2cF0ofRRHpo0G5kTwgQws3MmzAlYP3WOXe0gEMZ81iwg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/editor-locales": "2.4.0",
|
"@svar-ui/editor-locales": "2.4.0",
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/lib-state": "1.9.6",
|
"@svar-ui/lib-state": "1.9.6",
|
||||||
"@svar-ui/react-comments": "2.4.1",
|
"@svar-ui/react-comments": "2.4.3",
|
||||||
"@svar-ui/react-core": "2.4.1",
|
"@svar-ui/react-core": "2.4.3",
|
||||||
"@svar-ui/react-tasklist": "2.4.1",
|
"@svar-ui/react-tasklist": "2.4.3",
|
||||||
"@svar-ui/react-toolbar": "2.4.1"
|
"@svar-ui/react-toolbar": "2.4.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18",
|
"react": ">=18",
|
||||||
@@ -1478,9 +1478,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/react-filter": {
|
"node_modules/@svar-ui/react-filter": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/react-filter/-/react-filter-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/react-filter/-/react-filter-2.4.3.tgz",
|
||||||
"integrity": "sha512-FEoGwofzkMpQtWVXArmP9DL/s9mLsRLedLVea9BQQ7yjND2fnlLKo9c8wMvlQJ2e7reZ8QQbWskh11v0dx9vtQ==",
|
"integrity": "sha512-fO9rK0nJEDUf9dQuUKdNOECHDIwuFhSEp27tDDAfSFYOOzOy+ysObs6yMSQ5I8PmCUv/gkIsxu4cYR+Pm4xnJg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/filter-locales": "2.4.0",
|
"@svar-ui/filter-locales": "2.4.0",
|
||||||
@@ -1488,9 +1488,8 @@
|
|||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/lib-react": "1.2.2",
|
"@svar-ui/lib-react": "1.2.2",
|
||||||
"@svar-ui/lib-state": "1.9.6",
|
"@svar-ui/lib-state": "1.9.6",
|
||||||
"@svar-ui/react-core": "2.4.1",
|
"@svar-ui/react-core": "2.4.3",
|
||||||
"@svar-ui/react-grid": "^2.0.0",
|
"@svar-ui/react-menu": "2.4.3"
|
||||||
"@svar-ui/react-menu": "2.4.1"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18",
|
"react": ">=18",
|
||||||
@@ -1498,21 +1497,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/react-grid": {
|
"node_modules/@svar-ui/react-grid": {
|
||||||
"version": "2.4.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/react-grid/-/react-grid-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/react-grid/-/react-grid-2.5.1.tgz",
|
||||||
"integrity": "sha512-Er89V+wxdaXQryUAYi4lvxY66j84/m1mx5JO5Ui3iXAKaKbsSNY9dHArU4vaXphFKeA017u95M52hUJNmG6URQ==",
|
"integrity": "sha512-b4xJGnEIAYcksdSzyfLxb2NyNsaNZiSjiuHVeAUBhX6yGtfZarh99oFFIK6zn94HySbh57S4bSy4fzzGrEqChw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/grid-data-provider": "2.4.0",
|
"@svar-ui/grid-data-provider": "2.5.0",
|
||||||
"@svar-ui/grid-locales": "2.4.0",
|
"@svar-ui/grid-locales": "2.5.0",
|
||||||
"@svar-ui/grid-store": "2.4.0",
|
"@svar-ui/grid-store": "2.5.0",
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/lib-react": "1.2.2",
|
"@svar-ui/lib-react": "1.2.2",
|
||||||
"@svar-ui/lib-state": "1.9.6",
|
"@svar-ui/lib-state": "1.9.6",
|
||||||
"@svar-ui/react-core": "2.4.1",
|
"@svar-ui/react-core": "2.4.3",
|
||||||
"@svar-ui/react-editor": "2.4.1",
|
"@svar-ui/react-editor": "2.4.3",
|
||||||
"@svar-ui/react-filter": "2.4.1",
|
"@svar-ui/react-filter": "2.4.3",
|
||||||
"@svar-ui/react-menu": "2.4.1"
|
"@svar-ui/react-menu": "2.4.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18",
|
"react": ">=18",
|
||||||
@@ -1520,14 +1519,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/react-menu": {
|
"node_modules/@svar-ui/react-menu": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/react-menu/-/react-menu-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/react-menu/-/react-menu-2.4.3.tgz",
|
||||||
"integrity": "sha512-psW3v0VwoKHVTTkZ5kI+R7WocymCA9C96igr/bX6dWpg/pUVO6/8xQMn0p8vuYxPq02nGYncbmDTIzAOT5SPLA==",
|
"integrity": "sha512-c3d6CxeJS3/mA6lkQZY4c8AblRk1oRi0xfADktcrxLVKiyzrwn8alEUJ6QqWlGK7TjCHX/IPsWwRK4e32FrjJA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/core-locales": "2.4.0",
|
"@svar-ui/core-locales": "2.4.0",
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/react-core": "2.4.1"
|
"@svar-ui/react-core": "2.4.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18",
|
"react": ">=18",
|
||||||
@@ -1535,15 +1534,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/react-tasklist": {
|
"node_modules/@svar-ui/react-tasklist": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/react-tasklist/-/react-tasklist-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/react-tasklist/-/react-tasklist-2.4.3.tgz",
|
||||||
"integrity": "sha512-tyg5Fh18PEH5UTpRDb99BuYpK6A1q1dqQ1yN4uYC4c7tufvE/WqJWqsvVy2rcmAl6y0Xmzd01NPu+/TunFGWKw==",
|
"integrity": "sha512-M7BgmfzUZq6XM+/OcRVRh78baa66pDXtV+w/xhLWSHbSOP8LcTZgJQJm3CxjucRSB4SpN9+Yw0dA/E5EZJLT8A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/lib-data-provider": "1.7.1",
|
"@svar-ui/lib-data-provider": "1.7.1",
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/lib-state": "1.9.6",
|
"@svar-ui/lib-state": "1.9.6",
|
||||||
"@svar-ui/react-core": "2.4.1",
|
"@svar-ui/react-core": "2.4.3",
|
||||||
"@svar-ui/tasklist-locales": "2.4.0"
|
"@svar-ui/tasklist-locales": "2.4.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@@ -1552,14 +1551,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svar-ui/react-toolbar": {
|
"node_modules/@svar-ui/react-toolbar": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@svar-ui/react-toolbar/-/react-toolbar-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@svar-ui/react-toolbar/-/react-toolbar-2.4.3.tgz",
|
||||||
"integrity": "sha512-cKFMkmLQ0X8xToG0omni2/y850oL5cxU/6RtPOUv4uC9FFrgrbwJKiuummSxST6nVCrLBfZ+JlKazZH1Ez3Rew==",
|
"integrity": "sha512-w9qMxDhmOw2PJRZM9gGLQ7oAhY1ImVfUeGrdG2Mg5D9uo1R6sX74zV3DxaRoRbO79PIqaPgY6ROwQoG00V+/Ow==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/core-locales": "2.4.0",
|
"@svar-ui/core-locales": "2.4.0",
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/react-core": "2.4.1"
|
"@svar-ui/react-core": "2.4.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18",
|
"react": ">=18",
|
||||||
|
|||||||
18
package.json
18
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@svar-ui/react-gantt",
|
"name": "@svar-ui/react-gantt",
|
||||||
"version": "2.4.5",
|
"version": "2.5.2",
|
||||||
"description": "A customizable, high-performance React Gantt chart component for building project timelines.",
|
"description": "A customizable, high-performance React Gantt chart component for building project timelines.",
|
||||||
"productTag": "gantt",
|
"productTag": "gantt",
|
||||||
"productTrial": true,
|
"productTrial": true,
|
||||||
@@ -59,17 +59,17 @@
|
|||||||
"react-dom": ">=18"
|
"react-dom": ">=18"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@svar-ui/gantt-data-provider": "2.4.4",
|
"@svar-ui/gantt-data-provider": "2.5.1",
|
||||||
"@svar-ui/gantt-locales": "2.4.4",
|
"@svar-ui/gantt-locales": "2.5.1",
|
||||||
"@svar-ui/gantt-store": "2.4.4",
|
"@svar-ui/gantt-store": "2.5.1",
|
||||||
"@svar-ui/lib-dom": "0.11.1",
|
"@svar-ui/lib-dom": "0.11.1",
|
||||||
"@svar-ui/lib-state": "1.9.6",
|
"@svar-ui/lib-state": "1.9.6",
|
||||||
"@svar-ui/lib-react": "1.2.2",
|
"@svar-ui/lib-react": "1.2.2",
|
||||||
"@svar-ui/react-core": "2.4.1",
|
"@svar-ui/react-core": "2.4.3",
|
||||||
"@svar-ui/react-menu": "2.4.1",
|
"@svar-ui/react-menu": "2.4.3",
|
||||||
"@svar-ui/react-grid": "2.4.1",
|
"@svar-ui/react-grid": "2.5.1",
|
||||||
"@svar-ui/react-toolbar": "2.4.1",
|
"@svar-ui/react-toolbar": "2.4.3",
|
||||||
"@svar-ui/react-editor": "2.4.1"
|
"@svar-ui/react-editor": "2.4.3"
|
||||||
},
|
},
|
||||||
"homepage": "https://svar.dev/react/gantt/",
|
"homepage": "https://svar.dev/react/gantt/",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -41,8 +41,18 @@ const ContextMenu = forwardRef(function ContextMenu(
|
|||||||
const selectedVal = useStoreLater(api, 'selected');
|
const selectedVal = useStoreLater(api, 'selected');
|
||||||
const selectedTasksVal = useStoreLater(api, '_selected');
|
const selectedTasksVal = useStoreLater(api, '_selected');
|
||||||
const splitTasksVal = useStoreLater(api, 'splitTasks');
|
const splitTasksVal = useStoreLater(api, 'splitTasks');
|
||||||
|
const summaryVal = useStoreLater(api, 'summary');
|
||||||
|
|
||||||
const fullOptions = useMemo(() => getMenuOptions({ splitTasks: true }), []);
|
const config = useMemo(
|
||||||
|
() => ({
|
||||||
|
splitTasks: splitTasksVal,
|
||||||
|
taskTypes: taskTypesVal,
|
||||||
|
summary: summaryVal,
|
||||||
|
}),
|
||||||
|
[splitTasksVal, taskTypesVal, summaryVal],
|
||||||
|
);
|
||||||
|
|
||||||
|
const fullOptions = useMemo(() => getMenuOptions(config), [config]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!api) return;
|
if (!api) return;
|
||||||
@@ -68,20 +78,14 @@ const ContextMenu = forwardRef(function ContextMenu(
|
|||||||
function getOptions() {
|
function getOptions() {
|
||||||
const finalOptions = optionsInit.length
|
const finalOptions = optionsInit.length
|
||||||
? optionsInit
|
? optionsInit
|
||||||
: getMenuOptions({ splitTasks: splitTasksVal });
|
: getMenuOptions(config);
|
||||||
const convertOption = finalOptions.find((o) => o.id === 'convert-task');
|
|
||||||
if (convertOption) {
|
|
||||||
convertOption.data = [];
|
|
||||||
(taskTypesVal || []).forEach((t) => {
|
|
||||||
convertOption.data.push(convertOption.dataFactory(t));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return applyLocaleFn(finalOptions);
|
return applyLocaleFn(finalOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cOptions = useMemo(() => {
|
const cOptions = useMemo(() => {
|
||||||
return getOptions();
|
return getOptions();
|
||||||
}, [api, optionsInit, taskTypesVal, splitTasksVal, _]);
|
}, [api, optionsInit, config, _]);
|
||||||
|
|
||||||
const selectedTasks = useMemo(
|
const selectedTasks = useMemo(
|
||||||
() => (selectedTasksVal && selectedTasksVal.length ? selectedTasksVal : []),
|
() => (selectedTasksVal && selectedTasksVal.length ? selectedTasksVal : []),
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ function Editor({
|
|||||||
const activeTask = useStore(api, '_activeTask');
|
const activeTask = useStore(api, '_activeTask');
|
||||||
const taskId = useStore(api, 'activeTask');
|
const taskId = useStore(api, 'activeTask');
|
||||||
const unscheduledTasks = useStore(api, 'unscheduledTasks');
|
const unscheduledTasks = useStore(api, 'unscheduledTasks');
|
||||||
|
const summary = useStore(api, 'summary');
|
||||||
const links = useStore(api, 'links');
|
const links = useStore(api, 'links');
|
||||||
const splitTasks = useStore(api, 'splitTasks');
|
const splitTasks = useStore(api, 'splitTasks');
|
||||||
const segmentIndex = useMemo(
|
const segmentIndex = useMemo(
|
||||||
@@ -105,9 +106,10 @@ function Editor({
|
|||||||
() => segmentIndex || segmentIndex === 0,
|
() => segmentIndex || segmentIndex === 0,
|
||||||
[segmentIndex],
|
[segmentIndex],
|
||||||
);
|
);
|
||||||
|
const taskTypes = useStore(api, 'taskTypes');
|
||||||
const baseItems = useMemo(
|
const baseItems = useMemo(
|
||||||
() => getEditorItems({ unscheduledTasks }),
|
() => getEditorItems({ unscheduledTasks, summary, taskTypes }),
|
||||||
[unscheduledTasks],
|
[unscheduledTasks, summary, taskTypes],
|
||||||
);
|
);
|
||||||
const undo = useStore(api, 'undo');
|
const undo = useStore(api, 'undo');
|
||||||
|
|
||||||
@@ -116,8 +118,6 @@ function Editor({
|
|||||||
const [editorValues, setEditorValues] = useState();
|
const [editorValues, setEditorValues] = useState();
|
||||||
const [editorErrors, setEditorErrors] = useState(null);
|
const [editorErrors, setEditorErrors] = useState(null);
|
||||||
|
|
||||||
const taskTypes = useStore(api, 'taskTypes');
|
|
||||||
|
|
||||||
const task = useMemo(() => {
|
const task = useMemo(() => {
|
||||||
if (!activeTask) return null;
|
if (!activeTask) return null;
|
||||||
let data;
|
let data;
|
||||||
@@ -165,7 +165,7 @@ function Editor({
|
|||||||
item.onLinksChange = handleLinksChange;
|
item.onLinksChange = handleLinksChange;
|
||||||
}
|
}
|
||||||
if (item.comp === 'select' && item.key === 'type') {
|
if (item.comp === 'select' && item.key === 'type') {
|
||||||
const options = item.options ?? (taskTypes ? taskTypes : []);
|
const options = item.options ?? [];
|
||||||
item.options = options.map((t) => ({
|
item.options = options.map((t) => ({
|
||||||
...t,
|
...t,
|
||||||
label: _(t.label),
|
label: _(t.label),
|
||||||
@@ -196,7 +196,7 @@ function Editor({
|
|||||||
return eItems.filter(
|
return eItems.filter(
|
||||||
(item) => !item.isHidden || !item.isHidden(editorValues, api.getState()),
|
(item) => !item.isHidden || !item.isHidden(editorValues, api.getState()),
|
||||||
);
|
);
|
||||||
}, [items, baseItems, editorValues, taskTypes, _, api, autoSave]);
|
}, [items, baseItems, editorValues, _, api, autoSave]);
|
||||||
|
|
||||||
const editorKeys = useMemo(
|
const editorKeys = useMemo(
|
||||||
() => editorItems.map((i) => i.key),
|
() => editorItems.map((i) => i.key),
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ const Gantt = forwardRef(function Gantt(
|
|||||||
calendar = null,
|
calendar = null,
|
||||||
undo = false,
|
undo = false,
|
||||||
splitTasks = false,
|
splitTasks = false,
|
||||||
|
summary = null,
|
||||||
|
_export = false,
|
||||||
...restProps
|
...restProps
|
||||||
},
|
},
|
||||||
ref,
|
ref,
|
||||||
@@ -136,12 +138,16 @@ const Gantt = forwardRef(function Gantt(
|
|||||||
// parse task dates effect
|
// parse task dates effect
|
||||||
const parsedTasksRef = useRef(null);
|
const parsedTasksRef = useRef(null);
|
||||||
if (parsedTasksRef.current !== tasks) {
|
if (parsedTasksRef.current !== tasks) {
|
||||||
|
if (!_export) {
|
||||||
parseTaskDates(tasks, { durationUnit, splitTasks, calendar });
|
parseTaskDates(tasks, { durationUnit, splitTasks, calendar });
|
||||||
|
}
|
||||||
parsedTasksRef.current = tasks;
|
parsedTasksRef.current = tasks;
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!_export) {
|
||||||
parseTaskDates(tasks, { durationUnit, splitTasks, calendar });
|
parseTaskDates(tasks, { durationUnit, splitTasks, calendar });
|
||||||
}, [tasks, durationUnit, calendar, splitTasks]);
|
}
|
||||||
|
}, [tasks, durationUnit, calendar, splitTasks, _export]);
|
||||||
|
|
||||||
const firstInRoute = useMemo(() => dataStore.in, [dataStore]);
|
const firstInRoute = useMemo(() => dataStore.in, [dataStore]);
|
||||||
|
|
||||||
@@ -176,7 +182,7 @@ const Gantt = forwardRef(function Gantt(
|
|||||||
on: firstInRoute.on.bind(firstInRoute),
|
on: firstInRoute.on.bind(firstInRoute),
|
||||||
detach: firstInRoute.detach.bind(firstInRoute),
|
detach: firstInRoute.detach.bind(firstInRoute),
|
||||||
getTask: dataStore.getTask.bind(dataStore),
|
getTask: dataStore.getTask.bind(dataStore),
|
||||||
serialize: dataStore.serialize.bind(dataStore),
|
serialize: () => dataStore.serialize(),
|
||||||
getTable: (waitRender) =>
|
getTable: (waitRender) =>
|
||||||
waitRender
|
waitRender
|
||||||
? new Promise((res) => setTimeout(() => res(tableAPIRef.current), 1))
|
? new Promise((res) => setTimeout(() => res(tableAPIRef.current), 1))
|
||||||
@@ -229,6 +235,7 @@ const Gantt = forwardRef(function Gantt(
|
|||||||
undo,
|
undo,
|
||||||
_weekStart: lCalendar.weekStart,
|
_weekStart: lCalendar.weekStart,
|
||||||
splitTasks,
|
splitTasks,
|
||||||
|
summary,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initOnceRef.current++;
|
initOnceRef.current++;
|
||||||
@@ -258,6 +265,7 @@ const Gantt = forwardRef(function Gantt(
|
|||||||
undo,
|
undo,
|
||||||
lCalendar,
|
lCalendar,
|
||||||
splitTasks,
|
splitTasks,
|
||||||
|
summary,
|
||||||
dataStore,
|
dataStore,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -290,6 +298,7 @@ const Gantt = forwardRef(function Gantt(
|
|||||||
undo,
|
undo,
|
||||||
_weekStart: lCalendar.weekStart,
|
_weekStart: lCalendar.weekStart,
|
||||||
splitTasks,
|
splitTasks,
|
||||||
|
summary,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ function Bars(props) {
|
|||||||
const tree = useStore(api, 'tasks');
|
const tree = useStore(api, 'tasks');
|
||||||
const schedule = useStore(api, 'schedule');
|
const schedule = useStore(api, 'schedule');
|
||||||
const splitTasks = useStore(api, 'splitTasks');
|
const splitTasks = useStore(api, 'splitTasks');
|
||||||
|
const summary = useStore(api, 'summary');
|
||||||
|
|
||||||
const tasks = useMemo(() => {
|
const tasks = useMemo(() => {
|
||||||
if (!areaValue || !Array.isArray(rTasksValue)) return [];
|
if (!areaValue || !Array.isArray(rTasksValue)) return [];
|
||||||
@@ -53,7 +54,15 @@ function Bars(props) {
|
|||||||
const [taskMove, setTaskMove] = useState(null);
|
const [taskMove, setTaskMove] = useState(null);
|
||||||
const progressFromRef = useRef(null);
|
const progressFromRef = useRef(null);
|
||||||
|
|
||||||
const [selectedLink, setSelectedLink] = useState(null);
|
const [selectedLinkId, setSelectedLinkId] = useState(null);
|
||||||
|
|
||||||
|
const selectedLink = useMemo(() => {
|
||||||
|
return (
|
||||||
|
selectedLinkId && {
|
||||||
|
...rLinksValue.find((link) => link.id === selectedLinkId),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}, [selectedLinkId, rLinksCounter]);
|
||||||
|
|
||||||
const [touched, setTouched] = useState(undefined);
|
const [touched, setTouched] = useState(undefined);
|
||||||
const touchTimerRef = useRef(null);
|
const touchTimerRef = useRef(null);
|
||||||
@@ -200,12 +209,9 @@ function Bars(props) {
|
|||||||
[down],
|
[down],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSelectLink = useCallback(
|
const onSelectLink = useCallback((id) => {
|
||||||
(id) => {
|
setSelectedLinkId(id);
|
||||||
setSelectedLink(id && { ...rLinksValue.find((link) => link.id === id) });
|
}, []);
|
||||||
},
|
|
||||||
[rLinksValue],
|
|
||||||
);
|
|
||||||
|
|
||||||
const up = useCallback(() => {
|
const up = useCallback(() => {
|
||||||
if (progressFromRef.current) {
|
if (progressFromRef.current) {
|
||||||
@@ -285,10 +291,11 @@ function Bars(props) {
|
|||||||
const { mode, l, w, x, id, start, segment, index } = taskMove;
|
const { mode, l, w, x, id, start, segment, index } = taskMove;
|
||||||
const task = api.getTask(id);
|
const task = api.getTask(id);
|
||||||
const dx = clientX - x;
|
const dx = clientX - x;
|
||||||
|
const minWidth = Math.round(lengthUnitWidth) || 1;
|
||||||
if (
|
if (
|
||||||
(!start && Math.abs(dx) < 20) ||
|
(!start && Math.abs(dx) < 20) ||
|
||||||
(mode === 'start' && w - dx < lengthUnitWidth) ||
|
(mode === "start" && w - dx < minWidth) ||
|
||||||
(mode === 'end' && w + dx < lengthUnitWidth) ||
|
(mode === "end" && w + dx < minWidth) ||
|
||||||
(mode === 'move' &&
|
(mode === 'move' &&
|
||||||
((dx < 0 && l + dx < 0) ||
|
((dx < 0 && l + dx < 0) ||
|
||||||
(dx > 0 && l + w + dx > totalWidth))) ||
|
(dx > 0 && l + w + dx > totalWidth))) ||
|
||||||
@@ -315,6 +322,7 @@ function Bars(props) {
|
|||||||
width: width,
|
width: width,
|
||||||
left: left,
|
left: left,
|
||||||
inProgress: true,
|
inProgress: true,
|
||||||
|
start,
|
||||||
...(segment && { segmentIndex: index }),
|
...(segment && { segmentIndex: index }),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -465,8 +473,8 @@ function Bars(props) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (css.contains('wx-delete-button-icon')) {
|
} else if (css.contains('wx-delete-button-icon')) {
|
||||||
api.exec('delete-link', { id: selectedLink.id });
|
api.exec('delete-link', { id: selectedLinkId });
|
||||||
setSelectedLink(null);
|
setSelectedLinkId(null);
|
||||||
} else {
|
} else {
|
||||||
let segmentIndex;
|
let segmentIndex;
|
||||||
const segmentNode = locate(e, 'data-segment');
|
const segmentNode = locate(e, 'data-segment');
|
||||||
@@ -662,7 +670,9 @@ function Bars(props) {
|
|||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{!readonly && !(splitTasks && task.segments) ? (
|
{!readonly &&
|
||||||
|
!(splitTasks && task.segments) &&
|
||||||
|
!(task.type == 'summary' && summary?.autoProgress) ? (
|
||||||
<div
|
<div
|
||||||
className="wx-GKbcLEGA wx-progress-marker"
|
className="wx-GKbcLEGA wx-progress-marker"
|
||||||
style={{ left: `calc(${task.progress}% - 10px)` }}
|
style={{ left: `calc(${task.progress}% - 10px)` }}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wx-markers.wx-mR7v2Xag {
|
.wx-markers.wx-mR7v2Xag {
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ export default function Links({ api, autoSave, onLinksChange }) {
|
|||||||
{(linksData || []).map((group, idx) =>
|
{(linksData || []).map((group, idx) =>
|
||||||
group.data.length ? (
|
group.data.length ? (
|
||||||
<div className="wx-j93aYGQf wx-links" key={idx}>
|
<div className="wx-j93aYGQf wx-links" key={idx}>
|
||||||
|
<context.fieldId.Provider value={null}>
|
||||||
<Field label={group.title} position="top">
|
<Field label={group.title} position="top">
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -153,6 +154,7 @@ export default function Links({ api, autoSave, onLinksChange }) {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</Field>
|
</Field>
|
||||||
|
</context.fieldId.Provider>
|
||||||
</div>
|
</div>
|
||||||
) : null,
|
) : null,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import Material from './themes/Material.jsx';
|
|||||||
import Willow from './themes/Willow.jsx';
|
import Willow from './themes/Willow.jsx';
|
||||||
import WillowDark from './themes/WillowDark.jsx';
|
import WillowDark from './themes/WillowDark.jsx';
|
||||||
|
|
||||||
|
import pkg from '../package.json' with { type: 'json' };
|
||||||
|
|
||||||
export {
|
export {
|
||||||
defaultEditorItems,
|
defaultEditorItems,
|
||||||
defaultToolbarButtons,
|
defaultToolbarButtons,
|
||||||
@@ -24,6 +26,8 @@ export {
|
|||||||
|
|
||||||
export { registerEditorItem } from '@svar-ui/react-editor';
|
export { registerEditorItem } from '@svar-ui/react-editor';
|
||||||
|
|
||||||
|
export const version = pkg.version;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Gantt,
|
Gantt,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
|
|||||||
37
whatsnew.md
37
whatsnew.md
@@ -1,3 +1,19 @@
|
|||||||
|
## 2.5.1
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
- Server-side export to PNG, PDF, XLSX, MS Project | PRO feature
|
||||||
|
- Client-side export and import from MS Project | PRO feature
|
||||||
|
- Auto calculation of progress for summary tasks | PRO feature
|
||||||
|
- Auto conversion of parent tasks to summary tasks | PRO feature
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- Scale is expanded left with a small dataset during screen resizing
|
||||||
|
- Markers ignore scale boundaries
|
||||||
|
- Delete link placeholder is misplaced sometimes
|
||||||
|
- Task duration and start date and incorrect during drag-n-drop on some scales
|
||||||
|
|
||||||
## Version 2.4.5
|
## Version 2.4.5
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
@@ -16,21 +32,18 @@ Community license changed from GPL to MIT
|
|||||||
|
|
||||||
### New features
|
### New features
|
||||||
|
|
||||||
|
- Basic auto scheduling | PRO feature
|
||||||
|
- Handling of invalid links | PRO feature
|
||||||
|
- Critical path calculation | PRO feature
|
||||||
|
- Global calendar to define working schedule | PRO feature
|
||||||
|
- Unscheduled tasks | PRO feature
|
||||||
|
- Vertical markers on timeline | PRO feature
|
||||||
|
- Baselines | PRO feature
|
||||||
|
- Split tasks | PRO feature
|
||||||
|
- Undo/redo | PRO feature
|
||||||
- Ability to remove links from Chart UI
|
- Ability to remove links from Chart UI
|
||||||
- Locale-based scale formatting
|
- Locale-based scale formatting
|
||||||
|
|
||||||
### Pro edition features
|
|
||||||
|
|
||||||
- Basic auto scheduling
|
|
||||||
- Handling of invalid links
|
|
||||||
- Critical path calculation
|
|
||||||
- Global calendar to define working schedule
|
|
||||||
- Unscheduled tasks
|
|
||||||
- Vertical markers on timeline
|
|
||||||
- Baselines
|
|
||||||
- Split tasks
|
|
||||||
- Undo/redo
|
|
||||||
|
|
||||||
### Updates
|
### Updates
|
||||||
|
|
||||||
- Resizer line can be dragged to expand current display mode
|
- Resizer line can be dragged to expand current display mode
|
||||||
|
|||||||
Reference in New Issue
Block a user