Our state of the art Gantt chart


Post by rtbennett »

Dear Bryntum:
I have a question about how the startDate and endDate fields work in React Gantt? From the data we provide the tasksData -- I would expect the Gantt to render the startDate and endDate based on the values that we supply for each individual milestone or task?

However, I'm experiencing all startDates begin on the same date -- you can see from the screenshot of Gantt display provided (highlighted in red - START DATE column)?

Can you please explain to me if my configuration for the tasksData object is not setup correctly? I have supplied for your reference the gantt configuration, and a screenshot of the data that we are feeding into the tasksData object. This is labeled as the "GANTT DATA".

I have highlighted in a red box the first milestone ("Uncle Leo"). You will see that the startDate for this milestone is given as "2022-11-29". But the startDate is rendering everything as "2022-11-28" (see screenshot of the rendered Gantt chart -- start date column is all set at 11/28/2022 -- for each milestone and task)? I'm confused why this would be the case -- and hope you can explain. Am I supplying the wrong data -- or not formatting correctly? Please advise? Please note that the "Due Date" column (endDate) is also not showing proper dates compared to data supplied? The duration values are different?

Below is the gantt configuration file. You will see for the tasksData object -- we are feeding it the ganttData object (as shown in screenshot). I'm wondering if I'm doing this wrong -- or if this is some type of bug or issue with how gantt is rendering the data?

Please note the ganttData is the object I show in the screenshot attachment for the data that we are feeding into the tasksData (as shown).

I would appreciate your help with this.
Thanks so much!

import React, { useEffect, useRef, useState } from 'react'
import '@bryntum/gantt/gantt.stockholm.css'

import { useGetGantt } from '~/views/hooks/Gantt/useGetGantt'

import { withRouter } from '~/views/hooks/useRouter'
import dynamic from 'next/dynamic'
import Loader from '~/views/components/ui/Loader'

const Gantt = dynamic(() => import('./components/Gantt/Gantt'), {
  ssr: false,
})

const PlanTimelineView = (milestone) => {
  const ganttRef = useRef()
  const [ganttData, setGanttData] = useState(null)
  const [delayed, setDelayed] = useState(true)

  const projectId = milestone.router.query.projectId
  const { data } = useGetGantt({
    projectId,
  })

  useEffect(() => {
    if (data) {
      setDelayed(false)
      setGanttData((ganttConfig.project.tasksData = data.ganttChartTimelines))
    }
  }, [data])

  const onSettingsRowHeightChange = ({ value }) => {
    ganttRef.current.instance.rowHeight = value
  }

  const onSettingsMarginChange = ({ value }) => {
    ganttRef.current.instance.barMargin = value
  }

  const ganttConfig = {
    project: {
      autoLoad: true,
      hoursPerDay: 24,
      daysPerWeek: 5,
      daysPerMonth: 20,
      validateResponse: true,

  tasksData: ganttData,
},
taskMenu: {
  items: {
    indent: false,
    outdent: false,
    convertToMilestone: false,
  },
},
tbar: {
  items: [
    {
      type: 'buttonGroup',
      items: [
        {
          ref: 'expandAllButton',
          icon: 'b-fa b-fa-angle-double-down',
          tooltip: 'Expand all',
          onAction: () => {
            ganttRef.current.instance.expandAll()
          },
        },
        {
          ref: 'collapseAllButton',
          icon: 'b-fa b-fa-angle-double-up',
          tooltip: 'Collapse all',
          onAction: () => {
            ganttRef.current.instance.collapseAll()
          },
        },
        {
          ref: 'zoomInButton',
          icon: 'b-fa b-fa-search-plus',
          tooltip: 'Zoom in',
          onAction: () => {
            ganttRef.current.instance.zoomIn()
          },
        },
        {
          ref: 'zoomOutButton',
          icon: 'b-fa b-fa-search-minus',
          tooltip: 'Zoom out',
          onAction: () => {
            ganttRef.current.instance.zoomOut()
          },
        },
        {
          ref: 'zoomToFitButton',
          icon: 'b-fa b-fa-compress-arrows-alt',
          tooltip: 'Zoom to fit',
          onAction: () => {
            ganttRef.current.instance.zoomToFit({
              leftMargin: 50,
              rightMargin: 50,
            })
          },
        },
        {
          ref: 'previousButton',
          icon: 'b-fa b-fa-angle-left',
          tooltip: 'Previous time span',
          onAction: () => {
            ganttRef.current.instance.shiftPrevious()
          },
        },
        {
          ref: 'nextButton',
          icon: 'b-fa b-fa-angle-right',
          tooltip: 'Next time span',
          onAction: () => {
            ganttRef.current.instance.shiftNext()
          },
        },
      ],
    },
    {
      type: 'buttonGroup',
      items: [
        {
          type: 'button',
          ref: 'settingsButton',
          icon: 'b-fa b-fa-cogs',
          text: 'Settings',
          tooltip: 'Adjust settings',
          toggleable: true,
          menu: {
            type: 'popup',
            anchor: true,
            cls: 'settings-menu',
            layoutStyle: {
              flexDirection: 'column',
            },
            onBeforeShow: 'up.onSettingsShow',

            items: [
              {
                type: 'slider',
                ref: 'rowHeight',
                text: 'Row height',
                width: '12em',
                showValue: true,
                min: 30,
                max: 70,
                onInput: (rowHeight) => {
                  onSettingsRowHeightChange(rowHeight)
                },
              },
              {
                type: 'slider',
                ref: 'barMargin',
                text: 'Bar margin',
                width: '12em',
                showValue: true,
                min: 0,
                max: 10,
                onInput: (barMargin) => {
                  onSettingsMarginChange(barMargin)
                },
              },
            ],
          },
        },
      ],
    },
    {
      type: 'button',
      color: 'b-blue',
      text: 'Export PDF/PNG',
      icon: 'b-fa-file-export',
      ref: 'exportButton',
      tooltip: 'Export PDF/PNG',
      onAction: () => {
        ganttRef.current?.instance.features.pdfExport.showExportDialog()
      },
    },
    {
      type: 'button',
      color: 'b-blue',
      text: 'Export as .xslx',
      ref: 'excelExportBtn',
      icon: 'b-fa-file-export',
      tooltip: 'Export Excel file',
      onAction: () => {
        const filename =
          ganttRef.current?.instance.project.taskStore.first &&
          ganttRef.current?.instance.project.taskStore.first.name
        ganttRef.current?.instance.excelExporterFeature.export({
          filename,
        })
      },
    },
    {
      type: 'button',
      color: 'b-red',
      ref: 'criticalPathsButton',
      icon: 'b-fa b-fa-fire',
      text: 'Critical paths',
      tooltip: 'Highlight critical paths',
      toggleable: true,
      onAction: () => {
        ganttRef.current.instance.features.criticalPaths.disabled =
          !ganttRef.current.instance.features.criticalPaths.disabled
      },
    },
  ],
},
columns: [
  { type: 'name', field: 'name', width: 230 },
  { type: 'date', field: 'startDate', text: 'Start Date', width: 50 },
  { type: 'date', field: 'endDate', text: 'Due Date', width: 50 },
  { type: 'duration', width: 70 },
  { type: 'effort', width: 70 },
],
viewPreset: {
  base: 'weekAndDay',
  displayDateFormat: 'YYYY-MM-DD',
},
barMargin: 10,
headerMenuFeature: true,
minHeight: 1000,
autoHeight: true,

excelExporterFeature: {
  dateFormat: 'YYYY-MM-DD HH:mm',
},

pdfExportFeature: {
  exportServer: 'http://localhost:3000',
  translateURLsToAbsolute: 'http://localhost:3000',
  clientURL: 'http://localhost:3000',
},
features: {
  filter: true,
  criticalPaths: {
    disabled: true,
  },
},
  }

  return !delayed ? (
    <>
      <Gantt ganttRef={ganttRef} {...ganttConfig} />
    </>
  ) : (
    <>
      <Loader />
    </>
  )
}
Attachments
Screen Shot 2022-12-19 at 5.04.16 PM.png
Screen Shot 2022-12-19 at 5.04.16 PM.png (303.71 KiB) Viewed 389 times
Screen Shot 2022-12-19 at 5.03.09 PM.png
Screen Shot 2022-12-19 at 5.03.09 PM.png (454.38 KiB) Viewed 389 times

