diff --git a/frontend/__snapshots__/scenes-app-dashboards--new--dark.png b/frontend/__snapshots__/scenes-app-dashboards--new--dark.png index 55f0e1fbf59bb..2d2269afd3318 100644 Binary files a/frontend/__snapshots__/scenes-app-dashboards--new--dark.png and b/frontend/__snapshots__/scenes-app-dashboards--new--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-dashboards--new--light.png b/frontend/__snapshots__/scenes-app-dashboards--new--light.png index f3b6a2a26d326..4d6bed52fab2a 100644 Binary files a/frontend/__snapshots__/scenes-app-dashboards--new--light.png and b/frontend/__snapshots__/scenes-app-dashboards--new--light.png differ diff --git a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-activation--light.png b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-activation--light.png index 7ac01be8786cf..72801db4f858e 100644 Binary files a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-activation--light.png and b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-activation--light.png differ diff --git a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--light.png b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--light.png index e4704beb7187c..221586f151909 100644 Binary files a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--light.png and b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--light.png differ diff --git a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-notebooks--light.png b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-notebooks--light.png index 458b91c0296a2..2b4433e5dbc68 100644 Binary files a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-notebooks--light.png and b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-notebooks--light.png differ diff --git a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-no-email--light.png b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-no-email--light.png index 8e42d79382346..a518764172f95 100644 Binary files a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-no-email--light.png and b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-no-email--light.png differ diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index 39f106016c231..8901552b42537 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -201,6 +201,7 @@ export const FEATURE_FLAGS = { ALERTS: 'alerts', // owner: github.com/nikitaevg ERROR_TRACKING: 'error-tracking', // owner: #team-replay SETTINGS_BOUNCE_RATE_PAGE_VIEW_MODE: 'settings-bounce-rate-page-view-mode', // owner: @robbie-c + ONBOARDING_DASHBOARD_TEMPLATES: 'onboarding-dashboard-templates', // owner: @raquelmsmith MULTIPLE_BREAKDOWNS: 'multiple-breakdowns', // owner: @skoob13 #team-product-analytics WEB_ANALYTICS_LIVE_USER_COUNT: 'web-analytics-live-user-count', // owner: @robbie-c SETTINGS_SESSION_TABLE_VERSION: 'settings-session-table-version', // owner: @robbie-c diff --git a/frontend/src/scenes/dashboard/DashboardTemplateChooser.tsx b/frontend/src/scenes/dashboard/DashboardTemplateChooser.tsx index 0efb9876bd5fd..52d0056ea662f 100644 --- a/frontend/src/scenes/dashboard/DashboardTemplateChooser.tsx +++ b/frontend/src/scenes/dashboard/DashboardTemplateChooser.tsx @@ -1,5 +1,6 @@ import './DashboardTemplateChooser.scss' +import { LemonTag } from '@posthog/lemon-ui' import clsx from 'clsx' import { useActions, useValues } from 'kea' import { FallbackCoverImage } from 'lib/components/FallbackCoverImage/FallbackCoverImage' @@ -14,7 +15,11 @@ import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic' import { DashboardTemplateType } from '~/types' -export function DashboardTemplateChooser({ scope = 'default' }: DashboardTemplateProps): JSX.Element { +export function DashboardTemplateChooser({ + scope = 'default', + onItemClick, + redirectAfterCreation = true, +}: DashboardTemplateProps): JSX.Element { const templatesLogic = dashboardTemplatesLogic({ scope }) const { allTemplates, allTemplatesLoading } = useValues(templatesLogic) @@ -67,7 +72,11 @@ export function DashboardTemplateChooser({ scope = 'default' }: DashboardTemplat if (template.variables === null) { template.variables = [] } - createDashboardFromTemplate(template, template.variables || []) + createDashboardFromTemplate( + template, + template.variables || [], + redirectAfterCreation + ) } else { if (!newDashboardModalVisible) { showVariableSelectModal(template) @@ -75,6 +84,7 @@ export function DashboardTemplateChooser({ scope = 'default' }: DashboardTemplat setActiveDashboardTemplate(template) } } + onItemClick?.() }} index={index + 1} data-attr="create-dashboard-from-template" @@ -92,7 +102,7 @@ function TemplateItem({ index, 'data-attr': dataAttr, }: { - template: Pick + template: Pick onClick: () => void index: number 'data-attr': string @@ -114,6 +124,13 @@ function TemplateItem({
{template?.template_name}
+
+ {template.tags?.map((tag, index) => ( + + {tag} + + ))} +

{template?.dashboard_description ?? ' '} diff --git a/frontend/src/scenes/dashboard/DashboardTemplateVariables.tsx b/frontend/src/scenes/dashboard/DashboardTemplateVariables.tsx index 702ecb89753a5..9f8db83b4cd29 100644 --- a/frontend/src/scenes/dashboard/DashboardTemplateVariables.tsx +++ b/frontend/src/scenes/dashboard/DashboardTemplateVariables.tsx @@ -1,5 +1,6 @@ import { LemonLabel } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' +import { useEffect } from 'react' import { ActionFilter } from 'scenes/insights/filters/ActionFilter/ActionFilter' import { FilterType, InsightType } from '~/types' @@ -9,12 +10,16 @@ import { newDashboardLogic } from './newDashboardLogic' export function DashboardTemplateVariables(): JSX.Element { const { activeDashboardTemplate } = useValues(newDashboardLogic) - const theDashboardTemplateVariablesLogic = dashboardTemplateVariablesLogic({ variables: activeDashboardTemplate?.variables || [], }) const { variables } = useValues(theDashboardTemplateVariablesLogic) - const { setVariable } = useActions(theDashboardTemplateVariablesLogic) + const { setVariable, setVariables } = useActions(theDashboardTemplateVariablesLogic) + + // this is a hack, I'm not sure why it's not set properly initially. Figure it out. + useEffect(() => { + setVariables(activeDashboardTemplate?.variables || []) + }, [activeDashboardTemplate]) return (

diff --git a/frontend/src/scenes/dashboard/dashboards/templates/dashboardTemplatesLogic.tsx b/frontend/src/scenes/dashboard/dashboards/templates/dashboardTemplatesLogic.tsx index f199b7cd2eeaf..688d99404ef45 100644 --- a/frontend/src/scenes/dashboard/dashboards/templates/dashboardTemplatesLogic.tsx +++ b/frontend/src/scenes/dashboard/dashboards/templates/dashboardTemplatesLogic.tsx @@ -10,6 +10,8 @@ import type { dashboardTemplatesLogicType } from './dashboardTemplatesLogicType' export interface DashboardTemplateProps { // default is to present global templates _and_ those visible only in the current team scope?: 'default' | DashboardTemplateScope + onItemClick?: () => void + redirectAfterCreation?: boolean } export const dashboardTemplatesLogic = kea([ diff --git a/frontend/src/scenes/dashboard/newDashboardLogic.ts b/frontend/src/scenes/dashboard/newDashboardLogic.ts index d77ec832b9c47..7e03ff6170fe1 100644 --- a/frontend/src/scenes/dashboard/newDashboardLogic.ts +++ b/frontend/src/scenes/dashboard/newDashboardLogic.ts @@ -76,11 +76,19 @@ export const newDashboardLogic = kea([ addDashboard: (form: Partial) => ({ form }), setActiveDashboardTemplate: (template: DashboardTemplateType) => ({ template }), clearActiveDashboardTemplate: true, - createDashboardFromTemplate: (template: DashboardTemplateType, variables: DashboardTemplateVariableType[]) => ({ + createDashboardFromTemplate: ( + template: DashboardTemplateType, + variables: DashboardTemplateVariableType[], + redirectAfterCreation?: boolean + ) => ({ template, variables, + redirectAfterCreation, + }), + submitNewDashboardSuccessWithResult: (result: DashboardType, variables?: DashboardTemplateVariableType[]) => ({ + result, + variables, }), - submitNewDashboardSuccessWithResult: (result: DashboardType) => ({ result }), }), reducers({ isLoading: [ @@ -137,7 +145,8 @@ export const newDashboardLogic = kea([ ) actions.hideNewDashboardModal() actions.resetNewDashboard() - dashboardsModel.actions.addDashboardSuccess(getQueryBasedDashboard(result)!) + const queryBasedDashboard = getQueryBasedDashboard(result) + queryBasedDashboard && dashboardsModel.actions.addDashboardSuccess(queryBasedDashboard) actions.submitNewDashboardSuccessWithResult(result) if (show) { breakpoint() @@ -169,7 +178,8 @@ export const newDashboardLogic = kea([ actions.clearActiveDashboardTemplate() actions.resetNewDashboard() }, - createDashboardFromTemplate: async ({ template, variables }) => { + createDashboardFromTemplate: async ({ template, variables, redirectAfterCreation = true }) => { + actions.setIsLoading(true) const tiles = makeTilesUsingVariables(template.tiles, variables) const dashboardJSON = { ...template, @@ -183,9 +193,12 @@ export const newDashboardLogic = kea([ ) actions.hideNewDashboardModal() actions.resetNewDashboard() - dashboardsModel.actions.addDashboardSuccess(getQueryBasedDashboard(result)!) - actions.submitNewDashboardSuccessWithResult(result) - router.actions.push(urls.dashboard(result.id)) + const queryBasedDashboard = getQueryBasedDashboard(result) + queryBasedDashboard && dashboardsModel.actions.addDashboardSuccess(queryBasedDashboard) + actions.submitNewDashboardSuccessWithResult(result, variables) + if (redirectAfterCreation) { + router.actions.push(urls.dashboard(result.id)) + } } catch (e: any) { if (!isBreakpoint(e)) { const message = e.code && e.detail ? `${e.code}: ${e.detail}` : e diff --git a/frontend/src/scenes/onboarding/Onboarding.tsx b/frontend/src/scenes/onboarding/Onboarding.tsx index d11307ab74f15..37c6bc42cdb7f 100644 --- a/frontend/src/scenes/onboarding/Onboarding.tsx +++ b/frontend/src/scenes/onboarding/Onboarding.tsx @@ -4,6 +4,7 @@ import { FEATURE_FLAGS, SESSION_REPLAY_MINIMUM_DURATION_OPTIONS } from 'lib/cons import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { useEffect, useState } from 'react' import { billingLogic } from 'scenes/billing/billingLogic' +import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic' import { AndroidInstructions } from 'scenes/onboarding/sdks/session-replay' import { SceneExport } from 'scenes/sceneTypes' import { teamLogic } from 'scenes/teamLogic' @@ -19,6 +20,8 @@ import { OnboardingProductConfiguration } from './OnboardingProductConfiguration import { ProductConfigOption } from './onboardingProductConfigurationLogic' import { OnboardingProductIntroduction } from './OnboardingProductIntroduction' import { OnboardingReverseProxy } from './OnboardingReverseProxy' +import { OnboardingDashboardTemplateConfigureStep } from './productAnalyticsSteps/DashboardTemplateConfigureStep' +import { OnboardingDashboardTemplateSelectStep } from './productAnalyticsSteps/DashboardTemplateSelectStep' import { FeatureFlagsSDKInstructions } from './sdks/feature-flags/FeatureFlagsSDKInstructions' import { ProductAnalyticsSDKInstructions } from './sdks/product-analytics/ProductAnalyticsSDKInstructions' import { SDKs } from './sdks/SDKs' @@ -84,7 +87,7 @@ const OnboardingWrapper = ({ children }: { children: React.ReactNode }): JSX.Ele steps = [...steps, BillingStep] } const inviteTeammatesStep = - steps = [...steps, inviteTeammatesStep] + steps = [...steps, inviteTeammatesStep].filter(Boolean) setAllSteps(steps) } @@ -101,6 +104,10 @@ const OnboardingWrapper = ({ children }: { children: React.ReactNode }): JSX.Ele const ProductAnalyticsOnboarding = (): JSX.Element => { const { currentTeam } = useValues(teamLogic) + const { featureFlags } = useValues(featureFlagLogic) + // mount the logic here so that it stays mounted for the entire onboarding flow + // not sure if there is a better way to do this + useValues(newDashboardLogic) const options: ProductConfigOption[] = [ { @@ -158,6 +165,12 @@ const ProductAnalyticsOnboarding = (): JSX.Element => { stepKey={OnboardingStepKey.INSTALL} /> + {featureFlags[FEATURE_FLAGS.ONBOARDING_DASHBOARD_TEMPLATES] == 'test' ? ( + + ) : null} + {featureFlags[FEATURE_FLAGS.ONBOARDING_DASHBOARD_TEMPLATES] == 'test' ? ( + + ) : null} ) } diff --git a/frontend/src/scenes/onboarding/OnboardingStep.tsx b/frontend/src/scenes/onboarding/OnboardingStep.tsx index 5e54171335aed..9472c266d0f3a 100644 --- a/frontend/src/scenes/onboarding/OnboardingStep.tsx +++ b/frontend/src/scenes/onboarding/OnboardingStep.tsx @@ -4,8 +4,10 @@ import { useActions, useValues } from 'kea' import { supportLogic } from 'lib/components/Support/supportLogic' import { IconChevronRight } from 'lib/lemon-ui/icons' import React from 'react' +import { urls } from 'scenes/urls' -import { onboardingLogic, OnboardingStepKey, stepKeyToTitle } from './onboardingLogic' +import { breadcrumbExcludeSteps, onboardingLogic, OnboardingStepKey, stepKeyToTitle } from './onboardingLogic' +import { onboardingTemplateConfigLogic } from './productAnalyticsSteps/onboardingTemplateConfigLogic' export const OnboardingStep = ({ stepKey, @@ -19,6 +21,7 @@ export const OnboardingStep = ({ continueText, continueOverride, hideHeader, + breadcrumbHighlightName, }: { stepKey: OnboardingStepKey title: string @@ -31,14 +34,17 @@ export const OnboardingStep = ({ continueText?: string continueOverride?: JSX.Element hideHeader?: boolean + breadcrumbHighlightName?: OnboardingStepKey }): JSX.Element => { const { hasNextStep, onboardingStepKeys, currentOnboardingStep } = useValues(onboardingLogic) const { completeOnboarding, goToNextStep, setStepKey } = useActions(onboardingLogic) const { openSupportForm } = useActions(supportLogic) + const { dashboardCreatedDuringOnboarding } = useValues(onboardingTemplateConfigLogic) if (!stepKey) { throw new Error('stepKey is required in any OnboardingStep') } + const breadcrumbStepKeys = onboardingStepKeys.filter((stepKey) => !breadcrumbExcludeSteps.includes(stepKey)) return ( <> @@ -48,26 +54,24 @@ export const OnboardingStep = ({ className="flex items-center justify-start gap-x-3 px-2 shrink-0 w-full" data-attr="onboarding-breadcrumbs" > - {onboardingStepKeys.map((stepName, idx) => { + {breadcrumbStepKeys.map((stepName, idx) => { + const highlightStep = [ + currentOnboardingStep?.props.stepKey, + breadcrumbHighlightName, + ].includes(stepName) return ( setStepKey(stepName)} > - + {stepKeyToTitle(stepName)} - {onboardingStepKeys.length > 1 && idx !== onboardingStepKeys.length - 1 && ( + {breadcrumbStepKeys.length > 1 && idx !== breadcrumbStepKeys.length - 1 && ( )} @@ -96,7 +100,14 @@ export const OnboardingStep = ({ type="secondary" onClick={() => { onSkip && onSkip() - !hasNextStep ? completeOnboarding() : goToNextStep() + !hasNextStep + ? completeOnboarding( + undefined, + dashboardCreatedDuringOnboarding + ? urls.dashboard(dashboardCreatedDuringOnboarding.id) + : undefined + ) + : goToNextStep() }} data-attr="onboarding-skip-button" > @@ -112,7 +123,14 @@ export const OnboardingStep = ({ data-attr="onboarding-continue" onClick={() => { continueAction && continueAction() - !hasNextStep ? completeOnboarding() : goToNextStep() + !hasNextStep + ? completeOnboarding( + undefined, + dashboardCreatedDuringOnboarding + ? urls.dashboard(dashboardCreatedDuringOnboarding.id) + : undefined + ) + : goToNextStep() }} sideIcon={hasNextStep ? : null} > diff --git a/frontend/src/scenes/onboarding/onboardingLogic.tsx b/frontend/src/scenes/onboarding/onboardingLogic.tsx index 1cf174801d78c..6a637b81ee33e 100644 --- a/frontend/src/scenes/onboarding/onboardingLogic.tsx +++ b/frontend/src/scenes/onboarding/onboardingLogic.tsx @@ -32,8 +32,12 @@ export enum OnboardingStepKey { PRODUCT_CONFIGURATION = 'configure', REVERSE_PROXY = 'proxy', INVITE_TEAMMATES = 'invite_teammates', + DASHBOARD_TEMPLATE = 'dashboard_template', + DASHBOARD_TEMPLATE_CONFIGURE = 'dashboard_template_configure', } +export const breadcrumbExcludeSteps = [OnboardingStepKey.DASHBOARD_TEMPLATE_CONFIGURE] + export const availableOnboardingProducts: AvailableOnboardingProducts = { [ProductKey.PRODUCT_ANALYTICS]: { name: 'Product Analytics', @@ -124,16 +128,20 @@ export const onboardingLogic = kea([ actions({ setProduct: (product: OnboardingProduct | null) => ({ product }), setProductKey: (productKey: string | null) => ({ productKey }), - completeOnboarding: (nextProductKey?: string) => ({ nextProductKey }), + completeOnboarding: (nextProductKey?: string, redirectUrlOverride?: string) => ({ + nextProductKey, + redirectUrlOverride, + }), setAllOnboardingSteps: (allOnboardingSteps: AllOnboardingSteps) => ({ allOnboardingSteps }), setStepKey: (stepKey: OnboardingStepKey) => ({ stepKey }), setSubscribedDuringOnboarding: (subscribedDuringOnboarding: boolean) => ({ subscribedDuringOnboarding }), setIncludeIntro: (includeIntro: boolean) => ({ includeIntro }), setTeamPropertiesForProduct: (productKey: ProductKey) => ({ productKey }), setWaitForBilling: (waitForBilling: boolean) => ({ waitForBilling }), - goToNextStep: true, + goToNextStep: (numStepsToAdvance?: number) => ({ numStepsToAdvance }), goToPreviousStep: true, resetStepKey: true, + setOnCompleteOnboardingRedirectUrl: (url: string | null) => ({ url }), }), reducers(() => ({ productKey: [ @@ -178,6 +186,12 @@ export const onboardingLogic = kea([ setWaitForBilling: (_, { waitForBilling }) => waitForBilling, }, ], + onCompleteOnboardingRedirectUrlOverride: [ + null as string | null, + { + setOnCompleteOnboardingRedirectUrl: (_, { url }) => url, + }, + ], })), selectors({ breadcrumbs: [ @@ -200,8 +214,11 @@ export const onboardingLogic = kea([ }, ], onCompleteOnboardingRedirectUrl: [ - (s) => [s.productKey], - (productKey: string | null) => { + (s) => [s.productKey, s.onCompleteOnboardingRedirectUrlOverride], + (productKey: string | null, onCompleteOnboardingRedirectUrlOverride) => { + if (onCompleteOnboardingRedirectUrlOverride) { + return onCompleteOnboardingRedirectUrlOverride + } return productKey ? getProductUri(productKey as ProductKey) : urls.default() }, ], @@ -314,7 +331,10 @@ export const onboardingLogic = kea([ } }, - completeOnboarding: ({ nextProductKey }) => { + completeOnboarding: ({ nextProductKey, redirectUrlOverride }) => { + if (redirectUrlOverride) { + actions.setOnCompleteOnboardingRedirectUrl(redirectUrlOverride) + } if (values.productKey) { const product = values.productKey eventUsageLogic.actions.reportOnboardingCompleted(product) @@ -351,11 +371,11 @@ export const onboardingLogic = kea([ } return [`/onboarding/${values.productKey}`, router.values.searchParams] }, - goToNextStep: () => { + goToNextStep: ({ numStepsToAdvance }) => { const currentStepIndex = values.allOnboardingSteps.findIndex( (step) => step.props.stepKey === values.stepKey ) - const nextStep = values.allOnboardingSteps[currentStepIndex + 1] + const nextStep = values.allOnboardingSteps[currentStepIndex + (numStepsToAdvance || 1)] if (nextStep) { return [ `/onboarding/${values.productKey}`, diff --git a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx new file mode 100644 index 0000000000000..cc3878fed6474 --- /dev/null +++ b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx @@ -0,0 +1,54 @@ +import { LemonButton } from '@posthog/lemon-ui' +import { useActions, useValues } from 'kea' +import { useState } from 'react' +import { DashboardTemplateVariables } from 'scenes/dashboard/DashboardTemplateVariables' +import { dashboardTemplateVariablesLogic } from 'scenes/dashboard/dashboardTemplateVariablesLogic' +import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic' + +import { OnboardingStepKey } from '../onboardingLogic' +import { OnboardingStep } from '../OnboardingStep' +import { onboardingTemplateConfigLogic } from './onboardingTemplateConfigLogic' + +export const OnboardingDashboardTemplateConfigureStep = ({ + stepKey = OnboardingStepKey.DASHBOARD_TEMPLATE, +}: { + stepKey?: OnboardingStepKey +}): JSX.Element => { + const { activeDashboardTemplate } = useValues(onboardingTemplateConfigLogic) + const { createDashboardFromTemplate } = useActions(newDashboardLogic) + const { isLoading } = useValues(newDashboardLogic) + const { variables } = useValues(dashboardTemplateVariablesLogic) + + const [isSubmitting, setIsSubmitting] = useState(false) + + return ( + { + if (activeDashboardTemplate) { + setIsSubmitting(true) + createDashboardFromTemplate(activeDashboardTemplate, variables, false) + } + }} + loading={isLoading} + > + Create dashboard + + } + > + {isSubmitting || isLoading ? ( +

Creating dashboard...

+ ) : ( + <> +

Select the events or website elements that represent important parts of your funnel.

+ + + )} +
+ ) +} diff --git a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateSelectStep.tsx b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateSelectStep.tsx new file mode 100644 index 0000000000000..7a6bd9f9ea00f --- /dev/null +++ b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateSelectStep.tsx @@ -0,0 +1,46 @@ +import { LemonButton } from '@posthog/lemon-ui' +import { useActions } from 'kea' +import { useEffect } from 'react' +import { DashboardTemplateChooser } from 'scenes/dashboard/DashboardTemplateChooser' +import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic' + +import { onboardingLogic, OnboardingStepKey } from '../onboardingLogic' +import { OnboardingStep } from '../OnboardingStep' + +export const OnboardingDashboardTemplateSelectStep = ({ + stepKey = OnboardingStepKey.DASHBOARD_TEMPLATE, +}: { + stepKey?: OnboardingStepKey +}): JSX.Element => { + const { goToNextStep } = useActions(onboardingLogic) + const { clearActiveDashboardTemplate } = useActions(newDashboardLogic) + + // TODO: this is hacky, find a better way to clear the active template when coming back to this screen + useEffect(() => { + clearActiveDashboardTemplate() + }, []) + + return ( + { + goToNextStep(2) + }} + data-attr="onboarding-skip-button" + > + Skip for now + + } + > +

