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",
|
"enabled",
|
||||||
"reference_doctype",
|
"reference_doctype",
|
||||||
"subject",
|
"subject",
|
||||||
|
"response",
|
||||||
"modified",
|
"modified",
|
||||||
]
|
]
|
||||||
return {'columns': columns, 'rows': rows}
|
return {'columns': columns, 'rows': rows}
|
||||||
|
|||||||
@ -3,10 +3,7 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
:rows="rows"
|
:rows="rows"
|
||||||
:options="{
|
:options="{
|
||||||
getRowRoute: (row) => ({
|
onRowClick: (row) => emit('showEmailTemplate', row.name),
|
||||||
name: 'Email Template',
|
|
||||||
params: { emailTemplateId: row.name },
|
|
||||||
}),
|
|
||||||
selectable: options.selectable,
|
selectable: options.selectable,
|
||||||
}"
|
}"
|
||||||
row-key="name"
|
row-key="name"
|
||||||
@ -72,6 +69,7 @@ import {
|
|||||||
ListRowItem,
|
ListRowItem,
|
||||||
ListFooter,
|
ListFooter,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
|
import { defineModel } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
rows: {
|
rows: {
|
||||||
@ -92,7 +90,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['loadMore'])
|
const emit = defineEmits(['loadMore', 'showEmailTemplate'])
|
||||||
|
|
||||||
const pageLengthCount = defineModel()
|
const pageLengthCount = defineModel()
|
||||||
</script>
|
</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,
|
totalCount: emailTemplates.data.total_count,
|
||||||
}"
|
}"
|
||||||
@loadMore="() => loadMore++"
|
@loadMore="() => loadMore++"
|
||||||
|
@showEmailTemplate="showEmailTemplate"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-else-if="emailTemplates.data"
|
v-else-if="emailTemplates.data"
|
||||||
@ -27,31 +28,27 @@
|
|||||||
<div
|
<div
|
||||||
class="flex flex-col items-center gap-3 text-xl font-medium text-gray-500"
|
class="flex flex-col items-center gap-3 text-xl font-medium text-gray-500"
|
||||||
>
|
>
|
||||||
<PhoneIcon class="h-10 w-10" />
|
<EmailIcon class="h-10 w-10" />
|
||||||
<span>No Logs Found</span>
|
<span>No Email Templates Found</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<EmailTemplateModal
|
||||||
|
v-model="showEmailTemplateModal"
|
||||||
|
v-model:reloadEmailTemplates="emailTemplates"
|
||||||
|
:emailTemplate="emailTemplate"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
import EmailIcon from '@/components/Icons/EmailIcon.vue'
|
||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
import ViewControls from '@/components/ViewControls.vue'
|
import ViewControls from '@/components/ViewControls.vue'
|
||||||
import EmailTemplatesListView from '@/components/ListViews/EmailTemplatesListView.vue'
|
import EmailTemplatesListView from '@/components/ListViews/EmailTemplatesListView.vue'
|
||||||
import {
|
import EmailTemplateModal from '@/components/Modals/EmailTemplateModal.vue'
|
||||||
secondsToDuration,
|
import { dateFormat, dateTooltipFormat, timeAgo } from '@/utils'
|
||||||
dateFormat,
|
|
||||||
dateTooltipFormat,
|
|
||||||
timeAgo,
|
|
||||||
} from '@/utils'
|
|
||||||
import { usersStore } from '@/stores/users'
|
|
||||||
import { contactsStore } from '@/stores/contacts'
|
|
||||||
import { Breadcrumbs } from 'frappe-ui'
|
import { Breadcrumbs } from 'frappe-ui'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
const { getUser } = usersStore()
|
|
||||||
const { getContact, getLeadContact } = contactsStore()
|
|
||||||
|
|
||||||
const breadcrumbs = [
|
const breadcrumbs = [
|
||||||
{ label: 'Email Templates', route: { name: 'Email Templates' } },
|
{ label: 'Email Templates', route: { name: 'Email Templates' } },
|
||||||
]
|
]
|
||||||
@ -67,12 +64,7 @@ const rows = computed(() => {
|
|||||||
emailTemplates.value?.data.rows.forEach((row) => {
|
emailTemplates.value?.data.rows.forEach((row) => {
|
||||||
_rows[row] = emailTemplate[row]
|
_rows[row] = emailTemplate[row]
|
||||||
|
|
||||||
if (row === 'status') {
|
if (['modified', 'creation'].includes(row)) {
|
||||||
_rows[row] = {
|
|
||||||
label: statusLabelMap[emailTemplate.status],
|
|
||||||
color: statusColorMap[emailTemplate.status],
|
|
||||||
}
|
|
||||||
} else if (['modified', 'creation'].includes(row)) {
|
|
||||||
_rows[row] = {
|
_rows[row] = {
|
||||||
label: dateFormat(emailTemplate[row], dateTooltipFormat),
|
label: dateFormat(emailTemplate[row], dateTooltipFormat),
|
||||||
timeAgo: timeAgo(emailTemplate[row]),
|
timeAgo: timeAgo(emailTemplate[row]),
|
||||||
@ -83,27 +75,20 @@ const rows = computed(() => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const statusLabelMap = {
|
const showEmailTemplateModal = ref(false)
|
||||||
Completed: 'Completed',
|
|
||||||
Initiated: 'Initiated',
|
|
||||||
Busy: 'Declined',
|
|
||||||
Failed: 'Failed',
|
|
||||||
Queued: 'Queued',
|
|
||||||
Cancelled: 'Cancelled',
|
|
||||||
Ringing: 'Ringing',
|
|
||||||
'No Answer': 'Missed Call',
|
|
||||||
'In Progress': 'In Progress',
|
|
||||||
}
|
|
||||||
|
|
||||||
const statusColorMap = {
|
const emailTemplate = ref({})
|
||||||
Completed: 'green',
|
|
||||||
Busy: 'orange',
|
function showEmailTemplate(name) {
|
||||||
Failed: 'red',
|
let et = rows.value?.find((row) => row.name === name)
|
||||||
Initiated: 'gray',
|
emailTemplate.value = {
|
||||||
Queued: 'gray',
|
subject: et.subject,
|
||||||
Cancelled: 'gray',
|
response: et.response,
|
||||||
Ringing: 'gray',
|
name: et.name,
|
||||||
'No Answer': 'red',
|
enabled: et.enabled,
|
||||||
'In Progress': 'blue',
|
owner: et.owner,
|
||||||
|
reference_doctype: et.reference_doctype,
|
||||||
|
}
|
||||||
|
showEmailTemplateModal.value = true
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user