Add util for loading DashboardLinks
parent
e81180742b
commit
75c123323b
|
@ -47,7 +47,6 @@ import idNormalizer, {TYPE_ID} from 'src/normalizers/id'
|
|||
import {defaultTimeRange} from 'src/shared/data/timeRanges'
|
||||
|
||||
// Types
|
||||
import {AxiosResponse} from 'axios'
|
||||
import {
|
||||
Dashboard,
|
||||
Cell,
|
||||
|
@ -58,7 +57,6 @@ import {
|
|||
TemplateValue,
|
||||
TemplateType,
|
||||
} from 'src/types'
|
||||
import * as DashboardsApis from 'src/types/apis/dashboards'
|
||||
|
||||
export enum ActionType {
|
||||
LoadDashboards = 'LOAD_DASHBOARDS',
|
||||
|
@ -401,9 +399,7 @@ export const getDashboardsAsync = () => async (
|
|||
try {
|
||||
const {
|
||||
data: {dashboards},
|
||||
} = (await getDashboardsAJAX()) as AxiosResponse<
|
||||
DashboardsApis.DashboardsResponse
|
||||
>
|
||||
} = await getDashboardsAJAX()
|
||||
dispatch(loadDashboards(dashboards))
|
||||
return dashboards
|
||||
} catch (error) {
|
||||
|
@ -584,9 +580,8 @@ export const importDashboardAsync = (dashboard: Dashboard) => async (
|
|||
|
||||
const {
|
||||
data: {dashboards},
|
||||
} = (await getDashboardsAJAX()) as AxiosResponse<
|
||||
DashboardsApis.DashboardsResponse
|
||||
>
|
||||
} = await getDashboardsAJAX()
|
||||
|
||||
dispatch(loadDashboards(dashboards))
|
||||
|
||||
dispatch(notify(notifyDashboardImported(name)))
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import AJAX from 'src/utils/ajax'
|
||||
|
||||
import {AxiosResponse} from 'axios'
|
||||
import {DashboardsResponse} from 'src/types/apis/dashboards'
|
||||
import {DashboardsResponse, GetDashboards} from 'src/types/apis/dashboards'
|
||||
|
||||
export const getDashboards = (): Promise<
|
||||
AxiosResponse<DashboardsResponse> | DashboardsResponse
|
||||
> => {
|
||||
return AJAX({
|
||||
export const getDashboards: GetDashboards = () => {
|
||||
return AJAX<DashboardsResponse>({
|
||||
method: 'GET',
|
||||
resource: 'dashboards',
|
||||
})
|
||||
}) as Promise<AxiosResponse<DashboardsResponse>>
|
||||
}
|
||||
|
||||
export const getDashboard = async dashboardID => {
|
||||
|
|
|
@ -32,8 +32,7 @@ interface Props {
|
|||
zoomedTimeRange: QueriesModels.TimeRange
|
||||
onCancel: () => void
|
||||
onSave: (name: string) => Promise<void>
|
||||
dashboardLinks: DashboardsModels.DashboardSwitcherLink[]
|
||||
activeDashboardLink?: DashboardsModels.DashboardSwitcherLink
|
||||
dashboardLinks: DashboardsModels.DashboardSwitcherLinks
|
||||
isHidden: boolean
|
||||
}
|
||||
|
||||
|
@ -146,15 +145,10 @@ class DashboardHeader extends Component<Props> {
|
|||
}
|
||||
|
||||
private get dashboardSwitcher(): JSX.Element {
|
||||
const {dashboardLinks, activeDashboardLink} = this.props
|
||||
const {dashboardLinks} = this.props
|
||||
|
||||
if (dashboardLinks.length > 1) {
|
||||
return (
|
||||
<DashboardSwitcher
|
||||
links={dashboardLinks}
|
||||
activeLink={activeDashboardLink}
|
||||
/>
|
||||
)
|
||||
if (dashboardLinks.links.length > 1) {
|
||||
return <DashboardSwitcher dashboardLinks={dashboardLinks} />
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import {Link} from 'react-router'
|
||||
import _ from 'lodash'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import OnClickOutside from 'src/shared/components/OnClickOutside'
|
||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||
|
@ -8,12 +9,13 @@ import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
|||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
import {DROPDOWN_MENU_MAX_HEIGHT} from 'src/shared/constants/index'
|
||||
|
||||
import {DashboardSwitcherLink} from 'src/types/dashboards'
|
||||
import {
|
||||
DashboardSwitcherLinks,
|
||||
DashboardSwitcherLink,
|
||||
} from 'src/types/dashboards'
|
||||
|
||||
interface Props {
|
||||
links: DashboardSwitcherLink[]
|
||||
activeLink?: DashboardSwitcherLink
|
||||
dashboardLinks: DashboardSwitcherLinks
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -66,17 +68,14 @@ class DashboardSwitcher extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
private get links(): JSX.Element[] {
|
||||
const {links, activeLink} = this.props
|
||||
|
||||
return _.sortBy(links, ['text', 'key']).map(link => {
|
||||
let activeClass = ''
|
||||
|
||||
if (activeLink && link.key === activeLink.key) {
|
||||
activeClass = 'active'
|
||||
}
|
||||
|
||||
return _.sortBy(this.dashLinks, ['text', 'key']).map(link => {
|
||||
return (
|
||||
<li key={link.key} className={`dropdown-item ${activeClass}`}>
|
||||
<li
|
||||
key={link.key}
|
||||
className={classnames('dropdown-item', {
|
||||
active: link === this.activeLink,
|
||||
})}
|
||||
>
|
||||
<Link to={link.to} onClick={this.handleCloseMenu}>
|
||||
{link.text}
|
||||
</Link>
|
||||
|
@ -84,6 +83,14 @@ class DashboardSwitcher extends PureComponent<Props, State> {
|
|||
)
|
||||
})
|
||||
}
|
||||
|
||||
private get activeLink(): DashboardSwitcherLink {
|
||||
return this.props.dashboardLinks.active
|
||||
}
|
||||
|
||||
private get dashLinks(): DashboardSwitcherLink[] {
|
||||
return this.props.dashboardLinks.links
|
||||
}
|
||||
}
|
||||
|
||||
export default OnClickOutside(DashboardSwitcher)
|
||||
|
|
|
@ -24,7 +24,7 @@ import * as notifyActions from 'src/shared/actions/notifications'
|
|||
import idNormalizer, {TYPE_ID} from 'src/normalizers/id'
|
||||
import {millisecondTimeRange} from 'src/dashboards/utils/time'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
import {getDashboards as getDashboardsAJAX} from 'src/dashboards/apis'
|
||||
import * as dashboardSwitcher from 'src/dashboards/utils/dashboardSwitcherLinks'
|
||||
|
||||
// Constants
|
||||
import {
|
||||
|
@ -40,8 +40,6 @@ import {WithRouterProps} from 'react-router'
|
|||
import {ManualRefreshProps} from 'src/shared/components/ManualRefresh'
|
||||
import {Location} from 'history'
|
||||
import {InjectedRouter} from 'react-router'
|
||||
import {AxiosResponse} from 'axios'
|
||||
import {DashboardsResponse} from 'src/types/apis/dashboards'
|
||||
import * as AnnotationsActions from 'src/types/actions/annotations'
|
||||
import * as AppActions from 'src/types/actions/app'
|
||||
import * as ColorsModels from 'src/types/colors'
|
||||
|
@ -112,7 +110,7 @@ interface State {
|
|||
selectedCell: DashboardsModels.Cell | null
|
||||
scrollTop: number
|
||||
windowHeight: number
|
||||
dashboardLinks: DashboardsModels.DashboardSwitcherLink[]
|
||||
dashboardLinks: DashboardsModels.DashboardSwitcherLinks
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
|
@ -127,7 +125,7 @@ class DashboardPage extends Component<Props, State> {
|
|||
selectedCell: null,
|
||||
scrollTop: 0,
|
||||
windowHeight: window.innerHeight,
|
||||
dashboardLinks: [],
|
||||
dashboardLinks: dashboardSwitcher.EMPTY_LINKS,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,7 +288,6 @@ class DashboardPage extends Component<Props, State> {
|
|||
onCancel={this.handleCancelEditDashboard}
|
||||
onEditDashboard={this.handleEditDashboard}
|
||||
dashboardLinks={dashboardLinks}
|
||||
activeDashboardLink={this.activeDashboardLink}
|
||||
activeDashboard={dashboard ? dashboard.name : ''}
|
||||
showTemplateControlBar={showTemplateControlBar}
|
||||
handleChooseAutoRefresh={handleChooseAutoRefresh}
|
||||
|
@ -487,38 +484,22 @@ class DashboardPage extends Component<Props, State> {
|
|||
}
|
||||
|
||||
private getDashboardLinks = async (): Promise<void> => {
|
||||
const {source} = this.props
|
||||
const {source, dashboard} = this.props
|
||||
|
||||
try {
|
||||
const resp = (await getDashboardsAJAX()) as AxiosResponse<
|
||||
DashboardsResponse
|
||||
>
|
||||
const dashboards = resp.data.dashboards
|
||||
const dashboardLinks = dashboards.map(d => {
|
||||
return {
|
||||
key: String(d.id),
|
||||
text: d.name,
|
||||
to: `/sources/${source.id}/dashboards/${d.id}`,
|
||||
}
|
||||
})
|
||||
const links = await dashboardSwitcher.loadDashboardLinks(source)
|
||||
const dashboardLinks = dashboardSwitcher.updateActiveDashboardLink(
|
||||
links,
|
||||
dashboard
|
||||
)
|
||||
|
||||
this.setState({dashboardLinks})
|
||||
this.setState({
|
||||
dashboardLinks,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
private get activeDashboardLink(): DashboardsModels.DashboardSwitcherLink | null {
|
||||
const {dashboard} = this.props
|
||||
|
||||
if (!dashboard) {
|
||||
return null
|
||||
}
|
||||
|
||||
const {dashboardLinks} = this.state
|
||||
|
||||
return dashboardLinks.find(link => link.key === String(dashboard.id))
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = (state, {params: {dashboardID}}) => {
|
||||
|
@ -560,7 +541,6 @@ const mstp = (state, {params: {dashboardID}}) => {
|
|||
dashboardID: Number(dashboardID),
|
||||
timeRange,
|
||||
zoomedTimeRange,
|
||||
dashboards,
|
||||
autoRefresh,
|
||||
isUsingAuth,
|
||||
cellQueryStatus,
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import {getDashboards} from 'src/dashboards/apis'
|
||||
|
||||
import {GetDashboards} from 'src/types/apis/dashboards'
|
||||
import {Source} from 'src/types/sources'
|
||||
import {Dashboard, DashboardSwitcherLinks} from 'src/types/dashboards'
|
||||
|
||||
export const EMPTY_LINKS = {
|
||||
links: [],
|
||||
active: null,
|
||||
}
|
||||
|
||||
export const loadDashboardLinks = async (
|
||||
source: Source,
|
||||
dashboardsAJAX: GetDashboards = getDashboards
|
||||
): Promise<DashboardSwitcherLinks> => {
|
||||
const {
|
||||
data: {dashboards},
|
||||
} = await dashboardsAJAX()
|
||||
|
||||
return linksFromDashboards(dashboards, source)
|
||||
}
|
||||
|
||||
const linksFromDashboards = (
|
||||
dashboards: Dashboard[],
|
||||
source: Source
|
||||
): DashboardSwitcherLinks => {
|
||||
const links = dashboards.map(d => {
|
||||
return {
|
||||
key: String(d.id),
|
||||
text: d.name,
|
||||
to: `/sources/${source.id}/dashboards/${d.id}`,
|
||||
}
|
||||
})
|
||||
|
||||
return {links, active: null}
|
||||
}
|
||||
|
||||
export const updateActiveDashboardLink = (
|
||||
dashboardLinks: DashboardSwitcherLinks,
|
||||
dashboard: Dashboard
|
||||
) => {
|
||||
if (!dashboard) {
|
||||
return {...dashboardLinks, active: null}
|
||||
}
|
||||
|
||||
const active = dashboardLinks.links.find(
|
||||
link => link.key === String(dashboard.id)
|
||||
)
|
||||
|
||||
return {...dashboardLinks, active}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
import {Dashboard} from 'src/types/dashboards'
|
||||
import {AxiosResponse} from 'axios'
|
||||
|
||||
export interface DashboardsResponse {
|
||||
dashboards: Dashboard[]
|
||||
}
|
||||
|
||||
export type GetDashboards = () => Promise<AxiosResponse<DashboardsResponse>>
|
||||
|
|
|
@ -151,3 +151,8 @@ export interface DashboardUIState {
|
|||
hoverTime: string
|
||||
activeCellID: string
|
||||
}
|
||||
|
||||
export interface DashboardSwitcherLinks {
|
||||
active?: DashboardSwitcherLink
|
||||
links: DashboardSwitcherLink[]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
import {
|
||||
loadDashboardLinks,
|
||||
updateActiveDashboardLink,
|
||||
} from 'src/dashboards/utils/dashboardSwitcherLinks'
|
||||
import {dashboard, source} from 'test/resources'
|
||||
|
||||
describe('dashboards.utils.dashboardSwitcherLinks', () => {
|
||||
describe('loadDashboardLinks', () => {
|
||||
const socure = {...source, id: '897'}
|
||||
|
||||
const dashboards = [
|
||||
{
|
||||
...dashboard,
|
||||
id: 123,
|
||||
name: 'Test Dashboard',
|
||||
},
|
||||
]
|
||||
|
||||
const data = {
|
||||
dashboards,
|
||||
}
|
||||
|
||||
const axiosResponse = {
|
||||
data,
|
||||
status: 200,
|
||||
statusText: 'Okay',
|
||||
headers: null,
|
||||
config: null,
|
||||
}
|
||||
|
||||
const getDashboards = async () => axiosResponse
|
||||
|
||||
it('can load dashboard links for source', async () => {
|
||||
const actualLinks = await loadDashboardLinks(socure, getDashboards)
|
||||
|
||||
const expectedLinks = {
|
||||
links: [
|
||||
{
|
||||
key: '123',
|
||||
text: 'Test Dashboard',
|
||||
to: '/sources/897/dashboards/123',
|
||||
},
|
||||
],
|
||||
active: null,
|
||||
}
|
||||
|
||||
expect(actualLinks).toEqual(expectedLinks)
|
||||
})
|
||||
})
|
||||
|
||||
describe('updateActiveDashboardLink', () => {
|
||||
const activeDashboard = {
|
||||
...dashboard,
|
||||
id: 123,
|
||||
name: 'Test Dashboard',
|
||||
}
|
||||
|
||||
const activeLink = {
|
||||
key: '123',
|
||||
text: 'Test Dashboard',
|
||||
to: '/sources/897/dashboards/123',
|
||||
}
|
||||
|
||||
const link1 = {
|
||||
key: '9001',
|
||||
text: 'Low Dash',
|
||||
to: '/sources/897/dashboards/9001',
|
||||
}
|
||||
|
||||
const link2 = {
|
||||
key: '2282',
|
||||
text: 'Low Dash',
|
||||
to: '/sources/897/dashboards/2282',
|
||||
}
|
||||
|
||||
const links = [link1, activeLink, link2]
|
||||
it('can set the active link', () => {
|
||||
const loadedLinks = {links, active: null}
|
||||
const actualLinks = updateActiveDashboardLink(
|
||||
loadedLinks,
|
||||
activeDashboard
|
||||
)
|
||||
const expectedLinks = {links, active: activeLink}
|
||||
|
||||
expect(actualLinks).toEqual(expectedLinks)
|
||||
})
|
||||
|
||||
it('can handle a missing dashboard', () => {
|
||||
const loadedLinks = {links, active: null}
|
||||
const actualLinks = updateActiveDashboardLink(loadedLinks, undefined)
|
||||
const expectedLinks = {links, active: null}
|
||||
|
||||
expect(actualLinks).toEqual(expectedLinks)
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue