aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/ducks/utils/list.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/src/js/ducks/utils/list.js')
-rw-r--r--web/src/js/ducks/utils/list.js85
1 files changed, 49 insertions, 36 deletions
diff --git a/web/src/js/ducks/utils/list.js b/web/src/js/ducks/utils/list.js
index e66a8549..a93b2d45 100644
--- a/web/src/js/ducks/utils/list.js
+++ b/web/src/js/ducks/utils/list.js
@@ -1,54 +1,74 @@
import _ from 'lodash'
-export const SET = 'LIST_SET'
-export const CLEAR = 'LIST_CLEAR'
-export const REQUEST = 'LIST_REQUEST'
+export const ADD = 'LIST_ADD'
+export const UPDATE = 'LIST_UPDATE'
+export const REMOVE = 'LIST_REMOVE'
export const RECEIVE = 'LIST_RECEIVE'
const defaultState = {
- data: {},
- pendingActions: null,
+ data: [],
+ byId: {},
+ indexOf: {},
}
export default function reduce(state = defaultState, action) {
switch (action.type) {
- case SET:
- if (state.pendingActions) {
- return {
- ...state,
- pendingActions: [...state.pendingActions, action]
- }
- }
+ case ADD:
return {
...state,
- data: { ...state.data, [action.id]: null, [action.item.id]: action.item }
+ data: [...state.data, action.item],
+ byId: { ...state.byId, [action.item.id]: action.item },
+ indexOf: { ...state.indexOf, [action.item.id]: state.data.length },
}
- case CLEAR:
- if (state.pendingActions) {
- return {
- ...state,
- pendingActions: [...state.pendingActions, action]
- }
+ case UPDATE: {
+ const data = [...state.data]
+ const index = state.indexOf[action.id]
+
+ if (index == null) {
+ throw new Error('Item not found')
}
+
+ data[index] = action.item
+
return {
...state,
- data: { ...state.data, [action.id]: null }
+ data,
+ byId: { ...state.byId, [action.id]: null, [action.item.id]: action.item },
+ indexOf: { ...state.indexOf, [action.id]: null, [action.item.id]: index },
+ }
+ }
+
+ case REMOVE: {
+ const data = [...state.data]
+ const indexOf = { ...state.indexOf }
+ const index = indexOf[action.id]
+
+ if (index == null) {
+ throw new Error('Item not found')
+ }
+
+ data.splice(index, 1)
+ for (let i = data.length - 1; i >= index; i--) {
+ indexOf[data[i].id] = i
}
- case REQUEST:
return {
...state,
- pendingActions: []
+ data,
+ indexOf,
+ byId: { ...state.byId, [action.id]: null },
}
+ }
case RECEIVE:
- return state.pendingActions.reduce(reduce, {
+ return {
...state,
- pendingActions: null,
- data: _.fromPairs(action.list.map(item => [item.id, item])),
- })
+ data: action.list,
+ byId: _.fromPairs(action.list.map(item => [item.id, item])),
+ indexOf: _.fromPairs(action.list.map((item, index) => [item.id, index])),
+ }
default:
return state
@@ -59,28 +79,21 @@ export default function reduce(state = defaultState, action) {
* @public
*/
export function add(item) {
- return { type: SET, id: item.id, item }
+ return { type: ADD, item }
}
/**
* @public
*/
export function update(id, item) {
- return { type: SET, id, item }
+ return { type: UPDATE, id, item }
}
/**
* @public
*/
export function remove(id) {
- return { type: CLEAR, id }
-}
-
-/**
- * @public
- */
-export function request() {
- return { type: REQUEST }
+ return { type: REMOVE, id }
}
/**