Skip to content

Commit

Permalink
feat(bi): Adds support for list type variables in BI (#25651)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
Gilbert09 and github-actions[bot] authored Oct 18, 2024
1 parent 2ca6df5 commit c6ca943
Show file tree
Hide file tree
Showing 15 changed files with 109 additions and 24 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 6 additions & 11 deletions frontend/src/queries/Query/Query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export function Query<Q extends Node>(props: QueryProps<Q>): JSX.Element | null
}, [propsQuery])

const query = readOnly ? propsQuery : localQuery
const setQuery = readOnly ? undefined : propsSetQuery ?? localSetQuery
const setQuery = propsSetQuery ?? localSetQuery

const queryContext = props.context || {}

Expand All @@ -98,17 +98,18 @@ export function Query<Q extends Node>(props: QueryProps<Q>): JSX.Element | null
component = (
<DataTable
query={query}
setQuery={setQuery as ((query: DataTableNode) => void) | undefined}
setQuery={setQuery as unknown as (query: DataTableNode) => void}
context={queryContext}
cachedResults={props.cachedResults}
uniqueKey={uniqueKey}
readOnly={readOnly}
/>
)
} else if (isDataVisualizationNode(query)) {
component = (
<DataTableVisualization
query={query}
setQuery={setQuery as ((query: DataVisualizationNode) => void) | undefined}
setQuery={setQuery as unknown as (query: DataVisualizationNode) => void}
cachedResults={props.cachedResults}
uniqueKey={uniqueKey}
context={queryContext}
Expand All @@ -122,7 +123,7 @@ export function Query<Q extends Node>(props: QueryProps<Q>): JSX.Element | null
component = (
<InsightViz
query={query}
setQuery={setQuery as ((query: InsightVizNode) => void) | undefined}
setQuery={setQuery as unknown as (query: InsightVizNode) => void}
context={queryContext}
readOnly={readOnly}
uniqueKey={uniqueKey}
Expand All @@ -135,13 +136,7 @@ export function Query<Q extends Node>(props: QueryProps<Q>): JSX.Element | null
} else if (isWebOverviewQuery(query)) {
component = <WebOverview query={query} cachedResults={props.cachedResults} context={queryContext} />
} else if (isHogQuery(query)) {
component = (
<HogDebug
query={query}
setQuery={setQuery as undefined | ((query: any) => void)}
queryKey={String(uniqueKey)}
/>
)
component = <HogDebug query={query} setQuery={setQuery as (query: any) => void} queryKey={String(uniqueKey)} />
} else {
component = <DataNode query={query} cachedResults={props.cachedResults} />
}
Expand Down
14 changes: 11 additions & 3 deletions frontend/src/queries/nodes/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ import { DataTableOpenEditor } from './DataTableOpenEditor'
interface DataTableProps {
uniqueKey?: string | number
query: DataTableNode
setQuery?: (query: DataTableNode) => void
setQuery: (query: DataTableNode) => void
/** Custom table columns */
context?: QueryContext<DataTableNode>
/* Cached Results are provided when shared or exported,
the data node logic becomes read only implicitly */
cachedResults?: AnyResponseType
// Override the data logic node key if needed
dataNodeLogicKey?: string
readOnly?: boolean
}

const eventGroupTypes = [
Expand All @@ -88,7 +89,14 @@ const personGroupTypes = [TaxonomicFilterGroupType.HogQLExpression, TaxonomicFil

let uniqueNode = 0

export function DataTable({ uniqueKey, query, setQuery, context, cachedResults }: DataTableProps): JSX.Element {
export function DataTable({
uniqueKey,
query,
setQuery,
context,
cachedResults,
readOnly,
}: DataTableProps): JSX.Element {
const [uniqueNodeKey] = useState(() => uniqueNode++)
const [dataKey] = useState(() => `DataNode.${uniqueKey || uniqueNodeKey}`)
const insightProps: InsightLogicProps<DataTableNode> = context?.insightProps || {
Expand Down Expand Up @@ -148,7 +156,7 @@ export function DataTable({ uniqueKey, query, setQuery, context, cachedResults }
showTimings,
} = queryWithDefaults

const isReadOnly = setQuery === undefined
const isReadOnly = !!readOnly

const eventActionsColumnShown =
showActions && sourceFeatures.has(QueryFeature.eventActionsColumn) && columnsInResponse?.includes('*')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './Variables.scss'

import { IconCopy, IconGear, IconTrash } from '@posthog/icons'
import { LemonButton, LemonDivider, LemonInput, LemonSegmentedButton, Popover } from '@posthog/lemon-ui'
import { LemonButton, LemonDivider, LemonInput, LemonSegmentedButton, LemonSelect, Popover } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { FEATURE_FLAGS } from 'lib/constants'
import { LemonField } from 'lib/lemon-ui/LemonField'
Expand Down Expand Up @@ -154,6 +154,14 @@ const VariableInput = ({
]}
/>
)}
{variable.type === 'List' && (
<LemonSelect
className="grow"
value={localInputValue}
onChange={(value) => setLocalInputValue(value)}
options={variable.values.map((n) => ({ label: n, value: n }))}
/>
)}
<LemonButton
type="primary"
onClick={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,11 @@ export const variablesLogic = kea<variablesLogicType>([
return
}

actions.setQuery(query)

if (props.readOnly) {
// Refresh the data manaully via dataNodeLogic when in insight view mode
actions.loadData(true, undefined, query.source)
} else {
// Update the query source when in edit mode
actions.setQuery(query)
}
},
})),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import { displayLogic } from './displayLogic'
interface DataTableVisualizationProps {
uniqueKey?: string | number
query: DataVisualizationNode
setQuery?: (query: DataVisualizationNode) => void
setQuery: (query: DataVisualizationNode) => void
context?: QueryContext<DataVisualizationNode>
/* Cached Results are provided when shared or exported,
the data node logic becomes read only implicitly */
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/queries/nodes/InsightViz/InsightViz.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const insightVizDataCollectionId = (props: InsightLogicProps<any> | undef
type InsightVizProps = {
uniqueKey?: string | number
query: InsightVizNode
setQuery?: (node: InsightVizNode) => void
setQuery: (node: InsightVizNode) => void
context?: QueryContext
readOnly?: boolean
embedded?: boolean
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/debug/HogDebug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export function HogQueryEditor(props: HogQueryEditorProps): JSX.Element {
interface HogDebugProps {
queryKey: string
query: HogQuery
setQuery?: (query: HogQuery) => void
setQuery: (query: HogQuery) => void
debug?: boolean
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/insights/Insight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function Insight({ insightId }: InsightSceneProps): JSX.Element {

<Query
query={isInsightVizNode(query) ? { ...query, full: true } : query}
setQuery={insightMode === ItemMode.Edit ? setQuery : undefined}
setQuery={setQuery}
readOnly={insightMode !== ItemMode.Edit}
context={{
showOpenEditorButton: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { actions, afterMount, connect, kea, path, props, reducers, selectors } from 'kea'
import { loaders } from 'kea-loaders'
import api from 'lib/api'
import { isObject } from 'lib/utils'
import { variantKeyToIndexFeatureFlagPayloads } from 'scenes/feature-flags/featureFlagLogic'
import { teamLogic } from 'scenes/teamLogic'

import { FeatureFlagBasicType } from '~/types'

import type { sessionReplayLinkedFlagLogicType } from './sessionReplayLinkedFlagLogicType'

export interface ReplayLinkedFlagLogicProps {
id: number | null
}

export const sessionReplayLinkedFlagLogic = kea<sessionReplayLinkedFlagLogicType>([
path(['scenes', 'settings', 'project', 'sessionReplayLinkedFlagLogic']),
actions({
selectFeatureFlag: (flag: FeatureFlagBasicType) => ({ flag }),
}),
connect({ values: [teamLogic, ['currentTeam']] }),
reducers({
selectedFlag: [
null as FeatureFlagBasicType | null,
{
selectFeatureFlag: (_, { flag }) => flag,
},
],
}),
props({} as ReplayLinkedFlagLogicProps),
loaders(({ props }) => ({
featureFlag: {
loadFeatureFlag: async () => {
if (props.id) {
const retrievedFlag = await api.featureFlags.get(props.id)
return variantKeyToIndexFeatureFlagPayloads(retrievedFlag)
}
return null
},
},
})),
selectors({
linkedFlag: [
(s) => [s.featureFlag, s.selectedFlag, s.currentTeam],
// an existing linked flag is loaded from the API,
// a newly chosen flag is selected can be passed in
// the current team is used to ensure that we don't show stale values
// as people change the selection
(featureFlag, selectedFlag, currentTeam) =>
currentTeam?.session_recording_linked_flag?.id ? selectedFlag || featureFlag : null,
],
flagHasVariants: [(s) => [s.linkedFlag], (linkedFlag) => isObject(linkedFlag?.filters.multivariate)],
}),
afterMount(({ actions }) => {
actions.loadFeatureFlag()
}),
])
2 changes: 1 addition & 1 deletion latest_migrations.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ contenttypes: 0002_remove_content_type_name
ee: 0016_rolemembership_organization_member
otp_static: 0002_throttling
otp_totp: 0002_auto_20190420_0723
posthog: 0492_team_session_recording_url_trigger_config
posthog: 0493_insightvariable_values
sessions: 0001_initial
social_django: 0010_uid_db_index
two_factor: 0007_auto_20201201_1019
2 changes: 1 addition & 1 deletion posthog/api/insight_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class InsightVariableSerializer(serializers.ModelSerializer):
class Meta:
model = InsightVariable

fields = ["id", "name", "type", "default_value", "created_by", "created_at", "code_name"]
fields = ["id", "name", "type", "default_value", "created_by", "created_at", "code_name", "values"]

read_only_fields = ["id", "code_name", "created_by", "created_at"]

Expand Down
17 changes: 17 additions & 0 deletions posthog/migrations/0493_insightvariable_values.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.15 on 2024-10-17 10:44

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("posthog", "0492_team_session_recording_url_trigger_config"),
]

operations = [
migrations.AddField(
model_name="insightvariable",
name="values",
field=models.JSONField(blank=True, null=True),
),
]
1 change: 1 addition & 0 deletions posthog/models/insight_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ class Type(models.TextChoices):
code_name = models.CharField(max_length=400, null=True, blank=True)
type = models.CharField(max_length=128, choices=Type.choices)
default_value = models.JSONField(null=True, blank=True)
values = models.JSONField(null=True, blank=True)

__repr__ = sane_repr("id")

0 comments on commit c6ca943

Please sign in to comment.