@oondemand/create-central-oon 0.3.9 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -40,6 +40,12 @@ Aliases: o binário também responde por `scaffold-central-oon`.
|
|
|
40
40
|
|
|
41
41
|
O pacote inclui documentação canônica em `docs/`. Ela é publicada no npm junto com o gerador.
|
|
42
42
|
|
|
43
|
+
A referência completa das opções do manifesto front fica em:
|
|
44
|
+
|
|
45
|
+
```txt
|
|
46
|
+
packages/create-central-oon/docs/FRONTEND_MANIFEST_REFERENCE.md
|
|
47
|
+
```
|
|
48
|
+
|
|
43
49
|
Ao criar uma Central, o CLI gera uma pasta `.ooncore/` com um cache local da documentação da versão instalada:
|
|
44
50
|
|
|
45
51
|
```txt
|
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
# Referência do Manifesto Frontend OonCore
|
|
2
|
+
|
|
3
|
+
Este documento é a referência operacional para o Codex criar ou alterar manifestos do frontend OonCore.
|
|
4
|
+
|
|
5
|
+
Use este arquivo junto com `FRONTEND_PATTERNS.md`. O arquivo de padrões explica como pensar a UI; este arquivo lista as opções do contrato atual.
|
|
6
|
+
|
|
7
|
+
## Arquivos envolvidos
|
|
8
|
+
|
|
9
|
+
```txt
|
|
10
|
+
frontend/central.ui.json # manifesto declarativo da Central
|
|
11
|
+
frontend/src/main.tsx # bootstrap do frontend
|
|
12
|
+
packages/oonCore-front/src/manifest.ts # conversão central.ui.json -> OonCoreFrontConfig
|
|
13
|
+
packages/oonCore-front/src/types.ts # tipos oficiais do contrato
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Regra principal
|
|
17
|
+
|
|
18
|
+
O manifesto JSON não deve carregar componentes React. Ele só pode declarar dados e chaves de renderer, como:
|
|
19
|
+
|
|
20
|
+
```txt
|
|
21
|
+
custom:MeusAppsHeader
|
|
22
|
+
fields.password
|
|
23
|
+
cells.statusBadge
|
|
24
|
+
cards.appLauncher
|
|
25
|
+
actions.ativarApp
|
|
26
|
+
menus.portal
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Os componentes reais devem ser registrados em código TypeScript/React pelo `registry`.
|
|
30
|
+
|
|
31
|
+
## Níveis de contrato
|
|
32
|
+
|
|
33
|
+
Existem três níveis importantes:
|
|
34
|
+
|
|
35
|
+
1. `central.ui.json`: entrada declarativa usada pelas Centrais geradas.
|
|
36
|
+
2. `CentralUiManifest`: contrato lido por `startFromManifest`.
|
|
37
|
+
3. `OonUiManifest` / `OonCoreFrontConfig`: contrato interno mais completo do Core Front.
|
|
38
|
+
|
|
39
|
+
Para Codex, a ordem recomendada é:
|
|
40
|
+
|
|
41
|
+
1. Começar pelo `central.ui.json`.
|
|
42
|
+
2. Usar `pages` e `blocks` quando precisar de UI v2.
|
|
43
|
+
3. Usar registry/overrides em TypeScript quando precisar de componentes customizados.
|
|
44
|
+
4. Evitar recriar shell, rotas, menu, grid, cards ou formulários manualmente.
|
|
45
|
+
|
|
46
|
+
## CentralUiManifest
|
|
47
|
+
|
|
48
|
+
Contrato aceito por `startFromManifest(manifest, runtime)`.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
interface CentralUiManifest {
|
|
52
|
+
name: string;
|
|
53
|
+
slug: string;
|
|
54
|
+
backend?: { metadataUrl?: string };
|
|
55
|
+
schemaVersion?: 1 | 2;
|
|
56
|
+
layout?: OonLayoutConfig;
|
|
57
|
+
registry?: OonComponentRegistry;
|
|
58
|
+
navigation?: OonNavigationConfig;
|
|
59
|
+
pages?: OonPageDef[];
|
|
60
|
+
collections?: Array<{
|
|
61
|
+
model: string;
|
|
62
|
+
mode?: CollectionMode;
|
|
63
|
+
path?: string;
|
|
64
|
+
label?: string;
|
|
65
|
+
section?: string;
|
|
66
|
+
}>;
|
|
67
|
+
pipelines?: Array<{
|
|
68
|
+
name?: string;
|
|
69
|
+
model?: string;
|
|
70
|
+
mode?: string;
|
|
71
|
+
stageField?: string;
|
|
72
|
+
path?: string;
|
|
73
|
+
label?: string;
|
|
74
|
+
section?: string;
|
|
75
|
+
}>;
|
|
76
|
+
documents?: Array<{
|
|
77
|
+
model: string;
|
|
78
|
+
mode?: string;
|
|
79
|
+
path?: string;
|
|
80
|
+
label?: string;
|
|
81
|
+
section?: string;
|
|
82
|
+
approval?: boolean;
|
|
83
|
+
attachments?: boolean;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Opções de raiz
|
|
89
|
+
|
|
90
|
+
| Campo | Tipo | Uso |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| `name` | `string` | Nome exibido da Central. |
|
|
93
|
+
| `slug` | `string` | Identificador da Central/app. |
|
|
94
|
+
| `backend.metadataUrl` | `string` | URL explícita de metadata, quando aplicável. |
|
|
95
|
+
| `schemaVersion` | `1 \| 2` | Sem valor = compatibilidade v1. Use `2` para UI v2. |
|
|
96
|
+
| `layout` | `OonLayoutConfig` | Shell, sidebar, topbar, header, footer e slots. |
|
|
97
|
+
| `navigation` | `OonNavigationConfig` | Modo do menu e itens manuais. |
|
|
98
|
+
| `pages` | `OonPageDef[]` | Páginas por blocos da UI v2. |
|
|
99
|
+
| `collections` | `Array` | Atalho para gerar views de coleção. |
|
|
100
|
+
| `pipelines` | `Array` | Atalho para gerar esteiras. |
|
|
101
|
+
| `documents` | `Array` | Atalho para gerar documentos. |
|
|
102
|
+
|
|
103
|
+
## Layout
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
type OonSlotConfig = "core" | "none" | `custom:${string}`;
|
|
107
|
+
|
|
108
|
+
interface OonLayoutConfig {
|
|
109
|
+
shell?: "default" | "portal" | "content-only" | `custom:${string}`;
|
|
110
|
+
sidebar?: OonSlotConfig;
|
|
111
|
+
topbar?: OonSlotConfig;
|
|
112
|
+
header?: "none" | `custom:${string}`;
|
|
113
|
+
footer?: "core" | "none" | `custom:${string}`;
|
|
114
|
+
assistant?: "core" | "none" | `custom:${string}`;
|
|
115
|
+
main?: "core";
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Valores de `layout.shell`
|
|
120
|
+
|
|
121
|
+
| Valor | Comportamento |
|
|
122
|
+
| --- | --- |
|
|
123
|
+
| `default` | Shell operacional padrão com sidebar/topbar. |
|
|
124
|
+
| `portal` | Shell para portal, útil para Meus Apps ou home de cards. |
|
|
125
|
+
| `content-only` | Experiência focada em conteúdo. |
|
|
126
|
+
| `custom:<key>` | Shell registrado em `registry.layoutSlots`. |
|
|
127
|
+
|
|
128
|
+
### Slots
|
|
129
|
+
|
|
130
|
+
| Campo | Valores | Uso |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| `sidebar` | `core`, `none`, `custom:<key>` | Menu lateral. |
|
|
133
|
+
| `topbar` | `core`, `none`, `custom:<key>` | Barra superior. |
|
|
134
|
+
| `header` | `none`, `custom:<key>` | Header custom acima da página. |
|
|
135
|
+
| `footer` | `core`, `none`, `custom:<key>` | Rodapé. |
|
|
136
|
+
| `assistant` | `core`, `none`, `custom:<key>` | Assistente/copiloto, quando suportado. |
|
|
137
|
+
| `main` | `core` | Área principal do Core. |
|
|
138
|
+
|
|
139
|
+
### Exemplo
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"schemaVersion": 2,
|
|
144
|
+
"name": "Meus Apps",
|
|
145
|
+
"slug": "meus-apps",
|
|
146
|
+
"layout": {
|
|
147
|
+
"shell": "portal",
|
|
148
|
+
"sidebar": "none",
|
|
149
|
+
"topbar": "none",
|
|
150
|
+
"header": "custom:MeusAppsHeader",
|
|
151
|
+
"footer": "core"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Navigation
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
type OonNavigationMode = "auto" | "manual" | "mixed";
|
|
160
|
+
|
|
161
|
+
interface OonNavigationConfig {
|
|
162
|
+
mode?: OonNavigationMode;
|
|
163
|
+
items?: OonMenuItem[];
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Modos
|
|
168
|
+
|
|
169
|
+
| Valor | Comportamento |
|
|
170
|
+
| --- | --- |
|
|
171
|
+
| `auto` | Core gera menu a partir de coleções, documentos, esteiras, dashboards e páginas. |
|
|
172
|
+
| `manual` | Usa apenas `navigation.items`. |
|
|
173
|
+
| `mixed` | Combina menu automático com itens manuais. |
|
|
174
|
+
|
|
175
|
+
## Menu item
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
interface OonMenuItem {
|
|
179
|
+
label: string;
|
|
180
|
+
href: string;
|
|
181
|
+
icon?: ReactNode;
|
|
182
|
+
section?: string;
|
|
183
|
+
order?: number;
|
|
184
|
+
permissions?: string[];
|
|
185
|
+
children?: OonMenuItem[];
|
|
186
|
+
badge?: string | number;
|
|
187
|
+
external?: boolean;
|
|
188
|
+
hidden?: boolean;
|
|
189
|
+
action?: string;
|
|
190
|
+
renderer?: string;
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Opções de menu
|
|
195
|
+
|
|
196
|
+
| Campo | Uso |
|
|
197
|
+
| --- | --- |
|
|
198
|
+
| `label` | Texto do menu. |
|
|
199
|
+
| `href` | Rota interna ou URL. |
|
|
200
|
+
| `section` | Agrupamento visual. |
|
|
201
|
+
| `order` | Ordenação. |
|
|
202
|
+
| `permissions` | Permissões exigidas. |
|
|
203
|
+
| `children` | Subitens. |
|
|
204
|
+
| `badge` | Indicador simples. |
|
|
205
|
+
| `external` | Link externo. |
|
|
206
|
+
| `hidden` | Oculta item sem remover do manifesto. |
|
|
207
|
+
| `action` | Chave de ação. |
|
|
208
|
+
| `renderer` | Renderer customizado em `registry.menuRenderers`. |
|
|
209
|
+
|
|
210
|
+
## Collections no central.ui.json
|
|
211
|
+
|
|
212
|
+
Atalho simples para coleções.
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"collections": [
|
|
217
|
+
{
|
|
218
|
+
"model": "Cliente",
|
|
219
|
+
"mode": "dynamic",
|
|
220
|
+
"path": "/clientes",
|
|
221
|
+
"label": "Clientes",
|
|
222
|
+
"section": "Cadastros"
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Campos aceitos no atalho `collections[]`
|
|
229
|
+
|
|
230
|
+
| Campo | Tipo | Uso |
|
|
231
|
+
| --- | --- | --- |
|
|
232
|
+
| `model` | `string` | Model do backend. |
|
|
233
|
+
| `mode` | `full`, `minimal`, `dynamic` | Modo de renderização. |
|
|
234
|
+
| `path` | `string` | Rota. |
|
|
235
|
+
| `label` | `string` | Nome no menu/tela. |
|
|
236
|
+
| `section` | `string` | Grupo do menu. |
|
|
237
|
+
|
|
238
|
+
## CollectionViewDef completo
|
|
239
|
+
|
|
240
|
+
Contrato interno completo quando a coleção já está em `ui.views` ou em blocos.
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
interface CollectionViewDef {
|
|
244
|
+
type: "collection";
|
|
245
|
+
id?: string;
|
|
246
|
+
model: string;
|
|
247
|
+
label?: string;
|
|
248
|
+
path?: string;
|
|
249
|
+
icon?: ReactNode;
|
|
250
|
+
section?: string;
|
|
251
|
+
mode?: "full" | "minimal" | "dynamic";
|
|
252
|
+
columns?: OonColumnDef[];
|
|
253
|
+
form?: OonFormFieldDef[];
|
|
254
|
+
importExport?: boolean;
|
|
255
|
+
renderer?: string;
|
|
256
|
+
cardRenderer?: string;
|
|
257
|
+
actions?: OonActionDef[];
|
|
258
|
+
permissions?: string[];
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Column
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
interface OonColumnDef {
|
|
266
|
+
field: string;
|
|
267
|
+
label?: string;
|
|
268
|
+
kind?: FieldKind;
|
|
269
|
+
sortable?: boolean;
|
|
270
|
+
width?: number;
|
|
271
|
+
renderer?: string;
|
|
272
|
+
permissions?: string[];
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Form field
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
interface OonFormFieldDef {
|
|
280
|
+
field: string;
|
|
281
|
+
label?: string;
|
|
282
|
+
kind?: FieldKind;
|
|
283
|
+
required?: boolean;
|
|
284
|
+
options?: string[];
|
|
285
|
+
ref?: string;
|
|
286
|
+
renderer?: string;
|
|
287
|
+
permissions?: string[];
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Action
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
interface OonActionDef {
|
|
295
|
+
id: string;
|
|
296
|
+
label?: string;
|
|
297
|
+
renderer?: string;
|
|
298
|
+
permissions?: string[];
|
|
299
|
+
action?: string;
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Documents
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{
|
|
307
|
+
"documents": [
|
|
308
|
+
{
|
|
309
|
+
"model": "DocumentoFiscal",
|
|
310
|
+
"path": "/documentos-fiscais",
|
|
311
|
+
"label": "Documentos Fiscais",
|
|
312
|
+
"section": "Fiscal",
|
|
313
|
+
"approval": true,
|
|
314
|
+
"attachments": true
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Opções
|
|
321
|
+
|
|
322
|
+
| Campo | Uso |
|
|
323
|
+
| --- | --- |
|
|
324
|
+
| `model` | Model do documento. |
|
|
325
|
+
| `mode` | Modo futuro/reservado. |
|
|
326
|
+
| `path` | Rota. |
|
|
327
|
+
| `label` | Nome exibido. |
|
|
328
|
+
| `section` | Grupo do menu. |
|
|
329
|
+
| `approval` | Habilita comportamento de aprovação. |
|
|
330
|
+
| `attachments` | Habilita anexos. |
|
|
331
|
+
|
|
332
|
+
## Pipelines
|
|
333
|
+
|
|
334
|
+
```json
|
|
335
|
+
{
|
|
336
|
+
"pipelines": [
|
|
337
|
+
{
|
|
338
|
+
"model": "Pedido",
|
|
339
|
+
"stageField": "status",
|
|
340
|
+
"path": "/pedidos/esteira",
|
|
341
|
+
"label": "Esteira de Pedidos",
|
|
342
|
+
"section": "Operação"
|
|
343
|
+
}
|
|
344
|
+
]
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Opções
|
|
349
|
+
|
|
350
|
+
| Campo | Uso |
|
|
351
|
+
| --- | --- |
|
|
352
|
+
| `name` | Nome alternativo usado como model quando `model` não for informado. |
|
|
353
|
+
| `model` | Model dos cards/tickets. |
|
|
354
|
+
| `mode` | Modo futuro/reservado. |
|
|
355
|
+
| `stageField` | Campo que define a coluna/etapa. |
|
|
356
|
+
| `path` | Rota. |
|
|
357
|
+
| `label` | Nome exibido. |
|
|
358
|
+
| `section` | Grupo do menu. |
|
|
359
|
+
|
|
360
|
+
## PipelineViewDef completo
|
|
361
|
+
|
|
362
|
+
```ts
|
|
363
|
+
interface PipelineViewDef {
|
|
364
|
+
type: "pipeline";
|
|
365
|
+
id?: string;
|
|
366
|
+
model: string;
|
|
367
|
+
label?: string;
|
|
368
|
+
path?: string;
|
|
369
|
+
icon?: ReactNode;
|
|
370
|
+
section?: string;
|
|
371
|
+
stageField?: string;
|
|
372
|
+
stages?: Array<{ id: string; label: string }>;
|
|
373
|
+
permissions?: string[];
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## DocumentViewDef completo
|
|
378
|
+
|
|
379
|
+
```ts
|
|
380
|
+
interface DocumentViewDef {
|
|
381
|
+
type: "document";
|
|
382
|
+
id?: string;
|
|
383
|
+
model: string;
|
|
384
|
+
label?: string;
|
|
385
|
+
path?: string;
|
|
386
|
+
icon?: ReactNode;
|
|
387
|
+
section?: string;
|
|
388
|
+
approval?: boolean;
|
|
389
|
+
attachments?: boolean;
|
|
390
|
+
permissions?: string[];
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## DashboardViewDef
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
interface DashboardViewDef {
|
|
398
|
+
type: "dashboard";
|
|
399
|
+
id?: string;
|
|
400
|
+
label?: string;
|
|
401
|
+
path?: string;
|
|
402
|
+
icon?: ReactNode;
|
|
403
|
+
section?: string;
|
|
404
|
+
widgets?: DashboardWidgetDef[];
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
interface DashboardWidgetDef {
|
|
408
|
+
id: string;
|
|
409
|
+
label: string;
|
|
410
|
+
model?: string;
|
|
411
|
+
kind?: "count" | "sum" | "custom";
|
|
412
|
+
field?: string;
|
|
413
|
+
render?: () => ReactNode;
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Observação: `render` é função React e não deve estar em JSON. Use somente em configuração TypeScript.
|
|
418
|
+
|
|
419
|
+
## Pages UI v2
|
|
420
|
+
|
|
421
|
+
Páginas permitem compor rotas por blocos.
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
interface OonPageDef {
|
|
425
|
+
id?: string;
|
|
426
|
+
path: string;
|
|
427
|
+
label?: string;
|
|
428
|
+
title?: string;
|
|
429
|
+
section?: string;
|
|
430
|
+
icon?: ReactNode;
|
|
431
|
+
layout?: "default" | "content-only" | "portal";
|
|
432
|
+
blocks?: OonBlockDef[];
|
|
433
|
+
component?: string;
|
|
434
|
+
permissions?: string[];
|
|
435
|
+
hidden?: boolean;
|
|
436
|
+
order?: number;
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Opções de página
|
|
441
|
+
|
|
442
|
+
| Campo | Uso |
|
|
443
|
+
| --- | --- |
|
|
444
|
+
| `id` | Identificador opcional. |
|
|
445
|
+
| `path` | Rota. |
|
|
446
|
+
| `label` | Nome no menu. |
|
|
447
|
+
| `title` | Título da página. |
|
|
448
|
+
| `section` | Grupo do menu. |
|
|
449
|
+
| `layout` | Layout da página. |
|
|
450
|
+
| `blocks` | Blocos renderizados. |
|
|
451
|
+
| `component` | Componente custom em `registry.pageComponents`. |
|
|
452
|
+
| `permissions` | Permissões da página. |
|
|
453
|
+
| `hidden` | Oculta do menu. |
|
|
454
|
+
| `order` | Ordenação no menu. |
|
|
455
|
+
|
|
456
|
+
## Blocks UI v2
|
|
457
|
+
|
|
458
|
+
Tipos atuais:
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
type OonBlockDef =
|
|
462
|
+
| OonCustomBlockDef
|
|
463
|
+
| OonCollectionDataGridBlockDef
|
|
464
|
+
| OonCollectionCardsBlockDef
|
|
465
|
+
| OonSectionBlockDef
|
|
466
|
+
| OonMarkdownBlockDef
|
|
467
|
+
| OonGenericBlockDef;
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Campos comuns
|
|
471
|
+
|
|
472
|
+
```ts
|
|
473
|
+
interface OonBaseBlockDef {
|
|
474
|
+
id?: string;
|
|
475
|
+
title?: string;
|
|
476
|
+
permissions?: string[];
|
|
477
|
+
hidden?: boolean;
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### custom
|
|
482
|
+
|
|
483
|
+
```json
|
|
484
|
+
{
|
|
485
|
+
"type": "custom",
|
|
486
|
+
"component": "MeusAppsHero",
|
|
487
|
+
"props": {
|
|
488
|
+
"titulo": "Bem-vindo"
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
Renderiza componente de `registry.pageComponents.MeusAppsHero`.
|
|
494
|
+
|
|
495
|
+
### collection.datagrid
|
|
496
|
+
|
|
497
|
+
```json
|
|
498
|
+
{
|
|
499
|
+
"type": "collection.datagrid",
|
|
500
|
+
"model": "App",
|
|
501
|
+
"mode": "dynamic",
|
|
502
|
+
"title": "Apps"
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
Opções:
|
|
507
|
+
|
|
508
|
+
```ts
|
|
509
|
+
interface OonCollectionDataGridBlockDef {
|
|
510
|
+
type: "collection.datagrid";
|
|
511
|
+
model: string;
|
|
512
|
+
mode?: CollectionMode;
|
|
513
|
+
renderer?: string;
|
|
514
|
+
columns?: OonColumnDef[];
|
|
515
|
+
form?: OonFormFieldDef[];
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### collection.cards
|
|
520
|
+
|
|
521
|
+
```json
|
|
522
|
+
{
|
|
523
|
+
"type": "collection.cards",
|
|
524
|
+
"model": "App",
|
|
525
|
+
"renderer": "cards.appLauncher"
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Renderiza cards usando `registry.cardRenderers.appLauncher` quando registrado.
|
|
530
|
+
|
|
531
|
+
### section
|
|
532
|
+
|
|
533
|
+
```json
|
|
534
|
+
{
|
|
535
|
+
"type": "section",
|
|
536
|
+
"title": "Administração",
|
|
537
|
+
"description": "Gestão dos apps e permissões",
|
|
538
|
+
"blocks": [
|
|
539
|
+
{ "type": "collection.datagrid", "model": "Usuario" }
|
|
540
|
+
]
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### markdown
|
|
545
|
+
|
|
546
|
+
```json
|
|
547
|
+
{
|
|
548
|
+
"type": "markdown",
|
|
549
|
+
"content": "Texto institucional ou instruções da página."
|
|
550
|
+
}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Blocos reservados/genéricos
|
|
554
|
+
|
|
555
|
+
O contrato já reserva:
|
|
556
|
+
|
|
557
|
+
```txt
|
|
558
|
+
collection.form
|
|
559
|
+
pipeline.board
|
|
560
|
+
document.viewer
|
|
561
|
+
dashboard.kpi
|
|
562
|
+
tabs
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Esses blocos podem ser usados como contrato futuro, mas confirme suporte visual antes de depender deles em produção.
|
|
566
|
+
|
|
567
|
+
## Registry
|
|
568
|
+
|
|
569
|
+
```ts
|
|
570
|
+
interface OonComponentRegistry {
|
|
571
|
+
layoutSlots?: Record<string, OonRendererComponent<any>>;
|
|
572
|
+
fieldRenderers?: Record<string, OonRendererComponent<any>>;
|
|
573
|
+
cellRenderers?: Record<string, OonRendererComponent<any>>;
|
|
574
|
+
cardRenderers?: Record<string, OonRendererComponent<any>>;
|
|
575
|
+
actionRenderers?: Record<string, OonRendererComponent<any>>;
|
|
576
|
+
pageComponents?: Record<string, OonRendererComponent<any>>;
|
|
577
|
+
menuRenderers?: Record<string, OonRendererComponent<any>>;
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### Mapeamento de chaves
|
|
582
|
+
|
|
583
|
+
| Chave no manifesto | Bucket esperado |
|
|
584
|
+
| --- | --- |
|
|
585
|
+
| `custom:MeusAppsHeader` | `layoutSlots` ou `pageComponents`, conforme uso. |
|
|
586
|
+
| `fields.password` | `fieldRenderers` |
|
|
587
|
+
| `cells.statusBadge` | `cellRenderers` |
|
|
588
|
+
| `cards.appLauncher` | `cardRenderers` |
|
|
589
|
+
| `actions.ativarApp` | `actionRenderers` |
|
|
590
|
+
| `menus.portal` | `menuRenderers` |
|
|
591
|
+
|
|
592
|
+
## Exemplo v1 simples
|
|
593
|
+
|
|
594
|
+
```json
|
|
595
|
+
{
|
|
596
|
+
"name": "Central SS Eventos",
|
|
597
|
+
"slug": "central-ss-eventos",
|
|
598
|
+
"navigation": { "mode": "auto" },
|
|
599
|
+
"collections": [
|
|
600
|
+
{ "model": "Orcamento", "label": "Orçamentos", "section": "Operação" },
|
|
601
|
+
{ "model": "Prestador", "label": "Prestadores", "section": "Cadastros" }
|
|
602
|
+
],
|
|
603
|
+
"pipelines": [
|
|
604
|
+
{ "model": "Pagamento", "stageField": "status", "label": "Esteira de Pagamentos" }
|
|
605
|
+
],
|
|
606
|
+
"documents": [
|
|
607
|
+
{ "model": "DocumentoFiscal", "label": "Documentos Fiscais", "approval": true, "attachments": true }
|
|
608
|
+
]
|
|
609
|
+
}
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
## Exemplo v2 portal / Meus Apps
|
|
613
|
+
|
|
614
|
+
```json
|
|
615
|
+
{
|
|
616
|
+
"schemaVersion": 2,
|
|
617
|
+
"name": "Meus Apps",
|
|
618
|
+
"slug": "meus-apps",
|
|
619
|
+
"layout": {
|
|
620
|
+
"shell": "portal",
|
|
621
|
+
"sidebar": "none",
|
|
622
|
+
"topbar": "none",
|
|
623
|
+
"header": "custom:MeusAppsHeader",
|
|
624
|
+
"footer": "core"
|
|
625
|
+
},
|
|
626
|
+
"navigation": { "mode": "mixed" },
|
|
627
|
+
"pages": [
|
|
628
|
+
{
|
|
629
|
+
"path": "/",
|
|
630
|
+
"label": "Meus Apps",
|
|
631
|
+
"layout": "content-only",
|
|
632
|
+
"blocks": [
|
|
633
|
+
{ "type": "custom", "component": "MeusAppsHero" },
|
|
634
|
+
{ "type": "collection.cards", "model": "App", "renderer": "cards.appLauncher" }
|
|
635
|
+
]
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
"path": "/admin/apps",
|
|
639
|
+
"label": "Apps",
|
|
640
|
+
"section": "Administração",
|
|
641
|
+
"blocks": [
|
|
642
|
+
{ "type": "collection.datagrid", "model": "App", "mode": "dynamic" }
|
|
643
|
+
]
|
|
644
|
+
}
|
|
645
|
+
]
|
|
646
|
+
}
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
## Exemplo de registry em TypeScript
|
|
650
|
+
|
|
651
|
+
```tsx
|
|
652
|
+
import manifest from "../central.ui.json";
|
|
653
|
+
import { manifestToConfig, start } from "@oondemand/oon-core-front";
|
|
654
|
+
import { MeusAppsHeader } from "./overrides/MeusAppsHeader";
|
|
655
|
+
import { AppLauncherCard } from "./overrides/AppLauncherCard";
|
|
656
|
+
|
|
657
|
+
const config = manifestToConfig(manifest, {
|
|
658
|
+
apiBaseUrl: import.meta.env.VITE_API_URL,
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
start({
|
|
662
|
+
...config,
|
|
663
|
+
registry: {
|
|
664
|
+
layoutSlots: {
|
|
665
|
+
MeusAppsHeader,
|
|
666
|
+
},
|
|
667
|
+
cardRenderers: {
|
|
668
|
+
"cards.appLauncher": AppLauncherCard,
|
|
669
|
+
appLauncher: AppLauncherCard,
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
});
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
## Limitações atuais importantes
|
|
676
|
+
|
|
677
|
+
- O atalho `collections[]` do `central.ui.json` lê apenas `model`, `mode`, `path`, `label` e `section`.
|
|
678
|
+
- Para `columns`, `form`, `actions`, `renderer` e `cardRenderer`, use blocos UI v2, `ui.views` em configuração TypeScript ou evolução futura do conversor.
|
|
679
|
+
- `registry` não deve ser escrito em JSON com componentes React. Use código TypeScript.
|
|
680
|
+
- Blocos `collection.form`, `pipeline.board`, `document.viewer`, `dashboard.kpi` e `tabs` estão reservados no contrato, mas precisam de confirmação visual antes de uso em produção.
|
|
681
|
+
|
|
682
|
+
## Checklist para Codex
|
|
683
|
+
|
|
684
|
+
Antes de criar UI customizada, confirme:
|
|
685
|
+
|
|
686
|
+
- O requisito cabe em `collections`, `documents` ou `pipelines`?
|
|
687
|
+
- O requisito cabe em `pages` + `blocks`?
|
|
688
|
+
- O requisito cabe em renderer registrado por chave?
|
|
689
|
+
- A permissão está declarada em página, bloco, menu ou backend?
|
|
690
|
+
- Não há componente React serializado no JSON?
|
|
691
|
+
- A Central continua funcionando com atualização do pacote Core?
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
O frontend da Central deve ser declarativo. Shell, providers, rotas, menu, datagrid, formulários, documentos e esteiras pertencem ao `@oondemand/oon-core-front`.
|
|
4
4
|
|
|
5
|
+
Para a lista completa de opções do manifesto, use `FRONTEND_MANIFEST_REFERENCE.md`.
|
|
6
|
+
|
|
5
7
|
## Estrutura esperada
|
|
6
8
|
|
|
7
9
|
```txt
|
|
@@ -29,7 +31,16 @@ Use `central.ui.json` como entrada principal para declarar:
|
|
|
29
31
|
- documentos;
|
|
30
32
|
- esteiras;
|
|
31
33
|
- dashboards;
|
|
32
|
-
- agrupamentos
|
|
34
|
+
- agrupamentos;
|
|
35
|
+
- layout v2;
|
|
36
|
+
- páginas por blocos;
|
|
37
|
+
- renderers por chave.
|
|
38
|
+
|
|
39
|
+
## Manifesto v1 e v2
|
|
40
|
+
|
|
41
|
+
- Manifesto sem `schemaVersion` mantém compatibilidade v1.
|
|
42
|
+
- Manifesto com `schemaVersion: 2` habilita composição por `layout`, `navigation`, `pages` e `blocks`.
|
|
43
|
+
- Componentes React não devem ser serializados no JSON; use chaves e registre os componentes no `registry` em TypeScript.
|
|
33
44
|
|
|
34
45
|
## Regras
|
|
35
46
|
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"sync:metadata": "oonCore-front sync:metadata"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@oondemand/oon-core-front": "^0.3.
|
|
13
|
+
"@oondemand/oon-core-front": "^0.3.10",
|
|
14
14
|
"@chakra-ui/react": "^3.13.0",
|
|
15
15
|
"@emotion/react": "^11.14.0",
|
|
16
16
|
"@tanstack/react-query": "^5.65.0",
|