Page 1 of 1

[ANGULAR] ContextMenu async processItems

Posted: Fri Jun 24, 2022 2:18 am
by cheradee

Hi,

We have a use case where we want to hide/show context menu items based on the results of an async function by toggling the item's hidden property in the processItems function. It works for non-async functions, but for async functions, we noticed that the context menu does not wait for the async function to finish before showing the context menu, so all items end up visible.

Is there a way for us to hide/show context menu items based on the results of an async function?

Thanks,
Chardine


Re: [ANGULAR] ContextMenu async processItems

Posted: Fri Jun 24, 2022 7:03 am
by tasnim

Could you please show the code inside processItems?


Re: [ANGULAR] ContextMenu async processItems

Posted: Fri Jun 24, 2022 7:54 am
by cheradee

Here's a sample code:

processItems: async ({ items, resourceRecord, event }: {
  items: {
    createResourceDowntime: ScheduleMenuItemConfig
    createCrewDowntime: ScheduleMenuItemConfig
    relocateResource: ScheduleMenuItemConfig
    reassignResource: ScheduleMenuItemConfig
  },
  resourceRecord: {
    schedulerResourceType: SchedulerResourceType
    apiResourceId: number
  },
  event: {
    layerX: number,
    layerY: number,
    ObjID: number
  }
}): Promise<void> => {
  console.log(event, resourceRecord);

  return new Promise(resolve => {
    setTimeout(() => {
      items.relocateResource.hidden = true;
      items.reassignResource.hidden = true;
      console.log({...items});
      resolve(undefined);
    });
  });
}

console.log of items shows the relocateResource and reassignResource are hidden, but they still show in the context menu.


Re: [ANGULAR] ContextMenu async processItems

Posted: Fri Jun 24, 2022 8:46 am
by tasnim

Try this :

processItems({ items, resourceRecord, event, menu }) {
    console.log(event, resourceRecord);

setTimeout(() => {
    menu.menu.widgetMap.relocateResource.hidden = true;
    menu.menu.widgetMap.reassignResource.hidden = true;
});
}
  

Re: [ANGULAR] ContextMenu async processItems

Posted: Fri Jun 24, 2022 11:09 am
by cheradee

Hi,

What I provided is just a sample code to show that processItems is not waiting for an async function to finish. Our actual code has more complex logic that has to wait on an async function/Observable to hide/show items:

processItems: async ({ items, resourceRecord, event }: {
  items: {
    createResourceDowntime: ScheduleMenuItemConfig
    createCrewDowntime: ScheduleMenuItemConfig
    relocateResource: ScheduleMenuItemConfig
    reassignResource: ScheduleMenuItemConfig
  },
  resourceRecord: {
    schedulerResourceType: SchedulerResourceType
    apiResourceId: number
  },
  event: {
    layerX: number,
    layerY: number,
    ObjID: number
  }
}): Promise<void> => {
  if (resourceRecord.schedulerResourceType !== SchedulerResourceType.Crew) {
    items.createCrewDowntime.hidden = true;
  }

  if (resourceRecord.schedulerResourceType !== SchedulerResourceType.Resource) {
    items.createResourceDowntime.hidden = true;
    items.relocateResource.hidden = true; 
    items.reassignResource.hidden = true;
  }

  const hasCRUDAccess$ = this.accessService.userHasCRUDAccess(ObjectTypeEnum.Resource, AccessRightsEnum.CRUD);
  const resources$ = from(this.dataLayer.getResource(resourceRecord.apiResourceId));

  forkJoin([hasCRUDAccess$, resources$]).subscribe(result => {
    const [hasCRUDAccess, resources] = result;
    if (!hasCRUDAccess) {
      items.createResourceDowntime.hidden = true;
      items.createCrewDowntime.hidden = true;
      items.relocateResource.hidden = true;
      items.reassignResource.hidden = true;
      return;
    }

const arr = [event.layerX, event.layerY];
const date: Date = new Date(this.scheduler.instance.getDateFromXY(arr));
const res = nullableFind(resources, r => isDateTimeBetweenRange(date, {
  start: utcStrToDate(r.EffectiveFrom as unknown as string),
  end: utcStrToDate(r.EffectiveTo as unknown as string)
}));

if (!res) {
  // THIS SHOULD HIDE THE ITEMS
  items.relocateResource.hidden = true;
  items.reassignResource.hidden = true;
  console.log({...items});  // console.log shows the items have hidden=true, but they are still shown
}
  });
}

Re: [ANGULAR] ContextMenu async processItems

Posted: Fri Jun 24, 2022 12:18 pm
by tasnim

You can use this event: https://bryntum.com/docs/gantt/api/Core/widget/Menu#event-beforeShow

Here is an example of how you can use it :

scheduler.features.eventMenu.menu.on('beforeShow', async ({ source }) => {
    const items = source.widgetMap;
    return new Promise(resolve => {
        setTimeout(() => {
            items.cutEvent.hidden = true;
            items.deleteEvent.hidden = true;
            console.log({...items});
            resolve(undefined);
        });
    });
});

Re: [ANGULAR] ContextMenu async processItems

Posted: Mon Jun 27, 2022 6:06 am
by cheradee

Hi,

The code above works, but it only has the "source" and "type" included in the event. We want the "resourceRecord" and "date" included in the event, like what "scheduleMenuBeforeShow" provides. We have tried

scheduler.features.scheduleMenu.menu.on('scheduleMenuBeforeShow', (event) => {...})

but it did not call our function.


Re: [ANGULAR] ContextMenu async processItems

Posted: Mon Jun 27, 2022 8:17 am
by tasnim

Hi,
It's really hard to achieve with this.
I've created a feature request to make the processItems async. Here it is: https://github.com/bryntum/support/issues/4855