diff --git a/frontend/src/lib/components/IframedToolbarBrowser/IframedToolbarBrowser.tsx b/frontend/src/lib/components/IframedToolbarBrowser/IframedToolbarBrowser.tsx index 3e34575b31c96..aa32b83e36ee7 100644 --- a/frontend/src/lib/components/IframedToolbarBrowser/IframedToolbarBrowser.tsx +++ b/frontend/src/lib/components/IframedToolbarBrowser/IframedToolbarBrowser.tsx @@ -35,10 +35,10 @@ export function IframedToolbarBrowser({ iframeRef, userIntent, }: { - iframeRef?: React.MutableRefObject + iframeRef: React.MutableRefObject userIntent: ToolbarUserIntent }): JSX.Element | null { - const logic = iframedToolbarBrowserLogic() + const logic = iframedToolbarBrowserLogic({ iframeRef, userIntent: userIntent }) const { browserUrl } = useValues(logic) const { onIframeLoad, setIframeWidth } = useActions(logic) diff --git a/frontend/src/lib/components/IframedToolbarBrowser/iframedToolbarBrowserLogic.ts b/frontend/src/lib/components/IframedToolbarBrowser/iframedToolbarBrowserLogic.ts index 71a59fdde32a1..f60838e83eed5 100644 --- a/frontend/src/lib/components/IframedToolbarBrowser/iframedToolbarBrowserLogic.ts +++ b/frontend/src/lib/components/IframedToolbarBrowser/iframedToolbarBrowserLogic.ts @@ -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 clearBrowserUrlOnUnmount?: boolean + userIntent?: ToolbarUserIntent } export interface IFrameBanner { @@ -50,6 +53,9 @@ export const iframedToolbarBrowserLogic = kea([ setIframeBanner: (banner: IFrameBanner | null) => ({ banner }), startTrackingLoading: true, stopTrackingLoading: true, + enableElementSelector: true, + disableElementSelector: true, + setNewActionName: (name: string | null) => ({ name }), }), reducers({ @@ -138,7 +144,7 @@ export const iframedToolbarBrowserLogic = kea([ '*' ) }, - + // heatmaps patchHeatmapFilters: ({ filters }) => { actions.sendToolbarMessage(PostHogAppToolbarEvent.PH_PATCH_HEATMAP_FILTERS, { filters }) }, @@ -159,6 +165,17 @@ export const iframedToolbarBrowserLogic = kea([ 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 @@ -171,9 +188,13 @@ export const iframedToolbarBrowserLogic = kea([ 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 => { diff --git a/frontend/src/lib/components/IframedToolbarBrowser/utils.ts b/frontend/src/lib/components/IframedToolbarBrowser/utils.ts index dbb47dd057d3c..1fc509d407f6c 100644 --- a/frontend/src/lib/components/IframedToolbarBrowser/utils.ts +++ b/frontend/src/lib/components/IframedToolbarBrowser/utils.ts @@ -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 = { diff --git a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx index 2bed8e8a07d2f..e9f87cbadefff 100644 --- a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx +++ b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx @@ -116,7 +116,7 @@ export const OnboardingDashboardTemplateConfigureStep = ({ {' '} (no need to send it now) .

- + }): JSX.Element { const { activeDashboardTemplate } = useValues(newDashboardLogic) const theDashboardTemplateVariablesLogic = dashboardTemplateVariablesLogic({ @@ -23,6 +26,9 @@ function VariableSelector({ const { allVariablesAreTouched, variables, activeVariableIndex } = useValues(theDashboardTemplateVariablesLogic) const [customEventName, setCustomEventName] = useState(null) const [showCustomEventField, setShowCustomEventField] = useState(false) + const { enableElementSelector, disableElementSelector, setNewActionName } = useActions( + iframedToolbarBrowserLogic({ iframeRef, clearBrowserUrlOnUnmount: true }) + ) const FALLBACK_EVENT = { id: '$other_event', @@ -131,12 +137,21 @@ function VariableSelector({ status="alt" onClick={() => { setShowCustomEventField(false) + enableElementSelector() + setNewActionName(variable.name) setVariable(variable.name, { events: [FALLBACK_EVENT] }) }} > Select from site - setShowCustomEventField(true)}> + { + disableElementSelector() + setNewActionName(null) + setShowCustomEventField(true) + }} + > Use custom event @@ -147,7 +162,13 @@ function VariableSelector({ ) } -export function DashboardTemplateVariables({ hasSelectedSite }: { hasSelectedSite: boolean }): JSX.Element { +export function DashboardTemplateVariables({ + hasSelectedSite, + iframeRef, +}: { + hasSelectedSite: boolean + iframeRef: React.RefObject +}): JSX.Element { const { activeDashboardTemplate } = useValues(newDashboardLogic) const theDashboardTemplateVariablesLogic = dashboardTemplateVariablesLogic({ variables: activeDashboardTemplate?.variables || [], @@ -172,7 +193,9 @@ export function DashboardTemplateVariables({ hasSelectedSite }: { hasSelectedSit {v.touched && } ), - content: , + content: ( + + ), className: 'p-4 bg-white', onHeaderClick: () => { setActiveVariableIndex(i) diff --git a/frontend/src/toolbar/actions/actionsTabLogic.tsx b/frontend/src/toolbar/actions/actionsTabLogic.tsx index 759d410d00f97..e59353d4c287a 100644 --- a/frontend/src/toolbar/actions/actionsTabLogic.tsx +++ b/frontend/src/toolbar/actions/actionsTabLogic.tsx @@ -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, } @@ -67,6 +67,7 @@ export const actionsTabLogic = kea([ hideButtonActions: true, setShowActionsTooltip: (showActionsTooltip: boolean) => ({ showActionsTooltip }), setElementSelector: (selector: string, index: number) => ({ selector, index }), + setAutomaticActionCreationEnabled: (enabled: boolean, name?: string) => ({ enabled, name }), }), connect(() => ({ @@ -142,6 +143,18 @@ export const actionsTabLogic = kea([ 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 }) => ({ @@ -211,22 +224,34 @@ export const actionsTabLogic = kea([ }, ], 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: [{}] }) @@ -237,6 +262,9 @@ export const actionsTabLogic = kea([ ? selectedAction.steps.map((step) => actionStepToActionStepFormItem(step, false)) : [{}], }) + if (values.isReadyForAutomaticSubmit) { + actions.submitActionForm() + } } }, })), diff --git a/frontend/src/toolbar/bar/toolbarLogic.ts b/frontend/src/toolbar/bar/toolbarLogic.ts index 20148d0ca3b40..67d0a3b1dda30 100644 --- a/frontend/src/toolbar/bar/toolbarLogic.ts +++ b/frontend/src/toolbar/bar/toolbarLogic.ts @@ -31,7 +31,7 @@ export const toolbarLogic = kea([ connect(() => ({ actions: [ actionsTabLogic, - ['showButtonActions', 'hideButtonActions', 'selectAction'], + ['showButtonActions', 'hideButtonActions', 'selectAction', 'setAutomaticActionCreationEnabled'], elementsLogic, ['enableInspect', 'disableInspect', 'createAction'], heatmapLogic, @@ -440,6 +440,16 @@ export const toolbarLogic = kea([ 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}`) } diff --git a/frontend/src/toolbar/elements/elementsLogic.ts b/frontend/src/toolbar/elements/elementsLogic.ts index eb019fdfe3edb..c7060ea5ba547 100644 --- a/frontend/src/toolbar/elements/elementsLogic.ts +++ b/frontend/src/toolbar/elements/elementsLogic.ts @@ -405,6 +405,7 @@ export const elementsLogic = kea([ }, createAction: ({ element }) => { actions.selectElement(null) + // this just sets the action form actions.newAction(element) }, })),