Perspective Horizontal Menu Component

One more.

Trying to just pass props.items[x].enabled and start there.

It works but in testing in my browser:
land on the page unauthenticated and menu items are unavailable. Good.
Hit a header icon that runs system.perspective.login() and go to login screen and login. Come back and menu items still are not enabled.
Switch to console in browser and make app switch to small break-point and back to reload the header view and the menu items are enabled now.

Maybe expected behavior although I’d think the view would reload during login. But, how could you get the behavior of enabled menu items after login without reloading view or call .login and .reload with the header icon that goes to login? Or how to get a new session-id? Can’t reload view on start-up script lol

Why don’t you bind against the user’s authentication values and/or permissions, then use a transform to construct the structure?

I think that is the plan…
I originally had a binding on the items enabled prop. Bound to session.props.auth.user.roles and could only get it to work by closing page completely and reloading to make menu items enable after login(). But, I wasn’t calling a refresh binding on it anywhere. I need to add to the startup script maybe and try it out that way. But, if the start-up script of view doesn’t run after login (like above) then it won’t help.

As kind of a weird workaround, you could bind some custom property to the session.auth.username property, then put an onChange script on this custom property to invoke refreshBinding on the props.items property.

1 Like

what would this structure look like. I get the idea of using a transform script to create the “items” structure and using the users authentication as a binding and effectively a trigger.

I could add additional items based on their roles, for example.

I’m just not sure how to build the structure to bind to props.items

Not sure if this is right, but it seems to be working

list = []
list.append({"enabled":True,"target":'',"label":'Item1',"items":[],"icon":[]})
list.append({"enabled":True,"target":'',"label":'Item2',"items":[],"icon":[]})
		
self.parent.parent.parent.getChild("CoordinateContainer").getChild("HorizontalMenu_0").props.items = list

While that will technically work, I advise against using list as a variable name because “list” is a type in Python. You run the risk of encountering some errors/exceptions which could seem nonsensical given that variable name.

What, may I ask, is the right way? because this works in the designer, but I get a Component Error in chrome.

Sorry, I just realized you wanted me to change the variable name. This is done, however, I still get an error in chrome. I am limiting the Horizontalmenu items with a Transform Script. If an user with admin role is logged in, they should get extra menu options

	uName = self.session.props.auth.user.userName
	roles = self.session.props.auth.user.roles
	isGELT = 0
	isAdmin = 0 
	
	for role in roles:
		if role == 'Administrator':
			isAdmin = 1
			isGELT =1
		elif role == 'TT_Admin':
			isAdmin = 1
			isGELT =1
		elif role =='TT_GELT':
			isGELT = 1
		
	
	l = []
	#File
	l.append({"enabled":True,"target":'',"label":'File',"icon":{"path":''},"items":[],"style":{"classes":''}})
	l[0]['items'].append({"enabled":True,"target":'',"label":'Logout',"icon":{"path":''},"items":[]})
	#Admin
	if isAdmin ==1:
		l.append({"enabled":True,"target":'',"label":'Admin',"icon":{"path":''},"items":[],"style":{"classes":''}})
		l[i]['items'].append({"enabled":True,"target":'/Users',"label":'User List',"icon":{"path":''},"items":[],"style":{"classes":''}})
		
		i=i+1
    return l

It works in the designer, but I get the following error in chrome with a Component Error.

image

I’m surprised that’s working in the Designer because you reference a variable (i) before it’s ever defined.

This line right here:

l[i]['items'].append({"enabled":True,"target":'/Users',"label":'User List',"icon":{"path":''},"items":[],"style":{"classes":''}})

should fail even in the Designer because you have not defined i before you use it.

sorry, that was a cut and paste error. i is defined in my code. I just didn’t want you to see everything in between. Here is what i have at the moment, working in the designer, not working in chrome

	
	uName = value
	roles = self.session.props.auth.user.roles
	
	isGELT = 0
	isAdmin = 0 
	
	for role in roles:
		if role == 'Administrator':
			isAdmin = 1
			isGELT =1
		elif role == 'TT_Admin':
			isAdmin = 1
			isGELT =1
		elif role =='TT_GELT':
			isGELT = 1
		
	
	l = []
	
	#File
	l.append({"enabled":True,"target":'',"label":'File',"icon":{"path":''},"items":[],"style":{"classes":''}})
	l[0]['items'].append({"enabled":True,"target":'',"label":'Logout',"icon":{"path":''},"items":[]})
	
	i=1

	#Admin
	if isAdmin == 1:
		l.append({"enabled":True,"target":'',"label":'Admin',"icon":{"path":''},"items":[],"style":{"classes":''}})
		l[i]['items'].append({"enabled":True,"target":'/Users',"label":'User List',"icon":{"path":''},"items":[],"style":{"classes":''}})
		i=i+1
				
	return l

Two things I had to change in your script to get it working on my end:
1.

    # If user is not authenticated then roles is null/None, and therefore not iterable
	if roles:
		for role in roles:
			if role == 'Administrator':
				isAdmin = 1
				isGELT =1
			elif role == 'TT_Admin':
				isAdmin = 1
				isGELT =1
			elif role =='TT_GELT':
				isGELT = 1
		
  1. Maybe a copy/paste issue, but the return l statement was tabbed too far so it wasn’t executing unless isAdmin was 1.

After I made these adjustments I had no issue.

I implemented #1 and no discernible change on my end. Still getting the same error in chrome.

#2 must be copy paste issue, it executes correctly at the return statement, omitted Admin == 1 to confirm.

Since you haven’t supplied the full code of the transform, I don’t know how else I can help here. The code you’ve supplied here works, so look at the code you haven’t supplied; somewhere within the transform you’re modifying the items in a way that can’t be parsed by the component.

I am running the exact code I have supplied above with the same results.

The strange thing is that the component builds just fine. I only get the error when I click on it in Chrome.

While not signed in:
Screen Shot 2020-08-31 at 8.53.04AM
After signing in:
Screen Shot 2020-08-31 at 9.02.26AM

Perhaps the issue is a result of the layout of the View?

would it matter that this is a docked header?

No, it would be the layout of the View which contains the Horizontal Menu.

It works as is on a view. It does not work in a view that is a docked header

Could you post a screenshot of the component in an active session?