Просмотр исходного кода

add useRefreshProfile composable and remove em.refreshProfile

Olivier Massot 2 лет назад
Родитель
Сommit
639b4807a6

+ 3 - 1
components/Layout/AlertBar/SwitchYear.vue

@@ -25,12 +25,14 @@ Barre d'alerte qui s'affiche lorsque l'utilisateur n'est pas sur l'année couran
   import Access from "~/models/Access/Access";
   import {usePageStore} from "~/stores/page";
   import {useEntityManager} from "~/composables/data/useEntityManager";
+  import {useRefreshProfile} from "~/composables/data/useRefreshProfile";
 
   const { em } = useEntityManager()
   const accessProfile = useAccessProfileStore()
   const organizationProfile = useOrganizationProfileStore()
   const { setDirty } = useFormStore()
   const pageStore = usePageStore()
+  const { refreshProfile } = useRefreshProfile()
 
   const show: ComputedRef<boolean> = computed(() => {
     return (
@@ -58,7 +60,7 @@ Barre d'alerte qui s'affiche lorsque l'utilisateur n'est pas sur l'année couran
     await em.patch(Access, accessProfile.currentAccessId, defaultValues)
     if (process.server) {
         // Force profile refresh server side to avoid a bug where server and client stores diverge on profile refresh
-        await em.refreshProfile()
+      await refreshProfile()
     }
     window.location.reload()
   }

+ 0 - 2
components/Layout/Header/Notification.vue

@@ -184,8 +184,6 @@ const update = async () => {
  * @param notification
  */
 const getMessage = (notification: Notification) => {
-  console.log(notification)
-  console.log(notification.message)
   switch (notification.type){
     case NOTIFICATION_TYPE.FILE :
       return `${i18n.t('your_file')} ${notification.message?.fileName} ${i18n.t('is_ready_to_be_downloaded')}`

+ 3 - 1
components/Layout/Parameters/Website.vue

@@ -10,7 +10,9 @@
         <v-col cols="6">
           <div class="mb-6">
             <div>{{ $t('your_opentalent_website_address_is')}} : </div>
-            <div class="ma-2 text-primary"><strong>{{ organizationProfile.website }}</strong></div>
+            <div class="ma-2 text-primary">
+              <strong>{{ organizationProfile.website }}</strong>
+            </div>
           </div>
 
           <div class="mb-6">

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

@@ -34,6 +34,7 @@ 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";
 
 const { em } = useEntityManager()
 const accessProfileStore = useAccessProfileStore()
@@ -41,6 +42,7 @@ const organizationProfileStore = useOrganizationProfileStore()
 const formStore = useFormStore()
 const pageStore = usePageStore()
 const { mdAndUp } = useDisplay()
+const { refreshProfile } = useRefreshProfile()
 
 const currentActivityYear: ComputedRef<number | undefined> = computed(() => accessProfileStore.activityYear ?? undefined)
 const yearPlusOne: boolean = !organizationProfileStore.isManagerProduct
@@ -65,7 +67,7 @@ const setActivityYear = async (event: string) => {
   await em.patch(Access, accessProfileStore.currentAccessId, { activityYear: activityYear })
   if (process.server) {
       // Force profile refresh server side to avoid a bug where server and client stores diverge on profile refresh
-      await em.refreshProfile()
+    await refreshProfile()
   }
 
   window.location.reload()

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

@@ -36,6 +36,7 @@ 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']
@@ -45,6 +46,7 @@ const accessProfileStore = useAccessProfileStore()
 const { em } = useEntityManager()
 const { mdAndUp } = useDisplay()
 const pageStore = usePageStore()
+const { refreshProfile } = useRefreshProfile()
 
 const toggle = ref(null)
 
@@ -71,7 +73,7 @@ const onUpdate = async (newValue: Array<string>) => {
   await em.patch(Access, accessProfileStore.id, {'historical': accessProfileStore.historical})
   if (process.server) {
       // Force profile refresh server side to avoid a bug where server and client stores diverge on profile refresh
-      await em.refreshProfile()
+    await refreshProfile()
   }
 
   window.location.reload()

+ 3 - 1
components/Layout/SubHeader/DataTimingRange.vue

@@ -22,11 +22,13 @@ import {useEntityManager} from "~/composables/data/useEntityManager";
 import Access from "~/models/Access/Access";
 import DateUtils from "~/services/utils/dateUtils";
 import {usePageStore} from "~/stores/page";
+import {useRefreshProfile} from "~/composables/data/useRefreshProfile";
 
 const { setDirty } = useFormStore()
 const accessProfileStore = useAccessProfileStore()
 const { em } = useEntityManager()
 const pageStore = usePageStore()
+const { refreshProfile } = useRefreshProfile()
 
 const start = accessProfileStore.historical.dateStart
 const end = accessProfileStore.historical.dateEnd
@@ -54,7 +56,7 @@ const updateDateTimeRange = async (dates: Array<Date>): Promise<any> => {
   await em.patch(Access, accessProfileStore.id, {'historical': accessProfileStore.historical})
   if (process.server) {
       // Force profile refresh server side to avoid a bug where server and client stores diverge on profile refresh
-      await em.refreshProfile()
+    await refreshProfile()
   }
 
   window.location.reload()

+ 3 - 1
components/Ui/Form.vue

@@ -92,6 +92,7 @@ import {watch} from "@vue/runtime-core";
 import {AnyJson} from "~/types/data";
 import * as _ from 'lodash-es'
 import {Bool} from "pinia-orm/dist/decorators";
+import {useRefreshProfile} from "~/composables/data/useRefreshProfile";
 
 const props = defineProps({
   /**
@@ -150,6 +151,7 @@ const props = defineProps({
 const i18n = useI18n()
 const router = useRouter()
 const { em } = useEntityManager()
+const { refreshProfile } = useRefreshProfile()
 
 // Le formulaire est-il valide
 const isValid: Ref<boolean> = ref(true)
@@ -201,7 +203,7 @@ const submit = async (next: string|null = null) => {
     const updatedEntity = await em.persist(props.model, props.entity)
 
     if (props.refreshProfile) {
-      await em.refreshProfile()
+      await refreshProfile()
     }
 
     usePageStore().addAlert(TYPE_ALERT.SUCCESS, ['saveSuccess'])

+ 1 - 1
composables/data/useAp2iRequestService.ts

@@ -1,4 +1,3 @@
-import {FetchContext, FetchOptions} from "ohmyfetch";
 import {TYPE_ALERT} from "~/types/enum/enums";
 import ApiRequestService from "~/services/data/apiRequestService";
 import {Ref} from "@vue/reactivity";
@@ -6,6 +5,7 @@ import {usePageStore} from "~/stores/page";
 import UnauthorizedError from "~/services/error/UnauthorizedError";
 import {useAccessProfileStore} from "~/stores/accessProfile";
 import {AssociativeArray} from "~/types/data";
+import {FetchContext, FetchOptions} from "ofetch";
 
 /**
  * Retourne une instance de ApiRequestService configurée pour interroger l'api Ap2i

+ 61 - 0
composables/data/useRefreshProfile.ts

@@ -0,0 +1,61 @@
+import {useEntityManager} from "~/composables/data/useEntityManager";
+import MyProfile from "~/models/Access/MyProfile";
+import {useAccessProfileStore} from "~/stores/accessProfile";
+import {useOrganizationProfileStore} from "~/stores/organizationProfile";
+
+export const useRefreshProfile = () => {
+
+    const accessProfileStore = useAccessProfileStore()
+    const organizationProfileStore = useOrganizationProfileStore()
+    const { em } = useEntityManager()
+
+    const fetchProfile = async (accessId: number | null = null): Promise<MyProfile> => {
+        if (accessId === null) {
+            accessId = accessProfileStore.currentAccessId
+        }
+
+        return await em.fetch(MyProfile, accessId, true) as MyProfile
+    }
+
+    /**
+     * Fetch the access profile and initiate the user profile and organization profile stores
+     *
+     * /!\ Server side only!
+     *
+     * @param accessId
+     * @param bearer
+     * @param switchId
+     */
+    const initiateProfile = async (accessId: number, bearer: string, switchId: number | null): Promise<void> => {
+        accessProfileStore.$patch({
+            bearer: bearer,
+            id: accessId,
+            switchId: switchId
+        })
+
+        const profile = await fetchProfile(accessId)
+
+        // Sans le flush, on observe un bug non-expliqué au rechargement de la page en mode dev : la fonction save
+        //  du repo de MyProfile ne fonctionne pas quand le plugin init.server.ts re-fetch le profil
+        em.flush(MyProfile)
+
+        accessProfileStore.initiateProfile(profile)
+        organizationProfileStore.initiateProfile(profile.organization)
+    }
+
+    /**
+     * Re-fetch the user profile and update the store
+     */
+    const refreshProfile = async (accessId: number | null = null) => {
+        const profile = await fetchProfile(accessId)
+
+        // Sans le flush, on observe un bug non-expliqué au rechargement de la page en mode dev : la fonction save
+        //  du repo de MyProfile ne fonctionne pas quand le plugin init.server.ts re-fetch le profil
+        em.flush(MyProfile)
+
+        accessProfileStore.setProfile(profile)
+        organizationProfileStore.setProfile(profile.organization)
+    }
+
+    return { initiateProfile, refreshProfile }
+}

+ 2 - 1
lang/fr.json

@@ -616,5 +616,6 @@
   "Not a valid subdomain": "Le sous-domaine est invalide",
   "This organization can not register new subdomains": "Nombre maximum de sous-domaines enregistrés atteint",
   "This subdomain is not available": "Ce sous-domaine n'est pas disponible",
-  "This subdomain is already registered": "Ce sous-domaine est déjà enregistré"
+  "This subdomain is already registered": "Ce sous-domaine est déjà enregistré",
+  "subdomain_activated": "Le sous-domaine a bien été activé"
 }

+ 0 - 1
pages/parameters/index.vue

@@ -92,7 +92,6 @@ Page Paramètres
   const currentTab: Ref<string | null> = ref(null)
 
   onMounted(() => {
-    console.log(route.query, route.query.tab, tabs.includes(route.query.tab as string))
     if (!route.query || !route.query.tab || !tabs.includes(route.query.tab as string)) {
       updateQuery(tabs[0])
     }

+ 14 - 4
pages/parameters/subdomains/[id].vue

@@ -2,8 +2,8 @@
 <template>
   <main>
     <LayoutContainer>
-      <UiLoadingPanel v-if="pending || activationPending" />
-      <div>
+      <UiLoadingPanel v-if="pending" />
+      <div v-else>
         <div>
           {{ $t('youRegisteredTheFollowingSubdomain')}} :
         </div>
@@ -45,6 +45,9 @@
   import {useEntityFetch} from "~/composables/data/useEntityFetch";
   import {useOrganizationProfileStore} from "~/stores/organizationProfile";
   import {useEntityManager} from "~/composables/data/useEntityManager";
+  import {usePageStore} from "~/stores/page";
+  import {TYPE_ALERT} from "~/types/enum/enums";
+  import {useRefreshProfile} from "~/composables/data/useRefreshProfile";
 
   const { em } = useEntityManager()
   const { fetch } = useEntityFetch()
@@ -53,6 +56,8 @@
   const router = useRouter()
   const route = useRoute()
 
+  const { refreshProfile } = useRefreshProfile()
+
   if (!route.params.id || isNaN(route.params.id as any)) {
     throw new Error('no id found')
   }
@@ -62,16 +67,21 @@
 
   const activationPending: Ref<boolean> = ref(false)
 
+  const pageStore = usePageStore()
+
   const activateAndQuit = async () => {
     activationPending.value = true
+    pageStore.loading = true
     await em.patch(Subdomain, id, { active: true} )
-    await em.refreshProfile()
+    await refreshProfile()
+    usePageStore().addAlert(TYPE_ALERT.SUCCESS, ['subdomain_activated'])
     quit()
   }
 
   const quit = () => {
-    router.push('/parameters#website')
+    router.push('/parameters?tab=website')
     activationPending.value = false
+    pageStore.loading = false
   }
 
 

+ 1 - 1
plugins/ability.ts

@@ -26,7 +26,7 @@ export default defineNuxtPlugin(() => {
                                                                 onError, // hook if the action throws or rejects
                                                             }: any) => {
         after((result: any)=>{
-            if (name === 'setProfile'){
+            if (name === 'initiateProfile'){
                 // On construit les habilités et on les enregistre dans le store
                 // noinspection UnnecessaryLocalVariableJS
                 const abilities = abilityUtils.buildAbilities();

+ 12 - 15
plugins/init.server.ts

@@ -1,14 +1,14 @@
-import {useAccessProfileStore} from "~/stores/accessProfile";
-import {useEntityManager} from "~/composables/data/useEntityManager";
 import UnauthorizedError from "~/services/error/UnauthorizedError";
 import {useRedirectToLogout} from "~/composables/utils/useRedirectToLogout";
+import {useRefreshProfile} from "~/composables/data/useRefreshProfile";
+import {CookieRef} from "#app";
 
 export default defineNuxtPlugin(async () => {
     const redirectToLogout = useRedirectToLogout()
 
-    const bearer = useCookie('BEARER')
-    let accessCookieId = useCookie('AccessId')
-    const switchId = useCookie('SwitchAccessId')
+    const bearer: CookieRef<string | null> = useCookie('BEARER') ?? null
+    let accessCookieId: CookieRef<string | null> = useCookie('AccessId') ?? null
+    const switchId: CookieRef<string | null> = useCookie('SwitchAccessId') ?? null
 
     if (accessCookieId.value === null || Number.isNaN(accessCookieId.value)) {
         redirectToLogout()
@@ -17,18 +17,15 @@ export default defineNuxtPlugin(async () => {
 
     const accessId: number = parseInt(accessCookieId.value)
 
-    const accessProfile = useAccessProfileStore()
-
-    accessProfile.$patch({
-        bearer: bearer.value,
-        id: accessId,
-        switchId: switchId.value !== null ? parseInt(switchId.value) : null
-    })
-
-    const {em} = useEntityManager()
+    const { initiateProfile } = useRefreshProfile()
 
     try {
-        await em.refreshProfile(accessId)
+        await initiateProfile(
+            accessId,
+            bearer.value ?? '',
+            switchId.value !== null ? parseInt(switchId.value) : null
+        )
+
     } catch (error) {
         if (error instanceof UnauthorizedError) {
             redirectToLogout()

+ 0 - 24
services/data/entityManager.ts

@@ -296,30 +296,6 @@ class EntityManager {
         return initialInstance
     }
 
-    /**
-     * @todo: à déplacer dans le store directement
-     * @Deprecated : a priori ce n'est pas le bon service pour mettre à jour le profil, on devrait voir ça
-     * depuis un service dédié, un composable, ou directement dans le store ==> oui !
-     *
-     * Re-fetch the user profile and update the store
-     */
-    public async refreshProfile(accessId: number | null = null) {
-        const accessProfileStore = useAccessProfileStore()
-
-        if (accessId === null) {
-            accessId = accessProfileStore.currentAccessId
-        }
-
-        // Sans le flush, on observe un bug non-expliqué au rechargement de la page en mode dev : la fonction save
-        //  du repo de MyProfile ne fonctionne pas quand le plugin init.server.ts re-fetch le profil
-        this.flush(MyProfile)
-
-        const profile = await this.fetch(MyProfile, accessId, true)
-
-        // On met à jour le store accessProfile
-        accessProfileStore.setProfile(profile)
-    }
-
     /**
      * Delete all records in the repository of the model
      *

+ 22 - 15
stores/accessProfile.ts

@@ -97,16 +97,15 @@ export const useAccessProfileStore = defineStore('accessProfile', () => {
     return roles.value && roles.value.includes(role)
   }
 
-  const setProfile = (profile: any) => {
-    const profileRoles: Array<string> = Array.from(Object.values(profile.roles))
+  /**
+   * /!\ Server-side only
+   *
+   * @param profile
+   * @param abilitiesValue
+   */
+  const initiateProfile = (profile: any): void => {
 
-    name.value = profile.name
-    givenName.value = profile.givenName
-    gender.value = profile.gender
-    avatarId.value = profile.avatarId
-    activityYear.value = profile.activityYear
-    historical.value = profile.historical
-    isAdminAccess.value = profile.isAdminAccess
+    const profileRoles: Array<string> = Array.from(Object.values(profile.roles))
 
     isAdmin.value = RoleUtils.isA('ADMIN', profileRoles)
     isAdministratifManager.value = RoleUtils.isA('ADMINISTRATIF_MANAGER', profileRoles)
@@ -117,9 +116,21 @@ export const useAccessProfileStore = defineStore('accessProfile', () => {
     isTeacher.value = RoleUtils.isA('TEACHER', profileRoles)
     isMember.value = RoleUtils.isA('MEMBER', profileRoles)
     isOther.value = RoleUtils.isA('OTHER', profileRoles)
+    roles.value = RoleUtils.filterFunctionRoles(profileRoles)
+
+    setProfile(profile)
+  }
+
+  const setProfile = (profile: any): void => {
+    name.value = profile.name
+    givenName.value = profile.givenName
+    gender.value = profile.gender
+    avatarId.value = profile.avatarId
+    activityYear.value = profile.activityYear
+    historical.value = profile.historical
+    isAdminAccess.value = profile.isAdminAccess
     isGuardian.value = profile.isGuardian
     isPayer.value = profile.isPayor
-    roles.value = RoleUtils.filterFunctionRoles(profileRoles)
 
     // Add the original Access (switch User case)
     if (profile.originalAccess !== null) {
@@ -142,11 +153,6 @@ export const useAccessProfileStore = defineStore('accessProfile', () => {
 
     // Set family-accesses
     setFamilyAccesses(Array.from(profile.familyAccesses))
-
-    // Set organization profile
-    // TODO: à voir si c'est bien d'appeler un autre store d'ici où s'il vaudrait mieux le faire dans la couche supérieure
-    const organizationProfile = useOrganizationProfileStore()
-    organizationProfile.setProfile(profile.organization)
   }
 
   const setHistorical = (past: boolean, present: boolean, future: boolean) => {
@@ -199,6 +205,7 @@ export const useAccessProfileStore = defineStore('accessProfile', () => {
     currentAccessId,
     setMultiAccesses,
     setFamilyAccesses,
+    initiateProfile,
     setProfile,
     setHistorical,
     setHistoricalRange

+ 12 - 1
stores/organizationProfile.ts

@@ -146,6 +146,16 @@ export const useOrganizationProfileStore = defineStore('organizationProfile', ()
     return modules.value && modules.value.includes(module)
   }
 
+  /**
+   * /!\ Server side only
+   * @param profile
+   */
+  const initiateProfile = (profile: any) => {
+    setProfile(profile)
+
+    // >>> Triggers a listener in plugins/ability
+  }
+
   // Actions
   const setProfile = (profile: any) => {
     id.value = profile.id
@@ -204,6 +214,7 @@ export const useOrganizationProfileStore = defineStore('organizationProfile', ()
     getWebsite,
     hasModule,
     setProfile,
-    refreshProfile
+    refreshProfile,
+    initiateProfile
   }
 })