From 90651e94f4ea2438286f3c1eadd06471cf5e4263 Mon Sep 17 00:00:00 2001 From: Raquel Smith Date: Fri, 17 Nov 2023 07:58:21 -0800 Subject: [PATCH] chore: remove old ingestion flow (#18667) * stop redirecting based on flag * remove /ingestion * fix import * fix * fix typo * fix, make single-click work on products * include initial billing limit info on subscribe success * fix type --- .../src/layout/navigation-3000/Navigation.tsx | 3 +- frontend/src/layout/navigation/Navigation.tsx | 6 +- .../src/layout/navigation/ProjectNotice.tsx | 14 +- .../TopBar/announcementLogic.test.ts | 2 +- .../navigation/TopBar/announcementLogic.ts | 4 +- .../ActivationSidebar/activationLogic.ts | 4 +- frontend/src/lib/utils/eventUsageLogic.ts | 95 +-- frontend/src/scenes/App.tsx | 4 +- frontend/src/scenes/appScenes.ts | 1 - frontend/src/scenes/billing/billingLogic.ts | 7 +- .../src/scenes/ingestion/CardContainer.tsx | 35 - .../IngestionInviteMembersButton.tsx | 26 - .../src/scenes/ingestion/IngestionWizard.scss | 77 -- .../src/scenes/ingestion/IngestionWizard.tsx | 94 --- frontend/src/scenes/ingestion/Sidebar.tsx | 95 --- frontend/src/scenes/ingestion/constants.tsx | 87 --- .../ingestion/frameworks/APIInstructions.tsx | 27 - .../frameworks/AndroidInstructions.tsx | 57 -- .../frameworks/ElixirInstructions.tsx | 33 - .../frameworks/FlutterInstructions.tsx | 64 -- .../ingestion/frameworks/GoInstructions.tsx | 45 -- .../ingestion/frameworks/NodeInstructions.tsx | 58 -- .../ingestion/frameworks/PHPInstructions.tsx | 54 -- .../frameworks/PythonInstructions.tsx | 38 - .../frameworks/ReactNativeInstructions.tsx | 64 -- .../ingestion/frameworks/RubyInstructions.tsx | 42 - .../ingestion/frameworks/WebInstructions.tsx | 105 --- .../ingestion/frameworks/iOSInstructions.tsx | 60 -- .../src/scenes/ingestion/frameworks/index.tsx | 11 - .../src/scenes/ingestion/ingestionLogic.ts | 717 ------------------ .../scenes/ingestion/panels/BillingPanel.tsx | 83 -- .../ingestion/panels/FrameworkPanel.tsx | 54 -- .../panels/GeneratingDemoDataPanel.tsx | 30 - .../ingestion/panels/InstructionsPanel.scss | 30 - .../ingestion/panels/InstructionsPanel.tsx | 78 -- .../ingestion/panels/InviteTeamPanel.tsx | 66 -- .../ingestion/panels/NoDemoIngestionPanel.tsx | 40 - .../ingestion/panels/PanelComponents.tsx | 123 --- .../src/scenes/ingestion/panels/Panels.scss | 37 - .../scenes/ingestion/panels/PlatformPanel.tsx | 48 -- .../ingestion/panels/SuperpowersPanel.tsx | 87 --- .../ingestion/panels/TeamInvitedPanel.tsx | 45 -- .../ingestion/panels/ThirdPartyIcons.tsx | 58 -- .../ingestion/panels/ThirdPartyPanel.tsx | 156 ---- .../ingestion/panels/VerificationPanel.tsx | 62 -- frontend/src/scenes/ingestion/types.ts | 5 - frontend/src/scenes/onboarding/Onboarding.tsx | 10 - .../onboarding/OnboardingBillingStep.tsx | 14 +- .../src/scenes/onboarding/onboardingLogic.tsx | 6 +- frontend/src/scenes/products/Products.tsx | 10 - .../src/scenes/products/productsLogic.tsx | 10 +- frontend/src/scenes/sceneLogic.ts | 15 +- frontend/src/scenes/sceneTypes.ts | 1 - frontend/src/scenes/scenes.ts | 6 - .../settings/project/AutocaptureSettings.tsx | 10 +- frontend/src/scenes/urls.ts | 1 - frontend/src/types.ts | 1 + 57 files changed, 59 insertions(+), 2956 deletions(-) delete mode 100644 frontend/src/scenes/ingestion/CardContainer.tsx delete mode 100644 frontend/src/scenes/ingestion/IngestionInviteMembersButton.tsx delete mode 100644 frontend/src/scenes/ingestion/IngestionWizard.scss delete mode 100644 frontend/src/scenes/ingestion/IngestionWizard.tsx delete mode 100644 frontend/src/scenes/ingestion/Sidebar.tsx delete mode 100644 frontend/src/scenes/ingestion/constants.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/APIInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/AndroidInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/ElixirInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/FlutterInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/GoInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/NodeInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/PHPInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/PythonInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/ReactNativeInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/RubyInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/WebInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/iOSInstructions.tsx delete mode 100644 frontend/src/scenes/ingestion/frameworks/index.tsx delete mode 100644 frontend/src/scenes/ingestion/ingestionLogic.ts delete mode 100644 frontend/src/scenes/ingestion/panels/BillingPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/FrameworkPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/GeneratingDemoDataPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/InstructionsPanel.scss delete mode 100644 frontend/src/scenes/ingestion/panels/InstructionsPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/InviteTeamPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/NoDemoIngestionPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/PanelComponents.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/Panels.scss delete mode 100644 frontend/src/scenes/ingestion/panels/PlatformPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/SuperpowersPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/TeamInvitedPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/ThirdPartyIcons.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/ThirdPartyPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/panels/VerificationPanel.tsx delete mode 100644 frontend/src/scenes/ingestion/types.ts diff --git a/frontend/src/layout/navigation-3000/Navigation.tsx b/frontend/src/layout/navigation-3000/Navigation.tsx index 851a3fe2b86ab..522dfc2bef618 100644 --- a/frontend/src/layout/navigation-3000/Navigation.tsx +++ b/frontend/src/layout/navigation-3000/Navigation.tsx @@ -8,7 +8,7 @@ import './Navigation.scss' import { themeLogic } from './themeLogic' import { navigation3000Logic } from './navigationLogic' import clsx from 'clsx' -import { Scene, SceneConfig } from 'scenes/sceneTypes' +import { SceneConfig } from 'scenes/sceneTypes' import { FlaggedFeature } from 'lib/components/FlaggedFeature' import { FEATURE_FLAGS } from 'lib/constants' import { SidePanel } from './sidepanel/SidePanel' @@ -18,7 +18,6 @@ export function Navigation({ sceneConfig, }: { children: ReactNode - scene: Scene | null sceneConfig: SceneConfig | null }): JSX.Element { useMountedLogic(themeLogic) diff --git a/frontend/src/layout/navigation/Navigation.tsx b/frontend/src/layout/navigation/Navigation.tsx index 57b29956bdde1..18ff8d9fed01f 100644 --- a/frontend/src/layout/navigation/Navigation.tsx +++ b/frontend/src/layout/navigation/Navigation.tsx @@ -1,6 +1,6 @@ import clsx from 'clsx' import { BillingAlertsV2 } from 'lib/components/BillingAlertsV2' -import { Scene, SceneConfig } from 'scenes/sceneTypes' +import { SceneConfig } from 'scenes/sceneTypes' import { Breadcrumbs } from './Breadcrumbs/Breadcrumbs' import { ProjectNotice } from './ProjectNotice' import { SideBar } from './SideBar/SideBar' @@ -9,16 +9,14 @@ import { ReactNode } from 'react' export function Navigation({ children, - scene, sceneConfig, }: { children: ReactNode - scene: Scene | null sceneConfig: SceneConfig | null }): JSX.Element { return (
- {scene !== Scene.Ingestion && } +
{ - updateCurrentTeam(altTeamForIngestion?.id, urls.ingestion()) + updateCurrentTeam(altTeamForIngestion?.id, urls.products()) }} data-attr="demo-project-alt-team-ingestion_link" > - ingestion wizard + onboarding wizard {' '} to get started with your own data. @@ -60,8 +61,11 @@ export function ProjectNotice(): JSX.Element | null { message: ( <> This project has no events yet. Go to the{' '} - - ingestion wizard + + onboarding wizard {' '} or grab your project API key/HTML snippet from{' '} @@ -71,7 +75,7 @@ export function ProjectNotice(): JSX.Element | null { ), action: { - to: '/ingestion', + to: urls.onboarding(ProductKey.PRODUCT_ANALYTICS), 'data-attr': 'demo-warning-cta', icon: , children: 'Go to wizard', diff --git a/frontend/src/layout/navigation/TopBar/announcementLogic.test.ts b/frontend/src/layout/navigation/TopBar/announcementLogic.test.ts index b5f3e96fd31c8..ecef00b2cdfb0 100644 --- a/frontend/src/layout/navigation/TopBar/announcementLogic.test.ts +++ b/frontend/src/layout/navigation/TopBar/announcementLogic.test.ts @@ -31,7 +31,7 @@ describe('announcementLogic', () => { }) it('hides announcements during the ingestion phase', async () => { - router.actions.push(urls.ingestion()) + router.actions.push(urls.products()) await expectLogic(logic).toMatchValues({ cloudAnnouncement: DEFAULT_CLOUD_ANNOUNCEMENT, shownAnnouncementType: null, diff --git a/frontend/src/layout/navigation/TopBar/announcementLogic.ts b/frontend/src/layout/navigation/TopBar/announcementLogic.ts index 4a947e95107c7..60e0b5915b2f0 100644 --- a/frontend/src/layout/navigation/TopBar/announcementLogic.ts +++ b/frontend/src/layout/navigation/TopBar/announcementLogic.ts @@ -3,7 +3,6 @@ import { router } from 'kea-router' import { FEATURE_FLAGS, OrganizationMembershipLevel } from 'lib/constants' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic' -import { urls } from 'scenes/urls' import { userLogic } from 'scenes/userLogic' import { navigationLogic } from '../navigationLogic' import posthog from 'posthog-js' @@ -87,7 +86,8 @@ export const announcementLogic = kea([ (closable && (closed || (relevantAnnouncementType && persistedClosedAnnouncements[relevantAnnouncementType]))) || // hide if already closed - pathname == urls.ingestion() // hide during the ingestion phase + pathname.includes('/onboarding') || + pathname.includes('/products') // hide during the onboarding phase ) { return null } diff --git a/frontend/src/lib/components/ActivationSidebar/activationLogic.ts b/frontend/src/lib/components/ActivationSidebar/activationLogic.ts index b2579b889df9e..16cf859f6aefc 100644 --- a/frontend/src/lib/components/ActivationSidebar/activationLogic.ts +++ b/frontend/src/lib/components/ActivationSidebar/activationLogic.ts @@ -8,7 +8,7 @@ import { membersLogic } from 'scenes/organization/membersLogic' import { pluginsLogic } from 'scenes/plugins/pluginsLogic' import { teamLogic } from 'scenes/teamLogic' import { navigationLogic } from '~/layout/navigation/navigationLogic' -import { EventDefinitionType, TeamBasicType } from '~/types' +import { EventDefinitionType, ProductKey, TeamBasicType } from '~/types' import type { activationLogicType } from './activationLogicType' import { urls } from 'scenes/urls' import { savedInsightsLogic } from 'scenes/saved-insights/savedInsightsLogic' @@ -327,7 +327,7 @@ export const activationLogic = kea([ runTask: async ({ id }) => { switch (id) { case ActivationTasks.IngestFirstEvent: - router.actions.push(urls.ingestion()) + router.actions.push(urls.onboarding(ProductKey.PRODUCT_ANALYTICS)) break case ActivationTasks.InviteTeamMember: actions.showInviteModal() diff --git a/frontend/src/lib/utils/eventUsageLogic.ts b/frontend/src/lib/utils/eventUsageLogic.ts index 2ec59bf991d2d..5ce1faefa6d13 100644 --- a/frontend/src/lib/utils/eventUsageLogic.ts +++ b/frontend/src/lib/utils/eventUsageLogic.ts @@ -33,7 +33,6 @@ import type { Dayjs } from 'lib/dayjs' import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic' import { convertPropertyGroupToProperties } from 'lib/utils' import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types' -import { PlatformType, Framework } from 'scenes/ingestion/types' import { now } from 'lib/dayjs' import { isFilterWithDisplay, @@ -332,7 +331,6 @@ export const eventUsageLogic = kea([ ) => ({ attribute, originalLength, newLength }), reportDashboardShareToggled: (isShared: boolean) => ({ isShared }), reportUpgradeModalShown: (featureName: string) => ({ featureName }), - reportIngestionLandingSeen: true, reportTimezoneComponentViewed: ( component: 'label' | 'indicator', project_timezone?: string, @@ -439,27 +437,11 @@ export const eventUsageLogic = kea([ reportInsightOpenedFromRecentInsightList: true, reportRecordingOpenedFromRecentRecordingList: true, reportPersonOpenedFromNewlySeenPersonsList: true, - reportIngestionSelectPlatformType: (platform: PlatformType) => ({ platform }), - reportIngestionSelectFrameworkType: (framework: Framework) => ({ framework }), - reportIngestionRecordingsTurnedOff: ( - session_recording_opt_in: boolean, - capture_console_log_opt_in: boolean, - capture_performance_opt_in: boolean - ) => ({ session_recording_opt_in, capture_console_log_opt_in, capture_performance_opt_in }), - reportIngestionAutocaptureToggled: (autocapture_opt_out: boolean) => ({ autocapture_opt_out }), - reportIngestionAutocaptureExceptionsToggled: (autocapture_opt_in: boolean) => ({ autocapture_opt_in }), - reportIngestionHelpClicked: (type: string) => ({ type }), - reportIngestionTryWithBookmarkletClicked: true, - reportIngestionTryWithDemoDataClicked: true, reportIngestionContinueWithoutVerifying: true, - reportIngestionContinueWithoutBilling: true, - reportIngestionBillingCancelled: true, - reportIngestionThirdPartyAboutClicked: (name: string) => ({ name }), - reportIngestionThirdPartyConfigureClicked: (name: string) => ({ name }), - reportIngestionThirdPartyPluginInstalled: (name: string) => ({ name }), + reportAutocaptureToggled: (autocapture_opt_out: boolean) => ({ autocapture_opt_out }), + reportAutocaptureExceptionsToggled: (autocapture_opt_in: boolean) => ({ autocapture_opt_in }), reportFailedToCreateFeatureFlagWithCohort: (code: string, detail: string) => ({ code, detail }), reportInviteMembersButtonClicked: true, - reportIngestionSidebarButtonClicked: (name: string) => ({ name }), reportDashboardLoadingTime: (loadingMilliseconds: number, dashboardId: number) => ({ loadingMilliseconds, dashboardId, @@ -794,9 +776,6 @@ export const eventUsageLogic = kea([ } posthog.capture('test account filters updated', payload) }, - reportIngestionLandingSeen: async () => { - posthog.capture('ingestion landing seen') - }, reportInsightFilterRemoved: async ({ index }) => { posthog.capture('local filter removed', { index }) @@ -1049,70 +1028,17 @@ export const eventUsageLogic = kea([ reportPersonOpenedFromNewlySeenPersonsList: () => { posthog.capture('person opened from newly seen persons list') }, - reportIngestionSelectPlatformType: ({ platform }) => { - posthog.capture('ingestion select platform type', { - platform: platform, - }) - }, - reportIngestionSelectFrameworkType: ({ framework }) => { - posthog.capture('ingestion select framework type', { - framework: framework, - }) - }, - reportIngestionRecordingsTurnedOff: ({ - session_recording_opt_in, - capture_console_log_opt_in, - capture_performance_opt_in, - }) => { - posthog.capture('ingestion recordings turned off', { - session_recording_opt_in, - capture_console_log_opt_in, - capture_performance_opt_in, - }) - }, - reportIngestionAutocaptureToggled: ({ autocapture_opt_out }) => { - posthog.capture('ingestion autocapture toggled', { - autocapture_opt_out, - }) - }, - reportIngestionAutocaptureExceptionsToggled: ({ autocapture_opt_in }) => { - posthog.capture('ingestion autocapture exceptions toggled', { - autocapture_opt_in, - }) - }, - reportIngestionHelpClicked: ({ type }) => { - posthog.capture('ingestion help clicked', { - type: type, - }) - }, - reportIngestionTryWithBookmarkletClicked: () => { - posthog.capture('ingestion try posthog with bookmarklet clicked') - }, - reportIngestionTryWithDemoDataClicked: () => { - posthog.capture('ingestion try posthog with demo data clicked') - }, reportIngestionContinueWithoutVerifying: () => { posthog.capture('ingestion continue without verifying') }, - reportIngestionContinueWithoutBilling: () => { - posthog.capture('ingestion continue without adding billing details') - }, - reportIngestionBillingCancelled: () => { - posthog.capture('ingestion billing cancelled') - }, - reportIngestionThirdPartyAboutClicked: ({ name }) => { - posthog.capture('ingestion third party about clicked', { - name: name, - }) - }, - reportIngestionThirdPartyConfigureClicked: ({ name }) => { - posthog.capture('ingestion third party configure clicked', { - name: name, + reportAutocaptureToggled: ({ autocapture_opt_out }) => { + posthog.capture('autocapture toggled', { + autocapture_opt_out, }) }, - reportIngestionThirdPartyPluginInstalled: ({ name }) => { - posthog.capture('report ingestion third party plugin installed', { - name: name, + reportAutocaptureExceptionsToggled: ({ autocapture_opt_in }) => { + posthog.capture('autocapture exceptions toggled', { + autocapture_opt_in, }) }, reportFailedToCreateFeatureFlagWithCohort: ({ detail, code }) => { @@ -1121,11 +1047,6 @@ export const eventUsageLogic = kea([ reportInviteMembersButtonClicked: () => { posthog.capture('invite members button clicked') }, - reportIngestionSidebarButtonClicked: ({ name }) => { - posthog.capture('ingestion sidebar button clicked', { - name: name, - }) - }, reportTeamSettingChange: ({ name, value }) => { posthog.capture(`${name} team setting updated`, { setting: name, diff --git a/frontend/src/scenes/App.tsx b/frontend/src/scenes/App.tsx index bfeb6836c9ef0..225efc7dffeaa 100644 --- a/frontend/src/scenes/App.tsx +++ b/frontend/src/scenes/App.tsx @@ -165,9 +165,7 @@ function AppScene(): JSX.Element | null { return ( <> - - {wrappedSceneElement} - + {wrappedSceneElement} {toastContainer} diff --git a/frontend/src/scenes/appScenes.ts b/frontend/src/scenes/appScenes.ts index 9b0ef2ed521ae..ad997bb2635a3 100644 --- a/frontend/src/scenes/appScenes.ts +++ b/frontend/src/scenes/appScenes.ts @@ -53,7 +53,6 @@ export const appScenes: Record any> = { [Scene.PreflightCheck]: () => import('./PreflightCheck/PreflightCheck'), [Scene.Signup]: () => import('./authentication/signup/SignupContainer'), [Scene.InviteSignup]: () => import('./authentication/InviteSignup'), - [Scene.Ingestion]: () => import('./ingestion/IngestionWizard'), [Scene.Billing]: () => import('./billing/Billing'), [Scene.Apps]: () => import('./plugins/AppsScene'), [Scene.FrontendAppScene]: () => import('./apps/FrontendAppScene'), diff --git a/frontend/src/scenes/billing/billingLogic.ts b/frontend/src/scenes/billing/billingLogic.ts index 4e694d0d115b2..60aa5bf9dc27b 100644 --- a/frontend/src/scenes/billing/billingLogic.ts +++ b/frontend/src/scenes/billing/billingLogic.ts @@ -12,7 +12,6 @@ import { userLogic } from 'scenes/userLogic' import { pluralize } from 'lib/utils' import type { billingLogicType } from './billingLogicType' import { forms } from 'kea-forms' -import { urls } from 'scenes/urls' import { eventUsageLogic } from 'lib/utils/eventUsageLogic' export const ALLOCATION_THRESHOLD_ALERT = 0.85 // Threshold to show warning of event usage near limit @@ -77,9 +76,7 @@ export const billingLogic = kea([ '' as string, { setRedirectPath: () => { - return window.location.pathname.includes('/ingestion') - ? urls.ingestion() + '/billing' - : window.location.pathname.includes('/onboarding') + return window.location.pathname.includes('/onboarding') ? window.location.pathname + window.location.search : '' }, @@ -88,7 +85,7 @@ export const billingLogic = kea([ isOnboarding: [ false, { - setIsOnboarding: () => window.location.pathname.includes('/ingestion'), + setIsOnboarding: () => window.location.pathname.includes('/onboarding'), }, ], }), diff --git a/frontend/src/scenes/ingestion/CardContainer.tsx b/frontend/src/scenes/ingestion/CardContainer.tsx deleted file mode 100644 index ed26c428d8101..0000000000000 --- a/frontend/src/scenes/ingestion/CardContainer.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { PanelFooter } from './panels/PanelComponents' -import './panels/Panels.scss' -import { IngestionState } from 'scenes/ingestion/ingestionLogic' - -export function CardContainer({ - children, - nextProps, - onContinue, - finalStep = false, - showInviteTeamMembers = true, -}: { - children: React.ReactNode - nextProps?: Partial - onContinue?: () => void - finalStep?: boolean - showInviteTeamMembers?: boolean -}): JSX.Element { - return ( - // We want a forced width for this view only - // eslint-disable-next-line react/forbid-dom-props -
- {children} -
- {nextProps && ( - - )} -
-
- ) -} diff --git a/frontend/src/scenes/ingestion/IngestionInviteMembersButton.tsx b/frontend/src/scenes/ingestion/IngestionInviteMembersButton.tsx deleted file mode 100644 index 439390bd83164..0000000000000 --- a/frontend/src/scenes/ingestion/IngestionInviteMembersButton.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { LemonButton } from '@posthog/lemon-ui' -import { useActions } from 'kea' -import { IconArrowRight } from 'lib/lemon-ui/icons' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { inviteLogic } from 'scenes/settings/organization/inviteLogic' - -export function IngestionInviteMembersButton(): JSX.Element { - const { showInviteModal } = useActions(inviteLogic) - const { reportInviteMembersButtonClicked } = useActions(eventUsageLogic) - - return ( - } - className="mt-6" - onClick={() => { - showInviteModal() - reportInviteMembersButtonClicked() - }} - > - Invite a team member to help with this step - - ) -} diff --git a/frontend/src/scenes/ingestion/IngestionWizard.scss b/frontend/src/scenes/ingestion/IngestionWizard.scss deleted file mode 100644 index e1d2b422bdf7c..0000000000000 --- a/frontend/src/scenes/ingestion/IngestionWizard.scss +++ /dev/null @@ -1,77 +0,0 @@ -.IngestionContainer { - display: flex; - height: 100%; - align-items: center; - justify-content: center; - padding: 2rem; - flex-direction: column; - width: 100%; -} - -.IngestionContent { - .BridgePage__content { - max-width: 700px; - } -} - -.IngestionTopbar { - border-bottom: 1px solid var(--border); - padding: 0.25rem 1rem; - display: flex; - justify-content: space-between; - position: sticky; - top: 0; - background-color: white; - width: 100%; - z-index: 10; - - .help-button { - margin-right: 1rem; - } -} - -.platform-item { - margin-right: 10px; - padding: 10px; - padding-left: 20px; - padding-right: 20px; - border: 1px solid gray; - border-radius: 2px; - cursor: pointer; -} - -.platform-item:hover { - background-color: gainsboro; -} - -.selectable-item:hover { - background-color: gainsboro; - cursor: pointer; -} - -.IngestionSidebar__bottom { - margin-top: auto; - - .popover { - padding-left: 0.5rem; - padding-right: 0.5rem; - } -} - -.IngestionSidebar__help { - display: flex; - flex-direction: column; - font-weight: 500; - color: var(--primary); - margin-top: 1rem; -} - -.IngestionSidebar__steps { - color: var(--muted-alt); - font-size: 14px; - - .LemonButton { - font-weight: 600; - margin-bottom: 0.5rem; - } -} diff --git a/frontend/src/scenes/ingestion/IngestionWizard.tsx b/frontend/src/scenes/ingestion/IngestionWizard.tsx deleted file mode 100644 index 80c8d8c8690a2..0000000000000 --- a/frontend/src/scenes/ingestion/IngestionWizard.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useEffect } from 'react' -import './IngestionWizard.scss' - -import { VerificationPanel } from 'scenes/ingestion/panels/VerificationPanel' -import { InstructionsPanel } from 'scenes/ingestion/panels/InstructionsPanel' -import { useValues, useActions } from 'kea' -import { ingestionLogic, INGESTION_VIEWS } from 'scenes/ingestion/ingestionLogic' -import { FrameworkPanel } from 'scenes/ingestion/panels/FrameworkPanel' -import { PlatformPanel } from 'scenes/ingestion/panels/PlatformPanel' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { GeneratingDemoDataPanel } from './panels/GeneratingDemoDataPanel' -import { ThirdPartyPanel } from './panels/ThirdPartyPanel' -import { BillingPanel } from './panels/BillingPanel' -import { Sidebar } from './Sidebar' -import { InviteModal } from 'scenes/settings/organization/InviteModal' -import { inviteLogic } from 'scenes/settings/organization/inviteLogic' -import { Logo } from '~/toolbar/assets/Logo' -import { SitePopover } from '~/layout/navigation/TopBar/SitePopover' -import { HelpButton } from 'lib/components/HelpButton/HelpButton' -import { BridgePage } from 'lib/components/BridgePage/BridgePage' -import { PanelHeader } from './panels/PanelComponents' -import { InviteTeamPanel } from './panels/InviteTeamPanel' -import { TeamInvitedPanel } from './panels/TeamInvitedPanel' -import { NoDemoIngestionPanel } from './panels/NoDemoIngestionPanel' -import { SuperpowersPanel } from 'scenes/ingestion/panels/SuperpowersPanel' -import { featureFlagLogic } from 'lib/logic/featureFlagLogic' -import { FEATURE_FLAGS } from 'lib/constants' -import { router } from 'kea-router' -import { urls } from 'scenes/urls' - -export function IngestionWizard(): JSX.Element { - const { currentView, platform } = useValues(ingestionLogic) - const { reportIngestionLandingSeen } = useActions(eventUsageLogic) - const { featureFlags } = useValues(featureFlagLogic) - - useEffect(() => { - if (!platform) { - reportIngestionLandingSeen() - } - }, [platform]) - - if (featureFlags[FEATURE_FLAGS.PRODUCT_SPECIFIC_ONBOARDING] === 'test') { - router.actions.replace(urls.products()) - } - - return ( - - {currentView === INGESTION_VIEWS.BILLING && } - {currentView === INGESTION_VIEWS.SUPERPOWERS && } - {currentView === INGESTION_VIEWS.INVITE_TEAM && } - {currentView === INGESTION_VIEWS.TEAM_INVITED && } - {currentView === INGESTION_VIEWS.CHOOSE_PLATFORM && } - {currentView === INGESTION_VIEWS.CHOOSE_FRAMEWORK && } - {currentView === INGESTION_VIEWS.WEB_INSTRUCTIONS && } - {currentView === INGESTION_VIEWS.VERIFICATION && } - {currentView === INGESTION_VIEWS.GENERATING_DEMO_DATA && } - {currentView === INGESTION_VIEWS.CHOOSE_THIRD_PARTY && } - {currentView === INGESTION_VIEWS.NO_DEMO_INGESTION && } - - ) -} - -function IngestionContainer({ children }: { children: React.ReactNode }): JSX.Element { - const { isInviteModalShown } = useValues(inviteLogic) - const { hideInviteModal } = useActions(inviteLogic) - const { isSmallScreen } = useValues(ingestionLogic) - - return ( -
-
- -
- - -
-
-
- {!isSmallScreen && } - {/*
} - className="IngestionContent h-full" - fullScreen={false} - > - {children} - -
- -
- ) -} diff --git a/frontend/src/scenes/ingestion/Sidebar.tsx b/frontend/src/scenes/ingestion/Sidebar.tsx deleted file mode 100644 index b3f656cee12e7..0000000000000 --- a/frontend/src/scenes/ingestion/Sidebar.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { ingestionLogic } from './ingestionLogic' -import { useActions, useValues } from 'kea' -import './IngestionWizard.scss' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { LemonButton, LemonButtonWithDropdown } from 'lib/lemon-ui/LemonButton' -import { IconArticle, IconQuestionAnswer } from 'lib/lemon-ui/icons' -import { HelpType } from '~/types' -import { LemonDivider } from 'lib/lemon-ui/LemonDivider' -import { ProjectSwitcherOverlay } from '~/layout/navigation/ProjectSwitcher' -import { Lettermark } from 'lib/lemon-ui/Lettermark' -import { organizationLogic } from 'scenes/organizationLogic' -import { Link } from '@posthog/lemon-ui' - -const HELP_UTM_TAGS = '?utm_medium=in-product-onboarding&utm_campaign=help-button-sidebar' - -export function Sidebar(): JSX.Element { - const { currentStep, sidebarSteps, isProjectSwitcherShown } = useValues(ingestionLogic) - const { sidebarStepClick, toggleProjectSwitcher, hideProjectSwitcher } = useActions(ingestionLogic) - const { reportIngestionHelpClicked, reportIngestionSidebarButtonClicked } = useActions(eventUsageLogic) - const { currentOrganization } = useValues(organizationLogic) - - const currentIndex = sidebarSteps.findIndex((x) => x === currentStep) - - return ( -
-
-
- {sidebarSteps.map((step: string, index: number) => ( - currentIndex} - onClick={() => { - sidebarStepClick(step) - reportIngestionSidebarButtonClicked(step) - }} - > - {step} - - ))} -
-
- {currentOrganization?.teams && currentOrganization.teams.length > 1 && ( - <> - } - onClick={() => toggleProjectSwitcher()} - dropdown={{ - visible: isProjectSwitcherShown, - onClickOutside: hideProjectSwitcher, - overlay: , - actionable: true, - placement: 'top-end', - }} - type="secondary" - fullWidth - > - Switch project - - - - )} -
- - } - fullWidth - onClick={() => { - reportIngestionHelpClicked(HelpType.Slack) - }} - > - Get support on Slack - - - - } - fullWidth - onClick={() => { - reportIngestionHelpClicked(HelpType.Docs) - }} - > - Read our documentation - - -
-
-
-
- ) -} diff --git a/frontend/src/scenes/ingestion/constants.tsx b/frontend/src/scenes/ingestion/constants.tsx deleted file mode 100644 index 50fefffadbf4a..0000000000000 --- a/frontend/src/scenes/ingestion/constants.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { PlatformType } from 'scenes/ingestion/types' -import { Segment, RSS } from './panels/ThirdPartyIcons' - -export const TECHNICAL = 'TECHNICAL' -export const PLATFORM_TYPE = 'PLATFORM_TYPE' -export const FRAMEWORK = 'FRAMEWORK' -export const INSTRUCTIONS = 'INSTRUCTIONS' -export const VERIFICATION = 'VERIFICATION' - -export const WEB = 'web' -export const MOBILE = 'mobile' -export const BACKEND = 'backend' -export const THIRD_PARTY = 'third-party' -export const platforms: PlatformType[] = [WEB, MOBILE, BACKEND] - -export const NODEJS = 'NODEJS' -export const GO = 'GO' -export const RUBY = 'RUBY' -export const PYTHON = 'PYTHON' -export const PHP = 'PHP' -export const ELIXIR = 'ELIXIR' -export const API = 'API' - -export const ANDROID = 'ANDROID' -export const IOS = 'IOS' -export const REACT_NATIVE = 'REACT_NATIVE' -export const FLUTTER = 'FLUTTER' - -export const httpFrameworks = { - [API]: 'HTTP API', -} -export const webFrameworks = { - [NODEJS]: 'Node.js', - [GO]: 'Go', - [RUBY]: 'Ruby', - [PYTHON]: 'Python', - [PHP]: 'PHP', - [ELIXIR]: 'Elixir', -} - -export const mobileFrameworks = { - [ANDROID]: 'Android', - [IOS]: 'iOS', - [REACT_NATIVE]: 'React Native', - [FLUTTER]: 'Flutter', -} - -export const allFrameworks = { - ...webFrameworks, - ...mobileFrameworks, - ...httpFrameworks, -} -export interface ThirdPartySource { - name: string - icon: JSX.Element - docsLink: string - aboutLink: string - labels?: string[] - description?: string -} - -export const thirdPartySources: ThirdPartySource[] = [ - { - name: 'Segment', - icon: , - docsLink: 'https://posthog.com/docs/integrate/third-party/segment', - aboutLink: 'https://segment.com', - }, - { - name: 'Rudderstack', - icon: ( - - ), - docsLink: 'https://posthog.com/docs/integrate/third-party/rudderstack', - aboutLink: 'https://rudderstack.com', - }, - { - name: 'RSS items', - description: 'Send events from releases, blog posts, status pages, or any other RSS feed into PostHog', - icon: , - docsLink: 'https://posthog.com/tutorials/rss-item-capture', - aboutLink: 'https://en.wikipedia.org/wiki/RSS', - }, -] diff --git a/frontend/src/scenes/ingestion/frameworks/APIInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/APIInstructions.tsx deleted file mode 100644 index 3ac66f7281952..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/APIInstructions.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function APISnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - const url = window.location.origin - - return ( - - {'POST ' + - url + - '/capture/\nContent-Type: application/json\n\n{\n\t"api_key": "' + - currentTeam?.api_token + - '",\n\t"event": "[event name]",\n\t"properties": {\n\t\t"distinct_id": "[your users\' distinct id]",\n\t\t"key1": "value1",\n\t\t"key2": "value2"\n\t},\n\t"timestamp": "[optional timestamp in ISO 8601 format]"\n}'} - - ) -} - -export function APIInstructions(): JSX.Element { - return ( - <> -

Usage

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/AndroidInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/AndroidInstructions.tsx deleted file mode 100644 index 1e7d262f36640..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/AndroidInstructions.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function AndroidInstallSnippet(): JSX.Element { - return ( - - {`dependencies { - implementation 'com.posthog.android:posthog:1.+' -}`} - - ) -} - -function AndroidSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {`public class SampleApp extends Application { - private static final String POSTHOG_API_KEY = "${currentTeam?.api_token}"; - private static final String POSTHOG_HOST = "${window.location.origin}"; - - @Override - public void onCreate() { - // Create a PostHog client with the given context, API key and host - PostHog posthog = new PostHog.Builder(this, POSTHOG_API_KEY, POSTHOG_HOST) - .captureApplicationLifecycleEvents() // Record certain application events automatically! - .recordScreenViews() // Record screen views automatically! - .build(); - - // Set the initialized instance as a globally accessible instance - PostHog.setSingletonInstance(posthog); - - // Now any time you call PostHog.with, the custom instance will be returned - PostHog posthog = PostHog.with(this); - }`} - - ) -} - -function AndroidCaptureSnippet(): JSX.Element { - return PostHog.with(this).capture("test-event"); -} - -export function AndroidInstructions(): JSX.Element { - return ( - <> -

Install

- -

Configure

- -

Send an Event

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/ElixirInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/ElixirInstructions.tsx deleted file mode 100644 index 7d476a6630db0..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/ElixirInstructions.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function ElixirInstallSnippet(): JSX.Element { - return ( - - {'def deps do\n [\n {:posthog, "~> 0.1"}\n ]\nend'} - - ) -} - -function ElixirSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - const url = window.location.origin - - return ( - - {'config :posthog,\n api_url: "' + url + '",\n api_key: "' + currentTeam?.api_token + '"'} - - ) -} - -export function ElixirInstructions(): JSX.Element { - return ( - <> -

Install

- -

Configure

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/FlutterInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/FlutterInstructions.tsx deleted file mode 100644 index 46d496917a9b9..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/FlutterInstructions.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function FlutterInstallSnippet(): JSX.Element { - return {'posthog_flutter: # insert version number'} -} - -function FlutterCaptureSnippet(): JSX.Element { - return ( - - { - "import 'package:posthog_flutter/posthog_flutter.dart';\n\nPosthog().screen(\n\tscreenName: 'Example Screen',\n);" - } - - ) -} - -function FlutterAndroidSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - const url = window.location.origin - - return ( - - {'\n\t\n\t\t[...]\n\t\n\t\n\t\n\t\n\t\n'} - - ) -} - -function FlutterIOSSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - const url = window.location.origin - - return ( - - {'\n\t[...]\n\tcom.posthog.posthog.API_KEY\n\t' + - currentTeam?.api_token + - '\n\tcom.posthog.posthog.POSTHOG_HOST\n\t' + - url + - '\n\tcom.posthog.posthog.TRACK_APPLICATION_LIFECYCLE_EVENTS\n\t\n\t[...]\n'} - - ) -} - -export function FlutterInstructions(): JSX.Element { - return ( - <> -

Install

- -

Android Setup

-

{'Add these values in AndroidManifest.xml'}

- -

iOS Setup

-

{'Add these values in Info.plist'}

- -

Send an Event

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/GoInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/GoInstructions.tsx deleted file mode 100644 index 5dc33e57499c4..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/GoInstructions.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function GoInstallSnippet(): JSX.Element { - return {'go get "github.com/posthog/posthog-go"'} -} - -function GoSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {`package main -import ( - "github.com/posthog/posthog-go" -) -func main() { - client, _ := posthog.NewWithConfig("${currentTeam?.api_token}", posthog.Config{Endpoint: "${window.location.origin}"}) - defer client.Close() -}`} - - ) -} - -function GoCaptureSnippet(): JSX.Element { - return ( - - {'client.Enqueue(posthog.Capture{\n DistinctId: "test-user",\n Event: "test-snippet",\n})'} - - ) -} - -export function GoInstructions(): JSX.Element { - return ( - <> -

Install

- -

Configure

- -

Send an Event

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/NodeInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/NodeInstructions.tsx deleted file mode 100644 index 46551b2627d32..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/NodeInstructions.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function NodeInstallSnippet(): JSX.Element { - return ( - - {`npm install posthog-node -# OR -yarn add posthog-node -# OR -pnpm add posthog-node`} - - ) -} - -function NodeSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {`import { PostHog } from 'posthog-node' - -const client = new PostHog( - '${currentTeam?.api_token}', - { host: '${window.location.origin}' } -)`} - - ) -} - -function NodeCaptureSnippet(): JSX.Element { - return ( - - {`client.capture({ - distinctId: 'test-id', - event: 'test-event' -}) - -// Send queued events immediately. Use for example in a serverless environment -// where the program may terminate before everything is sent -client.flush()`} - - ) -} - -export function NodeInstructions(): JSX.Element { - return ( - <> -

Install

- -

Configure

- -

Send an Event

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/PHPInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/PHPInstructions.tsx deleted file mode 100644 index c9dc1665ab977..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/PHPInstructions.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function PHPConfigSnippet(): JSX.Element { - return ( - - {`{ - "require": { - "posthog/posthog-php": "1.0.*" - } -}`} - - ) -} - -function PHPInstallSnippet(): JSX.Element { - return {'php composer.phar install'} -} - -function PHPSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {`PostHog::init('${currentTeam?.api_token}', - array('host' => '${window.location.origin}') -);`} - - ) -} - -function PHPCaptureSnippet(): JSX.Element { - return ( - - {"PostHog::capture(array(\n 'distinctId' => 'test-user',\n 'event' => 'test-event'\n));"} - - ) -} - -export function PHPInstructions(): JSX.Element { - return ( - <> -

Dependency Setup

- -

Install

- -

Configure

- -

Send an Event

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/PythonInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/PythonInstructions.tsx deleted file mode 100644 index 0d596f57e50e1..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/PythonInstructions.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function PythonInstallSnippet(): JSX.Element { - return {'pip install posthog'} -} - -function PythonSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {`from posthog import Posthog - -posthog = Posthog(project_api_key='${currentTeam?.api_token}', host='${window.location.origin}') - - `} - - ) -} - -function PythonCaptureSnippet(): JSX.Element { - return {"posthog.capture('test-id', 'test-event')"} -} - -export function PythonInstructions(): JSX.Element { - return ( - <> -

Install

- -

Configure

- -

Send an Event

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/ReactNativeInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/ReactNativeInstructions.tsx deleted file mode 100644 index 76298cc842821..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/ReactNativeInstructions.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' -import { Link } from '@posthog/lemon-ui' - -export function RNInstructions(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - const url = window.location.origin - - return ( - <> -

Install

- - {`# Expo apps -expo install posthog-react-native expo-file-system expo-application expo-device expo-localization - -# Standard React Native apps -yarn add posthog-react-native @react-native-async-storage/async-storage react-native-device-info -# or -npm i -s posthog-react-native @react-native-async-storage/async-storage react-native-device-info - -# for iOS -cd ios -pod install`} - -

Configure

-

- PostHog is most easily used via the PostHogProvider component but if you need to - instantiate it directly,{' '} - - check out the docs - {' '} - which explain how to do this correctly. -

- - {`// App.(js|ts) -import { PostHogProvider } from 'posthog-react-native' -... - -export function MyApp() { - return ( - - - - ) -}`} - -

Send an Event

- {`// With hooks -import { usePostHog } from 'posthog-react-native' - -const MyComponent = () => { - const posthog = usePostHog() - - useEffect(() => { - posthog.capture("MyComponent loaded", { foo: "bar" }) - }, []) -} - `} - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/RubyInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/RubyInstructions.tsx deleted file mode 100644 index b3a944a8ff11f..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/RubyInstructions.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function RubyInstallSnippet(): JSX.Element { - return {'gem "posthog-ruby"'} -} - -function RubySetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {`posthog = PostHog::Client.new({ - api_key: "${currentTeam?.api_token}", - host: "${window.location.origin}", - on_error: Proc.new { |status, msg| print msg } -})`} - - ) -} - -function RubyCaptureSnippet(): JSX.Element { - return ( - - {"posthog.capture({\n distinct_id: 'test-id',\n event: 'test-event'})"} - - ) -} - -export function RubyInstructions(): JSX.Element { - return ( - <> -

Install

- -

Configure

- -

Send an Event

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/WebInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/WebInstructions.tsx deleted file mode 100644 index 4decaf1051d98..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/WebInstructions.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { Link } from 'lib/lemon-ui/Link' -import { JSSnippet } from 'lib/components/JSSnippet' -import { LemonDivider } from 'lib/lemon-ui/LemonDivider' -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function JSInstallSnippet(): JSX.Element { - return ( - - {['npm install posthog-js', '# OR', 'yarn add posthog-js', '# OR', 'pnpm add posthog-js'].join('\n')} - - ) -} - -function JSSetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {[ - "import posthog from 'posthog-js'", - '', - `posthog.init('${currentTeam?.api_token}', { api_host: '${window.location.origin}' })`, - ].join('\n')} - - ) -} - -function JSEventSnippet(): JSX.Element { - return ( - {`posthog.capture('my event', { property: 'value' })`} - ) -} - -export function WebInstructions(): JSX.Element { - return ( - <> -

Connect your web app or product

-
-

Option 1. Code snippet

-
- Recommended -
-
-

- Just add this snippet to your website and we'll automatically capture page views, sessions and all - relevant interactions within your website.{' '} - - Learn more - - . -

-

Install the snippet

-

- Insert this snippet in your website within the <head> tag. -

-

Send events

-

Visit your site and click around to generate some initial events.

- -
-

Option 2. Javascript Library

-
-

- Use this option if you want more granular control of how PostHog runs in your website and the events you - capture. Recommended for teams with more stable products and more defined analytics requirements.{' '} - - Learn more - - . -

-

Install the package

- -

- Configure & initialize (see more{' '} - - configuration options - - ) -

- -

Send your first event

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/iOSInstructions.tsx b/frontend/src/scenes/ingestion/frameworks/iOSInstructions.tsx deleted file mode 100644 index 7ccc1ae487fc3..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/iOSInstructions.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { CodeSnippet, Language } from 'lib/components/CodeSnippet' -import { useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -function IOSInstallSnippet(): JSX.Element { - return ( - - {'pod "PostHog", "~> 1.0" # Cocoapods \n# OR \ngithub "posthog/posthog-ios" # Carthage'} - - ) -} - -function IOS_OBJ_C_SetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {`#import \n#import \n\nPHGPostHogConfiguration *configuration = [PHGPostHogConfiguration configurationWithApiKey:@"${currentTeam?.api_token}" host:@"${window.location.origin}"];\n\nconfiguration.captureApplicationLifecycleEvents = YES; // Record certain application events automatically!\nconfiguration.recordScreenViews = YES; // Record screen views automatically!\n\n[PHGPostHog setupWithConfiguration:configuration];`} - - ) -} - -function IOS_SWIFT_SetupSnippet(): JSX.Element { - const { currentTeam } = useValues(teamLogic) - - return ( - - {`import PostHog\n\nlet configuration = PHGPostHogConfiguration(apiKey: "${currentTeam?.api_token}", host: "${window.location.origin}")\n\nconfiguration.captureApplicationLifecycleEvents = true; // Record certain application events automatically!\nconfiguration.recordScreenViews = true; // Record screen views automatically!\n\nPHGPostHog.setup(with: configuration)\nlet posthog = PHGPostHog.shared()`} - - ) -} - -function IOS_OBJ_C_CaptureSnippet(): JSX.Element { - return ( - - {'[[PHGPostHog sharedPostHog] capture:@"Test Event"];'} - - ) -} - -function IOS_SWIFT_CaptureSnippet(): JSX.Element { - return {'posthog.capture("Test Event")'} -} - -export function IOSInstructions(): JSX.Element { - return ( - <> -

Install

- -

Configure Swift

- -

Or configure Objective-C

- -

Send an event with swift

- -

Send an event with Objective-C

- - - ) -} diff --git a/frontend/src/scenes/ingestion/frameworks/index.tsx b/frontend/src/scenes/ingestion/frameworks/index.tsx deleted file mode 100644 index 71597b3648c6b..0000000000000 --- a/frontend/src/scenes/ingestion/frameworks/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -export * from './AndroidInstructions' -export * from './GoInstructions' -export * from './NodeInstructions' -export * from './iOSInstructions' -export * from './PHPInstructions' -export * from './PythonInstructions' -export * from './ReactNativeInstructions' -export * from './RubyInstructions' -export * from './APIInstructions' -export * from './ElixirInstructions' -export * from './FlutterInstructions' diff --git a/frontend/src/scenes/ingestion/ingestionLogic.ts b/frontend/src/scenes/ingestion/ingestionLogic.ts deleted file mode 100644 index 500821474d69b..0000000000000 --- a/frontend/src/scenes/ingestion/ingestionLogic.ts +++ /dev/null @@ -1,717 +0,0 @@ -import { actions, connect, kea, listeners, path, reducers, selectors } from 'kea' -import { Framework, PlatformType } from 'scenes/ingestion/types' -import { API, MOBILE, BACKEND, WEB, thirdPartySources, THIRD_PARTY, ThirdPartySource } from './constants' -import { featureFlagLogic } from 'lib/logic/featureFlagLogic' -import { teamLogic } from 'scenes/teamLogic' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { urls } from 'scenes/urls' -import { actionToUrl, combineUrl, router, urlToAction } from 'kea-router' -import { getBreakpoint } from 'lib/utils/responsiveUtils' -import { windowValues } from 'kea-window-values' -import { subscriptions } from 'kea-subscriptions' -import { TeamType } from '~/types' -import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic' -import { inviteLogic } from 'scenes/settings/organization/inviteLogic' -import api from 'lib/api' -import { loaders } from 'kea-loaders' -import type { ingestionLogicType } from './ingestionLogicType' - -export enum INGESTION_STEPS { - START = 'Get started', - PLATFORM = 'Select your platform', - CONNECT_PRODUCT = 'Connect your product', - VERIFY = 'Listen for events', - SUPERPOWERS = 'Enable superpowers', - BILLING = 'Add payment method', - DONE = 'Done!', -} - -export enum INGESTION_STEPS_WITHOUT_BILLING { - START = 'Get started', - PLATFORM = 'Select your platform', - CONNECT_PRODUCT = 'Connect your product', - VERIFY = 'Listen for events', - SUPERPOWERS = 'Enable superpowers', - DONE = 'Done!', -} - -export enum INGESTION_VIEWS { - BILLING = 'billing', - SUPERPOWERS = 'superpowers', - INVITE_TEAM = 'invite-team', - TEAM_INVITED = 'post-invite-team', - CHOOSE_PLATFORM = 'choose-platform', - VERIFICATION = 'verification', - WEB_INSTRUCTIONS = 'web-instructions', - CHOOSE_FRAMEWORK = 'choose-framework', - GENERATING_DEMO_DATA = 'generating-demo-data', - CHOOSE_THIRD_PARTY = 'choose-third-party', - NO_DEMO_INGESTION = 'no-demo-ingestion', -} - -export const INGESTION_VIEW_TO_STEP = { - [INGESTION_VIEWS.BILLING]: INGESTION_STEPS.BILLING, - [INGESTION_VIEWS.SUPERPOWERS]: INGESTION_STEPS.SUPERPOWERS, - [INGESTION_VIEWS.INVITE_TEAM]: INGESTION_STEPS.START, - [INGESTION_VIEWS.TEAM_INVITED]: INGESTION_STEPS.START, - [INGESTION_VIEWS.NO_DEMO_INGESTION]: INGESTION_STEPS.START, - [INGESTION_VIEWS.CHOOSE_PLATFORM]: INGESTION_STEPS.PLATFORM, - [INGESTION_VIEWS.VERIFICATION]: INGESTION_STEPS.VERIFY, - [INGESTION_VIEWS.WEB_INSTRUCTIONS]: INGESTION_STEPS.CONNECT_PRODUCT, - [INGESTION_VIEWS.CHOOSE_FRAMEWORK]: INGESTION_STEPS.CONNECT_PRODUCT, - [INGESTION_VIEWS.GENERATING_DEMO_DATA]: INGESTION_STEPS.CONNECT_PRODUCT, - [INGESTION_VIEWS.CHOOSE_THIRD_PARTY]: INGESTION_STEPS.CONNECT_PRODUCT, -} - -export type IngestionState = { - platform: PlatformType - framework: Framework - readyToVerify: boolean - showSuperpowers: boolean - showBilling: boolean - hasInvitedMembers: boolean | null - isTechnicalUser: boolean | null - isDemoProject: boolean | null - generatingDemoData: boolean | null -} - -const viewToState = (view: string, props: IngestionState): IngestionState => { - switch (view) { - case INGESTION_VIEWS.INVITE_TEAM: - return { - isTechnicalUser: null, - hasInvitedMembers: null, - platform: null, - framework: null, - readyToVerify: false, - showSuperpowers: false, - showBilling: false, - isDemoProject: props.isDemoProject, - generatingDemoData: false, - } - case INGESTION_VIEWS.TEAM_INVITED: - return { - isTechnicalUser: false, - hasInvitedMembers: true, - platform: null, - framework: null, - readyToVerify: false, - showSuperpowers: false, - showBilling: false, - isDemoProject: props.isDemoProject, - generatingDemoData: false, - } - case INGESTION_VIEWS.BILLING: - return { - isTechnicalUser: null, - hasInvitedMembers: null, - platform: props.platform, - framework: props.framework, - readyToVerify: false, - showSuperpowers: false, - showBilling: true, - isDemoProject: props.isDemoProject, - generatingDemoData: false, - } - case INGESTION_VIEWS.VERIFICATION: - return { - isTechnicalUser: true, - hasInvitedMembers: null, - platform: props.platform, - framework: props.framework, - readyToVerify: true, - showSuperpowers: false, - showBilling: false, - isDemoProject: props.isDemoProject, - generatingDemoData: false, - } - case INGESTION_VIEWS.SUPERPOWERS: - return { - isTechnicalUser: null, - hasInvitedMembers: null, - platform: props.platform, - framework: props.framework, - readyToVerify: false, - showSuperpowers: true, - showBilling: false, - isDemoProject: props.isDemoProject, - generatingDemoData: false, - } - case INGESTION_VIEWS.CHOOSE_PLATFORM: - return { - isTechnicalUser: true, - hasInvitedMembers: null, - platform: null, - framework: null, - readyToVerify: false, - showSuperpowers: false, - showBilling: false, - isDemoProject: props.isDemoProject, - generatingDemoData: false, - } - - case INGESTION_VIEWS.CHOOSE_FRAMEWORK: - return { - isTechnicalUser: true, - hasInvitedMembers: null, - platform: props.platform, - framework: null, - readyToVerify: false, - showSuperpowers: false, - showBilling: false, - isDemoProject: props.isDemoProject, - generatingDemoData: false, - } - } - return { - isTechnicalUser: null, - hasInvitedMembers: null, - platform: null, - framework: null, - readyToVerify: false, - showSuperpowers: false, - showBilling: false, - isDemoProject: props.isDemoProject, - generatingDemoData: false, - } -} - -export const ingestionLogic = kea([ - path(['scenes', 'ingestion', 'ingestionLogic']), - connect({ - values: [ - featureFlagLogic, - ['featureFlags'], - teamLogic, - ['currentTeam'], - preflightLogic, - ['preflight'], - inviteLogic, - ['isInviteModalShown'], - ], - actions: [ - teamLogic, - ['updateCurrentTeamSuccess', 'createTeamSuccess'], - inviteLogic, - ['inviteTeamMembersSuccess'], - ], - }), - actions({ - setState: ({ - isTechnicalUser, - hasInvitedMembers, - platform, - framework, - readyToVerify, - showSuperpowers, - showBilling, - isDemoProject, - generatingDemoData, - }: IngestionState) => ({ - isTechnicalUser, - hasInvitedMembers, - platform, - framework, - readyToVerify, - showSuperpowers, - showBilling, - isDemoProject, - generatingDemoData, - }), - setInstructionsModal: (isOpen: boolean) => ({ isOpen }), - setThirdPartySource: (sourceIndex: number) => ({ sourceIndex }), - completeOnboarding: true, - setCurrentStep: (currentStep: string) => ({ currentStep }), - sidebarStepClick: (step: string) => ({ step }), - next: (props: Partial) => props, - onBack: true, - goToView: (view: INGESTION_VIEWS) => ({ view }), - setSidebarSteps: (steps: string[]) => ({ steps }), - setPollTimeout: (pollTimeout: number) => ({ pollTimeout }), - toggleProjectSwitcher: true, - hideProjectSwitcher: true, - }), - windowValues({ - isSmallScreen: (window: Window) => window.innerWidth < getBreakpoint('md'), - }), - reducers({ - isTechnicalUser: [ - null as null | boolean, - { - setState: (_, { isTechnicalUser }) => isTechnicalUser, - }, - ], - hasInvitedMembers: [ - null as null | boolean, - { - setState: (_, { hasInvitedMembers }) => hasInvitedMembers, - }, - ], - platform: [ - null as null | PlatformType, - { - setState: (_, { platform }) => platform, - }, - ], - framework: [ - null as null | Framework, - { - setState: (_, { framework }) => (framework ? (framework.toUpperCase() as Framework) : null), - }, - ], - readyToVerify: [ - false, - { - setState: (_, { readyToVerify }) => readyToVerify, - }, - ], - showSuperpowers: [ - false, - { - setState: (_, { showSuperpowers }) => showSuperpowers, - }, - ], - showBilling: [ - false, - { - setState: (_, { showBilling }) => showBilling, - }, - ], - instructionsModalOpen: [ - false as boolean, - { - setInstructionsModal: (_, { isOpen }) => isOpen, - }, - ], - thirdPartyIntegrationSource: [ - null as ThirdPartySource | null, - { - setThirdPartySource: (_, { sourceIndex }) => thirdPartySources[sourceIndex], - }, - ], - sidebarSteps: [ - Object.values(INGESTION_STEPS_WITHOUT_BILLING) as string[], - { - setSidebarSteps: (_, { steps }) => steps, - }, - ], - isDemoProject: [ - false as null | boolean, - { - setState: (_, { isDemoProject }) => isDemoProject, - }, - ], - generatingDemoData: [ - false as boolean | null, - { - setState: (_, { generatingDemoData }) => generatingDemoData, - }, - ], - pollTimeout: [ - 0, - { - setPollTimeout: (_, payload) => payload.pollTimeout, - }, - ], - isProjectSwitcherShown: [ - false, - { - toggleProjectSwitcher: (state) => !state, - hideProjectSwitcher: () => false, - }, - ], - }), - loaders(({ actions, values }) => ({ - isDemoDataReady: [ - false as boolean, - { - checkIfDemoDataIsReady: async (_, breakpoint) => { - await breakpoint(1) - - clearTimeout(values.pollTimeout) - - try { - const res = await api.get('api/projects/@current/is_generating_demo_data') - if (!res.is_generating_demo_data) { - return true - } - const pollTimeoutMilliseconds = 1000 - const timeout = window.setTimeout(actions.checkIfDemoDataIsReady, pollTimeoutMilliseconds) - actions.setPollTimeout(timeout) - return false - } catch (e) { - return false - } - }, - }, - ], - })), - selectors(() => ({ - currentState: [ - (s) => [ - s.platform, - s.framework, - s.readyToVerify, - s.showSuperpowers, - s.showBilling, - s.isTechnicalUser, - s.hasInvitedMembers, - s.isDemoProject, - s.generatingDemoData, - ], - ( - platform, - framework, - readyToVerify, - showSuperpowers, - showBilling, - isTechnicalUser, - hasInvitedMembers, - isDemoProject, - generatingDemoData - ) => ({ - platform, - framework, - readyToVerify, - showSuperpowers, - showBilling, - isTechnicalUser, - hasInvitedMembers, - isDemoProject, - generatingDemoData, - }), - ], - currentView: [ - (s) => [s.currentState], - ({ - isTechnicalUser, - platform, - framework, - readyToVerify, - showSuperpowers, - showBilling, - hasInvitedMembers, - isDemoProject, - generatingDemoData, - }) => { - if (isDemoProject) { - return INGESTION_VIEWS.NO_DEMO_INGESTION - } - if (showBilling) { - return INGESTION_VIEWS.BILLING - } - if (showSuperpowers) { - return INGESTION_VIEWS.SUPERPOWERS - } - if (readyToVerify) { - return INGESTION_VIEWS.VERIFICATION - } - if (isTechnicalUser) { - if (!platform) { - return INGESTION_VIEWS.CHOOSE_PLATFORM - } - if (framework || platform === WEB) { - return INGESTION_VIEWS.WEB_INSTRUCTIONS - } - if (platform === MOBILE || platform === BACKEND) { - return INGESTION_VIEWS.CHOOSE_FRAMEWORK - } - if (platform === THIRD_PARTY) { - return INGESTION_VIEWS.CHOOSE_THIRD_PARTY - } - // could be null, so we check that it's set to false - } else if (isTechnicalUser === false) { - if (generatingDemoData) { - return INGESTION_VIEWS.GENERATING_DEMO_DATA - } - if (hasInvitedMembers) { - return INGESTION_VIEWS.TEAM_INVITED - } - if (!platform && !readyToVerify) { - return INGESTION_VIEWS.INVITE_TEAM - } - } - return INGESTION_VIEWS.INVITE_TEAM - }, - ], - currentStep: [ - (s) => [s.currentView], - (currentView) => { - return INGESTION_VIEW_TO_STEP[currentView] - }, - ], - previousStep: [ - (s) => [s.currentStep], - (currentStep) => { - const currentStepIndex = Object.values(INGESTION_STEPS).indexOf(currentStep) - return Object.values(INGESTION_STEPS)[currentStepIndex - 1] - }, - ], - frameworkString: [ - (s) => [s.framework], - (framework): string => { - if (framework) { - const frameworkStrings = { - NODEJS: 'Node.js', - GO: 'Go', - RUBY: 'Ruby', - PYTHON: 'Python', - PHP: 'PHP', - ELIXIR: 'Elixir', - ANDROID: 'Android', - IOS: 'iOS', - REACT_NATIVE: 'React Native', - FLUTTER: 'Flutter', - API: 'HTTP API', - } - return frameworkStrings[framework] || framework - } - return '' - }, - ], - showBillingStep: [ - (s) => [s.preflight], - (preflight): boolean => { - return !!preflight?.cloud && !preflight?.demo - }, - ], - })), - - actionToUrl(({ values }) => ({ - setState: () => getUrl(values), - updateCurrentTeamSuccess: (val) => { - if ( - (router.values.location.pathname.includes( - values.showBillingStep ? '/ingestion/billing' : '/ingestion/superpowers' - ) || - router.values.location.pathname.includes('/ingestion/invites-sent')) && - val.payload?.completed_snippet_onboarding - ) { - return combineUrl(urls.events(), { onboarding_completed: true }).url - } - }, - })), - - urlToAction(({ actions, values }) => ({ - '/ingestion': () => actions.goToView(INGESTION_VIEWS.INVITE_TEAM), - '/ingestion/invites-sent': () => actions.goToView(INGESTION_VIEWS.TEAM_INVITED), - '/ingestion/superpowers': () => actions.goToView(INGESTION_VIEWS.SUPERPOWERS), - '/ingestion/billing': () => actions.goToView(INGESTION_VIEWS.BILLING), - '/ingestion/verify': () => actions.goToView(INGESTION_VIEWS.VERIFICATION), - '/ingestion/platform': () => actions.goToView(INGESTION_VIEWS.CHOOSE_FRAMEWORK), - '/ingestion(/:platform)(/:framework)': (pathParams, searchParams) => { - const platform = pathParams.platform || searchParams.platform || null - const framework = pathParams.framework || searchParams.framework || null - actions.setState({ - isTechnicalUser: true, - hasInvitedMembers: null, - platform: platform, - framework: framework, - readyToVerify: false, - showBilling: false, - showSuperpowers: false, - isDemoProject: values.isDemoProject, - generatingDemoData: false, - }) - }, - })), - listeners(({ actions, values }) => ({ - next: (props) => { - actions.setState({ ...values.currentState, ...props } as IngestionState) - }, - goToView: ({ view }) => { - actions.setState(viewToState(view, values.currentState as IngestionState)) - }, - completeOnboarding: () => { - teamLogic.actions.updateCurrentTeam({ - completed_snippet_onboarding: true, - }) - if ( - !values.currentTeam?.session_recording_opt_in || - !values.currentTeam?.capture_console_log_opt_in || - !values.currentTeam?.capture_performance_opt_in - ) { - eventUsageLogic.actions.reportIngestionRecordingsTurnedOff( - !!values.currentTeam?.session_recording_opt_in, - !!values.currentTeam?.capture_console_log_opt_in, - !!values.currentTeam?.capture_performance_opt_in - ) - } - if (values.currentTeam?.autocapture_opt_out) { - eventUsageLogic.actions.reportIngestionAutocaptureToggled(!!values.currentTeam?.autocapture_opt_out) - } - }, - setPlatform: ({ platform }) => { - eventUsageLogic.actions.reportIngestionSelectPlatformType(platform) - }, - setFramework: ({ framework }) => { - eventUsageLogic.actions.reportIngestionSelectFrameworkType(framework) - }, - sidebarStepClick: ({ step }) => { - switch (step) { - case INGESTION_STEPS.START: - actions.goToView(INGESTION_VIEWS.INVITE_TEAM) - return - case INGESTION_STEPS.PLATFORM: - actions.goToView(INGESTION_VIEWS.CHOOSE_PLATFORM) - return - case INGESTION_STEPS.CONNECT_PRODUCT: - actions.goToView(INGESTION_VIEWS.CHOOSE_FRAMEWORK) - return - case INGESTION_STEPS.VERIFY: - actions.goToView(INGESTION_VIEWS.VERIFICATION) - return - case INGESTION_STEPS.BILLING: - actions.goToView(INGESTION_VIEWS.BILLING) - return - case INGESTION_STEPS.SUPERPOWERS: - actions.goToView(INGESTION_VIEWS.SUPERPOWERS) - return - default: - return - } - }, - onBack: () => { - switch (values.currentView) { - case INGESTION_VIEWS.BILLING: - return actions.goToView(INGESTION_VIEWS.VERIFICATION) - case INGESTION_VIEWS.SUPERPOWERS: - return actions.goToView(INGESTION_VIEWS.CHOOSE_FRAMEWORK) - case INGESTION_VIEWS.TEAM_INVITED: - return actions.goToView(INGESTION_VIEWS.INVITE_TEAM) - case INGESTION_VIEWS.CHOOSE_PLATFORM: - return actions.goToView(INGESTION_VIEWS.INVITE_TEAM) - case INGESTION_VIEWS.VERIFICATION: - return actions.goToView(INGESTION_VIEWS.SUPERPOWERS) - case INGESTION_VIEWS.WEB_INSTRUCTIONS: - return actions.goToView(INGESTION_VIEWS.CHOOSE_PLATFORM) - case INGESTION_VIEWS.CHOOSE_FRAMEWORK: - return actions.goToView(INGESTION_VIEWS.CHOOSE_PLATFORM) - // If they're on the InviteTeam step, but on the Team Invited panel, - // we still want them to be able to go back to the previous step. - // So this resets the state for that panel so they can go back. - case INGESTION_VIEWS.INVITE_TEAM: - return actions.goToView(INGESTION_VIEWS.INVITE_TEAM) - case INGESTION_VIEWS.CHOOSE_THIRD_PARTY: - return actions.goToView(INGESTION_VIEWS.CHOOSE_PLATFORM) - default: - return actions.goToView(INGESTION_VIEWS.INVITE_TEAM) - } - }, - inviteTeamMembersSuccess: () => { - if (router.values.location.pathname.includes(urls.ingestion())) { - actions.setState(viewToState(INGESTION_VIEWS.TEAM_INVITED, values.currentState as IngestionState)) - } - }, - createTeamSuccess: ({ currentTeam }) => { - if (window.location.href.includes(urls.ingestion()) && currentTeam.is_demo) { - actions.checkIfDemoDataIsReady(null) - } else { - window.location.href = urls.ingestion() - } - }, - checkIfDemoDataIsReadySuccess: ({ isDemoDataReady }) => { - if (isDemoDataReady) { - window.location.href = urls.default() - } - }, - })), - subscriptions(({ actions, values }) => ({ - showBillingStep: (value) => { - const steps = value ? INGESTION_STEPS : INGESTION_STEPS_WITHOUT_BILLING - actions.setSidebarSteps(Object.values(steps)) - }, - currentTeam: (currentTeam: TeamType) => { - if (currentTeam?.ingested_event && values.readyToVerify && !values.showBillingStep) { - actions.setCurrentStep(INGESTION_STEPS.DONE) - } - }, - })), -]) - -function getUrl(values: ingestionLogicType['values']): string | [string, Record] { - const { - isTechnicalUser, - platform, - framework, - readyToVerify, - showBilling, - showSuperpowers, - hasInvitedMembers, - generatingDemoData, - } = values - - let url = '/ingestion' - - if (showBilling) { - return url + '/billing' - } - - if (showSuperpowers) { - url += '/superpowers' - return [ - url, - { - platform: platform || undefined, - framework: framework?.toLowerCase() || undefined, - }, - ] - } - - if (readyToVerify) { - url += '/verify' - return [ - url, - { - platform: platform || undefined, - framework: framework?.toLowerCase() || undefined, - }, - ] - } - - if (isTechnicalUser) { - if (framework === API) { - url += '/api' - return [ - url, - { - platform: platform || undefined, - }, - ] - } - - if (platform === MOBILE) { - url += '/mobile' - } - - if (platform === WEB) { - url += '/web' - } - - if (platform === BACKEND) { - url += '/backend' - } - - if (generatingDemoData) { - url += '/just-exploring' - } - - if (platform === THIRD_PARTY) { - url += '/third-party' - } - - if (!platform) { - url += '/platform' - } - - if (framework) { - url += `/${framework.toLowerCase()}` - } - } else { - if (!platform && hasInvitedMembers) { - url += '/invites-sent' - } - } - - return url -} diff --git a/frontend/src/scenes/ingestion/panels/BillingPanel.tsx b/frontend/src/scenes/ingestion/panels/BillingPanel.tsx deleted file mode 100644 index b42fef3eb9de0..0000000000000 --- a/frontend/src/scenes/ingestion/panels/BillingPanel.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { useActions, useValues } from 'kea' -import { CardContainer } from 'scenes/ingestion/CardContainer' -import { ingestionLogic } from 'scenes/ingestion/ingestionLogic' -import { LemonButton } from 'lib/lemon-ui/LemonButton' -import './Panels.scss' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { LemonDivider } from '@posthog/lemon-ui' -import { billingLogic } from 'scenes/billing/billingLogic' -import { Billing } from 'scenes/billing/Billing' -import { LemonSkeleton } from 'lib/lemon-ui/LemonSkeleton' - -export function BillingPanel(): JSX.Element { - const { completeOnboarding } = useActions(ingestionLogic) - const { reportIngestionContinueWithoutBilling } = useActions(eventUsageLogic) - const { billing } = useValues(billingLogic) - - if (!billing) { - return ( - -
- - - -
-
- - -
- - ) - } - - const hasSubscribedToAllProducts = billing.products - .filter((product) => !product.contact_support) - .every((product) => product.subscribed) - const hasSubscribedToAnyProduct = billing.products.some((product) => product.subscribed) - - return ( - - {hasSubscribedToAllProducts ? ( -
-

You're good to go!

- -

- Your organisation is setup for billing with premium features and the increased free tiers - enabled. -

- { - completeOnboarding() - }} - > - Complete - -
- ) : ( -
-

Subscribe for access to all features

- - - - - { - completeOnboarding() - !hasSubscribedToAnyProduct && reportIngestionContinueWithoutBilling() - }} - > - {hasSubscribedToAnyProduct ? 'Continue' : 'Skip for now'} - -
- )} -
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/FrameworkPanel.tsx b/frontend/src/scenes/ingestion/panels/FrameworkPanel.tsx deleted file mode 100644 index 598012915577d..0000000000000 --- a/frontend/src/scenes/ingestion/panels/FrameworkPanel.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { useActions, useValues } from 'kea' -import { CardContainer } from 'scenes/ingestion/CardContainer' -import { ingestionLogic } from '../ingestionLogic' -import { API, mobileFrameworks, BACKEND, webFrameworks } from 'scenes/ingestion/constants' -import { LemonButton } from 'lib/lemon-ui/LemonButton' -import './Panels.scss' -import { IngestionInviteMembersButton } from '../IngestionInviteMembersButton' - -export function FrameworkPanel(): JSX.Element { - const { next } = useActions(ingestionLogic) - const { platform } = useValues(ingestionLogic) - const frameworks = platform === BACKEND ? webFrameworks : mobileFrameworks - - return ( - -
-

- {platform === BACKEND ? 'Choose the framework your app is built in' : 'Pick a mobile platform'} -

-

- We'll provide you with snippets that you can easily add to your codebase to get started! -

-
- {(Object.keys(frameworks) as (keyof typeof frameworks)[]).map((item) => ( - next({ framework: item })} - > - {frameworks[item]} - - ))} - next({ framework: API })} - > - Other - - -
-
-
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/GeneratingDemoDataPanel.tsx b/frontend/src/scenes/ingestion/panels/GeneratingDemoDataPanel.tsx deleted file mode 100644 index a568dd9a82340..0000000000000 --- a/frontend/src/scenes/ingestion/panels/GeneratingDemoDataPanel.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useValues } from 'kea' -import { LemonBanner } from 'lib/lemon-ui/LemonBanner' -import { Spinner } from 'lib/lemon-ui/Spinner/Spinner' -import { organizationLogic } from 'scenes/organizationLogic' -import { CardContainer } from '../CardContainer' -import './Panels.scss' - -export function GeneratingDemoDataPanel(): JSX.Element { - const { currentOrganization } = useValues(organizationLogic) - return ( - -
-
-
- -
-

Generating demo data...

-

- Your demo data is on the way! This can take up to one minute - we'll redirect you when your demo - data is ready. -

- - We're using a demo project. Your other {currentOrganization?.name} projects won't be - affected. - -
-
-
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/InstructionsPanel.scss b/frontend/src/scenes/ingestion/panels/InstructionsPanel.scss deleted file mode 100644 index 5d7b1c7ce4408..0000000000000 --- a/frontend/src/scenes/ingestion/panels/InstructionsPanel.scss +++ /dev/null @@ -1,30 +0,0 @@ -.InstructionsPanel { - max-width: 50rem; - - h1 { - font-size: 28px; - font-weight: 800; - line-height: 40px; - letter-spacing: -0.02em; - } - - h2 { - font-size: 20px; - font-weight: 800; - line-height: 24px; - letter-spacing: -0.02em; - margin-top: 0.5rem; - } - - h3 { - font-size: 16px; - font-weight: 700; - line-height: 24px; - letter-spacing: 0; - margin-top: 0.5rem; - } - - ol { - padding-left: 1rem; - } -} diff --git a/frontend/src/scenes/ingestion/panels/InstructionsPanel.tsx b/frontend/src/scenes/ingestion/panels/InstructionsPanel.tsx deleted file mode 100644 index 48a5114953f28..0000000000000 --- a/frontend/src/scenes/ingestion/panels/InstructionsPanel.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import './InstructionsPanel.scss' -import { CardContainer } from 'scenes/ingestion/CardContainer' -import { - AndroidInstructions, - APIInstructions, - ElixirInstructions, - FlutterInstructions, - GoInstructions, - IOSInstructions, - NodeInstructions, - PHPInstructions, - PythonInstructions, - RNInstructions, - RubyInstructions, -} from 'scenes/ingestion/frameworks' -import { API, MOBILE, BACKEND, WEB } from '../constants' -import { useValues } from 'kea' -import { ingestionLogic } from '../ingestionLogic' -import { WebInstructions } from '../frameworks/WebInstructions' -import { Link } from '@posthog/lemon-ui' - -const frameworksSnippet: Record = { - NODEJS: NodeInstructions, - GO: GoInstructions, - RUBY: RubyInstructions, - PYTHON: PythonInstructions, - PHP: PHPInstructions, - ELIXIR: ElixirInstructions, - ANDROID: AndroidInstructions, - IOS: IOSInstructions, - REACT_NATIVE: RNInstructions, - FLUTTER: FlutterInstructions, - API: APIInstructions, -} - -export function InstructionsPanel(): JSX.Element { - const { platform, framework, frameworkString } = useValues(ingestionLogic) - - if (platform !== WEB && !framework) { - return <> - } - - const FrameworkSnippet: React.ComponentType = frameworksSnippet[framework as string] - - return ( -
- {platform === WEB ? ( - - - - ) : framework === API ? ( - -

{frameworkString}

-

- Need a different framework? Our HTTP API is a flexible way to use PostHog anywhere. Try the - endpoint below to send your first event, and view our API docs{' '} - here. -

- -
- ) : ( - -

{`Setup ${frameworkString}`}

- - {platform === BACKEND ? ( - <> -

- Follow the instructions below to send custom events from your {frameworkString} backend. -

- - - ) : null} - {platform === MOBILE ? : null} -
- )} -
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/InviteTeamPanel.tsx b/frontend/src/scenes/ingestion/panels/InviteTeamPanel.tsx deleted file mode 100644 index c6a30c5cf484f..0000000000000 --- a/frontend/src/scenes/ingestion/panels/InviteTeamPanel.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { useActions } from 'kea' -import { ingestionLogic } from 'scenes/ingestion/ingestionLogic' -import { LemonButton } from 'lib/lemon-ui/LemonButton' -import './Panels.scss' -import { LemonDivider } from 'lib/lemon-ui/LemonDivider' -import { IconChevronRight } from 'lib/lemon-ui/icons' -import { inviteLogic } from 'scenes/settings/organization/inviteLogic' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { DemoProjectButton } from './PanelComponents' - -export function InviteTeamPanel(): JSX.Element { - const { next } = useActions(ingestionLogic) - const { showInviteModal } = useActions(inviteLogic) - const { reportInviteMembersButtonClicked } = useActions(eventUsageLogic) - - return ( -
-

Welcome to PostHog

-

- PostHog enables you to understand your customers, answer product questions, and test new features{' '} - - all in our comprehensive product suite. To get started, we'll need to add a code snippet to your - product. -

- -
- next({ isTechnicalUser: true })} - fullWidth - size="large" - className="mb-4" - type="primary" - sideIcon={} - > -
-

I can add a code snippet to my product.

-

- Available for JavaScript, Android, iOS, React Native, Node.js, Ruby, Go, and more. -

-
-
- { - showInviteModal() - reportInviteMembersButtonClicked() - }} - fullWidth - size="large" - className="mb-4" - type="secondary" - sideIcon={} - > -
-

I'll need a team member to add the code snippet to our product.

-

- We'll send an invite and instructions for getting the code snippet added. -

-
-
- -
-
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/NoDemoIngestionPanel.tsx b/frontend/src/scenes/ingestion/panels/NoDemoIngestionPanel.tsx deleted file mode 100644 index 722ba20e9e603..0000000000000 --- a/frontend/src/scenes/ingestion/panels/NoDemoIngestionPanel.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { LemonButton } from '@posthog/lemon-ui' -import { useActions, useValues } from 'kea' -import { IconArrowRight } from 'lib/lemon-ui/icons' -import { organizationLogic } from 'scenes/organizationLogic' -import { userLogic } from 'scenes/userLogic' -import { CardContainer } from '../CardContainer' -import './Panels.scss' - -export function NoDemoIngestionPanel(): JSX.Element { - const { currentOrganization } = useValues(organizationLogic) - const { updateCurrentTeam } = useActions(userLogic) - - return ( - -
-

Whoops!

-

- New events can't be ingested into a demo project. But, you can switch to another project if you'd - like: -

-
- {currentOrganization?.teams - ?.filter((team) => !team.is_demo) - .map((team) => ( -

- } - fullWidth - onClick={() => updateCurrentTeam(team.id)} - > - {team.name} - -

- ))} -
-
-
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/PanelComponents.tsx b/frontend/src/scenes/ingestion/panels/PanelComponents.tsx deleted file mode 100644 index 4d817149a280b..0000000000000 --- a/frontend/src/scenes/ingestion/panels/PanelComponents.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { useActions, useValues } from 'kea' -import { LemonButton } from 'lib/lemon-ui/LemonButton' -import { LemonDivider } from 'lib/lemon-ui/LemonDivider' -import { ingestionLogic, INGESTION_STEPS, IngestionState } from '../ingestionLogic' -import './Panels.scss' -import { IconArrowLeft, IconChevronRight } from 'lib/lemon-ui/icons' -import { IngestionInviteMembersButton } from '../IngestionInviteMembersButton' -import { teamLogic } from 'scenes/teamLogic' -import { organizationLogic } from 'scenes/organizationLogic' -import { userLogic } from 'scenes/userLogic' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { FEATURE_FLAGS } from 'lib/constants' -import { featureFlagLogic } from 'lib/logic/featureFlagLogic' - -const DEMO_TEAM_NAME: string = 'Hedgebox' - -export function PanelFooter({ - nextProps, - onContinue, - finalStep = false, - showInviteTeamMembers = true, -}: { - nextProps: Partial - onContinue?: () => void - finalStep?: boolean - showInviteTeamMembers?: boolean -}): JSX.Element { - const { next } = useActions(ingestionLogic) - - return ( -
- -
- { - onContinue && onContinue() - next(nextProps) - }} - > - {finalStep ? 'Complete' : 'Continue'} - - {showInviteTeamMembers && } -
-
- ) -} - -export function PanelHeader(): JSX.Element | null { - const { isSmallScreen, previousStep, currentStep, hasInvitedMembers } = useValues(ingestionLogic) - const { onBack } = useActions(ingestionLogic) - - // no back buttons on the Getting Started step - // but only if it's not the MembersInvited panel - // (since they'd want to be able to go back from there) - if (currentStep === INGESTION_STEPS.START && !hasInvitedMembers) { - return null - } - - return ( -
- } size="small"> - {isSmallScreen - ? '' - : // If we're on the MembersInvited panel, they "go back" to - // the Get Started step, even though it's technically the same step - currentStep === INGESTION_STEPS.START && hasInvitedMembers - ? currentStep - : previousStep} - -
- ) -} - -export function DemoProjectButton({ text, subtext }: { text: string; subtext?: string }): JSX.Element { - const { next } = useActions(ingestionLogic) - const { createTeam } = useActions(teamLogic) - const { currentOrganization } = useValues(organizationLogic) - const { updateCurrentTeam } = useActions(userLogic) - const { reportIngestionTryWithDemoDataClicked, reportProjectCreationSubmitted } = useActions(eventUsageLogic) - const { featureFlags } = useValues(featureFlagLogic) - - if (featureFlags[FEATURE_FLAGS.ONBOARDING_V2_DEMO] !== 'test') { - return <> - } - return ( - { - // If the current org has a demo team, just navigate there - if (currentOrganization?.teams && currentOrganization.teams.filter((team) => team.is_demo).length > 0) { - updateCurrentTeam(currentOrganization.teams.filter((team) => team.is_demo)[0].id) - } else { - // Create a new demo team - createTeam({ name: DEMO_TEAM_NAME, is_demo: true }) - next({ isTechnicalUser: false, generatingDemoData: true }) - reportProjectCreationSubmitted( - currentOrganization?.teams ? currentOrganization.teams.length : 0, - DEMO_TEAM_NAME.length - ) - } - reportIngestionTryWithDemoDataClicked() - }} - fullWidth - size="large" - className="ingestion-view-demo-data mb-4" - type="secondary" - sideIcon={} - > -
-

- {currentOrganization?.teams && currentOrganization.teams.filter((team) => team.is_demo).length > 0 - ? 'Explore the demo project' - : text} -

- {subtext ?

{subtext}

: null} -
-
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/Panels.scss b/frontend/src/scenes/ingestion/panels/Panels.scss deleted file mode 100644 index ca98aa806c405..0000000000000 --- a/frontend/src/scenes/ingestion/panels/Panels.scss +++ /dev/null @@ -1,37 +0,0 @@ -.FrameworkPanel { - max-width: 400px; -} - -.panel-footer { - background-color: white; - margin-bottom: 1rem; - bottom: 0; -} - -.ingestion-title { - font-size: 28px; - font-weight: 700; - line-height: 40px; - display: flex; - align-items: center; - gap: 0.5rem; - margin: 0; -} - -.IngestionSubtitle { - font-size: 20px; - font-weight: 800; - margin: 1rem 0; -} - -.prompt-text { - margin-top: 1rem; -} - -.ingestion-listening-for-events { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - margin-bottom: 1rem; -} diff --git a/frontend/src/scenes/ingestion/panels/PlatformPanel.tsx b/frontend/src/scenes/ingestion/panels/PlatformPanel.tsx deleted file mode 100644 index 5ee33d73597c5..0000000000000 --- a/frontend/src/scenes/ingestion/panels/PlatformPanel.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { useActions } from 'kea' -import { ingestionLogic } from '../ingestionLogic' -import { THIRD_PARTY, platforms } from '../constants' -import { LemonButton } from 'lib/lemon-ui/LemonButton' -import './Panels.scss' -import { LemonDivider } from 'lib/lemon-ui/LemonDivider' -import { IngestionInviteMembersButton } from '../IngestionInviteMembersButton' - -export function PlatformPanel(): JSX.Element { - const { next } = useActions(ingestionLogic) - - return ( -
-

Where do you want to send events from?

-

- With PostHog, you can collect events from nearly anywhere. Select one to start, and you can always add - more sources later. -

- -
- {platforms.map((platform) => ( - next({ platform })} - > - {platform} - - ))} - next({ platform: THIRD_PARTY })} - fullWidth - center - size="large" - className="mb-2" - type="primary" - > - Import events from a third party - - -
-
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/SuperpowersPanel.tsx b/frontend/src/scenes/ingestion/panels/SuperpowersPanel.tsx deleted file mode 100644 index 5ec5cad19e87e..0000000000000 --- a/frontend/src/scenes/ingestion/panels/SuperpowersPanel.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { LemonSwitch, Link } from '@posthog/lemon-ui' -import { CardContainer } from 'scenes/ingestion/CardContainer' -import { useActions, useValues } from 'kea' -import { SupportHeroHog } from 'lib/components/hedgehogs' -import { useState } from 'react' -import { teamLogic } from 'scenes/teamLogic' -import { ingestionLogic } from '../ingestionLogic' - -export function SuperpowersPanel(): JSX.Element { - const { updateCurrentTeam } = useActions(teamLogic) - const { showBillingStep } = useValues(ingestionLogic) - const { completeOnboarding } = useActions(ingestionLogic) - const [sessionRecordingsChecked, setSessionRecordingsChecked] = useState(true) - const [autocaptureChecked, setAutocaptureChecked] = useState(true) - - return ( - { - updateCurrentTeam({ - session_recording_opt_in: sessionRecordingsChecked, - capture_console_log_opt_in: sessionRecordingsChecked, - capture_performance_opt_in: sessionRecordingsChecked, - autocapture_opt_out: !autocaptureChecked, - }) - if (!showBillingStep) { - completeOnboarding() - } - }} - finalStep={!showBillingStep} - > -
-
-

Enable your product superpowers

-

- Collecting events from your app is just the first step toward building great products. PostHog - gives you other superpowers, too, like recording user sessions and automagically capturing - frontend interactions. -

-
-
- -
-
-
- { - setSessionRecordingsChecked(checked) - }} - label="Record user sessions" - fullWidth={true} - labelClassName={'text-base font-semibold'} - checked={sessionRecordingsChecked} - /> -

- See recordings of how your users are really using your product with powerful features like error - tracking, filtering, and analytics.{' '} - - Learn more - {' '} - about Session recordings. -

-
-
- { - setAutocaptureChecked(checked) - }} - label="Autocapture frontend interactions" - fullWidth={true} - labelClassName={'text-base font-semibold'} - checked={autocaptureChecked} - /> -

- If you use our JavaScript or React Native libraries, we'll automagically capture frontend - interactions like pageviews, clicks, and more.{' '} - - Fine-tune what you capture - {' '} - directly in your code snippet. -

-
-
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/TeamInvitedPanel.tsx b/frontend/src/scenes/ingestion/panels/TeamInvitedPanel.tsx deleted file mode 100644 index 5d6365d22c335..0000000000000 --- a/frontend/src/scenes/ingestion/panels/TeamInvitedPanel.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useActions } from 'kea' -import { ingestionLogic } from 'scenes/ingestion/ingestionLogic' -import { LemonButton } from 'lib/lemon-ui/LemonButton' -import './Panels.scss' -import { LemonDivider } from 'lib/lemon-ui/LemonDivider' -import { IconChevronRight } from 'lib/lemon-ui/icons' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { DemoProjectButton } from './PanelComponents' - -export function TeamInvitedPanel(): JSX.Element { - const { completeOnboarding } = useActions(ingestionLogic) - const { reportIngestionContinueWithoutVerifying } = useActions(eventUsageLogic) - - return ( -
-

Help is on the way!

-

You can still explore PostHog while you wait for your team members to join.

- -
- - { - completeOnboarding() - reportIngestionContinueWithoutVerifying() - }} - fullWidth - size="large" - className="mb-4" - type="secondary" - sideIcon={} - > -
-

Continue without any events.

-

- It might look a little empty in there, but we'll do our best. -

-
-
-
-
- ) -} diff --git a/frontend/src/scenes/ingestion/panels/ThirdPartyIcons.tsx b/frontend/src/scenes/ingestion/panels/ThirdPartyIcons.tsx deleted file mode 100644 index 1ebb0e6545346..0000000000000 --- a/frontend/src/scenes/ingestion/panels/ThirdPartyIcons.tsx +++ /dev/null @@ -1,58 +0,0 @@ -export const Segment = (props: React.SVGProps): JSX.Element => { - return ( - - - - - - - - - - - - - ) -} - -export const RSS = (props: React.SVGProps): JSX.Element => { - return ( - - - - - - - - - - - - - - - - - - - - ) -} diff --git a/frontend/src/scenes/ingestion/panels/ThirdPartyPanel.tsx b/frontend/src/scenes/ingestion/panels/ThirdPartyPanel.tsx deleted file mode 100644 index 8fd51654aafb9..0000000000000 --- a/frontend/src/scenes/ingestion/panels/ThirdPartyPanel.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { useValues, useActions } from 'kea' -import { LemonButton } from 'lib/lemon-ui/LemonButton' -import { CardContainer } from '../CardContainer' -import { ingestionLogic } from '../ingestionLogic' -import './Panels.scss' -import { LemonModal } from 'lib/lemon-ui/LemonModal' -import { thirdPartySources } from '../constants' -import { IconOpenInNew } from 'lib/lemon-ui/icons' -import { CodeSnippet } from 'lib/components/CodeSnippet' -import { teamLogic } from 'scenes/teamLogic' -import { LemonTag } from 'lib/lemon-ui/LemonTag/LemonTag' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { Link } from '@posthog/lemon-ui' - -export function ThirdPartyPanel(): JSX.Element { - const { setInstructionsModal, setThirdPartySource } = useActions(ingestionLogic) - const { reportIngestionThirdPartyAboutClicked, reportIngestionThirdPartyConfigureClicked } = - useActions(eventUsageLogic) - - return ( - -
-

Set up third-party integrations

- {thirdPartySources.map((source, idx) => { - return ( -
-
-
-
{source.icon}
-
-

- {source.name} Import - {source.labels?.map((label, labelIdx) => ( - - {label} - - ))} -

-

- {source.description - ? source.description - : `Send events from ${source.name} into PostHog`} -

-
-
-
- { - reportIngestionThirdPartyAboutClicked(source.name) - }} - > - About - - { - setThirdPartySource(idx) - setInstructionsModal(true) - reportIngestionThirdPartyConfigureClicked(source.name) - }} - > - Configure - -
-
-
- ) - })} -
- -
- ) -} - -export function IntegrationInstructionsModal(): JSX.Element { - const { instructionsModalOpen, thirdPartyIntegrationSource } = useValues(ingestionLogic) - const { setInstructionsModal } = useActions(ingestionLogic) - const { currentTeam } = useValues(teamLogic) - - return ( - <> - {thirdPartyIntegrationSource?.name && ( - setInstructionsModal(false)} - title="Configure integration" - footer={ - setInstructionsModal(false)}> - Done - - } - > -
-

- {thirdPartyIntegrationSource.icon} - Integrate with {thirdPartyIntegrationSource.name} -

-
-
-

- The{' '} - - {thirdPartyIntegrationSource.name} docs page for the PostHog integration - {' '} - provides a detailed overview of how to set up this integration. -

- PostHog Project API Key - {currentTeam?.api_token || ''} -
-
- window.open(thirdPartyIntegrationSource.aboutLink)} - sideIcon={} - > - Take me to the {thirdPartyIntegrationSource.name} docs - -
-

Steps:

-
    -
  1. Complete the steps for the {thirdPartyIntegrationSource.name} integration.
  2. -
  3. - Close this step and click continue to begin listening for events. -
  4. -
-
-
-
- )} - - ) -} diff --git a/frontend/src/scenes/ingestion/panels/VerificationPanel.tsx b/frontend/src/scenes/ingestion/panels/VerificationPanel.tsx deleted file mode 100644 index a6138f22fa438..0000000000000 --- a/frontend/src/scenes/ingestion/panels/VerificationPanel.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { useActions, useValues } from 'kea' -import { useInterval } from 'lib/hooks/useInterval' -import { CardContainer } from '../CardContainer' -import { ingestionLogic } from '../ingestionLogic' -import { teamLogic } from 'scenes/teamLogic' -import { Spinner } from 'lib/lemon-ui/Spinner/Spinner' -import { LemonButton } from 'lib/lemon-ui/LemonButton' -import './Panels.scss' -import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { IngestionInviteMembersButton } from '../IngestionInviteMembersButton' - -export function VerificationPanel(): JSX.Element { - const { loadCurrentTeam } = useActions(teamLogic) - const { currentTeam } = useValues(teamLogic) - const { next } = useActions(ingestionLogic) - const { reportIngestionContinueWithoutVerifying } = useActions(eventUsageLogic) - - useInterval(() => { - if (!currentTeam?.ingested_event) { - loadCurrentTeam() - } - }, 2000) - - return !currentTeam?.ingested_event ? ( - -
-
- -

Listening for events...

-

- Once you have integrated the snippet and sent an event, we will verify it was properly received - and continue. -

- - { - next({ showSuperpowers: true }) - reportIngestionContinueWithoutVerifying() - }} - > - or continue without verifying - -
-
-
- ) : ( - -
-
-

Successfully sent events!

-

- You will now be able to explore PostHog and take advantage of all its features to understand - your users. -

-
-
-
- ) -} diff --git a/frontend/src/scenes/ingestion/types.ts b/frontend/src/scenes/ingestion/types.ts deleted file mode 100644 index 7d64652d8cdb5..0000000000000 --- a/frontend/src/scenes/ingestion/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { API, MOBILE, mobileFrameworks, BACKEND, WEB, webFrameworks, THIRD_PARTY } from 'scenes/ingestion/constants' - -export type Framework = keyof typeof webFrameworks | keyof typeof mobileFrameworks | typeof API | null - -export type PlatformType = typeof WEB | typeof MOBILE | typeof BACKEND | typeof THIRD_PARTY | null diff --git a/frontend/src/scenes/onboarding/Onboarding.tsx b/frontend/src/scenes/onboarding/Onboarding.tsx index 50a1ff9f25956..96badaa09ce95 100644 --- a/frontend/src/scenes/onboarding/Onboarding.tsx +++ b/frontend/src/scenes/onboarding/Onboarding.tsx @@ -1,9 +1,6 @@ import { SceneExport } from 'scenes/sceneTypes' import { useActions, useValues } from 'kea' import { useEffect, useState } from 'react' -import { featureFlagLogic } from 'lib/logic/featureFlagLogic' -import { FEATURE_FLAGS } from 'lib/constants' -import { urls } from 'scenes/urls' import { OnboardingStepKey, onboardingLogic } from './onboardingLogic' import { SDKs } from './sdks/SDKs' import { ProductKey } from '~/types' @@ -120,15 +117,8 @@ const SurveysOnboarding = (): JSX.Element => { } export function Onboarding(): JSX.Element | null { - const { featureFlags } = useValues(featureFlagLogic) const { product } = useValues(onboardingLogic) - useEffect(() => { - if (featureFlags[FEATURE_FLAGS.PRODUCT_SPECIFIC_ONBOARDING] !== 'test') { - location.href = urls.ingestion() - } - }, []) - if (!product) { return <> } diff --git a/frontend/src/scenes/onboarding/OnboardingBillingStep.tsx b/frontend/src/scenes/onboarding/OnboardingBillingStep.tsx index 552a490688887..f6ef3ee324f77 100644 --- a/frontend/src/scenes/onboarding/OnboardingBillingStep.tsx +++ b/frontend/src/scenes/onboarding/OnboardingBillingStep.tsx @@ -6,7 +6,7 @@ import { OnboardingStepKey, onboardingLogic } from './onboardingLogic' import { BillingProductV2Type } from '~/types' import { Spinner } from 'lib/lemon-ui/Spinner' import { BillingHero } from 'scenes/billing/BillingHero' -import { LemonButton } from '@posthog/lemon-ui' +import { LemonBanner, LemonButton } from '@posthog/lemon-ui' import { getUpgradeProductLink } from 'scenes/billing/billing-utils' import { billingProductLogic } from 'scenes/billing/billingProductLogic' import { eventUsageLogic } from 'lib/utils/eventUsageLogic' @@ -25,6 +25,7 @@ export const OnboardingBillingStep = ({ const { currentAndUpgradePlans } = useValues(billingProductLogic({ product })) const { reportBillingUpgradeClicked } = useActions(eventUsageLogic) const plan = currentAndUpgradePlans?.upgradePlan + const currentPlan = currentAndUpgradePlans?.currentPlan return ( {product.subscribed ? (
-
+
@@ -64,6 +65,15 @@ export const OnboardingBillingStep = ({
+ {currentPlan.initial_billing_limit && ( +
+ + To protect your costs and ours, this product has an initial billing limit of $ + {currentPlan.initial_billing_limit}. You can change or remove this limit on the + Billing page. + +
+ )}
) : ( <> diff --git a/frontend/src/scenes/onboarding/onboardingLogic.tsx b/frontend/src/scenes/onboarding/onboardingLogic.tsx index c96defd34a1a5..c5c02e1db0c60 100644 --- a/frontend/src/scenes/onboarding/onboardingLogic.tsx +++ b/frontend/src/scenes/onboarding/onboardingLogic.tsx @@ -153,7 +153,9 @@ export const onboardingLogic = kea([ }), listeners(({ actions, values }) => ({ loadBillingSuccess: () => { - actions.setProduct(values.billing?.products.find((p) => p.type === values.productKey) || null) + if (window.location.pathname.startsWith('/onboarding')) { + actions.setProduct(values.billing?.products.find((p) => p.type === values.productKey) || null) + } }, setProduct: ({ product }) => { if (!product) { @@ -205,7 +207,7 @@ export const onboardingLogic = kea([ } }, resetStepKey: () => { - actions.setStepKey(values.allOnboardingSteps[0].props.stepKey) + values.allOnboardingSteps[0] && actions.setStepKey(values.allOnboardingSteps[0]?.props.stepKey) }, })), actionToUrl(({ values }) => ({ diff --git a/frontend/src/scenes/products/Products.tsx b/frontend/src/scenes/products/Products.tsx index 66994f4ab0f72..cba24e76c8a36 100644 --- a/frontend/src/scenes/products/Products.tsx +++ b/frontend/src/scenes/products/Products.tsx @@ -3,9 +3,6 @@ import { SceneExport } from 'scenes/sceneTypes' import { BillingProductV2Type, ProductKey } from '~/types' import { useActions, useValues } from 'kea' import { teamLogic } from 'scenes/teamLogic' -import { useEffect } from 'react' -import { featureFlagLogic } from 'lib/logic/featureFlagLogic' -import { FEATURE_FLAGS } from 'lib/constants' import { urls } from 'scenes/urls' import { billingLogic } from 'scenes/billing/billingLogic' import { Spinner } from 'lib/lemon-ui/Spinner' @@ -131,18 +128,11 @@ export function ProductCard({ } export function Products(): JSX.Element { - const { featureFlags } = useValues(featureFlagLogic) const { billing } = useValues(billingLogic) const { currentTeam } = useValues(teamLogic) const isFirstProduct = Object.keys(currentTeam?.has_completed_onboarding_for || {}).length === 0 const products = billing?.products || [] - useEffect(() => { - if (featureFlags[FEATURE_FLAGS.PRODUCT_SPECIFIC_ONBOARDING] !== 'test') { - location.href = urls.ingestion() - } - }, []) - return (
diff --git a/frontend/src/scenes/products/productsLogic.tsx b/frontend/src/scenes/products/productsLogic.tsx index 48a17171bdc8a..29c2678b63fe7 100644 --- a/frontend/src/scenes/products/productsLogic.tsx +++ b/frontend/src/scenes/products/productsLogic.tsx @@ -1,16 +1,20 @@ -import { kea, path, actions, listeners } from 'kea' +import { kea, path, actions, listeners, connect } from 'kea' import { teamLogic } from 'scenes/teamLogic' import { ProductKey } from '~/types' import type { productsLogicType } from './productsLogicType' import { eventUsageLogic } from 'lib/utils/eventUsageLogic' +import { onboardingLogic } from 'scenes/onboarding/onboardingLogic' export const productsLogic = kea([ path(() => ['scenes', 'products', 'productsLogic']), + connect({ + actions: [teamLogic, ['updateCurrentTeam'], onboardingLogic, ['setProduct']], + }), actions(() => ({ onSelectProduct: (product: ProductKey) => ({ product }), })), - listeners(() => ({ + listeners(({ actions }) => ({ onSelectProduct: ({ product }) => { eventUsageLogic.actions.reportOnboardingProductSelected(product) @@ -18,7 +22,7 @@ export const productsLogic = kea([ case ProductKey.PRODUCT_ANALYTICS: return case ProductKey.SESSION_REPLAY: - teamLogic.actions.updateCurrentTeam({ + actions.updateCurrentTeam({ session_recording_opt_in: true, capture_console_log_opt_in: true, capture_performance_opt_in: true, diff --git a/frontend/src/scenes/sceneLogic.ts b/frontend/src/scenes/sceneLogic.ts index bd5c46206d001..8e87f1029fd0b 100644 --- a/frontend/src/scenes/sceneLogic.ts +++ b/frontend/src/scenes/sceneLogic.ts @@ -13,8 +13,6 @@ import { LoadedScene, Params, Scene, SceneConfig, SceneExport, SceneParams } fro import { emptySceneParams, preloadedScenes, redirects, routes, sceneConfigurations } from 'scenes/scenes' import { organizationLogic } from './organizationLogic' import { appContextLogic } from './appContextLogic' -import { featureFlagLogic } from 'lib/logic/featureFlagLogic' -import { FEATURE_FLAGS } from 'lib/constants' /** Mapping of some scenes that aren't directly accessible from the sidebar to ones that are - for the sidebar. */ const sceneNavAlias: Partial> = { @@ -256,21 +254,12 @@ export const sceneLogic = kea([ !location.pathname.startsWith('/settings') ) { if ( - featureFlagLogic.values.featureFlags[FEATURE_FLAGS.PRODUCT_SPECIFIC_ONBOARDING] === - 'test' && + !teamLogic.values.currentTeam.completed_snippet_onboarding && !Object.keys(teamLogic.values.currentTeam.has_completed_onboarding_for || {}).length ) { - console.warn('No onboarding completed, redirecting to products') + console.warn('No onboarding completed, redirecting to /products') router.actions.replace(urls.products()) return - } else if ( - featureFlagLogic.values.featureFlags[FEATURE_FLAGS.PRODUCT_SPECIFIC_ONBOARDING] !== - 'test' && - !teamLogic.values.currentTeam.completed_snippet_onboarding - ) { - console.warn('Ingestion tutorial not completed, redirecting to it') - router.actions.replace(urls.ingestion()) - return } } } diff --git a/frontend/src/scenes/sceneTypes.ts b/frontend/src/scenes/sceneTypes.ts index be279d2e22f45..3f41023e13f63 100644 --- a/frontend/src/scenes/sceneTypes.ts +++ b/frontend/src/scenes/sceneTypes.ts @@ -65,7 +65,6 @@ export enum Scene { PasswordReset = 'PasswordReset', PasswordResetComplete = 'PasswordResetComplete', PreflightCheck = 'PreflightCheck', - Ingestion = 'IngestionWizard', OrganizationCreationConfirm = 'OrganizationCreationConfirm', Unsubscribe = 'Unsubscribe', DebugQuery = 'DebugQuery', diff --git a/frontend/src/scenes/scenes.ts b/frontend/src/scenes/scenes.ts index 22533e73b9130..8a0ec5f699aa2 100644 --- a/frontend/src/scenes/scenes.ts +++ b/frontend/src/scenes/scenes.ts @@ -196,10 +196,6 @@ export const sceneConfigurations: Partial> = { [Scene.IntegrationsRedirect]: { name: 'Integrations Redirect', }, - [Scene.Ingestion]: { - projectBased: true, - layout: 'plain', - }, [Scene.Products]: { projectBased: true, layout: 'plain', @@ -472,8 +468,6 @@ export const routes: Record = { [urls.inviteSignup(':id')]: Scene.InviteSignup, [urls.passwordReset()]: Scene.PasswordReset, [urls.passwordResetComplete(':uuid', ':token')]: Scene.PasswordResetComplete, - [urls.ingestion()]: Scene.Ingestion, - [urls.ingestion() + '/*']: Scene.Ingestion, [urls.products()]: Scene.Products, [urls.onboarding(':productKey')]: Scene.Onboarding, [urls.verifyEmail()]: Scene.VerifyEmail, diff --git a/frontend/src/scenes/settings/project/AutocaptureSettings.tsx b/frontend/src/scenes/settings/project/AutocaptureSettings.tsx index e65c24e6f76b5..6b5492fc05069 100644 --- a/frontend/src/scenes/settings/project/AutocaptureSettings.tsx +++ b/frontend/src/scenes/settings/project/AutocaptureSettings.tsx @@ -11,7 +11,7 @@ export function AutocaptureSettings(): JSX.Element { const { userLoading } = useValues(userLogic) const { currentTeam } = useValues(teamLogic) const { updateCurrentTeam } = useActions(teamLogic) - const { reportIngestionAutocaptureToggled } = useActions(eventUsageLogic) + const { reportAutocaptureToggled } = useActions(eventUsageLogic) return ( <> @@ -33,7 +33,7 @@ export function AutocaptureSettings(): JSX.Element { updateCurrentTeam({ autocapture_opt_out: !checked, }) - reportIngestionAutocaptureToggled(!checked) + reportAutocaptureToggled(!checked) }} checked={!currentTeam?.autocapture_opt_out} disabled={userLoading} @@ -49,7 +49,7 @@ export function ExceptionAutocaptureSettings(): JSX.Element { const { userLoading } = useValues(userLogic) const { currentTeam } = useValues(teamLogic) const { updateCurrentTeam } = useActions(teamLogic) - const { reportIngestionAutocaptureExceptionsToggled } = useActions(eventUsageLogic) + const { reportAutocaptureExceptionsToggled } = useActions(eventUsageLogic) const { errorsToIgnoreRules, rulesCharacters } = useValues(autocaptureExceptionsLogic) const { setErrorsToIgnoreRules } = useActions(autocaptureExceptionsLogic) @@ -62,7 +62,7 @@ export function ExceptionAutocaptureSettings(): JSX.Element { updateCurrentTeam({ autocapture_exceptions_opt_in: checked, }) - reportIngestionAutocaptureExceptionsToggled(checked) + reportAutocaptureExceptionsToggled(checked) }} checked={!!currentTeam?.autocapture_exceptions_opt_in} disabled={userLoading} @@ -81,7 +81,7 @@ export function ExceptionAutocaptureSettings(): JSX.Element {

You can enter a regular expression that matches values of{' '} here to ignore them. One per line. For example, if you - want to drop all errors that contain the word "bot", or you can enter "bot" here. Or if you want to drop + want to drop all errors that contain the word "bot", you can enter "bot" here. Or if you want to drop all errors that are exactly "bot", you can enter "^bot$".

Only up to 300 characters of config are allowed here.

diff --git a/frontend/src/scenes/urls.ts b/frontend/src/scenes/urls.ts index 32f56860cbabb..d84ac0cfa7473 100644 --- a/frontend/src/scenes/urls.ts +++ b/frontend/src/scenes/urls.ts @@ -157,7 +157,6 @@ export const urls = { verifyEmail: (userUuid: string = '', token: string = ''): string => `/verify_email${userUuid ? `/${userUuid}` : ''}${token ? `/${token}` : ''}`, inviteSignup: (id: string): string => `/signup/${id}`, - ingestion: (): string => '/ingestion', products: (): string => '/products', onboarding: (productKey: string): string => `/onboarding/${productKey}`, // Cloud only diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 7c305c1cff971..27f80e6b98922 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -1278,6 +1278,7 @@ export interface BillingV2PlanType { current_plan?: any tiers?: BillingV2TierType[] included_if?: 'no_active_subscription' | 'has_subscription' | null + initial_billing_limit?: number } export interface PlanInterface {