diff --git a/frontend/src/lib/components/ChartFilter/ChartFilter.tsx b/frontend/src/lib/components/ChartFilter/ChartFilter.tsx index 6f7d9cef6cff4..0c4bf137b0950 100644 --- a/frontend/src/lib/components/ChartFilter/ChartFilter.tsx +++ b/frontend/src/lib/components/ChartFilter/ChartFilter.tsx @@ -10,17 +10,19 @@ import { PieChartOutlined, TableOutlined, } from '@ant-design/icons' -import { ChartDisplayType, FilterType, ViewType } from '~/types' +import { ChartDisplayType, FilterType, FunnelVizType, ViewType } from '~/types' +import { preflightLogic } from 'scenes/PreflightCheck/logic' interface ChartFilterProps { filters: FilterType - onChange: (chartFilter: ChartDisplayType) => void + onChange: (chartFilter: ChartDisplayType | FunnelVizType) => void disabled: boolean } export function ChartFilter({ filters, onChange, disabled }: ChartFilterProps): JSX.Element { const { chartFilter } = useValues(chartFilterLogic) const { setChartFilter } = useActions(chartFilterLogic) + const { preflight } = useValues(preflightLogic) const linearDisabled = !!filters.session && filters.session === 'dist' const cumulativeDisabled = @@ -55,21 +57,28 @@ export function ChartFilter({ filters, onChange, disabled }: ChartFilterProps): const options = filters.insight === ViewType.FUNNELS - ? [ - { - value: ChartDisplayType.FunnelViz, - label: , - }, - { - value: ChartDisplayType.ActionsLineGraphLinear, - label: ( - - ), - }, - ] + ? preflight?.is_clickhouse_enabled + ? [ + { + value: FunnelVizType.Steps, + label: , + }, + { + value: FunnelVizType.Trends, + label: ( + + ), + }, + ] + : [ + { + value: FunnelVizType.Steps, + label: , + }, + ] : [ { label: 'Line Chart', @@ -117,7 +126,7 @@ export function ChartFilter({ filters, onChange, disabled }: ChartFilterProps): key="2" defaultValue={filters.display || defaultDisplay} value={chartFilter || defaultDisplay} - onChange={(value: ChartDisplayType) => { + onChange={(value: ChartDisplayType | FunnelVizType) => { setChartFilter(value) onChange(value) }} diff --git a/frontend/src/lib/components/ChartFilter/chartFilterLogic.ts b/frontend/src/lib/components/ChartFilter/chartFilterLogic.ts index 88553a9304d8a..df8be55976289 100644 --- a/frontend/src/lib/components/ChartFilter/chartFilterLogic.ts +++ b/frontend/src/lib/components/ChartFilter/chartFilterLogic.ts @@ -2,43 +2,50 @@ import { kea } from 'kea' import { router } from 'kea-router' import { objectsEqual } from 'lib/utils' import { chartFilterLogicType } from './chartFilterLogicType' -import { ChartDisplayType, ViewType } from '~/types' +import { ChartDisplayType, FunnelVizType, ViewType } from '~/types' + +function isFunnelVizType(filter: FunnelVizType | ChartDisplayType): filter is FunnelVizType { + return Object.values(FunnelVizType).includes(filter as FunnelVizType) +} export const chartFilterLogic = kea({ actions: () => ({ - setChartFilter: (filter: ChartDisplayType) => ({ filter }), + setChartFilter: (filter: ChartDisplayType | FunnelVizType) => ({ filter }), }), reducers: { chartFilter: [ - null as null | ChartDisplayType, + null as null | ChartDisplayType | FunnelVizType, { setChartFilter: (_, { filter }) => filter, }, ], }, listeners: ({ values }) => ({ - setChartFilter: () => { - const { display, ...searchParams } = router.values.searchParams // eslint-disable-line + setChartFilter: ({ filter }) => { + const { display, funnel_viz_type, ...searchParams } = router.values.searchParams // eslint-disable-line const { pathname } = router.values.location - searchParams.display = values.chartFilter - - if (!objectsEqual(display, values.chartFilter)) { + if (isFunnelVizType(filter)) { + searchParams.funnel_viz_type = filter + searchParams.display = ChartDisplayType.FunnelViz + } else { + searchParams.display = values.chartFilter + } + if ( + (!isFunnelVizType(filter) && !objectsEqual(display, values.chartFilter)) || + (isFunnelVizType(filter) && !objectsEqual(funnel_viz_type, values.chartFilter)) + ) { router.actions.replace(pathname, searchParams) } }, }), urlToAction: ({ actions }) => ({ - '/insights': (_, { display, insight }) => { - if (display) { + '/insights': (_, { display, insight, funnel_viz_type }) => { + if (display && !funnel_viz_type) { actions.setChartFilter(display) } else if (insight === ViewType.RETENTION) { actions.setChartFilter(ChartDisplayType.ActionsTable) } else if (insight === ViewType.FUNNELS) { - if (display === ChartDisplayType.FunnelsTimeToConvert) { - actions.setChartFilter(ChartDisplayType.FunnelsTimeToConvert) - } else { - actions.setChartFilter(ChartDisplayType.FunnelViz) - } + actions.setChartFilter(funnel_viz_type) } }, }), diff --git a/frontend/src/scenes/dashboard/DashboardItem.tsx b/frontend/src/scenes/dashboard/DashboardItem.tsx index e2e74f14dc052..e80b8d389e34a 100644 --- a/frontend/src/scenes/dashboard/DashboardItem.tsx +++ b/frontend/src/scenes/dashboard/DashboardItem.tsx @@ -40,7 +40,6 @@ import { ActionsBarValueGraph } from 'scenes/trends/viz' import relativeTime from 'dayjs/plugin/relativeTime' import { eventUsageLogic } from 'lib/utils/eventUsageLogic' -import { FunnelHistogram } from 'scenes/funnels/FunnelHistogram' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { FEATURE_FLAGS } from 'lib/constants' import { Funnel } from 'scenes/funnels/Funnel' @@ -138,19 +137,6 @@ export const displayMap: Record = { ).url }, }, - FunnelsTimeToConvert: { - className: 'funnel-time-to-convert', - element: FunnelHistogram, - icon: BarChartOutlined, - viewText: 'View time conversion', - link: ({ id, dashboard, name, filters }: DashboardItemType): string => { - return combineUrl( - `/insights`, - { insight: ViewType.FUNNELS, ...filters }, - { fromItem: id, fromItemName: name, fromDashboard: dashboard } - ).url - }, - }, RetentionContainer: { className: 'retention', element: RetentionContainer, diff --git a/frontend/src/scenes/funnels/Funnel.tsx b/frontend/src/scenes/funnels/Funnel.tsx index 522c494d6f97b..b0470504bb557 100644 --- a/frontend/src/scenes/funnels/Funnel.tsx +++ b/frontend/src/scenes/funnels/Funnel.tsx @@ -1,6 +1,6 @@ import { useActions, useValues } from 'kea' import React, { useEffect } from 'react' -import { ChartDisplayType, ChartParams } from '~/types' +import { ChartParams, FunnelVizType } from '~/types' import { FunnelBarGraph } from './FunnelBarGraph' import { FunnelHistogram } from './FunnelHistogram' import { funnelLogic } from './funnelLogic' @@ -14,9 +14,9 @@ export function Funnel(props: Omit): JSX.Element | null { loadResults() }, []) - const display = filters.display || props.filters.display + const funnel_viz_type = filters.funnel_viz_type || props.filters.funnel_viz_type - if (display == ChartDisplayType.FunnelsTimeToConvert) { + if (funnel_viz_type == FunnelVizType.TimeToConvert) { return timeConversionBins?.bins?.length ? : null } diff --git a/frontend/src/scenes/funnels/FunnelCanvasLabel.tsx b/frontend/src/scenes/funnels/FunnelCanvasLabel.tsx index f839af3dbeecd..652164e1ffede 100644 --- a/frontend/src/scenes/funnels/FunnelCanvasLabel.tsx +++ b/frontend/src/scenes/funnels/FunnelCanvasLabel.tsx @@ -8,7 +8,7 @@ import { insightLogic } from 'scenes/insights/insightLogic' import { funnelLogic } from './funnelLogic' import './FunnelCanvasLabel.scss' import { chartFilterLogic } from 'lib/components/ChartFilter/chartFilterLogic' -import { ChartDisplayType } from '~/types' +import { FunnelVizType } from '~/types' export function FunnelCanvasLabel(): JSX.Element | null { const { stepsWithCount, histogramStep, conversionMetrics, clickhouseFeaturesEnabled } = useValues(funnelLogic) @@ -21,7 +21,7 @@ export function FunnelCanvasLabel(): JSX.Element | null { return (
- {allFilters.display === ChartDisplayType.FunnelViz && ( + {allFilters.funnel_viz_type === FunnelVizType.Steps && ( <> @@ -43,10 +43,10 @@ export function FunnelCanvasLabel(): JSX.Element | null { diff --git a/frontend/src/scenes/funnels/FunnelHistogram.tsx b/frontend/src/scenes/funnels/FunnelHistogram.tsx index d7611babd156c..c380d848ef4b7 100644 --- a/frontend/src/scenes/funnels/FunnelHistogram.tsx +++ b/frontend/src/scenes/funnels/FunnelHistogram.tsx @@ -7,9 +7,9 @@ import { calcPercentage, getReferenceStep } from './funnelUtils' import { funnelLogic } from './funnelLogic' import { Histogram } from 'scenes/insights/Histogram' import { insightLogic } from 'scenes/insights/insightLogic' -import { ChartDisplayType } from '~/types' import './FunnelHistogram.scss' +import { FunnelVizType } from '~/types' import { ChartParams } from '~/types' export function FunnelHistogramHeader(): JSX.Element | null { @@ -17,7 +17,7 @@ export function FunnelHistogramHeader(): JSX.Element | null { const { changeHistogramStep } = useActions(funnelLogic) const { allFilters } = useValues(insightLogic) - if (allFilters.display !== ChartDisplayType.FunnelsTimeToConvert) { + if (allFilters.funnel_viz_type !== FunnelVizType.TimeToConvert) { return null } diff --git a/frontend/src/scenes/funnels/FunnelViz.tsx b/frontend/src/scenes/funnels/FunnelViz.tsx index bda5d473decf7..ae71d553e3ee4 100644 --- a/frontend/src/scenes/funnels/FunnelViz.tsx +++ b/frontend/src/scenes/funnels/FunnelViz.tsx @@ -4,15 +4,15 @@ import FunnelGraph from 'funnel-graph-js' import { Loading, humanFriendlyDuration } from 'lib/utils' import { useActions, useValues, BindLogic } from 'kea' import { funnelLogic } from './funnelLogic' -import { ACTIONS_LINE_GRAPH_LINEAR } from 'lib/constants' import { LineGraph } from 'scenes/insights/LineGraph' import { router } from 'kea-router' -import { InputNumber } from 'antd' +import { InputNumber, Row } from 'antd' import { preflightLogic } from 'scenes/PreflightCheck/logic' -import { ChartParams } from '~/types' +import { ChartParams, FunnelVizType } from '~/types' import { FunnelEmptyState } from 'scenes/insights/EmptyStates' import './FunnelViz.scss' +import { personsModalLogic } from 'scenes/trends/personsModalLogic' export function FunnelViz({ filters: defaultFilters, @@ -32,6 +32,7 @@ export function FunnelViz({ areFiltersValid, } = useValues(logic) const { loadResults: loadFunnel, loadConversionWindow } = useActions(logic) + const { loadPeople } = useActions(personsModalLogic) const { hashParams: { fromItem }, } = useValues(router) @@ -40,7 +41,7 @@ export function FunnelViz({ function buildChart(): void { // Build and mount graph for default "flow" visualization. // If steps are empty, new bargraph view is active, or linechart is visible, don't render flow graph. - if (!steps || steps.length === 0 || filters.display === ACTIONS_LINE_GRAPH_LINEAR) { + if (!steps || steps.length === 0 || filters.funnel_viz_type === FunnelVizType.Trends) { return } if (container.current) { @@ -103,10 +104,10 @@ export function FunnelViz({ ) } - if (filters.display === ACTIONS_LINE_GRAPH_LINEAR) { + if (filters.funnel_viz_type === FunnelVizType.Trends) { return steps && steps.length > 0 && steps[0].labels ? ( <> -
+ {preflight?.is_clickhouse_enabled && ( <> converted within  @@ -121,7 +122,7 @@ export function FunnelViz({ )} % converted from first to last step -
+ { + loadPeople({ + action: { id: point.index, name: point.label, properties: [], type: 'actions' }, + label: `Persons converted on ${point.label}`, + date_from: point.day, + date_to: point.day, + filters: filters, + saveOriginal: true, + }) + } + } /> ) : null diff --git a/frontend/src/scenes/funnels/funnelLogic.ts b/frontend/src/scenes/funnels/funnelLogic.ts index efc35cdcc7fa3..62aad35f72d66 100644 --- a/frontend/src/scenes/funnels/funnelLogic.ts +++ b/frontend/src/scenes/funnels/funnelLogic.ts @@ -10,7 +10,7 @@ import { funnelLogicType } from './funnelLogicType' import { EntityTypes, FilterType, - ChartDisplayType, + FunnelVizType, FunnelResult, FunnelStep, FunnelsTimeConversionBins, @@ -96,6 +96,8 @@ export const cleanFunnelParams = (filters: Partial): FilterType => { ...(filters.funnel_step ? { funnel_step: filters.funnel_step } : {}), ...(filters.funnel_viz_type ? { funnel_viz_type: filters.funnel_viz_type } : {}), ...(filters.funnel_step ? { funnel_to_step: filters.funnel_step } : {}), + ...(filters.entrance_period_start ? { entrance_period_start: filters.entrance_period_start } : {}), + ...(filters.drop_off ? { drop_off: filters.drop_off } : {}), interval: autocorrectInterval(filters), breakdown: filters.breakdown || undefined, breakdown_type: filters.breakdown_type || undefined, @@ -178,7 +180,7 @@ export const funnelLogic = kea({ } async function loadBinsResults(): Promise { - if (filters.display === ChartDisplayType.FunnelsTimeToConvert) { + if (filters.funnel_viz_type === FunnelVizType.TimeToConvert) { try { // API specs (#5110) require neither funnel_{from|to}_step to be provided if querying // for all steps @@ -187,7 +189,6 @@ export const funnelLogic = kea({ const binsResult = await pollFunnel({ ...apiParams, ...(refresh ? { refresh } : {}), - funnel_viz_type: 'time_to_convert', ...(!isAllSteps ? { funnel_from_step: histogramStep.from_step } : {}), ...(!isAllSteps ? { funnel_to_step: histogramStep.to_step } : {}), }) @@ -307,8 +308,8 @@ export const funnelLogic = kea({ ], showBarGraph: [ () => [selectors.filters], - ({ display }: { display: ChartDisplayType }) => - display === ChartDisplayType.FunnelViz || display === ChartDisplayType.FunnelsTimeToConvert, + ({ funnel_viz_type }: { funnel_viz_type: FunnelVizType }) => + funnel_viz_type === FunnelVizType.Steps || funnel_viz_type === FunnelVizType.TimeToConvert, ], clickhouseFeaturesEnabled: [ () => [featureFlagLogic.selectors.featureFlags, selectors.preflight], @@ -426,10 +427,14 @@ export const funnelLogic = kea({ ], steps: [ () => [selectors.results, selectors.stepsWithNestedBreakdown, selectors.filters], - (results, stepsWithNestedBreakdown, filters): FunnelStepWithNestedBreakdown[] => - !!filters.breakdown + (results, stepsWithNestedBreakdown, filters): FunnelStepWithNestedBreakdown[] => { + if (!Array.isArray(results)) { + return [] + } + return !!filters.breakdown ? stepsWithNestedBreakdown - : ([...results] as FunnelStep[]).sort((a, b) => a.order - b.order), + : ([...results] as FunnelStep[]).sort((a, b) => a.order - b.order) + }, ], stepsWithCount: [() => [selectors.steps], (steps) => steps.filter((step) => typeof step.count === 'number')], }), diff --git a/frontend/src/scenes/funnels/funnelUtils.ts b/frontend/src/scenes/funnels/funnelUtils.ts index 9f28a4c033836..111f97c2a4f41 100644 --- a/frontend/src/scenes/funnels/funnelUtils.ts +++ b/frontend/src/scenes/funnels/funnelUtils.ts @@ -71,7 +71,7 @@ export function getSeriesPositionName( } export function humanizeStepCount(count: number): string { - return count > 9999 ? humanizeNumber(count, 2) : count.toLocaleString() + return count > 9999 ? humanizeNumber(count, 2) : count?.toLocaleString() } export function cleanBinResult(binsResult: FunnelsTimeConversionBins): FunnelsTimeConversionBins { diff --git a/frontend/src/scenes/insights/InsightTabs/FunnelTab/ToggleButtonChartFilter.tsx b/frontend/src/scenes/insights/InsightTabs/FunnelTab/ToggleButtonChartFilter.tsx index c7b20d3b10139..f2bc3d5cbe90e 100644 --- a/frontend/src/scenes/insights/InsightTabs/FunnelTab/ToggleButtonChartFilter.tsx +++ b/frontend/src/scenes/insights/InsightTabs/FunnelTab/ToggleButtonChartFilter.tsx @@ -1,12 +1,12 @@ import React from 'react' import { useActions, useValues } from 'kea' import { Radio, Tooltip } from 'antd' -import { ChartDisplayType } from '~/types' +import { FunnelVizType } from '~/types' import { chartFilterLogic } from 'lib/components/ChartFilter/chartFilterLogic' import { funnelLogic } from 'scenes/funnels/funnelLogic' interface ToggleButtonChartFilterProps { - onChange?: (chartFilter: ChartDisplayType) => void + onChange?: (chartFilter: FunnelVizType) => void disabled?: boolean } @@ -19,21 +19,21 @@ export function ToggleButtonChartFilter({ const { clickhouseFeaturesEnabled } = useValues(funnelLogic()) const { chartFilter } = useValues(chartFilterLogic) const { setChartFilter } = useActions(chartFilterLogic) - const defaultDisplay = ChartDisplayType.FunnelViz + const defaultDisplay = FunnelVizType.Steps const options = [ { - value: ChartDisplayType.FunnelViz, + value: FunnelVizType.Steps, label: Conversion steps, visible: true, }, { - value: ChartDisplayType.FunnelsTimeToConvert, + value: FunnelVizType.TimeToConvert, label: Time to convert, visible: clickhouseFeaturesEnabled, }, { - value: ChartDisplayType.ActionsLineGraphLinear, + value: FunnelVizType.Trends, label: Historical, visible: true, }, @@ -44,7 +44,7 @@ export function ToggleButtonChartFilter({ key="2" defaultValue={defaultDisplay} value={chartFilter || defaultDisplay} - onChange={({ target: { value } }: { target: { value?: ChartDisplayType } }) => { + onChange={({ target: { value } }: { target: { value?: FunnelVizType } }) => { if (value) { setChartFilter(value) onChange(value) diff --git a/frontend/src/scenes/insights/InsightTabs/InsightDisplayConfig.tsx b/frontend/src/scenes/insights/InsightTabs/InsightDisplayConfig.tsx index c62422df5c7f8..b68e7ede9b52d 100644 --- a/frontend/src/scenes/insights/InsightTabs/InsightDisplayConfig.tsx +++ b/frontend/src/scenes/insights/InsightTabs/InsightDisplayConfig.tsx @@ -2,15 +2,9 @@ import { ChartFilter } from 'lib/components/ChartFilter' import { CompareFilter } from 'lib/components/CompareFilter/CompareFilter' import { IntervalFilter } from 'lib/components/IntervalFilter' import { TZIndicator } from 'lib/components/TimezoneAware' -import { - ACTIONS_BAR_CHART_VALUE, - ACTIONS_LINE_GRAPH_LINEAR, - ACTIONS_PIE_CHART, - ACTIONS_TABLE, - FEATURE_FLAGS, -} from 'lib/constants' +import { ACTIONS_BAR_CHART_VALUE, ACTIONS_PIE_CHART, ACTIONS_TABLE, FEATURE_FLAGS } from 'lib/constants' import React from 'react' -import { ChartDisplayType, FilterType, ViewType } from '~/types' +import { ChartDisplayType, FilterType, FunnelVizType, ViewType } from '~/types' import { CalendarOutlined } from '@ant-design/icons' import { InsightDateFilter } from '../InsightDateFilter' import { RetentionDatePicker } from '../RetentionDatePicker' @@ -30,7 +24,7 @@ interface InsightDisplayConfigProps { const showIntervalFilter = function (activeView: ViewType, filter: FilterType): boolean { switch (activeView) { case ViewType.FUNNELS: - return filter.display === ACTIONS_LINE_GRAPH_LINEAR + return filter.funnel_viz_type === FunnelVizType.Trends case ViewType.RETENTION: case ViewType.PATHS: return false @@ -102,7 +96,7 @@ export function InsightDisplayConfig({
{showChartFilter(activeView) && ( { + onChange={(display: ChartDisplayType | FunnelVizType) => { if (display === ACTIONS_TABLE || display === ACTIONS_PIE_CHART) { clearAnnotationsToCreate() } @@ -115,7 +109,7 @@ export function InsightDisplayConfig({ {activeView === ViewType.RETENTION && } - {showFunnelBarOptions && allFilters.display !== ChartDisplayType.FunnelsTimeToConvert && ( + {showFunnelBarOptions && allFilters.funnel_viz_type === FunnelVizType.Steps && ( <> diff --git a/frontend/src/scenes/insights/Insights.tsx b/frontend/src/scenes/insights/Insights.tsx index 76f2fb7a9a7eb..ee847458919bd 100644 --- a/frontend/src/scenes/insights/Insights.tsx +++ b/frontend/src/scenes/insights/Insights.tsx @@ -6,13 +6,7 @@ import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' import { Tabs, Row, Col, Card, Button, Tooltip } from 'antd' -import { - FUNNEL_VIZ, - ACTIONS_TABLE, - ACTIONS_BAR_CHART_VALUE, - FEATURE_FLAGS, - ACTIONS_LINE_GRAPH_LINEAR, -} from 'lib/constants' +import { FUNNEL_VIZ, ACTIONS_TABLE, ACTIONS_BAR_CHART_VALUE, FEATURE_FLAGS } from 'lib/constants' import { annotationsLogic } from '~/lib/components/Annotations' import { router } from 'kea-router' @@ -35,7 +29,7 @@ import { People } from 'scenes/funnels/People' import { InsightsTable } from './InsightsTable' import { TrendInsight } from 'scenes/trends/Trends' import { trendsLogic } from 'scenes/trends/trendsLogic' -import { HotKeys, ViewType } from '~/types' +import { FunnelVizType, HotKeys, ViewType } from '~/types' import { useKeyboardHotkeys } from 'lib/hooks/useKeyboardHotkeys' import { eventUsageLogic } from 'lib/utils/eventUsageLogic' import { InsightDisplayConfig } from './InsightTabs/InsightDisplayConfig' @@ -434,8 +428,8 @@ function FunnelInsight(): JSX.Element { const { isValidFunnel, isLoading, + filters: { funnel_viz_type }, areFiltersValid, - filters: { display }, showBarGraph, } = useValues(funnelLogic({})) const { clickhouseFeaturesEnabled } = useValues(funnelLogic) @@ -448,15 +442,15 @@ function FunnelInsight(): JSX.Element { 'non-empty-state': isValidFunnel && areFiltersValid && - (!featureFlags[FEATURE_FLAGS.FUNNEL_BAR_VIZ] || display === ACTIONS_LINE_GRAPH_LINEAR), + (!featureFlags[FEATURE_FLAGS.FUNNEL_BAR_VIZ] || funnel_viz_type === FunnelVizType.Trends), })} > {isLoading && } {isValidFunnel ? ( featureFlags[FEATURE_FLAGS.FUNNEL_BAR_VIZ] && showBarGraph ? ( - + ) : ( - + ) ) : ( !isLoading && ( diff --git a/frontend/src/scenes/insights/LineGraph/LineGraph.js b/frontend/src/scenes/insights/LineGraph/LineGraph.js index 1d3f4c7b89a9f..0e583fbeaa7f3 100644 --- a/frontend/src/scenes/insights/LineGraph/LineGraph.js +++ b/frontend/src/scenes/insights/LineGraph/LineGraph.js @@ -262,7 +262,6 @@ export function LineGraph({ // This could either be a color or an array of colors (`horizontalBar`) const colorSet = entityData.backgroundColor || entityData.borderColor - return ( { return localStorage.getItem('default_filter_test_accounts') === 'true' || false } +interface UrlParams { + insight: string + properties: PropertyFilter[] | undefined + filter_test_accounts: boolean + funnel_viz_type?: string + display?: string +} + export const logicFromInsight = (insight: string, logicProps: Record): Logic & BuiltLogic => { if (insight === ViewType.FUNNELS) { return funnelLogic(logicProps) @@ -228,11 +236,16 @@ export const insightLogic = kea({ return cachedUrl + '&' + toParams({ properties }) } - const urlParams = { + const urlParams: UrlParams = { insight: type, properties: values.allFilters.properties, filter_test_accounts: defaultFilterTestAccounts(), } + + if (type === ViewType.FUNNELS) { + urlParams.funnel_viz_type = FunnelVizType.Steps + urlParams.display = 'FunnelViz' + } return ['/insights', urlParams] }, }), diff --git a/frontend/src/scenes/trends/personsModalLogic.ts b/frontend/src/scenes/trends/personsModalLogic.ts index 5534c25a99538..339ab6b2a6097 100644 --- a/frontend/src/scenes/trends/personsModalLogic.ts +++ b/frontend/src/scenes/trends/personsModalLogic.ts @@ -1,9 +1,10 @@ +import dayjs from 'dayjs' import { kea } from 'kea' import api from 'lib/api' import { errorToast, toParams } from 'lib/utils' -import { cleanFunnelParams, funnelLogic } from 'scenes/funnels/funnelLogic' +import { cleanFunnelParams } from 'scenes/funnels/funnelLogic' import { cohortLogic } from 'scenes/persons/cohortLogic' -import { ActionFilter, FilterType, ViewType } from '~/types' +import { ActionFilter, FilterType, FunnelVizType, ViewType } from '~/types' import { personsModalLogicType } from './personsModalLogicType' import { parsePeopleParams, TrendPeople } from './trendsLogic' @@ -146,8 +147,16 @@ export const personsModalLogic = kea>({ const filterParams = parsePeopleParams({ label, action, date_from, date_to, breakdown_value }, filters) actions.setPeople(tempPeople) people = await api.get(`api/person/stickiness/?${filterParams}${searchTermParam}`) - } else if (funnelStep) { - const params = { ...funnelLogic().values.filters, funnel_step: funnelStep } + } else if (funnelStep || filters.funnel_viz_type === FunnelVizType.Trends) { + let params + if (filters.funnel_viz_type === FunnelVizType.Trends) { + // funnel trends + const entrance_period_start = dayjs(date_from).format('YYYY-MM-DD HH:mm:ss') + params = { ...filters, entrance_period_start, drop_off: false } + } else { + // regular funnel steps + params = { ...filters, funnel_step: funnelStep } + } const cleanedParams = cleanFunnelParams(params) const funnelParams = toParams(cleanedParams) people = await api.create(`api/person/funnel/?${funnelParams}${searchTermParam}`) diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 13f94ce773321..43d7a012aceef 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -556,7 +556,6 @@ export enum ChartDisplayType { ActionsBarChartValue = 'ActionsBarValue', PathsViz = 'PathsViz', FunnelViz = 'FunnelViz', - FunnelsTimeToConvert = 'FunnelsTimeToConvert', } export type ShownAsType = ShownAsValue // DEPRECATED: Remove when releasing `remove-shownas` @@ -584,6 +583,12 @@ export enum PathType { CustomEvent = 'custom_event', } +export enum FunnelVizType { + Steps = 'steps', + TimeToConvert = 'time_to_convert', + Trends = 'trends', +} + export type RetentionType = typeof RETENTION_RECURRING | typeof RETENTION_FIRST_TIME export interface FilterType { @@ -617,6 +622,8 @@ export interface FilterType { filter_test_accounts?: boolean from_dashboard?: boolean funnel_step?: number + entrance_period_start?: string // this and drop_off is used for funnels time conversion date for the persons modal + drop_off?: boolean funnel_viz_type?: string // parameter sent to funnels API for time conversion code path funnel_from_step?: number // used in time to convert: initial step index to compute time to convert funnel_to_step?: number // used in time to convert: ending step index to compute time to convert