Our state of the art Gantt chart


Post by jhill@achieveit.com »

My tasks are manually scheduled and when the start date changes, the task "bar" is shifting the entire task even though end date does not change. It seems like it's trying to maintain the original timespan between the task. Is there any way to prevent this? If you run the code below and click "adjust start date" you can see what I mean.

import './App.css';
import { useState, useRef, useMemo, useEffect } from 'react';
import '@bryntum/gantt/gantt.stockholm.css';
import { BryntumGantt } from '@bryntum/gantt-react';
import styles from './myModule.module.scss';

const DateDisplay = ({ date }) => {
  return <span>{date.toDateString()}</span>
}

function BryntumComponent({ data }) {
  const ganttRef = useRef(null);
  const tasksRef = useRef();

  const tasks = useMemo(() => {
    return data.map((task) => {
      return {
        ...task,
        startDate: task.start,
        endDate: task.due,
        manuallyScheduled: true
      };
    });
  }, [data]);

  const [config] = useState({
    viewPreset: {
      timeResolution: { unit: 'day', increment: 1 },
      headers: [
        { unit: 'year', dateFormat: 'YYYY' },
        {
          unit: 'quarter',
          dateFormat: 'Q',
          renderer: (date, __, { value }) => {
            return `Q${value} ${date.getFullYear()}`;
          }
        },
        {
          unit: 'month',
          dateFormat: 'MMM'
        }
      ]
    },
    subGridConfigs: { locked: { width: '40%' } },
    autoAdjustTimeAxis: false,
    fixedRowHeight: false,
    cellEditFeature: false,
    cellMenuFeature: false,
    columnReorderFeature: false,
    taskMenuFeature: false,
    taskEditFeature: false,
    rowReorderFeature: false,
    columnLines: false,
    projectLinesFeature: false,
    headerMenuFeature: false,
    zoomOnTimeAxisDoubleClick: false,
    zoomOnMouseWheel: false,
    dependenciesFeature: { allowCreate: false },
    sortFeature: false,
    startDate: new Date(2023, 0, 1),
    endDate: new Date(2025, 11, 30),
  })

  const [columns] = useState([
    {
      type: 'name',
      field: 'name',
      id: 'name',
      autoHeight: true,
      width: 100,
      renderer: (args) => {
        return [{ text: args.value, class: styles.nameCell }];
      },
      sortable: false,
      leafIconCls: null,
    },
    {
      field: 'start',
      id: 'start',
      text: 'Start Date',
      type: 'date',
      width: 100,
      renderer: ({ record, value }) => {
  
if (!value) { return ''; } return <DateDisplay date={value} />; } }, { field: 'due', id: 'due', text: 'Due Date', type: 'date', width: 100, renderer: ({ record, value }) => { if (!value) { return ''; } return <DateDisplay date={value} />; } }, ]); useEffect(() => { if (ganttRef.current && tasksRef.current !== tasks) { ganttRef.current.instance.taskStore.data = tasks; tasksRef.current = tasks; } }, [tasks]); return ( <div> <BryntumGantt ref={ganttRef} columns={columns} {...config} /> </div> ); } function App() { const [data, setData] = useState([]); useEffect(() => { const load = async () => { await new Promise(resolve => setTimeout(resolve, 1000)); setData([{ id: 1, name: 'task 1', start: new Date(2024, 0, 1), due: new Date(2024,6, 30)}]); } load(); }, []); return ( <div style={{ height: '100%', display: 'flex', flexDirection: 'column', padding: 10}}> <BryntumComponent data={data} /> <button onClick={(e) => setData(prev => [{ ...prev[0], start: new Date(2023, 6, 1)}])} style={{ width: 200 }}>Adjust start date</button> </div> ); } export default App;

Post by Animal »

Setting the start date moves the event.

You can use this method to change the event duration by changing the start date: https://bryntum.com/products/scheduler/docs/api/Scheduler/model/TimeSpan#function-setStartDate


Post by jhill@achieveit.com »

There's no way to have the resize behavior by default? Wouldn't that mean you have to manually diff the tasks on every change and call setStartDate on every changed record? That seems wildly inefficient.


Post by jhill@achieveit.com »

Manually setting duration give me the desired resize behavior.

const tasks = [{ ...otherStuff, duration: differenceInDays(startDate, endDate) }] // comes from date-fns library.

Post by alex.l »

Hi,

No, by default when you change startDate, it changes startDate only and keeps duration. When you change endDate, it changes duration of the task and keeps task on the place. To change as you requested you can use flag for setStartDate, or change duration/endDate.

All the best,
Alex


Post by Animal »

jhill@achieveit.com wrote: Wed Feb 28, 2024 5:41 pm

There's no way to have the resize behavior by default? Wouldn't that mean you have to manually diff the tasks on every change and call setStartDate on every changed record? That seems wildly inefficient.

No, you don’t have to do that. You just use the linked method.


Post Reply