EntityStore: allow deleting entities

environments/review-create-gro-jgifse/deployments/2863
Alex Gleason 2023-03-14 14:13:49 -05:00
rodzic 6ac57910bf
commit 8f8807eb76
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
5 zmienionych plików z 73 dodań i 12 usunięć

Wyświetl plik

@ -1,5 +1,6 @@
import { entitiesFetchFail, entitiesFetchRequest, importEntities } from '../actions'; import { deleteEntities, entitiesFetchFail, entitiesFetchRequest, importEntities } from '../actions';
import reducer from '../reducer'; import reducer, { State } from '../reducer';
import { createListState } from '../utils';
import type { EntityCache } from '../types'; import type { EntityCache } from '../types';
@ -76,4 +77,24 @@ test('failure adds the error to the state', () => {
const result = reducer(undefined, action); const result = reducer(undefined, action);
expect(result.TestEntity!.lists.thingies!.state.error).toBe(error); expect(result.TestEntity!.lists.thingies!.state.error).toBe(error);
});
test('deleting items', () => {
const state: State = {
TestEntity: {
store: { '1': { id: '1' }, '2': { id: '2' }, '3': { id: '3' } },
lists: {
'': {
ids: new Set(['1', '2', '3']),
state: createListState(),
},
},
},
};
const action = deleteEntities(['3', '1'], 'TestEntity');
const result = reducer(state, action);
expect(result.TestEntity!.store).toMatchObject({ '2': { id: '2' } });
expect([...result.TestEntity!.lists['']!.ids]).toEqual(['2']);
}); });

Wyświetl plik

