@praxisui/table 5.0.0-beta.0 → 7.0.0-beta.0
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 +470 -414
- package/fesm2022/praxisui-table.mjs +3071 -31
- package/index.d.ts +209 -4
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
---
|
|
1
|
+
---
|
|
2
2
|
title: "Table"
|
|
3
3
|
slug: "table-overview"
|
|
4
4
|
description: "Visao geral do @praxisui/table com TableConfig unificada, filtros, renderers, performance e integracao enterprise."
|
|
@@ -50,12 +50,12 @@ last_updated: "2026-03-07"
|
|
|
50
50
|
|
|
51
51
|
# @praxisui/table
|
|
52
52
|
|
|
53
|
-
> Estado canônico do workspace Angular: JSON Logic é o único contrato ativo de regras
|
|
53
|
+
> Estado canônico do workspace Angular: JSON Logic é o único contrato ativo de regras condicionais.
|
|
54
54
|
|
|
55
55
|
## Documentation
|
|
56
56
|
|
|
57
|
-
-
|
|
58
|
-
-
|
|
57
|
+
- Documentação oficial: https://praxisui.dev
|
|
58
|
+
- Aplicação de referência: https://github.com/codexrodrigues/praxis-ui-quickstart
|
|
59
59
|
- Indicado para: data grids enterprise com filtros, edicao, virtualizacao, renderers e governanca de configuracao
|
|
60
60
|
|
|
61
61
|
## When to use
|
|
@@ -64,7 +64,67 @@ last_updated: "2026-03-07"
|
|
|
64
64
|
- Governar configuracao de colunas, toolbar e comportamento em runtime
|
|
65
65
|
- Integrar tabelas a fluxos CRUD, IA e editores visuais do ecossistema Praxis UI
|
|
66
66
|
|
|
67
|
-
##
|
|
67
|
+
## Rich Content Convergence
|
|
68
|
+
|
|
69
|
+
- `mapTableRendererToRichContentP0(...)` e a ponte canonica entre os renderers de celula da tabela e o vocabulario compartilhado `1.0` de rich content em `@praxisui/core`.
|
|
70
|
+
- O subconjunto promovido nesta fase e intencionalmente pequeno: `icon`, `image`, `badge`, `chip -> badge`, `avatar`, `progress` e `compose`.
|
|
71
|
+
- Renderers interativos como `button`, `toggle`, `menu`, `link`, `html` e `rating`, alem do shell de detail/expansion, continuam table-owned ate promocao semantica explicita.
|
|
72
|
+
|
|
73
|
+
## Detail Rich Surfaces
|
|
74
|
+
|
|
75
|
+
- `behavior.expansion.detail.schemaContract.allowedNodes` agora inclui `detailList` como node canônico novo para colecoes ricas no detail row.
|
|
76
|
+
- A mesma fronteira agora inclui `cardGrid` como container canônico para grades densas de cards no detail.
|
|
77
|
+
- `mediaBlock` entrou como primitive compartilhada para headers/identidade rica no topo do detail, sem criar renderer paralelo table-owned.
|
|
78
|
+
- `timeline` entrou como surface cronologica compartilhada para atividade recente, preservando o shell host-owned da tabela.
|
|
79
|
+
- `actionBar` entrou como surface host-mediated para grupos de ações contextuais no detail, sem duplicar `row actions`.
|
|
80
|
+
- `tableRef`, `formRef`, `chartRef`, `templateRef` e `diagramEmbed` agora entram como embeds governados no detail row.
|
|
81
|
+
- `list` continua significando colecao simples. Ele nao foi promovido para subtree declarativa por item.
|
|
82
|
+
- `detailList` e host-mediated:
|
|
83
|
+
- o host resolve a colecao e despacha `itemActions`
|
|
84
|
+
- cada item renderiza sua subtree declarativa via `PraxisRichContent`
|
|
85
|
+
- `cardGrid` tambem e host-mediated:
|
|
86
|
+
- o host resolve apenas o shell responsivo do grid
|
|
87
|
+
- cada card continua renderizado como `RichCardNode` via `PraxisRichContent`
|
|
88
|
+
- `actionBar` tambem e host-mediated:
|
|
89
|
+
- o host continua dono de dispatch, disabled, `visibleWhen` e `payloadExpr`
|
|
90
|
+
- o miolo visual de cada botão continua delegado para `PraxisRichContent`
|
|
91
|
+
- embeds governados tambem sao host-mediated:
|
|
92
|
+
- o host continua dono de discovery, resolucao e abertura de surface
|
|
93
|
+
- o shell visual, metadados e CTA do embed ficam padronizados na tabela
|
|
94
|
+
- `diagramEmbed` adiciona preview governado de fonte, sem abrir uma DSL paralela no detail
|
|
95
|
+
- `mediaBlock` e host-neutral:
|
|
96
|
+
- o contrato base vive em `@praxisui/core`
|
|
97
|
+
- o rendering vive em `@praxisui/rich-content`
|
|
98
|
+
- a tabela apenas o aceita no detail schema e o delega para o runtime compartilhado
|
|
99
|
+
- O primeiro corte cobre:
|
|
100
|
+
- `field` ou `items`
|
|
101
|
+
- `emptyText`
|
|
102
|
+
- `itemSchema.nodes`
|
|
103
|
+
- `itemContext` (`detailItem` / `detailIndex`)
|
|
104
|
+
- `itemActions` com `payloadExpr`, `visibleWhen` e `disabledWhen`
|
|
105
|
+
- O segundo corte cobre:
|
|
106
|
+
- `columns` (`1 | 2 | 3 | 4 | 'auto'`)
|
|
107
|
+
- `minCardWidth`
|
|
108
|
+
- `cards[]` com `title`, `subtitle` e `content` limitado a `RichPresenterNode | RichComposeNode`
|
|
109
|
+
- O terceiro corte agora cobre:
|
|
110
|
+
- `mediaBlock.avatar`
|
|
111
|
+
- `mediaBlock.title`
|
|
112
|
+
- `mediaBlock.subtitle`
|
|
113
|
+
- `mediaBlock.meta`
|
|
114
|
+
- `mediaBlock.trailing`
|
|
115
|
+
- O quarto corte agora cobre:
|
|
116
|
+
- `timeline.field` ou `timeline.items`
|
|
117
|
+
- `timeline.emptyText`
|
|
118
|
+
- `timeline.itemSchema.titleField`
|
|
119
|
+
- `timeline.itemSchema.subtitleField`
|
|
120
|
+
- `timeline.itemSchema.metaField`
|
|
121
|
+
- `timeline.itemSchema.iconField`
|
|
122
|
+
- `timeline.itemSchema.badgeField`
|
|
123
|
+
- O quinto corte agora cobre:
|
|
124
|
+
- `tableRef`, `formRef`, `chartRef` e `templateRef` com `description`, `caption`, `inputs`, `presetRef`, `emptyText` e `action`
|
|
125
|
+
- `diagramEmbed` com `provider`, `source` ou `sourceField`, `presetRef` e `action`
|
|
126
|
+
|
|
127
|
+
## `x-ui.analytics` como fallback tabular canônico
|
|
68
128
|
|
|
69
129
|
O `@praxisui/table` materializa a familia `analytic-table` quando o `@praxisui/core`
|
|
70
130
|
resolve que uma projection de `x-ui.analytics` continua valida, mas nao e um chart
|
|
@@ -95,7 +155,7 @@ Filtro runtime:
|
|
|
95
155
|
- somente `filters` entram no request remoto nesta fase
|
|
96
156
|
- `sort`, `limit` e agregacao continuam vindo da projection publicada
|
|
97
157
|
|
|
98
|
-
> Componente de tabela empresarial
|
|
158
|
+
> Componente de tabela empresarial avançado com arquitetura unificada
|
|
99
159
|
|
|
100
160
|
## Customization Mode Contract
|
|
101
161
|
|
|
@@ -109,92 +169,92 @@ Filtro runtime:
|
|
|
109
169
|
- Hosts that relied on the previous implicit authoring behavior must now declare `[enableCustomization]="true"` explicitly.
|
|
110
170
|
- This is an intentional breaking change for enterprise governance: authoring is opt-in, not ambient.
|
|
111
171
|
|
|
112
|
-
##
|
|
172
|
+
## 🌟 Visão Geral
|
|
113
173
|
|
|
114
|
-
A biblioteca `@praxisui/table` fornece um componente de tabela robusto e altamente
|
|
174
|
+
A biblioteca `@praxisui/table` fornece um componente de tabela robusto e altamente configurável para aplicações Angular empresariais. Com a nova arquitetura unificada, oferece uma experiência de desenvolvimento simplificada mantendo todos os recursos avançados.
|
|
115
175
|
|
|
116
|
-
##
|
|
176
|
+
## 🎨 Tema M3 (tokens mÃnimos)
|
|
117
177
|
|
|
118
178
|
Para garantir que a tabela, filtros e editores reflitam o tema do app host:
|
|
119
179
|
|
|
120
|
-
-
|
|
180
|
+
- SuperfÃcies: `--md-sys-color-surface`, `--md-sys-color-surface-variant`, `--md-sys-color-surface-container-*`
|
|
121
181
|
- Texto/contorno: `--md-sys-color-on-surface`, `--md-sys-color-on-surface-variant`, `--md-sys-color-on-primary`, `--md-sys-color-outline`, `--md-sys-color-outline-variant`
|
|
122
|
-
-
|
|
182
|
+
- Semânticos: `--md-sys-color-primary`, `--md-sys-color-secondary`, `--md-sys-color-tertiary`, `--md-sys-color-error`
|
|
123
183
|
- Containers: `--md-sys-color-primary-container`, `--md-sys-color-secondary-container`, `--md-sys-color-tertiary-container`, `--md-sys-color-error-container`
|
|
124
184
|
- Overlay: `--md-sys-color-scrim`
|
|
125
|
-
-
|
|
185
|
+
- Elevação: `--md-sys-elevation-level1`–`--md-sys-elevation-level3`
|
|
126
186
|
|
|
127
|
-
|
|
128
|
-
Nota: a classe de tema
|
|
187
|
+
Observação: tokens `--md-sys-*` e `--mdc-theme-*` continuam aceitos quando presentes.
|
|
188
|
+
Nota: a classe de tema é decisão do host (`.dark-theme` ou `.theme-dark`/`.theme-light`); mantenha tokens e componentes no mesmo escopo.
|
|
129
189
|
|
|
130
|
-
##
|
|
190
|
+
## ✨ CaracterÃsticas Principais
|
|
131
191
|
|
|
132
|
-
###
|
|
192
|
+
### ðŸ—ï¸ Arquitetura Unificada
|
|
133
193
|
|
|
134
|
-
- **Interface
|
|
194
|
+
- **Interface única**: `TableConfig` consolidada
|
|
135
195
|
- **Type Safety**: Tipagem forte em toda a API
|
|
136
|
-
- **Performance otimizada**:
|
|
137
|
-
- **API simplificada**: Menos
|
|
138
|
-
|
|
139
|
-
###
|
|
140
|
-
|
|
141
|
-
- **
|
|
142
|
-
- **
|
|
143
|
-
- **Filtros
|
|
144
|
-
- **
|
|
145
|
-
- **Redimensionamento**: Colunas
|
|
146
|
-
- **
|
|
147
|
-
- **
|
|
196
|
+
- **Performance otimizada**: Eliminação de overhead de adaptação
|
|
197
|
+
- **API simplificada**: Menos confusão, mais produtividade
|
|
198
|
+
|
|
199
|
+
### 📊 Recursos Avançados
|
|
200
|
+
|
|
201
|
+
- **Paginação inteligente**: Client-side e server-side
|
|
202
|
+
- **Ordenação múltipla**: Suporte a multi-sort
|
|
203
|
+
- **Filtros dinâmicos**: Global e por coluna
|
|
204
|
+
- **Seleção de linhas**: Single, multiple e bulk actions
|
|
205
|
+
- **Redimensionamento**: Colunas redimensionáveis
|
|
206
|
+
- **Virtualização**: Para grandes volumes de dados
|
|
207
|
+
- **Exportação**: CSV, Excel, PDF
|
|
148
208
|
- **Acessibilidade**: WCAG 2.1 AA compliant
|
|
149
|
-
- **
|
|
209
|
+
- **Verificação de Schema**: ETag/If-None-Match com notificações (somente em customização)
|
|
150
210
|
|
|
151
211
|
## Expansion Hypermedia
|
|
152
212
|
|
|
153
|
-
O primeiro corte de `behavior.expansion.detail.source.mode = "hypermedia"`
|
|
213
|
+
O primeiro corte de `behavior.expansion.detail.source.mode = "hypermedia"` é
|
|
154
214
|
`capabilities-first`:
|
|
155
215
|
|
|
156
|
-
- a row expandida
|
|
157
|
-
- `surfaces`, `actions` e
|
|
216
|
+
- a row expandida começa em `_links.capabilities`
|
|
217
|
+
- `surfaces`, `actions` e operações canônicas vêm do snapshot agregado retornado
|
|
158
218
|
pelo backend
|
|
159
219
|
- o detail renderiza um resumo contextual somente leitura, com foco em UX de
|
|
160
|
-
|
|
161
|
-
- este corte
|
|
162
|
-
- quando o item
|
|
220
|
+
negócio e affordances disponÃveis naquele registro
|
|
221
|
+
- este corte não executa `surface.open` inline nem dispara workflow inline
|
|
222
|
+
- quando o item não expõe `rel="capabilities"`, o runtime aplica fail-closed
|
|
163
223
|
|
|
164
|
-
|
|
224
|
+
Observação de escala:
|
|
165
225
|
- o prefetch por linha continua ativo quando `actions.row.enabled=true`
|
|
166
|
-
- quando apenas o expansion `hypermedia`
|
|
226
|
+
- quando apenas o expansion `hypermedia` está ligado, o discovery contextual é
|
|
167
227
|
resolvido sob demanda ao expandir a linha
|
|
168
228
|
|
|
169
|
-
###
|
|
229
|
+
### 📄 Contrato Inline do Filtro
|
|
170
230
|
|
|
171
231
|
- Referencia canonica: `projects/praxis-dynamic-fields/docs/dynamic-fields-inline-components-guide.md` (slug publicado: `dynamic-fields-inline-components-guide`)
|
|
172
232
|
- No contexto da tabela, use este contrato para definir `controlType` inline e politica de compatibilidade (canonica vs legado).
|
|
173
233
|
|
|
174
|
-
###
|
|
234
|
+
### 🧠Decisoes de Arquitetura (ADR)
|
|
175
235
|
|
|
176
236
|
- Bundle/adapters: `projects/praxis-table/docs/adr/2026-03-filter-drawer-adapter-light-entrypoint.md`
|
|
177
237
|
|
|
178
|
-
###
|
|
238
|
+
### 🎨 Editores Visuais
|
|
179
239
|
|
|
180
|
-
- **Behavior Editor**:
|
|
181
|
-
- **Columns Editor**:
|
|
182
|
-
- **Toolbar Editor**:
|
|
183
|
-
- **Messages Editor**: Textos e
|
|
240
|
+
- **Behavior Editor**: Configuração de comportamentos
|
|
241
|
+
- **Columns Editor**: Gestão avançada de colunas
|
|
242
|
+
- **Toolbar Editor**: Personalização de ações
|
|
243
|
+
- **Messages Editor**: Textos e localização
|
|
184
244
|
|
|
185
245
|
Nota (Regras)
|
|
186
|
-
- A antiga aba visual
|
|
246
|
+
- A antiga aba visual genérica foi removida deste pacote. O editor especializado de regras da Tabela já está disponÃvel no painel de configuração.
|
|
187
247
|
|
|
188
|
-
###
|
|
248
|
+
### 🧩 Editor de Regras (column-first)
|
|
189
249
|
|
|
190
|
-
O novo editor
|
|
250
|
+
O novo editor é "column-first" e usa uma tipagem compartilhada com o Editor de Colunas. Principais pontos:
|
|
191
251
|
|
|
192
|
-
- Escopo: aplique regras na linha inteira (rowConditionalStyles) ou em uma coluna
|
|
193
|
-
- Operadores por tipo: o conjunto de operadores
|
|
194
|
-
- Editores de valor
|
|
195
|
-
- Grupos
|
|
196
|
-
- Preview: execute
|
|
197
|
-
- Import/Export: exporta JSON sem o campo `enabled`; importa com
|
|
252
|
+
- Escopo: aplique regras na linha inteira (rowConditionalStyles) ou em uma coluna especÃfica (columns[].conditionalStyles).
|
|
253
|
+
- Operadores por tipo: o conjunto de operadores é filtrado por tipo (string/number/date/boolean/enum).
|
|
254
|
+
- Editores de valor dinâmicos: inputs numéricos, listas (CSV/múltipla seleção), datepickers.
|
|
255
|
+
- Grupos lógicos: construa condições com AND/OR/NOT e reordene via arrastar-e-soltar (CDK DragDrop).
|
|
256
|
+
- Preview: execute “Testar†para ver quantas linhas seriam afetadas pelas regras ativas.
|
|
257
|
+
- Import/Export: exporta JSON sem o campo `enabled`; importa com validação estrutural de JSON Logic e sanitização de estilos (allowlist).
|
|
198
258
|
|
|
199
259
|
Exemplos de JSON Logic:
|
|
200
260
|
|
|
@@ -208,80 +268,77 @@ Exemplos de JSON Logic:
|
|
|
208
268
|
```
|
|
209
269
|
|
|
210
270
|
Notas sobre enum/CSV:
|
|
211
|
-
- Para campos enumerados, as
|
|
212
|
-
- Para `in/not in` em
|
|
271
|
+
- Para campos enumerados, as opções são inferidas de `valueMapping` da coluna ou de `fields?.options`.
|
|
272
|
+
- Para `in/not in` em números/strings, use CSV (ex.: `10, 20, 30` ou `Alice, Bob`).
|
|
213
273
|
|
|
214
|
-
####
|
|
274
|
+
#### Operadores e helpers de JSON Logic
|
|
215
275
|
|
|
216
|
-
O runtime da tabela
|
|
276
|
+
O runtime da tabela já inclui operadores e helpers canônicos para JSON/tempo/listas/texto sem configuração extra:
|
|
217
277
|
|
|
218
278
|
- JSON: `jsonGet`, `hasJsonKey`, `jsonPathMatches`, `jsonEq`, `jsonIn`, `jsonType`
|
|
219
279
|
- Texto/valor: `isBlank`, `eqIgnoreCase`, `coalesce`
|
|
220
280
|
- Faixas: `between`, `dateBetween`
|
|
221
|
-
-
|
|
281
|
+
- Coleções: `containsAny`, `containsAll`, `len`, `lenEq`, `lenGt`, `lenLt`, `lenAtLeast`
|
|
222
282
|
- Tempo: `today`, `now`, `dateAdd`, `dateFormat`, `isToday`, `inLast`, `isPast`, `isPastOrNow`, `isFuture`, `isFutureOrNow`, `weekdayIn`
|
|
223
283
|
|
|
224
|
-
Exemplos de
|
|
225
|
-
- `
|
|
226
|
-
- `jsonIn
|
|
227
|
-
- `eqIgnoreCase
|
|
228
|
-
- `between
|
|
229
|
-
- `dateBetween
|
|
230
|
-
- `containsAll
|
|
231
|
-
|
|
232
|
-
Observação de gramática:
|
|
233
|
-
- comparações diretas sobre retorno de função (`fn(...) == 'x'`) não são suportadas pela gramática atual; prefira funções predicativas (booleanas) na `condition`.
|
|
284
|
+
Exemplos de JSON Logic:
|
|
285
|
+
- `{ "===": [{ "jsonGet": [{ "var": "payload" }, "$.user.name"] }, "Alice"] }`
|
|
286
|
+
- `{ "jsonIn": [{ "var": "customer" }, "$.id", [10, 20]] }`
|
|
287
|
+
- `{ "eqIgnoreCase": [{ "var": "status" }, "ATIVO"] }`
|
|
288
|
+
- `{ "between": [{ "var": "amount" }, 10, 20] }`
|
|
289
|
+
- `{ "dateBetween": [{ "var": "createdAt" }, "2025-01-01", "2025-12-31"] }`
|
|
290
|
+
- `{ "containsAll": [{ "var": "tags" }, ["vip", "gold"]] }`
|
|
234
291
|
|
|
235
|
-
Guia completo: `projects/praxis-table/docs/
|
|
292
|
+
Guia completo: `projects/praxis-table/docs/json-logic-operators-and-helpers.md`
|
|
236
293
|
|
|
237
|
-
####
|
|
294
|
+
#### 🎨 Efeitos (Conteúdo C)
|
|
238
295
|
|
|
239
|
-
O bloco de Efeitos permite aplicar estilo e visuais quando a
|
|
296
|
+
O bloco de Efeitos permite aplicar estilo e visuais quando a condição é verdadeira:
|
|
240
297
|
|
|
241
|
-
- Toolbar de texto com
|
|
242
|
-
- Presets de feedback com
|
|
243
|
-
-
|
|
244
|
-
-
|
|
245
|
-
- Layout do compose:
|
|
298
|
+
- Toolbar de texto com Ãcones (negrito, itálico, sublinhado) e presets rápidos (tachado, maiúsculas/minúsculas/capitalizar, tamanho +/- e reset).
|
|
299
|
+
- Presets de feedback com Ãcones (sucesso, aviso, erro, info) — mantêm o rótulo via tooltip e `aria-label`.
|
|
300
|
+
- “Posição do valor†como grupo de alternância (antes / entre-1 / entre-2 / depois / oculto).
|
|
301
|
+
- “Ordem dos visuais†com seletor compacto (3 mais comuns) e menu para opções extras.
|
|
302
|
+
- Layout do compose: espaçamento, alinhamento, quebra de linha e reticências.
|
|
246
303
|
|
|
247
304
|
Dicas
|
|
248
|
-
- Use
|
|
249
|
-
- Para acessibilidade, os grupos possuem `role="toolbar"`, tooltips e
|
|
305
|
+
- Use “Resetar texto†para reverter efeitos de texto sem perder cor de fundo/borda.
|
|
306
|
+
- Para acessibilidade, os grupos possuem `role="toolbar"`, tooltips e navegação por teclado consistente.
|
|
250
307
|
|
|
251
308
|
Como reverter efeitos
|
|
252
|
-
-
|
|
253
|
-
-
|
|
309
|
+
- “Reset Text†remove apenas propriedades de tipografia e transformação de texto.
|
|
310
|
+
- “Limpar efeitos†apaga classe e estilo livres do bloco rápido.
|
|
254
311
|
|
|
255
|
-
|
|
312
|
+
Observação: capturas de tela “antes/depois†podem ser adicionadas no PR conforme necessário.
|
|
256
313
|
|
|
257
314
|
#### Relacionais (lookup)
|
|
258
315
|
|
|
259
|
-
Campos relacionais (FK/objetos) podem ser editados no Rules Editor com busca
|
|
316
|
+
Campos relacionais (FK/objetos) podem ser editados no Rules Editor com busca assÃncrona (typeahead) e seleção single/multiple.
|
|
260
317
|
|
|
261
|
-
Boas
|
|
318
|
+
Boas práticas
|
|
262
319
|
- Informe `resourcePath` (ou `endpoint`) no `FieldDefinition` para habilitar o lookup via `GenericCrudService` do host.
|
|
263
|
-
- Defina `valueField` (chave
|
|
320
|
+
- Defina `valueField` (chave estável, tipicamente `id`) e `displayField` (label amigável, como `name`).
|
|
264
321
|
|
|
265
|
-
##
|
|
322
|
+
## 🔎 Filtro: Atalhos para PerÃodo (DateRange)
|
|
266
323
|
|
|
267
|
-
Habilite atalhos de
|
|
324
|
+
Habilite atalhos de perÃodo no filtro dinâmico sem alterar o contrato do `praxis-filter` — apenas via metadata do campo:
|
|
268
325
|
|
|
269
326
|
```ts
|
|
270
327
|
// Em FilterConfig (ou na metadata de campos do filtro)
|
|
271
328
|
{
|
|
272
329
|
name: 'period',
|
|
273
|
-
label: '
|
|
330
|
+
label: 'PerÃodo',
|
|
274
331
|
controlType: 'dateRange',
|
|
275
332
|
showShortcuts: true,
|
|
276
333
|
shortcuts: ['thisMonth','lastMonth','thisYear'],
|
|
277
334
|
// Opcional:
|
|
278
|
-
// i18nShortcuts: { thisMonth: 'Este
|
|
335
|
+
// i18nShortcuts: { thisMonth: 'Este mês', lastMonth: 'Mês passado' },
|
|
279
336
|
// applyOnShortcutClick: true
|
|
280
337
|
}
|
|
281
338
|
```
|
|
282
|
-
- Para
|
|
283
|
-
- No runtime da tabela
|
|
284
|
-
- APIs com busca: suporte a um
|
|
339
|
+
- Para múltipla seleção, use `multiple: true` no `FieldDefinition` quando aplicável.
|
|
340
|
+
- No runtime da tabela não é necessário registrar funções JSON/data manualmente; os helpers já são embutidos.
|
|
341
|
+
- APIs com busca: suporte a um parâmetro livre de texto (por ex. `search`) facilita a experiência do autocomplete.
|
|
285
342
|
|
|
286
343
|
Exemplo de FieldDefinition (lookup)
|
|
287
344
|
```ts
|
|
@@ -293,108 +350,107 @@ const fields: FieldDefinition[] = [
|
|
|
293
350
|
type: 'object',
|
|
294
351
|
// Habilita o lookup via GenericCrudService
|
|
295
352
|
resourcePath: 'customers',
|
|
296
|
-
// Mapeia o id/label que
|
|
353
|
+
// Mapeia o id/label que virão do backend
|
|
297
354
|
valueField: 'id',
|
|
298
355
|
displayField: 'name',
|
|
299
|
-
// Se quiser
|
|
356
|
+
// Se quiser multiseleção em todo o app
|
|
300
357
|
// multiple: true,
|
|
301
358
|
},
|
|
302
359
|
];
|
|
303
360
|
```
|
|
304
361
|
|
|
305
|
-
Operadores
|
|
306
|
-
- `id ==`
|
|
307
|
-
- `id in`
|
|
308
|
-
- `has property`
|
|
309
|
-
- Condições por caminho (join simples): use `
|
|
362
|
+
Operadores relacionais em JSON Logic
|
|
363
|
+
- `id ==` -> `{ "jsonEq": [{ "var": "customer" }, "$.id", 10] }`
|
|
364
|
+
- `id in` -> `{ "jsonIn": [{ "var": "customer" }, "$.id", [10, 20]] }`
|
|
365
|
+
- `has property` -> `{ "hasJsonKey": [{ "var": "customer" }, "$.meta.etag"] }`
|
|
366
|
+
- Condições por caminho (join simples): use `jsonEq/jsonIn` sobre o path necessário
|
|
310
367
|
|
|
311
368
|
UI (no editor)
|
|
312
|
-
- `id ==` (single): autocomplete + chip
|
|
313
|
-
- `id in` (multi): autocomplete + chips
|
|
369
|
+
- `id ==` (single): autocomplete + chip “label [id]†com ação “Limparâ€.
|
|
370
|
+
- `id in` (multi): autocomplete + chips removÃveis por item.
|
|
314
371
|
- `has property`: input do caminho (ex.: `$.meta.etag`).
|
|
315
372
|
|
|
316
373
|
Formato esperado do payload (relacional)
|
|
317
374
|
|
|
318
|
-
Para que o editor/preview e o runtime avaliem corretamente as regras relacionais, o valor do campo deve ser um objeto (ou
|
|
375
|
+
Para que o editor/preview e o runtime avaliem corretamente as regras relacionais, o valor do campo deve ser um objeto (ou compatÃvel com JSON) contendo ao menos o identificador e, opcionalmente, propriedades exibidas:
|
|
319
376
|
|
|
320
377
|
```ts
|
|
321
378
|
// Exemplo de linha (row) com campo relacional "customer"
|
|
322
379
|
const row = {
|
|
323
380
|
id: 123,
|
|
324
381
|
customer: {
|
|
325
|
-
id: 10, //
|
|
326
|
-
name: 'ACME', //
|
|
382
|
+
id: 10, // ↠usado em id == / id in via jsonEq/jsonIn
|
|
383
|
+
name: 'ACME', // ↠usado para exibir label no autocomplete/chip
|
|
327
384
|
meta: { etag: 'v1' },
|
|
328
385
|
},
|
|
329
386
|
};
|
|
330
387
|
|
|
331
|
-
// Regras
|
|
388
|
+
// Regras relacionais em JSON Logic
|
|
332
389
|
// id ==
|
|
333
|
-
// jsonEq
|
|
390
|
+
// { "jsonEq": [{ "var": "customer" }, "$.id", 10] }
|
|
334
391
|
// id in
|
|
335
|
-
// jsonIn
|
|
392
|
+
// { "jsonIn": [{ "var": "customer" }, "$.id", [10, 20]] }
|
|
336
393
|
// has property
|
|
337
|
-
// hasJsonKey
|
|
394
|
+
// { "hasJsonKey": [{ "var": "customer" }, "$.meta.etag"] }
|
|
338
395
|
// caminho/valor (join simples)
|
|
339
|
-
// jsonEq
|
|
396
|
+
// { "jsonEq": [{ "var": "customer" }, "$.name", "ACME"] }
|
|
340
397
|
```
|
|
341
398
|
|
|
342
399
|
Notas
|
|
343
|
-
- O editor usa `displayField` (ex.: `name`) para compor o rótulo, e `valueField` (ex.: `id`) para gerar
|
|
344
|
-
- Se o backend devolver o relacionamento
|
|
400
|
+
- O editor usa `displayField` (ex.: `name`) para compor o rótulo, e `valueField` (ex.: `id`) para gerar o AST Json Logic correspondente.
|
|
401
|
+
- Se o backend devolver o relacionamento já "normalizado" (ex.: `customerId` e `customerName` na mesma linha), você ainda pode expressar condições com operadores padrão (`==`, `in`) no campo numérico/literal — a abordagem relacional é útil quando o payload contém o objeto.
|
|
345
402
|
|
|
346
|
-
Onde
|
|
403
|
+
Onde é consumido (preview e runtime)
|
|
347
404
|
|
|
348
|
-
- Preview/
|
|
349
|
-
- Authoring
|
|
405
|
+
- Preview/validação no Editor de Regras:
|
|
406
|
+
- Authoring canônico manual e visual em JSON Logic: `projects/praxis-table/src/lib/rules-editor/table-rules-editor.component.ts`
|
|
350
407
|
- Runtime na Tabela (aplica `rowConditionalStyles`/`conditionalStyles`):
|
|
351
|
-
- JSON Logic
|
|
408
|
+
- JSON Logic canônico: `projects/praxis-table/src/lib/praxis-table.ts`
|
|
352
409
|
|
|
353
|
-
|
|
354
|
-
- JSON Logic
|
|
355
|
-
- O runtime ainda mantém compatibilidade transitória para regras DSL antigas.
|
|
410
|
+
Observação
|
|
411
|
+
- JSON Logic é o contrato canônico para novas regras e para o editor de regras da tabela.
|
|
356
412
|
|
|
357
413
|
|
|
358
|
-
###
|
|
414
|
+
### âš™ï¸ Painel de Configurações
|
|
359
415
|
|
|
360
|
-
Para abrir o painel de
|
|
416
|
+
Para abrir o painel de configurações, habilite o modo de edição na tabela:
|
|
361
417
|
|
|
362
418
|
```html
|
|
363
419
|
<praxis-table [enableCustomization]="true"></praxis-table>
|
|
364
420
|
```
|
|
365
421
|
|
|
366
|
-
Um
|
|
422
|
+
Um botão de engrenagem será exibido no canto superior direito. Ao clicar nele, o `SettingsPanel` é aberto permitindo ajustar:
|
|
367
423
|
|
|
368
|
-
- **Comportamento**:
|
|
424
|
+
- **Comportamento**: paginação, ordenação, filtros e recursos avançados.
|
|
369
425
|
- **Colunas**: visibilidade, ordem, largura e estilo.
|
|
370
|
-
- **Toolbar**:
|
|
371
|
-
- **Mensagens**: textos e
|
|
426
|
+
- **Toolbar**: ações e botões da barra de ferramentas.
|
|
427
|
+
- **Mensagens**: textos e rótulos exibidos na interface.
|
|
372
428
|
|
|
373
|
-
As
|
|
429
|
+
As alterações podem ser aplicadas temporariamente com **Aplicar** ou salvas de forma persistente com **Salvar & Fechar**.
|
|
374
430
|
|
|
375
|
-
##
|
|
431
|
+
## 🚀 Instalação
|
|
376
432
|
|
|
377
433
|
```bash
|
|
378
434
|
npm install @praxisui/core @praxisui/table
|
|
379
435
|
```
|
|
380
436
|
|
|
381
|
-
Peers
|
|
437
|
+
Peers necessários (instale no app host):
|
|
382
438
|
- `@angular/core` `^20.0.0`, `@angular/common` `^20.0.0`
|
|
383
439
|
- `@praxisui/core` `^0.0.1`
|
|
384
|
-
- `@praxisui/dynamic-fields` `^0.0.1` (quando usar editores/inputs
|
|
385
|
-
- `@praxisui/dynamic-form` `^0.0.1` (quando integrar com
|
|
386
|
-
- `@praxisui/settings-panel` `^0.0.1` (para painel de
|
|
440
|
+
- `@praxisui/dynamic-fields` `^0.0.1` (quando usar editores/inputs dinâmicos)
|
|
441
|
+
- `@praxisui/dynamic-form` `^0.0.1` (quando integrar com formulários dinâmicos)
|
|
442
|
+
- `@praxisui/settings-panel` `^0.0.1` (para painel de configuração embutido)
|
|
387
443
|
|
|
388
|
-
##
|
|
444
|
+
## 📠Uso Básico
|
|
389
445
|
|
|
390
446
|
### Conectando ao Backend com `resourcePath`
|
|
391
447
|
|
|
392
|
-
A forma mais poderosa de usar a `<praxis-table>`
|
|
448
|
+
A forma mais poderosa de usar a `<praxis-table>` é conectá-la diretamente a um endpoint de API compatÃvel com o ecossistema Praxis. Isso é feito através do input `resourcePath`.
|
|
393
449
|
|
|
394
|
-
Quando `resourcePath`
|
|
450
|
+
Quando `resourcePath` é fornecido, a tabela se torna "inteligente":
|
|
395
451
|
|
|
396
|
-
1. **Busca
|
|
397
|
-
2. **
|
|
452
|
+
1. **Busca automática de dados**: A tabela gerencia a paginação, ordenação e filtros, fazendo as requisições necessárias ao backend.
|
|
453
|
+
2. **Geração dinâmica de colunas**: A tabela busca os metadados (schema) do backend para gerar as colunas automaticamente, respeitando as configurações definidas no `praxis-metadata-core` (via anotação `@UISchema`).
|
|
398
454
|
|
|
399
455
|
```html
|
|
400
456
|
<!-- Exemplo no template do seu componente -->
|
|
@@ -404,12 +460,12 @@ Quando `resourcePath` é fornecido, a tabela se torna "inteligente":
|
|
|
404
460
|
Neste exemplo:
|
|
405
461
|
|
|
406
462
|
- `resourcePath="human-resources/departamentos"` instrui a tabela a se comunicar com o endpoint `/api/human-resources/departamentos`.
|
|
407
|
-
- A tabela
|
|
408
|
-
- `enableCustomization` controla explicitamente o gate de
|
|
463
|
+
- A tabela fará requisições como `POST /api/human-resources/departamentos/filter` para obter os dados e `GET /schemas/filtered?path=/api/human-resources/departamentos/all&operation=get&schemaType=response` para obter o schema estrutural usado no bootstrap das colunas.
|
|
464
|
+
- `enableCustomization` controla explicitamente o gate de edição visual. O default canônico agora é `false`; declare `[enableCustomization]="true"` quando o host quiser expor customização e surfaces editoriais.
|
|
409
465
|
|
|
410
466
|
### Consulta Declarativa com `queryContext`
|
|
411
467
|
|
|
412
|
-
Para
|
|
468
|
+
Para orquestração entre widgets em `praxis-dynamic-page`, o contrato semântico primário da tabela passa a ser `queryContext`.
|
|
413
469
|
|
|
414
470
|
```html
|
|
415
471
|
<praxis-table
|
|
@@ -424,23 +480,23 @@ Para orquestração entre widgets em `praxis-dynamic-page`, o contrato semântic
|
|
|
424
480
|
|
|
425
481
|
Regras atuais:
|
|
426
482
|
|
|
427
|
-
- `queryContext.filters`
|
|
483
|
+
- `queryContext.filters` já participa do pipeline efetivo da tabela
|
|
428
484
|
- `filterCriteria` continua aceito como bridge legada de compatibilidade
|
|
429
485
|
- em novo authoring, examples e bindings, prefira `queryContext`
|
|
430
486
|
|
|
431
487
|
### Empty State + Quick Connect (sem `resourcePath`)
|
|
432
488
|
|
|
433
|
-
Se a tabela for renderizada sem `resourcePath`, um
|
|
489
|
+
Se a tabela for renderizada sem `resourcePath`, um cartão de "Empty State" é exibido convidando a conectar o componente a um recurso. Basta clicar em "Conectar a recurso" para abrir um painel rápido com um único campo:
|
|
434
490
|
|
|
435
491
|
```text
|
|
436
492
|
resourcePath: ex.: human-resources/departamentos
|
|
437
493
|
```
|
|
438
494
|
|
|
439
|
-
Ao aplicar/salvar, a `<praxis-table>`
|
|
495
|
+
Ao aplicar/salvar, a `<praxis-table>` é automaticamente configurada para buscar o schema e os dados do backend. Esse fluxo evita telas em branco e simplifica o onboarding do componente em páginas novas.
|
|
440
496
|
|
|
441
|
-
### Fluxo de
|
|
497
|
+
### Fluxo de Comunicação do `resourcePath`
|
|
442
498
|
|
|
443
|
-
O diagrama abaixo ilustra como a propriedade `resourcePath` conecta o componente frontend ao backend no runtime atual da tabela. Antes de iniciar o fluxo remoto, a lib resolve o modo de dados com
|
|
499
|
+
O diagrama abaixo ilustra como a propriedade `resourcePath` conecta o componente frontend ao backend no runtime atual da tabela. Antes de iniciar o fluxo remoto, a lib resolve o modo de dados com precedência **`resourcePath` explÃcito > `data` local > conexão persistida**. Quando o modo efetivo é `remote`, o bootstrap ocorre em três etapas principais: **Configurar**, **Carregar Schema estrutural** e **Buscar Dados**.
|
|
444
500
|
|
|
445
501
|
```mermaid
|
|
446
502
|
sequenceDiagram
|
|
@@ -455,7 +511,7 @@ sequenceDiagram
|
|
|
455
511
|
|
|
456
512
|
activate Praxis_Table
|
|
457
513
|
Praxis_Table->>Praxis_Table: ngOnInit()/ngOnChanges() resolve dataMode
|
|
458
|
-
Note over Praxis_Table: remote quando
|
|
514
|
+
Note over Praxis_Table: remote quando há resourcePath efetivo
|
|
459
515
|
Praxis_Table->>Crud_Service: 1. Chama crudService.configure("human-resources/departamentos")
|
|
460
516
|
|
|
461
517
|
activate Crud_Service
|
|
@@ -466,7 +522,7 @@ sequenceDiagram
|
|
|
466
522
|
Praxis_Table->>Crud_Service: Chama crudService.getSchema()
|
|
467
523
|
|
|
468
524
|
activate Crud_Service
|
|
469
|
-
Crud_Service->>Crud_Service: schemaUrl() preserva o base path
|
|
525
|
+
Crud_Service->>Crud_Service: schemaUrl() preserva o base path canônico
|
|
470
526
|
Crud_Service->>Crud_Service: Deriva path="/api/human-resources/departamentos/all"<br>operation="get", schemaType="response"
|
|
471
527
|
Crud_Service->>Docs_Controller: GET /schemas/filtered?path=.../all&operation=get&schemaType=response
|
|
472
528
|
deactivate Crud_Service
|
|
@@ -481,21 +537,21 @@ sequenceDiagram
|
|
|
481
537
|
Crud_Service-->>Praxis_Table: Normaliza schema e retorna FieldDefinition[]
|
|
482
538
|
deactivate Crud_Service
|
|
483
539
|
|
|
484
|
-
Praxis_Table->>Praxis_Table:
|
|
540
|
+
Praxis_Table->>Praxis_Table: Constrói as colunas da tabela<br>a partir do schema recebido
|
|
485
541
|
|
|
486
542
|
Praxis_Table->>Praxis_Table: 3. Chama this.fetchData()
|
|
487
543
|
Praxis_Table->>Crud_Service: Chama crudService.filter(...) para buscar dados
|
|
488
544
|
|
|
489
545
|
activate Crud_Service
|
|
490
|
-
Crud_Service->>Crud_Service: getEndpointUrl('filter')
|
|
491
|
-
Crud_Service->>BE_Controller:
|
|
546
|
+
Crud_Service->>Crud_Service: getEndpointUrl('filter') constrói a URL: <br> "/api/human-resources/departamentos/filter"
|
|
547
|
+
Crud_Service->>BE_Controller: Requisição HTTP POST para .../filter
|
|
492
548
|
deactivate Crud_Service
|
|
493
549
|
|
|
494
550
|
activate BE_Controller
|
|
495
|
-
BE_Controller->>Abstract_Controller: Herda o
|
|
551
|
+
BE_Controller->>Abstract_Controller: Herda o método que lida com @PostMapping("/filter")
|
|
496
552
|
|
|
497
553
|
activate Abstract_Controller
|
|
498
|
-
Abstract_Controller->>Abstract_Controller: Processa a
|
|
554
|
+
Abstract_Controller->>Abstract_Controller: Processa a requisição e busca os dados
|
|
499
555
|
Abstract_Controller-->>BE_Controller: Retorna os dados
|
|
500
556
|
deactivate Abstract_Controller
|
|
501
557
|
|
|
@@ -512,21 +568,21 @@ sequenceDiagram
|
|
|
512
568
|
|
|
513
569
|
Notas importantes:
|
|
514
570
|
|
|
515
|
-
- O host informa `resourcePath` sem o prefixo `/api`; o `GenericCrudService` resolve as URLs reais do backend a partir da
|
|
516
|
-
- O bootstrap de schema
|
|
571
|
+
- O host informa `resourcePath` sem o prefixo `/api`; o `GenericCrudService` resolve as URLs reais do backend a partir da configuração de API do host.
|
|
572
|
+
- O bootstrap de schema não depende mais de uma chamada frontend para `GET /{resource}/schemas`; o runtime consome diretamente `/schemas/filtered` com `ETag`/`X-Schema-Hash`.
|
|
517
573
|
- O `praxis-filter` acoplado acompanha o mesmo `resourcePath` em modo remoto e deriva seu schema via `/schemas/filtered?path=.../filter&operation=post&schemaType=request`.
|
|
518
|
-
- Sem `resourcePath` efetivo, a tabela
|
|
574
|
+
- Sem `resourcePath` efetivo, a tabela não entra nesse fluxo remoto; ela cai em `local` ou `empty` conforme a precedência canônica.
|
|
519
575
|
|
|
520
|
-
##
|
|
576
|
+
## â„¹ï¸ Dicas de UX (Tabela)
|
|
521
577
|
|
|
522
|
-
- Multi
|
|
523
|
-
- Duplo clique na linha: configure em Comportamento
|
|
524
|
-
-
|
|
525
|
-
- Densidade e linhas de grade: ajuste em Comportamento
|
|
578
|
+
- Multi‑sort: habilite em Comportamento → Ordenação. No uso, mantenha Ctrl/Cmd pressionado ao clicar em múltiplas colunas.
|
|
579
|
+
- Duplo clique na linha: configure em Comportamento → Interação (habilitar e escolha a ação: editar/visualizar/personalizada).
|
|
580
|
+
- Virtualização: habilite em Comportamento → Virtualização para listas grandes (requer altura de linha previsÃvel).
|
|
581
|
+
- Densidade e linhas de grade: ajuste em Comportamento → Aparência rápida (compacta/confortável/espaçosa; bordas horizontais/verticais).
|
|
526
582
|
|
|
527
583
|
## Rolagem Horizontal (owner do scroll)
|
|
528
584
|
|
|
529
|
-
Por
|
|
585
|
+
Por padrão, a `<praxis-table>` agora assume a responsabilidade pela rolagem horizontal quando o conteúdo excede a largura do container. Isso evita cortes de conteúdo e comportamentos inconsistentes entre projetos.
|
|
530
586
|
|
|
531
587
|
### Input: `horizontalScroll`
|
|
532
588
|
|
|
@@ -534,17 +590,17 @@ Por padrão, a `<praxis-table>` agora assume a responsabilidade pela rolagem hor
|
|
|
534
590
|
@Input() horizontalScroll: 'auto' | 'wrap' | 'none' = 'auto';
|
|
535
591
|
```
|
|
536
592
|
|
|
537
|
-
- `auto` (
|
|
538
|
-
- `wrap`: permite quebra de linha nas
|
|
539
|
-
- `none`: desabilita o comportamento interno; o host (
|
|
593
|
+
- `auto` (padrão): a tabela cria um viewport com `overflow-x: auto` e permite que a tabela interna cresça com `width: max-content`. Quando a soma das colunas > container, aparece a barra de rolagem horizontal neste viewport.
|
|
594
|
+
- `wrap`: permite quebra de linha nas células (libera `white-space: normal`), reduzindo a largura necessária; ideal quando você prefere minimizar a rolagem horizontal.
|
|
595
|
+
- `none`: desabilita o comportamento interno; o host (página) deve fornecer o container com `overflow-x: auto` e as regras de largura necessárias.
|
|
540
596
|
|
|
541
597
|
Exemplo:
|
|
542
598
|
|
|
543
599
|
```html
|
|
544
|
-
<!-- Comportamento
|
|
600
|
+
<!-- Comportamento padrão (auto) -->
|
|
545
601
|
<praxis-table resourcePath="employees"></praxis-table>
|
|
546
602
|
|
|
547
|
-
<!-- Reduz rolagem: permite quebra de linha nas
|
|
603
|
+
<!-- Reduz rolagem: permite quebra de linha nas células -->
|
|
548
604
|
<praxis-table resourcePath="employees" horizontalScroll="wrap"></praxis-table>
|
|
549
605
|
|
|
550
606
|
<!-- Host controla o scroll horizontal -->
|
|
@@ -554,28 +610,28 @@ Exemplo:
|
|
|
554
610
|
</div>
|
|
555
611
|
```
|
|
556
612
|
|
|
557
|
-
### Editor de
|
|
613
|
+
### Editor de Configuração (Settings Panel)
|
|
558
614
|
|
|
559
|
-
Na aba
|
|
615
|
+
Na aba “Visão Geral & Comportamentoâ€, há um seletor “Scroll Horizontal†com as opções `Auto`, `Wrap` e `Host` (none). As alterações podem ser aplicadas (Aplicar) ou salvas (Salvar & Fechar). O valor é persistido junto com outras preferências da tabela.
|
|
560
616
|
|
|
561
617
|
### Notas
|
|
562
618
|
|
|
563
|
-
- O caminho virtual (CDK Virtual Scroll) permanece sendo o owner da rolagem vertical; o viewport horizontal
|
|
564
|
-
-
|
|
619
|
+
- O caminho virtual (CDK Virtual Scroll) permanece sendo o owner da rolagem vertical; o viewport horizontal é um contêiner externo que não interfere no scroll vertical.
|
|
620
|
+
- Cabeçalho sticky continua funcional. Teste combinações com colunas sticky/virt para seu caso.
|
|
565
621
|
- Para grids alternativos (ex.: Kendo), as mesmas regras de `max-content`/`min-width: 100%` se aplicam ao elemento de tabela interno.
|
|
566
622
|
|
|
567
|
-
##
|
|
623
|
+
## Virtualização (CDK)
|
|
568
624
|
|
|
569
|
-
Quando `behavior.virtualization.enabled` estiver ativo, as linhas da tabela
|
|
625
|
+
Quando `behavior.virtualization.enabled` estiver ativo, as linhas da tabela são renderizadas com `cdk-virtual-scroll-viewport` (cabeçalho permanece igual).
|
|
570
626
|
|
|
571
627
|
- Propriedades:
|
|
572
|
-
- `itemHeight`: altura da linha (px);
|
|
628
|
+
- `itemHeight`: altura da linha (px); padrão 44.
|
|
573
629
|
- `bufferSize`: itens adicionais de buffer.
|
|
574
|
-
- `minContainerHeight`: altura
|
|
575
|
-
- `strategy`: `fixed` | `dynamic` (atual uso visual
|
|
576
|
-
-
|
|
630
|
+
- `minContainerHeight`: altura mÃnima do viewport (px ou CSS, ex.: `320` ou `50vh`).
|
|
631
|
+
- `strategy`: `fixed` | `dynamic` (atual uso visual não altera lógica de medição).
|
|
632
|
+
- Observação: sticky/pinned em colunas pode ter limitações em conjunto com virtual scroll (mantido sob feature flag; caminho não‑virtual preservado como fallback).
|
|
577
633
|
|
|
578
|
-
##
|
|
634
|
+
## Paginação (posição/estilo)
|
|
579
635
|
|
|
580
636
|
### Concept Usage
|
|
581
637
|
|
|
@@ -587,16 +643,16 @@ Quando `behavior.virtualization.enabled` estiver ativo, as linhas da tabela são
|
|
|
587
643
|
- `behavior.pagination.position`: `top` | `bottom` | `both`.
|
|
588
644
|
- `behavior.pagination.style`: `default` | `compact` (aplica classe de estilo no paginator).
|
|
589
645
|
|
|
590
|
-
Nota sobre
|
|
591
|
-
- Se `behavior.pagination.strategy`
|
|
646
|
+
Nota sobre estratégia (client vs server)
|
|
647
|
+
- Se `behavior.pagination.strategy` não estiver definido, a tabela assume `server` automaticamente quando há `resourcePath` (dados remotos). Caso contrário, usa `client`.
|
|
592
648
|
- O mesmo vale para `behavior.sorting.strategy`.
|
|
593
649
|
|
|
594
650
|
## Duplo clique na linha
|
|
595
651
|
|
|
596
|
-
Ative em Comportamento
|
|
652
|
+
Ative em Comportamento → Interação.
|
|
597
653
|
|
|
598
654
|
- Output: `rowDoubleClick` com payload `{ action: string; row: any }`.
|
|
599
|
-
-
|
|
655
|
+
- Ação: `edit` | `view` | `custom` (quando `custom`, use `customAction` no Behavior para definir o identificador).
|
|
600
656
|
|
|
601
657
|
Exemplo de uso (template do host):
|
|
602
658
|
|
|
@@ -615,16 +671,16 @@ onRowDoubleClick(evt: { action: string; row: any }) {
|
|
|
615
671
|
} else if (evt.action === 'view') {
|
|
616
672
|
// abrir detalhe somente leitura
|
|
617
673
|
} else {
|
|
618
|
-
//
|
|
674
|
+
// ação customizada
|
|
619
675
|
}
|
|
620
676
|
}
|
|
621
677
|
```
|
|
622
678
|
|
|
623
|
-
##
|
|
679
|
+
## Ordenação inicial (defaultSort)
|
|
624
680
|
|
|
625
681
|
- Configure em `behavior.sorting.defaultSort`.
|
|
626
|
-
- Aceita objeto
|
|
627
|
-
- Status runtime atual: `behavior.sorting.multiSort`
|
|
682
|
+
- Aceita objeto único (coluna/direção) ou array para multi‑sort.
|
|
683
|
+
- Status runtime atual: `behavior.sorting.multiSort` está **schema-only** (apenas 1 critério efetivo em runtime).
|
|
628
684
|
|
|
629
685
|
Exemplos:
|
|
630
686
|
|
|
@@ -649,20 +705,20 @@ sorting: {
|
|
|
649
705
|
}
|
|
650
706
|
```
|
|
651
707
|
|
|
652
|
-
|
|
653
|
-
|
|
708
|
+
Observação: quando informado, o defaultSort é aplicado na carga inicial se não houver estado de ordenação ativo.
|
|
709
|
+
Observação enterprise: para evitar ambiguidade de contrato, mantenha `multiSort: false` no runtime atual. Se um array for informado em `defaultSort`, trate como payload de compatibilidade/roadmap e valide no host como single-sort efetivo.
|
|
654
710
|
|
|
655
|
-
### Roadmap /
|
|
711
|
+
### Roadmap / migração de multiSort
|
|
656
712
|
|
|
657
713
|
- Curto prazo: `multiSort` segue schema-only no runtime.
|
|
658
|
-
-
|
|
659
|
-
- Planejamento: quando multi-sort runtime for implementado, publicar release note com guia de
|
|
714
|
+
- Recomendação de migração: desenhar integrações com fallback para ordenação única (`column` + `direction`).
|
|
715
|
+
- Planejamento: quando multi-sort runtime for implementado, publicar release note com guia de ativação gradual (feature-flag + validação de payload legado).
|
|
660
716
|
|
|
661
|
-
## Coluna de
|
|
717
|
+
## Coluna de ações (sticky)
|
|
662
718
|
|
|
663
|
-
Nota: por
|
|
719
|
+
Nota: por padrão a coluna de ações vem desabilitada. Habilite explicitamente em `actions.row.enabled` e defina as ações desejadas.
|
|
664
720
|
|
|
665
|
-
- Fixe a coluna de
|
|
721
|
+
- Fixe a coluna de ações no inÃcio/fim configurando `actions.row.sticky`:
|
|
666
722
|
|
|
667
723
|
```ts
|
|
668
724
|
actions: {
|
|
@@ -675,11 +731,11 @@ actions: {
|
|
|
675
731
|
}
|
|
676
732
|
```
|
|
677
733
|
|
|
678
|
-
|
|
734
|
+
Observação: em modo virtualizado, sticky pode ter limitações dependendo do layout.
|
|
679
735
|
|
|
680
736
|
## Colunas de dados (sticky)
|
|
681
737
|
|
|
682
|
-
Fixe colunas
|
|
738
|
+
Fixe colunas especÃficas no inÃcio/fim usando `columns[].sticky`:
|
|
683
739
|
|
|
684
740
|
```ts
|
|
685
741
|
columns: [
|
|
@@ -690,28 +746,28 @@ columns: [
|
|
|
690
746
|
```
|
|
691
747
|
|
|
692
748
|
- Valores aceitos: `true` | `'start'` | `'end'`.
|
|
693
|
-
- `true` equivale a `'start'` (fixa no
|
|
749
|
+
- `true` equivale a `'start'` (fixa no inÃcio).
|
|
694
750
|
- Dica: combine com `width` para evitar jitter de layout.
|
|
695
751
|
|
|
696
752
|
Onde configurar no Editor Visual:
|
|
697
753
|
|
|
698
|
-
- Aba
|
|
699
|
-
- Para a coluna de
|
|
754
|
+
- Aba “Colunas†→ grupo “Posição Fixaâ€: escolha entre Nenhum / InÃcio / Fim.
|
|
755
|
+
- Para a coluna de ações, use a aba “Barra de Ferramentas & Ações†→ grupo “Coluna de Ações†→ “Fixar coluna de açõesâ€.
|
|
700
756
|
|
|
701
|
-
##
|
|
757
|
+
## 🔒 Verificação de Schema (ETag) e Notificações (somente em customização)
|
|
702
758
|
|
|
703
|
-
Quando
|
|
759
|
+
Quando já existe uma configuração salva (colunas presentes), a tabela não baixa o schema bruto do servidor para montar as colunas. Em vez disso, valida se há uma nova versão do schema usando ETag/If-None-Match. Notificações são exibidas somente quando o modo de customização está ativo (`enableCustomization = true`).
|
|
704
760
|
|
|
705
761
|
### Comportamento
|
|
706
762
|
|
|
707
763
|
- Primeira vez (sem colunas):
|
|
708
764
|
- Baixa o schema (200), gera as colunas e persiste `config.meta` (incluindo `schemaId`, `serverHash`, `lastVerifiedAt`).
|
|
709
|
-
-
|
|
710
|
-
- Faz uma
|
|
711
|
-
- 304 Not Modified: atualiza `config.meta.lastVerifiedAt` e segue usando a
|
|
712
|
-
- 200 OK (hash mudou): atualiza `config.meta.serverHash/lastVerifiedAt`, marca estado `schemaOutdated=true` e (em modo de
|
|
765
|
+
- Próximas vezes (colunas já existentes):
|
|
766
|
+
- Faz uma verificação leve em `/schemas/filtered` com `If-None-Match: "<serverHash>"`.
|
|
767
|
+
- 304 Not Modified: atualiza `config.meta.lastVerifiedAt` e segue usando a configuração local.
|
|
768
|
+
- 200 OK (hash mudou): atualiza `config.meta.serverHash/lastVerifiedAt`, marca estado `schemaOutdated=true` e (em modo de customização) exibe aviso e CTA para reconciliar. O schema bruto não é usado/armazenado nesta etapa.
|
|
713
769
|
|
|
714
|
-
### Diagrama:
|
|
770
|
+
### Diagrama: Verificação de Schema via ETag
|
|
715
771
|
|
|
716
772
|
```mermaid
|
|
717
773
|
sequenceDiagram
|
|
@@ -728,15 +784,15 @@ sequenceDiagram
|
|
|
728
784
|
PT->>PT: Persiste config + meta (serverHash, lastVerifiedAt)
|
|
729
785
|
end
|
|
730
786
|
|
|
731
|
-
opt
|
|
787
|
+
opt Próximas vezes (colunas existentes)
|
|
732
788
|
PT->>API: GET /schemas/filtered?path=... (If-None-Match: "<serverHash>")
|
|
733
|
-
alt Igual (sem
|
|
789
|
+
alt Igual (sem mudanças)
|
|
734
790
|
API-->>PT: 304 Not Modified (sem body)
|
|
735
791
|
PT->>PT: Atualiza lastVerifiedAt; segue usando config
|
|
736
792
|
else Diferente (mudou)
|
|
737
793
|
API-->>PT: 200 OK (com ETag/X-Schema-Hash)
|
|
738
794
|
PT->>PT: Atualiza serverHash + lastVerifiedAt; schemaOutdated=true
|
|
739
|
-
Note over PT: Em
|
|
795
|
+
Note over PT: Em customização: mostrar banner/snackbar + badge e CTA “Reconciliarâ€
|
|
740
796
|
end
|
|
741
797
|
end
|
|
742
798
|
```
|
|
@@ -749,30 +805,30 @@ sequenceDiagram
|
|
|
749
805
|
- `autoOpenSettingsOnOutdated: boolean = false`
|
|
750
806
|
- Outputs:
|
|
751
807
|
- `schemaStatusChange: { outdated: boolean; serverHash?: string; lastVerifiedAt?: string; trigger?: string; tableId?: string }`
|
|
752
|
-
- Emitido tanto na
|
|
808
|
+
- Emitido tanto na verificação leve (304/200) quanto no bootstrap do schema (primeira carga via `loadSchema()`).
|
|
753
809
|
- `metadataChange: { trigger: string; meta: any; tableId?: string }`
|
|
754
|
-
- Emitido quando `config.meta`
|
|
810
|
+
- Emitido quando `config.meta` é atualizado (ex.: após bootstrap ou verificação ETag). Útil para sincronizar sidebars/bridges de metadados.
|
|
755
811
|
|
|
756
812
|
### Fallback Global (opcional)
|
|
757
813
|
|
|
758
|
-
- Quando os inputs do widget permanecem com os valores
|
|
759
|
-
- Cadeia de
|
|
760
|
-
-
|
|
814
|
+
- Quando os inputs do widget permanecem com os valores padrão da biblioteca e não há overrides locais equivalentes, a Tabela aplica como último fallback as preferências globais lidas via `GlobalConfigService.getSchemaPrefsGlobal()`.
|
|
815
|
+
- Cadeia de precedência (inalterada): `@Inputs (widget)` → Prefs do widget → Prefs da página → Prefs globais → Defaults.
|
|
816
|
+
- Não há persistência no widget a partir das globais; o fallback é aplicado somente em memória.
|
|
761
817
|
|
|
762
|
-
###
|
|
818
|
+
### Persistência por hash (ConfigStorage)
|
|
763
819
|
|
|
764
|
-
- `schemaIgnore:{tableId}:{serverHash}`
|
|
765
|
-
- `schemaSnooze:{tableId}:{serverHash}`
|
|
766
|
-
- `schemaNotified:{tableId}:{serverHash}`
|
|
820
|
+
- `schemaIgnore:{tableId}:{serverHash}` → ignora avisos para este hash.
|
|
821
|
+
- `schemaSnooze:{tableId}:{serverHash}` → ISODate até quando não avisar (lembrar depois).
|
|
822
|
+
- `schemaNotified:{tableId}:{serverHash}` → evita snackbar duplicado.
|
|
767
823
|
|
|
768
824
|
### UX
|
|
769
825
|
|
|
770
|
-
- Banner inline (acima da tabela) quando `schemaOutdated=true`, com
|
|
771
|
-
- Reconciliar (abre
|
|
826
|
+
- Banner inline (acima da tabela) quando `schemaOutdated=true`, com ações:
|
|
827
|
+
- Reconciliar (abre Configurações)
|
|
772
828
|
- Lembrar depois (snooze)
|
|
773
829
|
- Ignorar (silenciar para este hash)
|
|
774
|
-
- Snackbar opcional (uma vez por hash) com
|
|
775
|
-
- Badge
|
|
830
|
+
- Snackbar opcional (uma vez por hash) com ação “Reconciliarâ€.
|
|
831
|
+
- Badge “!†na engrenagem com tooltip contextual: “Schema do servidor mudou — Reconciliarâ€.
|
|
776
832
|
|
|
777
833
|
### Exemplo de uso
|
|
778
834
|
|
|
@@ -798,56 +854,56 @@ onSchemaStatus(ev: { outdated: boolean; serverHash?: string; lastVerifiedAt?: st
|
|
|
798
854
|
|
|
799
855
|
### Notas
|
|
800
856
|
|
|
801
|
-
- A
|
|
802
|
-
- Em ambientes sem
|
|
857
|
+
- A verificação leve não grava nem usa o schema bruto quando `config.columns` já existe.
|
|
858
|
+
- Em ambientes sem customização (`enableCustomization=false`), não há notificações visuais; ainda assim `schemaStatusChange` é emitido e `config.meta.lastVerifiedAt` atualizado.
|
|
803
859
|
|
|
804
|
-
## Filtro
|
|
860
|
+
## Filtro Avançado (PraxisFilter)
|
|
805
861
|
|
|
806
|
-
### Boas
|
|
862
|
+
### Boas práticas para estabilidade
|
|
807
863
|
|
|
808
|
-
- Evite literais em bindings para o carregador
|
|
809
|
-
-
|
|
810
|
-
- Reutilize `FormGroup` quando
|
|
811
|
-
- Evite recriar arrays/objetos desnecessariamente em `ngOnChanges`/`ngAfterViewInit`. Prefira atualizar valores (`setValue`, `patchValue`) e manter
|
|
812
|
-
- Observers (Resize/Mutation): atualize `overlayOrigin` e largura apenas quando houver
|
|
864
|
+
- Evite literais em bindings para o carregador dinâmico:
|
|
865
|
+
- Não use `[fields]="[pinnedFieldMeta]"`; prefira um array estável como `pinnedFieldMetaArray` atualizado apenas quando o metadata mudar.
|
|
866
|
+
- Reutilize `FormGroup` quando possÃvel. Se precisar trocar o `FormGroup` sem mudar os campos, deixe o `DynamicFieldLoader` reatribuir os controles (rebind-only) em vez de recriar componentes.
|
|
867
|
+
- Evite recriar arrays/objetos desnecessariamente em `ngOnChanges`/`ngAfterViewInit`. Prefira atualizar valores (`setValue`, `patchValue`) e manter referências estáveis.
|
|
868
|
+
- Observers (Resize/Mutation): atualize `overlayOrigin` e largura apenas quando houver mudanças reais; isso evita loops de CD.
|
|
813
869
|
|
|
814
|
-
###
|
|
870
|
+
### Diagnóstico e Logs
|
|
815
871
|
|
|
816
|
-
- O `DynamicFieldLoader` possui logs de
|
|
872
|
+
- O `DynamicFieldLoader` possui logs de diagnóstico que podem ser habilitados em tempo de execução definindo `window.__PRAXIS_DEBUG_DFL__ = true` no console do navegador.
|
|
817
873
|
- Quando desabilitado (default), o carregador reduz a verbosidade de logs.
|
|
818
874
|
|
|
819
875
|
### Comportamento do carregador (v20+)
|
|
820
876
|
|
|
821
|
-
- Guardas internas evitam re-
|
|
822
|
-
- Se o snapshot do
|
|
823
|
-
- Se apenas o `FormGroup` mudou (mesmo snapshot de campos), os controles
|
|
877
|
+
- Guardas internas evitam re-renderizações desnecessárias:
|
|
878
|
+
- Se o snapshot do conteúdo dos campos (nome + controlType) for idêntico e o `FormGroup` não tiver mudado, a renderização é ignorada.
|
|
879
|
+
- Se apenas o `FormGroup` mudou (mesmo snapshot de campos), os controles são reatribuÃdos aos componentes existentes (rebind-only), preservando o estado visual e evitando recriações.
|
|
824
880
|
|
|
825
881
|
### Testes
|
|
826
882
|
|
|
827
|
-
-
|
|
828
|
-
-
|
|
829
|
-
- Ignorar re-render quando apenas a
|
|
883
|
+
- Há testes cobrindo:
|
|
884
|
+
- Reatribuição de `FormControl` em troca de `FormGroup` (select/multiselect/autocomplete).
|
|
885
|
+
- Ignorar re-render quando apenas a referência do array muda mas o conteúdo é igual.
|
|
830
886
|
- Recriar componentes quando `controlType` muda.
|
|
831
887
|
|
|
832
888
|
### Fluxo de Schema e Metadados
|
|
833
889
|
|
|
834
890
|
- O `PraxisFilter` busca schema do DTO de filtro via `/schemas/filtered` com ETag/If-None-Match
|
|
835
891
|
e emite `metaChanged` com `{ schemaId, serverHash, context }`.
|
|
836
|
-
- O schema
|
|
837
|
-
- Detalhes: `projects/praxis-core/docs/schema-flow.md` (
|
|
892
|
+
- O schema é normalizado e `advancedConfig.metadata` é preenchido para auditoria/telemetria.
|
|
893
|
+
- Detalhes: `projects/praxis-core/docs/schema-flow.md` (canônico) e `docs/schemas/fluxo-schema.md` (resumo operacional) para cliente/caching, 200/304 e reconciliadores Form/Filter.
|
|
838
894
|
|
|
839
|
-
###
|
|
895
|
+
### Resolução da chave primária (idField)
|
|
840
896
|
|
|
841
897
|
- O backend anota o schema com `x-ui.resource.idField` (e `idFieldValid`) via `/schemas/filtered`.
|
|
842
|
-
- A tabela adota o campo identificador automaticamente com a seguinte
|
|
843
|
-
- `@Input() idField`
|
|
844
|
-
- Se `config.meta.idField` divergir do servidor, o componente alerta o
|
|
845
|
-
- A
|
|
846
|
-
- Para recursos cuja PK
|
|
898
|
+
- A tabela adota o campo identificador automaticamente com a seguinte precedência:
|
|
899
|
+
- `@Input() idField` → `crudContext.idField` → `config.meta.idField` (persistido) → `GenericCrudService.getResourceIdField()` (derivado do schema) → `'id'`.
|
|
900
|
+
- Se `config.meta.idField` divergir do servidor, o componente alerta o usuário e mantém o valor do TableConfig até reconciliação.
|
|
901
|
+
- A resolução ocorre no `loadSchema()` e também é considerada em tempo de execução para evitar corridas.
|
|
902
|
+
- Para recursos cuja PK não é `id`, defina `getIdFieldName()` no controller backend correspondente.
|
|
847
903
|
|
|
848
904
|
### Diagramas
|
|
849
905
|
|
|
850
|
-
Fluxo (Grid):
|
|
906
|
+
Fluxo (Grid): adoção de schema e idField
|
|
851
907
|
|
|
852
908
|
```mermaid
|
|
853
909
|
sequenceDiagram
|
|
@@ -867,7 +923,7 @@ sequenceDiagram
|
|
|
867
923
|
PT->>PT: construir colunas e renderizar
|
|
868
924
|
```
|
|
869
925
|
|
|
870
|
-
Fluxo (Delete):
|
|
926
|
+
Fluxo (Delete): resolução do identificador
|
|
871
927
|
|
|
872
928
|
```mermaid
|
|
873
929
|
sequenceDiagram
|
|
@@ -876,7 +932,7 @@ sequenceDiagram
|
|
|
876
932
|
participant GS as GenericCrudService
|
|
877
933
|
participant API as Backend
|
|
878
934
|
|
|
879
|
-
PT->>PT: key = getIdField() (
|
|
935
|
+
PT->>PT: key = getIdField() (precedência)
|
|
880
936
|
PT->>PT: id = getNestedPropertyValue(row, key)
|
|
881
937
|
PT->>GS: delete(id)
|
|
882
938
|
GS->>API: DELETE {resource}/{id}
|
|
@@ -885,17 +941,17 @@ sequenceDiagram
|
|
|
885
941
|
PT->>PT: fetchData() em modo remoto
|
|
886
942
|
```
|
|
887
943
|
|
|
888
|
-
### Troubleshooting
|
|
944
|
+
### Troubleshooting rápido (idField)
|
|
889
945
|
|
|
890
|
-
- A
|
|
891
|
-
- O ID
|
|
892
|
-
- Cache 304 sem idField aplicado: confirme que o
|
|
946
|
+
- A ação delete falhou por ID ausente: verifique se o schema contém `x-ui.resource.idField` e se a coluna correspondente existe no dataset.
|
|
947
|
+
- O ID está em outra propriedade: defina `@Input() idField` ou `crudContext.idField` temporariamente; ajuste o backend com `getIdFieldName()` para persistir o comportamento.
|
|
948
|
+
- Cache 304 sem idField aplicado: confirme que o serviço recebeu o body pelo menos uma vez (200) e que `GenericCrudService.getResourceIdField()` retorna o valor esperado.
|
|
893
949
|
|
|
894
950
|
### Uso com Dados Locais (Client-Side)
|
|
895
951
|
|
|
896
|
-
Se
|
|
897
|
-
Importante: o modo local
|
|
898
|
-
Quando a flag
|
|
952
|
+
Se você precisar fornecer os dados manualmente (por exemplo, de uma fonte que não é uma API Praxis), pode usar o input `[data]` e omitir o `resourcePath`.
|
|
953
|
+
Importante: o modo local está protegido por feature flag e exige `behavior.localDataMode.enabled = true` (default é `false`).
|
|
954
|
+
Quando a flag está ativa, as operações de paginação, ordenação e filtro são executadas no lado do cliente.
|
|
899
955
|
|
|
900
956
|
```typescript
|
|
901
957
|
import { PraxisTable } from "@praxisui/table";
|
|
@@ -908,7 +964,7 @@ import { TableConfig } from "@praxisui/core";
|
|
|
908
964
|
template: ` <praxis-table [config]="tableConfig" [data]="employees"> </praxis-table> `,
|
|
909
965
|
})
|
|
910
966
|
export class ExampleComponent {
|
|
911
|
-
//
|
|
967
|
+
// Configuração de colunas e comportamento é obrigatória neste modo
|
|
912
968
|
tableConfig: TableConfig = {
|
|
913
969
|
columns: [
|
|
914
970
|
{ field: "id", header: "ID", type: "number" },
|
|
@@ -919,57 +975,57 @@ export class ExampleComponent {
|
|
|
919
975
|
pagination: { enabled: true, pageSize: 10 },
|
|
920
976
|
sorting: { enabled: true },
|
|
921
977
|
filtering: { enabled: true },
|
|
922
|
-
localDataMode: { enabled: true }, //
|
|
978
|
+
localDataMode: { enabled: true }, // obrigatório para fluxo local oficial
|
|
923
979
|
},
|
|
924
980
|
};
|
|
925
981
|
|
|
926
982
|
employees = [
|
|
927
|
-
{ id: 1, name: "
|
|
983
|
+
{ id: 1, name: "João Silva", email: "joao@empresa.com" },
|
|
928
984
|
{ id: 2, name: "Maria Santos", email: "maria@empresa.com" },
|
|
929
985
|
// ... mais dados
|
|
930
986
|
];
|
|
931
987
|
}
|
|
932
988
|
```
|
|
933
989
|
|
|
934
|
-
##
|
|
990
|
+
## âš™ï¸ Fluxo de Paginação e Filtros (Server-Side)
|
|
935
991
|
|
|
936
|
-
Quando a `<praxis-table>` opera com `resourcePath`, o runtime resolve o modo remoto e passa a delegar
|
|
992
|
+
Quando a `<praxis-table>` opera com `resourcePath`, o runtime resolve o modo remoto e passa a delegar paginação, ordenação e filtros ao backend. Isso reduz tráfego, preserva a semântica do DTO de filtro e mantém o banco como fonte de verdade para `WHERE`, `ORDER BY`, `LIMIT` e `OFFSET`.
|
|
937
993
|
|
|
938
|
-
Importante: se
|
|
994
|
+
Importante: se você não configurar explicitamente as estratégias de paginação/ordenação no `TableConfig`, a tabela resolve automaticamente como `server` quando há `resourcePath`. Se preferir operar no cliente, defina `behavior.pagination.strategy = 'client'` e/ou `behavior.sorting.strategy = 'client'` conscientemente.
|
|
939
995
|
|
|
940
|
-
###
|
|
996
|
+
### Versão Pedagógica de Alto NÃvel
|
|
941
997
|
|
|
942
|
-
Esta
|
|
998
|
+
Esta é a leitura adequada para documentação pública e landing pages.
|
|
943
999
|
|
|
944
1000
|
```mermaid
|
|
945
1001
|
sequenceDiagram
|
|
946
|
-
participant Usuario as
|
|
1002
|
+
participant Usuario as Usuário
|
|
947
1003
|
participant Tabela as praxis-table
|
|
948
1004
|
participant Frontend as GenericCrudService
|
|
949
1005
|
participant Backend as API Praxis
|
|
950
1006
|
participant Banco as Banco de Dados
|
|
951
1007
|
|
|
952
|
-
Usuario->>Tabela: muda
|
|
953
|
-
Tabela->>Tabela: consolida filterCriteria +
|
|
1008
|
+
Usuario->>Tabela: muda página, ordena ou aplica filtro
|
|
1009
|
+
Tabela->>Tabela: consolida filterCriteria + paginação + sort
|
|
954
1010
|
Tabela->>Frontend: filter(criteria, pageable)
|
|
955
1011
|
Frontend->>Backend: POST /api/.../filter?page&size&sort
|
|
956
1012
|
Backend->>Banco: executa consulta filtrada e paginada
|
|
957
|
-
Banco-->>Backend: retorna
|
|
958
|
-
Backend-->>Frontend: responde com
|
|
1013
|
+
Banco-->>Backend: retorna página de resultados
|
|
1014
|
+
Backend-->>Frontend: responde com página de DTOs
|
|
959
1015
|
Frontend-->>Tabela: entrega Page<T>
|
|
960
|
-
Tabela->>Tabela: atualiza linhas,
|
|
1016
|
+
Tabela->>Tabela: atualiza linhas, paginação e estado visual
|
|
961
1017
|
```
|
|
962
1018
|
|
|
963
|
-
Leitura
|
|
1019
|
+
Leitura pedagógica:
|
|
964
1020
|
|
|
965
|
-
1. **A tabela captura a
|
|
966
|
-
2. **O frontend envia o DTO de filtro para o endpoint
|
|
967
|
-
3. **O backend aplica o filtro no conjunto remoto**:
|
|
968
|
-
4. **O resultado volta
|
|
1021
|
+
1. **A tabela captura a intenção do usuário**: página, ordenação e filtros viram estado de consulta.
|
|
1022
|
+
2. **O frontend envia o DTO de filtro para o endpoint canônico**: corpo JSON para filtro, query params para paginação e sort.
|
|
1023
|
+
3. **O backend aplica o filtro no conjunto remoto**: não é a UI que filtra localmente em modo remoto.
|
|
1024
|
+
4. **O resultado volta já paginado**: a tabela apenas renderiza a página retornada pela API.
|
|
969
1025
|
|
|
970
|
-
###
|
|
1026
|
+
### Versão Detalhada e Fiel ao Runtime Atual
|
|
971
1027
|
|
|
972
|
-
Esta
|
|
1028
|
+
Esta versão documenta o fluxo real do `praxis-table`, do `praxis-filter`, do `GenericCrudService` e do `praxis-metadata-starter`.
|
|
973
1029
|
|
|
974
1030
|
```mermaid
|
|
975
1031
|
sequenceDiagram
|
|
@@ -997,12 +1053,12 @@ sequenceDiagram
|
|
|
997
1053
|
Crud-->>Filtro: metadata de filtro
|
|
998
1054
|
end
|
|
999
1055
|
|
|
1000
|
-
alt
|
|
1056
|
+
alt paginação
|
|
1001
1057
|
Tabela->>Tabela: onPageChange(pageIndex, pageSize)
|
|
1002
|
-
else
|
|
1058
|
+
else ordenação
|
|
1003
1059
|
Tabela->>Tabela: onSortChange(active, direction)
|
|
1004
1060
|
Tabela->>Tabela: reseta pageIndex = 0
|
|
1005
|
-
else filtro
|
|
1061
|
+
else filtro avançado
|
|
1006
1062
|
Filtro-->>Tabela: submit/change/clear
|
|
1007
1063
|
Tabela->>Tabela: onAdvancedFilterSubmit(criteria)
|
|
1008
1064
|
end
|
|
@@ -1015,7 +1071,7 @@ sequenceDiagram
|
|
|
1015
1071
|
Crud->>Controller: POST /filter?page&size&sort
|
|
1016
1072
|
Note over Crud,Controller: body = filterCriteria JSON
|
|
1017
1073
|
|
|
1018
|
-
Controller->>Controller:
|
|
1074
|
+
Controller->>Controller: lê page,size,sort de query params
|
|
1019
1075
|
Controller->>Controller: PageableBuilder.from(page,size,sort,...)
|
|
1020
1076
|
Controller->>Service: filterMappedWithIncludeIds(filterDTO, pageable, includeIds, toDto)
|
|
1021
1077
|
|
|
@@ -1035,56 +1091,56 @@ sequenceDiagram
|
|
|
1035
1091
|
|
|
1036
1092
|
### Pontos-Chave do Fluxo Real
|
|
1037
1093
|
|
|
1038
|
-
1. **`resourcePath`
|
|
1039
|
-
2. **O filtro
|
|
1040
|
-
3. **O controller
|
|
1094
|
+
1. **`resourcePath` não dispara só fetch**: em modo remoto, a tabela primeiro configura o `GenericCrudService` e pode carregar schema antes da primeira busca.
|
|
1095
|
+
2. **O filtro avançado vive em `praxis-filter`**: os eventos reais são `submit`, `change` e `clear`, que a tabela recebe como `onAdvancedFilterSubmit`, `onAdvancedFilterChange` e `onAdvancedFilterClear`.
|
|
1096
|
+
3. **O controller não recebe `Pageable` pronto do Spring nesse endpoint**: ele reconstrói o `Pageable` a partir de `page`, `size` e `sort`.
|
|
1041
1097
|
4. **O backend do starter responde com `RestApiResponse<Page<...>>`**: o `GenericCrudService` faz `unwrapPageResponse(...)` para entregar `Page<T>` ao runtime da tabela.
|
|
1042
|
-
5. **A coluna ordenada pode mapear para `sortField`**: o `active` da UI
|
|
1098
|
+
5. **A coluna ordenada pode mapear para `sortField`**: o `active` da UI não é necessariamente o campo final enviado ao backend.
|
|
1043
1099
|
|
|
1044
|
-
##
|
|
1100
|
+
## 🎨 Edição Visual da Tabela: O Poder do Low-Code
|
|
1045
1101
|
|
|
1046
|
-
A `<praxis-table>` vem com um poderoso editor de
|
|
1102
|
+
A `<praxis-table>` vem com um poderoso editor de configuração visual que permite personalizar quase todos os aspectos da sua tabela em tempo real, sem escrever uma única linha de código. O runtime expõe esse editor somente quando o host ativa `[enableCustomization]="true"`.
|
|
1047
1103
|
|
|
1048
|
-
A seguir, veja os principais recursos que
|
|
1104
|
+
A seguir, veja os principais recursos que você pode configurar visualmente:
|
|
1049
1105
|
|
|
1050
1106
|
### 1. Gerenciamento de Colunas
|
|
1051
1107
|
|
|
1052
|
-
Controle total sobre as colunas da sua tabela. Dentro do editor,
|
|
1108
|
+
Controle total sobre as colunas da sua tabela. Dentro do editor, você pode:
|
|
1053
1109
|
|
|
1054
|
-
- **Reordenar com Arrastar e Soltar:** Simplesmente clique e arraste uma coluna para a
|
|
1055
|
-
- **Alterar Visibilidade:** Use a caixa de
|
|
1056
|
-
- **Editar
|
|
1110
|
+
- **Reordenar com Arrastar e Soltar:** Simplesmente clique e arraste uma coluna para a posição desejada.
|
|
1111
|
+
- **Alterar Visibilidade:** Use a caixa de seleção ao lado de cada coluna para mostrá-la ou ocultá-la instantaneamente.
|
|
1112
|
+
- **Editar TÃtulos e Largura:** Clique em uma coluna para abrir suas propriedades e altere o texto do cabeçalho, defina uma largura fixa (ex: `150px`) ou deixe-a automática.
|
|
1057
1113
|
|
|
1058
|
-
### 2.
|
|
1114
|
+
### 2. Transformação de Dados Sem Código
|
|
1059
1115
|
|
|
1060
|
-
Converta dados brutos em
|
|
1116
|
+
Converta dados brutos em informações claras e formatadas para o usuário.
|
|
1061
1117
|
|
|
1062
|
-
- **
|
|
1063
|
-
- **Mapeamento de Valores:** Transforme
|
|
1118
|
+
- **Formatação Automática:** Selecione uma coluna e escolha seu "Tipo de Dado". Se escolher `Moeda`, os valores serão formatados como `R$ 1.234,56`. Se escolher `Data`, você pode selecionar formatos como `dd/MM/yyyy` ou `25 de janeiro de 2025`.
|
|
1119
|
+
- **Mapeamento de Valores:** Transforme códigos e valores brutos em texto legÃvel. Na seção "Mapeamento de Valores", você pode definir visualmente que o valor `true` deve ser exibido como "Ativo" e `false` como "Inativo", ou que o código `1` significa "Pendente" e `2` significa "Aprovado".
|
|
1064
1120
|
|
|
1065
|
-
### 3. Colunas Calculadas com
|
|
1121
|
+
### 3. Colunas Calculadas com Fórmulas Visuais
|
|
1066
1122
|
|
|
1067
1123
|
Crie novas colunas dinamicamente a partir de dados existentes, sem precisar programar.
|
|
1068
1124
|
|
|
1069
|
-
- **Concatenar Texto:** Crie uma "Coluna Calculada", escolha a
|
|
1070
|
-
- **Realizar
|
|
1071
|
-
- **Criar Valores Condicionais (IF/ELSE):** Com a
|
|
1125
|
+
- **Concatenar Texto:** Crie uma "Coluna Calculada", escolha a fórmula "Concatenar" e selecione os campos `nome` e `sobrenome` para criar uma coluna "Nome Completo".
|
|
1126
|
+
- **Realizar Operações Matemáticas:** Use a fórmula "Operação Matemática" para criar uma coluna que calcula `preço * quantidade`.
|
|
1127
|
+
- **Criar Valores Condicionais (IF/ELSE):** Com a fórmula "Condicional", você pode criar uma coluna "NÃvel de Risco" que exibe "Alto" se o `valor` for maior que 1000, e "Baixo" caso contrário.
|
|
1072
1128
|
|
|
1073
|
-
### 4.
|
|
1129
|
+
### 4. Formatação Condicional (Regras de Estilo)
|
|
1074
1130
|
|
|
1075
|
-
Destaque
|
|
1131
|
+
Destaque informações importantes aplicando estilos que mudam com base nos dados da linha.
|
|
1076
1132
|
|
|
1077
|
-
- **Crie Regras Visuais:** Na
|
|
1078
|
-
- **Defina a
|
|
1079
|
-
- **Aplique o Estilo:** Use seletores de cor para definir que, quando a
|
|
1133
|
+
- **Crie Regras Visuais:** Na seção de "Formatação Condicional", crie uma nova regra.
|
|
1134
|
+
- **Defina a Condição:** Estabeleça a condição, por exemplo: "Quando a coluna `status` tiver o valor igual a 'Urgente'".
|
|
1135
|
+
- **Aplique o Estilo:** Use seletores de cor para definir que, quando a condição for verdadeira, a cor de fundo da célula ou da linha inteira deve se tornar vermelha e o texto, branco.
|
|
1080
1136
|
|
|
1081
1137
|
### 5. Comportamentos da Tabela
|
|
1082
1138
|
|
|
1083
|
-
Habilite e configure as funcionalidades centrais da tabela com um clique. Na aba "Comportamento",
|
|
1139
|
+
Habilite e configure as funcionalidades centrais da tabela com um clique. Na aba "Comportamento", você pode:
|
|
1084
1140
|
|
|
1085
|
-
- **Ativar/Desativar
|
|
1086
|
-
- **Controlar
|
|
1087
|
-
- **Gerenciar
|
|
1141
|
+
- **Ativar/Desativar Paginação:** Com um único interruptor, ative a paginação para tabelas com muitos dados e defina quantos itens exibir por página.
|
|
1142
|
+
- **Controlar Ordenação e Filtros:** Habilite a capacidade dos usuários de ordenar colunas e filtrar os dados com simples caixas de seleção.
|
|
1143
|
+
- **Gerenciar Seleção de Linhas:** Permita que os usuários selecionem uma ou várias linhas para realizar ações em lote.
|
|
1088
1144
|
|
|
1089
1145
|
### Editores Especializados
|
|
1090
1146
|
|
|
@@ -1093,7 +1149,7 @@ Habilite e configure as funcionalidades centrais da tabela com um clique. Na aba
|
|
|
1093
1149
|
```typescript
|
|
1094
1150
|
import { BehaviorConfigEditorComponent } from '@praxisui/table';
|
|
1095
1151
|
|
|
1096
|
-
// Usar como componente standalone para
|
|
1152
|
+
// Usar como componente standalone para edição especÃfica
|
|
1097
1153
|
<behavior-config-editor
|
|
1098
1154
|
[config]="tableConfig"
|
|
1099
1155
|
(configChange)="onBehaviorChange($event)">
|
|
@@ -1112,9 +1168,9 @@ import { ColumnsConfigEditorComponent } from '@praxisui/table';
|
|
|
1112
1168
|
</columns-config-editor>
|
|
1113
1169
|
```
|
|
1114
1170
|
|
|
1115
|
-
##
|
|
1171
|
+
## 🔧 Configuração Avançada
|
|
1116
1172
|
|
|
1117
|
-
### Performance com
|
|
1173
|
+
### Performance com Virtualização
|
|
1118
1174
|
|
|
1119
1175
|
```typescript
|
|
1120
1176
|
const highVolumeConfig: TableConfig = {
|
|
@@ -1162,7 +1218,7 @@ const accessibleConfig: TableConfig = {
|
|
|
1162
1218
|
};
|
|
1163
1219
|
```
|
|
1164
1220
|
|
|
1165
|
-
###
|
|
1221
|
+
### Aparência Customizada
|
|
1166
1222
|
|
|
1167
1223
|
```typescript
|
|
1168
1224
|
const styledConfig: TableConfig = {
|
|
@@ -1195,7 +1251,7 @@ const styledConfig: TableConfig = {
|
|
|
1195
1251
|
};
|
|
1196
1252
|
```
|
|
1197
1253
|
|
|
1198
|
-
##
|
|
1254
|
+
## 🎯 Event Handling
|
|
1199
1255
|
|
|
1200
1256
|
### Eventos da Tabela
|
|
1201
1257
|
|
|
@@ -1213,7 +1269,7 @@ const styledConfig: TableConfig = {
|
|
|
1213
1269
|
</praxis-table>
|
|
1214
1270
|
```
|
|
1215
1271
|
|
|
1216
|
-
###
|
|
1272
|
+
### Implementação dos Handlers
|
|
1217
1273
|
|
|
1218
1274
|
```typescript
|
|
1219
1275
|
export class MyComponent {
|
|
@@ -1240,25 +1296,25 @@ export class MyComponent {
|
|
|
1240
1296
|
}
|
|
1241
1297
|
```
|
|
1242
1298
|
|
|
1243
|
-
##
|
|
1299
|
+
## ðŸ› ï¸ Utilitários e Helpers
|
|
1244
1300
|
|
|
1245
1301
|
### Helper Functions
|
|
1246
1302
|
|
|
1247
1303
|
```typescript
|
|
1248
1304
|
import { createDefaultTableConfig, isValidTableConfig, cloneTableConfig, mergeTableConfigs } from "@praxisui/core";
|
|
1249
1305
|
|
|
1250
|
-
// Criar
|
|
1306
|
+
// Criar configuração padrão
|
|
1251
1307
|
const defaultConfig = createDefaultTableConfig();
|
|
1252
1308
|
|
|
1253
|
-
// Validar
|
|
1309
|
+
// Validar configuração
|
|
1254
1310
|
if (isValidTableConfig(myConfig)) {
|
|
1255
|
-
//
|
|
1311
|
+
// Configuração válida
|
|
1256
1312
|
}
|
|
1257
1313
|
|
|
1258
|
-
// Clonar
|
|
1314
|
+
// Clonar configuração
|
|
1259
1315
|
const clonedConfig = cloneTableConfig(originalConfig);
|
|
1260
1316
|
|
|
1261
|
-
// Merge
|
|
1317
|
+
// Merge configurações
|
|
1262
1318
|
const mergedConfig = mergeTableConfigs(baseConfig, overrides);
|
|
1263
1319
|
```
|
|
1264
1320
|
|
|
@@ -1272,10 +1328,10 @@ export class MyComponent {
|
|
|
1272
1328
|
constructor(private configService: TableConfigService) {}
|
|
1273
1329
|
|
|
1274
1330
|
ngOnInit() {
|
|
1275
|
-
// Usar
|
|
1331
|
+
// Usar serviço para gerenciar configuração
|
|
1276
1332
|
this.configService.setConfig(this.tableConfig);
|
|
1277
1333
|
|
|
1278
|
-
// Verificar recursos
|
|
1334
|
+
// Verificar recursos disponÃveis
|
|
1279
1335
|
// No runtime atual, multiSort permanece schema-only.
|
|
1280
1336
|
const hasMultiSort = false;
|
|
1281
1337
|
const hasBulkActions = this.configService.isFeatureEnabled('bulkActions');
|
|
@@ -1283,7 +1339,7 @@ export class MyComponent {
|
|
|
1283
1339
|
}
|
|
1284
1340
|
```
|
|
1285
1341
|
|
|
1286
|
-
##
|
|
1342
|
+
## 🧪 Testes
|
|
1287
1343
|
|
|
1288
1344
|
### Unit Tests
|
|
1289
1345
|
|
|
@@ -1322,11 +1378,11 @@ describe("PraxisTable", () => {
|
|
|
1322
1378
|
});
|
|
1323
1379
|
```
|
|
1324
1380
|
|
|
1325
|
-
##
|
|
1381
|
+
## 📋 Migration Guide
|
|
1326
1382
|
|
|
1327
|
-
###
|
|
1383
|
+
### Migração da Arquitetura V1/V2
|
|
1328
1384
|
|
|
1329
|
-
Se
|
|
1385
|
+
Se você estava usando as versões anteriores com dual architecture, aqui estão as principais mudanças:
|
|
1330
1386
|
|
|
1331
1387
|
#### Imports Atualizados
|
|
1332
1388
|
|
|
@@ -1338,14 +1394,14 @@ import { TableConfigV1, TableConfigV2, TableConfigUnified } from "@praxisui/core
|
|
|
1338
1394
|
import { TableConfig } from "@praxisui/core";
|
|
1339
1395
|
```
|
|
1340
1396
|
|
|
1341
|
-
####
|
|
1397
|
+
#### Serviços Removidos
|
|
1342
1398
|
|
|
1343
1399
|
```typescript
|
|
1344
1400
|
// Antes
|
|
1345
1401
|
import { TableConfigAdapterService } from "@praxisui/table";
|
|
1346
1402
|
|
|
1347
|
-
// Depois -
|
|
1348
|
-
// Uso direto da
|
|
1403
|
+
// Depois - Não mais necessário
|
|
1404
|
+
// Uso direto da configuração
|
|
1349
1405
|
```
|
|
1350
1406
|
|
|
1351
1407
|
#### Tipos Simplificados
|
|
@@ -1360,29 +1416,29 @@ config: TableConfig;
|
|
|
1360
1416
|
|
|
1361
1417
|
### Breaking Changes
|
|
1362
1418
|
|
|
1363
|
-
1. **TableConfigAdapterService**: Removido - uso direto da
|
|
1419
|
+
1. **TableConfigAdapterService**: Removido - uso direto da configuração
|
|
1364
1420
|
2. **TableConfigMigrationService**: Simplificado - funcionalidade integrada
|
|
1365
1421
|
3. **TableConfigUnified**: Renomeado para `TableConfig`
|
|
1366
1422
|
|
|
1367
|
-
##
|
|
1423
|
+
## 🔠Troubleshooting
|
|
1368
1424
|
|
|
1369
1425
|
### Problemas Comuns
|
|
1370
1426
|
|
|
1371
|
-
####
|
|
1427
|
+
#### Configuração não está funcionando
|
|
1372
1428
|
|
|
1373
1429
|
```typescript
|
|
1374
|
-
// Verificar se a
|
|
1430
|
+
// Verificar se a configuração é válida
|
|
1375
1431
|
import { isValidTableConfig } from "@praxisui/core";
|
|
1376
1432
|
|
|
1377
1433
|
if (!isValidTableConfig(myConfig)) {
|
|
1378
|
-
console.error("
|
|
1434
|
+
console.error("Configuração inválida:", myConfig);
|
|
1379
1435
|
}
|
|
1380
1436
|
```
|
|
1381
1437
|
|
|
1382
1438
|
#### Performance Issues
|
|
1383
1439
|
|
|
1384
1440
|
```typescript
|
|
1385
|
-
// Habilitar
|
|
1441
|
+
// Habilitar virtualização para grandes datasets
|
|
1386
1442
|
const config: TableConfig = {
|
|
1387
1443
|
// ...
|
|
1388
1444
|
performance: {
|
|
@@ -1398,7 +1454,7 @@ const config: TableConfig = {
|
|
|
1398
1454
|
#### Acessibilidade
|
|
1399
1455
|
|
|
1400
1456
|
```typescript
|
|
1401
|
-
// Garantir que acessibilidade
|
|
1457
|
+
// Garantir que acessibilidade está habilitada
|
|
1402
1458
|
const config: TableConfig = {
|
|
1403
1459
|
// ...
|
|
1404
1460
|
accessibility: {
|
|
@@ -1408,35 +1464,35 @@ const config: TableConfig = {
|
|
|
1408
1464
|
};
|
|
1409
1465
|
```
|
|
1410
1466
|
|
|
1411
|
-
##
|
|
1467
|
+
## 📚 API Reference
|
|
1412
1468
|
|
|
1413
1469
|
### Interfaces Principais
|
|
1414
1470
|
|
|
1415
1471
|
#### TableConfig
|
|
1416
1472
|
|
|
1417
|
-
Interface principal para
|
|
1473
|
+
Interface principal para configuração da tabela.
|
|
1418
1474
|
|
|
1419
1475
|
#### ColumnDefinition
|
|
1420
1476
|
|
|
1421
|
-
Define
|
|
1477
|
+
Define configuração individual de colunas.
|
|
1422
1478
|
|
|
1423
1479
|
#### TableBehaviorConfig
|
|
1424
1480
|
|
|
1425
|
-
|
|
1481
|
+
Configurações de comportamento (paginação, ordenação, etc.).
|
|
1426
1482
|
|
|
1427
1483
|
#### TableAppearanceConfig
|
|
1428
1484
|
|
|
1429
|
-
|
|
1485
|
+
Configurações de aparência visual.
|
|
1430
1486
|
|
|
1431
|
-
Para
|
|
1487
|
+
Para documentação completa da API, consulte `projects/praxis-core/README.md`.
|
|
1432
1488
|
|
|
1433
|
-
##
|
|
1489
|
+
## 🤠Contribuição
|
|
1434
1490
|
|
|
1435
1491
|
### Como Contribuir
|
|
1436
1492
|
|
|
1437
1493
|
1. Fork o projeto
|
|
1438
1494
|
2. Crie branch para feature (`git checkout -b feature/nova-funcionalidade`)
|
|
1439
|
-
3. Commit
|
|
1495
|
+
3. Commit mudanças (`git commit -m 'Add: nova funcionalidade'`)
|
|
1440
1496
|
4. Push para branch (`git push origin feature/nova-funcionalidade`)
|
|
1441
1497
|
5. Abra Pull Request
|
|
1442
1498
|
|
|
@@ -1444,12 +1500,12 @@ Para documentação completa da API, consulte `projects/praxis-core/README.md`.
|
|
|
1444
1500
|
|
|
1445
1501
|
- Seguir Angular Style Guide
|
|
1446
1502
|
- Adicionar testes para novas features
|
|
1447
|
-
- Manter
|
|
1503
|
+
- Manter documentação atualizada
|
|
1448
1504
|
- Usar TypeScript strict mode
|
|
1449
1505
|
|
|
1450
|
-
##
|
|
1506
|
+
## 🔠Exemplo de Integração com PraxisFilter
|
|
1451
1507
|
|
|
1452
|
-
O `PraxisFilter` pode ser acoplado
|
|
1508
|
+
O `PraxisFilter` pode ser acoplado à barra de ferramentas da tabela. O exemplo abaixo mostra a busca de pessoas por CPF e status.
|
|
1453
1509
|
|
|
1454
1510
|
```html
|
|
1455
1511
|
<praxis-filter [resourcePath]="'pessoas'" [formId]="'pessoas-filter'" [persistenceKey]="'pessoas-filter-v1'" [alwaysVisibleFields]="['status']" (requestSearch)="onFilter($event)"></praxis-filter> <praxis-table [data]="tableData"></praxis-table>
|
|
@@ -1464,16 +1520,16 @@ onFilter(dto: any) {
|
|
|
1464
1520
|
}
|
|
1465
1521
|
```
|
|
1466
1522
|
|
|
1467
|
-
###
|
|
1523
|
+
### âš™ï¸ Configuração do Filtro
|
|
1468
1524
|
|
|
1469
|
-
O `PraxisFilter` pode ser configurado por inputs/JSON de
|
|
1470
|
-
visual por
|
|
1471
|
-
Quando
|
|
1472
|
-
`openSettings()`. Nesse painel
|
|
1525
|
+
O `PraxisFilter` pode ser configurado por inputs/JSON de configuração. O atalho
|
|
1526
|
+
visual por Ãcone de engrenagem não é exposto por padrão na tabela/demo.
|
|
1527
|
+
Quando necessário, também é possÃvel abrir o painel programaticamente via
|
|
1528
|
+
`openSettings()`. Nesse painel é possÃvel ajustar:
|
|
1473
1529
|
|
|
1474
|
-
- **alwaysVisibleFields**
|
|
1475
|
-
- **alwaysVisibleFieldMetadataOverrides**
|
|
1476
|
-
- **showAdvanced**
|
|
1530
|
+
- **alwaysVisibleFields** – campos que permanecem sempre visÃveis
|
|
1531
|
+
- **alwaysVisibleFieldMetadataOverrides** – patch de metadata por campo sempre visÃvel (controle, clearButton, inlineAutoSize etc.)
|
|
1532
|
+
- **showAdvanced** – define se a seção avançada inicia aberta
|
|
1477
1533
|
|
|
1478
1534
|
```ts
|
|
1479
1535
|
@ViewChild(PraxisFilter) filter!: PraxisFilter;
|
|
@@ -1483,100 +1539,100 @@ abrirConfiguracoes() {
|
|
|
1483
1539
|
}
|
|
1484
1540
|
```
|
|
1485
1541
|
|
|
1486
|
-
Ao aplicar ou salvar, as escolhas
|
|
1542
|
+
Ao aplicar ou salvar, as escolhas são validadas contra os metadados
|
|
1487
1543
|
do **DTO de filtro** (schema de `POST /{resource}/filter`). Campos ausentes
|
|
1488
|
-
no DTO
|
|
1489
|
-
O componente exibe uma barra de progresso durante o processo de
|
|
1490
|
-
mensagens de sucesso ou erro via _snack bar_, garantindo uma
|
|
1544
|
+
no DTO não são aplicados em `alwaysVisibleFields`.
|
|
1545
|
+
O componente exibe uma barra de progresso durante o processo de persistência e
|
|
1546
|
+
mensagens de sucesso ou erro via _snack bar_, garantindo uma experiência
|
|
1491
1547
|
consistente.
|
|
1492
1548
|
|
|
1493
|
-
###
|
|
1549
|
+
### 🔖 Mini‑guia: Atalhos do Filtro (tags)
|
|
1494
1550
|
|
|
1495
|
-
Atalhos
|
|
1551
|
+
Atalhos são “chips†que guardam um conjunto de filtros (DTO) para reuso rápido.
|
|
1496
1552
|
|
|
1497
1553
|
- Criar/Salvar
|
|
1498
|
-
- Modal (
|
|
1499
|
-
- Gaveta (Drawer): o Adapter recebe `allowSaveTags?`, `i18nSaveAsShortcut?` e `onSaveShortcut?` (opcionais). O host deve exibir o
|
|
1500
|
-
- O DTO
|
|
1554
|
+
- Modal (padrão): o host do diálogo exibe o botão quando `allowSaveTags === true`.
|
|
1555
|
+
- Gaveta (Drawer): o Adapter recebe `allowSaveTags?`, `i18nSaveAsShortcut?` e `onSaveShortcut?` (opcionais). O host deve exibir o botão e chamar `onSaveShortcut(clean({ ...initialDto, ...lastValue }))`.
|
|
1556
|
+
- O DTO é limpo antes de persistir (remove `'' | null | undefined`).
|
|
1501
1557
|
- Aplicar
|
|
1502
1558
|
- Clique/Enter no chip aplica imediatamente `tag.patch` (substitui o estado atual), emite `submit` e persiste.
|
|
1503
|
-
- O chip ativo
|
|
1559
|
+
- O chip ativo é destacado (cor/borda + Ãcone de “checkâ€) quando o DTO atual é igual ao patch do atalho.
|
|
1504
1560
|
- Editar/Renomear
|
|
1505
|
-
- Apenas atalhos do
|
|
1561
|
+
- Apenas atalhos do usuário exibem Ãcone de lápis. Predefinidos mostram Ãcone de “cadeado†(somente leitura).
|
|
1506
1562
|
- Excluir (com Undo)
|
|
1507
|
-
-
|
|
1508
|
-
- Ao clicar em
|
|
1563
|
+
- Exclusão remove imediatamente o atalho do usuário e exibe snackbar “Atalho removido†com ação “Desfazer†quando `confirmTagDelete === true`.
|
|
1564
|
+
- Ao clicar em “Desfazerâ€, o atalho é restaurado na mesma posição e os eventos são reemitidos.
|
|
1509
1565
|
- i18n
|
|
1510
|
-
- Chaves
|
|
1566
|
+
- Chaves úteis: `saveAsShortcut`, `renameShortcut`, `removeShortcut`, `shortcutSaved`, `shortcutRemoved`, `undo`, `readonlyShortcut`.
|
|
1511
1567
|
|
|
1512
|
-
Veja
|
|
1568
|
+
Veja também: `docs/host-crud-integration.md` (guia operacional host) e `projects/praxis-crud/docs/host-crud-runtime-and-openmode.md` (contrato técnico canônico) para detalhes do contrato do Adapter.
|
|
1513
1569
|
|
|
1514
1570
|
### Novos Inputs/Outputs (PraxisFilter)
|
|
1515
1571
|
|
|
1516
1572
|
- Inputs (efetivos apenas quando `enableCustomization = true`):
|
|
1517
|
-
- `enableCustomization: boolean`
|
|
1518
|
-
- `notifyIfOutdated: 'inline' | 'snackbar' | 'both' | 'none' = 'both'`
|
|
1519
|
-
- `snoozeMs: number = 86400000`
|
|
1520
|
-
- `autoOpenSettingsOnOutdated: boolean = false`
|
|
1573
|
+
- `enableCustomization: boolean` — habilita o gate de customização para notificações de schema.
|
|
1574
|
+
- `notifyIfOutdated: 'inline' | 'snackbar' | 'both' | 'none' = 'both'` — seleciona como o runtime publica avisos de drift quando a polÃtica operacional estiver habilitada.
|
|
1575
|
+
- `snoozeMs: number = 86400000` — tempo de soneca para avisos (ms).
|
|
1576
|
+
- `autoOpenSettingsOnOutdated: boolean = false` — abre Configurações ao detectar schema desatualizado.
|
|
1521
1577
|
- Output:
|
|
1522
|
-
- `schemaStatusChange: { outdated: boolean; serverHash?: string; lastVerifiedAt?: string; tableId?: string }`
|
|
1578
|
+
- `schemaStatusChange: { outdated: boolean; serverHash?: string; lastVerifiedAt?: string; tableId?: string }` — emitido após verificação leve (304/200).
|
|
1523
1579
|
|
|
1524
1580
|
#### Fallback Global (opcional)
|
|
1525
1581
|
|
|
1526
|
-
- Quando os inputs do componente permanecem com os valores
|
|
1527
|
-
- Cadeia de
|
|
1528
|
-
- O fallback global
|
|
1582
|
+
- Quando os inputs do componente permanecem com os valores padrão e não há overrides locais, o Filter utiliza como último fallback as preferências globais via `GlobalConfigService.getSchemaPrefsGlobal()`.
|
|
1583
|
+
- Cadeia de precedência (inalterada): `@Inputs (widget)` → Prefs do widget → Prefs da página → Prefs globais → Defaults.
|
|
1584
|
+
- O fallback global não é persistido no componente; serve apenas para defaults em memória.
|
|
1529
1585
|
|
|
1530
|
-
Notas
|
|
1531
|
-
-
|
|
1586
|
+
Notas rápidas (Flow ETag no Filter):
|
|
1587
|
+
- Verificação leve sempre no init (sem baixar o corpo): usa ETag/If-None-Match em `/schemas/filtered` (path=`.../filter`, operation=`post`, schemaType=`request`, `includeInternalSchemas=true`).
|
|
1532
1588
|
- 304: atualiza `lastVerifiedAt`; emite `schemaStatusChange(outdated=false)`.
|
|
1533
|
-
- 200: atualiza `serverHash/lastVerifiedAt`; marca `outdated=true` apenas quando em
|
|
1534
|
-
- O corpo do schema
|
|
1589
|
+
- 200: atualiza `serverHash/lastVerifiedAt`; marca `outdated=true` apenas quando em customização; não aplica o schema automaticamente.
|
|
1590
|
+
- O corpo do schema é baixado apenas quando necessário para renderização (ex.: `alwaysVisibleFields` ou ao abrir o painel Avançado).
|
|
1535
1591
|
|
|
1536
|
-
##
|
|
1592
|
+
## Formatação de Colunas (format)
|
|
1537
1593
|
|
|
1538
|
-
Cada coluna pode declarar `type` e uma string de
|
|
1594
|
+
Cada coluna pode declarar `type` e uma string de formatação `format` consumida pelo `DataFormattingService`. Os tipos suportados são: `string`, `number`, `currency`, `percentage`, `date`, `datetime`, `time`, `boolean`, `custom`.
|
|
1539
1595
|
|
|
1540
1596
|
Regra geral:
|
|
1541
|
-
- `format`
|
|
1542
|
-
- Para `number`, `currency`, `percentage`, `date`, `datetime` e `time`, a tabela
|
|
1543
|
-
- `string`, `boolean` e `custom` continuam conservadores; nesses casos, use `format`
|
|
1597
|
+
- `format` explÃcito continua com precedência máxima.
|
|
1598
|
+
- Para `number`, `currency`, `percentage`, `date`, `datetime` e `time`, a tabela também consegue derivar formatação básica a partir de `type + config.localization`, mesmo quando `format` estiver ausente.
|
|
1599
|
+
- `string`, `boolean` e `custom` continuam conservadores; nesses casos, use `format` explÃcito quando precisar de transformação.
|
|
1544
1600
|
|
|
1545
1601
|
Nota de plataforma:
|
|
1546
|
-
- o contrato
|
|
1547
|
-
- a tabela converge internamente para a
|
|
1602
|
+
- o contrato público da tabela continua sendo `column.type + config.localization + format`.
|
|
1603
|
+
- a tabela converge internamente para a semântica canônica horizontal do core, mas não expõe `valuePresentation` como bloco público de configuração de coluna.
|
|
1548
1604
|
|
|
1549
|
-
Tipos e
|
|
1605
|
+
Tipos e padrões de `format`:
|
|
1550
1606
|
- number (DecimalPipe)
|
|
1551
|
-
-
|
|
1607
|
+
- Padrões: `minInt.minFrac-maxFrac`
|
|
1552
1608
|
- Exemplos: `1.0-0`, `1.2-2`, `1.0-3|nosep` (remove separador de milhar)
|
|
1553
1609
|
- currency (CurrencyPipe)
|
|
1554
1610
|
- Sintaxe: `CURRENCY|DISPLAY|DECIMALS[|nosep]`
|
|
1555
1611
|
- Exemplos: `BRL|symbol|2`, `USD|code|0`, `EUR|symbol|2|nosep`
|
|
1556
1612
|
- percentage (PercentPipe/DecimalPipe)
|
|
1557
1613
|
- Sem multiplicador: `1.0-0` (PercentPipe)
|
|
1558
|
-
- Multiplicar por 100: `1.1-1|x100` (
|
|
1614
|
+
- Multiplicar por 100: `1.1-1|x100` (DecimalPipe×100 + `%`)
|
|
1559
1615
|
- date (DatePipe)
|
|
1560
1616
|
- Tokens Angular: `shortDate`, `mediumDate`, `longDate`, `fullDate`, `short`, `shortTime`
|
|
1561
|
-
-
|
|
1562
|
-
- string (
|
|
1617
|
+
- Padrões customizados: `dd/MM/yyyy`, `yyyy-MM-dd`, `dd/MM/yyyy HH:mm`
|
|
1618
|
+
- string (transformações + truncamento)
|
|
1563
1619
|
- Transform: `uppercase` | `lowercase` | `titlecase` | `capitalize` | `none`
|
|
1564
1620
|
- Transform + truncar: `<transform>|truncate|<max>|<suffix>`
|
|
1565
1621
|
- Exemplos: `uppercase|truncate|50|...`, `titlecase`
|
|
1566
|
-
- boolean (pr
|
|
1622
|
+
- boolean (pré-definidos ou custom)
|
|
1567
1623
|
- Presets: `true-false` | `yes-no` | `active-inactive` | `on-off` | `enabled-disabled`
|
|
1568
1624
|
- Custom: `custom|Verdadeiro|Falso`
|
|
1569
1625
|
|
|
1570
1626
|
Exemplos de ColumnDefinition:
|
|
1571
1627
|
```ts
|
|
1572
|
-
{ field: 'salario', type: 'currency', format: 'BRL|symbol|2', header: '
|
|
1628
|
+
{ field: 'salario', type: 'currency', format: 'BRL|symbol|2', header: 'Salário' }
|
|
1573
1629
|
{ field: 'desconto', type: 'percentage', format: '1.1-1|x100', header: 'Desconto' }
|
|
1574
1630
|
{ field: 'criadoEm', type: 'date', format: 'dd/MM/yyyy', header: 'Criado em' }
|
|
1575
|
-
{ field: 'nome', type: 'string', format: 'titlecase|truncate|32
|
|
1631
|
+
{ field: 'nome', type: 'string', format: 'titlecase|truncate|32|…', header: 'Nome' }
|
|
1576
1632
|
{ field: 'ativo', type: 'boolean', format: 'yes-no', header: 'Ativo' }
|
|
1577
1633
|
```
|
|
1578
1634
|
|
|
1579
|
-
Exemplos com defaults
|
|
1635
|
+
Exemplos com defaults implÃcitos por `type + localization`:
|
|
1580
1636
|
```ts
|
|
1581
1637
|
{
|
|
1582
1638
|
localization: {
|
|
@@ -1586,22 +1642,22 @@ Exemplos com defaults implícitos por `type + localization`:
|
|
|
1586
1642
|
number: { decimalSeparator: ',', thousandsSeparator: '.', defaultPrecision: 2, negativeSign: '-', negativeSignPosition: 'before' },
|
|
1587
1643
|
},
|
|
1588
1644
|
columns: [
|
|
1589
|
-
{ field: 'salario', type: 'currency', header: '
|
|
1645
|
+
{ field: 'salario', type: 'currency', header: 'Salário' },
|
|
1590
1646
|
{ field: 'criadoEm', type: 'date', header: 'Criado em' },
|
|
1591
1647
|
{ field: 'taxa', type: 'percentage', header: 'Taxa' },
|
|
1592
1648
|
],
|
|
1593
1649
|
}
|
|
1594
1650
|
```
|
|
1595
1651
|
|
|
1596
|
-
|
|
1597
|
-
- `|nosep` remove separadores de milhar da
|
|
1598
|
-
- Para datas
|
|
1599
|
-
- Colunas com renderizador `custom`
|
|
1600
|
-
-
|
|
1601
|
-
- Quando `config.localization.currency` estiver presente, a tabela usa esse bloco como override para
|
|
1652
|
+
Observações:
|
|
1653
|
+
- `|nosep` remove separadores de milhar da saÃda formatada.
|
|
1654
|
+
- Para datas inválidas ou valores não numéricos, o serviço retorna o valor original (com aviso no console).
|
|
1655
|
+
- Colunas com renderizador `custom` não passam por formatação automática.
|
|
1656
|
+
- Precedência de locale para formatação: `config.localization.locale` -> `LOCALE_ID` do host.
|
|
1657
|
+
- Quando `config.localization.currency` estiver presente, a tabela usa esse bloco como override para código, sÃmbolo, posição, espaçamento e precisão da moeda.
|
|
1602
1658
|
- Quando `config.localization.number` estiver presente, a tabela respeita `decimalSeparator`, `thousandsSeparator`, `defaultPrecision`, `negativeSign` e `negativeSignPosition` em number/currency/percentage.
|
|
1603
1659
|
|
|
1604
|
-
Exemplos
|
|
1660
|
+
Exemplos práticos no workspace (rotas):
|
|
1605
1661
|
- Regras Visuais (Simples): `/table-rules-simple`
|
|
1606
1662
|
- Regras Visuais (Complexas): `/table-rules-complex`
|
|
1607
1663
|
|
|
@@ -1642,22 +1698,22 @@ A11y, seguranca e performance:
|
|
|
1642
1698
|
- URL da imagem sanitizada (bloqueia esquemas perigosos)
|
|
1643
1699
|
- imagem com `loading=\"lazy\"`
|
|
1644
1700
|
|
|
1645
|
-
##
|
|
1701
|
+
## 📊 Roadmap
|
|
1646
1702
|
|
|
1647
|
-
###
|
|
1703
|
+
### Próximas Versões
|
|
1648
1704
|
|
|
1649
|
-
-
|
|
1650
|
-
-
|
|
1651
|
-
-
|
|
1652
|
-
-
|
|
1705
|
+
- ✅ Arquitetura unificada (v2.0.0)
|
|
1706
|
+
- 🔄 Enhanced mobile support (v2.1.0)
|
|
1707
|
+
- 📋 Advanced export options (v2.2.0)
|
|
1708
|
+
- 🎨 Theme customization (v2.3.0)
|
|
1653
1709
|
|
|
1654
|
-
##
|
|
1710
|
+
## 📄 Licença
|
|
1655
1711
|
|
|
1656
|
-
Apache-2.0
|
|
1712
|
+
Apache-2.0 — consulte `LICENSE` na raiz do workspace para detalhes.
|
|
1657
1713
|
|
|
1658
1714
|
---
|
|
1659
1715
|
|
|
1660
1716
|
**Parte do Praxis UI Workspace**
|
|
1661
|
-
**
|
|
1717
|
+
**Versão**: 2.0.0 (Unified Architecture)
|
|
1662
1718
|
**Compatibilidade**: Angular 18+
|
|
1663
1719
|
|