PronounsPage/components/CustomFlagsWidget.vue
Valentyne Stigloher b25afefc49 (fmt)
2024-10-29 10:56:32 +01:00

156 lines
6.2 KiB
Vue

<template>
<div class="form-group">
<draggable
v-model="images"
tag="ul"
handle=".handle"
ghost-class="ghost"
class="list-unstyled"
item-key="value"
@end="$emit('update:modelValue', images)"
>
<template #item="{ element }">
<li class="mb-4">
<div class="input-group mb-1">
<button class="btn btn-light border handle" type="button" :aria-label="$t('table.sort')">
<Icon v="bars" />
</button>
<div class="d-flex flex-grow-1 flex-column">
<div class="d-flex">
<ImageThumb :id="element.value" small-size="flag" big-size="flag" size="2.4em" />
<input
v-model="element.name"
type="text"
class="form-control"
:placeholder="$t('profile.flagsCustomForm.label')"
required
:maxlength="maxLength"
@keyup="update"
@change="update"
>
</div>
<div>
<input
v-model="element.description"
type="text"
class="form-control form-control-sm"
:placeholder="$t('profile.flagsCustomForm.description')"
maxlength="512"
@keyup="update"
@change="update"
>
</div>
<div>
<input
v-model="element.alt"
type="text"
class="form-control form-control-sm"
:placeholder="$t('profile.flagsCustomForm.alt')"
maxlength="512"
@keyup="update"
@change="update"
>
</div>
<div>
<input
v-model="element.link"
type="url"
class="form-control form-control-sm"
:placeholder="$t('profile.flagsCustomForm.link')"
@keyup="update"
@change="update"
>
<p v-if="element.link && !isValidLink(element.link)" class="small text-danger m-1">
<Icon v="exclamation-triangle" />
<span class="ml-1">{{ $t('crud.validation.invalidLink') }}</span>
</p>
</div>
</div>
<button class="btn btn-outline-danger" type="button" :aria-label="$t('crud.remove')" @click.prevent="removeFile(element.value)">
<Icon v="times" />
</button>
</div>
</li>
</template>
<template #footer>
<li>
<ImageUploader
v-if="maxitems === null || modelValue.length < maxitems"
multiple
:name="name"
form
:sizes="sizes"
@uploaded="addFiles"
/>
<div v-if="images.length" class="alert alert-info small mt-3 mb-0">
<p>
<Icon v="info-circle" />
<T>profile.flagsCustomForm.altExample</T><T>quotation.colon</T>
</p>
<p class="simple">
<Flag img="/flags/Progress Pride_.png" name="" :alt="$t('flags_alt.Progress_Pride_')" />
<T>flags_alt.Progress_Pride_</T>
</p>
</div>
</li>
</template>
<li v-if="maxitems && modelValue.length > maxitems" class="alert alert-danger">
<Icon v="exclamation-triangle" />
<T :params="{ maxlength: maxitems }" class="ml-1">crud.validation.listMaxLength</T>
</li>
</draggable>
</div>
</template>
<script>
import draggable from 'vuedraggable';
import useDialogue from '../composables/useDialogue.ts';
import { curry, isValidLink } from '../src/helpers.ts';
export default {
components: {
draggable,
},
props: {
modelValue: { required: true, type: Array },
name: { default: 'images' },
maxLength: { default: 24 },
sizes: { default: 'all' },
maxitems: { default: null, type: Number },
},
emits: ['update:modelValue'],
setup() {
return {
dialogue: useDialogue(),
};
},
data() {
return {
images: this.modelValue,
curry,
isValidLink,
};
},
watch: {
modelValue() {
this.images = this.modelValue;
},
},
methods: {
addFiles(fileIds) {
this.$emit('update:modelValue', [...this.images, ...fileIds.map((id) => {
return { value: id, name: '', description: '', link: '', alt: '' };
})]);
},
async removeFile(id) {
await this.dialogue.confirm(this.$t('crud.removeConfirm'), 'danger');
this.$emit('update:modelValue', this.images.filter((i) => i.value !== id));
},
update() {
this.$emit('update:modelValue', this.images);
},
},
};
</script>