Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new onboarding navigation #17582

Merged
merged 6 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/src/scenes/billing/billingLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const billingLogic = kea<billingLogicType>([
return window.location.pathname.includes('/ingestion')
? urls.ingestion() + '/billing'
: window.location.pathname.includes('/onboarding')
? window.location.pathname
? window.location.pathname + window.location.search
: ''
},
},
Expand Down
102 changes: 98 additions & 4 deletions frontend/src/scenes/onboarding/onboardingLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,23 @@ import { billingLogic } from 'scenes/billing/billingLogic'
export interface OnboardingLogicProps {
productKey: ProductKey | null
}

export enum OnboardingStepKey {
PRODUCT_INTRO = 'product_intro',
SDKS = 'sdks',
BILLING = 'billing',
PAIRS_WITH = 'pairs_with',
}

export type OnboardingStepMap = Record<OnboardingStepKey, string>

const onboardingStepMap: OnboardingStepMap = {
[OnboardingStepKey.PRODUCT_INTRO]: 'OnboardingProductIntro',
[OnboardingStepKey.SDKS]: 'SDKs',
[OnboardingStepKey.BILLING]: 'OnboardingBillingStep',
[OnboardingStepKey.PAIRS_WITH]: 'OnboardingPairsWithStep',
}

export type AllOnboardingSteps = JSX.Element[]

export const onboardingLogic = kea<onboardingLogicType>({
Expand Down Expand Up @@ -51,6 +68,12 @@ export const onboardingLogic = kea<onboardingLogicType>({
setAllOnboardingSteps: (_, { allOnboardingSteps }) => allOnboardingSteps as AllOnboardingSteps,
},
],
stepKey: [
'' as string,
{
setStepKey: (_, { stepKey }) => stepKey,
},
],
onCompleteOnbardingRedirectUrl: [
urls.default() as string,
{
Expand Down Expand Up @@ -110,18 +133,89 @@ export const onboardingLogic = kea<onboardingLogicType>({
completeOnboarding: () => {
window.location.href = values.onCompleteOnbardingRedirectUrl
},
setAllOnboardingSteps: ({ allOnboardingSteps }) => {
// once we have the onboarding steps we need to make sure the step key is valid,
// and if so use it to set the step number. if not valid, remove it from the state.
// valid step keys are either numbers (used for unnamed steps) or keys from the onboardingStepMap.
// if it's a number, we try to convert it to a named step key using the onboardingStepMap.
let stepKey = values.stepKey
if (values.stepKey) {
if (parseInt(values.stepKey) > 0) {
// try to convert the step number to a step key
const stepName = allOnboardingSteps[parseInt(values.stepKey) - 1]?.type?.name
const newStepKey = Object.keys(onboardingStepMap).find((key) => onboardingStepMap[key] === stepName)
if (stepName && stepKey) {
stepKey = newStepKey || stepKey
actions.setStepKey(stepKey)
}
}
if (stepKey in onboardingStepMap) {
const stepIndex = allOnboardingSteps
.map((step) => step.type.name)
.indexOf(onboardingStepMap[stepKey as OnboardingStepKey])
if (stepIndex > -1) {
actions.setCurrentOnboardingStepNumber(stepIndex + 1)
} else {
actions.setStepKey('')
actions.setCurrentOnboardingStepNumber(1)
}
} else if (
// if it's a number, just use that and set the correct onboarding step number
parseInt(stepKey) > 1 &&
allOnboardingSteps.length > 0 &&
allOnboardingSteps[parseInt(stepKey) - 1]
) {
actions.setCurrentOnboardingStepNumber(parseInt(stepKey))
}
}
},
setStepKey: ({ stepKey }) => {
// if the step key is invalid (doesn't exist in the onboardingStepMap or the allOnboardingSteps array)
// remove it from the state. Numeric step keys are also allowed, as long as they are a valid
// index for the allOnboardingSteps array.
if (
stepKey &&
values.allOnboardingSteps.length > 0 &&
(!values.allOnboardingSteps.find(
(step) => step.type.name === onboardingStepMap[stepKey as OnboardingStepKey]
) ||
!values.allOnboardingSteps[parseInt(stepKey) - 1])
) {
actions.setStepKey('')
}
},
}),
urlToAction: ({ actions }) => ({
'/onboarding/:productKey': ({ productKey }, { success, upgraded }) => {
actionToUrl: ({ values }) => ({
setCurrentOnboardingStepNumber: () => {
// when the current step number changes, update the url to reflect the new step
const stepName = values.allOnboardingSteps[values.currentOnboardingStepNumber - 1]?.type?.name
const stepKey =
Object.keys(onboardingStepMap).find((key) => onboardingStepMap[key] === stepName) ||
values.currentOnboardingStepNumber.toString()
if (stepKey) {
return [`/onboarding/${values.productKey}`, { step: stepKey }]
} else {
return [`/onboarding/${values.productKey}`]
}
},
}),
urlToAction: ({ actions, values }) => ({
'/onboarding/:productKey': ({ productKey }, { success, upgraded, step }) => {
if (!productKey) {
window.location.href = urls.default()
return
}
if (success || upgraded) {
actions.setSubscribedDuringOnboarding(true)
}
actions.setProductKey(productKey)
actions.setCurrentOnboardingStepNumber(1)
if (productKey !== values.productKey) {
actions.setProductKey(productKey)
}
if (step && (step in onboardingStepMap || parseInt(step) > 0)) {
actions.setStepKey(step)
} else {
actions.setCurrentOnboardingStepNumber(1)
}
},
}),
})
Loading