Skip to content

Commit

Permalink
feat(data-warehouse): make separate property type in taxonomic filter…
Browse files Browse the repository at this point in the history
… for data warehouse person properties (#21169)

* make separate property type in popup

* add flag

* change type

* use separate filter type

* add types

* more types

* more typing

* more types

* restore
  • Loading branch information
EDsCODE authored Apr 2, 2024
1 parent ea8ebb3 commit d9da73e
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 6 deletions.
5 changes: 5 additions & 0 deletions frontend/src/lib/components/PropertyFilters/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export const PROPERTY_FILTER_TYPE_TO_TAXONOMIC_FILTER_GROUP_TYPE: Omit<
[PropertyFilterType.HogQL]: TaxonomicFilterGroupType.HogQLExpression,
[PropertyFilterType.Group]: TaxonomicFilterGroupType.GroupsPrefix,
[PropertyFilterType.DataWarehouse]: TaxonomicFilterGroupType.DataWarehouse,
[PropertyFilterType.DataWarehousePersonProperty]: TaxonomicFilterGroupType.DataWarehousePersonProperties,
}

export function formatPropertyLabel(
Expand Down Expand Up @@ -332,6 +333,10 @@ export function taxonomicFilterTypeToPropertyFilterType(
return PropertyFilterType.DataWarehouse
}

if (filterType == TaxonomicFilterGroupType.DataWarehousePersonProperties) {
return PropertyFilterType.DataWarehousePersonProperty
}

return Object.entries(propertyFilterMapping).find(([, v]) => v === filterType)?.[0] as
| PropertyFilterType
| undefined
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/lib/components/TaxonomicFilter/InfiniteList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ export function InfiniteList({ popupAnchorElement }: InfiniteListProps): JSX.Ele
<div
{...commonDivProps}
data-attr={`prop-filter-${listGroupType}-${rowIndex}`}
onClick={() => canSelectItem(listGroupType) && selectItem(group, itemValue ?? null, item)}
onClick={() => {
return canSelectItem(listGroupType) && selectItem(group, itemValue ?? null, item)
}}
>
{renderItemContents({
item,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { IconCohort } from 'lib/lemon-ui/icons'
import { CORE_FILTER_DEFINITIONS_BY_GROUP } from 'lib/taxonomy'
import { capitalizeFirstLetter, pluralize, toParams } from 'lib/utils'
import { getEventDefinitionIcon, getPropertyDefinitionIcon } from 'scenes/data-management/events/DefinitionHeader'
import { dataWarehouseJoinsLogic } from 'scenes/data-warehouse/external/dataWarehouseJoinsLogic'
import { dataWarehouseSceneLogic } from 'scenes/data-warehouse/external/dataWarehouseSceneLogic'
import { DataWarehouseTableType } from 'scenes/data-warehouse/types'
import { experimentsLogic } from 'scenes/experiments/experimentsLogic'
Expand Down Expand Up @@ -86,6 +87,8 @@ export const taxonomicFilterLogic = kea<taxonomicFilterLogicType>([
['allGroupProperties'],
dataWarehouseSceneLogic,
['externalTables'],
dataWarehouseJoinsLogic,
['columnsJoinedToPersons'],
],
}),
actions(() => ({
Expand Down Expand Up @@ -225,6 +228,16 @@ export const taxonomicFilterLogic = kea<taxonomicFilterLogicType>([
getPopoverHeader: () => 'Data Warehouse Column',
getIcon: () => <IconServer />,
},
{
name: 'Data Warehouse Person Properties',
searchPlaceholder: 'person properties from data warehouse tables',
type: TaxonomicFilterGroupType.DataWarehousePersonProperties,
logic: dataWarehouseJoinsLogic,
value: 'columnsJoinedToPersons',
getName: (personProperty: PersonProperty) => personProperty.name,
getValue: (personProperty: PersonProperty) => personProperty.id,
getPopoverHeader: () => 'Data Warehouse Person Property',
},
{
name: 'Autocapture elements',
searchPlaceholder: 'autocapture elements',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/components/TaxonomicFilter/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export enum TaxonomicFilterGroupType {
CohortsWithAllUsers = 'cohorts_with_all',
DataWarehouse = 'data_warehouse',
DataWarehouseProperties = 'data_warehouse_properties',
DataWarehousePersonProperties = 'data_warehouse_person_properties',
Elements = 'elements',
Events = 'events',
EventProperties = 'event_properties',
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/queries/nodes/InsightViz/GlobalAndOrFilters.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useActions, useValues } from 'kea'
import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types'
import { FEATURE_FLAGS } from 'lib/constants'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { insightVizDataLogic } from 'scenes/insights/insightVizDataLogic'
import { keyForInsightLogicProps } from 'scenes/insights/sharedUtils'

Expand All @@ -16,6 +18,7 @@ export function GlobalAndOrFilters({ insightProps }: EditorFilterProps): JSX.Ele
const { groupsTaxonomicTypes } = useValues(groupsModel)
const { isTrends, querySource, isDataWarehouseSeries } = useValues(insightVizDataLogic(insightProps))
const { updateQuerySource } = useActions(insightVizDataLogic(insightProps))
const { featureFlags } = useValues(featureFlagLogic)

const taxonomicGroupTypes = [
TaxonomicFilterGroupType.EventProperties,
Expand All @@ -26,6 +29,9 @@ export function GlobalAndOrFilters({ insightProps }: EditorFilterProps): JSX.Ele
TaxonomicFilterGroupType.Elements,
...(isTrends ? [TaxonomicFilterGroupType.Sessions] : []),
TaxonomicFilterGroupType.HogQLExpression,
...(featureFlags[FEATURE_FLAGS.DATA_WAREHOUSE] && featureFlags[FEATURE_FLAGS.HOGQL_INSIGHTS]
? [TaxonomicFilterGroupType.DataWarehousePersonProperties]
: []),
]

return (
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/queries/nodes/InsightViz/TrendsSeries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export function TrendsSeries(): JSX.Element | null {
...(isTrends ? [TaxonomicFilterGroupType.Sessions] : []),
TaxonomicFilterGroupType.HogQLExpression,
TaxonomicFilterGroupType.DataWarehouseProperties,
...(featureFlags[FEATURE_FLAGS.DATA_WAREHOUSE] && featureFlags[FEATURE_FLAGS.HOGQL_INSIGHTS]
? [TaxonomicFilterGroupType.DataWarehousePersonProperties]
: []),
]

if (!isInsightQueryNode(querySource)) {
Expand Down
29 changes: 28 additions & 1 deletion frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@
},
{
"$ref": "#/definitions/DataWarehousePropertyFilter"
},
{
"$ref": "#/definitions/DataWarehousePersonPropertyFilter"
}
]
},
Expand Down Expand Up @@ -862,6 +865,29 @@
"required": ["distinct_id_field", "id", "id_field", "kind", "table_name", "timestamp_field"],
"type": "object"
},
"DataWarehousePersonPropertyFilter": {
"additionalProperties": false,
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"operator": {
"$ref": "#/definitions/PropertyOperator"
},
"type": {
"const": "data_warehouse_person_property",
"type": "string"
},
"value": {
"$ref": "#/definitions/PropertyFilterValue"
}
},
"required": ["key", "operator", "type"],
"type": "object"
},
"DataWarehousePropertyFilter": {
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -3528,7 +3554,8 @@
"recording",
"group",
"hogql",
"data_warehouse"
"data_warehouse",
"data_warehouse_person_property"
],
"type": "string"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { afterMount, kea, path } from 'kea'
import { afterMount, connect, kea, path, selectors } from 'kea'
import { loaders } from 'kea-loaders'
import api from 'lib/api'
import { capitalizeFirstLetter } from 'lib/utils'

import { DataWarehouseViewLink } from '~/types'
import { DatabaseSchemaQueryResponseField } from '~/queries/schema'
import { DataWarehouseViewLink, PropertyDefinition, PropertyType } from '~/types'

import type { dataWarehouseJoinsLogicType } from './dataWarehouseJoinsLogicType'
import { dataWarehouseSceneLogic } from './dataWarehouseSceneLogic'

export const dataWarehouseJoinsLogic = kea<dataWarehouseJoinsLogicType>([
path(['scenes', 'data-warehouse', 'external', 'dataWarehouseJoinsLogic']),
Expand All @@ -19,6 +22,43 @@ export const dataWarehouseJoinsLogic = kea<dataWarehouseJoinsLogicType>([
},
],
}),
connect(() => ({
values: [dataWarehouseSceneLogic, ['externalTablesMap']],
})),
selectors({
personTableJoins: [(s) => [s.joins], (joins) => joins.filter((join) => join.source_table_name === 'persons')],
tablesJoinedToPersons: [
(s) => [s.externalTablesMap, s.personTableJoins],
(externalTablesMap, personTableJoins) => {
return personTableJoins.map((join: DataWarehouseViewLink) => {
// valid join should have a joining table name
const table = externalTablesMap[join.joining_table_name as string]
return {
table,
join,
}
})
},
],
columnsJoinedToPersons: [
(s) => [s.tablesJoinedToPersons],
(tablesJoinedToPersons) => {
return tablesJoinedToPersons.reduce((acc, { table, join }) => {
if (table) {
acc.push(
...table.columns.map((column: DatabaseSchemaQueryResponseField) => ({
id: join.field_name + ': ' + column.key,
name: join.field_name + ': ' + column.key,
table: join.field_name,
property_type: capitalizeFirstLetter(column.type) as PropertyType,
}))
)
}
return acc
}, [] as PropertyDefinition[])
},
],
}),
afterMount(({ actions }) => {
actions.loadJoins()
}),
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ export enum PropertyFilterType {
Group = 'group',
HogQL = 'hogql',
DataWarehouse = 'data_warehouse',
DataWarehousePersonProperty = 'data_warehouse_person_property',
}

/** Sync with plugin-server/src/types.ts */
Expand Down Expand Up @@ -679,6 +680,11 @@ export interface DataWarehousePropertyFilter extends BasePropertyFilter {
operator: PropertyOperator
}

export interface DataWarehousePersonPropertyFilter extends BasePropertyFilter {
type: PropertyFilterType.DataWarehousePersonProperty
operator: PropertyOperator
}

/** Sync with plugin-server/src/types.ts */
export interface ElementPropertyFilter extends BasePropertyFilter {
type: PropertyFilterType.Element
Expand Down Expand Up @@ -735,6 +741,7 @@ export type AnyPropertyFilter =
| HogQLPropertyFilter
| EmptyPropertyFilter
| DataWarehousePropertyFilter
| DataWarehousePersonPropertyFilter

export type AnyFilterLike = AnyPropertyFilter | PropertyGroupFilter | PropertyGroupFilterValue

Expand Down
16 changes: 15 additions & 1 deletion plugin-server/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,14 @@ export interface PersonPropertyFilter extends PropertyFilterWithOperator {
type: 'person'
}

export interface DataWarehousePropertyFilter extends PropertyFilterWithOperator {
type: 'data_warehouse'
}

export interface DataWarehousePersonPropertyFilter extends PropertyFilterWithOperator {
type: 'data_warehouse_person_property'
}

/** Sync with posthog/frontend/src/types.ts */
export interface ElementPropertyFilter extends PropertyFilterWithOperator {
type: 'element'
Expand All @@ -890,7 +898,13 @@ export interface CohortPropertyFilter extends PropertyFilterBase {
}

/** Sync with posthog/frontend/src/types.ts */
export type PropertyFilter = EventPropertyFilter | PersonPropertyFilter | ElementPropertyFilter | CohortPropertyFilter
export type PropertyFilter =
| EventPropertyFilter
| PersonPropertyFilter
| ElementPropertyFilter
| CohortPropertyFilter
| DataWarehousePropertyFilter
| DataWarehousePersonPropertyFilter

/** Sync with posthog/frontend/src/types.ts */
export enum StringMatching {
Expand Down
8 changes: 7 additions & 1 deletion posthog/hogql/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def property_to_expr(
or property.type == "person"
or property.type == "group"
or property.type == "data_warehouse"
or property.type == "data_warehouse_person_property"
or property.type == "session"
):
if scope == "person" and property.type != "person":
Expand All @@ -146,9 +147,14 @@ def property_to_expr(
)
operator = cast(Optional[PropertyOperator], property.operator) or PropertyOperator.exact
value = property.value

if property.type == "person" and scope != "person":
chain = ["person", "properties"]
elif property.type == "data_warehouse_person_property":
if isinstance(property.value, str):
table, value = property.value.split(": ")
chain = ["person", table]
else:
raise NotImplementedException("Data warehouse person property filter value must be a string")
elif property.type == "group":
chain = [f"group_{property.group_type_index}", "properties"]
elif property.type == "data_warehouse":
Expand Down
1 change: 1 addition & 0 deletions posthog/models/property/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class BehavioralPropertyType(str, Enum):
"session",
"hogql",
"data_warehouse",
"data_warehouse_person_property",
]

PropertyName = str
Expand Down
Loading

0 comments on commit d9da73e

Please sign in to comment.