Skip to content
Snippets Groups Projects
App.vue 12.7 KiB
Newer Older
DESPRES Damien's avatar
DESPRES Damien committed
    <script
      type="application/javascript"
      :src="
        baseUrl +
          'resources/leaflet-control-geocoder-1.13.0/Control.Geocoder.js'
DESPRES Damien's avatar
DESPRES Damien committed
      "
Timothee P's avatar
Timothee P committed
      <div class="menu container">
            :is="isSharedProject ? 'span' : 'router-link'"
            :to="isSharedProject ? '' : '/'"
            :class="['header item', {disable: isSharedProject}]"
          >
Timothee P's avatar
Timothee P committed
            <img
              class="ui mini right spaced image"
              :src="logo"
            >
            <span class="desktop">
              {{ APPLICATION_NAME }}
            </span>
            v-if="width <= 560 || (width > 560 && project)"
            :class="['ui dropdown item', { 'active visible': menuIsOpen }]"
            <!-- empty span to occupy space for style if no project -->
            <span>
              <span v-if="project"> Projet : {{ project.title }} </span>
            </span>
            <i class="dropdown icon" />
              :class="[
                'menu dropdown-list',
                { 'visible transition': menuIsOpen },
              ]"
                :to="{
                  name: 'project_detail',
                  params: { slug: project.slug },
                }"
                class="item"
              >
                <i class="home icon" />Accueil
                v-if="project"
                :to="{
                  name: 'liste-signalements',
                  params: { slug: project.slug },
                }"
                class="item"
              >
                <i class="list icon" />Liste & Carte
                  project && isOnline &&
                    (user.is_administrator || user.is_superuser || isAdmin)
                :to="{
                  name: 'project_mapping',
                  params: { slug: project.slug },
                }"
                class="item"
              >
                <i class="map icon" />Fonds cartographiques
                    (user.is_administrator || user.is_superuser || isAdmin)
                :to="{
                  name: 'project_members',
                  params: { slug: project.slug },
                }"
                class="item"
              >
                <i class="users icon" />Membres
              <div class="mobile">
                <router-link
                  :is="isOnline ? 'router-link' : 'span'"
                  v-if="user"
Timothee P's avatar
Timothee P committed
                  :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"
                >
                  {{ USER_LEVEL_PROJECTS[project.slug] }}
                <div
                  v-if="user && user.is_administrator"
                  class="item ui label vertical no-hover"
                  Gestionnaire métier
                </div>
                <div
                  v-if="!DISABLE_LOGIN_BUTTON"
                  v-frag
                >
                  <a
                    v-if="user"
                    class="item"
                    @click="logout"
                  ><i class="ui logout icon" />
                  </a>
                  <router-link
                    v-else-if="!user && !SSO_LOGIN_URL"
                    :to="{ name : 'login' }"
                    Se connecter
                  </router-link>
                  <a
                    v-else
                    class="item"
                    :href="SSO_LOGIN_URL"
                  >Se connecter</a>
Florent Lavelle's avatar
Florent Lavelle committed
          <div class="desktop flex push-right-desktop item title">
            <span>
              {{ APPLICATION_ABSTRACT }}
            </span>
          </div>

          <div class="desktop flex push-right-desktop">
Timothee P's avatar
Timothee P committed
            <router-link
              :is="isOnline ? 'router-link' : 'span'"
Timothee P's avatar
Timothee P committed
              v-if="user"
Timothee P's avatar
Timothee P committed
              :to="{
                name: 'my_account',
                params: { slug: isSharedProject && $route.params.slug ? $route.params.slug : null }
              }"
Timothee P's avatar
Timothee P committed
            >
              {{ userFullname || user.username || "Utilisateur inconnu" }}
            </router-link>
            <div
              v-if="USER_LEVEL_PROJECTS && project"
              class="item ui label vertical no-hover"
            >
              {{ USER_LEVEL_PROJECTS[project.slug] }}
            <div
              v-if="user && user.is_administrator"
              class="item ui label vertical no-hover"
              Gestionnaire métier
            </div>
            <div
              v-if="!DISABLE_LOGIN_BUTTON"
              v-frag
            >
              <a
                v-if="user"
                class="item"
                @click="logout"
              ><i class="ui logout icon" />
              </a>
              <router-link
                v-else-if="!user && !SSO_LOGIN_URL"
                :to="{ name : 'login' }"
                Se Connecter
              </router-link>
              <a
                v-else
                class="item"
                :href="SSO_LOGIN_URL"
              >Se connecter</a>
      <div
        id="content"
        class="ui stackable grid centered container"
      >
Timothee P's avatar
Timothee P committed
        <transition name="fadeDownUp">
Timothee P's avatar
Timothee P committed
          <div
            v-if="messages && messages.length > 0"
            class="row over-content"
          >
            <div class="fourteen wide column">
              <div
                v-for="(message, index) in messages"
                :key="'message-' + index"
                :class="['ui', message.level ? message.level : 'info', 'message']"
              >
                <i
                  class="close icon"
                  @click="DISCARD_MESSAGE(message)"
                />
                <div class="header">
                  <i class="info circle icon" />
                  Informations
