gantt-task-react/src/helpers/bar-helper.ts
2020-08-11 01:16:53 +03:00

305 lines
7.3 KiB
TypeScript

import { Task } from "../types/public-types";
import { BarTask } from "../types/bar-task";
export const convertToBarTasks = (
tasks: Task[],
dates: Date[],
columnWidth: number,
rowHeight: number,
barFill: number,
headerHeight: number,
barCornerRadius: number,
handleWidth: number,
barProgressColor: string,
barProgressSelectedColor: string,
barBackgroundColor: string,
barBackgroundSelectedColor: string
) => {
const dateDelta =
dates[1].getTime() -
dates[0].getTime() -
dates[1].getTimezoneOffset() * 60 * 1000 +
dates[0].getTimezoneOffset() * 60 * 1000;
const taskHeight = (rowHeight * barFill) / 100;
let barTasks = tasks.map((t, i) => {
return convertToBarTask(
t,
i,
dates,
dateDelta,
columnWidth,
rowHeight,
taskHeight,
headerHeight,
barCornerRadius,
handleWidth,
barProgressColor,
barProgressSelectedColor,
barBackgroundColor,
barBackgroundSelectedColor
);
});
// set dependencies
barTasks = barTasks.map((task, i) => {
const dependencies = task.dependencies || [];
for (let j = 0; j < dependencies.length; j++) {
const dependence = barTasks.findIndex(
value => value.id === dependencies[j]
);
if (dependence !== -1) barTasks[dependence].barChildren.push(i);
}
return task;
});
return barTasks;
};
export const convertToBarTask = (
task: Task,
index: number,
dates: Date[],
dateDelta: number,
columnWidth: number,
rowHeight: number,
taskHeight: number,
headerHeight: number,
barCornerRadius: number,
handleWidth: number,
barProgressColor: string,
barProgressSelectedColor: string,
barBackgroundColor: string,
barBackgroundSelectedColor: string
): BarTask => {
const x1 = taskXCoordinate(task.start, dates, dateDelta, columnWidth);
const x2 = taskXCoordinate(task.end, dates, dateDelta, columnWidth);
const y = taskYCoordinate(index, rowHeight, taskHeight, headerHeight);
const styles = {
backgroundColor: barBackgroundColor,
backgroundSelectedColor: barBackgroundSelectedColor,
progressColor: barProgressColor,
progressSelectedColor: barProgressSelectedColor,
...task.styles,
};
return {
...task,
x1,
x2,
y,
index,
barCornerRadius,
handleWidth,
height: taskHeight,
barChildren: [],
styles,
};
};
export const taskXCoordinate = (
xDate: Date,
dates: Date[],
dateDelta: number,
columnWidth: number
) => {
const index = ~~(
(xDate.getTime() -
dates[0].getTime() +
xDate.getTimezoneOffset() -
dates[0].getTimezoneOffset()) /
dateDelta
);
const x = Math.round(
(index +
(xDate.getTime() -
dates[index].getTime() -
xDate.getTimezoneOffset() * 60 * 1000 +
dates[index].getTimezoneOffset() * 60 * 1000) /
dateDelta) *
columnWidth
);
return x;
};
export const taskYCoordinate = (
index: number,
rowHeight: number,
taskHeight: number,
headerHeight: number
) => {
const y = index * rowHeight + headerHeight + (rowHeight - taskHeight) / 2;
return y;
};
export const progressWithByParams = (
taskX1: number,
taskX2: number,
progress: number
) => {
return (taskX2 - taskX1) * progress * 0.01;
};
export const progressByProgressWidth = (
progressWidth: number,
barTask: BarTask
) => {
const barWidth = barTask.x2 - barTask.x1;
const progressPercent = Math.round((progressWidth * 100) / barWidth);
if (progressPercent >= 100) return 100;
else if (progressPercent <= 0) return 0;
else {
return progressPercent;
}
};
export const progressByX = (x: number, task: BarTask) => {
if (x >= task.x2) return 100;
else if (x <= task.x1) return 0;
else {
const barWidth = task.x2 - task.x1;
const progressPercent = Math.round(((x - task.x1) * 100) / barWidth);
return progressPercent;
}
};
export const getProgressPoint = (
progressX: number,
taskY: number,
taskHeight: number
) => {
const point = [
progressX - 5,
taskY + taskHeight,
progressX + 5,
taskY + taskHeight,
progressX,
taskY + taskHeight - 8.66,
];
return point.join(",");
};
export const startByX = (x: number, xStep: number, task: BarTask) => {
if (x >= task.x2 - task.handleWidth * 2) {
x = task.x2 - task.handleWidth * 2;
}
const steps = Math.round((x - task.x1) / xStep);
const additionalXValue = steps * xStep;
const newX = task.x1 + additionalXValue;
return newX;
};
export const endByX = (x: number, xStep: number, task: BarTask) => {
if (x <= task.x1 + task.handleWidth * 2) {
x = task.x1 + task.handleWidth * 2;
}
const steps = Math.round((x - task.x2) / xStep);
const additionalXValue = steps * xStep;
const newX = task.x2 + additionalXValue;
return newX;
};
export const moveByX = (x: number, xStep: number, task: BarTask) => {
const steps = Math.round((x - task.x1) / xStep);
const additionalXValue = steps * xStep;
const newX1 = task.x1 + additionalXValue;
const newX2 = newX1 + task.x2 - task.x1;
return [newX1, newX2];
};
export const dateByX = (
x: number,
taskX: number,
taskDate: Date,
xStep: number,
timeStep: number
) => {
let newDate = new Date(((x - taskX) / xStep) * timeStep + taskDate.getTime());
newDate = new Date(
newDate.getTime() +
(newDate.getTimezoneOffset() - taskDate.getTimezoneOffset()) * 60000
);
return newDate;
};
export type BarMoveAction = "progress" | "end" | "start" | "move" | "";
/**
* Method handles event in real time(mousemove) and on finish(mouseup)
*/
export const handleTaskBySVGMouseEvent = (
svgX: number,
action: BarMoveAction,
selectedTask: BarTask,
xStep: number,
timeStep: number,
initEventX1Delta: number
) => {
const changedTask: BarTask = { ...selectedTask };
let isChanged = false;
switch (action) {
case "progress":
changedTask.progress = progressByX(svgX, selectedTask);
isChanged = changedTask.progress !== selectedTask.progress;
break;
case "start": {
const newX1 = startByX(svgX, xStep, selectedTask);
changedTask.x1 = newX1;
isChanged = changedTask.x1 !== selectedTask.x1;
if (isChanged) {
changedTask.start = dateByX(
newX1,
selectedTask.x1,
selectedTask.start,
xStep,
timeStep
);
}
break;
}
case "end": {
const newX2 = endByX(svgX, xStep, selectedTask);
changedTask.x2 = newX2;
isChanged = changedTask.x2 !== selectedTask.x2;
if (isChanged) {
changedTask.end = dateByX(
newX2,
selectedTask.x2,
selectedTask.end,
xStep,
timeStep
);
}
break;
}
case "move": {
const [newMoveX1, newMoveX2] = moveByX(
svgX - initEventX1Delta,
xStep,
selectedTask
);
isChanged = newMoveX1 !== selectedTask.x1;
if (isChanged) {
changedTask.start = dateByX(
newMoveX1,
selectedTask.x1,
selectedTask.start,
xStep,
timeStep
);
changedTask.end = dateByX(
newMoveX2,
selectedTask.x2,
selectedTask.end,
xStep,
timeStep
);
changedTask.x1 = newMoveX1;
changedTask.x2 = newMoveX2;
}
break;
}
}
return { isChanged, changedTask };
};