Premium support for our pure JavaScript UI components


Post by rayudu.pasumarthy »

Hi Team,

Issue 1 — Bars render offset from calendar-day columns

In v7, histogram bars drift progressively leftward from their correct columns. Console shows the cause:

ru.timeAxis.count  // 910 — calendar days
hist.data.length   // 911 — working days only

Bryntum positions bars by array index, but datums are working-days only while the timeAxis is calendar-days. By datum[231], the bar is 91 calendar days off.

We worked around this with getBarDOMConfig (repositioning rects via tick.startDate), but the SVG text labels still render at the old positions since they are computed before getBarDOMConfig runs. Also note: this inside getBarDOMConfig is the Histogram child widget — we had to use this.owner.timeAxis to reach ResourceUtilization.

Q: Is there an official v7 config to align bars to calendar-day columns?


Issue 2 — datum.assignments is undefined in v7

Our getBarClass checks datum.assignments to compute allocation % and return color classes (b-quarterallocated, b-overallocated, etc.). In v7 this is always undefined, so every bar returns b-unallocated and loses its color.

var d = hist.data.find(d => d.effort > 0);
console.log(d.assignments);        // undefined  ← was an array in v6
console.log(d.effort);             // 86400000   ← data exists
console.log(d.assignmentIntervals); // Map(1) {ModelClass => {...}}  ← new in v7?

Q: Is datum.assignments removed in v7? What is the correct replacement — is it datum.assignmentIntervals? If so, what is the Map structure?

Thanks,
Rayudu


Post by tasnim »

Before answering your questions, I'm a bit confused about the issues you're facing! Could you please let us know how can we reproduce the issue? Are you able to reproduce the issue here https://bryntum.com/products/gantt/examples/resourcehistogram/?
Please share the steps and code that we should follow to reproduce the issue

Best regards,
Tasnim

How to ask for help? Please read our Support Policy


Post by rayudu.pasumarthy »

Hi Tasnim,

We migrated from v6.3.1 → v7.1.3 and found the nonWorkingTime shading in ResourceUtilization is misaligned at daily zoom — shifted 3/4 of a day to the right.

We were able to reproduce this on your official demo at https://bryntum.com/products/gantt/examples/resourceutilization/ using only console commands — no custom code needed.


Reproduction steps

  1. Open https://bryntum.com/products/gantt/examples/resourceutilization/
  2. Open DevTools console (F12)
  3. Run:
{
  const ru = bryntum.query('resourceutilization');
  const cal = ru.project.calendar;
  console.log('Calendar name:', cal?.name);
  
  const nwRanges = cal?.getNonWorkingTimeRanges?.(
    new Date('2024-01-14'), 
    new Date('2024-01-28')
  );
  console.log('NW ranges:');
  nwRanges?.forEach(r => console.log(
    r.startDate?.toISOString(), '→', r.endDate?.toISOString()
  ));
}
  1. Observe the output

Actual output from your official demo (Jan 2024 data)

Calendar name: General
NW ranges:
  2024-01-14T00:00:00.000Z → 2024-01-14T18:30:00.000Z
  2024-01-19T18:30:00.000Z → 2024-01-21T18:30:00.000Z   ← BUG HERE
  2024-01-26T18:30:00.000Z → 2024-01-28T00:00:00.000Z   ← BUG HERE

Why this causes a visual shift

  • Jan 19 is Friday. The non-working range starts at 18:30 (end of working day) instead of 00:00 Saturday
  • At a 25px-per-day tick width: 18.5h ÷ 24h × 25px = **19.3px** shift to the right
  • Weekend shading visually appears to start 3/4 of the way into Friday's column instead of at the Saturday midnight boundary

Expected output

2024-01-19T00:00:00.000Z → 2024-01-21T23:59:59.999Z   ← midnight-aligned (v6 behaviour)

Impact in our application

