106 lines
3.0 KiB
JavaScript
106 lines
3.0 KiB
JavaScript
// Shared helpers for parsing and sorting web list query state.
|
|
|
|
function parsePageNumber(value) {
|
|
const pageNumber = Math.floor(Number(value) || 1);
|
|
return Math.max(1, pageNumber);
|
|
}
|
|
|
|
function getSearchQuery(req) {
|
|
return String(req && req.query && req.query.search || '').trim();
|
|
}
|
|
|
|
function getSortQuery(req) {
|
|
return String(req && req.query && req.query.sort || '').trim();
|
|
}
|
|
|
|
function getSortDirectionQuery(req) {
|
|
return String(req && req.query && req.query.direction || '').trim().toLowerCase() === 'desc' ? 'desc' : 'asc';
|
|
}
|
|
|
|
function normalizeSortDirection(value) {
|
|
return String(value || '').trim().toLowerCase() === 'desc' ? 'desc' : 'asc';
|
|
}
|
|
|
|
function getComparableSortValue(rawValue) {
|
|
const value = String(rawValue || '').trim();
|
|
if (!value) {
|
|
return { type: 'empty', value: '' };
|
|
}
|
|
|
|
const numericValue = Number(value.replace(/,/g, ''));
|
|
if (!Number.isNaN(numericValue)) {
|
|
return { type: 'number', value: numericValue };
|
|
}
|
|
|
|
const dateValue = Date.parse(value);
|
|
if (!Number.isNaN(dateValue)) {
|
|
return { type: 'date', value: dateValue };
|
|
}
|
|
|
|
return { type: 'string', value: value.toLowerCase() };
|
|
}
|
|
|
|
function compareSortValues(leftValue, rightValue) {
|
|
if (leftValue.type === 'empty' && rightValue.type === 'empty') {
|
|
return 0;
|
|
}
|
|
if (leftValue.type === 'empty') {
|
|
return 1;
|
|
}
|
|
if (rightValue.type === 'empty') {
|
|
return -1;
|
|
}
|
|
if (leftValue.type === rightValue.type) {
|
|
if (leftValue.value < rightValue.value) {
|
|
return -1;
|
|
}
|
|
if (leftValue.value > rightValue.value) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
return String(leftValue.value).localeCompare(String(rightValue.value), undefined, { numeric: true, sensitivity: 'base' });
|
|
}
|
|
|
|
function sortRows(rows, accessor, sortDirection) {
|
|
const multiplier = normalizeSortDirection(sortDirection) === 'desc' ? -1 : 1;
|
|
return (Array.isArray(rows) ? rows.slice() : []).sort(function (leftRow, rightRow) {
|
|
return compareSortValues(getComparableSortValue(accessor(leftRow)), getComparableSortValue(accessor(rightRow))) * multiplier;
|
|
});
|
|
}
|
|
|
|
function createSearchMatcher(searchTerm, fields) {
|
|
const query = String(searchTerm || '').trim().toLowerCase();
|
|
|
|
if (!query) {
|
|
return function () {
|
|
return true;
|
|
};
|
|
}
|
|
|
|
const normalizedFields = Array.isArray(fields) ? fields : [];
|
|
return function (item) {
|
|
const haystack = normalizedFields.map(function (field) {
|
|
if (typeof field === 'function') {
|
|
return field(item);
|
|
}
|
|
return item && field ? item[field] : '';
|
|
}).map(function (value) {
|
|
return String(value || '').trim().toLowerCase();
|
|
}).join(' ');
|
|
|
|
return haystack.indexOf(query) !== -1;
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
parsePageNumber: parsePageNumber,
|
|
getSearchQuery: getSearchQuery,
|
|
getSortQuery: getSortQuery,
|
|
normalizeSortDirection: normalizeSortDirection,
|
|
getSortDirectionQuery: getSortDirectionQuery,
|
|
getComparableSortValue: getComparableSortValue,
|
|
compareSortValues: compareSortValues,
|
|
sortRows: sortRows,
|
|
createSearchMatcher: createSearchMatcher
|
|
}; |