Add sorting foundation as util and using it within indexed-db-handler (#2773)

This commit is contained in:
Carlos Alcaide Corvo authored and GitHub committed 2025-05-13 16:18:04 -04:00
1 parent e96131a933
commit b0d26fe1e6
5 files changed
+594 -26

No files matched your search

+3 -8
View File
@@ -70,14 +70,9 @@ export async function queryIndexedDb(indexedDb, resource, query) {
);
}
// OrderBy has to be used on where clauses while if it's a
// collection already we have to use sortBy. We'll also sort by
// descending order based on created time to match the API as any
// "or" clause can change the order
if (filterCollection.orderBy) {
return filterCollection.orderBy(getKey('created_time')).reverse().toArray();
}
return filterCollection.reverse().sortBy(getKey('created_time'));
// filterCollection can be Dexie Table or a Dexie Collection.
// This is an important detail you need to keep in mind when working on it.
return filterCollection.toArray();
}
const buildInitialWhereClause = ({ filterArrayOrObject, table, key }) => {
+73
View File
@@ -0,0 +1,73 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
// created_time is not an attribute defined on all models, but is present in all the resources
// coming from API
const SORT_DEFAULT_ATTRIBUTE = 'created_time';
const SORT_DIRECTION_ASCENDING = 'asc';
const SORT_DIRECTION_DESCENDING = 'desc';
const sortFunctions = {
string: (a, b) => String(a).localeCompare(String(b)),
date: (a, b) => new Date(a).getTime() - new Date(b).getTime(),
number: (a, b) => Number(a) - Number(b),
boolean: (a, b) => Number(a) - Number(b),
};
function getSortableValue(schema, record, attribute) {
if (attribute === 'id') {
return record.id;
}
// all models have a created_time attribute but not all models have it defined
if (attribute === 'created_time') {
return record.attributes.created_time;
}
if (schema.attributes.has(attribute)) {
return record.attributes[attribute];
}
const attributes = Array.from(schema.attributes.keys());
throw new Error(
`The attribute "${attribute}" does not map to the model definition of type "${record.type}". Supported sortable attributes are 'id', 'created_time', or ${attributes.map((attr) => `'${attr}'`).join(', ')}`,
);
}
export const sortResults = (results, { querySort, schema }) => {
querySort = querySort ?? {};
const sortAttribute = querySort.attribute || SORT_DEFAULT_ATTRIBUTE;
// Default sort direction is ascending unless we are sorting by `created_time` (default sort attribute)
const defaultSortDirection =
sortAttribute === SORT_DEFAULT_ATTRIBUTE
? SORT_DIRECTION_DESCENDING
: SORT_DIRECTION_ASCENDING;
const sortDirection = querySort.direction || defaultSortDirection;
if (
![SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING].includes(
sortDirection,
)
) {
throw new Error('Invalid sort direction');
}
const sortAttributeDataType = schema.attributes.get(sortAttribute)?.type;
const sortFunction =
sortFunctions[sortAttributeDataType] ?? sortFunctions.string;
return results.toSorted((a, b) => {
// Extract the values to sort and sort them.
const sortValueA = getSortableValue(schema, a, sortAttribute);
const sortValueB = getSortableValue(schema, b, sortAttribute);
const sortResult = sortFunction(sortValueA, sortValueB);
return sortDirection === SORT_DIRECTION_ASCENDING
? sortResult
: -1 * sortResult;
});
};