Merge pull request #691 from shariquerik/onboarding-fix
fix: Onboarding fixes
This commit is contained in:
commit
48845491d1
BIN
crm/public/videos/changeDealStatus.mov
Normal file
BIN
crm/public/videos/changeDealStatus.mov
Normal file
Binary file not shown.
BIN
crm/public/videos/convertToDeal.mov
Normal file
BIN
crm/public/videos/convertToDeal.mov
Normal file
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit b6efd25b2122c2c1f3beeea1702788c5e6e5555f
|
Subproject commit 3423aa5b5c38d3a1b143ae8ab08cbde7360f9a7c
|
||||||
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -192,7 +192,6 @@ declare module 'vue' {
|
|||||||
SidePanelLayout: typeof import('./src/components/SidePanelLayout.vue')['default']
|
SidePanelLayout: typeof import('./src/components/SidePanelLayout.vue')['default']
|
||||||
SidePanelLayoutEditor: typeof import('./src/components/SidePanelLayoutEditor.vue')['default']
|
SidePanelLayoutEditor: typeof import('./src/components/SidePanelLayoutEditor.vue')['default']
|
||||||
SidePanelModal: typeof import('./src/components/Modals/SidePanelModal.vue')['default']
|
SidePanelModal: typeof import('./src/components/Modals/SidePanelModal.vue')['default']
|
||||||
SignupBanner: typeof import('./src/components/SignupBanner.vue')['default']
|
|
||||||
SLASection: typeof import('./src/components/SLASection.vue')['default']
|
SLASection: typeof import('./src/components/SLASection.vue')['default']
|
||||||
SmileIcon: typeof import('./src/components/Icons/SmileIcon.vue')['default']
|
SmileIcon: typeof import('./src/components/Icons/SmileIcon.vue')['default']
|
||||||
SortBy: typeof import('./src/components/SortBy.vue')['default']
|
SortBy: typeof import('./src/components/SortBy.vue')['default']
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@twilio/voice-sdk": "^2.10.2",
|
"@twilio/voice-sdk": "^2.10.2",
|
||||||
"@vueuse/integrations": "^10.3.0",
|
"@vueuse/integrations": "^10.3.0",
|
||||||
"frappe-ui": "^0.1.119",
|
"frappe-ui": "^0.1.120",
|
||||||
"gemoji": "^8.1.0",
|
"gemoji": "^8.1.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mime": "^4.0.1",
|
"mime": "^4.0.1",
|
||||||
|
|||||||
@ -72,14 +72,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 flex flex-col gap-1">
|
<div class="m-2 flex flex-col gap-1">
|
||||||
<SignupBanner :isSidebarCollapsed="isSidebarCollapsed" />
|
<div class="flex flex-col gap-2 mb-1">
|
||||||
<TrialBanner v-if="isFCSite" :isSidebarCollapsed="isSidebarCollapsed" />
|
<SignupBanner
|
||||||
<GettingStartedBanner
|
v-if="isDemoSite"
|
||||||
v-if="!isOnboardingStepsCompleted"
|
:isSidebarCollapsed="isSidebarCollapsed"
|
||||||
:isSidebarCollapsed="isSidebarCollapsed"
|
:afterSignup="() => capture('signup_from_demo_site')"
|
||||||
/>
|
/>
|
||||||
|
<TrialBanner
|
||||||
|
v-if="isFCSite"
|
||||||
|
:isSidebarCollapsed="isSidebarCollapsed"
|
||||||
|
:afterUpgrade="() => capture('upgrade_plan_from_trial_banner')"
|
||||||
|
/>
|
||||||
|
<GettingStartedBanner
|
||||||
|
v-if="!isOnboardingStepsCompleted"
|
||||||
|
:isSidebarCollapsed="isSidebarCollapsed"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
v-else
|
v-if="isOnboardingStepsCompleted"
|
||||||
:label="__('Help')"
|
:label="__('Help')"
|
||||||
:isCollapsed="isSidebarCollapsed"
|
:isCollapsed="isSidebarCollapsed"
|
||||||
@click="
|
@click="
|
||||||
@ -118,9 +128,14 @@
|
|||||||
:logo="CRMLogo"
|
:logo="CRMLogo"
|
||||||
:afterSkip="(step) => capture('onboarding_step_skipped_' + step)"
|
:afterSkip="(step) => capture('onboarding_step_skipped_' + step)"
|
||||||
:afterSkipAll="() => capture('onboarding_steps_skipped')"
|
:afterSkipAll="() => capture('onboarding_steps_skipped')"
|
||||||
:afterReset="() => capture('onboarding_steps_reset')"
|
:afterReset="(step) => capture('onboarding_step_reset_' + step)"
|
||||||
|
:afterResetAll="() => capture('onboarding_steps_reset')"
|
||||||
docsLink="https://docs.frappe.io/crm"
|
docsLink="https://docs.frappe.io/crm"
|
||||||
/>
|
/>
|
||||||
|
<IntermediateStepModal
|
||||||
|
v-model="showIntermediateModal"
|
||||||
|
:currentStep="currentStep"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -148,7 +163,6 @@ import HelpIcon from '@/components/Icons/HelpIcon.vue'
|
|||||||
import SidebarLink from '@/components/SidebarLink.vue'
|
import SidebarLink from '@/components/SidebarLink.vue'
|
||||||
import Notifications from '@/components/Notifications.vue'
|
import Notifications from '@/components/Notifications.vue'
|
||||||
import Settings from '@/components/Settings/Settings.vue'
|
import Settings from '@/components/Settings/Settings.vue'
|
||||||
import SignupBanner from '@/components/SignupBanner.vue'
|
|
||||||
import { viewsStore } from '@/stores/views'
|
import { viewsStore } from '@/stores/views'
|
||||||
import {
|
import {
|
||||||
unreadNotificationsCount,
|
unreadNotificationsCount,
|
||||||
@ -157,12 +171,14 @@ import {
|
|||||||
import { showSettings, activeSettingsPage } from '@/composables/settings'
|
import { showSettings, activeSettingsPage } from '@/composables/settings'
|
||||||
import { FeatherIcon, call } from 'frappe-ui'
|
import { FeatherIcon, call } from 'frappe-ui'
|
||||||
import {
|
import {
|
||||||
|
SignupBanner,
|
||||||
TrialBanner,
|
TrialBanner,
|
||||||
HelpModal,
|
HelpModal,
|
||||||
GettingStartedBanner,
|
GettingStartedBanner,
|
||||||
useOnboarding,
|
useOnboarding,
|
||||||
showHelpModal,
|
showHelpModal,
|
||||||
minimize,
|
minimize,
|
||||||
|
IntermediateStepModal,
|
||||||
} from 'frappe-ui/frappe'
|
} from 'frappe-ui/frappe'
|
||||||
import { capture } from '@/telemetry'
|
import { capture } from '@/telemetry'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
@ -175,6 +191,7 @@ const { toggle: toggleNotificationPanel } = notificationsStore()
|
|||||||
const isSidebarCollapsed = useStorage('isSidebarCollapsed', false)
|
const isSidebarCollapsed = useStorage('isSidebarCollapsed', false)
|
||||||
|
|
||||||
const isFCSite = ref(window.is_fc_site)
|
const isFCSite = ref(window.is_fc_site)
|
||||||
|
const isDemoSite = ref(window.is_demo_site)
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
{
|
{
|
||||||
@ -284,19 +301,21 @@ function getIcon(routeName, icon) {
|
|||||||
// onboarding
|
// onboarding
|
||||||
const { isOnboardingStepsCompleted, setUp } = useOnboarding('frappecrm')
|
const { isOnboardingStepsCompleted, setUp } = useOnboarding('frappecrm')
|
||||||
|
|
||||||
const firstLead = ref('')
|
|
||||||
const firstDeal = ref('')
|
|
||||||
|
|
||||||
async function getFirstLead() {
|
async function getFirstLead() {
|
||||||
if (firstLead.value) return firstLead.value
|
let firstLead = localStorage.getItem('firstLead')
|
||||||
|
if (firstLead) return firstLead
|
||||||
return await call('crm.api.onboarding.get_first_lead')
|
return await call('crm.api.onboarding.get_first_lead')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFirstDeal() {
|
async function getFirstDeal() {
|
||||||
if (firstDeal.value) return firstDeal.value
|
let firstDeal = localStorage.getItem('firstDeal')
|
||||||
|
if (firstDeal) return firstDeal
|
||||||
return await call('crm.api.onboarding.get_first_deal')
|
return await call('crm.api.onboarding.get_first_deal')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showIntermediateModal = ref(false)
|
||||||
|
const currentStep = ref({})
|
||||||
|
|
||||||
const steps = reactive([
|
const steps = reactive([
|
||||||
{
|
{
|
||||||
name: 'create_first_lead',
|
name: 'create_first_lead',
|
||||||
@ -327,13 +346,23 @@ const steps = reactive([
|
|||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
minimize.value = true
|
minimize.value = true
|
||||||
|
|
||||||
let lead = await getFirstLead()
|
currentStep.value = {
|
||||||
|
title: __('Convert lead to deal'),
|
||||||
|
buttonLabel: __('Convert'),
|
||||||
|
videoURL: '/assets/crm/videos/convertToDeal.mov',
|
||||||
|
onClick: async () => {
|
||||||
|
showIntermediateModal.value = false
|
||||||
|
currentStep.value = {}
|
||||||
|
|
||||||
if (lead) {
|
let lead = await getFirstLead()
|
||||||
router.push({ name: 'Lead', params: { leadId: lead } })
|
if (lead) {
|
||||||
} else {
|
router.push({ name: 'Lead', params: { leadId: lead } })
|
||||||
router.push({ name: 'Leads' })
|
} else {
|
||||||
|
router.push({ name: 'Leads' })
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
showIntermediateModal.value = true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -423,17 +452,28 @@ const steps = reactive([
|
|||||||
completed: false,
|
completed: false,
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
minimize.value = true
|
minimize.value = true
|
||||||
let deal = await getFirstDeal()
|
|
||||||
|
|
||||||
if (deal) {
|
currentStep.value = {
|
||||||
router.push({
|
title: __('Change deal status'),
|
||||||
name: 'Deal',
|
buttonLabel: __('Change'),
|
||||||
params: { dealId: deal },
|
videoURL: '/assets/crm/videos/changeDealStatus.mov',
|
||||||
hash: '#activity',
|
onClick: async () => {
|
||||||
})
|
showIntermediateModal.value = false
|
||||||
} else {
|
currentStep.value = {}
|
||||||
router.push({ name: 'Leads' })
|
|
||||||
|
let deal = await getFirstDeal()
|
||||||
|
if (deal) {
|
||||||
|
router.push({
|
||||||
|
name: 'Deal',
|
||||||
|
params: { dealId: deal },
|
||||||
|
hash: '#activity',
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
router.push({ name: 'Leads' })
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
showIntermediateModal.value = true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|||||||
@ -168,7 +168,9 @@ function createNewLead() {
|
|||||||
isLeadCreating.value = false
|
isLeadCreating.value = false
|
||||||
show.value = false
|
show.value = false
|
||||||
router.push({ name: 'Lead', params: { leadId: data.name } })
|
router.push({ name: 'Lead', params: { leadId: data.name } })
|
||||||
updateOnboardingStep('create_first_lead')
|
updateOnboardingStep('create_first_lead', true, false, () => {
|
||||||
|
localStorage.setItem('firstLead', data.name)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onError(err) {
|
onError(err) {
|
||||||
isLeadCreating.value = false
|
isLeadCreating.value = false
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
v-if="!isSidebarCollapsed && showBanner"
|
|
||||||
class="m-2 flex flex-col gap-3 shadow-sm rounded-lg py-2.5 px-3 bg-surface-white text-base"
|
|
||||||
>
|
|
||||||
<div class="flex flex-col gap-1">
|
|
||||||
<div class="inline-flex gap-2 items-center font-medium">
|
|
||||||
<FeatherIcon class="h-4" name="info" />
|
|
||||||
{{ __('Loved the demo?') }}
|
|
||||||
</div>
|
|
||||||
<div class="text-ink-gray-7 text-p-sm">
|
|
||||||
{{ __('Try Frappe CRM for free with a 14-day trial.') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Button :label="__('Sign up now')" theme="blue" @click="signupNow">
|
|
||||||
<template #prefix>
|
|
||||||
<LightningIcon class="size-4" />
|
|
||||||
</template>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
import LightningIcon from '@/components/Icons/LightningIcon.vue'
|
|
||||||
import { capture } from '@/telemetry'
|
|
||||||
import { createResource } from 'frappe-ui'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
isSidebarCollapsed: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const showBanner = ref(window.is_demo_site)
|
|
||||||
|
|
||||||
function signupNow() {
|
|
||||||
capture('signup_from_demo_site')
|
|
||||||
window.open('https://frappecloud.com/crm/signup', '_blank')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -657,7 +657,9 @@ async function convertToDeal() {
|
|||||||
existingOrganizationChecked.value = false
|
existingOrganizationChecked.value = false
|
||||||
existingContact.value = ''
|
existingContact.value = ''
|
||||||
existingOrganization.value = ''
|
existingOrganization.value = ''
|
||||||
updateOnboardingStep('convert_lead_to_deal')
|
updateOnboardingStep('convert_lead_to_deal', true, false, () => {
|
||||||
|
localStorage.setItem('firstDeal', _deal)
|
||||||
|
})
|
||||||
capture('convert_lead_to_deal')
|
capture('convert_lead_to_deal')
|
||||||
router.push({ name: 'Deal', params: { dealId: _deal } })
|
router.push({ name: 'Deal', params: { dealId: _deal } })
|
||||||
}
|
}
|
||||||
|
|||||||
20
package.json
20
package.json
@ -1,9 +1,13 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"workspaces": ["frontend", "frappe-ui"],
|
"workspaces": ["frontend", "frappe-ui"],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "cd frontend && yarn install",
|
"postinstall": "cd frontend && yarn install",
|
||||||
"dev": "cd frontend && yarn dev",
|
"dev": "cd frontend && yarn dev",
|
||||||
"build": "cd frontend && yarn build"
|
"build": "cd frontend && yarn build",
|
||||||
}
|
"disable-workspaces": "sed -i '' 's/\"workspaces\"/\"aworkspaces\"/g' package.json",
|
||||||
}
|
"enable-workspaces": "sed -i '' 's/\"aworkspaces\"/\"workspaces\"/g' package.json && rm -rf node_modules ./frontend/node_modules/ frappe-ui/node_modules/ && yarn install",
|
||||||
|
"upgrade-frappeui": "cd frontend && yarn add frappe-ui@latest && cd ..",
|
||||||
|
"disable-workspaces-and-upgrade-frappeui": "yarn disable-workspaces && yarn upgrade-frappeui"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -2542,10 +2542,10 @@ fraction.js@^4.3.7:
|
|||||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
||||||
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
||||||
|
|
||||||
frappe-ui@^0.1.119:
|
frappe-ui@^0.1.120:
|
||||||
version "0.1.119"
|
version "0.1.120"
|
||||||
resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.1.119.tgz#e41ff3a7ea3ff21008587564c3cefcea86e8d244"
|
resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.1.120.tgz#0ccbc626bc44ef62b0b253f2b759bb9deca1c6fd"
|
||||||
integrity sha512-qgJE3I+N+AxwTsJuTU8O1zDfSePxI8oKm+Cn6RmHTOp6SwdiRvgEu/btKXityAY6nZf6A7OAgqUI4cVHXsr7mQ==
|
integrity sha512-vwXo5Jgu5HInvA0hXpP44ItIYqK4USx0flNeT80Ffygg3uBPE7ZV9B3cWVd3RRjxWtrZvSDG0XTmXq7uuE4e9g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@headlessui/vue" "^1.7.14"
|
"@headlessui/vue" "^1.7.14"
|
||||||
"@popperjs/core" "^2.11.2"
|
"@popperjs/core" "^2.11.2"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user