Forráskód Böngészése

V8-3857 menu de gauche, maj config vuetify

Olivier Massot 3 éve
szülő
commit
180aebdf5a
76 módosított fájl, 407 hozzáadás és 379 törlés
  1. 9 43
      assets/css/global.scss
  2. 3 3
      components/Layout/BannerTop.vue
  3. 3 3
      components/Layout/Dialog.vue
  4. 5 5
      components/Layout/Header.vue
  5. 5 5
      components/Layout/Header/Menu.vue
  6. 5 5
      components/Layout/Header/Notification.vue
  7. 3 3
      components/Layout/Header/UniversalCreation/CreateButton.vue
  8. 3 3
      components/Layout/Header/UniversalCreation/GenerateCardsSteps.vue
  9. 3 3
      components/Layout/Header/UniversalCreation/TypeCard.vue
  10. 177 0
      components/Layout/MainMenu.vue
  11. 0 151
      components/Layout/Menu.vue
  12. 3 3
      components/Layout/SubHeader/ActivityYear.vue
  13. 3 3
      components/Layout/SubHeader/DataTiming.vue
  14. 2 2
      components/Layout/SubHeader/DataTimingRange.vue
  15. 2 2
      components/Layout/SubHeader/PersonnalizedList.vue
  16. 2 2
      components/Layout/Subheader.vue
  17. 3 3
      components/Ui/Button/Delete.vue
  18. 1 1
      components/Ui/Button/Submit.vue
  19. 2 2
      components/Ui/Collection.vue
  20. 1 1
      components/Ui/DataTable.vue
  21. 2 2
      components/Ui/ExpansionPanel.vue
  22. 5 5
      components/Ui/Form.vue
  23. 1 1
      components/Ui/Input/Autocomplete.vue
  24. 1 1
      components/Ui/Input/DatePicker.vue
  25. 0 3
      components/Ui/Input/Enum.vue
  26. 3 3
      components/Ui/Input/Image.vue
  27. 2 2
      composables/data/useAp2iRequestService.ts
  28. 1 1
      composables/data/useEntityFetch.ts
  29. 1 1
      composables/data/useEnumFetch.ts
  30. 1 1
      composables/data/useImageFetch.ts
  31. 4 2
      composables/layout/useMenuBuilder.ts
  32. 3 7
      layouts/default.vue
  33. 1 1
      nuxt.config.ts
  34. 1 0
      pages/index.vue
  35. 6 6
      pages/organization/index.vue
  36. 6 0
      pages/poc.vue
  37. 1 1
      pages/poc/index.vue
  38. 1 1
      plugins/vuetify.ts
  39. 2 1
      services/data/apiRequestService.ts
  40. 2 1
      services/data/serializer/denormalizer/hydraDenormalizer.ts
  41. 1 1
      services/data/serializer/denormalizer/yamlDenormalizer.ts
  42. 11 11
      services/menuBuilder/abstractMenuBuilder.ts
  43. 2 1
      services/menuBuilder/accessMenuBuilder.ts
  44. 2 1
      services/menuBuilder/accountMenuBuilder.ts
  45. 2 1
      services/menuBuilder/admin2iosMenuBuilder.ts
  46. 2 1
      services/menuBuilder/agendaMenuBuilder.ts
  47. 2 1
      services/menuBuilder/billingMenuBuilder.ts
  48. 2 1
      services/menuBuilder/communicationMenuBuilder.ts
  49. 2 1
      services/menuBuilder/configurationMenuBuilder.ts
  50. 2 1
      services/menuBuilder/cotisationsMenuBuilder.ts
  51. 2 1
      services/menuBuilder/donorsMenuBuilder.ts
  52. 2 1
      services/menuBuilder/educationalMenuBuilder.ts
  53. 2 1
      services/menuBuilder/equipmentMenuBuilder.ts
  54. 1 1
      services/menuBuilder/mainMenuBuilder.ts
  55. 6 2
      services/menuBuilder/medalsMenuBuilder.ts
  56. 2 1
      services/menuBuilder/myAccessesMenuBuilder.ts
  57. 2 1
      services/menuBuilder/myFamilyMenuBuilder.ts
  58. 2 1
      services/menuBuilder/parametersMenuBuilder.ts
  59. 2 1
      services/menuBuilder/statsMenuBuilder.ts
  60. 2 1
      services/menuBuilder/websiteAdminMenuBuilder.ts
  61. 2 1
      services/menuBuilder/websiteListMenuBuilder.ts
  62. 1 1
      services/profile/accessProfile.ts
  63. 1 1
      services/profile/organizationProfile.ts
  64. 1 1
      services/rights/abilitiesUtils.ts
  65. 1 1
      services/rights/roleUtils.ts
  66. 1 1
      services/utils/objectUtils.ts
  67. 2 2
      store/form.ts
  68. 1 1
      store/page.ts
  69. 2 6
      tsconfig.json
  70. 0 12
      types/data.d.ts
  71. 11 0
      types/enum/data.ts
  72. 0 0
      types/enum/enums.ts
  73. 7 0
      types/enum/layout.ts
  74. 2 2
      types/interfaces.d.ts
  75. 45 0
      types/layout.d.ts
  76. 0 36
      types/menus.d.ts

+ 9 - 43
assets/css/global.scss

