Our state of the art Gantt chart


Post by ninjakon »

Hello,

We have implemented basic undo/redo buttons using the https://bryntum.com/docs/gantt/api/Core/data/stm/StateTrackingManager.
Now we would like to disable those buttons based on the flags stm.canUndo and stm.canRedo.

We make use of React.useState() to trigger a re-render if those flags change:

const [canUndo, setCanUndo] = useState(false);
const [canRedo, setCanRedo] = useState(false);

And subscribe to TaskStore.onChange in a useEffect like this:

useEffect(() => {
    if (gantt) {
      gantt.taskStore.onChange = ({
        source,
      }: {
        source: { stm: StateTrackingManager };
      }) => {
        const { stm } = source;
        setCanUndo(stm.canUndo);
        setCanRedo(stm.canRedo);
      };
    }
 }, [gantt]);

However, after any task store event both flags, stm.canUndo and stm.canRedo, always return false.
But when we output the stm in the dev console canUndo is true after a change event as it should be.

How can we subscribe to task store events in such a fashion that our useState() is set correctly?


Post by marcio »

Hello ninjakon,

Thanks for the detailed case, do you have some special configuration set in the Gantt configuration?? In the useEffect code that you shared, you only set in the component state the current state of the stm.

Could you please provide a complete example with your case?? You can check the guidelines here viewtopic.php?f=1&t=772

Best regards,
Márcio


Post by ninjakon »

Attached to this post is a zip demonstrating the issue.

You can run it with:

  1. npm install
  2. npm run start

To reproduce the issue follow these steps:

  1. Change a tasks startDate by dragging it in the gantt chart
  2. Check the console.log
  3. taskStore.onChange was triggered but stm.canUndo is still "false"

The button placement is not ideal so I marked it here:

Screenshot 2022-10-03 at 11.07.29.png
Screenshot 2022-10-03 at 11.07.29.png (190.94 KiB) Viewed 161 times
Attachments
gantt-undo-redo.zip
(79.14 KiB) Downloaded 23 times

Post by marcio »

Hey ninjakon,

Thanks for the sample project and the detailed step-by-step to reproduce. Checking the code, you need to check the STM of the project (that's the one that you enabled in the config), also, the console.log issue is because STM transactions are asynchronous, so when you console them, they aren't finished, so the undo is still false, then after checking the dev console, it displays true. I updated the useEffect to work as you described/coded.

 useEffect(() => {
    if (ganttRef && ganttRef.current) {
      const gantt = ganttRef.current.instance;
        gantt.project.stm.addListener({
          recordingStop: (data: any) => {
              const {stm} = data
              console.log(`STM: canUndo=${stm.canUndo} canRedo=${stm.canRedo}`);  
} }) } }, [ganttRef]);

https://www.bryntum.com/docs/gantt/api/Core/data/stm/StateTrackingManager#event-recordingStop

Best regards,
Márcio


Post by ninjakon »

Yes, but then we still had the problem with react not re-rendering.

However, you nudged me in the right direction with the listeners.
Creating our own StateTrackingManager instance did the trick.

If anyone runs into the same problem, this is the code which worked for us:

const [canUndo, setCanUndo] = useState(false);
const [canRedo, setCanRedo] = useState(false);
const [stateTrackingManager, setStateTrackingManager] = useState<StateTrackingManager>();

useEffect(() => {
  const tmp = new StateTrackingManager({
    autoRecord: true,
    listeners: {
      recordingstop: ({ stm }: { stm: StateTrackingManager }) => {
        setCanUndo(stm.canUndo);
        setCanRedo(stm.canRedo);
      },
      restoringstop: ({ stm }: { stm: StateTrackingManager }) => {
        setCanUndo(stm.canUndo);
        setCanRedo(stm.canRedo);
      },
    },
  });
  tmp.addStore(gantt.project.taskStore);
  tmp.enable();
  setStateTrackingManager(tmp);
}, [gantt]);

Thanks Marcio!


Post by marcio »

Thanks ninjakon for sharing your solution too! Glad that you figure it out! :)

Best regards,
Márcio


Post Reply