Merge pull request #389 from frappe/develop
chore: Merge develop to main
This commit is contained in:
commit
c6edba6622
@ -18,16 +18,18 @@ def notify_mentions(doc):
|
||||
if not content:
|
||||
return
|
||||
mentions = extract_mentions(content)
|
||||
reference_doc = frappe.get_doc(doc.reference_doctype, doc.reference_name)
|
||||
for mention in mentions:
|
||||
owner = frappe.get_cached_value("User", doc.owner, "full_name")
|
||||
doctype = doc.reference_doctype
|
||||
if doctype.startswith("CRM "):
|
||||
doctype = doctype[4:].lower()
|
||||
name = reference_doc.lead_name or name if doctype == "lead" else reference_doc.organization or reference_doc.lead_name or name
|
||||
notification_text = f"""
|
||||
<div class="mb-2 leading-5 text-gray-600">
|
||||
<span class="font-medium text-gray-900">{ owner }</span>
|
||||
<span>{ _('mentioned you in {0}').format(doctype) }</span>
|
||||
<span class="font-medium text-gray-900">{ doc.reference_name }</span>
|
||||
<span class="font-medium text-gray-900">{ name }</span>
|
||||
</div>
|
||||
"""
|
||||
notify_user({
|
||||
|
||||
@ -617,6 +617,7 @@ def get_field_obj(field):
|
||||
obj["placeholder"] = field.get("placeholder") or "Select " + field.label + "..."
|
||||
obj["doctype"] = field.options
|
||||
elif field.fieldtype == "Select" and field.options:
|
||||
obj["placeholder"] = field.get("placeholder") or "Select " + field.label + "..."
|
||||
obj["options"] = [{"label": option, "value": option} for option in field.options.split("\n")]
|
||||
|
||||
if field.read_only:
|
||||
|
||||
@ -27,7 +27,7 @@ def get_notifications():
|
||||
"type": notification.type,
|
||||
"to_user": notification.to_user,
|
||||
"read": notification.read,
|
||||
"comment": notification.comment,
|
||||
"hash": get_hash(notification),
|
||||
"notification_text": notification.notification_text,
|
||||
"notification_type_doctype": notification.notification_type_doctype,
|
||||
"notification_type_doc": notification.notification_type_doc,
|
||||
@ -58,3 +58,17 @@ def mark_as_read(user=None, doc=None):
|
||||
d = frappe.get_doc("CRM Notification", n.name)
|
||||
d.read = True
|
||||
d.save()
|
||||
|
||||
def get_hash(notification):
|
||||
_hash = ""
|
||||
if notification.type == "Mention" and notification.notification_type_doc:
|
||||
_hash = "#" + notification.notification_type_doc
|
||||
|
||||
if notification.type == "WhatsApp":
|
||||
_hash = "#whatsapp"
|
||||
|
||||
if notification.type == "Assignment" and notification.notification_type_doctype == "CRM Task":
|
||||
_hash = "#tasks"
|
||||
if "has been removed by" in notification.message:
|
||||
_hash = ""
|
||||
return _hash
|
||||
@ -52,8 +52,8 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
|
||||
if doctype.startswith("CRM "):
|
||||
doctype = doctype[4:].lower()
|
||||
|
||||
if doctype in ["CRM Lead", "CRM Deal"]:
|
||||
name = reference_doc.lead_name or name if doctype == "CRM Lead" else reference_doc.organization or reference_doc.lead_name or name
|
||||
if doctype in ["lead", "deal"]:
|
||||
name = reference_doc.lead_name or name if doctype == "lead" else reference_doc.organization or reference_doc.lead_name or name
|
||||
|
||||
if is_cancelled:
|
||||
return f"""
|
||||
@ -76,7 +76,7 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
|
||||
</div>
|
||||
"""
|
||||
|
||||
if doc.reference_type == "CRM Task":
|
||||
if doctype == "task":
|
||||
if is_cancelled:
|
||||
return f"""
|
||||
<div class="mb-2 leading-5 text-gray-600">
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit cf4e7d347237c23ebde5f5c890abdf7e81284961
|
||||
Subproject commit 427b76188fe8b20e683bccf9bb4003821253259f
|
||||
@ -14,7 +14,7 @@
|
||||
"@vueuse/core": "^10.3.0",
|
||||
"@vueuse/integrations": "^10.3.0",
|
||||
"feather-icons": "^4.28.0",
|
||||
"frappe-ui": "^0.1.66",
|
||||
"frappe-ui": "^0.1.70",
|
||||
"gemoji": "^8.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mime": "^4.0.1",
|
||||
|
||||
@ -457,10 +457,6 @@ const { getUser } = usersStore()
|
||||
const { getContact, getLeadContact } = contactsStore()
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Activity',
|
||||
},
|
||||
doctype: {
|
||||
type: String,
|
||||
default: 'CRM Lead',
|
||||
@ -471,6 +467,8 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const doc = defineModel()
|
||||
const reload = defineModel('reload')
|
||||
const tabIndex = defineModel('tabIndex')
|
||||
@ -478,6 +476,8 @@ const tabIndex = defineModel('tabIndex')
|
||||
const reload_email = ref(false)
|
||||
const modalRef = ref(null)
|
||||
|
||||
const title = computed(() => props.tabs?.[tabIndex.value]?.name || 'Activity')
|
||||
|
||||
const all_activities = createResource({
|
||||
url: 'crm.api.activities.get_activities',
|
||||
params: { name: doc.value.data.name },
|
||||
@ -549,6 +549,14 @@ onMounted(() => {
|
||||
whatsappMessages.reload()
|
||||
}
|
||||
})
|
||||
|
||||
nextTick(() => {
|
||||
const hash = route.hash.slice(1) || null
|
||||
let tabNames = props.tabs?.map((tab) => tab.name)
|
||||
if (!tabNames?.includes(hash)) {
|
||||
scroll(hash)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function sendTemplate(template) {
|
||||
@ -577,25 +585,25 @@ function get_activities() {
|
||||
|
||||
const activities = computed(() => {
|
||||
let activities = []
|
||||
if (props.title == 'Activity') {
|
||||
if (title.value == 'Activity') {
|
||||
activities = get_activities()
|
||||
} else if (props.title == 'Emails') {
|
||||
} else if (title.value == 'Emails') {
|
||||
if (!all_activities.data?.versions) return []
|
||||
activities = all_activities.data.versions.filter(
|
||||
(activity) => activity.activity_type === 'communication',
|
||||
)
|
||||
} else if (props.title == 'Comments') {
|
||||
} else if (title.value == 'Comments') {
|
||||
if (!all_activities.data?.versions) return []
|
||||
activities = all_activities.data.versions.filter(
|
||||
(activity) => activity.activity_type === 'comment',
|
||||
)
|
||||
} else if (props.title == 'Calls') {
|
||||
} else if (title.value == 'Calls') {
|
||||
if (!all_activities.data?.calls) return []
|
||||
return sortByCreation(all_activities.data.calls)
|
||||
} else if (props.title == 'Tasks') {
|
||||
} else if (title.value == 'Tasks') {
|
||||
if (!all_activities.data?.tasks) return []
|
||||
return sortByCreation(all_activities.data.tasks)
|
||||
} else if (props.title == 'Notes') {
|
||||
} else if (title.value == 'Notes') {
|
||||
if (!all_activities.data?.notes) return []
|
||||
return sortByCreation(all_activities.data.notes)
|
||||
}
|
||||
@ -649,17 +657,17 @@ function update_activities_details(activity) {
|
||||
|
||||
const emptyText = computed(() => {
|
||||
let text = 'No Activities'
|
||||
if (props.title == 'Emails') {
|
||||
if (title.value == 'Emails') {
|
||||
text = 'No Email Communications'
|
||||
} else if (props.title == 'Comments') {
|
||||
} else if (title.value == 'Comments') {
|
||||
text = 'No Comments'
|
||||
} else if (props.title == 'Calls') {
|
||||
} else if (title.value == 'Calls') {
|
||||
text = 'No Call Logs'
|
||||
} else if (props.title == 'Notes') {
|
||||
} else if (title.value == 'Notes') {
|
||||
text = 'No Notes'
|
||||
} else if (props.title == 'Tasks') {
|
||||
} else if (title.value == 'Tasks') {
|
||||
text = 'No Tasks'
|
||||
} else if (props.title == 'WhatsApp') {
|
||||
} else if (title.value == 'WhatsApp') {
|
||||
text = 'No WhatsApp Messages'
|
||||
}
|
||||
return text
|
||||
@ -667,17 +675,17 @@ const emptyText = computed(() => {
|
||||
|
||||
const emptyTextIcon = computed(() => {
|
||||
let icon = ActivityIcon
|
||||
if (props.title == 'Emails') {
|
||||
if (title.value == 'Emails') {
|
||||
icon = Email2Icon
|
||||
} else if (props.title == 'Comments') {
|
||||
} else if (title.value == 'Comments') {
|
||||
icon = CommentIcon
|
||||
} else if (props.title == 'Calls') {
|
||||
} else if (title.value == 'Calls') {
|
||||
icon = PhoneIcon
|
||||
} else if (props.title == 'Notes') {
|
||||
} else if (title.value == 'Notes') {
|
||||
icon = NoteIcon
|
||||
} else if (props.title == 'Tasks') {
|
||||
} else if (title.value == 'Tasks') {
|
||||
icon = TaskIcon
|
||||
} else if (props.title == 'WhatsApp') {
|
||||
} else if (title.value == 'WhatsApp') {
|
||||
icon = WhatsAppIcon
|
||||
}
|
||||
return h(icon, { class: 'text-gray-500' })
|
||||
@ -720,6 +728,7 @@ watch([reload, reload_email], ([reload_value, reload_email_value]) => {
|
||||
})
|
||||
|
||||
function scroll(hash) {
|
||||
if (['tasks', 'notes'].includes(route.hash?.slice(1))) return
|
||||
setTimeout(() => {
|
||||
let el
|
||||
if (!hash) {
|
||||
@ -736,11 +745,4 @@ function scroll(hash) {
|
||||
}
|
||||
|
||||
defineExpose({ emailBox })
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
nextTick(() => {
|
||||
const hash = route.hash.slice(1) || null
|
||||
scroll(hash)
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
:task="task"
|
||||
:doctype="doctype"
|
||||
:doc="doc.data?.name"
|
||||
@after="redirect('tasks')"
|
||||
/>
|
||||
<NoteModal
|
||||
v-model="showNoteModal"
|
||||
@ -12,6 +13,7 @@
|
||||
:note="note"
|
||||
:doctype="doctype"
|
||||
:doc="doc.data?.name"
|
||||
@after="redirect('notes')"
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
@ -19,6 +21,7 @@ import TaskModal from '@/components/Modals/TaskModal.vue'
|
||||
import NoteModal from '@/components/Modals/NoteModal.vue'
|
||||
import { call } from 'frappe-ui'
|
||||
import { ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const props = defineProps({
|
||||
doctype: String,
|
||||
@ -74,6 +77,19 @@ function showNote(n) {
|
||||
showNoteModal.value = true
|
||||
}
|
||||
|
||||
// common
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
function redirect(tabName) {
|
||||
if (route.name == 'Lead' || route.name == 'Deal') {
|
||||
let hash = '#' + tabName
|
||||
if (route.hash != hash) {
|
||||
router.push({ ...route, hash })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showTask,
|
||||
deleteTask,
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
@update:modelValue="
|
||||
() => {
|
||||
content += emoji
|
||||
$refs.textarea.$el.focus()
|
||||
$refs.textareaRef.el.focus()
|
||||
capture('whatsapp_emoji_added')
|
||||
}
|
||||
"
|
||||
@ -50,7 +50,7 @@
|
||||
</IconPicker>
|
||||
</div>
|
||||
<Textarea
|
||||
ref="textarea"
|
||||
ref="textareaRef"
|
||||
type="textarea"
|
||||
class="min-h-8 w-full"
|
||||
:rows="rows"
|
||||
@ -58,7 +58,7 @@
|
||||
:placeholder="placeholder"
|
||||
@focus="rows = 6"
|
||||
@blur="rows = 1"
|
||||
@keydown.enter="(e) => sendTextMessage(e)"
|
||||
@keydown.enter.stop="(e) => sendTextMessage(e)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -78,7 +78,7 @@ const doc = defineModel()
|
||||
const whatsapp = defineModel('whatsapp')
|
||||
const reply = defineModel('reply')
|
||||
const rows = ref(1)
|
||||
const textarea = ref(null)
|
||||
const textareaRef = ref(null)
|
||||
const emoji = ref('')
|
||||
|
||||
const content = ref('')
|
||||
@ -86,7 +86,7 @@ const placeholder = ref(__('Type your message here...'))
|
||||
const fileType = ref('')
|
||||
|
||||
function show() {
|
||||
nextTick(() => textarea.value.$el.focus())
|
||||
nextTick(() => textareaRef.value.el.focus())
|
||||
}
|
||||
|
||||
function uploadFile(file) {
|
||||
@ -99,7 +99,7 @@ function uploadFile(file) {
|
||||
function sendTextMessage(event) {
|
||||
if (event.shiftKey) return
|
||||
sendWhatsAppMessage()
|
||||
textarea.value.$el.blur()
|
||||
textareaRef.value.el?.blur()
|
||||
content.value = ''
|
||||
capture('whatsapp_send_message')
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
<FormControl
|
||||
v-if="field.read_only && field.type !== 'Check'"
|
||||
type="text"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
v-model="data[field.name]"
|
||||
:disabled="true"
|
||||
/>
|
||||
@ -59,7 +59,7 @@
|
||||
:class="field.prefix ? 'prefix' : ''"
|
||||
:options="field.options"
|
||||
v-model="data[field.name]"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
>
|
||||
<template v-if="field.prefix" #prefix>
|
||||
<IndicatorIcon :class="field.prefix" />
|
||||
@ -91,7 +91,7 @@
|
||||
:doctype="field.options"
|
||||
:filters="field.filters"
|
||||
@change="(v) => (data[field.name] = v)"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
:onCreate="field.create"
|
||||
/>
|
||||
<Button
|
||||
@ -113,7 +113,7 @@
|
||||
:doctype="field.options"
|
||||
:filters="field.filters"
|
||||
@change="(v) => (data[field.name] = v)"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
:hideMe="true"
|
||||
>
|
||||
<template #prefix>
|
||||
@ -182,13 +182,13 @@
|
||||
<DateTimePicker
|
||||
v-else-if="field.type === 'Datetime'"
|
||||
v-model="data[field.name]"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
input-class="border-none"
|
||||
/>
|
||||
<DatePicker
|
||||
v-else-if="field.type === 'Date'"
|
||||
v-model="data[field.name]"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
input-class="border-none"
|
||||
/>
|
||||
<FormControl
|
||||
@ -196,19 +196,19 @@
|
||||
['Small Text', 'Text', 'Long Text'].includes(field.type)
|
||||
"
|
||||
type="textarea"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
v-model="data[field.name]"
|
||||
/>
|
||||
<FormControl
|
||||
v-else-if="['Int'].includes(field.type)"
|
||||
type="number"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
v-model="data[field.name]"
|
||||
/>
|
||||
<FormControl
|
||||
v-else
|
||||
type="text"
|
||||
:placeholder="__(field.placeholder || field.label)"
|
||||
:placeholder="getPlaceholder(field)"
|
||||
v-model="data[field.name]"
|
||||
:disabled="Boolean(field.read_only)"
|
||||
/>
|
||||
@ -235,6 +235,17 @@ const props = defineProps({
|
||||
sections: Array,
|
||||
data: Object,
|
||||
})
|
||||
|
||||
const getPlaceholder = (field) => {
|
||||
if (field.placeholder) {
|
||||
return __(field.placeholder)
|
||||
}
|
||||
if (['Select', 'Link'].includes(field.type)) {
|
||||
return __('Select {0}', [__(field.label)])
|
||||
} else {
|
||||
return __('Enter {0}', [__(field.label)])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -141,7 +141,7 @@ const props = defineProps({
|
||||
const show = defineModel()
|
||||
const tasks = defineModel('reloadTasks')
|
||||
|
||||
const emit = defineEmits(['updateTask'])
|
||||
const emit = defineEmits(['updateTask', 'after'])
|
||||
|
||||
const router = useRouter()
|
||||
const { getUser } = usersStore()
|
||||
@ -202,6 +202,7 @@ async function updateTask() {
|
||||
if (d.name) {
|
||||
capture('task_created')
|
||||
tasks.value.reload()
|
||||
emit('after')
|
||||
}
|
||||
}
|
||||
show.value = false
|
||||
|
||||
@ -147,10 +147,11 @@ function getRoute(notification) {
|
||||
dealId: notification.reference_name,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: notification.route_name,
|
||||
params: params,
|
||||
hash: '#' + notification.comment || notification.notification_type_doc,
|
||||
hash: notification.hash,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,9 +55,9 @@
|
||||
v-else-if="field.type === 'select'"
|
||||
class="form-control cursor-pointer [&_select]:cursor-pointer"
|
||||
type="select"
|
||||
:value="data[field.name]"
|
||||
v-model="data[field.name]"
|
||||
:options="field.options"
|
||||
:debounce="500"
|
||||
:placeholder="field.placeholder"
|
||||
@change.stop="emit('update', field.name, $event.target.value)"
|
||||
/>
|
||||
<Link
|
||||
@ -141,7 +141,7 @@ const data = defineModel()
|
||||
const _fields = computed(() => {
|
||||
let all_fields = []
|
||||
props.fields?.forEach((field) => {
|
||||
let df = field.all_properties
|
||||
let df = field?.all_properties
|
||||
if (df?.depends_on) evaluate_depends_on(df.depends_on, field)
|
||||
all_fields.push({
|
||||
...field,
|
||||
|
||||
@ -133,9 +133,9 @@ function saveChanges() {
|
||||
let _sections = JSON.parse(JSON.stringify(sections.data))
|
||||
_sections.forEach((section) => {
|
||||
if (!section.fields) return
|
||||
section.fields = section.fields.map(
|
||||
(field) => field.fieldname || field.name,
|
||||
)
|
||||
section.fields = section.fields
|
||||
.map((field) => field.name || field.fieldname)
|
||||
.filter(Boolean)
|
||||
})
|
||||
loading.value = true
|
||||
call(
|
||||
|
||||
@ -3,16 +3,17 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
import { useDebounceFn, useStorage } from '@vueuse/core'
|
||||
|
||||
export function useActiveTabManager(tabs, storageKey) {
|
||||
const activieTab = useStorage(storageKey, 'activity')
|
||||
const activeTab = useStorage(storageKey, 'activity')
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const preserveLastVisitedTab = useDebounceFn((tabName) => {
|
||||
activieTab.value = tabName.toLowerCase()
|
||||
activeTab.value = tabName.toLowerCase()
|
||||
}, 300)
|
||||
|
||||
function setActiveTabInUrl(tabName) {
|
||||
let hash = '#' + tabName.toLowerCase()
|
||||
if (route.hash === hash) return
|
||||
router.push({ ...route, hash })
|
||||
}
|
||||
|
||||
@ -21,7 +22,7 @@ export function useActiveTabManager(tabs, storageKey) {
|
||||
}
|
||||
|
||||
function findTabIndex(tabName) {
|
||||
return tabs.value.findIndex(
|
||||
return tabs.value?.findIndex(
|
||||
(tabOptions) => tabOptions.name.toLowerCase() === tabName,
|
||||
)
|
||||
}
|
||||
@ -31,22 +32,18 @@ export function useActiveTabManager(tabs, storageKey) {
|
||||
return index !== -1 ? index : 0 // Default to the first tab if not found
|
||||
}
|
||||
|
||||
function getActiveTabFromLocalStorage() {
|
||||
return activieTab.value
|
||||
}
|
||||
|
||||
function getActiveTab() {
|
||||
let activeTab = getActiveTabFromUrl()
|
||||
if (activeTab) {
|
||||
let index = findTabIndex(activeTab)
|
||||
let _activeTab = getActiveTabFromUrl()
|
||||
if (_activeTab) {
|
||||
let index = findTabIndex(_activeTab)
|
||||
if (index !== -1) {
|
||||
preserveLastVisitedTab(activeTab)
|
||||
preserveLastVisitedTab(_activeTab)
|
||||
return index
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
let lastVisitedTab = getActiveTabFromLocalStorage()
|
||||
let lastVisitedTab = activeTab.value
|
||||
if (lastVisitedTab) {
|
||||
return getTabIndex(lastVisitedTab)
|
||||
}
|
||||
@ -57,7 +54,7 @@ export function useActiveTabManager(tabs, storageKey) {
|
||||
const tabIndex = ref(getActiveTab())
|
||||
|
||||
watch(tabIndex, (tabIndexValue) => {
|
||||
let currentTab = tabs.value[tabIndexValue].name
|
||||
let currentTab = tabs.value?.[tabIndexValue].name
|
||||
setActiveTabInUrl(currentTab)
|
||||
preserveLastVisitedTab(currentTab)
|
||||
})
|
||||
@ -71,11 +68,15 @@ export function useActiveTabManager(tabs, storageKey) {
|
||||
let index = findTabIndex(tabName)
|
||||
if (index === -1) index = 0
|
||||
|
||||
let currentTab = tabs.value[index].name
|
||||
let currentTab = tabs.value?.[index].name
|
||||
preserveLastVisitedTab(currentTab)
|
||||
tabIndex.value = index
|
||||
},
|
||||
)
|
||||
|
||||
watch(tabs, () => {
|
||||
tabIndex.value = getActiveTab()
|
||||
})
|
||||
|
||||
return { tabIndex }
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
<Activities
|
||||
ref="activities"
|
||||
doctype="CRM Deal"
|
||||
:title="tab.name"
|
||||
:tabs="tabs"
|
||||
v-model:reload="reload"
|
||||
v-model:tabIndex="tabIndex"
|
||||
v-model="deal"
|
||||
@ -356,7 +356,6 @@ import { ref, computed, h, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useActiveTabManager } from '@/composables/useActiveTabManager'
|
||||
|
||||
|
||||
const { $dialog, $socket, makeCall } = globalStore()
|
||||
const { statusOptions, getDealStatus } = statusesStore()
|
||||
const { isManager } = usersStore()
|
||||
|
||||
@ -45,7 +45,6 @@
|
||||
<Activities
|
||||
ref="activities"
|
||||
doctype="CRM Lead"
|
||||
:title="tab.name"
|
||||
:tabs="tabs"
|
||||
v-model:reload="reload"
|
||||
v-model:tabIndex="tabIndex"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user