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(cdp): site destinations #26572

Merged
merged 14 commits into from
Dec 3, 2024
22 changes: 15 additions & 7 deletions frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1764,11 +1764,17 @@ const api = {
},
},
hogFunctions: {
async list(params?: {
filters?: any
type?: HogFunctionTypeType
}): Promise<PaginatedResponse<HogFunctionType>> {
return await new ApiRequest().hogFunctions().withQueryString(params).get()
async list(
filters?: any,
type?: HogFunctionTypeType | HogFunctionTypeType[]
): Promise<PaginatedResponse<HogFunctionType>> {
return await new ApiRequest()
.hogFunctions()
.withQueryString({
filters: filters,
...(type ? (Array.isArray(type) ? { types: type.join(',') } : { type }) : {}),
})
.get()
},
async get(id: HogFunctionType['id']): Promise<HogFunctionType> {
return await new ApiRequest().hogFunction(id).get()
Expand Down Expand Up @@ -1797,10 +1803,12 @@ const api = {
): Promise<AppMetricsTotalsV2Response> {
return await new ApiRequest().hogFunction(id).withAction('metrics/totals').withQueryString(params).get()
},
async listTemplates(type?: HogFunctionTypeType): Promise<PaginatedResponse<HogFunctionTemplateType>> {
async listTemplates(
type?: HogFunctionTypeType | HogFunctionTypeType[]
): Promise<PaginatedResponse<HogFunctionTemplateType>> {
return new ApiRequest()
.hogFunctionTemplates()
.withQueryString({ type: type ?? 'destination' })
.withQueryString(Array.isArray(type) ? { types: type.join(',') } : { type: type ?? 'destination' })
.get()
},
async getTemplate(id: HogFunctionTemplateType['id']): Promise<HogFunctionTemplateType> {
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 @@ -232,6 +232,7 @@ export const FEATURE_FLAGS = {
CUSTOM_CSS_THEMES: 'custom-css-themes', // owner: @daibhin
WEB_ANALYTICS_WARN_CUSTOM_EVENT_NO_SESSION: 'web-analytics-warn-custom-event-no-session', // owner: @robbie-c #team-web-analytics
TWO_FACTOR_UI: 'two-factor-ui', // owner: @zach
SITE_DESTINATIONS: 'site-destinations', // owner: @mariusandra #team-cdp
} as const
export type FeatureFlagKey = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS]

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/actions/actionLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const actionLogic = kea<actionLogicType>([
null as HogFunctionType[] | null,
{
loadMatchingHogFunctions: async () => {
const res = await api.hogFunctions.list({ filters: { actions: [{ id: `${props.id}` }] } })
const res = await api.hogFunctions.list({ actions: [{ id: `${props.id}` }] })

return res.results
},
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/messaging/functionsTableLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const functionsTableLogic = kea<functionsTableLogicType>([
{
loadHogFunctions: async () => {
// TODO: pagination?
return (await api.hogFunctions.list({ type: props.type ?? 'destination' })).results
return (await api.hogFunctions.list(undefined, props.type ?? 'destination')).results
},
deleteHogFunction: async ({ hogFunction }) => {
await deleteWithUndo({
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/scenes/pipeline/destinations/DestinationTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export function DestinationTag({ status }: { status: HogFunctionTemplateStatus }
return <LemonTag type="completion">Beta</LemonTag>
case 'stable':
return <LemonTag type="highlight">New</LemonTag> // Once Hog Functions are fully released we can remove the new label
case 'client-side':
return <LemonTag type="success">Client-Side</LemonTag>
default:
return status ? <LemonTag type="highlight">{capitalizeFirstLetter(status)}</LemonTag> : null
}
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/scenes/pipeline/destinations/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { HogFunctionTypeType } from '~/types'

export const getDestinationTypes = (featureFlagEnabled: boolean): HogFunctionTypeType[] =>
featureFlagEnabled ? ['destination', 'site_destination'] : ['destination']
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
WebhookDestination,
} from '../types'
import { captureBatchExportEvent, capturePluginEvent, loadPluginsFromUrl } from '../utils'
import { getDestinationTypes } from './constants'
import { destinationsFiltersLogic } from './destinationsFiltersLogic'
import type { pipelineDestinationsLogicType } from './destinationsLogicType'

Expand Down Expand Up @@ -165,8 +166,8 @@ export const pipelineDestinationsLogic = kea<pipelineDestinationsLogicType>([
[] as HogFunctionType[],
{
loadHogFunctions: async () => {
// TODO: Support pagination?
return (await api.hogFunctions.list({ type: 'destination' })).results
const destinationTypes = getDestinationTypes(!!values.featureFlags[FEATURE_FLAGS.SITE_DESTINATIONS])
return (await api.hogFunctions.list(undefined, destinationTypes)).results
},

deleteNodeHogFunction: async ({ destination }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { humanizeBatchExportName } from '../batch-exports/utils'
import { HogFunctionIcon } from '../hogfunctions/HogFunctionIcon'
import { PipelineBackend } from '../types'
import { RenderBatchExportIcon } from '../utils'
import { getDestinationTypes } from './constants'
import { destinationsFiltersLogic } from './destinationsFiltersLogic'
import type { newDestinationsLogicType } from './newDestinationsLogicType'

Expand All @@ -43,20 +44,21 @@ export const newDestinationsLogic = kea<newDestinationsLogicType>([
actions({
openFeedbackDialog: true,
}),
loaders({
loaders(({ values }) => ({
hogFunctionTemplates: [
{} as Record<string, HogFunctionTemplateType>,
{
loadHogFunctionTemplates: async () => {
const templates = await api.hogFunctions.listTemplates()
const destinationTypes = getDestinationTypes(!!values.featureFlags[FEATURE_FLAGS.SITE_DESTINATIONS])
const templates = await api.hogFunctions.listTemplates(destinationTypes)
return templates.results.reduce((acc, template) => {
acc[template.id] = template
return acc
}, {} as Record<string, HogFunctionTemplateType>)
},
},
],
}),
})),

selectors(() => ({
loading: [(s) => [s.hogFunctionTemplatesLoading], (hogFunctionTemplatesLoading) => hogFunctionTemplatesLoading],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,14 @@ export function HogFunctionConfiguration({ templateId, id }: HogFunctionConfigur
return <PayGateMini feature={AvailableFeature.DATA_PIPELINES} />
}

const showFilters = type === 'destination' || type === 'broadcast'
const showExpectedVolume = type === 'destination'
const showEnabled = type === 'destination' || type === 'email'
const canEditSource = type === 'destination' || type === 'email'
const showFilters = type === 'destination' || type === 'site_destination' || type === 'broadcast'
const showExpectedVolume = type === 'destination' || type === 'site_destination'
const showStatus = type === 'destination' || type === 'email'
const showEnabled = type === 'destination' || type === 'email' || type === 'site_destination' || type === 'site_app'
const canEditSource =
type === 'destination' || type === 'email' || type === 'site_destination' || type === 'site_app'
const showPersonsCount = type === 'broadcast'
const showTesting = type === 'destination' || type === 'broadcast' || type === 'email'

return (
<div className="space-y-3">
Expand Down Expand Up @@ -210,7 +213,7 @@ export function HogFunctionConfiguration({ templateId, id }: HogFunctionConfigur
{template && <DestinationTag status={template.status} />}
</div>

{showEnabled && <HogFunctionStatusIndicator hogFunction={hogFunction} />}
{showStatus && <HogFunctionStatusIndicator hogFunction={hogFunction} />}
{showEnabled && (
<LemonField name="enabled">
{({ value, onChange }) => (
Expand All @@ -236,7 +239,7 @@ export function HogFunctionConfiguration({ templateId, id }: HogFunctionConfigur
<LemonTextArea disabled={loading} />
</LemonField>

{hogFunction?.template ? (
{hogFunction?.template && !hogFunction.template.id.startsWith('template-blank-') ? (
<LemonDropdown
showArrow
overlay={
Expand Down Expand Up @@ -458,14 +461,16 @@ export function HogFunctionConfiguration({ templateId, id }: HogFunctionConfigur
<LemonField name="hog">
{({ value, onChange }) => (
<>
<span className="text-xs text-muted-alt">
This is the underlying Hog code that will run whenever the
filters match.{' '}
<Link to="https://posthog.com/docs/hog">See the docs</Link> for
more info
</span>
{!type.startsWith('site_') ? (
<span className="text-xs text-muted-alt">
This is the underlying Hog code that will run whenever the
filters match.{' '}
<Link to="https://posthog.com/docs/hog">See the docs</Link>{' '}
for more info
</span>
) : null}
<CodeEditorResizeable
language="hog"
language={type.startsWith('site_') ? 'typescript' : 'hog'}
value={value ?? ''}
onChange={(v) => onChange(v ?? '')}
globals={globalsWithInputs}
Expand All @@ -489,8 +494,13 @@ export function HogFunctionConfiguration({ templateId, id }: HogFunctionConfigur
) : null}
</div>
)}

{!id || id === 'new' ? <HogFunctionTestPlaceholder /> : <HogFunctionTest id={id} />}
{showTesting ? (
!id || id === 'new' ? (
<HogFunctionTestPlaceholder />
) : (
<HogFunctionTest id={id} />
)
) : null}
<div className="flex gap-2 justify-end">{saveButtons}</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ export function HogFunctionInputWithSchema({ schema }: HogFunctionInputWithSchem
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: schema.key })
const { showSource, configuration } = useValues(hogFunctionConfigurationLogic)
const { setConfigurationValue } = useActions(hogFunctionConfigurationLogic)
const [editing, setEditing] = useState(showSource)
const [editing, setEditing] = useState(false)

const value = configuration.inputs?.[schema.key]

Expand Down
Loading
Loading