fix: added custom paragraph in tiptap editor to allow adding class attribute

This commit is contained in:
Shariq Ansari 2024-07-12 17:22:43 +05:30
parent 475c50b101
commit ee8fdf099f
2 changed files with 48 additions and 11 deletions

View File

@ -442,7 +442,7 @@
'outgoing_call', 'outgoing_call',
].includes(activity.activity_type), ].includes(activity.activity_type),
'bg-white': ['added', 'removed', 'changed'].includes( 'bg-white': ['added', 'removed', 'changed'].includes(
activity.activity_type activity.activity_type,
), ),
}" }"
> >
@ -528,7 +528,10 @@
<span v-if="activity.data.bcc">{{ activity.data.bcc }}</span> <span v-if="activity.data.bcc">{{ activity.data.bcc }}</span>
</div> </div>
<EmailContent :content="activity.data.content" /> <EmailContent :content="activity.data.content" />
<div class="flex flex-wrap gap-2"> <div
v-if="activity.data?.attachments?.length"
class="flex flex-wrap gap-2"
>
<AttachmentItem <AttachmentItem
v-for="a in activity.data.attachments" v-for="a in activity.data.attachments"
:key="a.file_url" :key="a.file_url"
@ -1102,7 +1105,7 @@ const defaultActions = computed(() => {
}, },
] ]
return actions.filter((action) => return actions.filter((action) =>
action.condition ? action.condition() : true action.condition ? action.condition() : true,
) )
}) })
@ -1120,12 +1123,12 @@ const activities = computed(() => {
} else if (props.title == 'Emails') { } else if (props.title == 'Emails') {
if (!all_activities.data?.versions) return [] if (!all_activities.data?.versions) return []
activities = all_activities.data.versions.filter( activities = all_activities.data.versions.filter(
(activity) => activity.activity_type === 'communication' (activity) => activity.activity_type === 'communication',
) )
} else if (props.title == 'Comments') { } else if (props.title == 'Comments') {
if (!all_activities.data?.versions) return [] if (!all_activities.data?.versions) return []
activities = all_activities.data.versions.filter( activities = all_activities.data.versions.filter(
(activity) => activity.activity_type === 'comment' (activity) => activity.activity_type === 'comment',
) )
} else if (props.title == 'Calls') { } else if (props.title == 'Calls') {
if (!all_activities.data?.calls) return [] if (!all_activities.data?.calls) return []
@ -1338,12 +1341,15 @@ function reply(email, reply_all = false) {
editor.bccEmails = bcc editor.bccEmails = bcc
} }
let repliedMessage = `<blockquote>${message}</blockquote>`
editor.editor editor.editor
.chain() .chain()
.clearContent() .clearContent()
.insertContent(message) .insertContent('<p>.</p>')
.updateAttributes('paragraph', {class:'reply-to-content'})
.insertContent(repliedMessage)
.focus('all') .focus('all')
.setBlockquote()
.insertContentAt(0, { type: 'paragraph' }) .insertContentAt(0, { type: 'paragraph' })
.focus('start') .focus('start')
.run() .run()

View File

@ -1,12 +1,20 @@
<template> <template>
<TextEditor <TextEditor
ref="textEditor" ref="textEditor"
:editor-class="['prose-sm max-w-none', editable && 'min-h-[7rem]']" :editor-class="[
'prose-sm max-w-none',
editable && 'min-h-[7rem]',
'[&_p.reply-to-content]:hidden',
]"
:content="content" :content="content"
@change="editable ? (content = $event) : null" @change="editable ? (content = $event) : null"
:starterkit-options="{ heading: { levels: [2, 3, 4, 5, 6] } }" :starterkit-options="{
heading: { levels: [2, 3, 4, 5, 6] },
paragraph: false,
}"
:placeholder="placeholder" :placeholder="placeholder"
:editable="editable" :editable="editable"
:extensions="[CustomParagraph]"
> >
<template #top> <template #top>
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
@ -25,13 +33,17 @@
:label="__('CC')" :label="__('CC')"
variant="ghost" variant="ghost"
@click="toggleCC()" @click="toggleCC()"
:class="[cc ? '!bg-gray-300 hover:bg-gray-200' : '!text-gray-500']" :class="[
cc ? '!bg-gray-300 hover:bg-gray-200' : '!text-gray-500',
]"
/> />
<Button <Button
:label="__('BCC')" :label="__('BCC')"
variant="ghost" variant="ghost"
@click="toggleBCC()" @click="toggleBCC()"
:class="[bcc ? '!bg-gray-300 hover:bg-gray-200' : '!text-gray-500']" :class="[
bcc ? '!bg-gray-300 hover:bg-gray-200' : '!text-gray-500',
]"
/> />
</div> </div>
</div> </div>
@ -164,6 +176,7 @@ import MultiselectInput from '@/components/Controls/MultiselectInput.vue'
import EmailTemplateSelectorModal from '@/components/Modals/EmailTemplateSelectorModal.vue' import EmailTemplateSelectorModal from '@/components/Modals/EmailTemplateSelectorModal.vue'
import { TextEditorBubbleMenu, TextEditor, FileUploader, call } from 'frappe-ui' import { TextEditorBubbleMenu, TextEditor, FileUploader, call } from 'frappe-ui'
import { validateEmail } from '@/utils' import { validateEmail } from '@/utils'
import Paragraph from '@tiptap/extension-paragraph'
import { EditorContent } from '@tiptap/vue-3' import { EditorContent } from '@tiptap/vue-3'
import { ref, computed, defineModel, nextTick } from 'vue' import { ref, computed, defineModel, nextTick } from 'vue'
@ -198,6 +211,24 @@ const props = defineProps({
}, },
}) })
const CustomParagraph = Paragraph.extend({
addAttributes() {
return {
class: {
default: null,
renderHTML: (attributes) => {
if (!attributes.class) {
return {}
}
return {
class: `${attributes.class}`,
}
},
},
}
},
})
const modelValue = defineModel() const modelValue = defineModel()
const attachments = defineModel('attachments') const attachments = defineModel('attachments')
const content = defineModel('content') const content = defineModel('content')