Skip to content

Commit

Permalink
Dashboard item page view (#4142)
Browse files Browse the repository at this point in the history
* add dashboard item information to insights page

(cherry picked from commit 63cec8e6c9416a3d89a0420894c9184dec36256d)

* update all dashboard item links

* add logic to include dashboard name on insights dashboard item

* add back to dashboards link and update all dashboard item links

* style clean up

* typescript fixes

* add comments for posterity

* update dashboard item design and componentize item header

* remove dashboardName variable

* refactor displayMap

* update dashboard item logic and props

* span fix

* clean up insight dashboard item view url

* fix weird state bug with trends

* update dashboard item view for paths

* clean up params for dashboardItemHeader

* maintain update dashboard item functionality

* bandaid fix retention insight history bug

* remove stale comment

* typing tweak

* feedback updates

* url namespace update for clarity

* update e2e

Co-authored-by: Paolo D'Amico <paolodamico@users.noreply.github.com>
  • Loading branch information
liyiy and paolodamico authored May 5, 2021
1 parent f4009c1 commit 19d3042
Show file tree
Hide file tree
Showing 17 changed files with 317 additions and 247 deletions.
2 changes: 1 addition & 1 deletion cypress/integration/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ describe('Dashboard', () => {
it('Opens dashboard item in insights', () => {
cy.get('[data-attr=dashboard-name]').contains('My App Dashboard').click()
cy.get('[data-attr=dashboard-item-0] .dashboard-item-title a').click()
cy.location('pathname').should('include', '/insights')
cy.location('pathname').should('include', '/insights/dashboard_item')
cy.get('[data-attr=math-selector-0]').contains('Unique users').should('exist')
cy.get('[data-attr=trend-line-graph]').should('exist')
})
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/lib/components/SaveToDashboard/SaveToDashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useState } from 'react'
import { Button } from 'antd'
import { SaveToDashboardModal } from './SaveToDashboardModal'
import { router } from 'kea-router'
import { useValues } from 'kea'
import { insightLogic } from 'scenes/insights/insightLogic'

interface Props {
item: DashboardItemAttributes
Expand All @@ -24,7 +25,8 @@ interface FunnelPayload {
export function SaveToDashboard(props: Props): JSX.Element {
const { item } = props
const [openModal, setOpenModal] = useState<boolean>(false)
const [{ fromItem, fromItemName, fromDashboard }] = useState(router.values.hashParams)
const { dashboardItem } = useValues(insightLogic)

let _name: string = ''
let _filters: Record<string, any> | null = null
let _annotations: Array<Record<string, any>> | null = null
Expand All @@ -43,14 +45,14 @@ export function SaveToDashboard(props: Props): JSX.Element {
closeModal={(): void => setOpenModal(false)}
name={_name}
filters={_filters}
fromItem={fromItem}
fromDashboard={fromDashboard}
fromItemName={fromItemName}
fromItem={dashboardItem?.id}
fromDashboard={dashboardItem?.dashboard}
fromItemName={dashboardItem?.name}
annotations={_annotations}
/>
)}
<Button onClick={(): void => setOpenModal(true)} type="primary" data-attr="save-to-dashboard-button">
{fromItem ? 'Update Dashboard' : 'Add to dashboard'}
{dashboardItem?.id ? 'Update Dashboard' : 'Add to dashboard'}
</Button>
</span>
)
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/scenes/dashboard/Dashboard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,25 @@ $dashboard-title-size: 32px;
}
}
}

.dashboard-item-header {
padding-top: $default_spacing * 2;
padding-bottom: $default_spacing;

.dashboard-item-description {
padding-top: $default_spacing;
padding-bottom: $default_spacing;
padding-left: 9px;
background: white;

.title {
display: flex;
align-items: center;
svg {
color: $warning;
font-size: 18px;
margin-right: 6px;
}
}
}
}
120 changes: 31 additions & 89 deletions frontend/src/scenes/dashboard/DashboardItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,97 +68,39 @@ interface DisplayProps {
element: (props: any) => JSX.Element | null
icon: (props: any) => JSX.Element | null
viewText: string
link: (item: DashboardItemType) => string
}

const displayMapItem = (className: string, element: any, icon: any, viewText: string): DisplayProps => {
return { className, element, icon, viewText }
}

const displayMapItemLink = ({ id }: DashboardItemType): string => {
return `/insights/dashboard_item/${id}`
}

