feat(web): upgrade lists to ReUI Table v9 and EventCalendar
quality / commitlint (push) Skipped
quality / changes (push) Successful in 9s
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 39s
quality / web (push) Successful in 1m29s
quality / go (push) Successful in 1m3s
quality / bird2 (push) Successful in 15s
CD / quality (push) Successful in 3m43s
CD / publish (push) Failing after 8m29s

Единый kitDataGridTableLayout и ResourcePage/FrameDataGrid на всех списках.
Календарь задач переведён на EventCalendar, lookup — на cascader, у операций появился вид доски.
Удалены settings-7 и самописные DataGridSection/toolbar.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
DenozordecandCursor committed 2026-08-23 01:38:56 +07:00
1 parent 927e27640a
commit d56405af7b
157 files changed
+39067 -6110

No files matched your search

-60
View File
@@ -1,25 +1,3 @@
import {
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
type FilterFn,
type TableOptions,
} from '@tanstack/react-table'
import type { DataGridProps } from '@/components/reui/data-grid/data-grid'
export const DATA_GRID_TABLE_LAYOUT: NonNullable<DataGridProps<object>['tableLayout']> = {
dense: false,
headerSticky: true,
rowBorder: true,
}
/** REUI c-data-grid-19 edge cell padding. */
export const DATA_GRID_TABLE_CLASS_NAMES: NonNullable<DataGridProps<object>['tableClassNames']> = {
edgeCell: 'px-5',
}
export const DATA_GRID_PAGINATION_RU = {
sizes: [10, 25, 50] as number[],
sizesLabel: 'Показать',
@@ -40,41 +18,3 @@ export const DATA_GRID_MESSAGES_RU = {
unpinRowLabel: 'Открепить строку',
allRecordsLoadedMessage: 'Все записи загружены',
}
export const DATA_GRID_DENSE_LAYOUT: NonNullable<DataGridProps<object>['tableLayout']> = {
...DATA_GRID_TABLE_LAYOUT,
dense: true,
width: 'auto',
}
export function createTextGlobalFilter<TData extends object>(
getSearchText: (row: TData) => string,
): FilterFn<TData> {
return (row, _columnId, filterValue) => {
const query = String(filterValue ?? '')
.toLowerCase()
.trim()
if (!query) return true
return getSearchText(row.original).toLowerCase().includes(query)
}
}
export function createClientDataGridOptions<TData extends object>(
overrides?: Partial<TableOptions<TData>>,
): Pick<
TableOptions<TData>,
| 'getCoreRowModel'
| 'getFilteredRowModel'
| 'getSortedRowModel'
| 'getPaginationRowModel'
| 'initialState'
> {
return {
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
initialState: { pagination: { pageSize: 10 } },
...overrides,
}
}
+76 -85
View File
@@ -1,94 +1,85 @@
import {
DEFAULT_I18N,
type FilterI18nConfig,
} from '@/components/reui/filters'
DEFAULT_FILTER_OPERATOR_LABELS,
type FilterOperatorLabels,
} from '@/components/reui/filters/filters-operators'
import type { FilterLabels } from '@/components/reui/filters/filters-types'
const OPERATOR_LABEL_RU: Record<string, string> = {
is: 'равно',
is_not: 'не равно',
is_any_of: 'любое из',
is_not_any_of: 'кроме',
includes_all: 'включает все',
excludes_all: 'исключает все',
before: 'до',
after: 'после',
between: 'между',
not_between: 'вне диапазона',
export const FILTERS_LABELS_RU: Partial<FilterLabels> = {
addFilter: 'Фильтр',
advancedFilter: 'Расширенный фильтр',
showRecords: 'В этом виде показывать записи',
builderEmpty: 'Фильтров пока нет',
builderEmptyHint: 'Добавьте фильтр, чтобы сузить выборку.',
addCondition: 'Добавить фильтр',
addConditionGroup: 'Добавить группу',
addToGroup: 'Добавить фильтр в эту группу',
removeGroup: 'Удалить группу',
wrapInGroup: 'Обернуть в группу',
ungroup: 'Разгруппировать',
moveToTopLevel: 'На верхний уровень',
moveToGroup: (position) => `Переместить в группу ${position}`,
reorder: 'Порядок',
reorderHint: 'Alt + стрелки вверх/вниз меняют порядок',
groupAll: 'Все следующие условия истинны…',
groupAny: 'Любое из следующих условий истинно…',
groupPlaceholder: 'Перетащите фильтры сюда',
clearAll: 'Сбросить все',
groupMenu: 'Параметры группы',
searchFields: 'Поиск полей…',
searchOperators: 'Поиск операторов…',
searchOptions: 'Поиск…',
back: 'Назад',
clear: 'Очистить',
apply: 'Применить',
discard: 'Отменить изменения',
empty: 'Нет результатов',
loading: 'Загрузка…',
loadingMore: 'Загрузка…',
loadMore: 'Ещё',
error: 'Не удалось загрузить',
retry: 'Повторить',
where: 'Где',
and: 'И',
or: 'Или',
combinator: 'Изменить связку',
duplicate: 'Дублировать',
negate: 'Инвертировать',
convertToAdvanced: 'Расширенный редактор',
remove: 'Удалить',
filtersLabel: 'Фильтры',
readOnly: 'Только чтение. Эти фильтры нельзя изменить.',
valuePlaceholder: 'введите текст…',
selectPlaceholder: 'Выбрать…',
noValue: 'нет значения',
selectCondition: 'Выберите условие',
incomplete: 'незавершённый фильтр',
}
export const FILTERS_OPERATOR_LABELS_RU: FilterOperatorLabels = {
...DEFAULT_FILTER_OPERATOR_LABELS,
contains: 'содержит',
not_contains: 'не содержит',
starts_with: 'начинается с',
ends_with: 'заканчивается на',
equals: 'равно',
not_equals: 'не равно',
greater_than: 'больше',
less_than: 'меньше',
overlaps: 'пересекается',
includes: 'включает',
excludes: 'исключает',
is: 'равно',
is_not: 'не равно',
is_any_of: 'любое из',
is_none_of: 'кроме',
has_any_of: 'есть любое из',
has_all_of: 'есть все',
has_none_of: 'нет ни одного',
eq: 'равно',
neq: 'не равно',
gt: 'больше',
gte: 'больше или равно',
lt: 'меньше',
lte: 'меньше или равно',
between: 'между',
not_between: 'вне диапазона',
is_before: 'до',
is_after: 'после',
is_on_or_before: 'не позже',
is_on_or_after: 'не раньше',
empty: 'пусто',
not_empty: 'не пусто',
}
export const FILTERS_I18N_RU: FilterI18nConfig = {
...DEFAULT_I18N,
addFilter: 'Фильтр',
searchFields: 'Фильтр…',
noFieldsFound: 'Поля не найдены.',
noResultsFound: 'Ничего не найдено.',
select: 'Выбрать…',
true: 'Да',
false: 'Нет',
min: 'Мин.',
max: 'Макс.',
to: '—',
typeAndPressEnter: 'Введите и нажмите Enter',
selected: 'выбрано',
selectedCount: 'выбрано',
addFilterTitle: 'Добавить фильтр',
operators: {
...DEFAULT_I18N.operators,
is: 'равно',
isNot: 'не равно',
isAnyOf: 'любое из',
isNotAnyOf: 'кроме',
includesAll: 'включает все',
excludesAll: 'исключает все',
before: 'до',
after: 'после',
between: 'между',
notBetween: 'вне диапазона',
contains: 'содержит',
notContains: 'не содержит',
startsWith: 'начинается с',
endsWith: 'заканчивается на',
isExactly: 'точно',
equals: 'равно',
notEquals: 'не равно',
greaterThan: 'больше',
lessThan: 'меньше',
overlaps: 'пересекается',
includes: 'включает',
excludes: 'исключает',
includesAllOf: 'включает все',
includesAnyOf: 'включает любое',
empty: 'пусто',
notEmpty: 'не пусто',
},
placeholders: {
enterField: (fieldType: string) => `Введите ${fieldType}…`,
selectField: 'Выбрать…',
searchField: (fieldName: string) => `Поиск ${fieldName.toLowerCase()}…`,
enterKey: 'Введите ключ…',
enterValue: 'Введите значение…',
},
helpers: {
formatOperator: (operator: string) =>
OPERATOR_LABEL_RU[operator] ?? operator.replace(/_/g, ' '),
},
validation: {
invalidEmail: 'Некорректный email',
invalidUrl: 'Некорректный URL',
invalidTel: 'Некорректный телефон',
invalid: 'Некорректное значение',
},
}
+1 -1
View File
@@ -3,7 +3,7 @@
*
* Ops / list / dashboard / detail / settings: **Frame** only.
* KPI tiles: **stats-12** via `KpiStatGrid` / `reui-kit/KpiStatGrid`.
* Lists: Frame + DataGrid (`ResourcePage` / `DataGridSection`), not Card shell.
* Lists: Frame + DataGrid (`ResourcePage` / `FrameDataGrid`), not Card shell.
*
* @see https://reui.io/preview/base/stats-12
* @see https://reui.io/preview/base/dashboard-1