aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/ducks
diff options
context:
space:
mode:
authorJason <jason.daurus@gmail.com>2016-06-23 00:17:35 +0800
committerJason <jason.daurus@gmail.com>2016-06-23 00:17:35 +0800
commita42512a1cc1d84cd056d016bbcac9b1a66c3f05a (patch)
tree18db46c82aa25efd04c90f9c46330d6e3ac72cea /web/src/js/ducks
parent42f433e395beafbf8eab6d04a84a52580c5e8cda (diff)
downloadmitmproxy-a42512a1cc1d84cd056d016bbcac9b1a66c3f05a.tar.gz
mitmproxy-a42512a1cc1d84cd056d016bbcac9b1a66c3f05a.tar.bz2
mitmproxy-a42512a1cc1d84cd056d016bbcac9b1a66c3f05a.zip
[web] finish utils/list
Diffstat (limited to 'web/src/js/ducks')
-rw-r--r--web/src/js/ducks/eventLog.js40
-rw-r--r--web/src/js/ducks/utils/list.js262
-rw-r--r--web/src/js/ducks/websocket.js4
3 files changed, 153 insertions, 153 deletions
diff --git a/web/src/js/ducks/eventLog.js b/web/src/js/ducks/eventLog.js
index 31dc82ea..86a9effb 100644
--- a/web/src/js/ducks/eventLog.js
+++ b/web/src/js/ducks/eventLog.js
@@ -1,15 +1,17 @@
import { fetchApi as fetch } from '../utils'
+import { CMD_RESET as WS_CMD_RESET } from './websocket'
import reduceList, * as listActions from './utils/list'
-export const TOGGLE_FILTER = 'EVENTLOG_TOGGLE_FILTER'
export const TOGGLE_VISIBILITY = 'EVENTLOG_TOGGLE_VISIBILITY'
+export const TOGGLE_FILTER = 'EVENTLOG_TOGGLE_FILTER'
export const ADD = 'EVENTLOG_ADD'
-export const UPDATE = 'EVENTLOG_UPDATE'
+export const WS_MSG = 'EVENTLOG_WS_MSG'
export const REQUEST = 'EVENTLOG_REQUEST'
export const RECEIVE = 'EVENTLOG_RECEIVE'
export const ERROR = 'EVENTLOG_ERROR'
const defaultState = {
+ logId: 0,
visible: false,
filters: { debug: false, info: true, web: true },
list: reduceList(undefined, { type: Symbol('EVENTLOG_INIT_LIST') })
@@ -32,19 +34,36 @@ export default function reduce(state = defaultState, action) {
case ADD:
return {
...state,
- list: reduceList(state.list, listActions.add({ message: action.message, level: action.level }))
+ logId: state.logId + 1,
+ list: reduceList(state.list, listActions.add({
+ id: `log-${state.logId}`,
+ message: action.message,
+ level: action.level,
+ }))
+ }
+
+ case WS_MSG:
+ return {
+ ...state,
+ list: reduceList(state.list, listActions.handleWsMsg(action.msg))
}
- case UPDATE:
+ case REQUEST:
return {
...state,
- list: reduceList(state.list, listActions.update(action))
+ list: reduceList(state.list, listActions.request())
}
case RECEIVE:
return {
...state,
- list: reduceList(state.list, listActions.reset(action.list))
+ list: reduceList(state.list, listActions.receive(action.list))
+ }
+
+ case FETCH_ERROR:
+ return {
+ ...state,
+ list: reduceList(state.list, listActions.fetchError(action.error))
}
default:
@@ -84,14 +103,7 @@ export function handleWsMsg(msg) {
if (msg.cmd === WS_CMD_RESET) {
return fetch()
}
- return update(msg.cmd, msg.data)
-}
-
-/**
- * @private
- */
-export function update(cmd, data) {
- return { type: UPDATE, cmd, data }
+ return { type: WS_MSG, msg }
}
/**
diff --git a/web/src/js/ducks/utils/list.js b/web/src/js/ducks/utils/list.js
index a830fe99..1c1d9692 100644
--- a/web/src/js/ducks/utils/list.js
+++ b/web/src/js/ducks/utils/list.js
@@ -1,166 +1,150 @@
-import {fetchApi} from "../../utils"
-
-export const ADD = "ADD"
-export const UPDATE = "UPDATE"
-export const REMOVE = "REMOVE"
-export const REQUEST_LIST = "REQUEST_LIST"
-export const RECEIVE_LIST = "RECEIVE_LIST"
-
-
+import * as websocketActions from './websocket'
+
+export const UPDATE_FILTER = 'LIST_UPDATE_FILTER'
+export const UPDATE_SORTER = 'LIST_UPDATE_SORTER'
+export const ADD = 'LIST_ADD'
+export const UPDATE = 'LIST_UPDATE'
+export const REMOVE = 'LIST_REMOVE'
+export const UNKNOWN_CMD = 'LIST_UNKNOWN_CMD'
+export const REQUEST = 'LIST_REQUEST'
+export const RECEIVE = 'LIST_RECEIVE'
+export const FETCH_ERROR = 'LIST_FETCH_ERROR'
+
+export const SYM_FILTER = Symbol('LIST_SYM_FILTER')
+export const SYM_SORTER = Symbol('LIST_SYM_SORTER')
+export const SYM_PENDING = Symbol('LIST_SYM_PENDING')
+
+// @todo add indexOf map if necessary
const defaultState = {
- list: [],
- isFetching: false,
- actionsDuringFetch: [],
+ raw: [],
+ data: [],
byId: {},
- indexOf: {},
+ isFetching: false,
+ [SYM_FILTER]: () => true,
+ [SYM_SORTER]: () => 0,
+ [SYM_PENDING]: [],
}
-export default function makeList(actionType, fetchURL) {
- function reduceList(state = defaultState, action = {}) {
-
- if (action.type !== actionType) {
- return state
+export default function reduce(state = defaultState, action) {
+ if (state.isFetching && action.type !== RECEIVE) {
+ return {
+ ...state,
+ [SYM_PENDING]: [...state[SYM_PENDING], action]
}
+ }
- // 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: {}
+ switch (action.type) {
+
+ case UPDATE_FILTER:
+ return {
+ ...state,
+ [SYM_FILTER]: action.filter,
+ data: state.raw.filter(action.filter).sort(state[SYM_SORTER]),
}
- for (let i = 0; i < action.list.length; i++) {
- let item = action.list[i]
- s.byId[item.id] = item
- s.indexOf[item.id] = i
+
+ case UPDATE_SORTER:
+ return {
+ ...state,
+ [SYM_SORTER]: action.sorter,
+ data: state.data.slice().sort(state[SYM_SORTER]),
}
- for (action of state.actionsDuringFetch) {
- s = reduceList(s, action)
+
+ case ADD:
+ let data = state.data
+ if (state[SYM_FILTER](action.item)) {
+ data = [...state.data, action.item].sort(state[SYM_SORTER])
}
- return s
- } else if (state.isFetching) {
return {
...state,
- actionsDuringFetch: [...state.actionsDuringFetch, action]
+ data,
+ raw: [...state.raw, action.item],
+ byId: { ...state.byId, [action.item.id]: action.item },
}
- }
- let list, itemIndex
- 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 UPDATE:
-
- list = [...state.list]
- itemIndex = state.indexOf[action.item.id]
- list[itemIndex] = action.item
- return {
- ...state,
- list,
- byId: {...state.byId, [action.item.id]: action.item},
- }
-
- case REMOVE:
- list = [...state.list]
- itemIndex = state.indexOf[action.item.id]
- list.splice(itemIndex, 1)
- return {
- ...state,
- list,
- byId: {...state.byId, [action.item.id]: undefined},
- indexOf: {...state.indexOf, [action.item.id]: undefined},
- }
-
- case REQUEST_LIST:
- return {
- ...state,
- isFetching: true
- }
-
- default:
- console.debug("unknown action", action)
- return state
- }
- }
+ case UPDATE:
+ // @todo optimize if necessary
+ const raw = state.raw.map(item => item.id === action.id ? action.item : item)
+ return {
+ ...state,
+ raw,
+ data: raw.filter(state[SYM_FILTER]).sort(state[SYM_SORTER]),
+ byId: { ...state.byId, [action.id]: null, [action.item.id]: action.item },
+ }
- function addItem(item) {
- return {
- type: actionType,
- cmd: ADD,
- item
- }
- }
+ case REMOVE:
+ // @todo optimize if necessary
+ return {
+ ...state,
+ raw: state.raw.filter(item => item.id !== action.id),
+ data: state.data.filter(item => item.id !== action.id),
+ byId: { ...state.byId, [action.id]: null },
+ }
- function updateItem(item) {
- return {
- type: actionType,
- cmd: UPDATE,
- item
- }
- }
+ case REQUEST:
+ return {
+ ...state,
+ isFetching: true,
+ }
- function removeItem(item) {
- return {
- type: actionType,
- cmd: REMOVE,
- item
- }
+ case RECEIVE:
+ return {
+ ...state,
+ isFetching: false,
+ raw: action.list,
+ data: action.list.filter(state[SYM_FILTER]).sort(state[SYM_SORTER]),
+ byId: _.fromPairs(action.list.map(item => [item.id, item])),
+ }
+
+ default:
+ return state
}
+}
+export function updateFilter(filter) {
+ return { type: UPDATE_FILTER, filter }
+}
- function updateList(event) {
- /* This action creater takes all WebSocket events */
- return dispatch => {
- switch (event.cmd) {
- case "add":
- return dispatch(addItem(event.data))
- case "update":
- return dispatch(updateItem(event.data))
- case "remove":
- return dispatch(removeItem(event.data))
- case "reset":
- return dispatch(fetchList())
- default:
- console.error("unknown list update", event)
- }
- }
- }
+export function updateSorter(sorter) {
+ return { type: UPDATE_SORTER, sorter }
+}
- function requestList() {
- return {
- type: actionType,
- cmd: REQUEST_LIST,
- }
- }
+export function add(item) {
+ return { type: ADD, item }
+}
- function receiveList(list) {
- return {
- type: actionType,
- cmd: RECEIVE_LIST,
- list
- }
- }
+export function update(id, item) {
+ return { type: UPDATE, id, item }
+}
- function fetchList() {
- return dispatch => {
+export function remove(id) {
+ return { type: REMOVE, id }
+}
- dispatch(requestList())
+export function handleWsMsg(msg) {
+ switch (msg.cmd) {
- return fetchApi(fetchURL).then(response => {
- return response.json().then(json => {
- dispatch(receiveList(json.data))
- })
- })
- }
+ case websocketActions.CMD_ADD:
+ return add(msg.data)
+
+ case websocketActions.CMD_UPDATE:
+ return update(msg.data.id, msg.data)
+
+ case websocketActions.CMD_REMOVE:
+ return remove(msg.data.id)
+
+ default:
+ return { type: UNKNOWN_CMD, msg }
}
+}
+export function request() {
+ return { type: REQUEST }
+}
+
+export function receive(list) {
+ return { type: RECEIVE, list }
+}
- return {reduceList, updateList, fetchList, addItem, updateItem, removeItem,}
-} \ No newline at end of file
+export function fetchError(error) {
+ return { type: FETCH_ERROR, error }
+}
diff --git a/web/src/js/ducks/websocket.js b/web/src/js/ducks/websocket.js
index ebb39cf8..c10f9f5e 100644
--- a/web/src/js/ducks/websocket.js
+++ b/web/src/js/ducks/websocket.js
@@ -1,6 +1,10 @@
const CONNECTED = 'WEBSOCKET_CONNECTED'
const DISCONNECTED = 'WEBSOCKET_DISCONNECTED'
+export const CMD_ADD = 'add'
+export const CMD_UPDATE = 'update'
+export const CMD_REMOVE = 'remove'
+export const CMD_RESET = 'reset'
const defaultState = {
connected: false,