1
0
forked from test/crm

Merge pull request #389 from frappe/develop

chore: Merge develop to main
This commit is contained in:
Shariq Ansari 2024-10-01 12:22:42 +05:30 committed by GitHub
commit c6edba6622
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 2009 additions and 121 deletions

View File

@ -18,16 +18,18 @@ def notify_mentions(doc):
if not content: if not content:
return return
mentions = extract_mentions(content) mentions = extract_mentions(content)
reference_doc = frappe.get_doc(doc.reference_doctype, doc.reference_name)
for mention in mentions: for mention in mentions:
owner = frappe.get_cached_value("User", doc.owner, "full_name") owner = frappe.get_cached_value("User", doc.owner, "full_name")
doctype = doc.reference_doctype doctype = doc.reference_doctype
if doctype.startswith("CRM "): if doctype.startswith("CRM "):
doctype = doctype[4:].lower() 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""" notification_text = f"""
<div class="mb-2 leading-5 text-gray-600"> <div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ owner }</span> <span class="font-medium text-gray-900">{ owner }</span>
<span>{ _('mentioned you in {0}').format(doctype) }</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> </div>
""" """
notify_user({ notify_user({

View File

@ -617,6 +617,7 @@ def get_field_obj(field):
obj["placeholder"] = field.get("placeholder") or "Select " + field.label + "..." obj["placeholder"] = field.get("placeholder") or "Select " + field.label + "..."
obj["doctype"] = field.options obj["doctype"] = field.options
elif field.fieldtype == "Select" and 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")] obj["options"] = [{"label": option, "value": option} for option in field.options.split("\n")]
if field.read_only: if field.read_only:

View File

@ -27,7 +27,7 @@ def get_notifications():
"type": notification.type, "type": notification.type,
"to_user": notification.to_user, "to_user": notification.to_user,
"read": notification.read, "read": notification.read,
"comment": notification.comment, "hash": get_hash(notification),
"notification_text": notification.notification_text, "notification_text": notification.notification_text,
"notification_type_doctype": notification.notification_type_doctype, "notification_type_doctype": notification.notification_type_doctype,
"notification_type_doc": notification.notification_type_doc, "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 = frappe.get_doc("CRM Notification", n.name)
d.read = True d.read = True
d.save() 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

View File

@ -52,8 +52,8 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
if doctype.startswith("CRM "): if doctype.startswith("CRM "):
doctype = doctype[4:].lower() doctype = doctype[4:].lower()
if doctype in ["CRM Lead", "CRM Deal"]: if doctype in ["lead", "deal"]:
name = reference_doc.lead_name or name if doctype == "CRM Lead" else reference_doc.organization or reference_doc.lead_name or name name = reference_doc.lead_name or name if doctype == "lead" else reference_doc.organization or reference_doc.lead_name or name
if is_cancelled: if is_cancelled:
return f""" return f"""
@ -76,7 +76,7 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
</div> </div>
""" """
if doc.reference_type == "CRM Task": if doctype == "task":
if is_cancelled: if is_cancelled:
return f""" return f"""
<div class="mb-2 leading-5 text-gray-600"> <div class="mb-2 leading-5 text-gray-600">

@ -1 +1 @@
Subproject commit cf4e7d347237c23ebde5f5c890abdf7e81284961 Subproject commit 427b76188fe8b20e683bccf9bb4003821253259f

View File

@ -14,7 +14,7 @@
"@vueuse/core": "^10.3.0", "@vueuse/core": "^10.3.0",
"@vueuse/integrations": "^10.3.0", "@vueuse/integrations": "^10.3.0",
"feather-icons": "^4.28.0", "feather-icons": "^4.28.0",
"frappe-ui": "^0.1.66", "frappe-ui": "^0.1.70",
"gemoji": "^8.1.0", "gemoji": "^8.1.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mime": "^4.0.1", "mime": "^4.0.1",

View File

@ -457,10 +457,6 @@ const { getUser } = usersStore()
const { getContact, getLeadContact } = contactsStore() const { getContact, getLeadContact } = contactsStore()
const props = defineProps({ const props = defineProps({
title: {
type: String,
default: 'Activity',
},
doctype: { doctype: {
type: String, type: String,
default: 'CRM Lead', default: 'CRM Lead',
@ -471,6 +467,8 @@ const props = defineProps({
}, },
}) })
const route = useRoute()
const doc = defineModel() const doc = defineModel()
const reload = defineModel('reload') const reload = defineModel('reload')
const tabIndex = defineModel('tabIndex') const tabIndex = defineModel('tabIndex')
@ -478,6 +476,8 @@ const tabIndex = defineModel('tabIndex')
const reload_email = ref(false) const reload_email = ref(false)
const modalRef = ref(null) const modalRef = ref(null)
const title = computed(() => props.tabs?.[tabIndex.value]?.name || 'Activity')
const all_activities = createResource({ const all_activities = createResource({
url: 'crm.api.activities.get_activities', url: 'crm.api.activities.get_activities',
params: { name: doc.value.data.name }, params: { name: doc.value.data.name },
@ -549,6 +549,14 @@ onMounted(() => {
whatsappMessages.reload() 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) { function sendTemplate(template) {
@ -577,25 +585,25 @@ function get_activities() {
const activities = computed(() => { const activities = computed(() => {
let activities = [] let activities = []
if (props.title == 'Activity') { if (title.value == 'Activity') {
activities = get_activities() activities = get_activities()
} else if (props.title == 'Emails') { } else if (title.value == 'Emails') {
if (!all_activities.data?.versions) return [] if (!all_activities.data?.versions) return []
activities = all_activities.data.versions.filter( activities = all_activities.data.versions.filter(
(activity) => activity.activity_type === 'communication', (activity) => activity.activity_type === 'communication',
) )
} else if (props.title == 'Comments') { } else if (title.value == 'Comments') {
if (!all_activities.data?.versions) return [] if (!all_activities.data?.versions) return []
activities = all_activities.data.versions.filter( activities = all_activities.data.versions.filter(
(activity) => activity.activity_type === 'comment', (activity) => activity.activity_type === 'comment',
) )
} else if (props.title == 'Calls') { } else if (title.value == 'Calls') {
if (!all_activities.data?.calls) return [] if (!all_activities.data?.calls) return []
return sortByCreation(all_activities.data.calls) return sortByCreation(all_activities.data.calls)
} else if (props.title == 'Tasks') { } else if (title.value == 'Tasks') {
if (!all_activities.data?.tasks) return [] if (!all_activities.data?.tasks) return []
return sortByCreation(all_activities.data.tasks) return sortByCreation(all_activities.data.tasks)
} else if (props.title == 'Notes') { } else if (title.value == 'Notes') {
if (!all_activities.data?.notes) return [] if (!all_activities.data?.notes) return []
return sortByCreation(all_activities.data.notes) return sortByCreation(all_activities.data.notes)
} }
@ -649,17 +657,17 @@ function update_activities_details(activity) {
const emptyText = computed(() => { const emptyText = computed(() => {
let text = 'No Activities' let text = 'No Activities'
if (props.title == 'Emails') { if (title.value == 'Emails') {
text = 'No Email Communications' text = 'No Email Communications'
} else if (props.title == 'Comments') { } else if (title.value == 'Comments') {
text = 'No Comments' text = 'No Comments'
} else if (props.title == 'Calls') { } else if (title.value == 'Calls') {
text = 'No Call Logs' text = 'No Call Logs'
} else if (props.title == 'Notes') { } else if (title.value == 'Notes') {
text = 'No Notes' text = 'No Notes'
} else if (props.title == 'Tasks') { } else if (title.value == 'Tasks') {
text = 'No Tasks' text = 'No Tasks'
} else if (props.title == 'WhatsApp') { } else if (title.value == 'WhatsApp') {
text = 'No WhatsApp Messages' text = 'No WhatsApp Messages'
} }
return text return text
@ -667,17 +675,17 @@ const emptyText = computed(() => {
const emptyTextIcon = computed(() => { const emptyTextIcon = computed(() => {
let icon = ActivityIcon let icon = ActivityIcon
if (props.title == 'Emails') { if (title.value == 'Emails') {
icon = Email2Icon icon = Email2Icon
} else if (props.title == 'Comments') { } else if (title.value == 'Comments') {
icon = CommentIcon icon = CommentIcon
} else if (props.title == 'Calls') { } else if (title.value == 'Calls') {
icon = PhoneIcon icon = PhoneIcon
} else if (props.title == 'Notes') { } else if (title.value == 'Notes') {
icon = NoteIcon icon = NoteIcon
} else if (props.title == 'Tasks') { } else if (title.value == 'Tasks') {
icon = TaskIcon icon = TaskIcon
} else if (props.title == 'WhatsApp') { } else if (title.value == 'WhatsApp') {
icon = WhatsAppIcon icon = WhatsAppIcon
} }
return h(icon, { class: 'text-gray-500' }) return h(icon, { class: 'text-gray-500' })
@ -720,6 +728,7 @@ watch([reload, reload_email], ([reload_value, reload_email_value]) => {
}) })
function scroll(hash) { function scroll(hash) {
if (['tasks', 'notes'].includes(route.hash?.slice(1))) return
setTimeout(() => { setTimeout(() => {
let el let el
if (!hash) { if (!hash) {
@ -736,11 +745,4 @@ function scroll(hash) {
} }
defineExpose({ emailBox }) defineExpose({ emailBox })
const route = useRoute()
nextTick(() => {
const hash = route.hash.slice(1) || null
scroll(hash)
})
</script> </script>

View File

@ -5,6 +5,7 @@
:task="task" :task="task"
:doctype="doctype" :doctype="doctype"
:doc="doc.data?.name" :doc="doc.data?.name"
@after="redirect('tasks')"
/> />
<NoteModal <NoteModal
v-model="showNoteModal" v-model="showNoteModal"
@ -12,6 +13,7 @@
:note="note" :note="note"
:doctype="doctype" :doctype="doctype"
:doc="doc.data?.name" :doc="doc.data?.name"
@after="redirect('notes')"
/> />
</template> </template>
<script setup> <script setup>
@ -19,6 +21,7 @@ import TaskModal from '@/components/Modals/TaskModal.vue'
import NoteModal from '@/components/Modals/NoteModal.vue' import NoteModal from '@/components/Modals/NoteModal.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'
const props = defineProps({ const props = defineProps({
doctype: String, doctype: String,
@ -74,6 +77,19 @@ function showNote(n) {
showNoteModal.value = true 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({ defineExpose({
showTask, showTask,
deleteTask, deleteTask,

View File

@ -38,7 +38,7 @@
@update:modelValue=" @update:modelValue="
() => { () => {
content += emoji content += emoji
$refs.textarea.$el.focus() $refs.textareaRef.el.focus()
capture('whatsapp_emoji_added') capture('whatsapp_emoji_added')
} }
" "
@ -50,7 +50,7 @@
</IconPicker> </IconPicker>
</div> </div>
<Textarea <Textarea
ref="textarea" ref="textareaRef"
type="textarea" type="textarea"
class="min-h-8 w-full" class="min-h-8 w-full"
:rows="rows" :rows="rows"
@ -58,7 +58,7 @@
:placeholder="placeholder" :placeholder="placeholder"
@focus="rows = 6" @focus="rows = 6"
@blur="rows = 1" @blur="rows = 1"
@keydown.enter="(e) => sendTextMessage(e)" @keydown.enter.stop="(e) => sendTextMessage(e)"
/> />
</div> </div>
</template> </template>
@ -78,7 +78,7 @@ const doc = defineModel()
const whatsapp = defineModel('whatsapp') const whatsapp = defineModel('whatsapp')
const reply = defineModel('reply') const reply = defineModel('reply')
const rows = ref(1) const rows = ref(1)
const textarea = ref(null) const textareaRef = ref(null)
const emoji = ref('') const emoji = ref('')
const content = ref('') const content = ref('')
@ -86,7 +86,7 @@ const placeholder = ref(__('Type your message here...'))
const fileType = ref('') const fileType = ref('')
function show() { function show() {
nextTick(() => textarea.value.$el.focus()) nextTick(() => textareaRef.value.el.focus())
} }
function uploadFile(file) { function uploadFile(file) {
@ -99,7 +99,7 @@ function uploadFile(file) {
function sendTextMessage(event) { function sendTextMessage(event) {
if (event.shiftKey) return if (event.shiftKey) return
sendWhatsAppMessage() sendWhatsAppMessage()
textarea.value.$el.blur() textareaRef.value.el?.blur()
content.value = '' content.value = ''
capture('whatsapp_send_message') capture('whatsapp_send_message')
} }

View File

@ -48,7 +48,7 @@
<FormControl <FormControl
v-if="field.read_only && field.type !== 'Check'" v-if="field.read_only && field.type !== 'Check'"
type="text" type="text"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
v-model="data[field.name]" v-model="data[field.name]"
:disabled="true" :disabled="true"
/> />
@ -59,7 +59,7 @@
:class="field.prefix ? 'prefix' : ''" :class="field.prefix ? 'prefix' : ''"
:options="field.options" :options="field.options"
v-model="data[field.name]" v-model="data[field.name]"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
> >
<template v-if="field.prefix" #prefix> <template v-if="field.prefix" #prefix>
<IndicatorIcon :class="field.prefix" /> <IndicatorIcon :class="field.prefix" />
@ -91,7 +91,7 @@
:doctype="field.options" :doctype="field.options"
:filters="field.filters" :filters="field.filters"
@change="(v) => (data[field.name] = v)" @change="(v) => (data[field.name] = v)"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
:onCreate="field.create" :onCreate="field.create"
/> />
<Button <Button
@ -113,7 +113,7 @@
:doctype="field.options" :doctype="field.options"
:filters="field.filters" :filters="field.filters"
@change="(v) => (data[field.name] = v)" @change="(v) => (data[field.name] = v)"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
:hideMe="true" :hideMe="true"
> >
<template #prefix> <template #prefix>
@ -182,13 +182,13 @@
<DateTimePicker <DateTimePicker
v-else-if="field.type === 'Datetime'" v-else-if="field.type === 'Datetime'"
v-model="data[field.name]" v-model="data[field.name]"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
input-class="border-none" input-class="border-none"
/> />
<DatePicker <DatePicker
v-else-if="field.type === 'Date'" v-else-if="field.type === 'Date'"
v-model="data[field.name]" v-model="data[field.name]"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
input-class="border-none" input-class="border-none"
/> />
<FormControl <FormControl
@ -196,19 +196,19 @@
['Small Text', 'Text', 'Long Text'].includes(field.type) ['Small Text', 'Text', 'Long Text'].includes(field.type)
" "
type="textarea" type="textarea"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
v-model="data[field.name]" v-model="data[field.name]"
/> />
<FormControl <FormControl
v-else-if="['Int'].includes(field.type)" v-else-if="['Int'].includes(field.type)"
type="number" type="number"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
v-model="data[field.name]" v-model="data[field.name]"
/> />
<FormControl <FormControl
v-else v-else
type="text" type="text"
:placeholder="__(field.placeholder || field.label)" :placeholder="getPlaceholder(field)"
v-model="data[field.name]" v-model="data[field.name]"
:disabled="Boolean(field.read_only)" :disabled="Boolean(field.read_only)"
/> />
@ -235,6 +235,17 @@ const props = defineProps({
sections: Array, sections: Array,
data: Object, 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> </script>
<style scoped> <style scoped>

View File

@ -141,7 +141,7 @@ const props = defineProps({
const show = defineModel() const show = defineModel()
const tasks = defineModel('reloadTasks') const tasks = defineModel('reloadTasks')
const emit = defineEmits(['updateTask']) const emit = defineEmits(['updateTask', 'after'])
const router = useRouter() const router = useRouter()
const { getUser } = usersStore() const { getUser } = usersStore()
@ -202,6 +202,7 @@ async function updateTask() {
if (d.name) { if (d.name) {
capture('task_created') capture('task_created')
tasks.value.reload() tasks.value.reload()
emit('after')
} }
} }
show.value = false show.value = false

View File

@ -147,10 +147,11 @@ function getRoute(notification) {
dealId: notification.reference_name, dealId: notification.reference_name,
} }
} }
return { return {
name: notification.route_name, name: notification.route_name,
params: params, params: params,
hash: '#' + notification.comment || notification.notification_type_doc, hash: notification.hash,
} }
} }

View File

@ -55,9 +55,9 @@
v-else-if="field.type === 'select'" v-else-if="field.type === 'select'"
class="form-control cursor-pointer [&_select]:cursor-pointer" class="form-control cursor-pointer [&_select]:cursor-pointer"
type="select" type="select"
:value="data[field.name]" v-model="data[field.name]"
:options="field.options" :options="field.options"
:debounce="500" :placeholder="field.placeholder"
@change.stop="emit('update', field.name, $event.target.value)" @change.stop="emit('update', field.name, $event.target.value)"
/> />
<Link <Link
@ -141,7 +141,7 @@ const data = defineModel()
const _fields = computed(() => { const _fields = computed(() => {
let all_fields = [] let all_fields = []
props.fields?.forEach((field) => { 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) if (df?.depends_on) evaluate_depends_on(df.depends_on, field)
all_fields.push({ all_fields.push({
...field, ...field,

View File

@ -133,9 +133,9 @@ function saveChanges() {
let _sections = JSON.parse(JSON.stringify(sections.data)) let _sections = JSON.parse(JSON.stringify(sections.data))
_sections.forEach((section) => { _sections.forEach((section) => {
if (!section.fields) return if (!section.fields) return
section.fields = section.fields.map( section.fields = section.fields
(field) => field.fieldname || field.name, .map((field) => field.name || field.fieldname)
) .filter(Boolean)
}) })
loading.value = true loading.value = true
call( call(

View File

@ -3,16 +3,17 @@ import { useRoute, useRouter } from 'vue-router'
import { useDebounceFn, useStorage } from '@vueuse/core' import { useDebounceFn, useStorage } from '@vueuse/core'
export function useActiveTabManager(tabs, storageKey) { export function useActiveTabManager(tabs, storageKey) {
const activieTab = useStorage(storageKey, 'activity') const activeTab = useStorage(storageKey, 'activity')
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const preserveLastVisitedTab = useDebounceFn((tabName) => { const preserveLastVisitedTab = useDebounceFn((tabName) => {
activieTab.value = tabName.toLowerCase() activeTab.value = tabName.toLowerCase()
}, 300) }, 300)
function setActiveTabInUrl(tabName) { function setActiveTabInUrl(tabName) {
let hash = '#' + tabName.toLowerCase() let hash = '#' + tabName.toLowerCase()
if (route.hash === hash) return
router.push({ ...route, hash }) router.push({ ...route, hash })
} }
@ -21,7 +22,7 @@ export function useActiveTabManager(tabs, storageKey) {
} }
function findTabIndex(tabName) { function findTabIndex(tabName) {
return tabs.value.findIndex( return tabs.value?.findIndex(
(tabOptions) => tabOptions.name.toLowerCase() === tabName, (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 return index !== -1 ? index : 0 // Default to the first tab if not found
} }
function getActiveTabFromLocalStorage() {
return activieTab.value
}
function getActiveTab() { function getActiveTab() {
let activeTab = getActiveTabFromUrl() let _activeTab = getActiveTabFromUrl()
if (activeTab) { if (_activeTab) {
let index = findTabIndex(activeTab) let index = findTabIndex(_activeTab)
if (index !== -1) { if (index !== -1) {
preserveLastVisitedTab(activeTab) preserveLastVisitedTab(_activeTab)
return index return index
} }
return 0 return 0
} }
let lastVisitedTab = getActiveTabFromLocalStorage() let lastVisitedTab = activeTab.value
if (lastVisitedTab) { if (lastVisitedTab) {
return getTabIndex(lastVisitedTab) return getTabIndex(lastVisitedTab)
} }
@ -57,7 +54,7 @@ export function useActiveTabManager(tabs, storageKey) {
const tabIndex = ref(getActiveTab()) const tabIndex = ref(getActiveTab())
watch(tabIndex, (tabIndexValue) => { watch(tabIndex, (tabIndexValue) => {
let currentTab = tabs.value[tabIndexValue].name let currentTab = tabs.value?.[tabIndexValue].name
setActiveTabInUrl(currentTab) setActiveTabInUrl(currentTab)
preserveLastVisitedTab(currentTab) preserveLastVisitedTab(currentTab)
}) })
@ -71,11 +68,15 @@ export function useActiveTabManager(tabs, storageKey) {
let index = findTabIndex(tabName) let index = findTabIndex(tabName)
if (index === -1) index = 0 if (index === -1) index = 0
let currentTab = tabs.value[index].name let currentTab = tabs.value?.[index].name
preserveLastVisitedTab(currentTab) preserveLastVisitedTab(currentTab)
tabIndex.value = index tabIndex.value = index
}, },
) )
watch(tabs, () => {
tabIndex.value = getActiveTab()
})
return { tabIndex } return { tabIndex }
} }

View File

@ -40,7 +40,7 @@
<Activities <Activities
ref="activities" ref="activities"
doctype="CRM Deal" doctype="CRM Deal"
:title="tab.name" :tabs="tabs"
v-model:reload="reload" v-model:reload="reload"
v-model:tabIndex="tabIndex" v-model:tabIndex="tabIndex"
v-model="deal" v-model="deal"
@ -356,7 +356,6 @@ import { ref, computed, h, onMounted, onBeforeUnmount } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useActiveTabManager } from '@/composables/useActiveTabManager' import { useActiveTabManager } from '@/composables/useActiveTabManager'
const { $dialog, $socket, makeCall } = globalStore() const { $dialog, $socket, makeCall } = globalStore()
const { statusOptions, getDealStatus } = statusesStore() const { statusOptions, getDealStatus } = statusesStore()
const { isManager } = usersStore() const { isManager } = usersStore()

View File

@ -45,7 +45,6 @@
<Activities <Activities
ref="activities" ref="activities"
doctype="CRM Lead" doctype="CRM Lead"
:title="tab.name"
:tabs="tabs" :tabs="tabs"
v-model:reload="reload" v-model:reload="reload"
v-model:tabIndex="tabIndex" v-model:tabIndex="tabIndex"

1931
yarn.lock

File diff suppressed because it is too large Load Diff