Skip to content

Commit

Permalink
feat: Move onboarding into the app (#20224)
Browse files Browse the repository at this point in the history
* bring onboarding panels into the app

* tune up product intro page breadcrumbs

* combine verification and config steps

* add breadcrumbs, tune up topbar breadcrumbs

* tune up some buttons, step order

* mostly update the plans page

* Update UI snapshots for `chromium` (1)

* Update UI snapshots for `chromium` (2)

* tune up state for not first product onboarding

* Update UI snapshots for `chromium` (2)

* some type fixes

* fix up remaining tasks

* Update UI snapshots for `chromium` (1)

* make product intro onboarding step

* Only report onboarding product selected when "get started button clicked"
* Don't show intro if coming from /products page

* show verification on install screen

* fix a type error, update intro in stories

* Update UI snapshots for `chromium` (1)

* fix a type generation issue

* improve verify section

* sentence case

* make breadcrumbs smaller

* fix intro pages

* fix breadcrumbs

* update padding on onboarding steps, remove other products step

* mostly revert billing page changes?

* highlight the navbar item

* Update UI snapshots for `chromium` (1)

* fix type errors

* Revert "Update UI snapshots for `chromium` (1)"

This reverts commit 7b9ac96.

* Revert "Update UI snapshots for `chromium` (2)"

This reverts commit 3c4b26f.

* Update UI snapshots for `chromium` (1)

* Update UI snapshots for `chromium` (1)

* Update UI snapshots for `chromium` (2)

* Update UI snapshots for `chromium` (1)

* constrain width of onboarding steps, remove new tag from notebooks nav

* Update UI snapshots for `webkit` (2)

* fix some onboarding snapshots

* Revert "Update UI snapshots for `chromium` (2)"

This reverts commit c2fb465.

* Revert "Update UI snapshots for `chromium` (1)"

This reverts commit 613b5a1.

* Update UI snapshots for `chromium` (1)

* Update frontend/src/scenes/onboarding/OnboardingBillingStep.tsx

Co-authored-by: Raquel Smith <[email protected]>

* Update UI snapshots for `webkit` (2)

* wip

* address pr comments

* add back subscribe buttons on billing page
* rename a selector

* Update UI snapshots for `chromium` (1)

* Update UI snapshots for `webkit` (2)

* small change to upgrade button

* remove extraneous files

* Update UI snapshots for `webkit` (2)

* Update UI snapshots for `webkit` (2)

* Update UI snapshots for `webkit` (2)

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Raquel Smith <[email protected]>
  • Loading branch information
3 people authored Feb 15, 2024
1 parent 661d66d commit 2fb1358
Show file tree
Hide file tree
Showing 32 changed files with 501 additions and 499 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-other-products--products--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
159 changes: 93 additions & 66 deletions frontend/src/layout/navigation-3000/navigationLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
IconGraph,
IconHome,
IconLive,
IconLogomark,
IconNotebook,
IconPeople,
IconPieChart,
Expand Down Expand Up @@ -58,7 +59,14 @@ export const navigation3000Logic = kea<navigation3000LogicType>([
path(['layout', 'navigation-3000', 'navigationLogic']),
props({} as { inputElement?: HTMLInputElement | null }),
connect(() => ({
values: [sceneLogic, ['sceneConfig'], navigationLogic, ['mobileLayout'], teamLogic, ['currentTeam']],
values: [
sceneLogic,
['sceneConfig'],
navigationLogic,
['mobileLayout'],
teamLogic,
['currentTeam', 'hasOnboardedAnyProduct'],
],
actions: [navigationLogic, ['closeAccountPopover']],
})),
actions({
Expand Down Expand Up @@ -324,76 +332,95 @@ export const navigation3000Logic = kea<navigation3000LogicType>([
dashboardsModel.selectors.dashboardsLoading,
dashboardsModel.selectors.pinnedDashboards,
s.currentTeam,
s.hasOnboardedAnyProduct,
],
(featureFlags, dashboardsLoading, pinnedDashboards, currentTeam): NavbarItem[][] => {
(
featureFlags,
dashboardsLoading,
pinnedDashboards,
currentTeam,
hasOnboardedAnyProduct
): NavbarItem[][] => {
const isUsingSidebar = featureFlags[FEATURE_FLAGS.POSTHOG_3000_NAV]
const hasOnboardedFeatureFlags = currentTeam?.has_completed_onboarding_for?.[ProductKey.FEATURE_FLAGS]
return [
[
{
identifier: Scene.ProjectHomepage,
label: 'Home',
icon: <IconHome />,
to: urls.projectHomepage(),
},
{
identifier: Scene.Dashboards,
label: 'Dashboards',
icon: <IconDashboard />,
logic: isUsingSidebar ? dashboardsSidebarLogic : undefined,
to: isUsingSidebar ? undefined : urls.dashboards(),
sideAction: {
identifier: 'pinned-dashboards-dropdown',
dropdown: {
overlay: (
<LemonMenuOverlay
items={[
{
title: 'Pinned dashboards',
items: pinnedDashboards.map((dashboard) => ({
label: dashboard.name,
to: urls.dashboard(dashboard.id),
})),
footer: dashboardsLoading && (
<div className="px-2 py-1 text-text-secondary-3000">
<Spinner /> Loading…
</div>
),
},
]}
/>
),
placement: 'bottom-end',
},
const sectionOne: NavbarItem[] = [
{
identifier: Scene.Dashboards,
label: 'Dashboards',
icon: <IconDashboard />,
logic: isUsingSidebar ? dashboardsSidebarLogic : undefined,
to: isUsingSidebar ? undefined : urls.dashboards(),
sideAction: {
identifier: 'pinned-dashboards-dropdown',
dropdown: {
overlay: (
<LemonMenuOverlay
items={[
{
title: 'Pinned dashboards',
items: pinnedDashboards.map((dashboard) => ({
label: dashboard.name,
to: urls.dashboard(dashboard.id),
})),
footer: dashboardsLoading && (
<div className="px-2 py-1 text-text-secondary-3000">
<Spinner /> Loading…
</div>
),
},
]}
/>
),
placement: 'bottom-end',
},
},
{
identifier: Scene.Notebooks,
label: 'Notebooks',
icon: <IconNotebook />,
to: urls.notebooks(),
},
{
identifier: Scene.DataManagement,
label: 'Data management',
icon: <IconDatabase />,
logic: isUsingSidebar ? dataManagementSidebarLogic : undefined,
to: isUsingSidebar ? undefined : urls.eventDefinitions(),
},
{
identifier: Scene.PersonsManagement,
label: 'People',
icon: <IconPeople />,
logic: isUsingSidebar ? personsAndGroupsSidebarLogic : undefined,
to: isUsingSidebar ? undefined : urls.persons(),
},
{
identifier: Scene.Events,
label: 'Activity',
icon: <IconLive />,
to: urls.events(),
},
],
},
{
identifier: Scene.Notebooks,
label: 'Notebooks',
icon: <IconNotebook />,
to: urls.notebooks(),
},
{
identifier: Scene.DataManagement,
label: 'Data management',
icon: <IconDatabase />,
logic: isUsingSidebar ? dataManagementSidebarLogic : undefined,
to: isUsingSidebar ? undefined : urls.eventDefinitions(),
},
{
identifier: Scene.PersonsManagement,
label: 'People',
icon: <IconPeople />,
logic: isUsingSidebar ? personsAndGroupsSidebarLogic : undefined,
to: isUsingSidebar ? undefined : urls.persons(),
},
{
identifier: Scene.Events,
label: 'Activity',
icon: <IconLive />,
to: urls.events(),
},
]

sectionOne.unshift(
hasOnboardedAnyProduct
? {
identifier: Scene.ProjectHomepage,
label: 'Home',
icon: <IconHome />,
to: urls.projectHomepage(),
}
: {
identifier: Scene.Products,
label: 'Welcome to PostHog',
icon: <IconLogomark />,
to: urls.products(),
}
)

return [
sectionOne,
[
{
identifier: Scene.SavedInsights,
Expand Down
1 change: 0 additions & 1 deletion frontend/src/scenes/appScenes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ export const appScenes: Record<Scene, () => any> = {
[Scene.Canvas]: () => import('./notebooks/NotebookCanvasScene'),
[Scene.Products]: () => import('./products/Products'),
[Scene.Onboarding]: () => import('./onboarding/Onboarding'),
[Scene.OnboardingProductIntroduction]: () => import('./onboarding/OnboardingProductIntroduction'),
[Scene.Settings]: () => import('./settings/SettingsScene'),
[Scene.MoveToPostHogCloud]: () => import('./moveToPostHogCloud/MoveToPostHogCloud'),
}
35 changes: 8 additions & 27 deletions frontend/src/scenes/billing/PlanComparison.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ export const PlanComparison = ({
return null
}
const fullyFeaturedPlan = plans[plans.length - 1]
const { reportBillingUpgradeClicked } = useActions(eventUsageLogic)
const { redirectPath, billing } = useValues(billingLogic)
const { billing, redirectPath } = useValues(billingLogic)
const { width, ref: planComparisonRef } = useResizeObserver()
const { reportBillingUpgradeClicked } = useActions(eventUsageLogic)

const upgradeButtons = plans?.map((plan) => {
return (
Expand All @@ -132,7 +132,7 @@ export const PlanComparison = ({
>
{plan.current_plan ? 'Current plan' : 'Subscribe'}
</LemonButton>
{!plan.current_plan && includeAddons && product.addons?.length > 0 && (
{!plan.current_plan && !plan.free_allocation && includeAddons && product.addons?.length > 0 && (
<p className="text-center ml-0 mt-2 mb-0">
<Link
to={`/api/billing-v2/activation?products=${product.type}:${plan.plan_key}&redirect_path=${redirectPath}`}
Expand Down Expand Up @@ -160,15 +160,6 @@ export const PlanComparison = ({
</tr>
</thead>
<tbody>
{/* Pricing section */}
<tr>
<th
colSpan={3}
className="PlanTable__th__section bg-side text-muted justify-left rounded text-left mb-2"
>
<span>Pricing</span>
</th>
</tr>
<tr className="PlanTable__tr__border">
<td className="font-bold">Monthly base price</td>
{plans?.map((plan) => (
Expand All @@ -177,7 +168,6 @@ export const PlanComparison = ({
</td>
))}
</tr>

<tr className="PlanTable__tr__border">
<th scope="row">
{includeAddons && product.addons?.length > 0 && (
Expand All @@ -191,7 +181,6 @@ export const PlanComparison = ({
<td key={`${plan.plan_key}-tiers-td`}>{getProductTiers(plan, product)}</td>
))}
</tr>

{includeAddons &&
product.addons?.map((addon) => {
return addon.tiered ? (
Expand Down Expand Up @@ -220,22 +209,15 @@ export const PlanComparison = ({
</tr>
) : null
})}

<tr>
<td />
{upgradeButtons}
</tr>
<tr>
<th colSpan={3} className="PlanTable__th__section bg-side justify-left rounded text-left mb-2">
<div className="flex items-center gap-x-2 my-2">
{getProductIcon(product.icon_key, 'text-2xl')}
<Tooltip title={product.description}>
<span className="font-bold">{product.name}</span>
</Tooltip>
</div>
<th colSpan={1} className="PlanTable__th__section rounded text-left">
<h3 className="mt-6 mb-2">Product Features:</h3>
</th>
</tr>

{fullyFeaturedPlan?.features?.map((feature, i) => (
<tr
key={`tr-${feature.key}`}
Expand Down Expand Up @@ -266,16 +248,15 @@ export const PlanComparison = ({
))}
</tr>
))}

{!billing?.has_active_subscription && (
<>
<tr>
<th colSpan={3} className="PlanTable__th__section rounded text-left">
<p className="mt-6 mb-2 italic text-center text-muted">
<th colSpan={1} className="PlanTable__th__section rounded text-left">
<h3 className="mt-6 mb-2">
<Tooltip title="Organizations with any paid subscription get access to additional features.">
Included platform features:
</Tooltip>
</p>
</h3>
</th>
</tr>
{billing?.products
Expand Down
43 changes: 3 additions & 40 deletions frontend/src/scenes/onboarding/Onboarding.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const _OnboardingSDKs = (): JSX.Element => {
useEffect(() => {
const product: BillingProductV2Type = billingJson.products[1] as unknown as BillingProductV2Type
setProduct(product)
router.actions.push(urls.onboarding(ProductKey.SESSION_REPLAY) + '?step=sdks')
router.actions.push(urls.onboarding(ProductKey.SESSION_REPLAY) + '?step=install')
}, [])
return <App />
}
Expand All @@ -64,45 +64,8 @@ export const _OnboardingBilling = (): JSX.Element => {
const { setProduct } = useActions(onboardingLogic)

useEffect(() => {
setProduct(billingJson.products[1] as unknown as BillingProductV2Type)
router.actions.push(urls.onboarding(ProductKey.SESSION_REPLAY, OnboardingStepKey.BILLING))
}, [])
return <App />
}

export const _OnboardingOtherProducts = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
...billingJson,
},
},
})

const { setProduct } = useActions(onboardingLogic)

useEffect(() => {
setProduct(billingJson.products[1] as unknown as BillingProductV2Type)
router.actions.push(urls.onboarding(ProductKey.SESSION_REPLAY, OnboardingStepKey.OTHER_PRODUCTS))
}, [])
return <App />
}
_OnboardingOtherProducts.tags = ['test-skip'] // FIXME: For some reason this is captured correctly the first time, but then is written over a second time with SDKs view

export const _OnboardingProductIntroduction = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
...billingJson,
},
},
})

const { setProduct } = useActions(onboardingLogic)

useEffect(() => {
setProduct(billingJson.products[0])
router.actions.push(urls.onboardingProductIntroduction(ProductKey.PRODUCT_ANALYTICS))
setProduct(billingUnsubscribedJson.products[1] as unknown as BillingProductV2Type)
router.actions.push(urls.onboarding(ProductKey.SESSION_REPLAY, OnboardingStepKey.PLANS))
}, [])
return <App />
}
Loading

0 comments on commit 2fb1358

Please sign in to comment.