Skip to content

Commit

Permalink
Merge branch 'master' into dn-fix/notebooks-insights
Browse files Browse the repository at this point in the history
  • Loading branch information
daibhin committed Nov 8, 2023
2 parents 839623c + f808085 commit 53133c0
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 30 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
126 changes: 96 additions & 30 deletions frontend/src/stories/How to build a scene.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { Meta } from '@storybook/addon-docs';

If you want to add a new scene in the PostHog App frontend, here are 7 easy steps for fun and profit.

## 1. Create the component, logic and styles.

But first, you must answer one question: Does your scene depend on an `id` in the URL, like `/dashboard/:id`?

## 1.1. I'm buliding a global scene that does not depend on an `id` in the URL.
## Option A: I'm buliding a global scene that does not depend on an `id` in the URL.

### 1. Create the component, logic and styles.

Create a component like: `frontend/src/scenes/dashboard/Dashboards.tsx`

Expand All @@ -22,13 +22,13 @@ import { useValues } from 'kea'

export function Dashboards (): JSX.Element {
const {
dashboard: dashboard
} = useValues(dashboardLogic)
counter
} = useValues(dashboardsLogic)

return (
// TODO: consolidate on a recommended naming convention
<div className='dashboard-scene'>
Dashboard Scene!
Dashboard Scene {counter}!
</div>
)
}
Expand All @@ -42,11 +42,14 @@ export const scene: SceneExport = {
Create the logic: `frontend/src/scenes/dashboard/dashboardsLogic.tsx`

```ts
import { dashboardsLogicType } from './dashboardsLogicType'

export const dashboardsLogic = kea<dashboardsLogicType>({
path: ['scenes', 'dashboard', 'dashboardsLogic'],
})
import { kea, reducers, path } from 'kea'

export const dashboardsLogic = kea([
path(['scenes', 'dashboard', 'dashboardsLogic']),
reducers({
counter: [1, {}],
}),
])
```

Create the styles `frontend/src/scenes/dashboard/Dashboards.scss`.
Expand All @@ -57,33 +60,90 @@ Create the styles `frontend/src/scenes/dashboard/Dashboards.scss`.
}
```

## 1.2. My scene depends on an `id` in the URL (`/dashboard/:id`).
Run kea type generation and check, which will created `dashboardsLogicType.ts` and update imports in `dashboardsLogic.tsx`

```bash
pnpm typegen:write && pnpm typescript:check
```

### 2. Add a URL function

in `frontend/src/scenes/urls.ts`

```ts
export const urls = {
dashboards: () => `/dashboard`,
}
```

### 3. Add a scene to the enum

in `frontend/src/scenes/sceneTypes.ts`

```ts
export enum Scene {
Dashboards = 'Dashboards',
}
```

### 4. Add a scene configuration and a route to scene mapping

in `frontend/src/scenes/scenes.ts`

```ts
export const sceneConfigurations: Partial<Record<Scene, SceneConfig>> = {
[Scene.Dashboards]: {
projectBased: true,
name: 'Dashboards',
},
}

export const routes: Record<string, Scene> = {
[urls.dashboards()]: Scene.Dashboards,
}
```

### 5. Add a scene import

in `frontend/src/scenes/appScenes.ts`

```ts
export const appScenes: Record<Scene, () => any> = {
[Scene.Dashboards]: () => import('./dashboard/Dashboards'),
}
```

## Option B: My scene depends on an `id` in the URL (`/dashboard/:id`).

### 1. Create the component, logic and styles.

Create a component like: `frontend/src/scenes/dashboard/Dashboard.tsx`

```ts
import './Dashboard.scss'
import { dashboardLogic } from './dashboardLogic'
import { SceneExport } from 'scenes/sceneTypes'
import { useActions, useValues } from 'kea'
import { useValues } from 'kea'

export const scene: SceneExport = {
component: Dashboard,
logic: dashboardLogic,
// paramsToProps - Convert url _string_ params to logic props.
// This mounts the right logic with turbo mode before the component renders.
// This wraps the scene's logic in <BindLogic />
paramsToProps: ({ id }) => ({ id: id ? parseInt(id) : 'new' }),
paramsToProps: ({ params: {id} }:{ params: { id?: string }}) => ({ id: id ? parseInt(id) : 'new' }),
}

export function Dashboard ({ id }: { id?: string } = {}): JSX.Element {
// dashboardLogic is automatically bound to the props above with BindLogic
const { dashboard } = useValues(dashboardLogic)
const { reloadDashboard } = useActions(dashboardLogic)
const {
counter
} = useValues(dashboardLogic)

return (
// TODO: consolidate on a recommended naming convention
<div className='dashboard-scene'>
Dashboard Scene!
Dashboard Scene {id} {counter}!
</div>
)
}
Expand All @@ -92,18 +152,20 @@ export function Dashboard ({ id }: { id?: string } = {}): JSX.Element {
Create the logic: `frontend/src/scenes/dashboard/dashboardLogic.tsx`

```ts
import { dashboardLogicType } from './dashboardLogicType'
import { kea, reducers, path, props, key } from 'kea'

export interface DashboardLogicProps {
id: number | 'new'
}

export const dashboardLogic = kea<dashboardLogicType<DashboardLogicProps>>({
path: ['scenes', 'dashboard', 'dashboardLogic'],
props: {} as DashboardLogicProps,
key: (props) => props.id,

})
export const dashboardLogic = kea([
props({} as DashboardLogicProps),
key(({ id }) => id),
path((id) => ['scenes', 'dashboard', 'dashboardLogic', id]),
reducers({
counter: [1, {}],
}),
])
```

Create the styles `frontend/src/scenes/dashboard/Dashboard.scss`.
Expand All @@ -114,18 +176,23 @@ Create the styles `frontend/src/scenes/dashboard/Dashboard.scss`.
}
```

## 2. Add a URL function
Run kea type generation and check, which will created `dashboardLogicType.ts` and update imports in `dashboardLogic.tsx`

```bash
pnpm typegen:write && pnpm typescript:check
```

### 2. Add a URL function

in `frontend/src/scenes/urls.ts`

```ts
export const urls = {
dashboard: (id: string | number) => `/dashboard{id ? `/${id}` : ''}`,
dashboards: () => `/dashboard`,
}
```

## 3. Add a scene to the enum
### 3. Add a scene to the enum

in `frontend/src/scenes/sceneTypes.ts`

Expand All @@ -135,7 +202,7 @@ export enum Scene {
}
```

## 4. Add a scene configuration and a route to scene mapping
### 4. Add a scene configuration and a route to scene mapping

in `frontend/src/scenes/scenes.ts`

Expand All @@ -150,11 +217,10 @@ export const sceneConfigurations: Partial<Record<Scene, SceneConfig>> = {
export const routes: Record<string, Scene> = {
// this `:id` gets used in "params" in "paramsToProps" and passed to the <Dashboard /> component
[urls.dashboard(':id')]: Scene.Dashboard,
[urls.dashboards()]: Scene.Dashboard,
}
```

## 5. Add a scene import
### 5. Add a scene import

in `frontend/src/scenes/appScenes.ts`

Expand Down

0 comments on commit 53133c0

Please sign in to comment.