Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(messaging): ui #25811

Merged
merged 44 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
043c3e2
feat(messaging): different types of hog functions
mariusandra Oct 24, 2024
e3fb034
merge
mariusandra Oct 24, 2024
a66cce4
mailchimp type
mariusandra Oct 24, 2024
324df0a
fix
mariusandra Oct 24, 2024
dcb30a2
test
mariusandra Oct 24, 2024
ffbb89a
more fixes
mariusandra Oct 24, 2024
9b9696c
remove "shared"
mariusandra Oct 24, 2024
9b06f4d
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
d02b402
test that we can list
mariusandra Oct 24, 2024
70f4763
Merge branch 'messaging-part-1' of github.com:PostHog/posthog into me…
mariusandra Oct 24, 2024
5177554
fix
mariusandra Oct 24, 2024
108df5d
was not used
mariusandra Oct 24, 2024
0a64fb5
test for destinations
mariusandra Oct 24, 2024
955ca6d
Merge branch 'master' into messaging-part-1
mariusandra Oct 24, 2024
1bb9729
Update query snapshots
github-actions[bot] Oct 24, 2024
24b8894
Update query snapshots
github-actions[bot] Oct 24, 2024
3508529
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
129282c
Update query snapshots
github-actions[bot] Oct 24, 2024
22f230b
Merge branch 'master' into messaging-part-1
mariusandra Oct 24, 2024
fd78b10
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
a8c34f2
Merge branch 'master' into messaging-part-1
mariusandra Oct 24, 2024
0ff33b4
went down
mariusandra Oct 24, 2024
f9b46a7
make it reversable
mariusandra Oct 24, 2024
183f43e
Merge branch 'messaging-part-1' of github.com:PostHog/posthog into me…
mariusandra Oct 24, 2024
5e47b5f
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
581cbbd
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
fc9c117
feat(messaging): ui
mariusandra Oct 25, 2024
19bd61b
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 25, 2024
cbd5e3d
Merge branch 'master' into messaging-part-3
mariusandra Oct 25, 2024
f0ad30d
Merge branch 'messaging-part-3' of github.com:PostHog/posthog into me…
mariusandra Oct 25, 2024
19e9e55
fix(snapshots): disable flakes
mariusandra Oct 25, 2024
df08675
Merge branch 'fix-flakes-ffs' into messaging-part-3
mariusandra Oct 25, 2024
9fdcb9b
Update UI snapshots for `chromium` (2)
github-actions[bot] Oct 25, 2024
fd64e00
Update UI snapshots for `chromium` (2)
github-actions[bot] Oct 25, 2024
97f2d05
Merge branch 'master' into messaging-part-3
mariusandra Oct 25, 2024
92d900d
Merge branch 'messaging-part-3' of github.com:PostHog/posthog into me…
mariusandra Oct 25, 2024
8957ade
lists
mariusandra Oct 25, 2024
21230d3
rename
mariusandra Oct 25, 2024
3810fcd
Merge branch 'master' into messaging-part-3
mariusandra Oct 25, 2024
8c6f201
Update query snapshots
github-actions[bot] Oct 25, 2024
5fb56f7
Update query snapshots
github-actions[bot] Oct 25, 2024
654d257
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 25, 2024
dc20aec
Update query snapshots
github-actions[bot] Oct 25, 2024
94e8227
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
10 changes: 10 additions & 0 deletions frontend/src/layout/navigation-3000/navigationLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
IconHome,
IconLive,
IconLogomark,
IconMegaphone,
IconNotebook,
IconPeople,
IconPieChart,
Expand Down Expand Up @@ -526,6 +527,15 @@ export const navigation3000Logic = kea<navigation3000LogicType>([
to: urls.pipeline(),
}
: null,
featureFlags[FEATURE_FLAGS.MESSAGING] && hasOnboardedAnyProduct
? {
identifier: Scene.MessagingBroadcasts,
label: 'Messaging',
icon: <IconMegaphone />,
to: urls.messagingBroadcasts(),
tag: 'alpha' as const,
}
: null,
].filter(isNotNil),
]
},
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ export const FEATURE_FLAGS = {
LEGACY_ACTION_WEBHOOKS: 'legacy-action-webhooks', // owner: @mariusandra #team-cdp
SESSION_REPLAY_URL_TRIGGER: 'session-replay-url-trigger', // owner: @richard-better #team-replay
REPLAY_TEMPLATES: 'replay-templates', // owner: @raquelmsmith #team-replay
MESSAGING: 'messaging', // owner @mariusandra #team-cdp
} as const
export type FeatureFlagKey = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS]

