blob: eeab0e3d528ccd9d06e1dc13eeb71553783e5aef [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>
<div>
<div class="input-row">
<a-form-item no-style>
<a-input v-model:value="newKey" :placeholder="$t('label.key')" class="input-field" />
</a-form-item>
<a-form-item no-style>
<a-input v-model:value="newValue" :placeholder="$t('label.value')" class="input-field" />
</a-form-item>
<a-button type="primary" class="add-button" @click="addEntry" :disabled="!newKey || !newValue">
Add
</a-button>
</div>
<a-table
:columns="columns"
:dataSource="tableData"
rowKey="key"
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.key)" />
</div>
</template>
</template>
<template v-else-if="record.editing">
<a-form-item no-style>
<a-input v-model:value="editBuffer[column.key]" />
</a-form-item>
</template>
<template v-else>
{{ record[column.key] }}
</template>
</template>
</a-table>
</div>
</template>
<script>
import TooltipButton from '@/components/widgets/TooltipButton'
export default {
name: 'DetailsInput',
components: { TooltipButton },
props: {
value: {
type: Object,
default: () => ({})
},
showTableHeaders: {
type: Boolean,
default: true
}
},
data () {
return {
columns: [
{ title: this.$t('label.key'), dataIndex: 'key', key: 'key', width: '40%' },
{ title: this.$t('label.value'), dataIndex: 'value', key: 'value', width: '40%' },
{ title: this.$t('label.actions'), key: 'actions', width: '20%' }
],
newKey: '',
newValue: '',
tableData: [],
editBuffer: {}
}
},
created () {
if (this.value && typeof this.value === 'object') {
this.tableData = this.mapToTableData(this.value)
}
},
watch: {
value (newVal) {
this.tableData = this.mapToTableData(newVal)
}
},
emits: ['update:value'],
methods: {
mapToTableData (obj) {
return Object.entries(obj || {}).map(([key, value]) => ({
key,
value,
editing: false
}))
},
addEntry () {
if (!this.newKey || !this.newValue) return
const existingIndex = this.tableData.findIndex(row => row.key === this.newKey)
if (existingIndex !== -1) {
this.tableData[existingIndex].value = this.newValue
} else {
this.tableData.push({ key: this.newKey, value: this.newValue, editing: false })
}
this.updateData()
this.newKey = ''
this.newValue = ''
},
removeEntry (key) {
this.tableData = this.tableData.filter(item => item.key !== key)
this.updateData()
},
editRow (record) {
this.editBuffer = {
key: record.key,
value: record.value
}
record.editing = true
},
cancelEdit (record) {
record.editing = false
this.editBuffer = {}
},
saveEdit (record) {
record.key = this.editBuffer.key
record.value = this.editBuffer.value
record.editing = false
this.updateData()
},
updateData () {
const obj = {}
this.tableData.forEach(({ key, value }) => {
obj[key] = value
})
this.$emit('update:value', obj)
}
}
}
</script>
<style lang="css" scoped>
.input-row {
display: flex;
gap: 8px;
margin-bottom: 16px;
}
.input-field {
flex: 1; /* each takes half of the remaining 80% */
}
.add-button {
width: 20%;
min-width: 100px; /* optional: prevents it from getting too narrow */
}
.table {
width: 100%;
}
.flex-gap {
display: flex;
gap: 8px;
}
</style>