Skip to content

Commit

Permalink
updates to custom widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
hjohns committed Apr 14, 2024
1 parent 83aa634 commit be54a31
Show file tree
Hide file tree
Showing 11 changed files with 530 additions and 82 deletions.
48 changes: 34 additions & 14 deletions prez-components/src/custom-components/CustomCitation.vue
Original file line number Diff line number Diff line change
@@ -1,36 +1,56 @@
<script lang="ts" setup>
import { PrezProperty, PrezLiteral, PrezNode } from 'prez-lib';
import type { CitationProperties } from './CustomCitation'
defineProps<{focusNode: PrezNode, properties: CitationProperties}>();
const props = defineProps<{focusNode: PrezNode, properties: CitationProperties}>();
import CopyButton from "../components/CopyButton.vue";
import Button from 'primevue/button';
//import Tooltip from 'primevue/tooltip';
const propertyValue = (property:PrezProperty|undefined, dataType?:string) =>
property?.objects?.filter(obj => !dataType || (obj.termType == "Literal" && dataType == (obj as PrezLiteral).datatype?.value))
.map(obj => obj.value).join(', ') || "";
const firstTruthy = (...args: any[]): any => args.find(Boolean);
// Compute the citation text
const citationText = `Open Geospatial Consortium,
<em>${propertyValue(props.properties['http://purl.org/dc/terms/title'])}</em>
(<em>${propertyValue(props.properties['http://purl.org/dc/terms/identifier'], 'http://www.opengis.net/def/metamodel/ogc-na/doc_no')}</em>)
(${propertyValue(props.properties['http://purl.org/dc/terms/created']).toString().split('-')[0]}).
OGC ${propertyValue(props.properties['https://www.opengis.net/def/metamodel/ogc-na/doctype'])},
Eds. ${propertyValue(props.properties["http://purl.org/dc/terms/creator"])}.
${firstTruthy(
propertyValue(props.properties['http://purl.org/dc/terms/identifier'], 'http://example.com/datatypes/DOI'),
props.focusNode?.value
)}`;
</script>

<template>

<div v-if="propertyValue(properties['http://purl.org/dc/terms/identifier'], 'http://www.opengis.net/def/metamodel/ogc-na/doc_no')">
Open Geospatial Consortium,
<em>{{ propertyValue(properties['http://purl.org/dc/terms/title']) }}</em>
(<em>{{ propertyValue(properties['http://purl.org/dc/terms/identifier'], 'http://www.opengis.net/def/metamodel/ogc-na/doc_no') }}</em>)
({{ propertyValue(properties['http://purl.org/dc/terms/created']).toString().split('-')[0] }}).
OGC {{ propertyValue(properties['https://www.opengis.net/def/metamodel/ogc-na/doctype']) }},
Eds. {{ propertyValue(properties["http://purl.org/dc/terms/creator"]) }}.
{{ firstTruthy(
propertyValue(properties['http://purl.org/dc/terms/identifier'], 'http://example.com/datatypes/DOI'),
focusNode?.value
) }}
<div v-if="propertyValue(properties['http://purl.org/dc/terms/identifier'], 'http://www.opengis.net/def/metamodel/ogc-na/doc_no')"
v-tooltip="'This widget will use a configurable range of properties to show data in human and machine readable form'">
<div v-html="citationText" />

<div style="padding-top: 5px;">
<CopyButton :value="citationText" iconOnly class="sm" />
&nbsp;
<Button size="small">XML</Button>
&nbsp;
<Button size="small"><i class="pi pi-share-alt"/></Button>
</div>
</div>

</template>

