mirror of
https://github.com/abhinavxd/libredesk.git
synced 2025-11-17 20:32:24 +00:00
refactor(editor): Remove unncessary props and simplify code for tiptap editor, update all editors for the same
This commit is contained in:
@@ -30,25 +30,23 @@
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
@click.prevent="isBold = !isBold"
|
||||
:active="isBold"
|
||||
:class="{ 'bg-gray-200 dark:bg-secondary': isBold }"
|
||||
@click.prevent="editor?.chain().focus().toggleBold().run()"
|
||||
:class="{ 'bg-gray-200 dark:bg-secondary': editor?.isActive('bold') }"
|
||||
>
|
||||
<Bold size="14" />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
@click.prevent="isItalic = !isItalic"
|
||||
:active="isItalic"
|
||||
:class="{ 'bg-gray-200 dark:bg-secondary': isItalic }"
|
||||
@click.prevent="editor?.chain().focus().toggleItalic().run()"
|
||||
:class="{ 'bg-gray-200 dark:bg-secondary': editor?.isActive('italic') }"
|
||||
>
|
||||
<Italic size="14" />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
@click.prevent="toggleBulletList"
|
||||
@click.prevent="editor?.chain().focus().toggleBulletList().run()"
|
||||
:class="{ 'bg-gray-200 dark:bg-secondary': editor?.isActive('bulletList') }"
|
||||
>
|
||||
<List size="14" />
|
||||
@@ -57,7 +55,7 @@
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
@click.prevent="toggleOrderedList"
|
||||
@click.prevent="editor?.chain().focus().toggleOrderedList().run()"
|
||||
:class="{ 'bg-gray-200 dark:bg-secondary': editor?.isActive('orderedList') }"
|
||||
>
|
||||
<ListOrdered size="14" />
|
||||
@@ -91,7 +89,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, watchEffect, onUnmounted, computed } from 'vue'
|
||||
import { ref, watch, onUnmounted } from 'vue'
|
||||
import { useEditor, EditorContent, BubbleMenu } from '@tiptap/vue-3'
|
||||
import {
|
||||
ChevronDown,
|
||||
@@ -121,21 +119,14 @@ import TableRow from '@tiptap/extension-table-row'
|
||||
import TableCell from '@tiptap/extension-table-cell'
|
||||
import TableHeader from '@tiptap/extension-table-header'
|
||||
|
||||
const selectedText = defineModel('selectedText', { default: '' })
|
||||
const textContent = defineModel('textContent')
|
||||
const htmlContent = defineModel('htmlContent')
|
||||
const isBold = defineModel('isBold')
|
||||
const isItalic = defineModel('isItalic')
|
||||
const cursorPosition = defineModel('cursorPosition', { default: 0 })
|
||||
const textContent = defineModel('textContent', { default: '' })
|
||||
const htmlContent = defineModel('htmlContent', { default: '' })
|
||||
const showLinkInput = ref(false)
|
||||
const linkUrl = ref('')
|
||||
|
||||
const props = defineProps({
|
||||
placeholder: String,
|
||||
contentToSet: String,
|
||||
setInlineImage: Object,
|
||||
insertContent: String,
|
||||
clearContent: Boolean,
|
||||
autoFocus: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
@@ -150,8 +141,6 @@ const emit = defineEmits(['send', 'aiPromptSelected'])
|
||||
|
||||
const emitPrompt = (key) => emit('aiPromptSelected', key)
|
||||
|
||||
const getSelectionText = (from, to, doc) => doc.textBetween(from, to)
|
||||
|
||||
// To preseve the table styling in emails, need to set the table style inline.
|
||||
// Created these custom extensions to set the table style inline.
|
||||
const CustomTable = Table.extend({
|
||||
@@ -160,7 +149,7 @@ const CustomTable = Table.extend({
|
||||
...this.parent?.(),
|
||||
style: {
|
||||
parseHTML: (element) =>
|
||||
(element.getAttribute('style') || '') + ' border: 1px solid #dee2e6 !important; width: 100%; margin:0; table-layout: fixed; border-collapse: collapse; position:relative; border-radius: 0.25rem;'
|
||||
(element.getAttribute('style') || '') + '; border: 1px solid #dee2e6 !important; width: 100%; margin:0; table-layout: fixed; border-collapse: collapse; position:relative; border-radius: 0.25rem;'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,7 +162,7 @@ const CustomTableCell = TableCell.extend({
|
||||
style: {
|
||||
parseHTML: (element) =>
|
||||
(element.getAttribute('style') || '') +
|
||||
' border: 1px solid #dee2e6 !important; box-sizing: border-box !important; min-width: 1em !important; padding: 6px 8px !important; vertical-align: top !important;'
|
||||
'; border: 1px solid #dee2e6 !important; box-sizing: border-box !important; min-width: 1em !important; padding: 6px 8px !important; vertical-align: top !important;'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,26 +175,27 @@ const CustomTableHeader = TableHeader.extend({
|
||||
style: {
|
||||
parseHTML: (element) =>
|
||||
(element.getAttribute('style') || '') +
|
||||
' background-color: #f8f9fa !important; color: #212529 !important; font-weight: bold !important; text-align: left !important; border: 1px solid #dee2e6 !important; padding: 6px 8px !important;'
|
||||
'; background-color: #f8f9fa !important; color: #212529 !important; font-weight: bold !important; text-align: left !important; border: 1px solid #dee2e6 !important; padding: 6px 8px !important;'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const editorConfig = computed(() => ({
|
||||
const isInternalUpdate = ref(false)
|
||||
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit.configure(),
|
||||
Image.configure({ HTMLAttributes: { class: 'inline-image' } }),
|
||||
Placeholder.configure({ placeholder: () => props.placeholder }),
|
||||
Link,
|
||||
CustomTable.configure({
|
||||
resizable: false
|
||||
}),
|
||||
CustomTable.configure({ resizable: false }),
|
||||
TableRow,
|
||||
CustomTableCell,
|
||||
CustomTableHeader
|
||||
],
|
||||
autofocus: props.autoFocus,
|
||||
content: htmlContent.value,
|
||||
editorProps: {
|
||||
attributes: { class: 'outline-none' },
|
||||
handleKeyDown: (view, event) => {
|
||||
@@ -213,110 +203,30 @@ const editorConfig = computed(() => ({
|
||||
emit('send')
|
||||
return true
|
||||
}
|
||||
if (event.ctrlKey && event.key.toLowerCase() === 'b') {
|
||||
// Prevent outer listeners
|
||||
event.stopPropagation()
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
const editor = ref(
|
||||
useEditor({
|
||||
...editorConfig.value,
|
||||
content: htmlContent.value,
|
||||
onSelectionUpdate: ({ editor }) => {
|
||||
const { from, to } = editor.state.selection
|
||||
selectedText.value = getSelectionText(from, to, editor.state.doc)
|
||||
},
|
||||
onUpdate: ({ editor }) => {
|
||||
htmlContent.value = editor.getHTML()
|
||||
textContent.value = editor.getText()
|
||||
cursorPosition.value = editor.state.selection.from
|
||||
},
|
||||
onCreate: ({ editor }) => {
|
||||
if (cursorPosition.value) {
|
||||
editor.commands.setTextSelection(cursorPosition.value)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
watchEffect(() => {
|
||||
const editorInstance = editor.value
|
||||
if (!editorInstance) return
|
||||
isBold.value = editorInstance.isActive('bold')
|
||||
isItalic.value = editorInstance.isActive('italic')
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
const editorInstance = editor.value
|
||||
if (!editorInstance) return
|
||||
|
||||
if (isBold.value !== editorInstance.isActive('bold')) {
|
||||
isBold.value
|
||||
? editorInstance.chain().focus().setBold().run()
|
||||
: editorInstance.chain().focus().unsetBold().run()
|
||||
}
|
||||
if (isItalic.value !== editorInstance.isActive('italic')) {
|
||||
isItalic.value
|
||||
? editorInstance.chain().focus().setItalic().run()
|
||||
: editorInstance.chain().focus().unsetItalic().run()
|
||||
},
|
||||
// To update state when user types.
|
||||
onUpdate: ({ editor }) => {
|
||||
isInternalUpdate.value = true
|
||||
htmlContent.value = editor.getHTML()
|
||||
textContent.value = editor.getText()
|
||||
isInternalUpdate.value = false
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.contentToSet,
|
||||
(newContentData) => {
|
||||
if (!newContentData) return
|
||||
try {
|
||||
const parsedData = JSON.parse(newContentData)
|
||||
const content = parsedData.content
|
||||
if (content === '') {
|
||||
editor.value?.commands.clearContent()
|
||||
} else {
|
||||
editor.value?.commands.setContent(content, true)
|
||||
}
|
||||
editor.value?.commands.focus()
|
||||
} catch (e) {
|
||||
console.error('Error parsing content data', e)
|
||||
htmlContent,
|
||||
(newContent) => {
|
||||
if (!isInternalUpdate.value && editor.value && newContent !== editor.value.getHTML()) {
|
||||
editor.value.commands.setContent(newContent || '', false)
|
||||
textContent.value = editor.value.getText()
|
||||
editor.value.commands.focus()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(cursorPosition, (newPos, oldPos) => {
|
||||
if (editor.value && newPos !== oldPos && newPos !== editor.value.state.selection.from) {
|
||||
editor.value.commands.setTextSelection(newPos)
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.clearContent,
|
||||
() => {
|
||||
if (!props.clearContent) return
|
||||
editor.value?.commands.clearContent()
|
||||
editor.value?.commands.focus()
|
||||
// `onUpdate` is not called when clearing content, so need to reset the content here.
|
||||
htmlContent.value = ''
|
||||
textContent.value = ''
|
||||
cursorPosition.value = 0
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.setInlineImage,
|
||||
(val) => {
|
||||
if (val) {
|
||||
editor.value?.commands.setImage({
|
||||
src: val.src,
|
||||
alt: val.alt,
|
||||
title: val.title
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// Insert content at cursor position when insertContent prop changes.
|
||||
watch(
|
||||
() => props.insertContent,
|
||||
(val) => {
|
||||
@@ -328,18 +238,6 @@ onUnmounted(() => {
|
||||
editor.value?.destroy()
|
||||
})
|
||||
|
||||
const toggleBulletList = () => {
|
||||
if (editor.value) {
|
||||
editor.value.chain().focus().toggleBulletList().run()
|
||||
}
|
||||
}
|
||||
|
||||
const toggleOrderedList = () => {
|
||||
if (editor.value) {
|
||||
editor.value.chain().focus().toggleOrderedList().run()
|
||||
}
|
||||
}
|
||||
|
||||
const openLinkModal = () => {
|
||||
if (editor.value?.isActive('link')) {
|
||||
linkUrl.value = editor.value.getAttributes('link').href
|
||||
|
||||
@@ -138,8 +138,7 @@ export const accountNavItems = [
|
||||
{
|
||||
titleKey: 'globals.terms.profile',
|
||||
href: '/account/profile',
|
||||
description: 'Update your profile'
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
export const contactNavItems = [
|
||||
|
||||
@@ -248,18 +248,10 @@ const fetchBusinessHours = async () => {
|
||||
})
|
||||
businessHours.value = response.data.data
|
||||
} catch (error) {
|
||||
// If unauthorized (no permission), show a toast message.
|
||||
if (error.response.status === 403) {
|
||||
emitter.emit(EMITTER_EVENTS.SHOW_TOAST, {
|
||||
variant: 'destructive',
|
||||
description: t('admin.businessHours.unauthorized')
|
||||
})
|
||||
} else {
|
||||
emitter.emit(EMITTER_EVENTS.SHOW_TOAST, {
|
||||
variant: 'destructive',
|
||||
description: handleHTTPError(error).message
|
||||
})
|
||||
}
|
||||
emitter.emit(EMITTER_EVENTS.SHOW_TOAST, {
|
||||
variant: 'destructive',
|
||||
description: handleHTTPError(error).message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<Editor
|
||||
v-model:htmlContent="componentField.modelValue"
|
||||
@update:htmlContent="(value) => componentField.onChange(value)"
|
||||
:placeholder="t('editor.newLine') + t('editor.send') + t('editor.cmdK')"
|
||||
:placeholder="t('editor.newLine')"
|
||||
/>
|
||||
</div>
|
||||
</FormControl>
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<div class="w-full space-y-6 pb-8 relative">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="text-xl font-semibold text-gray-900 dark:text-foreground">{{ $t('globals.terms.note', 2) }}</span>
|
||||
<span class="text-xl font-semibold text-gray-900 dark:text-foreground">
|
||||
{{ $t('globals.terms.note', 2) }}
|
||||
</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@@ -27,7 +29,7 @@
|
||||
<Editor
|
||||
v-model:htmlContent="newNote"
|
||||
@update:htmlContent="(value) => (newNote = value)"
|
||||
:placeholder="t('editor.newLine') + t('editor.send') + t('editor.cmdK')"
|
||||
:placeholder="t('editor.newLine') + t('editor.send')"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex justify-end space-x-3 pt-2">
|
||||
@@ -64,7 +66,9 @@
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-900 dark:text-foreground">{{ note.first_name }} {{ note.last_name }}</p>
|
||||
<p class="text-sm font-medium text-gray-900 dark:text-foreground">
|
||||
{{ note.first_name }} {{ note.last_name }}
|
||||
</p>
|
||||
<p class="text-xs text-muted-foreground flex items-center">
|
||||
<ClockIcon class="h-3 w-3 mr-1 inline-block opacity-70" />
|
||||
{{ formatDate(note.created_at) }}
|
||||
@@ -115,7 +119,9 @@
|
||||
<div class="rounded-full bg-gray-100 dark:bg-foreground p-4 mb-2">
|
||||
<MessageSquareIcon class="text-gray-400 dark:text-background" size="25" />
|
||||
</div>
|
||||
<h3 class="mt-2 text-base font-medium text-gray-900 dark:text-foreground">{{ $t('contact.notes.empty') }}</h3>
|
||||
<h3 class="mt-2 text-base font-medium text-gray-900 dark:text-foreground">
|
||||
{{ $t('contact.notes.empty') }}
|
||||
</h3>
|
||||
<p class="mt-1 text-sm text-muted-foreground max-w-sm mx-auto">
|
||||
{{ $t('contact.notes.help') }}
|
||||
</p>
|
||||
|
||||
@@ -161,9 +161,7 @@
|
||||
<Editor
|
||||
v-model:htmlContent="componentField.modelValue"
|
||||
@update:htmlContent="(value) => componentField.onChange(value)"
|
||||
:contentToSet="contentToSet"
|
||||
:placeholder="t('editor.newLine') + t('editor.send') + t('editor.cmdK')"
|
||||
:clearContent="clearEditorContent"
|
||||
:placeholder="t('editor.newLine') + t('editor.cmdK')"
|
||||
:insertContent="insertContent"
|
||||
:autoFocus="false"
|
||||
class="w-full flex-1 overflow-y-auto p-2 box min-h-0"
|
||||
@@ -199,6 +197,7 @@
|
||||
<ReplyBoxMenuBar
|
||||
:handleFileUpload="handleFileUpload"
|
||||
@emojiSelect="handleEmojiSelect"
|
||||
:showSendButton="false"
|
||||
/>
|
||||
<Button type="submit" :disabled="isDisabled" :isLoading="loading">
|
||||
{{ $t('globals.buttons.submit') }}
|
||||
@@ -266,9 +265,6 @@ const emailQuery = ref('')
|
||||
const conversationStore = useConversationStore()
|
||||
const macroStore = useMacroStore()
|
||||
let timeoutId = null
|
||||
|
||||
const contentToSet = ref('')
|
||||
const clearEditorContent = ref(false)
|
||||
const insertContent = ref('')
|
||||
|
||||
const handleEmojiSelect = (emoji) => {
|
||||
@@ -420,11 +416,7 @@ const createConversation = form.handleSubmit(async (values) => {
|
||||
watch(
|
||||
() => conversationStore.getMacro('new-conversation').id,
|
||||
() => {
|
||||
// Setting timestamp, so the same macro can be set again.
|
||||
contentToSet.value = JSON.stringify({
|
||||
content: conversationStore.getMacro('new-conversation').message_content,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
form.setFieldValue('content', conversationStore.getMacro('new-conversation').message_content)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div
|
||||
v-for="action in actions"
|
||||
:key="action.type"
|
||||
class="flex items-center border border-gray-200 rounded shadow-sm transition-all duration-300 ease-in-out hover:shadow-md group gap-2"
|
||||
class="flex items-center border bg-background border-gray-200 rounded shadow-sm transition-all duration-300 ease-in-out hover:shadow-md group gap-2"
|
||||
>
|
||||
<div class="flex items-center space-x-2 px-2">
|
||||
<component
|
||||
|
||||
@@ -53,13 +53,8 @@
|
||||
:isSending="isSending"
|
||||
:uploadingFiles="uploadingFiles"
|
||||
:clearEditorContent="clearEditorContent"
|
||||
:contentToSet="contentToSet"
|
||||
v-model:htmlContent="htmlContent"
|
||||
v-model:textContent="textContent"
|
||||
v-model:selectedText="selectedText"
|
||||
v-model:isBold="isBold"
|
||||
v-model:isItalic="isItalic"
|
||||
v-model:cursorPosition="cursorPosition"
|
||||
v-model:to="to"
|
||||
v-model:cc="cc"
|
||||
v-model:bcc="bcc"
|
||||
@@ -88,14 +83,9 @@
|
||||
:isSending="isSending"
|
||||
:uploadingFiles="uploadingFiles"
|
||||
:clearEditorContent="clearEditorContent"
|
||||
:contentToSet="contentToSet"
|
||||
:uploadedFiles="mediaFiles"
|
||||
v-model:htmlContent="htmlContent"
|
||||
v-model:textContent="textContent"
|
||||
v-model:selectedText="selectedText"
|
||||
v-model:isBold="isBold"
|
||||
v-model:isItalic="isItalic"
|
||||
v-model:cursorPosition="cursorPosition"
|
||||
v-model:to="to"
|
||||
v-model:cc="cc"
|
||||
v-model:bcc="bcc"
|
||||
@@ -181,11 +171,6 @@ const emailErrors = ref([])
|
||||
const aiPrompts = ref([])
|
||||
const htmlContent = ref('')
|
||||
const textContent = ref('')
|
||||
const selectedText = ref('')
|
||||
const isBold = ref(false)
|
||||
const isItalic = ref(false)
|
||||
const cursorPosition = ref(0)
|
||||
const contentToSet = ref('')
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchAiPrompts()
|
||||
@@ -218,10 +203,7 @@ const handleAiPromptSelected = async (key) => {
|
||||
prompt_key: key,
|
||||
content: textContent.value
|
||||
})
|
||||
contentToSet.value = JSON.stringify({
|
||||
content: resp.data.data.replace(/\n/g, '<br>'),
|
||||
timestamp: Date.now()
|
||||
})
|
||||
htmlContent.value = resp.data.data.replace(/\n/g, '<br>')
|
||||
} catch (error) {
|
||||
// Check if user needs to enter OpenAI API key and has permission to do so.
|
||||
if (error.response?.status === 400 && userStore.can('ai:manage')) {
|
||||
@@ -348,11 +330,7 @@ const processSend = async () => {
|
||||
watch(
|
||||
() => conversationStore.getMacro('reply').id,
|
||||
() => {
|
||||
// Setting timestamp, so the same macro can be set again.
|
||||
contentToSet.value = JSON.stringify({
|
||||
content: conversationStore.getMacro('reply').message_content,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
htmlContent.value = conversationStore.getMacro('reply').message_content
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
@@ -84,21 +84,14 @@
|
||||
<!-- Main tiptap editor -->
|
||||
<div class="flex-grow flex flex-col overflow-hidden">
|
||||
<Editor
|
||||
v-model:selectedText="selectedText"
|
||||
v-model:isBold="isBold"
|
||||
v-model:isItalic="isItalic"
|
||||
v-model:htmlContent="htmlContent"
|
||||
v-model:textContent="textContent"
|
||||
v-model:cursorPosition="cursorPosition"
|
||||
:placeholder="t('editor.newLine') + t('editor.send') + t('editor.cmdK')"
|
||||
:aiPrompts="aiPrompts"
|
||||
@aiPromptSelected="handleAiPromptSelected"
|
||||
:contentToSet="contentToSet"
|
||||
@send="handleSend"
|
||||
:clearContent="clearEditorContent"
|
||||
:setInlineImage="setInlineImage"
|
||||
:insertContent="insertContent"
|
||||
:autoFocus="true"
|
||||
@aiPromptSelected="handleAiPromptSelected"
|
||||
@send="handleSend"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -124,14 +117,9 @@
|
||||
class="mt-1 shrink-0"
|
||||
:isFullscreen="isFullscreen"
|
||||
:handleFileUpload="handleFileUpload"
|
||||
:isBold="isBold"
|
||||
:isItalic="isItalic"
|
||||
:isSending="isSending"
|
||||
@toggleBold="toggleBold"
|
||||
@toggleItalic="toggleItalic"
|
||||
:enableSend="enableSend"
|
||||
:handleSend="handleSend"
|
||||
:showSendButton="true"
|
||||
@emojiSelect="handleEmojiSelect"
|
||||
/>
|
||||
</div>
|
||||
@@ -162,10 +150,6 @@ const showBcc = defineModel('showBcc', { default: false })
|
||||
const emailErrors = defineModel('emailErrors', { default: () => [] })
|
||||
const htmlContent = defineModel('htmlContent', { default: '' })
|
||||
const textContent = defineModel('textContent', { default: '' })
|
||||
const selectedText = defineModel('selectedText', { default: '' })
|
||||
const isBold = defineModel('isBold', { default: false })
|
||||
const isItalic = defineModel('isItalic', { default: false })
|
||||
const cursorPosition = defineModel('cursorPosition', { default: 0 })
|
||||
const macroStore = useMacroStore()
|
||||
|
||||
const props = defineProps({
|
||||
@@ -185,14 +169,6 @@ const props = defineProps({
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
clearEditorContent: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
contentToSet: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
uploadedFiles: {
|
||||
type: Array,
|
||||
required: false,
|
||||
@@ -212,9 +188,7 @@ const emit = defineEmits([
|
||||
const conversationStore = useConversationStore()
|
||||
const emitter = useEmitter()
|
||||
const { t } = useI18n()
|
||||
|
||||
const insertContent = ref(null)
|
||||
const setInlineImage = ref(null)
|
||||
|
||||
const toggleBcc = async () => {
|
||||
showBcc.value = !showBcc.value
|
||||
@@ -231,14 +205,6 @@ const toggleFullscreen = () => {
|
||||
emit('toggleFullscreen')
|
||||
}
|
||||
|
||||
const toggleBold = () => {
|
||||
isBold.value = !isBold.value
|
||||
}
|
||||
|
||||
const toggleItalic = () => {
|
||||
isItalic.value = !isItalic.value
|
||||
}
|
||||
|
||||
const enableSend = computed(() => {
|
||||
return (
|
||||
(textContent.value.trim().length > 0 ||
|
||||
|
||||
@@ -65,7 +65,10 @@ defineProps({
|
||||
isSending: Boolean,
|
||||
enableSend: Boolean,
|
||||
handleSend: Function,
|
||||
showSendButton: Boolean,
|
||||
showSendButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
handleFileUpload: Function,
|
||||
handleInlineImageUpload: Function
|
||||
})
|
||||
|
||||
@@ -640,7 +640,7 @@ export const useConversationStore = defineStore('conversation', () => {
|
||||
}
|
||||
|
||||
|
||||
/** Macros for new conversation or open conversation **/
|
||||
/** Macros set for new conversation or an open conversation **/
|
||||
async function setMacro (macro, context) {
|
||||
macros.value[context] = macro
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user