From a2868015e906b766e8a6f2d5d5b8d67bb6e07b8e Mon Sep 17 00:00:00 2001
From: Mathieu Massaviol <mathieu.massaviol@univ-amu.fr>
Date: Thu, 7 Nov 2024 16:55:56 +0100
Subject: [PATCH] Add parentCatalogue(s) and version to search results #29

---
 .../OcSearchResultCard/OcSearchResultCard.vue | 71 +++++++++++++++++--
 src/declarations.ts                           |  2 +-
 src/locales/en.ts                             |  6 +-
 src/locales/fr.ts                             |  6 +-
 src/sparql/search.ts                          | 17 +++++
 5 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/src/components/Search/OcSearchResultCard/OcSearchResultCard.vue b/src/components/Search/OcSearchResultCard/OcSearchResultCard.vue
index 12fa32f..eecfa29 100644
--- a/src/components/Search/OcSearchResultCard/OcSearchResultCard.vue
+++ b/src/components/Search/OcSearchResultCard/OcSearchResultCard.vue
@@ -2,7 +2,7 @@
   <div
     class="rounded-md shadow-md border bg-gray-100"
   >
-  <div class="p-4">
+  <div class="px-4 pt-4">
     <div id="title" class="font-semibold text-2xl mb-2">
       <i :class="iconsDict[dcatType] ?? ''" :title="t('resourceType.'+dcatType)" class="fa-lg fa-fw"></i>
       <OcVisibilityIcon
@@ -27,12 +27,21 @@
     </div>
     <div id="subtitle" class="text-sm text-gray-600">
       <span>{{ t('search.searchResult.id') + ': ' + props.searchResult.identifier }}</span>
-      <span v-if="props.searchResult.version">/ {{ t('search.searchResult.version') + ' ' + props.searchResult.version }}</span>
+      <span v-if="props.searchResult.version"> | {{ t('search.searchResult.version') + ': ' + props.searchResult.version }}</span>
     </div>
     <div v-if="creators" id="creators" class="mt-1 mb-1">{{ creators }}</div>
     <div v-if="description" id="description">
       <p class="font-medium">{{ t('search.searchResult.description') }}</p>
-      <p class="text-justify text-sm">{{ description }}</p>
+      <ScrollPanel 
+        style="width: 100%; max-height: 150px;"
+        :dt="{
+          bar: {
+            background: `black`
+          }
+        }"
+      >
+        <p class="text-justify text-sm">{{ description }}</p>
+      </ScrollPanel>
     </div>
   </div>
   <div id="footer" class="pl-4 pr-4 pt-2 pb-2 bg-gray-200 rounded-b-md text-sm flex flex-row gap-2 justify-between">
@@ -40,7 +49,49 @@
       {{ datasets + ' ' + t('search.searchResult.datasets') + ' ' + t('and') + ' ' + catalogues + ' ' + t('search.searchResult.catalogues') }}
     </span>
     <span v-if="dcatType===ResourceType.DATASET">{{ distributions + ' ' +  t('search.searchResult.distributions')}}</span>
-    <span v-if="parentCatalogueTitle">{{ t('search.searchResult.parentCatalogue') + ': ' + parentCatalogueTitle }}</span>
+    <span v-if="props.searchResult.parentCatalog && !Array.isArray(props.searchResult.parentCatalog)">
+      {{ t('search.searchResult.parentCatalog') + ': ' }}
+      <OcLink
+        class="ml-1"
+        :to="{
+          name: 'community.resource',
+          params: {
+            identifier: props.searchResult.parentCatalog.identifier,
+            community: props.community.name,
+            resource: 'catalog'
+          }
+        }"
+      >
+        {{ translateValue(props.searchResult.parentCatalog.title) }}
+      </OcLink>
+    </span>
+    <span v-if="Array.isArray(props.searchResult.parentCatalog)">
+      <Popover ref="parentCatalogPop">
+        <div v-for="parentCatalog in props.searchResult.parentCatalog" v-bind:key="parentCatalog.identifier">
+          <OcLink
+            class="ml-1"
+            :to="{
+              name: 'community.resource',
+              params: {
+                identifier: parentCatalog.identifier,
+                community: props.community.name,
+                resource: 'catalog'
+              }
+            }"
+          >
+            {{ translateValue(parentCatalog.title) }}
+          </OcLink>
+        </div>
+      </Popover>
+      <Button
+        v-if="parentCatalogPop"
+        @click="parentCatalogPop.toggle"
+        severity="secondary"
+        class="h-6"
+      >
+        {{ t('search.searchResult.parentCatalogs') }}
+      </Button>
+    </span>
   </div>
   </div>
 </template>
@@ -49,11 +100,14 @@ import { useTranslateValue } from '@/composables/useTranslateValue'
 import type { OcCommunity, OcOrganization, OcPerson, OcSearchResult } from '@/declarations';
 import { iconsDict } from '@/helpers/icons';
 import { getResourceTypeFromAtType, ResourceType } from '@/helpers/resourceType';