<style scoped>
div {
float:right;
width:400px;
font-size:small;
}
.copy-btn.sm {
padding: 8px 10px;
width: 33px;
height: 33px;
}
</style>
154 changes: 154 additions & 0 deletions prez-components/src/custom-components/CustomDataList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<script lang="ts" setup>
import { ref, computed } from "vue";
import { RouterLink } from "vue-router";
import DataView from "primevue/dataview";
import Button from "primevue/button";
import Skeleton from "primevue/skeleton";
import type { PrezNode, PrezLiteral, PrezItem } from "prez-lib"
import { PrezUIItemListProps } from "../types";
import { HIDDEN_PREDICATES } from "../util/consts";
import { sortLiterals, sortNodes } from "../util/helpers";
import PrezUINode from "../components/PrezUINode.vue";
import PrezUITerm from "../components/PrezUITerm.vue";
const props = defineProps<PrezUIItemListProps & {layout: 'grid' | 'table'}>();
const sortedItems = ref<PrezItem[]>(props.data || []);
// get the list of predicates that exist in item properties
const predicates = computed<PrezNode[]>(() => {
if (props.data) {
const list = props.data.map(item => Object.values(item.properties).map(prop => prop.predicate)).flat(1);
const iris: string[] = [];
const p: PrezNode[] = [];
list.forEach(item => {
if (!iris.includes(item.value) && !HIDDEN_PREDICATES.includes(item.value)) {
p.push(item);
iris.push(item.value);
}
});
return p;
} else {
return [];
}
});
// to use for rendering when "loading"
const placeholderItems = [
{
value: "1",
properties: {}
},
{
value: "2",
properties: {}
},
{
value: "3",
properties: {}
}
];
</script>

<template>

<div v-if="layout == 'table'">

<DataTable :value="props.loading ? placeholderItems : sortedItems" tableStyle="min-width: 50rem">
<Column v-for="col of listHeaders" body="" v-bind="col" v-bind:key="col.field" style="width: 25%" />
</DataTable>
<!-- <th v-for="predicate in predicates">
<div class="col-header">
<PrezUINode v-bind="predicate" />
<Button size="small" :icon="`pi pi-sort-alpha-${sortField === predicate.value && sortOrder === 'desc' ? 'up' : 'down'}`" @click="handleSortClick(predicate.value)" :outlined="sortField !== predicate.value" />
</div>
</th> -->
</div>

<DataView :value="props.loading ? placeholderItems : sortedItems" dataKey="value">
<template #list="slotProps">
<table>
<tr>
<th class="label">
<Skeleton v-if="props.loading" height="1.5rem" width="6rem" class="mb-2"></Skeleton>
<div v-else class="col-header">
Label
<Button size="small" :icon="`pi pi-sort-alpha-${sortField === 'label' && sortOrder === 'desc' ? 'up' : 'down'}`" @click="handleSortClick('label')" :outlined="sortField !== 'label'" />
</div>
</th>
<th v-for="predicate in predicates">
<div class="col-header">
<PrezUINode v-bind="predicate" />
<Button size="small" :icon="`pi pi-sort-alpha-${sortField === predicate.value && sortOrder === 'desc' ? 'up' : 'down'}`" @click="handleSortClick(predicate.value)" :outlined="sortField !== predicate.value" />
</div>
</th>
<th class="members-col"></th>
</tr>
<template v-for="item in slotProps.items">
<tr>
<td class="label">
<Skeleton v-if="props.loading" height="1.5rem" width="14rem" class="mb-2"></Skeleton>
<PrezUINode v-else v-bind="item.focusNode" showType :showDesc="false" :showExt="false" />
</td>
<td v-for="predicate in predicates">
<template v-if="predicate.value in item.properties">
<PrezUITerm v-for="obj in item.properties[predicate.value].objects" v-bind="obj" />
</template>
</td>
<td v-if="!props.loading && item.focusNode.members" class="members-col">
<RouterLink v-for="member in item.focusNode.members" :to="member.link">
<Button size="small" outlined>{{ member.label }}</Button>
</RouterLink>
</td>
</tr>
<tr>
<td class="desc" :colspan="predicates.length + 2">
<Skeleton v-if="props.loading" width="32rem" class="mb-2"></Skeleton>
<template v-else>{{ item.focusNode.description?.value || "" }}</template>
</td>
</tr>
</template>
</table>
</template>
</DataView>
</template>

