Skip to content

Commit

Permalink
hook into the iframe a bit, save actions automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
raquelmsmith committed Sep 5, 2024
1 parent 6d6dd2e commit bd6e21d
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ export function IframedToolbarBrowser({
iframeRef,
userIntent,
}: {
iframeRef?: React.MutableRefObject<HTMLIFrameElement | null>
iframeRef: React.MutableRefObject<HTMLIFrameElement | null>
userIntent: ToolbarUserIntent
}): JSX.Element | null {
const logic = iframedToolbarBrowserLogic()
const logic = iframedToolbarBrowserLogic({ iframeRef, userIntent: userIntent })

const { browserUrl } = useValues(logic)
const { onIframeLoad, setIframeWidth } = useActions(logic)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import { LemonBannerProps } from 'lib/lemon-ui/LemonBanner'
import posthog from 'posthog-js'
import { RefObject } from 'react'

import { ToolbarUserIntent } from '~/types'

import type { iframedToolbarBrowserLogicType } from './iframedToolbarBrowserLogicType'

export type IframedToolbarBrowserLogicProps = {
iframeRef: RefObject<HTMLIFrameElement | null>
clearBrowserUrlOnUnmount?: boolean
userIntent?: ToolbarUserIntent
}

export interface IFrameBanner {
Expand Down Expand Up @@ -50,6 +53,9 @@ export const iframedToolbarBrowserLogic = kea<iframedToolbarBrowserLogicType>([
setIframeBanner: (banner: IFrameBanner | null) => ({ banner }),
startTrackingLoading: true,
stopTrackingLoading: true,
enableElementSelector: true,
disableElementSelector: true,
setNewActionName: (name: string | null) => ({ name }),
}),

reducers({
Expand Down Expand Up @@ -138,7 +144,7 @@ export const iframedToolbarBrowserLogic = kea<iframedToolbarBrowserLogicType>([
'*'
)
},

// heatmaps
patchHeatmapFilters: ({ filters }) => {
actions.sendToolbarMessage(PostHogAppToolbarEvent.PH_PATCH_HEATMAP_FILTERS, { filters })
},
Expand All @@ -159,6 +165,17 @@ export const iframedToolbarBrowserLogic = kea<iframedToolbarBrowserLogicType>([
actions.sendToolbarMessage(PostHogAppToolbarEvent.PH_HEATMAPS_COMMON_FILTERS, { commonFilters: filters })
},

// actions
enableElementSelector: () => {
actions.sendToolbarMessage(PostHogAppToolbarEvent.PH_ELEMENT_SELECTOR, { enabled: true })
},
disableElementSelector: () => {
actions.sendToolbarMessage(PostHogAppToolbarEvent.PH_ELEMENT_SELECTOR, { enabled: false })
},
setNewActionName: ({ name }) => {
actions.sendToolbarMessage(PostHogAppToolbarEvent.PH_NEW_ACTION_NAME, { name })
},

onIframeLoad: () => {
// we get this callback whether the iframe loaded successfully or not
// and don't get a signal if the load was successful, so we have to check
Expand All @@ -171,9 +188,13 @@ export const iframedToolbarBrowserLogic = kea<iframedToolbarBrowserLogicType>([
fixedPositionMode: values.heatmapFixedPositionMode,
commonFilters: values.commonFilters,
})
actions.sendToolbarMessage(PostHogAppToolbarEvent.PH_HEATMAPS_CONFIG, {
enabled: true,
})
switch (props.userIntent) {
case 'heatmaps':
actions.sendToolbarMessage(PostHogAppToolbarEvent.PH_HEATMAPS_CONFIG, {
enabled: true,
})
break
}
}

const onIframeMessage = (e: MessageEvent): void => {
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lib/components/IframedToolbarBrowser/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export enum PostHogAppToolbarEvent {
PH_TOOLBAR_HEATMAP_LOADING = 'ph-toolbar-heatmap-loading',
PH_TOOLBAR_HEATMAP_LOADED = 'ph-toolbar-heatmap-loaded',
PH_TOOLBAR_HEATMAP_FAILED = 'ph-toolbar-heatmap-failed',
PH_ELEMENT_SELECTOR = 'ph-element-selector',
PH_NEW_ACTION_NAME = 'ph-new-action-name',
}

export const DEFAULT_HEATMAP_FILTERS: HeatmapFilters = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export const OnboardingDashboardTemplateConfigureStep = ({
</Link>{' '}
(no need to send it now) .
</p>
<DashboardTemplateVariables hasSelectedSite={!!browserUrl} />
<DashboardTemplateVariables hasSelectedSite={!!browserUrl} iframeRef={iframeRef} />
<LemonButton
type="primary"
status="alt"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { IconCheckCircle, IconInfo, IconTrash } from '@posthog/icons'
import { LemonBanner, LemonButton, LemonCollapse, LemonInput, LemonLabel } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { iframedToolbarBrowserLogic } from 'lib/components/IframedToolbarBrowser/iframedToolbarBrowserLogic'
import { useEffect, useState } from 'react'
import { dashboardTemplateVariablesLogic } from 'scenes/dashboard/dashboardTemplateVariablesLogic'
import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic'
Expand All @@ -10,9 +11,11 @@ import { DashboardTemplateVariableType } from '~/types'
function VariableSelector({
variable,
hasSelectedSite,
iframeRef,
}: {
variable: DashboardTemplateVariableType
hasSelectedSite: boolean
iframeRef: React.RefObject<HTMLIFrameElement>
}): JSX.Element {
const { activeDashboardTemplate } = useValues(newDashboardLogic)
const theDashboardTemplateVariablesLogic = dashboardTemplateVariablesLogic({
Expand All @@ -23,6 +26,9 @@ function VariableSelector({
const { allVariablesAreTouched, variables, activeVariableIndex } = useValues(theDashboardTemplateVariablesLogic)
const [customEventName, setCustomEventName] = useState<string | null>(null)
const [showCustomEventField, setShowCustomEventField] = useState(false)
const { enableElementSelector, disableElementSelector, setNewActionName } = useActions(
iframedToolbarBrowserLogic({ iframeRef, clearBrowserUrlOnUnmount: true })
)

const FALLBACK_EVENT = {
id: '$other_event',
Expand Down Expand Up @@ -131,12 +137,21 @@ function VariableSelector({
status="alt"
onClick={() => {
setShowCustomEventField(false)
enableElementSelector()
setNewActionName(variable.name)
setVariable(variable.name, { events: [FALLBACK_EVENT] })
}}
>
Select from site
</LemonButton>
<LemonButton type="secondary" onClick={() => setShowCustomEventField(true)}>
<LemonButton
type="secondary"
onClick={() => {
disableElementSelector()
setNewActionName(null)
setShowCustomEventField(true)
}}
>
Use custom event
</LemonButton>
</div>
Expand All @@ -147,7 +162,13 @@ function VariableSelector({
)
}

export function DashboardTemplateVariables({ hasSelectedSite }: { hasSelectedSite: boolean }): JSX.Element {
export function DashboardTemplateVariables({
hasSelectedSite,
iframeRef,
}: {
hasSelectedSite: boolean
iframeRef: React.RefObject<HTMLIFrameElement>
}): JSX.Element {
const { activeDashboardTemplate } = useValues(newDashboardLogic)
const theDashboardTemplateVariablesLogic = dashboardTemplateVariablesLogic({
variables: activeDashboardTemplate?.variables || [],
Expand All @@ -172,7 +193,9 @@ export function DashboardTemplateVariables({ hasSelectedSite }: { hasSelectedSit
{v.touched && <IconCheckCircle className="text-success ml-2 text-base" />}
</div>
),
content: <VariableSelector variable={v} {...v} hasSelectedSite={hasSelectedSite} />,
content: (
<VariableSelector variable={v} {...v} hasSelectedSite={hasSelectedSite} iframeRef={iframeRef} />
),
className: 'p-4 bg-white',
onHeaderClick: () => {
setActiveVariableIndex(i)
Expand Down
40 changes: 34 additions & 6 deletions frontend/src/toolbar/actions/actionsTabLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import { ActionType, ElementType } from '~/types'

import type { actionsTabLogicType } from './actionsTabLogicType'

function newAction(element: HTMLElement | null, dataAttributes: string[] = []): ActionDraftType {
function newAction(element: HTMLElement | null, dataAttributes: string[] = [], name: string | null): ActionDraftType {
return {
name: '',
name: name || '',
steps: [element ? actionStepToActionStepFormItem(elementToActionStep(element, dataAttributes), true) : {}],
pinned_at: null,
}
Expand Down Expand Up @@ -67,6 +67,7 @@ export const actionsTabLogic = kea<actionsTabLogicType>([
hideButtonActions: true,
setShowActionsTooltip: (showActionsTooltip: boolean) => ({ showActionsTooltip }),
setElementSelector: (selector: string, index: number) => ({ selector, index }),
setAutomaticActionCreationEnabled: (enabled: boolean, name?: string) => ({ enabled, name }),
}),

connect(() => ({
Expand Down Expand Up @@ -142,6 +143,18 @@ export const actionsTabLogic = kea<actionsTabLogicType>([
setShowActionsTooltip: (_, { showActionsTooltip }) => showActionsTooltip,
},
],
automaticActionCreationEnabled: [
false as boolean,
{
setAutomaticActionCreationEnabled: (_, { enabled }) => enabled,
},
],
newActionName: [
null as string | null,
{
setAutomaticActionCreationEnabled: (_, { enabled, name }) => (enabled && name ? name : null),
},
],
}),

forms(({ values, actions }) => ({
Expand Down Expand Up @@ -211,22 +224,34 @@ export const actionsTabLogic = kea<actionsTabLogicType>([
},
],
selectedAction: [
(s) => [s.selectedActionId, s.newActionForElement, s.allActions, s.dataAttributes],
(s) => [s.selectedActionId, s.newActionForElement, s.allActions, s.dataAttributes, s.newActionName],
(
selectedActionId,
newActionForElement,
allActions,
dataAttributes
dataAttributes,
newActionName
): ActionType | ActionDraftType | null => {
if (selectedActionId === 'new') {
return newAction(newActionForElement, dataAttributes)
return newAction(newActionForElement, dataAttributes, newActionName)
}
return allActions.find((a) => a.id === selectedActionId) || null
},
],
isReadyForAutomaticSubmit: [
(s) => [s.automaticActionCreationEnabled, s.selectedAction, s.actionForm],
(automaticActionCreationEnabled, selectedAction, actionForm): boolean => {
return (
(automaticActionCreationEnabled &&
selectedAction?.name &&
actionForm.steps?.[0]?.selector_selected) ||
false // annoying type requirement
)
},
],
}),

subscriptions(({ actions }) => ({
subscriptions(({ actions, values }) => ({
selectedAction: (selectedAction: ActionType | ActionDraftType | null) => {
if (!selectedAction) {
actions.setActionFormValues({ name: null, steps: [{}] })
Expand All @@ -237,6 +262,9 @@ export const actionsTabLogic = kea<actionsTabLogicType>([
? selectedAction.steps.map((step) => actionStepToActionStepFormItem(step, false))
: [{}],
})
if (values.isReadyForAutomaticSubmit) {
actions.submitActionForm()
}
}
},
})),
Expand Down
12 changes: 11 additions & 1 deletion frontend/src/toolbar/bar/toolbarLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const toolbarLogic = kea<toolbarLogicType>([
connect(() => ({
actions: [
actionsTabLogic,
['showButtonActions', 'hideButtonActions', 'selectAction'],
['showButtonActions', 'hideButtonActions', 'selectAction', 'setAutomaticActionCreationEnabled'],
elementsLogic,
['enableInspect', 'disableInspect', 'createAction'],
heatmapLogic,
Expand Down Expand Up @@ -440,6 +440,16 @@ export const toolbarLogic = kea<toolbarLogicType>([
case PostHogAppToolbarEvent.PH_HEATMAPS_COMMON_FILTERS:
actions.setCommonFilters(e.data.payload.commonFilters)
return
case PostHogAppToolbarEvent.PH_ELEMENT_SELECTOR:
if (e.data.payload.enabled) {
actions.enableInspect()
} else {
actions.disableInspect()
}
return
case PostHogAppToolbarEvent.PH_NEW_ACTION_NAME:
actions.setAutomaticActionCreationEnabled(true, e.data.payload.name)
return
default:
console.warn(`[PostHog Toolbar] Received unknown parent window message: ${type}`)
}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/toolbar/elements/elementsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ export const elementsLogic = kea<elementsLogicType>([
},
createAction: ({ element }) => {
actions.selectElement(null)
// this just sets the action form
actions.newAction(element)
},
})),
Expand Down

0 comments on commit bd6e21d

Please sign in to comment.