export const displayHistoryItemLink = ({ id, dashboard, filters }: DashboardItemType): string => {
const specialViewTypes = [ViewType.FUNNELS, ViewType.PATHS, ViewType.RETENTION]

if (specialViewTypes.includes(filters.insights)) {
return combineUrl(
`/insights`,
{ insight: filters.insights, dashboardItem: { id: id, dashboard: dashboard }, ...filters },
{}
).url
}
return combineUrl(`/insights`, { dashboardItem: { id: id, dashboard: dashboard }, ...filters }, {}).url
}

export const displayMap: Record<DisplayedType, DisplayProps> = {
ActionsLineGraph: {
className: 'graph',
element: ActionsLineGraph,
icon: LineChartOutlined,
viewText: 'View graph',
link: ({ filters, id, dashboard, name }: DashboardItemType): string =>
combineUrl('/insights', filters, { fromItem: id, fromItemName: name, fromDashboard: dashboard }).url,
},
ActionsLineGraphCumulative: {
className: 'graph',
element: ActionsLineGraph,
icon: LineChartOutlined,
viewText: 'View graph',
link: ({ filters, id, dashboard, name }: DashboardItemType): string =>
combineUrl('/insights', filters, { fromItem: id, fromItemName: name, fromDashboard: dashboard }).url,
},
ActionsBar: {
className: 'bar',
element: ActionsLineGraph,
icon: BarChartOutlined,
viewText: 'View graph',
link: ({ filters, id, dashboard, name }: DashboardItemType): string =>
combineUrl('/insights', filters, { fromItem: id, fromItemName: name, fromDashboard: dashboard }).url,
},
ActionsBarValue: {
className: 'bar',
element: ActionsBarValueGraph,
icon: BarChartOutlined,
viewText: 'View graph',
link: ({ filters, id, dashboard, name }: DashboardItemType): string =>
combineUrl('/insights', filters, { fromItem: id, fromItemName: name, fromDashboard: dashboard }).url,
},
ActionsTable: {
className: 'table',
element: ActionsTable,
icon: TableOutlined,
viewText: 'View table',
link: ({ filters, id, dashboard, name }: DashboardItemType): string =>
combineUrl('/insights', filters, { fromItem: id, fromItemName: name, fromDashboard: dashboard }).url,
},
ActionsPie: {
className: 'pie',
element: ActionsPie,
icon: PieChartOutlined,
viewText: 'View graph',
link: ({ filters, id, dashboard, name }: DashboardItemType): string =>
combineUrl('/insights', filters, { fromItem: id, fromItemName: name, fromDashboard: dashboard }).url,
},
FunnelViz: {
className: 'funnel',
element: FunnelViz,
icon: FunnelPlotOutlined,
viewText: 'View funnel',
link: ({ id, dashboard, name, filters }: DashboardItemType): string => {
return combineUrl(
`/insights`,
{ insight: ViewType.FUNNELS, ...filters },
{ fromItem: id, fromItemName: name, fromDashboard: dashboard }
).url
},
},
RetentionContainer: {
className: 'retention',
element: RetentionContainer,
icon: TableOutlined,
viewText: 'View retention',
link: ({ id, dashboard, name, filters }: DashboardItemType): string => {
return combineUrl(
`/insights`,
{ insight: ViewType.RETENTION, ...filters },
{ fromItem: id, fromItemName: name, fromDashboard: dashboard }
).url
},
},
PathsViz: {
className: 'paths-viz',
element: Paths,
icon: FunnelPlotOutlined,
viewText: 'View graph',
link: ({ id, dashboard, name, filters }: DashboardItemType): string => {
return combineUrl(
`/insights`,
{ insight: ViewType.PATHS, ...filters },
{ fromItem: id, fromItemName: name, fromDashboard: dashboard }
).url
},
},
ActionsLineGraph: displayMapItem('graph', ActionsLineGraph, LineChartOutlined, 'View graph'),
ActionsLineGraphCumulative: displayMapItem('graph', ActionsLineGraph, LineChartOutlined, 'View graph'),
ActionsBar: displayMapItem('bar', ActionsLineGraph, BarChartOutlined, 'View graph'),
ActionsBarValue: displayMapItem('bar', ActionsBarValueGraph, BarChartOutlined, 'View graph'),
ActionsTable: displayMapItem('table', ActionsTable, TableOutlined, 'View table'),
ActionsPie: displayMapItem('pie', ActionsPie, PieChartOutlined, 'View graph'),
FunnelViz: displayMapItem('funnel', FunnelViz, FunnelPlotOutlined, 'View funnel'),
RetentionContainer: displayMapItem('retention', RetentionContainer, TableOutlined, 'View retention'),
PathsViz: displayMapItem('paths-viz', Paths, FunnelPlotOutlined, 'View graph'),
}

