aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/ducks/utils
diff options
context:
space:
mode:
authorJason <jason.daurus@gmail.com>2016-06-23 23:20:41 +0800
committerJason <jason.daurus@gmail.com>2016-06-23 23:20:41 +0800
commit5adb7a54fd689f69d5734d64fea0d3de43f4ce6d (patch)
tree4c733db43737e1b6d02fe81a14e1a1ce08ecf06b /web/src/js/ducks/utils
parent397554b7c7ceddb54755605dc5df29731bb37214 (diff)
downloadmitmproxy-5adb7a54fd689f69d5734d64fea0d3de43f4ce6d.tar.gz
mitmproxy-5adb7a54fd689f69d5734d64fea0d3de43f4ce6d.tar.bz2
mitmproxy-5adb7a54fd689f69d5734d64fea0d3de43f4ce6d.zip
[web] separate views and list
Diffstat (limited to 'web/src/js/ducks/utils')
-rw-r--r--web/src/js/ducks/utils/list.js129
-rwxr-xr-xweb/src/js/ducks/utils/view.js139
2 files changed, 182 insertions, 86 deletions
diff --git a/web/src/js/ducks/utils/list.js b/web/src/js/ducks/utils/list.js
index fd8ac106..b95a4527 100644
--- a/web/src/js/ducks/utils/list.js
+++ b/web/src/js/ducks/utils/list.js
@@ -1,99 +1,50 @@
+import _ from 'lodash'
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 SET = 'LIST_SET'
+export const CLEAR = 'LIST_CLEAR'
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 = {
- raw: [],
- data: [],
- byId: {},
- isFetching: false,
- [SYM_FILTER]: () => true,
- [SYM_SORTER]: () => 0,
- [SYM_PENDING]: [],
+ data: {},
+ pendingActions: null,
}
export default function reduce(state = defaultState, action) {
- if (state.isFetching && action.type !== RECEIVE) {
+ if (state.pendingActions && action.type !== RECEIVE) {
return {
...state,
- [SYM_PENDING]: [...state[SYM_PENDING], action]
+ pendingActions: [...state.pendingActions, action]
}
}
switch (action.type) {
- case UPDATE_FILTER:
+ case SET:
return {
...state,
- [SYM_FILTER]: action.filter,
- data: state.raw.filter(action.filter).sort(state[SYM_SORTER]),
+ data: { ...state.data, [action.id]: null, [action.item.id]: action.item }
}
- case UPDATE_SORTER:
+ case CLEAR:
return {
...state,
- [SYM_SORTER]: action.sorter,
- data: state.data.slice().sort(state[SYM_SORTER]),
- }
-
- case ADD:
- let data = state.data
- if (state[SYM_FILTER](action.item)) {
- data = [...state.data, action.item].sort(state[SYM_SORTER])
- }
- return {
- ...state,
- data,
- raw: [...state.raw, action.item],
- byId: { ...state.byId, [action.item.id]: action.item },
- }
-
- 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 },
- }
-
- 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 },
+ data: { ...state.data, [action.id]: null }
}
case REQUEST:
return {
...state,
- isFetching: true,
+ pendingActions: []
}
case RECEIVE:
- return state[SYM_PENDING].reduce(reduce, {
+ return state.pendingActions.reduce(reduce, {
...state,
- [SYM_PENDING]: [],
- 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])),
+ pendingActions: null,
+ data: _.fromPairs(action.list.map(item => [item.id, item])),
})
default:
@@ -101,26 +52,44 @@ export default function reduce(state = defaultState, action) {
}
}
-export function updateFilter(filter) {
- return { type: UPDATE_FILTER, filter }
+/**
+ * @public
+ */
+export function add(item) {
+ return { type: SET, id: item.id, item }
}
-export function updateSorter(sorter) {
- return { type: UPDATE_SORTER, sorter }
+/**
+ * @public
+ */
+export function update(id, item) {
+ return { type: SET, id, item }
}
-export function add(item) {
- return { type: ADD, item }
+/**
+ * @public
+ */
+export function remove(id) {
+ return { type: CLEAR, id }
}
-export function update(id, item) {
- return { type: UPDATE, id, item }
+/**
+ * @public
+ */
+export function request() {
+ return { type: REQUEST }
}
-export function remove(id) {
- return { type: REMOVE, id }
+/**
+ * @public
+ */
+export function receive(list) {
+ return { type: RECEIVE, list }
}
+/**
+ * @public websocket
+ */
export function handleWsMsg(msg) {
switch (msg.cmd) {
@@ -137,15 +106,3 @@ export function handleWsMsg(msg) {
return { type: UNKNOWN_CMD, msg }
}
}
-
-export function request() {
- return { type: REQUEST }
-}
-
-export function receive(list) {
- return { type: RECEIVE, list }
-}
-
-export function fetchError(error) {
- return { type: FETCH_ERROR, error }
-}
diff --git a/web/src/js/ducks/utils/view.js b/web/src/js/ducks/utils/view.js
new file mode 100755
index 00000000..adf7fc6a
--- /dev/null
+++ b/web/src/js/ducks/utils/view.js
@@ -0,0 +1,139 @@
+import _ from 'lodash'
+
+export const UPDATE_FILTER = 'VIEW_UPDATE_FILTER'
+export const UPDATE_SORTER = 'VIEW_UPDATE_SORTER'
+export const ADD = 'VIEW_ADD'
+export const UPDATE = 'VIEW_UPDATE'
+export const REMOVE = 'VIEW_REMOVE'
+export const RECEIVE = 'VIEW_RECEIVE'
+
+const defaultState = {
+ data: [],
+ indexOf: {},
+}
+
+export default function reduce(state = defaultState, action) {
+ switch (action.type) {
+
+ case UPDATE_FILTER:
+ const data = action.list.data.filter(action.filter).sort(action.sorter)
+ return {
+ ...state,
+ data,
+ indexOf: _.fromPairs(data.map((item, index) => [item.id, index])),
+ }
+
+ case UPDATE_SORTER:
+ const data = state.data.slice().sort(action.sorter)
+ return {
+ ...state,
+ data,
+ indexOf: _.fromPairs(data.map((item, index) => [item.id, index]))
+ }
+
+ case ADD:
+ if (!action.filter(action.item)) {
+ return state
+ }
+ return {
+ ...state,
+ ...sortedInsert(state, action.item, action.sorter),
+ }
+
+ case REMOVE:
+ return {
+ ...state,
+ ...sortedRemove(state, action.id),
+ }
+
+ case UPDATE:
+ const nextState = {
+ ...state,
+ ...sortedRemove(state, action.id),
+ }
+ if (!action.filter(action.item)) {
+ return nextState
+ }
+ return {
+ ...nextState,
+ ...sortedInsert(nextState, action.item, action.sorter)
+ }
+
+ case RECEIVE:
+ const data = action.list.data.filter(action.filter).sort(action.sorter)
+ return {
+ ...state,
+ data,
+ indexOf: _.fromPairs(data.map((item, index) => [item.id, index])),
+ }
+
+ default:
+ return state
+ }
+}
+
+export function updateFilter(list, filter, sorter) {
+ return { type: UPDATE_FILTER, list, filter, sorter }
+}
+
+export function updateSorter(sorter) {
+ return { type: UPDATE_SORTER, sorter }
+}
+
+export function add(item, filter, sorter) {
+ return { type: ADD, item, filter, sorter }
+}
+
+export function update(id, item, filter, sorter) {
+ return { type: UPDATE, id, item, filter, sorter }
+}
+
+export function remove(id) {
+ return { type: REMOVE, id }
+}
+
+export function receive(list, filter, sorter) {
+ return { type: RECEIVE, list, filter, sorter }
+}
+
+function sortedInsert(state, item, sorter) {
+ const index = sortedIndex(state.data, item, sorter)
+ const data = [...state.data]
+ const indexOf = { ...state.indexOf }
+
+ data.splice(index, 0, item)
+ for (let i = data.length - 1; i >= index; i--) {
+ indexOf[data[i].id] = i
+ }
+
+ return { data, indexOf }
+}
+
+function sortedRemove(state, id) {
+ const index = state.indexOf[id]
+ const data = [...state.data]
+ const indexOf = { ...state.indexOf, [id]: null }
+
+ data.splice(index, 1)
+ for (let i = data.length - 1; i >= index; i--) {
+ indexOf[data[i].id] = i
+ }
+
+ return { data, indexOf }
+}
+
+function sortedIndex(list, item, sorter) {
+ let low = 0
+ let high = list.length
+
+ while (low < high) {
+ const middle = (low + high) >>> 1
+ if (sorter(item, list[middle]) > 0) {
+ low = middle + 1
+ } else {
+ high = middle
+ }
+ }
+
+ return low
+}