From 4aed575e02d0b010e263cbeb72eb802d5d6e0284 Mon Sep 17 00:00:00 2001 From: Francois Zaninotto Date: Tue, 23 Oct 2018 14:54:27 +0200 Subject: [PATCH] Add support for arrays of references in fetchRelatedRecords Closes #2452 --- .../src/button/ExportButton.js | 41 +++++++++++++++---- .../src/button/ExportButton.spec.js | 30 ++++++++++++++ 2 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 packages/ra-ui-materialui/src/button/ExportButton.spec.js diff --git a/packages/ra-ui-materialui/src/button/ExportButton.js b/packages/ra-ui-materialui/src/button/ExportButton.js index 125bfa11410..d4be01ec854 100644 --- a/packages/ra-ui-materialui/src/button/ExportButton.js +++ b/packages/ra-ui-materialui/src/button/ExportButton.js @@ -19,6 +19,38 @@ const sanitizeRestProps = ({ ...rest }) => rest; +/** + * Extracts, aggregates and deduplicates the ids of related records + * + * @example + * const books = [ + * { id: 1, author_id: 123, title: 'Pride and Prejudice' }, + * { id: 2, author_id: 123, title: 'Sense and Sensibility' }, + * { id: 3, author_id: 456, title: 'War and Peace' }, + * ]; + * getRelatedIds(books, 'author_id'); => [123, 456] + * + * @example + * const books = [ + * { id: 1, tag_ids: [1, 2], title: 'Pride and Prejudice' }, + * { id: 2, tag_ids: [2, 3], title: 'Sense and Sensibility' }, + * { id: 3, tag_ids: [4], title: 'War and Peace' }, + * ]; + * getRelatedIds(records, 'tag_ids'); => [1, 2, 3, 4] + * + * @param {Object[]} records An array of records + * @param {string} field the identifier of the record field to use + */ +export const getRelatedIds = (records, field) => + Array.from( + new Set( + records + .filter(record => record[field] != null) + .map(record => record[field]) + .reduce((ids, value) => ids.concat(value), []) + ) + ); + /** * Helper function for calling the data provider with GET_MANY * via redux and saga, and getting a Promise in return @@ -32,16 +64,9 @@ const sanitizeRestProps = ({ */ const fetchRelatedRecords = dispatch => (data, field, resource) => new Promise((resolve, reject) => { - const sanitizedData = data - .filter(record => record[field]) - .map(record => record[field]); - - // find unique keys - const ids = Array.from(new Set(sanitizedData)); - dispatch({ type: CRUD_GET_MANY, - payload: { ids }, + payload: { ids: getRelatedIds(data, field) }, meta: { resource, fetch: GET_MANY, diff --git a/packages/ra-ui-materialui/src/button/ExportButton.spec.js b/packages/ra-ui-materialui/src/button/ExportButton.spec.js new file mode 100644 index 00000000000..a4c332ac739 --- /dev/null +++ b/packages/ra-ui-materialui/src/button/ExportButton.spec.js @@ -0,0 +1,30 @@ +import { getRelatedIds } from './ExportButton'; + +describe('ExportButton', () => { + describe('getRelatedIds', () => { + it('should ignore null or undefined values', () => { + const books = [ + { id: 1, author_id: 123, title: 'Pride and Prejudice' }, + { id: 2, author_id: null }, + { id: 3 }, + ]; + expect(getRelatedIds(books, 'author_id')).toEqual([123]); + }); + it('should aggregate scalar related ids', () => { + const books = [ + { id: 1, author_id: 123, title: 'Pride and Prejudice' }, + { id: 2, author_id: 123, title: 'Sense and Sensibility' }, + { id: 3, author_id: 456, title: 'War and Peace' }, + ]; + expect(getRelatedIds(books, 'author_id')).toEqual([123, 456]); + }); + it('should aggregate arrays of related ids', () => { + const books = [ + { id: 1, tag_ids: [1, 2], title: 'Pride and Prejudice' }, + { id: 2, tag_ids: [2, 3], title: 'Sense and Sensibility' }, + { id: 3, tag_ids: [4], title: 'War and Peace' }, + ]; + expect(getRelatedIds(books, 'tag_ids')).toEqual([1, 2, 3, 4]); + }); + }); +});