Skip to content

Commit

Permalink
Merge branch 'master' into improve-person-limit-filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
timgl committed Oct 25, 2024
2 parents 87762fc + dff2676 commit b534f06
Show file tree
Hide file tree
Showing 46 changed files with 1,484 additions and 325 deletions.
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
11 changes: 11 additions & 0 deletions frontend/src/layout/navigation/EnvironmentSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,17 @@ function determineProjectSwitchUrl(pathname: string, newTeamId: number): string
// and after switching is on a different page than before.
let route = removeProjectIdIfPresent(pathname)
route = removeFlagIdIfPresent(route)

// List of routes that should redirect to project home
// instead of keeping the current path.
const redirectToHomeRoutes = ['/products', '/onboarding']

const shouldRedirectToHome = redirectToHomeRoutes.some((redirectRoute) => route.includes(redirectRoute))

if (shouldRedirectToHome) {
return urls.project(newTeamId) // Go to project home
}

return urls.project(newTeamId, route)
}

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
47 changes: 17 additions & 30 deletions frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -10322,6 +10322,21 @@
"required": ["k", "t"],
"type": "object"
},
"RecordingOrder": {
"enum": [
"duration",
"recording_duration",
"inactive_seconds",
"active_seconds",
"start_time",
"console_error_count",
"click_count",
"keypress_count",
"mouse_activity_count",
"activity_score"
],
"type": "string"
},
"RecordingPropertyFilter": {
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -10411,35 +10426,7 @@
"$ref": "#/definitions/FilterLogicalOperator"
},
"order": {
"anyOf": [
{
"$ref": "#/definitions/DurationType"
},
{
"const": "start_time",
"type": "string"
},
{
"const": "console_error_count",
"type": "string"
},
{
"const": "click_count",
"type": "string"
},
{
"const": "keypress_count",
"type": "string"
},
{
"const": "mouse_activity_count",
"type": "string"
},
{
"const": "activity_score",
"type": "string"
}
]
"$ref": "#/definitions/RecordingOrder"
},
"person_uuid": {
"type": "string"
Expand All @@ -10463,7 +10450,7 @@
"type": "object"
}
},
"required": ["kind", "order"],
"required": ["kind"],
"type": "object"
},
"RecordingsQueryResponse": {
Expand Down
22 changes: 13 additions & 9 deletions frontend/src/queries/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
ChartDisplayCategory,
ChartDisplayType,
CountPerActorMathType,
DurationType,
EventPropertyFilter,
EventType,
FeaturePropertyFilter,
Expand Down Expand Up @@ -313,6 +312,18 @@ export interface RecordingsQueryResponse {
has_next: boolean
}

export type RecordingOrder =
| 'duration'
| 'recording_duration'
| 'inactive_seconds'
| 'active_seconds'
| 'start_time'
| 'console_error_count'
| 'click_count'
| 'keypress_count'
| 'mouse_activity_count'
| 'activity_score'

export interface RecordingsQuery extends DataNode<RecordingsQueryResponse> {
kind: NodeKind.RecordingsQuery
date_from?: string | null
Expand All @@ -326,14 +337,7 @@ export interface RecordingsQuery extends DataNode<RecordingsQueryResponse> {
operand?: FilterLogicalOperator
session_ids?: string[]
person_uuid?: string
order:
| DurationType
| 'start_time'
| 'console_error_count'
| 'click_count'
| 'keypress_count'
| 'mouse_activity_count'
| 'activity_score'
order?: RecordingOrder
limit?: integer
offset?: integer
user_modified_filters?: Record<string, any>
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,
}
Loading

0 comments on commit b534f06

Please sign in to comment.