<template> <FormTable class="tw-max-w-3xl"> <FormGroup :label="t('noteEditor.title')" :errors="title.errors" :is-saving="title.isSaving"> <template #default="attrs"> <input v-model="title.value" :placeholder="t('noteEditor.titlePlaceholder')" required v-bind="attrs" @blur="title.save()" /> <p v-if="note.slug" class="tw-text-xs tw-text-gray-400 tw-mt-1 tw-mb-0"> {{ t('slug') }}: {{ note.slug }} </p> </template> </FormGroup> <FormGroup :label="t('noteEditor.summary')" :errors="summary.errors" :is-saving="summary.isSaving" > <template #default="attrs"> <textarea ref="summaryEl" v-model="summary.value" class="tw-resize-none tw-overflow-hidden tw-min-h-[3.55rem]" :placeholder="t('noteEditor.summaryPlaceholder')" v-bind="attrs" @blur="summary.save()" /> </template> </FormGroup> <FormGroup :label="t('noteEditor.content')" :errors="content.errors" :is-saving="content.isSaving" > <template #default="attrs"> <textarea ref="contentEl" v-model="content.value" class="tw-resize-none tw-overflow-hidden tw-min-h-[8rem]" rows="6" :placeholder="t('noteEditor.contentPlaceholder')" required v-bind="attrs" @blur="content.save()" /> </template> </FormGroup> <FormGroup :label="t('noteEditor.image')" :errors="imageId.errors" :is-saving="imageId.isSaving" custom-control > <ImagePicker v-model="imageId.value" class="tw-flex-none tw-w-min" /> </FormGroup> <FormGroup :label="t('noteEditor.contributors')" :errors="contributors.errors" :is-saving="contributors.isSaving" > <ComboBoxSimple v-model="contributors.value" :choices="contributors.choices" /> </FormGroup> <FormGroup :label="t('noteEditor.topics')" :errors="topics.errors" :is-saving="topics.isSaving"> <ComboBoxSimple v-model="topics.value" :choices="topics.choices" /> </FormGroup> <FormGroup :label="t('noteEditor.languages')" :errors="languages.errors" :is-saving="languages.isSaving" > <ComboBoxSimple v-model="languages.value" :choices="languages.choices" /> </FormGroup> <FormGroup :label="t('noteEditor.tags')" :errors="tags.errors" :is-saving="tags.isSaving"> <TagInput v-model="tags.value" /> </FormGroup> <FormGroup :label="t('noteEditor.links')" :is-saving="links.isSaving" :errors="getFieldErrors(links.errors, 'links')" :has-error="links.errors.length > 0" custom-control > <ALinkCollectionEditor v-model="links.value" :error-lists="getTreeFieldChildrenErrorsList(links.errors, 'links')" allow-add @save="links.save()" /> </FormGroup> </FormTable> </template> <script lang="ts" setup> import { useTextareaAutosize } from '@vueuse/core' import { computed } from 'vue' import { useI18n } from '@/i18n' import { Note, Show, TimeSlot } from '@/types' import { useHostStore, useLanguageStore, useNoteStore, useTopicStore } from '@/stores' import FormGroup from '@/components/generic/FormGroup.vue' import ImagePicker from '@/components/images/ImagePicker.vue' import TagInput from '@/components/generic/TagInput.vue' import ComboBoxSimple from '@/components/ComboBoxSimple.vue' import { getFieldErrors, getTreeFieldChildrenErrorsList, useAPIObjectFieldCopy, useRelationList, } from '@/form' import FormTable from '@/components/generic/FormTable.vue' import ALinkCollectionEditor from '@/components/generic/ALinkCollectionEditor.vue' defineOptions({ compatConfig: { MODE: 3 } }) const props = defineProps<{ timeslot: TimeSlot show: Show note: Note }>() const { t } = useI18n() const noteStore = useNoteStore() const hostStore = useHostStore() const languageStore = useLanguageStore() const topicStore = useTopicStore() const note = computed(() => props.note) const title = useAPIObjectFieldCopy(noteStore, note, 'title', { debounce: 2 }) const summary = useAPIObjectFieldCopy(noteStore, note, 'summary', { noAutoSave: true }) const content = useAPIObjectFieldCopy(noteStore, note, 'content', { noAutoSave: true }) const tags = useAPIObjectFieldCopy(noteStore, note, 'tags') const imageId = useAPIObjectFieldCopy(noteStore, note, 'imageId', { debounce: 0 }) const links = useAPIObjectFieldCopy(noteStore, note, 'links', { debounce: 2 }) const contributors = useRelationList(noteStore, note, 'contributorIds', hostStore) const languages = useRelationList(noteStore, note, 'languageIds', languageStore) const topics = useRelationList(noteStore, note, 'topicIds', topicStore) const { textarea: summaryEl } = useTextareaAutosize({ watch: () => note.value.summary }) const { textarea: contentEl } = useTextareaAutosize({ watch: () => note.value.content }) </script>