-import { computed, type PropType } from 'vue'
+import { computed, ref, type PropType } from 'vue'
 import { useI18n } from 'vue-i18n';
 import OcLink from '@/components/OcLink.vue';
 import { getResourceVisibility } from '@/helpers/resourceVisibility';
 import OcVisibilityIcon from '@/components/OcVisibilityIcon/OcVisibilityIcon.vue';
+import ScrollPanel from 'primevue/scrollpanel';
+import Popover from 'primevue/popover';
+import Button from 'primevue/button';
 
 const { t } = useI18n()
 const { translateValue } = useTranslateValue()
@@ -100,11 +154,16 @@ const creatorName = (creator: OcPerson | OcOrganization) => {
 }
 
 const description = computed(() => translateValue(props.searchResult.description))
-const parentCatalogueTitle = computed(() => translateValue(props.searchResult.parentCatalog?.title))
 
 const catalogues = props.searchResult.catalog?.length ?? 0
 const datasets = props.searchResult.dataset?.length ?? 0
 const distributions = props.searchResult.distribution?.length ?? 0
+
+const parentCatalogPop = ref()
 </script>
+
 <style scoped>
+:deep(.p-scrollpanel-content-container){
+  z-index: 0;
+}
 </style>
\ No newline at end of file
diff --git a/src/declarations.ts b/src/declarations.ts
index 93cd00b..499be1e 100644
--- a/src/declarations.ts
+++ b/src/declarations.ts
@@ -141,7 +141,7 @@ export type OcSearchResult = OcResource & {
   catalog?: string[]
   dataset?: string[]
   distribution?: string[]
-  parentCatalog?: OcCatalog
+  parentCatalog?: OcCatalog | OcCatalog[]
 }
 
 /** A representation of a search query */
diff --git a/src/locales/en.ts b/src/locales/en.ts
index 27f1f3a..6d7a47e 100644
--- a/src/locales/en.ts
+++ b/src/locales/en.ts
@@ -353,8 +353,10 @@ Greetings,
       description: "Description",
       datasets: "Datasets",
       distributions: "Distributions",
-      parentCatalogue: "Parent catalogue",
-      id: "Id"
+      parentCatalog: "Parent catalogue",
+      parentCatalogs: "Parent catalogues",
+      id: "Id",
+      version: "Version"
     }
   },
   resourceType: {
diff --git a/src/locales/fr.ts b/src/locales/fr.ts
index 7868483..f797786 100644
--- a/src/locales/fr.ts
+++ b/src/locales/fr.ts
@@ -369,8 +369,10 @@ Cordialement,
       catalogues: "Sous-catalogues",
       datasets: "Jeux de données",
       distributions: "Distributions",
-      parentCatalogue: "Catalogue parent",
-      id: "Id"
+      parentCatalog: "Catalogue parent",
+      parentCatalogs: "Catalogues parent",
+      id: "Id",
+      version: "Version"
     }
   },
   resourceType: {
diff --git a/src/sparql/search.ts b/src/sparql/search.ts
index fea4c5b..8d7a0df 100644
--- a/src/sparql/search.ts
+++ b/src/sparql/search.ts
@@ -84,6 +84,12 @@ export const getSearchResults = async (resourceUriList: string[], auth?: Credent
     },
     creator: {
       '@id': 'http://purl.org/dc/terms/creator'
+    },
+    parentCatalog: {
+      '@id': 'http://purl.org/dc/terms/isPartOf'
+    },
+    version: {
+      '@id': 'http://www.w3.org/ns/dcat#version'
     }
   }
 
@@ -110,6 +116,10 @@ export const getSearchResults = async (resourceUriList: string[], auth?: Credent
       creator: {
         '@id': 'http://purl.org/dc/terms/creator',
         '@embed': '@always',
+      },
+      parentCatalog: {
+        '@id': 'http://purl.org/dc/terms/isPartOf',
+        '@embed': '@always'
       }
     }
   }
@@ -124,6 +134,8 @@ export const getSearchResults = async (resourceUriList: string[], auth?: Credent
         ?s dct:identifier ?identifier.
         ?s dct:creator ?creator.
         ?creator ?p2 ?o2.
+        ?s dct:isPartOf ?parentCatalog.
+        ?parentCatalog ?pparentCatalog ?oparentCatalog.
       }
       WHERE {
         VALUES ?s { ${formattedUris} }
@@ -142,6 +154,11 @@ export const getSearchResults = async (resourceUriList: string[], auth?: Credent
           VALUES ?p2 { foaf:name foaf:givenName foaf:familyName foaf:firstName }
           ?creator ?p2 ?o2.
         }
+        OPTIONAL {
+          ?parentCatalog dcat:dataset|dcat:catalog ?s.
+          VALUES ?pparentCatalog { dct:identifier dct:title }
+          ?parentCatalog ?pparentCatalog ?oparentCatalog.
+        }
         GRAPH ?g {
           ?s dct:identifier ?identifier.
         }
-- 
GitLab