Skip to content

Commit ec34c28

Browse files
Merge pull request #23 from anushacs-dell/branch-ui
Add Cwl-Svg Visualization, Metadata Display,Structured data Integration
2 parents efd0e99 + c60eb95 commit ec34c28

File tree

12 files changed

+10020
-6865
lines changed

12 files changed

+10020
-6865
lines changed

package-lock.json

Lines changed: 4979 additions & 6763 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
"@sidebase/nuxt-auth": "^0.9.0",
2121
"cookie": ">=0.7.0",
2222
"crypto-js": "^4.2.0",
23+
"cwl-svg": "^2.1.14",
24+
"cwlts": "^1.23.10",
2325
"html2canvas": "^1.4.1",
26+
"js-yaml": "^4.1.1",
2427
"nanoid": ">=5.0.9",
2528
"next-auth": "^4.21.1",
2629
"nuxt": "^3.15.4",

pages/processes/[processId].vue

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
import { useHead } from '#imports'
23
import { ref, onMounted, watch, reactive } from 'vue'
34
import { useRoute } from 'vue-router'
45
import { useRuntimeConfig } from '#imports'
@@ -9,6 +10,7 @@ import HelpDialog from '@/components/help/HelpDialog.vue'
910
import processIdHelp from '@/components/help/processIdHelp.js'
1011
1112
13+
1214
const {
1315
params: { processId }
1416
} = useRoute()
@@ -100,6 +102,7 @@ const typeLabel = (input: any, valForInputId: any) => {
100102
return input?.schema?.type || 'literal'
101103
}
102104
105+
103106
const fetchData = async () => {
104107
try {
105108
data.value = await $fetch(`${config.public.NUXT_ZOO_BASEURL}/ogc-api/processes/${processId}`, {
@@ -108,6 +111,8 @@ const fetchData = async () => {
108111
}
109112
})
110113
114+
115+
111116
if (data.value && data.value.inputs) {
112117
for (const [key, input] of Object.entries(data.value.inputs)) {
113118
if (input.minOccurs === undefined && input.maxOccurs === undefined) {
@@ -211,6 +216,94 @@ const fetchData = async () => {
211216
}
212217
}
213218
219+
220+
watch(
221+
() => data.value,
222+
(val) => {
223+
if (!val) return
224+
225+
const rawMetadata = val.metadata || []
226+
227+
// Extract items by role
228+
const extractByRole = (role) =>
229+
rawMetadata
230+
.filter(md => md.role === role)
231+
.map(md => md.value)
232+
233+
// Authors (may be multiple)
234+
const authors = extractByRole("https://schema.org/author")
235+
.map(a => ({
236+
"@type": a["@type"] || "Person",
237+
"name": a.name || a.fullName || ""
238+
}))
239+
240+
// Contributors
241+
const contributors = extractByRole("https://schema.org/contributor")
242+
.map(c => ({
243+
"@type": c["@type"] || "Person",
244+
"name": c.name || c.fullName || ""
245+
}))
246+
247+
// Organizations
248+
const organizations = extractByRole("https://schema.org/organization")
249+
.map(org => ({
250+
"@type": "Organization",
251+
"name": org.name || ""
252+
}))
253+
254+
// Additional metadata (anything NOT author/contributor/organization)
255+
const skipRoles = [
256+
"https://schema.org/author",
257+
"https://schema.org/contributor",
258+
"https://schema.org/organization"
259+
]
260+
261+
const additionalProps = rawMetadata
262+
.filter(md => !skipRoles.includes(md.role))
263+
.map(md => ({
264+
"@type": "PropertyValue",
265+
"name": md.role,
266+
"value": md.value
267+
}))
268+
269+
// Build final JSON-LD
270+
const jsonLd = {
271+
"@context": "https://schema.org",
272+
"@type": "SoftwareSourceCode",
273+
"name": val.id,
274+
"description": val.description,
275+
"softwareVersion": val.version || null,
276+
"keywords": val.keywords || [],
277+
"identifier": processId,
278+
"url": `http://localhost:3058/processes/${processId}`,
279+
280+
// New metadata mapping
281+
"author": authors,
282+
"contributor": contributors,
283+
"provider": organizations.length ? organizations[0] : {
284+
"@type": "Organization",
285+
"name": "ZOO-Project"
286+
},
287+
288+
"additionalProperty": additionalProps
289+
}
290+
291+
// Inject JSON-LD into <head>
292+
useHead({
293+
script: [
294+
{
295+
type: "application/ld+json",
296+
children: JSON.stringify(jsonLd)
297+
}
298+
]
299+
})
300+
},
301+
{ immediate: true }
302+
)
303+
304+
305+
306+
214307
onMounted(() => {
215308
fetchData()
216309
})
@@ -594,6 +687,65 @@ const removeInputField = (inputId: string, index: number) => {
594687
<div class="text-subtitle1 text-grey-7">
595688
{{ data.description }}
596689
</div>
690+
<q-card-section class="q-pa-md bg-grey-1 rounded-borders q-mt-md">
691+
692+
<!-- Version -->
693+
<div class="row q-mb-sm">
694+
<div class="col-3 text-grey-7 text-weight-bold">Version</div>
695+
<div class="col">
696+
{{ data.version || '—' }}
697+
</div>
698+
</div>
699+
700+
<!-- Keywords -->
701+
<div class="row q-mb-sm">
702+
<div class="col-3 text-grey-7 text-weight-bold">Keywords</div>
703+
<div class="col">
704+
<span v-if="data.keywords?.length">
705+
{{ data.keywords.join(', ') }}
706+
</span>
707+
<span v-else>—</span>
708+
</div>
709+
</div>
710+
711+
<!-- Metadata -->
712+
<div class="row q-mb-sm">
713+
<div class="col-12 text-grey-7 text-weight-bold q-mb-xs">Additional Metadata</div>
714+
715+
<div v-if="data.metadata?.length" class="col-12">
716+
717+
<div v-for="(md, index) in data.metadata" :key="index" class="q-pa-sm bg-white rounded-borders q-mb-sm shadow-1">
718+
719+
<!-- Detect Person -->
720+
<div v-if="md.value && typeof md.value === 'object' && md.value['@type'] === 'Person'">
721+
<div class="text-weight-bold text-primary">👤 {{ md.title || 'Person' }}</div>
722+
<div class="q-mt-xs">
723+
<div><strong>Name:</strong> {{ md.value.name }}</div>
724+
<div v-if="md.value.role"><strong>Role:</strong> {{ md.value.role }}</div>
725+
<div v-if="md.value.email"><strong>Email:</strong> {{ md.value.email }}</div>
726+
<div v-if="md.value.affiliation"><strong>Affiliation:</strong> {{ md.value.affiliation }}</div>
727+
</div>
728+
</div>
729+
730+
<!-- Default metadata -->
731+
<div v-else>
732+
<div class="text-weight-bold">{{ md.title || md.role }}</div>
733+
<div class="text-grey-8">{{ md.value }}</div>
734+
</div>
735+
736+
</div>
737+
738+
</div>
739+
740+
741+
<div v-else class="col-12">
742+
743+
</div>
744+
</div>
745+
746+
</q-card-section>
747+
748+
597749
<q-separator class="q-mt-md" />
598750
</div>
599751

0 commit comments

Comments
 (0)