Simple Link in Topbar

Forum rules
Please note that response time for technical support is within 3-5 business days.
UlrichC
Posts: 18
Joined: 03 Sep 2015, 23:49

09 Jan 2019, 09:37

Hi,

I bought Avalon theme and now I try to integrate a direct link into the topbar, which should look like the other "menus", but don't work like the menu (open a sub-menu). I have this here in the topbar:

Code: Select all

                <li class="profile-item" style="margin-top: -3px;">
                    <span>
                        <h:link outcome="login">
                            <span class="topbar-item-name">Anmelden</span>
                        </h:link>
                    </span>
                </li>
Image

This looks fine and works, but when the screen is getting smaller and the Hamburger Icon appears, it looks very bad:
Image

If I remove the <span> around the h:link, then it looks alright, but then the Link did not work.

Can someone point me to the right direction? Many thanks in advance, Ulrich

mert.sincan
Posts: 5281
Joined: 29 Jun 2013, 12:38

11 Jan 2019, 13:45

Please try;

Code: Select all

<li class="profile-item">
      <h:link outcome="login">
              <span class="topbar-item-name">Anmelden</span>
      </h:link>
 </li>

UlrichC
Posts: 18
Joined: 03 Sep 2015, 23:49

12 Jan 2019, 12:53

Thanks for the response.
The "view"-part works, the menu-item is rendered correctly in the menubar and the "Hambuger"-menu, but the link is not triggert there is no request fired.

One solution is following:

Code: Select all

<li class="profile-item" onclick="location.href='/login.xhtml';">
    <a href="#">
        <span class="topbar-item-name">Anmelden</span>
    </a>
</li>

In addition, then you can use the following to call a backend-method from that link:

Code: Select all

<p:remoteCommand name="logoff" update="@all" actionListener="#{userSession.logout}" />
<li class="profile-item" onclick="logoff();" jsf:rendered="#{userSession.loggedIn}">
    <a href="#">
        <span class="topbar-item-name">Abmelden</span>
    </a>
</li>
Clearly not the best solution, but it worked without modification of the theme or custom-css ;-)

mert.sincan
Posts: 5281
Joined: 29 Jun 2013, 12:38

14 Jan 2019, 09:21

Please add the following line to layout.js;

Code: Select all

...
         this.topbarLinks.off('click.topbarLink').on('click.topbarLink', function(e) {
             ...
//line 229
            var href = link.attr('href');
            if(href && href !== '#') {
                window.location.href = href;
            }
            
            e.preventDefault();         
        });
Then,

Code: Select all

<li class="profile-item">
    <h:link outcome="login">
                <span class="topbar-item-name">Anmelden</span>
    </h:link>
 </li>
 
 OR
 
 <li class="profile-item">
    <a href="login.xhtml">
        <span class="topbar-item-name">Anmelden</span>
    </a>
</li>

UlrichC
Posts: 18
Joined: 03 Sep 2015, 23:49

23 Jan 2019, 19:27

Thank you very much, interesting solution, I will try that out on weekend...

mert.sincan
Posts: 5281
Joined: 29 Jun 2013, 12:38

24 Jan 2019, 07:53

Thanks a lot for the update!

tony.herstell
Posts: 214
Joined: 29 Nov 2011, 00:40

27 Jan 2020, 01:36

I used this to get the link to work...

Code: Select all

                    <li role="menuitem">
                    	<h:form id="logoutForm" style="display:block; display: inline-block; box-sizing:border-box">
    	                	<span style="display: inline-block; vertical-align: middle; width:100%">
    	                		<p:commandLink action="#{securityController.logout()}"> <i style="display: inline-block; vertical-align:middle" class="fa fa-fw fa-sign-out"></i>Logout</p:commandLink>
    	                	</span>
                    	</h:form>
                    </li>
PF12+, Quarkus 3.2+ (CDI, JPA etc.), JSF Bridge (MyFaces 4.0.1)
Dont forget the classifier:

Code: Select all

   ...primefaces
  <classifier>jakarta</classifier>
     ... theme
  <classifier>jakarta</classifier>

mert.sincan
Posts: 5281
Joined: 29 Jun 2013, 12:38

30 Jan 2020, 15:31

Thank a lot for the sample, Tony ;)

Best Regards,

tony.herstell
Posts: 214
Joined: 29 Nov 2011, 00:40

30 Jan 2020, 22:58

Here is a "fuller" one...
I usually have to hack that top bar to pieces...
I use Keycloak for auth and that works with JEE Security as I am using wildfly app server.... so role works!
KISS!

This does simple login/logout/show profile info etc.

