Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Box, Chip, Typography } from '@mui/material';
import { useTheme } from '@mui/system';
import { CSSProperties, DragEvent, MouseEvent, useEffect, useState } from 'react';
import { CSSProperties, DragEvent, MouseEvent, useCallback, useEffect, useRef, useState } from 'react';
import useMeasure from 'react-use-measure';
import { addDaysToDate } from 'shared';
import { GanttChange, GanttTask, GANTT_CHART_CELL_SIZE } from '../../../../../utils/gantt.utils';
Expand Down Expand Up @@ -33,18 +33,20 @@ export const GanttTaskBarEditView = <T,>({
onAddTaskPressed
}: GanttTaskBarEditProps<T>) => {
const theme = useTheme();
const [startX, setStartX] = useState<number | null>(null);
const [showDropPoints, setShowDropPoints] = useState(false);
const [isResizing, setIsResizing] = useState(false);
const [width, setWidth] = useState(0); // current width of component, will change on resize
const [width, setWidth] = useState(0);
const [correctWidth, setCorrectWidth] = useState(0);
const [measureRef, bounds] = useMeasure();
const hasMeasuredRef = useRef(false);
const boxRef = useRef<HTMLDivElement | null>(null);
const widthPerDay = 7.2; //width per day to use for resizing calculations, kind of arbitrary,

const taskBarDisplayStyles: CSSProperties = {
gridColumnStart: getStartCol(task.start),
gridColumnEnd: getEndCol(task.end),
height: '2rem',
width: task.root ? 'unset' : width === 0 ? `unset` : `${width}px`,
width: task.root ? 'unset' : correctWidth > 0 ? `${correctWidth}px` : 'auto',
border: `1px solid ${isResizing ? theme.palette.text.primary : theme.palette.divider}`,
borderRadius: '0.25rem',
backgroundColor: task.styles ? task.styles.backgroundColor : theme.palette.background.paper,
Expand All @@ -67,48 +69,54 @@ export const GanttTaskBarEditView = <T,>({
right: '-10'
};

const getCorrectWidth = useCallback((rawWidth: number) => {
const newEventLengthInDays = roundToMultipleOf7(rawWidth / widthPerDay);
const displayWeeks = newEventLengthInDays / 7 + 1;
return displayWeeks * 40 + (displayWeeks - 1) * 10;
}, []);

useEffect(() => {
if (bounds.width !== 0 && width === 0) {
if (!hasMeasuredRef.current && bounds.width > 0) {
setWidth(bounds.width);
setCorrectWidth(getCorrectWidth(bounds.width));
hasMeasuredRef.current = true;
}
}, [bounds, width]);
}, [bounds.width, getCorrectWidth]);

// used to make sure that any changes to the start and end dates are made in multiples of 7
const roundToMultipleOf7 = (num: number) => {
return Math.round(num / 7) * 7;
return Math.ceil(num / 7) * 7;
};

const getDistanceFromLeft = (clientX: number) => {
const rect = boxRef.current!.getBoundingClientRect();
return clientX - rect.left;
};

const handleMouseDown = (e: MouseEvent<HTMLElement>) => {
setIsResizing(true);
setStartX(e.clientX);
boxRef.current = (e.currentTarget as HTMLElement).closest('[data-gantt-bar]') as HTMLDivElement;
};

const handleMouseMove = (e: MouseEvent<HTMLElement>) => {
if (isResizing) {
const currentX = e.clientX;
const deltaX = currentX - startX!;
setWidth(Math.max(100, width + deltaX));
setStartX(currentX);
}
if (!isResizing) return;

const newWidth = Math.max(100, getDistanceFromLeft(e.clientX));

setWidth(newWidth); // sync render
setCorrectWidth(getCorrectWidth(newWidth));
};

const handleMouseUp = () => {
if (isResizing) {
setIsResizing(false);
// Use change in width to calculate new length
const newEventLengthInDays = roundToMultipleOf7(width / widthPerDay);
// The gantt chart tasks are inclusive (their width includes the full width of their start and end date)
const displayWeeks = newEventLengthInDays / 7 + 1;
// We need these magic pixel numbers to dynamically calculate the correct width of the task to keep it in sync with the stored end date
const correctWidth = displayWeeks * 38 + (displayWeeks - 1) * 10;
const newEndDate = addDaysToDate(task.start, newEventLengthInDays);
setWidth(correctWidth);
createChange({
id: uuidv4(),
element: task.element,
type: 'change-end-date',
originalEnd: task.end,
newEnd: newEndDate
newEnd: addDaysToDate(task.start, newEventLengthInDays)
});
}
};
Expand Down Expand Up @@ -156,7 +164,7 @@ export const GanttTaskBarEditView = <T,>({
};
})}
>
<div ref={measureRef} style={taskBarDisplayStyles}>
<div data-gantt-bar ref={measureRef} style={taskBarDisplayStyles}>
<Box sx={webKitBoxContainerStyles()}>
<Box draggable={!task.root} onDrag={onDragStart} onDragEnd={onDragEnd} sx={webKitBoxStyles()}>
<Box sx={{ display: 'flex', flexDirection: 'row' }}>
Expand Down