Skip to content

Commit

Permalink
feat: Webhooks UI changes (#20545)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite authored Feb 26, 2024
1 parent da1d9fb commit 636f063
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 101 deletions.
6 changes: 3 additions & 3 deletions frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2136,11 +2136,11 @@ const api = {
return response
},

async loadPaginatedResults(
async loadPaginatedResults<T extends Record<string, any>>(
url: string | null,
maxIterations: number = PAGINATION_DEFAULT_MAX_PAGES
): Promise<any[]> {
let results: any[] = []
): Promise<T[]> {
let results: T[] = []
for (let i = 0; i <= maxIterations; ++i) {
if (!url) {
break
Expand Down
151 changes: 66 additions & 85 deletions frontend/src/scenes/actions/ActionEdit.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IconInfo, IconPlus, IconWarning } from '@posthog/icons'
import { LemonTextArea } from '@posthog/lemon-ui'
import { LemonCheckbox, LemonTextArea } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { Form } from 'kea-forms'
import { combineUrl, router } from 'kea-router'
Expand All @@ -8,7 +8,6 @@ import { ObjectTags } from 'lib/components/ObjectTags/ObjectTags'
import { PageHeader } from 'lib/components/PageHeader'
import { IconPlayCircle } from 'lib/lemon-ui/icons'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
import { LemonCheckbox } from 'lib/lemon-ui/LemonCheckbox'
import { LemonField } from 'lib/lemon-ui/LemonField'
import { LemonLabel } from 'lib/lemon-ui/LemonLabel/LemonLabel'
import { Link } from 'lib/lemon-ui/Link'
Expand Down Expand Up @@ -170,28 +169,15 @@ export function ActionEdit({ action: loadedAction, id }: ActionEditLogicProps):

<div>
<h2 className="subtitle">Match groups</h2>
<div>
<p>
Your action will be triggered whenever <b>any of your match groups</b> are received.
<Link to="https://posthog.com/docs/features/actions" target="_blank">
<IconInfo className="ml-1 text-muted text-xl" />
</Link>
</div>
<LemonField name="steps">
{({ onChange }) => (
<div className="flex justify-end mb-2">
<LemonButton
onClick={() => onChange([...(action.steps || []), { isNew: uuid() }])}
size="small"
type="secondary"
>
Add another match group
</LemonButton>
</div>
)}
</LemonField>
</p>
<LemonField name="steps">
{({ value: stepsValue, onChange }) => (
<div className="grid grid-cols-2 gap-3">
<div className="grid lg:grid-cols-2 gap-3">
{stepsValue.map((step: ActionStepType, index: number) => {
const identifier = String(JSON.stringify(step))
return (
Expand Down Expand Up @@ -229,87 +215,82 @@ export function ActionEdit({ action: loadedAction, id }: ActionEditLogicProps):
})}

<div>
<div
className="match-group-add-skeleton"
<LemonButton
icon={<IconPlus />}
onClick={() => {
onChange([...(action.steps || []), { isNew: uuid() }])
}}
center
className="w-full h-full border-dashed border"
>
<IconPlus style={{ fontSize: 28, color: '#666666' }} />
</div>
Add match group
</LemonButton>
</div>
</div>
)}
</LemonField>
</div>
<div className="my-8">
<LemonField name="post_to_slack">
{({ value, onChange }) => (
<div>
<LemonCheckbox
id="webhook-checkbox"
checked={action.bytecode_error ? false : !!value}
onChange={onChange}
disabledReason={
!slackEnabled
? 'Configure webhooks in project settings'
: action.bytecode_error ?? null
}
label={
<>
<span>Post to webhook when this action is triggered.</span>
{action.bytecode_error ? (
<IconWarning className="text-warning text-xl ml-1" />
) : null}
</>
}
/>
<div className="mt-1 pl-6">
<Link to={urls.settings('project-integrations', 'integration-webhooks')}>
{slackEnabled ? 'Configure' : 'Enable'} webhooks in project settings.
</Link>
</div>
</div>
)}
</LemonField>
{!action.bytecode_error && action.post_to_slack && (
<>
<LemonField name="slack_message_format">
{({ value, onChange }) => (
<LemonField name="post_to_slack">
{({ value, onChange }) => (
<div className="my-4">
<LemonCheckbox
id="webhook-checkbox"
checked={action.bytecode_error ? false : !!value}
onChange={onChange}
disabledReason={
!slackEnabled
? 'Configure webhooks in project settings'
: action.bytecode_error ?? null
}
label={
<>
<LemonLabel showOptional>Message format</LemonLabel>
<LemonTextArea
placeholder="Default: [action.name] triggered by [person]"
value={value}
onChange={onChange}
disabled={!slackEnabled || !action.post_to_slack}
data-attr="edit-slack-message-format"
/>
<small>
<Link
to="https://posthog.com/docs/integrate/webhooks/message-formatting"
target="_blank"
>
See documentation on how to format webhook messages.
</Link>
</small>
<span>Post to webhook when this action is triggered.</span>
{action.bytecode_error ? (
<IconWarning className="text-warning text-xl ml-1" />
) : null}
</>
)}
</LemonField>
}
/>
<div className="mt-1 pl-6">
<Link to={urls.settings('project-integrations', 'integration-webhooks')}>
{slackEnabled ? 'Configure' : 'Enable'} webhooks in project settings.
</Link>
</div>
</div>
)}
</LemonField>
<div>
{action.post_to_slack && (
<>
{!action.bytecode_error && action.post_to_slack && (
<>
<LemonField name="slack_message_format">
{({ value, onChange }) => (
<>
<LemonLabel showOptional>Slack message format</LemonLabel>
<LemonTextArea
placeholder="Default: [action.name] triggered by [person]"
value={value}
onChange={onChange}
disabled={!slackEnabled || !action.post_to_slack}
data-attr="edit-slack-message-format"
/>
<small>
<Link
to="https://posthog.com/docs/integrate/webhooks/message-formatting"
target="_blank"
>
See documentation on how to format webhook messages.
</Link>
</small>
</>
)}
</LemonField>
</>
)}
</>
)}
</div>
<div className="flex justify-end gap-2">
{id ? deleteButton() : cancelButton()}
<LemonButton
data-attr="save-action-button"
type="primary"
htmlType="submit"
loading={actionLoading}
>
Save
</LemonButton>
</div>
</Form>
</div>
)
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/actions/ActionStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function ActionStep({ step, actionId, isOnlyStep, index, identifier, onDe
}

return (
<div className="ActionStep rounded border p-4 relative h-full">
<div className="ActionStep bg-bg-light rounded border p-4 relative">
{index > 0 && !(index % 2 === 0) && (
<div className="ActionStep__or-tag">
<OperandTag operand="or" />
Expand Down Expand Up @@ -162,7 +162,7 @@ function Option({

return (
<div className="space-y-1">
<div className="flex space-x-1">
<div className="flex flex-wrap gap-1">
<LemonLabel>{label}</LemonLabel>
{extra_options}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export const exportsUnsubscribeTableLogic = kea<exportsUnsubscribeTableLogicType
{} as Record<BatchExportConfiguration['id'], BatchExportConfiguration>,
{
loadBatchExportConfigs: async () => {
const res = await api.loadPaginatedResults(`api/organizations/@current/batch_exports`)
const res = await api.loadPaginatedResults<BatchExportConfiguration>(
`api/organizations/@current/batch_exports`
)
return Object.fromEntries(
res
.filter((batchExportConfig) => !batchExportConfig.paused)
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/scenes/pipeline/destinationsLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const pipelineDestinationsLogic = kea<pipelineDestinationsLogicType>([
{} as Record<number, PluginType>,
{
loadPlugins: async () => {
const results: PluginType[] = await api.loadPaginatedResults(
const results = await api.loadPaginatedResults<PluginType>(
`api/organizations/@current/pipeline_destinations`
)
const plugins: Record<number, PluginType> = {}
Expand All @@ -48,7 +48,7 @@ export const pipelineDestinationsLogic = kea<pipelineDestinationsLogicType>([
{
loadPluginConfigs: async () => {
const pluginConfigs: Record<number, PluginConfigTypeNew> = {}
const results = await api.loadPaginatedResults(
const results = await api.loadPaginatedResults<PluginConfigTypeNew>(
`api/projects/${values.currentTeamId}/pipeline_destination_configs`
)

Expand Down Expand Up @@ -85,7 +85,7 @@ export const pipelineDestinationsLogic = kea<pipelineDestinationsLogicType>([
{} as Record<string, BatchExportConfiguration>,
{
loadBatchExports: async () => {
const results: BatchExportConfiguration[] = await api.loadPaginatedResults(
const results = await api.loadPaginatedResults<BatchExportConfiguration>(
`api/projects/${values.currentTeamId}/batch_exports`
)
return Object.fromEntries(results.map((batchExport) => [batchExport.id, batchExport]))
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/pipeline/transformationsLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const pipelineTransformationsLogic = kea<pipelineTransformationsLogicType
{} as Record<number, PluginType>,
{
loadPlugins: async () => {
const results: PluginType[] = await api.loadPaginatedResults(
const results = await api.loadPaginatedResults<PluginType>(
`api/organizations/@current/pipeline_transformations`
)
const plugins: Record<number, PluginType> = {}
Expand All @@ -53,7 +53,7 @@ export const pipelineTransformationsLogic = kea<pipelineTransformationsLogicType
{} as Record<number, PluginConfigTypeNew>,
{
loadPluginConfigs: async () => {
const res: PluginConfigTypeNew[] = await api.loadPaginatedResults(
const res = await api.loadPaginatedResults<PluginConfigTypeNew>(
`api/projects/${values.currentTeamId}/pipeline_transformation_configs`
)

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/plugins/pluginsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const pluginsLogic = kea<pluginsLogicType>([
{} as Record<number, PluginType>,
{
loadPlugins: async () => {
const results: PluginType[] = await api.loadPaginatedResults('api/organizations/@current/plugins')
const results = await api.loadPaginatedResults<PluginType>('api/organizations/@current/plugins')
const plugins: Record<string, PluginType> = {}
for (const plugin of results) {
plugins[plugin.id] = plugin
Expand Down Expand Up @@ -137,7 +137,7 @@ export const pluginsLogic = kea<pluginsLogicType>([
{
loadPluginConfigs: async () => {
const pluginConfigs: Record<string, PluginConfigType> = {}
const results: PluginConfigType[] = await api.loadPaginatedResults('api/plugin_config')
const results = await api.loadPaginatedResults<PluginConfigType>('api/plugin_config')

for (const pluginConfig of results) {
pluginConfigs[pluginConfig.plugin] = { ...pluginConfig }
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/scenes/web-analytics/webAnalyticsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
InsightLogicProps,
InsightType,
IntervalType,
PluginConfigTypeNew,
PluginType,
PropertyDefinition,
PropertyFilterType,
PropertyOperator,
Expand Down Expand Up @@ -1169,8 +1171,8 @@ export const webAnalyticsLogic = kea<webAnalyticsLogicType>([
event_names: ['$pageview'],
properties: ['$geoip_country_code'],
}),
api.loadPaginatedResults('api/organizations/@current/plugins'),
api.loadPaginatedResults('api/plugin_config'),
api.loadPaginatedResults<PluginType>('api/organizations/@current/plugins'),
api.loadPaginatedResults<PluginConfigTypeNew>('api/plugin_config'),
])

const hasNonStaleCountryCodeDefinition =
Expand All @@ -1185,7 +1187,7 @@ export const webAnalyticsLogic = kea<webAnalyticsLogicType>([

const geoIpPlugin =
pluginsResponse.status === 'fulfilled' &&
pluginsResponse.value.find((plugin) => GEOIP_PLUGIN_URLS.includes(plugin.url))
pluginsResponse.value.find((plugin) => plugin.url && GEOIP_PLUGIN_URLS.includes(plugin.url))
const geoIpPluginId = geoIpPlugin ? geoIpPlugin.id : undefined

const geoIpPluginConfig =
Expand Down

0 comments on commit 636f063

Please sign in to comment.