@@ -1,4 +1,4 @@
-header .v-toolbar__content{
+header .v-toolbar__content {
   padding-right: 0;
 }
 
@@ -9,70 +9,36 @@ header .v-toolbar__content{
   z-index: 1;
 }
 
-.no-decoration{
+.no-decoration {
   text-decoration: none !important;
   color: inherit !important;
 }
 
-.v-application a{
-  color: var(--v-ot_green-base, white)
+.v-application a {
+  color: rgb(var(--v-theme-ot-green))
 }
 
-.v-menu__content{
+.v-menu__content {
   z-index: 400 !important;
 }
 
-.toolbarForm .v-toolbar__content{
+.toolbarForm .v-toolbar__content {
   padding-left: 0 !important;
 }
 
-.toolbarForm .v-toolbar__title .v-icon{
+.toolbarForm .v-toolbar__title .v-icon {
   height: 46px;
   width: 46px;
 }
 
-.left-menu > div > .v-list-group--no-action > .v-list-group__header,
-.left-menu > div > .v-list-item
-{
-  border-left:3px solid var(--v-ot_dark_grey-base, white);
-  height: 48px;
-}
-
-.left-menu > div > .v-list-group--no-action > .v-list-group__header:hover,
-.left-menu > div > .v-list-group--no-action > .v-list-item--active,
-.left-menu > div > .v-list-group--no-action > .v-list-group__items,
-.left-menu > div > .v-list-item:hover,
-.left-menu > div > .v-list-item--active
-{
-  border-left:3px solid var(--v-ot_green-base, white);
-  background: var(--v-ot_dark_grey_hover-base, white);
-}
-
-.left-menu > div > .v-list-group--no-action > .v-list-group__header:hover > .v-list-item__action > .v-icon,
-.left-menu > div > .v-list-group--no-action > .v-list-group__header:hover > .v-list-item__content > .v-list-item__title,
-.left-menu > div > .v-list-group--no-action > .v-list-item--active > .v-list-item__action > .v-icon,
-.left-menu > div > .v-list-group--no-action > .v-list-item--active > .v-list-item__content > .v-list-item__title,
-.left-menu > div > .v-list-group--no-action > .v-list-group__items > .v-list-item__action,
-.left-menu > div > .v-list-item:hover > .v-list-item__action > .v-icon,
-.left-menu > div > .v-list-item:hover > .v-list-item__content > .v-list-item__title,
-{
-  color: var(--v-ot_white-base, white) !important;
-
-}
-
-.left-menu > div > .v-list-group--no-action > .v-list-item--active,
-.left-menu > div > .v-list-group--no-action > .v-list-group__items{
-  background: var(--v-ot_dark_grey_hover-base, white);
-}
-
-.header-menu{
+.header-menu {
   max-height: 300px;
   min-width: 300px;
   overflow-y: auto;
   .v-list{
     .v-list-item{
       border-bottom: 1px solid;
-      border-bottom-color: var(--v-ot_border_menu-base, white);
+      border-bottom-color: rgb(var(--v-theme-ot-border-menu));
     }
   }
 }

+ 3 - 3
components/Layout/BannerTop.vue

@@ -2,13 +2,13 @@
 
 <template>
   <v-row justify="center" align="center" class="bannerTopForm">
-    <v-col cols="3" class="ot_dark_grey ot_white--text">
+    <v-col cols="3" class="ot-dark_grey ot-white--text">
       <slot name="block1" />
     </v-col>
-    <v-col cols="6" class="ot_white ot_grey--text">
+    <v-col cols="6" class="ot-white ot-grey--text">
       <slot name="block2" />
     </v-col>
-    <v-col cols="3" class="ot_light_grey ot_grey--text">
+    <v-col cols="3" class="ot-light_grey ot-grey--text">
       <slot name="block3" />
     </v-col>
   </v-row>

+ 3 - 3
components/Layout/Dialog.vue

@@ -54,7 +54,7 @@ const props = defineProps({
     font-weight: normal;
   }
   .dialog-type{
-    background: var(--v-ot_green-base, #00AD8E);
+    background: var(--v-theme-ot-green, #00AD8E);
     color: #fff;
     width: 160px;
    h3{
@@ -74,12 +74,12 @@ const props = defineProps({
   }
   .modal-level-alert{
     .dialog-type{
-      background: var(--v-ot_danger-base, #f56954);
+      background: var(--v-theme-ot-danger, #f56954);
     }
   }
   .modal-level-warning{
     .dialog-type{
-      background: var(--v-ot_warning-base, #f39c12);
+      background: var(--v-theme-ot-warning, #f39c12);
     }
   }
 </style>

+ 5 - 5
components/Layout/Header.vue

@@ -10,19 +10,19 @@ et aux préférences de l'utilisateur
     dense
     fixed
     app
-    class="ot_green ot_white--text"
+    class="ot-green ot-white--text"
   >
     <v-btn
       v-if="displayedMiniVariant"
       class="menu-btn d-none d-sm-none d-sm-none d-md-none d-lg-flex" icon @click.stop="displayedMiniMenu()"
     >
-      <v-icon class="ot_white--text">
+      <v-icon class="ot-white--text">
         mdi-menu{{ `${properties.miniVariant ? '' : '-open'}` }}
       </v-icon>
     </v-btn>
 
     <v-btn class="menu-btn d-sm-flex d-md-flex d-lg-none" icon @click.stop="displayedMenu()">
-      <v-icon class="ot_white--text">
+      <v-icon class="ot-white--text">
         mdi-menu
       </v-icon>
     </v-btn>
@@ -41,7 +41,7 @@ et aux préférences de l'utilisateur
           v-bind="attrs"
           v-on="on"
         >
-          <a class="no-decoration" :href="properties.homeUrl + '/'"><v-icon class="ot_white--text" small>fa-home</v-icon></a>
+          <a class="no-decoration" :href="properties.homeUrl + '/'"><v-icon class="ot-white--text" small>fa-home</v-icon></a>
         </v-btn>
       </template>
       <span>{{ $t('welcome') }}</span>
@@ -59,7 +59,7 @@ et aux préférences de l'utilisateur
 
     <LayoutHeaderMenu :menu="accountMenu"/>
 
-    <a class="text-body pa-3 ml-2 ot_dark_grey ot_white--text text-decoration-none" href="https://support.opentalent.fr/" target="_blank">
+    <a class="text-body pa-3 ml-2 ot-dark_grey ot-white--text text-decoration-none" href="https://support.opentalent.fr/" target="_blank">
       <span class="d-none d-sm-none d-md-flex">{{ $t('help_access') }}</span>
       <v-icon class="d-sm-flex d-md-none" color="white">fas fa-question-circle</v-icon>
     </a>

+ 5 - 5
components/Layout/Header/Menu.vue

@@ -21,7 +21,7 @@ header principal (configuration, paramètres du compte...)
             >
               <UiImage :id="menu.icon.avatarId" :imageByDefault="menu.icon.avatarByDefault" :width="30"></UiImage>
             </v-avatar>
-            <v-icon  v-else class="ot_white--text" small>
+            <v-icon  v-else class="ot-white--text" small>
               {{ menu.icon.name }}
             </v-icon>
           </v-btn>
@@ -30,7 +30,7 @@ header principal (configuration, paramètres du compte...)
       </v-tooltip>
     </template>
     <v-card scrollable>
-      <v-card-title class="ot_header_menu text-body-2 font-weight-bold">
+      <v-card-title class="ot-header_menu text-body-2 font-weight-bold">
         {{$t(menu.title)}}
       </v-card-title>
       <v-card-text class="ma-0 pa-0 header-menu">
@@ -52,7 +52,7 @@ header principal (configuration, paramètres du compte...)
                   >
                     <UiImage :id="item.icon.avatarId" :imageByDefault="item.icon.avatarByDefault" :width="30"></UiImage>
                   </v-avatar>
-                  <v-icon v-else class="ot_white--text" small>
+                  <v-icon v-else class="ot-white--text" small>
                     {{ item.icon.name }}
                   </v-icon>
                 </span>
@@ -71,7 +71,7 @@ header principal (configuration, paramètres du compte...)
             :to="!item.isExternalLink ? item.to : undefined"
             router
           >
-            <v-list-item-title class="text-body-2 ot_white--text" v-text="$t(item.title)"/>
+            <v-list-item-title class="text-body-2 ot-white--text" v-text="$t(item.title)"/>
           </v-list-item>
         </template>
       </v-card-actions>
@@ -96,7 +96,7 @@ export default defineComponent({
 </script>
 <style scoped>
   #logout{
-    background: var(--v-ot_green-base, white);
+    background: var(--v-theme-ot-green, white);
     color: white;
   }
 </style>

+ 5 - 5
components/Layout/Header/Notification.vue

@@ -16,7 +16,7 @@
               :value="unreadNotification.length > 0"
               :content="unreadNotification.length"
             >
-              <v-icon class="ot_white--text" small>
+              <v-icon class="ot-white--text" small>
                 fa-bell
               </v-icon>
             </v-badge>
@@ -26,7 +26,7 @@
       </v-tooltip>
     </template>
     <v-card scrollable max-width="400">
-      <v-card-title class="ot_header_menu text-body-2 font-weight-bold">
+      <v-card-title class="ot-header_menu text-body-2 font-weight-bold">
         {{ $t('notification') }}
       </v-card-title>
       <v-card-text class="ma-0 pa-0 header-menu">
@@ -64,7 +64,7 @@
             :href="notificationUrl"
             router
           >
-            <v-list-item-title class="text-body-2 ot_white--text" v-text="$t('all_notification')"/>
+            <v-list-item-title class="text-body-2 ot-white--text" v-text="$t('all_notification')"/>
           </v-list-item>
         </template>
       </v-card-actions>
@@ -74,7 +74,7 @@
 
 <script lang="ts">
 import {computed, ComputedRef, defineComponent, onUnmounted, Ref, ref, useContext, useFetch, watch} from '@nuxtjs/composition-api'
-import {NOTIFICATION_TYPE, QUERY_TYPE} from "~/types/enums";
+import {NOTIFICATION_TYPE, QUERY_TYPE} from "~/types/enum/enums";
 import {Notification} from "~/models/Core/Notification";
 import {repositoryHelper} from "~/services/store/repository";
 import {ApiResponse, HydraMetadata} from "~/types/interfaces";
@@ -250,7 +250,7 @@ export default defineComponent({
 
 <style scoped>
   #all_notifications{
-    background: var(--v-ot_green-base, white);
+    background: var(--v-theme-ot-green, white);
     color: white;
   }
   .list_item{

+ 3 - 3
components/Layout/Header/UniversalCreation/CreateButton.vue

@@ -6,7 +6,7 @@ bouton Créer
   <main>
     <v-btn
       elevation="2"
-      color="ot_warning ot_white--text"
+      color="ot-warning ot-white--text"
       @click="showDialog=true"
     >
       {{ $t('create') }}
@@ -28,14 +28,14 @@ bouton Créer
       <template #dialogBtn>
         <div class="text-center">
           <v-btn
-            color="ot_super_light_grey"
+            color="ot-super_light_grey"
             @click="showDialog=false;step=1;type='home'"
           >
             {{ $t('cancel') }}
           </v-btn>
           <v-btn
             v-if="step > 1"
-            color="ot_super_light_grey"
+            color="ot-super_light_grey"
             @click="step=1;type='home'"
           >
             {{ $t('previous') }}

+ 3 - 3
components/Layout/Header/UniversalCreation/GenerateCardsSteps.vue

@@ -120,14 +120,14 @@ export default defineComponent({
     .icon{
       i{
         font-size: 50px;
-        color: var(--v-ot_grey-base, #777777);
+        color: var(--v-theme-ot-grey, #777777);
       }
     }
     .infos-container{
       padding: 15px 0;
       h4{
         font-size: 15px;
-        color: var(--v-ot_green-base, #00AD8E);
+        color: var(--v-theme-ot-green, #00AD8E);
         font-weight: bold;
         margin-bottom: 6px;
       }
@@ -141,7 +141,7 @@ export default defineComponent({
     &>div{
       &:hover{
         cursor: pointer;
-        background: var(--v-ot_light_green-base, #a9e0d6);
+        background: var(--v-theme-ot-light_green, #a9e0d6);
       }
     }
   }

+ 3 - 3
components/Layout/Header/UniversalCreation/TypeCard.vue

@@ -62,14 +62,14 @@ export default defineComponent({
   .icon{
     i{
       font-size: 50px;
-      color: var(--v-ot_grey-base, #777777);
+      color: var(--v-theme-ot-grey, #777777);
     }
   }
   .infos-container{
     padding: 15px 0;
     h4{
       font-size: 15px;
-      color: var(--v-ot_green-base, #00AD8E);
+      color: var(--v-theme-ot-green, #00AD8E);
       font-weight: bold;
       margin-bottom: 6px;
     }
@@ -83,7 +83,7 @@ export default defineComponent({
   &>div{
     &:hover{
       cursor: pointer;
-      background: var(--v-ot_light_green-base, #a9e0d6);
+      background: var(--v-theme-ot-light_green, #a9e0d6);
     }
   }
 

+ 177 - 0
components/Layout/MainMenu.vue

@@ -0,0 +1,177 @@
+<!--
+Menu principal de l'application
+Prend en paramètre une liste de ItemMenu et les met en forme
+-->
+
+<template>
+  <v-navigation-drawer
+    :mini-variant.sync="miniVariant"
+    v-model="open"
+    class="bg-ot-dark-grey text-ot-menu-color main-menu"
+  >
+    <template #prepend>
+      <slot name="title"></slot>
+    </template>
+
+    <v-list
+        open-strategy="single"
+        active-class="active"
+        class="left-menu"
+    >
+      <div v-for="(item, i) in menu.children" :key="i">
+
+        <!-- Cas 1 : l'item n'a pas d'enfants, c'est un lien -->
+        <v-list-item
+          v-if="!item.children"
+          :title="$t(item.label)"
+          :prepend-icon="item.icon.name"
+          :href="!isInternalLink(item) ? item.to : undefined"
+          :to="isInternalLink(item) ? item.to : undefined"
+          exact
+          class="text-ot-menu-color"
+          height="48px"
+        ></v-list-item>
+
+        <!-- Cas 2 : l'item a des enfants, c'est un groupe -->
+        <v-list-group
+          v-else
+          expand-icon="fas fa-angle-right"
+          collapse-icon="fas fa-angle-down"
+          class="text-ot-menu-color"
+          v-model="item.expanded"
+        >
+          <template #activator="{ props }">
+            <v-list-item
+                v-bind="props"
+                :prepend-icon="item.icon.name"
+                :title="$t(item.label)"
+                class="text-ot-menu-color"
+                height="48px"
+            ></v-list-item>
+          </template>
+
+          <v-list-item
+            v-for="child in item.children"
+            :key="$t(child.label)"
+            :title="$t(child.label)"
+            :prepend-icon="child.icon.name"
+            :href="!isInternalLink(child) ? child.to : undefined"
+            :to="isInternalLink(child) ? child.to : undefined"
+            exact
+            height="48px"
+            class="text-ot-white"
+          ></v-list-item>
+        </v-list-group>
+      </div>
+    </v-list>
+
+    <template #append>
+      <slot name="foot"></slot>
+    </template>
+  </v-navigation-drawer>
+
+</template>
+
+<script setup lang="ts">
+import {onUnmounted, watch, WatchStopHandle} from "@vue/runtime-core";
+import {ref, toRefs} from "@vue/reactivity";
+import {MenuGroup, MenuItem} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
+
+const props = defineProps({
+  menu: {
+    type: Object as () => MenuGroup,
+    required: true
+  },
+  miniVariant: {
+    type: Boolean,
+    required: true
+  },
+  openMenu: {
+    type: Boolean,
+    required: true
+  }
+})
+
+const { openMenu } = toRefs(props)
+const open = ref(true)
+
+
+// Par défaut si l'écran est trop petit au chargement de la page, le menu doit être fermé.
+if(process.client)
+  open.value = window.innerWidth >= 1264
+
+// TODO : ajouter une petite explication de ce qu'on fait dans ce watch
+const unwatch: WatchStopHandle = watch(openMenu, (newValue, oldValue) => {
+  if (newValue !== oldValue) {
+    open.value = true
+  }
+})
+
+const isInternalLink = (menuItem: MenuItem | MenuGroup) => {
+  return 'type' in menuItem && menuItem.type === MENU_LINK_TYPE.INTERNAL
+}
+
+onUnmounted(() => {
+  unwatch()
+})
+</script>
+
+<style scoped lang="scss">
+
+  .v-list-item {
+    min-height: 10px !important;
+  }
+
+  :deep(.v-list-item-title),
+  :deep(.v-icon),
+  {
+    font-size: 14px;
+    color: rgb(var(--v-theme-ot-menu-color));
+  }
+
+  .v-list-item__prepend {
+    margin: 10px 0;
+    margin-right: 10px !important;
+  }
+
+  .v-application--is-ltr .v-list-group--no-action > .v-list-group__header {
+    margin-left: 0;
+    padding-left: 0;
+  }
+  .v-application--is-ltr .v-list-group--no-action > .v-list-group__items > .v-list-item {
+    padding-left: 30px;
+  }
+
+  .v-list-item__content {
+    padding: 8px 0;
+  }
+
+  .v-list-group__items .v-list-item {
+    padding-inline-start: 30px !important;
+  }
+
+  .v-list-group--no-action > .v-list-group__header,
+  .v-list-item
+  {
+    border-left:3px solid rgb(var(--v-theme-ot-dark-grey));
+    height: 48px;
+  }
+
+  .v-list-item:hover,
+  .v-list-item.active,
+  :deep(.v-list-group__items .v-list-item)
+  {
+    border-left: 3px solid rgb(var(--v-theme-ot-green));
+    background: rgb(var(--v-theme-ot-dark-grey-hover));
+  }
+
+  :deep(.v-list-group__items .v-list-item-title) {
+    color: rgb(var(--v-theme-ot-white));
+  }
+
+  :deep(.v-list-item .v-icon) {
+    margin-right: 10px;
+  }
+
+</style>

+ 0 - 151
components/Layout/Menu.vue

@@ -1,151 +0,0 @@
-<!--
-Menu principal de l'application
-Prend en paramètre une liste de ItemMenu et les met en forme
--->
-
-<template>
-  <v-navigation-drawer
-    :mini-variant.sync="miniVariant"
-    v-model="open"
-    class="bg-ot-dark-grey text-ot-menu-color"
-  >
-    <template #prepend>
-      <slot name="title"></slot>
-    </template>
-
-    <v-list class="left-menu">
-      <div v-for="(item, i) in menu.children" :key="i">
-        <!-- Cas 1 : l'item n'a pas d'enfants, c'est un lien -->
-        <v-list-item
-          v-if="!item.children"
-          :href="isExternalLink(item) ? item.to : undefined"
-          :to="!isExternalLink(item) ? item.to : undefined"
-          exact
-        >
-          <template v-slot:prepend>
-            <v-list-item-action start>
-              <v-icon :icon="item.icon.name" class="text-ot-menu-color" small />
-            </v-list-item-action>
-          </template>
-
-          <v-list-item-title
-              v-text="item.title"
-              class="text-ot-menu-color"
-          />
-        </v-list-item>
-
-        <!-- Cas 2 : l'item a des enfants, c'est un groupe -->
-        <v-list-group
-          v-else
-          v-model="item.active"
-        >
-          <template #activator>
-              <v-list-item-action>
-                <v-icon :icon="item.icon.name" class="text-ot-menu-color" small />
-              </v-list-item-action>
-            <v-list-item-title class="text-ot-menu-color" v-text="item.title" />
-          </template>
-
-          <v-list-item
-            v-for="child in item.children"
-            :key="child.label"
-            :href="isExternalLink(child) ? child.to : undefined"
-            :to="!isExternalLink(child) ? child.to : undefined"
-            router
-            exact
-          >
-            <v-list-item-action>
-              <v-icon :icon="child.icon.name" class="text-ot-white" small />
-            </v-list-item-action>
-
-            <v-list-item-title class="text-ot-white" v-text="child.title" />
-          </v-list-item>
-
-          <template #appendIcon>
-            <v-icon class="text-ot-menu-color" small>mdi-chevron-down</v-icon>
-          </template>
-        </v-list-group>
-      </div>
-    </v-list>
-
-    <template #append>
-      <slot name="foot"></slot>
-    </template>
-  </v-navigation-drawer>
-
-</template>
-
-<script setup lang="ts">
-import {onUnmounted, watch, WatchStopHandle} from "@vue/runtime-core";
-import {ref, toRefs} from "@vue/reactivity";
-import {MENU_LINK_TYPE, MenuGroup, MenuItem} from "~/types/menus";
-
-const props = defineProps({
-  menu: {
-    type: Object as () => MenuGroup,
-    required: true
-  },
-  miniVariant: {
-    type: Boolean,
-    required: true
-  },
-  openMenu: {
-    type: Boolean,
-    required: true
-  }
-})
-
-const { openMenu } = toRefs(props)
-const open = ref(true)
-
-// Par défaut si l'écran est trop petit au chargement de la page, le menu doit être fermé.
-if(process.client)
-  open.value = window.innerWidth >= 1264
-
-// TODO : ajouter une petite explication de ce qu'on fait dans ce watch
-const unwatch: WatchStopHandle = watch(openMenu, (newValue, oldValue) => {
-  if (newValue !== oldValue) {
-    open.value = true
-  }
-})
-
-const isExternalLink = (menuItem: MenuItem | MenuGroup) => 'type' in menuItem && menuItem.type === MENU_LINK_TYPE.EXTERNAL
-
-onUnmounted(() => {
-  unwatch()
-})
-</script>
-
-<style scoped>
-  .v-list-item__action, .v-list-group__header__prepend-icon {
-    margin-right: 10px !important;
-  }
-
-  .v-application--is-ltr .v-list-group--no-action > .v-list-group__header {
-    margin-left: 0;
-    padding-left: 0;
-  }
-  .v-application--is-ltr .v-list-group--no-action > .v-list-group__items > .v-list-item {
-    padding-left: 30px;
-  }
-
-  .v-list-item__title {
-    font-size: 14px;
-  }
-
-  .v-list-item {
-    min-height: 10px !important;
-  }
-
-  .v-list-item__action {
-    margin: 10px 0;
-  }
-
-  .v-list-item__content {
-    padding: 8px 0;
-  }
-
-  .home_menu {
-    font-size: 23px;
-  }
-</style>

+ 3 - 3
components/Layout/SubHeader/ActivityYear.vue

@@ -1,6 +1,6 @@
 <template>
   <main class="d-flex">
-    <span class="mr-2 ot_dark_grey--text font-weight-bold">{{ $t(label) }} : </span>
+    <span class="mr-2 ot-dark_grey--text font-weight-bold">{{ $t(label) }} : </span>
     <UiXeditableText
       class="activity-year-input"
       type="number"
@@ -8,10 +8,10 @@
       @update="updateActivityYear"
     >
       <template #xeditable.read="{inputValue}">
-        <v-icon aria-hidden="false" class="ot_green--text" x-small>
+        <v-icon aria-hidden="false" class="ot-green--text" x-small>
           fas fa-edit
         </v-icon>
-        <strong class="ot_green--text"> {{ inputValue }} <span v-if="yearPlusOne">/ {{ parseInt(inputValue) + 1 }}</span></strong>
+        <strong class="ot-green--text"> {{ inputValue }} <span v-if="yearPlusOne">/ {{ parseInt(inputValue) + 1 }}</span></strong>
       </template>
     </UiXeditableText>
   </main>

+ 3 - 3
components/Layout/SubHeader/DataTiming.vue

@@ -1,12 +1,12 @@
 <template>
   <main class="d-flex align-baseline">
-    <span class="mr-2 ot_dark_grey--text font-weight-bold">{{ $t('display_data') }} : </span>
+    <span class="mr-2 ot-dark_grey--text font-weight-bold">{{ $t('display_data') }} : </span>
 
     <v-btn-toggle
       v-model="historicalBtn"
       dense
-      class="ot_light_grey toggle-btn"
-      active-class="ot_green ot_white--text"
+      class="ot-light_grey toggle-btn"
+      active-class="ot-green ot-white--text"
       multiple
     >
       <v-btn max-height="25" class="font-weight-normal text-caption">

+ 2 - 2
components/Layout/SubHeader/DataTimingRange.vue

@@ -1,7 +1,7 @@
 <template>
   <main class="d-flex align-baseline">
     <div v-if="show" class="d-flex align-baseline">
-      <span class="mr-2 ot_dark_grey--text font-weight-bold">{{ $t('period_choose') }}</span>
+      <span class="mr-2 ot-dark_grey--text font-weight-bold">{{ $t('period_choose') }}</span>
       <UiInputDatePicker
         class="time-range"
         label="date_choose"
@@ -25,7 +25,7 @@
           v-on="on"
           @click="show=!show"
         >
-          <v-icon color="ot_grey" class="font-weight-normal" x-small>
+          <v-icon color="ot-grey" class="font-weight-normal" x-small>
             fas fa-history
           </v-icon>
         </v-btn>

+ 2 - 2
components/Layout/SubHeader/PersonnalizedList.vue

@@ -10,7 +10,7 @@
       <template #activator="{ on, attrs }">
         <span
           v-bind="attrs"
-          class="ot_green--text"
+          class="ot-green--text"
           v-on="on"
         >
           {{ $t('my_list') }}
@@ -55,7 +55,7 @@ import {
   computed, defineComponent, useContext, useFetch, ref, Ref, ComputedRef
 } from '@nuxtjs/composition-api'
 import { Collection } from '@vuex-orm/core'
-import { QUERY_TYPE } from '~/types/enums'
+import { QUERY_TYPE } from '~/types/enum/enums'
 import { PersonalizedList } from '~/models/Access/PersonalizedList'
 import { repositoryHelper } from '~/services/store/repository'
 import { AnyJson } from '~/types/interfaces'

+ 2 - 2
components/Layout/Subheader.vue

@@ -6,14 +6,14 @@ Contient entre autres le breadcrumb, les commandes de changement d'année et les
 <template>
   <main>
     <v-card
-      class="d-md-flex ot_light_grey text-body-2"
+      class="d-md-flex ot-light_grey text-body-2"
       flat
       tile
     >
       <LayoutSubHeaderBreadcrumbs class="mr-auto d-sm-none d-md-flex d-none d-sm-flex" />
 
       <v-card
-        class="d-md-flex ot_light_grey pt-2 mr-6  align-baseline"
+        class="d-md-flex ot-light_grey pt-2 mr-6  align-baseline"
         flat
         tile
       >

+ 3 - 3
components/Ui/Button/Delete.vue

@@ -19,10 +19,10 @@ Bouton Delete avec modale de confirmation de la suppression
         </v-card-text>
       </template>
       <template #dialogBtn>
-        <v-btn class="mr-4 submitBtn ot_grey ot_white--text" @click="closeDialog">
+        <v-btn class="mr-4 submitBtn ot-grey ot-white--text" @click="closeDialog">
           {{ $t('cancel') }}
         </v-btn>
-        <v-btn class="mr-4 submitBtn ot_danger ot_white--text" @click="deleteItem">
+        <v-btn class="mr-4 submitBtn ot-danger ot-white--text" @click="deleteItem">
           {{ $t('delete') }}
         </v-btn>
       </template>
@@ -31,7 +31,7 @@ Bouton Delete avec modale de confirmation de la suppression
 </template>
 
 <script setup lang="ts">
-import {TYPE_ALERT} from '~/types/enums'
+import {TYPE_ALERT} from '~/types/enum/enums'
 import {Ref} from "@vue/reactivity";
 import {useEntityManager} from "~/composables/data/useEntityManager";
 import ApiResource from "~/models/ApiResource";

+ 1 - 1
components/Ui/Button/Submit.vue

@@ -1,5 +1,5 @@
 <template>
-  <v-btn class="mr-4 ot_green ot_white--text" :class="hasOtherActions ? 'pr-0' : ''" @click="submitAction(mainAction)" ref="mainBtn">
+  <v-btn class="mr-4 ot-green ot-white--text" :class="hasOtherActions ? 'pr-0' : ''" @click="submitAction(mainAction)" ref="mainBtn">
 
     {{ $t(mainAction) }}
 

+ 2 - 2
components/Ui/Collection.vue

@@ -9,7 +9,7 @@
       <slot name="list.item" v-bind="{items}" />
 
       <!-- New button -->
-      <v-btn v-if="newLink" class="ot_white--text ot_green float-right">
+      <v-btn v-if="newLink" class="ot-white--text ot-green float-right">
         <NuxtLink :to="newLink" class="no-decoration">
           <v-icon>fa-plus-circle</v-icon>
           <span>{{$t('add')}}</span>
@@ -24,7 +24,7 @@
 
 import {computed, ComputedRef, toRefs, ToRefs} from "@vue/reactivity";
 import {useEntityFetch} from "~/composables/data/useEntityFetch";
-import {Collection} from "~/types/data";
+import {Collection} from "~/types/enum/data";
 import ApiResource from "~/models/ApiResource";
 
 const props = defineProps({

+ 1 - 1
components/Ui/DataTable.vue

@@ -44,7 +44,7 @@ Tableau interactif
 <script setup lang="ts">
 
 import {ref, Ref, toRefs} from "@vue/reactivity";
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 import {useEntityFetch} from "~/composables/data/useEntityFetch";
 import ApiResource from "~/models/ApiResource";
 

+ 2 - 2
components/Ui/ExpansionPanel.vue

@@ -6,8 +6,8 @@ Panneaux déroulants de type "accordéon"
 
 <template>
   <v-expansion-panel :id="id">
-    <v-expansion-panel-header color="ot_light_grey">
-      <v-icon class="ot_white--text ot_green icon">
+    <v-expansion-panel-header color="ot-light_grey">
+      <v-icon class="ot-white--text ot-green icon">
         {{ icon }}
       </v-icon>
       {{ $t(id) }}

+ 5 - 5
components/Ui/Form.vue

@@ -60,13 +60,13 @@ Formulaire générique
         </v-card-text>
       </template>
       <template #dialogBtn>
-        <v-btn class="mr-4 submitBtn ot_green ot_white--text" @click="closeDialog">
+        <v-btn class="mr-4 submitBtn ot-green ot-white--text" @click="closeDialog">
           {{ $t('back_to_form') }}
         </v-btn>
-        <v-btn class="mr-4 submitBtn ot_green ot_white--text" @click="saveAndQuit">
+        <v-btn class="mr-4 submitBtn ot-green ot-white--text" @click="saveAndQuit">
           {{ $t('save_and_quit') }}
         </v-btn>
-        <v-btn class="mr-4 submitBtn ot_danger ot_white--text" @click="quitForm">
+        <v-btn class="mr-4 submitBtn ot-danger ot-white--text" @click="quitForm">
           {{ $t('quit_form') }}
         </v-btn>
       </template>
@@ -78,8 +78,8 @@ Formulaire générique
 <script setup lang="ts">
 
 import {computed, ComputedRef, ref, Ref} from "@vue/reactivity";
-import {AnyJson} from "~/types/data";
-import {FORM_FUNCTION, SUBMIT_TYPE, TYPE_ALERT} from "~/types/enums";
+import {AnyJson} from "~/types/enum/data";
+import {FORM_FUNCTION, SUBMIT_TYPE, TYPE_ALERT} from "~/types/enum/enums";
 import {useNuxtApp, useRouter} from "#app";
 import { useFormStore } from "~/store/form";
 import {Route} from "@intlify/vue-router-bridge";

+ 1 - 1
components/Ui/Input/Autocomplete.vue

@@ -38,7 +38,7 @@ Liste déroulante avec autocompletion
 import {useNuxtApp} from "#app";
 import {computed, ComputedRef, Ref} from "@vue/reactivity";
 import {useFieldViolation} from "~/composables/form/useFieldViolation";
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 import {onUnmounted, watch} from "@vue/runtime-core";
 import ObjectUtils from "~/services/utils/objectUtils";
 

+ 1 - 1
components/Ui/Input/DatePicker.vue

@@ -32,7 +32,7 @@ Sélecteur de dates
       <v-date-picker
         v-model="datesParsed"
         :range="range"
-        color="ot_green lighten-1"
+        color="ot-green lighten-1"
         @input="dateOpen = range && datesParsed.length < 2"
       />
     </v-menu>

+ 0 - 3
components/Ui/Input/Enum.vue

@@ -110,12 +110,9 @@ const { fieldViolations, updateViolationState } = useFieldViolation(props.field)
 const { fetch } = useEnumFetch()
 const { data: items, pending } = fetch(props.enum)
 
-const onClick = () => console.log(items.value)
-
 const emit = defineEmits(['update:modelValue', 'change'])
 
 const onModelUpdate = (event: any) => {
-  console.log(event)
   updateViolationState(event)
   emit('change', event)
   emit('update:modelValue', event)

+ 3 - 3
components/Ui/Input/Image.vue

@@ -46,10 +46,10 @@ https://norserium.github.io/vue-advanced-cropper/
         </div>
       </template>
       <template #dialogBtn>
-        <v-btn class="mr-4 submitBtn ot_grey ot_white--text" @click="$emit('close')">
+        <v-btn class="mr-4 submitBtn ot-grey ot-white--text" @click="$emit('close')">
           {{ $t('cancel') }}
         </v-btn>
-        <v-btn class="mr-4 submitBtn ot_danger ot_white--text" @click="save">
+        <v-btn class="mr-4 submitBtn ot-danger ot-white--text" @click="save">
           {{ $t('save') }}
         </v-btn>
       </template>
@@ -61,7 +61,7 @@ https://norserium.github.io/vue-advanced-cropper/
 
 import {useNuxtApp} from "#app";
 import {ref, Ref} from "@vue/reactivity";
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 import {File} from '~/models/Core/File'
 import {useAp2iRequestService} from "~/composables/data/useAp2iRequestService";
 import Url from "~/services/utils/url";

+ 2 - 2
composables/data/useAp2iRequestService.ts

@@ -1,9 +1,9 @@
 import {useAccessProfileStore} from "~/store/profile/access";
 import {FetchContext, FetchOptions} from "ohmyfetch";
-import {TYPE_ALERT} from "~/types/enums";
+import {TYPE_ALERT} from "~/types/enum/enums";
 import {navigateTo, useRuntimeConfig} from "#app";
 import ApiRequestService from "~/services/data/apiRequestService";
-import {AssociativeArray} from "~/types/data";
+import {AssociativeArray} from "~/types/enum/data";
 import {Ref} from "@vue/reactivity";
 import {usePageStore} from "~/store/page";
 import UnauthorizedError from "~/services/error/UnauthorizedError";

+ 1 - 1
composables/data/useEntityFetch.ts

@@ -1,7 +1,7 @@
 import {useAsyncData, AsyncData} from "#app";
 import {useEntityManager} from "~/composables/data/useEntityManager";
 import ApiResource from "~/models/ApiResource";
-import {AssociativeArray, Collection} from "~/types/data";
+import {AssociativeArray, Collection} from "~/types/enum/data";
 
 interface useEntityFetchReturnType {
     fetch: (model: typeof ApiResource, id: number) => AsyncData<ApiResource, ApiResource | true>,

+ 1 - 1
composables/data/useEnumFetch.ts

@@ -1,5 +1,5 @@
 import {useAsyncData, AsyncData} from "#app";
-import {Enum} from "~/types/data";
+import {Enum} from "~/types/enum/data";
 import {useEnumManager} from "~/composables/data/useEnumManager";
 
 interface useEnumFetchReturnType {

+ 1 - 1
composables/data/useImageFetch.ts

@@ -1,7 +1,7 @@
 import {useAsyncData, AsyncData, useFetch, FetchResult} from "#app";
 import {useEntityManager} from "~/composables/data/useEntityManager";
 import ApiResource from "~/models/ApiResource";
-import {AssociativeArray} from "~/types/data";
+import {AssociativeArray} from "~/types/enum/data";
 import {useImageManager} from "~/composables/data/useImageManager";
 import {ref, Ref} from "@vue/reactivity";
 

+ 4 - 2
composables/layout/useMenuBuilder.ts

@@ -1,6 +1,6 @@
 import {Ref, ref} from "@vue/reactivity";
 import {useAccessProfileStore} from "~/store/profile/access";
-import {useRuntimeConfig} from "#app";
+import {useRouter, useRuntimeConfig} from "#app";
 import {useAbility} from "@casl/vue";
 import {useOrganizationProfileStore} from "~/store/profile/organization";
 import AbstractMenuBuilder from "~/services/menuBuilder/abstractMenuBuilder";
@@ -11,6 +11,7 @@ import MyAccessesMenuBuilder from "~/services/menuBuilder/myAccessesMenuBuilder"
 import MyFamilyMenuBuilder from "~/services/menuBuilder/myFamilyMenuBuilder";
 import WebsiteListMenuBuilder from "~/services/menuBuilder/websiteListMenuBuilder";
 import ParametersMenuBuilder from "~/services/menuBuilder/parametersMenuBuilder";
+import {useEach} from "#imports";
 
 /**
  * Renvoie certaines méthodes pour interagir avec les menus
@@ -57,8 +58,9 @@ export const useMenuBuilder = () => {
     const menu = builder.build()
 
     // On enregistre l'état du menu dans le store
-    accessProfile.hasMenu[menu.name()] = menu.length > 0
+    accessProfile.hasMenu[builder.name()] = menu.children.length > 0
 
+    console.log('Menu ' + builder.name() + ' built (' + menu.children.length + ' entries)')
     return ref(menu)
   }
 

+ 3 - 7
layouts/default.vue

@@ -3,11 +3,11 @@
     <!-- The client only is used to show the loading picture -->
 <!--    <ClientOnly placeholder-tag="client-only-placeholder" placeholder=" " />-->
     <v-app>
-      <LayoutMenu v-if="displayMenu" :menu="menu" :mini-variant="properties.miniVariant" :openMenu="properties.openMenu" />
+      <LayoutMainMenu v-if="displayMenu" :menu="menu" :mini-variant="properties.miniVariant" :openMenu="properties.openMenu" />
 
 <!--      <LayoutHeader @handle-open-menu-click="handleOpenMenu" @handle-open-mini-menu-click="handleOpenMiniMenu" />-->
 
-      <v-main class="ot_content_color">
+      <v-main class="ot-content-color">
 <!--        <LayoutSubheader />-->
 
 <!--        <LayoutAlertbar class="mt-1"></LayoutAlertbar>-->
@@ -23,17 +23,13 @@
 </template>
 
 <script setup lang="ts">
-import {useAccessProfileStore} from "~/store/profile/access";
 import {useMenuBuilder} from "~/composables/layout/useMenuBuilder";
-import {computed} from "@vue/reactivity";
-
+import {computed, reactive} from "@vue/reactivity";
 
 const { buildMainMenu, hasMenu } = useMenuBuilder()
 
 const menu = buildMainMenu()
 
-const accessProfileStore = useAccessProfileStore()
-
 const displayMenu = computed(() => hasMenu('Main'))
 
 const properties = reactive({

+ 1 - 1
nuxt.config.ts

@@ -5,7 +5,7 @@ import type { I18nOptions } from 'vue-i18n'
 export default defineNuxtConfig({
     vuetify: {
         customVariables: ['~/assets/css/variables.scss'],
-        treeShake: true,
+        treeShake: false,
     },
     css: [
         '@/assets/css/global.css',

+ 1 - 0
pages/index.vue

@@ -8,3 +8,4 @@
 
 </script>
 
+

+ 6 - 6
pages/organization/index.vue

@@ -180,13 +180,13 @@ Contient toutes les informations sur l'organization courante
 <!--                              </template>-->
 <!--                              <template #card.text>-->
 <!--                                <span v-if="item.email"><strong>{{ $t('email') }}</strong> : {{ item.email }} <br></span>-->
-<!--                                <span v-if="item.emailInvalid" class="ot_danger&#45;&#45;text"><v-icon class="ot_danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('emailInvalid') }}</strong> : {{ item.emailInvalid }} <br></span>-->
+<!--                                <span v-if="item.emailInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('emailInvalid') }}</strong> : {{ item.emailInvalid }} <br></span>-->
 
 <!--                                <span v-if="item.telphone"><strong>{{ $t('telphone') }}</strong> : {{ formatPhoneNumber(item.telphone) }} <br></span>-->
-<!--                                <span v-if="item.telphoneInvalid" class="ot_danger&#45;&#45;text"><v-icon class="ot_danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('telphoneInvalid') }}</strong> : {{ formatPhoneNumber(item.telphoneInvalid) }} <br></span>-->
+<!--                                <span v-if="item.telphoneInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('telphoneInvalid') }}</strong> : {{ formatPhoneNumber(item.telphoneInvalid) }} <br></span>-->
 
 <!--                                <span v-if="item.mobilPhone"><strong>{{ $t('mobilPhone') }}</strong> : {{ formatPhoneNumber(item.mobilPhone) }} <br></span>-->
-<!--                                <span v-if="item.mobilPhoneInvalid" class="ot_danger&#45;&#45;text"><v-icon class="ot_danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('mobilPhoneInvalid') }}</strong> : {{ formatPhoneNumber(item.mobilPhoneInvalid) }} </span>-->
+<!--                                <span v-if="item.mobilPhoneInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('mobilPhoneInvalid') }}</strong> : {{ formatPhoneNumber(item.mobilPhoneInvalid) }} </span>-->
 <!--                              </template>-->
 <!--                            </UiCard>-->
 <!--                          </v-col>-->
@@ -372,7 +372,7 @@ Contient toutes les informations sur l'organization courante
 <!--                    loaderType="text"-->
 <!--                  >-->
 <!--                    <template #list.item="{items}">-->
-<!--                      <h4 class="ot_grey&#45;&#45;text font-weight-regular">{{$t('organizationArticle')}}</h4>-->
+<!--                      <h4 class="ot-grey&#45;&#45;text font-weight-regular">{{$t('organizationArticle')}}</h4>-->
 <!--                      <UiTemplateDataTable-->
 <!--                        :headers="[-->
 <!--                          { text: $t('title'), value: 'title' },-->
@@ -421,10 +421,10 @@ Contient toutes les informations sur l'organization courante
 <!--                                <span v-if="item.bankName"><strong>{{ $t('bankName') }}</strong> : {{ item.bankName }} <br></span>-->
 
 <!--                                <span v-if="item.bic"><strong>{{ $t('bic') }}</strong> : {{ item.bic }} <br></span>-->
-<!--                                <span v-if="item.bicInvalid" class="ot_danger&#45;&#45;text"><v-icon class="ot_danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('bicInvalid') }}</strong> : {{ item.bicInvalid }} <br></span>-->
+<!--                                <span v-if="item.bicInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('bicInvalid') }}</strong> : {{ item.bicInvalid }} <br></span>-->
 
 <!--                                <span v-if="item.iban"><strong>{{ $t('iban') }}</strong> : {{ item.iban }} <br></span>-->
-<!--                                <span v-if="item.ibanInvalid" class="ot_danger&#45;&#45;text"><v-icon class="ot_danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('ibanInvalid') }}</strong> : {{ item.ibanInvalid }} <br></span>-->
+<!--                                <span v-if="item.ibanInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('ibanInvalid') }}</strong> : {{ item.ibanInvalid }} <br></span>-->
 
 <!--                              </template>-->
 <!--                            </UiCard>-->

+ 6 - 0
pages/poc.vue

@@ -9,3 +9,9 @@
 
 <script setup lang="ts">
 </script>
+
+<style scoped lang="scss">
+  h1 {
+    color: rgb(var(--v-theme-ot-green))
+  }
+</style>

+ 1 - 1
pages/poc/index.vue

@@ -31,7 +31,7 @@
   import {computed, ComputedRef, ref, Ref} from "@vue/reactivity";
   import ApiResource from "~/models/ApiResource";
   import {File} from "~/models/Core/File";
-  import {Collection, Pagination} from "~/types/data";
+  import {Collection, Pagination} from "~/types/enum/data";
   import {useLazyAsyncData} from "#app";
   import {useEntityFetch} from "~/composables/data/useEntityFetch";
 

+ 1 - 1
plugins/vuetify.ts

@@ -36,7 +36,7 @@ export default defineNuxtPlugin(nuxtApp => {
                         'ot-black': '#000000'
                     }
                 }
-            }
+            },
         },
         icons: {
             defaultSet: 'fa',

+ 2 - 1
services/data/apiRequestService.ts

@@ -3,9 +3,10 @@
  *
  * It will send basic http requests and returns raw results
  */
-import {AssociativeArray, HTTP_METHOD} from "~/types/data.d";
+import {AssociativeArray} from "~/types/data";
 import {$Fetch} from "nitropack";
 import {FetchOptions} from "ohmyfetch";
+import {HTTP_METHOD} from "~/types/enum/data";
 
 class ApiRequestService {
     private readonly fetch: $Fetch

+ 2 - 1
services/data/serializer/denormalizer/hydraDenormalizer.ts

@@ -1,5 +1,6 @@
-import {AnyJson, ApiResponse, HydraMetadata, METADATA_TYPE} from "~/types/data.d";
+import {AnyJson, ApiResponse, HydraMetadata} from "~/types/data";
 import Url from "~/services/utils/url";
+import {METADATA_TYPE} from "~/types/enum/data";
 
 /**
  * Classe permettant d'assurer la dé-normalization d'un objet Hydra en JSON

+ 1 - 1
services/data/serializer/denormalizer/yamlDenormalizer.ts

@@ -1,6 +1,6 @@
 import { read } from 'yaml-import'
 import {dump, load} from 'js-yaml';
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 
 
 /**

+ 11 - 11
services/menuBuilder/abstractMenuBuilder.ts

@@ -1,8 +1,10 @@
-import {MenuItem, MenuItems, IconItem, MENU_LINK_TYPE, MenuGroup, MenuBuilder} from '~/types/menus'
+import {IconItem, MenuBuilder, MenuGroup, MenuItem, MenuItems} from '~/types/layout'
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 import {RuntimeConfig} from "@nuxt/schema";
 import Url from "~/services/utils/url";
 import {AnyAbility} from "@casl/ability";
 import {accessState, organizationState} from "~/types/interfaces";
+import {Router} from "vue-router";
 
 /**
  * Classe de base des menus et sous-menus.
@@ -19,7 +21,7 @@ abstract class AbstractMenuBuilder implements MenuBuilder{
       runtimeConfig: RuntimeConfig,
       ability: AnyAbility,
       organizationProfile: organizationState,
-      accessProfile: accessState
+      accessProfile: accessState,
   ) {
     this.runtimeConfig = runtimeConfig
     this.ability = ability
@@ -33,12 +35,12 @@ abstract class AbstractMenuBuilder implements MenuBuilder{
   abstract name(): string
 
   /**
-   * Construit et retourne un menu ou sous-menu selon le profil de l'utilisateur, le profil de son organisation,
+   * Construit et retourne un menu ou sous-menu selon le profil de l'utilisateur, le profil de son organisation
    * et les droits de l'utilisateur.
    *
    * Si le menu comporte plusieurs éléments, retourne une instance de MenuGroup
    * Si le menu ne comporte qu'un seul élément, retourne une instance de MenuItem
-   * Si le menu ne comporte aucun élément, retourne null
+   * Si le menu ne comporte aucun élément, retourne null.
    */
   abstract build (): MenuItem | MenuGroup | null
 
@@ -48,15 +50,15 @@ abstract class AbstractMenuBuilder implements MenuBuilder{
    * @param label
    * @param icon
    * @param {Array<MenuItem>} children Tableau d'ItemMenu représentant les sous menu du menu principal
-   * @param active
+   * @param expanded
    */
   protected createGroup(
       label: string,
       icon?: IconItem,
       children: MenuItems = [],
-      active: boolean = true
+      expanded: boolean = false
   ): MenuGroup {
-    return { label, icon, children, active }
+    return { label, icon, children, expanded }
   }
 
   /**
@@ -67,7 +69,6 @@ abstract class AbstractMenuBuilder implements MenuBuilder{
    * @param to
    * @param type
    * @param isAction
-   * @param active
    * @return {MenuItem}
    */
   protected createItem (
@@ -75,8 +76,7 @@ abstract class AbstractMenuBuilder implements MenuBuilder{
       icon?: IconItem,
       to: string = '',
       type: MENU_LINK_TYPE = MENU_LINK_TYPE.INTERNAL,
-      isAction = false,
-      active: boolean = true
+      isAction = false
   ): MenuItem {
     let url: string
 
@@ -89,7 +89,7 @@ abstract class AbstractMenuBuilder implements MenuBuilder{
         url = to
     }
 
-    return { icon, label, to: url, type, active, isAction }
+    return { icon, label, to: url, type, isAction , active: false }
   }
 
   protected buildSubmenu(menuBuilder: typeof AbstractMenuBuilder) {

+ 2 - 1
services/menuBuilder/accessMenuBuilder.ts

@@ -1,6 +1,7 @@
 import {$organizationProfile} from '~/services/profile/organizationProfile'
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Répertoire

+ 2 - 1
services/menuBuilder/accountMenuBuilder.ts

@@ -1,4 +1,5 @@
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from '~/types/menus'
+import {MenuGroup, MenuItem, MenuItems} from '~/types/layout'
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
 
 /**

+ 2 - 1
services/menuBuilder/admin2iosMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Admin 2IOS

+ 2 - 1
services/menuBuilder/agendaMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu agenda

+ 2 - 1
services/menuBuilder/billingMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Facturation

+ 2 - 1
services/menuBuilder/communicationMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Communication

+ 2 - 1
services/menuBuilder/configurationMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Classe pour la construction du Menu Paramètres

+ 2 - 1
services/menuBuilder/cotisationsMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MenuItems, MENU_LINK_TYPE, MenuGroup, MenuItem} from "~/types/menus";
+import {MenuItems, MenuGroup, MenuItem} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Cotisation (CMF)

+ 2 - 1
services/menuBuilder/donorsMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuItem} from "~/types/menus";
+import {MenuItem} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Donneurs

+ 2 - 1
services/menuBuilder/educationalMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Suivi pédagogique

+ 2 - 1
services/menuBuilder/equipmentMenuBuilder.ts

@@ -1,4 +1,5 @@
-import {MENU_LINK_TYPE, MenuItem} from "~/types/menus";
+import {MenuItem} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 import AbstractMenuBuilder from "~/services/menuBuilder/abstractMenuBuilder";
 
 /**

+ 1 - 1
services/menuBuilder/mainMenuBuilder.ts

@@ -1,5 +1,5 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
 import AccessMenuBuilder from "~/services/menuBuilder/accessMenuBuilder";
 import AgendaMenuBuilder from "~/services/menuBuilder/agendaMenuBuilder";
 import EquipmentMenuBuilder from "~/services/menuBuilder/equipmentMenuBuilder";

+ 6 - 2
services/menuBuilder/medalsMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuItem} from "~/types/menus";
+import {MenuItem} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Médailles
@@ -15,7 +16,10 @@ export default class MedalsMenuBuilder extends AbstractMenuBuilder {
    */
   build (): MenuItem | null {
     if (this.ability.can('display', 'medals_page')) {
-      return this.createItem('medals', {name: 'fas fa-trophy'}, '/medals/list/', MENU_LINK_TYPE.V1)
+      // TODO: restaurer le bon lien
+      return this.createItem('medals', {name: 'fas fa-trophy'}, '/poc/blank', MENU_LINK_TYPE.INTERNAL)
+
+      // return this.createItem('medals', {name: 'fas fa-trophy'}, '/medals/list/', MENU_LINK_TYPE.V1)
     }
     return null
   }

+ 2 - 1
services/menuBuilder/myAccessesMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 import {useEach} from "#imports";
 
 /**

+ 2 - 1
services/menuBuilder/myFamilyMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 import {useEach} from "#imports";
 
 /**

+ 2 - 1
services/menuBuilder/parametersMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Paramètres

+ 2 - 1
services/menuBuilder/statsMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItem, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItem, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Statistiques

+ 2 - 1
services/menuBuilder/websiteAdminMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuItem} from "~/types/menus";
+import {MenuItem} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 
 /**
  * Menu Site internet

+ 2 - 1
services/menuBuilder/websiteListMenuBuilder.ts

@@ -1,5 +1,6 @@
 import AbstractMenuBuilder from '~/services/menuBuilder/abstractMenuBuilder'
-import {MENU_LINK_TYPE, MenuGroup, MenuItems} from "~/types/menus";
+import {MenuGroup, MenuItems} from "~/types/layout";
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
 import {useEach} from "#imports";
 
 /**

+ 1 - 1
services/profile/accessProfile.ts

@@ -1,7 +1,7 @@
 import {AbilitiesType, accessState} from "~/types/interfaces";
 import {useAccessProfileStore} from "~/store/profile/access";
 import {MongoAbility} from "@casl/ability/dist/types/Ability";
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 
 /**
  * L'AccessProfile permet de manipuler l'AccessState l'Access qui peuvent

+ 1 - 1
services/profile/organizationProfile.ts

@@ -1,6 +1,6 @@
 import { organizationState } from '~/types/interfaces'
 import {useOrganizationProfileStore} from "~/store/profile/organization";
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 /**
  * L'OrganizationProfile permet de manipuler l'OrganizationState auquel
  * l'access courant est connecté et qui peuvent  être nécessaires pour l'affichage

+ 1 - 1
services/rights/abilitiesUtils.ts

@@ -6,7 +6,7 @@ import {useAccessProfileStore} from "~/store/profile/access";
 import {useOrganizationProfileStore} from "~/store/profile/organization";
 import YamlDenormalizer from "~/services/data/serializer/denormalizer/yamlDenormalizer";
 import {MongoAbility} from "@casl/ability/dist/types/Ability";
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 
 /**
  * Classe permettant de mener des opérations sur les habilités

+ 1 - 1
services/rights/roleUtils.ts

@@ -1,5 +1,5 @@
 import { AbilitiesType } from '~/types/interfaces'
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 
 // TODO: peut-être passer ces constantes dans la config?
 const rolesByFunction: Array<string> = [

+ 1 - 1
services/utils/objectUtils.ts

@@ -3,7 +3,7 @@
  * @class ObjectUtils
  * Classe aidant à manipuler des Objets
  */
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 import ApiResource from "~/models/ApiResource";
 
 

+ 2 - 2
store/form.ts

@@ -1,7 +1,7 @@
 import {formState} from '~/types/interfaces'
-import {FORM_FUNCTION} from "~/types/enums";
+import {FORM_FUNCTION} from "~/types/enum/enums";
 import {defineStore} from "pinia";
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 
 export const useFormStore = defineStore('form', {
   state: (): formState => {

+ 1 - 1
store/page.ts

@@ -1,6 +1,6 @@
 import {Alert, pageState} from '~/types/interfaces'
 import {defineStore} from "pinia";
-import {FORM_FUNCTION, TYPE_ALERT} from "~/types/enums";
+import {FORM_FUNCTION, TYPE_ALERT} from "~/types/enum/enums";
 
 export const usePageStore = defineStore('page', {
   state: (): pageState => {

+ 2 - 6
tsconfig.json

@@ -1,5 +1,5 @@
 {
-  // https://v3.nuxtjs.org/concepts/typescript
+  // https://nuxtjs.org/concepts/typescript
   "extends": "./.nuxt/tsconfig.json",
   "useDefineForClassFields": false,
   "compilerOptions": {
@@ -16,11 +16,7 @@
       ".nuxt"
     ],
     "typeRoots": [
-      "./types/types.d.ts",
-      "./types/interfaces.d.ts",
-      "./types/enums.d.ts",
-      "./types/data.d.ts",
-      "./types/menus.d.ts"
+      "./types"
     ]
   }
 }

+ 0 - 12
types/data.d.ts

@@ -3,13 +3,6 @@ import {EnumChoice} from "~/types/interfaces";
 
 type AnyJson = Record<string, any>
 
-export const enum HTTP_METHOD {
-    POST = 'POST',
-    PUT = 'PUT',
-    GET = 'GET',
-    DELETE = 'DELETE'
-}
-
 interface AssociativeArray {
     [key: string]: any;
 }
@@ -24,11 +17,6 @@ interface Connector {
     )
 }
 
-export const enum METADATA_TYPE {
-    ITEM,
-    COLLECTION
-}
-
 interface HydraMetadata {
     readonly totalItems?: number
     firstPage?: number

+ 11 - 0
types/enum/data.ts

@@ -0,0 +1,11 @@
+export const enum HTTP_METHOD {
+    POST = 'POST',
+    PUT = 'PUT',
+    GET = 'GET',
+    DELETE = 'DELETE'
+}
+
+export const enum METADATA_TYPE {
+    ITEM,
+    COLLECTION
+}

+ 0 - 0
types/enums.ts → types/enum/enums.ts


+ 7 - 0
types/enum/layout.ts

@@ -0,0 +1,7 @@
+
+// Menus
+export const enum MENU_LINK_TYPE {
+    INTERNAL,
+    V1,
+    EXTERNAL,
+}

+ 2 - 2
types/interfaces.d.ts

@@ -8,9 +8,9 @@ import {
   FORM_FUNCTION,
   GENDER,
   TYPE_ALERT,
-} from '~/types/enums'
+} from '~/types/enum/enums'
 import ApiResource from "~/models/ApiResource";
-import {AnyJson} from "~/types/data";
+import {AnyJson} from "~/types/enum/data";
 import {Record} from "immutable";
 
 /**

+ 45 - 0
types/layout.d.ts

@@ -0,0 +1,45 @@
+import {MENU_LINK_TYPE} from "~/types/enum/layout";
+
+interface IconItem {
+    name?: string
+    // TODO: les avatars sont ils encore utiles?
+    avatarId?: number | null
+    avatarByDefault?: string
+}
+
+/**
+ * Entrée d'un menu, correspondant à un lien de navigation
+ */
+interface MenuItem {
+    label: string
+    icon?: IconItem
+    to?: string
+    /** Type de lien (interne, externe, v1)  */
+    type: MENU_LINK_TYPE
+    /** Modifie l'affichage de l'item pour signifier une action (ex: se déconnecter) */
+    isAction: boolean
+    // TODO: revoir l'utilité de avatar?
+    avatar?: number
+    /** Correspond à la page actuelle */
+    active: boolean
+}
+
+/**
+ * Sous-menu, regroupant d'autres MenuItem et/ou MenuGroup
+ */
+interface MenuGroup {
+    label: string
+    icon?: IconItem
+    children?: MenuItems
+    /** Le sous-menu est-il déplié ou non */
+    expanded: boolean
+}
+
+type MenuItems = Array<MenuItem | MenuGroup>
+
+/**
+ * Service responsable de la génération d'un menu
+ */
+interface MenuBuilder {
+    build: () => MenuItem | MenuGroup | null
+}

+ 0 - 36
types/menus.d.ts

@@ -1,36 +0,0 @@
-interface IconItem {
-    name?: string
-    avatarId?: number | null
-    avatarByDefault?: string
-}
-
-export const enum MENU_LINK_TYPE {
-    INTERNAL = 1,
-    V1 = 2,
-    EXTERNAL = 3,
-}
-
-interface MenuItem {
-    label: string
-    icon?: IconItem
-    to?: string
-    type: MENU_LINK_TYPE
-    active: boolean
-    isAction: boolean
-    avatar?: number
-}
-
-interface MenuGroup {
-    label: string
-    icon?: IconItem
-    children?: MenuItems
-    active: boolean
-}
-
-type MenuItems = Array<MenuItem | MenuGroup>
-
-interface MenuBuilder {
-    build: () => MenuItem | MenuGroup | null
-}
-
-