Timothee P's avatar
Timothee P committed
                </div>
                <ul class="list">
                  {{
                    message.comment
                  }}
                </ul>
        <div
          :class="{ active: loader.isLoading }"
          class="ui inverted dimmer"
        >
          <div class="ui text loader">
            {{ loader.message }}
          </div>
        </div>
        <router-view />
        <!-- //* Les views sont injectées ici -->
      </div>
    </main>

    <footer>
      <div class="ui compact text menu">
Timothee P's avatar
Timothee P committed
        <router-link
          :to="{name: 'mentions'}"
          class="item"
        >
          Mentions légales
        </router-link>
        <router-link
          :to="{name: 'aide'}"
          class="item"
        >
          Aide
        </router-link>
        <p class="item">
          Version {{ PACKAGE_VERSION }}
        </p>
Timothee P's avatar
Timothee P committed
import frag from 'vue-frag';
import { mapMutations, mapState } from 'vuex';
  name: 'App',
DESPRES Damien's avatar
DESPRES Damien committed
      baseUrl: this.$store.state.configuration.BASE_URL,
      width: window.innerWidth > 0 ? window.innerWidth : screen.width,
    ...mapState([
Timothee P's avatar
Timothee P committed
      'user',
      'USER_LEVEL_PROJECTS',
      'configuration',
      'messages',
      'loader',
Florent Lavelle's avatar
Florent Lavelle committed
    ...mapState('projects', [
Florent Lavelle's avatar
Florent Lavelle committed
    ]),
    APPLICATION_NAME() {
Timothee P's avatar
Timothee P committed
      return this.configuration.VUE_APP_APPLICATION_NAME;
    },
Florent Lavelle's avatar
Florent Lavelle committed
    APPLICATION_ABSTRACT() {
      return this.$store.state.configuration.VUE_APP_APPLICATION_ABSTRACT;
    },
    DISABLE_LOGIN_BUTTON() {
      return this.configuration.VUE_APP_DISABLE_LOGIN_BUTTON;
    },
    SSO_LOGIN_URL() {
      return this.configuration.VUE_APP_LOGIN_URL;
    },
    PACKAGE_VERSION: () => process.env.PACKAGE_VERSION || '0',
    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;
    isAdmin() {
      return this.USER_LEVEL_PROJECTS &&
        this.USER_LEVEL_PROJECTS[this.project.slug] === 'Administrateur projet'
    isSharedProject() {
      return this.$route.path.includes('projet-partage');
    }
  created() {
    window.addEventListener('mousedown', this.clickOutsideMenu);
  },

  beforeDestroy() {
    window.removeEventListener('mousedown', this.clickOutsideMenu);
  },

    ...mapMutations(['DISCARD_MESSAGE']),
      this.$store.dispatch('LOGOUT');
      if (e.target.closest && !e.target.closest('#menu-dropdown'))
        this.menuIsOpen = false;
    },
  },
};
</script>

<style>
@import "./assets/styles/base.css";
@import "./assets/resources/semantic-ui-2.4.2/semantic.min.css";

body {
  height: 100vh;
  margin: 0;
}

header {
  min-height: 61px;
}
footer {
  min-height: 40px;
}

/* Trick */
body {
  display: flex;
  flex-direction: column;
}

/* to display loader between header and footer */
main {
  position: relative;
}

footer {
  margin-top: auto;
}

.vertical {
  flex-direction: column;
  justify-content: center;
}
.flex {
  display: flex;
}

/* keep above loader */
#menu-dropdown {
  z-index: 1001;
}

@media screen and (min-width: 560px) {
  .mobile {
    display: none !important;
  }
  .header-menu {
    min-width: 560px;
  }
  .menu.container {
    width: auto !important;
  }
  .push-right-desktop {
    margin-left: auto;
  }
}
@media screen and (max-width: 560px) {
  .desktop {
    display: none !important;
  }
    left: -70px !important; /* should be the same than belows */
  .menu.container a.header {
    width: 70px;
  }
  .menu.container a.header > img {
    margin: 0;
  }
  #menu-dropdown {
    width: calc(100vw - 70px);
    justify-content: space-between;
  }
  #menu-dropdown > span {
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
}

.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;
}
Florent Lavelle's avatar
Florent Lavelle committed
.item.title::before {
  background: none !important;
}

.ui.grid > .row.over-content {
  position: absolute;
  z-index: 99;
  opacity: 0.95;
Timothee P's avatar
Timothee P committed
.fadeDownUp-enter-active {
  animation: fadeInDown .5s;
}
Timothee P's avatar
Timothee P committed
.fadeDownUp-leave-active {
  animation: fadeOutUp .5s;
}
@keyframes fadeOutUp {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    transform: translate3d(0, -100%, 0);
  }
}

@keyframes fadeInDown {
  from {
    opacity: 0;
    transform: translate3d(0, -100%, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

.ui.message > .close.icon {
  cursor: pointer;
  position: absolute;
  margin: 0em;
  top: 0.78575em;
  right: 0.5em;
  opacity: 0.7;
  -webkit-transition: opacity 0.1s ease;
  transition: opacity 0.1s ease;
}

 
 <style scoped>
 .disable:hover {
   cursor: default !important;
   background-color: #373636 !important;
 }
 </style>