Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
63adde3
Added some styling
MohdNishan Jul 1, 2025
4f93868
Updated Processes
MohdNishan Jul 1, 2025
272a38d
Merge branch 'zooproject-ui' of https://github.com/MohdNishan/zooproj…
MohdNishan Jul 1, 2025
646af62
Merge branch 'develop' into zooproject-ui
MohdNishan Jul 1, 2025
f2d3250
Delete pages/processes/index.vue
MohdNishan Jul 1, 2025
acec7ba
Updated the JSON displayed on the page
MohdNishan Jul 1, 2025
545fa62
Updated Bug on Search
MohdNishan Jul 2, 2025
366831e
Merge branch 'zooproject-ui' of https://github.com/MohdNishan/zooproj…
MohdNishan Jul 2, 2025
6e5c19c
Bug Fix on search
MohdNishan Jul 2, 2025
b62bb5f
Updated the add/delete input function for supporting multiple values
MohdNishan Jul 4, 2025
6a41019
Merge branch 'develop' into zooproject-ui
MohdNishan Jul 4, 2025
ce8de8c
Update app.vue
MohdNishan Jul 4, 2025
d304a62
Updated Conflicts of Header.vue
MohdNishan Jul 4, 2025
7eb2f12
Updated Conflicts of index.vue
MohdNishan Jul 4, 2025
eab6650
Deleted pages/one.vue
MohdNishan Jul 4, 2025
20fc370
Updated index.vue
MohdNishan Jul 8, 2025
ca7aa4c
Updated [processId].vue
MohdNishan Jul 8, 2025
fe6cc29
Updated index.vue
MohdNishan Jul 9, 2025
55fef09
Updated the handling of bounding box input and complex input
MohdNishan Jul 16, 2025
f5b5dae
Updated
MohdNishan Jul 16, 2025
8b2c785
Merge branch 'zooproject-ui' of https://github.com/MohdNishan/zooproj…
MohdNishan Jul 16, 2025
b77d58c
Updated the input of complext input(providing value) into textarea
MohdNishan Jul 22, 2025
585fce1
Updated pages/processes/[processId].vue
MohdNishan Jul 23, 2025
20b982c
Updated pages/processes/[processId].vue
MohdNishan Jul 23, 2025
211d41c
Updated pages/processes/[processId].vue
MohdNishan Jul 23, 2025
d07bac8
Updated pages/processes/[processId].vue
MohdNishan Jul 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@

