diff --git a/src/ts/@overflow/app/index.tsx b/src/ts/@overflow/app/index.tsx index 7126f59..61b1445 100644 --- a/src/ts/@overflow/app/index.tsx +++ b/src/ts/@overflow/app/index.tsx @@ -12,6 +12,9 @@ import Platform from '@overflow/commons/platform'; import AppContext from '@overflow/commons/context'; import * as AppContextLifecycleActions from '@overflow/commons/context/redux/action/lifecycle'; import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC'; +import ReducerManager from '@overflow/commons/redux/ReducerManager'; + + import { store, sagaMiddleware, history } from './redux/store'; import appConfig, { Config } from './config'; @@ -33,12 +36,14 @@ class Application { private store: Store; private sagaMiddleware: SagaMiddleware; private history: History; + private reducerManager: ReducerManager; public constructor() { this.config = appConfig; this.sagaMiddleware = sagaMiddleware; this.store = store; this.history = history; + this.reducerManager = new ReducerManager(); } public static Run(): void { @@ -89,16 +94,15 @@ class Application { } private initRedux(): Promise { - // state tree - // reducer - // middleware - // saga - const rpcClient = new Promise(resolve => { - this.sagaMiddleware.run(sagas); - resolve(); + const init = new Promise(resolve => { + // state tree + // reducer + // middleware + // saga + }); - return rpcClient; + return init; } private initSagaEffect(): Promise { @@ -158,9 +162,7 @@ class Application { } private displayDebugApp(): void { if (module.hot) { - // app module.hot.accept('./views/App', async () => { - // const NextApp = require('./app').App; const NextApp = (await import('./views/App')).default; ReactDOM.render( diff --git a/src/ts/@overflow/app/redux/store.ts b/src/ts/@overflow/app/redux/store.ts index 6e07a57..211c88f 100644 --- a/src/ts/@overflow/app/redux/store.ts +++ b/src/ts/@overflow/app/redux/store.ts @@ -19,8 +19,6 @@ import { composeWithDevTools, } from 'redux-devtools-extension/logOnlyInProduction'; -import reduxLogger from 'redux-logger'; - import reducer from './reducer'; import State from './state'; diff --git a/src/ts/@overflow/app/views/layout/AppLayout.tsx b/src/ts/@overflow/app/views/layout/AppLayout.tsx index 1114aa2..a15026f 100644 --- a/src/ts/@overflow/app/views/layout/AppLayout.tsx +++ b/src/ts/@overflow/app/views/layout/AppLayout.tsx @@ -3,7 +3,6 @@ import { Redirect, RouteComponentProps, RouteProps, Route, Switch } from 'react- import { Container, Menu, Sidebar, Segment, Icon, Breadcrumb, Grid, Dropdown } from 'semantic-ui-react'; import { Header } from './Header'; import { Footer } from './Footer'; -import { TitleBar } from './TitleBar'; import LeftMenu from './LeftMenu'; import Home from '../Home'; @@ -38,7 +37,6 @@ export class AppLayout extends React.Component {
- diff --git a/src/ts/@overflow/app/views/layout/ProbeDetailLayout.tsx b/src/ts/@overflow/app/views/layout/ProbeDetailLayout.tsx index 2326eb3..213a47f 100644 --- a/src/ts/@overflow/app/views/layout/ProbeDetailLayout.tsx +++ b/src/ts/@overflow/app/views/layout/ProbeDetailLayout.tsx @@ -13,6 +13,7 @@ import ProbeHistory from '../../views/monitoring/probe/History'; export interface Props extends RouteComponentProps { } export interface State { + currUrl: string; } export class ProbeDetailLayout extends React.Component { @@ -20,6 +21,7 @@ export class ProbeDetailLayout extends React.Component { constructor(props: Props, context: State) { super(props, context); this.state = { + currUrl: this.props.location.pathname, }; } @@ -28,11 +30,11 @@ export class ProbeDetailLayout extends React.Component { const sub = [ { 'name': 'Info', - 'path': `${this.props.location.pathname}`, + 'path': this.state.currUrl, }, { 'name': 'History', - 'path': `${this.props.location.pathname}/history`, + 'path': this.state.currUrl + '/history', }, ]; return ( @@ -40,7 +42,7 @@ export class ProbeDetailLayout extends React.Component {
- + diff --git a/src/ts/@overflow/app/views/layout/TitleBar.tsx b/src/ts/@overflow/app/views/layout/TitleBar.tsx index 8db5ac5..4a99108 100644 --- a/src/ts/@overflow/app/views/layout/TitleBar.tsx +++ b/src/ts/@overflow/app/views/layout/TitleBar.tsx @@ -4,6 +4,7 @@ import { Grid, Container, Breadcrumb, Header, Menu, Input, Segment } from 'seman export interface StateProps { sub: any; + title: any; } export interface DispatchProps { @@ -13,6 +14,7 @@ export interface DispatchProps { export type Props = StateProps & DispatchProps; export interface State { + selected: number; } export class TitleBar extends React.Component { @@ -20,12 +22,17 @@ export class TitleBar extends React.Component { constructor(props: any, context: any) { super(props, context); this.state = { + selected: 0, }; } - public handleMenu(menu:any): any { - console.log(menu.path); - this.props.onRedirect(menu.path); + public handleMenu(menu: any, index: number): any { + this.setState({ + selected: index, + }); + if (this.state.selected !== index) { + this.props.onRedirect(menu.path); + } } public renderSubMenus(): JSX.Element { @@ -35,15 +42,15 @@ export class TitleBar extends React.Component { } return subMenus.map((menu: any, index: number) => ( - + )); } public render(): JSX.Element { return ( - -
TEMP + +
{this.props.title} Home diff --git a/src/ts/@overflow/app/views/layout/TitleBarContainer.tsx b/src/ts/@overflow/app/views/layout/TitleBarContainer.tsx index 5ca518a..b56d32c 100644 --- a/src/ts/@overflow/app/views/layout/TitleBarContainer.tsx +++ b/src/ts/@overflow/app/views/layout/TitleBarContainer.tsx @@ -10,6 +10,7 @@ import { push as routerPush } from 'react-router-redux'; export function mapStateToProps(state: any, ownProps: any): StateProps { return { sub: ownProps.sub, + title: ownProps.title, }; } diff --git a/src/ts/@overflow/app/views/monitoring/probe/List.tsx b/src/ts/@overflow/app/views/monitoring/probe/List.tsx index 345de7a..f43e073 100644 --- a/src/ts/@overflow/app/views/monitoring/probe/List.tsx +++ b/src/ts/@overflow/app/views/monitoring/probe/List.tsx @@ -4,6 +4,7 @@ import ProbeListContainer from '@overflow/probe/react/ProbeList'; import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC'; import AppContext from '@overflow/commons/context'; import inject from '@overflow/commons/context/decorator/inject'; +import TitleBarContainer from '@overflow/app/views/layout/TitleBarContainer'; class ProbeList extends React.Component, object> { @inject() @@ -17,7 +18,10 @@ class ProbeList extends React.Component, object> { public render(): JSX.Element { return ( - +
+ + +
); } } diff --git a/src/ts/@overflow/commons/redux/ReducerManager.ts b/src/ts/@overflow/commons/redux/ReducerManager.ts new file mode 100644 index 0000000..d136ecc --- /dev/null +++ b/src/ts/@overflow/commons/redux/ReducerManager.ts @@ -0,0 +1,56 @@ +import Action from './Action'; +import * as Redux from 'redux'; + +interface ReducerItem { + initialState: State; + reducer: Redux.Reducer; +} + +class ReducerManager { + private reducerMap: Map[]>; + + public constructor() { + this.reducerMap = new Map(); + } + + public putReducer(type: string, initialState: State, reducer: Redux.Reducer): void { + let reducerItems: ReducerItem[]; + if (!this.reducerMap.has(type)) { + reducerItems = new Array(); + this.reducerMap.set(type, reducerItems); + } else { + reducerItems = this.reducerMap.get(type); + } + let reducerItem: ReducerItem = { + initialState: initialState, + reducer: reducer, + }; + + reducerItems.push(reducerItem); + } + + public putReducers(initialState: State, handlers: Redux.ReducersMapObject): void { + for(let type in handlers) { + if (handlers.hasOwnProperty(type)) { + this.putReducer(type, initialState, handlers[type]); + } + } + } + + public reducer(state: State, action: A): State { + const actionType = action.type; + if (this.reducerMap.has(actionType)) { + let reducerItems = this.reducerMap.get(actionType); + for (let reducerItem of reducerItems) { + let initialState = reducerItem.initialState; + let reducer = reducerItem.reducer; + state = reducer(state, action); + } + } else { + console.log(`Reducer for [${actionType}] is not loaded.`); + } + return state; + } +} + +export default ReducerManager; diff --git a/src/ts/@overflow/commons/redux/StateTreeManager.ts b/src/ts/@overflow/commons/redux/StateTreeManager.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/ts/@overflow/commons/redux/createReducer.ts b/src/ts/@overflow/commons/redux/createReducer.ts new file mode 100644 index 0000000..1058e05 --- /dev/null +++ b/src/ts/@overflow/commons/redux/createReducer.ts @@ -0,0 +1,19 @@ +import Action from './Action'; +import * as Redux from 'redux'; + +// export type Reducer = (state: S, action: A) => S; + +// export interface ReducersMapObject { +// [key: string]: Reducer; +// } + +const createReducer = (initialState: State, handlers: Redux.ReducersMapObject): Redux.Reducer => { + return (state: State = initialState, action: A): State => { + if (handlers[action.type]) { + return handlers[action.type](state, action); + } + return state; + }; +}; + +export default createReducer; diff --git a/src/ts/@overflow/member/redux/reducer/signIn.ts b/src/ts/@overflow/member/redux/reducer/signIn.ts index f0ffafc..d06efb4 100644 --- a/src/ts/@overflow/member/redux/reducer/signIn.ts +++ b/src/ts/@overflow/member/redux/reducer/signIn.ts @@ -1,4 +1,5 @@ import Action from '@overflow/commons/redux/Action'; +import createReducer from '@overflow/commons/redux/createReducer'; import Member from '@overflow/member/api/model/Member'; import * as SigninActionTypes from '../action/signIn'; @@ -6,24 +7,34 @@ import SigninState, { defaultState as signinDefaultState } from '../state/SignIn export type reducer = (state: SigninState, action: Action) => SigninState; -export const reducer: reducer = (state: SigninState = signinDefaultState, action: Action): SigninState => { - switch (action.type) { - case SigninActionTypes.REQUEST_SUCCESS: - { - let member = (>action).payload; +export const reducer: reducer = createReducer(signinDefaultState, { + [SigninActionTypes.REQUEST_SUCCESS]: (state: SigninState, action: Action): SigninState => { + return state; + }, + [SigninActionTypes.REQUEST_FAILURE]: (state: SigninState, action: Action): SigninState => { + return state; + }, +}); - const aaa: SigninState = { - ...state, - isAuthenticated: true, - }; - return aaa; - } - case SigninActionTypes.REQUEST_FAILURE: - { - return state; - } - default: - return state; - } -}; +// export const reducer: reducer = (state: SigninState = signinDefaultState, action: Action): SigninState => { +// switch (action.type) { +// case SigninActionTypes.REQUEST_SUCCESS: +// { +// let member = (>action).payload; + +// const aaa: SigninState = { +// ...state, +// isAuthenticated: true, +// }; + +// return aaa; +// } +// case SigninActionTypes.REQUEST_FAILURE: +// { +// return state; +// } +// default: +// return state; +// } +// };