blob: f77b0471eaa2fae88f39b491167bcb7c04a24118 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
<template>
<a-card>
<a-row :gutter="[16, 8]">
<a-col :span="18">
<a-row :gutter="[16, 8]">
<a-col :span="18">
<a-form-item no-style>
<tooltip-label :title="$t('label.name')" />
<a-input
v-model:value="newParam.name"
:placeholder="$t('label.name')"
class="input-field"
/>
</a-form-item>
</a-col>
<a-col :span="6" style="display: flex; align-items: flex-end;">
<a-form-item no-style>
<a-checkbox
v-model:checked="newParam.required"
class="required-checkbox"
>
Required
</a-checkbox>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item no-style>
<tooltip-label :title="$t('label.type')" />
<a-select
v-model:value="newParam.type"
:placeholder="$t('label.type')"
class="input-field"
@change="onNewParamTypeChange"
>
<a-select-option
v-for="t in types"
:key="t"
:value="t"
>
{{ t }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item no-style>
<tooltip-label :title="$t('label.validationformat')" :tooltip="$t('message.desc.validationformat')" />
<a-select
:disabled="!['NUMBER', 'STRING'].includes(newParam.type)"
v-model:value="newParam.validationformat"
:placeholder="$t('message.desc.validationformat')"
class="input-field"
>
<a-select-option
v-for="t in newParamFormats"
:key="t"
:value="t"
>
{{ t }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item no-style>
<tooltip-label :title="$t('label.valueoptions')" :tooltip="$t('message.desc.valueoptions')" />
<a-input
:disabled="!['NUMBER', 'STRING'].includes(newParam.type)"
v-model:value="newParam.valueoptions"
:placeholder="$t('message.desc.valueoptions')"
class="input-field"
/>
</a-form-item>
</a-col>
</a-row>
</a-col>
<a-col :span="6" style="display: flex; align-items: flex-end; justify-content: center;">
<a-button
type="primary"
class="add-button"
@click="addEntry"
:disabled="!newParam.name || !newParam.type"
>
Add
</a-button>
</a-col>
</a-row>
<a-table
:columns="columns"
:dataSource="tableData"
rowKey="name"
size="small"
:pagination="false"
:showHeader="showTableHeaders"
class="table"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'actions'">
<template v-if="record.editing">
<div class="flex-gap">
<tooltip-button :tooltip="$t('label.ok')" icon="check-outlined" @onClick="saveEdit(record)" />
<tooltip-button :tooltip="$t('label.cancel')" icon="close-outlined" @onClick="cancelEdit(record)" />
</div>
</template>
<template v-else>
<div class="flex-gap">
<tooltip-button :tooltip="$t('label.edit')" icon="edit-outlined" @onClick="editRow(record)" />
<tooltip-button type="danger" :tooltip="$t('label.remove')" icon="delete-outlined" @onClick="removeEntry(record.name)" />
</div>
</template>
</template>
<template v-else-if="record.editing">
<a-form-item no-style>
<a-input v-if="column.key === 'name'" v-model:value="editBuffer.name" />
</a-form-item>
<a-form-item no-style>
<a-select v-if="column.key === 'type'" v-model:value="editBuffer.type" @change="onEditBufferTypeChange">
<a-select-option v-for="t in types" :key="t" :value="t">{{ t }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item no-style>
<a-select v-if="column.key === 'validationformat'" :disabled="!['NUMBER', 'STRING'].includes(editBuffer.type)" v-model:value="editBuffer.validationformat">
<a-select-option v-for="t in editBufferFormats" :key="t" :value="t">{{ t }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item no-style>
<a-input v-if="column.key === 'valueoptions'" :disabled="!['NUMBER', 'STRING'].includes(editBuffer.type)" v-model:value="editBuffer.valueoptions" />
</a-form-item>
<a-form-item no-style>
<a-checkbox v-if="column.key === 'required'" v-model:checked="editBuffer.required" />
</a-form-item>
</template>
<template v-else>
<template v-if="column.key === 'required'">{{ record.required ? 'Yes' : 'No' }}</template>
<template v-else-if="column.key === 'valueoptions'">
{{ Array.isArray(record.valueoptions) ? record.valueoptions.join(',') : record.valueoptions }}
</template>
<template v-else>{{ record[column.key] }}</template>
</template>
</template>
</a-table>
</a-card>
</template>
<script>
import TooltipButton from '@/components/widgets/TooltipButton'
import TooltipLabel from '@/components/widgets/TooltipLabel'
export default {
name: 'ParametersInput',
components: {
TooltipButton,
TooltipLabel
},
props: {
value: {
type: Array,
default: () => []
},
showTableHeaders: {
type: Boolean,
default: true
}
},
data () {
return {
newParam: {},
columns: [
{ title: this.$t('label.name'), dataIndex: 'name', key: 'name', width: '20%' },
{ title: this.$t('label.type'), dataIndex: 'type', key: 'type', width: '15%' },
{ title: this.$t('label.validationformat'), dataIndex: 'validationformat', key: 'validationformat', width: '15%' },
{ title: this.$t('label.valueoptions'), dataIndex: 'valueoptions', key: 'valueoptions', width: '25%' },
{ title: this.$t('label.required'), dataIndex: 'required', key: 'required', width: '10%' },
{ title: this.$t('label.actions'), key: 'actions', width: '15%' }
],
tableData: [],
editBuffer: null
}
},
watch: {
value: {
immediate: true,
handler (newVal) {
this.tableData = (newVal || []).map(p => ({
...p,
editing: false
}))
}
}
},
emits: ['update:value'],
computed: {
types () {
return [
'BOOLEAN',
'DATE',
'NUMBER',
'STRING'
]
},
newParamFormats () {
return this.getFormatOptions(this.newParam?.type)
},
editBufferFormats () {
return this.getFormatOptions(this.editBuffer?.type)
}
},
methods: {
getFormatOptions (type) {
const formats = ['NONE']
if (type === 'STRING') {
formats.push('EMAIL', 'PASSWORD', 'URL', 'UUID')
} else if (type === 'NUMBER') {
formats.push('DECIMAL')
}
return formats
},
resetFormatAndOptions (obj) {
delete obj.validationformat
delete obj.valueoptions
},
onNewParamTypeChange () {
this.resetFormatAndOptions(this.newParam)
},
onEditBufferTypeChange () {
this.resetFormatAndOptions(this.editBuffer)
},
addEntry () {
const existingIndex = this.tableData.findIndex(row => row.name === this.newParam.name)
if (existingIndex !== -1) {
this.tableData[existingIndex] = { ...this.newParam }
} else {
this.tableData.push({ ...this.newParam, editing: false })
}
this.updateData()
this.newParam = {}
},
removeEntry (name) {
this.tableData = this.tableData.filter(item => item.name !== name)
this.updateData()
},
editRow (record) {
this.editBuffer = { ...record }
if (Array.isArray(this.editBuffer.valueoptions)) {
this.editBuffer.valueoptions = this.editBuffer.valueoptions.join(',')
}
record.editing = true
},
cancelEdit (record) {
record.editing = false
this.editBuffer = {}
},
saveEdit (record) {
if (!this.editBuffer) return
Object.assign(record, this.editBuffer)
if (!this.editBuffer.validationformat) {
delete record.validationformat
}
if (!this.editBuffer.valueoptions) {
delete record.valueoptions
}
record.editing = false
this.updateData()
this.editBuffer = {}
},
updateData () {
const data = this.tableData.map(({ name, type, validationformat, valueoptions, required }) => ({
name,
type,
validationformat,
valueoptions: Array.isArray(valueoptions) ? valueoptions.join(',') : valueoptions,
required
}))
this.$emit('update:value', data)
}
}
}
</script>
<style scoped>
.input-row {
display: grid;
grid-template-columns: 1fr auto; /* First column flexible, second column auto-sized */
grid-template-rows: auto auto auto;
gap: 8px 16px; /* row-gap and column-gap */
align-items: center;
}
.grid-cell {
display: flex;
flex-direction: column;
gap: 4px;
}
.input-field {
width: 100%;
}
.add-button {
white-space: nowrap;
}
.table {
margin-top: 10px;
width: 100%;
}
.flex-gap {
display: flex;
gap: 8px;
}
</style>