Skip to content

Commit

Permalink
fix(pipeline): Fix loading of apps and refactor enums (#19719)
Browse files Browse the repository at this point in the history
* fix(pipeline): Fix loading of apps and refactor enums

* Restore Billing.stories.tsx

* Update UI snapshots for `chromium` (1)

* Update UI snapshots for `chromium` (1)

* Rename `DestinationTypeKind` to `PipelineAppBackend`

* Update UI snapshots for `chromium` (1)

* Fix typing

* Fix typing more

* Update UI snapshots for `chromium` (1)

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
Twixes and github-actions[bot] authored Jan 12, 2024
1 parent 269fa4b commit 99de2ca
Show file tree
Hide file tree
Showing 45 changed files with 254 additions and 201 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 1 addition & 3 deletions frontend/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
MOCK_DEFAULT_USER,
MOCK_PERSON_PROPERTIES,
MOCK_SECOND_ORGANIZATION_MEMBER,
MOCK_TEAM_ID,
} from 'lib/api.mock'

import { getAvailableFeatures } from '~/mocks/features'
Expand Down Expand Up @@ -73,8 +72,7 @@ export const defaultMocks: Mocks = {
'/api/organizations/@current/plugins/repository/': [],
'/api/organizations/@current/plugins/unused/': [],
'/api/plugin_config/': toPaginatedResponse([MOCK_DEFAULT_PLUGIN_CONFIG]),
[`/api/projects/${MOCK_TEAM_ID}/plugin_configs/${MOCK_DEFAULT_PLUGIN_CONFIG.id}/`]: MOCK_DEFAULT_PLUGIN_CONFIG,
'/api/projects/@current/persons/properties/': toPaginatedResponse(MOCK_PERSON_PROPERTIES),
[`/api/projects/:team_id/plugin_configs/${MOCK_DEFAULT_PLUGIN_CONFIG.id}/`]: MOCK_DEFAULT_PLUGIN_CONFIG,
'/api/projects/:team_id/persons': EMPTY_PAGINATED_RESPONSE,
'/api/projects/:team_id/persons/properties/': toPaginatedResponse(MOCK_PERSON_PROPERTIES),
'/api/personal_api_keys/': [],
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/apps/AppLogsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useValues } from 'kea'
import { LemonSkeleton } from 'lib/lemon-ui/LemonSkeleton'
import { PipelineAppLogs } from 'scenes/pipeline/PipelineAppLogs'

import { PipelineTabs } from '~/types'
import { PipelineAppKind } from '~/types'

import { appMetricsSceneLogic } from './appMetricsSceneLogic'

Expand All @@ -15,7 +15,7 @@ export function AppLogsTab(): JSX.Element {

return (
<div className="space-y-8">
<PipelineAppLogs id={pluginConfig.id} kind={PipelineTabs.Destinations} />
<PipelineAppLogs id={pluginConfig.id} kind={PipelineAppKind.Destination} />
</div>
)
}
3 changes: 2 additions & 1 deletion frontend/src/scenes/pipeline/AppMetrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,8 @@ function ErrorDetailsModal({ pluginConfigId }: { pluginConfigId: number }): JSX.
// eslint-disable-next-line react/forbid-dom-props
<div className="flex flex-col space-y-2" style={{ height: '80vh' }}>
<div>
<LemonLabel>When:</LemonLabel> <TZLabel time={activeErrorDetails.timestamp} showSeconds />
<span className="font-semibold">When:</span>{' '}
<TZLabel time={activeErrorDetails.timestamp} showSeconds />
</div>

