diff --git a/frontend/src/lib/components/icons.tsx b/frontend/src/lib/components/icons.tsx index 0a44f93d842..e7a951bb0a7 100644 --- a/frontend/src/lib/components/icons.tsx +++ b/frontend/src/lib/components/icons.tsx @@ -428,25 +428,77 @@ export function DiveIcon({ style }: { style?: CSSProperties }): JSX.Element { ) } -// Antd arrows rotated at convenient angles - -export function ArrowTopLeftOutlined({ style }: { style?: CSSProperties }): JSX.Element { +export function IconInfinity({ style }: { style?: CSSProperties }): JSX.Element { return ( - + + + + ) +} + +export function IconPathsCompletedArrow(): JSX.Element { + return ( + + + + ) +} + +export function IconPathsDropoffArrow(): JSX.Element { + return ( + + + + ) +} + +export function IconTrendUp({ style }: { style?: CSSProperties }): JSX.Element { + return ( + + + + ) +} + +export function IconFeedbackWarning({ style }: { style?: CSSProperties }): JSX.Element { + return ( + + + + ) +} + +// AntD arrows rotated at convenient angles + +export function ArrowBottomRightOutlined({ style }: { style?: CSSProperties }): JSX.Element { + return ( + ) @@ -459,60 +511,3 @@ export function ArrowTopRightOutlined({ style }: { style?: CSSProperties }): JSX ) } - -export function ArrowBottomRightOutlined({ style }: { style?: CSSProperties }): JSX.Element { - return ( - - - - ) -} - -export function ArrowBottomLeftOutlined({ style }: { style?: CSSProperties }): JSX.Element { - return ( - - - - ) -} - -export function Infinity({ style }: { style?: CSSProperties }): JSX.Element { - return ( - - - - ) -} - -export function PathsCompletedArrow(): JSX.Element { - return ( - - - - ) -} - -export function PathsDropoffArrow(): JSX.Element { - return ( - - - - ) -} - -export function TrendUp({ style }: { style?: CSSProperties }): JSX.Element { - return ( - - - - ) -} diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index b1f60c74c8b..ec126c9970e 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -240,7 +240,7 @@ export const FEATURE_FLAGS = { NEW_PATHS_UI: 'new-paths-ui', // owner: @EDsCODE NEW_PATHS_UI_EDGE_WEIGHTS: 'new-paths-ui-edge-weights', // owner: @neilkakkar SPLIT_PERSON: '5898-split-persons', // owner: @timgl - TOOLBAR_FEATURE_FLAGS: 'posthog-toolbar-feature-flags', // owner: @mariusnadra + TOOLBAR_FEATURE_FLAGS: 'posthog-toolbar-feature-flags', // owner: @mariusandra REMOVE_SESSIONS: '6050-remove-sessions', // owner: @rcmarron FUNNEL_VERTICAL_BREAKDOWN: '5733-funnel-vertical-breakdown', // owner: @alexkim RENAME_FILTERS: '6063-rename-filters', // owner: @alexkim diff --git a/frontend/src/scenes/funnels/FunnelBarGraph.tsx b/frontend/src/scenes/funnels/FunnelBarGraph.tsx index f28f9c0c16e..f127afe1e4d 100644 --- a/frontend/src/scenes/funnels/FunnelBarGraph.tsx +++ b/frontend/src/scenes/funnels/FunnelBarGraph.tsx @@ -7,7 +7,7 @@ import { Button, ButtonProps, Popover } from 'antd' import { ArrowRightOutlined, InfoCircleOutlined } from '@ant-design/icons' import { useResizeObserver } from 'lib/utils/responsiveUtils' import { SeriesGlyph } from 'lib/components/SeriesGlyph' -import { ArrowBottomRightOutlined, Infinity } from 'lib/components/icons' +import { ArrowBottomRightOutlined, IconInfinity } from 'lib/components/icons' import { funnelLogic } from './funnelLogic' import { useThrottledCallback } from 'use-debounce' import './FunnelBarGraph.scss' @@ -485,7 +485,7 @@ export function FunnelBarGraph({ color = 'white' }: { color?: string }): JSX.Ele
{filters.funnel_order_type === StepOrderValue.UNORDERED ? ( - + ) : ( {humanizeOrder(step.order)} diff --git a/frontend/src/scenes/funnels/funnelLogic.ts b/frontend/src/scenes/funnels/funnelLogic.ts index 29a660d004f..82e253e300e 100644 --- a/frontend/src/scenes/funnels/funnelLogic.ts +++ b/frontend/src/scenes/funnels/funnelLogic.ts @@ -101,6 +101,7 @@ export const funnelLogic = kea({ // Correlation related actions setCorrelationTypes: (types: FunnelCorrelationType[]) => ({ types }), setPropertyCorrelationTypes: (types: FunnelCorrelationType[]) => ({ types }), + hideSkewWarning: true, }), loaders: ({ values }) => ({ @@ -200,6 +201,12 @@ export const funnelLogic = kea({ setPropertyCorrelationTypes: (_, { types }) => types, }, ], + skewWarningHidden: [ + false, + { + hideSkewWarning: () => true, + }, + ], }), selectors: ({ selectors }) => ({ @@ -344,9 +351,9 @@ export const funnelLogic = kea({ }, ], isSkewed: [ - () => [selectors.conversionMetrics], - (conversionMetrics: FunnelTimeConversionMetrics) => { - return conversionMetrics.totalRate < 0.1 || conversionMetrics.totalRate > 0.9 + (s) => [s.conversionMetrics, s.skewWarningHidden], + (conversionMetrics, skewWarningHidden): boolean => { + return !skewWarningHidden && (conversionMetrics.totalRate < 0.1 || conversionMetrics.totalRate > 0.9) }, ], apiParams: [ diff --git a/frontend/src/scenes/insights/EmptyStates/EmptyStates.tsx b/frontend/src/scenes/insights/EmptyStates/EmptyStates.tsx index cac27316a2d..959a9b9ee10 100644 --- a/frontend/src/scenes/insights/EmptyStates/EmptyStates.tsx +++ b/frontend/src/scenes/insights/EmptyStates/EmptyStates.tsx @@ -3,7 +3,7 @@ import React from 'react' import imgEmptyLineGraph from 'public/empty-line-graph.svg' import imgEmptyLineGraphDark from 'public/empty-line-graph-dark.svg' import { QuestionCircleOutlined, LoadingOutlined, PlusCircleOutlined } from '@ant-design/icons' -import { IllustrationDanger, TrendUp } from 'lib/components/icons' +import { IllustrationDanger, IconTrendUp } from 'lib/components/icons' import { preflightLogic } from 'scenes/PreflightCheck/logic' import { funnelLogic } from 'scenes/funnels/funnelLogic' import { entityFilterLogic } from 'scenes/insights/ActionFilter/entityFilterLogic' @@ -277,7 +277,7 @@ export function SavedInsightsEmptyState(): JSX.Element {
- +

{SAVED_INSIGHTS_COPY[tab].title}

{SAVED_INSIGHTS_COPY[tab].description}

diff --git a/frontend/src/scenes/insights/FunnelCorrelation.scss b/frontend/src/scenes/insights/FunnelCorrelation.scss new file mode 100644 index 00000000000..c06c780b340 --- /dev/null +++ b/frontend/src/scenes/insights/FunnelCorrelation.scss @@ -0,0 +1,36 @@ +@import '~/vars'; + +.funnel-correlation { + .skew-warning { + margin-top: $default_spacing; + line-height: 2em; + border: 1px solid $warning; + + .ant-card-body { + padding: $default_spacing / 2 $default_spacing; + } + + h4 { + font-size: 1.1em; + display: flex; + align-items: center; + border-bottom: 1px solid $border; + padding: $default_spacing / 2 $default_spacing; + margin-left: -$default_spacing; + margin-right: -$default_spacing; + position: relative; + + .close-button { + position: absolute; + right: 16px; + color: $text_muted !important; + cursor: pointer; + } + } + + b { + padding-bottom: $default_spacing / 2; + font-weight: $medium; + } + } +} diff --git a/frontend/src/scenes/insights/FunnelCorrelation.tsx b/frontend/src/scenes/insights/FunnelCorrelation.tsx index 8f2c4690a3a..0f295e1d71a 100644 --- a/frontend/src/scenes/insights/FunnelCorrelation.tsx +++ b/frontend/src/scenes/insights/FunnelCorrelation.tsx @@ -1,37 +1,47 @@ import { Card } from 'antd' -import { useValues } from 'kea' +import { useActions, useValues } from 'kea' import React from 'react' import { funnelLogic } from 'scenes/funnels/funnelLogic' import { insightLogic } from './insightLogic' -import WarningOutlined from '@ant-design/icons/lib/icons/WarningOutlined' - +import './FunnelCorrelation.scss' import { FunnelCorrelationTable } from './InsightTabs/FunnelTab/FunnelCorrelationTable' import { FunnelPropertyCorrelationTable } from './InsightTabs/FunnelTab/FunnelPropertyCorrelationTable' +import { IconFeedbackWarning } from 'lib/components/icons' +import { CloseOutlined } from '@ant-design/icons' -export const FunnelCorrelation = (): JSX.Element => { +export const FunnelCorrelation = (): JSX.Element | null => { const { insightProps } = useValues(insightLogic) const { isSkewed, stepsWithCount } = useValues(funnelLogic(insightProps)) + const { hideSkewWarning } = useActions(funnelLogic(insightProps)) - return stepsWithCount.length > 1 ? ( - <> - {isSkewed ? ( - -
-
- - Funnel skewed! - Your funnel has a large skew to either successes or failures. With such funnels it's hard to - get meaningful odds for events and property correlations. Try adjusting your funnel to have - a more balanced success/failure ratio. -
+ if (stepsWithCount.length <= 1) { + return null + } + + return ( +
+ {isSkewed && ( + +

+ Adjust + your funnel definition to improve correlation analysis + +

+
+ Tips for adjusting your funnel: +
    +
  1. + Adjust your first funnel step to be more specific. For example, choose a page or an + event that occurs less frequently. +
  2. +
  3. Choose an event that happens more frequently for subsequent funnels steps.
  4. +
- ) : null} + )} - - ) : ( - <> +
) } diff --git a/frontend/src/scenes/paths/NewPaths.tsx b/frontend/src/scenes/paths/NewPaths.tsx index 4ffd869b409..e20a2b2209a 100644 --- a/frontend/src/scenes/paths/NewPaths.tsx +++ b/frontend/src/scenes/paths/NewPaths.tsx @@ -6,7 +6,7 @@ import * as Sankey from 'd3-sankey' import { pathsLogic } from 'scenes/paths/pathsLogic' import { useWindowSize } from 'lib/hooks/useWindowSize' import { Button, Menu, Dropdown, Tooltip, Row } from 'antd' -import { PathsCompletedArrow, PathsDropoffArrow } from 'lib/components/icons' +import { IconPathsCompletedArrow, IconPathsDropoffArrow } from 'lib/components/icons' import { ClockCircleOutlined } from '@ant-design/icons' import { humanFriendlyDuration } from 'lib/utils' import './Paths.scss' @@ -324,7 +324,7 @@ export function NewPaths({ dashboardItemId = null, color = 'white' }: PathsProps > - + {' '} Continuing {' '} @@ -361,7 +361,7 @@ export function NewPaths({ dashboardItemId = null, color = 'white' }: PathsProps alignItems: 'center', }} > - + {' '} Dropping off {' '} diff --git a/frontend/src/scenes/sessionRecordings/SessionPlayerDrawer.tsx b/frontend/src/scenes/sessionRecordings/SessionPlayerDrawer.tsx index 007f01e97d9..785f43716da 100644 --- a/frontend/src/scenes/sessionRecordings/SessionPlayerDrawer.tsx +++ b/frontend/src/scenes/sessionRecordings/SessionPlayerDrawer.tsx @@ -4,7 +4,7 @@ import { Drawer } from 'lib/components/Drawer' import { SessionsPlay } from 'scenes/sessions/SessionsPlay' import { SessionRecordingPlayerV2 } from 'scenes/sessionRecordings/player/SessionRecordingPlayerV2' import { useValues } from 'kea' -import { ArrowTopLeftOutlined } from 'lib/components/icons' +import { ArrowLeftOutlined } from '@ant-design/icons' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { FEATURE_FLAGS } from 'lib/constants' import { Button } from 'antd' @@ -21,7 +21,7 @@ export function SessionPlayerDrawer({ isPersonPage = false, onClose }: SessionPl <>