Merge pull request #725 from frappe/mergify/bp/main/pr-716
fix: Create & Make call (backport #716)
This commit is contained in:
commit
2e578787f6
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -150,6 +150,7 @@ declare module 'vue' {
|
|||||||
MobileLayout: typeof import('./src/components/Layouts/MobileLayout.vue')['default']
|
MobileLayout: typeof import('./src/components/Layouts/MobileLayout.vue')['default']
|
||||||
MobileSidebar: typeof import('./src/components/Mobile/MobileSidebar.vue')['default']
|
MobileSidebar: typeof import('./src/components/Mobile/MobileSidebar.vue')['default']
|
||||||
MoneyIcon: typeof import('./src/components/Icons/MoneyIcon.vue')['default']
|
MoneyIcon: typeof import('./src/components/Icons/MoneyIcon.vue')['default']
|
||||||
|
MultiActionButton: typeof import('./src/components/MultiActionButton.vue')['default']
|
||||||
MultipleAvatar: typeof import('./src/components/MultipleAvatar.vue')['default']
|
MultipleAvatar: typeof import('./src/components/MultipleAvatar.vue')['default']
|
||||||
MultiSelectEmailInput: typeof import('./src/components/Controls/MultiSelectEmailInput.vue')['default']
|
MultiSelectEmailInput: typeof import('./src/components/Controls/MultiSelectEmailInput.vue')['default']
|
||||||
MuteIcon: typeof import('./src/components/Icons/MuteIcon.vue')['default']
|
MuteIcon: typeof import('./src/components/Icons/MuteIcon.vue')['default']
|
||||||
|
|||||||
@ -373,11 +373,7 @@
|
|||||||
>
|
>
|
||||||
<component :is="emptyTextIcon" class="h-10 w-10" />
|
<component :is="emptyTextIcon" class="h-10 w-10" />
|
||||||
<span>{{ __(emptyText) }}</span>
|
<span>{{ __(emptyText) }}</span>
|
||||||
<Button
|
<MultiActionButton v-if="title == 'Calls'" :options="callActions" />
|
||||||
v-if="title == 'Calls'"
|
|
||||||
:label="__('Make a Call')"
|
|
||||||
@click="makeCall(doc.data.mobile_no)"
|
|
||||||
/>
|
|
||||||
<Button
|
<Button
|
||||||
v-else-if="title == 'Notes'"
|
v-else-if="title == 'Notes'"
|
||||||
:label="__('Create Note')"
|
:label="__('Create Note')"
|
||||||
@ -470,6 +466,7 @@ import WhatsAppIcon from '@/components/Icons/WhatsAppIcon.vue'
|
|||||||
import WhatsAppArea from '@/components/Activities/WhatsAppArea.vue'
|
import WhatsAppArea from '@/components/Activities/WhatsAppArea.vue'
|
||||||
import WhatsAppBox from '@/components/Activities/WhatsAppBox.vue'
|
import WhatsAppBox from '@/components/Activities/WhatsAppBox.vue'
|
||||||
import LoadingIndicator from '@/components/Icons/LoadingIndicator.vue'
|
import LoadingIndicator from '@/components/Icons/LoadingIndicator.vue'
|
||||||
|
import MultiActionButton from '@/components/MultiActionButton.vue'
|
||||||
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
|
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
|
||||||
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
||||||
import DotIcon from '@/components/Icons/DotIcon.vue'
|
import DotIcon from '@/components/Icons/DotIcon.vue'
|
||||||
@ -487,7 +484,7 @@ import FilesUploader from '@/components/FilesUploader/FilesUploader.vue'
|
|||||||
import { timeAgo, formatDate, startCase } from '@/utils'
|
import { timeAgo, formatDate, startCase } from '@/utils'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { whatsappEnabled } from '@/composables/settings'
|
import { whatsappEnabled, callEnabled } from '@/composables/settings'
|
||||||
import { capture } from '@/telemetry'
|
import { capture } from '@/telemetry'
|
||||||
import { Button, Tooltip, createResource } from 'frappe-ui'
|
import { Button, Tooltip, createResource } from 'frappe-ui'
|
||||||
import { useElementVisibility } from '@vueuse/core'
|
import { useElementVisibility } from '@vueuse/core'
|
||||||
@ -785,5 +782,23 @@ function scroll(hash) {
|
|||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const callActions = computed(() => {
|
||||||
|
let actions = [
|
||||||
|
{
|
||||||
|
label: __('Create Call Log'),
|
||||||
|
onClick: () => modalRef.value.createCallLog(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Make a Call'),
|
||||||
|
onClick: () => makeCall(doc.data.mobile_no),
|
||||||
|
condition: () => callEnabled.value,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return actions.filter((action) =>
|
||||||
|
action.condition ? action.condition() : true,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
defineExpose({ emailBox, all_activities })
|
defineExpose({ emailBox, all_activities })
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -26,16 +26,11 @@
|
|||||||
</template>
|
</template>
|
||||||
<span>{{ __('New Comment') }}</span>
|
<span>{{ __('New Comment') }}</span>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<MultiActionButton
|
||||||
v-else-if="title == 'Calls'"
|
v-else-if="title == 'Calls'"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
@click="makeCall(doc.data.mobile_no)"
|
:options="callActions"
|
||||||
>
|
/>
|
||||||
<template #prefix>
|
|
||||||
<PhoneIcon class="h-4 w-4" />
|
|
||||||
</template>
|
|
||||||
<span>{{ __('Make a Call') }}</span>
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
v-else-if="title == 'Notes'"
|
v-else-if="title == 'Notes'"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
@ -97,6 +92,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import MultiActionButton from '@/components/MultiActionButton.vue'
|
||||||
import Email2Icon from '@/components/Icons/Email2Icon.vue'
|
import Email2Icon from '@/components/Icons/Email2Icon.vue'
|
||||||
import CommentIcon from '@/components/Icons/CommentIcon.vue'
|
import CommentIcon from '@/components/Icons/CommentIcon.vue'
|
||||||
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||||
@ -136,6 +132,11 @@ const defaultActions = computed(() => {
|
|||||||
label: __('New Comment'),
|
label: __('New Comment'),
|
||||||
onClick: () => (props.emailBox.showComment = true),
|
onClick: () => (props.emailBox.showComment = true),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: h(PhoneIcon, { class: 'h-4 w-4' }),
|
||||||
|
label: __('Create Call Log'),
|
||||||
|
onClick: () => props.modalRef.createCallLog(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
icon: h(PhoneIcon, { class: 'h-4 w-4' }),
|
icon: h(PhoneIcon, { class: 'h-4 w-4' }),
|
||||||
label: __('Make a Call'),
|
label: __('Make a Call'),
|
||||||
@ -172,4 +173,24 @@ const defaultActions = computed(() => {
|
|||||||
function getTabIndex(name) {
|
function getTabIndex(name) {
|
||||||
return props.tabs.findIndex((tab) => tab.name === name)
|
return props.tabs.findIndex((tab) => tab.name === name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const callActions = computed(() => {
|
||||||
|
let actions = [
|
||||||
|
{
|
||||||
|
label: __('Create Call Log'),
|
||||||
|
icon: 'plus',
|
||||||
|
onClick: () => props.modalRef.createCallLog(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Make a Call'),
|
||||||
|
icon: h(PhoneIcon, { class: 'h-4 w-4' }),
|
||||||
|
onClick: () => makeCall(doc.data.mobile_no),
|
||||||
|
condition: () => callEnabled.value,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return actions.filter((action) =>
|
||||||
|
action.condition ? action.condition() : true,
|
||||||
|
)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -15,10 +15,16 @@
|
|||||||
:doc="doc.data?.name"
|
:doc="doc.data?.name"
|
||||||
@after="redirect('notes')"
|
@after="redirect('notes')"
|
||||||
/>
|
/>
|
||||||
|
<CallLogModal
|
||||||
|
v-model="showCallLogModal"
|
||||||
|
v-model:callLog="callLog"
|
||||||
|
:options="{ afterInsert: () => activities.reload() }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import TaskModal from '@/components/Modals/TaskModal.vue'
|
import TaskModal from '@/components/Modals/TaskModal.vue'
|
||||||
import NoteModal from '@/components/Modals/NoteModal.vue'
|
import NoteModal from '@/components/Modals/NoteModal.vue'
|
||||||
|
import CallLogModal from '@/components/Modals/CallLogModal.vue'
|
||||||
import { call } from 'frappe-ui'
|
import { call } from 'frappe-ui'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
@ -77,6 +83,22 @@ function showNote(n) {
|
|||||||
showNoteModal.value = true
|
showNoteModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call Logs
|
||||||
|
const showCallLogModal = ref(false)
|
||||||
|
const callLog = ref({})
|
||||||
|
|
||||||
|
function createCallLog() {
|
||||||
|
let doctype = props.doctype
|
||||||
|
let docname = props.doc.data?.name
|
||||||
|
callLog.value = {
|
||||||
|
data: {
|
||||||
|
reference_doctype: doctype,
|
||||||
|
reference_docname: docname,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
showCallLogModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
// common
|
// common
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -95,5 +117,6 @@ defineExpose({
|
|||||||
deleteTask,
|
deleteTask,
|
||||||
updateTaskStatus,
|
updateTaskStatus,
|
||||||
showNote,
|
showNote,
|
||||||
|
createCallLog,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
71
frontend/src/components/MultiActionButton.vue
Normal file
71
frontend/src/components/MultiActionButton.vue
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Button
|
||||||
|
:variant="$attrs.variant"
|
||||||
|
class="border-0"
|
||||||
|
:label="activeButton.label"
|
||||||
|
:size="$attrs.size"
|
||||||
|
:class="[
|
||||||
|
$attrs.class,
|
||||||
|
showDropdown ? 'rounded-br-none rounded-tr-none' : '',
|
||||||
|
]"
|
||||||
|
@click="() => activeButton.onClick()"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<FeatherIcon
|
||||||
|
v-if="activeButton.icon && typeof activeButton.icon === 'string'"
|
||||||
|
:name="activeButton.icon"
|
||||||
|
class="h-4 w-4"
|
||||||
|
/>
|
||||||
|
<component
|
||||||
|
v-else-if="activeButton.icon"
|
||||||
|
:is="activeButton.icon"
|
||||||
|
class="h-4 w-4"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
<Dropdown
|
||||||
|
v-show="showDropdown"
|
||||||
|
:options="parsedOptions"
|
||||||
|
size="sm"
|
||||||
|
class="flex-1 [&>div>div>div]:w-full"
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<template v-slot="{ togglePopover }">
|
||||||
|
<Button
|
||||||
|
:variant="$attrs.variant"
|
||||||
|
@click="togglePopover"
|
||||||
|
icon="chevron-down"
|
||||||
|
class="!w-6 justify-start rounded-bl-none rounded-tl-none border-0 pr-0 text-xs"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { Dropdown } from 'frappe-ui'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const showDropdown = ref(props.options?.length > 1)
|
||||||
|
const activeButton = ref(props.options?.[0] || {})
|
||||||
|
|
||||||
|
const parsedOptions = computed(() => {
|
||||||
|
return (
|
||||||
|
props.options?.map((option) => {
|
||||||
|
return {
|
||||||
|
label: option.label,
|
||||||
|
onClick: () => {
|
||||||
|
activeButton.value = option
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}) || []
|
||||||
|
)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@ -545,7 +545,6 @@ const tabs = computed(() => {
|
|||||||
name: 'Calls',
|
name: 'Calls',
|
||||||
label: __('Calls'),
|
label: __('Calls'),
|
||||||
icon: PhoneIcon,
|
icon: PhoneIcon,
|
||||||
condition: () => callEnabled.value,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Tasks',
|
name: 'Tasks',
|
||||||
|
|||||||
@ -532,7 +532,6 @@ const tabs = computed(() => {
|
|||||||
name: 'Calls',
|
name: 'Calls',
|
||||||
label: __('Calls'),
|
label: __('Calls'),
|
||||||
icon: PhoneIcon,
|
icon: PhoneIcon,
|
||||||
condition: () => callEnabled.value,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Tasks',
|
name: 'Tasks',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user