diff options
Diffstat (limited to 'web/src/js/ducks/utils/list.js')
-rw-r--r-- | web/src/js/ducks/utils/list.js | 209 |
1 files changed, 67 insertions, 142 deletions
diff --git a/web/src/js/ducks/utils/list.js b/web/src/js/ducks/utils/list.js index a830fe99..e66a8549 100644 --- a/web/src/js/ducks/utils/list.js +++ b/web/src/js/ducks/utils/list.js @@ -1,166 +1,91 @@ -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 _ from 'lodash' +export const SET = 'LIST_SET' +export const CLEAR = 'LIST_CLEAR' +export const REQUEST = 'LIST_REQUEST' +export const RECEIVE = 'LIST_RECEIVE' const defaultState = { - list: [], - isFetching: false, - actionsDuringFetch: [], - byId: {}, - indexOf: {}, + data: {}, + pendingActions: null, } -export default function makeList(actionType, fetchURL) { - function reduceList(state = defaultState, action = {}) { - - if (action.type !== actionType) { - return state - } +export default function reduce(state = defaultState, action) { + switch (action.type) { - // 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) + case SET: + if (state.pendingActions) { + return { + ...state, + pendingActions: [...state.pendingActions, action] + } } - return s - } else if (state.isFetching) { return { ...state, - actionsDuringFetch: [...state.actionsDuringFetch, action] + data: { ...state.data, [action.id]: null, [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 + case CLEAR: + if (state.pendingActions) { return { ...state, - list, - byId: {...state.byId, [action.item.id]: action.item}, + pendingActions: [...state.pendingActions, action] } + } + return { + ...state, + data: { ...state.data, [action.id]: null } + } - 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 - } - } - - function addItem(item) { - return { - type: actionType, - cmd: ADD, - item - } - } - - function updateItem(item) { - return { - type: actionType, - cmd: UPDATE, - item - } - } - - function removeItem(item) { - return { - type: actionType, - cmd: REMOVE, - item - } - } - - - 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) + case REQUEST: + return { + ...state, + pendingActions: [] } - } - } - function requestList() { - return { - type: actionType, - cmd: REQUEST_LIST, - } - } + case RECEIVE: + return state.pendingActions.reduce(reduce, { + ...state, + pendingActions: null, + data: _.fromPairs(action.list.map(item => [item.id, item])), + }) - function receiveList(list) { - return { - type: actionType, - cmd: RECEIVE_LIST, - list - } + default: + return state } +} - function fetchList() { - return dispatch => { +/** + * @public + */ +export function add(item) { + return { type: SET, id: item.id, item } +} - dispatch(requestList()) +/** + * @public + */ +export function update(id, item) { + return { type: SET, id, item } +} - return fetchApi(fetchURL).then(response => { - return response.json().then(json => { - dispatch(receiveList(json.data)) - }) - }) - } - } +/** + * @public + */ +export function remove(id) { + return { type: CLEAR, id } +} +/** + * @public + */ +export function request() { + return { type: REQUEST } +} - return {reduceList, updateList, fetchList, addItem, updateItem, removeItem,} -}
\ No newline at end of file +/** + * @public + */ +export function receive(list) { + return { type: RECEIVE, list } +} |