Our state of the art Gantt chart


Post by bharat95 »

Hi,

I'm getting error for

const gantt = window.gantt;

and the error is 'Property 'gantt' does not exist on type 'Window & typeof globalThis'.'


Post by tasnim »

You could apply it in React with useEffect like this

    useEffect(() => {
        // Getting Gantt instance from Gantt ref
        const gantt = ganttRef.current.instance;
        // Adding a listener
        gantt.features.rowReorder.on('gridRowBeforeDropFinalize', ({ context }) => {
            // Getting the old parent
            const parent = gantt.project.taskStore.getById(context.oldPositionContext[0].parentId);
            if (parent.name.toLowerCase() === 'setup web server' && context.insertBefore.parent?.name.toLowerCase() === 'website design') {
                // Prevent droping the row
                context.valid = false;
            }
        })
    }, []);

Post by bharat95 »

Hi,

Can you please let me know where I can add useEffect(), below is my code

import { GanttConfig, TaskMenu } from '@bryntum/gantt';
import GanttCustomTasks from './GanttCustomTasks';
import { format } from 'date-fns';

const ganttConfig: Partial<GanttConfig> = {
  project: {
    taskModelClass: GanttCustomTasks,
    autoLoad: true,
    autoSync: true,
    transport: {
      load: {
        url: '/Layout/ProjectTimeView/GetGanttData',
        method: 'POST',
        params: {
          projectId: null,
        },
      },
      sync: {
        url: '/Layout/ProjectTimeView/UpdateGanttData',
        method: 'POST',
        params: {
          projectId: null,
        },
      },
    },
    // This config enables response validation and dumping of found errors to the browser console.
    // It's meant to be used as a development stage helper only so please set it to false for production systems.
    validateResponse: true,
    listeners: {
      beforeSend: ({ params }: { params: { projectId: string } }) => {
        const queryString = new URLSearchParams(window.location.search.toLowerCase());
        params.projectId = queryString.get('projectid') || '';
      },
    },
  },
  listeners: {
    startCellEdit: ({ editorContext }: { editorContext: any }) => {
      const { record, editor, column } = editorContext;
      if (column.field === 'owner') {
        editor.inputField.items = record.ownerItems;
      }
      if (column.field === 'status') {
        editor.inputField.items = record.statusItems;
      }
      editor.inputField.pickerWidth = 220;
    },
  },
  features: {
    taskMenu: {
      processItems({ taskRecord }: { taskRecord: any }) {
        if (taskRecord.typeid != 1) {
          return false;
        }
      },
      items: {
        cut: false,
        copy: false,
        convertToMilestone: false,
        indent: false,
        outdent: false,
        add: {
          menu: {
            milestone: false,
            addTaskAbove: {
              text: 'Deliverable above',
            },
            addTaskBelow: {
              text: 'Deliverable below',
            },
            subtask: {
              text: 'Activity',
            },
          },
        },
      },
    },
    indicators: {
      disabled: false,
    },
    dependencies: true,
    dependencyEdit: {
      editorConfig: {
        items: {
          // Custom label for the type field
          typeField: {
            label: 'Type',
          },
          lagField: {
            hidden: true,
          },
          activeField: {
            hidden: true,
          },
        },

    bbar: {
      items: {
        // Hiding save button
        saveButton: {
          hidden: false,
        },
      },
    },
  },
},
  },
  columns: [
    {
      text: 'Name',
      type: 'name',
      width: 250,
      collapseIconCls: 'ic-gantt-collapse',
      expandIconCls: 'ic-gantt-expand',
    },
    { text: 'Function', field: 'function', width: 85 },
    {
      text: 'Owner',
      field: 'owner',
      width: 85,
      editor: {
        type: 'combo',
      },
    },
    {
      text: 'Status',
      field: 'status',
      width: 100,
      editor: {
        type: 'combo',
      },
    },
    {
      text: 'Start',
      type: 'startdate',
      width: 80,
      renderer: ({ record }: { record: any }) => {
        if (record.startDate) return format(new Date(record.startDate), record.dateFormat);
        return null;
      },
    },
    {
      text: 'Finish',
      type: 'enddate',
      width: 80,
      renderer: ({ record }: { record: any }) => {
        if (record.endDate) return format(new Date(record.endDate), record.dateFormat);
        return null;
      },
    },
    {
      text: 'Deadline',
      field: 'deadlineDate',
      type: 'date',
      width: 80,
      renderer: ({ cellElement, record }: { cellElement: HTMLElement; record: any }) => {
        if (record.deadlineDate) {
          if (Date.parse(record.endDate) >= Date.parse(record.deadlineDate) && record.status !== 'Completed') {
            cellElement.classList.add('error');
          }
          return format(new Date(record.deadlineDate), record.dateFormat);
        }
        return null;
      },
    },
    { text: 'Duration', type: 'duration', width: 72 },
  ],
};

