Our state of the art Gantt chart


Post by jhill@achieveit.com »

If there are two consecutive tasks that both depend on the previous task, the way dependencies are drawn makes it look like the 3rd task is dependent on the 2nd task. Is there any way to customize this? You can re-create this scenario with the below code. Screenshot also attached.

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

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,
  })

  const [columns] = useState([
    {
      type: 'name',
      field: 'name',
      id: 'name',
      autoHeight: true,
      width: 100,
      renderer: (args) => {
        return <div>{args.value}</div>;
      },
      sortable: false,
      leafIconCls: null,
      htmlEncode: false
    },
    {
      field: 'start',
      id: 'start',
      text: 'Start Date',
      type: 'date',
      width: 100,
      htmlEncode: false,
      renderer: ({ record, value }) => {
  
// const date = record.getData('start'); if (!value) { return ''; } return <DateDisplay date={value} />; } }, { field: 'due', id: 'due', text: 'Due Date', type: 'date', width: 100, htmlEncode: false, renderer: ({ record, value }) => { // const date = record.getData('start'); 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 style={{ height: '100%', flex: 1, border: '1px solid black' }}> <BryntumGantt ref={ganttRef} columns={columns} project={{ tasks: data, dependencies: [{ id: 2, fromEvent: 1, toEvent: 2 }, { id: 3, fromEvent: 1, toEvent: 3}] }} {...config} /> </div> ); } function App() { const [data] = useState([{ id: 1, name: 'task 1', start: new Date(2024, 0, 1), due: new Date(2024,1, 27)}, { id: 2, name: 'task 2', start: new Date(2024,1, 28), due: new Date(2024,2, 28)}, { id: 3, name: 'task 3', start: new Date(2024,1, 28), due: new Date(2024,2, 28)}]); return ( <div style={{ height: '100%', display: 'flex', padding: 10}}> <BryntumComponent data={data} /> </div> ); } export default App;
Attachments
Screenshot 2024-02-22 at 4.02.48 PM.png
Screenshot 2024-02-22 at 4.02.48 PM.png (143.28 KiB) Viewed 98 times

Post by ghulam.ghous »

Hi there,

I agree this confusing and visually not helping. But currently there is no config to handle this. I have created a ticket to by default handle this https://github.com/bryntum/support/issues/8669. You can subscribe to the ticket to keep track of updates.

Regards,
Ghous


Post Reply