Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds ability to send custom action for resource #22

Merged
merged 4 commits into from
Jun 9, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@
"react-addons-transition-group": "^15.5.2",
"react-dom": "^15.4.2",
"react-redux": "^5.0.3",
"react-router": "~3.0.2",
"react-router": "^4.1.1",
"react-router-redux": "^4.0.8",
"react-ultimate-pagination": "^1.0.1",
"reactstrap": "^4.5.0",
@@ -56,7 +56,7 @@
"html-webpack-plugin": "^2.28.0",
"jest": "^19.0.2",
"node-sass": "^4.5.0",
"react-addons-test-utils": "^15.4.2",
"react-test-renderer": "^15.5.4",
"sass-loader": "^6.0.3",
"shx": "^0.2.2",
"style-loader": "^0.13.2",
5 changes: 1 addition & 4 deletions client/src/api/client.js
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ export const client = axios.create({
Accept: 'application/vnd.api+json',
'Content-Type': 'application/vnd.api+json',
},
paramsSerializer: params => qs.stringify(params, { format: 'RFC1738', arrayFormat: 'brackets' }),
});

client.interceptors.response.use(
@@ -47,10 +48,6 @@ client.interceptors.request.use(
error => Promise.reject(error),
);

const stringifyParams = params => qs.stringify(params, { format: 'RFC1738', arrayFormat: 'brackets' });

export const withParams = (url, params) => `${url}?${stringifyParams(params)}`;

export const normalizeResponse = (response) => {
const { data = [], included = [] } = response.data;
const dataByType = groupBy(castArray(data).concat(included), 'type');
5 changes: 4 additions & 1 deletion client/src/hocs/withResource.js
Original file line number Diff line number Diff line change
@@ -10,11 +10,12 @@ import {
createResource,
updateResource,
deleteResource,
resourceAction,
getOne,
getError,
} from '../store/api';

const withResource = (resourceType, resourceMeta) => (WrappedComponent) => {
const withResource = (resourceType, resourceMeta = {}) => (WrappedComponent) => {
const enhance = compose(
withHandlers({
onSubmit: props => (values, meta = {}) => {
@@ -48,6 +49,8 @@ const withResource = (resourceType, resourceMeta) => (WrappedComponent) => {
dispatch(updateResource(resourceType, payload, { ...resourceMeta, ...meta })),
deleteResource: (payload, meta) =>
dispatch(deleteResource(resourceType, payload, { ...resourceMeta, ...meta })),
resourceAction: (payload, meta) =>
dispatch(resourceAction(resourceType, payload, { ...resourceMeta, ...meta })),
});

return connect(mapStateToProps, mapDispatchToProps)(enhance(WrappedComponent));
7 changes: 5 additions & 2 deletions client/src/hocs/withResourceList.js
Original file line number Diff line number Diff line change
@@ -10,10 +10,11 @@ import {
createResource,
updateResource,
deleteResource,
resourceAction,
getList,
} from '../store/api';

const withResourceList = (resourceType, resourceMeta) => (WrappedComponent) => {
const withResourceList = (resourceType, resourceMeta = {}) => (WrappedComponent) => {
const enhance = compose(
withHandlers({
onFilter: props => (filter) => {
@@ -51,7 +52,7 @@ const withResourceList = (resourceType, resourceMeta) => (WrappedComponent) => {
);

const mapStateToProps = (state, props) => ({
resourceList: getList(state, resourceType),
resourceList: getList(state, resourceType, resourceMeta.list),
});

const mapDispatchToProps = dispatch => ({
@@ -63,6 +64,8 @@ const withResourceList = (resourceType, resourceMeta) => (WrappedComponent) => {
dispatch(updateResource(resourceType, payload, { ...resourceMeta, ...meta })),
deleteResource: (payload, meta) =>
dispatch(deleteResource(resourceType, payload, { ...resourceMeta, ...meta })),
resourceAction: (payload, meta) =>
dispatch(resourceAction(resourceType, payload, { ...resourceMeta, ...meta }))
});

return connect(mapStateToProps, mapDispatchToProps)(enhance(WrappedComponent));
23 changes: 17 additions & 6 deletions client/src/store/api/actions.js
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ import { omit } from 'lodash';

import {
client,
withParams,
normalizeResponse,
normalizeEndpointError,
normalizeErrors,
@@ -20,35 +19,47 @@ export const GET_MANY = createAsyncActionType('GET_MANY');
export const CREATE = createAsyncActionType('CREATE');
export const UPDATE = createAsyncActionType('UPDATE');
export const DELETE = createAsyncActionType('DELETE');
export const ACTION = createAsyncActionType('ACTION');

export const fetchOne = createAsyncAction(GET_ONE, (payload, meta) => client({
url: withParams(`${meta.url}/${payload.id}`, { include: meta.include, ...omit(payload, 'id') }),
url: `${meta.url}/${payload.id}`,
params: { include: meta.include, ...omit(payload, 'id') },
method: 'GET',
data: JSON.stringify(payload),
}).then(normalizeResponse).catch(normalizeEndpointError));

export const fetchList = createAsyncAction(GET_LIST, (payload, meta) => {
const params = { include: meta.include, ...payload };
return client({
url: withParams(meta.url, params),
url: meta.url,
params,
method: 'GET',
data: JSON.stringify(payload),
}).then(normalizeResponse).then(res => ({ ...res, params }));
});

export const createResource = createAsyncAction(CREATE, (payload, meta) => client({
url: withParams(meta.url, { include: meta.include }),
url: meta.url,
params: { include: meta.include },
method: 'POST',
data: denormalize(meta.key, payload),
}).then(normalizeResponse).catch(normalizeErrors));

export const updateResource = createAsyncAction(UPDATE, (payload, meta) => client({
url: withParams(`${meta.url}/${payload.id}`, { include: meta.include }),
url: `${meta.url}/${payload.id}`,
params: { include: meta.include },
method: 'PUT',
data: denormalize(meta.key, payload),
}).then(normalizeResponse).catch(normalizeErrors));

export const deleteResource = createAsyncAction(DELETE, (payload, meta) => client({
url: withParams(`${meta.url}/${payload.id}`),
url: `${meta.url}/${payload.id}`,
method: 'DELETE',
}).then(() => ({ data: payload })));

export const resourceAction = createAsyncAction(ACTION, (payload, meta = {}) => client({
url: meta.url,
params: { include: meta.include },
method: meta.method || 'PUT',
data: JSON.stringify(payload),
}).then(normalizeResponse).catch(normalizeErrors));
57 changes: 36 additions & 21 deletions client/yarn.lock
Original file line number Diff line number Diff line change
@@ -2733,13 +2733,14 @@ he@1.1.x:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"

history@^3.0.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/history/-/history-3.3.0.tgz#fcedcce8f12975371545d735461033579a6dae9c"
history@^4.6.0:
version "4.6.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.6.1.tgz#911cf8eb65728555a94f2b12780a0c531a14d2fd"
dependencies:
invariant "^2.2.1"
loose-envify "^1.2.0"
query-string "^4.2.2"
resolve-pathname "^2.0.0"
value-equal "^0.2.0"
warning "^3.0.0"

hmac-drbg@^1.0.0:
@@ -3808,7 +3809,7 @@ longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"

loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
dependencies:
@@ -4399,6 +4400,12 @@ path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"

path-to-regexp@^1.5.3:
version "1.7.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
dependencies:
isarray "0.0.1"

path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@@ -4791,7 +4798,7 @@ qs@^5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-5.2.1.tgz#801fee030e0b9450d6385adc48a4cc55b44aedfc"

query-string@^4.1.0, query-string@^4.2.2:
query-string@^4.1.0:
version "4.3.4"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
dependencies:
@@ -4841,13 +4848,6 @@ react-addons-css-transition-group@^15.5.2:
fbjs "^0.8.4"
object-assign "^4.1.0"

react-addons-test-utils@^15.4.2:
version "15.5.1"
resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.5.1.tgz#e0d258cda2a122ad0dff69f838260d0c3958f5f7"
dependencies:
fbjs "^0.8.4"
object-assign "^4.1.0"

react-addons-transition-group@^15.5.2:
version "15.5.2"
resolved "https://registry.yarnpkg.com/react-addons-transition-group/-/react-addons-transition-group-15.5.2.tgz#da6989d9cffe27dffacaedc862000ffb09ae2206"
@@ -4880,18 +4880,25 @@ react-router-redux@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/react-router-redux/-/react-router-redux-4.0.8.tgz#227403596b5151e182377dab835b5d45f0f8054e"

react-router@~3.0.2:
version "3.0.5"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-3.0.5.tgz#c3b7873758045a8bbc9562aef4ff4bc8cce7c136"
react-router@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95"
dependencies:
create-react-class "^15.5.1"
history "^3.0.0"
history "^4.6.0"
hoist-non-react-statics "^1.2.0"
invariant "^2.2.1"
loose-envify "^1.2.0"
prop-types "^15.5.6"
invariant "^2.2.2"
loose-envify "^1.3.1"
path-to-regexp "^1.5.3"
prop-types "^15.5.4"
warning "^3.0.0"

react-test-renderer@^15.5.4:
version "15.5.4"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-15.5.4.tgz#d4ebb23f613d685ea8f5390109c2d20fbf7c83bc"
dependencies:
fbjs "^0.8.9"
object-assign "^4.1.0"

react-ultimate-pagination@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/react-ultimate-pagination/-/react-ultimate-pagination-1.0.1.tgz#605b06e5499626b41b527bf11458985bd7fa7d91"
@@ -5176,6 +5183,10 @@ resolve-from@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"

resolve-pathname@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944"

resolve@1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
@@ -5868,6 +5879,10 @@ validate-npm-package-license@^3.0.1:
spdx-correct "~1.0.0"
spdx-expression-parse "~1.0.0"

value-equal@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.1.tgz#c220a304361fce6994dbbedaa3c7e1a1b895871d"

vary@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"