From 5b91bb9163abce2966ebf8744429bc8d67d72d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 27 Dec 2017 13:15:27 +0100 Subject: [PATCH] tech: minor progress on mobx state tree & react containers, working on unit testing --- .../ServerStats/ServerStats.jest.tsx | 24 +++++ .../{ => ServerStats}/ServerStats.tsx | 9 +- .../__snapshots__/ServerStats.jest.tsx.snap | 99 +++++++++++++++++++ public/app/routes/ReactContainer.tsx | 2 +- public/app/routes/bundle_loader.ts | 26 ----- public/app/routes/routes.ts | 2 +- public/app/stores/NavStore/NavStore.ts | 74 ++++++++++++++ public/app/stores/RootStore.ts | 2 + public/app/stores/ServerStatsStore.tsx | 31 +++--- 9 files changed, 223 insertions(+), 46 deletions(-) create mode 100644 public/app/containers/ServerStats/ServerStats.jest.tsx rename public/app/containers/{ => ServerStats}/ServerStats.tsx (77%) create mode 100644 public/app/containers/ServerStats/__snapshots__/ServerStats.jest.tsx.snap delete mode 100644 public/app/routes/bundle_loader.ts create mode 100644 public/app/stores/NavStore/NavStore.ts diff --git a/public/app/containers/ServerStats/ServerStats.jest.tsx b/public/app/containers/ServerStats/ServerStats.jest.tsx new file mode 100644 index 00000000000..da30f24568a --- /dev/null +++ b/public/app/containers/ServerStats/ServerStats.jest.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { ServerStats } from './ServerStats'; +import { RootStore } from 'app/stores/RootStore'; + +describe('ServerStats', () => { + it('Should render table with stats', done => { + let backendSrvMock = { + get: jest.fn().mockReturnValue( + Promise.resolve({ + dashboards: 10, + }) + ), + }; + + const store = RootStore.create({}, { backendSrv: backendSrvMock }); + const page = renderer.create(); + + setTimeout(() => { + expect(page.toJSON()).toMatchSnapshot(); + done(); + }); + }); +}); diff --git a/public/app/containers/ServerStats.tsx b/public/app/containers/ServerStats/ServerStats.tsx similarity index 77% rename from public/app/containers/ServerStats.tsx rename to public/app/containers/ServerStats/ServerStats.tsx index b4ec56c4311..c5fdbe8a2fd 100644 --- a/public/app/containers/ServerStats.tsx +++ b/public/app/containers/ServerStats/ServerStats.tsx @@ -9,20 +9,19 @@ export interface IProps { @inject('store') @observer -export default class ServerStats extends React.Component { - navModel: NavModel; - +export class ServerStats extends React.Component { constructor(props) { super(props); - this.navModel = new NavModelSrv().getNav('cfg', 'admin', 'server-stats', 1); + // this.navModel = new NavModelSrv().getNav('cfg', 'admin', 'server-stats', 1); + this.props.store.nav.load('cfg', 'admin', 'server-stats'); this.props.store.serverStats.load(); } render() { return (
- +
diff --git a/public/app/containers/ServerStats/__snapshots__/ServerStats.jest.tsx.snap b/public/app/containers/ServerStats/__snapshots__/ServerStats.jest.tsx.snap new file mode 100644 index 00000000000..c36cc64e3a1 --- /dev/null +++ b/public/app/containers/ServerStats/__snapshots__/ServerStats.jest.tsx.snap @@ -0,0 +1,99 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ServerStats Should render table with stats 1`] = ` +
+ // +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Name + + Value +
+ Total dashboards + + 10 +
+ Total users + + 0 +
+ Active users (seen last 30 days) + + 0 +
+ Total orgs + + 0 +
+ Total playlists + + 0 +
+ Total snapshots + + 0 +
+ Total dashboard tags + + 0 +
+ Total starred dashboards + + 0 +
+ Total alerts + + 0 +
+
+
+`; diff --git a/public/app/routes/ReactContainer.tsx b/public/app/routes/ReactContainer.tsx index 92a1baa9a8c..7db429f7dc2 100644 --- a/public/app/routes/ReactContainer.tsx +++ b/public/app/routes/ReactContainer.tsx @@ -16,7 +16,7 @@ function WrapInProvider(store, Component, props) { export function reactContainer($route) { return { restrict: 'E', - template: '

hasad

', + template: '', link(scope, elem) { let component = $route.current.locals.component; let props = {}; diff --git a/public/app/routes/bundle_loader.ts b/public/app/routes/bundle_loader.ts deleted file mode 100644 index e4e345b49fc..00000000000 --- a/public/app/routes/bundle_loader.ts +++ /dev/null @@ -1,26 +0,0 @@ -export class BundleLoader { - lazy: any; - - constructor(bundleName) { - var defer = null; - - this.lazy = [ - '$q', - '$route', - '$rootScope', - ($q, $route, $rootScope) => { - if (defer) { - return defer.promise; - } - - defer = $q.defer(); - - System.import(bundleName).then(() => { - defer.resolve(); - }); - - return defer.promise; - }, - ]; - } -} diff --git a/public/app/routes/routes.ts b/public/app/routes/routes.ts index 592e56dfda7..ab6b74b1492 100644 --- a/public/app/routes/routes.ts +++ b/public/app/routes/routes.ts @@ -1,6 +1,6 @@ import './dashboard_loaders'; import './ReactContainer'; -import ServerStats from 'app/containers/ServerStats'; +import { ServerStats } from 'app/containers/ServerStats/ServerStats'; /** @ngInject **/ export function setupAngularRoutes($routeProvider, $locationProvider) { diff --git a/public/app/stores/NavStore/NavStore.ts b/public/app/stores/NavStore/NavStore.ts new file mode 100644 index 00000000000..375a8a27fc6 --- /dev/null +++ b/public/app/stores/NavStore/NavStore.ts @@ -0,0 +1,74 @@ +import { types } from 'mobx-state-tree'; +import config from 'app/core/config'; +import _ from 'lodash'; + +export const NavItem = types.model('NavItem', { + id: types.identifier(types.string), + text: types.string, + url: types.optional(types.string, ''), + description: types.optional(types.string, ''), + icon: types.optional(types.string, ''), + img: types.optional(types.string, ''), + active: types.optional(types.boolean, false), + children: types.optional(types.array(types.late(() => NavItem)), []), +}); + +export const NavStore = types + .model('NavStore', { + main: types.maybe(NavItem), + node: types.maybe(NavItem), + breadcrumbs: types.optional(types.array(NavItem), []), + }) + .actions(self => ({ + load(...args) { + var children = config.bootData.navTree; + let main, node; + let breadcrumbs = []; + + for (let id of args) { + // if its a number then it's the index to use for main + if (_.isNumber(id)) { + main = breadcrumbs[id]; + break; + } + + let current = _.find(children, { id: id }); + breadcrumbs.push(current); + main = node; + node = current; + children = node.children; + } + + if (main.children) { + for (let item of main.children) { + item.active = false; + + if (item.url === node.url) { + item.active = true; + } + } + } + + self.main = NavItem.create(main); + self.node = NavItem.create(node); + + for (let item of breadcrumbs) { + self.breadcrumbs.push(NavItem.create(item)); + } + + // self.main = NavItem.create({ + // id: 'test', + // text: 'test', + // url: '/test'; + // children: [ + // { + // id: 'test', + // text: 'text', + // url: '/test', + // active: true, + // children: [] + // } + // ] + // }); + }, + })); diff --git a/public/app/stores/RootStore.ts b/public/app/stores/RootStore.ts index 55727b6ff68..c77f4378bfd 100644 --- a/public/app/stores/RootStore.ts +++ b/public/app/stores/RootStore.ts @@ -1,6 +1,7 @@ import { types } from 'mobx-state-tree'; import { SearchStore } from './SearchStore'; import { ServerStatsStore } from './ServerStatsStore'; +import { NavStore } from './NavStore/NavStore'; export const RootStore = types.model({ search: types.optional(SearchStore, { @@ -9,6 +10,7 @@ export const RootStore = types.model({ serverStats: types.optional(ServerStatsStore, { stats: [], }), + nav: types.optional(NavStore, {}), }); type IRootStoreType = typeof RootStore.Type; diff --git a/public/app/stores/ServerStatsStore.tsx b/public/app/stores/ServerStatsStore.tsx index a388fb77269..b8a3968d427 100644 --- a/public/app/stores/ServerStatsStore.tsx +++ b/public/app/stores/ServerStatsStore.tsx @@ -2,28 +2,33 @@ import { types, getEnv, flow } from 'mobx-state-tree'; export const ServerStat = types.model('ServerStat', { name: types.string, - value: types.number, + value: types.optional(types.number, 0), }); export const ServerStatsStore = types .model('ServerStatsStore', { stats: types.array(ServerStat), + error: types.optional(types.string, ''), }) .actions(self => ({ load: flow(function* load() { let backendSrv = getEnv(self).backendSrv; - let res = yield backendSrv.get('/api/admin/stats'); - - self.stats.clear(); - self.stats.push(ServerStat.create({ name: 'Total dashboards', value: res.dashboards })); - self.stats.push(ServerStat.create({ name: 'Total users', value: res.users })); - self.stats.push(ServerStat.create({ name: 'Active users (seen last 30 days)', value: res.activeUsers })); - self.stats.push(ServerStat.create({ name: 'Total orgs', value: res.orgs })); - self.stats.push(ServerStat.create({ name: 'Total playlists', value: res.playlists })); - self.stats.push(ServerStat.create({ name: 'Total snapshots', value: res.snapshots })); - self.stats.push(ServerStat.create({ name: 'Total dashboard tags', value: res.tags })); - self.stats.push(ServerStat.create({ name: 'Total starred dashboards', value: res.stars })); - self.stats.push(ServerStat.create({ name: 'Total alerts', value: res.alerts })); + try { + let res = yield backendSrv.get('/api/admin/stats'); + self.stats.clear(); + self.stats.push(ServerStat.create({ name: 'Total dashboards', value: res.dashboards })); + self.stats.push(ServerStat.create({ name: 'Total users', value: res.users })); + self.stats.push(ServerStat.create({ name: 'Active users (seen last 30 days)', value: res.activeUsers })); + self.stats.push(ServerStat.create({ name: 'Total orgs', value: res.orgs })); + self.stats.push(ServerStat.create({ name: 'Total playlists', value: res.playlists })); + self.stats.push(ServerStat.create({ name: 'Total snapshots', value: res.snapshots })); + self.stats.push(ServerStat.create({ name: 'Total dashboard tags', value: res.tags })); + self.stats.push(ServerStat.create({ name: 'Total starred dashboards', value: res.stars })); + self.stats.push(ServerStat.create({ name: 'Total alerts', value: res.alerts })); + } catch (err) { + console.log('ServerStats.load error', err); + self.error = err.toString(); + } }), }));