diff --git a/src/components/ItemListSortButton.vue b/src/components/ItemListSortButton.vue index 841d314..2c055e5 100644 --- a/src/components/ItemListSortButton.vue +++ b/src/components/ItemListSortButton.vue @@ -1,24 +1,20 @@ diff --git a/src/components/SortableTabularList.vue b/src/components/SortableTabularList.vue new file mode 100644 index 0000000..5842e88 --- /dev/null +++ b/src/components/SortableTabularList.vue @@ -0,0 +1,150 @@ + + + + + \ No newline at end of file diff --git a/src/components/VocabItemList.vue b/src/components/VocabItemList.vue deleted file mode 100644 index 61e477c..0000000 --- a/src/components/VocabItemList.vue +++ /dev/null @@ -1,176 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/types.ts b/src/types.ts index 94d5e52..bf0c79f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,8 +3,6 @@ import type { Quad } from "n3"; export type PrezFlavour = "CatPrez" | "SpacePrez" | "VocPrez"; -export type listingTableColumn = "label" | "description" | "status" | "derivationMode"; - export const mapConfigKey: InjectionKey = Symbol(); export const sidenavConfigKey: InjectionKey = Symbol(); export const enabledPrezsConfigKey: InjectionKey = Symbol(); @@ -94,26 +92,17 @@ export interface ListItem { type?: string; }; -export interface RegStatus { - iri: string; - label: string; - color?: string; -}; +// extra properies for SortableTable display go in extras +export interface ListItemExtra extends ListItem { + extras: { + [key: string]: ListItemSortable + }; +} -export interface DerivationMode { - iri: string; +export interface ListItemSortable { label: string; -}; - -export interface VocabListItem { - iri: string; - title?: string; - description?: string; - link?: string; - type?: string; - status?: RegStatus; - derivationMode?: DerivationMode; - [key: string]: string | RegStatus | undefined; + iri?: string; + color?: string; }; export interface AnnotatedPredicate { diff --git a/src/views/ItemListView.vue b/src/views/ItemListView.vue index 159371b..f07049d 100644 --- a/src/views/ItemListView.vue +++ b/src/views/ItemListView.vue @@ -5,14 +5,14 @@ import { DataFactory, type Quad_Object, type Quad_Subject } from "n3"; import { useUiStore } from "@/stores/ui"; import { useRdfStore } from "@/composables/rdfStore"; import { useGetRequest } from "@/composables/api"; -import { apiBaseUrlConfigKey, type Breadcrumb, type ListItem, type VocabListItem, type PrezFlavour, type Profile, type RegStatus, type DerivationMode } from "@/types"; +import { apiBaseUrlConfigKey, type Breadcrumb, type ListItem, type PrezFlavour, type Profile, type ListItemExtra, type ListItemSortable } from "@/types"; import ItemList from "@/components/ItemList.vue"; -import VocabItemList from "@/components/VocabItemList.vue"; import AdvancedSearch from "@/components/search/AdvancedSearch.vue"; import ProfilesTable from "@/components/ProfilesTable.vue"; import ErrorMessage from "@/components/ErrorMessage.vue"; import PaginationComponent from "@/components/PaginationComponent.vue"; import { getPrezSystemLabel } from "@/util/prezSystemLabelMapping"; +import SortableTabularList from "@/components/SortableTabularList.vue"; const { namedNode } = DataFactory; @@ -37,7 +37,7 @@ const TOP_LEVEL_TYPES = [ const ALT_PROFILES_TOKEN = "lt-prfl:alt-profile"; // const parent = ref({} as ListItem); // might need to store parent info (dataset & feature collection) -const items = ref([]); +const items = ref([]); const itemType = ref({ uri: "", label: "" @@ -185,7 +185,10 @@ function getProperties() { // fill out item list & handle vocprez items nodeList.forEach(member => { - let c: VocabListItem = { iri: member.id }; // already contains all attributes we need + let c: ListItemExtra = { + iri: member.id, + extras: {} + }; store.value.forEach(q => { if (labelPredicates.includes(q.predicate.value)) { @@ -195,7 +198,7 @@ function getProperties() { } else if (q.predicate.value === qname("prez:link")) { c.link = q.object.value; } else if (flavour.value === "VocPrez" && q.predicate.value === qname("reg:status")) { - const status: RegStatus = {iri: q.object.value, label: getIRILocalName(q.object.value)}; + const status: ListItemSortable = {iri: q.object.value, label: getIRILocalName(q.object.value)}; store.value.forObjects(result => { status.label = result.value; @@ -204,16 +207,16 @@ function getProperties() { store.value.forObjects(result => { status.color = result.value; }, q.object, qname("sdo:color"), null); - c.status = status; + c.extras.status = status; } else if (flavour.value === "VocPrez" && q.predicate.value === qname("prov:qualifiedDerivation")) { store.value.forObjects(result => { - const mode: DerivationMode = {iri: result.value, label: getIRILocalName(result.value)}; + const mode: ListItemSortable = {iri: result.value, label: getIRILocalName(result.value)}; store.value.forObjects(innerResult => { mode.label = innerResult.value; }, result,qname("rdfs:label"), null); - c.derivationMode = mode; + c.extras.derivationMode = mode; }, q.object, qname("prov:hadRole"), null); } }, member, null, null, null); @@ -322,7 +325,7 @@ onMounted(() => { Loading... diff --git a/src/views/PropTableView.vue b/src/views/PropTableView.vue index 7a7214a..63698a8 100644 --- a/src/views/PropTableView.vue +++ b/src/views/PropTableView.vue @@ -5,7 +5,7 @@ import { BlankNode, DataFactory, Quad, Store } from "n3"; import { useUiStore } from "@/stores/ui"; import { useRdfStore } from "@/composables/rdfStore"; import { useGetRequest } from "@/composables/api"; -import { apiBaseUrlConfigKey, type ListItem, type AnnotatedQuad, type Breadcrumb, type Concept, type PrezFlavour, type Profile } from "@/types"; +import { apiBaseUrlConfigKey, type ListItem, type AnnotatedQuad, type Breadcrumb, type Concept, type PrezFlavour, type Profile, type ListItemExtra, type ListItemSortable } from "@/types"; import PropTable from "@/components/proptable/PropTable.vue"; import ConceptComponent from "@/components/ConceptComponent.vue"; import AdvancedSearch from "@/components/search/AdvancedSearch.vue"; @@ -14,6 +14,7 @@ import ErrorMessage from "@/components/ErrorMessage.vue"; import { getPrezSystemLabel } from "@/util/prezSystemLabelMapping"; import MapClient from "@/components/MapClient.vue"; import type { WKTResult } from "@/stores/mapSearchStore.d"; +import SortableTabularList from "@/components/SortableTabularList.vue"; const { namedNode } = DataFactory; @@ -31,7 +32,7 @@ const RECURSION_LIMIT = 5; // limit on recursive search of blank nodes const ALT_PROFILES_TOKEN = "lt-prfl:alt-profile"; const item = ref({} as ListItem); -const children = ref([]); +const children = ref([]); const concepts = ref([]); // only for vocab const properties = ref([]); const blankNodes = ref([]); @@ -185,6 +186,10 @@ function getBreadcrumbs(): Breadcrumb[] { switch (pathSegment) { case "catalogs": crumbs.push({ name: "Catalogs", url: "/c/catalogs" }); + if (index + 1 !== pathSegments.length) { + crumbs.push({ name: "Catalog", url: `/c/catalogs/${route.params.catalogId}` }); + skipSegment = true; + } break; case "datasets": crumbs.push({ name: "Datasets", url: "/s/datasets" }); @@ -232,6 +237,16 @@ function getBreadcrumbs(): Breadcrumb[] { return crumbs; } +function getIRILocalName(iri: string) { + let result = iri.split("#"); + if (result.length === 1) { + return result[0].split("/").slice(-1)[0] + } + else { + return result.slice(-1)[0]; + } +} + function getChildren() { if (item.value.type === qname("skos:ConceptScheme")) { getConcepts(); @@ -239,8 +254,9 @@ function getChildren() { const labelPredicates = defaultProfile.value!.labelPredicates.length > 0 ? defaultProfile.value!.labelPredicates : DEFAULT_LABEL_PREDICATES; store.value.forObjects((obj) => { - let child: ListItem = { - iri: obj.id + let child: ListItemExtra = { + iri: obj.id, + extras: {} }; store.value.forEach(q => { @@ -250,7 +266,26 @@ function getChildren() { child.link = q.object.value; } else if (q.predicate.value === qname("a")) { child.type = q.object.value; - } + } else if (item.value.type === qname("dcat:Catalog") && q.predicate.value === qname("dcterms:publisher")) { + const publisher: ListItemSortable = { iri: q.object.value, label: getIRILocalName(q.object.value) }; + + store.value.forObjects(result => { + publisher.label = result.value; + }, q.object, qname("rdfs:label"), null); + + child.extras.publisher = publisher; + } else if (item.value.type === qname("dcat:Catalog") && q.predicate.value === qname("dcterms:creator")) { + const creator: ListItemSortable = { iri: q.object.value, label: getIRILocalName(q.object.value) }; + + store.value.forObjects(result => { + creator.label = result.value; + }, q.object, qname("rdfs:label"), null); + + child.extras.creator = creator; + } else if (item.value.type === qname("dcat:Catalog") && q.predicate.value === qname("dcterms:issued")) { + const issued: ListItemSortable = { label: q.object.value }; + child.extras.issued = issued; + } }, obj, null, null, null); children.value.push(child); @@ -462,7 +497,12 @@ onMounted(() => {