diff --git a/frontend/__snapshots__/scenes-app-pipeline--pipeline-filtering-page.png b/frontend/__snapshots__/scenes-app-pipeline--pipeline-filtering-page.png new file mode 100644 index 0000000000000..57b43ed4238ff Binary files /dev/null and b/frontend/__snapshots__/scenes-app-pipeline--pipeline-filtering-page.png differ diff --git a/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page.png b/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page.png index f71305149b638..854c2468d8cfc 100644 Binary files a/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page.png and b/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page.png differ diff --git a/frontend/__snapshots__/scenes-app-pipeline--pipeline-transformations-page.png b/frontend/__snapshots__/scenes-app-pipeline--pipeline-transformations-page.png new file mode 100644 index 0000000000000..4cf705d0bb98b Binary files /dev/null and b/frontend/__snapshots__/scenes-app-pipeline--pipeline-transformations-page.png differ diff --git a/frontend/src/scenes/pipeline/Pipeline.stories.tsx b/frontend/src/scenes/pipeline/Pipeline.stories.tsx index dd0b1641b9e72..e386b2400c0a5 100644 --- a/frontend/src/scenes/pipeline/Pipeline.stories.tsx +++ b/frontend/src/scenes/pipeline/Pipeline.stories.tsx @@ -3,6 +3,8 @@ import { Meta } from '@storybook/react' import { App } from 'scenes/App' import { router } from 'kea-router' import { urls } from 'scenes/urls' +import { PipelineTabs } from '~/types' +import { pipelineLogic } from './pipelineLogic' export default { title: 'Scenes-App/Pipeline', @@ -11,8 +13,24 @@ export default { } as Meta export function PipelineLandingPage(): JSX.Element { + // also Destinations page useEffect(() => { router.actions.push(urls.pipeline()) + pipelineLogic.mount() + }, []) + return +} +export function PipelineFilteringPage(): JSX.Element { + useEffect(() => { + router.actions.push(urls.pipeline(PipelineTabs.Filters)) + pipelineLogic.mount() + }, []) + return +} +export function PipelineTransformationsPage(): JSX.Element { + useEffect(() => { + router.actions.push(urls.pipeline(PipelineTabs.Transformations)) + pipelineLogic.mount() }, []) return } diff --git a/frontend/src/scenes/pipeline/Pipeline.tsx b/frontend/src/scenes/pipeline/Pipeline.tsx index 42ee27cc7c66b..29d417fbf614d 100644 --- a/frontend/src/scenes/pipeline/Pipeline.tsx +++ b/frontend/src/scenes/pipeline/Pipeline.tsx @@ -1,11 +1,35 @@ import { SceneExport } from 'scenes/sceneTypes' -import { pipelineLogic } from './pipelineLogic' import { PageHeader } from 'lib/components/PageHeader' +import { humanFriendlyTabName, pipelineLogic, singularName } from './pipelineLogic' +import { LemonTabs } from 'lib/lemon-ui/LemonTabs' +import { useValues } from 'kea' +import { LemonButton } from 'lib/lemon-ui/LemonButton' +import { urls } from 'scenes/urls' +import { router } from 'kea-router' +import { PipelineTabs } from '~/types' export function Pipeline(): JSX.Element { + const { currentTab } = useValues(pipelineLogic) + + const singular = singularName(currentTab) return (
- + + New {singular} + + } + /> + router.actions.push(urls.pipeline(tab as PipelineTabs))} + tabs={Object.values(PipelineTabs).map((tab) => ({ + label: humanFriendlyTabName(tab), + key: tab, + }))} + />
) } @@ -14,6 +38,3 @@ export const scene: SceneExport = { component: Pipeline, logic: pipelineLogic, } - -// TODO: error from import ./pipeline/PipelineScene -// TODO: update https://storybook.posthog.net/?path=/docs/how-to-build-a-scene--docs <- about kea stuff to exclude and have run pnpm ... for type creation diff --git a/frontend/src/scenes/pipeline/pipelineLogic.tsx b/frontend/src/scenes/pipeline/pipelineLogic.tsx index 9d74a469558e0..017e1966745b7 100644 --- a/frontend/src/scenes/pipeline/pipelineLogic.tsx +++ b/frontend/src/scenes/pipeline/pipelineLogic.tsx @@ -1,6 +1,67 @@ -import { kea } from 'kea' +import { actions, kea, path, reducers, selectors } from 'kea' import type { pipelineLogicType } from './pipelineLogicType' +import { actionToUrl, urlToAction } from 'kea-router' +import { urls } from 'scenes/urls' +import { Breadcrumb, PipelineTabs } from '~/types' -export const pipelineLogic = kea({ - path: ['scenes', 'pipeline', 'pipelineLogic'], -}) +export const singularName = (tab: PipelineTabs): string => { + switch (tab) { + case PipelineTabs.Filters: + return 'filter' + case PipelineTabs.Transformations: + return 'transformation' + case PipelineTabs.Destinations: + return 'destination' + } +} + +export const humanFriendlyTabName = (tab: PipelineTabs): string => { + switch (tab) { + case PipelineTabs.Filters: + return 'Filters' + case PipelineTabs.Transformations: + return 'Transformations' + case PipelineTabs.Destinations: + return 'Destinations' + } +} + +export const pipelineLogic = kea([ + path(['scenes', 'pipeline', 'pipelineLogic']), + actions({ + setCurrentTab: (tab: PipelineTabs = PipelineTabs.Destinations) => ({ tab }), + }), + reducers({ + currentTab: [ + PipelineTabs.Destinations as PipelineTabs, + { + setCurrentTab: (_, { tab }) => tab, + }, + ], + }), + selectors(() => ({ + breadcrumbs: [ + (s) => [s.currentTab], + (tab): Breadcrumb[] => { + const breadcrumbs: Breadcrumb[] = [{ name: 'Pipeline' }] + breadcrumbs.push({ + name: humanFriendlyTabName(tab), + }) + + return breadcrumbs + }, + ], + })), + actionToUrl(({ values }) => { + return { + setCurrentTab: () => [urls.pipeline(values.currentTab)], + } + }), + urlToAction(({ actions, values }) => ({ + '/pipeline/:tab': ({ tab }) => { + if (tab !== values.currentTab) { + actions.setCurrentTab(tab as PipelineTabs) + } + }, + })), +]) diff --git a/frontend/src/scenes/scenes.ts b/frontend/src/scenes/scenes.ts index 311a72f6f5c34..78153fac0cf1e 100644 --- a/frontend/src/scenes/scenes.ts +++ b/frontend/src/scenes/scenes.ts @@ -3,7 +3,7 @@ import { Error404 as Error404Component } from '~/layout/Error404' import { ErrorNetwork as ErrorNetworkComponent } from '~/layout/ErrorNetwork' import { ErrorProjectUnavailable as ErrorProjectUnavailableComponent } from '~/layout/ErrorProjectUnavailable' import { urls } from 'scenes/urls' -import { InsightShortId, PropertyFilterType, ReplayTabs } from '~/types' +import { InsightShortId, PipelineTabs, PropertyFilterType, ReplayTabs } from '~/types' import { combineUrl } from 'kea-router' import { getDefaultEventsSceneQuery } from 'scenes/events/defaults' import { EventsQuery } from '~/queries/schema' @@ -437,6 +437,11 @@ export const routes: Record = { [urls.personByUUID('*', false)]: Scene.Person, [urls.persons()]: Scene.Persons, [urls.pipeline()]: Scene.Pipeline, + // One entry for every available tab + ...Object.values(PipelineTabs).reduce((acc, tab) => { + acc[urls.pipeline(tab)] = Scene.Pipeline + return acc + }, {} as Record), [urls.groups(':groupTypeIndex')]: Scene.Groups, [urls.group(':groupTypeIndex', ':groupKey', false)]: Scene.Group, [urls.group(':groupTypeIndex', ':groupKey', false, ':groupTab')]: Scene.Group, diff --git a/frontend/src/scenes/urls.ts b/frontend/src/scenes/urls.ts index 9e454a67f9f81..a0253f81ffc21 100644 --- a/frontend/src/scenes/urls.ts +++ b/frontend/src/scenes/urls.ts @@ -6,6 +6,7 @@ import { FilterType, InsightShortId, ReplayTabs, + PipelineTabs, } from '~/types' import { combineUrl } from 'kea-router' import { ExportOptions } from '~/exporter/types' @@ -93,7 +94,8 @@ export const urls = { personByUUID: (uuid: string, encode: boolean = true): string => encode ? `/persons/${encodeURIComponent(uuid)}` : `/persons/${uuid}`, persons: (): string => '/persons', - pipeline: (): string => '/pipeline', + pipeline: (tab?: PipelineTabs): string => `/pipeline/${tab ? tab : 'destinations'}`, + pipelineNew: (tab?: PipelineTabs): string => `/pipeline/${tab ? tab : 'destinations'}/new`, groups: (groupTypeIndex: string | number): string => `/groups/${groupTypeIndex}`, // :TRICKY: Note that groupKey is provided by user. We need to override urlPatternOptions for kea-router. group: (groupTypeIndex: string | number, groupKey: string, encode: boolean = true, tab?: string | null): string => diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 00a73ed0b8cf3..21c2465b8e0d7 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -515,6 +515,12 @@ export enum ExperimentsTabs { Archived = 'archived', } +export enum PipelineTabs { + Filters = 'filters', + Transformations = 'transformations', + Destinations = 'destinations', +} + export enum ProgressStatus { Draft = 'draft', Running = 'running',