Custom-зоны · 0.8.1

Admin: свои ячейки, формы и страницы

Выберите точечное расширение или полную замену стандартной страницы.

На этой странице

Интерфейс можно расширить точечно или заменить страницу целиком. В первом случае генератор продолжает строить стандартный список и форму, а custom-код добавляет нужные элементы. Во втором ваша команда поддерживает страницу и её поведение.

ENTITY_NAME в пути — каталог сущности, например product. EntityName в имени экспорта — её PascalCase-имя, например Product. Откройте уже созданные файлы своей сущности и используйте их реальные имена.

Файлы расширений

Файл Что менять
admin/src/features/ENTITY_NAME/custom/ui-extension.tsx Ячейки, дополнительные колонки, действия и элементы стандартной формы
admin/src/features/ENTITY_NAME/custom/extension.tsx Заголовки, действия, преобразование данных и полные PageOverride
admin/src/features/ENTITY_NAME/generated/ui-extension.tsx Контракт расширений для чтения; файл обновляет генератор
admin/custom/vite.ts Поддерживаемые дополнительные настройки Vite

Изменить список

В useEntityNameListUI(context) доступны текущие записи, состояние загрузки, ошибка и сгенерированные колонки. Верните только нужные дополнения:

Свойство Назначение
columns Новые колонки с уникальными идентификаторами
cells Своё отображение существующих ячеек по имени поля
rowActions Действия со строкой: ID, подпись, проверка isAllowed, обработчик и при необходимости disabled
status Дополнительное состояние списка

Новая custom-колонка не получает SQL-фильтрацию и сортировку автоматически. Не используйте имена существующих колонок и служебные __actions, __customActions, __related. Если нужны данные из другого API, запрашивайте их ограниченной партией для ID текущей страницы и обрабатывайте загрузку, ошибку и смену страницы.

Изменить поле формы

useEntityNameFormUI() возвращает расширения формы. textFields подходит для поддерживаемых обычных видимых редактируемых string/text; imageFields — для изображений, когда они есть в модели; wrappers — для обёрток отдельных полей.

Собственный текстовый контрол получает inputProps. Сохраните их, включая name, required, disabled и значение: стандартная форма собирает FormData. Обёртка должна вывести defaultControl ровно один раз. Для сложного состояния используйте предусмотренный onDirtyChange, чтобы предупреждение о несохранённых изменениях оставалось корректным.

У локализованного поля name обозначает поле модели, а inputName/inputProps.name — реальное имя HTML-ввода для выбранного языка. Не собирайте его из подписи вроде name-ru. Учитывайте readonly/disabled и серверные права, даже если в демо можно печатать в поле без возможности сохранить.

Полностью заменить страницу

В custom/extension.tsx найдите существующий экспорт EntityNameListPageOverride или EntityNameEditPageOverride. Вместо null укажите свой React-компонент:

function MyListPage() {
  return <section>Содержимое вашей страницы</section>
}

export const EntityNameListPageOverride: ComponentType | null = MyListPage

Замените существующее объявление, не добавляйте второе. Сгенерированный маршрут выберет override вместо стандартной страницы — обычная таблица снизу не добавляется автоматически. Не вставляйте её в свой компонент, если она не нужна. У virtual-страниц предусмотрены EntityNameListPageOverride и EntityNameDetailsPageOverride.

В полной замене вы реализуете запросы, сохранение, состояние ожидания, ошибки, пагинацию и доступность. Для одной изменённой ячейки используйте cells, а не полный override. Custom-интерфейс не обходит серверные права.

После изменения соберите admin через npm run build из admin/ и проверьте свой экран с подходящими правами пользователя. Контракты и порядок генерации описаны в рабочем цикле.