fix: числовая сортировка date/datetime/number полей в реестре задач
Сортировка кастомных полей шла лексикографически по отображаемой строке: даты «ДД.ММ.ГГГГ» сортировались по дню («01.12.2025» < «02.01.2024»), числа как строки («10» < «9»). Теперь для field_<id> типов date/datetime/number сравнение идёт по сырому значению (timestamp/число), пустые — всегда в конец.
This commit is contained in:
@@ -267,6 +267,30 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
|
||||
|
||||
const DATE_COLS = new Set(['createdAt', 'updatedAt', 'dueDate', 'completedAt']);
|
||||
|
||||
// Числовые и датовые кастомные поля сортируем по сырому значению,
|
||||
// а не по отображаемой строке (иначе «01.12.2025» < «02.01.2024» и «10» < «9»)
|
||||
type TaskWithFV = Task & { fieldValues?: Record<number, unknown> };
|
||||
let numericFieldId: number | null = null;
|
||||
let numericFieldIsDate = false;
|
||||
if (sortColumn.startsWith('field_')) {
|
||||
const fieldId = parseInt(sortColumn.replace('field_', ''));
|
||||
const field = formFields.find((f) => f.id === fieldId);
|
||||
if (field && ['date', 'datetime', 'number'].includes(field.type)) {
|
||||
numericFieldId = fieldId;
|
||||
numericFieldIsDate = field.type === 'date' || field.type === 'datetime';
|
||||
}
|
||||
}
|
||||
const toSortNumber = (t: TaskWithFV): number | null => {
|
||||
const v = t.fieldValues?.[numericFieldId!];
|
||||
if (v === undefined || v === null || v === '') return null;
|
||||
if (numericFieldIsDate) {
|
||||
const ts = new Date(String(v)).getTime();
|
||||
return isNaN(ts) ? null : ts;
|
||||
}
|
||||
const n = Number(String(v).replace(/\s/g, ''));
|
||||
return isNaN(n) ? null : n;
|
||||
};
|
||||
|
||||
tasks = [...tasks].sort((a, b) => {
|
||||
if (DATE_COLS.has(sortColumn)) {
|
||||
const _a = (a as Record<string, unknown>)[sortColumn];
|
||||
@@ -275,6 +299,15 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
|
||||
const bv = _b ? new Date(String(_b)).getTime() : 0;
|
||||
return sortDir === 'asc' ? av - bv : bv - av;
|
||||
}
|
||||
if (numericFieldId !== null) {
|
||||
const av = toSortNumber(a as TaskWithFV);
|
||||
const bv = toSortNumber(b as TaskWithFV);
|
||||
// Пустые значения всегда в конец независимо от направления
|
||||
if (av === null && bv === null) return 0;
|
||||
if (av === null) return 1;
|
||||
if (bv === null) return -1;
|
||||
return sortDir === 'asc' ? av - bv : bv - av;
|
||||
}
|
||||
const av = getTaskColumnValue(a, sortColumn, statusMap, userMap, formFields, roleMap, undefined, legalEntityMap, taskTitleMap).toLowerCase();
|
||||
const bv = getTaskColumnValue(b, sortColumn, statusMap, userMap, formFields, roleMap, undefined, legalEntityMap, taskTitleMap).toLowerCase();
|
||||
const cmp = av.localeCompare(bv, 'ru');
|
||||
|
||||
Reference in New Issue
Block a user