@praxisui/table 5.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 +416 -414
- package/fesm2022/praxisui-table.mjs +650 -18
- package/index.d.ts +43 -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,13 @@ 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
|
+
## `x-ui.analytics` como fallback tabular canônico
|
|
68
74
|
|
|
69
75
|
O `@praxisui/table` materializa a familia `analytic-table` quando o `@praxisui/core`
|
|
70
76
|
resolve que uma projection de `x-ui.analytics` continua valida, mas nao e um chart
|
|
@@ -95,7 +101,7 @@ Filtro runtime:
|
|
|
95
101
|
- somente `filters` entram no request remoto nesta fase
|
|
96
102
|
- `sort`, `limit` e agregacao continuam vindo da projection publicada
|
|
97
103
|
|
|
98
|
-
> Componente de tabela empresarial
|
|
104
|
+
> Componente de tabela empresarial avançado com arquitetura unificada
|
|
99
105
|
|
|
100
106
|
## Customization Mode Contract
|
|
101
107
|
|
|
@@ -109,92 +115,92 @@ Filtro runtime:
|
|
|
109
115
|
- Hosts that relied on the previous implicit authoring behavior must now declare `[enableCustomization]="true"` explicitly.
|
|
110
116
|
- This is an intentional breaking change for enterprise governance: authoring is opt-in, not ambient.
|
|
111
117
|
|
|
112
|
-
##
|
|
118
|
+
## 🌟 Visão Geral
|
|
113
119
|
|
|
114
|
-
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.
|
|
115
121
|
|
|
116
|
-
##
|
|
122
|
+
## 🎨 Tema M3 (tokens mÃnimos)
|
|
117
123
|
|
|
118
124
|
Para garantir que a tabela, filtros e editores reflitam o tema do app host:
|
|
119
125
|
|
|
120
|
-
-
|
|
126
|
+
- SuperfÃcies: `--md-sys-color-surface`, `--md-sys-color-surface-variant`, `--md-sys-color-surface-container-*`
|
|
121
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`
|
|
122
|
-
-
|
|
128
|
+
- Semânticos: `--md-sys-color-primary`, `--md-sys-color-secondary`, `--md-sys-color-tertiary`, `--md-sys-color-error`
|
|
123
129
|
- Containers: `--md-sys-color-primary-container`, `--md-sys-color-secondary-container`, `--md-sys-color-tertiary-container`, `--md-sys-color-error-container`
|
|
124
130
|
- Overlay: `--md-sys-color-scrim`
|
|
125
|
-
-
|
|
131
|
+
- Elevação: `--md-sys-elevation-level1`–`--md-sys-elevation-level3`
|
|
126
132
|
|
|
127
|
-
|
|
128
|
-
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.
|
|
129
135
|
|
|
130
|
-
##
|
|
136
|
+
## ✨ CaracterÃsticas Principais
|
|
131
137
|
|
|
132
|
-
###
|
|
138
|
+
### ðŸ—ï¸ Arquitetura Unificada
|
|
133
139
|
|
|
134
|
-
- **Interface
|
|
140
|
+
- **Interface única**: `TableConfig` consolidada
|
|
135
141
|
- **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
|
-
- **
|
|
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
|
|
148
154
|
- **Acessibilidade**: WCAG 2.1 AA compliant
|
|
149
|
-
- **
|
|
155
|
+
- **Verificação de Schema**: ETag/If-None-Match com notificações (somente em customização)
|
|
150
156
|
|
|
151
157
|
## Expansion Hypermedia
|
|
152
158
|
|
|
153
|
-
O primeiro corte de `behavior.expansion.detail.source.mode = "hypermedia"`
|
|
159
|
+
O primeiro corte de `behavior.expansion.detail.source.mode = "hypermedia"` é
|
|
154
160
|
`capabilities-first`:
|
|
155
161
|
|
|
156
|
-
- a row expandida
|
|
157
|
-
- `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
|
|
158
164
|
pelo backend
|
|
159
165
|
- o detail renderiza um resumo contextual somente leitura, com foco em UX de
|
|
160
|
-
|
|
161
|
-
- este corte
|
|
162
|
-
- 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
|
|
163
169
|
|
|
164
|
-
|
|
170
|
+
Observação de escala:
|
|
165
171
|
- o prefetch por linha continua ativo quando `actions.row.enabled=true`
|
|
166
|
-
- quando apenas o expansion `hypermedia`
|
|
172
|
+
- quando apenas o expansion `hypermedia` está ligado, o discovery contextual é
|
|
167
173
|
resolvido sob demanda ao expandir a linha
|
|
168
174
|
|
|
169
|
-
###
|
|
175
|
+
### 📄 Contrato Inline do Filtro
|
|
170
176
|
|
|
171
177
|
- Referencia canonica: `projects/praxis-dynamic-fields/docs/dynamic-fields-inline-components-guide.md` (slug publicado: `dynamic-fields-inline-components-guide`)
|
|
172
178
|
- No contexto da tabela, use este contrato para definir `controlType` inline e politica de compatibilidade (canonica vs legado).
|
|
173
179
|
|
|
174
|
-
###
|
|
180
|
+
### 🧠Decisoes de Arquitetura (ADR)
|
|
175
181
|
|
|
176
182
|
- Bundle/adapters: `projects/praxis-table/docs/adr/2026-03-filter-drawer-adapter-light-entrypoint.md`
|
|
177
183
|
|
|
178
|
-
###
|
|
184
|
+
### 🎨 Editores Visuais
|
|
179
185
|
|
|
180
|
-
- **Behavior Editor**:
|
|
181
|
-
- **Columns Editor**:
|
|
182
|
-
- **Toolbar Editor**:
|
|
183
|
-
- **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
|
|
184
190
|
|
|
185
191
|
Nota (Regras)
|
|
186
|
-
- 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.
|
|
187
193
|
|
|
188
|
-
###
|
|
194
|
+
### 🧩 Editor de Regras (column-first)
|
|
189
195
|
|
|
190
|
-
O novo editor
|
|
196
|
+
O novo editor é "column-first" e usa uma tipagem compartilhada com o Editor de Colunas. Principais pontos:
|
|
191
197
|
|
|
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
|
|
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).
|
|
198
204
|
|
|
199
205
|
Exemplos de JSON Logic:
|
|
200
206
|
|
|
@@ -208,80 +214,77 @@ Exemplos de JSON Logic:
|
|
|
208
214
|
```
|
|
209
215
|
|
|
210
216
|
Notas sobre enum/CSV:
|
|
211
|
-
- Para campos enumerados, as
|
|
212
|
-
- 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`).
|
|
213
219
|
|
|
214
|
-
####
|
|
220
|
+
#### Operadores e helpers de JSON Logic
|
|
215
221
|
|
|
216
|
-
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:
|
|
217
223
|
|
|
218
224
|
- JSON: `jsonGet`, `hasJsonKey`, `jsonPathMatches`, `jsonEq`, `jsonIn`, `jsonType`
|
|
219
225
|
- Texto/valor: `isBlank`, `eqIgnoreCase`, `coalesce`
|
|
220
226
|
- Faixas: `between`, `dateBetween`
|
|
221
|
-
-
|
|
227
|
+
- Coleções: `containsAny`, `containsAll`, `len`, `lenEq`, `lenGt`, `lenLt`, `lenAtLeast`
|
|
222
228
|
- Tempo: `today`, `now`, `dateAdd`, `dateFormat`, `isToday`, `inLast`, `isPast`, `isPastOrNow`, `isFuture`, `isFutureOrNow`, `weekdayIn`
|
|
223
229
|
|
|
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`.
|
|
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"]] }`
|
|
234
237
|
|
|
235
|
-
Guia completo: `projects/praxis-table/docs/
|
|
238
|
+
Guia completo: `projects/praxis-table/docs/json-logic-operators-and-helpers.md`
|
|
236
239
|
|
|
237
|
-
####
|
|
240
|
+
#### 🎨 Efeitos (Conteúdo C)
|
|
238
241
|
|
|
239
|
-
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:
|
|
240
243
|
|
|
241
|
-
- Toolbar de texto com
|
|
242
|
-
- Presets de feedback com
|
|
243
|
-
-
|
|
244
|
-
-
|
|
245
|
-
- 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.
|
|
246
249
|
|
|
247
250
|
Dicas
|
|
248
|
-
- Use
|
|
249
|
-
- 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.
|
|
250
253
|
|
|
251
254
|
Como reverter efeitos
|
|
252
|
-
-
|
|
253
|
-
-
|
|
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.
|
|
254
257
|
|
|
255
|
-
|
|
258
|
+
Observação: capturas de tela “antes/depois†podem ser adicionadas no PR conforme necessário.
|
|
256
259
|
|
|
257
260
|
#### Relacionais (lookup)
|
|
258
261
|
|
|
259
|
-
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.
|
|
260
263
|
|
|
261
|
-
Boas
|
|
264
|
+
Boas práticas
|
|
262
265
|
- Informe `resourcePath` (ou `endpoint`) no `FieldDefinition` para habilitar o lookup via `GenericCrudService` do host.
|
|
263
|
-
- Defina `valueField` (chave
|
|
266
|
+
- Defina `valueField` (chave estável, tipicamente `id`) e `displayField` (label amigável, como `name`).
|
|
264
267
|
|
|
265
|
-
##
|
|
268
|
+
## 🔎 Filtro: Atalhos para PerÃodo (DateRange)
|
|
266
269
|
|
|
267
|
-
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:
|
|
268
271
|
|
|
269
272
|
```ts
|
|
270
273
|
// Em FilterConfig (ou na metadata de campos do filtro)
|
|
271
274
|
{
|
|
272
275
|
name: 'period',
|
|
273
|
-
label: '
|
|
276
|
+
label: 'PerÃodo',
|
|
274
277
|
controlType: 'dateRange',
|
|
275
278
|
showShortcuts: true,
|
|
276
279
|
shortcuts: ['thisMonth','lastMonth','thisYear'],
|
|
277
280
|
// Opcional:
|
|
278
|
-
// i18nShortcuts: { thisMonth: 'Este
|
|
281
|
+
// i18nShortcuts: { thisMonth: 'Este mês', lastMonth: 'Mês passado' },
|
|
279
282
|
// applyOnShortcutClick: true
|
|
280
283
|
}
|
|
281
284
|
```
|
|
282
|
-
- Para
|
|
283
|
-
- No runtime da tabela
|
|
284
|
-
- 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.
|
|
285
288
|
|
|
286
289
|
Exemplo de FieldDefinition (lookup)
|
|
287
290
|
```ts
|
|
@@ -293,108 +296,107 @@ const fields: FieldDefinition[] = [
|
|
|
293
296
|
type: 'object',
|
|
294
297
|
// Habilita o lookup via GenericCrudService
|
|
295
298
|
resourcePath: 'customers',
|
|
296
|
-
// Mapeia o id/label que
|
|
299
|
+
// Mapeia o id/label que virão do backend
|
|
297
300
|
valueField: 'id',
|
|
298
301
|
displayField: 'name',
|
|
299
|
-
// Se quiser
|
|
302
|
+
// Se quiser multiseleção em todo o app
|
|
300
303
|
// multiple: true,
|
|
301
304
|
},
|
|
302
305
|
];
|
|
303
306
|
```
|
|
304
307
|
|
|
305
|
-
Operadores
|
|
306
|
-
- `id ==`
|
|
307
|
-
- `id in`
|
|
308
|
-
- `has property`
|
|
309
|
-
- 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
|
|
310
313
|
|
|
311
314
|
UI (no editor)
|
|
312
|
-
- `id ==` (single): autocomplete + chip
|
|
313
|
-
- `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.
|
|
314
317
|
- `has property`: input do caminho (ex.: `$.meta.etag`).
|
|
315
318
|
|
|
316
319
|
Formato esperado do payload (relacional)
|
|
317
320
|
|
|
318
|
-
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:
|
|
319
322
|
|
|
320
323
|
```ts
|
|
321
324
|
// Exemplo de linha (row) com campo relacional "customer"
|
|
322
325
|
const row = {
|
|
323
326
|
id: 123,
|
|
324
327
|
customer: {
|
|
325
|
-
id: 10, //
|
|
326
|
-
name: 'ACME', //
|
|
328
|
+
id: 10, // ↠usado em id == / id in via jsonEq/jsonIn
|
|
329
|
+
name: 'ACME', // ↠usado para exibir label no autocomplete/chip
|
|
327
330
|
meta: { etag: 'v1' },
|
|
328
331
|
},
|
|
329
332
|
};
|
|
330
333
|
|
|
331
|
-
// Regras
|
|
334
|
+
// Regras relacionais em JSON Logic
|
|
332
335
|
// id ==
|
|
333
|
-
// jsonEq
|
|
336
|
+
// { "jsonEq": [{ "var": "customer" }, "$.id", 10] }
|
|
334
337
|
// id in
|
|
335
|
-
// jsonIn
|
|
338
|
+
// { "jsonIn": [{ "var": "customer" }, "$.id", [10, 20]] }
|
|
336
339
|
// has property
|
|
337
|
-
// hasJsonKey
|
|
340
|
+
// { "hasJsonKey": [{ "var": "customer" }, "$.meta.etag"] }
|
|
338
341
|
// caminho/valor (join simples)
|
|
339
|
-
// jsonEq
|
|
342
|
+
// { "jsonEq": [{ "var": "customer" }, "$.name", "ACME"] }
|
|
340
343
|
```
|
|
341
344
|
|
|
342
345
|
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
|
|
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.
|
|
345
348
|
|
|
346
|
-
Onde
|
|
349
|
+
Onde é consumido (preview e runtime)
|
|
347
350
|
|
|
348
|
-
- Preview/
|
|
349
|
-
- Authoring
|
|
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`
|
|
350
353
|
- Runtime na Tabela (aplica `rowConditionalStyles`/`conditionalStyles`):
|
|
351
|
-
- JSON Logic
|
|
354
|
+
- JSON Logic canônico: `projects/praxis-table/src/lib/praxis-table.ts`
|
|
352
355
|
|
|
353
|
-
|
|
354
|
-
- JSON Logic
|
|
355
|
-
- O runtime ainda mantém compatibilidade transitória para regras DSL antigas.
|
|
356
|
+
Observação
|
|
357
|
+
- JSON Logic é o contrato canônico para novas regras e para o editor de regras da tabela.
|
|
356
358
|
|
|
357
359
|
|
|
358
|
-
###
|
|
360
|
+
### âš™ï¸ Painel de Configurações
|
|
359
361
|
|
|
360
|
-
Para abrir o painel de
|
|
362
|
+
Para abrir o painel de configurações, habilite o modo de edição na tabela:
|
|
361
363
|
|
|
362
364
|
```html
|
|
363
365
|
<praxis-table [enableCustomization]="true"></praxis-table>
|
|
364
366
|
```
|
|
365
367
|
|
|
366
|
-
Um
|
|
368
|
+
Um botão de engrenagem será exibido no canto superior direito. Ao clicar nele, o `SettingsPanel` é aberto permitindo ajustar:
|
|
367
369
|
|
|
368
|
-
- **Comportamento**:
|
|
370
|
+
- **Comportamento**: paginação, ordenação, filtros e recursos avançados.
|
|
369
371
|
- **Colunas**: visibilidade, ordem, largura e estilo.
|
|
370
|
-
- **Toolbar**:
|
|
371
|
-
- **Mensagens**: textos e
|
|
372
|
+
- **Toolbar**: ações e botões da barra de ferramentas.
|
|
373
|
+
- **Mensagens**: textos e rótulos exibidos na interface.
|
|
372
374
|
|
|
373
|
-
As
|
|
375
|
+
As alterações podem ser aplicadas temporariamente com **Aplicar** ou salvas de forma persistente com **Salvar & Fechar**.
|
|
374
376
|
|
|
375
|
-
##
|
|
377
|
+
## 🚀 Instalação
|
|
376
378
|
|
|
377
379
|
```bash
|
|
378
380
|
npm install @praxisui/core @praxisui/table
|
|
379
381
|
```
|
|
380
382
|
|
|
381
|
-
Peers
|
|
383
|
+
Peers necessários (instale no app host):
|
|
382
384
|
- `@angular/core` `^20.0.0`, `@angular/common` `^20.0.0`
|
|
383
385
|
- `@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
|
|
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)
|
|
387
389
|
|
|
388
|
-
##
|
|
390
|
+
## 📠Uso Básico
|
|
389
391
|
|
|
390
392
|
### Conectando ao Backend com `resourcePath`
|
|
391
393
|
|
|
392
|
-
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`.
|
|
393
395
|
|
|
394
|
-
Quando `resourcePath`
|
|
396
|
+
Quando `resourcePath` é fornecido, a tabela se torna "inteligente":
|
|
395
397
|
|
|
396
|
-
1. **Busca
|
|
397
|
-
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`).
|
|
398
400
|
|
|
399
401
|
```html
|
|
400
402
|
<!-- Exemplo no template do seu componente -->
|
|
@@ -404,12 +406,12 @@ Quando `resourcePath` é fornecido, a tabela se torna "inteligente":
|
|
|
404
406
|
Neste exemplo:
|
|
405
407
|
|
|
406
408
|
- `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
|
|
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.
|
|
409
411
|
|
|
410
412
|
### Consulta Declarativa com `queryContext`
|
|
411
413
|
|
|
412
|
-
Para
|
|
414
|
+
Para orquestração entre widgets em `praxis-dynamic-page`, o contrato semântico primário da tabela passa a ser `queryContext`.
|
|
413
415
|
|
|
414
416
|
```html
|
|
415
417
|
<praxis-table
|
|
@@ -424,23 +426,23 @@ Para orquestração entre widgets em `praxis-dynamic-page`, o contrato semântic
|
|
|
424
426
|
|
|
425
427
|
Regras atuais:
|
|
426
428
|
|
|
427
|
-
- `queryContext.filters`
|
|
429
|
+
- `queryContext.filters` já participa do pipeline efetivo da tabela
|
|
428
430
|
- `filterCriteria` continua aceito como bridge legada de compatibilidade
|
|
429
431
|
- em novo authoring, examples e bindings, prefira `queryContext`
|
|
430
432
|
|
|
431
433
|
### Empty State + Quick Connect (sem `resourcePath`)
|
|
432
434
|
|
|
433
|
-
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:
|
|
434
436
|
|
|
435
437
|
```text
|
|
436
438
|
resourcePath: ex.: human-resources/departamentos
|
|
437
439
|
```
|
|
438
440
|
|
|
439
|
-
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.
|
|
440
442
|
|
|
441
|
-
### Fluxo de
|
|
443
|
+
### Fluxo de Comunicação do `resourcePath`
|
|
442
444
|
|
|
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
|
|
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**.
|
|
444
446
|
|
|
445
447
|
```mermaid
|
|
446
448
|
sequenceDiagram
|
|
@@ -455,7 +457,7 @@ sequenceDiagram
|
|
|
455
457
|
|
|
456
458
|
activate Praxis_Table
|
|
457
459
|
Praxis_Table->>Praxis_Table: ngOnInit()/ngOnChanges() resolve dataMode
|
|
458
|
-
Note over Praxis_Table: remote quando
|
|
460
|
+
Note over Praxis_Table: remote quando há resourcePath efetivo
|
|
459
461
|
Praxis_Table->>Crud_Service: 1. Chama crudService.configure("human-resources/departamentos")
|
|
460
462
|
|
|
461
463
|
activate Crud_Service
|
|
@@ -466,7 +468,7 @@ sequenceDiagram
|
|
|
466
468
|
Praxis_Table->>Crud_Service: Chama crudService.getSchema()
|
|
467
469
|
|
|
468
470
|
activate Crud_Service
|
|
469
|
-
Crud_Service->>Crud_Service: schemaUrl() preserva o base path
|
|
471
|
+
Crud_Service->>Crud_Service: schemaUrl() preserva o base path canônico
|
|
470
472
|
Crud_Service->>Crud_Service: Deriva path="/api/human-resources/departamentos/all"<br>operation="get", schemaType="response"
|
|
471
473
|
Crud_Service->>Docs_Controller: GET /schemas/filtered?path=.../all&operation=get&schemaType=response
|
|
472
474
|
deactivate Crud_Service
|
|
@@ -481,21 +483,21 @@ sequenceDiagram
|
|
|
481
483
|
Crud_Service-->>Praxis_Table: Normaliza schema e retorna FieldDefinition[]
|
|
482
484
|
deactivate Crud_Service
|
|
483
485
|
|
|
484
|
-
Praxis_Table->>Praxis_Table:
|
|
486
|
+
Praxis_Table->>Praxis_Table: Constrói as colunas da tabela<br>a partir do schema recebido
|
|
485
487
|
|
|
486
488
|
Praxis_Table->>Praxis_Table: 3. Chama this.fetchData()
|
|
487
489
|
Praxis_Table->>Crud_Service: Chama crudService.filter(...) para buscar dados
|
|
488
490
|
|
|
489
491
|
activate Crud_Service
|
|
490
|
-
Crud_Service->>Crud_Service: getEndpointUrl('filter')
|
|
491
|
-
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
|
|
492
494
|
deactivate Crud_Service
|
|
493
495
|
|
|
494
496
|
activate BE_Controller
|
|
495
|
-
BE_Controller->>Abstract_Controller: Herda o
|
|
497
|
+
BE_Controller->>Abstract_Controller: Herda o método que lida com @PostMapping("/filter")
|
|
496
498
|
|
|
497
499
|
activate Abstract_Controller
|
|
498
|
-
Abstract_Controller->>Abstract_Controller: Processa a
|
|
500
|
+
Abstract_Controller->>Abstract_Controller: Processa a requisição e busca os dados
|
|
499
501
|
Abstract_Controller-->>BE_Controller: Retorna os dados
|
|
500
502
|
deactivate Abstract_Controller
|
|
501
503
|
|
|
@@ -512,21 +514,21 @@ sequenceDiagram
|
|
|
512
514
|
|
|
513
515
|
Notas importantes:
|
|
514
516
|
|
|
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
|
|
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`.
|
|
517
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`.
|
|
518
|
-
- 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.
|
|
519
521
|
|
|
520
|
-
##
|
|
522
|
+
## â„¹ï¸ Dicas de UX (Tabela)
|
|
521
523
|
|
|
522
|
-
- Multi
|
|
523
|
-
- Duplo clique na linha: configure em Comportamento
|
|
524
|
-
-
|
|
525
|
-
- 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).
|
|
526
528
|
|
|
527
529
|
## Rolagem Horizontal (owner do scroll)
|
|
528
530
|
|
|
529
|
-
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.
|
|
530
532
|
|
|
531
533
|
### Input: `horizontalScroll`
|
|
532
534
|
|
|
@@ -534,17 +536,17 @@ Por padrão, a `<praxis-table>` agora assume a responsabilidade pela rolagem hor
|
|
|
534
536
|
@Input() horizontalScroll: 'auto' | 'wrap' | 'none' = 'auto';
|
|
535
537
|
```
|
|
536
538
|
|
|
537
|
-
- `auto` (
|
|
538
|
-
- `wrap`: permite quebra de linha nas
|
|
539
|
-
- `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.
|
|
540
542
|
|
|
541
543
|
Exemplo:
|
|
542
544
|
|
|
543
545
|
```html
|
|
544
|
-
<!-- Comportamento
|
|
546
|
+
<!-- Comportamento padrão (auto) -->
|
|
545
547
|
<praxis-table resourcePath="employees"></praxis-table>
|
|
546
548
|
|
|
547
|
-
<!-- Reduz rolagem: permite quebra de linha nas
|
|
549
|
+
<!-- Reduz rolagem: permite quebra de linha nas células -->
|
|
548
550
|
<praxis-table resourcePath="employees" horizontalScroll="wrap"></praxis-table>
|
|
549
551
|
|
|
550
552
|
<!-- Host controla o scroll horizontal -->
|
|
@@ -554,28 +556,28 @@ Exemplo:
|
|
|
554
556
|
</div>
|
|
555
557
|
```
|
|
556
558
|
|
|
557
|
-
### Editor de
|
|
559
|
+
### Editor de Configuração (Settings Panel)
|
|
558
560
|
|
|
559
|
-
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.
|
|
560
562
|
|
|
561
563
|
### Notas
|
|
562
564
|
|
|
563
|
-
- O caminho virtual (CDK Virtual Scroll) permanece sendo o owner da rolagem vertical; o viewport horizontal
|
|
564
|
-
-
|
|
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.
|
|
565
567
|
- Para grids alternativos (ex.: Kendo), as mesmas regras de `max-content`/`min-width: 100%` se aplicam ao elemento de tabela interno.
|
|
566
568
|
|
|
567
|
-
##
|
|
569
|
+
## Virtualização (CDK)
|
|
568
570
|
|
|
569
|
-
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).
|
|
570
572
|
|
|
571
573
|
- Propriedades:
|
|
572
|
-
- `itemHeight`: altura da linha (px);
|
|
574
|
+
- `itemHeight`: altura da linha (px); padrão 44.
|
|
573
575
|
- `bufferSize`: itens adicionais de buffer.
|
|
574
|
-
- `minContainerHeight`: altura
|
|
575
|
-
- `strategy`: `fixed` | `dynamic` (atual uso visual
|
|
576
|
-
-
|
|
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).
|
|
577
579
|
|
|
578
|
-
##
|
|
580
|
+
## Paginação (posição/estilo)
|
|
579
581
|
|
|
580
582
|
### Concept Usage
|
|
581
583
|
|
|
@@ -587,16 +589,16 @@ Quando `behavior.virtualization.enabled` estiver ativo, as linhas da tabela são
|
|
|
587
589
|
- `behavior.pagination.position`: `top` | `bottom` | `both`.
|
|
588
590
|
- `behavior.pagination.style`: `default` | `compact` (aplica classe de estilo no paginator).
|
|
589
591
|
|
|
590
|
-
Nota sobre
|
|
591
|
-
- 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`.
|
|
592
594
|
- O mesmo vale para `behavior.sorting.strategy`.
|
|
593
595
|
|
|
594
596
|
## Duplo clique na linha
|
|
595
597
|
|
|
596
|
-
Ative em Comportamento
|
|
598
|
+
Ative em Comportamento → Interação.
|
|
597
599
|
|
|
598
600
|
- Output: `rowDoubleClick` com payload `{ action: string; row: any }`.
|
|
599
|
-
-
|
|
601
|
+
- Ação: `edit` | `view` | `custom` (quando `custom`, use `customAction` no Behavior para definir o identificador).
|
|
600
602
|
|
|
601
603
|
Exemplo de uso (template do host):
|
|
602
604
|
|
|
@@ -615,16 +617,16 @@ onRowDoubleClick(evt: { action: string; row: any }) {
|
|
|
615
617
|
} else if (evt.action === 'view') {
|
|
616
618
|
// abrir detalhe somente leitura
|
|
617
619
|
} else {
|
|
618
|
-
//
|
|
620
|
+
// ação customizada
|
|
619
621
|
}
|
|
620
622
|
}
|
|
621
623
|
```
|
|
622
624
|
|
|
623
|
-
##
|
|
625
|
+
## Ordenação inicial (defaultSort)
|
|
624
626
|
|
|
625
627
|
- Configure em `behavior.sorting.defaultSort`.
|
|
626
|
-
- Aceita objeto
|
|
627
|
-
- 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).
|
|
628
630
|
|
|
629
631
|
Exemplos:
|
|
630
632
|
|
|
@@ -649,20 +651,20 @@ sorting: {
|
|
|
649
651
|
}
|
|
650
652
|
```
|
|
651
653
|
|
|
652
|
-
|
|
653
|
-
|
|
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.
|
|
654
656
|
|
|
655
|
-
### Roadmap /
|
|
657
|
+
### Roadmap / migração de multiSort
|
|
656
658
|
|
|
657
659
|
- Curto prazo: `multiSort` segue schema-only no runtime.
|
|
658
|
-
-
|
|
659
|
-
- 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).
|
|
660
662
|
|
|
661
|
-
## Coluna de
|
|
663
|
+
## Coluna de ações (sticky)
|
|
662
664
|
|
|
663
|
-
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.
|
|
664
666
|
|
|
665
|
-
- Fixe a coluna de
|
|
667
|
+
- Fixe a coluna de ações no inÃcio/fim configurando `actions.row.sticky`:
|
|
666
668
|
|
|
667
669
|
```ts
|
|
668
670
|
actions: {
|
|
@@ -675,11 +677,11 @@ actions: {
|
|
|
675
677
|
}
|
|
676
678
|
```
|
|
677
679
|
|
|
678
|
-
|
|
680
|
+
Observação: em modo virtualizado, sticky pode ter limitações dependendo do layout.
|
|
679
681
|
|
|
680
682
|
## Colunas de dados (sticky)
|
|
681
683
|
|
|
682
|
-
Fixe colunas
|
|
684
|
+
Fixe colunas especÃficas no inÃcio/fim usando `columns[].sticky`:
|
|
683
685
|
|
|
684
686
|
```ts
|
|
685
687
|
columns: [
|
|
@@ -690,28 +692,28 @@ columns: [
|
|
|
690
692
|
```
|
|
691
693
|
|
|
692
694
|
- Valores aceitos: `true` | `'start'` | `'end'`.
|
|
693
|
-
- `true` equivale a `'start'` (fixa no
|
|
695
|
+
- `true` equivale a `'start'` (fixa no inÃcio).
|
|
694
696
|
- Dica: combine com `width` para evitar jitter de layout.
|
|
695
697
|
|
|
696
698
|
Onde configurar no Editor Visual:
|
|
697
699
|
|
|
698
|
-
- Aba
|
|
699
|
-
- 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â€.
|
|
700
702
|
|
|
701
|
-
##
|
|
703
|
+
## 🔒 Verificação de Schema (ETag) e Notificações (somente em customização)
|
|
702
704
|
|
|
703
|
-
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`).
|
|
704
706
|
|
|
705
707
|
### Comportamento
|
|
706
708
|
|
|
707
709
|
- Primeira vez (sem colunas):
|
|
708
710
|
- 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
|
|
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.
|
|
713
715
|
|
|
714
|
-
### Diagrama:
|
|
716
|
+
### Diagrama: Verificação de Schema via ETag
|
|
715
717
|
|
|
716
718
|
```mermaid
|
|
717
719
|
sequenceDiagram
|
|
@@ -728,15 +730,15 @@ sequenceDiagram
|
|
|
728
730
|
PT->>PT: Persiste config + meta (serverHash, lastVerifiedAt)
|
|
729
731
|
end
|
|
730
732
|
|
|
731
|
-
opt
|
|
733
|
+
opt Próximas vezes (colunas existentes)
|
|
732
734
|
PT->>API: GET /schemas/filtered?path=... (If-None-Match: "<serverHash>")
|
|
733
|
-
alt Igual (sem
|
|
735
|
+
alt Igual (sem mudanças)
|
|
734
736
|
API-->>PT: 304 Not Modified (sem body)
|
|
735
737
|
PT->>PT: Atualiza lastVerifiedAt; segue usando config
|
|
736
738
|
else Diferente (mudou)
|
|
737
739
|
API-->>PT: 200 OK (com ETag/X-Schema-Hash)
|
|
738
740
|
PT->>PT: Atualiza serverHash + lastVerifiedAt; schemaOutdated=true
|
|
739
|
-
Note over PT: Em
|
|
741
|
+
Note over PT: Em customização: mostrar banner/snackbar + badge e CTA “Reconciliarâ€
|
|
740
742
|
end
|
|
741
743
|
end
|
|
742
744
|
```
|
|
@@ -749,30 +751,30 @@ sequenceDiagram
|
|
|
749
751
|
- `autoOpenSettingsOnOutdated: boolean = false`
|
|
750
752
|
- Outputs:
|
|
751
753
|
- `schemaStatusChange: { outdated: boolean; serverHash?: string; lastVerifiedAt?: string; trigger?: string; tableId?: string }`
|
|
752
|
-
- Emitido tanto na
|
|
754
|
+
- Emitido tanto na verificação leve (304/200) quanto no bootstrap do schema (primeira carga via `loadSchema()`).
|
|
753
755
|
- `metadataChange: { trigger: string; meta: any; tableId?: string }`
|
|
754
|
-
- 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.
|
|
755
757
|
|
|
756
758
|
### Fallback Global (opcional)
|
|
757
759
|
|
|
758
|
-
- Quando os inputs do widget permanecem com os valores
|
|
759
|
-
- Cadeia de
|
|
760
|
-
-
|
|
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.
|
|
761
763
|
|
|
762
|
-
###
|
|
764
|
+
### Persistência por hash (ConfigStorage)
|
|
763
765
|
|
|
764
|
-
- `schemaIgnore:{tableId}:{serverHash}`
|
|
765
|
-
- `schemaSnooze:{tableId}:{serverHash}`
|
|
766
|
-
- `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.
|
|
767
769
|
|
|
768
770
|
### UX
|
|
769
771
|
|
|
770
|
-
- Banner inline (acima da tabela) quando `schemaOutdated=true`, com
|
|
771
|
-
- Reconciliar (abre
|
|
772
|
+
- Banner inline (acima da tabela) quando `schemaOutdated=true`, com ações:
|
|
773
|
+
- Reconciliar (abre Configurações)
|
|
772
774
|
- Lembrar depois (snooze)
|
|
773
775
|
- Ignorar (silenciar para este hash)
|
|
774
|
-
- Snackbar opcional (uma vez por hash) com
|
|
775
|
-
- Badge
|
|
776
|
+
- Snackbar opcional (uma vez por hash) com ação “Reconciliarâ€.
|
|
777
|
+
- Badge “!†na engrenagem com tooltip contextual: “Schema do servidor mudou — Reconciliarâ€.
|
|
776
778
|
|
|
777
779
|
### Exemplo de uso
|
|
778
780
|
|
|
@@ -798,56 +800,56 @@ onSchemaStatus(ev: { outdated: boolean; serverHash?: string; lastVerifiedAt?: st
|
|
|
798
800
|
|
|
799
801
|
### Notas
|
|
800
802
|
|
|
801
|
-
- A
|
|
802
|
-
- 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.
|
|
803
805
|
|
|
804
|
-
## Filtro
|
|
806
|
+
## Filtro Avançado (PraxisFilter)
|
|
805
807
|
|
|
806
|
-
### Boas
|
|
808
|
+
### Boas práticas para estabilidade
|
|
807
809
|
|
|
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
|
|
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.
|
|
813
815
|
|
|
814
|
-
###
|
|
816
|
+
### Diagnóstico e Logs
|
|
815
817
|
|
|
816
|
-
- 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.
|
|
817
819
|
- Quando desabilitado (default), o carregador reduz a verbosidade de logs.
|
|
818
820
|
|
|
819
821
|
### Comportamento do carregador (v20+)
|
|
820
822
|
|
|
821
|
-
- Guardas internas evitam re-
|
|
822
|
-
- Se o snapshot do
|
|
823
|
-
- 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.
|
|
824
826
|
|
|
825
827
|
### Testes
|
|
826
828
|
|
|
827
|
-
-
|
|
828
|
-
-
|
|
829
|
-
- 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.
|
|
830
832
|
- Recriar componentes quando `controlType` muda.
|
|
831
833
|
|
|
832
834
|
### Fluxo de Schema e Metadados
|
|
833
835
|
|
|
834
836
|
- O `PraxisFilter` busca schema do DTO de filtro via `/schemas/filtered` com ETag/If-None-Match
|
|
835
837
|
e emite `metaChanged` com `{ schemaId, serverHash, context }`.
|
|
836
|
-
- O schema
|
|
837
|
-
- 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.
|
|
838
840
|
|
|
839
|
-
###
|
|
841
|
+
### Resolução da chave primária (idField)
|
|
840
842
|
|
|
841
843
|
- 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
|
|
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.
|
|
847
849
|
|
|
848
850
|
### Diagramas
|
|
849
851
|
|
|
850
|
-
Fluxo (Grid):
|
|
852
|
+
Fluxo (Grid): adoção de schema e idField
|
|
851
853
|
|
|
852
854
|
```mermaid
|
|
853
855
|
sequenceDiagram
|
|
@@ -867,7 +869,7 @@ sequenceDiagram
|
|
|
867
869
|
PT->>PT: construir colunas e renderizar
|
|
868
870
|
```
|
|
869
871
|
|
|
870
|
-
Fluxo (Delete):
|
|
872
|
+
Fluxo (Delete): resolução do identificador
|
|
871
873
|
|
|
872
874
|
```mermaid
|
|
873
875
|
sequenceDiagram
|
|
@@ -876,7 +878,7 @@ sequenceDiagram
|
|
|
876
878
|
participant GS as GenericCrudService
|
|
877
879
|
participant API as Backend
|
|
878
880
|
|
|
879
|
-
PT->>PT: key = getIdField() (
|
|
881
|
+
PT->>PT: key = getIdField() (precedência)
|
|
880
882
|
PT->>PT: id = getNestedPropertyValue(row, key)
|
|
881
883
|
PT->>GS: delete(id)
|
|
882
884
|
GS->>API: DELETE {resource}/{id}
|
|
@@ -885,17 +887,17 @@ sequenceDiagram
|
|
|
885
887
|
PT->>PT: fetchData() em modo remoto
|
|
886
888
|
```
|
|
887
889
|
|
|
888
|
-
### Troubleshooting
|
|
890
|
+
### Troubleshooting rápido (idField)
|
|
889
891
|
|
|
890
|
-
- A
|
|
891
|
-
- O ID
|
|
892
|
-
- 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.
|
|
893
895
|
|
|
894
896
|
### Uso com Dados Locais (Client-Side)
|
|
895
897
|
|
|
896
|
-
Se
|
|
897
|
-
Importante: o modo local
|
|
898
|
-
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.
|
|
899
901
|
|
|
900
902
|
```typescript
|
|
901
903
|
import { PraxisTable } from "@praxisui/table";
|
|
@@ -908,7 +910,7 @@ import { TableConfig } from "@praxisui/core";
|
|
|
908
910
|
template: ` <praxis-table [config]="tableConfig" [data]="employees"> </praxis-table> `,
|
|
909
911
|
})
|
|
910
912
|
export class ExampleComponent {
|
|
911
|
-
//
|
|
913
|
+
// Configuração de colunas e comportamento é obrigatória neste modo
|
|
912
914
|
tableConfig: TableConfig = {
|
|
913
915
|
columns: [
|
|
914
916
|
{ field: "id", header: "ID", type: "number" },
|
|
@@ -919,57 +921,57 @@ export class ExampleComponent {
|
|
|
919
921
|
pagination: { enabled: true, pageSize: 10 },
|
|
920
922
|
sorting: { enabled: true },
|
|
921
923
|
filtering: { enabled: true },
|
|
922
|
-
localDataMode: { enabled: true }, //
|
|
924
|
+
localDataMode: { enabled: true }, // obrigatório para fluxo local oficial
|
|
923
925
|
},
|
|
924
926
|
};
|
|
925
927
|
|
|
926
928
|
employees = [
|
|
927
|
-
{ id: 1, name: "
|
|
929
|
+
{ id: 1, name: "João Silva", email: "joao@empresa.com" },
|
|
928
930
|
{ id: 2, name: "Maria Santos", email: "maria@empresa.com" },
|
|
929
931
|
// ... mais dados
|
|
930
932
|
];
|
|
931
933
|
}
|
|
932
934
|
```
|
|
933
935
|
|
|
934
|
-
##
|
|
936
|
+
## âš™ï¸ Fluxo de Paginação e Filtros (Server-Side)
|
|
935
937
|
|
|
936
|
-
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`.
|
|
937
939
|
|
|
938
|
-
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.
|
|
939
941
|
|
|
940
|
-
###
|
|
942
|
+
### Versão Pedagógica de Alto NÃvel
|
|
941
943
|
|
|
942
|
-
Esta
|
|
944
|
+
Esta é a leitura adequada para documentação pública e landing pages.
|
|
943
945
|
|
|
944
946
|
```mermaid
|
|
945
947
|
sequenceDiagram
|
|
946
|
-
participant Usuario as
|
|
948
|
+
participant Usuario as Usuário
|
|
947
949
|
participant Tabela as praxis-table
|
|
948
950
|
participant Frontend as GenericCrudService
|
|
949
951
|
participant Backend as API Praxis
|
|
950
952
|
participant Banco as Banco de Dados
|
|
951
953
|
|
|
952
|
-
Usuario->>Tabela: muda
|
|
953
|
-
Tabela->>Tabela: consolida filterCriteria +
|
|
954
|
+
Usuario->>Tabela: muda página, ordena ou aplica filtro
|
|
955
|
+
Tabela->>Tabela: consolida filterCriteria + paginação + sort
|
|
954
956
|
Tabela->>Frontend: filter(criteria, pageable)
|
|
955
957
|
Frontend->>Backend: POST /api/.../filter?page&size&sort
|
|
956
958
|
Backend->>Banco: executa consulta filtrada e paginada
|
|
957
|
-
Banco-->>Backend: retorna
|
|
958
|
-
Backend-->>Frontend: responde com
|
|
959
|
+
Banco-->>Backend: retorna página de resultados
|
|
960
|
+
Backend-->>Frontend: responde com página de DTOs
|
|
959
961
|
Frontend-->>Tabela: entrega Page<T>
|
|
960
|
-
Tabela->>Tabela: atualiza linhas,
|
|
962
|
+
Tabela->>Tabela: atualiza linhas, paginação e estado visual
|
|
961
963
|
```
|
|
962
964
|
|
|
963
|
-
Leitura
|
|
965
|
+
Leitura pedagógica:
|
|
964
966
|
|
|
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
|
|
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.
|
|
969
971
|
|
|
970
|
-
###
|
|
972
|
+
### Versão Detalhada e Fiel ao Runtime Atual
|
|
971
973
|
|
|
972
|
-
Esta
|
|
974
|
+
Esta versão documenta o fluxo real do `praxis-table`, do `praxis-filter`, do `GenericCrudService` e do `praxis-metadata-starter`.
|
|
973
975
|
|
|
974
976
|
```mermaid
|
|
975
977
|
sequenceDiagram
|
|
@@ -997,12 +999,12 @@ sequenceDiagram
|
|
|
997
999
|
Crud-->>Filtro: metadata de filtro
|
|
998
1000
|
end
|
|
999
1001
|
|
|
1000
|
-
alt
|
|
1002
|
+
alt paginação
|
|
1001
1003
|
Tabela->>Tabela: onPageChange(pageIndex, pageSize)
|
|
1002
|
-
else
|
|
1004
|
+
else ordenação
|
|
1003
1005
|
Tabela->>Tabela: onSortChange(active, direction)
|
|
1004
1006
|
Tabela->>Tabela: reseta pageIndex = 0
|
|
1005
|
-
else filtro
|
|
1007
|
+
else filtro avançado
|
|
1006
1008
|
Filtro-->>Tabela: submit/change/clear
|
|
1007
1009
|
Tabela->>Tabela: onAdvancedFilterSubmit(criteria)
|
|
1008
1010
|
end
|
|
@@ -1015,7 +1017,7 @@ sequenceDiagram
|
|
|
1015
1017
|
Crud->>Controller: POST /filter?page&size&sort
|
|
1016
1018
|
Note over Crud,Controller: body = filterCriteria JSON
|
|
1017
1019
|
|
|
1018
|
-
Controller->>Controller:
|
|
1020
|
+
Controller->>Controller: lê page,size,sort de query params
|
|
1019
1021
|
Controller->>Controller: PageableBuilder.from(page,size,sort,...)
|
|
1020
1022
|
Controller->>Service: filterMappedWithIncludeIds(filterDTO, pageable, includeIds, toDto)
|
|
1021
1023
|
|
|
@@ -1035,56 +1037,56 @@ sequenceDiagram
|
|
|
1035
1037
|
|
|
1036
1038
|
### Pontos-Chave do Fluxo Real
|
|
1037
1039
|
|
|
1038
|
-
1. **`resourcePath`
|
|
1039
|
-
2. **O filtro
|
|
1040
|
-
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`.
|
|
1041
1043
|
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
|
|
1044
|
+
5. **A coluna ordenada pode mapear para `sortField`**: o `active` da UI não é necessariamente o campo final enviado ao backend.
|
|
1043
1045
|
|
|
1044
|
-
##
|
|
1046
|
+
## 🎨 Edição Visual da Tabela: O Poder do Low-Code
|
|
1045
1047
|
|
|
1046
|
-
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"`.
|
|
1047
1049
|
|
|
1048
|
-
A seguir, veja os principais recursos que
|
|
1050
|
+
A seguir, veja os principais recursos que você pode configurar visualmente:
|
|
1049
1051
|
|
|
1050
1052
|
### 1. Gerenciamento de Colunas
|
|
1051
1053
|
|
|
1052
|
-
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:
|
|
1053
1055
|
|
|
1054
|
-
- **Reordenar com Arrastar e Soltar:** Simplesmente clique e arraste uma coluna para a
|
|
1055
|
-
- **Alterar Visibilidade:** Use a caixa de
|
|
1056
|
-
- **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.
|
|
1057
1059
|
|
|
1058
|
-
### 2.
|
|
1060
|
+
### 2. Transformação de Dados Sem Código
|
|
1059
1061
|
|
|
1060
|
-
Converta dados brutos em
|
|
1062
|
+
Converta dados brutos em informações claras e formatadas para o usuário.
|
|
1061
1063
|
|
|
1062
|
-
- **
|
|
1063
|
-
- **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".
|
|
1064
1066
|
|
|
1065
|
-
### 3. Colunas Calculadas com
|
|
1067
|
+
### 3. Colunas Calculadas com Fórmulas Visuais
|
|
1066
1068
|
|
|
1067
1069
|
Crie novas colunas dinamicamente a partir de dados existentes, sem precisar programar.
|
|
1068
1070
|
|
|
1069
|
-
- **Concatenar Texto:** Crie uma "Coluna Calculada", escolha a
|
|
1070
|
-
- **Realizar
|
|
1071
|
-
- **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.
|
|
1072
1074
|
|
|
1073
|
-
### 4.
|
|
1075
|
+
### 4. Formatação Condicional (Regras de Estilo)
|
|
1074
1076
|
|
|
1075
|
-
Destaque
|
|
1077
|
+
Destaque informações importantes aplicando estilos que mudam com base nos dados da linha.
|
|
1076
1078
|
|
|
1077
|
-
- **Crie Regras Visuais:** Na
|
|
1078
|
-
- **Defina a
|
|
1079
|
-
- **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.
|
|
1080
1082
|
|
|
1081
1083
|
### 5. Comportamentos da Tabela
|
|
1082
1084
|
|
|
1083
|
-
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:
|
|
1084
1086
|
|
|
1085
|
-
- **Ativar/Desativar
|
|
1086
|
-
- **Controlar
|
|
1087
|
-
- **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.
|
|
1088
1090
|
|
|
1089
1091
|
### Editores Especializados
|
|
1090
1092
|
|
|
@@ -1093,7 +1095,7 @@ Habilite e configure as funcionalidades centrais da tabela com um clique. Na aba
|
|
|
1093
1095
|
```typescript
|
|
1094
1096
|
import { BehaviorConfigEditorComponent } from '@praxisui/table';
|
|
1095
1097
|
|
|
1096
|
-
// Usar como componente standalone para
|
|
1098
|
+
// Usar como componente standalone para edição especÃfica
|
|
1097
1099
|
<behavior-config-editor
|
|
1098
1100
|
[config]="tableConfig"
|
|
1099
1101
|
(configChange)="onBehaviorChange($event)">
|
|
@@ -1112,9 +1114,9 @@ import { ColumnsConfigEditorComponent } from '@praxisui/table';
|
|
|
1112
1114
|
</columns-config-editor>
|
|
1113
1115
|
```
|
|
1114
1116
|
|
|
1115
|
-
##
|
|
1117
|
+
## 🔧 Configuração Avançada
|
|
1116
1118
|
|
|
1117
|
-
### Performance com
|
|
1119
|
+
### Performance com Virtualização
|
|
1118
1120
|
|
|
1119
1121
|
```typescript
|
|
1120
1122
|
const highVolumeConfig: TableConfig = {
|
|
@@ -1162,7 +1164,7 @@ const accessibleConfig: TableConfig = {
|
|
|
1162
1164
|
};
|
|
1163
1165
|
```
|
|
1164
1166
|
|
|
1165
|
-
###
|
|
1167
|
+
### Aparência Customizada
|
|
1166
1168
|
|
|
1167
1169
|
```typescript
|
|
1168
1170
|
const styledConfig: TableConfig = {
|
|
@@ -1195,7 +1197,7 @@ const styledConfig: TableConfig = {
|
|
|
1195
1197
|
};
|
|
1196
1198
|
```
|
|
1197
1199
|
|
|
1198
|
-
##
|
|
1200
|
+
## 🎯 Event Handling
|
|
1199
1201
|
|
|
1200
1202
|
### Eventos da Tabela
|
|
1201
1203
|
|
|
@@ -1213,7 +1215,7 @@ const styledConfig: TableConfig = {
|
|
|
1213
1215
|
</praxis-table>
|
|
1214
1216
|
```
|
|
1215
1217
|
|
|
1216
|
-
###
|
|
1218
|
+
### Implementação dos Handlers
|
|
1217
1219
|
|
|
1218
1220
|
```typescript
|
|
1219
1221
|
export class MyComponent {
|
|
@@ -1240,25 +1242,25 @@ export class MyComponent {
|
|
|
1240
1242
|
}
|
|
1241
1243
|
```
|
|
1242
1244
|
|
|
1243
|
-
##
|
|
1245
|
+
## ðŸ› ï¸ Utilitários e Helpers
|
|
1244
1246
|
|
|
1245
1247
|
### Helper Functions
|
|
1246
1248
|
|
|
1247
1249
|
```typescript
|
|
1248
1250
|
import { createDefaultTableConfig, isValidTableConfig, cloneTableConfig, mergeTableConfigs } from "@praxisui/core";
|
|
1249
1251
|
|
|
1250
|
-
// Criar
|
|
1252
|
+
// Criar configuração padrão
|
|
1251
1253
|
const defaultConfig = createDefaultTableConfig();
|
|
1252
1254
|
|
|
1253
|
-
// Validar
|
|
1255
|
+
// Validar configuração
|
|
1254
1256
|
if (isValidTableConfig(myConfig)) {
|
|
1255
|
-
//
|
|
1257
|
+
// Configuração válida
|
|
1256
1258
|
}
|
|
1257
1259
|
|
|
1258
|
-
// Clonar
|
|
1260
|
+
// Clonar configuração
|
|
1259
1261
|
const clonedConfig = cloneTableConfig(originalConfig);
|
|
1260
1262
|
|
|
1261
|
-
// Merge
|
|
1263
|
+
// Merge configurações
|
|
1262
1264
|
const mergedConfig = mergeTableConfigs(baseConfig, overrides);
|
|
1263
1265
|
```
|
|
1264
1266
|
|
|
@@ -1272,10 +1274,10 @@ export class MyComponent {
|
|
|
1272
1274
|
constructor(private configService: TableConfigService) {}
|
|
1273
1275
|
|
|
1274
1276
|
ngOnInit() {
|
|
1275
|
-
// Usar
|
|
1277
|
+
// Usar serviço para gerenciar configuração
|
|
1276
1278
|
this.configService.setConfig(this.tableConfig);
|
|
1277
1279
|
|
|
1278
|
-
// Verificar recursos
|
|
1280
|
+
// Verificar recursos disponÃveis
|
|
1279
1281
|
// No runtime atual, multiSort permanece schema-only.
|
|
1280
1282
|
const hasMultiSort = false;
|
|
1281
1283
|
const hasBulkActions = this.configService.isFeatureEnabled('bulkActions');
|
|
@@ -1283,7 +1285,7 @@ export class MyComponent {
|
|
|
1283
1285
|
}
|
|
1284
1286
|
```
|
|
1285
1287
|
|
|
1286
|
-
##
|
|
1288
|
+
## 🧪 Testes
|
|
1287
1289
|
|
|
1288
1290
|
### Unit Tests
|
|
1289
1291
|
|
|
@@ -1322,11 +1324,11 @@ describe("PraxisTable", () => {
|
|
|
1322
1324
|
});
|
|
1323
1325
|
```
|
|
1324
1326
|
|
|
1325
|
-
##
|
|
1327
|
+
## 📋 Migration Guide
|
|
1326
1328
|
|
|
1327
|
-
###
|
|
1329
|
+
### Migração da Arquitetura V1/V2
|
|
1328
1330
|
|
|
1329
|
-
Se
|
|
1331
|
+
Se você estava usando as versões anteriores com dual architecture, aqui estão as principais mudanças:
|
|
1330
1332
|
|
|
1331
1333
|
#### Imports Atualizados
|
|
1332
1334
|
|
|
@@ -1338,14 +1340,14 @@ import { TableConfigV1, TableConfigV2, TableConfigUnified } from "@praxisui/core
|
|
|
1338
1340
|
import { TableConfig } from "@praxisui/core";
|
|
1339
1341
|
```
|
|
1340
1342
|
|
|
1341
|
-
####
|
|
1343
|
+
#### Serviços Removidos
|
|
1342
1344
|
|
|
1343
1345
|
```typescript
|
|
1344
1346
|
// Antes
|
|
1345
1347
|
import { TableConfigAdapterService } from "@praxisui/table";
|
|
1346
1348
|
|
|
1347
|
-
// Depois -
|
|
1348
|
-
// Uso direto da
|
|
1349
|
+
// Depois - Não mais necessário
|
|
1350
|
+
// Uso direto da configuração
|
|
1349
1351
|
```
|
|
1350
1352
|
|
|
1351
1353
|
#### Tipos Simplificados
|
|
@@ -1360,29 +1362,29 @@ config: TableConfig;
|
|
|
1360
1362
|
|
|
1361
1363
|
### Breaking Changes
|
|
1362
1364
|
|
|
1363
|
-
1. **TableConfigAdapterService**: Removido - uso direto da
|
|
1365
|
+
1. **TableConfigAdapterService**: Removido - uso direto da configuração
|
|
1364
1366
|
2. **TableConfigMigrationService**: Simplificado - funcionalidade integrada
|
|
1365
1367
|
3. **TableConfigUnified**: Renomeado para `TableConfig`
|
|
1366
1368
|
|
|
1367
|
-
##
|
|
1369
|
+
## 🔠Troubleshooting
|
|
1368
1370
|
|
|
1369
1371
|
### Problemas Comuns
|
|
1370
1372
|
|
|
1371
|
-
####
|
|
1373
|
+
#### Configuração não está funcionando
|
|
1372
1374
|
|
|
1373
1375
|
```typescript
|
|
1374
|
-
// Verificar se a
|
|
1376
|
+
// Verificar se a configuração é válida
|
|
1375
1377
|
import { isValidTableConfig } from "@praxisui/core";
|
|
1376
1378
|
|
|
1377
1379
|
if (!isValidTableConfig(myConfig)) {
|
|
1378
|
-
console.error("
|
|
1380
|
+
console.error("Configuração inválida:", myConfig);
|
|
1379
1381
|
}
|
|
1380
1382
|
```
|
|
1381
1383
|
|
|
1382
1384
|
#### Performance Issues
|
|
1383
1385
|
|
|
1384
1386
|
```typescript
|
|
1385
|
-
// Habilitar
|
|
1387
|
+
// Habilitar virtualização para grandes datasets
|
|
1386
1388
|
const config: TableConfig = {
|
|
1387
1389
|
// ...
|
|
1388
1390
|
performance: {
|
|
@@ -1398,7 +1400,7 @@ const config: TableConfig = {
|
|
|
1398
1400
|
#### Acessibilidade
|
|
1399
1401
|
|
|
1400
1402
|
```typescript
|
|
1401
|
-
// Garantir que acessibilidade
|
|
1403
|
+
// Garantir que acessibilidade está habilitada
|
|
1402
1404
|
const config: TableConfig = {
|
|
1403
1405
|
// ...
|
|
1404
1406
|
accessibility: {
|
|
@@ -1408,35 +1410,35 @@ const config: TableConfig = {
|
|
|
1408
1410
|
};
|
|
1409
1411
|
```
|
|
1410
1412
|
|
|
1411
|
-
##
|
|
1413
|
+
## 📚 API Reference
|
|
1412
1414
|
|
|
1413
1415
|
### Interfaces Principais
|
|
1414
1416
|
|
|
1415
1417
|
#### TableConfig
|
|
1416
1418
|
|
|
1417
|
-
Interface principal para
|
|
1419
|
+
Interface principal para configuração da tabela.
|
|
1418
1420
|
|
|
1419
1421
|
#### ColumnDefinition
|
|
1420
1422
|
|
|
1421
|
-
Define
|
|
1423
|
+
Define configuração individual de colunas.
|
|
1422
1424
|
|
|
1423
1425
|
#### TableBehaviorConfig
|
|
1424
1426
|
|
|
1425
|
-
|
|
1427
|
+
Configurações de comportamento (paginação, ordenação, etc.).
|
|
1426
1428
|
|
|
1427
1429
|
#### TableAppearanceConfig
|
|
1428
1430
|
|
|
1429
|
-
|
|
1431
|
+
Configurações de aparência visual.
|
|
1430
1432
|
|
|
1431
|
-
Para
|
|
1433
|
+
Para documentação completa da API, consulte `projects/praxis-core/README.md`.
|
|
1432
1434
|
|
|
1433
|
-
##
|
|
1435
|
+
## 🤠Contribuição
|
|
1434
1436
|
|
|
1435
1437
|
### Como Contribuir
|
|
1436
1438
|
|
|
1437
1439
|
1. Fork o projeto
|
|
1438
1440
|
2. Crie branch para feature (`git checkout -b feature/nova-funcionalidade`)
|
|
1439
|
-
3. Commit
|
|
1441
|
+
3. Commit mudanças (`git commit -m 'Add: nova funcionalidade'`)
|
|
1440
1442
|
4. Push para branch (`git push origin feature/nova-funcionalidade`)
|
|
1441
1443
|
5. Abra Pull Request
|
|
1442
1444
|
|
|
@@ -1444,12 +1446,12 @@ Para documentação completa da API, consulte `projects/praxis-core/README.md`.
|
|
|
1444
1446
|
|
|
1445
1447
|
- Seguir Angular Style Guide
|
|
1446
1448
|
- Adicionar testes para novas features
|
|
1447
|
-
- Manter
|
|
1449
|
+
- Manter documentação atualizada
|
|
1448
1450
|
- Usar TypeScript strict mode
|
|
1449
1451
|
|
|
1450
|
-
##
|
|
1452
|
+
## 🔠Exemplo de Integração com PraxisFilter
|
|
1451
1453
|
|
|
1452
|
-
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.
|
|
1453
1455
|
|
|
1454
1456
|
```html
|
|
1455
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>
|
|
@@ -1464,16 +1466,16 @@ onFilter(dto: any) {
|
|
|
1464
1466
|
}
|
|
1465
1467
|
```
|
|
1466
1468
|
|
|
1467
|
-
###
|
|
1469
|
+
### âš™ï¸ Configuração do Filtro
|
|
1468
1470
|
|
|
1469
|
-
O `PraxisFilter` pode ser configurado por inputs/JSON de
|
|
1470
|
-
visual por
|
|
1471
|
-
Quando
|
|
1472
|
-
`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:
|
|
1473
1475
|
|
|
1474
|
-
- **alwaysVisibleFields**
|
|
1475
|
-
- **alwaysVisibleFieldMetadataOverrides**
|
|
1476
|
-
- **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
|
|
1477
1479
|
|
|
1478
1480
|
```ts
|
|
1479
1481
|
@ViewChild(PraxisFilter) filter!: PraxisFilter;
|
|
@@ -1483,100 +1485,100 @@ abrirConfiguracoes() {
|
|
|
1483
1485
|
}
|
|
1484
1486
|
```
|
|
1485
1487
|
|
|
1486
|
-
Ao aplicar ou salvar, as escolhas
|
|
1488
|
+
Ao aplicar ou salvar, as escolhas são validadas contra os metadados
|
|
1487
1489
|
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
|
|
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
|
|
1491
1493
|
consistente.
|
|
1492
1494
|
|
|
1493
|
-
###
|
|
1495
|
+
### 🔖 Mini‑guia: Atalhos do Filtro (tags)
|
|
1494
1496
|
|
|
1495
|
-
Atalhos
|
|
1497
|
+
Atalhos são “chips†que guardam um conjunto de filtros (DTO) para reuso rápido.
|
|
1496
1498
|
|
|
1497
1499
|
- Criar/Salvar
|
|
1498
|
-
- Modal (
|
|
1499
|
-
- Gaveta (Drawer): o Adapter recebe `allowSaveTags?`, `i18nSaveAsShortcut?` e `onSaveShortcut?` (opcionais). O host deve exibir o
|
|
1500
|
-
- 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`).
|
|
1501
1503
|
- Aplicar
|
|
1502
1504
|
- Clique/Enter no chip aplica imediatamente `tag.patch` (substitui o estado atual), emite `submit` e persiste.
|
|
1503
|
-
- O chip ativo
|
|
1505
|
+
- O chip ativo é destacado (cor/borda + Ãcone de “checkâ€) quando o DTO atual é igual ao patch do atalho.
|
|
1504
1506
|
- Editar/Renomear
|
|
1505
|
-
- Apenas atalhos do
|
|
1507
|
+
- Apenas atalhos do usuário exibem Ãcone de lápis. Predefinidos mostram Ãcone de “cadeado†(somente leitura).
|
|
1506
1508
|
- Excluir (com Undo)
|
|
1507
|
-
-
|
|
1508
|
-
- 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.
|
|
1509
1511
|
- i18n
|
|
1510
|
-
- Chaves
|
|
1512
|
+
- Chaves úteis: `saveAsShortcut`, `renameShortcut`, `removeShortcut`, `shortcutSaved`, `shortcutRemoved`, `undo`, `readonlyShortcut`.
|
|
1511
1513
|
|
|
1512
|
-
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.
|
|
1513
1515
|
|
|
1514
1516
|
### Novos Inputs/Outputs (PraxisFilter)
|
|
1515
1517
|
|
|
1516
1518
|
- Inputs (efetivos apenas quando `enableCustomization = true`):
|
|
1517
|
-
- `enableCustomization: boolean`
|
|
1518
|
-
- `notifyIfOutdated: 'inline' | 'snackbar' | 'both' | 'none' = 'both'`
|
|
1519
|
-
- `snoozeMs: number = 86400000`
|
|
1520
|
-
- `autoOpenSettingsOnOutdated: boolean = false`
|
|
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.
|
|
1521
1523
|
- Output:
|
|
1522
|
-
- `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).
|
|
1523
1525
|
|
|
1524
1526
|
#### Fallback Global (opcional)
|
|
1525
1527
|
|
|
1526
|
-
- Quando os inputs do componente permanecem com os valores
|
|
1527
|
-
- Cadeia de
|
|
1528
|
-
- 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.
|
|
1529
1531
|
|
|
1530
|
-
Notas
|
|
1531
|
-
-
|
|
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`).
|
|
1532
1534
|
- 304: atualiza `lastVerifiedAt`; emite `schemaStatusChange(outdated=false)`.
|
|
1533
|
-
- 200: atualiza `serverHash/lastVerifiedAt`; marca `outdated=true` apenas quando em
|
|
1534
|
-
- 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).
|
|
1535
1537
|
|
|
1536
|
-
##
|
|
1538
|
+
## Formatação de Colunas (format)
|
|
1537
1539
|
|
|
1538
|
-
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`.
|
|
1539
1541
|
|
|
1540
1542
|
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`
|
|
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.
|
|
1544
1546
|
|
|
1545
1547
|
Nota de plataforma:
|
|
1546
|
-
- o contrato
|
|
1547
|
-
- 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.
|
|
1548
1550
|
|
|
1549
|
-
Tipos e
|
|
1551
|
+
Tipos e padrões de `format`:
|
|
1550
1552
|
- number (DecimalPipe)
|
|
1551
|
-
-
|
|
1553
|
+
- Padrões: `minInt.minFrac-maxFrac`
|
|
1552
1554
|
- Exemplos: `1.0-0`, `1.2-2`, `1.0-3|nosep` (remove separador de milhar)
|
|
1553
1555
|
- currency (CurrencyPipe)
|
|
1554
1556
|
- Sintaxe: `CURRENCY|DISPLAY|DECIMALS[|nosep]`
|
|
1555
1557
|
- Exemplos: `BRL|symbol|2`, `USD|code|0`, `EUR|symbol|2|nosep`
|
|
1556
1558
|
- percentage (PercentPipe/DecimalPipe)
|
|
1557
1559
|
- Sem multiplicador: `1.0-0` (PercentPipe)
|
|
1558
|
-
- Multiplicar por 100: `1.1-1|x100` (
|
|
1560
|
+
- Multiplicar por 100: `1.1-1|x100` (DecimalPipe×100 + `%`)
|
|
1559
1561
|
- date (DatePipe)
|
|
1560
1562
|
- Tokens Angular: `shortDate`, `mediumDate`, `longDate`, `fullDate`, `short`, `shortTime`
|
|
1561
|
-
-
|
|
1562
|
-
- string (
|
|
1563
|
+
- Padrões customizados: `dd/MM/yyyy`, `yyyy-MM-dd`, `dd/MM/yyyy HH:mm`
|
|
1564
|
+
- string (transformações + truncamento)
|
|
1563
1565
|
- Transform: `uppercase` | `lowercase` | `titlecase` | `capitalize` | `none`
|
|
1564
1566
|
- Transform + truncar: `<transform>|truncate|<max>|<suffix>`
|
|
1565
1567
|
- Exemplos: `uppercase|truncate|50|...`, `titlecase`
|
|
1566
|
-
- boolean (pr
|
|
1568
|
+
- boolean (pré-definidos ou custom)
|
|
1567
1569
|
- Presets: `true-false` | `yes-no` | `active-inactive` | `on-off` | `enabled-disabled`
|
|
1568
1570
|
- Custom: `custom|Verdadeiro|Falso`
|
|
1569
1571
|
|
|
1570
1572
|
Exemplos de ColumnDefinition:
|
|
1571
1573
|
```ts
|
|
1572
|
-
{ field: 'salario', type: 'currency', format: 'BRL|symbol|2', header: '
|
|
1574
|
+
{ field: 'salario', type: 'currency', format: 'BRL|symbol|2', header: 'Salário' }
|
|
1573
1575
|
{ field: 'desconto', type: 'percentage', format: '1.1-1|x100', header: 'Desconto' }
|
|
1574
1576
|
{ field: 'criadoEm', type: 'date', format: 'dd/MM/yyyy', header: 'Criado em' }
|
|
1575
|
-
{ field: 'nome', type: 'string', format: 'titlecase|truncate|32
|
|
1577
|
+
{ field: 'nome', type: 'string', format: 'titlecase|truncate|32|…', header: 'Nome' }
|
|
1576
1578
|
{ field: 'ativo', type: 'boolean', format: 'yes-no', header: 'Ativo' }
|
|
1577
1579
|
```
|
|
1578
1580
|
|
|
1579
|
-
Exemplos com defaults
|
|
1581
|
+
Exemplos com defaults implÃcitos por `type + localization`:
|
|
1580
1582
|
```ts
|
|
1581
1583
|
{
|
|
1582
1584
|
localization: {
|
|
@@ -1586,22 +1588,22 @@ Exemplos com defaults implícitos por `type + localization`:
|
|
|
1586
1588
|
number: { decimalSeparator: ',', thousandsSeparator: '.', defaultPrecision: 2, negativeSign: '-', negativeSignPosition: 'before' },
|
|
1587
1589
|
},
|
|
1588
1590
|
columns: [
|
|
1589
|
-
{ field: 'salario', type: 'currency', header: '
|
|
1591
|
+
{ field: 'salario', type: 'currency', header: 'Salário' },
|
|
1590
1592
|
{ field: 'criadoEm', type: 'date', header: 'Criado em' },
|
|
1591
1593
|
{ field: 'taxa', type: 'percentage', header: 'Taxa' },
|
|
1592
1594
|
],
|
|
1593
1595
|
}
|
|
1594
1596
|
```
|
|
1595
1597
|
|
|
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
|
|
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.
|
|
1602
1604
|
- Quando `config.localization.number` estiver presente, a tabela respeita `decimalSeparator`, `thousandsSeparator`, `defaultPrecision`, `negativeSign` e `negativeSignPosition` em number/currency/percentage.
|
|
1603
1605
|
|
|
1604
|
-
Exemplos
|
|
1606
|
+
Exemplos práticos no workspace (rotas):
|
|
1605
1607
|
- Regras Visuais (Simples): `/table-rules-simple`
|
|
1606
1608
|
- Regras Visuais (Complexas): `/table-rules-complex`
|
|
1607
1609
|
|
|
@@ -1642,22 +1644,22 @@ A11y, seguranca e performance:
|
|
|
1642
1644
|
- URL da imagem sanitizada (bloqueia esquemas perigosos)
|
|
1643
1645
|
- imagem com `loading=\"lazy\"`
|
|
1644
1646
|
|
|
1645
|
-
##
|
|
1647
|
+
## 📊 Roadmap
|
|
1646
1648
|
|
|
1647
|
-
###
|
|
1649
|
+
### Próximas Versões
|
|
1648
1650
|
|
|
1649
|
-
-
|
|
1650
|
-
-
|
|
1651
|
-
-
|
|
1652
|
-
-
|
|
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)
|
|
1653
1655
|
|
|
1654
|
-
##
|
|
1656
|
+
## 📄 Licença
|
|
1655
1657
|
|
|
1656
|
-
Apache-2.0
|
|
1658
|
+
Apache-2.0 — consulte `LICENSE` na raiz do workspace para detalhes.
|
|
1657
1659
|
|
|
1658
1660
|
---
|
|
1659
1661
|
|
|
1660
1662
|
**Parte do Praxis UI Workspace**
|
|
1661
|
-
**
|
|
1663
|
+
**Versão**: 2.0.0 (Unified Architecture)
|
|
1662
1664
|
**Compatibilidade**: Angular 18+
|
|
1663
1665
|
|