<template> <div id="app-header" :class="$route.name" > <div class="menu container"> <div class="ui inverted icon menu"> <router-link :is="isSharedProject ? 'span' : 'router-link'" :to="isSharedProject ? '' : '/'" :class="['header item', {disable: isSharedProject}]" > <img class="ui right spaced image" alt="Logo de l'application" :src="logo" > <span class="desktop"> {{ APPLICATION_NAME }} </span> </router-link> <div v-if="width <= 560 || (width > 560 && project)" id="menu-dropdown" :class="['ui dropdown item', { 'active visible': menuIsOpen }]" @click="menuIsOpen = !menuIsOpen" > <div v-if="!isOnline" class="crossed-out mobile" > <i class="wifi icon" aria-hidden="true" /> </div> <span class="expand-center"> <span v-if="project"> Projet : {{ project.title }} </span> </span> <i class="dropdown icon" aria-hidden="true" /> <div :class="[ 'menu dropdown-list transition', { 'visible': menuIsOpen }, ]" style="z-index: 401" > <router-link v-if="project" :to="{ name: 'project_detail', params: { slug: project.slug }, }" class="item" > <i class="home icon" aria-hidden="true" />Accueil </router-link> <router-link v-if="project" :to="{ name: 'liste-signalements', params: { slug: project.slug }, }" class="item" > <i class="list icon" aria-hidden="true" />Liste & Carte </router-link> <router-link v-if=" project && isOnline && (user.is_administrator || user.is_superuser || isAdmin) " :to="{ name: 'project_mapping', params: { slug: project.slug }, }" class="item" > <i class="map icon" aria-hidden="true" />Fonds cartographiques </router-link> <router-link v-if=" project && isOnline && (user.is_administrator || user.is_superuser || isAdmin) " :to="{ name: 'project_members', params: { slug: project.slug }, }" class="item" > <i class="users icon" aria-hidden="true" />Membres </router-link> <div class="mobile"> <router-link :is="isOnline ? 'router-link' : 'span'" v-if="user" :to="{ name: 'my_account', params: { slug: isSharedProject && $route.params.slug ? $route.params.slug : null } }" class="item" > {{ userFullname || user.username || "Utilisateur inconnu" }} </router-link> <div v-if="USER_LEVEL_PROJECTS && project" class="item ui label vertical no-hover" > <!-- super user rights are higher than others --> {{ user.is_superuser ? 'Administrateur' : USER_LEVEL_PROJECTS[project.slug] }} <br> </div> <div v-if="user && user.is_administrator" class="item ui label vertical no-hover" > Gestionnaire métier </div> <div v-if="!DISABLE_LOGIN_BUTTON" > <a v-if="user" class="item" @click="logout" ><i class="ui logout icon" aria-hidden="true" /> </a> <router-link v-else-if="!user && !SSO_LOGIN_URL" :to="{ name : 'login' }" class="item" > Se connecter </router-link> <a v-else class="item" :href="SSO_LOGIN_URL" target="_self" >Se connecter</a> </div> </div> </div> </div> <div class="desktop flex push-right-desktop item title abstract"> <span> {{ APPLICATION_ABSTRACT }} </span> </div> <div class="desktop flex push-right-desktop"> <div v-if="!isOnline" class="item network-icon" > <span data-tooltip="Vous êtes hors-ligne, vos changements pourront être envoyés au serveur au retour de la connexion" data-position="bottom right" > <div class="crossed-out"> <i class="wifi icon" aria-hidden="true" /> </div> </span> </div> <router-link :is="isOnline ? 'router-link' : 'span'" v-if="user" :to="{ name: 'my_account', params: { slug: isSharedProject && $route.params.slug ? $route.params.slug : null } }" class="item" > {{ userFullname || user.username || "Utilisateur inconnu" }} </router-link> <div v-if="USER_LEVEL_PROJECTS && project" class="item ui label vertical no-hover" > <!-- super user rights are higher than others --> {{ user.is_superuser ? 'Administrateur' : USER_LEVEL_PROJECTS[project.slug] }} <br> </div> <div v-if="user && user.is_administrator" class="item ui label vertical no-hover" > Gestionnaire métier </div> <div v-if="!DISABLE_LOGIN_BUTTON" > <a v-if="user" class="item log-item" @click="logout" ><i class="ui logout icon" aria-hidden="true" /> </a> <router-link v-else-if="!user && !SSO_LOGIN_URL" :to="{ name : 'login' }" class="item log-item" > Se Connecter </router-link> <a v-else class="item log-item" :href="SSO_LOGIN_URL" target="_self" >Se connecter</a> </div> </div> </div> <MessageInfoList /> </div> </div> </template> <script> import { mapState } from 'vuex'; import MessageInfoList from '@/components/MessageInfoList'; export default { name: 'AppHeader', components: { MessageInfoList }, data() { return { menuIsOpen: false, width: window.innerWidth > 0 ? window.innerWidth : screen.width, }; }, computed: { ...mapState([ 'user', 'USER_LEVEL_PROJECTS', 'configuration', 'loader', 'isOnline' ]), ...mapState('projects', [ 'projects', 'project', ]), APPLICATION_NAME() { return this.configuration.VUE_APP_APPLICATION_NAME; }, APPLICATION_ABSTRACT() { return this.configuration.VUE_APP_APPLICATION_ABSTRACT; }, DISABLE_LOGIN_BUTTON() { return this.configuration.VUE_APP_DISABLE_LOGIN_BUTTON; }, SSO_LOGIN_URL() { if (this.configuration.VUE_APP_LOGIN_URL) { // add a next parameter with the pathname as expected by OGS to redirect after login return `${this.configuration.VUE_APP_LOGIN_URL}/?next=${encodeURIComponent(window.location.pathname)}`; } return null; }, logo() { return this.configuration.VUE_APP_LOGO_PATH; }, userFullname() { if (this.user.first_name || this.user.last_name) { return `${this.user.first_name} ${this.user.last_name}`; } return null; }, isAdmin() { return this.USER_LEVEL_PROJECTS && this.USER_LEVEL_PROJECTS[this.project.slug] === 'Administrateur projet' ? true : false; }, isSharedProject() { return this.$route.path.includes('projet-partage'); } }, created() { window.addEventListener('mousedown', this.clickOutsideMenu); }, beforeDestroy() { window.removeEventListener('mousedown', this.clickOutsideMenu); }, methods: { logout() { this.$store.dispatch('LOGOUT'); }, clickOutsideMenu(e) { if (e.target.closest && !e.target.closest('#menu-dropdown')) { this.menuIsOpen = false; } }, } }; </script> <style lang="less" scoped> .menu.container .header { padding-top: 5px !important; padding-bottom: 5px !important; &> img { max-height: 30px; } } .vertical { flex-direction: column; justify-content: center; } .flex { display: flex; } /* keep above loader */ #menu-dropdown { z-index: 1001; } .expand-center { width: 100%; text-align: center; } .network-icon { padding: .5rem !important; } .crossed-out { position: relative; padding: .2em; &::before { content: ""; position: absolute; top: 45%; left: -8%; width: 100%; border-top: 2px solid #ee2e24; transform: rotate(45deg); box-shadow: 0px 0px 0px 1px #373636; border-radius: 3px; } } @media screen and (max-width: 1110px) { .abstract{ display: none !important; } } @media screen and (min-width: 726px) { .mobile { display: none !important; } #app-header { min-width: 560px; } .menu.container { width: auto !important; } .push-right-desktop { margin-left: auto; } } @media screen and (max-width: 725px) { .desktop { display: none !important; } div.dropdown-list { width: 100vw; } .menu.container .header { //width: 70px; width: 100%; } #app-header:not(.index) { /* make the logo disappear on scroll */ position: sticky; top: -90px; height: 80px; .menu.container { /* make the logo disappear on scroll */ height: 30px; position: sticky; top: 0; } } .menu.container .header > img { margin: 0; margin: auto; max-width: 100%; } #menu-dropdown { width: 100%; } #menu-dropdown > span { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } } .menu.container { position: relative; } .disable:hover { cursor: default !important; background-color: #373636 !important; } /* keep above map controls or buttons */ #app-header { z-index: 9999; .menu.container .ui.inverted.icon.menu { /* avoid adding space when messages are displayed */ margin: 0; display: flex; flex-wrap: wrap; } } .ui.menu .ui.dropdown .menu { .item.no-hover:hover { cursor: auto !important; background: white !important; } } /* copy style to apply inside nested div */ .ui.menu .ui.dropdown .menu .item { margin: 0; text-align: left; font-size: 1em !important; padding: 0.78571429em 1.14285714em !important; background: 0 0 !important; color: #252525 !important; text-transform: none !important; font-weight: 400 !important; box-shadow: none !important; transition: none !important; } .item.title::before { background: none !important; } .log-item { height: 100% !important; } </style>