We use ResourceUtilization with nonWorkingTime: true and a Mon–Fri 8am–5pm project calendar. The shading shift is 17px at our 25px tick width, making weekends appear to start Friday afternoon.


Question

Is there a v7 config option to force getNonWorkingTimeRanges (or the NonWorkingTime feature rendering) to snap boundaries to whole-day tick edges rather than exact calendar work-hour times? Something like:

features: {
    nonWorkingTime: {
        snapToTicks: true  // hypothetical — does this exist?
    }
}

Or is there a calendar interval definition that produces midnight-aligned non-working ranges?


Environment: Bryntum Gantt v7.1.3 · Angular 17 ·

Thank you!


Post by tasnim »

I've tried the steps you mentioned for our online demo, but it works fine for me!

Screenshot 2026-03-26 164934.png
Screenshot 2026-03-26 164934.png (298.05 KiB) Viewed 3228 times

The non-working time color has taken the space of the full tick

Is there a v7 config option to force getNonWorkingTimeRanges (or the NonWorkingTime feature rendering) to snap boundaries to whole-day tick edges rather than exact calendar work-hour times? Something like:

As far as I know, we don't have any public config available for this!

Am I missing something?

Best regards,
Tasnim

How to ask for help? Please read our Support Policy


Post by rayudu.pasumarthy »

Hi Tasnim,

Thank you for checking on your demo. We continued investigating and have now identified the root cause in our setup. We can reproduce the issue and confirm the fix. Please see our full findings below.


Root Cause Found

The offset is caused by a silent v7 breaking change in viewPreset handling combined with how nonWorkingTime uses timeResolution.

What happens step by step

Step 1 — Our viewPreset config (no id)

We define a custom viewPreset in our ResourceUtilization config without an explicit id:

viewPreset: {
  // no id
  tickWidth      : 25,
  shiftUnit      : 'week',
  timeResolution : { unit: 'HOUR', increment: 1 },
  headers: [
    { unit: 'month', dateFormat: 'MMM YY' },
    { unit: 'week',  dateFormat: 'W' },
    { unit: 'day',   dateFormat: 'DD' }
  ]
}

Step 2 — v7 silently merges our preset with dayAndweekAndMonth

Because we have a 3-level header (month → week → day) and no id, v7 matches our config to the built-in registered preset dayAndweekAndMonth and merges them. This overrides our timeResolution with the registered preset's value:

Our config:           timeResolution: { unit: 'HOUR' }
Registered preset:    timeResolution: { unit: 'HOUR' }   ← same, no problem here
Actual running value: timeResolution: { unit: 'HOUR' }   ← confirmed in console

We confirmed this by running a config report on both your demo and our app:

Bryntum demo:  presetId = "weekAndDay"        timeResolutionUnit = "day"   nwt_canvasChildren = 3  ✓
Our app:       presetId = "dayAndweekAndMonth" timeResolutionUnit = "HOUR"  nwt_canvasChildren = 0  ✗

Step 3 — timeResolution: HOUR causes nonWorkingTime to compute hourly boundaries

In v7 (unlike v6), the NonWorkingTime feature uses timeResolution as the snap unit when computing where to draw shading boundaries. With HOUR resolution and a Mon–Fri calendar, Bryntum computes:

Friday working day ends at 17:00  →  non-working starts at 17:00 Friday

Instead of the expected midnight boundary:

Saturday 00:00  →  Monday 00:00

Step 4 — The 3/4 day visual offset

At our 25px-per-day tick width:

17h ÷ 24h × 25px = 17.7px shift to the right

The weekend shading visually starts 18px into Friday's column instead of at the Saturday column boundary — which looks like a 3/4 day offset.


Why It Worked in v6 But Breaks in v7

In v6, the NonWorkingTime feature computed boundaries directly from the calendar interval definitions (Sat 00:00 → Mon 00:00), completely ignoring timeResolution. So even with HOUR resolution, shading snapped to midnight correctly.