export { ganttConfig };

Post by tasnim »

Inside of your App component

/**
 * Application
 */
import React, { Fragment, useEffect, useRef } from 'react';

import { BryntumDemoHeader, BryntumThemeCombo, BryntumGantt } from '@bryntum/gantt-react';
import { ganttConfig } from './AppConfig';
import './App.scss';

const App = () => {
    const ganttRef = useRef(null);
    // edit button click handler
    const handleEditClick = ({ record, grid : gantt }) => {
        gantt.editTask(record);
    };

useEffect(() => {
    // Getting Gantt instance from Gantt ref
    const gantt = ganttRef.current.instance;
    // Adding a listener
    gantt.features.rowReorder.on('gridRowBeforeDropFinalize', ({ context }) => {
        // Getting the old parent
        const parent = gantt.project.taskStore.getById(context.oldPositionContext[0].parentId);
        if (parent.name.toLowerCase() === 'setup web server' && context.insertBefore.parent?.name.toLowerCase() === 'website design') {
            // Prevent droping the row
            context.valid = false;
        }
    })
}, []);

return (
    <Fragment>
        {/* BryntumDemoHeader component is used for Bryntum example styling only and can be removed */}
        <BryntumDemoHeader
            children={<BryntumThemeCombo />}
        />
        <BryntumGantt
            {...ganttConfig}
            ref={ganttRef}
            extraData={{ handleEditClick }}
        />
    </Fragment>
);
};

export default App;

Post by bharat95 »

Hi,

I'm getting error ' Property 'project' does not exist on type 'RefObject<BryntumGantt>'.' for code

      const parent = gantt.project.taskStore.getById(context.oldPositionContext[0].parentId);

Post by tasnim »

Hi,

Use it like this.
This should not give you any troubles

/**
 * Main Application script
 */
import React, { Fragment, FunctionComponent, useEffect, useRef } from 'react';

import { BryntumDemoHeader, BryntumThemeCombo, BryntumGantt, BryntumGanttBase, BryntumGanttBaseProps } from '@bryntum/gantt-react';
import { ganttConfig } from './AppConfig';
import './App.scss';

const App: FunctionComponent = () => {
    const ganttRef = useRef<any>(null);

useEffect(() => {
    // Getting Gantt instance from Gantt ref
    const gantt = ganttRef.current.instance;
    // Adding a listener
    gantt.features.rowReorder.on('gridRowBeforeDropFinalize', ({ context } : any) => {
        // Getting the old parent
        const parent = gantt.project.taskStore.getById(context.oldPositionContext[0].parentId);
        if (parent.name.toLowerCase() === 'setup web server' && context.insertBefore.parent?.name.toLowerCase() === 'website design') {
            // Prevent droping the row
            context.valid = false;
        }
    })
}, []);
return (
    <Fragment>
        {/* BryntumDemoHeader component is used for Bryntum example styling only and can be removed */}
        <BryntumDemoHeader
            children = {<BryntumThemeCombo />}
        />
        <BryntumGantt ref={ganttRef} {...ganttConfig} />
    </Fragment>
);
};

export default App;


Post by bharat95 »

Hi,

I'm getting error ' Property 'project' does not exist on type 'RefObject<BryntumGantt>'.' I have made bold for line where I'm getting error.

useEffect(() => {
    // Getting Gantt instance from Gantt ref
    const gantt = ganttRef.current.instance;
    // Adding a listener
    gantt.features.rowReorder.on('gridRowBeforeDropFinalize', ({ context } : any) => {
        // Getting the old parent
       [b] const parent = gantt.project.taskStore.getById(context.oldPositionContext[0].parentId);[/b]
        if (parent.name.toLowerCase() === 'setup web server' && context.insertBefore.parent?.name.toLowerCase() === 'website design') {
            // Prevent droping the row
            context.valid = false;
        }
    })
}, []);

Post by tasnim »

Can you please upload a runnable test case so we can check what's wrong?


Post by bharat95 »

Hi,

I was able to fix the issue. Thank you for your help.


Post Reply