Skip to content

Commit

Permalink
feat(sorting): Added support for sorting results from the API (EN-1536)
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel James authored and thzinc committed Mar 24, 2017
1 parent 4b2f8ed commit fb5994c
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ export const vehicles = {
toBlob(vehicles.list),
{
headers: {
Link: '</1/SYNC/vehicles?page=1&perPage=10&q=12>; rel="next", </1/SYNC/vehicles?page=1&perPage=10&q=12>; rel="last"',
Link: '</1/SYNC/vehicles?page=1&perPage=10&q=12&sort=>; rel="next", </1/SYNC/vehicles?page=1&perPage=10&q=12&sort=>; rel="last"',
},
});
const singleResponse = () => new Response(toBlob(vehicles.getById(1)));

fetchMock
.get(client.resolve('/1/SYNC/vehicles?page=1&perPage=10&q=12'), listResponse)
.get(client.resolve('/1/SYNC/vehicles?page=1&perPage=10&q=12&sort='), listResponse)
.get(client.resolve('/1/SYNC/vehicles/1'), singleResponse);
},
getById: id => vehicles.list.find(v => v.id === id),
Expand Down
63 changes: 62 additions & 1 deletion src/resources/PagedContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ class PagedContext {
* @param {Object} [params] Object of querystring parameters to append to the URL
* @param {Number} [params.page=1] Number of the page to request
* @param {Number} [params.perPage=10] Number of items per page to request
* @param {Object[]} [params.sortFields] Array of sort fields to sort the results by
* @param {string} params.sortFields[].field String representing the field to sort by.
* Fields are specified in dotted property notation.
* @param {string} params.sortFields[].direction Direction by which to sort results.
* Valid values are 'asc' and 'desc'.
*/
constructor(client, params = {}) {
this.client = client;
this.params = {
page: 1,
perPage: 10,
sortFields: [],
...params,
};
}
Expand Down Expand Up @@ -52,6 +58,57 @@ class PagedContext {
return this;
}

/**
* Sets the requested sort order of the response, clearing any prior sort order
* @example
* const context = new PagedContext(...);
* context
* .sortBy('assignment.start', 'desc')
* .thenBy('name')
* .getPage()
* .then(page => ...);
* @param {string} field String representing the field to sort by.
* Fields are specified in dotted property notation.
* @param {string} [direction=asc] Direction by which to sort results.
* Valid values are 'asc' and 'desc'.
* @returns {PagedContext} Returns itself
*/
sortedBy(field, direction = 'asc') {
this.params.sortFields = [
{
field,
direction,
},
];
return this;
}

/**
* Adds to the requested sort order
* @example
* const context = new PagedContext(...);
* context
* .sortBy('assignment.start', 'desc')
* .thenBy('name')
* .getPage()
* .then(page => ...);
* @param {string} field String representing the field to sort by.
* Fields are specified in dotted property notation.
* @param {string} [direction=asc] Direction by which to sort results.
* Valid values are 'asc' and 'desc'.
* @returns {PagedContext} Returns itself
*/
thenBy(field, direction = 'asc') {
this.params.sortFields = [
...this.params.sortFields,
{
field,
direction,
},
];
return this;
}

/**
* Gets the first page of results for this context
* @param {Object} Type Type of resource to request a page of
Expand All @@ -61,7 +118,11 @@ class PagedContext {
*/
page(Type, uri, params = {}) {
const fromObject = o => new Type(this.client, o);
return new Page(this.client, fromObject, uri, { ...this.params, ...params }).fetch();
const { sortFields, ...otherParams } = this.params;
const sort = sortFields
.map(x => `${x.field} ${x.direction}`)
.join(',');
return new Page(this.client, fromObject, uri, { ...otherParams, sort, ...params }).fetch();
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/resources/VehiclesContext.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('When building a query for vehicles', () => {
client.setAuthenticated();

beforeEach(() => fetchMock
.get(client.resolve('/1/SYNC/vehicles?page=9&perPage=27&q=valid'), mockVehicles.list)
.get(client.resolve('/1/SYNC/vehicles?page=9&perPage=27&q=valid&sort='), mockVehicles.list)
.catch(503));
afterEach(fetchMock.restore);

Expand Down

0 comments on commit fb5994c

Please sign in to comment.