<style lang="scss" scoped>
table {
border-collapse: collapse;
width: 100%;

& > tr {
&:nth-child(4n - 2), &:nth-child(4n - 1) {
background-color: #f8fafc;
}

th > .col-header {
display: flex;
flex-direction: row;
gap: 8px;
align-items: center;
padding: 6px;
}

td {
padding: 8px;

&.desc {
font-style: italic;
font-size: 0.9em;
color: #b1b1b1;
}

&.members-col {
text-align: right;
}
}
}

.label {
min-width: 300px;
}
}
</style>
35 changes: 35 additions & 0 deletions prez-components/src/custom-components/CustomItem.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { PrezProperties, PrezProperty, PrezTerm } from "prez-lib";

const fields = [
'http://purl.org/dc/terms/title',
'http://purl.org/dc/terms/isPartOf',
'http://purl.org/dc/terms/identifier',
// 'http://www.w3.org/ns/dcat#Resource',
'https://www.opengis.net/def/metamodel/ogc-na/doctype',
'http://purl.org/dc/terms/creator',
'http://purl.org/dc/terms/created',
] as const;

export type ItemFields = typeof fields[number];

export type ItemProperties = Partial<Record<ItemFields, PrezProperty>>;

function getProps(obj, props) {
const result = {};
props.forEach(prop => {
if (obj.hasOwnProperty(prop)) {
result[prop] = obj[prop];
}
});
return result;
}

export function filterProps(properties: PrezProperties) {
return getProps(
properties,
[
'http://www.opengis.net/def/metamodel/ogc-na/status',
'http://www.w3.org/2000/01/rdf-schema#seeAlso'
]
)
}
76 changes: 76 additions & 0 deletions prez-components/src/custom-components/CustomItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<script lang="ts" setup>
import { PrezProperty, PrezLiteral, PrezNode } from 'prez-lib';
import type { ItemProperties } from './CustomItem';
import PrezUITerm from '../components/PrezUITerm.vue';
import CopyButton from "../components/CopyButton.vue";
const props = defineProps<{focusNode: PrezNode, properties: ItemProperties}>();
const propertyValue = (property:PrezProperty|undefined, dataType?:string) =>
property?.objects?.filter(obj => !dataType || (obj.termType == "Literal" && dataType == (obj as PrezLiteral).datatype?.value))
.map(obj => obj.value).join(', ') || "";
</script>

<template>
<div class="item-header">
<h1>{{ props.focusNode?.label?.value || props.focusNode?.value }}</h1>
<div class="flex-row">
IRI:
<div class="iri">
<a :href="props.focusNode?.value" target="_blank" rel="noopener noreferrer">{{ props.focusNode?.value }}</a>
<CopyButton :value="props.focusNode?.value" iconOnly />
</div>
</div>

<div class="flex-row">
<div>Defined by: </div>
<PrezUITerm
v-if="props.properties?.['http://purl.org/dc/terms/isPartOf']"
v-for="o in props.properties['http://purl.org/dc/terms/isPartOf'].objects"
v-bind="o"
/>
</div>

<p class="desc">
<template v-if="props.focusNode">{{ props.focusNode.description?.value }}</template>
</p>

</div>
</template>

<style scoped>
.flex-row {
display: flex;
flex-direction: row;
align-items: center;
gap: 8px;
margin-bottom: 10px;
}

.types {
display: flex;
flex-direction: row;
gap: 6px;
}

.iri {
padding: 8px;
background-color: #e9e9e9;
border-radius: 4px;
font-family: monospace;
display: flex;
flex-direction: row;
align-items: center;
gap: 20px;
}

.desc {
font-style: italic;
}

#right-nav {
padding: 12px;
min-width: 280px;
max-width: 280px;
}
</style>
Loading

0 comments on commit be54a31

Please sign in to comment.