{activeErrorDetails.error_details.eventCount && (
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/scenes/pipeline/Destinations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { updatedAtColumn } from 'lib/lemon-ui/LemonTable/columnUtils'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { deleteWithUndo } from 'lib/utils/deleteWithUndo'

import { PipelineTabs, ProductKey } from '~/types'
import { PipelineAppKind, ProductKey } from '~/types'

import { DestinationType, pipelineDestinationsLogic } from './destinationsLogic'
import { NewButton } from './NewButton'
Expand All @@ -42,7 +42,7 @@ export function Destinations(): JSX.Element {
productKey={ProductKey.PIPELINE_DESTINATIONS}
description="Pipeline destinations allow you to export data outside of PostHog, such as webhooks to Slack."
docsURL="https://posthog.com/docs/cdp"
actionElementOverride={<NewButton tab={PipelineTabs.Destinations} />}
actionElementOverride={<NewButton kind={PipelineAppKind.Destination} />}
isEmpty={true}
/>
)}
Expand Down Expand Up @@ -85,7 +85,7 @@ function DestinationsTable(): JSX.Element {
{
title: 'App',
render: function RenderAppInfo(_, destination) {
if (destination.type === 'webhook') {
if (destination.backend === 'plugin') {
return <RenderApp plugin={destination.plugin} />
}
return <></> // TODO: batch export
Expand All @@ -100,7 +100,7 @@ function DestinationsTable(): JSX.Element {
{
title: '24h', // TODO: two options 24h or 7d selected
render: function Render24hDeliveryRate(_, destination) {
if (destination.type === 'webhook') {
if (destination.backend === 'plugin') {
let tooltip = 'No events exported in the past 24 hours'
let value = '-'
let tagType: LemonTagType = 'muted'
Expand Down Expand Up @@ -206,7 +206,7 @@ function DestinationsTable(): JSX.Element {
</LemonButton>
)}
<LemonDivider />
{destination.type === 'webhook' && (
{destination.backend === 'plugin' && (
<LemonButton // TODO: batch exports
status="danger"
onClick={() => {
Expand Down
15 changes: 6 additions & 9 deletions frontend/src/scenes/pipeline/NewButton.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import { LemonButton } from 'lib/lemon-ui/LemonButton'
import { urls } from 'scenes/urls'

import { PipelineAppTabs, PipelineTabs } from '~/types'

import { singularName } from './pipelineLogic'
import { PipelineAppKind, PipelineAppTab } from '~/types'

type NewButtonProps = {
tab: PipelineTabs
kind: PipelineAppKind
}

export function NewButton({ tab }: NewButtonProps): JSX.Element {
const singular = singularName(tab)
export function NewButton({ kind }: NewButtonProps): JSX.Element {
return (
<LemonButton
data-attr={`new-${singular}`}
to={urls.pipelineApp(tab, 'new', PipelineAppTabs.Configuration)}
data-attr={`new-${kind}`}
to={urls.pipelineApp(kind, 'new', PipelineAppTab.Configuration)}
type="primary"
>
New {singular}
New {kind}
</LemonButton>
)
}
99 changes: 59 additions & 40 deletions frontend/src/scenes/pipeline/Pipeline.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import { App } from 'scenes/App'
import { urls } from 'scenes/urls'

import { mswDecorator, useStorybookMocks } from '~/mocks/browser'
import { PipelineAppTabs, PipelineTabs } from '~/types'
import { PipelineAppKind, PipelineAppTab, PipelineTab } from '~/types'

import batchExports from './__mocks__/batchExports.json'
import pluginConfigs from './__mocks__/pluginConfigs.json'
import plugins from './__mocks__/plugins.json'
import { appMetricsLogic } from './appMetricsLogic'
import { appsManagementLogic } from './appsManagementLogic'
import { pipelineLogic } from './pipelineLogic'
Expand All @@ -18,9 +21,14 @@ export default {
// mocks used by all stories in this file
mswDecorator({
get: {
'api/organizations/@current/pipeline_transformations/': {},
'api/organizations/@current/plugins/': {},
'api/projects/:team_id/pipeline_transformation_configs/': {},
'/api/projects/:team_id/batch_exports/': batchExports,
'/api/organizations/:organization_id/batch_exports/': batchExports,
'/api/organizations/@current/plugins/': plugins,
'/api/organizations/@current/pipeline_transformations/': plugins,
'/api/projects/:team_id/pipeline_transformation_configs/': pluginConfigs,
// TODO: Differentiate between transformation and destination mocks for nicer mocks
'/api/organizations/@current/pipeline_destinations/': plugins,
'/api/projects/:team_id/pipeline_destination_configs/': pluginConfigs,
},
}),
],
Expand All @@ -33,6 +41,13 @@ export default {
}, // scene mode
} as Meta

const eventSequenceTimerPluginConfigId = pluginConfigs.results.find(
(conf) => conf.plugin === plugins.results.find((plugin) => plugin.name === 'Event Sequence Timer Plugin')!.id
)!.id
const geoIpConfigId = pluginConfigs.results.find(
(conf) => conf.plugin === plugins.results.find((plugin) => plugin.name === 'GeoIP')!.id
)!.id

export function PipelineLandingPage(): JSX.Element {
// also Destinations page
useEffect(() => {
Expand All @@ -41,80 +56,90 @@ export function PipelineLandingPage(): JSX.Element {
}, [])
return <App />
}

export function PipelineFilteringPage(): JSX.Element {
useEffect(() => {
router.actions.push(urls.pipeline(PipelineTabs.Filters))
router.actions.push(urls.pipeline(PipelineTab.Filters))
pipelineLogic.mount()
}, [])
return <App />
}

export function PipelineTransformationsPageEmpty(): JSX.Element {
useEffect(() => {
router.actions.push(urls.pipeline(PipelineTabs.Transformations))
router.actions.push(urls.pipeline(PipelineTab.Transformations))
pipelineLogic.mount()
}, [])
return <App />
}

export function PipelineTransformationsPage(): JSX.Element {
useStorybookMocks({
get: {
'api/organizations/@current/pipeline_transformations/': require('./__mocks__/plugins.json'),
'api/projects/:team_id/pipeline_transformation_configs/': require('./__mocks__/transformationPluginConfigs.json'),
},
})
useEffect(() => {
router.actions.push(urls.pipeline(PipelineTabs.Transformations))
router.actions.push(urls.pipeline(PipelineTab.Transformations))
pipelineLogic.mount()
}, [])
return <App />
}

export function PipelineDestinationsPage(): JSX.Element {
useStorybookMocks({
get: {
'api/organizations/@current/pipeline_destinations/': require('./__mocks__/plugins.json'),
'api/projects/:team_id/pipeline_destination_configs/': require('./__mocks__/transformationPluginConfigs.json'),
},
})
useEffect(() => {
router.actions.push(urls.pipeline(PipelineTabs.Destinations))
router.actions.push(urls.pipeline(PipelineTab.Destinations))
pipelineLogic.mount()
}, [])
return <App />
}

export function PipelineAppConfiguration(): JSX.Element {
useEffect(() => {
router.actions.push(urls.pipelineApp(PipelineTabs.Destinations, 1, PipelineAppTabs.Configuration))
router.actions.push(
urls.pipelineApp(
PipelineAppKind.Destination,
eventSequenceTimerPluginConfigId,
PipelineAppTab.Configuration
)
)
}, [])
return <App />
}

export function PipelineAppConfigurationEmpty(): JSX.Element {
useEffect(() => {
router.actions.push(urls.pipelineApp(PipelineAppKind.Destination, geoIpConfigId, PipelineAppTab.Configuration))
}, [])
return <App />
}

export function PipelineAppConfiguration404(): JSX.Element {
useEffect(() => {
router.actions.push(urls.pipelineApp(PipelineAppKind.Destination, 4239084923809, PipelineAppTab.Configuration))
}, [])
return <App />
}

export function PipelineAppMetrics(): JSX.Element {
useStorybookMocks({
get: {
'api/projects/:team_id/app_metrics/4?date_from=-7d': require('./__mocks__/pluginMetrics.json'),
'api/projects/:team_id/app_metrics/4/error_details?error_type=Error': require('./__mocks__/pluginErrorDetails.json'),
'/api/projects/:team_id/app_metrics/:plugin_config_id?date_from=-7d': require('./__mocks__/pluginMetrics.json'),
'/api/projects/:team_id/app_metrics/:plugin_config_id/error_details?error_type=Error': require('./__mocks__/pluginErrorDetails.json'),
},
})
useEffect(() => {
router.actions.push(urls.pipelineApp(PipelineTabs.Destinations, 4, PipelineAppTabs.Metrics))
appMetricsLogic({ pluginConfigId: 4 }).mount()
router.actions.push(urls.pipelineApp(PipelineAppKind.Destination, geoIpConfigId, PipelineAppTab.Metrics))
appMetricsLogic({ pluginConfigId: geoIpConfigId }).mount()
}, [])
return <App />
}

export function PipelineAppMetricsErrorModal(): JSX.Element {
useStorybookMocks({
get: {
'api/projects/:team_id/app_metrics/4?date_from=-7d': require('./__mocks__/pluginMetrics.json'),
'api/projects/:team_id/app_metrics/4/error_details?error_type=Error': require('./__mocks__/pluginErrorDetails.json'),
'/api/projects/:team_id/app_metrics/:plugin_config_id?date_from=-7d': require('./__mocks__/pluginMetrics.json'),
'/api/projects/:team_id/app_metrics/:plugin_config_id/error_details?error_type=Error': require('./__mocks__/pluginErrorDetails.json'),
},
})
useEffect(() => {
router.actions.push(urls.pipelineApp(PipelineTabs.Destinations, 4, PipelineAppTabs.Metrics))
const logic = appMetricsLogic({ pluginConfigId: 4 })
router.actions.push(urls.pipelineApp(PipelineAppKind.Destination, geoIpConfigId, PipelineAppTab.Metrics))
const logic = appMetricsLogic({ pluginConfigId: geoIpConfigId })
logic.mount()
logic.actions.openErrorDetailsModal('Error')
}, [])
Expand All @@ -124,38 +149,32 @@ export function PipelineAppMetricsErrorModal(): JSX.Element {
export function PipelineAppLogs(): JSX.Element {
useStorybookMocks({
get: {
'api/projects/:team_id/plugin_configs/1/logs': require('./__mocks__/pluginLogs.json'),
'/api/projects/:team_id/plugin_configs/:plugin_config_id/logs': require('./__mocks__/pluginLogs.json'),
},
})
useEffect(() => {
router.actions.push(urls.pipelineApp(PipelineTabs.Destinations, 1, PipelineAppTabs.Logs))
router.actions.push(urls.pipelineApp(PipelineAppKind.Destination, geoIpConfigId, PipelineAppTab.Logs))
}, [])
return <App />
}

export function PipelineAppLogsBatchExport(): JSX.Element {
useStorybookMocks({
get: {
'api/projects/:team_id/batch_exports/018cf79f-a9e5-0001-cd6a-edc4886d939d/logs': require('./__mocks__/batchExportLogs.json'),
'/api/projects/:team_id/batch_exports/:export_id/logs': require('./__mocks__/batchExportLogs.json'),
},
})
useEffect(() => {
router.actions.push(
urls.pipelineApp(PipelineTabs.Destinations, '018cf79f-a9e5-0001-cd6a-edc4886d939d', PipelineAppTabs.Logs)
urls.pipelineApp(PipelineAppKind.Destination, batchExports.results[0].id, PipelineAppTab.Logs)
)
}, [])
return <App />
}

export function PipelineAppsManagementPage(): JSX.Element {
useStorybookMocks({
get: {
'api/organizations/@current/plugins/': require('./__mocks__/plugins.json'),
},
})

useEffect(() => {
router.actions.push(urls.pipeline(PipelineTabs.AppsManagement))
router.actions.push(urls.pipeline(PipelineTab.AppsManagement))
appsManagementLogic.mount()
}, [])
return <App />
Expand Down
21 changes: 12 additions & 9 deletions frontend/src/scenes/pipeline/Pipeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,37 @@ import { LemonTabs } from 'lib/lemon-ui/LemonTabs'
import { SceneExport } from 'scenes/sceneTypes'
import { urls } from 'scenes/urls'

import { PipelineTabs } from '~/types'
import { PipelineTab } from '~/types'

import { AppsManagement } from './AppsManagement'
import { Destinations } from './Destinations'
import { NewButton } from './NewButton'
import { PIPELINE_TAB_TO_APP_KIND } from './PipelineApp'
import { humanFriendlyTabName, pipelineLogic } from './pipelineLogic'
import { Transformations } from './Transformations'

export function Pipeline(): JSX.Element {
const { currentTab } = useValues(pipelineLogic)

const tabToContent: Record<PipelineTabs, JSX.Element> = {
[PipelineTabs.Filters]: <div>Coming soon</div>,
[PipelineTabs.Transformations]: <Transformations />,
[PipelineTabs.Destinations]: <Destinations />,
[PipelineTabs.AppsManagement]: <AppsManagement />,
const tabToContent: Record<PipelineTab, JSX.Element> = {
[PipelineTab.Filters]: <div>Coming soon</div>,
[PipelineTab.Transformations]: <Transformations />,
[PipelineTab.Destinations]: <Destinations />,
[PipelineTab.AppsManagement]: <AppsManagement />,
}

const maybeKind = PIPELINE_TAB_TO_APP_KIND[currentTab]

return (
<div className="pipeline-scene">
<PageHeader
caption="Add filters or transformations to the events sent to PostHog or export them to other tools."
buttons={<NewButton tab={currentTab} />}
buttons={maybeKind ? <NewButton kind={maybeKind} /> : undefined}
/>
<LemonTabs
activeKey={currentTab}
onChange={(tab) => router.actions.push(urls.pipeline(tab as PipelineTabs))}
tabs={Object.values(PipelineTabs).map((tab) => ({
onChange={(tab) => router.actions.push(urls.pipeline(tab as PipelineTab))}
tabs={Object.values(PipelineTab).map((tab) => ({
// TODO: Hide admin management based on `canGloballyManagePlugins` permission
label: humanFriendlyTabName(tab),
key: tab,
Expand Down
Loading

0 comments on commit 99de2ca

Please sign in to comment.