Skip to content

Commit

Permalink
🌟 Add the ability perform list operations on all other lists not expl…
Browse files Browse the repository at this point in the history
…icitly referenced
  • Loading branch information
greena13 committed Oct 7, 2020
1 parent 5afb6a1 commit 6730199
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 5 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ configure({
| acceptType | String | No | The `Accept` header to use with each request. Defaults to the contentType if not defined. |
| contentType | String | No | The `Content-Type` header to use with each request |
| errorContentType | String | No | The `Content-Type` of error responses that should be parsed as JSON. Defaults to the `contentType` if not defined. |
| listWildcard | String | '*' | The list key used to reference all lists for action creator's option's list operations |
| request | RequestInit | No | The request configuration object to be passed to the fetch method, or the new XMLHttpRequest object, when the progress option is used. |
| beforeReducers | Array of reducers | No | A list of functions to call before passing the resource to the reducer. This is useful if you want to use the default reducer, but provide some additional pre-processing to standardise the resource before it is added to the store. |
| afterReducers | Array of reducers | No | A list of functions to call after passing the resource to the reducer. This is useful if you want to use the default reducer, but provide some additional post-processing to standardise the resource before it is added to the store. |
Expand Down Expand Up @@ -1389,6 +1390,14 @@ import { UNSPECIFIED_KEY } from 'redux-and-the-rest';
createUser(userAttributes, { push: [UNSPECIFIED_KEY] })
```

If you want to perform a list operation on all other lists whose key has not been explicitly referenced, you can use the `getConfiguration().listWildcard` value (`'*'` by default).

For example the following will unshift an item to the `newest` list and invalidate all others:

```javascript
createTodoItem({ title: 'Pick up milk'}, { unshift: ['newest'], invalidate: ['*'] });
```

When the item is successfully created, the default createItem reducer expects the server to respond with a JSON object containing the item's attributes. If the request fails, it expects the server to respond with a JSON object containing an error.

### Update a item on the server
Expand Down
5 changes: 5 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,11 @@ export interface GlobalConfigurationOptions {
*/
contentType?: String,

/**
* The key to use use as a wildcard to mean all lists
*/
listWildcard?: String,

/**
* The Content-Type of error responses that should be parsed as JSON. Defaults to the contentType if not defined.
*/
Expand Down
1 change: 0 additions & 1 deletion src/actions/RESTful/newItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import warn from '../../utils/dev/warn';
import applyListOperators from '../../reducers/helpers/applyListOperators';
import wrapInObject from '../../utils/object/wrapInObject';
import adaptOptionsForSingularResource from '../../action-creators/helpers/adaptOptionsForSingularResource';
import { registerActionEnd } from '../../utils/ActionQueue';

/** ************************************************************************************************************
* Action creators
Expand Down
5 changes: 5 additions & 0 deletions src/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ const DefaultConfigurationOptions = {
* Assume a default content-type of application/json
*/
contentType: 'application/json',

/**
* The key to use use as a wildcard to mean all lists
*/
listWildcard: '*',
};

let configuration = {
Expand Down
48 changes: 44 additions & 4 deletions src/reducers/helpers/applyListOperators.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { LIST } from '../../constants/DataStructures';
import contains from '../../utils/list/contains';
import { getConfiguration } from '../../configuration';
import without from '../../utils/list/without';

function applyListOperators(lists, listOperations = {}, temporaryKey) {
const updatedLists = {};

listOperations.push.forEach((listKey) => {
const { listWildcard } = getConfiguration();

const keysExplicitlyReferenced = [
...(listOperations.push || []),
...(listOperations.unshift || []),
...(listOperations.invalidate || []),
];

function pushPosition(listKey) {
const existingList = lists[listKey] || LIST;

if (contains(existingList.positions, temporaryKey)) {
Expand All @@ -18,9 +28,9 @@ function applyListOperators(lists, listOperations = {}, temporaryKey) {
]
};
}
});
}

listOperations.unshift.forEach((listKey) => {
function unshiftPosition(listKey) {
const existingList = lists[listKey] || LIST;

if (contains(existingList.positions, temporaryKey)) {
Expand All @@ -34,10 +44,40 @@ function applyListOperators(lists, listOperations = {}, temporaryKey) {
]
};
}
}

function invalidateList(listKey) {
updatedLists[listKey] = LIST;
}

function applyToAllListsNotExplicitlyReferenced(listOperation) {
without(Object.keys(lists), keysExplicitlyReferenced).forEach((listKey) => {
listOperation(listKey);
});
}

listOperations.push.forEach((listKey) => {
if (listKey === listWildcard) {
applyToAllListsNotExplicitlyReferenced(pushPosition);
} else {
pushPosition(listKey);
}
});

listOperations.unshift.forEach((listKey) => {
if (listKey === listWildcard) {
applyToAllListsNotExplicitlyReferenced(unshiftPosition);
} else {
unshiftPosition(listKey);
}
});

listOperations.invalidate.forEach((listKey) => {
updatedLists[listKey] = LIST;
if (listKey === listWildcard) {
applyToAllListsNotExplicitlyReferenced(invalidateList);
} else {
invalidateList(listKey);
}
});

return {
Expand Down

0 comments on commit 6730199

Please sign in to comment.