<style>
.q-card,
.q-table,
.q-btn,
.q-btn-dropdown,
.q-dialog__inner,
.q-item,
.q-table{
border-radius: 12px !important;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.06);
}
.q-input{
border-radius: 12px !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.q-menu {
border-radius: 12px !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
Expand All @@ -38,5 +45,4 @@
border: 1px solid #ccc;
margin-top: 20px;
}

</style>
1 change: 0 additions & 1 deletion components/layout/default/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,3 @@ onMounted(() => {
<style scoped>

</style>

2 changes: 1 addition & 1 deletion pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,4 @@ const getReadableLinkText = (link: any): string => {


onMounted(fetchLandingAndApiInfo)
</script>
</script>
2 changes: 1 addition & 1 deletion pages/jobs/[jobId].vue
Original file line number Diff line number Diff line change
Expand Up @@ -246,4 +246,4 @@ async function showMapOnGeojson() {
})
}

</script>
</script>
239 changes: 210 additions & 29 deletions pages/processes/[processId].vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { ref, onMounted, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useRuntimeConfig } from '#imports'

const {
params: { processId }
} = useRoute()
Expand All @@ -16,7 +15,7 @@ const outputValues = ref<Record<string, any>>({})
const response = ref(null)
const loading = ref(false)
const jobStatus = ref('')

const preferMode = ref<'respond-async' | 'respond-sync'>('respond-async')
const jsonRequestPreview = ref('')
const showDialog = ref(false)

Expand All @@ -38,6 +37,39 @@ const fetchData = async () => {
if (data.value && data.value.inputs) {
for (const [key, input] of Object.entries(data.value.inputs)) {
console.log(input)
console.log('isComplexInput:', input, isComplexInput(input))

if (
input?.schema?.contentMediaType ||
input?.schema?.mediaType ||
(input?.schema?.oneOf?.some(f => f.contentMediaType))
) {
const supportedFormats = input.schema.oneOf?.map(f => f.contentMediaType) || DEFAULT_SUPPORTED_FORMATS;

inputValues.value[key] = {
mode: 'href',
href: '',
value: '',
format: supportedFormats[0],
availableFormats: supportedFormats
};
continue;
}

// Bounding Box Detection and Initialization
if (
input.schema?.type === 'object' &&
input.schema?.properties?.bbox &&
input.schema?.properties?.crs
) {
inputValues.value[key] = reactive({
bbox: [0, 0, 0, 0],
crs: 'EPSG:4326'
})
continue
}

// Default Init for other types
inputValues.value[key] = input.schema?.default ?? (input.schema?.type === 'number' ? 0 : '')
}
}
Expand Down Expand Up @@ -93,8 +125,28 @@ const convertOutputsToPayload = (outputs: Record<string, any[]>) => {
watch([inputValues, outputValues, subscriberValues], ([newInputs, newOutputs, newSubscribers]) => {
console.log('Outputs changed:', newOutputs)

const formattedInputs: Record<string, any> = {}

for (const [key, val] of Object.entries(newInputs)) {
// If multiple inputs (array)
if (Array.isArray(val)) {
formattedInputs[key] = val.map(v => typeof v === 'object' && 'mode' in v
? v.mode === 'href'
? { href: v.href }
: { value: v.value, format: { mediaType: v.format } }
: v
)
} else if (val && typeof val === 'object' && 'mode' in val) {
formattedInputs[key] = val.mode === 'href'
? { href: val.href }
: { value: val.value, format: { mediaType: val.format } }
} else {
formattedInputs[key] = val
}
}

const payload = {
inputs: newInputs,
inputs: formattedInputs,
outputs: convertOutputsToPayload(newOutputs),
subscriber: {
successUri: newSubscribers.successUri,
Expand Down Expand Up @@ -147,7 +199,8 @@ const submitProcess = async () => {
method: 'POST',
headers: {
Authorization: `Bearer ${authStore.token.access_token}`,
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'Prefer': preferMode.value
},
body: JSON.stringify(payload)
})
Expand All @@ -168,6 +221,23 @@ const isMultipleInput = (input: any) => {
return input.maxOccurs > 1 ? true : false
}

const isBoundingBoxInput = (input: any) => {
return input.schema?.type === 'object' &&
input.schema?.properties?.bbox?.type === 'array' &&
input.schema?.properties?.crs?.type === 'string';
}

const isComplexInput = (input: any) => {
return (
input?.schema &&
(
input.schema.contentMediaType ||
input.schema.mediaType ||
(Array.isArray(input.schema.oneOf) && input.schema.oneOf.some(x => x.contentMediaType))
)
)
}

const addInputField = (inputId: string) => {
if (!Array.isArray(inputValues.value[inputId])) {
inputValues.value[inputId] = [inputValues.value[inputId] || '']
Expand Down Expand Up @@ -242,33 +312,137 @@ const removeInputField = (inputId: string, index: number) => {
</div>

<!-- <div class="text-blue text-bold q-mb-sm">{{ inputId.toUpperCase() }}</div> -->
<div class="q-gutter-sm row items-center">
<q-badge color="grey-3" text-color="black">
<div class="q-gutter-sm">
<q-badge color="grey-3" text-color="black" class="q-mb-sm">
{{ input.schema?.type || 'text' }}
</q-badge>


<q-input
v-if="!input.schema?.enum"
filled
v-model="inputValues[inputId]"
:type="input.schema?.type === 'number' ? 'number' : 'text'"
:label="input.title || inputId"
dense
class="q-ml-sm"
style="flex: 1"
/>
<!-- Complex Input FIRST -->
<template v-if="isComplexInput(input)">
<q-option-group
v-model="inputValues[inputId].mode"
:options="[
{ label: 'Provide URL (href)', value: 'href' },
{ label: 'Provide Value Inline', value: 'value' }
]"
type="radio"
inline
class="q-mb-md"
/>

<q-select
v-else
filled
v-model="inputValues[inputId]"
:options="input.schema.enum"
:label="input.title || inputId"
dense
class="q-ml-sm"
style="flex: 1"
/>
<q-input
v-if="inputValues[inputId].mode === 'href'"
v-model="inputValues[inputId].href"
label="Reference URL (href)"
placeholder="https://example.com/input.json"
filled
dense
/>

<q-banner
v-if="inputValues[inputId].mode === 'href' && inputValues[inputId].availableFormats?.length"
class="bg-grey-2 text-black q-mt-sm"
>
Supported formats: {{ inputValues[inputId].availableFormats.join(', ') }}
</q-banner>

<div v-if="inputValues[inputId].mode === 'value'" class="q-gutter-md">
<q-select
v-model="inputValues[inputId].format"
:options="inputValues[inputId].availableFormats"
label="Content Format"
dense
filled
/>
<q-input
v-model="inputValues[inputId].value"
label="Input Value"
type="textarea"
autogrow
filled
dense
class="resizable-textarea"
/>
</div>
</template>

<!-- Bounding Box Input -->
<template v-else-if="isBoundingBoxInput(input)">
<div class="q-gutter-md">
<div class="row q-gutter-sm">
<q-input
v-for="(coord, idx) in ['minX', 'minY', 'maxX', 'maxY']"
:key="idx"
v-model.number="inputValues[inputId].bbox[idx]"
:label="coord"
type="number"
filled
dense
style="flex: 1"
/>
</div>
<q-select
v-model="inputValues[inputId].crs"
:options="EPSG_CODES"
label="EPSG Code"
filled
dense
class="q-mt-sm"
/>
</div>
</template>

<!-- Multiple input array -->
<template v-else-if="Array.isArray(inputValues[inputId])">
<div v-for="(val, idx) in inputValues[inputId]" :key="idx" class="row items-center q-gutter-sm q-mb-sm">
<q-input
filled
v-model="inputValues[inputId][idx]"
:type="input.schema?.type === 'number' ? 'number' : 'text'"
:label="`${input.title || inputId} ${idx + 1}`"
dense
style="flex: 1"
/>
<q-btn
icon="delete"
round
dense
flat
color="red"
size="sm"
@click="removeInputField(inputId, idx)"
v-if="inputValues[inputId].length > 1"
>
<q-tooltip>Remove</q-tooltip>
</q-btn>
</div>
</template>

<!-- Literal input (no enum) -->
<template v-else-if="!input.schema?.enum">
<q-input
filled
v-model="inputValues[inputId]"
:type="input.schema?.type === 'number' ? 'number' : 'text'"
:label="input.title || inputId"
dense
class="q-ml-sm"
style="flex: 1"
/>
</template>

<!-- Enum input -->
<template v-else>
<q-select
filled
v-model="inputValues[inputId]"
:options="input.schema.enum"
:label="input.title || inputId"
dense
class="q-ml-sm"
style="flex: 1"
/>
</template>
</div>
</q-card>

Expand Down Expand Up @@ -392,7 +566,14 @@ const removeInputField = (inputId: string, index: number) => {
</div>
</q-card>
</div>

<q-select
v-model="preferMode"
:options="['respond-async', 'respond-sync']"
label="Execution Mode"
filled
dense
class="q-mb-md"
/>
<div class="q-mt-md row q-gutter-sm">
<q-btn label="Submit" type="submit" color="primary" />
<q-btn color="primary" outline label="Show JSON Preview" @click="showDialog = true" />
Expand Down Expand Up @@ -448,4 +629,4 @@ const removeInputField = (inputId: string, index: number) => {
</div>
<q-spinner v-else />
</q-page>
</template>
</template>
Loading