fix(front): add a required attribute to the text editor and show error message if text empty on blur
Also improve text editor borders Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
ef20585f8c
commit
ba66874cc3
|
@ -32,6 +32,7 @@
|
|||
v-if="currentActor"
|
||||
:currentActor="currentActor"
|
||||
:placeholder="t('Write a new message')"
|
||||
:required="true"
|
||||
/>
|
||||
<o-notification
|
||||
class="my-2"
|
||||
|
|
|
@ -217,7 +217,15 @@
|
|||
</button>
|
||||
</bubble-menu>
|
||||
|
||||
<editor-content class="editor__content" :editor="editor" v-if="editor" />
|
||||
<editor-content
|
||||
class="editor__content"
|
||||
:class="{ editorErrorStatus }"
|
||||
:editor="editor"
|
||||
v-if="editor"
|
||||
/>
|
||||
<p v-if="editorErrorMessage" class="text-sm text-mbz-danger">
|
||||
{{ editorErrorMessage }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -249,7 +257,7 @@ import Underline from "@tiptap/extension-underline";
|
|||
import Link from "@tiptap/extension-link";
|
||||
import { AutoDir } from "./Editor/Autodir";
|
||||
// import sanitizeHtml from "sanitize-html";
|
||||
import { computed, inject, onBeforeUnmount, watch } from "vue";
|
||||
import { computed, inject, onBeforeUnmount, ref, watch } from "vue";
|
||||
import { Dialog } from "@/plugins/dialog";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
|
@ -279,11 +287,13 @@ const props = withDefaults(
|
|||
currentActor: IPerson;
|
||||
placeholder?: string;
|
||||
headingLevel?: Level[];
|
||||
required?: boolean;
|
||||
}>(),
|
||||
{
|
||||
mode: "description",
|
||||
maxSize: 100_000_000,
|
||||
headingLevel: () => [3, 4, 5],
|
||||
required: false,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -333,7 +343,7 @@ const editor = useEditor({
|
|||
"aria-label": ariaLabel.value ?? "",
|
||||
role: "textbox",
|
||||
class:
|
||||
"prose dark:prose-invert prose-sm lg:prose-lg xl:prose-xl bg-zinc-50 dark:bg-zinc-700 focus:outline-none !max-w-full",
|
||||
"prose dark:prose-invert prose-sm lg:prose-lg xl:prose-xl bg-white dark:bg-zinc-700 focus:outline-none !max-w-full",
|
||||
},
|
||||
transformPastedHTML: transformPastedHTML,
|
||||
},
|
||||
|
@ -373,6 +383,13 @@ const editor = useEditor({
|
|||
onUpdate: () => {
|
||||
emit("update:modelValue", editor.value?.getHTML());
|
||||
},
|
||||
onBlur: () => {
|
||||
checkEditorEmpty();
|
||||
},
|
||||
onFocus: () => {
|
||||
editorErrorStatus.value = false;
|
||||
editorErrorMessage.value = "";
|
||||
},
|
||||
});
|
||||
|
||||
watch(value, (val: string) => {
|
||||
|
@ -470,6 +487,18 @@ defineExpose({ replyToComment, focus });
|
|||
onBeforeUnmount(() => {
|
||||
editor.value?.destroy();
|
||||
});
|
||||
|
||||
const editorErrorStatus = ref(false);
|
||||
const editorErrorMessage = ref("");
|
||||
|
||||
const isEmpty = computed(
|
||||
() => props.required === true && editor.value?.isEmpty === true
|
||||
);
|
||||
|
||||
const checkEditorEmpty = () => {
|
||||
editorErrorStatus.value = isEmpty.value;
|
||||
editorErrorMessage.value = isEmpty.value ? t("You need to enter a text") : "";
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@use "@/styles/_mixins" as *;
|
||||
|
@ -525,7 +554,6 @@ onBeforeUnmount(() => {
|
|||
min-height: 2.5rem;
|
||||
box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dbdbdb;
|
||||
padding: 12px 6px;
|
||||
|
||||
&:focus {
|
||||
|
@ -655,4 +683,15 @@ onBeforeUnmount(() => {
|
|||
.mention[data-id] {
|
||||
@apply inline-block border border-zinc-600 dark:border-zinc-300 rounded py-0.5 px-1;
|
||||
}
|
||||
|
||||
.editor__content {
|
||||
@apply border focus:border-[#2563eb] rounded border-[#6b7280];
|
||||
}
|
||||
|
||||
.editorErrorStatus {
|
||||
@apply border-red-500;
|
||||
}
|
||||
.editor__content p.is-editor-empty:first-child::before {
|
||||
@apply text-slate-300;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1642,5 +1642,6 @@
|
|||
"Visit {instance_domain}": "Visit {instance_domain}",
|
||||
"Software details: {software_details}": "Software details: {software_details}",
|
||||
"Only instances with an application actor can be followed": "Only instances with an application actor can be followed",
|
||||
"Domain or instance name": "Domain or instance name"
|
||||
"Domain or instance name": "Domain or instance name",
|
||||
"You need to enter a text": "You need to enter a text"
|
||||
}
|
|
@ -1636,5 +1636,6 @@
|
|||
"Visit {instance_domain}": "Visiter {instance_domain}",
|
||||
"Software details: {software_details}": "Détails du logiciel : {software_details}",
|
||||
"Only instances with an application actor can be followed": "Seules les instances avec un acteur application peuvent être suivies",
|
||||
"Domain or instance name": "Domaine ou nom de l'instance"
|
||||
"Domain or instance name": "Domaine ou nom de l'instance",
|
||||
"You need to enter a text": "Vous devez entrer un texte"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue