Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(insights): simplify "save insight" #24093

Merged
merged 2 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions frontend/src/lib/utils/eventUsageLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import {
EntityType,
Experiment,
FilterLogicalOperator,
FilterType,
FunnelCorrelation,
HelpType,
InsightModel,
Expand Down Expand Up @@ -292,7 +291,7 @@ export const eventUsageLogic = kea<eventUsageLogicType>([
}),
// insights
reportInsightCreated: (insightType: InsightType | null) => ({ insightType }),
reportInsightSaved: (filters: Partial<FilterType>, isNewInsight: boolean) => ({ filters, isNewInsight }),
reportInsightSaved: (query: Node | null, isNewInsight: boolean) => ({ query, isNewInsight }),
reportInsightViewed: (
insightModel: Partial<InsightModel>,
query: Node | null,
Expand Down Expand Up @@ -636,10 +635,10 @@ export const eventUsageLogic = kea<eventUsageLogicType>([
await breakpoint(500) // Debounce to avoid multiple quick "New insight" clicks being reported
posthog.capture('insight created', { insight: insightType })
},
reportInsightSaved: async ({ filters, isNewInsight }) => {
reportInsightSaved: async ({ query, isNewInsight }) => {
// "insight saved" is a proxy for the new insight's results being valuable to the user
posthog.capture('insight saved', {
...filters,
...sanitizeQuery(query),
is_new_insight: isNewInsight,
})
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { LemonButton, LemonTabs, Link } from '@posthog/lemon-ui'
import { BindLogic, useActions, useValues } from 'kea'
import { router } from 'kea-router'
import { PageHeader } from 'lib/components/PageHeader'
import { insightDataLogic } from 'scenes/insights/insightDataLogic'
import { insightLogic } from 'scenes/insights/insightLogic'
import { insightSceneLogic } from 'scenes/insights/insightSceneLogic'
import { SceneExport } from 'scenes/sceneTypes'
Expand Down Expand Up @@ -41,19 +40,18 @@ export const humanFriendlyDataWarehouseTabName = (tab: DataWarehouseTab): string
export function DataWarehouseExternalScene(): JSX.Element {
const { currentTab } = useValues(dataWarehouseSceneLogic)

const { insightSaving, insightProps } = useValues(
const { insightSaving } = useValues(
insightLogic({
dashboardItemId: 'new',
dashboardItemId: 'new-dataWarehouse',
cachedInsight: null,
})
)
const { saveAs } = useActions(
insightLogic({
dashboardItemId: 'new',
dashboardItemId: 'new-dataWarehouse',
cachedInsight: null,
})
)
const { query } = useValues(insightDataLogic(insightProps))

return (
<div>
Expand All @@ -64,7 +62,7 @@ export function DataWarehouseExternalScene(): JSX.Element {
<LemonButton
type="primary"
data-attr="save-exploration"
onClick={() => saveAs(query, true)}
onClick={() => saveAs(true)}
loading={insightSaving}
>
Save as insight
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { DeleteTableModal, TableData } from './TableData'
export const DataWarehouseTables = (): JSX.Element => {
// insightLogic
const logic = insightLogic({
dashboardItemId: 'new',
dashboardItemId: 'new-dataWarehouse',
cachedInsight: null,
})
const { insightProps } = useValues(logic)
Expand Down
7 changes: 3 additions & 4 deletions frontend/src/scenes/insights/InsightPageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ export function InsightPageHeader({ insightLogicProps }: { insightLogicProps: In
insightSaving,
hasDashboardItemId,
} = useValues(insightLogic(insightLogicProps))
const { setInsightMetadata, saveAs } = useActions(insightLogic(insightLogicProps))
const { setInsightMetadata, saveAs, saveInsight } = useActions(insightLogic(insightLogicProps))

// savedInsightsLogic
const { duplicateInsight, loadInsights } = useActions(savedInsightsLogic)

// insightDataLogic
const { queryChanged, showQueryEditor, hogQL, exportContext, query } = useValues(insightDataLogic(insightProps))
const { saveInsight, toggleQueryEditorPanel } = useActions(insightDataLogic(insightProps))
const { queryChanged, showQueryEditor, hogQL, exportContext } = useValues(insightDataLogic(insightProps))
const { toggleQueryEditorPanel } = useActions(insightDataLogic(insightProps))

// other logics
useMountedLogic(insightCommandLogic(insightProps))
Expand Down Expand Up @@ -275,7 +275,6 @@ export function InsightPageHeader({ insightLogicProps }: { insightLogicProps: In
)
) : (
<InsightSaveButton
query={query}
saveAs={saveAs}
saveInsight={saveInsight}
isSaved={hasDashboardItemId}
Expand Down
12 changes: 2 additions & 10 deletions frontend/src/scenes/insights/InsightSaveButton.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { LemonButton } from 'lib/lemon-ui/LemonButton'

import { Node } from '~/queries/schema'

export function InsightSaveButton({
query,
saveAs,
saveInsight,
isSaved,
insightSaving,
insightChanged,
addingToDashboard,
}: {
query: Node
saveAs: (query: Node) => void
saveAs: () => void
saveInsight: (redirectToViewMode?: boolean) => void
isSaved: boolean | undefined
insightSaving: boolean
Expand Down Expand Up @@ -44,11 +40,7 @@ export function InsightSaveButton({
</LemonButton>
)}
{saveAsAvailable && (
<LemonButton
onClick={() => saveAs(query)}
data-attr="insight-save-as-new-insight"
fullWidth
>
<LemonButton onClick={() => saveAs()} data-attr="insight-save-as-new-insight" fullWidth>
Save as…
</LemonButton>
)}
Expand Down
30 changes: 2 additions & 28 deletions frontend/src/scenes/insights/insightDataLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const insightDataLogic = kea<insightDataLogicType>([
],
actions: [
insightLogic,
['setInsight', 'loadInsightSuccess', 'saveInsight as insightLogicSaveInsight'],
['setInsight', 'loadInsightSuccess'],
dataNodeLogic({ key: insightVizDataNodeKey(props) } as DataNodeLogicProps),
['loadData', 'loadDataSuccess', 'loadDataFailure', 'setResponse as setInsightData'],
],
Expand All @@ -73,7 +73,6 @@ export const insightDataLogic = kea<insightDataLogicType>([

actions({
setQuery: (query: Node | null) => ({ query }),
saveInsight: (redirectToViewMode = true) => ({ redirectToViewMode }),
toggleQueryEditorPanel: true,
cancelChanges: true,
}),
Expand Down Expand Up @@ -101,7 +100,7 @@ export const insightDataLogic = kea<insightDataLogicType>([

query: [
(s) => [s.propsQuery, s.queryBasedInsight, s.internalQuery, s.filterTestAccountsDefault],
(propsQuery, insight, internalQuery, filterTestAccountsDefault) =>
(propsQuery, insight, internalQuery, filterTestAccountsDefault): Node | null =>
propsQuery ||
internalQuery ||
insight.query ||
Expand Down Expand Up @@ -203,31 +202,6 @@ export const insightDataLogic = kea<insightDataLogicType>([
actions.setQuery(query)
}
},
saveInsight: ({ redirectToViewMode }) => {
let filters = values.legacyInsight.filters
if (isInsightVizNode(values.query)) {
const querySource = values.query.source
filters = queryNodeToFilter(querySource)
} else if (values.isQueryBasedInsight) {
filters = {}
}

let query = undefined
if (values.isQueryBasedInsight) {
query = values.query
}

actions.setInsight(
{
...values.legacyInsight,
filters: filters,
query: query ?? undefined,
},
{ overrideFilter: true, fromPersistentApi: false }
)

actions.insightLogicSaveInsight(redirectToViewMode)
},
cancelChanges: () => {
const savedFilters = values.savedInsight.filters
const savedResult = values.savedInsight.result
Expand Down
69 changes: 49 additions & 20 deletions frontend/src/scenes/insights/insightLogic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
DashboardTile,
DashboardType,
FilterType,
InsightLogicProps,
InsightModel,
InsightShortId,
InsightType,
Expand Down Expand Up @@ -460,12 +461,16 @@ describe('insightLogic', () => {
})

test('keeps saved name, description, tags', async () => {
logic = insightLogic({
const insightProps: InsightLogicProps = {
dashboardItemId: Insight43,
cachedInsight: { ...createEmptyInsight(Insight43, false), filters: API_FILTERS },
})
}

logic = insightLogic(insightProps)
logic.mount()

insightDataLogic(insightProps).mount()

const expectedPartialInsight = {
name: '',
description: '',
Expand Down Expand Up @@ -502,11 +507,15 @@ describe('insightLogic', () => {
})

test('saveInsight saves new insight and redirects to view mode', async () => {
logic = insightLogic({
const insightProps: InsightLogicProps = {
dashboardItemId: 'new',
})
}

logic = insightLogic(insightProps)
logic.mount()

insightDataLogic(insightProps).mount()

await expectLogic(logic, () => {
logic.actions.setFilters(cleanFilters({}))
logic.actions.saveInsight()
Expand All @@ -515,16 +524,21 @@ describe('insightLogic', () => {

test('saveInsight and updateInsight update the saved insights list', async () => {
savedInsightsLogic.mount()
logic = insightLogic({

const insightProps: InsightLogicProps = {
dashboardItemId: Insight42,
cachedInsight: {
short_id: Insight42,
filters: { insight: InsightType.FUNNELS },
results: {},
result: {},
},
})
}

logic = insightLogic(insightProps)
logic.mount()

insightDataLogic(insightProps).mount()

logic.actions.saveInsight()
await expectLogic(logic).toDispatchActions([savedInsightsLogic.actionTypes.addInsight])

Expand All @@ -539,10 +553,14 @@ describe('insightLogic', () => {

savedInsightsLogic.mount()

logic = insightLogic({
const insightProps: InsightLogicProps = {
dashboardItemId: Insight43,
})
}
logic = insightLogic(insightProps)
logic.mount()

insightDataLogic(insightProps).mount()

logic.actions.saveInsight()

await expectLogic(dashLogic).toDispatchActions(['loadDashboard'])
Expand All @@ -567,19 +585,20 @@ describe('insightLogic', () => {
router.actions.push(url)
savedInsightsLogic.mount()

logic = insightLogic({
const insightProps: InsightLogicProps = {
dashboardItemId: Insight42,
cachedInsight: {
filters: { insight: InsightType.FUNNELS },
},
})
}

logic = insightLogic(insightProps)
logic.mount()

const dataLogic = insightDataLogic(logic.values.insightProps)
dataLogic.mount()
insightDataLogic(insightProps).mount()

await expectLogic(logic, () => {
logic.actions.saveAsConfirmation('New Insight (copy)', dataLogic.values.query)
logic.actions.saveAsConfirmation('New Insight (copy)')
})
.toDispatchActions(['setInsight'])
.toDispatchActions(savedInsightsLogic, ['loadInsights'])
Expand Down Expand Up @@ -727,10 +746,11 @@ describe('insightLogic', () => {

describe('saving query based insights', () => {
beforeEach(async () => {
logic = insightLogic({
dashboardItemId: 'new',
})
const insightProps: InsightLogicProps = { dashboardItemId: 'new' }
logic = insightLogic(insightProps)
logic.mount()

insightDataLogic(insightProps).mount()
})

it('sends query when saving', async () => {
Expand All @@ -747,14 +767,23 @@ describe('insightLogic', () => {
const mockCreateCalls = (api.create as jest.Mock).mock.calls
expect(mockCreateCalls).toEqual([
[
`api/projects/${MOCK_TEAM_ID}/insights/`,
{
`api/projects/${MOCK_TEAM_ID}/insights`,
expect.objectContaining({
derived_name: 'DataTableNode query',
query: {
kind: 'DataTableNode',
},
saved: true,
},
}),
expect.objectContaining({
data: {
derived_name: 'DataTableNode query',
query: {
kind: 'DataTableNode',
},
saved: true,
},
}),
],
])
})
Expand Down
Loading
Loading