project type init

This commit is contained in:
VikariiCGI 2021-03-27 21:05:38 +02:00
parent 507e8a4d69
commit 02c9c58091
10 changed files with 158 additions and 20 deletions

View File

@ -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. |
| 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. |
| 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. |
@ -131,6 +131,7 @@ npm start
| | | - **progressSelectedColor**: String. Specifies the taskbar progress fill color globally on select. |
| isDisabled | bool | Disables all action for current task. |
| fontSize | string | Specifies the taskbar font size locally. |
| project | string | Task project name |
\*Required

View File

@ -1,7 +1,7 @@
import React from "react";
import { Task, ViewMode, Gantt } from "gantt-task-react";
import { ViewSwitcher } from "./components/view-switcher";
import { initTasks } from "./helper";
import { getStartEndDateForProject, initTasks } from "./helper";
import "gantt-task-react/dist/index.css";
//Init
@ -18,7 +18,20 @@ const App = () => {
const onTaskChange = (task: Task) => {
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);
};
@ -55,20 +68,22 @@ const App = () => {
tasks={tasks}
viewMode={view}
onDateChange={onTaskChange}
onTaskDelete={onTaskDelete}
onDelete={onTaskDelete}
onProgressChange={onProgressChange}
onDoubleClick={onDblClick}
onSelect={onSelect}
listCellWidth={isChecked ? "155px" : ""}
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>
<Gantt
tasks={tasks}
viewMode={view}
onDateChange={onTaskChange}
onTaskDelete={onTaskDelete}
onDelete={onTaskDelete}
onProgressChange={onProgressChange}
onDoubleClick={onDblClick}
onSelect={onSelect}

View File

@ -3,6 +3,14 @@ import { Task } from "../../dist/types/public-types";
export function initTasks() {
const currentDate = new Date();
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),
end: new Date(
@ -16,6 +24,7 @@ export function initTasks() {
id: "Task 0",
progress: 45,
type: "task",
project: "ProjectSample",
},
{
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 2),
@ -25,6 +34,7 @@ export function initTasks() {
progress: 25,
dependencies: ["Task 0"],
type: "task",
project: "ProjectSample",
},
{
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 4),
@ -34,6 +44,7 @@ export function initTasks() {
progress: 10,
dependencies: ["Task 1"],
type: "task",
project: "ProjectSample",
},
{
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 8),
@ -43,6 +54,7 @@ export function initTasks() {
progress: 2,
dependencies: ["Task 2"],
type: "task",
project: "ProjectSample",
},
{
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 8),
@ -52,20 +64,21 @@ export function initTasks() {
type: "task",
progress: 70,
dependencies: ["Task 2"],
project: "ProjectSample",
},
{
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",
id: "Task 6",
progress: currentDate.getMonth(),
type: "milestone",
dependencies: ["Task 4"],
styles: { progressColor: "#ffbb54", progressSelectedColor: "#ff9e0d" },
project: "ProjectSample",
},
{
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 24),
end: new Date(currentDate.getFullYear(), currentDate.getMonth(), 25),
start: new Date(currentDate.getFullYear(), currentDate.getMonth(), 18),
end: new Date(currentDate.getFullYear(), currentDate.getMonth(), 19),
name: "Party Time",
id: "Task 9",
progress: 0,
@ -75,3 +88,20 @@ export function initTasks() {
];
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];
}

View File

@ -1,6 +1,6 @@
{
"name": "gantt-task-react",
"version": "0.2.2",
"version": "0.3.0",
"description": "Interactive Gantt Chart for React with TypeScript.",
"author": "MaTeMaTuK <maksym.vikarii@gmail.com>",
"homepage": "https://github.com/MaTeMaTuK/gantt-task-react",

View File

@ -46,7 +46,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
onDateChange,
onProgressChange,
onDoubleClick,
onTaskDelete,
onDelete,
onSelect,
}) => {
const wrapperRef = useRef<HTMLDivElement>(null);
@ -300,7 +300,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
onDateChange,
onProgressChange,
onDoubleClick,
onTaskDelete,
onDelete,
TooltipContent,
};

View File

@ -61,7 +61,7 @@ export const TaskGanttContent: React.FC<TaskGanttContentProps> = ({
onDateChange,
onProgressChange,
onDoubleClick,
onTaskDelete,
onDelete,
TooltipContent,
}) => {
const point = svg?.current?.createSVGPoint();
@ -204,9 +204,9 @@ export const TaskGanttContent: React.FC<TaskGanttContentProps> = ({
// Keyboard events
else if (isKeyboardEvent(event)) {
if (action === "delete") {
if (onTaskDelete) {
if (onDelete) {
try {
const result = await onTaskDelete(task);
const result = await onDelete(task);
if (result !== undefined && result) {
setGanttEvent({ action, changedTask: task });
}

View File

@ -0,0 +1,13 @@
.projectWrapper {
cursor: pointer;
outline: none;
}
.projectBackground {
user-select: none;
opacity: 0.5;
}
.projectTop {
user-select: none;
}

View 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>
);
};

View File

@ -3,6 +3,7 @@ import { BarTask } from "../../types/bar-task";
import { GanttContentMoveAction } from "../../types/gantt-task-actions";
import { Bar } from "./bar/bar";
import { Milestone } from "./milestone/milestone";
import { Project } from "./project/project";
import style from "./task-list.module.css";
export type TaskItemProps = {
@ -40,6 +41,9 @@ export const TaskItem: React.FC<TaskItemProps> = props => {
case "milestone":
setTaskItem(<Milestone {...props} />);
break;
case "project":
setTaskItem(<Project {...props} />);
break;
default:
setTaskItem(<Bar {...props} />);
break;

View File

@ -6,7 +6,7 @@ export enum ViewMode {
Week = "Week",
Month = "Month",
}
export type TaskType = "task" | "milestone";
export type TaskType = "task" | "milestone" | "project";
export interface Task {
id: string;
type: TaskType;
@ -24,6 +24,7 @@ export interface Task {
progressSelectedColor?: string;
};
isDisabled?: boolean;
project?: string;
dependencies?: string[];
}
@ -55,9 +56,7 @@ export interface EventOption {
/**
* Invokes on delete selected task. Chart undoes operation if method return false or error.
*/
onTaskDelete?: (
task: Task
) => void | boolean | Promise<void> | Promise<boolean>;
onDelete?: (task: Task) => void | boolean | Promise<void> | Promise<boolean>;
}
export interface DisplayOption {