From cd2b798fef38705a8c39769b63641b9e51bfbd02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Maa=C3=9F?= <mathias.maass@uni-leipzig.de> Date: Fri, 5 Apr 2019 15:53:15 +0200 Subject: [PATCH] Refactor state update patterns --- package.json | 6 + src/state/reducers/annotations.js | 47 +++--- src/state/reducers/companionWindows.js | 17 +-- src/state/reducers/infoResponses.js | 49 +++---- src/state/reducers/manifests.js | 55 +++---- src/state/reducers/viewers.js | 17 +-- src/state/reducers/windows.js | 194 +++++++------------------ 7 files changed, 132 insertions(+), 253 deletions(-) diff --git a/package.json b/package.json index 8d5e632b7..8020d248a 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,12 @@ "Jack Reed <phillipjreed@gmail.com> (https://www.jack-reed.com)" ], "repository": "https://github.com/ProjectMirador/mirador", + "size-limit": [ + { + "limit": "370 KB", + "path": "dist/mirador.min.js" + } + ], "dependencies": { "@material-ui/core": "^3.9.1", "@material-ui/icons": "^3.0.2", diff --git a/src/state/reducers/annotations.js b/src/state/reducers/annotations.js index 1eca687ac..286c6baab 100644 --- a/src/state/reducers/annotations.js +++ b/src/state/reducers/annotations.js @@ -1,3 +1,4 @@ +import { set } from './utils'; import ActionTypes from '../actions/action-types'; /** @@ -6,37 +7,25 @@ import ActionTypes from '../actions/action-types'; export const annotationsReducer = (state = {}, action) => { switch (action.type) { case ActionTypes.REQUEST_ANNOTATION: - return { - ...state, - [action.canvasId]: { - [action.annotationId]: { - id: action.annotationId, - isFetching: true, - }, - }, - }; + return set(state, [action.canvasId, action.annotationId], { + id: action.annotationId, + isFetching: true, + }); + case ActionTypes.RECEIVE_ANNOTATION: - return { - ...state, - [action.canvasId]: { - [action.annotationId]: { - id: action.annotationId, - isFetching: false, - json: action.annotationJson, - }, - }, - }; + return set(state, [action.canvasId, action.annotationId], { + id: action.annotationId, + isFetching: false, + json: action.annotationJson, + }); + case ActionTypes.RECEIVE_ANNOTATION_FAILURE: - return { - ...state, - [action.canvasId]: { - [action.annotationId]: { - error: action.error, - id: action.annotationId, - isFetching: false, - }, - }, - }; + return set(state, [action.canvasId, action.annotationId], { + error: action.error, + id: action.annotationId, + isFetching: false, + }); + default: return state; } }; diff --git a/src/state/reducers/companionWindows.js b/src/state/reducers/companionWindows.js index 6cd71b959..3c09a441a 100644 --- a/src/state/reducers/companionWindows.js +++ b/src/state/reducers/companionWindows.js @@ -1,28 +1,23 @@ -import { - removeIn, setIn, updateIn, merge, -} from 'immutable'; +import { set, update, unset } from './utils'; import ActionTypes from '../actions/action-types'; /** */ export function companionWindowsReducer(state = {}, action) { switch (action.type) { case ActionTypes.ADD_COMPANION_WINDOW: - return setIn(state, [action.id], action.payload); + return set(state, [action.id], action.payload); case ActionTypes.ADD_WINDOW: - return action.companionWindows.reduce((newState, cw) => { - newState[cw.id] = cw; // eslint-disable-line no-param-reassign - return newState; - }, state); + return action.companionWindows.reduce((acc, cw) => set(acc, [cw.id], cw), state); case ActionTypes.REMOVE_WINDOW: - return action.companionWindowIds.reduce((newState, id) => removeIn(newState, [id]), state); + return action.companionWindowIds.reduce((acc, id) => unset(acc, [id]), state); case ActionTypes.UPDATE_COMPANION_WINDOW: - return updateIn(state, [action.id], orig => merge(orig, action.payload)); + return update(state, [action.id], action.payload); case ActionTypes.REMOVE_COMPANION_WINDOW: - return removeIn(state, [action.id]); + return unset(state, [action.id]); default: return state; diff --git a/src/state/reducers/infoResponses.js b/src/state/reducers/infoResponses.js index 12808e226..4d7bad70d 100644 --- a/src/state/reducers/infoResponses.js +++ b/src/state/reducers/infoResponses.js @@ -1,3 +1,4 @@ +import { set, unset } from './utils'; import ActionTypes from '../actions/action-types'; /** @@ -6,38 +7,28 @@ import ActionTypes from '../actions/action-types'; export const infoResponsesReducer = (state = {}, action) => { switch (action.type) { case ActionTypes.REQUEST_INFO_RESPONSE: - return { - ...state, - [action.infoId]: { - id: action.infoId, - isFetching: true, - }, - }; + return set(state, [action.infoId], { + id: action.infoId, + isFetching: true, + }); + case ActionTypes.RECEIVE_INFO_RESPONSE: - return { - ...state, - [action.infoId]: { - id: action.infoId, - isFetching: false, - json: action.infoJson, - }, - }; + return set(state, [action.infoId], { + id: action.infoId, + isFetching: false, + json: action.infoJson, + }); + case ActionTypes.RECEIVE_INFO_RESPONSE_FAILURE: - return { - ...state, - [action.infoId]: { - error: action.error, - id: action.infoId, - isFetching: false, - }, - }; + return set(state, [action.infoId], { + error: action.error, + id: action.infoId, + isFetching: false, + }); + case ActionTypes.REMOVE_INFO_RESPONSE: - return Object.keys(state).reduce((object, key) => { - if (key !== action.infoId) { - object[key] = state[key]; // eslint-disable-line no-param-reassign - } - return object; - }, {}); + return unset(state, [action.infoId]); + default: return state; } }; diff --git a/src/state/reducers/manifests.js b/src/state/reducers/manifests.js index eab3daf40..94da6ae1b 100644 --- a/src/state/reducers/manifests.js +++ b/src/state/reducers/manifests.js @@ -1,4 +1,4 @@ -import omit from 'lodash/omit'; +import { update, unset } from './utils'; import ActionTypes from '../actions/action-types'; /** @@ -7,42 +7,29 @@ import ActionTypes from '../actions/action-types'; export const manifestsReducer = (state = {}, action) => { switch (action.type) { case ActionTypes.REQUEST_MANIFEST: - return { - [action.manifestId]: { - ...state[action.manifestId], - ...action.properties, - id: action.manifestId, - }, - ...omit(state, action.manifestId), - }; + return update(state, [action.manifestId], { + ...action.properties, + id: action.manifestId, + }); + case ActionTypes.RECEIVE_MANIFEST: - return { - ...state, - [action.manifestId]: { - ...state[action.manifestId], - error: null, // Explicitly set the error to null in case this is a re-fetch - id: action.manifestId, - isFetching: false, - json: action.manifestJson, - }, - }; + return update(state, [action.manifestId], { + error: null, // Explicitly set the error to null in case this is a re-fetch + id: action.manifestId, + isFetching: false, + json: action.manifestJson, + }); + case ActionTypes.RECEIVE_MANIFEST_FAILURE: - return { - ...state, - [action.manifestId]: { - ...state[action.manifestId], - error: action.error, - id: action.manifestId, - isFetching: false, - }, - }; + return update(state, [action.manifestId], { + error: action.error, + id: action.manifestId, + isFetching: false, + }); + case ActionTypes.REMOVE_MANIFEST: - return Object.keys(state).reduce((object, key) => { - if (key !== action.manifestId) { - object[key] = state[key]; // eslint-disable-line no-param-reassign - } - return object; - }, {}); + return unset(state, [action.manifestId]); + default: return state; } }; diff --git a/src/state/reducers/viewers.js b/src/state/reducers/viewers.js index e31e42d03..9a85d3ffc 100644 --- a/src/state/reducers/viewers.js +++ b/src/state/reducers/viewers.js @@ -1,3 +1,4 @@ +import { set, unset } from './utils'; import ActionTypes from '../actions/action-types'; /** @@ -6,19 +7,11 @@ import ActionTypes from '../actions/action-types'; export const viewersReducer = (state = {}, action) => { switch (action.type) { case ActionTypes.UPDATE_VIEWPORT: - return { - ...state, - [action.windowId]: { - ...action.payload, - }, - }; + return set(state, [action.windowId], action.payload); + case ActionTypes.REMOVE_WINDOW: - return Object.keys(state).reduce((object, key) => { - if (key !== action.windowId) { - object[key] = state[key]; // eslint-disable-line no-param-reassign - } - return object; - }, {}); + return unset(state, [action.windowId]); + default: return state; } diff --git a/src/state/reducers/windows.js b/src/state/reducers/windows.js index 76bd83ee1..3b8b01337 100644 --- a/src/state/reducers/windows.js +++ b/src/state/reducers/windows.js @@ -1,4 +1,4 @@ -import { remove, updateIn, merge } from 'immutable'; +import { set, update, unset } from './utils'; import ActionTypes from '../actions/action-types'; /** @@ -7,83 +7,49 @@ import ActionTypes from '../actions/action-types'; export const windowsReducer = (state = {}, action) => { switch (action.type) { case ActionTypes.ADD_WINDOW: - return { ...state, [action.window.id]: action.window }; + return set(state, [action.window.id], action.window); case ActionTypes.MAXIMIZE_WINDOW: - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - maximized: true, - }, - }; + return set(state, [action.windowId, 'maximized'], true); + case ActionTypes.MINIMIZE_WINDOW: - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - maximized: false, - }, - }; + return set(state, [action.windowId, 'maximized'], false); case ActionTypes.UPDATE_WINDOW: - return updateIn(state, [action.id], orig => merge(orig, action.payload)); + return update(state, [action.id], action.payload); case ActionTypes.REMOVE_WINDOW: - return Object.keys(state).reduce((object, key) => { - if (key !== action.windowId) { - object[key] = state[key]; // eslint-disable-line no-param-reassign - } - return object; - }, {}); + return unset(state, [action.windowId]); + case ActionTypes.TOGGLE_WINDOW_SIDE_BAR: - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - sideBarOpen: !state[action.windowId].sideBarOpen, - }, - }; + return update(state, [action.windowId], props => ({ + ...props, + sideBarOpen: !props.sideBarOpen, + })); + case ActionTypes.SET_WINDOW_VIEW_TYPE: - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - view: action.viewType, - }, - }; + return set(state, [action.windowId, 'view'], action.viewType); + case ActionTypes.SET_WINDOW_SIDE_BAR_PANEL: - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - sideBarPanel: ( - action.panelType - ), - }, - }; + return set(state, [action.windowId, 'sideBarPanel'], action.panelType); + case ActionTypes.UPDATE_WINDOW_POSITION: - return { - ...state, - [action.payload.windowId]: { - ...state[action.payload.windowId], - x: action.payload.position.x, - y: action.payload.position.y, - }, - }; + return update(state, [action.payload.windowId], { + x: action.payload.position.x, + y: action.payload.position.y, + }); + case ActionTypes.SET_WINDOW_SIZE: - return { - ...state, - [action.payload.windowId]: { - ...state[action.payload.windowId], - height: action.payload.size.height, - width: action.payload.size.width, - x: action.payload.size.x, - y: action.payload.size.y, - }, - }; + return update(state, [action.payload.windowId], { + height: action.payload.size.height, + width: action.payload.size.width, + x: action.payload.size.x, + y: action.payload.size.y, + }); + case ActionTypes.SET_CANVAS: - return setCanvasIndex(state, action.windowId, currentIndex => action.canvasIndex); + return set(state, [action.windowId, 'canvasIndex'], action.canvasIndex); + case ActionTypes.ADD_COMPANION_WINDOW: if (action.payload.position === 'left') { const { companionWindowIds } = state[action.windowId]; @@ -91,66 +57,38 @@ export const windowsReducer = (state = {}, action) => { const newCompanionWindowIds = companionWindowIds .filter(id => companionWindows[id].position !== action.payload.position); - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - companionAreaOpen: true, - companionWindowIds: newCompanionWindowIds.concat([action.id]), - sideBarPanel: action.payload.content, - }, - }; + return update(state, [action.windowId], { + companionAreaOpen: true, + companionWindowIds: newCompanionWindowIds.concat([action.id]), + sideBarPanel: action.payload.content, + }); } + return update(state, [action.windowId], props => ({ + ...props, + companionWindowIds: props.companionWindowIds.concat([action.id]), + })); - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - companionWindowIds: state[action.windowId].companionWindowIds.concat([action.id]), - }, - }; case ActionTypes.REMOVE_COMPANION_WINDOW: - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - companionWindowIds: state[action.windowId] - .companionWindowIds.filter(id => id !== action.id), - }, - }; + return update(state, [action.windowId], props => ({ + ...props, + companionWindowIds: props.companionWindowIds.filter(id => id !== action.id), + })); + case ActionTypes.SELECT_ANNOTATION: - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - selectedAnnotations: { - ...state[action.windowId].selectedAnnotations, - [action.canvasId]: [ - ...((state[action.windowId].selectedAnnotations || {})[action.canvasId] || []), - action.annotationId, - ], - }, - }, - }; + return update(state, [action.windowId, 'selectedAnnotations', action.canvasId], + arr => [...(arr || []), action.annotationId]); + case ActionTypes.DESELECT_ANNOTATION: { const selectedAnnotations = updatedSelectedAnnotations(state, action); - - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - selectedAnnotations, - }, - }; + return update(state, [action.windowId], { selectedAnnotations }); } + case ActionTypes.TOGGLE_ANNOTATION_DISPLAY: - return { - ...state, - [action.windowId]: { - ...state[action.windowId], - displayAllAnnotations: !state[action.windowId].displayAllAnnotations, - }, - }; + return update(state, [action.windowId], props => ({ + ...props, + displayAllAnnotations: !props.displayAllAnnotations, + })); + default: return state; } @@ -172,25 +110,5 @@ function updatedSelectedAnnotations(state, action) { }; } - return remove(state[action.windowId].selectedAnnotations, action.canvasId); -} - -/** - * @param {Object} state - * @param {String} windowId - * @param {Function} getIndex - gets curent canvas index passed and should return new index - */ -function setCanvasIndex(state, windowId, getIndex) { - return Object.values(state).reduce((object, window) => { - if (window.id === windowId) { - return { - ...object, - [window.id]: { - ...window, - canvasIndex: getIndex(window.canvasIndex), - }, - }; - } - return { ...object, [window.id]: window }; - }, {}); + return unset(state[action.windowId].selectedAnnotations, [action.canvasId]); } -- GitLab