Univerzální zobrazení entit z OpenAPI v2
Framework pro automatické generování kompletního uživatelského rozhraní z OpenAPI specifikace. Backend popíše datový model a jeho vizuální metadata — frontend z nich bez jediného řádku konfigurace postaví tabulku i formuláře se sloupci, formátováním, řazením, filtrováním, vazbami a RBAC.
Jaký problém to řeší?
Proč jsme se rozhodli generovat UI automaticky ze schématu místo ručního psaní tabulek a formulářů.
Tradiční přístup
- Pro každou entitu (Produkt, Kategorie, Objednávka…) se ručně píší sloupce tabulky
- Každý renderer buňky (měna, datum, štítek) se konfiguruje individuálně
- Při změně modelu na backendu se musí ručně aktualizovat i frontend
- Vazby mezi entitami (produkt → kategorie) se řeší ad-hoc
- Desítky téměř identických stránek s drobně odlišnou konfigurací
Přístup s x-admin-* / x-eshop-*
- Backend popíše model jednou — v OpenAPI schématu s rozšířeními x-admin-* a x-eshop-*
- Frontend automaticky vygeneruje tabulku i formulář včetně rendererů
- Změna modelu na backendu se projeví okamžitě bez úprav frontendu
- Vazby se řeší deklarativně přes
x-admin-relation+ sideloading - JSON:API envelope s paginací, UUID identifikátory, OAuth 2.0 + RBAC
Co je OpenAPI a proč x-admin-* / x-eshop-*?
Základní pojmy, které je potřeba znát pro pochopení celého systému.
OpenAPI 3.1 specifikace
OpenAPI 3.1 je nejnovější verze standardu pro popis REST API, plně kompatibilní s JSON Schema. Supports type: ["number", "null"] místo nullable: true, UUID formát a další vylepšení.
Rozšíření x-admin-* a x-eshop-*
Standard OpenAPI umožňuje přidávat vlastní rozšíření s prefixem x-. V2 definuje dvě sady: x-admin-* pro administrační UI a x-eshop-* pro storefront.
x-admin-resource
Metadata entity — název, popis, ikona, operace, RBAC politiky
x-admin-datagrid
Konfigurace tabulky — sloupce, řazení, hromadné akce, filtry
x-admin-form
Konfigurace formuláře — layout, skupiny polí, widgety, závislosti
x-admin-enum
Barvy a popisky pro hodnoty výčtu — štítky, stavy
x-admin-relation
Vazba na jiný resource — sideloading přes ?include=
x-eshop-*
Storefront: display, facety, SEO, badges, prominence
Jak začít
Tři kroky k zobrazení libovolné entity — od schématu po vykreslenou tabulku.
Připravte OpenAPI 3.1 schéma s x-admin-* rozšířeními
{
"Product": {
"type": "object",
"x-admin-resource": {
"label": "Product", "labelPlural": "Products",
"displayField": "name", "icon": "ShoppingBag01"
},
"x-admin-datagrid": {
"columns": [
{ "field": "name", "sortable": true, "isRowHeader": true },
{ "field": "price", "renderer": "currency", "align": "right" }
]
},
"properties": { ... }
}
}Backend vrací JSON:API envelope
// GET /api/v2/products?include=categories&page=1&pageSize=10
{
"data": [{ "id": "a1b2c3d4-...", "name": "Notebook", ... }],
"meta": { "total": 26, "page": 1, "pageSize": 10, "pageCount": 3 },
"links": { "self": "/api/v2/products?page=1", "next": "...", ... },
"included": { "categories": [{ "id": "c0a80101-...", "name": "Electronics" }] }
}Použijte EntityTable a EntityForm
<EntityTable
schemaUrl="/api/v2/schema"
dataUrl="/api/v2/products"
schemaName="Product"
/>
<EntityForm
schemaUrl="/api/v2/schema"
schemaName="Product"
onSubmit={(data) => { /* save */ }}
/>Architektura systému v2
Jak funguje celý systém od OpenAPI specifikace až po vykreslenou tabulku — krok po kroku.
OpenAPI 3.1 specifikace
Backend publikuje specifikaci s x-admin-resource, x-admin-datagrid a x-admin-form. Datagrid sloupce jsou definovány na úrovni schématu, ne per-property. Vazby používají x-admin-relation s konvencí /api/v2/{resource}.
Schema Parser
parseSchemaProperties() normalizuje OAS 3.1 typy (type arrays → primary + nullable).parseAdminDatagrid() merguje datagrid columns s property daty.extractIncludes() generuje ?include= parametr pro sideloading.
Admin Renderers
createAdminCellRenderer() factory bere ParsedAdminColumn a vrací render funkci. Importuje base renderery (currency, badges, tags, relation) z sdílené vrstvy.
EntityTable + EntityForm → DataTable
EntityTable orchestruje schema parsing, data fetch s JSON:API envelope + sideloading, a předá vše DataTable. EntityForm generuje formuláře z x-admin-form s tabs/wizard layoutem.
Příklad transformací:
Datové typy a renderery
Přehled podporovaných datových typů a jejich automatické mapování na vizuální komponenty.
| Prop | Type | Default | Description |
|---|---|---|---|
string | Text | - | Prostý text. Výchozí zobrazení pro všechny řetězce. |
string + date | Date | - | Formátované datum v českém formátu (např. '15. led 2025'). |
string + date-time | DateTime | - | Datum a čas (např. '15. led 2025, 10:30'). |
string + uuid | UUID | - | UUID identifikátor — skrytý ve výchozím stavu. |
string + uri | Link | - | Klikatelný odkaz, který se otevře v novém panelu prohlížeče. |
string + email | Email link | - | Odkaz typu mailto: pro odeslání e-mailu. |
string + enum | Badge | - | Barevný štítek (Badge) s popisky z x-admin-enum. |
number + currency | Currency | - | Měnový formát (např. '2 499,00 CZK'). Vyžaduje renderer='currency' a currencyField. |
[number, null] | Nullable Number | - | OAS 3.1 nullable — type array obsahující 'null'. |
boolean | Ano / Ne | - | Zobrazí 'Ano' nebo 'Ne' s barevným rozlišením. |
array[string] | Tag list | - | Každá položka pole se zobrazí jako samostatný štítek (Badge). |
string + relation | Relation | - | Sideloading přes ?include= — UUID → display name. |
Referenční příručka rozšíření x-admin-* / x-eshop-*
Kompletní přehled všech rozšíření OpenAPI specifikace v2.
x-admin-resource — metadata entity
| Prop | Type | Default | Description |
|---|---|---|---|
label* | string | - | Název entity v jednotném čísle. |
labelPlural* | string | - | Název entity v množném čísle. |
displayField* | string | - | Hlavní zobrazovací pole (e.g. 'name'). |
icon | string | - | Identifikátor ikony. |
description | string | - | Popis entity. |
operations | Operation[] | - | Vlastní operace (duplicate, archive, ...). |
policies | { read?, write?, delete? } | - | RBAC scope requirements. |
x-admin-datagrid — konfigurace tabulky
| Prop | Type | Default | Description |
|---|---|---|---|
columns* | Column[] | - | Definice sloupců s field, label, sortable, renderer, ... |
defaultSort | { field, direction } | - | Výchozí řazení. |
batchActions | Action[] | - | Hromadné akce (delete, archive, ...). |
filters | Record<string, Filter> | - | Konfigurace filtrů. |
x-admin-form — konfigurace formuláře
| Prop | Type | Default | Description |
|---|---|---|---|
layout | 'single' | 'tabs' | 'wizard' | - | Rozložení formuláře. |
groups | Group[] | - | Skupiny polí s name, label, order, fields[]. |
fields | Record<string, Field> | - | Konfigurace polí — widget, placeholder, helpText, dependency. |
x-admin-relation — vazba na resource
| Prop | Type | Default | Description |
|---|---|---|---|
resource* | string | - | Název resource (e.g. 'categories'). Konvence: /api/v2/{resource}. |
displayField* | string | - | Pole na related entity, které se zobrazí. |
type | 'belongsTo' | 'hasMany' | 'manyToMany' | - | Typ vztahu. |
x-eshop-* — storefront rozšíření
| Prop | Type | Default | Description |
|---|---|---|---|
x-eshop-display | Property-level | - | prominence (hero/primary/secondary/hidden), badges[], visibility[] |
x-eshop-facets | Schema-level | - | Facetové filtry — type (term/range/boolean), widget, sort |
x-eshop-seo | Schema-level | - | SEO šablony — titlePattern, metaDescription, ogImage |
Vazby mezi entitami
V2 používá sideloading přes ?include= parametr místo N+1 fetchů.
Jak to funguje v v2
Pole categoryId má x-admin-relation s resource: "categories".
- Parser zavolá
extractIncludes()→["categories"] - Fetch:
GET /api/v2/products?include=categories - Response:
included.categoriesobsahuje sideloaded data - Renderer mapuje UUID → display name
Výhody sideloadingu
- Jeden HTTP request místo N+1 fetchů
- Konzistentní data v rámci response
- Optimalizace na backendu (eager loading)
- Client řídí, co potřebuje přes
?include=
Živá ukázka
EntityTable a EntityForm generované z OpenAPI v2 specifikace s JSON:API responses a UUID identifikátory.
Product — tabulka (16 vlastností, UUID, vazba na Category)
Loading schema...
Category — jednoduchá entita (4 vlastnosti)
Loading schema...
Backend a API endpointy v2
JSON:API formát, UUID identifikátory, bracket filtrování, sideloading.
REST endpointy
/api/v2/schemaOpenAPI 3.1 specifikace se všemi x-admin-* a x-eshop-* rozšířeními/api/v2/{resource}JSON:API list s paginací, sort, filter, include/api/v2/{resource}/{id}Detail jednoho záznamu (UUID)/api/v2/{resource}Vytvoření nového záznamu/api/v2/{resource}/{id}Úprava záznamu/api/v2/{resource}/{id}Smazání záznamuQuery parametry
| Prop | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Číslo stránky. |
pageSize | integer | 10 | Počet záznamů na stránku. |
sort | string | - | Řazení: 'name' (asc), '-price' (desc). |
include | string | - | Sideloading: 'categories' nebo 'categories,tags'. |
filter[field][op] | string | - | Filtr: filter[status][eq]=active, filter[price][gte]=100. |
Surové OpenAPI 3.1 schéma
Kompletní specifikace včetně všech x-admin-* a x-eshop-* rozšíření.
Stav implementace v2
Přehled hotových funkcí v2 frameworku.
Core v2
Komponenty
Plánovaná rozšíření
Zdrojové soubory
Přehled všech souborů frameworku v2.
| Prop | Type | Default | Description |
|---|---|---|---|
lib/openapi/types.ts | Typy | - | OAS 3.1 typy, x-admin-*, x-eshop-* interfaces, ParsedProperty, API response typy. |
lib/openapi/parser.ts | Parser | - | Sdílený základ: humanizeFieldName, normalizeType, parseSchemaProperties. |
lib/openapi/schema.ts | Schéma | - | OpenAPI 3.1 spec s Product a Category, x-admin-*, x-eshop-*. |
lib/openapi/cell-renderers.tsx | Renderery | - | Base renderery: date, currency, badge, tag, relation, image, boolean. |
lib/openapi/admin/parser.ts | Admin parser | - | parseAdminResource, parseAdminDatagrid, toDataTableColumns, parseAdminForm. |
lib/openapi/admin/renderers.tsx | Admin renderers | - | createAdminCellRenderer factory s ParsedAdminColumn vstupem. |
lib/openapi/storefront/parser.ts | Storefront parser | - | parseEshopFacets, filterByVisibility, sortByProminence, resolveSeoTemplate. |
lib/openapi/storefront/renderers.tsx | Storefront renderers | - | renderProductPrice, evaluateBadges. |
lib/auth/types.ts | Auth typy | - | AuthUser, TokenPair, AuthSession, AuthAction. |
lib/auth/auth-context.tsx | Auth context | - | AuthProvider, useAuth hook, mock dev user. |
lib/auth/rbac.ts | RBAC | - | hasAccess, hasScope, canRead, canWrite, canDelete. |
lib/api/client.ts | API klient | - | createApiClient s Bearer + tenant headery, CRUD metody. |
lib/api/types.ts | API typy | - | QueryParams, buildQueryString. |
lib/mock-data/products.ts | Data | - | 5 kategorií + 26 produktů s UUID a null. |
components/.../entity-table.tsx | Komponenta | - | EntityTable — v2 API, sideloading, admin datagrid. |
components/.../entity-form.tsx | Komponenta | - | EntityForm — schema-driven formuláře s react-hook-form. |
app/api/v2/schema/route.ts | API route | - | GET /api/v2/schema. |
app/api/v2/[resource]/route.ts | API route | - | GET + POST /api/v2/{resource} s JSON:API envelope. |
app/api/v2/[resource]/[id]/route.ts | API route | - | GET + PUT + DELETE /api/v2/{resource}/{id}. |