fix: merged twilio & exotel settings in one calling settings
This commit is contained in:
parent
b921ce9dff
commit
2dfe75931a
@ -1,6 +0,0 @@
|
||||
<template>
|
||||
<SettingsPage doctype="CRM Exotel Settings" class="p-8" />
|
||||
</template>
|
||||
<script setup>
|
||||
import SettingsPage from '@/components/Settings/SettingsPage.vue'
|
||||
</script>
|
||||
@ -56,8 +56,7 @@ import InviteMemberPage from '@/components/Settings/InviteMemberPage.vue'
|
||||
import ProfileSettings from '@/components/Settings/ProfileSettings.vue'
|
||||
import WhatsAppSettings from '@/components/Settings/WhatsAppSettings.vue'
|
||||
import ERPNextSettings from '@/components/Settings/ERPNextSettings.vue'
|
||||
import TwilioSettings from '@/components/Settings/TwilioSettings.vue'
|
||||
import ExotelSettings from '@/components/Settings/ExotelSettings.vue'
|
||||
import TelephonySettings from '@/components/Settings/TelephonySettings.vue'
|
||||
import SidebarLink from '@/components/SidebarLink.vue'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import {
|
||||
@ -106,14 +105,9 @@ const tabs = computed(() => {
|
||||
label: __('Integrations'),
|
||||
items: [
|
||||
{
|
||||
label: __('Twilio'),
|
||||
label: __('Telephony'),
|
||||
icon: PhoneIcon,
|
||||
component: markRaw(TwilioSettings),
|
||||
},
|
||||
{
|
||||
label: __('Exotel'),
|
||||
icon: PhoneIcon,
|
||||
component: markRaw(ExotelSettings),
|
||||
component: markRaw(TelephonySettings),
|
||||
},
|
||||
{
|
||||
label: __('WhatsApp'),
|
||||
|
||||
272
frontend/src/components/Settings/TelephonySettings.vue
Normal file
272
frontend/src/components/Settings/TelephonySettings.vue
Normal file
@ -0,0 +1,272 @@
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-8 p-8">
|
||||
<h2
|
||||
class="flex gap-2 text-xl font-semibold leading-none h-5 text-ink-gray-9"
|
||||
>
|
||||
<div>{{ __('Telephony Settings') }}</div>
|
||||
<Badge
|
||||
v-if="twilio.isDirty || exotel.isDirty"
|
||||
:label="__('Not Saved')"
|
||||
variant="subtle"
|
||||
theme="orange"
|
||||
/>
|
||||
</h2>
|
||||
<div
|
||||
v-if="!twilio.get.loading || !exotel.get.loading"
|
||||
class="flex-1 flex flex-col gap-8 overflow-y-auto"
|
||||
>
|
||||
<!-- General -->
|
||||
<FormControl
|
||||
type="select"
|
||||
v-model="defaultCallingMedium"
|
||||
:label="__('Default calling medium')"
|
||||
:options="[
|
||||
{ label: __(''), value: '' },
|
||||
{ label: __('Twilio'), value: 'Twilio' },
|
||||
{ label: __('Exotel'), value: 'Exotel' },
|
||||
]"
|
||||
class="w-1/2"
|
||||
/>
|
||||
|
||||
<!-- Twilio -->
|
||||
<div class="flex flex-col justify-between gap-4">
|
||||
<span class="text-base font-semibold text-ink-gray-9">
|
||||
{{ __('Twilio') }}
|
||||
</span>
|
||||
<FieldLayout
|
||||
v-if="twilio?.doc && twilioTabs"
|
||||
:tabs="twilioTabs"
|
||||
:data="twilio.doc"
|
||||
doctype="Twilio Settings"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Exotel -->
|
||||
<div class="flex flex-col justify-between gap-4">
|
||||
<span class="text-base font-semibold text-ink-gray-9">
|
||||
{{ __('Exotel') }}
|
||||
</span>
|
||||
<FieldLayout
|
||||
v-if="exotel?.doc && exotelTabs"
|
||||
:tabs="exotelTabs"
|
||||
:data="exotel.doc"
|
||||
doctype="CRM Exotel Settings"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex flex-1 items-center justify-center">
|
||||
<Spinner class="size-8" />
|
||||
</div>
|
||||
<div class="flex justify-between gap-2">
|
||||
<div>
|
||||
<ErrorMessage class="mt-2" :message="twilio.save.error" />
|
||||
<ErrorMessage class="mt-2" :message="exotel.save.error" />
|
||||
</div>
|
||||
<Button
|
||||
:loading="twilio.save.loading || exotel.save.loading"
|
||||
:label="__('Update')"
|
||||
variant="solid"
|
||||
@click="update"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import FieldLayout from '@/components/FieldLayout/FieldLayout.vue'
|
||||
import {
|
||||
createDocumentResource,
|
||||
createResource,
|
||||
FormControl,
|
||||
Spinner,
|
||||
Badge,
|
||||
ErrorMessage,
|
||||
call,
|
||||
} from 'frappe-ui'
|
||||
import { defaultCallingMedium } from '@/composables/settings'
|
||||
import { createToast, getRandom } from '@/utils'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const twilioFields = createResource({
|
||||
url: 'crm.api.doc.get_fields',
|
||||
cache: ['fields', 'Twilio Settings'],
|
||||
params: {
|
||||
doctype: 'Twilio Settings',
|
||||
allow_all_fieldtypes: true,
|
||||
},
|
||||
auto: true,
|
||||
})
|
||||
|
||||
const exotelFields = createResource({
|
||||
url: 'crm.api.doc.get_fields',
|
||||
cache: ['fields', 'CRM Exotel Settings'],
|
||||
params: {
|
||||
doctype: 'CRM Exotel Settings',
|
||||
allow_all_fieldtypes: true,
|
||||
},
|
||||
auto: true,
|
||||
})
|
||||
|
||||
const twilio = createDocumentResource({
|
||||
doctype: 'Twilio Settings',
|
||||
name: 'Twilio Settings',
|
||||
fields: ['*'],
|
||||
auto: true,
|
||||
setValue: {
|
||||
onSuccess: () => {
|
||||
createToast({
|
||||
title: __('Success'),
|
||||
text: __('Twilio settings updated successfully'),
|
||||
icon: 'check',
|
||||
iconClasses: 'text-ink-green-3',
|
||||
})
|
||||
},
|
||||
onError: (err) => {
|
||||
createToast({
|
||||
title: __('Error'),
|
||||
text: err.message + ': ' + err.messages[0],
|
||||
icon: 'x',
|
||||
iconClasses: 'text-ink-red-4',
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const exotel = createDocumentResource({
|
||||
doctype: 'CRM Exotel Settings',
|
||||
name: 'CRM Exotel Settings',
|
||||
fields: ['*'],
|
||||
auto: true,
|
||||
setValue: {
|
||||
onSuccess: () => {
|
||||
createToast({
|
||||
title: __('Success'),
|
||||
text: __('Exotel settings updated successfully'),
|
||||
icon: 'check',
|
||||
iconClasses: 'text-ink-green-3',
|
||||
})
|
||||
},
|
||||
onError: (err) => {
|
||||
createToast({
|
||||
title: __('Error'),
|
||||
text: err.message + ': ' + err.messages[0],
|
||||
icon: 'x',
|
||||
iconClasses: 'text-ink-red-4',
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const twilioTabs = computed(() => {
|
||||
if (!twilioFields.data) return []
|
||||
let _tabs = []
|
||||
let fieldsData = twilioFields.data
|
||||
|
||||
if (fieldsData[0].type != 'Tab Break') {
|
||||
let _sections = []
|
||||
if (fieldsData[0].type != 'Section Break') {
|
||||
_sections.push({
|
||||
name: 'first_section',
|
||||
columns: [{ name: 'first_column', fields: [] }],
|
||||
})
|
||||
}
|
||||
_tabs.push({ name: 'first_tab', sections: _sections })
|
||||
}
|
||||
|
||||
fieldsData.forEach((field) => {
|
||||
let last_tab = _tabs[_tabs.length - 1]
|
||||
let _sections = _tabs.length ? last_tab.sections : []
|
||||
if (field.fieldtype === 'Tab Break') {
|
||||
_tabs.push({
|
||||
label: field.label,
|
||||
name: field.fieldname,
|
||||
sections: [
|
||||
{
|
||||
name: 'section_' + getRandom(),
|
||||
columns: [{ name: 'column_' + getRandom(), fields: [] }],
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if (field.fieldtype === 'Section Break') {
|
||||
_sections.push({
|
||||
label: field.label,
|
||||
name: field.fieldname,
|
||||
columns: [{ name: 'column_' + getRandom(), fields: [] }],
|
||||
})
|
||||
} else if (field.fieldtype === 'Column Break') {
|
||||
_sections[_sections.length - 1].columns.push({
|
||||
name: field.fieldname,
|
||||
fields: [],
|
||||
})
|
||||
} else {
|
||||
let last_section = _sections[_sections.length - 1]
|
||||
let last_column = last_section.columns[last_section.columns.length - 1]
|
||||
last_column.fields.push(field)
|
||||
}
|
||||
})
|
||||
|
||||
return _tabs
|
||||
})
|
||||
|
||||
const exotelTabs = computed(() => {
|
||||
if (!exotelFields.data) return []
|
||||
let _tabs = []
|
||||
let fieldsData = exotelFields.data
|
||||
|
||||
if (fieldsData[0].type != 'Tab Break') {
|
||||
let _sections = []
|
||||
if (fieldsData[0].type != 'Section Break') {
|
||||
_sections.push({
|
||||
name: 'first_section',
|
||||
columns: [{ name: 'first_column', fields: [] }],
|
||||
})
|
||||
}
|
||||
_tabs.push({ name: 'first_tab', sections: _sections })
|
||||
}
|
||||
|
||||
fieldsData.forEach((field) => {
|
||||
let last_tab = _tabs[_tabs.length - 1]
|
||||
let _sections = _tabs.length ? last_tab.sections : []
|
||||
if (field.fieldtype === 'Tab Break') {
|
||||
_tabs.push({
|
||||
label: field.label,
|
||||
name: field.fieldname,
|
||||
sections: [
|
||||
{
|
||||
name: 'section_' + getRandom(),
|
||||
columns: [{ name: 'column_' + getRandom(), fields: [] }],
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if (field.fieldtype === 'Section Break') {
|
||||
_sections.push({
|
||||
label: field.label,
|
||||
name: field.fieldname,
|
||||
columns: [{ name: 'column_' + getRandom(), fields: [] }],
|
||||
})
|
||||
} else if (field.fieldtype === 'Column Break') {
|
||||
_sections[_sections.length - 1].columns.push({
|
||||
name: field.fieldname,
|
||||
fields: [],
|
||||
})
|
||||
} else {
|
||||
let last_section = _sections[_sections.length - 1]
|
||||
let last_column = last_section.columns[last_section.columns.length - 1]
|
||||
last_column.fields.push(field)
|
||||
}
|
||||
})
|
||||
|
||||
return _tabs
|
||||
})
|
||||
|
||||
async function update() {
|
||||
call('crm.integrations.api.set_default_calling_medium', {
|
||||
medium: defaultCallingMedium.value,
|
||||
})
|
||||
if (twilio.isDirty) {
|
||||
twilio.save.submit()
|
||||
}
|
||||
if (exotel.isDirty) {
|
||||
exotel.save.submit()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,6 +0,0 @@
|
||||
<template>
|
||||
<SettingsPage doctype="Twilio Settings" class="p-8" />
|
||||
</template>
|
||||
<script setup>
|
||||
import SettingsPage from '@/components/Settings/SettingsPage.vue'
|
||||
</script>
|
||||
Loading…
x
Reference in New Issue
Block a user