refactor: added email templates in settings modal
(cherry picked from commit 1c3ee8b557bf9371aad2d6803876095a1c0a8026)
This commit is contained in:
parent
aa59703709
commit
14ac102d6d
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -94,6 +94,7 @@ declare module 'vue' {
|
|||||||
EmailIcon: typeof import('./src/components/Icons/EmailIcon.vue')['default']
|
EmailIcon: typeof import('./src/components/Icons/EmailIcon.vue')['default']
|
||||||
EmailProviderIcon: typeof import('./src/components/Settings/EmailProviderIcon.vue')['default']
|
EmailProviderIcon: typeof import('./src/components/Settings/EmailProviderIcon.vue')['default']
|
||||||
EmailTemplateModal: typeof import('./src/components/Modals/EmailTemplateModal.vue')['default']
|
EmailTemplateModal: typeof import('./src/components/Modals/EmailTemplateModal.vue')['default']
|
||||||
|
EmailTemplates: typeof import('./src/components/Settings/EmailTemplate/EmailTemplates.vue')['default']
|
||||||
EmailTemplateSelectorModal: typeof import('./src/components/Modals/EmailTemplateSelectorModal.vue')['default']
|
EmailTemplateSelectorModal: typeof import('./src/components/Modals/EmailTemplateSelectorModal.vue')['default']
|
||||||
EmailTemplatesListView: typeof import('./src/components/ListViews/EmailTemplatesListView.vue')['default']
|
EmailTemplatesListView: typeof import('./src/components/ListViews/EmailTemplatesListView.vue')['default']
|
||||||
ERPNextIcon: typeof import('./src/components/Icons/ERPNextIcon.vue')['default']
|
ERPNextIcon: typeof import('./src/components/Icons/ERPNextIcon.vue')['default']
|
||||||
|
|||||||
@ -0,0 +1,203 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex h-full flex-col gap-6 p-8 text-ink-gray-8">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<div class="flex flex-col gap-1 w-9/12">
|
||||||
|
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||||
|
{{ __('Email templates') }}
|
||||||
|
</h2>
|
||||||
|
<p class="text-p-base text-ink-gray-6">
|
||||||
|
{{
|
||||||
|
__(
|
||||||
|
'Add, edit, and manage email templates for various CRM communications',
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||||
|
<Button :label="__('New')" icon-left="plus" variant="solid" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- loading state -->
|
||||||
|
<div
|
||||||
|
v-if="templates.loading"
|
||||||
|
class="flex mt-28 justify-between w-full h-full"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
:loading="templates.loading"
|
||||||
|
variant="ghost"
|
||||||
|
class="w-full"
|
||||||
|
size="2xl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Empty State -->
|
||||||
|
<div
|
||||||
|
v-if="!templates.loading && !templates.data?.length"
|
||||||
|
class="flex justify-between w-full h-full"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-ink-gray-4 border border-dashed rounded w-full flex items-center justify-center"
|
||||||
|
>
|
||||||
|
{{ __('No email templates found') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Email template list -->
|
||||||
|
<div
|
||||||
|
class="flex flex-col overflow-hidden"
|
||||||
|
v-if="!templates.loading && templates.data?.length"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="templates.data?.length > 10"
|
||||||
|
class="flex items-center justify-between mb-4"
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
ref="searchRef"
|
||||||
|
v-model="search"
|
||||||
|
:placeholder="__('Search template')"
|
||||||
|
class="w-1/3"
|
||||||
|
:debounce="300"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<FeatherIcon name="search" class="h-4 w-4 text-ink-gray-6" />
|
||||||
|
</template>
|
||||||
|
</TextInput>
|
||||||
|
<FormControl
|
||||||
|
type="select"
|
||||||
|
v-model="currentDoctype"
|
||||||
|
:options="[
|
||||||
|
{ label: __('All'), value: 'All' },
|
||||||
|
{ label: __('Lead'), value: 'CRM Lead' },
|
||||||
|
{ label: __('Deal'), value: 'CRM Deal' },
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center p-2 text-sm border-b text-ink-gray-5">
|
||||||
|
<div class="w-4/6">{{ __('Template name') }}</div>
|
||||||
|
<div class="w-1/6">{{ __('For') }}</div>
|
||||||
|
<div class="w-1/6">{{ __('Enabled') }}</div>
|
||||||
|
</div>
|
||||||
|
<ul class="divide-y divide-outline-gray-modals overflow-y-auto">
|
||||||
|
<template v-for="template in templatesList" :key="template.name">
|
||||||
|
<li class="flex items-center justify-between px-2 py-3">
|
||||||
|
<div class="flex flex-col w-4/6 pr-5">
|
||||||
|
<div class="text-base font-medium text-ink-gray-7">
|
||||||
|
{{ template.name }}
|
||||||
|
</div>
|
||||||
|
<div class="text-p-base text-ink-gray-5 truncate">
|
||||||
|
{{ template.subject }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-base text-ink-gray-6 w-1/6">
|
||||||
|
{{ template.reference_doctype.replace('CRM ', '') }}
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between w-1/6">
|
||||||
|
<Switch
|
||||||
|
size="sm"
|
||||||
|
v-model="template.enabled"
|
||||||
|
@update:model-value="toggleEmailTemplate(template)"
|
||||||
|
/>
|
||||||
|
<Dropdown
|
||||||
|
:options="[
|
||||||
|
{
|
||||||
|
label: __('Edit'),
|
||||||
|
icon: 'edit-2',
|
||||||
|
onClick: () => {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Duplicate'),
|
||||||
|
icon: 'copy',
|
||||||
|
onClick: () => {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Delete'),
|
||||||
|
icon: 'trash-2',
|
||||||
|
onClick: () => {},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
placement="right"
|
||||||
|
:button="{
|
||||||
|
icon: 'more-horizontal',
|
||||||
|
variant: 'ghost',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
<!-- Load More Button -->
|
||||||
|
<div
|
||||||
|
v-if="!templates.loading && templates.hasNextPage"
|
||||||
|
class="flex justify-center"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
class="mt-3.5 p-2"
|
||||||
|
@click="() => templates.next()"
|
||||||
|
:loading="templates.loading"
|
||||||
|
:label="__('Load More')"
|
||||||
|
icon-left="refresh-cw"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
TextInput,
|
||||||
|
FormControl,
|
||||||
|
Switch,
|
||||||
|
createListResource,
|
||||||
|
Dropdown,
|
||||||
|
} from 'frappe-ui'
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
|
||||||
|
const templates = createListResource({
|
||||||
|
type: 'list',
|
||||||
|
doctype: 'Email Template',
|
||||||
|
cache: 'emailTemplates',
|
||||||
|
fields: [
|
||||||
|
'name',
|
||||||
|
'enabled',
|
||||||
|
'use_html',
|
||||||
|
'reference_doctype',
|
||||||
|
'subject',
|
||||||
|
'response',
|
||||||
|
'response_html',
|
||||||
|
'modified',
|
||||||
|
'owner',
|
||||||
|
],
|
||||||
|
auto: true,
|
||||||
|
filters: { reference_doctype: ['in', ['CRM Lead', 'CRM Deal']] },
|
||||||
|
orderBy: 'modified desc',
|
||||||
|
pageLength: 20,
|
||||||
|
})
|
||||||
|
|
||||||
|
const search = ref('')
|
||||||
|
const currentDoctype = ref('All')
|
||||||
|
|
||||||
|
const templatesList = computed(() => {
|
||||||
|
let list = templates.data || []
|
||||||
|
if (search.value) {
|
||||||
|
list = list.filter(
|
||||||
|
(template) =>
|
||||||
|
template.name.toLowerCase().includes(search.value.toLowerCase()) ||
|
||||||
|
template.subject.toLowerCase().includes(search.value.toLowerCase()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (currentDoctype.value !== 'All') {
|
||||||
|
list = list.filter(
|
||||||
|
(template) => template.reference_doctype === currentDoctype.value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
|
function toggleEmailTemplate(template) {
|
||||||
|
templates.setValue.submit({
|
||||||
|
name: template.name,
|
||||||
|
enabled: template.enabled ? 1 : 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -51,6 +51,7 @@ import InviteUserPage from '@/components/Settings/InviteUserPage.vue'
|
|||||||
import ProfileSettings from '@/components/Settings/ProfileSettings.vue'
|
import ProfileSettings from '@/components/Settings/ProfileSettings.vue'
|
||||||
import WhatsAppSettings from '@/components/Settings/WhatsAppSettings.vue'
|
import WhatsAppSettings from '@/components/Settings/WhatsAppSettings.vue'
|
||||||
import ERPNextSettings from '@/components/Settings/ERPNextSettings.vue'
|
import ERPNextSettings from '@/components/Settings/ERPNextSettings.vue'
|
||||||
|
import EmailTemplates from '@/components/Settings/EmailTemplate/EmailTemplates.vue'
|
||||||
import TelephonySettings from '@/components/Settings/TelephonySettings.vue'
|
import TelephonySettings from '@/components/Settings/TelephonySettings.vue'
|
||||||
import EmailConfig from '@/components/Settings/EmailConfig.vue'
|
import EmailConfig from '@/components/Settings/EmailConfig.vue'
|
||||||
import SidebarLink from '@/components/SidebarLink.vue'
|
import SidebarLink from '@/components/SidebarLink.vue'
|
||||||
@ -107,6 +108,11 @@ const tabs = computed(() => {
|
|||||||
component: markRaw(EmailConfig),
|
component: markRaw(EmailConfig),
|
||||||
condition: () => isManager(),
|
condition: () => isManager(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: __('Email Templates'),
|
||||||
|
icon: Email2Icon,
|
||||||
|
component: markRaw(EmailTemplates),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user