UNPKG

@craftercms/studio-ui

Version:

Services, components, models & utils to build CrafterCMS authoring extensions.

244 lines (242 loc) 9.75 kB
/* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ import { createReducer } from '@reduxjs/toolkit'; import { clearClipboard, completeDetailedItem, fetchDetailedItem, fetchDetailedItemComplete, fetchDetailedItems, fetchDetailedItemsComplete, fetchQuickCreateList, fetchQuickCreateListComplete, fetchQuickCreateListFailed, fetchSandboxItem, fetchSandboxItemComplete, fetchSandboxItems, fetchSandboxItemsComplete, reloadDetailedItem, restoreClipboard, setClipboard, updateItemsByPath } from '../actions/content'; import { pathNavigatorConditionallySetPathComplete, pathNavigatorFetchParentItemsComplete, pathNavigatorFetchPathComplete } from '../actions/pathNavigator'; import { parseSandBoxItemToDetailedItem } from '../../utils/content'; import { createLookupTable, reversePluckProps } from '../../utils/object'; import { changeSite } from '../actions/sites'; import { pathNavigatorTreeFetchPathChildrenComplete, pathNavigatorTreeFetchPathPageComplete, pathNavigatorTreeRestoreComplete } from '../actions/pathNavigatorTree'; import { STATE_LOCKED_MASK } from '../../utils/constants'; import { deleteContentEvent, lockContentEvent, moveContentEvent } from '../actions/system'; const initialState = { quickCreate: { error: null, isFetching: false, items: null }, itemsByPath: {}, clipboard: null, itemsBeingFetchedByPath: {} }; const updateItemLockState = (state, { path, username, locked }) => { if ( !state.itemsByPath[path] || (locked && state.itemsByPath[path].stateMap.locked) || (!locked && !state.itemsByPath[path].stateMap.locked) ) { return state; } return Object.assign(Object.assign({}, state), { itemsByPath: Object.assign(Object.assign({}, state.itemsByPath), { [path]: Object.assign(Object.assign({}, state.itemsByPath[path]), { lockOwner: locked ? username : null, state: locked ? state.itemsByPath[path].state + STATE_LOCKED_MASK : state.itemsByPath[path].state - STATE_LOCKED_MASK, stateMap: Object.assign(Object.assign({}, state.itemsByPath[path].stateMap), { locked }) }) }) }); }; const updateItemByPath = (state, { payload: { parent, children } }) => { const nextByPath = Object.assign( Object.assign({}, state.itemsByPath), createLookupTable(parseSandBoxItemToDetailedItem(children, state.itemsByPath), 'path') ); if (children.levelDescriptor) { nextByPath[children.levelDescriptor.path] = parseSandBoxItemToDetailedItem( children.levelDescriptor, state.itemsByPath[children.levelDescriptor.path] ); } if (parent) { nextByPath[parent.path] = parent; } return Object.assign(Object.assign({}, state), { itemsByPath: nextByPath }); }; const updateItemsBeingFetchedByPath = (state, { payload: { path } }) => { state.itemsBeingFetchedByPath[path] = true; }; const updateItemsBeingFetchedByPaths = (state, { payload: { paths } }) => { paths.forEach((path) => { state.itemsBeingFetchedByPath[path] = true; }); }; const reducer = createReducer(initialState, { [fetchQuickCreateList.type]: (state) => Object.assign(Object.assign({}, state), { quickCreate: Object.assign(Object.assign({}, state.quickCreate), { isFetching: true }) }), [fetchQuickCreateListComplete.type]: (state, { payload }) => Object.assign(Object.assign({}, state), { quickCreate: Object.assign(Object.assign({}, state.quickCreate), { items: payload, isFetching: false }) }), [fetchQuickCreateListFailed.type]: (state, error) => Object.assign(Object.assign({}, state), { quickCreate: Object.assign(Object.assign({}, state.quickCreate), { isFetching: false, error: error.payload.response }) }), [fetchDetailedItem.type]: updateItemsBeingFetchedByPath, [reloadDetailedItem.type]: updateItemsBeingFetchedByPath, [completeDetailedItem.type]: updateItemsBeingFetchedByPath, [fetchSandboxItem.type]: updateItemsBeingFetchedByPath, [fetchSandboxItems.type]: updateItemsBeingFetchedByPaths, [fetchSandboxItemsComplete.type]: (state, { payload: { items } }) => { items.forEach((item) => { const path = item.path; state.itemsByPath[path] = parseSandBoxItemToDetailedItem(item, state.itemsByPath[item.path]); delete state.itemsBeingFetchedByPath[path]; }); }, [fetchDetailedItemComplete.type]: (state, { payload }) => Object.assign(Object.assign({}, state), { itemsByPath: Object.assign(Object.assign({}, state.itemsByPath), { [payload.path]: payload }), itemsBeingFetchedByPath: Object.assign({}, reversePluckProps(state.itemsBeingFetchedByPath, payload.path)) }), [fetchDetailedItems.type]: updateItemsBeingFetchedByPaths, [fetchDetailedItemsComplete.type]: (state, { payload: { items } }) => { items.forEach((item) => { const path = item.path; state.itemsByPath[path] = item; delete state.itemsBeingFetchedByPath[path]; }); }, [fetchSandboxItemComplete.type]: (state, { payload: { item } }) => { const path = item.path; state.itemsByPath[path] = parseSandBoxItemToDetailedItem(item, state.itemsByPath[item.path]); state.itemsBeingFetchedByPath[path] = false; }, [restoreClipboard.type]: (state, { payload }) => Object.assign(Object.assign({}, state), { clipboard: payload }), [setClipboard.type]: (state, { payload }) => Object.assign(Object.assign({}, state), { clipboard: payload }), [clearClipboard.type]: (state) => Object.assign(Object.assign({}, state), { clipboard: null }), [pathNavigatorConditionallySetPathComplete.type]: updateItemByPath, [pathNavigatorFetchPathComplete.type]: updateItemByPath, [pathNavigatorFetchParentItemsComplete.type]: (state, { payload: { items, children } }) => { return Object.assign(Object.assign({}, state), { itemsByPath: Object.assign( Object.assign( Object.assign( Object.assign({}, state.itemsByPath), createLookupTable(parseSandBoxItemToDetailedItem(children, state.itemsByPath), 'path') ), children.levelDescriptor && { [children.levelDescriptor.path]: parseSandBoxItemToDetailedItem( children.levelDescriptor, state.itemsByPath[children.levelDescriptor.path] ) } ), createLookupTable( items.reduce((items, item) => { var _a; if ((_a = state.itemsByPath[item.path]) === null || _a === void 0 ? void 0 : _a.live) { item.live = state.itemsByPath[item.path].live; item.staging = state.itemsByPath[item.path].staging; } return items; }, items), 'path' ) ) }); }, [pathNavigatorTreeFetchPathChildrenComplete.type]: updateItemByPath, [pathNavigatorTreeFetchPathPageComplete.type]: updateItemByPath, [pathNavigatorTreeRestoreComplete.type]: (state, action) => { const { payload: { children, items } } = action; let nextByPath = {}; Object.values(children).forEach((children) => { Object.assign(nextByPath, createLookupTable(parseSandBoxItemToDetailedItem(children, state.itemsByPath), 'path')); if (children.levelDescriptor) { nextByPath[children.levelDescriptor.path] = parseSandBoxItemToDetailedItem( children.levelDescriptor, state.itemsByPath[children.levelDescriptor.path] ); } }); items.forEach((item) => { nextByPath[item.path] = item; }); return Object.assign(Object.assign({}, state), { itemsByPath: Object.assign(Object.assign({}, state.itemsByPath), nextByPath) }); }, [updateItemsByPath.type]: (state, { payload }) => { return updateItemByPath(state, { payload: { parent: null, children: payload.items } }); }, [changeSite.type]: () => initialState, [lockContentEvent.type]: (state, { payload }) => updateItemLockState(state, { path: payload.targetPath, username: payload.user.username, locked: payload.locked }), [deleteContentEvent.type]: (state, { payload: { targetPath } }) => { delete state.itemsByPath[targetPath]; delete state.itemsBeingFetchedByPath[targetPath]; }, [moveContentEvent.type]: (state, { payload: { sourcePath } }) => { delete state.itemsByPath[sourcePath]; delete state.itemsBeingFetchedByPath[sourcePath]; } }); export default reducer;