Premium support for our pure JavaScript UI components


Post by jit@flowit.dk »

Hi,

Please fetch sample code from: https://github.com/Jemt/Bryntum-gantt-samples/tree/2024-10-01-incorrect-duration

Clone the repository.
Switch to the branch: 2024-10-01-incorrect-duration
Configure access to the Bryntum NPM registry if necessary.
Run npm install && npm run dev

We can't figure out why Duration is being incorrectly calculated for the "Plan" node.

Screenshot 2024-10-01 at 13.46.28.png
Screenshot 2024-10-01 at 13.46.28.png (326.37 KiB) Viewed 160 times

It has to do with the use of calendars and hoursPerDay:

Screenshot 2024-10-01 at 13.39.11.png
Screenshot 2024-10-01 at 13.39.11.png (308.3 KiB) Viewed 160 times

Are we doing anything wrong ?

-- Thanks in advance

Best regards
Jimmy Thomsen


Post by alex.l »

Hi,

Your task is manuallyScheduled. By default, it will ignore non working time in duration, so when you set hoursPerDay 8 hours, but ignore active calendar, 1 day becomes 3 days (8+8+8), that's why you see 550.

To change that, add into project's config skipNonWorkingTimeInDurationWhenSchedulingManually: true
Docs: https://bryntum.com/products/gantt/docs/api/Gantt/model/ProjectModel#field-skipNonWorkingTimeInDurationWhenSchedulingManually

When true the project's manually scheduled tasks duration will include only working periods of time. When false such tasks will ignore working time calendars and treat all intervals as working.

IMPORTANT: Setting this to false also forcefully sets the skipNonWorkingTimeWhenSchedulingManually option to false.

All the best,
Alex


Post by jit@flowit.dk »

Hi @alex.l

It makes no difference when I set skipNonWorkingTimeInDurationWhenSchedulingManually to true.
Please update the branch previously mentioned where I have applied both skipNonWorkingTimeInDurationWhenSchedulingManually:true and skipNonWorkingTimeWhenSchedulingManually:true. Commit: https://github.com/Jemt/Bryntum-gantt-samples/commit/2090617bf900c1aca622e28bbdc7601f29701bee

Duration is still wrong. What else are we missing ?

Screenshot 2024-10-04 at 09.37.36.png
Screenshot 2024-10-04 at 09.37.36.png (204.41 KiB) Viewed 93 times

Best regards
Jimmy Thomsen


Post by arcady »

Hello,

You have not provided any calendars to the Gantt. In this case it by default treats all time periods as working.
So you can try running in your browser console:

task = gantt.ganttInstance.tasks[0]
// since we have no weekends due to the reason I've mentioned above
// we can simply use "endDate - startDate" which gives us duration in ms
// then to convert "ms" into "days" we divide by "8 hours"
// since this is what you set as "hoursPerDay"
console.log((task.endDate - task.startDate) / (8*3600000))
// result: 550.125

Best regards,
Arcady


Post by arcady »

P.S. Ah wait a second actually it looks that you add a calendar dynamically.


Post by arcady »

Hello,

Here is the investigation result.
As I wrote above you do not provide any calendars.
The reason is how your code does that:

            <BryntumGantt key={isTrue + ""} {...getGanttConfig()} ref={(ref) => {

                // Calendar information is loaded async - simulate this
                // behaviour by applying calendar once gantt is created.

                (window as any).gantt = ref;
                if (ref?.instance) {
                  addCalendar(ref.instance)
                }
            }} />

The addCalendar call happens too early when the component is not yet fully initialized.
You can check that by simply wrapping it with a setTimeout call.

But I'd recommend going with the pattern that we use in our demos:

    const ganttRef = useRef();

    useEffect(() => {
      if (ganttRef.current?.instance) {
        addCalendar(ganttRef.current.instance)
      }
    }, []);

    return (
        <BryntumGantt {...getGanttConfig()} ref={ganttRef} />
    );

After doing that the duration will get the result you expect.

Best regards,
Arcady


Post by jit@flowit.dk »

Thanks a lot, @Arcady - it works in our demo app.

We still have projects showing 1825 days, but it's probably because they span more than 5 years, so we need to set https://bryntum.com/products/gantt/docs/api/Gantt/model/ProjectModel#config-maxCalendarRange to e.g. 10 years.

We now find ourself in a pickle. We don't use the ProjectModel in our production app (which runs on Gantt v. 5.6.10) since it was too buggy when we started developing our Gantt implementation, so we use inline data instead. How can we change maxCalendarRange, skipNonWorkingTimeInDurationWhenSchedulingManually, and skipNonWorkingTimeWhenSchedulingManually through the JS Api? Only ganttRef.current?.instance.project.skipNonWorkingTimeWhenSchedulingManually is suggested through intellisense in version 5.6.10. ganttRef.current?.instance.project.skipNonWorkingTimeInDurationWhenSchedulingManually is also suggestion in version 6.1.0 but upgrading Gantt is not an option right now as we are working on a patch release, and we can't risk breaking something else.
And maxCalendarRange I can't find anywhere in the JS API.

Any suggestions ?

Best regards
Jimmy Thomsen


Post by arcady »

Hello,

If you use inlineData or loadInlineData for data loading you can put project data there too:

project.inlineData = {
    project : {
        skipNonWorkingTimeWhenSchedulingManually : true,
        hoursPerDay : 8,
        ...
    },
    tasksData : [
        ...
    ],
    resourcesData : [
        ...
    ],
    ...
}

Since skipNonWorkingTimeWhenSchedulingManually is a project field.
BTW the field value used to be true by default before v6.0.0.
So it's not needed in v5.6.10 ..but won't hurt of course in case of upgrading in the future.

Regarding maxCalendarRange it's not shown since it's a config. So strictly speaking it's supposed to be provided to the project constructor.
But you still can provide the value to instance and it'll work fine. The only problem is TypeScript will be angry. You could silence that as a quick solution:

const ganttRef = useRef<BryntumGantt>();

useEffect(() => {
  const ganttWrapper : BryntumGantt = ganttRef.current as BryntumGantt

  // @ts-ignore
  ganttWrapper.instance.project.maxCalendarRange = 10 * 365 * 24 * 3600000

Best regards,
Arcady


Post by jit@flowit.dk »

Thanks again, @arcady.

Is the default behaviour in version 5.6 equivalent to skipNonWorkingTimeInDurationWhenSchedulingManually being True or False?
The property does not exist in this version, so I'm not sure what behaviour to expect.

Bryntum-2024-10-08-032.png
Bryntum-2024-10-08-032.png (41.89 KiB) Viewed 42 times
Bryntum-2024-10-08-033.png
Bryntum-2024-10-08-033.png (537.66 KiB) Viewed 42 times

Hopefully we get the same behaviour for both the date fields and the duration field, so that the active calendar is taken into account when calculating duration AND when startDate or endDate needs adjusting, so they remain within working hours.

This information is also relevant to ensure a smooth transition to version 6, where users would expect the behaviour to remain unchanged.

Best regards
Jimmy Thomsen


Post by arcady »

Hello,

Is the default behaviour in version 5.6 equivalent to skipNonWorkingTimeInDurationWhenSchedulingManually being True or False?

It used to respect non-working time by default for manual tasks (which is equivalent of true value).
The config might not exist (I just don't recall when exactly it was introduced ..or it could be private at that version or just not documented :( ) but the behavior was equivalent of true. And since v6.0.0 the config default value has changed to false.

So in v5.x you actually don't need to do anything but when upgrading to v6.x you'll need to set the config to true to keep the same behavior for manual tasks scheduling.

Best regards,
Arcady


Post Reply