In v7, NonWorkingTime now respects timeResolution for boundary snapping — a behaviour change that is not documented in the v6 → v7 migration guide.


Reproduction Steps on Your Official Demo

You can reproduce this directly on https://bryntum.com/products/gantt/examples/resourceutilization/ using only console commands:

(function() {
  var ru = bryntum.query('resourceutilization');

  // Step 1: Apply preset WITHOUT unique id + HOUR resolution (our broken config)
  ru.zoomTo({
    preset: {
      // NO id — v7 merges this with dayAndweekAndMonth
      tickWidth      : 25,
      shiftUnit      : 'week',
      timeResolution : { unit: 'HOUR', increment: 1 },
      headers: [
        { unit: 'month', dateFormat: 'MMM YY' },
        { unit: 'week',  dateFormat: 'W' },
        { unit: 'day',   dateFormat: 'DD' }
      ]
    }
  });

  setTimeout(function() {
    var shadingEls = document.querySelectorAll('.b-sch-non-working-time');
    if (shadingEls.length > 0) {
      var left = parseFloat(shadingEls[0].style.insetInlineStart);
      var date = ru.getDateFromCoordinate(left);
      console.log('BUG — Shading starts at:', date.toString());
      console.log('Expected Saturday 00:00, got day=' + date.getDay() + ' hour=' + date.getHours());
    }

    // Step 2: Fix — add unique id + DAY resolution
    ru.zoomTo({
      preset: {
        id             : 'customResLoadPreset',
        tickWidth      : 25,
        shiftUnit      : 'week',
        timeResolution : { unit: 'day', increment: 1 },
        headers: [
          { unit: 'month', dateFormat: 'MMM YY' },
          { unit: 'week',  dateFormat: 'W' },
          { unit: 'day',   dateFormat: 'DD' }
        ]
      }
    });

    setTimeout(function() {
      var shadingEls2 = document.querySelectorAll('.b-sch-non-working-time');
      if (shadingEls2.length > 0) {
        var left2 = parseFloat(shadingEls2[0].style.insetInlineStart);
        var date2 = ru.getDateFromCoordinate(left2);
        console.log('FIXED — Shading starts at:', date2.toString());
        console.log('Is Saturday midnight?', date2.getDay() === 6 && date2.getHours() === 0 ? 'YES ✓' : 'NO ✗');
      }
    }, 500);
  }, 500);
})();

Questions

  1. Is the anonymous viewPreset → registered preset merging behaviour intentional in v7? It did not happen in v6 — anonymous presets were always treated as fully independent.

  2. In v6, NonWorkingTime ignored timeResolution and always used midnight boundaries from the calendar. In v7 it respects timeResolution. Is this a documented breaking change in the v6 → v7 migration guide? We could not find any mention of it.

  3. Should adding a unique id to a custom viewPreset be the official recommended approach to prevent this merging?

  4. Is changing timeResolution from HOUR to day safe for our use case, or does it affect scheduling precision elsewhere in ResourceUtilization?

Thank you for your support!

Environment: Bryntum Gantt v6.3.1 → v7.1.3 · Angular 17


Post by alex.l »

Hi,

Am I right that the unexpected behaviour you claim on is that timeResolution config that you passed into viewPreset has been correctly applied since v7?

What do you mean by merging? if you need explicit behaviour why don't pass explicit config and don't rely on auto-handling? I don't see how the system might predict what you expect to see as default values, it depends on many things, such as current viewPreset you switched from, also viewPresets you have in component (you can filter them or redefine), I don't see how we can guarantee any behaviour here.
If you set timeResolution, that value should be used. If it doesn't - that's a bug.
If you didn't set timeResolution and preset id, we can't guarantee what viewPreset and timeResolution will be used. I can't find any description regarding to this behaviour in our docs, so I can't see how we can call it breaking changes.

Would be great to get some clarifications from your side!

All the best,
Alex Lazarev

How to ask for help? Please read our Support Policy


Post Reply