diff --git a/packages/common/src/services/__tests__/utilities.spec.ts b/packages/common/src/services/__tests__/utilities.spec.ts index 897e2ac2f..2ebab835a 100644 --- a/packages/common/src/services/__tests__/utilities.spec.ts +++ b/packages/common/src/services/__tests__/utilities.spec.ts @@ -57,6 +57,34 @@ describe('Service/Utilies', () => { ]); }); + it('should produce same result when calling the function twice with input that have a parent/child array and return a hierarchical array structure', () => { + const input = [ + { id: 18, size: 90, dateModified: '2015-03-03', file: 'something.txt', parentId: null, }, + { id: 11, file: 'Music', parentId: null, }, + { id: 12, file: 'mp3', parentId: 11, }, + { id: 16, file: 'rock', parentId: 12, }, + { id: 17, dateModified: '2015-05-13', file: 'soft.mp3', size: 98, parentId: 16, }, + { id: 14, file: 'pop', parentId: 12, }, + { id: 15, dateModified: '2015-03-01', file: 'theme.mp3', size: 85, parentId: 14, }, + ]; + + const output1 = unflattenParentChildArrayToTree(input, { parentPropName: 'parentId', childrenPropName: 'files' }); + const output2 = unflattenParentChildArrayToTree(input, { parentPropName: 'parentId', childrenPropName: 'files' }); + + expect(output1).toEqual([ + { + id: 11, __treeLevel: 0, __collapsed: false, parentId: null, file: 'Music', files: [{ + id: 12, __treeLevel: 1, __collapsed: false, parentId: 11, file: 'mp3', files: [ + { id: 14, __treeLevel: 2, __collapsed: false, parentId: 12, file: 'pop', files: [{ id: 15, __treeLevel: 3, parentId: 14, file: 'theme.mp3', dateModified: '2015-03-01', size: 85, }] }, + { id: 16, __treeLevel: 2, __collapsed: false, parentId: 12, file: 'rock', files: [{ id: 17, __treeLevel: 3, parentId: 16, file: 'soft.mp3', dateModified: '2015-05-13', size: 98, }] }, + ] + }] + }, + { id: 18, __treeLevel: 0, parentId: null, file: 'something.txt', dateModified: '2015-03-03', size: 90, }, + ]); + expect(output1).toEqual(output2); + }); + it('should take a parent/child array with aggregators and return a hierarchical array structure', () => { const input = [ { id: 18, size: 90, dateModified: '2015-03-03', file: 'something.txt', parentId: null, }, @@ -82,6 +110,34 @@ describe('Service/Utilies', () => { { id: 18, __treeLevel: 0, parentId: null, file: 'something.txt', dateModified: '2015-03-03', size: 90, }, ]); }); + + it('should produce same result when calling the function twice with input that have a parent/child array with aggregators and return a hierarchical array structure', () => { + const input = [ + { id: 18, size: 90, dateModified: '2015-03-03', file: 'something.txt', parentId: null, }, + { id: 11, file: 'Music', parentId: null, __treeTotals: { count: { size: 2, }, sum: { size: (98 + 85), }, }, }, + { id: 12, file: 'mp3', parentId: 11, __treeTotals: { count: { size: 2, }, sum: { size: (98 + 85), }, }, }, + { id: 16, file: 'rock', parentId: 12, __treeTotals: { count: { size: 2, }, sum: { size: 98, }, }, }, + { id: 17, dateModified: '2015-05-13', file: 'soft.mp3', size: 98, parentId: 16, }, + { id: 14, file: 'pop', parentId: 12, __treeTotals: { count: { size: 2, }, sum: { size: 85, }, }, }, + { id: 15, dateModified: '2015-03-01', file: 'theme.mp3', size: 85, parentId: 14, }, + ]; + + const output1 = unflattenParentChildArrayToTree(input, { aggregators: [new SumAggregator('size')], parentPropName: 'parentId', childrenPropName: 'files' }); + const output2 = unflattenParentChildArrayToTree(input, { aggregators: [new SumAggregator('size')], parentPropName: 'parentId', childrenPropName: 'files' }); + + expect(output1).toEqual([ + { + id: 11, __treeLevel: 0, __collapsed: false, parentId: null, file: 'Music', __treeTotals: { count: { size: 2, }, sum: { size: (98 + 85), }, }, files: [{ + id: 12, __treeLevel: 1, __collapsed: false, parentId: 11, file: 'mp3', __treeTotals: { count: { size: 2, }, sum: { size: (98 + 85), }, }, files: [ + { id: 14, __treeLevel: 2, __collapsed: false, parentId: 12, file: 'pop', __treeTotals: { count: { size: 1, }, sum: { size: 85, }, }, files: [{ id: 15, __treeLevel: 3, parentId: 14, file: 'theme.mp3', dateModified: '2015-03-01', size: 85, }] }, + { id: 16, __treeLevel: 2, __collapsed: false, parentId: 12, file: 'rock', __treeTotals: { count: { size: 1, }, sum: { size: 98, }, }, files: [{ id: 17, __treeLevel: 3, parentId: 16, file: 'soft.mp3', dateModified: '2015-05-13', size: 98, }] }, + ] + }] + }, + { id: 18, __treeLevel: 0, parentId: null, file: 'something.txt', dateModified: '2015-03-03', size: 90, }, + ]); + expect(output1).toEqual(output2); + }); }); describe('cancellablePromise method', () => { diff --git a/packages/common/src/services/utilities.ts b/packages/common/src/services/utilities.ts index e1d47a7cc..fbc17a928 100644 --- a/packages/common/src/services/utilities.ts +++ b/packages/common/src/services/utilities.ts @@ -123,7 +123,7 @@ export function flattenToParentChildArray(treeArray: T[], options?: { aggrega type FlatParentChildArray = Omit; if (options?.shouldAddTreeLevelNumber) { - if (options?.aggregators) { + if (Array.isArray(options?.aggregators)) { options.aggregators.forEach((aggregator) => { addTreeLevelAndAggregatorsByMutation(treeArray, { childrenPropName, levelPropName, aggregator }); }); @@ -179,7 +179,13 @@ export function unflattenParentChildArrayToTree x.id === item.id); + if (existIdx < 0) { + p[childrenPropName].push(item); + } else { + // replace existing one when already exists (probably equal to the same item in the end) + p[childrenPropName][existIdx] = item; + } if (p[collapsedPropName] === undefined) { p[collapsedPropName] = options?.initiallyCollapsed ?? false; } @@ -189,7 +195,7 @@ export function unflattenParentChildArrayToTree { addTreeLevelAndAggregatorsByMutation(roots, { childrenPropName, levelPropName, aggregator }, 0); });