From 3a4fe1ad16872630da8f2c5f890a807fc2f0d324 Mon Sep 17 00:00:00 2001 From: Hofstetter Benjamin Date: Fri, 12 Sep 2025 17:01:34 +0200 Subject: [PATCH 01/14] new Dataset and Distribution class --- .../dataset-detail/OdsDatasetCatalogPanel.vue | 4 +- .../dataset-detail/OdsDatasetMetaInfo.vue | 18 +- .../dataset-detail/OdsDetailsTable.vue | 76 ++--- .../dataset-detail/OdsDistributionList.vue | 49 +-- .../OdsDistributionListItem.vue | 42 +-- .../dataset-detail/{ => model}/category.ts | 0 .../model/dcat-ap-ch-v2-dataset-adapter.ts | 302 ++++++++++++++++++ .../dcat-ap-ch-v2-distribution-adapter.ts | 169 ++++++++++ .../dataset-detail/model/table-entry.ts | 15 + opendata.swiss/ui/i18n/locales/de.json | 5 +- opendata.swiss/ui/i18n/locales/en.json | 5 +- opendata.swiss/ui/i18n/locales/fr.json | 5 +- opendata.swiss/ui/i18n/locales/it.json | 5 +- opendata.swiss/ui/package-lock.json | 8 +- opendata.swiss/ui/package.json | 4 +- .../distribution/[distributionId].vue | 23 +- .../ui/pages/datasets/[datasetId]/index.vue | 51 +-- .../ui/sparql/invstigations.sparqlbook | 6 + 18 files changed, 609 insertions(+), 178 deletions(-) rename opendata.swiss/ui/app/components/dataset-detail/{ => model}/category.ts (100%) create mode 100644 opendata.swiss/ui/app/components/dataset-detail/model/dcat-ap-ch-v2-dataset-adapter.ts create mode 100644 opendata.swiss/ui/app/components/dataset-detail/model/dcat-ap-ch-v2-distribution-adapter.ts create mode 100644 opendata.swiss/ui/app/components/dataset-detail/model/table-entry.ts diff --git a/opendata.swiss/ui/app/components/dataset-detail/OdsDatasetCatalogPanel.vue b/opendata.swiss/ui/app/components/dataset-detail/OdsDatasetCatalogPanel.vue index 50b49bc..b72acaa 100644 --- a/opendata.swiss/ui/app/components/dataset-detail/OdsDatasetCatalogPanel.vue +++ b/opendata.swiss/ui/app/components/dataset-detail/OdsDatasetCatalogPanel.vue @@ -98,7 +98,7 @@ diff --git a/opendata.swiss/ui/app/components/dataset-detail/category.ts b/opendata.swiss/ui/app/components/dataset-detail/model/category.ts similarity index 100% rename from opendata.swiss/ui/app/components/dataset-detail/category.ts rename to opendata.swiss/ui/app/components/dataset-detail/model/category.ts diff --git a/opendata.swiss/ui/app/components/dataset-detail/model/dcat-ap-ch-v2-dataset-adapter.ts b/opendata.swiss/ui/app/components/dataset-detail/model/dcat-ap-ch-v2-dataset-adapter.ts new file mode 100644 index 0000000..0c15b08 --- /dev/null +++ b/opendata.swiss/ui/app/components/dataset-detail/model/dcat-ap-ch-v2-dataset-adapter.ts @@ -0,0 +1,302 @@ +import type { LinkedDataFormats, PropertyTableEntryNode } from '@piveau/sdk-vue'; +import type { Dataset } from '../../../model/dataset' +import { DcatApChV2DistributionAdapter } from './dcat-ap-ch-v2-distribution-adapter' +import type { TableEntry } from './table-entry'; + +export class DcatApChV2DatasetAdapter { + #dataset: Dataset; + + constructor(d: Dataset) { + this.#dataset = d; + const foo = this.propertyTable; + console.log('propertyTable', foo); + } + + /** + * Get the id of the dataset + * + */ + get id() { + return this.#dataset.getId; + } + + /** + * Get the title of the dataset. The title is mandatory but if not available it returns the id. + * The language handling is done by piveau. + * + * from dcat-ap-ch: + * Property Title + * Requirement level Mandatory + * Cardinality 1..n + * URI dct:title + * Range rdfs:Literal + * Usage Note + * This property contains a name given to the Dataset. + * This property can be repeated for parallel language versions of the title (see 2.3 Multilingualism). + */ + get title(): string { + return this.#dataset?.getTitle ?? this.id; + } + + /** + * Get the description of the dataset. A description is mandatory but if not available it returns an empty string. + * + * The language handling is done by piveau. + * + * from dcat-ap-ch: + * Property description + * Requirement level Mandatory + * Cardinality 1..n + * URI dct:description + * Range rdfs:Literal + * Usage Note + * This property contains a free-text account of the Dataset. + * This property can be repeated for parallel language versions of the description (see 2.3 Multilingualism). On the user interface of data portals, the content of the element whose language corresponds to the display language selected by the user is displayed. + */ + get description(): string | undefined { + return this.#dataset?.getDescription ?? ''; + } + + get getCategories(): { label: Record; id: string; resource: string; }[] { + return this.#dataset?.getCategories ?? []; + } + + /** + * Get the publisher of the dataset. + * + * from dcat-ap-ch: + * Property publisher + * Requirement level Mandatory + * Cardinality 1..1 + * URI dct:publisher + * Range foaf:Agent + * Usage Note + * - This property refers to an entity (organisation) responsible for making the Dataset available. + * + */ + get publisher() { + const publisher = this.#dataset.getPublisher; + // the interface in piveau is wrong. + // i get this ... + // { + // name: "Bundesamt für Lebensmittelsicherheit und Veterinärwesen BLV", + // resource: "https://www.blv.admin.ch", + // type: "Agent", + // } + + if (!publisher) { + return undefined + } + + return { + type: publisher.type ?? '', + name: publisher.name ?? '', + resource: (publisher as unknown as { resource: string }).resource ?? '' + } + + } + + get getFormats(): string[] { + return this.#dataset?.getFormats ?? []; + } + + get getLicenses(): string[] { + return this.#dataset?.getLicenses ?? []; + } + + get getIssued(): string | undefined { + return this.#dataset?.getIssued; + } + + get getCreated(): string | undefined { + return this.#dataset?.getCreated; + } + + /** + * Get the release date of the dataset if available + * + * from dcat-ap-ch: + * Property release date + * Requirement level Recommended + * Cardinality 0..1 + * URI dct:issued + * Range rdfs:Literal (typed as as xsd:date, xsd:dateTime, xsd:gYear or xsd:gYearMonth) + * Usage Note + * - This property contains the date of formal issuance (e.g., first publication of the Dataset). + * - If this date is not known, the date of the first referencing of the data collection in the Catalogue can be entered. + */ + get releaseDate() { + if (!this.#dataset.getIssued) { + return undefined + } + return new Date(this.#dataset.getIssued) + } + + /** + * Get the modification date of the dataset if available + * + * from dcat-ap-ch: + * Property update/ modification date + * Requirement level Recommended + * Cardinality 0..1 + * URI dct:modified + * Range rdfs:Literal (typed as as xsd:date, xsd:dateTime, xsd:gYear or xsd:gYearMonth) + * Usage Note + * - This property contains the most recent date on which the Dataset was changed or modified. + * - No value may indicate that the Dataset has never changed after its initial publication, + * or that the date of the last modification is not known, or that the Dataset is continuously updated + * - This property MUST only be set if the distributions (the actual data) that the Dataset describes + * have been updated after it has been issued. In this case the property MUST contain the date of the last update. + * That way a person or institution using the data for an analysis or application will know when to update the + * report or application on their side. + */ + get modificationDate() { + if (!this.#dataset.getModified) { + return undefined + } + return new Date(this.#dataset.getModified) + } + + + + + get getLinkedData(): Record { + return this.#dataset?.getLinkedData ?? {} as Record; + } + + get getDistributions(): { id: string; title: string | undefined; description: string | undefined; format: string; modified: string | undefined; license: { label?: string | null | undefined; id?: string | null | undefined; description?: string | null | undefined; resource?: string | null | undefined; } | undefined; created: string | undefined; issued: string | undefined; languages: string[]; accessUrls: string[]; downloadUrls: string[]; getLinkedData: Record; getPropertyTable: PropertyTableEntryNode[]; }[] { + return this.#dataset?.getDistributions ?? []; + } + + /** + * Returns the distributions wrapped in DistributionAdapter instances + * + * @returns {DistributionAdapter[]} An array of DistributionAdapter instances + */ + get distributions() { + return this.#dataset.getDistributions.map(d => new DcatApChV2DistributionAdapter(d, this)); + } + + get getPropertyTable(): PropertyTableEntryNode[] { + return this.#dataset?.getPropertyTable ?? []; + } + + get getPropertyTable2(): PropertyTableEntryNode[] { + return this.#dataset?.getPropertyTable2 ?? []; + } + + get getOdsFormats(): { id?: string | null | undefined; label?: string | null | undefined; resource?: string | null | undefined; }[] { + return this.#dataset?.getOdsFormats ?? []; + } + + + get getKeywords(): { id: string; label: string; language: string; }[] { + return this.#dataset?.getKeywords ?? []; + } + + get getOdsCatalogInfo() { + return this.#dataset.getOdsCatalogInfo + } + + /** + * Get the accrual periodicity of the dataset if available + * + * from dcat-ap-ch: + * Property frequency + * Requirement level Optional + * Cardinality 0..1 + * URI dct:accrualPeriodicity + * Range dct:Frequency + * Usage Note + * - This property refers to the frequency at which the Dataset is updated. + * - CV to be used: [VOCAB-EU-FREQUENCY]. + */ + get frequency() { + return this.#dataset.getOdsAccrualPeriodicity; + } + + + + + get propertyTable() { + const rootNode = this.#dataset.getPropertyTable; + if (!rootNode) { + return []; + } + + const ignoredNode = ['catalogRecord']; + const nodesToConsider = rootNode.filter(n => n.data).filter(n => !ignoredNode.includes(n.id)); + + console.log('flatNodes', nodesToConsider); + + + const table: TableEntry[] = []; + for (const node of nodesToConsider) { + + const entry = {} as Partial; + + if (node.type === 'node' && node.data) { + entry.help = node.help ?? ''; + entry.label = node.label; + entry.id = node.id; + entry.nodeType = 'node'; + + if (node.data && node.data.length > 0) { + for (const child of node.data) { + if (child.type === 'value') { + if (!entry.value) { + entry.value = [{ value: child.data as string, type: 'value' }]; + } else { + entry.value.push({ value: child.data as string, type: 'value' }); + } + } else if (child.type === 'href') { + const hrefData = child.data as { label: string; href: string }; + if (!entry.value) { + entry.value = [{ value: hrefData.label, href: hrefData.href, type: 'href' }]; + } else { + entry.value.push({ value: hrefData.label, href: hrefData.href, type: 'href' }); + } + } else { + if (node.id === 'publisher') { + // special handling for publisher node + for (const data of child.data ?? []) { + if (!entry.value) { + entry.value = [{ value: data.data as string, type: 'value' }]; + } else { + entry.value.push({ value: data.data as string, type: 'value' }); + } + } + } else if (node.id === 'contactPoint') { + // special handling for contactPoint node + const nameNode = child.data?.find(d => d.id === 'contactPointName') + const emailNode = child.data?.find(d => d.id === 'contactPointEmail') + if (nameNode && emailNode && nameNode.data && emailNode.data) { + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const emailData = ((emailNode.data as Array)[0] as any).data; + const href = emailData.href; + const name = emailData.label; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const nameData = ((nameNode.data as Array)[0] as any).data; + const publisherName = nameData as string; + if (!entry.value) { + entry.value = [{ value: publisherName, type: 'value' }]; + entry.value.push({ value: name, href, type: 'email' }); + } + } + } + } + } + table.push(entry as TableEntry); + } + + } + + } + return table.sort((a, b) => a.label.localeCompare(b.label)); + } +} + + + diff --git a/opendata.swiss/ui/app/components/dataset-detail/model/dcat-ap-ch-v2-distribution-adapter.ts b/opendata.swiss/ui/app/components/dataset-detail/model/dcat-ap-ch-v2-distribution-adapter.ts new file mode 100644 index 0000000..eb2fda4 --- /dev/null +++ b/opendata.swiss/ui/app/components/dataset-detail/model/dcat-ap-ch-v2-distribution-adapter.ts @@ -0,0 +1,169 @@ +import type { LinkedDataFormats } from '@piveau/sdk-vue'; +import type { Dataset } from '../../../model/dataset' +import type { DcatApChV2DatasetAdapter } from './dcat-ap-ch-v2-dataset-adapter'; + + +type EnhancedDistribution = Dataset['getDistributions'][number] + + +export class DcatApChV2DistributionAdapter implements EnhancedDistribution { + #distribution: EnhancedDistribution | undefined; + #dataset: DcatApChV2DatasetAdapter; + + constructor(d: EnhancedDistribution, dataset: DcatApChV2DatasetAdapter) { + this.#distribution = d; + this.#dataset = dataset; + } + + /** + * Get the dataset this distribution belongs to + */ + get dataset() { + return this.#dataset; + } + + /** + * Get the title of the distribution. + * + * It return the title of the distribution if available, otherwise it returns the title of the dataset. The title on a distribution is not mandatory if + * the distribution contains the whole dataset. + * Language handling is done by peiveau. + * + * From dcat-ap-ch: + * Property Title + * Requirement level Recommended + * Cardinality 0..n + * URI dct:title + * Range rdfs:Literal + * Usage Note + * - This property contains a name given to the Distribution. This property can be repeated for parallel language versions of the description (see 2.3 Multilingualism). + * - The title MUST be given if the distribution contains only part of the data offered by the Dataset + * - The title can be given in several languages. In multilingual data portals, the title in the language selected by a user will usually be shown as title for the distribution. + */ + get title() { + return this.#distribution?.title || this.#dataset.title; + } + + /** + * Get the description of the distribution. + * + * It returns the description of the distribution if available, otherwise it returns an empty string. + * Language handling is done by peiveau. + * + * Property description + * Requirement level Recommended + * Cardinality 0..n + * URI dct:description + * Range rdfs:Literal + * Usage Note + * - This property contains a free-text account of the Distribution. + * - The description MUST be provided if the distribution contains only part of the data offered by the Dataset. + * - This property can be repeated for parallel language versions of the description (see 2.3 Multilingualism). + * + */ + get description() { + return this.#distribution?.description ?? ''; + } + + /** + * Get the formattedByteSize size of the distribution if available + * + * from dcat-ap-ch: + * Property byte size + * Requirement level Optional + * Cardinality 0..1 + * URI dcat:byteSize + * Range rdfs:Literal (typed as as xsd:decimal). + * Usage Note + * This property contains the size of a Distribution in bytes. If the precise size is not known, an approximate size can be indicated. + */ + get formattedByteSize() { + const byteSizeNode = this.#distribution?.getPropertyTable.find(node => node.id === 'byteSize'); + + if (!byteSizeNode || !byteSizeNode.data?.length) { + return ''; + } + + const byteSizeValue = byteSizeNode.data[0]?.data; + + if (!byteSizeValue || typeof byteSizeValue !== 'string') { + return ''; + } + + // Try to parse the byte size as a number. + // Piveau returns it as a string with dots as thousands separators which is not valid for Number() + const byteSizeNumber = Number(byteSizeValue.replace(/\./g, '')); // Remove dots for thousands separators + + if (isNaN(byteSizeNumber)) { + return byteSizeValue; // Return the raw value if parsing fails + } + + if (byteSizeNumber === 0) { + return '0 B'; + } + + const units = ['B', 'KB', 'MB', 'GB', 'TB']; + let size = byteSizeNumber; + let unitIndex = 0; + + while (size >= 1024 && unitIndex < units.length - 1) { + size /= 1024; + unitIndex++; + } + + return `${size % 1 === 0 ? size : size.toFixed(2)} ${units[unitIndex]}`; + } + + + + get getPropertyTable() { + return this.#distribution?.getPropertyTable || []; + } + + + get downloadUrls() { + return this.#distribution?.downloadUrls || []; + } + + get accessUrls() { + return this.#distribution?.accessUrls || []; + } + + get format() { + return this.#distribution?.format ?? ''; + } + + get license() { + return this.#distribution?.license; + } + + get issued() { + return this.#distribution?.issued || ''; + } + + get modified() { + return this.#distribution?.modified || ''; + } + + get id() { + return this.#distribution?.id || ''; + } + + get created() { + return this.#distribution?.created; + } + + get languages() { + return this.#distribution?.languages || []; + } + + get getLinkedData(): Record { + return this.#distribution?.getLinkedData ?? { + rdf: '', + ttl: '', + n3: '', + nt: '', + jsonld: '' + }; + } +} diff --git a/opendata.swiss/ui/app/components/dataset-detail/model/table-entry.ts b/opendata.swiss/ui/app/components/dataset-detail/model/table-entry.ts new file mode 100644 index 0000000..3ac78ce --- /dev/null +++ b/opendata.swiss/ui/app/components/dataset-detail/model/table-entry.ts @@ -0,0 +1,15 @@ + + +export interface TableEntry { + id: string; + label: string; + help: string; + value: [ + { + value: string; + href?: string; + type: 'value' | 'href' | 'email'; + } + ]; + nodeType: 'node' | 'value' | 'href'; +} diff --git a/opendata.swiss/ui/i18n/locales/de.json b/opendata.swiss/ui/i18n/locales/de.json index 65802fa..0b11b1e 100644 --- a/opendata.swiss/ui/i18n/locales/de.json +++ b/opendata.swiss/ui/i18n/locales/de.json @@ -40,7 +40,7 @@ "dataset": "Datensatz", "catalog": "Katalog", "this_dataset_record": "Dieser Datensatz-Eintrag wurde", - "accrual_periodicity": "Aktualisierungsfrequenz", + "frequency": "Aktualisierungsfrequenz", "show_catalog_entry": "Katalogeintrag anzeigen", "hide_catalog_entry": "Katalogeintrag ausblenden", "distribution": "Distribution", @@ -54,7 +54,8 @@ "go_to_resource": "Gehe zur Ressource", "show_raw": "Datum anzeigen", "show_relative": "Relative Zeit anzeigen", - "details": "Details" + "details": "Details", + "released": "Veröffentlicht" }, "showcase": { "type": { diff --git a/opendata.swiss/ui/i18n/locales/en.json b/opendata.swiss/ui/i18n/locales/en.json index 285260b..9622982 100644 --- a/opendata.swiss/ui/i18n/locales/en.json +++ b/opendata.swiss/ui/i18n/locales/en.json @@ -40,7 +40,7 @@ "dataset": "Dataset", "catalog": "Catalog", "this_dataset_record": "This dataset record has been", - "accrual_periodicity": "Update frequency", + "frequency": "Update frequency", "show_catalog_entry": "Show catalog entry", "hide_catalog_entry": "Hide catalog entry", "distribution": "Distribution", @@ -54,7 +54,8 @@ "go_to_resource": "Go to resource", "show_raw": "Show raw date", "show_relative": "Show relative time", - "details": "Details" + "details": "Details", + "released": "Released" }, "showcase": { "type": { diff --git a/opendata.swiss/ui/i18n/locales/fr.json b/opendata.swiss/ui/i18n/locales/fr.json index 92ee26d..fc3929f 100644 --- a/opendata.swiss/ui/i18n/locales/fr.json +++ b/opendata.swiss/ui/i18n/locales/fr.json @@ -40,7 +40,7 @@ "dataset": "Jeu de données", "catalog": "Catalogue", "this_dataset_record": "Cette entrée de jeu de données a été", - "accrual_periodicity": "Fréquence de mise à jour", + "frequency": "Fréquence de mise à jour", "show_catalog_entry": "Afficher l’entrée du catalogue", "hide_catalog_entry": "Masquer l’entrée du catalogue", "distribution": "Distribution", @@ -54,7 +54,8 @@ "go_to_resource": "Aller à la ressource", "show_raw": "Afficher la date brute", "show_relative": "Afficher le temps relatif", - "details": "Détails" + "details": "Détails", + "released": "Publié" }, "showcase": { "type": { diff --git a/opendata.swiss/ui/i18n/locales/it.json b/opendata.swiss/ui/i18n/locales/it.json index f191452..806beb0 100644 --- a/opendata.swiss/ui/i18n/locales/it.json +++ b/opendata.swiss/ui/i18n/locales/it.json @@ -40,7 +40,7 @@ "dataset": "Set di dati", "catalog": "Catalogo", "this_dataset_record": "Questo record del set di dati è stato", - "accrual_periodicity": "Frequenza di aggiornamento", + "frequency": "Frequenza di aggiornamento", "show_catalog_entry": "Mostra la voce di catalogo", "hide_catalog_entry": "Nascondi la voce di catalogo", "distribution": "Distribuzione", @@ -54,7 +54,8 @@ "go_to_resource": "Vai alla risorsa", "show_raw": "Mostra data grezza", "show_relative": "Mostra tempo relativo", - "details": "Dettagli" + "details": "Dettagli", + "released": "Rilasciato" }, "showcase": { "type": { diff --git a/opendata.swiss/ui/package-lock.json b/opendata.swiss/ui/package-lock.json index 0589dbf..a6d6c45 100644 --- a/opendata.swiss/ui/package-lock.json +++ b/opendata.swiss/ui/package-lock.json @@ -15,7 +15,7 @@ "@nuxtjs/i18n": "^10.0.1", "@pinia/nuxt": "^0.11.1", "@piveau/sdk-core": "^0.0.0-beta.2", - "@piveau/sdk-vue": "^1.0.0-beta.9", + "@piveau/sdk-vue": "^1.0.0-beta.10", "better-sqlite3": "^12.2.0", "bootstrap": "^5.3.7", "decap-cms-app": "^3.8.3", @@ -4442,9 +4442,9 @@ } }, "node_modules/@piveau/sdk-vue": { - "version": "1.0.0-beta.9", - "resolved": "https://registry.npmjs.org/@piveau/sdk-vue/-/sdk-vue-1.0.0-beta.9.tgz", - "integrity": "sha512-3RzdfzsToZxA0xeDgNHzjOZaf3WGKMlCTYs6PrWVPjfb5hC0PBPFlFQPcXv+QWao71DWUxpVAoxtytoia+KXPA==", + "version": "1.0.0-beta.10", + "resolved": "https://registry.npmjs.org/@piveau/sdk-vue/-/sdk-vue-1.0.0-beta.10.tgz", + "integrity": "sha512-aaADwEwU/cJIWBIuFRY/agvnBgRU0382W5zn7FLbugM1ZxRwzoCRApO5uUQHfOVH5b9ppE469eObSvEwew0oIQ==", "license": "Apache-2.0", "dependencies": { "@piveau/sdk-core": "^0.0.0-beta.2", diff --git a/opendata.swiss/ui/package.json b/opendata.swiss/ui/package.json index 708632c..0ca24b2 100644 --- a/opendata.swiss/ui/package.json +++ b/opendata.swiss/ui/package.json @@ -22,7 +22,7 @@ "@nuxtjs/i18n": "^10.0.1", "@pinia/nuxt": "^0.11.1", "@piveau/sdk-core": "^0.0.0-beta.2", - "@piveau/sdk-vue": "^1.0.0-beta.9", + "@piveau/sdk-vue": "^1.0.0-beta.10", "better-sqlite3": "^12.2.0", "bootstrap": "^5.3.7", "decap-cms-app": "^3.8.3", @@ -52,4 +52,4 @@ "vite-plugin-vuetify": "^2.1.1", "vuetify": "^3.9.2" } -} +} \ No newline at end of file diff --git a/opendata.swiss/ui/pages/datasets/[datasetId]/distribution/[distributionId].vue b/opendata.swiss/ui/pages/datasets/[datasetId]/distribution/[distributionId].vue index 9bed8d8..665e2c2 100644 --- a/opendata.swiss/ui/pages/datasets/[datasetId]/distribution/[distributionId].vue +++ b/opendata.swiss/ui/pages/datasets/[datasetId]/distribution/[distributionId].vue @@ -8,6 +8,11 @@ import { useDatasetsSearch } from '../../../../app/piveau/search.js' import { homePageBreadcrumb } from "../../../../app/composables/breadcrumbs.js"; import OdsDetailTermsOfUse from '../../../../app/components/dataset-detail/OdsDetailTermsOfUse.vue'; import OdsDetailsTable from '../../../../app/components/dataset-detail/OdsDetailsTable.vue' + + +import { DcatApChV2DatasetAdapter } from '../../../../app/components/dataset-detail/model/dcat-ap-ch-v2-dataset-adapter.js' + + const { locale, t } = useI18n(); const route = useRoute() @@ -19,9 +24,21 @@ const distributionId = computed(() => route.params.distributionId as string) const { useResource } = useDatasetsSearch() const { isSuccess, resultEnhanced } = useResource(datasetId) +const dataset = computed(() => { + if (!resultEnhanced.value) { + return undefined + } + return new DcatApChV2DatasetAdapter(resultEnhanced.value) +}) + + const distribution = computed(() => { - const dists = resultEnhanced.value?.getDistributions.find(d => d.id === distributionId.value) ?? undefined - return dists + const dist = dataset.value?.distributions.find(d => d.id === distributionId.value); + if (!dist) { + return undefined + } + + return dist }) const node = computed(() => { @@ -52,7 +69,7 @@ const _breadcrumbs = [

{{ t('message.dataset_detail.distribution') }}{{ t('message.dataset_detail.published_on') }} {{ resultEnhanced?.getCreated }} {{ t('message.dataset_detail.modified_on') }} {{ resultEnhanced?.getModified }}

{{ distribution.title }}

-

{{ distribution.description }}

+
diff --git a/opendata.swiss/ui/pages/datasets/[datasetId]/index.vue b/opendata.swiss/ui/pages/datasets/[datasetId]/index.vue index 79fa4d7..6528cbb 100644 --- a/opendata.swiss/ui/pages/datasets/[datasetId]/index.vue +++ b/opendata.swiss/ui/pages/datasets/[datasetId]/index.vue @@ -2,7 +2,11 @@ import { definePropertyNode } from '@piveau/sdk-vue' import { computed } from 'vue' import { useRoute, useRouter } from 'vue-router' +import { useI18n } from 'vue-i18n'; + import { useDatasetsSearch } from '../../../app/piveau/search' +import { DcatApChV2DatasetAdapter } from '../../../app/components/dataset-detail/model/dcat-ap-ch-v2-dataset-adapter'; + import { homePageBreadcrumb } from "../../../app/composables/breadcrumbs"; import OdsBreadcrumbs from "../../../app/components/OdsBreadcrumbs.vue"; import OdsDetailTermsOfUse from '../../../app/components/dataset-detail/OdsDetailTermsOfUse.vue' @@ -10,7 +14,7 @@ import OdsDetailsTable from '../../../app/components/dataset-detail/OdsDetailsTa import OdsTagList from '../../../app/components/dataset-detail/OdsTagList.vue' import OdsDatasetMetaInfo from '../../../app/components/dataset-detail/OdsDatasetMetaInfo.vue' import OdsDistributionList from '../../../app/components/dataset-detail/OdsDistributionList.vue' -import { useI18n } from 'vue-i18n'; + const { locale, t } = useI18n(); const route = useRoute() @@ -22,6 +26,16 @@ const { isSuccess, resultEnhanced } = useResource(datasetId) const node = computed(() => definePropertyNode({ id: 'root', data: resultEnhanced.value?.getPropertyTable }, { compact: true, maxDepth: 2 })) +const dataset = computed(() => { + if (!resultEnhanced.value) { + return undefined + } + return new DcatApChV2DatasetAdapter(resultEnhanced.value) +}) + +const distributions = computed(() => (dataset.value?.distributions ?? []).sort((a, b) => a.title.localeCompare(b.title))) + + const homePage = await homePageBreadcrumb(locale) const breadcrumbs = computed(() => { const result = [ @@ -55,7 +69,7 @@ const breadcrumbs = computed(() => { diff --git a/opendata.swiss/ui/pages/datasets/[datasetId]/index.vue b/opendata.swiss/ui/pages/datasets/[datasetId]/index.vue index 670d5a4..5a8f175 100644 --- a/opendata.swiss/ui/pages/datasets/[datasetId]/index.vue +++ b/opendata.swiss/ui/pages/datasets/[datasetId]/index.vue @@ -1,5 +1,5 @@