feat: Add plain-text editor for non-rich content channels (#13058)
# Pull Request Template ## Description This PR restores the plain text editor for all channels except Website, Email, and API. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
This commit is contained in:
parent
df4c8cf58b
commit
696564863c
@ -200,6 +200,7 @@ const setSelectedContact = async ({ value, action, ...rest }) => {
|
|||||||
|
|
||||||
const handleInboxAction = ({ value, action, ...rest }) => {
|
const handleInboxAction = ({ value, action, ...rest }) => {
|
||||||
v$.value.$reset();
|
v$.value.$reset();
|
||||||
|
state.message = '';
|
||||||
emit('updateTargetInbox', { ...rest });
|
emit('updateTargetInbox', { ...rest });
|
||||||
showInboxesDropdown.value = false;
|
showInboxesDropdown.value = false;
|
||||||
state.attachedFiles = [];
|
state.attachedFiles = [];
|
||||||
@ -220,6 +221,7 @@ const removeSignatureFromMessage = () => {
|
|||||||
const removeTargetInbox = value => {
|
const removeTargetInbox = value => {
|
||||||
v$.value.$reset();
|
v$.value.$reset();
|
||||||
removeSignatureFromMessage();
|
removeSignatureFromMessage();
|
||||||
|
state.message = '';
|
||||||
emit('updateTargetInbox', value);
|
emit('updateTargetInbox', value);
|
||||||
state.attachedFiles = [];
|
state.attachedFiles = [];
|
||||||
};
|
};
|
||||||
@ -227,6 +229,7 @@ const removeTargetInbox = value => {
|
|||||||
const clearSelectedContact = () => {
|
const clearSelectedContact = () => {
|
||||||
removeSignatureFromMessage();
|
removeSignatureFromMessage();
|
||||||
emit('clearSelectedContact');
|
emit('clearSelectedContact');
|
||||||
|
state.message = '';
|
||||||
state.attachedFiles = [];
|
state.attachedFiles = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import Editor from 'dashboard/components-next/Editor/Editor.vue';
|
import Editor from 'dashboard/components-next/Editor/Editor.vue';
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
hasErrors: { type: Boolean, default: false },
|
hasErrors: { type: Boolean, default: false },
|
||||||
hasAttachments: { type: Boolean, default: false },
|
hasAttachments: { type: Boolean, default: false },
|
||||||
sendWithSignature: { type: Boolean, default: false },
|
sendWithSignature: { type: Boolean, default: false },
|
||||||
@ -12,6 +13,8 @@ defineProps({
|
|||||||
medium: { type: String, default: '' },
|
medium: { type: String, default: '' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const editorKey = computed(() => `editor-${props.channelType}-${props.medium}`);
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const modelValue = defineModel({
|
const modelValue = defineModel({
|
||||||
@ -23,6 +26,7 @@ const modelValue = defineModel({
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex-1 h-full" :class="[!hasAttachments && 'min-h-[200px]']">
|
<div class="flex-1 h-full" :class="[!hasAttachments && 'min-h-[200px]']">
|
||||||
<Editor
|
<Editor
|
||||||
|
:key="editorKey"
|
||||||
v-model="modelValue"
|
v-model="modelValue"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
t('COMPOSE_NEW_CONVERSATION.FORM.MESSAGE_EDITOR.PLACEHOLDER')
|
t('COMPOSE_NEW_CONVERSATION.FORM.MESSAGE_EDITOR.PLACEHOLDER')
|
||||||
|
|||||||
@ -7,7 +7,9 @@ import { useTrack } from 'dashboard/composables';
|
|||||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
||||||
|
|
||||||
|
import CannedResponse from './CannedResponse.vue';
|
||||||
import ReplyToMessage from './ReplyToMessage.vue';
|
import ReplyToMessage from './ReplyToMessage.vue';
|
||||||
|
import ResizableTextArea from 'shared/components/ResizableTextArea.vue';
|
||||||
import AttachmentPreview from 'dashboard/components/widgets/AttachmentsPreview.vue';
|
import AttachmentPreview from 'dashboard/components/widgets/AttachmentsPreview.vue';
|
||||||
import ReplyTopPanel from 'dashboard/components/widgets/WootWriter/ReplyTopPanel.vue';
|
import ReplyTopPanel from 'dashboard/components/widgets/WootWriter/ReplyTopPanel.vue';
|
||||||
import ReplyEmailHead from './ReplyEmailHead.vue';
|
import ReplyEmailHead from './ReplyEmailHead.vue';
|
||||||
@ -44,6 +46,7 @@ import {
|
|||||||
appendSignature,
|
appendSignature,
|
||||||
removeSignature,
|
removeSignature,
|
||||||
getEffectiveChannelType,
|
getEffectiveChannelType,
|
||||||
|
extractTextFromMarkdown,
|
||||||
} from 'dashboard/helper/editorHelper';
|
} from 'dashboard/helper/editorHelper';
|
||||||
|
|
||||||
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
||||||
@ -69,6 +72,8 @@ export default {
|
|||||||
WhatsappTemplates,
|
WhatsappTemplates,
|
||||||
WootMessageEditor,
|
WootMessageEditor,
|
||||||
QuotedEmailPreview,
|
QuotedEmailPreview,
|
||||||
|
ResizableTextArea,
|
||||||
|
CannedResponse,
|
||||||
},
|
},
|
||||||
mixins: [inboxMixin, fileUploadMixin, keyboardEventListenerMixins],
|
mixins: [inboxMixin, fileUploadMixin, keyboardEventListenerMixins],
|
||||||
props: {
|
props: {
|
||||||
@ -109,6 +114,8 @@ export default {
|
|||||||
recordingAudioState: '',
|
recordingAudioState: '',
|
||||||
recordingAudioDurationText: '',
|
recordingAudioDurationText: '',
|
||||||
replyType: REPLY_EDITOR_MODES.REPLY,
|
replyType: REPLY_EDITOR_MODES.REPLY,
|
||||||
|
mentionSearchKey: '',
|
||||||
|
hasSlashCommand: false,
|
||||||
bccEmails: '',
|
bccEmails: '',
|
||||||
ccEmails: '',
|
ccEmails: '',
|
||||||
toEmails: '',
|
toEmails: '',
|
||||||
@ -137,9 +144,12 @@ export default {
|
|||||||
isFeatureEnabledonAccount: 'accounts/isFeatureEnabledonAccount',
|
isFeatureEnabledonAccount: 'accounts/isFeatureEnabledonAccount',
|
||||||
}),
|
}),
|
||||||
currentContact() {
|
currentContact() {
|
||||||
return this.$store.getters['contacts/getContact'](
|
const senderId = this.currentChat?.meta?.sender?.id;
|
||||||
this.currentChat.meta.sender.id
|
if (!senderId) return {};
|
||||||
);
|
return this.$store.getters['contacts/getContact'](senderId);
|
||||||
|
},
|
||||||
|
isRichEditorEnabled() {
|
||||||
|
return this.isAWebWidgetInbox || this.isAnEmailChannel || this.isAPIInbox;
|
||||||
},
|
},
|
||||||
shouldShowReplyToMessage() {
|
shouldShowReplyToMessage() {
|
||||||
return (
|
return (
|
||||||
@ -396,6 +406,26 @@ export default {
|
|||||||
!!this.quotedEmailText
|
!!this.quotedEmailText
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
showRichContentEditor() {
|
||||||
|
if (this.isOnPrivateNote || this.isRichEditorEnabled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isAPIInbox) {
|
||||||
|
const {
|
||||||
|
display_rich_content_editor: displayRichContentEditor = false,
|
||||||
|
} = this.uiSettings;
|
||||||
|
return displayRichContentEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
// ensure that the signature is plain text depending on `showRichContentEditor`
|
||||||
|
signatureToApply() {
|
||||||
|
return this.showRichContentEditor
|
||||||
|
? this.messageSignature
|
||||||
|
: extractTextFromMarkdown(this.messageSignature);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
currentChat(conversation, oldConversation) {
|
currentChat(conversation, oldConversation) {
|
||||||
@ -438,7 +468,25 @@ export default {
|
|||||||
this.resetRecorderAndClearAttachments();
|
this.resetRecorderAndClearAttachments();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
message() {
|
message(updatedMessage) {
|
||||||
|
// Check if the message starts with a slash.
|
||||||
|
const bodyWithoutSignature = removeSignature(
|
||||||
|
updatedMessage,
|
||||||
|
this.signatureToApply
|
||||||
|
);
|
||||||
|
const startsWithSlash = bodyWithoutSignature.startsWith('/');
|
||||||
|
|
||||||
|
// Determine if the user is potentially typing a slash command.
|
||||||
|
// This is true if the message starts with a slash and the rich content editor is not active.
|
||||||
|
this.hasSlashCommand = startsWithSlash && !this.showRichContentEditor;
|
||||||
|
this.showMentions = this.hasSlashCommand;
|
||||||
|
|
||||||
|
// If a slash command is active, extract the command text after the slash.
|
||||||
|
// If not, reset the mentionSearchKey.
|
||||||
|
this.mentionSearchKey = this.hasSlashCommand
|
||||||
|
? bodyWithoutSignature.substring(1)
|
||||||
|
: '';
|
||||||
|
|
||||||
// Autosave the current message draft.
|
// Autosave the current message draft.
|
||||||
this.doAutoSaveDraft();
|
this.doAutoSaveDraft();
|
||||||
},
|
},
|
||||||
@ -488,14 +536,20 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
handleInsert(article) {
|
handleInsert(article) {
|
||||||
const { url, title } = article;
|
const { url, title } = article;
|
||||||
// Removing empty lines from the title
|
if (this.isRichEditorEnabled) {
|
||||||
const lines = title.split('\n');
|
// Removing empty lines from the title
|
||||||
const nonEmptyLines = lines.filter(line => line.trim() !== '');
|
const lines = title.split('\n');
|
||||||
const filteredMarkdown = nonEmptyLines.join(' ');
|
const nonEmptyLines = lines.filter(line => line.trim() !== '');
|
||||||
emitter.emit(
|
const filteredMarkdown = nonEmptyLines.join(' ');
|
||||||
BUS_EVENTS.INSERT_INTO_RICH_EDITOR,
|
emitter.emit(
|
||||||
`[${filteredMarkdown}](${url})`
|
BUS_EVENTS.INSERT_INTO_RICH_EDITOR,
|
||||||
);
|
`[${filteredMarkdown}](${url})`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.addIntoEditor(
|
||||||
|
`${this.$t('CONVERSATION.REPLYBOX.INSERT_READ_MORE')} ${url}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
useTrack(CONVERSATION_EVENTS.INSERT_ARTICLE_LINK);
|
useTrack(CONVERSATION_EVENTS.INSERT_ARTICLE_LINK);
|
||||||
},
|
},
|
||||||
@ -564,14 +618,26 @@ export default {
|
|||||||
if (this.isPrivate) {
|
if (this.isPrivate) {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
if (this.showRichContentEditor) {
|
||||||
const effectiveChannelType = getEffectiveChannelType(
|
const effectiveChannelType = getEffectiveChannelType(
|
||||||
this.channelType,
|
this.channelType,
|
||||||
this.inbox?.medium || ''
|
this.inbox?.medium || ''
|
||||||
);
|
);
|
||||||
|
return this.sendWithSignature
|
||||||
|
? appendSignature(
|
||||||
|
message,
|
||||||
|
this.messageSignature,
|
||||||
|
effectiveChannelType
|
||||||
|
)
|
||||||
|
: removeSignature(
|
||||||
|
message,
|
||||||
|
this.messageSignature,
|
||||||
|
effectiveChannelType
|
||||||
|
);
|
||||||
|
}
|
||||||
return this.sendWithSignature
|
return this.sendWithSignature
|
||||||
? appendSignature(message, this.messageSignature, effectiveChannelType)
|
? appendSignature(message, this.signatureToApply)
|
||||||
: removeSignature(message, this.messageSignature, effectiveChannelType);
|
: removeSignature(message, this.signatureToApply);
|
||||||
},
|
},
|
||||||
removeFromDraft() {
|
removeFromDraft() {
|
||||||
if (this.conversationIdByRoute) {
|
if (this.conversationIdByRoute) {
|
||||||
@ -587,6 +653,7 @@ export default {
|
|||||||
Escape: {
|
Escape: {
|
||||||
action: () => {
|
action: () => {
|
||||||
this.hideEmojiPicker();
|
this.hideEmojiPicker();
|
||||||
|
this.hideMentions();
|
||||||
},
|
},
|
||||||
allowOnFocusedInput: true,
|
allowOnFocusedInput: true,
|
||||||
},
|
},
|
||||||
@ -629,6 +696,9 @@ export default {
|
|||||||
},
|
},
|
||||||
onPaste(e) {
|
onPaste(e) {
|
||||||
const data = e.clipboardData.files;
|
const data = e.clipboardData.files;
|
||||||
|
if (!this.showRichContentEditor && data.length !== 0) {
|
||||||
|
this.$refs.messageInput.$el.blur();
|
||||||
|
}
|
||||||
if (!data.length || !data[0]) {
|
if (!data.length || !data[0]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -762,15 +832,19 @@ export default {
|
|||||||
// if signature is enabled, append it to the message
|
// if signature is enabled, append it to the message
|
||||||
// appendSignature ensures that the signature is not duplicated
|
// appendSignature ensures that the signature is not duplicated
|
||||||
// so we don't need to check if the signature is already present
|
// so we don't need to check if the signature is already present
|
||||||
const effectiveChannelType = getEffectiveChannelType(
|
if (this.showRichContentEditor) {
|
||||||
this.channelType,
|
const effectiveChannelType = getEffectiveChannelType(
|
||||||
this.inbox?.medium || ''
|
this.channelType,
|
||||||
);
|
this.inbox?.medium || ''
|
||||||
message = appendSignature(
|
);
|
||||||
message,
|
message = appendSignature(
|
||||||
this.messageSignature,
|
message,
|
||||||
effectiveChannelType
|
this.messageSignature,
|
||||||
);
|
effectiveChannelType
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = appendSignature(message, this.signatureToApply);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedMessage = replaceVariablesInMessage({
|
const updatedMessage = replaceVariablesInMessage({
|
||||||
@ -794,30 +868,52 @@ export default {
|
|||||||
});
|
});
|
||||||
if (canReply || this.isAWhatsAppChannel || this.isAPIInbox)
|
if (canReply || this.isAWhatsAppChannel || this.isAPIInbox)
|
||||||
this.replyType = mode;
|
this.replyType = mode;
|
||||||
if (this.isRecordingAudio) {
|
if (this.showRichContentEditor) {
|
||||||
this.toggleAudioRecorder();
|
if (this.isRecordingAudio) {
|
||||||
|
this.toggleAudioRecorder();
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this.$nextTick(() => this.$refs.messageInput.focus());
|
||||||
},
|
},
|
||||||
clearEditorSelection() {
|
clearEditorSelection() {
|
||||||
this.updateEditorSelectionWith = '';
|
this.updateEditorSelectionWith = '';
|
||||||
},
|
},
|
||||||
|
insertIntoTextEditor(text, selectionStart, selectionEnd) {
|
||||||
|
const { message } = this;
|
||||||
|
const newMessage =
|
||||||
|
message.slice(0, selectionStart) +
|
||||||
|
text +
|
||||||
|
message.slice(selectionEnd, message.length);
|
||||||
|
this.message = newMessage;
|
||||||
|
},
|
||||||
addIntoEditor(content) {
|
addIntoEditor(content) {
|
||||||
this.updateEditorSelectionWith = content;
|
if (this.showRichContentEditor) {
|
||||||
this.onFocus();
|
this.updateEditorSelectionWith = content;
|
||||||
|
this.onFocus();
|
||||||
|
}
|
||||||
|
if (!this.showRichContentEditor) {
|
||||||
|
const { selectionStart, selectionEnd } = this.$refs.messageInput.$el;
|
||||||
|
this.insertIntoTextEditor(content, selectionStart, selectionEnd);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
clearMessage() {
|
clearMessage() {
|
||||||
this.message = '';
|
this.message = '';
|
||||||
if (this.sendWithSignature && !this.isPrivate) {
|
if (this.sendWithSignature && !this.isPrivate) {
|
||||||
// if signature is enabled, append it to the message
|
// if signature is enabled, append it to the message
|
||||||
const effectiveChannelType = getEffectiveChannelType(
|
if (this.showRichContentEditor) {
|
||||||
this.channelType,
|
const effectiveChannelType = getEffectiveChannelType(
|
||||||
this.inbox?.medium || ''
|
this.channelType,
|
||||||
);
|
this.inbox?.medium || ''
|
||||||
this.message = appendSignature(
|
);
|
||||||
this.message,
|
this.message = appendSignature(
|
||||||
this.messageSignature,
|
this.message,
|
||||||
effectiveChannelType
|
this.messageSignature,
|
||||||
);
|
effectiveChannelType
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.message = appendSignature(this.message, this.signatureToApply);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.attachedFiles = [];
|
this.attachedFiles = [];
|
||||||
this.isRecordingAudio = false;
|
this.isRecordingAudio = false;
|
||||||
@ -852,6 +948,9 @@ export default {
|
|||||||
this.toggleEmojiPicker();
|
this.toggleEmojiPicker();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
hideMentions() {
|
||||||
|
this.showMentions = false;
|
||||||
|
},
|
||||||
onTypingOn() {
|
onTypingOn() {
|
||||||
this.toggleTyping('on');
|
this.toggleTyping('on');
|
||||||
},
|
},
|
||||||
@ -1098,6 +1197,13 @@ export default {
|
|||||||
:message="inReplyTo"
|
:message="inReplyTo"
|
||||||
@dismiss="resetReplyToMessage"
|
@dismiss="resetReplyToMessage"
|
||||||
/>
|
/>
|
||||||
|
<CannedResponse
|
||||||
|
v-if="showMentions && hasSlashCommand"
|
||||||
|
v-on-clickaway="hideMentions"
|
||||||
|
class="normal-editor__canned-box"
|
||||||
|
:search-key="mentionSearchKey"
|
||||||
|
@replace="replaceText"
|
||||||
|
/>
|
||||||
<EmojiInput
|
<EmojiInput
|
||||||
v-if="showEmojiPicker"
|
v-if="showEmojiPicker"
|
||||||
v-on-clickaway="hideEmojiPicker"
|
v-on-clickaway="hideEmojiPicker"
|
||||||
@ -1121,7 +1227,23 @@ export default {
|
|||||||
@play="recordingAudioState = 'playing'"
|
@play="recordingAudioState = 'playing'"
|
||||||
@pause="recordingAudioState = 'paused'"
|
@pause="recordingAudioState = 'paused'"
|
||||||
/>
|
/>
|
||||||
|
<ResizableTextArea
|
||||||
|
v-else-if="!showRichContentEditor"
|
||||||
|
ref="messageInput"
|
||||||
|
v-model="message"
|
||||||
|
class="rounded-none input"
|
||||||
|
:placeholder="messagePlaceHolder"
|
||||||
|
:min-height="4"
|
||||||
|
:signature="signatureToApply"
|
||||||
|
allow-signature
|
||||||
|
:send-with-signature="sendWithSignature"
|
||||||
|
@typing-off="onTypingOff"
|
||||||
|
@typing-on="onTypingOn"
|
||||||
|
@focus="onFocus"
|
||||||
|
@blur="onBlur"
|
||||||
|
/>
|
||||||
<WootMessageEditor
|
<WootMessageEditor
|
||||||
|
v-else
|
||||||
v-model="message"
|
v-model="message"
|
||||||
:editor-id="editorStateId"
|
:editor-id="editorStateId"
|
||||||
class="input popover-prosemirror-menu"
|
class="input popover-prosemirror-menu"
|
||||||
@ -1247,6 +1369,10 @@ export default {
|
|||||||
|
|
||||||
.reply-box__top {
|
.reply-box__top {
|
||||||
@apply relative py-0 px-4 -mt-px;
|
@apply relative py-0 px-4 -mt-px;
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
@apply shadow-none outline-none border-transparent bg-transparent m-0 max-h-60 min-h-[3rem] pt-4 pb-0 px-0 resize-none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-dialog {
|
.emoji-dialog {
|
||||||
@ -1266,4 +1392,9 @@ export default {
|
|||||||
@apply ltr:left-1 rtl:right-1 -bottom-2;
|
@apply ltr:left-1 rtl:right-1 -bottom-2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.normal-editor__canned-box {
|
||||||
|
width: calc(100% - 2 * 1rem);
|
||||||
|
left: 1rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -111,10 +111,15 @@ export default {
|
|||||||
// watcher, this means that if the value is true, the signature
|
// watcher, this means that if the value is true, the signature
|
||||||
// is supposed to be added, else we remove it.
|
// is supposed to be added, else we remove it.
|
||||||
toggleSignatureInEditor(signatureEnabled) {
|
toggleSignatureInEditor(signatureEnabled) {
|
||||||
const valueWithSignature = signatureEnabled
|
let valueWithSignature = signatureEnabled
|
||||||
? appendSignature(this.modelValue, this.cleanedSignature)
|
? appendSignature(this.modelValue, this.cleanedSignature)
|
||||||
: removeSignature(this.modelValue, this.cleanedSignature);
|
: removeSignature(this.modelValue, this.cleanedSignature);
|
||||||
|
|
||||||
|
// Clean up whitespace when removing signature from empty body
|
||||||
|
if (!signatureEnabled && !valueWithSignature.trim()) {
|
||||||
|
valueWithSignature = '';
|
||||||
|
}
|
||||||
|
|
||||||
this.$emit('update:modelValue', valueWithSignature);
|
this.$emit('update:modelValue', valueWithSignature);
|
||||||
this.$emit('input', valueWithSignature);
|
this.$emit('input', valueWithSignature);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user