@ -1,6 +1,7 @@
import type { Entity, EntityListState } from './types'; import type { Entity, EntityListState } from './types';
const ENTITIES_IMPORT = 'ENTITIES_IMPORT' as const; const ENTITIES_IMPORT = 'ENTITIES_IMPORT' as const;
const ENTITIES_DELETE = 'ENTITIES_DELETE' as const;
const ENTITIES_FETCH_REQUEST = 'ENTITIES_FETCH_REQUEST' as const; const ENTITIES_FETCH_REQUEST = 'ENTITIES_FETCH_REQUEST' as const;
const ENTITIES_FETCH_SUCCESS = 'ENTITIES_FETCH_SUCCESS' as const; const ENTITIES_FETCH_SUCCESS = 'ENTITIES_FETCH_SUCCESS' as const;
const ENTITIES_FETCH_FAIL = 'ENTITIES_FETCH_FAIL' as const; const ENTITIES_FETCH_FAIL = 'ENTITIES_FETCH_FAIL' as const;
@ -15,6 +16,14 @@ function importEntities(entities: Entity[], entityType: string, listKey?: string
}; };
} }
function deleteEntities(ids: Iterable<string>, entityType: string) {
return {
type: ENTITIES_DELETE,
ids,
entityType,
};
}
function entitiesFetchRequest(entityType: string, listKey?: string) { function entitiesFetchRequest(entityType: string, listKey?: string) {
return { return {
type: ENTITIES_FETCH_REQUEST, type: ENTITIES_FETCH_REQUEST,
@ -45,16 +54,19 @@ function entitiesFetchFail(entityType: string, listKey: string | undefined, erro
/** Any action pertaining to entities. */ /** Any action pertaining to entities. */
type EntityAction = type EntityAction =
ReturnType<typeof importEntities> ReturnType<typeof importEntities>
| ReturnType<typeof deleteEntities>
| ReturnType<typeof entitiesFetchRequest> | ReturnType<typeof entitiesFetchRequest>
| ReturnType<typeof entitiesFetchSuccess> | ReturnType<typeof entitiesFetchSuccess>
| ReturnType<typeof entitiesFetchFail>; | ReturnType<typeof entitiesFetchFail>;
export { export {
ENTITIES_IMPORT, ENTITIES_IMPORT,
ENTITIES_DELETE,
ENTITIES_FETCH_REQUEST, ENTITIES_FETCH_REQUEST,
ENTITIES_FETCH_SUCCESS, ENTITIES_FETCH_SUCCESS,
ENTITIES_FETCH_FAIL, ENTITIES_FETCH_FAIL,
importEntities, importEntities,
deleteEntities,
entitiesFetchRequest, entitiesFetchRequest,
entitiesFetchSuccess, entitiesFetchSuccess,
entitiesFetchFail, entitiesFetchFail,

Wyświetl plik

@ -2,6 +2,7 @@ import produce, { enableMapSet } from 'immer';
import { import {
ENTITIES_IMPORT, ENTITIES_IMPORT,
ENTITIES_DELETE,
ENTITIES_FETCH_REQUEST, ENTITIES_FETCH_REQUEST,
ENTITIES_FETCH_SUCCESS, ENTITIES_FETCH_SUCCESS,
ENTITIES_FETCH_FAIL, ENTITIES_FETCH_FAIL,
@ -43,6 +44,26 @@ const importEntities = (
}); });
}; };
const deleteEntities = (
state: State,
entityType: string,
ids: Iterable<string>,
) => {
return produce(state, draft => {
const cache = draft[entityType] ?? createCache();
for (const id of ids) {
delete cache.store[id];
for (const list of Object.values(cache.lists)) {
list?.ids.delete(id);
}
}
draft[entityType] = cache;
});
};
const setFetching = ( const setFetching = (
state: State, state: State,
entityType: string, entityType: string,
@ -69,6 +90,8 @@ function reducer(state: Readonly<State> = {}, action: EntityAction): State {
switch (action.type) { switch (action.type) {
case ENTITIES_IMPORT: case ENTITIES_IMPORT:
return importEntities(state, action.entityType, action.entities, action.listKey); return importEntities(state, action.entityType, action.entities, action.listKey);
case ENTITIES_DELETE:
return deleteEntities(state, action.entityType, action.ids);
case ENTITIES_FETCH_SUCCESS: case ENTITIES_FETCH_SUCCESS:
return importEntities(state, action.entityType, action.entities, action.listKey, action.newState); return importEntities(state, action.entityType, action.entities, action.listKey, action.newState);
case ENTITIES_FETCH_REQUEST: case ENTITIES_FETCH_REQUEST:
@ -80,4 +103,5 @@ function reducer(state: Readonly<State> = {}, action: EntityAction): State {
} }
} }
export default reducer; export default reducer;
export type { State };

Wyświetl plik

@ -1,4 +1,4 @@
import type { Entity, EntityStore, EntityList, EntityCache } from './types'; import type { Entity, EntityStore, EntityList, EntityCache, EntityListState } from './types';
/** Insert the entities into the store. */ /** Insert the entities into the store. */
const updateStore = (store: EntityStore, entities: Entity[]): EntityStore => { const updateStore = (store: EntityStore, entities: Entity[]): EntityStore => {
@ -26,13 +26,16 @@ const createCache = (): EntityCache => ({
/** Create an empty entity list. */ /** Create an empty entity list. */
const createList = (): EntityList => ({ const createList = (): EntityList => ({
ids: new Set(), ids: new Set(),
state: { state: createListState(),
next: undefined, });
prev: undefined,
fetching: false, /** Create an empty entity list state. */
error: null, const createListState = (): EntityListState => ({
lastFetchedAt: undefined, next: undefined,
}, prev: undefined,
fetching: false,
error: null,
lastFetchedAt: undefined,
}); });
export { export {
@ -40,4 +43,5 @@ export {
updateList, updateList,
createCache, createCache,
createList, createList,
createListState,
}; };

Wyświetl plik

@ -6,7 +6,7 @@
"strict": true, "strict": true,
"module": "es2022", "module": "es2022",
"lib": ["es2019", "es6", "dom", "webworker"], "lib": ["es2019", "es6", "dom", "webworker"],
"target": "es5", "target": "es2015",
"jsx": "react", "jsx": "react",
"allowJs": true, "allowJs": true,
"moduleResolution": "node", "moduleResolution": "node",