Skip to content

Commit

Permalink
camel case retention filter
Browse files Browse the repository at this point in the history
  • Loading branch information
thmsobrmlr committed Jan 16, 2024
1 parent 122d011 commit 67c6f68
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 57 deletions.
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 @@ -627,15 +627,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 @@ -289,11 +289,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
12 changes: 12 additions & 0 deletions frontend/src/queries/nodes/InsightQuery/utils/queryNodeToFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
LifecycleFilterLegacy,
NodeKind,
PathsFilterLegacy,
RetentionFilterLegacy,
StickinessFilterLegacy,
TrendsFilterLegacy,
} from '~/queries/schema'
Expand Down Expand Up @@ -214,6 +215,17 @@ export const queryNodeToFilter = (query: InsightQueryNode): Partial<FilterType>
delete insightFilter.maxEdgeWeight
delete insightFilter.funnelPaths
delete insightFilter.funnelFilter
} else if (isRetentionQuery(query)) {
;(legacyProps as RetentionFilterLegacy).retention_reference = insightFilter.retentionReference
;(legacyProps as RetentionFilterLegacy).retention_type = insightFilter.retentionType
;(legacyProps as RetentionFilterLegacy).returning_entity = insightFilter.returningEntity
;(legacyProps as RetentionFilterLegacy).target_entity = insightFilter.targetEntity
;(legacyProps as RetentionFilterLegacy).total_intervals = insightFilter.totalIntervals
delete insightFilter.retentionReference
delete insightFilter.retentionType
delete insightFilter.returningEntity
delete insightFilter.targetEntity
delete insightFilter.totalIntervals
}
Object.assign(filters, insightFilter)
Object.assign(filters, legacyProps)
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 @@ -569,7 +569,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
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
10 changes: 5 additions & 5 deletions frontend/src/scenes/insights/summarizeInsight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,17 +250,17 @@ export function summarizeInsightQuery(query: InsightQueryNode, context: SummaryC
return summary
} else if (isRetentionQuery(query)) {
const areTargetAndReturningIdentical =
query.retentionFilter?.returning_entity?.id === query.retentionFilter?.target_entity?.id &&
query.retentionFilter?.returning_entity?.type === query.retentionFilter?.target_entity?.type
query.retentionFilter?.returningEntity?.id === query.retentionFilter?.targetEntity?.id &&
query.retentionFilter?.returningEntity?.type === query.retentionFilter?.targetEntity?.type
return (
`Retention of ${context.aggregationLabel(query.aggregation_group_type_index, true).plural}` +
` based on doing ${getDisplayNameFromEntityFilter(
(query.retentionFilter?.target_entity || {}) as EntityFilter
(query.retentionFilter?.targetEntity || {}) as EntityFilter
)}` +
` ${retentionOptions[query.retentionFilter?.retention_type || RETENTION_FIRST_TIME]} and returning with ` +
` ${retentionOptions[query.retentionFilter?.retentionType || RETENTION_FIRST_TIME]} and returning with ` +
(areTargetAndReturningIdentical
? 'the same event'
: getDisplayNameFromEntityFilter((query.retentionFilter?.returning_entity || {}) as EntityFilter))
: getDisplayNameFromEntityFilter((query.retentionFilter?.returningEntity || {}) as EntityFilter))
)
} else if (isPathsQuery(query)) {
// Sync format with PathsSummary in InsightDetails
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/scenes/notebooks/Notebook/SlashCommands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,18 @@ const SLASH_COMMANDS: SlashCommandsItem[] = [
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
6 changes: 3 additions & 3 deletions frontend/src/scenes/web-analytics/webAnalyticsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -773,9 +773,9 @@ export const webAnalyticsLogic = kea<webAnalyticsLogicType>([
dateRange,
filterTestAccounts: true,
retentionFilter: {
retention_type: RETENTION_FIRST_TIME,
retention_reference: 'total',
total_intervals: isGreaterThanMd ? 8 : 5,
retentionType: RETENTION_FIRST_TIME,
retentionReference: 'total',
totalIntervals: isGreaterThanMd ? 8 : 5,
period: RetentionPeriod.Week,
},
},
Expand Down
10 changes: 5 additions & 5 deletions posthog/hogql_queries/legacy_compatibility/filter_to_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,13 +358,13 @@ def _insight_filter(filter: Dict):
elif _insight_type(filter) == "RETENTION":
insight_filter = {
"retentionFilter": RetentionFilter(
retention_type=filter.get("retention_type"),
retention_reference=filter.get("retention_reference"),
total_intervals=filter.get("total_intervals"),
returning_entity=to_base_entity_dict(filter.get("returning_entity"))
retentionType=filter.get("retention_type"),
retentionReference=filter.get("retention_reference"),
totalIntervals=filter.get("total_intervals"),
returningEntity=to_base_entity_dict(filter.get("returning_entity"))
if filter.get("returning_entity") is not None
else None,
target_entity=to_base_entity_dict(filter.get("target_entity"))
targetEntity=to_base_entity_dict(filter.get("target_entity"))
if filter.get("target_entity") is not None
else None,
period=filter.get("period"),
Expand Down
12 changes: 12 additions & 0 deletions posthog/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,18 @@ class QueryResponseAlternative11(BaseModel):


class RetentionFilter(BaseModel):
model_config = ConfigDict(
extra="forbid",
)
period: Optional[RetentionPeriod] = None
retentionReference: Optional[RetentionReference] = None
retentionType: Optional[RetentionType] = None
returningEntity: Optional[RetentionEntity] = None
targetEntity: Optional[RetentionEntity] = None
totalIntervals: Optional[int] = None


class RetentionFilterLegacy(BaseModel):
model_config = ConfigDict(
extra="forbid",
)
Expand Down

0 comments on commit 67c6f68

Please sign in to comment.