Merge pull request #21 from shariquerik/twilio-fix
This commit is contained in:
commit
a8c32cff36
@ -7,6 +7,7 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"section_break_malx",
|
||||
"account_sid",
|
||||
"api_key",
|
||||
"api_secret",
|
||||
@ -14,8 +15,9 @@
|
||||
"auth_token",
|
||||
"twiml_sid",
|
||||
"section_break_ssqj",
|
||||
"record_calls",
|
||||
"column_break_avmt"
|
||||
"enabled",
|
||||
"column_break_avmt",
|
||||
"record_calls"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -23,7 +25,7 @@
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Account SID",
|
||||
"reqd": 1
|
||||
"mandatory_depends_on": "eval: doc.enabled"
|
||||
},
|
||||
{
|
||||
"fieldname": "api_key",
|
||||
@ -46,7 +48,7 @@
|
||||
"fieldtype": "Password",
|
||||
"in_list_view": 1,
|
||||
"label": "Auth Token",
|
||||
"reqd": 1
|
||||
"mandatory_depends_on": "eval: doc.enabled"
|
||||
},
|
||||
{
|
||||
"fieldname": "twiml_sid",
|
||||
@ -67,12 +69,22 @@
|
||||
{
|
||||
"fieldname": "column_break_avmt",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_malx",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enabled"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2023-09-20 16:42:17.025651",
|
||||
"modified": "2023-11-03 15:13:09.155818",
|
||||
"modified_by": "Administrator",
|
||||
"module": "FCRM",
|
||||
"name": "Twilio Settings",
|
||||
|
||||
@ -5,6 +5,10 @@ import frappe
|
||||
from frappe import _
|
||||
from .twilio_handler import Twilio, IncomingCall, TwilioCallDetails
|
||||
|
||||
@frappe.whitelist()
|
||||
def is_enabled():
|
||||
return frappe.db.get_single_value("Twilio Settings", "enabled")
|
||||
|
||||
@frappe.whitelist()
|
||||
def generate_access_token():
|
||||
"""Returns access token that is required to authenticate Twilio Client SDK.
|
||||
|
||||
@ -27,8 +27,8 @@ class Twilio:
|
||||
"""Make a twilio connection.
|
||||
"""
|
||||
settings = frappe.get_doc("Twilio Settings")
|
||||
# if not (settings and settings.enabled):
|
||||
# return
|
||||
if not (settings and settings.enabled):
|
||||
return
|
||||
return Twilio(settings=settings)
|
||||
|
||||
def get_phone_numbers(self):
|
||||
@ -115,6 +115,8 @@ class Twilio:
|
||||
@classmethod
|
||||
def get_twilio_client(self):
|
||||
twilio_settings = frappe.get_doc("Twilio Settings")
|
||||
if not twilio_settings.enabled:
|
||||
frappe.throw(_("Please enable twilio settings before making a call."))
|
||||
|
||||
auth_token = get_decrypted_password("Twilio Settings", "Twilio Settings", 'auth_token')
|
||||
client = TwilioClient(twilio_settings.account_sid, auth_token)
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 38eb500cb47d6cfc7124817e9c2acdcd560045f1
|
||||
Subproject commit e0859c6165a5d54a999f94e7c1cf9647ecd2bf72
|
||||
@ -9,21 +9,23 @@
|
||||
"serve": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tiptap/vue-3": "^2.0.4",
|
||||
"@twilio/voice-sdk": "^2.7.1",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vueuse/core": "^10.3.0",
|
||||
"@vueuse/integrations": "^10.3.0",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"feather-icons": "^4.28.0",
|
||||
"frappe-ui": "^0.1.12",
|
||||
"frappe-ui": "^0.1.14",
|
||||
"pinia": "^2.0.33",
|
||||
"postcss": "^8.4.5",
|
||||
"socket.io-client": "^4.7.2",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"vite": "^4.4.9",
|
||||
"vue": "^3.3.4",
|
||||
"vue-router": "^4.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"postcss": "^8.4.5",
|
||||
"vite": "^4.4.9"
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,17 +2,17 @@
|
||||
<div
|
||||
v-show="showCallPopup"
|
||||
ref="callPopup"
|
||||
class="fixed select-none z-10 bg-gray-900 text-gray-300 rounded-lg shadow-2xl p-4 flex flex-col w-60 cursor-move"
|
||||
class="fixed z-10 flex w-60 cursor-move select-none flex-col rounded-lg bg-gray-900 p-4 text-gray-300 shadow-2xl"
|
||||
:style="style"
|
||||
>
|
||||
<div class="flex items-center flex-row-reverse gap-1">
|
||||
<MinimizeIcon class="w-4 h-4 cursor-pointer" @click="toggleCallWindow" />
|
||||
<div class="flex flex-row-reverse items-center gap-1">
|
||||
<MinimizeIcon class="h-4 w-4 cursor-pointer" @click="toggleCallWindow" />
|
||||
</div>
|
||||
<div class="flex flex-col justify-center items-center gap-3">
|
||||
<div class="flex flex-col items-center justify-center gap-3">
|
||||
<Avatar
|
||||
:image="contact.image"
|
||||
:label="contact.full_name"
|
||||
class="flex items-center justify-center [&>div]:text-[30px] !h-24 !w-24 relative"
|
||||
class="relative flex !h-24 !w-24 items-center justify-center [&>div]:text-[30px]"
|
||||
:class="onCall || calling ? '' : 'pulse'"
|
||||
/>
|
||||
<div class="flex flex-col items-center justify-center gap-1">
|
||||
@ -22,11 +22,11 @@
|
||||
<div class="text-sm text-gray-600">{{ contact.mobile_no }}</div>
|
||||
</div>
|
||||
<CountUpTimer ref="counterUp">
|
||||
<div v-if="onCall" class="text-base my-1">
|
||||
<div v-if="onCall" class="my-1 text-base">
|
||||
{{ counterUp?.updatedTime }}
|
||||
</div>
|
||||
</CountUpTimer>
|
||||
<div v-if="!onCall" class="text-base my-1">
|
||||
<div v-if="!onCall" class="my-1 text-base">
|
||||
{{
|
||||
callStatus == 'ringing'
|
||||
? 'Ringing...'
|
||||
@ -43,13 +43,13 @@
|
||||
/>
|
||||
<Button class="rounded-full">
|
||||
<template #icon>
|
||||
<DialpadIcon class="rounded-full cursor-pointer" />
|
||||
<DialpadIcon class="cursor-pointer rounded-full" />
|
||||
</template>
|
||||
</Button>
|
||||
<Button class="rounded-full">
|
||||
<template #icon>
|
||||
<NoteIcon
|
||||
class="text-gray-900 rounded-full cursor-pointer h-4 w-4"
|
||||
class="h-4 w-4 cursor-pointer rounded-full text-gray-900"
|
||||
@click="showNoteModal = true"
|
||||
/>
|
||||
</template>
|
||||
@ -57,7 +57,7 @@
|
||||
<Button class="rounded-full bg-red-600 hover:bg-red-700">
|
||||
<template #icon>
|
||||
<PhoneIcon
|
||||
class="text-white fill-white h-4 w-4 rotate-[135deg]"
|
||||
class="h-4 w-4 rotate-[135deg] fill-white text-white"
|
||||
@click="hangUpCall"
|
||||
/>
|
||||
</template>
|
||||
@ -73,7 +73,7 @@
|
||||
class="rounded-lg"
|
||||
>
|
||||
<template #prefix>
|
||||
<PhoneIcon class="fill-white h-4 w-4 rotate-[135deg]" />
|
||||
<PhoneIcon class="h-4 w-4 rotate-[135deg] fill-white" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
@ -87,7 +87,7 @@
|
||||
@click="acceptIncomingCall"
|
||||
>
|
||||
<template #prefix>
|
||||
<PhoneIcon class="fill-white h-4 w-4" />
|
||||
<PhoneIcon class="h-4 w-4 fill-white" />
|
||||
</template>
|
||||
</Button>
|
||||
<Button
|
||||
@ -99,7 +99,7 @@
|
||||
@click="rejectIncomingCall"
|
||||
>
|
||||
<template #prefix>
|
||||
<PhoneIcon class="fill-white h-4 w-4 rotate-[135deg]" />
|
||||
<PhoneIcon class="h-4 w-4 rotate-[135deg] fill-white" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
@ -107,16 +107,16 @@
|
||||
</div>
|
||||
<div
|
||||
v-show="showSmallCallWindow"
|
||||
class="flex items-center justify-between gap-3 bg-gray-900 text-base text-gray-300 ml-2 px-2 py-[7px] rounded-lg cursor-pointer select-none"
|
||||
class="ml-2 flex cursor-pointer select-none items-center justify-between gap-3 rounded-lg bg-gray-900 px-2 py-[7px] text-base text-gray-300"
|
||||
@click="toggleCallWindow"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<Avatar
|
||||
:image="contact.image"
|
||||
:label="contact.full_name"
|
||||
class="flex items-center justify-center !h-5 !w-5 relative"
|
||||
class="relative flex !h-5 !w-5 items-center justify-center"
|
||||
/>
|
||||
<div class="truncate max-w-[120px]">
|
||||
<div class="max-w-[120px] truncate">
|
||||
{{ contact.full_name }}
|
||||
</div>
|
||||
</div>
|
||||
@ -124,10 +124,10 @@
|
||||
<div class="my-1 min-w-[40px] text-center">
|
||||
{{ counterUp?.updatedTime }}
|
||||
</div>
|
||||
<Button variant="solid" theme="red" class="rounded-full !h-6 !w-6">
|
||||
<Button variant="solid" theme="red" class="!h-6 !w-6 rounded-full">
|
||||
<template #icon>
|
||||
<PhoneIcon
|
||||
class="fill-white h-4 w-4 rotate-[135deg]"
|
||||
class="h-4 w-4 rotate-[135deg] fill-white"
|
||||
@click.stop="hangUpCall"
|
||||
/>
|
||||
</template>
|
||||
@ -140,11 +140,11 @@
|
||||
<Button
|
||||
variant="solid"
|
||||
theme="red"
|
||||
class="rounded-full !h-6 !w-6"
|
||||
class="!h-6 !w-6 rounded-full"
|
||||
@click.stop="cancelCall"
|
||||
>
|
||||
<template #icon>
|
||||
<PhoneIcon class="fill-white h-4 w-4 rotate-[135deg]" />
|
||||
<PhoneIcon class="h-4 w-4 rotate-[135deg] fill-white" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
@ -152,21 +152,21 @@
|
||||
<Button
|
||||
variant="solid"
|
||||
theme="green"
|
||||
class="rounded-full !h-6 !w-6 pulse relative"
|
||||
class="pulse relative !h-6 !w-6 rounded-full"
|
||||
@click.stop="acceptIncomingCall"
|
||||
>
|
||||
<template #icon>
|
||||
<PhoneIcon class="fill-white h-4 w-4 animate-pulse" />
|
||||
<PhoneIcon class="h-4 w-4 animate-pulse fill-white" />
|
||||
</template>
|
||||
</Button>
|
||||
<Button
|
||||
variant="solid"
|
||||
theme="red"
|
||||
class="rounded-full !h-6 !w-6"
|
||||
class="!h-6 !w-6 rounded-full"
|
||||
@click.stop="rejectIncomingCall"
|
||||
>
|
||||
<template #icon>
|
||||
<PhoneIcon class="fill-white h-4 w-4 rotate-[135deg]" />
|
||||
<PhoneIcon class="h-4 w-4 rotate-[135deg] fill-white" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
@ -197,6 +197,7 @@ const contact = ref({
|
||||
mobile_no: '',
|
||||
})
|
||||
|
||||
let enabled = ref(false)
|
||||
let showCallPopup = ref(false)
|
||||
let showSmallCallWindow = ref(false)
|
||||
let onCall = ref(false)
|
||||
@ -244,6 +245,10 @@ let { style } = useDraggable(callPopup, {
|
||||
preventDefault: true,
|
||||
})
|
||||
|
||||
async function is_twilio_enabled() {
|
||||
return await call('crm.twilio.api.is_enabled')
|
||||
}
|
||||
|
||||
async function startupClient() {
|
||||
log.value = 'Requesting Access Token...'
|
||||
|
||||
@ -469,7 +474,10 @@ function toggleCallWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => startupClient())
|
||||
onMounted(async () => {
|
||||
enabled.value = await is_twilio_enabled()
|
||||
enabled.value && startupClient()
|
||||
})
|
||||
|
||||
watch(
|
||||
() => log.value,
|
||||
@ -481,6 +489,7 @@ watch(
|
||||
|
||||
const app = getCurrentInstance()
|
||||
app.appContext.config.globalProperties.makeCall = makeOutgoingCall
|
||||
app.appContext.config.globalProperties.is_twilio_enabled = enabled.value
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
6
frontend/src/composables/twilio.js
Normal file
6
frontend/src/composables/twilio.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { getCurrentInstance } from 'vue'
|
||||
|
||||
export function is_twilio_enabled() {
|
||||
const app = getCurrentInstance()
|
||||
return app.appContext.config.globalProperties.is_twilio_enabled
|
||||
}
|
||||
@ -5,23 +5,34 @@ import frappeui from 'frappe-ui/vite'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [frappeui(), vue({
|
||||
script: {
|
||||
defineModel: true,
|
||||
propsDestructure: true
|
||||
}
|
||||
})],
|
||||
plugins: [
|
||||
frappeui(),
|
||||
vue({
|
||||
script: {
|
||||
defineModel: true,
|
||||
propsDestructure: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
build: {
|
||||
outDir: `../${path.basename(path.resolve('..'))}/public/frontend`,
|
||||
outDir: '../crm/public/frontend',
|
||||
emptyOutDir: true,
|
||||
commonjsOptions: {
|
||||
include: [/tailwind.config.js/, /node_modules/],
|
||||
},
|
||||
sourcemap: true,
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: ['frappe-ui > feather-icons', 'showdown', 'engine.io-client'],
|
||||
include: [
|
||||
'feather-icons',
|
||||
'showdown',
|
||||
'tailwind.config.js',
|
||||
'engine.io-client',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
1795
frontend/yarn.lock
1795
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"aworkspaces": ["frappe-ui", "frontend"],
|
||||
"workspaces": ["frontend", "frappe-ui"],
|
||||
"scripts": {
|
||||
"postinstall": "cd frontend && yarn install",
|
||||
"dev": "cd frontend && yarn dev",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user