+ Get useful insights from your events super fast with our dashboard templates. Select one to get started + with based on your market and industry. +

+ +
+ ) +} diff --git a/frontend/src/scenes/onboarding/productAnalyticsSteps/onboardingTemplateConfigLogic.ts b/frontend/src/scenes/onboarding/productAnalyticsSteps/onboardingTemplateConfigLogic.ts new file mode 100644 index 0000000000000..3929824302c5b --- /dev/null +++ b/frontend/src/scenes/onboarding/productAnalyticsSteps/onboardingTemplateConfigLogic.ts @@ -0,0 +1,47 @@ +import { actions, connect, kea, listeners, path, reducers } from 'kea' +import { urlToAction } from 'kea-router' +import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic' + +import { DashboardType } from '~/types' + +import { onboardingLogic, OnboardingStepKey } from '../onboardingLogic' +import type { onboardingTemplateConfigLogicType } from './onboardingTemplateConfigLogicType' + +export const onboardingTemplateConfigLogic = kea([ + path(['scenes', 'onboarding', 'productAnalyticsSteps', 'onboardingTemplateConfigLogic']), + connect({ + values: [newDashboardLogic, ['activeDashboardTemplate']], + actions: [ + newDashboardLogic, + ['submitNewDashboardSuccessWithResult', 'setIsLoading'], + onboardingLogic, + ['goToPreviousStep'], + ], + }), + actions({}), + reducers({ + dashboardCreatedDuringOnboarding: [ + null as DashboardType | null, + { + submitNewDashboardSuccessWithResult: (_, { result }) => result, + }, + ], + }), + listeners({ + submitNewDashboardSuccessWithResult: ({ result, variables }) => { + if (result) { + onboardingLogic.actions.goToNextStep(variables?.length && variables.length > 0 ? 1 : 2) + } + }, + }), + urlToAction(({ actions, values }) => ({ + '/onboarding/:productKey': (_, { step }) => { + if (step === OnboardingStepKey.DASHBOARD_TEMPLATE_CONFIGURE) { + if (!values.activeDashboardTemplate || !values.activeDashboardTemplate.variables) { + actions.goToPreviousStep() + } + } + actions.setIsLoading(false) + }, + })), +])