Expand Down
2 changes: 2 additions & 0 deletions frontend/src/scenes/appScenes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,6 @@ export const appScenes: Record<Scene, () => any> = {
[Scene.Heatmaps]: () => import('./heatmaps/HeatmapsScene'),
[Scene.SessionAttributionExplorer]: () =>
import('scenes/web-analytics/SessionAttributionExplorer/SessionAttributionExplorerScene'),
[Scene.MessagingProviders]: () => import('./messaging/Providers'),
[Scene.MessagingBroadcasts]: () => import('./messaging/Broadcasts'),
}
43 changes: 43 additions & 0 deletions frontend/src/scenes/messaging/Broadcasts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { IconPlusSmall } from '@posthog/icons'
import { useValues } from 'kea'
import { PageHeader } from 'lib/components/PageHeader'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
import { broadcastsLogic } from 'scenes/messaging/broadcastsLogic'
import { FunctionsTable } from 'scenes/messaging/FunctionsTable'
import { MessagingTabs } from 'scenes/messaging/MessagingTabs'
import { HogFunctionConfiguration } from 'scenes/pipeline/hogfunctions/HogFunctionConfiguration'
import { SceneExport } from 'scenes/sceneTypes'
import { urls } from 'scenes/urls'

export function Broadcasts(): JSX.Element {
const { broadcastId } = useValues(broadcastsLogic)
return broadcastId ? (
<HogFunctionConfiguration
id={broadcastId === 'new' ? null : broadcastId}
templateId={broadcastId === 'new' ? 'template-new-broadcast' : ''}
/>
) : (
<>
<MessagingTabs key="tabs" />
<PageHeader
caption="Send one time communications to your users"
buttons={
<LemonButton
data-attr="new-broadcast"
to={urls.messagingBroadcastNew()}
type="primary"
icon={<IconPlusSmall />}
>
New broadcast
</LemonButton>
}
/>
<FunctionsTable type="broadcast" />
</>
)
}

export const scene: SceneExport = {
component: Broadcasts,
logic: broadcastsLogic,
}
125 changes: 125 additions & 0 deletions frontend/src/scenes/messaging/FunctionsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { LemonInput, LemonTable, LemonTableColumn, Link, Tooltip } from '@posthog/lemon-ui'
import { BindLogic, useActions, useValues } from 'kea'
import { More } from 'lib/lemon-ui/LemonButton/More'
import { LemonMenuOverlay } from 'lib/lemon-ui/LemonMenu/LemonMenu'
import { updatedAtColumn } from 'lib/lemon-ui/LemonTable/columnUtils'
import { LemonTableLink } from 'lib/lemon-ui/LemonTable/LemonTableLink'
import { functionsTableLogic } from 'scenes/messaging/functionsTableLogic'
import { hogFunctionUrl } from 'scenes/pipeline/hogfunctions/urls'

import { HogFunctionType, HogFunctionTypeType } from '~/types'

import { HogFunctionIcon } from '../pipeline/hogfunctions/HogFunctionIcon'
import { HogFunctionStatusIndicator } from '../pipeline/hogfunctions/HogFunctionStatusIndicator'

export interface FunctionsTableProps {
type?: HogFunctionTypeType
}

export function FunctionsTableFilters(): JSX.Element | null {
const { filters } = useValues(functionsTableLogic)
const { setFilters } = useActions(functionsTableLogic)

return (
<div className="space-y-2">
<div className="flex items-center gap-2">
<LemonInput
type="search"
placeholder="Search..."
value={filters.search ?? ''}
onChange={(e) => setFilters({ search: e })}
/>
</div>
</div>
)
}

export function FunctionsTable({ type }: FunctionsTableProps): JSX.Element {
const { hogFunctions, filteredHogFunctions, loading } = useValues(functionsTableLogic({ type }))
const { deleteHogFunction, resetFilters } = useActions(functionsTableLogic({ type }))

return (
<BindLogic logic={functionsTableLogic} props={{ type }}>
<div className="space-y-2">
<FunctionsTableFilters />

<LemonTable
dataSource={filteredHogFunctions}
size="small"
loading={loading}
columns={[
{
title: 'App',
width: 0,
render: function RenderAppInfo(_, hogFucntion) {
return <HogFunctionIcon src={hogFucntion.icon_url} size="small" />
},
},
{
title: 'Name',
sticky: true,
sorter: true,
key: 'name',
dataIndex: 'name',
render: function RenderPluginName(_, hogFunction) {
return (
<LemonTableLink
to={hogFunctionUrl(hogFunction.type, hogFunction.id)}
title={
<>
<Tooltip title="Click to update configuration, view metrics, and more">
<span>{hogFunction.name}</span>
</Tooltip>
</>
}
description={hogFunction.description}
/>
)
},
},

updatedAtColumn() as LemonTableColumn<HogFunctionType, any>,
{
title: 'Status',
key: 'enabled',
sorter: (a) => (a.enabled ? 1 : -1),
width: 0,
render: function RenderStatus(_, hogFunction) {
return <HogFunctionStatusIndicator hogFunction={hogFunction} />
},
},
{
width: 0,
render: function Render(_, hogFunction) {
return (
<More
overlay={
<LemonMenuOverlay
items={[
{
label: 'Delete',
status: 'danger' as const, // for typechecker happiness
onClick: () => deleteHogFunction(hogFunction),
},
]}
/>
}
/>
)
},
},
]}
emptyState={
hogFunctions.length === 0 && !loading ? (
'Nothing found'
) : (
<>
Nothing matches filters. <Link onClick={() => resetFilters()}>Clear filters</Link>{' '}
</>
)
}
/>
</div>
</BindLogic>
)
}
25 changes: 25 additions & 0 deletions frontend/src/scenes/messaging/MessagingTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useActions, useValues } from 'kea'
import { LemonTabs } from 'lib/lemon-ui/LemonTabs'
import { SceneExport } from 'scenes/sceneTypes'

