浏览代码

redux: wip progress for using redux

Torkel Ödegaard 7 年之前
父节点
当前提交
cf58eea1db

+ 1 - 0
docker/blocks/openldap/ldap_dev.toml

@@ -72,6 +72,7 @@ email =  "email"
 [[servers.group_mappings]]
 group_dn = "cn=admins,ou=groups,dc=grafana,dc=org"
 org_role = "Admin"
+grafana_admin = true
 # The Grafana organization database id, optional, if left out the default org (id 1) will be used
 # org_id = 1
 

+ 0 - 52
public/app/containers/ServerStats/ServerStats.tsx

@@ -1,52 +0,0 @@
-import React from 'react';
-import { hot } from 'react-hot-loader';
-import { inject, observer } from 'mobx-react';
-import PageHeader from 'app/core/components/PageHeader/PageHeader';
-import { store } from 'app/store/configureStore';
-import { setNav } from 'app/store/nav/actions';
-import ContainerProps from 'app/containers/ContainerProps';
-
-@inject('nav', 'serverStats')
-@observer
-export class ServerStats extends React.Component<ContainerProps, any> {
-  constructor(props) {
-    super(props);
-    const { nav, serverStats } = this.props;
-
-    nav.load('cfg', 'admin', 'server-stats');
-    serverStats.load();
-
-    store.dispatch(setNav('new', { asd: 'tasd' }));
-  }
-
-  render() {
-    const { nav, serverStats } = this.props;
-    return (
-      <div>
-        <PageHeader model={nav as any} />
-        <div className="page-container page-body">
-          <table className="filter-table form-inline">
-            <thead>
-              <tr>
-                <th>Name</th>
-                <th>Value</th>
-              </tr>
-            </thead>
-            <tbody>{serverStats.stats.map(StatItem)}</tbody>
-          </table>
-        </div>
-      </div>
-    );
-  }
-}
-
-function StatItem(stat) {
-  return (
-    <tr key={stat.name}>
-      <td>{stat.name}</td>
-      <td>{stat.value}</td>
-    </tr>
-  );
-}
-
-export default hot(module)(ServerStats);

+ 3 - 0
public/app/core/actions/index.ts

@@ -0,0 +1,3 @@
+import { initNav } from './navModel';
+
+export { initNav };

+ 11 - 0
public/app/core/actions/navModel.ts

@@ -0,0 +1,11 @@
+export type Action = InitNavModelAction;
+
+export interface InitNavModelAction {
+  type: 'INIT_NAV_MODEL';
+  args: string[];
+}
+
+export const initNav = (...args: string[]): InitNavModelAction => ({
+  type: 'INIT_NAV_MODEL',
+  args: args,
+});

+ 1 - 1
public/app/core/components/PageHeader/PageHeader.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import { observer } from 'mobx-react';
-import { NavModel, NavModelItem } from '../../nav_model_srv';
+import { NavModel, NavModelItem } from 'app/types';
 import classNames from 'classnames';
 import appEvents from 'app/core/app_events';
 import { toJS } from 'mobx';

+ 1 - 1
public/app/core/components/grafana_app.ts

@@ -10,7 +10,7 @@ import { createStore } from 'app/stores/store';
 import colors from 'app/core/utils/colors';
 import { BackendSrv, setBackendSrv } from 'app/core/services/backend_srv';
 import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
-import { configureStore } from 'app/store/configureStore';
+import { configureStore } from 'app/stores/configureStore';
 
 export class GrafanaCtrl {
   /** @ngInject */

+ 5 - 0
public/app/core/reducers/index.ts

@@ -0,0 +1,5 @@
+import navModel from './navModel';
+
+export default {
+  navModel,
+};

+ 64 - 0
public/app/core/reducers/navModel.ts

@@ -0,0 +1,64 @@
+import { Action } from 'app/core/actions/navModel';
+import { NavModel, NavModelItem } 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 {
+    breadcrumbs: [node],
+    node: node,
+    main: node,
+  };
+}
+
+export const initialState: NavModel = getNotFoundModel();
+
+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,
+        breadcrumbs: [],
+      };
+    }
+  }
+
+  return state;
+};
+
+export default navModelReducer;

+ 0 - 0
public/app/containers/ServerStats/ServerStats.test.tsx → public/app/features/server-stats/ServerStats.test.tsx


+ 69 - 0
public/app/features/server-stats/ServerStats.tsx

@@ -0,0 +1,69 @@
+import React 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 PageHeader from 'app/core/components/PageHeader/PageHeader';
+
+interface Props extends ContainerProps {}
+
+export class ServerStats extends React.Component<Props, any> {
+  constructor(props) {
+    super(props);
+
+    this.props.initNav('cfg', 'admin', 'server-stats');
+    // const { nav, serverStats } = this.props;
+    //
+    // nav.load('cfg', 'admin', 'server-stats');
+    // serverStats.load();
+    //
+    // store.dispatch(setNav('new', { asd: 'tasd' }));
+  }
+
+  render() {
+    const { navModel } = this.props;
+    console.log('render', navModel);
+    return (
+      <div>
+        <PageHeader model={navModel} />
+        <h2>aasd</h2>
+      </div>
+    );
+    // const { nav, serverStats } = this.props;
+    // return (
+    //   <div>
+    //     <PageHeader model={nav as any} />
+    //     <div className="page-container page-body">
+    //       <table className="filter-table form-inline">
+    //         <thead>
+    //           <tr>
+    //             <th>Name</th>
+    //             <th>Value</th>
+    //           </tr>
+    //         </thead>
+    //         <tbody>{serverStats.stats.map(StatItem)}</tbody>
+    //       </table>
+    //     </div>
+    //   </div>
+    // );
+  }
+}
+
+function StatItem(stat) {
+  return (
+    <tr key={stat.name}>
+      <td>{stat.name}</td>
+      <td>{stat.value}</td>
+    </tr>
+  );
+}
+
+const mapStateToProps = state => ({
+  navModel: state.navModel,
+});
+
+const mapDispatchToProps = {
+  initNav,
+};
+
+export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(ServerStats));

