Files
cloudron-box/dashboard/src/components/EditableField.vue
2025-12-01 11:50:19 +01:00

79 lines
2.6 KiB
Vue

<script setup>
import { ref, watch, nextTick, useTemplateRef } from 'vue';
import { Button, FormGroup, TextInput } from '@cloudron/pankow';
import { marked } from 'marked';
const props = defineProps({
label: { type: String, required: true },
helpUrl: { type: String, required: false },
value: { type: String, required: true },
disabled: { type: Boolean, default: false },
required: { type: Boolean, default: false },
saving: { type: Boolean, default: false },
multiline: { type: Boolean, default: false },
markdown: { type: Boolean, default: false },
rows: { type: Number, default: 2 },
maxlength: { type: Number, default: -1 },
});
const emit = defineEmits(['save']);
const editing = ref(false);
const draftValue = ref(props.value);
const textInput = useTemplateRef('textInput');
watch(() => props.value, (newVal) => {
if (!editing.value) draftValue.value = newVal;
});
watch(() => props.saving, (isSaving) => {
if (!isSaving && editing.value) {
editing.value = false;
}
});
function startEdit() {
if (props.disabled) return;
editing.value = true;
draftValue.value = props.value;
nextTick(() => {
textInput.value.focus();
});
}
function save() {
if (props.required && !draftValue.value) return;
emit('save', draftValue.value);
}
function cancel() {
editing.value = false;
}
</script>
<template>
<FormGroup>
<label>{{ label }} <sup v-if="helpUrl"><a :href="helpUrl" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
<div v-if="editing" style="display: flex; align-items: center; gap: 6px">
<TextInput v-if="!multiline" ref="textInput" v-model="draftValue" @keydown.enter="save()" :disabled="saving" :required="required ? true : null" :maxlength="maxlength === -1 ? null : maxlength"/>
<textarea v-else ref="textInput" :rows="rows" cols="80" v-model="draftValue" :disabled="saving" :required="required ? true : null" :maxlength="maxlength === -1 ? null : maxlength"></textarea>
<Button tool @click="save" :disabled="saving || (required && !draftValue)">{{ $t('main.dialog.save') }}</Button>
<Button tool plain secondary @click="cancel" :disabled="saving">{{ $t('main.dialog.cancel') }}</Button>
</div>
<div v-else>
<div v-if="markdown" v-html="marked.parseInline(value)"></div>
<div v-else>{{ value }}</div>
</div>
</FormGroup>
<div>
<div v-if="editing" style="display: flex; align-items: center; gap: 10px">
</div>
<div v-else>
<Button tool plain @click="startEdit" v-if="!disabled">{{ $t('main.dialog.edit') }}</Button>
</div>
</div>
</template>