diff options
author | Jason <jason.daurus@gmail.com> | 2016-06-23 23:20:41 +0800 |
---|---|---|
committer | Jason <jason.daurus@gmail.com> | 2016-06-23 23:20:41 +0800 |
commit | 5adb7a54fd689f69d5734d64fea0d3de43f4ce6d (patch) | |
tree | 4c733db43737e1b6d02fe81a14e1a1ce08ecf06b /web/src/js/ducks/utils | |
parent | 397554b7c7ceddb54755605dc5df29731bb37214 (diff) | |
download | mitmproxy-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.js | 129 | ||||
-rwxr-xr-x | web/src/js/ducks/utils/view.js | 139 |
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 +} |