import { MessagingTab, messagingTabsLogic } from './messagingTabsLogic'

export function MessagingTabs(): JSX.Element {
const { currentTab } = useValues(messagingTabsLogic)
const { setTab } = useActions(messagingTabsLogic)
return (
<LemonTabs
activeKey={currentTab}
onChange={(tab) => setTab(tab as MessagingTab)}
tabs={[
{ key: 'broadcasts', label: 'Broadcasts' },
{ key: 'providers', label: 'Providers' },
]}
/>
)
}

export const scene: SceneExport = {
component: MessagingTabs,
logic: messagingTabsLogic,
}
32 changes: 32 additions & 0 deletions frontend/src/scenes/messaging/Providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useValues } from 'kea'
import { PageHeader } from 'lib/components/PageHeader'
import { FunctionsTable } from 'scenes/messaging/FunctionsTable'
import { MessagingTabs } from 'scenes/messaging/MessagingTabs'
import { providersLogic } from 'scenes/messaging/providersLogic'
import { HogFunctionConfiguration } from 'scenes/pipeline/hogfunctions/HogFunctionConfiguration'
import { HogFunctionTemplateList } from 'scenes/pipeline/hogfunctions/list/HogFunctionTemplateList'
import { SceneExport } from 'scenes/sceneTypes'

export function Providers(): JSX.Element {
const { providerId, templateId } = useValues(providersLogic)
return providerId ? (
<HogFunctionConfiguration id={providerId} templateId={templateId} />
) : (
<>
<MessagingTabs key="tabs" />
<PageHeader caption="Configure e-mail, SMS and other messaging providers here" />
<FunctionsTable type="email" />
<div className="mt-4" />
<h2>Add Provider</h2>
<HogFunctionTemplateList defaultFilters={{}} type="email" />
<div className="mt-2 text-muted">
Note: to add a provider that's not in the list, select one that's similar and edit its source to point
to the right API URLs
</div>
</>
)
}
export const scene: SceneExport = {
component: Providers,
logic: providersLogic,
}
65 changes: 65 additions & 0 deletions frontend/src/scenes/messaging/broadcastsLogic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { actions, kea, path, reducers, selectors } from 'kea'
import { urlToAction } from 'kea-router'
import { Scene } from 'scenes/sceneTypes'
import { urls } from 'scenes/urls'

import { Breadcrumb } from '~/types'

import type { broadcastsLogicType } from './broadcastsLogicType'

export const broadcastsLogic = kea<broadcastsLogicType>([
path(['scenes', 'messaging', 'broadcastsLogic']),
actions({
editBroadcast: (id: string | null) => ({ id }),
}),
reducers({
broadcastId: [null as string | null, { editBroadcast: (_, { id }) => id }],
}),
selectors({
breadcrumbs: [
(s) => [s.broadcastId],
(broadcastId): Breadcrumb[] => {
return [
{
key: Scene.MessagingBroadcasts,
name: 'Messaging',
path: urls.messagingBroadcasts(),
},
{
key: 'broadcasts',
name: 'Broadcasts',
path: urls.messagingBroadcasts(),
},
...(broadcastId === 'new'
? [
{
key: 'new-broadcast',
name: 'New broadcast',
path: urls.messagingBroadcastNew(),
},
]
: broadcastId
? [
{
key: 'edit-broadcast',
name: 'Edit broadcast',
path: urls.messagingBroadcast(broadcastId),
},
]
: []),
]
},
],
}),
urlToAction(({ actions }) => ({
'/messaging/broadcasts/new': () => {
actions.editBroadcast('new')
},
'/messaging/broadcasts/:id': ({ id }) => {
actions.editBroadcast(id ?? null)
},
'/messaging/broadcasts': () => {
actions.editBroadcast(null)
},
})),
])
Loading
Loading