+ 0 - 0
public/app/containers/ServerStats/__snapshots__/ServerStats.test.tsx.snap → public/app/features/server-stats/__snapshots__/ServerStats.test.tsx.snap


+ 7 - 3
public/app/routes/ReactContainer.tsx

@@ -1,18 +1,22 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
 import { Provider } from 'mobx-react';
+import { Provider as ReduxProvider } from 'react-redux';
 
 import coreModule from 'app/core/core_module';
 import { store } from 'app/stores/store';
+import { store as reduxStore } from 'app/stores/configureStore';
 import { BackendSrv } from 'app/core/services/backend_srv';
 import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
 import { ContextSrv } from 'app/core/services/context_srv';
 
 function WrapInProvider(store, Component, props) {
   return (
-    <Provider {...store}>
-      <Component {...props} />
-    </Provider>
+    <ReduxProvider store={reduxStore}>
+      <Provider {...store}>
+        <Component {...props} />
+      </Provider>
+    </ReduxProvider>
   );
 }
 

+ 1 - 1
public/app/routes/routes.ts

@@ -1,7 +1,7 @@
 import './dashboard_loaders';
 import './ReactContainer';
 
-import ServerStats from 'app/containers/ServerStats/ServerStats';
+import ServerStats from 'app/features/server-stats/ServerStats';
 import AlertRuleList from 'app/containers/AlertRuleList/AlertRuleList';
 import FolderSettings from 'app/containers/ManageDashboards/FolderSettings';
 import FolderPermissions from 'app/containers/ManageDashboards/FolderPermissions';

+ 0 - 30
public/app/store/nav/actions.ts

@@ -1,30 +0,0 @@
-//
-// Only test actions to test redux & typescript
-//
-
-export enum ActionTypes {
-  SET_NAV = 'SET_NAV',
-  SET_QUERY = 'SET_QUERY',
-}
-
-export interface SetNavAction {
-  type: ActionTypes.SET_NAV;
-  payload: {
-    path: string;
-    query: object;
-  };
-}
-
-export interface SetQueryAction {
-  type: ActionTypes.SET_QUERY;
-  payload: {
-    query: object;
-  };
-}
-
-export type Action = SetNavAction | SetQueryAction;
-
-export const setNav = (path: string, query: object): SetNavAction => ({
-  type: ActionTypes.SET_NAV,
-  payload: { path: path, query: query },
-});

+ 0 - 30
public/app/store/nav/reducers.ts

@@ -1,30 +0,0 @@
-import { Action, ActionTypes } from './actions';
-
-export interface NavState {
-  path: string;
-  query: object;
-}
-
-const initialState: NavState = {
-  path: '/test',
-  query: {},
-};
-
-export const navReducer = (state: NavState = initialState, action: Action): NavState => {
-  switch (action.type) {
-    case ActionTypes.SET_NAV: {
-      return { ...state, path: action.payload.path, query: action.payload.query };
-    }
-
-    case ActionTypes.SET_QUERY: {
-      return {
-        ...state,
-        query: action.payload.query,
-      };
-    }
-
-    default: {
-      return state;
-    }
-  }
-};

+ 2 - 2
public/app/store/configureStore.ts → public/app/stores/configureStore.ts

@@ -1,10 +1,10 @@
 import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
 import thunk from 'redux-thunk';
 import { createLogger } from 'redux-logger';
-import { navReducer } from './nav/reducers';
+import sharedReducers from 'app/core/reducers';
 
 const rootReducer = combineReducers({
-  nav: navReducer,
+  ...sharedReducers
 });
 
 export let store;

+ 6 - 0
public/app/types/container.ts

@@ -0,0 +1,6 @@
+import { NavModel } from './navModel';
+
+export interface ContainerProps {
+  navModel: NavModel;
+  initNav: (...args: string[]) => void;
+}

+ 4 - 0
public/app/types/index.ts

@@ -0,0 +1,4 @@
+import { NavModel, NavModelItem } from './navModel';
+import { ContainerProps } from './container';
+
+export { NavModel, NavModelItem, ContainerProps };

+ 19 - 0
public/app/types/navModel.ts

@@ -0,0 +1,19 @@
+export interface NavModelItem {
+  text: string;
+  url: string;
+  subTitle?: string;
+  icon?: string;
+  img?: string;
+  id: string;
+  active?: boolean;
+  hideFromTabs?: boolean;
+  divider?: boolean;
+  children?: NavModelItem[];
+  target?: string;
+}
+
+export interface NavModel {
+  breadcrumbs: NavModelItem[];
+  main: NavModelItem;
+  node: NavModelItem;
+}