Browse Source

finalize website parameters section

Olivier Massot 2 years ago
parent
commit
4b9195d081

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

@@ -59,7 +59,7 @@
           <UiInputAutocompleteAccesses
               v-model="parameters.publicationDirectors"
               field="publicationDirectors"
-              :multiple="true"
+              multiple
               chips
           />
 
@@ -84,8 +84,6 @@ import Parameters from "~/models/Organization/Parameters";
 import {useEntityFetch} from "~/composables/data/useEntityFetch";
 import {AsyncData} from "#app";
 import Subdomain from "~/models/Organization/Subdomain";
-import ApiResource from "~/models/ApiResource";
-import Access from "~/models/Access/Access";
 
 const i18n = useI18n()
 
@@ -104,8 +102,6 @@ const { data: subdomains, pending: subdomainsPending } = fetchCollection(Subdoma
 
 const canAddNewSubdomain: ComputedRef<boolean> = computed(() => subdomains.value && subdomains.value.items.length < 3)
 
-
-
 const goToEditPage = (id: number) => {
   navigateTo(`parameters/subdomains/${id}`)
 }
@@ -117,14 +113,6 @@ const onAddSubdomainClick = () => {
   navigateTo('/parameters/subdomains/new')
 
 }
-
-const publicationDirectorsMapping = (access: Access): { id: number | string, title: string } => {
-  return {
-    id: access.id,
-    title: access.person ? `${access.person.givenName} ${access.person.name}` : i18n.t('unknown')
-  }
-}
-
 </script>
 
 <style scoped lang="scss">

+ 12 - 3
components/Ui/Input/Autocomplete.vue

@@ -14,7 +14,6 @@ Liste déroulante avec autocompletion, à placer dans un composant `UiForm`
         :label="$t(fieldLabel)"
         item-text="itemTextDisplay"
         :item-value="itemValue"
-        :no-data-text="$t('autocomplete_research')"
         :no-filter="noFilter"
         auto-select-first
         :multiple="multiple"
@@ -26,6 +25,8 @@ Liste déroulante avec autocompletion, à placer dans un composant `UiForm`
         :error-messages="errorMessage || fieldViolations ? $t(fieldViolations) : ''"
         :rules="rules"
         :chips="chips"
+        :hide-no-data="hideNoData"
+        :no-data-text="isLoading ? $t('please_wait') : $t('no_result_matching_your_request')"
         @update:model-value="onUpdate"
         @update:search="emit('update:search', $event)"
     >
@@ -110,7 +111,7 @@ const props = defineProps({
    */
   itemTitle: {
     type: String,
-    required: true
+    default: 'title'
   },
   /**
    * Propriété de l'objet à utiliser comme clé (et correspondant au v-model)
@@ -151,6 +152,14 @@ const props = defineProps({
     required: false,
     default: null
   },
+  /**
+   * @see https://vuetifyjs.com/en/api/v-autocomplete/#props-hide-no-data
+   */
+  hideNoData: {
+    type: Boolean,
+    required: false,
+    default: false
+  },
   // TODO: c'est quoi?
   slotText: {
     type: Array,
@@ -205,7 +214,7 @@ const emit = defineEmits(['update:model-value', 'update:search'])
 
 const onUpdate = (event: string) => {
   updateViolationState(event)
-  emit('update:model-value', props.modelValue)
+  emit('update:model-value', event)
 }
 
 /**

+ 13 - 17
components/Ui/Input/Autocomplete/Accesses.vue

@@ -1,3 +1,9 @@
+<!--
+Champs autocomplete dédié à la recherche des access d'une structure
+
+@see https://vuetifyjs.com/en/components/autocompletes/#usage
+-->
+
 <template>
   <main>
     <UiInputAutocomplete
@@ -6,13 +12,12 @@
         :label="label"
         :items="items"
         :isLoading="pending"
-        item-title="title"
-        item-value="id"
         :multiple="multiple"
         :chips="chips"
+        no-filter
         prependIcon="fas fa-magnifying-glass"
         :return-object="false"
-        @update:model-value="onUpdateModelvalue"
+        @update:model-value="$emit('update:model-value', $event)"
         @update:search="onUpdateSearch"
     />
   </main>
@@ -30,7 +35,7 @@ const props = defineProps({
    * v-model
    */
   modelValue: {
-    type: [String, Number, Object, Array],
+    type: [Object, Array],
     required: false,
     default: null
   },
@@ -91,16 +96,16 @@ const { fetchCollection } = useEntityFetch()
 
 const i18n = useI18n()
 
-const nameFilter = ref(null)
+const nameFilter: Ref<string | null> = ref(null)
 
 const query: ComputedRef<AnyJson> = computed(() => {
-
   let q = props.filters.value ?? {}
   if (nameFilter.value !== null) {
     q['fullname'] = nameFilter.value
   }
+  q['groups[]'] = 'access_people_ref'
 
-  return { ...q, ...{ 'groups[]': 'access_people_ref' } }
+  return q
 })
 
 const { data: collection, pending, refresh } = await fetchCollection(Access, null, query)
@@ -122,19 +127,10 @@ const items: ComputedRef<Array<{ id: number | string, title: string }>> = comput
 
 const emit = defineEmits(['update:model-value'])
 
-const onUpdateModelvalue = (event: Array<number>) => {
-  console.log(event)
-  emit('update:model-value', event)
-}
-
 const onUpdateSearch = (event: string) => {
-  if (event.length <= 2) {
-    return
-  }
+  nameFilter.value = event
   refresh()
 }
-
-
 </script>
 
 <style scoped lang="scss">

+ 3 - 2
lang/fr.json

@@ -300,7 +300,7 @@
   "of": "de",
   "allResult": "Tous",
   "itemsPerPage": "Nombre de résultats par page",
-  "autocomplete_research": "Aucun résultat ne correspond à votre recherche",
+  "no_result_matching_your_request": "Aucun résultat ne correspond à votre recherche",
   "add": "Ajouter",
   "save": "Enregistrer",
   "save_and_back": "Enregistrer et retour",
@@ -617,5 +617,6 @@
   "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é",
-  "subdomain_activated_and_available_in_a_few_minutes": "Le sous-domaine a bien été activé, et sera accessible d'ici quelques minutes"
+  "subdomain_activated_and_available_in_a_few_minutes": "Le sous-domaine a bien été activé, et sera accessible d'ici quelques minutes",
+  "unknown": "Inconnu"
 }

+ 44 - 1
services/data/normalizer/hydraDenormalizer.ts

@@ -21,7 +21,50 @@ class HydraDenormalizer {
   }
 
   protected static getData(hydraData: AnyJson): AnyJson {
-    return hydraData['@type'] === 'hydra:Collection' ? hydraData['hydra:member'] : hydraData
+    if (hydraData['@type'] === 'hydra:Collection') {
+      let members = hydraData['hydra:member']
+      let results = []
+
+      for (let item of members) {
+        results.push(HydraDenormalizer.denormalizeItem(item))
+      }
+
+      return results
+    } else {
+      return HydraDenormalizer.denormalizeItem(hydraData)
+    }
+  }
+
+  /**
+   * Dénormalise un item d'une réponse hydra
+   *
+   * @param item
+   * @protected
+   */
+  protected static denormalizeItem(item: AnyJson): AnyJson {
+    for (let key in item) {
+      if (item.hasOwnProperty(key)) {
+        let value = item[key]
+
+        // If value is an array of URIs (ex: `/api/persons/1`), replace this array with an array of numeric ids (ex: `1`)
+        if (
+            Array.isArray(value) &&
+            value.length > 0 &&
+            typeof value[0] === 'string' &&
+            value[0].match(/\/api\/[\w\/]+\d+/)
+        ) {
+          let childrenIds: Array<number> = []
+
+          for (let child of value) {
+            childrenIds.push(UrlUtils.extractIdFromUri(child) as number)
+          }
+
+          item[key] = childrenIds
+        }
+      }
+    }
+
+    return item
   }
 
   /**