-
My goal: Add a module that contains a single navigation menu to apps to create the illusion of a single "Portal", which would navigate from app to app. The critical feature that I want is the ability to hide/show menu items based on your user's groups, which would mirror the apps that user has access. The point being that I do not want to show a menu item for an app you do not have access to.
-
Issue: This proved to much more complex than I planned and I went through many iterations until I settled on a working but heavy solution.
a) The users object has access to the groups, but there is no way to get to the underlying apps. This can be done through the Retool API I think, but we do not have Enterprise, so that is not an option. For this reason, I ultimately settled on basically recreating the group/applications list in a Retool database table that has GROUP and APP as it's two fields. For new apps you now have to set the permission in Retool itself and add the necessary records to this table.
b) The navigation menu is not as robust as I needed. What I wanted to do is have a JS resource run on page load and query the DB and run through the navigation menu updating the hidden attribute of each menu item. However, you cannot programmatically change either the hidden or 'disabled` attributes. There are no .setHidden() or .setDisabled() methods exposed and the attribute itself is read-only. So I went with a function (meaning {{ }}) on each hidden attribute on each menu item (there are currently 47 menu items).
c) Menu Items on the Navigation Menu are not directly accessible, so you cannot reference the menu item you are on in the hidden attribute of the menu item. self references the Navigation Menu, not the menu item. And there is no index to the specific menu item. So I could not write a "copy and paste" function. Instead I had to write a function with hard-coded values for each menu item. The process is 'copy and paste' and then edit the hard-coded values. The function looks like this:
{{ !current_user.groups.map(group => group.name).some(g => fetchPermissionMap.data.find(p => p.app === "Driver Support Hub")?.roles.includes(g)) }}
which is pretty ugly but all you have to change is the name like 'Driver Support Hub'.
So, what should have been a small JS resource that made 1 call to the user's group's application list and a loop though that list that sets the Navigation Menu's item's hidden attribute turned into a huge effort that took a day to write, multiple dead-end development ideas, and a much more convoluted solution.
I am hoping I missed something and there is a better solution to this and I am looking for some best practices and other ideas.
A multi-page app doesn't solve my problem as I still need the DB to correlate the permissions and I would have the same access issues to the Navigation Menu. However, until very recently with multi-player, the biggest reason not to move to a multi-page app was the limitation that only one person could modify the app at a time safely and this app would be way to big for that.
- Additional info: (Cloud or Self-hosted, Screenshots) Self-hosted, Business Plan
Thanks,
Steve