From a15cd8d437dd7643e25fba7ae8184f2343ba9724 Mon Sep 17 00:00:00 2001 From: Juraj Majerik Date: Thu, 26 Dec 2024 10:55:44 +0100 Subject: [PATCH] wip --- .../src/scenes/experiments/Experiments.tsx | 4 + .../SavedMetrics/SavedFunnelsMetricForm.tsx | 63 ++++++----- .../experiments/SavedMetrics/SavedMetric.tsx | 9 +- .../experiments/SavedMetrics/SavedMetrics.tsx | 27 +---- .../SavedMetrics/SavedTrendsMetricForm.tsx | 104 ++++++++++-------- .../SavedMetrics/savedMetricLogic.tsx | 16 +-- .../SavedMetrics/savedMetricsLogic.tsx | 11 +- .../scenes/experiments/experimentsLogic.ts | 11 +- frontend/src/types.ts | 1 + 9 files changed, 128 insertions(+), 118 deletions(-) diff --git a/frontend/src/scenes/experiments/Experiments.tsx b/frontend/src/scenes/experiments/Experiments.tsx index 26c84171c6a8c..6ea164c74e82b 100644 --- a/frontend/src/scenes/experiments/Experiments.tsx +++ b/frontend/src/scenes/experiments/Experiments.tsx @@ -23,6 +23,7 @@ import { Experiment, ExperimentsTabs, ProductKey, ProgressStatus } from '~/types import { experimentsLogic, getExperimentStatus } from './experimentsLogic' import { StatusTag } from './ExperimentView/components' import { Holdouts } from './Holdouts' +import { SavedMetrics } from './SavedMetrics/SavedMetrics' export const scene: SceneExport = { component: Experiments, @@ -211,11 +212,14 @@ export function Experiments(): JSX.Element { { key: ExperimentsTabs.Yours, label: 'Your experiments' }, { key: ExperimentsTabs.Archived, label: 'Archived experiments' }, { key: ExperimentsTabs.Holdouts, label: 'Holdout groups' }, + { key: ExperimentsTabs.SavedMetrics, label: 'Saved metrics' }, ]} /> {tab === ExperimentsTabs.Holdouts ? ( + ) : tab === ExperimentsTabs.SavedMetrics ? ( + ) : ( <> {tab === ExperimentsTabs.Archived ? ( diff --git a/frontend/src/scenes/experiments/SavedMetrics/SavedFunnelsMetricForm.tsx b/frontend/src/scenes/experiments/SavedMetrics/SavedFunnelsMetricForm.tsx index 5cb8cde0dca0f..8a08ff8263b14 100644 --- a/frontend/src/scenes/experiments/SavedMetrics/SavedFunnelsMetricForm.tsx +++ b/frontend/src/scenes/experiments/SavedMetrics/SavedFunnelsMetricForm.tsx @@ -3,8 +3,6 @@ import { LemonInput } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types' import { TestAccountFilterSwitch } from 'lib/components/TestAccountFiltersSwitch' -import { EXPERIMENT_DEFAULT_DURATION } from 'lib/constants' -import { LemonBanner } from 'lib/lemon-ui/LemonBanner' import { ActionFilter } from 'scenes/insights/filters/ActionFilter/ActionFilter' import { MathAvailability } from 'scenes/insights/filters/ActionFilter/ActionFilterRow/ActionFilterRow' import { getHogQLValue } from 'scenes/insights/filters/AggregationSelect' @@ -12,8 +10,7 @@ import { teamLogic } from 'scenes/teamLogic' import { actionsAndEventsToSeries } from '~/queries/nodes/InsightQuery/utils/filtersToQueryNode' import { queryNodeToFilter } from '~/queries/nodes/InsightQuery/utils/queryNodeToFilter' -import { Query } from '~/queries/Query/Query' -import { ExperimentFunnelsQuery, NodeKind } from '~/queries/schema' +import { ExperimentFunnelsQuery } from '~/queries/schema' import { BreakdownAttributionType, FilterType } from '~/types' import { @@ -36,6 +33,12 @@ export function SavedFunnelsMetricForm(): JSX.Element { actionsTaxonomicGroupTypes: [TaxonomicFilterGroupType.Events, TaxonomicFilterGroupType.Actions], } + if (!savedMetric?.query) { + return <> + } + + const savedMetricQuery = savedMetric.query as ExperimentFunnelsQuery + return ( <>
@@ -52,8 +55,12 @@ export function SavedFunnelsMetricForm(): JSX.Element {
): void => { + if (!savedMetric?.query) { + return + } + const series = actionsAndEventsToSeries( { actions, events, data_warehouse } as any, true, @@ -61,9 +68,9 @@ export function SavedFunnelsMetricForm(): JSX.Element { ) setSavedMetric({ query: { - ...savedMetric.query, + ...savedMetricQuery, funnels_query: { - ...savedMetric.query.funnels_query, + ...savedMetricQuery.funnels_query, series, }, }, @@ -81,15 +88,15 @@ export function SavedFunnelsMetricForm(): JSX.Element {
{ setSavedMetric({ query: { - ...savedMetric.query, + ...savedMetricQuery, funnels_query: { - ...savedMetric.query.funnels_query, + ...savedMetricQuery.funnels_query, aggregation_group_type_index: value, }, }, @@ -97,17 +104,17 @@ export function SavedFunnelsMetricForm(): JSX.Element { }} /> { setSavedMetric({ query: { - ...savedMetric.query, + ...savedMetricQuery, funnels_query: { - ...savedMetric.query.funnels_query, + ...savedMetricQuery.funnels_query, // funnelWindowInterval: funnelWindowInterval, funnelsFilter: { - ...savedMetric.query.funnels_query.funnelsFilter, + ...savedMetricQuery.funnels_query.funnelsFilter, funnelWindowInterval: funnelWindowInterval, }, }, @@ -117,11 +124,11 @@ export function SavedFunnelsMetricForm(): JSX.Element { onFunnelWindowIntervalUnitChange={(funnelWindowIntervalUnit) => { setSavedMetric({ query: { - ...savedMetric.query, + ...savedMetricQuery, funnels_query: { - ...savedMetric.query.funnels_query, + ...savedMetricQuery.funnels_query, funnelsFilter: { - ...savedMetric.query.funnels_query.funnelsFilter, + ...savedMetricQuery.funnels_query.funnelsFilter, funnelWindowIntervalUnit: funnelWindowIntervalUnit || undefined, }, }, @@ -132,9 +139,9 @@ export function SavedFunnelsMetricForm(): JSX.Element { { const breakdownAttributionType = - savedMetric.query.funnels_query?.funnelsFilter?.breakdownAttributionType + savedMetricQuery.funnels_query?.funnelsFilter?.breakdownAttributionType const breakdownAttributionValue = - savedMetric.query.funnels_query?.funnelsFilter?.breakdownAttributionValue + savedMetricQuery.funnels_query?.funnelsFilter?.breakdownAttributionValue const currentValue: BreakdownAttributionType | `${BreakdownAttributionType.Step}/${number}` = !breakdownAttributionType @@ -149,11 +156,11 @@ export function SavedFunnelsMetricForm(): JSX.Element { const [breakdownAttributionType, breakdownAttributionValue] = (value || '').split('/') setSavedMetric({ query: { - ...savedMetric.query, + ...savedMetricQuery, funnels_query: { - ...savedMetric.query.funnels_query, + ...savedMetricQuery.funnels_query, funnelsFilter: { - ...savedMetric.query.funnels_query.funnelsFilter, + ...savedMetricQuery.funnels_query.funnelsFilter, breakdownAttributionType: breakdownAttributionType as BreakdownAttributionType, breakdownAttributionValue: breakdownAttributionValue ? parseInt(breakdownAttributionValue) @@ -163,19 +170,19 @@ export function SavedFunnelsMetricForm(): JSX.Element { }, }) }} - stepsLength={savedMetric.query.funnels_query?.series?.length} + stepsLength={savedMetricQuery.funnels_query?.series?.length} /> { - const val = savedMetric.query.funnels_query?.filterTestAccounts + const val = savedMetricQuery.funnels_query?.filterTestAccounts return hasFilters ? !!val : false })()} onChange={(checked: boolean) => { setSavedMetric({ query: { - ...savedMetric.query, + ...savedMetricQuery, funnels_query: { - ...savedMetric.query.funnels_query, + ...savedMetricQuery.funnels_query, filterTestAccounts: checked, }, }, diff --git a/frontend/src/scenes/experiments/SavedMetrics/SavedMetric.tsx b/frontend/src/scenes/experiments/SavedMetrics/SavedMetric.tsx index 86a26ec169819..e789bb8d1c52f 100644 --- a/frontend/src/scenes/experiments/SavedMetrics/SavedMetric.tsx +++ b/frontend/src/scenes/experiments/SavedMetrics/SavedMetric.tsx @@ -1,12 +1,13 @@ import { IconCheckCircle } from '@posthog/icons' +import { LemonButton } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { useState } from 'react' +import { SceneExport } from 'scenes/sceneTypes' + +import { getDefaultFunnelsMetric, getDefaultTrendsMetric } from '../experimentLogic' +import { SavedFunnelsMetricForm } from './SavedFunnelsMetricForm' import { savedMetricLogic } from './savedMetricLogic' import { SavedTrendsMetricForm } from './SavedTrendsMetricForm' -import { SavedFunnelsMetricForm } from './SavedFunnelsMetricForm' -import { getDefaultTrendsMetric, getDefaultFunnelsMetric } from '../experimentLogic' -import { LemonButton } from '@posthog/lemon-ui' -import { SceneExport } from 'kea' type MetricType = 'trends' | 'funnels' diff --git a/frontend/src/scenes/experiments/SavedMetrics/SavedMetrics.tsx b/frontend/src/scenes/experiments/SavedMetrics/SavedMetrics.tsx index 055cfda781af9..2e0abca44aa35 100644 --- a/frontend/src/scenes/experiments/SavedMetrics/SavedMetrics.tsx +++ b/frontend/src/scenes/experiments/SavedMetrics/SavedMetrics.tsx @@ -1,28 +1,11 @@ -import { IconPencil, IconTrash } from '@posthog/icons' -import { - LemonBanner, - LemonButton, - LemonDialog, - LemonDivider, - LemonInput, - LemonLabel, - LemonModal, - LemonTable, - LemonTableColumns, - Link, -} from '@posthog/lemon-ui' -import { useActions, useValues } from 'kea' -import { LemonSlider } from 'lib/lemon-ui/LemonSlider' -import { useState } from 'react' - -import { Holdout, holdoutsLogic, NEW_HOLDOUT } from '../holdoutsLogic' +import { LemonButton, LemonTable, LemonTableColumns } from '@posthog/lemon-ui' +import { useValues } from 'kea' +import { router } from 'kea-router' import { SceneExport } from 'scenes/sceneTypes' -import { experimentsLogic } from '../experimentsLogic' import { urls } from 'scenes/urls' -import { PageHeader } from 'lib/components/PageHeader' -import { SavedMetricLogicProps, savedMetricsLogic } from './savedMetricsLogic' + import { SavedMetric } from './savedMetricLogic' -import { router } from 'kea-router' +import { savedMetricsLogic } from './savedMetricsLogic' export const scene: SceneExport = { component: SavedMetrics, diff --git a/frontend/src/scenes/experiments/SavedMetrics/SavedTrendsMetricForm.tsx b/frontend/src/scenes/experiments/SavedMetrics/SavedTrendsMetricForm.tsx index 48dd0571dbe70..ea78798cdafee 100644 --- a/frontend/src/scenes/experiments/SavedMetrics/SavedTrendsMetricForm.tsx +++ b/frontend/src/scenes/experiments/SavedMetrics/SavedTrendsMetricForm.tsx @@ -4,7 +4,6 @@ import { useActions, useValues } from 'kea' import { TestAccountFilterSwitch } from 'lib/components/TestAccountFiltersSwitch' import { EXPERIMENT_DEFAULT_DURATION } from 'lib/constants' import { dayjs } from 'lib/dayjs' -import { LemonBanner } from 'lib/lemon-ui/LemonBanner' import { useState } from 'react' import { ActionFilter } from 'scenes/insights/filters/ActionFilter/ActionFilter' import { MathAvailability } from 'scenes/insights/filters/ActionFilter/ActionFilterRow/ActionFilterRow' @@ -12,7 +11,6 @@ import { teamLogic } from 'scenes/teamLogic' import { actionsAndEventsToSeries } from '~/queries/nodes/InsightQuery/utils/filtersToQueryNode' import { queryNodeToFilter } from '~/queries/nodes/InsightQuery/utils/queryNodeToFilter' -import { Query } from '~/queries/Query/Query' import { ExperimentTrendsQuery, InsightQueryNode, NodeKind } from '~/queries/schema' import { BaseMathType, ChartDisplayType, FilterType, PropertyMathType } from '~/types' @@ -25,7 +23,13 @@ export function SavedTrendsMetricForm(): JSX.Element { const { currentTeam } = useValues(teamLogic) const hasFilters = (currentTeam?.test_account_filters || []).length > 0 const [activeTab, setActiveTab] = useState('main') - console.log('savedMetric', savedMetric) + + if (!savedMetric?.query) { + return <> + } + + const savedMetricQuery = savedMetric.query as ExperimentTrendsQuery + return ( <> ): void => { const series = actionsAndEventsToSeries( { actions, events, data_warehouse } as any, @@ -59,9 +63,9 @@ export function SavedTrendsMetricForm(): JSX.Element { ) setSavedMetric({ query: { - ...savedMetric.query, + ...savedMetricQuery, count_query: { - ...savedMetric.query.count_query, + ...savedMetricQuery.count_query, series, }, }, @@ -78,15 +82,15 @@ export function SavedTrendsMetricForm(): JSX.Element {
{ - const val = savedMetric.query.count_query?.filterTestAccounts + const val = savedMetricQuery.count_query?.filterTestAccounts return hasFilters ? !!val : false })()} onChange={(checked: boolean) => { setSavedMetric({ query: { - ...savedMetric.query, + ...savedMetricQuery, count_query: { - ...savedMetric.query.count_query, + ...savedMetricQuery.count_query, filterTestAccounts: checked, }, }, @@ -124,19 +128,22 @@ export function SavedTrendsMetricForm(): JSX.Element {
{ setSavedMetric({ - exposure_query: undefined, + query: { + ...savedMetricQuery, + exposure_query: undefined, + }, }) }} >
Default - {!savedMetric.exposure_query && ( + {!savedMetricQuery.exposure_query && ( )}
@@ -149,41 +156,44 @@ export function SavedTrendsMetricForm(): JSX.Element {
{ setSavedMetric({ - exposure_query: { - kind: NodeKind.TrendsQuery, - series: [ - { - kind: NodeKind.EventsNode, - name: '$feature_flag_called', - event: '$feature_flag_called', - math: BaseMathType.UniqueUsers, + query: { + ...savedMetricQuery, + exposure_query: { + kind: NodeKind.TrendsQuery, + series: [ + { + kind: NodeKind.EventsNode, + name: '$feature_flag_called', + event: '$feature_flag_called', + math: BaseMathType.UniqueUsers, + }, + ], + interval: 'day', + dateRange: { + date_from: dayjs() + .subtract(EXPERIMENT_DEFAULT_DURATION, 'day') + .format('YYYY-MM-DDTHH:mm'), + date_to: dayjs().endOf('d').format('YYYY-MM-DDTHH:mm'), + explicitDate: true, }, - ], - interval: 'day', - dateRange: { - date_from: dayjs() - .subtract(EXPERIMENT_DEFAULT_DURATION, 'day') - .format('YYYY-MM-DDTHH:mm'), - date_to: dayjs().endOf('d').format('YYYY-MM-DDTHH:mm'), - explicitDate: true, - }, - trendsFilter: { - display: ChartDisplayType.ActionsLineGraph, + trendsFilter: { + display: ChartDisplayType.ActionsLineGraph, + }, + filterTestAccounts: true, }, - filterTestAccounts: true, }, }) }} >
Custom - {savedMetric.exposure_query && ( + {savedMetricQuery.exposure_query && ( )}
@@ -194,11 +204,13 @@ export function SavedTrendsMetricForm(): JSX.Element {
- {savedMetric.exposure_query && ( + {savedMetricQuery.exposure_query && ( <> { - const val = savedMetric.exposure_query?.filterTestAccounts + const val = savedMetricQuery.exposure_query?.filterTestAccounts return hasFilters ? !!val : false })()} onChange={(checked: boolean) => { setSavedMetric({ - exposure_query: { - ...savedMetric.exposure_query, - filterTestAccounts: checked, + query: { + ...savedMetricQuery, + exposure_query: { + ...savedMetricQuery.exposure_query, + filterTestAccounts: checked, + }, }, }) }} diff --git a/frontend/src/scenes/experiments/SavedMetrics/savedMetricLogic.tsx b/frontend/src/scenes/experiments/SavedMetrics/savedMetricLogic.tsx index f7a2872f9aa60..ebc10e6ea1abf 100644 --- a/frontend/src/scenes/experiments/SavedMetrics/savedMetricLogic.tsx +++ b/frontend/src/scenes/experiments/SavedMetrics/savedMetricLogic.tsx @@ -1,11 +1,11 @@ -import { actions, kea, key, path, props, reducers, selectors, listeners } from 'kea' -import { loaders } from 'kea-loaders' -import type { savedMetricLogicType } from './savedMetricLogicType' -import { getDefaultTrendsMetric } from '../experimentLogic' -import api from 'lib/api' import { lemonToast } from '@posthog/lemon-ui' +import { actions, kea, key, listeners, path, props, reducers, selectors } from 'kea' +import { loaders } from 'kea-loaders' import { router, urlToAction } from 'kea-router' -import { urls } from 'scenes/urls' +import api from 'lib/api' + +import { getDefaultTrendsMetric } from '../experimentLogic' +import type { savedMetricLogicType } from './savedMetricLogicType' export interface SavedMetricLogicProps { savedMetricId?: string | number @@ -38,8 +38,8 @@ export const savedMetricLogic = kea([ actions({ setSavedMetric: (metric: Partial) => ({ metric }), - createSavedMetric: (metric: Partial) => ({ metric }), - updateSavedMetric: (metric: Partial) => ({ metric }), + createSavedMetric: true, + updateSavedMetric: true, deleteSavedMetric: true, }), diff --git a/frontend/src/scenes/experiments/SavedMetrics/savedMetricsLogic.tsx b/frontend/src/scenes/experiments/SavedMetrics/savedMetricsLogic.tsx index 104120ac5eb93..c0eda3f551ce5 100644 --- a/frontend/src/scenes/experiments/SavedMetrics/savedMetricsLogic.tsx +++ b/frontend/src/scenes/experiments/SavedMetrics/savedMetricsLogic.tsx @@ -1,10 +1,9 @@ import { actions, events, kea, listeners, path, reducers } from 'kea' -import { router } from 'kea-router' -import type { savedMetricsLogicType } from '../savedMetricsLogicType' import { loaders } from 'kea-loaders' +import { router } from 'kea-router' import api from 'lib/api' -import { SavedMetric } from './savedMetricLogic' +import { SavedMetric } from './savedMetricLogic' import type { savedMetricsLogicType } from './savedMetricsLogicType' export enum SavedMetricsTabs { @@ -19,7 +18,7 @@ export const savedMetricsLogic = kea([ setSavedMetricsTab: (tabKey: SavedMetricsTabs) => ({ tabKey }), }), - loaders(({ values }) => ({ + loaders(() => ({ savedMetrics: { loadSavedMetrics: async () => { const response = await api.get('api/projects/@current/experiment_saved_metrics') @@ -35,8 +34,8 @@ export const savedMetricsLogic = kea([ }, ], }), - listeners(({ actions }) => ({ - setSavedMetricsTab: ({ tabKey }) => { + listeners(() => ({ + setSavedMetricsTab: () => { router.actions.push('/experiments/saved-metrics') }, })), diff --git a/frontend/src/scenes/experiments/experimentsLogic.ts b/frontend/src/scenes/experiments/experimentsLogic.ts index 13cc2627a8c25..9e07ce597e54e 100644 --- a/frontend/src/scenes/experiments/experimentsLogic.ts +++ b/frontend/src/scenes/experiments/experimentsLogic.ts @@ -1,14 +1,14 @@ import { LemonTagType } from '@posthog/lemon-ui' import Fuse from 'fuse.js' -import { actions, connect, events, kea, path, reducers, selectors, listeners } from 'kea' +import { actions, connect, events, kea, listeners, path, reducers, selectors } from 'kea' import { loaders } from 'kea-loaders' +import { router } from 'kea-router' import api from 'lib/api' import { FEATURE_FLAGS } from 'lib/constants' import { lemonToast } from 'lib/lemon-ui/LemonToast/LemonToast' import { featureFlagLogic, FeatureFlagsSet } from 'lib/logic/featureFlagLogic' import { projectLogic } from 'scenes/projectLogic' import { userLogic } from 'scenes/userLogic' -import { router } from 'kea-router' import { Experiment, ExperimentsTabs, ProgressStatus } from '~/types' @@ -74,7 +74,7 @@ export const experimentsLogic = kea([ }, ], }), - listeners(({ actions }) => ({ + listeners(() => ({ setExperimentsTab: ({ tabKey }) => { if (tabKey === ExperimentsTabs.SavedMetrics) { router.actions.push('/experiments/saved-metrics') @@ -160,12 +160,9 @@ export const experimentsLogic = kea([ (featureFlags: FeatureFlagsSet) => featureFlags[FEATURE_FLAGS.WEB_EXPERIMENTS], ], })), - events(({ actions, values }) => ({ + events(({ actions }) => ({ afterMount: () => { actions.loadExperiments() - // if (values.location.pathname === '/experiments/saved-metrics') { - // actions.setExperimentsTab(ExperimentsTabs.SavedMetrics) - // } }, })), ]) diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 4b218bd90f0f9..672a09c5ed154 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -702,6 +702,7 @@ export enum ExperimentsTabs { Yours = 'yours', Archived = 'archived', Holdouts = 'holdouts', + SavedMetrics = 'saved-metrics', } export enum ActivityTab {