fix: added email template modal which is showed when row in listview is clicked
This commit is contained in:
parent
b261506559
commit
2a5d4425d0
@ -43,6 +43,7 @@ class CustomEmailTemplate(EmailTemplate):
|
||||
"enabled",
|
||||
"reference_doctype",
|
||||
"subject",
|
||||
"response",
|
||||
"modified",
|
||||
]
|
||||
return {'columns': columns, 'rows': rows}
|
||||
|
||||
@ -3,10 +3,7 @@
|
||||
:columns="columns"
|
||||
:rows="rows"
|
||||
:options="{
|
||||
getRowRoute: (row) => ({
|
||||
name: 'Email Template',
|
||||
params: { emailTemplateId: row.name },
|
||||
}),
|
||||
onRowClick: (row) => emit('showEmailTemplate', row.name),
|
||||
selectable: options.selectable,
|
||||
}"
|
||||
row-key="name"
|
||||
@ -72,6 +69,7 @@ import {
|
||||
ListRowItem,
|
||||
ListFooter,
|
||||
} from 'frappe-ui'
|
||||
import { defineModel } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
rows: {
|
||||
@ -92,7 +90,7 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['loadMore'])
|
||||
const emit = defineEmits(['loadMore', 'showEmailTemplate'])
|
||||
|
||||
const pageLengthCount = defineModel()
|
||||
</script>
|
||||
|
||||
190
frontend/src/components/Modals/EmailTemplateModal.vue
Normal file
190
frontend/src/components/Modals/EmailTemplateModal.vue
Normal file
@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<Dialog
|
||||
v-model="show"
|
||||
:options="{
|
||||
title: editMode ? 'Edit Email Template' : 'Create Email Template',
|
||||
size: 'xl',
|
||||
actions: [
|
||||
{
|
||||
label: editMode ? 'Update' : 'Create',
|
||||
variant: 'solid',
|
||||
onClick: () => (editMode ? updateEmailTemplate() : callInsertDoc()),
|
||||
},
|
||||
],
|
||||
}"
|
||||
>
|
||||
<template #body-content>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div>
|
||||
<div class="mb-1.5 text-sm text-gray-600">
|
||||
Name
|
||||
<span class="text-red-500">*</span>
|
||||
</div>
|
||||
<TextInput
|
||||
variant="outline"
|
||||
v-model="_emailTemplate.name"
|
||||
placeholder="Add name"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-1.5 text-sm text-gray-600">Doctype</div>
|
||||
<TextInput
|
||||
variant="outline"
|
||||
v-model="_emailTemplate.reference_doctype"
|
||||
placeholder="Add Doctype"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-1.5 text-sm text-gray-600">
|
||||
Subject
|
||||
<span class="text-red-500">*</span>
|
||||
</div>
|
||||
<TextInput
|
||||
ref="subject"
|
||||
variant="outline"
|
||||
v-model="_emailTemplate.subject"
|
||||
placeholder="Add subject"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-1.5 text-sm text-gray-600">
|
||||
Content
|
||||
<span class="text-red-500">*</span>
|
||||
</div>
|
||||
<TextEditor
|
||||
variant="outline"
|
||||
ref="content"
|
||||
editor-class="!prose-sm overflow-auto min-h-[180px] max-h-80 py-1.5 px-2 rounded border border-gray-300 bg-white hover:border-gray-400 hover:shadow-sm focus:bg-white focus:border-gray-500 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-gray-400 text-gray-800 transition-colors"
|
||||
:bubbleMenu="true"
|
||||
:content="_emailTemplate.response"
|
||||
@change="(val) => (_emailTemplate.response = val)"
|
||||
placeholder="Type a Content"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Checkbox v-model="_emailTemplate.enabled" label="Enabled" />
|
||||
</div>
|
||||
<ErrorMessage :message="errorMessage" />
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Checkbox, TextEditor, call } from 'frappe-ui'
|
||||
import { ref, defineModel, nextTick, watch } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
emailTemplate: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
})
|
||||
|
||||
const show = defineModel()
|
||||
const emailTemplates = defineModel('reloadEmailTemplates')
|
||||
const errorMessage = ref('')
|
||||
|
||||
const emit = defineEmits(['after'])
|
||||
|
||||
const subject = ref(null)
|
||||
const editMode = ref(false)
|
||||
let _emailTemplate = ref({})
|
||||
|
||||
async function updateEmailTemplate() {
|
||||
if (!validate()) return
|
||||
const old = { ...props.emailTemplate }
|
||||
const newEmailTemplate = { ..._emailTemplate.value }
|
||||
|
||||
const nameChanged = old.name !== newEmailTemplate.name
|
||||
delete old.name
|
||||
delete newEmailTemplate.name
|
||||
|
||||
const otherFieldChanged =
|
||||
JSON.stringify(old) !== JSON.stringify(newEmailTemplate)
|
||||
const values = newEmailTemplate
|
||||
|
||||
if (!nameChanged && !otherFieldChanged) {
|
||||
show.value = false
|
||||
return
|
||||
}
|
||||
|
||||
let name
|
||||
if (nameChanged) {
|
||||
name = await callRenameDoc()
|
||||
}
|
||||
if (otherFieldChanged) {
|
||||
name = await callSetValue(values)
|
||||
}
|
||||
handleEmailTemplateUpdate({ name })
|
||||
}
|
||||
|
||||
async function callRenameDoc() {
|
||||
const d = await call('frappe.client.rename_doc', {
|
||||
doctype: 'Email Template',
|
||||
old_name: props.emailTemplate.name,
|
||||
new_name: _emailTemplate.value.name,
|
||||
})
|
||||
return d
|
||||
}
|
||||
|
||||
async function callSetValue(values) {
|
||||
const d = await call('frappe.client.set_value', {
|
||||
doctype: 'Email Template',
|
||||
name: _emailTemplate.value.name,
|
||||
fieldname: values,
|
||||
})
|
||||
return d.name
|
||||
}
|
||||
|
||||
async function callInsertDoc() {
|
||||
if (!validate()) return
|
||||
const doc = await call('frappe.client.insert', {
|
||||
doc: {
|
||||
doctype: 'Email Template',
|
||||
..._emailTemplate.value,
|
||||
},
|
||||
})
|
||||
doc.name && handleEmailTemplateUpdate(doc)
|
||||
}
|
||||
|
||||
function handleEmailTemplateUpdate(doc) {
|
||||
emailTemplates.value?.reload()
|
||||
show.value = false
|
||||
}
|
||||
|
||||
function validate() {
|
||||
if (!_emailTemplate.value.name) {
|
||||
errorMessage.value = 'Name is required'
|
||||
return false
|
||||
}
|
||||
if (!_emailTemplate.value.subject) {
|
||||
errorMessage.value = 'Subject is required'
|
||||
return false
|
||||
}
|
||||
if (
|
||||
!_emailTemplate.value.response ||
|
||||
_emailTemplate.value.response === '<p></p>'
|
||||
) {
|
||||
errorMessage.value = 'Content is required'
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
watch(
|
||||
() => show.value,
|
||||
(value) => {
|
||||
if (!value) return
|
||||
editMode.value = false
|
||||
errorMessage.value = ''
|
||||
nextTick(() => {
|
||||
subject.value.el.focus()
|
||||
_emailTemplate.value = { ...props.emailTemplate }
|
||||
if (_emailTemplate.value.name) {
|
||||
editMode.value = true
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
</script>
|
||||
@ -19,6 +19,7 @@
|
||||
totalCount: emailTemplates.data.total_count,
|
||||
}"
|
||||
@loadMore="() => loadMore++"
|
||||
@showEmailTemplate="showEmailTemplate"
|
||||
/>
|
||||
<div
|
||||
v-else-if="emailTemplates.data"
|
||||
@ -27,31 +28,27 @@
|
||||
<div
|
||||
class="flex flex-col items-center gap-3 text-xl font-medium text-gray-500"
|
||||
>
|
||||
<PhoneIcon class="h-10 w-10" />
|
||||
<span>No Logs Found</span>
|
||||
<EmailIcon class="h-10 w-10" />
|
||||
<span>No Email Templates Found</span>
|
||||
</div>
|
||||
</div>
|
||||
<EmailTemplateModal
|
||||
v-model="showEmailTemplateModal"
|
||||
v-model:reloadEmailTemplates="emailTemplates"
|
||||
:emailTemplate="emailTemplate"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||
import EmailIcon from '@/components/Icons/EmailIcon.vue'
|
||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||
import ViewControls from '@/components/ViewControls.vue'
|
||||
import EmailTemplatesListView from '@/components/ListViews/EmailTemplatesListView.vue'
|
||||
import {
|
||||
secondsToDuration,
|
||||
dateFormat,
|
||||
dateTooltipFormat,
|
||||
timeAgo,
|
||||
} from '@/utils'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { contactsStore } from '@/stores/contacts'
|
||||
import EmailTemplateModal from '@/components/Modals/EmailTemplateModal.vue'
|
||||
import { dateFormat, dateTooltipFormat, timeAgo } from '@/utils'
|
||||
import { Breadcrumbs } from 'frappe-ui'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const { getUser } = usersStore()
|
||||
const { getContact, getLeadContact } = contactsStore()
|
||||
|
||||
const breadcrumbs = [
|
||||
{ label: 'Email Templates', route: { name: 'Email Templates' } },
|
||||
]
|
||||
@ -67,12 +64,7 @@ const rows = computed(() => {
|
||||
emailTemplates.value?.data.rows.forEach((row) => {
|
||||
_rows[row] = emailTemplate[row]
|
||||
|
||||
if (row === 'status') {
|
||||
_rows[row] = {
|
||||
label: statusLabelMap[emailTemplate.status],
|
||||
color: statusColorMap[emailTemplate.status],
|
||||
}
|
||||
} else if (['modified', 'creation'].includes(row)) {
|
||||
if (['modified', 'creation'].includes(row)) {
|
||||
_rows[row] = {
|
||||
label: dateFormat(emailTemplate[row], dateTooltipFormat),
|
||||
timeAgo: timeAgo(emailTemplate[row]),
|
||||
@ -83,27 +75,20 @@ const rows = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const statusLabelMap = {
|
||||
Completed: 'Completed',
|
||||
Initiated: 'Initiated',
|
||||
Busy: 'Declined',
|
||||
Failed: 'Failed',
|
||||
Queued: 'Queued',
|
||||
Cancelled: 'Cancelled',
|
||||
Ringing: 'Ringing',
|
||||
'No Answer': 'Missed Call',
|
||||
'In Progress': 'In Progress',
|
||||
}
|
||||
const showEmailTemplateModal = ref(false)
|
||||
|
||||
const statusColorMap = {
|
||||
Completed: 'green',
|
||||
Busy: 'orange',
|
||||
Failed: 'red',
|
||||
Initiated: 'gray',
|
||||
Queued: 'gray',
|
||||
Cancelled: 'gray',
|
||||
Ringing: 'gray',
|
||||
'No Answer': 'red',
|
||||
'In Progress': 'blue',
|
||||
const emailTemplate = ref({})
|
||||
|
||||
function showEmailTemplate(name) {
|
||||
let et = rows.value?.find((row) => row.name === name)
|
||||
emailTemplate.value = {
|
||||
subject: et.subject,
|
||||
response: et.response,
|
||||
name: et.name,
|
||||
enabled: et.enabled,
|
||||
owner: et.owner,
|
||||
reference_doctype: et.reference_doctype,
|
||||
}
|
||||
showEmailTemplateModal.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user