Logging in is done by Keycloak intercepting ANY move to a protected page and it throws up the login challenge... (in fact for me anything under /pages/* is protected by Keycloak).

ANYHOW:

This may be useful in a few months when I am hunting again!

Code: Select all

<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui"
    xmlns:pa="http://primefaces.org/atlantis">

    <div class="topbar">

<!-- 
		<div class="logo">
            <p:graphicImage name="images/logo.png" library="atlantis-layout" />
        </div>
        
        <p:graphicImage name="images/appname.svg" library="atlantis-layout" styleClass="app-name"/>
 -->

		 <!-- style="background-color: white" -->
<!--		<div class="logo">
			<p:graphicImage name="images/brand/icon 120x70.svg" library="xxxxx-layout" />
		</div>
-->
        <div class="logo" style="margin-top:-16px; height: 80px">
			<p:outputLabel style="font-size: 32pt; color:white">
	            <i class="fa fa-globe"></i>
            </p:outputLabel>
        </div>
        
<!--         
        <p:graphicImage name="images/brand/XXXXX.png" library="xxxxxx-layout" styleClass="app-name" style="height:100%"/>
-->
        <span style="font-size: 22pt; color: white; font-weight: bolder; padding-left: 20px">XXXXXXX</span>
   						              
        <a id="topbar-menu-button" href="#">
            <i class="fa fa-bars"></i>
        </a>
                
        <ul class="topbar-menu fadeInDown animated">
            <li class="profile-item">
                <a href="#">
                    <div class="profile-info">
                        <span class="topbar-item-name profile-name">#{securityController.name}</span>
                        <h:outputText id="user-role" styleClass="topbar-item-name profile-role" value="#{securityController.role}"></h:outputText>
                        <p:tooltip for="user-role" value="#{securityController.roles}" position="bottom" trackMouse="true" />
                    </div>
                </a>
            </li>
            
            <li>
	            <h:form id="LoginForm" rendered="#{!facesContext.externalContext.isUserInRole('uma_authorization')}">
		            <i style="color:white; vertical-align:middle" class="fa fa-fw fa-sign-in"></i>
   		        	<p:commandButton actionListener="#{securityController.login()}" style="color:white; vertical-align:middle" value="Login" />
	            </h:form>
            </li>
            
            <li>
	            <h:form id="ProfileForm" rendered="#{facesContext.externalContext.isUserInRole('uma_authorization')}">
		            <i style="color:white; vertical-align:middle" class="fa fa-fw fa-user"></i>
   		        	<p:commandButton actionListener="#{securityController.profile()}" style="color:white; vertical-align:middle" value="Profile" />
	            </h:form>
            </li>
            
            <li>
	            <h:form id="logoutForm" rendered="#{facesContext.externalContext.isUserInRole('uma_authorization')}">
	            	<i style="color:white; vertical-align:middle" class="fa fa-fw fa-sign-out"></i>
    	        	<p:commandButton action="#{securityController.logout()}" style="color:white; vertical-align:middle"  value="Logout" />
	            </h:form>
            </li>
            
        </ul>
    </div>

</ui:composition>


here is the backing bean... but obviously you need a keycloak running with a realm set up...


Code: Select all

import java.io.Serializable;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@ViewScoped
public class HomeController implements Serializable {
	
	private static final long serialVersionUID = 2615773142108848634L;
	
	@Inject
	private Logger logger;
	
    @PostConstruct
    public void init() {  
    	logger.info("Home Controller (View Scoped)");
    }

    public String join() {
    	logger.info(">join");
    	logger.info("<join");
    	return "/pages/join?faces-redirect=true";
    }
    
    public String donate() {
    	logger.info(">donate");
    	logger.info("<donate");    	
    	return "/donate?faces-redirect=true";
    }
       
}
 

Code: Select all


import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import java.util.Iterator;
import java.util.Set;
import java.util.logging.Logger;
import java.io.IOException;
import java.io.Serializable;
import java.security.Principal;

import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.representations.IDToken;

@Named
@SessionScoped
public class SecurityController implements Serializable {
	
	private static final long serialVersionUID = 3893061551568273021L;

	@Inject
	private HttpServletRequest request;

	@Inject
	private Logger logger;
	
	@Inject
	private TokenController tokenController;
	
    @PostConstruct
    public void init() {  
    	logger.info("Security Controller (Session Scoped)");
    }
    
    public void login() throws IOException {
    	logger.info(">login");
    	logger.info("<login");
    	ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    	externalContext.redirect("http://localhost:8080/theplanetsparty/pages/my/dashboard.jsf");
    }

    public String logout() throws ServletException {
    	logger.info(">logout");
    	if (request.getUserPrincipal() != null) {
    		logger.info("Logging out: " + request.getUserPrincipal().getName());
    		
    		Principal principal = request.getUserPrincipal();
    		
    		if (principal instanceof KeycloakPrincipal) {
    		      KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
    		      
//    		      boolean hasPermission = kp.getKeycloakSecurityContext().getAuthorizationContext().hasPermission(arg0, arg1);
//    		      boolean hasResourcePermission = kp.getKeycloakSecurityContext().getAuthorizationContext().hasResourcePermission(resourceName);
//    		      boolean hasScopePermission = kp.getKeycloakSecurityContext().getAuthorizationContext().hasScopePermission(arg0);
    		      
    		      // this is how to get the real userName (or rather the login name)
    		      IDToken idToken =  kp.getKeycloakSecurityContext().getIdToken();
    		      
    		      logger.info("==========================");
    		      String userPreferredName = tokenController.getUserPreferredName(idToken);
    		      logger.info("Preferred Name " + userPreferredName);
    		      logger.info("==");
    		      logger.info("Name " + tokenController.getName(idToken));
    		      logger.info("==");
    		      logger.info("Gender " + tokenController.getGender(idToken));
    		      logger.info("==");
    		      logger.info("Family Name " + tokenController.getFamilyName(idToken));
    		      logger.info("Middle Name " + tokenController.getMiddlename(idToken));
    		      logger.info("Given Name " + tokenController.getGivenName(idToken));
    		      logger.info("==");
    		      logger.info("NickName " + tokenController.getNickname(idToken));
    		      logger.info("==");
    		      logger.info("Email " + tokenController.getEmail(idToken));
    		      logger.info("Phone " + tokenController.getPhoneNumber(idToken));
    		      logger.info("==");
    		      logger.info("Issuer " + tokenController.getIssuer(idToken));
    		      Set<String> roles = tokenController.getRoles(kp);
    		      String allRoles = String.join(" ", roles);
    		      logger.info("Roles " + allRoles);
    		      logger.info("==========================");
    		          		      
    		      logger.info("Logging out:" + userPreferredName);
    		    }
    		
    		request.logout();
    		logger.info("Logged out");
        	FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Logged Out.", "Logged Out."));
    	} else {
    		logger.info("Not Logged in");
        	FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Not Logged In.", "Not Logged In."));
    	}
    	
    	logger.info("<logout");
    	
    	return "/home?faces-redirect=true";
    }
    
    public void profile() throws IOException {
    	ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    	externalContext.redirect("http://localhost:8180/auth/realms/ThePlanetsParty/account");
    }
    
    public String getName() {
    	String name = null;
    	if (request.getUserPrincipal() != null) {
    		Principal principal = request.getUserPrincipal();
    		KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
		    IDToken idToken =  kp.getKeycloakSecurityContext().getIdToken();
		    name = tokenController.getName(idToken);
    	}
    	return name;
    }

    public String getRole() {
    	String role = null;
    	StringBuffer roleBuffy = new StringBuffer();
    	if (request.getUserPrincipal() != null) {
    		Principal principal = request.getUserPrincipal();
    		KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
		    IDToken idToken =  kp.getKeycloakSecurityContext().getIdToken();
		    Set<String> roles = tokenController.getRoles(kp);
		    if (!roles.isEmpty()) {
			    Iterator<String> iterator = roles.iterator();			    
			    roleBuffy.append(iterator.next());
		    	if (iterator.hasNext()) {
		    		roleBuffy.append(" +");
		    	}
		    }
		    role = roleBuffy.toString();
    	}
    	return role;
    }
    
    public String getRoles() {
    	String role = null;
    	StringBuffer roleBuffy = new StringBuffer();
    	if (request.getUserPrincipal() != null) {
    		Principal principal = request.getUserPrincipal();
    		KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
		    IDToken idToken =  kp.getKeycloakSecurityContext().getIdToken();
		    Set<String> roles = tokenController.getRoles(kp);
		    if (!roles.isEmpty()) {
			    Iterator<String> iterator = roles.iterator();			    
			    roleBuffy.append(iterator.next());
		    	if (iterator.hasNext()) {
		    		roleBuffy.append(", ");
		    		roleBuffy.append(iterator.next());
		    	}
		    }
		    role = roleBuffy.toString();
    	}
    	return role;
    }
    
}
 
PF12+, Quarkus 3.2+ (CDI, JPA etc.), JSF Bridge (MyFaces 4.0.1)
Dont forget the classifier:

Code: Select all

   ...primefaces
  <classifier>jakarta</classifier>
     ... theme
  <classifier>jakarta</classifier>

mert.sincan
Posts: 5281
Joined: 29 Jun 2013, 12:38

11 Feb 2020, 14:15

Ok, thanks a lot for the code blocks ;)

Best Regards,

Post Reply

Return to “Avalon - PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 6 guests