Olivier Massot 7 ماه پیش
والد
کامیت
809edc93e9
77فایلهای تغییر یافته به همراه371 افزوده شده و 405 حذف شده
  1. 2 1
      assets/css/global.scss
  2. 17 10
      components/Layout/AlertBar.vue
  3. 1 1
      components/Layout/AlertBar/Cotisation.vue
  4. 1 1
      components/Layout/AlertBar/OnlineRegistration.vue
  5. 1 1
      components/Layout/AlertBar/RegistrationStatus.vue
  6. 3 3
      components/Layout/AlertBar/SuperAdmin.vue
  7. 2 2
      components/Layout/AlertBar/SwitchYear.vue
  8. 5 2
      components/Layout/Dialog/Trial/AlreadyDid.vue
  9. 0 1
      components/Layout/Header.vue
  10. 1 1
      components/Layout/Header/HomeBtn.vue
  11. 5 5
      components/Layout/Header/Menu.vue
  12. 6 3
      components/Layout/Header/Title.vue
  13. 2 2
      components/Layout/Header/UniversalCreation/Card.vue
  14. 4 5
      components/Layout/Header/UniversalCreation/CreateButton.vue
  15. 2 3
      components/Layout/Header/UniversalCreation/EventParams.vue
  16. 27 34
      components/Layout/Header/UniversalCreation/GenerateCardsSteps.vue
  17. 3 3
      components/Layout/MainMenu.vue
  18. 6 6
      components/Layout/Parameters/EntityTable.vue
  19. 6 10
      components/Layout/Parameters/Menu.vue
  20. 30 34
      components/Layout/Parameters/Table.vue
  21. 11 18
      components/Layout/Parameters/Website/ActivationSwitch.vue
  22. 3 3
      components/Layout/SubHeader/ActivityYear.vue
  23. 4 5
      components/Layout/SubHeader/Breadcrumbs.vue
  24. 4 4
      components/Layout/SubHeader/DataTiming.vue
  25. 2 2
      components/Layout/SubHeader/DataTimingRange.vue
  26. 5 5
      components/Layout/SubHeader/PersonnalizedList.vue
  27. 4 4
      components/Layout/Subheader.vue
  28. 2 2
      components/Layout/UpgradePremiumButton.vue
  29. 9 10
      components/Ui/Button/Submit.vue
  30. 2 2
      components/Ui/Collection.vue
  31. 2 2
      components/Ui/DataTable.vue
  32. 0 1
      components/Ui/Form.vue
  33. 9 11
      components/Ui/Form/DeletionConfirmationDialog.vue
  34. 6 6
      components/Ui/Help.vue
  35. 2 3
      components/Ui/Image.vue
  36. 7 8
      components/Ui/Input/AutocompleteWithAPI.vue
  37. 0 2
      components/Ui/Input/Checkbox.vue
  38. 4 5
      components/Ui/Input/DatePicker.vue
  39. 2 2
      components/Ui/Input/Enum.vue
  40. 0 1
      components/Ui/Input/Number.vue
  41. 2 2
      components/Ui/Input/Phone.vue
  42. 2 2
      components/Ui/ItemFromUri.vue
  43. 1 2
      components/Ui/SystemBar.vue
  44. 2 2
      components/Ui/Template/Date.vue
  45. 3 3
      components/Ui/Xeditable/Text.vue
  46. 0 1
      composables/utils/useDownloadFile.ts
  47. 0 1
      composables/utils/useDownloadFromRoute.ts
  48. 6 2
      composables/utils/useRedirect.ts
  49. 1 1
      env/setupEnv.mjs
  50. 3 3
      eslint.config.mjs
  51. 0 1
      layouts/parameters.vue
  52. 2 2
      models/decorators.ts
  53. 7 7
      nuxt.config.ts
  54. 0 1
      pages/parameters.vue
  55. 2 5
      pages/parameters/attendances.vue
  56. 1 4
      pages/parameters/bulletin.vue
  57. 1 4
      pages/parameters/education_notation.vue
  58. 1 1
      pages/parameters/education_timings/index.vue
  59. 7 6
      pages/parameters/general_parameters.vue
  60. 3 6
      pages/parameters/intranet.vue
  61. 1 5
      pages/parameters/sms.vue
  62. 3 1
      pages/parameters/super_admin.vue
  63. 17 16
      pages/parameters/teaching.vue
  64. 14 15
      pages/parameters/website.vue
  65. 35 36
      pages/subscription.vue
  66. 5 2
      plugins/matomo.client.ts
  67. 6 2
      services/data/apiRequestService.ts
  68. 4 1
      services/data/enumManager.ts
  69. 5 5
      services/data/imageManager.ts
  70. 2 2
      services/data/normalizer/hydraNormalizer.ts
  71. 3 3
      services/layout/menuBuilder/basicomptaMenuBuilder.ts
  72. 1 2
      services/rights/abilityBuilder.ts
  73. 1 2
      services/utils/dateUtils.ts
  74. 19 19
      tests/units/services/data/apiRequestService.test.ts
  75. 7 9
      tests/units/services/data/entityManager.test.ts
  76. 1 4
      tests/units/services/data/imageManager.test.ts
  77. 1 1
      tests/units/services/data/normalizer/hydraNormalizer.test.ts

+ 2 - 1
assets/css/global.scss

@@ -71,7 +71,8 @@ header .v-toolbar__content {
   font-size: 0.9rem;
 }
 
-h3, h4 {
+h3,
+h4 {
   color: rgb(var(--v-theme-on-neutral-soft));
 }
 

+ 17 - 10
components/Layout/AlertBar.vue

@@ -8,19 +8,21 @@ Contient les différentes barres d'alertes qui s'affichent dans certains cas
   <main>
     <v-expand-transition>
       <div v-if="showAlertBars">
-        <LayoutAlertBarEnv style="z-index: 510"/>
+        <LayoutAlertBarEnv style="z-index: 510" />
 
         <LayoutAlertBarSwitchUser style="z-index: 509" />
 
         <client-only>
           <LayoutAlertBarCotisation
-            v-if="organizationProfile.isCmf && ability.can('manage', 'cotisation')"
+            v-if="
+              organizationProfile.isCmf && ability.can('manage', 'cotisation')
+            "
             style="z-index: 508"
           />
         </client-only>
 
-        <LayoutAlertBarSwitchYear style="z-index: 507"/>
-        <LayoutAlertBarSuperAdmin style="z-index: 506"/>
+        <LayoutAlertBarSwitchYear style="z-index: 507" />
+        <LayoutAlertBarSuperAdmin style="z-index: 506" />
         <LayoutAlertBarRegistrationStatus
           v-if="organizationProfile.hasModule('IEL')"
           style="z-index: 505"
@@ -35,18 +37,24 @@ Contient les différentes barres d'alertes qui s'affichent dans certains cas
         @click="onFoldedWarningClick"
       >
         <v-icon small icon="fas fa-exclamation-triangle mx-1" />
-        <span>{{ $t("show_warnings") }}</span>
-        <v-icon small :icon="'fas mx-1' + (unfoldWarnings ? ' fa-chevron-up' : ' fa-chevron-down')" />
+        <span>{{ $t('show_warnings') }}</span>
+        <v-icon
+          small
+          :icon="
+            'fas mx-1' +
+            (unfoldWarnings ? ' fa-chevron-up' : ' fa-chevron-down')
+          "
+        />
       </div>
     </div>
   </main>
 </template>
 
 <script setup lang="ts">
-import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 import { useAbility } from '@casl/vue'
-import {useDisplay} from 'vuetify';
-import {StencilPreview} from 'vue-advanced-cropper';
+import { useDisplay } from 'vuetify'
+import { StencilPreview } from 'vue-advanced-cropper'
+import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 
 const organizationProfile = useOrganizationProfileStore()
 const ability = useAbility()
@@ -59,7 +67,6 @@ const onFoldedWarningClick = () => {
 }
 
 const showAlertBars = computed(() => mdAndUp.value || unfoldWarnings.value)
-
 </script>
 
 <style scoped lang="scss">

+ 1 - 1
components/Layout/AlertBar/Cotisation.vue

@@ -17,8 +17,8 @@ Barre d'alerte qui s'affiche pour donner l'état de la cotisation
 </template>
 
 <script setup lang="ts">
-import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 import type { Ref } from 'vue'
+import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 import UrlUtils from '~/services/utils/urlUtils'
 import { ALERT_STATE_COTISATION } from '~/types/enum/enums'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'

+ 1 - 1
components/Layout/AlertBar/OnlineRegistration.vue

@@ -13,10 +13,10 @@ Barre d'alerte sur l'ouverture ou non de l'inscription en ligne
 </template>
 
 <script setup lang="ts">
+import { ComputedRef } from 'vue'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'
 import { useAccessProfileStore } from '~/stores/accessProfile'
 import RegistrationAvailability from '~/models/OnlineRegistration/RegistrationAvailability'
-import { ComputedRef } from '@vue/reactivity'
 
 const { fetch } = useEntityFetch()
 

+ 1 - 1
components/Layout/AlertBar/RegistrationStatus.vue

@@ -13,10 +13,10 @@ Barre d'alerte quand au statut (l'avancement) de l'inscription en ligne de l'uti
 </template>
 
 <script setup lang="ts">
+import type { ComputedRef } from 'vue'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'
 import { useAccessProfileStore } from '~/stores/accessProfile'
 import RegistrationStatus from '~/models/OnlineRegistration/RegistrationStatus'
-import type { ComputedRef } from '@vue/reactivity'
 
 const { fetch } = useEntityFetch()
 

+ 3 - 3
components/Layout/AlertBar/SuperAdmin.vue

@@ -13,10 +13,10 @@ Barre d'alerte qui s'affiche lorsque l'utilisateur est un super admin en mode sw
 </template>
 
 <script setup lang="ts">
+import type { ComputedRef } from 'vue'
+import { navigateTo } from '#app'
 import { useAccessProfileStore } from '~/stores/accessProfile'
 import UrlUtils from '~/services/utils/urlUtils'
-import type { ComputedRef } from '@vue/reactivity'
-import { navigateTo } from '#app'
 import { useAdminUrl } from '~/composables/utils/useAdminUrl'
 
 const { makeAdminUrl } = useAdminUrl()
