mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	* move list to component * use helper instead * add changelog * clarify changelog copy * delete components now that helper is in use * move helper to util, remove template helper invokation * add optional sorting to lazyPaginatedQuery based on sortBy query attribute * Add serialization to entity-alias and entity so that they can be sorted by name on list view * Same logic as base normalizeItems for extractLazyPaginatedData so that metadata shows on list * Add headers --------- Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										3
									
								
								changelog/24103.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								changelog/24103.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| ```release-note:improvement | ||||
| ui: Sort list view of entities and aliases alphabetically using the item name | ||||
| ``` | ||||
| @@ -13,6 +13,7 @@ export default Route.extend(ListRoute, { | ||||
|         responsePath: 'data.keys', | ||||
|         page: params.page, | ||||
|         pageFilter: params.pageFilter, | ||||
|         sortBy: 'name', | ||||
|       }) | ||||
|       .catch((err) => { | ||||
|         if (err.httpStatus === 404) { | ||||
|   | ||||
| @@ -13,6 +13,7 @@ export default Route.extend(ListRoute, { | ||||
|         responsePath: 'data.keys', | ||||
|         page: params.page, | ||||
|         pageFilter: params.pageFilter, | ||||
|         sortBy: 'name', | ||||
|       }) | ||||
|       .catch((err) => { | ||||
|         if (err.httpStatus === 404) { | ||||
|   | ||||
| @@ -4,6 +4,10 @@ import ApplicationSerializer from '../application'; | ||||
| export default ApplicationSerializer.extend({ | ||||
|   normalizeItems(payload) { | ||||
|     if (payload.data.keys && Array.isArray(payload.data.keys)) { | ||||
|       if (typeof payload.data.keys[0] !== 'string') { | ||||
|         // If keys is not an array of strings, it was already normalized into objects in extractLazyPaginatedData | ||||
|         return payload.data.keys; | ||||
|       } | ||||
|       return payload.data.keys.map((key) => { | ||||
|         const model = payload.data.key_info[key]; | ||||
|         model.id = key; | ||||
|   | ||||
| @@ -1,2 +1,13 @@ | ||||
| import IdentitySerializer from './_base'; | ||||
| export default IdentitySerializer.extend(); | ||||
| export default IdentitySerializer.extend({ | ||||
|   extractLazyPaginatedData(payload) { | ||||
|     return payload.data.keys.map((key) => { | ||||
|       const model = payload.data.key_info[key]; | ||||
|       model.id = key; | ||||
|       if (payload.backend) { | ||||
|         model.backend = payload.backend; | ||||
|       } | ||||
|       return model; | ||||
|     }); | ||||
|   }, | ||||
| }); | ||||
|   | ||||
| @@ -7,4 +7,14 @@ export default IdentitySerializer.extend(EmbeddedRecordsMixin, { | ||||
|   attrs: { | ||||
|     aliases: { embedded: 'always' }, | ||||
|   }, | ||||
|   extractLazyPaginatedData(payload) { | ||||
|     return payload.data.keys.map((key) => { | ||||
|       const model = payload.data.key_info[key]; | ||||
|       model.id = key; | ||||
|       if (payload.backend) { | ||||
|         model.backend = payload.backend; | ||||
|       } | ||||
|       return model; | ||||
|     }); | ||||
|   }, | ||||
| }); | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import { assert } from '@ember/debug'; | ||||
| import { set, get, computed } from '@ember/object'; | ||||
| import clamp from 'vault/utils/clamp'; | ||||
| import config from 'vault/config/environment'; | ||||
| import sortObjects from 'vault/utils/sort-objects'; | ||||
|  | ||||
| const { DEFAULT_PAGE_SIZE } = config.APP; | ||||
|  | ||||
| @@ -176,11 +177,12 @@ export default Store.extend({ | ||||
|   // store data cache as { response, dataset} | ||||
|   // also populated `lazyCaches` attribute | ||||
|   storeDataset(modelName, query, response, array) { | ||||
|     const dataSet = { | ||||
|     const dataset = query.sortBy ? sortObjects(array, query.sortBy) : array; | ||||
|     const value = { | ||||
|       response, | ||||
|       dataset: array, | ||||
|       dataset, | ||||
|     }; | ||||
|     this.setLazyCacheForModel(modelName, query, dataSet); | ||||
|     this.setLazyCacheForModel(modelName, query, value); | ||||
|   }, | ||||
|  | ||||
|   clearDataset(modelName) { | ||||
|   | ||||
							
								
								
									
										14
									
								
								ui/app/utils/sort-objects.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								ui/app/utils/sort-objects.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| export default function sortObjects(array, key) { | ||||
|   if (Array.isArray(array) && array?.every((e) => e[key] && typeof e[key] === 'string')) { | ||||
|     return array.sort((a, b) => { | ||||
|       // ignore upper vs lowercase | ||||
|       const valueA = a[key].toUpperCase(); | ||||
|       const valueB = b[key].toUpperCase(); | ||||
|       if (valueA < valueB) return -1; | ||||
|       if (valueA > valueB) return 1; | ||||
|       return 0; | ||||
|     }); | ||||
|   } | ||||
|   // if not sortable, return original array | ||||
|   return array; | ||||
| } | ||||
							
								
								
									
										86
									
								
								ui/tests/unit/utils/sort-objects-test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								ui/tests/unit/utils/sort-objects-test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| import sortObjects from 'vault/utils/sort-objects'; | ||||
| import { module, test } from 'qunit'; | ||||
|  | ||||
| module('Unit | Utility | sort-objects', function () { | ||||
|   test('it sorts array of objects', function (assert) { | ||||
|     const originalArray = [ | ||||
|       { foo: 'grape', bar: 'third' }, | ||||
|       { foo: 'banana', bar: 'second' }, | ||||
|       { foo: 'lemon', bar: 'fourth' }, | ||||
|       { foo: 'apple', bar: 'first' }, | ||||
|     ]; | ||||
|     const expectedArray = [ | ||||
|       { bar: 'first', foo: 'apple' }, | ||||
|       { bar: 'second', foo: 'banana' }, | ||||
|       { bar: 'third', foo: 'grape' }, | ||||
|       { bar: 'fourth', foo: 'lemon' }, | ||||
|     ]; | ||||
|  | ||||
|     assert.propEqual(sortObjects(originalArray, 'foo'), expectedArray, 'it sorts array of objects'); | ||||
|  | ||||
|     const originalWithNumbers = [ | ||||
|       { foo: 'Z', bar: 'fourth' }, | ||||
|       { foo: '1', bar: 'first' }, | ||||
|       { foo: '2', bar: 'second' }, | ||||
|       { foo: 'A', bar: 'third' }, | ||||
|     ]; | ||||
|     const expectedWithNumbers = [ | ||||
|       { bar: 'first', foo: '1' }, | ||||
|       { bar: 'second', foo: '2' }, | ||||
|       { bar: 'third', foo: 'A' }, | ||||
|       { bar: 'fourth', foo: 'Z' }, | ||||
|     ]; | ||||
|     assert.propEqual( | ||||
|       sortObjects(originalWithNumbers, 'foo'), | ||||
|       expectedWithNumbers, | ||||
|       'it sorts strings with numbers and letters' | ||||
|     ); | ||||
|   }); | ||||
|  | ||||
|   test('it disregards capitalization', function (assert) { | ||||
|     // sort() arranges capitalized values before lowercase, the helper removes case by making all strings toUppercase() | ||||
|     const originalArray = [ | ||||
|       { foo: 'something-a', bar: 'third' }, | ||||
|       { foo: 'D-something', bar: 'second' }, | ||||
|       { foo: 'SOMETHING-b', bar: 'fourth' }, | ||||
|       { foo: 'a-something', bar: 'first' }, | ||||
|     ]; | ||||
|     const expectedArray = [ | ||||
|       { bar: 'first', foo: 'a-something' }, | ||||
|       { bar: 'second', foo: 'D-something' }, | ||||
|       { bar: 'third', foo: 'something-a' }, | ||||
|       { bar: 'fourth', foo: 'SOMETHING-b' }, | ||||
|     ]; | ||||
|  | ||||
|     assert.propEqual( | ||||
|       sortObjects(originalArray, 'foo'), | ||||
|       expectedArray, | ||||
|       'it sorts array of objects regardless of capitalization' | ||||
|     ); | ||||
|   }); | ||||
|  | ||||
|   test('it fails gracefully', function (assert) { | ||||
|     const originalArray = [ | ||||
|       { foo: 'b', bar: 'two' }, | ||||
|       { foo: 'a', bar: 'one' }, | ||||
|     ]; | ||||
|     assert.propEqual( | ||||
|       sortObjects(originalArray, 'someKey'), | ||||
|       originalArray, | ||||
|       'it returns original array if key does not exist' | ||||
|     ); | ||||
|     assert.deepEqual(sortObjects('not an array'), 'not an array', 'it returns original arg if not an array'); | ||||
|  | ||||
|     const notStrings = [ | ||||
|       { foo: '1', bar: 'third' }, | ||||
|       { foo: 'Z', bar: 'second' }, | ||||
|       { foo: 1, bar: 'fourth' }, | ||||
|       { foo: 2, bar: 'first' }, | ||||
|     ]; | ||||
|     assert.propEqual( | ||||
|       sortObjects(notStrings, 'foo'), | ||||
|       notStrings, | ||||
|       'it returns original array if values are not all strings' | ||||
|     ); | ||||
|   }); | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user
	 Chelsea Shaw
					Chelsea Shaw