Our state of the art Gantt chart


Post by Qwerty »

Hi Bryntum, I hope this finds you well :)

I've been thoroughly debugging why a customer's gantt PDF export will show the task names beyond a certain row as blank. Its actually an intermittent issue, fails 3 out of 4 tries. I was curious and tried adding a 5 second wait 'onBeforePdfExport', but the result was the same.

I compared against your examples, and was able to find the breaking difference. The issue only happens when the request HTML has task name classes like 'b-react-portal-container', and these only happen when we use a custom 'TaskNameRenderer' in 'Columns.js'. Is it possible there is an upstream bug with React portals and PDF export?

Issue persisted with a simplified 'TaskNameRenderer' that just returned a span. We need the custom 'TaskNameRenderer' to satisfy business logic with links.

Could you please help direct me to not face this issue, whether that be fixing upstream or a workaround like forcing TNR not to use portal or simple rendering them 'onBeforePdfExport'?

Many thanks,
Ben


Post by mats »

Which version are you using? PDF export was recently refactored so possibly this may not be an issue anymore.


Post by Qwerty »

Hi Mats,
I confirmed that the server side version is still the latest at 0.0.2.
The client side is 5.2.1, so it would have the PDF improvements from 5.2.0.
It also fails with 'enableDirectRendering' set to false.

Thanks,
Ben


Post by Maxim Gorkovsky »

Hello.
Do I get it right that only task name column cell gets blank after certain point? Could you please try to reproduce it on one of our react demos?

When exporting we call regular row.render() method, same as in the regular rendering pipeline. I haven't tested it with react portals and I'm wondering if react does delayed rendering. In which case we would need to wait for those to finish.


Post by Qwerty »

Hi Maxim,
Thank you for the reply.
Yes, that's correct. Its only the task name column cells which become blank after a certain point.

I'd be happy to try and replicate on your React demo, after I finish another priority. In the meantime, are there any workarounds I could try to at least get the symptom off of production?


Post by Qwerty »

Hi Maxim,
I've been able to reproduce the issue on the official BG React demo (PDF attached)
https://bryntum.com/products/gantt/examples/frameworks/react/javascript/pdf-export/build/

Just add the following to '<BryntumGantt' in 'App.js':

columns={[{type: 'name', renderer: (data) => <span>FFF {data.value}</span>}]}

Could you please log and keep us notified of an upstream fix?

In the meantime, I'm unable to force unset the custom renderer before / then reapply after. I'm trying

ganttRef.current.instance.columns.applyChangeset

but can't unset the 'renderer'. Do you know how to do this or have a better workaround?

Thank you,
Ben

Attachments
Gantt(3).pdf
(66.44 KiB) Downloaded 28 times

Post by Maxim Gorkovsky »

You can try to disable direct rendering and override exporter method to add some delay:

Override.apply(class {
  static target = { class : Exporter }

  async scrollRowIntoView(client, index) {
    await this._overridden.scrollRowIntoView.call(this, client, index);
    // add delay for several animation frames
    await new Promise(resolve => setTimeout(resolve, 50));
  }
})

direct rendering will just call row renderer directly and wouldn't provide any means to delay before getting HTML


Post by Maxim Gorkovsky »

In the meantime, I'm unable to force unset the custom renderer before / then reapply after. I'm trying

ganttRef.current.instance.columns.applyChangeset

but can't unset the 'renderer'. Do you know how to do this or have a better workaround?

I would try to reach column renderer directly from column record:

const column = ganttRef.current.instance.columns.getById('mycolumnid');
const oldRenderer = column.renderer;
column.renderer = () => {...}
....
// run export, add listener to export finish, restore renderer
column.renderer = old;

Post by Maxim Gorkovsky »

Ticket opened here: https://github.com/bryntum/support/issues/5619 Thank you for report.

At the moment we have a lot of work, so I don't expect this ticket to be taken into work soon. We will help you find a workaround and I hope ticket can be started in the coming month or two.


Post by Qwerty »

Thank you Maxim,

I've subscribed to the GitHub issue, thanks. I set 'enableDirectRendering' to 'false' and applied the override but it was unsuccessful (I even changed to "resolve, 2000").

Reaching the column renderer directly from the column record has helped. My current workaround looks something like this and is passing all my test-cases:

// Save custom renderer to reset to after export
const columns = this.props.gantt.columns;
const nameCustom = columns.get('name');
const nameCustomRenderer = nameCustom?.renderer;

// Ensure task name uses Bryntum's default tree renderer for export as React portals often render blank
if (nameCustom && nameCustomRenderer) {
  columns.add({ id: -1, type: 'name' });
  nameCustom.renderer = undefined;
  nameCustom.renderer = columns.getById(-1).renderer;
  columns.remove(-1);
}

// ... in Axios's .then(() =>
if (nameCustomRenderer) {
  const nameColumn = columns.get('name');
  nameColumn.renderer = undefined;
  // Reset to custom renderer
  nameColumn.renderer = nameCustomRenderer;
}

I quite like this workaround but the 'add' part is much too hacky for my tastes. Is there a more legitimate way to get Bryntum's default task name renderer?


Post Reply