UNPKG

@wordpress/core-data

Version:
186 lines (185 loc) 5.26 kB
// packages/core-data/src/queried-data/reducer.js import { combineReducers } from "@wordpress/data"; import { compose } from "@wordpress/compose"; import { conservativeMapItem, ifMatchingAction, replaceAction, onSubKey } from "../utils/index.mjs"; import { DEFAULT_ENTITY_KEY } from "../entities.mjs"; import getQueryParts from "./get-query-parts.mjs"; function getContextFromAction(action) { const { query } = action; if (!query) { return "default"; } const queryParts = getQueryParts(query); return queryParts.context; } function getMergedItemIds(itemIds, nextItemIds, page, perPage) { const receivedAllIds = page === 1 && perPage === -1; if (receivedAllIds) { return nextItemIds; } const nextItemIdsStartIndex = (page - 1) * perPage; const size = Math.max( itemIds?.length ?? 0, nextItemIdsStartIndex + nextItemIds.length ); const mergedItemIds = new Array(size); for (let i = 0; i < size; i++) { const isInNextItemsRange = i >= nextItemIdsStartIndex && i < nextItemIdsStartIndex + perPage; mergedItemIds[i] = isInNextItemsRange ? nextItemIds[i - nextItemIdsStartIndex] : itemIds?.[i]; } return mergedItemIds; } function removeEntitiesById(entities, ids) { return Object.fromEntries( Object.entries(entities).filter( ([id]) => !ids.some((itemId) => { if (Number.isInteger(itemId)) { return itemId === +id; } return itemId === id; }) ) ); } function items(state = {}, action) { switch (action.type) { case "RECEIVE_ITEMS": { const context = getContextFromAction(action); const key = action.key || DEFAULT_ENTITY_KEY; return { ...state, [context]: { ...state[context], ...action.items.reduce((accumulator, value) => { const itemId = value?.[key]; accumulator[itemId] = conservativeMapItem( state?.[context]?.[itemId], value ); return accumulator; }, {}) } }; } case "REMOVE_ITEMS": return Object.fromEntries( Object.entries(state).map(([itemId, contextState]) => [ itemId, removeEntitiesById(contextState, action.itemIds) ]) ); } return state; } function itemIsComplete(state = {}, action) { switch (action.type) { case "RECEIVE_ITEMS": { const context = getContextFromAction(action); const { query, key = DEFAULT_ENTITY_KEY } = action; const queryParts = query ? getQueryParts(query) : {}; const isCompleteQuery = !query || !Array.isArray(queryParts.fields); return { ...state, [context]: { ...state[context], ...action.items.reduce((result, item) => { const itemId = item?.[key]; result[itemId] = state?.[context]?.[itemId] || isCompleteQuery; return result; }, {}) } }; } case "REMOVE_ITEMS": return Object.fromEntries( Object.entries(state).map(([itemId, contextState]) => [ itemId, removeEntitiesById(contextState, action.itemIds) ]) ); } return state; } var receiveQueries = compose([ // Limit to matching action type so we don't attempt to replace action on // an unhandled action. ifMatchingAction((action) => "query" in action), // Inject query parts into action for use both in `onSubKey` and reducer. replaceAction((action) => { if (action.query) { return { ...action, ...getQueryParts(action.query) }; } return action; }), onSubKey("context"), // Queries shape is shared, but keyed by query `stableKey` part. Original // reducer tracks only a single query object. onSubKey("stableKey") ])((state = {}, action) => { const { type, page, perPage, key = DEFAULT_ENTITY_KEY } = action; if (type !== "RECEIVE_ITEMS") { return state; } return { itemIds: getMergedItemIds( state?.itemIds || [], action.items.map((item) => item?.[key]).filter(Boolean), page, perPage ), meta: action.meta }; }); var queries = (state = {}, action) => { switch (action.type) { case "RECEIVE_ITEMS": return receiveQueries(state, action); case "REMOVE_ITEMS": const removedItems = action.itemIds.reduce((result, itemId) => { result[itemId] = true; return result; }, {}); return Object.fromEntries( Object.entries(state).map( ([queryGroup, contextQueries]) => [ queryGroup, Object.fromEntries( Object.entries(contextQueries).map( ([query, queryItems]) => [ query, { ...queryItems, itemIds: queryItems.itemIds.filter( (queryId) => !removedItems[queryId] ) } ] ) ) ] ) ); default: return state; } }; var reducer_default = combineReducers({ items, itemIsComplete, queries }); export { reducer_default as default, getMergedItemIds, itemIsComplete, items }; //# sourceMappingURL=reducer.mjs.map