project type init
This commit is contained in:
parent
507e8a4d69
commit
02c9c58091
@ -71,7 +71,7 @@ npm start
|
|||||||
| :----------------- | :---------------------------------------------------------- | :-------------------------------------------------------------------------------------- |
|
| :----------------- | :---------------------------------------------------------- | :-------------------------------------------------------------------------------------- |
|
||||||
| onSelect | (task: Task, isSelected: boolean) => void | Specifies the function to be executed on the taskbar select or unselect event. |
|
| onSelect | (task: Task, isSelected: boolean) => void | Specifies the function to be executed on the taskbar select or unselect event. |
|
||||||
| onDoubleClick | (task: Task) => void | Specifies the function to be executed on the taskbar onDoubleClick event. |
|
| onDoubleClick | (task: Task) => void | Specifies the function to be executed on the taskbar onDoubleClick event. |
|
||||||
| onTaskDelete\* | (task: Task) => void/boolean/Promise<void>/Promise<boolean> | Specifies the function to be executed on the taskbar on Delete button press event. |
|
| onDelete\* | (task: Task) => void/boolean/Promise<void>/Promise<boolean> | Specifies the function to be executed on the taskbar on Delete button press event. |
|
||||||
| onDateChange\* | (task: Task) => void/boolean/Promise<void>/Promise<boolean> | Specifies the function to be executed when drag taskbar event on timeline has finished. |
|
| onDateChange\* | (task: Task) => void/boolean/Promise<void>/Promise<boolean> | Specifies the function to be executed when drag taskbar event on timeline has finished. |
|
||||||
| onProgressChange\* | (task: Task) => void/boolean/Promise<void>/Promise<boolean> | Specifies the function to be executed when drag taskbar progress event has finished. |
|
| onProgressChange\* | (task: Task) => void/boolean/Promise<void>/Promise<boolean> | Specifies the function to be executed when drag taskbar progress event has finished. |
|
||||||
| timeStep | (task: Task) => number | A time step value for onDateChange. Specify in milliseconds. |
|
| timeStep | (task: Task) => number | A time step value for onDateChange. Specify in milliseconds. |
|
||||||
@ -131,6 +131,7 @@ npm start
|
|||||||
| | | - **progressSelectedColor**: String. Specifies the taskbar progress fill color globally on select. |
|
| | | - **progressSelectedColor**: String. Specifies the taskbar progress fill color globally on select. |
|
||||||
| isDisabled | bool | Disables all action for current task. |
|
| isDisabled | bool | Disables all action for current task. |
|
||||||
| fontSize | string | Specifies the taskbar font size locally. |
|
| fontSize | string | Specifies the taskbar font size locally. |
|
||||||
|
| project | string | Task project name |
|
||||||
|
|
||||||
\*Required
|
\*Required
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Task, ViewMode, Gantt } from "gantt-task-react";
|
import { Task, ViewMode, Gantt } from "gantt-task-react";
|
||||||
import { ViewSwitcher } from "./components/view-switcher";
|
import { ViewSwitcher } from "./components/view-switcher";
|
||||||
import { initTasks } from "./helper";
|
import { getStartEndDateForProject, initTasks } from "./helper";
|
||||||
import "gantt-task-react/dist/index.css";
|
import "gantt-task-react/dist/index.css";
|
||||||
|
|
||||||
//Init
|
//Init
|
||||||
@ -18,7 +18,20 @@ const App = () => {
|
|||||||
|
|
||||||
const onTaskChange = (task: Task) => {
|
const onTaskChange = (task: Task) => {
|
||||||
console.log("On date change Id:" + task.id);
|
console.log("On date change Id:" + task.id);
|
||||||
const newTasks = tasks.map(t => (t.id === task.id ? task : t));
|
let newTasks = tasks.map(t => (t.id === task.id ? task : t));
|
||||||
|
if (task.project) {
|
||||||
|
const [start, end] = getStartEndDateForProject(newTasks, task.project);
|
||||||
|
const project = newTasks[newTasks.findIndex(t => t.id === task.project)];
|
||||||
|
if (
|
||||||
|
project.start.getTime() !== start.getTime() ||
|
||||||
|
project.end.getTime() !== end.getTime()
|
||||||
|
) {
|
||||||
|
const changedProject = { ...project, start, end };
|
||||||
|
newTasks = newTasks.map(t =>
|
||||||
|
t.id === task.project ? changedProject : t
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
setTasks(newTasks);
|
setTasks(newTasks);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,20 +68,22 @@ const App = () => {
|
|||||||
tasks={tasks}
|
tasks={tasks}
|
||||||
viewMode={view}
|
viewMode={view}
|
||||||
onDateChange={onTaskChange}
|
onDateChange={onTaskChange}
|
||||||
onTaskDelete={onTaskDelete}
|
onDelete={onTaskDelete}
|
||||||
onProgressChange={onProgressChange}
|
onProgressChange={onProgressChange}
|
||||||
onDoubleClick={onDblClick}
|
onDoubleClick={onDblClick}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
listCellWidth={isChecked ? "155px" : ""}
|
listCellWidth={isChecked ? "155px" : ""}
|
||||||
columnWidth={columnWidth}
|
columnWidth={columnWidth}
|
||||||
/>
|
/>
|
||||||
<h3 style={{ color: "#e56b6f" }}>Milestones are not available</h3>
|
<h3 style={{ color: "#e56b6f" }}>
|
||||||
|
Milestones and projects are not available
|
||||||
|
</h3>
|
||||||
<h3>Gantt With Limited Height</h3>
|
<h3>Gantt With Limited Height</h3>
|
||||||
<Gantt
|
<Gantt
|
||||||
tasks={tasks}
|
tasks={tasks}
|
||||||
viewMode={view}
|
viewMode={view}
|
||||||
onDateChange={onTaskChange}
|
onDateChange={onTaskChange}
|
||||||
onTaskDelete={onTaskDelete}
|
onDelete={onTaskDelete}
|
||||||
onProgressChange={onProgressChange}
|
onProgressChange={onProgressChange}
|
||||||
onDoubleClick={onDblClick}
|
onDoubleClick={onDblClick}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
|
|||||||
@ -3,6 +3,14 @@ import { Task } from "../../dist/types/public-types";
|
|||||||
export function initTasks() {
|
export function initTasks() {
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
const tasks: Task[] = [
|
const tasks: Task[] = [
|
||||||
|
{
|
||||||
|
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 1),
|
||||||
|
end: new Date(currentDate.getFullYear(), currentDate.getMonth(), 15),
|
||||||
|
name: "Some Project",
|
||||||
|
id: "ProjectSample",
|
||||||
|
progress: 25,
|
||||||
|
type: "project",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 1),
|
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 1),
|
||||||
end: new Date(
|
end: new Date(
|
||||||
@ -16,6 +24,7 @@ export function initTasks() {
|
|||||||
id: "Task 0",
|
id: "Task 0",
|
||||||
progress: 45,
|
progress: 45,
|
||||||
type: "task",
|
type: "task",
|
||||||
|
project: "ProjectSample",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 2),
|
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 2),
|
||||||
@ -25,6 +34,7 @@ export function initTasks() {
|
|||||||
progress: 25,
|
progress: 25,
|
||||||
dependencies: ["Task 0"],
|
dependencies: ["Task 0"],
|
||||||
type: "task",
|
type: "task",
|
||||||
|
project: "ProjectSample",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 4),
|
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 4),
|
||||||
@ -34,6 +44,7 @@ export function initTasks() {
|
|||||||
progress: 10,
|
progress: 10,
|
||||||
dependencies: ["Task 1"],
|
dependencies: ["Task 1"],
|
||||||
type: "task",
|
type: "task",
|
||||||
|
project: "ProjectSample",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 8),
|
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 8),
|
||||||
@ -43,6 +54,7 @@ export function initTasks() {
|
|||||||
progress: 2,
|
progress: 2,
|
||||||
dependencies: ["Task 2"],
|
dependencies: ["Task 2"],
|
||||||
type: "task",
|
type: "task",
|
||||||
|
project: "ProjectSample",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 8),
|
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 8),
|
||||||
@ -52,20 +64,21 @@ export function initTasks() {
|
|||||||
type: "task",
|
type: "task",
|
||||||
progress: 70,
|
progress: 70,
|
||||||
dependencies: ["Task 2"],
|
dependencies: ["Task 2"],
|
||||||
|
project: "ProjectSample",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 15),
|
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 15),
|
||||||
end: new Date(currentDate.getFullYear(), currentDate.getMonth(), 16),
|
end: new Date(currentDate.getFullYear(), currentDate.getMonth(), 15),
|
||||||
name: "Release",
|
name: "Release",
|
||||||
id: "Task 6",
|
id: "Task 6",
|
||||||
progress: currentDate.getMonth(),
|
progress: currentDate.getMonth(),
|
||||||
type: "milestone",
|
type: "milestone",
|
||||||
dependencies: ["Task 4"],
|
dependencies: ["Task 4"],
|
||||||
styles: { progressColor: "#ffbb54", progressSelectedColor: "#ff9e0d" },
|
project: "ProjectSample",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 24),
|
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 18),
|
||||||
end: new Date(currentDate.getFullYear(), currentDate.getMonth(), 25),
|
end: new Date(currentDate.getFullYear(), currentDate.getMonth(), 19),
|
||||||
name: "Party Time",
|
name: "Party Time",
|
||||||
id: "Task 9",
|
id: "Task 9",
|
||||||
progress: 0,
|
progress: 0,
|
||||||
@ -75,3 +88,20 @@ export function initTasks() {
|
|||||||
];
|
];
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getStartEndDateForProject(tasks: Task[], projectId: string) {
|
||||||
|
const projectTasks = tasks.filter(t => t.project === projectId);
|
||||||
|
let start = projectTasks[0].start;
|
||||||
|
let end = projectTasks[0].end;
|
||||||
|
|
||||||
|
for (let i = 0; i < projectTasks.length; i++) {
|
||||||
|
const task = projectTasks[i];
|
||||||
|
if (start.getTime() > task.start.getTime()) {
|
||||||
|
start = task.start;
|
||||||
|
}
|
||||||
|
if (end.getTime() < task.end.getTime()) {
|
||||||
|
end = task.end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [start, end];
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gantt-task-react",
|
"name": "gantt-task-react",
|
||||||
"version": "0.2.2",
|
"version": "0.3.0",
|
||||||
"description": "Interactive Gantt Chart for React with TypeScript.",
|
"description": "Interactive Gantt Chart for React with TypeScript.",
|
||||||
"author": "MaTeMaTuK <maksym.vikarii@gmail.com>",
|
"author": "MaTeMaTuK <maksym.vikarii@gmail.com>",
|
||||||
"homepage": "https://github.com/MaTeMaTuK/gantt-task-react",
|
"homepage": "https://github.com/MaTeMaTuK/gantt-task-react",
|
||||||
|
|||||||
@ -46,7 +46,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
|
|||||||
onDateChange,
|
onDateChange,
|
||||||
onProgressChange,
|
onProgressChange,
|
||||||
onDoubleClick,
|
onDoubleClick,
|
||||||
onTaskDelete,
|
onDelete,
|
||||||
onSelect,
|
onSelect,
|
||||||
}) => {
|
}) => {
|
||||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||||
@ -300,7 +300,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
|
|||||||
onDateChange,
|
onDateChange,
|
||||||
onProgressChange,
|
onProgressChange,
|
||||||
onDoubleClick,
|
onDoubleClick,
|
||||||
onTaskDelete,
|
onDelete,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ export const TaskGanttContent: React.FC<TaskGanttContentProps> = ({
|
|||||||
onDateChange,
|
onDateChange,
|
||||||
onProgressChange,
|
onProgressChange,
|
||||||
onDoubleClick,
|
onDoubleClick,
|
||||||
onTaskDelete,
|
onDelete,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
}) => {
|
}) => {
|
||||||
const point = svg?.current?.createSVGPoint();
|
const point = svg?.current?.createSVGPoint();
|
||||||
@ -204,9 +204,9 @@ export const TaskGanttContent: React.FC<TaskGanttContentProps> = ({
|
|||||||
// Keyboard events
|
// Keyboard events
|
||||||
else if (isKeyboardEvent(event)) {
|
else if (isKeyboardEvent(event)) {
|
||||||
if (action === "delete") {
|
if (action === "delete") {
|
||||||
if (onTaskDelete) {
|
if (onDelete) {
|
||||||
try {
|
try {
|
||||||
const result = await onTaskDelete(task);
|
const result = await onDelete(task);
|
||||||
if (result !== undefined && result) {
|
if (result !== undefined && result) {
|
||||||
setGanttEvent({ action, changedTask: task });
|
setGanttEvent({ action, changedTask: task });
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/components/task-item/project/project.module.css
Normal file
13
src/components/task-item/project/project.module.css
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.projectWrapper {
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectBackground {
|
||||||
|
user-select: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectTop {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
76
src/components/task-item/project/project.tsx
Normal file
76
src/components/task-item/project/project.tsx
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { progressWithByParams } from "../../../helpers/bar-helper";
|
||||||
|
import { TaskItemProps } from "../task-item";
|
||||||
|
import styles from "./project.module.css";
|
||||||
|
|
||||||
|
export const Project: React.FC<TaskItemProps> = ({ task, isSelected }) => {
|
||||||
|
const barColor = isSelected
|
||||||
|
? task.styles.backgroundSelectedColor
|
||||||
|
: task.styles.backgroundColor;
|
||||||
|
const processColor = isSelected
|
||||||
|
? task.styles.progressSelectedColor
|
||||||
|
: task.styles.progressColor;
|
||||||
|
const progressWidth = progressWithByParams(task.x1, task.x2, task.progress);
|
||||||
|
const projectWith = task.x2 - task.x1;
|
||||||
|
|
||||||
|
const projectLeftTriangle = [
|
||||||
|
task.x1,
|
||||||
|
task.y + task.height / 2 - 1,
|
||||||
|
task.x1,
|
||||||
|
task.y + task.height,
|
||||||
|
task.x1 + 15,
|
||||||
|
task.y + task.height / 2 - 1,
|
||||||
|
].join(",");
|
||||||
|
const projectRightTriangle = [
|
||||||
|
task.x2,
|
||||||
|
task.y + task.height / 2 - 1,
|
||||||
|
task.x2,
|
||||||
|
task.y + task.height,
|
||||||
|
task.x2 - 15,
|
||||||
|
task.y + task.height / 2 - 1,
|
||||||
|
].join(",");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<g tabIndex={0} className={styles.projectWrapper}>
|
||||||
|
<rect
|
||||||
|
fill={barColor}
|
||||||
|
x={task.x1}
|
||||||
|
width={projectWith}
|
||||||
|
y={task.y}
|
||||||
|
height={task.height}
|
||||||
|
rx={task.barCornerRadius}
|
||||||
|
ry={task.barCornerRadius}
|
||||||
|
className={styles.projectBackground}
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
x={task.x1}
|
||||||
|
width={progressWidth}
|
||||||
|
y={task.y}
|
||||||
|
height={task.height}
|
||||||
|
ry={task.barCornerRadius}
|
||||||
|
rx={task.barCornerRadius}
|
||||||
|
fill={processColor}
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill={barColor}
|
||||||
|
x={task.x1}
|
||||||
|
width={projectWith}
|
||||||
|
y={task.y}
|
||||||
|
height={task.height / 2}
|
||||||
|
rx={task.barCornerRadius}
|
||||||
|
ry={task.barCornerRadius}
|
||||||
|
className={styles.projectTop}
|
||||||
|
/>
|
||||||
|
<polygon
|
||||||
|
className={styles.projectTop}
|
||||||
|
points={projectLeftTriangle}
|
||||||
|
fill={barColor}
|
||||||
|
/>
|
||||||
|
<polygon
|
||||||
|
className={styles.projectTop}
|
||||||
|
points={projectRightTriangle}
|
||||||
|
fill={barColor}
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -3,6 +3,7 @@ import { BarTask } from "../../types/bar-task";
|
|||||||
import { GanttContentMoveAction } from "../../types/gantt-task-actions";
|
import { GanttContentMoveAction } from "../../types/gantt-task-actions";
|
||||||
import { Bar } from "./bar/bar";
|
import { Bar } from "./bar/bar";
|
||||||
import { Milestone } from "./milestone/milestone";
|
import { Milestone } from "./milestone/milestone";
|
||||||
|
import { Project } from "./project/project";
|
||||||
import style from "./task-list.module.css";
|
import style from "./task-list.module.css";
|
||||||
|
|
||||||
export type TaskItemProps = {
|
export type TaskItemProps = {
|
||||||
@ -40,6 +41,9 @@ export const TaskItem: React.FC<TaskItemProps> = props => {
|
|||||||
case "milestone":
|
case "milestone":
|
||||||
setTaskItem(<Milestone {...props} />);
|
setTaskItem(<Milestone {...props} />);
|
||||||
break;
|
break;
|
||||||
|
case "project":
|
||||||
|
setTaskItem(<Project {...props} />);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
setTaskItem(<Bar {...props} />);
|
setTaskItem(<Bar {...props} />);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ export enum ViewMode {
|
|||||||
Week = "Week",
|
Week = "Week",
|
||||||
Month = "Month",
|
Month = "Month",
|
||||||
}
|
}
|
||||||
export type TaskType = "task" | "milestone";
|
export type TaskType = "task" | "milestone" | "project";
|
||||||
export interface Task {
|
export interface Task {
|
||||||
id: string;
|
id: string;
|
||||||
type: TaskType;
|
type: TaskType;
|
||||||
@ -24,6 +24,7 @@ export interface Task {
|
|||||||
progressSelectedColor?: string;
|
progressSelectedColor?: string;
|
||||||
};
|
};
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
|
project?: string;
|
||||||
dependencies?: string[];
|
dependencies?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,9 +56,7 @@ export interface EventOption {
|
|||||||
/**
|
/**
|
||||||
* Invokes on delete selected task. Chart undoes operation if method return false or error.
|
* Invokes on delete selected task. Chart undoes operation if method return false or error.
|
||||||
*/
|
*/
|
||||||
onTaskDelete?: (
|
onDelete?: (task: Task) => void | boolean | Promise<void> | Promise<boolean>;
|
||||||
task: Task
|
|
||||||
) => void | boolean | Promise<void> | Promise<boolean>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DisplayOption {
|
export interface DisplayOption {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user