Skip to content

Commit

Permalink
feat: Pipeline UI App tabs with logs view
Browse files Browse the repository at this point in the history
  • Loading branch information
tiina303 committed Nov 15, 2023
1 parent 7f851ce commit 7a2e3f4
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 14 deletions.
1 change: 1 addition & 0 deletions frontend/src/scenes/appScenes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const appScenes: Record<Scene, () => any> = {
[Scene.PersonsManagement]: () => import('./persons-management/PersonsManagementScene'),
[Scene.Person]: () => import('./persons/PersonScene'),
[Scene.Pipeline]: () => import('./pipeline/Pipeline'),
[Scene.PipelineApp]: () => import('./pipeline/PipelineApp'),
[Scene.Group]: () => import('./groups/Group'),
[Scene.Action]: () => import('./actions/Action'),
[Scene.Experiments]: () => import('./experiments/Experiments'),
Expand Down
28 changes: 27 additions & 1 deletion frontend/src/scenes/pipeline/Pipeline.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ 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 { PipelineAppTabs, PipelineTabs } from '~/types'
import { pipelineLogic } from './pipelineLogic'
import { mswDecorator, useStorybookMocks } from '~/mocks/browser'

Expand Down Expand Up @@ -58,3 +58,29 @@ export function PipelineTransformationsPage(): JSX.Element {
}, [])
return <App />
}

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

export function PipelineAppMetrics(): JSX.Element {
useEffect(() => {
router.actions.push(urls.pipelineApp(1, PipelineAppTabs.Metrics))
}, [])
return <App />
}

export function PipelineAppLogs(): JSX.Element {
useStorybookMocks({
get: {
'api/projects/:team_id/plugin_configs/1/logs': require('./__mocks__/pluginLogs.json'),
},
})
useEffect(() => {
router.actions.push(urls.pipelineApp(1, PipelineAppTabs.Logs))
}, [])
return <App />
}
47 changes: 47 additions & 0 deletions frontend/src/scenes/pipeline/PipelineApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { SceneExport } from 'scenes/sceneTypes'
import { useValues } from 'kea'
import { pipelineAppLogic } from './pipelineAppLogic'
import { PageHeader } from 'lib/components/PageHeader'
import { LemonTabs } from 'lib/lemon-ui/LemonTabs/LemonTabs'
import { router } from 'kea-router'
import { PipelineAppTabs } from '~/types'
import { urls } from 'scenes/urls'
import { PluginLogs } from 'scenes/plugins/plugin/PluginLogs'
import { Spinner } from '@posthog/lemon-ui'

export const scene: SceneExport = {
component: PipelineApp,
logic: pipelineAppLogic,
paramsToProps: ({ params: { id } }: { params: { id?: string } }) => ({ id: id ? parseInt(id) : 'new' }),
}