@@ -37,7 +37,7 @@ const url: ComputedRef<string> = computed(() => {
     ? accessProfile.originalAccess.id
     : null
 
-  if (show && orgId && originalAccessId) {
+  if (show.value && orgId && originalAccessId) {
     return makeAdminUrl(
       UrlUtils.join('switch_user', orgId, originalAccessId, 'exit'),
     )

+ 2 - 2
components/Layout/AlertBar/SwitchYear.vue

@@ -10,9 +10,9 @@ Barre d'alerte qui s'affiche lorsque l'utilisateur n'est pas sur l'année couran
     {{ $t('not_current_year') }}
 
     <a
-      @click="resetYear"
       class="text-decoration-none on-warning"
       style="cursor: pointer"
+      @click="resetYear"
     >
       <strong class="pl-2 text-neutral-strong">
         {{ $t('not_current_year_reset') }}
@@ -22,9 +22,9 @@ Barre d'alerte qui s'affiche lorsque l'utilisateur n'est pas sur l'année couran
 </template>
 
 <script setup lang="ts">
+import type { ComputedRef } from 'vue'
 import { useAccessProfileStore } from '~/stores/accessProfile'
 import { useOrganizationProfileStore } from '~/stores/organizationProfile'
-import type { ComputedRef } from '@vue/reactivity'
 import { useFormStore } from '~/stores/form'
 import Access from '~/models/Access/Access'
 import { usePageStore } from '~/stores/page'

+ 5 - 2
components/Layout/Dialog/Trial/AlreadyDid.vue

@@ -28,7 +28,10 @@
       <v-btn class="mr-4 submitBtn theme-warning" @click="goSubscribe">
         {{ $t('i_subscribe') }}
       </v-btn>
-      <v-btn class="mr-4 submitBtn theme-neutral-strong" @click="contactOpentalent">
+      <v-btn
+        class="mr-4 submitBtn theme-neutral-strong"
+        @click="contactOpentalent"
+      >
         {{ $t('opentalent_contact') }}
       </v-btn>
     </template>
@@ -36,7 +39,7 @@
 </template>
 
 <script setup lang="ts">
-import UrlUtils from "~/services/utils/urlUtils";
+import UrlUtils from '~/services/utils/urlUtils'
 
 const runtimeConfig = useRuntimeConfig()
 

+ 0 - 1
components/Layout/Header.vue

@@ -116,7 +116,6 @@ const layoutStore = useLayoutStore()
 </script>
 
 <style scoped>
-
 :deep(.v-toolbar__content > .v-toolbar-title) {
   margin-left: 2px;
 

+ 1 - 1
components/Layout/Header/HomeBtn.vue

@@ -12,7 +12,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from '@vue/reactivity'
+import { ref } from 'vue'
 import { useDisplay } from 'vuetify'
 import { useHomeUrl } from '~/composables/utils/useHomeUrl'
 

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

@@ -16,7 +16,7 @@ header principal (configuration, paramètres du compte...)
           :defaultImage="menu.icon.avatarByDefault"
           :width="30"
         /> -->
-        <UiImage :defaultImage="menu.icon.avatarByDefault" :width="30" />
+        <UiImage :default-image="menu.icon.avatarByDefault" :width="30" />
       </v-avatar>
 
       <v-icon v-else :icon="menu.icon.name" class="on-primary" />
@@ -27,7 +27,7 @@ header principal (configuration, paramètres du compte...)
     <v-menu
       :activator="btn"
       :model-value="isOpened()"
-      @update:modelValue="onStateUpdated"
+      @update:model-value="onStateUpdated"
     >
       <v-card>
         <v-card-title class="theme-neutral text-body-2 font-weight-bold">
@@ -48,8 +48,8 @@ header principal (configuration, paramètres du compte...)
                     size="30"
                   >
                     <UiImage
-                      :imageId="child.icon.avatarId"
-                      :defaultImage="child.icon.avatarByDefault"
+                      :image-id="child.icon.avatarId"
+                      :default-image="child.icon.avatarByDefault"
                       :width="30"
                     />
                   </v-avatar>
@@ -89,8 +89,8 @@ header principal (configuration, paramètres du compte...)
 </template>
 
 <script setup lang="ts">
+import { computed, ref } from 'vue'
 import { useMenu } from '~/composables/layout/useMenu'
-import { computed, ref } from '@vue/reactivity'
 
 const props = defineProps({
   name: {

+ 6 - 3
components/Layout/Header/Title.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="d-flex flex-row">
-    <a :href="homeUrl" :title="$t('go_back_home')" class="d-flex flex-row align-center">
+    <a
+      :href="homeUrl"
+      :title="$t('go_back_home')"
+      class="d-flex flex-row align-center"
+    >
       <v-img src="/favicon.ico" height="42" width="42" class="mr-2" />
       <span v-if="mdAndUp"><slot /></span>
     </a>
@@ -8,12 +12,11 @@
 </template>
 
 <script setup lang="ts">
-import { useHomeUrl } from '~/composables/utils/useHomeUrl'
 import { useDisplay } from 'vuetify'
+import { useHomeUrl } from '~/composables/utils/useHomeUrl'
 
 const { homeUrl } = useHomeUrl()
 const { mdAndUp } = useDisplay()
-
 </script>
 
 <style scoped lang="scss">

+ 2 - 2
components/Layout/Header/UniversalCreation/Card.vue

@@ -43,11 +43,11 @@
 </template>
 
 <script setup lang="ts">
-import type { PropType } from '@vue/runtime-core'
+import type { PropType } from 'vue'
+import { useDisplay } from 'vuetify'
 import { MENU_LINK_TYPE } from '~/types/enum/layout'
 import { useAdminUrl } from '~/composables/utils/useAdminUrl'
 import UrlUtils from '~/services/utils/urlUtils'
-import {useDisplay} from 'vuetify';
 
 const props = defineProps({
   /**

+ 4 - 5
components/Layout/Header/UniversalCreation/CreateButton.vue

@@ -49,8 +49,8 @@
       <template #dialogText>
         <LayoutHeaderUniversalCreationGenerateCardsSteps
           :path="path"
-          @cardClick="onCardClick"
-          @urlUpdate="onUrlUpdate"
+          @card-click="onCardClick"
+          @url-update="onUrlUpdate"
         />
       </template>
 
@@ -82,10 +82,9 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from '@vue/reactivity'
-import type { Ref } from '@vue/reactivity'
+import { ref } from 'vue'
+import type { Ref, ComputedRef } from 'vue'
 import { useDisplay } from 'vuetify'
-import type { ComputedRef } from 'vue'
 import { usePageStore } from '~/stores/page'
 
 const { mdAndDown: asIcon } = useDisplay()

+ 2 - 3
components/Layout/Header/UniversalCreation/EventParams.vue

@@ -54,10 +54,9 @@ Event parameters page in the create dialog
 </template>
 
 <script setup lang="ts">
-import { ref } from '@vue/reactivity'
-import type { Ref } from '@vue/reactivity'
+import { ref } from 'vue'
+import type { Ref, ComputedRef } from 'vue'
 import { add, format, startOfHour, formatISO } from 'date-fns'
-import type { ComputedRef } from 'vue'
 import DateUtils, { supportedLocales } from '~/services/utils/dateUtils'
 
 const i18n = useI18n()

+ 27 - 34
components/Layout/Header/UniversalCreation/GenerateCardsSteps.vue

@@ -11,41 +11,41 @@
         <v-container v-if="location === 'home'">
           <v-row>
             <!-- Une personne -->
-            <v-col cols="12" md="6" v-if="ability.can('manage', 'users')">
+            <v-col v-if="ability.can('manage', 'users')" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
-                @click="onCardClick('access')"
                 title="a_person"
                 text-content="add_new_person_student"
                 icon="fa fa-user"
+                @click="onCardClick('access')"
               />
             </v-col>
             <v-col
-              cols="12"
-              md="6"
               v-if="
                 ability.can('display', 'agenda_page') &&
                 (ability.can('display', 'course_page') ||
                   ability.can('display', 'exam_page') ||
                   ability.can('display', 'pedagogics_project_page'))
               "
+              cols="12"
+              md="6"
             >
               <!-- Un évènement -->
               <LayoutHeaderUniversalCreationCard
-                @click="onCardClick('event')"
                 title="an_event"
                 text-content="add_an_event_course"
                 icon="fa fa-calendar"
+                @click="onCardClick('event')"
               />
             </v-col>
 
             <!-- Autre évènement -->
             <v-col
-              cols="12"
-              md="6"
               v-else-if="
                 ability.can('display', 'agenda_page') &&
                 ability.can('manage', 'events')
               "
+              cols="12"
+              md="6"
             >
               <LayoutHeaderUniversalCreationCard
                 to="event-params"
@@ -59,29 +59,25 @@
 
             <!-- Une correspondance -->
             <v-col
-              cols="12"
-              md="6"
               v-if="
                 ability.can('display', 'message_send_page') &&
                 (ability.can('manage', 'emails') ||
                   ability.can('manage', 'mails') ||
                   ability.can('manage', 'texto'))
               "
+              cols="12"
+              md="6"
             >
               <LayoutHeaderUniversalCreationCard
-                @click="onCardClick('message')"
                 title="a_correspondence"
                 text-content="send_email_letter"
                 icon="fa fa-envelope"
+                @click="onCardClick('message')"
               />
             </v-col>
 
             <!-- Un matériel (direct link) -->
-            <v-col
-              cols="12"
-              md="6"
-              v-if="ability.can('manage', 'equipments')"
-            >
+            <v-col v-if="ability.can('manage', 'equipments')" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 title="a_materiel"
                 text-content="add_any_type_material"
@@ -99,11 +95,7 @@
         <v-container v-if="location === 'access'">
           <v-row>
             <!-- Un adhérent -->
-            <v-col
-              cols="12"
-              md="6"
-              v-if="isLaw1901"
-            >
+            <v-col v-if="isLaw1901" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 title="an_adherent"
                 text-content="adherent_text_creation_card"
@@ -114,11 +106,7 @@
             </v-col>
 
             <!-- Un membre du CA -->
-            <v-col
-              cols="12"
-              md="6"
-              v-if="isLaw1901"
-            >
+            <v-col v-if="isLaw1901" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 title="a_ca_member"
                 text-content="ca_member_text_creation_card"
@@ -184,7 +172,7 @@
             </v-col>
 
             <!-- Une inscription en ligne -->
-            <v-col cols="12" md="6" v-if="hasOnlineRegistrationModule">
+            <v-col v-if="hasOnlineRegistrationModule" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 title="online_registration"
                 text-content="online_registration_text_creation_card"
@@ -211,7 +199,11 @@
         <v-container v-if="location === 'event'">
           <v-row>
             <!-- Un cours -->
-            <v-col cols="12" md="6" v-if="ability.can('display', 'course_page')">
+            <v-col
+              v-if="ability.can('display', 'course_page')"
+              cols="12"
+              md="6"
+            >
               <LayoutHeaderUniversalCreationCard
                 title="course"
                 text-content="course_text_creation_card"
@@ -222,7 +214,7 @@
             </v-col>
 
             <!-- Un examen -->
-            <v-col cols="12" md="6" v-if="ability.can('display', 'exam_page')">
+            <v-col v-if="ability.can('display', 'exam_page')" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 title="exam"
                 text-content="exam_text_creation_card"
@@ -234,8 +226,9 @@
 
             <!-- Un projet pédagogique -->
             <v-col
-              cols="12" md="6"
               v-if="ability.can('display', 'pedagogics_project_page')"
+              cols="12"
+              md="6"
             >
               <LayoutHeaderUniversalCreationCard
                 title="educational_services"
@@ -247,7 +240,7 @@
             </v-col>
 
             <!-- Un autre évènement -->
-            <v-col cols="12" md="6" v-if="ability.can('manage', 'events')">
+            <v-col v-if="ability.can('manage', 'events')" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 to="event-params"
                 href="/calendar/create/events"
@@ -264,7 +257,7 @@
         <v-container v-if="location === 'message'">
           <v-row>
             <!-- Un email -->
-            <v-col cols="12" md="6" v-if="ability.can('manage', 'emails')">
+            <v-col v-if="ability.can('manage', 'emails')" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 title="an_email"
                 text-content="email_text_creation_card"
@@ -275,7 +268,7 @@
             </v-col>
 
             <!-- Un courrier -->
-            <v-col cols="12" md="6" v-if="ability.can('manage', 'mails')">
+            <v-col v-if="ability.can('manage', 'mails')" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 title="a_letter"
                 text-content="letter_text_creation_card"
@@ -286,7 +279,7 @@
             </v-col>
 
             <!-- Un SMS -->
-            <v-col cols="12" md="6" v-if="ability.can('manage', 'texto')">
+            <v-col v-if="ability.can('manage', 'texto')" cols="12" md="6">
               <LayoutHeaderUniversalCreationCard
                 title="a_sms"
                 text-content="sms_text_creation_card"
@@ -311,8 +304,8 @@
 </template>
 <script setup lang="ts">
 import { ref, computed } from 'vue'
-import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 import { useAbility } from '@casl/vue'
+import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 
 const props = defineProps({
   /**

+ 3 - 3
components/Layout/MainMenu.vue

@@ -61,9 +61,9 @@ Prend en paramètre une liste de ItemMenu et les met en forme
 
           <v-list-item
             v-for="child in item.children"
+            :id="'main-menu-item' + item.label + '-' + child.label"
             :key="child.label"
             :title="$t(child.label)"
-            :id="'main-menu-item' + item.label + '-' + child.label"
             :prepend-icon="child.icon.name"
             :href="!isInternalLink(child) ? child.to : undefined"
             :to="isInternalLink(child) ? child.to : undefined"
@@ -82,9 +82,9 @@ Prend en paramètre une liste de ItemMenu et les met en forme
 </template>
 
 <script setup lang="ts">
-import { useMenu } from '~/composables/layout/useMenu'
-import { computed } from '@vue/reactivity'
+import { computed } from 'vue'
 import { useDisplay } from 'vuetify'
+import { useMenu } from '~/composables/layout/useMenu'
 import type { MenuGroup, MenuItem } from '~/types/layout'
 import { useApiLegacyRequestService } from '~/composables/data/useApiLegacyRequestService'
 

+ 6 - 6
components/Layout/Parameters/EntityTable.vue

@@ -11,15 +11,15 @@ A data table for the parameters page
         :columns-definitions="columns"
         :actions="actions"
         :actions-route="actionsRoute"
-        @editClicked="onEditClicked"
-        @deleteClicked="onDeleteClicked"
-        @addClicked="goToCreatePage"
+        @edit-clicked="onEditClicked"
+        @delete-clicked="onDeleteClicked"
+        @add-clicked="goToCreatePage"
       />
 
       <UiFormDeletionConfirmationDialog
         v-model="showDeletionConfirmationDialog"
-        @deleteClicked="onDeleteConfirmed"
-        @cancelClicked="onCancelClicked"
+        @delete-clicked="onDeleteConfirmed"
+        @cancel-clicked="onCancelClicked"
       />
     </div>
   </div>
@@ -47,7 +47,7 @@ const props = defineProps({
   title: {
     type: String,
     required: false,
-    default: null
+    default: null,
   },
   /**
    * If provided, define the columns to show.

+ 6 - 10
components/Layout/Parameters/Menu.vue

@@ -54,17 +54,15 @@ const isOpened = computed(() => isMenuOpened('Parameters'))
 
 // En vue lg+, on affiche toujours le menu
 const displayMenu = computed(() => {
-  return menu !== null && hasMenu('Parameters') && (lgAndUp.value || isOpened.value)
+  return (
+    menu !== null && hasMenu('Parameters') && (lgAndUp.value || isOpened.value)
+  )
 })
 
 // En vue md+, fermer le menu le passe simplement en mode rail
 // Sinon, le fermer le masque complètement
 const isRail = computed(() => {
-  return (
-    menu !== null &&
-    mdAndUp.value &&
-    !isOpened.value
-  )
+  return menu !== null && mdAndUp.value && !isOpened.value
 })
 
 const onItemClicked = () => {
@@ -90,15 +88,14 @@ onUnmounted(() => {
 </script>
 
 <style scoped lang="scss">
-
 .parameters-menu {
   position: relative;
   overflow: hidden;
 }
 
 .parameters-menu::before {
-  content: "\f013";
-  font-family: "Font Awesome 6 Free",serif;
+  content: '\f013';
+  font-family: 'Font Awesome 6 Free', serif;
   font-weight: 900;
   font-size: 300px;
   color: rgb(var(--v-theme-neutral-soft));
@@ -110,7 +107,6 @@ onUnmounted(() => {
   user-select: none;
 }
 
-
 .title {
   display: flex;
   flex-direction: row;

+ 30 - 34
components/Layout/Parameters/Table.vue

@@ -19,26 +19,19 @@ A data table for the parameters page
         </tr>
       </thead>
       <tbody v-if="items.length > 0">
-        <tr
-          v-for="(item, i) in items"
-          :key="i"
-        >
-          <td
-            v-for="col in columnsDefinitions"
-            class="cycle-editable-cell"
-          >
+        <tr v-for="(item, i) in items" :key="i">
+          <td v-for="col in columnsDefinitions" class="cycle-editable-cell">
             {{ item[col.property] }}
           </td>
 
           <td class="d-flex flex-row justify-center actions-cell">
-            <v-menu
-              min-width="120"
-              location="end"
-              class="action-menu"
-            >
-              <template v-slot:activator="{ props }">
+            <v-menu min-width="120" location="end" class="action-menu">
+              <template #activator="{ props }">
                 <v-btn
-                  v-if="actions.includes(TABLE_ACTION.EDIT) || actions.includes(TABLE_ACTION.DELETE)"
+                  v-if="
+                    actions.includes(TABLE_ACTION.EDIT) ||
+                    actions.includes(TABLE_ACTION.DELETE)
+                  "
                   v-bind="props"
                   :flat="true"
                   icon="fas fa-ellipsis-vertical"
@@ -52,18 +45,18 @@ A data table for the parameters page
                 >
                   <v-list-item-title>
                     <v-icon>fas fa-pen</v-icon>
-                    {{ $t("edit") }}
+                    {{ $t('edit') }}
                   </v-list-item-title>
                 </v-list-item>
 
                 <v-list-item
                   v-if="actions.includes(TABLE_ACTION.DELETE)"
-                  @click="emit('deleteClicked', item)"
                   class="theme-danger"
+                  @click="emit('deleteClicked', item)"
                 >
                   <v-list-item-title icon="fas fa-trash">
                     <v-icon>fas fa-trash</v-icon>
-                    {{ $t("delete") }}
+                    {{ $t('delete') }}
                   </v-list-item-title>
                 </v-list-item>
               </v-list>
@@ -81,7 +74,10 @@ A data table for the parameters page
       </tbody>
     </v-table>
 
-    <div v-if="actions.includes(TABLE_ACTION.ADD)" class="d-flex justify-center my-3">
+    <div
+      v-if="actions.includes(TABLE_ACTION.ADD)"
+      class="d-flex justify-center my-3"
+    >
       <v-btn
         prepend-icon="fa fa-plus"
         class="theme-neutral"
@@ -94,9 +90,9 @@ A data table for the parameters page
 </template>
 
 <script setup lang="ts">
-import {TABLE_ACTION} from '~/types/enum/enums';
-import type {ColumnDefinition} from '~/types/interfaces';
-import {useDisplay} from 'vuetify';
+import { useDisplay } from 'vuetify'
+import { TABLE_ACTION } from '~/types/enum/enums'
+import type { ColumnDefinition } from '~/types/interfaces'
 
 const props = defineProps({
   /**
@@ -110,7 +106,7 @@ const props = defineProps({
   title: {
     type: String,
     required: false,
-    default: null
+    default: null,
   },
   /**
    * If provided, define the columns to show.
@@ -124,7 +120,7 @@ const props = defineProps({
   columnsDefinitions: {
     type: Array as PropType<Array<ColumnDefinition> | null>,
     required: false,
-    default: null
+    default: null,
   },
   /**
    * The property used as identifier (required by 'edition' link)
@@ -132,7 +128,7 @@ const props = defineProps({
   identifier: {
     type: String,
     required: false,
-    default: 'id'
+    default: 'id',
   },
   /**
    * List of the actions available for each record
@@ -140,7 +136,7 @@ const props = defineProps({
   actions: {
     type: Array as PropType<Array<TABLE_ACTION>>,
     required: false,
-    default: [TABLE_ACTION.EDIT, TABLE_ACTION.DELETE, TABLE_ACTION.ADD]
+    default: [TABLE_ACTION.EDIT, TABLE_ACTION.DELETE, TABLE_ACTION.ADD],
   },
   /**
    * The URL for the edit / create pages
@@ -152,8 +148,8 @@ const props = defineProps({
   actionsRoute: {
     type: String,
     required: false,
-    default: '/parameters'
-  }
+    default: '/parameters',
+  },
 })
 
 const i18n = useI18n()
@@ -167,18 +163,16 @@ const getId = (item: object) => {
 }
 
 const columns: ComputedRef<Array<ColumnDefinition>> = computed(() => {
-  return props.columnsDefinitions.map(col => {
+  return props.columnsDefinitions.map((col) => {
     return {
       property: col.property,
-      label: col.label ?? i18n.t(col.property)
+      label: col.label ?? i18n.t(col.property),
     }
   })
 })
-
 </script>
 
 <style scoped lang="scss">
-
 .container {
   //max-width: 1000px;
   //margin: 0 auto;
@@ -192,7 +186,8 @@ const columns: ComputedRef<Array<ColumnDefinition>> = computed(() => {
     font-weight: 600;
 
     td {
-      border-bottom: thin solid rgba(var(--v-border-color), var(--v-border-opacity));
+      border-bottom: thin solid
+        rgba(var(--v-border-color), var(--v-border-opacity));
     }
 
     td:last-of-type {
@@ -207,7 +202,8 @@ const columns: ComputedRef<Array<ColumnDefinition>> = computed(() => {
     }
   }
 
-  th, td {
+  th,
+  td {
     padding: 10px;
     text-align: left;
   }

+ 11 - 18
components/Layout/Parameters/Website/ActivationSwitch.vue

@@ -9,7 +9,7 @@
       false-icon="fas fa-xmark"
       true-icon="fas fa-check"
       hide-details
-      @update:modelValue="onUpdate"
+      @update:model-value="onUpdate"
     />
 
     <LazyLayoutDialog :show="showWebsiteDeactivationDialog" theme="warning">
@@ -20,19 +20,14 @@
         <v-col>
           <div>
             {{
-              $t(
-                'yourOpentalentWebsiteWillBeDeactivatedOnceYouLlHaveSaved',
-              )
+              $t('yourOpentalentWebsiteWillBeDeactivatedOnceYouLlHaveSaved')
             }}.
           </div>
           <span>{{ $t('doYouWantToContinue') }} ?</span>
         </v-col>
       </template>
       <template #dialogBtn>
-        <v-btn
-          class="theme-neutral-soft mr-4"
-          @click="onDialogNoBtnClick"
-        >
+        <v-btn class="theme-neutral-soft mr-4" @click="onDialogNoBtnClick">
           {{ $t('cancel') }}
         </v-btn>
 
@@ -45,9 +40,8 @@
 </template>
 
 <script setup lang="ts">
-
-import {useTheme} from 'vuetify';
-import type {Ref} from 'vue';
+import { useTheme } from 'vuetify'
+import type { Ref } from 'vue'
 
 const theme = useTheme()
 
@@ -59,12 +53,13 @@ const props = defineProps({
   modelValue: {
     type: Boolean,
     required: true,
-  }
+  },
 })
 
-const color = computed(() => props.modelValue ?
-  theme.current.value.colors['success'] :
-  theme.current.value.colors['danger']
+const color = computed(() =>
+  props.modelValue
+    ? theme.current.value.colors.success
+    : theme.current.value.colors.danger,
 )
 
 const showWebsiteDeactivationDialog: Ref<boolean> = ref(false)
@@ -88,6 +83,4 @@ const onDialogNoBtnClick = () => {
 }
 </script>
 
-<style scoped lang="scss">
-
-</style>
+<style scoped lang="scss"></style>

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

@@ -29,12 +29,12 @@
 </template>
 
 <script setup lang="ts">
+import { useDisplay } from 'vuetify'
 import { useEntityManager } from '~/composables/data/useEntityManager'
 import { useFormStore } from '~/stores/form'
 import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 import { useAccessProfileStore } from '~/stores/accessProfile'
 import Access from '~/models/Access/Access'
-import { useDisplay } from 'vuetify'
 import { usePageStore } from '~/stores/page'
 import { useRefreshProfile } from '~/composables/data/useRefreshProfile'
 
@@ -63,14 +63,14 @@ const label: string = organizationProfileStore.isSchool
 const setActivityYear = async (event: string) => {
   const activityYear = parseInt(event)
 
-  if (!(1900 < activityYear) || !(activityYear <= 2100)) {
+  if (!(activityYear > 1900) || !(activityYear <= 2100)) {
     throw new Error("Error: 'year' shall be a valid year")
   }
   formStore.setDirty(false)
 
   pageStore.loading = true
   await em.patch(Access, accessProfileStore.currentAccessId, {
-    activityYear: activityYear,
+    activityYear,
   })
   if (process.server) {
     // Force profile refresh server side to avoid a bug where server and client stores diverge on profile refresh

+ 4 - 5
components/Layout/SubHeader/Breadcrumbs.vue

@@ -3,10 +3,10 @@
 </template>
 
 <script setup lang="ts">
-import { computed } from '@vue/reactivity'
-import type { ComputedRef } from '@vue/reactivity'
-import type { AnyJson } from '~/types/data'
+import { computed } from 'vue'
+import type { ComputedRef } from 'vue'
 import { useI18n } from 'vue-i18n'
+import type { AnyJson } from '~/types/data'
 import UrlUtils from '~/services/utils/urlUtils'
 
 const runtimeConfig = useRuntimeConfig()
@@ -16,8 +16,7 @@ const router = useRouter()
 const items: ComputedRef<Array<AnyJson>> = computed(() => {
   const crumbs: Array<AnyJson> = []
   const baseUrl =
-    runtimeConfig.baseUrlAdminLegacy ??
-    runtimeConfig.public.baseUrlAdminLegacy
+    runtimeConfig.baseUrlAdminLegacy ?? runtimeConfig.public.baseUrlAdminLegacy
 
   crumbs.push({
     title: i18n.t('welcome'),

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

@@ -14,7 +14,7 @@
       border
       :rounded="true"
       class="toggle-btn"
-      @update:modelValue="onUpdate"
+      @update:model-value="onUpdate"
     >
       <v-btn
         v-for="choice in historicalChoices"
@@ -36,17 +36,17 @@
 </template>
 
 <script setup lang="ts">
+import type { Ref } from 'vue'
+import { useDisplay, useTheme } from 'vuetify'
 import { useFormStore } from '~/stores/form'
 import { useAccessProfileStore } from '~/stores/accessProfile'
-import type { Ref } from '@vue/reactivity'
 import { useEntityManager } from '~/composables/data/useEntityManager'
-import { useDisplay, useTheme } from 'vuetify'
 import Access from '~/models/Access/Access'
 import { usePageStore } from '~/stores/page'
 import { useRefreshProfile } from '~/composables/data/useRefreshProfile'
 
 // TODO: en v3.0.5, pas de solution documentée pour renseigner directement la couleur dans le template, à revoir
-const color = useTheme().current.value.colors['primary']
+const color = useTheme().current.value.colors.primary
 
 const { setDirty } = useFormStore()
 const accessProfileStore = useAccessProfileStore()

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

@@ -9,7 +9,7 @@
         :model-value="datesRange"
         :max-height="28"
         :range="true"
-        :autoApply="false"
+        :auto-apply="false"
         @update:model-value="updateDateTimeRange"
       />
     </div>
@@ -17,7 +17,7 @@
 </template>
 
 <script setup lang="ts">
-import type { Ref } from '@vue/reactivity'
+import type { Ref } from 'vue'
 import { useAccessProfileStore } from '~/stores/accessProfile'
 import { useFormStore } from '~/stores/form'
 import { useEntityManager } from '~/composables/data/useEntityManager'

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

@@ -1,6 +1,6 @@
 <template>
   <main>
-    <a ref="btn" id="activator">
+    <a id="activator" ref="btn">
       {{ $t('my_list') }}
     </a>
 
@@ -51,10 +51,10 @@
 </template>
 
 <script setup lang="ts">
+import { ref } from 'vue'
+import type { ComputedRef, Ref } from 'vue'
 import PersonalizedList from '~/models/Access/PersonalizedList'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'
-import { ref } from '@vue/reactivity'
-import type { ComputedRef, Ref } from '@vue/reactivity'
 import type { AnyJson } from '~/types/data'
 import ApiResource from '~/models/ApiResource'
 import UrlUtils from '~/services/utils/urlUtils'
@@ -84,8 +84,8 @@ const filteredItems = computed(() => {
   return items.value.filter((item) => {
     return (
       !search.value ||
-      item.label.toLowerCase().indexOf(search.value.toLowerCase()) >= 0 ||
-      item.menuKey.toLowerCase().indexOf(search.value.toLowerCase()) >= 0
+      item.label.toLowerCase().includes(search.value.toLowerCase()) ||
+      item.menuKey.toLowerCase().includes(search.value.toLowerCase())
     )
   })
 })

+ 4 - 4
components/Layout/Subheader.vue

@@ -68,11 +68,11 @@ Contient entre autres le breadcrumb, les commandes de changement d'année et les
 </template>
 
 <script setup lang="ts">
-import { useAccessProfileStore } from '~/stores/accessProfile'
-import { computed, ref } from '@vue/reactivity'
-import type { ComputedRef, Ref } from '@vue/reactivity'
-import { useMenu } from '~/composables/layout/useMenu'
+import { computed, ref } from 'vue'
+import type { ComputedRef, Ref } from 'vue'
 import { useDisplay } from 'vuetify'
+import { useMenu } from '~/composables/layout/useMenu'
+import { useAccessProfileStore } from '~/stores/accessProfile'
 
 const { smAndUp, lgAndUp } = useDisplay()
 const accessProfile = useAccessProfileStore()

+ 2 - 2
components/Layout/UpgradePremiumButton.vue

@@ -13,15 +13,15 @@
 
     <LayoutDialogTrialAlreadyDid
       :show="showDialog"
-      @closeDialog="showDialog = false"
+      @close-dialog="showDialog = false"
     />
   </div>
 </template>
 
 <script setup lang="ts">
+import { computed } from 'vue'
 import UrlUtils from '~/services/utils/urlUtils'
 import { useApiLegacyRequestService } from '~/composables/data/useApiLegacyRequestService'
-import { computed } from '@vue/reactivity'
 
 const runtimeConfig = useRuntimeConfig()
 const organizationProfile = useOrganizationProfileStore()

+ 9 - 10
components/Ui/Button/Submit.vue

@@ -1,20 +1,20 @@
 <template>
   <v-btn
+    ref="mainBtn"
     class="submit-btn theme-primary"
     :class="hasOtherActions ? 'pr-0' : ''"
-    @click="submitAction(mainAction)"
-    ref="mainBtn"
     :disabled="validationPending"
+    @click="submitAction(mainAction)"
   >
     {{ $t(mainAction) }}
 
-    <v-divider class="ml-3" :vertical="true" v-if="hasOtherActions"></v-divider>
+    <v-divider v-if="hasOtherActions" class="ml-3" :vertical="true"></v-divider>
 
     <v-menu
+      v-if="hasOtherActions"
       :top="dropDirection === 'top'"
       offset-y
       left
-      v-if="hasOtherActions"
       :nudge-top="dropDirection === 'top' ? 6 : 0"
       :nudge-bottom="dropDirection === 'bottom' ? 6 : 0"
     >
@@ -29,15 +29,15 @@
       </template>
       <v-list :min-width="menuSize">
         <v-list-item
-          dense
           v-for="(action, index) in actions"
+          v-if="index > 0"
           :key="index"
+          dense
           class="subAction"
-          v-if="index > 0"
         >
           <v-list-item-title
-            v-text="$t(action)"
             @click="submitAction(action)"
+            v-text="$t(action)"
           />
         </v-list-item>
       </v-list>
@@ -46,8 +46,8 @@
 </template>
 
 <script setup lang="ts">
-import { computed, ref } from '@vue/reactivity'
-import type { ComputedRef, Ref } from '@vue/reactivity'
+import { computed, ref } from 'vue'
+import type { ComputedRef, Ref } from 'vue'
 
 const props = defineProps({
   actions: {
@@ -88,7 +88,6 @@ const hasOtherActions: ComputedRef<boolean> = computed(() => {
 </script>
 
 <style scoped>
-
 .submit-btn {
   margin-right: 12px;
 

+ 2 - 2
components/Ui/Collection.vue

@@ -20,8 +20,8 @@
 </template>
 
 <script setup lang="ts">
-import { computed, toRefs } from '@vue/reactivity'
-import type { ComputedRef, ToRefs } from '@vue/reactivity'
+import { computed, toRefs } from 'vue'
+import type { ComputedRef, ToRefs } from 'vue'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'
 import type { Collection } from '~/types/data'
 

+ 2 - 2
components/Ui/DataTable.vue

@@ -28,8 +28,8 @@ Tableau interactif conçu pour l'affichage d'une collection d'entités
 </template>
 
 <script setup lang="ts">
-import { ref, toRefs } from '@vue/reactivity'
-import type { Ref } from '@vue/reactivity'
+import { ref, toRefs } from 'vue'
+import type { Ref } from 'vue'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'
 import ApiResource from '~/models/ApiResource'
 import type { AnyJson } from '~/types/data'

+ 0 - 1
components/Ui/Form.vue

@@ -425,7 +425,6 @@ defineExpose({ validate })
       }
     }
   }
-
 }
 
 .confirmation-dlg-actions {

+ 9 - 11
components/Ui/Form/DeletionConfirmationDialog.vue

@@ -1,9 +1,5 @@
 <template>
-  <LazyLayoutDialog
-    :show="modelValue"
-    theme="danger"
-  >
-
+  <LazyLayoutDialog :show="modelValue" theme="danger">
     <template #dialogTitle>
       {{ $t('caution') }}
     </template>
@@ -28,11 +24,15 @@
 <script setup lang="ts">
 const props = defineProps({
   modelValue: {
-    type: Boolean
-  }
+    type: Boolean,
+  },
 })
 
-const emit = defineEmits(['cancelClicked', 'deleteClicked', 'update:modelValue'])
+const emit = defineEmits([
+  'cancelClicked',
+  'deleteClicked',
+  'update:modelValue',
+])
 
 const onCancelClicked = () => {
   emit('cancelClicked')
@@ -45,6 +45,4 @@ const onDeleteClicked = () => {
 }
 </script>
 
-<style scoped lang="scss">
-
-</style>
+<style scoped lang="scss"></style>

+ 6 - 6
components/Ui/Help.vue

@@ -12,24 +12,24 @@
   >
     <template #activator="{}">
       <v-icon
-        @click="onIconClicked"
+        ref="iconRef"
         icon
         class="ml-3"
         size="18px"
-        ref="iconRef"
+        @click="onIconClicked"
       >
         {{ icon }}
       </v-icon>
     </template>
 
-    <div ref="slotDiv" class="tooltip" v-click-out="onClickOutside">
+    <div ref="slotDiv" v-click-out="onClickOutside" class="tooltip">
       <slot></slot>
     </div>
   </v-tooltip>
 </template>
 
 <script setup lang="ts">
-import type { Ref } from '@vue/reactivity'
+import type { Ref } from 'vue'
 
 const props = defineProps({
   left: {
@@ -61,13 +61,13 @@ const props = defineProps({
 
 const { $refs } = useNuxtApp()
 
-const show: Ref<Boolean> = ref(false)
+const show: Ref<boolean> = ref(false)
 
 // Template reference to the icon object
 const iconRef = ref(null)
 
 // Left is the default, set it to true if not any other is true
-const leftOrDefault: Ref<Boolean> = ref(
+const leftOrDefault: Ref<boolean> = ref(
   props.left || (!props.right && !props.bottom && !props.top),
 )
 

+ 2 - 3
components/Ui/Image.vue

@@ -14,10 +14,10 @@ Permet d'afficher une image par défaut si l'image demandée n'est pas disponibl
       >
         <template #placeholder>
           <v-row
+            v-if="pending"
             class="fill-height ma-0"
             align="center"
             justify="center"
-            v-if="pending"
           >
             <v-progress-circular :indeterminate="true" color="neutral" />
           </v-row>
@@ -36,10 +36,9 @@ Permet d'afficher une image par défaut si l'image demandée n'est pas disponibl
 </template>
 
 <script setup lang="ts">
+import type { WatchStopHandle, Ref } from 'vue'
 import { useImageFetch } from '~/composables/data/useImageFetch'
 import ImageManager from '~/services/data/imageManager'
-import type { WatchStopHandle } from '@vue/runtime-core'
-import type { Ref } from '@vue/reactivity'
 
 const props = defineProps({
   /**

+ 7 - 8
components/Ui/Input/AutocompleteWithAPI.vue

@@ -11,27 +11,26 @@ d'une api)
       :label="label"
       :data="remoteData ? remoteData : data"
       :items="items"
-      :isLoading="isLoading"
+      :is-loading="isLoading"
       :item-text="itemText"
-      :slotText="slotText"
+      :slot-text="slotText"
       :item-value="itemValue"
       :multiple="multiple"
       :chips="chips"
-      prependIcon="mdi-magnify"
+      prepend-icon="mdi-magnify"
       :return-object="returnObject"
-      @research="search"
       :no-filter="noFilter"
+      @research="search"
       @update="$emit('update', $event, field)"
     />
   </main>
 </template>
 
 <script setup lang="ts">
-import { ref, toRefs } from '@vue/reactivity'
-import type { Ref } from '@vue/reactivity'
-import UrlUtils from '~/services/utils/urlUtils'
+import { ref, toRefs, watch } from 'vue'
+import type { Ref } from 'vue'
 import { useFetch } from '#app'
-import { watch } from '@vue/runtime-core'
+import UrlUtils from '~/services/utils/urlUtils'
 
 const props = defineProps({
   label: {

+ 0 - 2
components/Ui/Input/Checkbox.vue

@@ -94,7 +94,6 @@ const onUpdate = (event: boolean) => {
 </script>
 
 <style scoped lang="scss">
-
 .checkbox {
   margin-top: -4px;
   margin-bottom: 8px;
@@ -109,5 +108,4 @@ const onUpdate = (event: boolean) => {
 :deep(.v-label) {
   padding-left: 8px;
 }
-
 </style>

+ 4 - 5
components/Ui/Input/DatePicker.vue

@@ -109,7 +109,6 @@ const onUpdate = (event: string) => {
 </script>
 
 <style scoped lang="scss">
-
 .container {
   position: relative;
 }
@@ -123,8 +122,10 @@ const onUpdate = (event: string) => {
   padding: 0 0.3rem;
   font-size: 0.8rem;
   z-index: 1;
-  transition: color 0.2s, font-size 0.2s, top 0.2s;
-
+  transition:
+    color 0.2s,
+    font-size 0.2s,
+    top 0.2s;
 }
 
 .date-picker:hover {
@@ -146,6 +147,4 @@ const onUpdate = (event: string) => {
     color: #333333;
   }
 }
-
-
 </style>

+ 2 - 2
components/Ui/Input/Enum.vue

@@ -23,7 +23,7 @@ Liste déroulante dédiée à l'affichage d'objets Enum
         errorMessage || (fieldViolations ? $t(fieldViolations) : '')
       "
       density="compact"
-      @update:modelValue="
+      @update:model-value="
         updateViolationState($event)
         $emit('update:modelValue', $event)
       "
@@ -104,7 +104,7 @@ const props = defineProps({
 })
 
 if (typeof props.enum === 'undefined') {
-  throw new Error("missing 'enum' property for input")
+  throw new TypeError("missing 'enum' property for input")
 }
 
 const { fieldViolations, updateViolationState } = useFieldViolation(props.field)

+ 0 - 1
components/Ui/Input/Number.vue

@@ -118,7 +118,6 @@ const keepInRange = (val: number) => {
 const emit = defineEmits(['update:modelValue'])
 
 const onModelUpdate = (event: string) => {
-  // eslint-disable-next-line vue/no-mutating-props
   // props.modelValue = keepInRange(cast(event))
   // emitUpdate()
   emit('update:modelValue', keepInRange(cast(event)))

+ 2 - 2
components/Ui/Input/Phone.vue

@@ -9,11 +9,11 @@ Champs de saisie d'un numéro de téléphone
 <template>
   <client-only>
     <vue-tel-input-vuetify
+      v-model="myPhone"
       :error="error || !!violation"
       :error-messages="errorMessage || violation ? $t(violation) : ''"
       :field="field"
       :label="label"
-      v-model="myPhone"
       :readonly="readonly"
       clearable
       valid-characters-only
@@ -27,8 +27,8 @@ Champs de saisie d'un numéro de téléphone
 
 <script setup lang="ts">
 import { useNuxtApp } from '#app'
+import type { Ref } from 'vue'
 import { useFieldViolation } from '~/composables/form/useFieldViolation'
-import type { Ref } from '@vue/reactivity'
 
 const props = defineProps({
   label: {

+ 2 - 2
components/Ui/ItemFromUri.vue

@@ -15,10 +15,10 @@ Espace permettant de récupérer un item via une uri et de gérer son affichage
 // TODO: renommer en EntityFromUri? voir si ce component est encore nécessaire, ou si ça ne peut pas être une méthode de l'entity manager
 
 import { Query } from 'pinia-orm'
+import { computed } from 'vue'
+import type { ComputedRef } from 'vue'
 import UrlUtils from '~/services/utils/urlUtils'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'
-import { computed } from '@vue/reactivity'
-import type { ComputedRef } from '@vue/reactivity'
 import ApiResource from '~/models/ApiResource'
 
 const props = defineProps({

+ 1 - 2
components/Ui/SystemBar.vue

@@ -15,7 +15,7 @@ System bars
 </template>
 
 <script setup lang="ts">
-import {useDisplay} from 'vuetify';
+import { useDisplay } from 'vuetify'
 
 const props = defineProps({
   text: {
@@ -36,7 +36,6 @@ const props = defineProps({
 })
 </script>
 
-
 <style scoped lang="scss">
 .alert-bar {
   position: relative;

+ 2 - 2
components/Ui/Template/Date.vue

@@ -7,9 +7,9 @@ Date formatée
 </template>
 
 <script setup lang="ts">
+import { computed } from 'vue'
+import type { ComputedRef } from 'vue'
 import DateUtils from '~/services/utils/dateUtils'
-import { computed } from '@vue/reactivity'
-import type { ComputedRef } from '@vue/reactivity'
 
 const props = defineProps({
   data: {

+ 3 - 3
components/Ui/Xeditable/Text.vue

@@ -8,7 +8,7 @@ Utilisé par exemple pour le choix de l'année active
   <main>
     <!-- Mode édition activé -->
     <div v-if="edit" class="d-flex align-center x-editable-input">
-      <UiInputText class="ma-0 pa-0" :type="type" v-model="inputValue" />
+      <UiInputText v-model="inputValue" class="ma-0 pa-0" :type="type" />
 
       <v-icon
         icon="fas fa-check"
@@ -34,8 +34,8 @@ Utilisé par exemple pour le choix de l'année active
 </template>
 
 <script setup lang="ts">
-import { ref } from '@vue/reactivity'
-import type { Ref } from '@vue/reactivity'
+import { ref } from 'vue'
+import type { Ref } from 'vue'
 
 const props = defineProps({
   type: {

+ 0 - 1
composables/utils/useDownloadFile.ts

@@ -17,6 +17,5 @@ export const useDownloadFile = async (file: File) => {
 
   const blob = new Blob([blobPart], { type: response.type })
 
-  // eslint-disable-next-line import/no-named-as-default-member
   FileSaver.saveAs(blob, file.name ?? 'unknown')
 }

+ 0 - 1
composables/utils/useDownloadFromRoute.ts

@@ -19,6 +19,5 @@ export const useDownloadFromRoute = async (route: string, filename: string) => {
 
   const blob = new Blob([response], { type: response.type })
 
-  // eslint-disable-next-line import/no-named-as-default-member
   FileSaver.saveAs(blob, filename)
 }

+ 6 - 2
composables/utils/useRedirect.ts

@@ -4,7 +4,9 @@ export const useRedirect = () => {
   const runtimeConfig = useRuntimeConfig()
 
   const redirectToLogout = () => {
-    const baseUrl = runtimeConfig.baseUrlAdminLegacy ?? runtimeConfig.public.baseUrlAdminLegacy
+    const baseUrl =
+      runtimeConfig.baseUrlAdminLegacy ??
+      runtimeConfig.public.baseUrlAdminLegacy
 
     if (!baseUrl) {
       throw new Error('Configuration error : no redirection target')
@@ -15,7 +17,9 @@ export const useRedirect = () => {
   }
 
   const redirectToHome = () => {
-    const baseUrl = runtimeConfig.baseUrlAdminLegacy ?? runtimeConfig.public.baseUrlAdminLegacy
+    const baseUrl =
+      runtimeConfig.baseUrlAdminLegacy ??
+      runtimeConfig.public.baseUrlAdminLegacy
 
     if (!baseUrl) {
       throw new Error('Configuration error : no redirection target')

+ 1 - 1
env/setupEnv.mjs

@@ -33,7 +33,7 @@ const environments = {
 }
 
 if (!environments.hasOwnProperty(hostname)) {
-  throw Error('Critical : unknown environment [' + hostname + ']')
+  throw new Error('Critical : unknown environment [' + hostname + ']')
 }
 
 const targetEnvFile = path.join(projectDir, 'env', environments[hostname])

+ 3 - 3
eslint.config.mjs

@@ -1,9 +1,9 @@
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
 import vue from 'eslint-plugin-vue'
 import typescriptEslint from '@typescript-eslint/eslint-plugin'
 import globals from 'globals'
 import parser from 'vue-eslint-parser'
-import path from 'node:path'
-import { fileURLToPath } from 'node:url'
 import js from '@eslint/js'
 import { FlatCompat } from '@eslint/eslintrc'
 
@@ -59,7 +59,7 @@ export default [
         useRepo: 'readonly',
       },
 
-      parser: parser,
+      parser,
       ecmaVersion: 2020,
       sourceType: 'module',
 

+ 0 - 1
layouts/parameters.vue

@@ -38,7 +38,6 @@ const route = useRoute()
 const i18n = useI18n()
 
 const pageTitle = computed(() => i18n.t(route.name || 'parameters_page'))
-
 </script>
 
 <style scoped lang="scss">

+ 2 - 2
models/decorators.ts

@@ -10,7 +10,7 @@ import ApiResource from '~/models/ApiResource'
 export function IriEncoded(apiResource: typeof ApiResource): PropertyDecorator {
   // We have to comply with the PropertyDecorator return type
   // eslint-disable-next-line @typescript-eslint/ban-types
-  return (target: Object, propertyKey: string | symbol) => {
+  return (target: object, propertyKey: string | symbol) => {
     // @ts-expect-error The object is an ApiResource
     const self = target.$self()
 
@@ -28,7 +28,7 @@ export function IriEncoded(apiResource: typeof ApiResource): PropertyDecorator {
 export function IdField(): PropertyDecorator {
   // We have to comply with the PropertyDecorator return type
   // eslint-disable-next-line @typescript-eslint/ban-types
-  return (target: Object, propertyKey: string | symbol) => {
+  return (target: object, propertyKey: string | symbol) => {
     // @ts-expect-error The object is an ApiResource
     const self = target.$self()
 

+ 7 - 7
nuxt.config.ts

@@ -125,13 +125,13 @@ export default defineNuxtConfig({
     },
   },
 
- css: [
-   '@/assets/css/global.scss',
-   '@/assets/css/theme.scss',
-   '@/assets/css/import.scss',
-   '@vuepic/vue-datepicker/dist/main.css',
-   '@/assets/css/vue-date-picker.scss',
- ],
+  css: [
+    '@/assets/css/global.scss',
+    '@/assets/css/theme.scss',
+    '@/assets/css/import.scss',
+    '@vuepic/vue-datepicker/dist/main.css',
+    '@/assets/css/vue-date-picker.scss',
+  ],
 
   typescript: {
     strict: true,

+ 0 - 1
pages/parameters.vue

@@ -16,7 +16,6 @@ definePageMeta({
   name: 'parameters_page',
   layout: false,
 })
-
 </script>
 
 <style scoped lang="scss">

+ 2 - 5
pages/parameters/attendances.vue

@@ -1,11 +1,8 @@
 <template>
   <LayoutParametersSection v-if="organizationProfile.isSchool">
-    <h4>{{ $t("alert_configuration") }}</h4>
+    <h4>{{ $t('alert_configuration') }}</h4>
     <UiLoadingPanel v-if="pending" />
-    <UiForm
-      v-else-if="parameters !== null"
-      v-model="parameters"
-    >
+    <UiForm v-else-if="parameters !== null" v-model="parameters">
       <v-row>
         <v-col cols="12">
           <UiInputCheckbox

+ 1 - 4
pages/parameters/bulletin.vue

@@ -2,10 +2,7 @@
   <LayoutContainer>
     <LayoutParametersSection>
       <UiLoadingPanel v-if="pending" />
-      <UiForm
-        v-else
-        v-model="parameters"
-      >
+      <UiForm v-else v-model="parameters">
         <v-row>
           <v-col cols="12">
             <h4 class="mb-8">{{ $t('itemsToDisplayOnBulletins') }}</h4>

+ 1 - 4
pages/parameters/education_notation.vue

@@ -2,10 +2,7 @@
   <LayoutContainer>
     <LayoutParametersSection>
       <UiLoadingPanel v-if="pending" />
-      <UiForm
-        v-else
-        v-model="parameters"
-      >
+      <UiForm v-else v-model="parameters">
         <v-row>
           <v-col cols="12">
             <UiInputCheckbox

+ 1 - 1
pages/parameters/education_timings/index.vue

@@ -1,6 +1,6 @@
 <template>
   <LayoutContainer>
-      <LayoutParametersSection>
+    <LayoutParametersSection>
       <LayoutParametersEntityTable
         :model="EducationTiming"
         :columns-definitions="[{ property: 'timing' }]"

+ 7 - 6
pages/parameters/general_parameters.vue

@@ -2,14 +2,14 @@
   <LayoutContainer>
     <LayoutParametersSection>
       <UiLoadingPanel v-if="pending" />
-      <UiForm
-        v-else-if="parameters !== null"
-        v-model="parameters"
-      >
+      <UiForm v-else-if="parameters !== null" v-model="parameters">
         <v-row>
           <v-col cols="12">
             <UiInputDatePicker
-              v-if="organizationProfile.isSchool || organizationProfile.isManagerProduct"
+              v-if="
+                organizationProfile.isSchool ||
+                organizationProfile.isManagerProduct
+              "
               v-model="parameters.financialDate"
               field="financialDate"
               label="start_date_of_financial_season"
@@ -58,7 +58,8 @@
 
             <UiInputCheckbox
               v-if="
-                organizationProfile.isSchool && organizationProfile.isAssociation
+                organizationProfile.isSchool &&
+                organizationProfile.isAssociation
               "
               v-model="parameters.studentsAreAdherents"
               field="studentsAreAdherents"

+ 3 - 6
pages/parameters/intranet.vue

@@ -2,13 +2,10 @@
   <LayoutContainer>
     <LayoutParametersSection>
       <UiLoadingPanel v-if="pending" />
-      <UiForm
-        v-else
-        v-model="parameters"
-      >
+      <UiForm v-else v-model="parameters">
         <v-row>
           <v-col cols="12">
-            <h4 class="mb-4">{{ $t('teachers')}}</h4>
+            <h4 class="mb-4">{{ $t('teachers') }}</h4>
 
             <UiInputCheckbox
               v-model="parameters.createCourse"
@@ -34,7 +31,7 @@
               label="allow_teachers_to_generate_attendance_reports"
             />
 
-            <h4 class="mt-3 mb-4">{{ $t('pupils-members')}}</h4>
+            <h4 class="mt-3 mb-4">{{ $t('pupils-members') }}</h4>
             <UiInputCheckbox
               v-model="parameters.administrationCc"
               field="administrationCc"

+ 1 - 5
pages/parameters/sms.vue

@@ -4,10 +4,7 @@
       <UiForm v-if="parameters" v-model="parameters">
         <v-row>
           <v-col cols="12">
-            <UiInputText
-              v-model="parameters.usernameSMS"
-              field="usernameSMS"
-            />
+            <UiInputText v-model="parameters.usernameSMS" field="usernameSMS" />
           </v-col>
           <v-col cols="12">
             <UiInputText
@@ -62,7 +59,6 @@ const rules = () => [
 </script>
 
 <style scoped lang="scss">
-
 /**
 Simule une apparence de saisie de type mot de passe
 Sans ça, les navigateurs proposent la saisie semi auto et la mémorisation du mot de passe

+ 3 - 1
pages/parameters/super_admin.vue

@@ -21,7 +21,9 @@
           <tbody>
             <tr>
               <td>{{ $t('username') }} :</td>
-              <td><b>{{ adminAccess.username }}</b></td>
+              <td>
+                <b>{{ adminAccess.username }}</b>
+              </td>
             </tr>
           </tbody>
         </v-table>

+ 17 - 16
pages/parameters/teaching.vue

@@ -4,10 +4,7 @@
       <h4>{{ $t('configuration') }}</h4>
 
       <UiLoadingPanel v-if="pending" />
-      <UiForm
-        v-else-if="parameters !== null"
-        v-model="parameters"
-      >
+      <UiForm v-else-if="parameters !== null" v-model="parameters">
         <UiInputCheckbox
           v-model="parameters.showEducationIsACollectivePractice"
           field="showEducationIsACollectivePractice"
@@ -20,10 +17,13 @@
       <LayoutParametersTable
         :items="tableItems"
         :title="$t('teaching_cycles')"
-        :columns-definitions="[{ property: 'originalLabel' }, { property: 'effectiveLabel' }]"
+        :columns-definitions="[
+          { property: 'originalLabel' },
+          { property: 'effectiveLabel' },
+        ]"
         identifier="value"
         :actions="[TABLE_ACTION.EDIT]"
-        @editClicked="goToCycleEditPage"
+        @edit-clicked="goToCycleEditPage"
       />
     </LayoutParametersSection>
   </LayoutContainer>
@@ -39,7 +39,7 @@ import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 import type { AnyJson } from '~/types/data'
 import { useEnumFetch } from '~/composables/data/useEnumFetch'
 import ApiResource from '~/models/ApiResource'
-import {TABLE_ACTION} from '~/types/enum/enums';
+import { TABLE_ACTION } from '~/types/enum/enums'
 
 definePageMeta({
   name: 'parameters_teaching_page',
@@ -91,13 +91,15 @@ const orderedCycles: ComputedRef<AnyJson> = computed(() => {
 })
 
 const tableItems = computed(() => {
-  return cycleEnum.value?.map((item) => {
-    return {
-      value: item.value,
-      originalLabel: item.label,
-      effectiveLabel: (orderedCycles.value[item.value] ?? item).label,
-    }
-  }) || []
+  return (
+    cycleEnum.value?.map((item) => {
+      return {
+        value: item.value,
+        originalLabel: item.label,
+        effectiveLabel: (orderedCycles.value[item.value] ?? item).label,
+      }
+    }) || []
+  )
 })
 
 const goToCycleEditPage = (item: object) => {
@@ -106,5 +108,4 @@ const goToCycleEditPage = (item: object) => {
 }
 </script>
 
-<style scoped lang="scss">
-</style>
+<style scoped lang="scss"></style>

+ 14 - 15
pages/parameters/website.vue

@@ -8,8 +8,8 @@
       <UiLoadingPanel v-if="pending" />
       <UiForm
         v-else-if="parameters !== null"
-        :model="Parameters"
         v-model="parameters"
+        :model="Parameters"
       >
         <div class="section-header">
           <div class="flex-grow-1 align-self-center">
@@ -22,13 +22,13 @@
           </div>
         </div>
 
-        <div
-          v-if="!organizationProfile.isCmf"
-          class="d-flex justify-left mt-6"
-        >
+        <div v-if="!organizationProfile.isCmf" class="d-flex justify-left mt-6">
           <LayoutParametersWebsiteActivationSwitch
             :model-value="!parameters.desactivateOpentalentSiteWeb"
-            @update:modelValue="parameters.desactivateOpentalentSiteWeb = !parameters.desactivateOpentalentSiteWeb"
+            @update:model-value="
+              parameters.desactivateOpentalentSiteWeb =
+                !parameters.desactivateOpentalentSiteWeb
+            "
           />
         </div>
 
@@ -66,17 +66,13 @@
               v-for="subdomain in subdomains!.items"
               :key="subdomain.id"
               :title="subdomain.subdomain"
-              :class="
-                'subdomainItem' + (subdomain.active ? ' active' : '')
-              "
+              :class="'subdomainItem' + (subdomain.active ? ' active' : '')"
               @click="goToEditPage(subdomain.id)"
             >
               <td>{{ subdomain.subdomain }}</td>
               <td>
                 <span v-if="subdomain.active">
-                  <v-icon class="text-success icon">
-                    fa-solid fa-check
-                  </v-icon>
+                  <v-icon class="text-success icon"> fa-solid fa-check </v-icon>
                   {{ $t('active') }}
                 </span>
               </td>
@@ -92,7 +88,11 @@
             class="my-5"
             @click="onAddSubdomainClick"
           >
-            {{ smAndUp ? $t('record_a_new_subdomain') : $t('record_a_new_subdomain_short') }}
+            {{
+              smAndUp
+                ? $t('record_a_new_subdomain')
+                : $t('record_a_new_subdomain_short')
+            }}
           </v-btn>
         </div>
       </div>
@@ -103,6 +103,7 @@
 <script setup lang="ts">
 import type { AsyncData } from '#app'
 import type { ComputedRef, Ref } from 'vue'
+import { useDisplay } from 'vuetify'
 import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 import Parameters from '~/models/Organization/Parameters'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'
@@ -110,7 +111,6 @@ import Subdomain from '~/models/Organization/Subdomain'
 import ApiResource from '~/models/ApiResource'
 import EqualFilter from '~/services/data/Filters/EqualFilter'
 import Query from '~/services/data/Query'
-import {useDisplay} from 'vuetify';
 
 definePageMeta({
   name: 'parameters_website_page',
@@ -156,7 +156,6 @@ const onAddSubdomainClick = () => {
 </script>
 
 <style scoped lang="scss">
-
 .section-header {
   margin: 10px 0;
   display: flex;

+ 35 - 36
pages/subscription.vue

@@ -24,23 +24,23 @@ Page 'Mon abonnement'
       </UiExpansionPanel>
 
       <UiExpansionPanel
+        v-if="dolibarrAccount && dolibarrAccount.contract"
         title="service_detail"
         icon="fas fa-info"
-        v-if="dolibarrAccount && dolibarrAccount.contract"
       >
         <v-container fluid class="container">
           <v-row>
             <v-col
-              cols="12"
-              lg="12"
               v-for="line in dolibarrAccount.contract.lines"
               :key="line.id"
+              cols="12"
+              lg="12"
             >
               <strong>{{ line.serviceLabel }}</strong> - {{ $t('until') }} :
               {{ $d(line.dateEnd) }}
             </v-col>
 
-            <v-col cols="12" lg="12" v-if="ability.can('manage', 'texto')">
+            <v-col v-if="ability.can('manage', 'texto')" cols="12" lg="12">
               <strong>{{ $t('remaining_sms_credit') }}</strong> -
               <span
                 v-if="
@@ -98,8 +98,8 @@ Page 'Mon abonnement'
                   </td>
                   <td>
                     <a
-                      @click="downloadDolibarrBill(bill.ref)"
                       class="clickable"
+                      @click="downloadDolibarrBill(bill.ref)"
                     >
                       {{ $t('download') }}
                     </a>
@@ -112,14 +112,14 @@ Page 'Mon abonnement'
       </UiExpansionPanel>
 
       <UiExpansionPanel
+        v-if="!organizationProfile.isManagerProduct"
         title="opentalent_offers"
         icon="fas fa-plus"
-        v-if="!organizationProfile.isManagerProduct"
       >
         <v-container fluid class="container">
           <v-row
-            class="offer_title"
             v-if="!md && mdAndUp && !organizationProfile.isSchool"
+            class="offer_title"
           >
             <v-col
               cols="12"
@@ -146,18 +146,18 @@ Page 'Mon abonnement'
 
           <v-row class="card-container">
             <v-col
-              lg="4"
-              sm="12"
-              md="6"
               v-if="
                 organizationProfile.isArtistProduct ||
                 organizationProfile.isTrialActive
               "
+              lg="4"
+              sm="12"
+              md="6"
             >
               <LayoutPagesSubscriptionCard
                 class="artistCard"
                 title="Logiciel Artist Standard"
-                :extraHeader="
+                :extra-header="
                   organizationProfile.isArtistProduct
                     ? 'Votre version actuelle'
                     : undefined
@@ -181,11 +181,11 @@ Page 'Mon abonnement'
                 <template #card.action>
                   <v-row>
                     <v-col
-                      cols="12"
                       v-if="
                         !organizationProfile.isArtistProduct &&
                         !organizationProfile.isTrialActive
                       "
+                      cols="12"
                     >
                       <v-btn
                         class="theme-artist btn"
@@ -214,11 +214,11 @@ Page 'Mon abonnement'
               </LayoutPagesSubscriptionCard>
             </v-col>
 
-            <v-col lg="4" sm="12" md="6" v-if="organizationProfile.isArtist">
+            <v-col v-if="organizationProfile.isArtist" lg="4" sm="12" md="6">
               <LayoutPagesSubscriptionCard
                 class="artistCard"
                 title="Logiciel Artist Premium*"
-                :extraHeader="
+                :extra-header="
                   organizationProfile.isArtistPremiumProduct
                     ? organizationProfile.isTrialActive
                       ? `Version en cours d'essai J-${organizationProfile.trialCountDown}`
@@ -230,11 +230,11 @@ Page 'Mon abonnement'
               >
                 <template #card.subTitle>
                   <div
-                    class="priceBlock"
                     v-if="
                       !organizationProfile.isArtistPremiumProduct ||
                       organizationProfile.isTrialActive
                     "
+                    class="priceBlock"
                   >
                     <span class="price">{{
                       organizationProfile.isCmf
@@ -247,12 +247,12 @@ Page 'Mon abonnement'
                 <template #card.action>
                   <v-row>
                     <v-col
-                      cols="12"
                       v-if="
                         !organizationProfile.isArtistPremiumProduct &&
                         (accessProfileStore.isAdmin ||
                           accessProfileStore.isCaMember)
                       "
+                      cols="12"
                     >
                       <v-btn class="btn trialBtn" @click="startTrial">
                         {{ $t('try_premium_version') }}
@@ -260,13 +260,13 @@ Page 'Mon abonnement'
                       </v-btn>
                     </v-col>
                     <v-col
-                      cols="12"
                       v-if="
                         (!organizationProfile.isArtistPremiumProduct ||
                           organizationProfile.isTrialActive) &&
                         (accessProfileStore.isAdmin ||
                           accessProfileStore.isCaMember)
                       "
+                      cols="12"
                     >
                       <v-btn class="theme-artist btn" @click="subscription">
                         {{ $t('subscribe_to_the_offer') }}
@@ -275,12 +275,12 @@ Page 'Mon abonnement'
                     </v-col>
 
                     <v-col
-                      cols="12"
                       v-if="
                         organizationProfile.isTrialActive &&
                         (accessProfileStore.isAdmin ||
                           accessProfileStore.isCaMember)
                       "
+                      cols="12"
                     >
                       <v-btn class="stop_btn" @click="showStopTrialDialog">
                         {{ $t('stop_trial') }}
@@ -298,13 +298,12 @@ Page 'Mon abonnement'
                           "
                         >
                           <br />
-                            **Tarif
-                            <span v-if="organizationProfile.isCmf"
+                          **Tarif
+                          <span v-if="organizationProfile.isCmf"
                             >adhérent CMF</span
-                            ><span v-else>public</span> 2025. Abonnement payable
-                            annuellement.
+                          ><span v-else>public</span> 2025. Abonnement payable
+                          annuellement.
                         </span>
-
                       </span>
                     </v-col>
                   </v-row>
@@ -329,8 +328,8 @@ Page 'Mon abonnement'
                       ? 'Logiciel School Premium'
                       : 'Logiciel School Standard'
                 "
-                :subTitle="!organizationProfile.isSchool ? 'Sur devis' : ''"
-                :extraHeader="
+                :sub-title="!organizationProfile.isSchool ? 'Sur devis' : ''"
+                :extra-header="
                   organizationProfile.isSchool
                     ? 'Votre version actuelle'
                     : undefined
@@ -425,13 +424,13 @@ Page 'Mon abonnement'
 
   <LayoutDialogTrialAlreadyDid
     :show="showDialogTrialAllReadyDid"
-    @closeDialog="showDialogTrialAllReadyDid = false"
+    @close-dialog="showDialogTrialAllReadyDid = false"
   />
 
   <LayoutDialogTrialStopConfirmation
     :show="showDialogTrialStopConfirmation"
-    @closeDialog="showDialogTrialStopConfirmation = false"
-    @stopTrial="stopTrial"
+    @close-dialog="showDialogTrialStopConfirmation = false"
+    @stop-trial="stopTrial"
   />
 </template>
 
@@ -449,12 +448,12 @@ import { useDownloadFromRoute } from '~/composables/utils/useDownloadFromRoute'
 import { useApiLegacyRequestService } from '~/composables/data/useApiLegacyRequestService'
 import { usePageStore } from '~/stores/page'
 
-//meta
+// meta
 definePageMeta({
   name: 'subscription_page',
 })
 
-//Get composables
+// Get composables
 const ability = useAbility()
 const runtimeConfig = useRuntimeConfig()
 const { mdAndUp, md } = useDisplay()
@@ -462,7 +461,7 @@ const { fetch } = useEntityFetch()
 const i18n = useI18n()
 const { apiRequestService } = useApiLegacyRequestService()
 
-//Init ref
+// Init ref
 const showDialogTrialAllReadyDid: Ref<boolean> = ref(false)
 const showDialogTrialStopConfirmation: Ref<boolean> = ref(false)
 const openedPanels: Ref<Array<string>> = initPanel()
@@ -560,16 +559,16 @@ function getMobytInformations(): {
   mobytStatus: Ref<MobytUserStatus | null>
   mobytPending: Ref<boolean>
 } {
-  let mobytStatus: Ref<MobytUserStatus | null> = ref(null)
-  let mobytPending: Ref<boolean> = ref(false)
+  const mobytStatus: Ref<MobytUserStatus | null> = ref(null)
+  const mobytPending: Ref<boolean> = ref(false)
 
   if (ability.can('manage', 'texto')) {
     const { data, pending } = fetch(
       MobytUserStatus,
       organizationProfile!.id!,
     ) as AsyncData<MobytUserStatus | null, Error | null>
-    mobytStatus = data
-    mobytPending = pending
+    mobytStatus.value = data
+    mobytPending.value = pending
   }
 
   return { mobytStatus, mobytPending }
@@ -685,7 +684,7 @@ const downloadDolibarrBill = (ref: string): void => {
   border: 1px solid rgb(var(--v-theme-artist));
 }
 
-.btn{
+.btn {
   font-size: 12px;
 }
 

+ 5 - 2
plugins/matomo.client.ts

@@ -10,13 +10,16 @@ export default defineNuxtPlugin((nuxtApp) => {
   nuxtApp.vueApp.use(VueMatomo, {
     router,
     host: 'https://stats.2iopenservice.com/',
-    siteId: process.env.NODE_ENV === 'production' ? OPENTALENT_PROD_ID : OPENTALENT_TEST_ID,
+    siteId:
+      process.env.NODE_ENV === 'production'
+        ? OPENTALENT_PROD_ID
+        : OPENTALENT_TEST_ID,
     enableLinkTracking: true,
     requireConsent: false, // Mettre à true si vous avez besoin du consentement RGPD
     trackInitialView: true,
     disableCookies: false, // Mettre à true pour respecter certaines règles RGPD
     requireCookieConsent: false, // Mettre à true pour demander le consentement pour les cookies
     debug: process.env.NODE_ENV !== 'production',
-    trackSiteSearch: true
+    trackSiteSearch: true,
   })
 })

+ 6 - 2
services/data/apiRequestService.ts

@@ -120,10 +120,14 @@ class ApiRequestService {
 
     config.headers = headers ? { ...headers } : {}
 
-    config.headers['Accept'] = 'application/ld+json'
+    config.headers.Accept = 'application/ld+json'
     config.headers['Content-Type'] = 'application/ld+json'
 
-    if (method === HTTP_METHOD.POST || method === HTTP_METHOD.PUT || method === HTTP_METHOD.PATCH) {
+    if (
+      method === HTTP_METHOD.POST ||
+      method === HTTP_METHOD.PUT ||
+      method === HTTP_METHOD.PATCH
+    ) {
       config.body = body
     }
 

+ 4 - 1
services/data/enumManager.ts

@@ -23,7 +23,10 @@ class EnumManager {
     const enum_: Enum = []
     for (const key in data.items) {
       if (Object.prototype.hasOwnProperty.call(data.items, key)) {
-        enum_.push({ value: data.items[key], label: this.i18n.t(data.items[key]) })
+        enum_.push({
+          value: data.items[key],
+          label: this.i18n.t(data.items[key]),
+        })
       }
     }
 

+ 5 - 5
services/data/imageManager.ts

@@ -49,16 +49,16 @@ class ImageManager {
     // Une image doit toujours avoir le time en options pour éviter les problèmes de cache
     const query = [this.getCacheKey()]
 
-    const blobPart = await this.apiRequestService.get(imageUrl, query);
+    const blobPart = await this.apiRequestService.get(imageUrl, query)
     if (!blobPart) {
-      console.error('Error: image ' + id + ' not found');
-      return defaultUrl;
+      console.error('Error: image ' + id + ' not found')
+      return defaultUrl
     }
 
     console.log(blobPart, blobPart instanceof Blob, blobPart.size)
     if (!(blobPart instanceof Blob) || blobPart.size === 0) {
-      console.error('Error: image ' + id + ' is invalid');
-      return defaultUrl;
+      console.error('Error: image ' + id + ' is invalid')
+      return defaultUrl
     }
 
     return await this.toBase64(blobPart)

+ 2 - 2
services/data/normalizer/hydraNormalizer.ts

@@ -58,7 +58,7 @@ class HydraNormalizer {
     model?: typeof ApiResource,
   ): AnyJson {
     if (hydraData['@type'] === 'Collection') {
-      const members = hydraData['member']
+      const members = hydraData.member
       return members.map((item: AnyJson) =>
         HydraNormalizer.denormalizeItem(item, model),
       )
@@ -171,7 +171,7 @@ class HydraNormalizer {
   }
 
   protected static denormalizeEntity(model: typeof ApiResource, item: AnyJson) {
-    item['id'] = this.getItemIdValue(model, item)
+    item.id = this.getItemIdValue(model, item)
 
     // eslint-disable-next-line new-cap
     const instance = new model(item)

+ 3 - 3
services/layout/menuBuilder/basicomptaMenuBuilder.ts

@@ -12,9 +12,9 @@ export default class BasicomptaMenuBuilder extends AbstractMenuBuilder {
     // cf droit : https://ressources-opentalent.atlassian.net/wiki/spaces/SPEC/pages/32637034/Acc+s+basi+compta+pour+les+structures+de+la+CMF#Acces-a-Basicompta-pour-les-administrateurs
     if (
       (this.accessProfile.isAdminAccess ||
-      this.accessProfile.isAdministratifManager ||
-      this.accessProfile.isFinancialManager)
-      && this.ability.can('display', 'basicompta_page')
+        this.accessProfile.isAdministratifManager ||
+        this.accessProfile.isFinancialManager) &&
+      this.ability.can('display', 'basicompta_page')
     ) {
       return this.createItem(
         'basicompta_admin',

+ 1 - 2
services/rights/abilityBuilder.ts

@@ -1,11 +1,10 @@
-// eslint-disable-next-line import/default
 import * as yaml from 'yaml-import'
 import * as _ from 'lodash-es'
+import type { MongoAbility } from '@casl/ability/dist/types/Ability'
 import RoleUtils from '~/services/rights/roleUtils'
 import type { AbilitiesType, AccessProfile } from '~/types/interfaces'
 import { ABILITIES } from '~/types/enum/enums'
 import type OrganizationProfile from '~/models/Organization/OrganizationProfile'
-import type { MongoAbility } from '@casl/ability/dist/types/Ability'
 
 interface ConditionParameters {
   action: string

+ 1 - 2
services/utils/dateUtils.ts

@@ -1,6 +1,5 @@
-// eslint-disable-next-line import/no-duplicates
 import { format } from 'date-fns'
-// eslint-disable-next-line import/no-duplicates
+
 import { enUS, fr } from 'date-fns/locale'
 import ArrayUtils from '~/services/utils/arrayUtils'
 

+ 19 - 19
tests/units/services/data/apiRequestService.test.ts

@@ -202,10 +202,10 @@ describe('request', () => {
     // @ts-ignore
     expect(fetcher).toHaveBeenCalledWith('https://myapi.com/api/item', {
       method: 'GET',
-           "headers": {
-             "Accept": "application/ld+json",
-             "Content-Type": "application/ld+json",
-           },
+      headers: {
+        Accept: 'application/ld+json',
+        'Content-Type': 'application/ld+json',
+      },
     })
   })
 
@@ -222,9 +222,9 @@ describe('request', () => {
     expect(fetcher).toHaveBeenCalledWith('https://myapi.com/api/item', {
       method: 'POST',
       body: 'a_body',
-      "headers": {
-        "Accept": "application/ld+json",
-        "Content-Type": "application/ld+json",
+      headers: {
+        Accept: 'application/ld+json',
+        'Content-Type': 'application/ld+json',
       },
     })
   })
@@ -242,9 +242,9 @@ describe('request', () => {
     expect(fetcher).toHaveBeenCalledWith('https://myapi.com/api/item', {
       method: 'PUT',
       body: 'a_body',
-      "headers": {
-        "Accept": "application/ld+json",
-        "Content-Type": "application/ld+json",
+      headers: {
+        Accept: 'application/ld+json',
+        'Content-Type': 'application/ld+json',
       },
     })
   })
@@ -262,9 +262,9 @@ describe('request', () => {
     expect(fetcher).toHaveBeenCalledWith('https://myapi.com/api/item', {
       method: 'PATCH',
       body: 'a_body',
-      "headers": {
-        "Accept": "application/ld+json",
-        "Content-Type": "application/merge-patch+json",
+      headers: {
+        Accept: 'application/ld+json',
+        'Content-Type': 'application/merge-patch+json',
       },
     })
   })
@@ -281,9 +281,9 @@ describe('request', () => {
     // @ts-ignore
     expect(fetcher).toHaveBeenCalledWith('https://myapi.com/api/item', {
       method: 'GET',
-      "headers": {
-        "Accept": "application/ld+json",
-        "Content-Type": "application/ld+json",
+      headers: {
+        Accept: 'application/ld+json',
+        'Content-Type': 'application/ld+json',
       },
     })
   })
@@ -303,9 +303,9 @@ describe('request', () => {
       method: 'PUT',
       body: 'a_body',
       query: { a: 1 },
-      "headers": {
-        "Accept": "application/ld+json",
-        "Content-Type": "application/ld+json",
+      headers: {
+        Accept: 'application/ld+json',
+        'Content-Type': 'application/ld+json',
       },
     })
   })

+ 7 - 9
tests/units/services/data/entityManager.test.ts

@@ -369,8 +369,8 @@ describe('fetchCollection', () => {
   test('simple call', async () => {
     const collection = {
       '@type': 'Collection',
-      'totalItems': 3,
-      'member': [{ id: 1 }, { id: 2 }, { id: 3 }],
+      totalItems: 3,
+      member: [{ id: 1 }, { id: 2 }, { id: 3 }],
     }
 
     // @ts-ignore
@@ -438,8 +438,8 @@ describe('fetchCollection', () => {
   test('with a parent', async () => {
     const collection = {
       '@type': 'Collection',
-      'totalItems': 3,
-      'member': [{ id: 1 }, { id: 2 }, { id: 3 }],
+      totalItems: 3,
+      member: [{ id: 1 }, { id: 2 }, { id: 3 }],
     }
 
     // @ts-ignore
@@ -471,8 +471,8 @@ describe('fetchCollection', () => {
   test('with a query', async () => {
     const collection = {
       '@type': 'Collection',
-      'totalItems': 3,
-      'member': [{ id: 1 }, { id: 2 }, { id: 3 }],
+      totalItems: 3,
+      member: [{ id: 1 }, { id: 2 }, { id: 3 }],
     }
 
     const query = vi.fn()
@@ -770,9 +770,7 @@ describe('reset', () => {
       (model: typeof ApiResource, id: string | number) => null,
     )
     // @ts-ignore
-    entityManager.getModel = vi.fn(
-      (instance: ApiResource) => DummyApiModel,
-    )
+    entityManager.getModel = vi.fn((instance: ApiResource) => DummyApiModel)
 
     expect(() => entityManager.reset(entity)).toThrowError(
       'no initial state recorded for this object - abort [dummyModel/1]',

+ 1 - 4
tests/units/services/data/imageManager.test.ts

@@ -25,13 +25,10 @@ afterEach(() => {
 
 describe('get', () => {
   test('simple call', async () => {
-
     const blobPart = new Blob(['some_data'])
 
     // @ts-ignore
-    apiRequestService.get = vi.fn(
-      (url: string, query: object) => blobPart
-    )
+    apiRequestService.get = vi.fn((url: string, query: object) => blobPart)
 
     // @ts-ignore
     imageManager.getCacheKey = vi.fn(() => '123456')

+ 1 - 1
tests/units/services/data/normalizer/hydraNormalizer.test.ts

@@ -127,7 +127,7 @@ describe('getData', () => {
       '@context': '/api/contexts/Foo',
       '@id': '/api/foo',
       '@type': 'Collection',
-      'member': ['foo'],
+      member: ['foo'],
     }
 
     // @ts-ignore