Skip to content

Commit

Permalink
chore(query-nodes): camel case retention filter (#19800)
Browse files Browse the repository at this point in the history
  • Loading branch information
thmsobrmlr authored Jan 19, 2024
1 parent f05329d commit bbfebce
Show file tree
Hide file tree
Showing 22 changed files with 190 additions and 130 deletions.
4 changes: 2 additions & 2 deletions frontend/src/queries/examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ const InsightRetentionQuery: RetentionQuery = {
filterTestAccounts,
retentionFilter: {
// TODO: this should be typed as (EventsNode | ActionsNode)[] without math and properties
target_entity: { type: 'events', id: '$pageview', name: '$pageview' },
returning_entity: { type: 'events', id: '$pageview', name: '$pageview' },
targetEntity: { type: 'events', id: '$pageview', name: '$pageview' },
returningEntity: { type: 'events', id: '$pageview', name: '$pageview' },
},
}

Expand Down
8 changes: 4 additions & 4 deletions frontend/src/queries/nodes/InsightQuery/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ const retentionQueryDefault: RetentionQuery = {
kind: NodeKind.RetentionQuery,
retentionFilter: {
period: RetentionPeriod.Day,
total_intervals: 11,
target_entity: {
totalIntervals: 11,
targetEntity: {
id: '$pageview',
name: '$pageview',
type: 'events',
},
returning_entity: {
returningEntity: {
id: '$pageview',
name: '$pageview',
type: 'events',
},
retention_type: 'retention_first_time',
retentionType: 'retention_first_time',
},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,11 +423,11 @@ describe('filtersToQueryNode', () => {
const query: RetentionQuery = {
kind: NodeKind.RetentionQuery,
retentionFilter: {
retention_type: 'retention_first_time',
retention_reference: 'total',
total_intervals: 2,
returning_entity: { id: '1' },
target_entity: { id: '1' },
retentionType: 'retention_first_time',
retentionReference: 'total',
totalIntervals: 2,
returningEntity: { id: '1' },
targetEntity: { id: '1' },
period: RetentionPeriod.Day,
},
}
Expand Down Expand Up @@ -674,15 +674,15 @@ describe('filtersToQueryNode', () => {
},
retentionFilter: {
period: RetentionPeriod.Week,
target_entity: {
targetEntity: {
id: 'signed_up',
name: 'signed_up',
type: 'events',
order: 0,
},
retention_type: 'retention_first_time',
total_intervals: 9,
returning_entity: {
retentionType: 'retention_first_time',
totalIntervals: 9,
returningEntity: {
id: 1,
name: 'Interacted with file',
type: 'actions',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,11 @@ export const filtersToQueryNode = (filters: Partial<FilterType>): InsightQueryNo
// retention filter
if (isRetentionFilter(filters) && isRetentionQuery(query)) {
query.retentionFilter = objectCleanWithEmpty({
retention_type: filters.retention_type,
retention_reference: filters.retention_reference,
total_intervals: filters.total_intervals,
returning_entity: filters.returning_entity,
target_entity: filters.target_entity,
retentionType: filters.retention_type,
retentionReference: filters.retention_reference,
totalIntervals: filters.total_intervals,
returningEntity: filters.returning_entity,
targetEntity: filters.target_entity,
period: filters.period,
})
// TODO: query.aggregation_group_type_index
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/queries/nodes/InsightQuery/utils/queryNodeToFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
LifecycleFilterLegacy,
NodeKind,
PathsFilterLegacy,
RetentionFilterLegacy,
StickinessFilterLegacy,
TrendsFilterLegacy,
} from '~/queries/schema'
Expand Down Expand Up @@ -154,6 +155,7 @@ export const queryNodeToFilter = (query: InsightQueryNode): Partial<FilterType>

// replace camel cased props with the snake cased variant
const camelCasedTrendsProps: TrendsFilterLegacy = {}
const camelCasedRetentionProps: RetentionFilterLegacy = {}
const camelCasedPathsProps: PathsFilterLegacy = {}
const camelCasedStickinessProps: StickinessFilterLegacy = {}
const camelCasedLifecycleProps: LifecycleFilterLegacy = {}
Expand All @@ -176,6 +178,17 @@ export const queryNodeToFilter = (query: InsightQueryNode): Partial<FilterType>
delete queryCopy.trendsFilter?.showPercentStackView
delete queryCopy.trendsFilter?.showLegend
delete queryCopy.trendsFilter?.showValuesOnSeries
} else if (isRetentionQuery(queryCopy)) {
camelCasedRetentionProps.retention_reference = queryCopy.retentionFilter?.retentionReference
camelCasedRetentionProps.retention_type = queryCopy.retentionFilter?.retentionType
camelCasedRetentionProps.returning_entity = queryCopy.retentionFilter?.returningEntity
camelCasedRetentionProps.target_entity = queryCopy.retentionFilter?.targetEntity
camelCasedRetentionProps.total_intervals = queryCopy.retentionFilter?.totalIntervals
delete queryCopy.retentionFilter?.retentionReference
delete queryCopy.retentionFilter?.retentionType
delete queryCopy.retentionFilter?.returningEntity
delete queryCopy.retentionFilter?.targetEntity
delete queryCopy.retentionFilter?.totalIntervals
} else if (isPathsQuery(queryCopy)) {
camelCasedPathsProps.edge_limit = queryCopy.pathsFilter?.edgeLimit
camelCasedPathsProps.paths_hogql_expression = queryCopy.pathsFilter?.pathsHogQLExpression
Expand Down Expand Up @@ -215,6 +228,7 @@ export const queryNodeToFilter = (query: InsightQueryNode): Partial<FilterType>
delete queryCopy.lifecycleFilter?.showValuesOnSeries
}
Object.assign(filters, camelCasedTrendsProps)
Object.assign(filters, camelCasedRetentionProps)
Object.assign(filters, camelCasedPathsProps)
Object.assign(filters, camelCasedStickinessProps)
Object.assign(filters, camelCasedLifecycleProps)
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3227,6 +3227,31 @@
"type": "object"
},
"RetentionFilter": {
"additionalProperties": false,
"properties": {
"period": {
"$ref": "#/definitions/RetentionPeriod"
},
"retentionReference": {
"enum": ["total", "previous"],
"type": "string"
},
"retentionType": {
"$ref": "#/definitions/RetentionType"
},
"returningEntity": {
"$ref": "#/definitions/RetentionEntity"
},
"targetEntity": {
"$ref": "#/definitions/RetentionEntity"
},
"totalIntervals": {
"type": "integer"
}
},
"type": "object"
},
"RetentionFilterLegacy": {
"additionalProperties": false,
"description": "`RetentionFilterType` minus everything inherited from `FilterType`",
"properties": {
Expand Down
11 changes: 10 additions & 1 deletion frontend/src/queries/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,16 @@ export interface FunnelsQuery extends InsightsQueryBase {
}

/** `RetentionFilterType` minus everything inherited from `FilterType` */
export type RetentionFilter = Omit<RetentionFilterType, keyof FilterType>
export type RetentionFilterLegacy = Omit<RetentionFilterType, keyof FilterType>

export type RetentionFilter = {
retentionType?: RetentionFilterLegacy['retention_type']
retentionReference?: RetentionFilterLegacy['retention_reference']
totalIntervals?: RetentionFilterLegacy['total_intervals']
returningEntity?: RetentionFilterLegacy['returning_entity']
targetEntity?: RetentionFilterLegacy['target_entity']
period?: RetentionFilterLegacy['period']
}

export interface RetentionValue {
/** @asType integer */
Expand Down
30 changes: 15 additions & 15 deletions frontend/src/scenes/insights/EditorFilters/RetentionSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function RetentionSummary({ insightProps }: EditorFilterProps): JSX.Eleme
const { showGroupsOptions } = useValues(groupsModel)
const { retentionFilter } = useValues(insightVizDataLogic(insightProps))
const { updateInsightFilter } = useActions(insightVizDataLogic(insightProps))
const { target_entity, returning_entity, retention_type, total_intervals, period } = retentionFilter || {}
const { targetEntity, returningEntity, retentionType, totalIntervals, period } = retentionFilter || {}

return (
<div className="space-y-2" data-attr="retention-summary">
Expand All @@ -45,17 +45,17 @@ export function RetentionSummary({ insightProps }: EditorFilterProps): JSX.Eleme
hideFilter
hideRename
buttonCopy="Add graph series"
filters={{ events: [target_entity] } as FilterType} // retention filters use target and returning entity instead of events
filters={{ events: [targetEntity] } as FilterType} // retention filters use target and returning entity instead of events
setFilters={(newFilters: FilterType) => {
if (newFilters.events && newFilters.events.length > 0) {
updateInsightFilter({ target_entity: newFilters.events[0] })
updateInsightFilter({ targetEntity: newFilters.events[0] })
} else if (newFilters.actions && newFilters.actions.length > 0) {
updateInsightFilter({ target_entity: newFilters.actions[0] })
updateInsightFilter({ targetEntity: newFilters.actions[0] })
} else {
updateInsightFilter({ target_entity: undefined })
updateInsightFilter({ targetEntity: undefined })
}
}}
typeKey={`${keyForInsightLogicProps('new')(insightProps)}-target_entity`}
typeKey={`${keyForInsightLogicProps('new')(insightProps)}-targetEntity`}
/>
</span>
<LemonSelect
Expand All @@ -71,8 +71,8 @@ export function RetentionSummary({ insightProps }: EditorFilterProps): JSX.Eleme
</>
),
}))}
value={retention_type ? retentionOptions[retention_type] : undefined}
onChange={(value): void => updateInsightFilter({ retention_type: value as RetentionType })}
value={retentionType ? retentionOptions[retentionType] : undefined}
onChange={(value): void => updateInsightFilter({ retentionType: value as RetentionType })}
dropdownMatchSelectWidth={false}
/>
</div>
Expand All @@ -81,8 +81,8 @@ export function RetentionSummary({ insightProps }: EditorFilterProps): JSX.Eleme
<LemonInput
type="number"
className="ml-2 w-20"
value={(total_intervals ?? 11) - 1}
onChange={(value) => updateInsightFilter({ total_intervals: (value || 0) + 1 })}
value={(totalIntervals ?? 11) - 1}
onChange={(value) => updateInsightFilter({ totalIntervals: (value || 0) + 1 })}
/>
<LemonSelect
className="mx-2"
Expand All @@ -105,17 +105,17 @@ export function RetentionSummary({ insightProps }: EditorFilterProps): JSX.Eleme
hideFilter
hideRename
buttonCopy="Add graph series"
filters={{ events: [returning_entity] } as FilterType}
filters={{ events: [returningEntity] } as FilterType}
setFilters={(newFilters: FilterType) => {
if (newFilters.events && newFilters.events.length > 0) {
updateInsightFilter({ returning_entity: newFilters.events[0] })
updateInsightFilter({ returningEntity: newFilters.events[0] })
} else if (newFilters.actions && newFilters.actions.length > 0) {
updateInsightFilter({ returning_entity: newFilters.actions[0] })
updateInsightFilter({ returningEntity: newFilters.actions[0] })
} else {
updateInsightFilter({ returning_entity: undefined })
updateInsightFilter({ returningEntity: undefined })
}
}}
typeKey={`${keyForInsightLogicProps('new')(insightProps)}-returning_entity`}
typeKey={`${keyForInsightLogicProps('new')(insightProps)}-returningEntity`}
/>
</span>
on any of the next {dateOptionPlurals[period ?? 'Day']}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,12 @@ describe('insightNavLogic', () => {
// source: {
// kind: NodeKind.RetentionQuery,
// retentionFilter: {
// returning_entity: {
// returningEntity: {
// id: 'returning',
// name: 'returning',
// type: 'events',
// },
// target_entity: {
// targetEntity: {
// id: 'target',
// name: 'target',
// type: 'events',
Expand Down
24 changes: 12 additions & 12 deletions frontend/src/scenes/insights/InsightNav/insightNavLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,15 +258,15 @@ const cachePropertiesFromQuery = (query: InsightQueryNode, cache: QueryPropertyC

// // set series (first two entries) from retention target and returning entity
// if (isRetentionQuery(query)) {
// const { target_entity, returning_entity } = query.retentionFilter || {}
// const { targetEntity, returningEntity } = query.retentionFilter || {}
// const series = actionsAndEventsToSeries({
// events: [
// ...(target_entity?.type === 'events' ? [target_entity as ActionFilter] : []),
// ...(returning_entity?.type === 'events' ? [returning_entity as ActionFilter] : []),
// ...(targetEntity?.type === 'events' ? [targetEntity as ActionFilter] : []),
// ...(returningEntity?.type === 'events' ? [returningEntity as ActionFilter] : []),
// ],
// actions: [
// ...(target_entity?.type === 'actions' ? [target_entity as ActionFilter] : []),
// ...(returning_entity?.type === 'actions' ? [returning_entity as ActionFilter] : []),
// ...(targetEntity?.type === 'actions' ? [targetEntity as ActionFilter] : []),
// ...(returningEntity?.type === 'actions' ? [returningEntity as ActionFilter] : []),
// ],
// })
// if (series.length > 0) {
Expand Down Expand Up @@ -301,21 +301,21 @@ const mergeCachedProperties = (query: InsightQueryNode, cache: QueryPropertyCach
} else {
mergedQuery.series = cache.series
}
} else if (cache.retentionFilter?.target_entity || cache.retentionFilter?.returning_entity) {
} else if (cache.retentionFilter?.targetEntity || cache.retentionFilter?.returningEntity) {
mergedQuery.series = [
...(cache.retentionFilter.target_entity
? [cache.retentionFilter.target_entity as EventsNode | ActionsNode]
...(cache.retentionFilter.targetEntity
? [cache.retentionFilter.targetEntity as EventsNode | ActionsNode]
: []),
...(cache.retentionFilter.returning_entity
? [cache.retentionFilter.returning_entity as EventsNode | ActionsNode]
...(cache.retentionFilter.returningEntity
? [cache.retentionFilter.returningEntity as EventsNode | ActionsNode]
: []),
]
}
} else if (isRetentionQuery(mergedQuery) && cache.series) {
mergedQuery.retentionFilter = {
...mergedQuery.retentionFilter,
...(cache.series.length > 0 ? { target_entity: cache.series[0] } : {}),
...(cache.series.length > 1 ? { returning_entity: cache.series[1] } : {}),
...(cache.series.length > 0 ? { targetEntity: cache.series[0] } : {}),
...(cache.series.length > 1 ? { returningEntity: cache.series[1] } : {}),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ export function RetentionReferencePicker(): JSX.Element {
const { retentionFilter } = useValues(insightVizDataLogic(insightProps))
const { updateInsightFilter } = useActions(insightVizDataLogic(insightProps))

const { retention_reference } = retentionFilter || {}
const { retentionReference } = retentionFilter || {}

return (
<LemonSelect
className="w-60"
size="small"
value={retention_reference || 'total'}
onChange={(retention_reference) => {
updateInsightFilter({ retention_reference })
value={retentionReference || 'total'}
onChange={(retentionReference) => {
updateInsightFilter({ retentionReference })
}}
options={[
{
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/scenes/insights/summarizeInsight.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -728,17 +728,17 @@ describe('summarizing insights', () => {
const query: RetentionQuery = {
kind: NodeKind.RetentionQuery,
retentionFilter: {
target_entity: {
targetEntity: {
id: '$autocapture',
name: '$autocapture',
type: 'events',
},
returning_entity: {
returningEntity: {
id: '$autocapture',
name: '$autocapture',
type: 'events',
},
retention_type: RETENTION_FIRST_TIME,
retentionType: RETENTION_FIRST_TIME,
},
}

Expand All @@ -757,17 +757,17 @@ describe('summarizing insights', () => {
const query: RetentionQuery = {
kind: NodeKind.RetentionQuery,
retentionFilter: {
target_entity: {
targetEntity: {
id: 'purchase',
name: 'purchase',
type: 'events',
},
returning_entity: {
returningEntity: {
id: '$pageview',
name: '$pageview',
type: 'events',
},
retention_type: RETENTION_RECURRING,
retentionType: RETENTION_RECURRING,
},
aggregation_group_type_index: 0,
}
Expand Down
Loading

0 comments on commit bbfebce

Please sign in to comment.