From 99b2b8633db4fa3fa21d43f3e6a27694b00908e4 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 16 Jun 2016 12:20:32 +0800 Subject: [web] settings store --- web/src/js/components/ProxyApp.jsx | 33 ++-------------- web/src/js/connection.js | 6 ++- web/src/js/ducks/index.js | 2 + web/src/js/ducks/settings.js | 81 ++++++++++++++++++++++++++++++++++++++ web/src/js/store/store.js | 2 +- 5 files changed, 92 insertions(+), 32 deletions(-) create mode 100644 web/src/js/ducks/settings.js (limited to 'web/src/js') diff --git a/web/src/js/components/ProxyApp.jsx b/web/src/js/components/ProxyApp.jsx index 81272268..d7f640a3 100644 --- a/web/src/js/components/ProxyApp.jsx +++ b/web/src/js/components/ProxyApp.jsx @@ -7,7 +7,6 @@ import { Splitter } from "./common.js" import Header from "./Header" import EventLog from "./EventLog" import Footer from "./Footer" -import { SettingsStore } from "../store/store.js" import { Key } from "../utils.js" class ProxyAppMain extends Component { @@ -24,17 +23,9 @@ class ProxyAppMain extends Component { constructor(props, context) { super(props, context) - this.settingsStore = new SettingsStore() - - // Default Settings before fetch - _.extend(this.settingsStore.dict, {}) - - this.state = { settings: this.settingsStore.dict } - this.focus = this.focus.bind(this) this.onKeyDown = this.onKeyDown.bind(this) this.updateLocation = this.updateLocation.bind(this) - this.onSettingsChange = this.onSettingsChange.bind(this) } /** @@ -61,29 +52,11 @@ class ProxyAppMain extends Component { } /** - * @todo remove settings store * @todo connect websocket here * @todo listen to window's key events */ componentDidMount() { this.focus() - this.settingsStore.addListener("recalculate", this.onSettingsChange) - } - - /** - * @todo remove settings store - * @todo disconnect websocket here - * @todo stop listening to window's key events - */ - componentWillUnmount() { - this.settingsStore.removeListener("recalculate", this.onSettingsChange) - } - - /** - * @todo move to actions - */ - onSettingsChange() { - this.setState({ settings: this.settingsStore.dict }) } /** @@ -143,8 +116,7 @@ class ProxyAppMain extends Component { } render() { - const { showEventLog, location, children } = this.props - const { settings } = this.state + const { showEventLog, location, children, settings } = this.props const query = this.getQuery() return (
@@ -165,6 +137,7 @@ class ProxyAppMain extends Component { export default connect( state => ({ - showEventLog: state.eventLog.visible + showEventLog: state.eventLog.visible, + settings: state.settings.settings, }) )(ProxyAppMain) diff --git a/web/src/js/connection.js b/web/src/js/connection.js index 5961909e..a2582288 100644 --- a/web/src/js/connection.js +++ b/web/src/js/connection.js @@ -3,6 +3,7 @@ import {AppDispatcher} from "./dispatcher.js"; import * as webSocketActions from "./ducks/websocket" import * as eventLogActions from "./ducks/eventLog" import * as flowActions from "./ducks/flows" +import * as settingsActions from './ducks/settings' export default function Connection(url, dispatch) { if (url[0] === "/") { @@ -12,6 +13,7 @@ export default function Connection(url, dispatch) { var ws = new WebSocket(url); ws.onopen = function () { dispatch(webSocketActions.connected()) + dispatch(settingsActions.fetch()) dispatch(flowActions.fetchFlows()) // workaround to make sure that our state is already available. .then(() => { @@ -28,6 +30,8 @@ export default function Connection(url, dispatch) { return dispatch(eventLogActions.updateLogEntries(message)) case flowActions.UPDATE_FLOWS: return dispatch(flowActions.updateFlows(message)) + case settingsActions.WS_MSG_TYPE: + return dispatch(settingsActions.handleWsMsg(message)) default: console.warn("unknown message", message) } @@ -42,4 +46,4 @@ export default function Connection(url, dispatch) { dispatch(webSocketActions.disconnected()); }; return ws; -} \ No newline at end of file +} diff --git a/web/src/js/ducks/index.js b/web/src/js/ducks/index.js index fee4d792..ffde1a64 100644 --- a/web/src/js/ducks/index.js +++ b/web/src/js/ducks/index.js @@ -2,12 +2,14 @@ import {combineReducers} from 'redux' import eventLog from './eventLog' import websocket from './websocket' import flows from './flows' +import settings from './settings' import ui from './ui' const rootReducer = combineReducers({ eventLog, websocket, flows, + settings, ui }) diff --git a/web/src/js/ducks/settings.js b/web/src/js/ducks/settings.js new file mode 100644 index 00000000..8513c2f1 --- /dev/null +++ b/web/src/js/ducks/settings.js @@ -0,0 +1,81 @@ +import { StoreCmds } from '../actions' + +export const WS_MSG_TYPE = 'settings' +export const WS_MSG_CMD_RESET = 'reset' +export const WS_MSG_CMD_UPDATE = 'update' + +export const BEGIN_FETCH = 'SETTINGS_BEGIN_FETCH' +export const FETCH_SETTINGS = 'SETTINGS_FETCH_SETTINGS' +export const FETCH_ERROR = 'SETTINGS_FETCH_ERROR' +export const RECV_WS_MSG = 'SETTINGS_RECV_WS_MSG' + +const defaultState = { settings: {}, pendings: null, req: null } + +function reduceData(data, action) { + switch (action.cmd) { + + case WS_MSG_CMD_RESET: + return action.data || {} + + case WS_MSG_CMD_UPDATE: + return _.merge({}, data.settings, action.data) + + default: + return data + } +} + +export default function reduce(state = defaultState, action) { + switch (action.type) { + + case BEGIN_FETCH: + return { ...state, pendings: [], req: action.req } + + case FETCH_SETTINGS: + const pendings = state.pendings || [] + return { ...state, pendings: null, settings: pendings.reduce(reduceData, data) } + + case RECV_WS_MSG: + if (state.pendings) { + return { ...state, pendings: state.pendings.concat(action) } + } + return { ...state, settings: reduceData(state.settings, action) } + + default: + return state + } +} + +export function fetch() { + return dispatch => { + const req = $.getJSON('/' + this.type) + .done(msg => dispatch(reset(msg.data))) + .fail(error => dispatch(handleFetchError(error))); + + dispatch({ type: BEGIN_FETCH, req }) + + return req + } +} + +export function handleWsMsg(msg) { + return (dispatch, getState) => { + if (msg.cmd === STORE_CMDS_RESET) { + const req = getState().settings.req + if (req) { + req.abort() + } + return dispatch(reset(msg.data)) + } + dispatch({ type: RECV_WS_MSG, cmd: msg.cmd, data: msg.data }) + } +} + +export function reset(data) { + return { type: FETCH_SETTINGS, data } +} + +export function handleFetchError(error) { + console.error(error) + return { type: FETCH_ERROR, error } +} diff --git a/web/src/js/store/store.js b/web/src/js/store/store.js index f3e2074f..2744a6fa 100644 --- a/web/src/js/store/store.js +++ b/web/src/js/store/store.js @@ -93,4 +93,4 @@ _.extend(LiveDictStore.prototype, DictStore.prototype, LiveStoreMixin.prototype) export function SettingsStore() { return new LiveDictStore(ActionTypes.SETTINGS_STORE); -} \ No newline at end of file +} -- cgit v1.2.3