From 3a89f6296555662d7947c7aef197c97e439195b0 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Mon, 19 May 2025 13:06:38 +0530 Subject: [PATCH 1/4] fix: get filtered steps based on condition (cherry picked from commit a7784c298534dcedf4fc93ca2b63f717dfb338f6) --- .../src/components/Layouts/AppSidebar.vue | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Layouts/AppSidebar.vue b/frontend/src/components/Layouts/AppSidebar.vue index 05d5bbb0..96237ee5 100644 --- a/frontend/src/components/Layouts/AppSidebar.vue +++ b/frontend/src/components/Layouts/AppSidebar.vue @@ -168,6 +168,7 @@ import { unreadNotificationsCount, notificationsStore, } from '@/stores/notifications' +import { usersStore } from '@/stores/users' import { showSettings, activeSettingsPage } from '@/composables/settings' import { FeatherIcon, call } from 'frappe-ui' import { @@ -299,6 +300,7 @@ function getIcon(routeName, icon) { } // onboarding +const { users, isManager } = usersStore() const { isOnboardingStepsCompleted, setUp } = useOnboarding('frappecrm') async function getFirstLead() { @@ -337,6 +339,7 @@ const steps = reactive([ showSettings.value = true activeSettingsPage.value = 'Invite Members' }, + condition: () => isManager(), }, { name: 'convert_lead_to_deal', @@ -478,7 +481,18 @@ const steps = reactive([ }, ]) -onMounted(() => setUp(steps)) +onMounted(async () => { + await users.promise + + const filteredSteps = steps.filter((step) => { + if (step.condition) { + return step.condition() + } + return true + }) + + setUp(filteredSteps) +}) // help center const articles = ref([ @@ -517,9 +531,7 @@ const articles = ref([ { title: __('Capturing leads'), opened: false, - subArticles: [ - { name: 'web-form', title: __('Web form') }, - ], + subArticles: [{ name: 'web-form', title: __('Web form') }], }, { title: __('Views'), From d9e731be3c3457ab2e6bd84787845d457232138d Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Mon, 19 May 2025 13:39:06 +0530 Subject: [PATCH 2/4] fix: added dependsOn value on dependent step to gray out (cherry picked from commit 21c349e1d784cd16f5a35ed7a71fd5d0bf610f7e) --- frontend/src/components/Layouts/AppSidebar.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/components/Layouts/AppSidebar.vue b/frontend/src/components/Layouts/AppSidebar.vue index 96237ee5..81fa3cfd 100644 --- a/frontend/src/components/Layouts/AppSidebar.vue +++ b/frontend/src/components/Layouts/AppSidebar.vue @@ -346,6 +346,7 @@ const steps = reactive([ title: __('Convert lead to deal'), icon: markRaw(ConvertIcon), completed: false, + dependsOn: 'create_first_lead', onClick: async () => { minimize.value = true @@ -413,6 +414,7 @@ const steps = reactive([ title: __('Add your first comment'), icon: markRaw(CommentIcon), completed: false, + dependsOn: 'create_first_lead', onClick: async () => { minimize.value = true let deal = await getFirstDeal() @@ -433,6 +435,7 @@ const steps = reactive([ title: __('Send email'), icon: markRaw(EmailIcon), completed: false, + dependsOn: 'create_first_lead', onClick: async () => { minimize.value = true let deal = await getFirstDeal() @@ -453,6 +456,7 @@ const steps = reactive([ title: __('Change deal status'), icon: markRaw(StepsIcon), completed: false, + dependsOn: 'convert_lead_to_deal', onClick: async () => { minimize.value = true From af5bef08cac55e9cc87aaed8168ea0dfc2d6519e Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Mon, 19 May 2025 13:40:26 +0530 Subject: [PATCH 3/4] fix: change heading to paragraph in invitation email template (cherry picked from commit ddc5810c715b1e4cd5ca2bce59f09ff7f9a6a8a8) --- crm/templates/emails/crm_invitation.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crm/templates/emails/crm_invitation.html b/crm/templates/emails/crm_invitation.html index 3e74b1d1..1c44ce67 100644 --- a/crm/templates/emails/crm_invitation.html +++ b/crm/templates/emails/crm_invitation.html @@ -1,4 +1,4 @@ -

You have been invited to join Frappe CRM

+

You have been invited to join Frappe CRM

Accept Invitation

From a514a99a756c291513ab130d842f6f0f84d93d6c Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Mon, 19 May 2025 16:44:42 +0530 Subject: [PATCH 4/4] fix: store firstLead & firstDeal per user (cherry picked from commit 44523a0392daae4a1b31f86dd0508be0339cca75) --- frontend/src/components/Layouts/AppSidebar.vue | 6 ++++-- frontend/src/components/Modals/LeadModal.vue | 4 +++- frontend/src/pages/Lead.vue | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Layouts/AppSidebar.vue b/frontend/src/components/Layouts/AppSidebar.vue index 81fa3cfd..f73a4564 100644 --- a/frontend/src/components/Layouts/AppSidebar.vue +++ b/frontend/src/components/Layouts/AppSidebar.vue @@ -169,6 +169,7 @@ import { notificationsStore, } from '@/stores/notifications' import { usersStore } from '@/stores/users' +import { sessionStore } from '@/stores/session' import { showSettings, activeSettingsPage } from '@/composables/settings' import { FeatherIcon, call } from 'frappe-ui' import { @@ -300,17 +301,18 @@ function getIcon(routeName, icon) { } // onboarding +const { user } = sessionStore() const { users, isManager } = usersStore() const { isOnboardingStepsCompleted, setUp } = useOnboarding('frappecrm') async function getFirstLead() { - let firstLead = localStorage.getItem('firstLead') + let firstLead = localStorage.getItem('firstLead' + user) if (firstLead) return firstLead return await call('crm.api.onboarding.get_first_lead') } async function getFirstDeal() { - let firstDeal = localStorage.getItem('firstDeal') + let firstDeal = localStorage.getItem('firstDeal' + user) if (firstDeal) return firstDeal return await call('crm.api.onboarding.get_first_deal') } diff --git a/frontend/src/components/Modals/LeadModal.vue b/frontend/src/components/Modals/LeadModal.vue index 95e0add2..0950b401 100644 --- a/frontend/src/components/Modals/LeadModal.vue +++ b/frontend/src/components/Modals/LeadModal.vue @@ -46,6 +46,7 @@ import EditIcon from '@/components/Icons/EditIcon.vue' import FieldLayout from '@/components/FieldLayout/FieldLayout.vue' import { usersStore } from '@/stores/users' import { statusesStore } from '@/stores/statuses' +import { sessionStore } from '@/stores/session' import { isMobileView } from '@/composables/settings' import { capture } from '@/telemetry' import { createResource } from 'frappe-ui' @@ -57,6 +58,7 @@ const props = defineProps({ defaults: Object, }) +const { user } = sessionStore() const { getUser, isManager } = usersStore() const { getLeadStatus, statusOptions } = statusesStore() const { updateOnboardingStep } = useOnboarding('frappecrm') @@ -169,7 +171,7 @@ function createNewLead() { show.value = false router.push({ name: 'Lead', params: { leadId: data.name } }) updateOnboardingStep('create_first_lead', true, false, () => { - localStorage.setItem('firstLead', data.name) + localStorage.setItem('firstLead' + user, data.name) }) }, onError(err) { diff --git a/frontend/src/pages/Lead.vue b/frontend/src/pages/Lead.vue index 502aff25..dd0229b6 100644 --- a/frontend/src/pages/Lead.vue +++ b/frontend/src/pages/Lead.vue @@ -352,6 +352,7 @@ import { } from '@/utils' import { getView } from '@/utils/view' import { getSettings } from '@/stores/settings' +import { sessionStore } from '@/stores/session' import { usersStore } from '@/stores/users' import { globalStore } from '@/stores/global' import { statusesStore } from '@/stores/statuses' @@ -380,6 +381,7 @@ import { useRouter, useRoute } from 'vue-router' import { useActiveTabManager } from '@/composables/useActiveTabManager' const { brand } = getSettings() +const { user } = sessionStore() const { isManager } = usersStore() const { $dialog, $socket, makeCall } = globalStore() const { statusOptions, getLeadStatus, getDealStatus } = statusesStore() @@ -675,7 +677,7 @@ async function convertToDeal() { existingContact.value = '' existingOrganization.value = '' updateOnboardingStep('convert_lead_to_deal', true, false, () => { - localStorage.setItem('firstDeal', _deal) + localStorage.setItem('firstDeal' + user, _deal) }) capture('convert_lead_to_deal') router.push({ name: 'Deal', params: { dealId: _deal } })