Commit cf58eea1 by Torkel Ödegaard

redux: wip progress for using redux

parent ad9f38ae
...@@ -72,6 +72,7 @@ email = "email" ...@@ -72,6 +72,7 @@ email = "email"
[[servers.group_mappings]] [[servers.group_mappings]]
group_dn = "cn=admins,ou=groups,dc=grafana,dc=org" group_dn = "cn=admins,ou=groups,dc=grafana,dc=org"
org_role = "Admin" org_role = "Admin"
grafana_admin = true
# The Grafana organization database id, optional, if left out the default org (id 1) will be used # The Grafana organization database id, optional, if left out the default org (id 1) will be used
# org_id = 1 # org_id = 1
......
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);
import { initNav } from './navModel';
export { initNav };
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,
});
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { NavModel, NavModelItem } from '../../nav_model_srv'; import { NavModel, NavModelItem } from 'app/types';
import classNames from 'classnames'; import classNames from 'classnames';
import appEvents from 'app/core/app_events'; import appEvents from 'app/core/app_events';
import { toJS } from 'mobx'; import { toJS } from 'mobx';
......
...@@ -10,7 +10,7 @@ import { createStore } from 'app/stores/store'; ...@@ -10,7 +10,7 @@ import { createStore } from 'app/stores/store';
import colors from 'app/core/utils/colors'; import colors from 'app/core/utils/colors';
import { BackendSrv, setBackendSrv } from 'app/core/services/backend_srv'; import { BackendSrv, setBackendSrv } from 'app/core/services/backend_srv';
import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
import { configureStore } from 'app/store/configureStore'; import { configureStore } from 'app/stores/configureStore';
export class GrafanaCtrl { export class GrafanaCtrl {
/** @ngInject */ /** @ngInject */
......
import navModel from './navModel';
export default {
navModel,
};
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;
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));
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Provider } from 'mobx-react'; import { Provider } from 'mobx-react';
import { Provider as ReduxProvider } from 'react-redux';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import { store } from 'app/stores/store'; import { store } from 'app/stores/store';
import { store as reduxStore } from 'app/stores/configureStore';
import { BackendSrv } from 'app/core/services/backend_srv'; import { BackendSrv } from 'app/core/services/backend_srv';
import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
import { ContextSrv } from 'app/core/services/context_srv'; import { ContextSrv } from 'app/core/services/context_srv';
function WrapInProvider(store, Component, props) { function WrapInProvider(store, Component, props) {
return ( return (
<Provider {...store}> <ReduxProvider store={reduxStore}>
<Component {...props} /> <Provider {...store}>
</Provider> <Component {...props} />
</Provider>
</ReduxProvider>
); );
} }
......
import './dashboard_loaders'; import './dashboard_loaders';
import './ReactContainer'; 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 AlertRuleList from 'app/containers/AlertRuleList/AlertRuleList';
import FolderSettings from 'app/containers/ManageDashboards/FolderSettings'; import FolderSettings from 'app/containers/ManageDashboards/FolderSettings';
import FolderPermissions from 'app/containers/ManageDashboards/FolderPermissions'; import FolderPermissions from 'app/containers/ManageDashboards/FolderPermissions';
......
//
// 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 },
});
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;
}
}
};
import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import thunk from 'redux-thunk'; import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger'; import { createLogger } from 'redux-logger';
import { navReducer } from './nav/reducers'; import sharedReducers from 'app/core/reducers';
const rootReducer = combineReducers({ const rootReducer = combineReducers({
nav: navReducer, ...sharedReducers
}); });
export let store; export let store;
......
import { NavModel } from './navModel';
export interface ContainerProps {
navModel: NavModel;
initNav: (...args: string[]) => void;
}
import { NavModel, NavModelItem } from './navModel';
import { ContainerProps } from './container';
export { NavModel, NavModelItem, ContainerProps };
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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment