From 7b06800295189343bb61e6ef56cebe70056cc23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sun, 2 Sep 2018 10:36:36 -0700 Subject: [PATCH] refactor: changed nav store to use nav index and selector instead of initNav action --- public/app/core/actions/index.ts | 3 +- public/app/core/actions/navModel.ts | 16 ++-- public/app/core/reducers/index.ts | 4 +- public/app/core/reducers/navModel.ts | 69 ++++----------- public/app/core/selectors/navModel.ts | 39 +++++++++ public/app/features/admin/apis/index.ts | 2 +- .../admin/containers/ServerStats.test.tsx | 7 +- .../features/admin/containers/ServerStats.tsx | 19 ++-- .../__snapshots__/ServerStats.test.tsx.snap | 87 ++++--------------- .../app/features/alerting/AlertRuleList.tsx | 15 ++-- .../alerting/state/ThresholdMapper.test.ts | 2 +- public/app/types/container.ts | 7 -- public/app/types/index.ts | 46 +++++++++- public/app/types/location.ts | 15 ---- public/app/types/navModel.ts | 19 ---- public/test/jest-setup.ts | 21 +++++ public/test/mocks/common.ts | 5 +- 17 files changed, 174 insertions(+), 202 deletions(-) create mode 100644 public/app/core/selectors/navModel.ts delete mode 100644 public/app/types/container.ts delete mode 100644 public/app/types/location.ts delete mode 100644 public/app/types/navModel.ts diff --git a/public/app/core/actions/index.ts b/public/app/core/actions/index.ts index 7a965f82dd1..74b61f845c0 100644 --- a/public/app/core/actions/index.ts +++ b/public/app/core/actions/index.ts @@ -1,4 +1,3 @@ -import { initNav } from './navModel'; import { updateLocation } from './location'; -export { initNav, updateLocation }; +export { updateLocation }; diff --git a/public/app/core/actions/navModel.ts b/public/app/core/actions/navModel.ts index 048afd4f8ff..56d129fd263 100644 --- a/public/app/core/actions/navModel.ts +++ b/public/app/core/actions/navModel.ts @@ -1,11 +1,13 @@ -export type Action = InitNavModelAction; +export type Action = UpdateNavIndexAction; -export interface InitNavModelAction { - type: 'INIT_NAV_MODEL'; - args: string[]; +// this action is not used yet +// kind of just a placeholder, will be need for dynamic pages +// like datasource edit, teams edit page + +export interface UpdateNavIndexAction { + type: 'UPDATE_NAV_INDEX'; } -export const initNav = (...args: string[]): InitNavModelAction => ({ - type: 'INIT_NAV_MODEL', - args: args, +export const updateNavIndex = (): UpdateNavIndexAction => ({ + type: 'UPDATE_NAV_INDEX', }); diff --git a/public/app/core/reducers/index.ts b/public/app/core/reducers/index.ts index 98f796981e4..a3f9ca909c9 100644 --- a/public/app/core/reducers/index.ts +++ b/public/app/core/reducers/index.ts @@ -1,7 +1,7 @@ -import navModel from './navModel'; +import { navIndexReducer as navIndex } from './navModel'; import location from './location'; export default { - navModel, + navIndex, location, }; diff --git a/public/app/core/reducers/navModel.ts b/public/app/core/reducers/navModel.ts index 4e9a7f8e434..26acdb39a3d 100644 --- a/public/app/core/reducers/navModel.ts +++ b/public/app/core/reducers/navModel.ts @@ -1,62 +1,29 @@ import { Action } from 'app/core/actions/navModel'; -import { NavModel, NavModelItem } from 'app/types'; +import { NavModelItem, NavIndex } from 'app/types'; import config from 'app/core/config'; -function getNotFoundModel(): NavModel { - var node: NavModelItem = { - id: 'not-found', - text: 'Page not found', - icon: 'fa fa-fw fa-warning', - subTitle: '404 Error', - url: 'not-found', - }; - - return { - node: node, - main: node, - }; +export function buildInitialState(): NavIndex { + const navIndex: NavIndex = {}; + const rootNodes = config.bootData.navTree as NavModelItem[]; + buildNavIndex(navIndex, rootNodes); + return navIndex; } -export const initialState: NavModel = getNotFoundModel(); +function buildNavIndex(navIndex: NavIndex, children: NavModelItem[], parentItem?: NavModelItem) { + for (const node of children) { + navIndex[node.id] = { + ...node, + parentItem: parentItem, + }; -const navModelReducer = (state = initialState, action: Action): NavModel => { - switch (action.type) { - case 'INIT_NAV_MODEL': { - let children = config.bootData.navTree as NavModelItem[]; - let main, node; - const parents = []; - - for (const id of action.args) { - node = children.find(el => el.id === id); - - if (!node) { - throw new Error(`NavItem with id ${id} not found`); - } - - children = node.children; - parents.push(node); - } - - main = parents[parents.length - 2]; - - if (main.children) { - for (const item of main.children) { - item.active = false; - - if (item.url === node.url) { - item.active = true; - } - } - } - - return { - main: main, - node: node, - }; + if (node.children) { + buildNavIndex(navIndex, node.children, node); } } +} +export const initialState: NavIndex = buildInitialState(); + +export const navIndexReducer = (state = initialState, action: Action): NavIndex => { return state; }; - -export default navModelReducer; diff --git a/public/app/core/selectors/navModel.ts b/public/app/core/selectors/navModel.ts new file mode 100644 index 00000000000..5f2d0318dff --- /dev/null +++ b/public/app/core/selectors/navModel.ts @@ -0,0 +1,39 @@ +import { NavModel, NavModelItem, NavIndex } from 'app/types'; + +function getNotFoundModel(): NavModel { + var node: NavModelItem = { + id: 'not-found', + text: 'Page not found', + icon: 'fa fa-fw fa-warning', + subTitle: '404 Error', + url: 'not-found', + }; + + return { + node: node, + main: node, + }; +} + +export function selectNavNode(navIndex: NavIndex, id: string): NavModel { + if (navIndex[id]) { + const node = navIndex[id]; + const main = { + ...node.parentItem, + }; + + main.children = main.children.map(item => { + return { + ...item, + active: item.url === node.url, + }; + }); + + return { + node: node, + main: main, + }; + } else { + return getNotFoundModel(); + } +} diff --git a/public/app/features/admin/apis/index.ts b/public/app/features/admin/apis/index.ts index 888cfd4f58f..d81fd299493 100644 --- a/public/app/features/admin/apis/index.ts +++ b/public/app/features/admin/apis/index.ts @@ -2,7 +2,7 @@ import { getBackendSrv } from 'app/core/services/backend_srv'; export interface ServerStat { name: string; - value: string; + value: number; } export const getServerStats = async (): Promise => { diff --git a/public/app/features/admin/containers/ServerStats.test.tsx b/public/app/features/admin/containers/ServerStats.test.tsx index a89e78cb4ba..e12dfc3bed4 100644 --- a/public/app/features/admin/containers/ServerStats.test.tsx +++ b/public/app/features/admin/containers/ServerStats.test.tsx @@ -1,18 +1,19 @@ import React from 'react'; import renderer from 'react-test-renderer'; import { ServerStats } from './ServerStats'; -import { initNav } from 'test/mocks/common'; +import { createNavModel } from 'test/mocks/common'; import { ServerStat } from '../apis'; describe('ServerStats', () => { it('Should render table with stats', done => { - const stats: ServerStat[] = [{ name: 'test', value: 'asd' }]; + const navModel = createNavModel('Admin', 'stats'); + const stats: ServerStat[] = [{ name: 'Total dashboards', value: 10 }, { name: 'Total Users', value: 1 }]; let getServerStats = () => { return Promise.resolve(stats); }; - const page = renderer.create(); + const page = renderer.create(); setTimeout(() => { expect(page.toJSON()).toMatchSnapshot(); diff --git a/public/app/features/admin/containers/ServerStats.tsx b/public/app/features/admin/containers/ServerStats.tsx index 29611696efa..0b44a9af65e 100644 --- a/public/app/features/admin/containers/ServerStats.tsx +++ b/public/app/features/admin/containers/ServerStats.tsx @@ -1,12 +1,13 @@ import React, { PureComponent } from 'react'; import { hot } from 'react-hot-loader'; import { connect } from 'react-redux'; -import { initNav } from 'app/core/actions'; -import { ContainerProps } from 'app/types'; +import { NavModel, StoreState } from 'app/types'; +import { selectNavNode } from 'app/core/selectors/navModel'; import { getServerStats, ServerStat } from '../apis'; import PageHeader from 'app/core/components/PageHeader/PageHeader'; -interface Props extends ContainerProps { +interface Props { + navModel: NavModel; getServerStats: () => Promise; } @@ -21,8 +22,6 @@ export class ServerStats extends PureComponent { this.state = { stats: [], }; - - this.props.initNav('cfg', 'admin', 'server-stats'); } async componentDidMount() { @@ -66,13 +65,9 @@ function StatItem(stat: ServerStat) { ); } -const mapStateToProps = state => ({ - navModel: state.navModel, +const mapStateToProps = (state: StoreState) => ({ + navModel: selectNavNode(state.navIndex, 'server-stats'), getServerStats: getServerStats, }); -const mapDispatchToProps = { - initNav, -}; - -export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(ServerStats)); +export default hot(module)(connect(mapStateToProps)(ServerStats)); diff --git a/public/app/features/admin/containers/__snapshots__/ServerStats.test.tsx.snap b/public/app/features/admin/containers/__snapshots__/ServerStats.test.tsx.snap index eac793ca2ca..63de5bcd870 100644 --- a/public/app/features/admin/containers/__snapshots__/ServerStats.test.tsx.snap +++ b/public/app/features/admin/containers/__snapshots__/ServerStats.test.tsx.snap @@ -17,8 +17,9 @@ exports[`ServerStats Should render table with stats 1`] = ` - - +
- admin-Text + Admin - +
+ subTitle +