export function PipelineApp({ id }: { id?: string } = {}): JSX.Element {
const { currentTab } = useValues(pipelineAppLogic)

const confId = id ? parseInt(id) : undefined

if (!confId) {
return <Spinner />
}

const tab_to_content: Record<PipelineAppTabs, JSX.Element> = {
[PipelineAppTabs.Configuration]: <div>Configuration editing</div>,
[PipelineAppTabs.Metrics]: <div>Metrics page</div>,
[PipelineAppTabs.Logs]: <PluginLogs pluginConfigId={confId} />,
}

return (
<div className="pipeline-app-scene">
<PageHeader title={`Pipeline App`} />
<LemonTabs
activeKey={currentTab}
onChange={(tab) => router.actions.push(urls.pipelineApp(confId, tab as PipelineAppTabs))}
tabs={Object.values(PipelineAppTabs).map((tab) => ({
label: tab,
key: tab,
content: tab_to_content[tab],
}))}
/>
</div>
)
}
22 changes: 16 additions & 6 deletions frontend/src/scenes/pipeline/Transformations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import { useActions, useValues } from 'kea'
import { pipelineTransformationsLogic } from './transformationsLogic'
import { PluginImage } from 'scenes/plugins/plugin/PluginImage'
import { PipelineTabs, PluginConfigTypeNew, PluginType, ProductKey } from '~/types'
import { PipelineAppTabs, PipelineTabs, PluginConfigTypeNew, PluginType, ProductKey } from '~/types'
import { urls } from 'scenes/urls'
import { SortableContext, arrayMove, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable'
import { DndContext, DragEndEvent } from '@dnd-kit/core'
Expand Down Expand Up @@ -100,7 +100,12 @@ export function Transformations(): JSX.Element {
return (
<>
<Tooltip title={'Click to update configuration, view metrics, and more'}>
<Link to={urls.appMetrics(pluginConfig.id)}>
<Link
to={urls.pipelineApp(
pluginConfig.id,
PipelineAppTabs.Configuration
)}
>
<span className="row-name">{pluginConfig.name}</span>
</Link>
</Tooltip>
Expand Down Expand Up @@ -153,7 +158,9 @@ export function Transformations(): JSX.Element {
</>
}
>
<Link to={urls.appLogs(pluginConfig.id)}>
<Link
to={urls.pipelineApp(pluginConfig.id, PipelineAppTabs.Logs)}
>
<LemonTag type="danger" className="uppercase">
Error
</LemonTag>
Expand Down Expand Up @@ -207,23 +214,26 @@ export function Transformations(): JSX.Element {
)}
<LemonButton
status="stealth"
to={urls.appMetrics(pluginConfig.id)} // TODO: fix the URL
to={urls.pipelineApp(
pluginConfig.id,
PipelineAppTabs.Configuration
)} // TODO: fix the URL
id={`app-${pluginConfig.id}-configuration`}
fullWidth
>
{canConfigurePlugins ? 'Edit' : 'View'} app configuration
</LemonButton>
<LemonButton
status="stealth"
to={urls.appMetrics(pluginConfig.id)}
to={urls.pipelineApp(pluginConfig.id, PipelineAppTabs.Metrics)}
id={`app-${pluginConfig.id}-metrics`}
fullWidth
>
View app metrics
</LemonButton>
<LemonButton
status="stealth"
to={urls.appLogs(pluginConfig.id)}
to={urls.pipelineApp(pluginConfig.id, PipelineAppTabs.Logs)}
id={`app-${pluginConfig.id}-logs`}
fullWidth
>
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/scenes/pipeline/__mocks__/pluginLogs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": "018bb51f-0f9f-0000-34ae-d3aa1d9a5770",
"team_id": 1,
"plugin_id": 1,
"plugin_config_id": 11,
"timestamp": "2023-11-09T17:26:33.626000Z",
"source": "PLUGIN",
"type": "ERROR",
"message": "Error: Received an unexpected error from the endpoint API. Response 400: {\"meta\":{\"errors\":[\"value for attribute '$current_url' cannot be longer than 1000 bytes\"]}}\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)",
"instance_id": "12345678-1234-1234-1234-123456789012"
},
{
"id": "018bb51e-262a-0000-eb34-39afd4691d56",
"team_id": 1,
"plugin_id": 1,
"plugin_config_id": 11,
"timestamp": "2023-11-09T17:25:33.790000Z",
"source": "PLUGIN",
"type": "INFO",
"message": "Successfully sent event to endpoint",
"instance_id": "12345678-1234-1234-1234-123456789012"
}
]
}
53 changes: 53 additions & 0 deletions frontend/src/scenes/pipeline/pipelineAppLogic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { kea, reducers, path, props, key, actions, selectors } from 'kea'

import type { pipelineAppLogicType } from './pipelineAppLogicType'
import { Breadcrumb, PipelineAppTabs } from '~/types'
import { urls } from 'scenes/urls'
import { actionToUrl, urlToAction } from 'kea-router'

export interface PipelineAppLogicProps {
id: number
}

export const pipelineAppLogic = kea<pipelineAppLogicType>([
props({} as PipelineAppLogicProps),
key(({ id }) => id),
path((id) => ['scenes', 'pipeline', 'PipelineAppLogic', id]),
actions({
setCurrentTab: (tab: PipelineAppTabs = PipelineAppTabs.Configuration) => ({ tab }),
}),
reducers({
currentTab: [
PipelineAppTabs.Configuration as PipelineAppTabs,
{
setCurrentTab: (_, { tab }) => tab,
},
],
}),
selectors({
breadcrumbs: [
() => [],
(): Breadcrumb[] => [
{
name: 'Pipeline',
path: urls.pipeline(),
},
{
name: 'App name',
},
],
],
}),
actionToUrl(({ values, props }) => {
return {
setCurrentTab: () => [urls.pipelineApp(props.id, values.currentTab)],
}
}),
urlToAction(({ actions, values }) => ({
'/pipeline/:id/:tab': ({ tab }) => {
if (tab !== values.currentTab) {
actions.setCurrentTab(tab as PipelineAppTabs)
}
},
})),
])
1 change: 1 addition & 0 deletions frontend/src/scenes/sceneTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export enum Scene {
PersonsManagement = 'PersonsManagement',
Person = 'Person',
Pipeline = 'Pipeline',
PipelineApp = 'PipelineApp',
Group = 'Group',
Action = 'Action',
Experiments = 'Experiments',
Expand Down
18 changes: 13 additions & 5 deletions frontend/src/scenes/scenes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, PipelineTabs, PropertyFilterType, ReplayTabs } from '~/types'
import { InsightShortId, PipelineAppTabs, PipelineTabs, PropertyFilterType, ReplayTabs } from '~/types'
import { combineUrl } from 'kea-router'
import { getDefaultEventsSceneQuery } from 'scenes/events/defaults'
import { EventsQuery } from '~/queries/schema'
Expand Down Expand Up @@ -112,6 +112,10 @@ export const sceneConfigurations: Partial<Record<Scene, SceneConfig>> = {
projectBased: true,
name: 'Pipeline',
},
[Scene.PipelineApp]: {
projectBased: true,
name: 'Pipeline app',
},
[Scene.Experiments]: {
projectBased: true,
name: 'Experiments',
Expand Down Expand Up @@ -405,10 +409,14 @@ export const routes: Record<string, Scene> = {
[urls.persons()]: Scene.PersonsManagement,
[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<string, Scene>),
...(Object.fromEntries(Object.values(PipelineTabs).map((tab) => [urls.pipeline(tab), Scene.Pipeline])) as Record<
string,
Scene
>),
// One entry for each available tab (key by app config id)
...(Object.fromEntries(
Object.values(PipelineAppTabs).map((tab) => [urls.pipelineApp(':id', tab), Scene.PipelineApp])
) as Record<string, Scene>),
[urls.groups(':groupTypeIndex')]: Scene.PersonsManagement,
[urls.group(':groupTypeIndex', ':groupKey', false)]: Scene.Group,
[urls.group(':groupTypeIndex', ':groupKey', false, ':groupTab')]: Scene.Group,
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/scenes/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
InsightShortId,
ReplayTabs,
PipelineTabs,
PipelineAppTabs,
} from '~/types'
import { combineUrl } from 'kea-router'
import { ExportOptions } from '~/exporter/types'
Expand Down Expand Up @@ -95,8 +96,10 @@ export const urls = {
personByUUID: (uuid: string, encode: boolean = true): string =>
encode ? `/persons/${encodeURIComponent(uuid)}` : `/persons/${uuid}`,
persons: (): string => '/persons',
pipeline: (tab?: PipelineTabs): string => `/pipeline/${tab ? tab : 'destinations'}`,
pipelineNew: (tab?: PipelineTabs): string => `/pipeline/${tab ? tab : 'destinations'}/new`,
pipeline: (tab?: PipelineTabs): string => `/pipeline/${tab ? tab : PipelineTabs.Destinations}`,
pipelineApp: (id: string | number, tab?: PipelineAppTabs): string =>
`/pipeline/${id}/${tab ? tab : PipelineAppTabs.Configuration}`,
pipelineNew: (tab?: PipelineTabs): string => `/pipeline/${tab ? tab : PipelineTabs.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 =>
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,12 @@ export enum PipelineTabs {
Destinations = 'destinations',
}

export enum PipelineAppTabs {
Configuration = 'configuration',
Logs = 'logs',
Metrics = 'metrics',
}

export enum ProgressStatus {
Draft = 'draft',
Running = 'running',
Expand Down

0 comments on commit 7a2e3f4

Please sign in to comment.