Post by mats »

Tasks are scheduled "as soon as possible" by default, meaning if you don't provide constraints, dependencies, or mark tasks as manually scheduled, tasks are scheduled at the project start date, or their parent start date.

If you want all dates fixed at the dates in your data, please use https://bryntum.com/products/gantt/docs/api/Gantt/model/TaskModel#field-manuallyScheduled


Post by rtbennett »

You mention above tasks get scheduled based on their parent start date. I'm trying to make it so that all my data (milestones and tasks) -- are scheduled based on the constraint of the "actual" start date and end dates are given in my data. I'm struggling to "override" or get my data to display based on the actual start dates?

Can you please share with me an example (maybe code or explanation) of how to override the parent start date. As it seems everything I've done (even using the "manually scheduled" field) -- it only shows the parent start date (all dates are the same). Or in other words -- the start dates stay the same -- and takes the top level start date only -- as shown above in my screenshot above. Can you please share with me how to fix this -- or make it so I can show only the start dates given in the data? Thanks for any help with this. I want to only display it exactly as its show in the data -- but after trying multiple things -- it does not seems to work. So I wanted to ask for your help with this. Thanks so much! You seem to mention that Bryntum takes the project level as the top level -- how to override this? Thanks.


Post by tasnim »

Hello,

As Mats says above, if you want the task's date to be fixed, you need to use https://bryntum.com/products/gantt/docs/api/Gantt/model/TaskModel#field-manuallyScheduled

Here is an example of how you could set this field in the task data

{
    "id"                : 11,
    "name"              : "Install Apache",
    "percentDone"       : 50,
    "startDate"         : "2019-01-14",
    "rollup"            : true,
    "duration"          : 3,
    "color"             : "teal",
    "endDate"           : "2019-01-17",
    "cost"              : 200,
    "priority"          : "high",
    "manuallyScheduled" : true
}

Post by rtbennett »

Thank you very much! This solves my issue. I was adding the "manuallyScheduled" property in the "project" object -- not within my data directly -- and that was my confusion/problem. This helped me to understand how to do it now.

You can mark this post as completed. Thank you!


Post Reply