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