export function DashboardItem({
Expand Down Expand Up @@ -208,7 +150,7 @@ export function DashboardItem({
const Element = displayMap[_type].element
const Icon = displayMap[_type].icon
const viewText = displayMap[_type].viewText
const link = displayMap[_type].link(item)
const link = displayMapItemLink(item)
const color = item.color || 'white'
const { dashboards } = useValues(dashboardsModel)
const { renameDashboardItem } = useActions(dashboardItemsModel)
Expand Down
38 changes: 38 additions & 0 deletions frontend/src/scenes/dashboard/DashboardItemHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react'
import { Link } from 'lib/components/Link'
import { PageHeader } from 'lib/components/PageHeader'
import { ArrowLeftOutlined } from '@ant-design/icons'
import { IconDashboard } from 'lib/components/icons'
import { useValues } from 'kea'
import { dashboardLogic } from './dashboardLogic'
import './Dashboard.scss'
import { insightLogic } from 'scenes/insights/insightLogic'

interface Props {
dashboardId: number
}

export function DashboardItemHeader({ dashboardId }: Props): JSX.Element {
const { dashboard } = useValues(dashboardLogic({ id: dashboardId }))
const { dashboardItem } = useValues(insightLogic)

return (
<div className="dashboard-item-header">
<Link to={`/dashboard/${dashboardId}`}>
<ArrowLeftOutlined /> To {dashboard?.name} dashboard
</Link>
<div style={{ marginTop: -16 }}>
<PageHeader title={dashboardItem?.name} />
<div className="dashboard-item-description text-default">
<div className="title">
<IconDashboard />
<span style={{ paddingLeft: 6 }}>
Viewing graph <b>{dashboardItem?.name}</b> from{' '}
<Link to={`/dashboard/${dashboardId}`}>{dashboard?.name}</Link> dashboard.
</span>
</div>
</div>
</div>
</div>
)
}
9 changes: 9 additions & 0 deletions frontend/src/scenes/funnels/funnelLogic.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ export const funnelLogic = kea({
}),
actionToUrl: ({ actions, values, props }) => ({
[actions.setSteps]: () => {
if (insightLogic.values.fromDashboardItem) {
return
}
if (!props.dashboardItemId) {
return ['/insights', values.propertiesForUrl]
}
Expand Down Expand Up @@ -246,5 +249,11 @@ export const funnelLogic = kea({
}
}
},
'/insights/dashboard_item/(:dashboardItemId)': () => {
const dashboardItem = insightLogic.values.dashboardItem
if (dashboardItem && dashboardItem.filters.insight === ViewType.FUNNELS) {
actions.setFilters(cleanFunnelParams(dashboardItem.filters), true)
}
},
}),
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import { Loading } from 'lib/utils'
import { useValues, useActions } from 'kea'
import { insightHistoryLogic } from './insightHistoryLogic'
import { DashboardItemType } from '~/types'
import { DashboardItem, DisplayedType, displayMap } from 'scenes/dashboard/DashboardItem'
import { DashboardItem, displayHistoryItemLink } from 'scenes/dashboard/DashboardItem'
import './InsightHistoryPanel.scss'
import dayjs from 'dayjs'
import { dashboardItemsModel } from '~/models/dashboardItemsModel'
import { router } from 'kea-router'
import { ViewType } from '../insightLogic'
import relativeTime from 'dayjs/plugin/relativeTime'
dayjs.extend(relativeTime)

Expand Down Expand Up @@ -63,11 +62,7 @@ function InsightPane({
}}
saveDashboardItem={updateInsight}
onClick={() => {
const _type: DisplayedType =
insight.filters.insight === ViewType.RETENTION
? 'RetentionContainer'
: insight.filters.display
router.actions.push(displayMap[_type].link(insight))
router.actions.push(displayHistoryItemLink(insight))
}}
moveDashboardItem={
insight.saved
Expand Down
Loading

0 comments on commit 19d3042

Please sign in to comment.