Skip to content

Commit

Permalink
feat(insights): explore persons modal further (#19198)
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusandra authored Dec 11, 2023
1 parent 7f450d6 commit 867a5e5
Show file tree
Hide file tree
Showing 17 changed files with 214 additions and 104 deletions.
Binary file modified frontend/__snapshots__/scenes-app-events--event-explorer.png
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.
15 changes: 12 additions & 3 deletions frontend/src/queries/nodes/DataNode/LoadNext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ interface LoadNextProps {
query: DataNode
}
export function LoadNext({ query }: LoadNextProps): JSX.Element {
const { nextDataLoading } = useValues(dataNodeLogic)
const { canLoadNextData, nextDataLoading, numberOfRows } = useValues(dataNodeLogic)
const { loadNextData } = useActions(dataNodeLogic)

return (
<div className="m-2 flex items-center">
<LemonButton onClick={loadNextData} loading={nextDataLoading} fullWidth center>
Load more {isPersonsNode(query) || isPersonsQuery(query) ? 'people' : 'events'}
<LemonButton onClick={loadNextData} loading={nextDataLoading} fullWidth center disabled={!canLoadNextData}>
Showing {canLoadNextData || numberOfRows === 1 ? '' : 'all '}
{numberOfRows === 1 ? 'one' : numberOfRows}{' '}
{isPersonsNode(query) || isPersonsQuery(query)
? numberOfRows === 1
? 'person'
: 'people'
: numberOfRows === 1
? 'event'
: 'events'}
{canLoadNextData ? '. Click to load more.' : '. Reached the end of results.'}
</LemonButton>
</div>
)
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/queries/nodes/DataNode/dataNodeLogic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ describe('dataNodeLogic', () => {
kind: NodeKind.EventsQuery,
select: ['*', 'event', 'timestamp'],
before: '2022-12-24T17:00:41.165000Z',
limit: 100,
},
response: partial({ results }),
})
Expand Down Expand Up @@ -268,6 +269,7 @@ describe('dataNodeLogic', () => {
kind: NodeKind.EventsQuery,
select: ['*', 'event', 'timestamp'],
before: '2022-12-24T17:00:41.165000Z',
limit: 100,
},
response: partial({ results }),
})
Expand All @@ -280,6 +282,7 @@ describe('dataNodeLogic', () => {
kind: NodeKind.EventsQuery,
select: ['*', 'event', 'timestamp'],
before: '2022-12-23T17:00:41.165000Z',
limit: 100,
},
response: partial({ results: [...results, ...results2] }),
})
Expand Down
44 changes: 43 additions & 1 deletion frontend/src/queries/nodes/DataNode/dataNodeLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import {
DataNode,
EventsQuery,
EventsQueryResponse,
InsightVizNode,
NodeKind,
PersonsNode,
PersonsQuery,
PersonsQueryResponse,
Expand All @@ -41,6 +43,7 @@ import {
} from '~/queries/schema'
import {
isEventsQuery,
isInsightPersonsQuery,
isInsightQueryNode,
isLifecycleQuery,
isPersonsNode,
Expand All @@ -61,6 +64,7 @@ export interface DataNodeLogicProps {
}

const AUTOLOAD_INTERVAL = 30000
const LOAD_MORE_ROWS_LIMIT = 10000

const queryEqual = (a: DataNode, b: DataNode): boolean => {
if (isInsightQueryNode(a) && isInsightQueryNode(b)) {
Expand Down Expand Up @@ -403,14 +407,22 @@ export const dataNodeLogic = kea<dataNodeLogicType>([
if (sortColumnIndex !== -1) {
const lastTimestamp = typedResults?.[typedResults.length - 1]?.[sortColumnIndex]
if (lastTimestamp) {
const newQuery: EventsQuery = { ...query, before: lastTimestamp }
const newQuery: EventsQuery = {
...query,
before: lastTimestamp,
limit: Math.max(
100,
Math.min(2 * (typedResults?.length || 100), LOAD_MORE_ROWS_LIMIT)
),
}
return newQuery
}
}
} else {
return {
...query,
offset: typedResults?.length || 0,
limit: Math.max(100, Math.min(2 * (typedResults?.length || 100), LOAD_MORE_ROWS_LIMIT)),
} as EventsQuery | PersonsQuery
}
}
Expand All @@ -431,6 +443,21 @@ export const dataNodeLogic = kea<dataNodeLogicType>([
(s) => [s.nextQuery, s.isShowingCachedResults],
(nextQuery, isShowingCachedResults) => (isShowingCachedResults ? false : !!nextQuery),
],
backToSourceQuery: [
(s) => [s.query],
(query): InsightVizNode | null => {
if (isPersonsQuery(query) && isInsightPersonsQuery(query.source) && !!query.source.source) {
const insightQuery = query.source.source
const insightVizNode: InsightVizNode = {
kind: NodeKind.InsightVizNode,
source: insightQuery,
full: true,
}
return insightVizNode
}
return null
},
],
autoLoadRunning: [
(s) => [s.autoLoadToggled, s.autoLoadStarted, s.dataLoading],
(autoLoadToggled, autoLoadStarted, dataLoading) => autoLoadToggled && autoLoadStarted && !dataLoading,
Expand Down Expand Up @@ -478,6 +505,21 @@ export const dataNodeLogic = kea<dataNodeLogicType>([
return response && 'timings' in response ? response.timings : null
},
],
numberOfRows: [
(s) => [s.response],
(response): number | null => {
if (!response) {
return null
}
const fields = ['result', 'results']
for (const field of fields) {
if (field in response && Array.isArray(response[field])) {
return response[field].length
}
}
return null
},
],
}),
listeners(({ actions, values, cache }) => ({
abortAnyRunningQuery: () => {
Expand Down
41 changes: 41 additions & 0 deletions frontend/src/queries/nodes/DataTable/BackToSource.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useValues } from 'kea'
import { router } from 'kea-router'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
import { summarizeInsightQuery } from 'scenes/insights/summarizeInsight'
import { mathsLogic } from 'scenes/trends/mathsLogic'
import { urls } from 'scenes/urls'

import { cohortsModel } from '~/models/cohortsModel'
import { groupsModel } from '~/models/groupsModel'
import { dataNodeLogic } from '~/queries/nodes/DataNode/dataNodeLogic'

export function BackToSource(): JSX.Element | null {
const { aggregationLabel } = useValues(groupsModel)
const { cohortsById } = useValues(cohortsModel)
const { mathDefinitions } = useValues(mathsLogic)

const { backToSourceQuery } = useValues(dataNodeLogic)

if (!backToSourceQuery) {
return null
}

const summary = summarizeInsightQuery(backToSourceQuery.source, {
aggregationLabel,
cohortsById,
mathDefinitions,
})

return (
<LemonButton
tooltip={summary}
type="secondary"
status="primary-alt"
onClick={() =>
router.actions.push(urls.insightNew(undefined, undefined, JSON.stringify(backToSourceQuery)))
}
>
&laquo; Back to {backToSourceQuery.source.kind?.replace('Query', '') ?? 'Insight'}
</LemonButton>
)
}
11 changes: 4 additions & 7 deletions frontend/src/queries/nodes/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { DateRange } from '~/queries/nodes/DataNode/DateRange'
import { ElapsedTime } from '~/queries/nodes/DataNode/ElapsedTime'
import { LoadNext } from '~/queries/nodes/DataNode/LoadNext'
import { Reload } from '~/queries/nodes/DataNode/Reload'
import { BackToSource } from '~/queries/nodes/DataTable/BackToSource'
import { ColumnConfigurator } from '~/queries/nodes/DataTable/ColumnConfigurator/ColumnConfigurator'
import { DataTableExport } from '~/queries/nodes/DataTable/DataTableExport'
import { dataTableLogic, DataTableLogicProps, DataTableRow } from '~/queries/nodes/DataTable/dataTableLogic'
Expand Down Expand Up @@ -97,11 +98,11 @@ export function DataTable({ uniqueKey, query, setQuery, context, cachedResults }
responseLoading,
responseError,
queryCancelled,
canLoadNextData,
canLoadNewData,
nextDataLoading,
newDataLoading,
highlightedRows,
backToSourceQuery,
} = useValues(builtDataNodeLogic)

const dataTableLogicProps: DataTableLogicProps = { query, vizKey: vizKey, dataKey: dataKey, context }
Expand Down Expand Up @@ -375,6 +376,7 @@ export function DataTable({ uniqueKey, query, setQuery, context, cachedResults }
)

const firstRowLeft = [
backToSourceQuery ? <BackToSource key="return-to-source" /> : null,
showDateRange && sourceFeatures.has(QueryFeature.dateRangePicker) ? (
<DateRange key="date-range" query={query.source} setQuery={setQuerySource} />
) : null,
Expand Down Expand Up @@ -553,12 +555,7 @@ export function DataTable({ uniqueKey, query, setQuery, context, cachedResults }
result && result[0] && result[0]['event'] === '$exception',
})
}
footer={
canLoadNextData &&
((response as any).results.length > 0 ||
(response as any).result.length > 0 ||
!responseLoading) && <LoadNext query={query.source} />
}
footer={(dataTableRows ?? []).length > 0 ? <LoadNext query={query.source} /> : null}
onRow={context?.rowProps}
/>
)}
Expand Down
1 change: 0 additions & 1 deletion frontend/src/queries/nodes/DataTable/renderColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ export function renderColumn(
return <Property value={eventRecord.person?.properties?.[propertyKey]} />
} else if (key === 'person') {
const personRecord = record as PersonType

const displayProps: PersonDisplayProps = {
withIcon: true,
person: record as PersonType,
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/queries/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
InsightFilter,
InsightFilterProperty,
InsightNodeKind,
InsightPersonsQuery,
InsightQueryNode,
InsightVizNode,
LifecycleQuery,
Expand Down Expand Up @@ -95,6 +96,10 @@ export function isPersonsQuery(node?: Node | null): node is PersonsQuery {
return node?.kind === NodeKind.PersonsQuery
}

export function isInsightPersonsQuery(node?: Node | null): node is InsightPersonsQuery {
return node?.kind === NodeKind.InsightPersonsQuery
}

export function isDataTableNode(node?: Node | null): node is DataTableNode {
return node?.kind === NodeKind.DataTableNode
}
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/scenes/insights/Insight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function Insight({ insightId }: InsightSceneProps): JSX.Element {
const { reportInsightViewedForRecentInsights } = useActions(logic)

// insightDataLogic
const { query, isQueryBasedInsight, showQueryEditor } = useValues(insightDataLogic(insightProps))
const { query, showQueryEditor } = useValues(insightDataLogic(insightProps))
const { setQuery: setInsightQuery } = useActions(insightDataLogic(insightProps))

// other logics
Expand All @@ -48,9 +48,7 @@ export function Insight({ insightId }: InsightSceneProps): JSX.Element {
return <InsightSkeleton />
}

const actuallyShowQueryEditor =
insightMode === ItemMode.Edit &&
((isQueryBasedInsight && !containsHogQLQuery(query)) || (!isQueryBasedInsight && showQueryEditor))
const actuallyShowQueryEditor = insightMode === ItemMode.Edit && showQueryEditor

const setQuery = (query: Node): void => {
if (!isInsightVizNode(query)) {
Expand Down
39 changes: 18 additions & 21 deletions frontend/src/scenes/insights/InsightPageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import { cohortsModel } from '~/models/cohortsModel'
import { groupsModel } from '~/models/groupsModel'
import { tagsModel } from '~/models/tagsModel'
import { DataTableNode, NodeKind } from '~/queries/schema'
import { isInsightVizNode } from '~/queries/utils'
import {
AvailableFeature,
ExporterFormat,
Expand Down Expand Up @@ -203,28 +202,26 @@ export function InsightPageHeader({ insightLogicProps }: { insightLogicProps: In
) : null}
</>
)}
{isInsightVizNode(query) ? (
<LemonButton
data-attr={`${showQueryEditor ? 'hide' : 'show'}-insight-source`}
status="stealth"
onClick={() => {
// for an existing insight in view mode
if (hasDashboardItemId && insightMode !== ItemMode.Edit) {
// enter edit mode
setInsightMode(ItemMode.Edit, null)
<LemonButton
data-attr={`${showQueryEditor ? 'hide' : 'show'}-insight-source`}
status="stealth"
onClick={() => {
// for an existing insight in view mode
if (hasDashboardItemId && insightMode !== ItemMode.Edit) {
// enter edit mode
setInsightMode(ItemMode.Edit, null)

// exit early if query editor doesn't need to be toggled
if (showQueryEditor !== false) {
return
}
// exit early if query editor doesn't need to be toggled
if (showQueryEditor !== false) {
return
}
toggleQueryEditorPanel()
}}
fullWidth
>
{showQueryEditor ? 'Hide source' : 'View source'}
</LemonButton>
) : null}
}
toggleQueryEditorPanel()
}}
fullWidth
>
{showQueryEditor ? 'Hide source' : 'View source'}
</LemonButton>
{hogQL && (
<LemonButton
data-attr={`edit-insight-sql`}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/insights/summarizeInsight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ function summarizeInsightFilters(filters: AnyPartialFilterType, context: Summary
return ''
}

function summarizeInsightQuery(query: InsightQueryNode, context: SummaryContext): string {
export function summarizeInsightQuery(query: InsightQueryNode, context: SummaryContext): string {
if (isTrendsQuery(query)) {
let summary = query.series
.map((s, index) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/persons/person-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function asDisplay(person: PersonPropType | null | undefined, maxLength?:
: undefined)
)?.trim()

return display ? midEllipsis(display, maxLength || 40) : 'Person without ID'
return display ? midEllipsis(display, maxLength || 40) : 'Person without distinct_id'
}

export const asLink = (person?: PersonPropType | null): string | undefined =>
Expand Down
Loading

0 comments on commit 867a5e5

Please sign in to comment.