overflow_app/src/ts/@overflow/app/index.tsx

245 lines
6.0 KiB
TypeScript
Raw Normal View History

2017-06-27 13:00:55 +00:00
import * as React from 'react';
import * as ReactDOM from 'react-dom';
2017-07-25 06:06:59 +00:00
import {
applyMiddleware,
compose,
createStore,
GenericStoreEnhancer,
Middleware,
Store,
} from 'redux';
import {
Provider,
} from 'react-redux';
import {
ConnectedRouter,
routerMiddleware,
} from 'react-router-redux';
import createSagaMiddleware, {
SagaMiddleware,
2017-07-25 10:28:27 +00:00
SagaIterator,
2017-07-25 06:06:59 +00:00
} from 'redux-saga';
2017-07-25 10:28:27 +00:00
import {
fork,
} from 'redux-saga/effects';
2017-07-25 06:06:59 +00:00
import {
createHashHistory,
History,
} from 'history';
import {
AppContainer,
} from 'react-hot-loader';
2017-07-21 07:08:04 +00:00
import * as injectTapEventPlugin from 'react-tap-event-plugin';
2017-07-03 10:47:54 +00:00
2017-07-03 10:21:42 +00:00
import Platform from '@overflow/commons/platform';
2017-07-20 09:46:42 +00:00
import AppContext from '@overflow/commons/context';
import * as AppContextLifecycleActions from '@overflow/commons/context/redux/action/lifecycle';
import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC';
2017-07-25 06:06:59 +00:00
import ReducerContext from '@overflow/commons/redux/ReducerContext';
2017-07-25 10:28:27 +00:00
import { SagaWatcher } from '@overflow/commons/redux-saga';
2017-07-24 10:58:45 +00:00
2017-07-25 06:06:59 +00:00
import appConfig, { Config, ReduxState } from './config';
2017-07-20 09:46:42 +00:00
2017-07-21 05:57:12 +00:00
import App from './views/App';
2017-06-28 07:50:19 +00:00
2017-06-27 13:00:55 +00:00
injectTapEventPlugin();
2017-07-25 06:06:59 +00:00
// const isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false;
// const useReduxDevTools = window.devToolsExtension && !isProduction ? true : false;
2017-07-20 09:46:42 +00:00
2017-07-21 05:57:12 +00:00
class Application {
2017-07-25 06:06:59 +00:00
private static isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false;
private static useReduxDevTools:boolean = window.devToolsExtension && !Application.isProduction ? true : false;
2017-07-20 09:46:42 +00:00
private config: Config;
private container: HTMLElement;
private context: AppContext;
private rpcClient: WebSocketRPC;
private store: Store<any>;
private sagaMiddleware: SagaMiddleware<any>;
private history: History;
2017-07-25 06:06:59 +00:00
2017-07-20 09:46:42 +00:00
public constructor() {
this.config = appConfig;
2017-07-25 06:06:59 +00:00
this.history = createHashHistory();
2017-07-20 09:46:42 +00:00
}
2017-07-23 14:40:48 +00:00
public static Run(): void {
2017-07-21 08:10:06 +00:00
let application = new Application();
2017-07-23 14:40:48 +00:00
application.start();
2017-07-21 08:10:06 +00:00
}
private async start(): Promise<void> {
2017-07-20 09:46:42 +00:00
try {
this.container = await Platform.getAppContainer(this.config.container.placeholderID);
this.displayLoading();
this.context = await this.initContext();
2017-07-25 10:29:14 +00:00
// this.rpcClient = await this.initRpcClient();
// this.context.put(this.rpcClient);
2017-07-25 06:06:59 +00:00
await this.initRedux();
2017-07-20 09:46:42 +00:00
this.store.dispatch(AppContextLifecycleActions.initialized());
this.displayApp();
} catch (e) {
2017-07-21 05:57:12 +00:00
console.error(e);
2017-07-20 09:46:42 +00:00
this.displayError(e);
}
}
2017-07-21 08:10:06 +00:00
private initContext(): Promise<AppContext> {
2017-07-20 09:46:42 +00:00
const appContext = new Promise<AppContext>(resolve => {
const context = AppContext.getContext();
resolve(context);
});
return appContext;
}
2017-07-21 08:10:06 +00:00
private initRpcClient(): Promise<WebSocketRPC> {
2017-07-20 09:46:42 +00:00
const rpcClient = new Promise<WebSocketRPC>((resolve, reject) => {
let client = new WebSocketRPC(this.config.rpc.url);
client.initialize()
.then(() => {
resolve(client);
})
.catch((err: any) => {
reject(err);
});
});
return rpcClient;
}
2017-07-23 14:40:48 +00:00
private initRedux(): Promise<void> {
2017-07-24 10:58:45 +00:00
const init = new Promise<void>(resolve => {
// state tree
// reducer
2017-07-25 06:06:59 +00:00
for (let reducerMap of this.config.redux.reducerMaps) {
ReducerContext.putReducers(reducerMap);
}
2017-07-24 10:58:45 +00:00
// middleware
2017-07-25 06:06:59 +00:00
let middlewares: Middleware[] = new Array();
this.sagaMiddleware = createSagaMiddleware();
middlewares.push(this.sagaMiddleware);
let routerReduxMiddleware = routerMiddleware(this.history);
middlewares.push(routerReduxMiddleware);
// store
let middleware: GenericStoreEnhancer = applyMiddleware(...middlewares);
this.store = createStore(
ReducerContext.reducer,
this.config.redux.state,
Application.useReduxDevTools ? compose(middleware, window.devToolsExtension()) : middleware,
);
2017-07-24 10:58:45 +00:00
// saga
2017-07-25 10:28:27 +00:00
this.sagaMiddleware.run(this.initReduxSagaWarchers, this.config.redux.sagaWarchers);
2017-07-23 14:40:48 +00:00
resolve();
});
2017-07-25 06:06:59 +00:00
return init;
2017-07-23 14:40:48 +00:00
}
2017-07-20 09:46:42 +00:00
2017-07-25 10:28:27 +00:00
private * initReduxSagaWarchers(sagaWarchers: (SagaWatcher[])[]): SagaIterator {
for (let sagaWarcher of sagaWarchers) {
for (let warcher of sagaWarcher) {
yield fork(warcher);
}
}
}
2017-07-20 09:46:42 +00:00
private displayLoading(): void {
ReactDOM.render(
<div style={{
width: '100vw',
height: '100vh',
backgroundColor: 'white',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
<h1>Loading...</h1>
</div>,
this.container,
);
}
private displayError(e: Error): void {
ReactDOM.render(
<div style={{
width: '100vw',
height: '100vh',
backgroundColor: 'white',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
<h1>{e.message}</h1>
</div>,
this.container,
);
}
private displayApp(): void {
2017-07-25 06:06:59 +00:00
Application.isProduction ? this.displayProductionApp() : this.displayDebugApp();
2017-07-23 14:40:48 +00:00
}
private displayProductionApp(): void {
2017-07-20 09:46:42 +00:00
ReactDOM.render(
2017-07-21 07:08:04 +00:00
<Provider store={this.store}>
<ConnectedRouter history={this.history}>
<App />
</ConnectedRouter>
</Provider>,
2017-07-20 09:46:42 +00:00
this.container,
);
}
2017-07-23 14:40:48 +00:00
private displayDebugApp(): void {
if (module.hot) {
module.hot.accept('./views/App', async () => {
const NextApp = (await import('./views/App')).default;
ReactDOM.render(
<AppContainer>
<Provider store={this.store}>
<ConnectedRouter history={this.history}>
<NextApp />
</ConnectedRouter>
</Provider>
</AppContainer>
,
this.container,
);
});
}
ReactDOM.render(
<AppContainer>
<Provider store={this.store}>
<ConnectedRouter history={this.history}>
<App />
</ConnectedRouter>
</Provider>
</AppContainer>
,
this.container,
);
}
2017-07-20 09:46:42 +00:00
2017-06-21 11:24:44 +00:00
}
2017-07-21 08:10:06 +00:00
Application.Run();