import { differenceWith, isEmpty, isEqual, reverse, unionWith } from 'lodash'; export const parseQueryString = (queryString: Record) => { // pagination const pageIndex = parseInt(queryString.page ?? '0', 0) - 1; const pageSize = Math.min(parseInt(queryString.limit ?? '10', 10), 100); const pagination = pageIndex >= 0 && pageSize > 0 ? { pageIndex, pageSize } : undefined; // pagination /*let pagination = undefined; if (page !== undefined && limit !== undefined) { let parsedPage = toSafeInteger(queryString['page']) - 1; if (parsedPage < 0) parsedPage = 0; let parsedPageSize = toSafeInteger(queryString['limit']); if (parsedPageSize > 100) parsedPageSize = 100; if (parsedPageSize < 5) parsedPageSize = 5; pagination = { pageIndex: parsedPage, pageSize: parsedPageSize, }; }*/ // sorter // sorter const sorter = (queryString.sort ?? '') .split(',') .map((token) => token.match(/([+-]?)([\w_]+)/i)) .slice(0, 3) .map((item) => (item ? { id: item[2], desc: item[1] === '-' } : null)) .filter(Boolean); /*let sorter = []; if (sort !== undefined) { sorter = sort .split(',') .map((token) => token.match(/([+-]?)([\w_]+)/i)) .slice(0, 3) .map((item) => item ? { id: item[2], desc: item[1] === '-' } : null ); }*/ // filters const filters = Object.entries(queryString) .filter(([key]) => key !== 'page' && key !== 'limit' && key !== 'sort') .map(([key, value]) => { const [, field, , , operator] = key.match(/([\w]+)(([\[])([\w]+)([\]]))*/i) ?? []; const sanitizedOperator = _sanitizeOperator(operator ?? ''); return !isEmpty(value) ? { field, operator: sanitizedOperator, value } : null; }) .filter(Boolean); /*let filters = []; if (filterCandidates !== undefined) { Object.keys(filterCandidates).map((token) => { const [, field, , , operator] = token.match( */ // /([\w]+)(([\[])([\w]+)([\]]))*/i /* ); const value = filterCandidates[token]; if (!isEmpty(value)) { filters.push({ field, operator: _sanitizeOperator(operator), value, }); } }); }*/ return { pagination, sorter, filters, }; }; export const buildQueryString = ({ pagination, sorter, filters }) => { const params = new URLSearchParams(); if ( pagination && pagination.pageIndex !== undefined && pagination.pageSize !== undefined ) { params.append('page', String(pagination.pageIndex + 1)); params.append('limit', String(pagination.pageSize)); } if (sorter && Array.isArray(sorter) && sorter.length > 0) { params.append( 'sort', sorter.map(({ id, desc }) => `${desc ? '-' : ''}${id}`).toString() ); } if (filters && Array.isArray(filters) && filters.length > 0) { filters.forEach((filterItem) => { if (filterItem.value !== undefined) { let operator = _mapFilterOperator(filterItem.operator); if (operator === 'eq') { params.append(`${filterItem.field}`, filterItem.value); } else { params.append( `${filterItem.field}[${_mapFilterOperator( filterItem.operator )}]`, filterItem.value ); } } }); } return params.toString(); }; export const combineFilters = (requiredFilters = [], otherFilters = []) => [ ...differenceWith(otherFilters, requiredFilters, isEqual), ...requiredFilters, ]; export const unionFilters = ( permanentFilter = [], newFilters = [], prevFilters = [] ) => reverse( unionWith( permanentFilter, newFilters, prevFilters, (left, right) => left.field == right.field && left.operator == right.operator ) ).filter( (crudFilter) => crudFilter.value !== undefined && crudFilter.value !== null ); export const extractTableSortPropertiesFromColumn = (columns) => { const _extractColumnSortProperies = (column) => { const { canSort, isSorted, sortedIndex, isSortedDesc } = column; if (!isSorted || !canSort) { return undefined; } else { return { index: sortedIndex, field: column.id, order: isSortedDesc ? 'DESC' : 'ASC', }; } }; return columns .map((column) => _extractColumnSortProperies(column)) .filter((item) => item) .sort((a, b) => a.index - b.index); }; export const extractTableSortProperties = (sorter) => { return sorter.map((sortItem, index) => ({ index, field: sortItem.id, order: sortItem.desc ? 'DESC' : 'ASC', })); }; export const extractTableFilterProperties = (filters) => filters.filter((item) => !isEmpty(item.value)); const _sanitizeOperator = (operator) => ['eq', 'ne', 'gte', 'lte', 'like'].includes(operator) ? operator : 'eq'; const _mapFilterOperator = (operator) => { switch (operator) { case 'ne': case 'gte': case 'lte': return `[${operator}]`; case 'contains': return '[like]'; default: return 'eq'; } };