aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/package.json2
-rw-r--r--web/src/js/app.js9
-rw-r--r--web/src/js/components/eventlog.js1
-rw-r--r--web/src/js/connection.js15
-rw-r--r--web/src/js/ducks/eventLog.js29
-rw-r--r--web/src/js/ducks/list.js21
-rw-r--r--web/src/js/ducks/utils/list.js121
7 files changed, 160 insertions, 38 deletions
diff --git a/web/package.json b/web/package.json
index bb32a2dc..3bbed9e8 100644
--- a/web/package.json
+++ b/web/package.json
@@ -27,6 +27,7 @@
"react-router": "^2.4.0",
"redux": "^3.5.2",
"redux-logger": "^2.6.1",
+ "redux-thunk": "^2.1.0",
"shallowequal": "^0.2.2"
},
"devDependencies": {
@@ -52,6 +53,7 @@
"gulp-sourcemaps": "^1.6.0",
"gulp-util": "^3.0.7",
"jest": "^0.1.40",
+ "redux-thunk": "^2.1.0",
"uglifyify": "^3.0.1",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0",
diff --git a/web/src/js/app.js b/web/src/js/app.js
index fc99f1d2..b49de002 100644
--- a/web/src/js/app.js
+++ b/web/src/js/app.js
@@ -2,7 +2,9 @@ import React from "react"
import {render} from 'react-dom'
import {applyMiddleware, createStore} from 'redux'
import {Provider} from 'react-redux'
-import createLogger from 'redux-logger';
+import createLogger from 'redux-logger'
+import thunkMiddleware from 'redux-thunk'
+
import Connection from "./connection"
import {App} from "./components/proxyapp.js"
@@ -11,7 +13,10 @@ import {addLogEntry} from "./ducks/eventLog";
// logger must be last
const logger = createLogger();
-const store = createStore(rootReducer, applyMiddleware(logger));
+const store = createStore(
+ rootReducer,
+ applyMiddleware(thunkMiddleware, logger)
+);
window.onerror = function (msg) {
store.dispatch(addLogEntry(msg));
diff --git a/web/src/js/components/eventlog.js b/web/src/js/components/eventlog.js
index 95889a66..6ada58ff 100644
--- a/web/src/js/components/eventlog.js
+++ b/web/src/js/components/eventlog.js
@@ -64,7 +64,6 @@ class EventLogContents extends React.Component {
}
setHeight(id, node) {
- console.log("setHeight", id, node);
if (node && !this.heights[id]) {
const height = node.offsetHeight;
if (this.heights[id] !== height) {
diff --git a/web/src/js/connection.js b/web/src/js/connection.js
index 75c2cf25..090dbb29 100644
--- a/web/src/js/connection.js
+++ b/web/src/js/connection.js
@@ -1,6 +1,7 @@
import {ConnectionActions, EventLogActions} from "./actions.js";
import {AppDispatcher} from "./dispatcher.js";
-import * as websocketActions from "./ducks/websocket"
+import * as webSocketActions from "./ducks/websocket"
+import * as eventLogActions from "./ducks/eventLog"
export default function Connection(url, dispatch) {
if (url[0] === "/") {
@@ -9,14 +10,20 @@ export default function Connection(url, dispatch) {
var ws = new WebSocket(url);
ws.onopen = function () {
- dispatch(websocketActions.connected());
- ConnectionActions.open();
+ dispatch(webSocketActions.connected())
+ dispatch(eventLogActions.fetchLogEntries())
+ ConnectionActions.open()
//TODO: fetch stuff!
};
ws.onmessage = function (m) {
var message = JSON.parse(m.data);
AppDispatcher.dispatchServerAction(message);
- dispatch(message);
+ switch (message.type) {
+ case eventLogActions.UPDATE_LOG:
+ return dispatch(eventLogActions.updateLogEntries(message))
+ default:
+ console.warn("unknown message", message)
+ }
};
ws.onerror = function () {
ConnectionActions.error();
diff --git a/web/src/js/ducks/eventLog.js b/web/src/js/ducks/eventLog.js
index 2040711c..081a2276 100644
--- a/web/src/js/ducks/eventLog.js
+++ b/web/src/js/ducks/eventLog.js
@@ -1,8 +1,17 @@
-import getList, {ADD} from "./list"
+import makeList, {ADD} from "./utils/list"
+
const TOGGLE_FILTER = 'TOGGLE_EVENTLOG_FILTER'
const TOGGLE_VISIBILITY = 'TOGGLE_EVENTLOG_VISIBILITY'
-const UPDATE_LIST = "UPDATE_EVENTLOG"
+export const UPDATE_LOG = "UPDATE_EVENTLOG"
+
+const {
+ reduceList,
+ addToList,
+ updateList,
+ fetchList,
+} = makeList(UPDATE_LOG, "/events");
+export {updateList as updateLogEntries, fetchList as fetchLogEntries}
const defaultState = {
visible: false,
@@ -11,7 +20,7 @@ const defaultState = {
"info": true,
"web": true
},
- events: getList(),
+ events: reduceList(),
filteredEvents: [],
}
@@ -32,8 +41,8 @@ export default function reducer(state = defaultState, action) {
...state,
visible: !state.visible
}
- case UPDATE_LIST:
- const events = getList(state.events, action)
+ case UPDATE_LOG:
+ const events = reduceList(state.events, action)
return {
...state,
events,
@@ -53,9 +62,9 @@ export function toggleEventLogVisibility() {
}
let id = 0;
export function addLogEntry(message, level = "web") {
- return {
- type: UPDATE_LIST,
- cmd: ADD,
- data: {message, level, id: `log-${id++}`}
- }
+ return addToList({
+ message,
+ level,
+ id: `log-${id++}`
+ })
} \ No newline at end of file
diff --git a/web/src/js/ducks/list.js b/web/src/js/ducks/list.js
deleted file mode 100644
index 0b3771e2..00000000
--- a/web/src/js/ducks/list.js
+++ /dev/null
@@ -1,21 +0,0 @@
-export const ADD = 'add'
-
-const defaultState = {
- list: [],
- //isFetching: false,
- //updateBeforeFetch: [],
- indexOf: {},
- //views: {}
-};
-
-export default function getList(state = defaultState, action = {}) {
- switch (action.cmd) {
- case ADD:
- return {
- list: [...state.list, action.data],
- indexOf: {...state.indexOf, [action.data.id]: state.list.length},
- }
- default:
- return state
- }
-} \ No newline at end of file
diff --git a/web/src/js/ducks/utils/list.js b/web/src/js/ducks/utils/list.js
new file mode 100644
index 00000000..37b2ae3a
--- /dev/null
+++ b/web/src/js/ducks/utils/list.js
@@ -0,0 +1,121 @@
+import {fetchApi} from "../../utils";
+
+const ADD = "ADD"
+const REQUEST_LIST = "REQUEST_LIST"
+const RECEIVE_LIST = "RECEIVE_LIST"
+
+
+const defaultState = {
+ list: [],
+ isFetching: false,
+ actionsDuringFetch: [],
+ byId: {},
+ indexOf: {},
+};
+
+export default function makeList(actionType, fetchURL) {
+ function reduceList(state = defaultState, action = {}) {
+
+ if (action.type !== actionType) {
+ return state
+ }
+
+ // Handle cases where we finished fetching or are still fetching.
+ if (action.cmd === RECEIVE_LIST) {
+ let s = {
+ isFetching: false,
+ actionsDuringFetch: [],
+ list: action.list,
+ byId: {},
+ indexOf: {}
+ }
+ for (let i = 0; i < action.list.length; i++) {
+ let item = action.list[i]
+ s.byId[item.id] = item
+ s.indexOf[item.id] = i
+ }
+ for (action of state.actionsDuringFetch) {
+ s = reduceList(s, action)
+ }
+ return s
+ } else if (state.isFetching) {
+ return {
+ ...state,
+ actionsDuringFetch: [...state.actionsDuringFetch, action]
+ }
+ }
+
+ switch (action.cmd) {
+ case ADD:
+ return {
+ list: [...state.list, action.item],
+ byId: {...state.byId, [action.item.id]: action.item},
+ indexOf: {...state.indexOf, [action.item.id]: state.list.length},
+ }
+
+ case REQUEST_LIST:
+ return {
+ ...defaultState,
+ isFetching: true
+ }
+
+ default:
+ console.debug("unknown action", action.type)
+ return state
+ }
+ }
+
+ function addToList(item) {
+ return {
+ type: actionType,
+ cmd: ADD,
+ item
+ }
+ }
+
+
+ function updateList(action) {
+ /* This action creater takes all WebSocket events */
+ return dispatch => {
+ switch (action.cmd) {
+ case "add":
+ return dispatch(addToList(action.data))
+ case "reset":
+ return dispatch(fetchList())
+ default:
+ console.error("unknown list update", action)
+ }
+ }
+ }
+
+ function requestList() {
+ return {
+ type: actionType,
+ cmd: REQUEST_LIST,
+ }
+ }
+
+ function receiveList(list) {
+ return {
+ type: actionType,
+ cmd: RECEIVE_LIST,
+ list
+ }
+ }
+
+ function fetchList() {
+ return dispatch => {
+
+ dispatch(requestList())
+
+ fetchApi(fetchURL).then(response => {
+ return response.json().then(json => {
+ dispatch(receiveList(json.data))
+ })
+ })
+ }
+ }
+
+
+ return {reduceList, addToList, updateList, fetchList}
+} \ No newline at end of file