Exemplos de Praxis Table

O percurso começa em resourcePath e avança para colunas, renderers, filtros, ações, expansion e authoring. Cada exemplo aproxima a demonstração, o contrato principal e a superfície de dados usada pela tabela.

Os previews ao vivo da página Angular requerem JavaScript; esta projeção publica os exemplos e o código fonte estáticos.

1. Uma tabela remota completa com uma tag

Declare um tableId estável e aponte para um resourcePath publicado pela API. A tabela resolve schema, dados reais, paginação e affordances de customização sem copiar colunas no template Angular.

O que você vê: Funcionários aparecem com o mesmo shape do recurso remoto: colunas vindas do contrato, registros paginados e nenhuma coluna declarada no Angular do host.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/funcionarios/filter GET /schemas/filtered?path=/api/human-resources/funcionarios/filter&operation=post&schemaType=response

Arquivos

  • example.html (html)
  • example.ts (ts)
  • schema.http (http)

example.html

<praxis-table
  tableId="employees-table"
  resourcePath="human-resources/funcionarios"
  [enableCustomization]="true"
></praxis-table>

Aprenda neste exemplo

  • O contrato mínimo é intencional: tableId identifica a instância; resourcePath conecta a tabela ao recurso remoto.
  • /schemas/filtered descreve os campos da resposta usada pela tabela para iniciar colunas, rótulos e tipos.
  • /filter entrega os registros paginados e preserva o backend como fonte de verdade para consulta.
  • Com enableCustomization ativo, o runtime exibe as affordances de editor; sem ele, a tabela continua operacional em modo leitura.

2. Primeira customização por JSON

Depois da primeira tag, entra o primeiro TableConfig: um JSON pequeno que escolhe colunas, rótulos, renderers e densidade sem transformar a tela em código de grid.

O que você vê: O JSON pega a grade do recurso de funcionários e reduz a leitura: remove campos secundários, reordena as colunas principais, encurta rótulos e transforma o booleano ativo em badge de status.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/funcionarios/filter GET /schemas/filtered?path=/api/human-resources/funcionarios/filter&operation=post&schemaType=response

Arquivos

  • table.config.json (json)
  • example.html (html)
  • schema.http (http)

table.config.json

{
  "columns": [
    {
      "field": "avatarUrl",
      "header": "Foto",
      "width": "84px",
      "align": "center",
      "renderer": {
        "type": "avatar",
        "avatar": {
          "srcField": "avatarUrl",
          "initialsField": "nomeCompleto",
          "shape": "circle",
          "size": 32
        }
      }
    },
    { "field": "nomeCompleto", "header": "Funcionário", "width": "220px" },
    { "field": "cargoNome", "header": "Cargo", "width": "240px" },
    { "field": "departamentoNome", "header": "Departamento", "width": "220px" },
    {
      "field": "ativo",
      "header": "Status",
      "renderer": {
        "type": "badge",
        "badge": { "textField": "ativo", "color": "primary" }
      }
    },
    { "field": "dataAdmissao", "header": "Admissão", "type": "date" }
  ],
  "toolbar": {
    "visible": true,
    "position": "top",
    "title": "Funcionários",
    "subtitle": "Schema remoto refinado por TableConfig",
    "appearance": {
      "variant": "outlined",
      "density": "comfortable",
      "divider": "start"
    },
    "columnsVisibility": { "enabled": true }
  },
  "behavior": {
    "pagination": {
      "enabled": true,
      "pageSize": 8,
      "pageSizeOptions": [8, 10, 25, 50],
      "showFirstLastButtons": true,
      "showPageNumbers": true,
      "showPageInfo": true,
      "position": "bottom",
      "style": "default",
      "strategy": "client"
    },
    "sorting": {
      "enabled": true,
      "multiSort": false,
      "strategy": "client",
      "showSortIndicators": true,
      "indicatorPosition": "end",
      "allowClearSort": true
    }
  },
  "appearance": { "density": "comfortable" }
}

Aprenda neste exemplo

  • A tag da página continua enxuta: [config]="employeeTableConfig" aponta para um documento declarativo.
  • O desenvolvedor pode versionar esse JSON ou permitir que o editor publique variações por perfil, tenant ou ambiente.
  • A configuração não duplica o DTO; ela seleciona e refina campos que o contrato remoto já conhece.

3. Modo local com pipeline completo

O modo local mostra o mesmo pipeline com dados em memória. Ele existe para protótipos, demos isoladas e testes visuais, sempre com localDataMode explícito.

O que você vê: Dados locais passam pelo pipeline oficial de colunas, paginação, sorting, renderização e ações por linha.

Modo: local

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: Sem endpoint obrigatório: usa [data] + behavior.localDataMode.enabled = true.

Arquivos

  • example.html (html)
  • example.ts (ts)
  • table.config.json (json)

table.config.json

{
  "behavior": {
    "localDataMode": { "enabled": true },
    "pagination": { "enabled": true, "pageSize": 10 },
    "sorting": { "enabled": true }
  },
	  "columns": [
	    { "field": "nomeCompleto", "header": "Nome" },
	    { "field": "cargoNome", "header": "Cargo" },
	    { "field": "ativo", "header": "Status", "renderer": { "type": "badge" } }
	  ],
	  "actions": {
	    "row": {
	      "enabled": true,
	      "display": "icons",
	      "trigger": "always",
	      "actions": [
	        { "id": "profile", "label": "Perfil", "action": "profile" },
	        {
	          "id": "reactivate",
	          "label": "Reativar",
	          "action": "reactivate",
	          "tooltip": "Coletar motivo e confirmar reativação",
	          "visibleWhen": { "===": [{ "var": "ativo" }, false] }
	        },
	        {
	          "id": "audit",
	          "label": "Auditar",
	          "action": "audit",
	          "visibleWhen": { "===": [{ "var": "ativo" }, true] }
	        }
	      ]
	    }
	  }
	}

Aprenda neste exemplo

  • Modo local não é atalho para fugir do contrato; é uma fonte de dados explícita.
  • O mesmo preview pode provar renderers, densidade, paginação, ordenação e ações de linha sem backend.
  • visibleWhen usa JSON Logic para trocar Reativar por Auditar conforme o estado de cada funcionário.
  • Quando existir API publicada, resourcePath continua sendo o caminho preferencial.

4. Colunas, tipos e formatação

Tipos, formatos, cálculos, regras visuais e animações ficam no contrato da coluna e da linha. A tabela transforma dados financeiros em leitura operacional sem pipes ou ifs espalhados no template.

O que você vê: Folhas de pagamento exibem moeda, percentual, data, compose, progress, computed, badge condicional, destaque de célula, destaque de linha e animação discreta para risco.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/folhas-pagamento/filter GET /schemas/filtered?path=/api/human-resources/folhas-pagamento/filter&operation=post&schemaType=response

Arquivos

  • table.config.json (json)
  • example.html (html)
  • localization.json (json)

table.config.json

{
  "appearance": {
    "density": "compact",
    "animations": {
      "enabled": true,
      "duration": 800,
      "easing": "ease-in-out",
      "specific": { "row": true, "cell": true }
    }
  },
  "localization": {
    "locale": "pt-BR",
    "direction": "ltr",
    "currency": { "code": "BRL", "symbol": "R$", "position": "before", "spacing": true, "precision": 2 }
  },
  "behavior": {
    "pagination": { "enabled": true, "pageSize": 5 },
    "sorting": { "enabled": true }
  },
  "columns": [
    {
      "field": "colaborador",
      "header": "Colaborador",
      "renderer": {
        "type": "compose",
        "compose": {
          "layout": { "direction": "row", "gap": 8, "align": "center", "wrap": true },
          "items": [
            { "type": "avatar", "avatar": { "initialsField": "colaborador", "shape": "circle", "size": 32 } },
            { "type": "value", "field": "colaborador" },
            { "type": "chip", "chip": { "textField": "centroCusto", "variant": "soft" } }
          ]
        }
      }
    },
    { "field": "salarioBase", "header": "Salário", "type": "currency", "format": "BRL|symbol|2" },
    { "field": "bonus", "header": "Bônus", "type": "currency", "format": "BRL|symbol|2" },
    { "field": "desconto", "header": "Desconto", "type": "percentage", "format": "1.1-1|x100" },
    {
      "field": "liquido",
      "header": "Líquido calculado",
      "type": "currency",
      "format": "BRL|symbol|2",
      "computed": {
        "expression": { "-": [{ "+": [{ "var": "salarioBase" }, { "var": "bonus" }] }, { "var": "descontoValor" }] },
        "outputType": "number",
        "dependencies": ["salarioBase", "bonus", "descontoValor"]
      }
    },
    {
      "field": "riscoFolha",
      "header": "Risco",
      "renderer": { "type": "progress", "progress": { "valueExpr": "= riscoFolha", "showLabel": true } },
      "conditionalStyles": [
        { "condition": { ">=": [{ "var": "riscoFolha" }, 80] }, "cssClass": "row--warning" }
      ],
      "conditionalRenderers": [
        {
          "condition": { ">=": [{ "var": "riscoFolha" }, 90] },
          "animation": { "preset": "warning-attention", "trigger": "onAppear", "repeat": 3 }
        }
      ]
    },
    {
      "field": "status",
      "header": "Status",
      "renderer": { "type": "badge", "badge": { "textField": "status", "variant": "soft" } },
      "conditionalRenderers": [
        {
          "condition": { "===": [{ "var": "status" }, "Aprovada"] },
          "renderer": { "type": "badge", "badge": { "text": "Aprovada", "color": "success", "variant": "soft", "icon": "check_circle" } }
        },
        {
          "condition": { "===": [{ "var": "status" }, "Revisar"] },
          "renderer": { "type": "badge", "badge": { "text": "Revisar", "color": "warn", "variant": "soft", "icon": "priority_high" } },
          "animation": { "preset": "pulse-soft", "trigger": "onAppear", "repeat": "once" }
        }
      ]
    },
    { "field": "dataPagamento", "header": "Pagamento", "type": "date", "format": "dd/MM/yyyy" }
  ],
  "rowConditionalStyles": [
    { "condition": { "===": [{ "var": "status" }, "Bloqueada"] }, "cssClass": "row--danger" },
    { "condition": { ">=": [{ "var": "riscoFolha" }, 80] }, "cssClass": "row--warning" }
  ],
  "rowConditionalRenderers": [
    {
      "condition": { "===": [{ "var": "status" }, "Bloqueada"] },
      "tooltip": { "text": "Folha bloqueada para auditoria antes do pagamento." },
      "animation": { "preset": "risk-critical", "trigger": "onAppear", "intensity": "subtle", "repeat": "once" }
    }
  ]
}

5. Catálogo de renderers ricos

Renderers transformam valores em representação visual. Avatar, badge, chip, icon, image, progress e compose entram no mesmo contrato que define as colunas.

O que você vê: Um perfil operacional com identidade visual, status e indicadores renderizados sem template customizado.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/vw-perfil-heroi/filter GET /schemas/filtered?path=/api/human-resources/vw-perfil-heroi/filter&operation=post&schemaType=response

Arquivos

  • table.config.json (json)
  • renderer.catalog.json (json)
  • example.html (html)

table.config.json

{
  "columns": [
    {
      "field": "nome",
      "header": "Pessoa",
      "renderer": {
        "type": "avatar",
        "avatar": { "srcField": "fotoUrl", "initialsField": "nome", "shape": "circle", "size": 32 }
      }
    },
    {
      "field": "status",
      "header": "Status",
      "renderer": { "type": "badge", "badge": { "textField": "status", "color": "primary" } }
    }
  ]
}

Aprenda neste exemplo

  • Renderers ricos reduzem templates customizados por coluna.
  • O editor pode trocar apresentação sem alterar datasource ou componente host.
  • Cada renderer preserva semântica de campo, formato e fallback no contrato.

6. Micro-layout CRM com compose

Compose junta avatar, nome, função, status e sinais operacionais em uma célula densa. A composição continua declarativa e editável.

O que você vê: Uma linha compacta carrega identidade, status e sinais visuais sem criar componente de célula específico.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/vw-perfil-heroi/filter GET /schemas/filtered?path=/api/human-resources/vw-perfil-heroi/filter&operation=post&schemaType=response

Arquivos

  • table.config.json (json)
  • example.html (html)
  • editor.patch.json (json)

table.config.json

{
  "columns": [
    {
      "field": "perfil",
      "header": "Perfil",
      "renderer": {
        "type": "compose",
        "compose": {
          "layout": { "direction": "row", "gap": 8, "wrap": false },
          "items": [
            { "type": "avatar", "avatar": { "srcField": "fotoUrl", "initialsField": "nome" } },
            { "type": "badge", "badge": { "textField": "status", "color": "primary" } },
            { "type": "chip", "chip": { "textField": "categoria" } }
          ]
        }
      }
    }
  ]
}

Aprenda neste exemplo

  • Compose é ideal para listas operacionais com identidade, cargo, status e sinais curtos.
  • A célula fica rica sem acoplar a tela a um componente de domínio.
  • O host muda composição, campo e layout sem redeploy quando a configuração é governada.

7. Superfícies ricas enterprise

Microvisualizações aparecem em células normais, a expansão abre contexto governado e um formulário em modo apresentação mostra o detalhe selecionado.

O que você vê: Uma operação densa com SLA, tendência, execução, delta, fluxo e risco em pequenos gráficos, além de detail row e formulário de leitura.

Modo: local

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: Contrato local: TableConfig.columns[].renderer.microVisualization Contrato local: behavior.expansion.detail.source.mode=inline Contrato local: FormConfig + presentationModeGlobal

Arquivos

  • table.config.json (json)
  • detail-form.config.json (json)
  • example.html (html)

table.config.json

{
  "columns": [
    {
      "field": "slaValue",
      "header": "SLA",
      "renderer": {
        "type": "microVisualization",
        "microVisualization": {
          "visualization": {
            "kind": "bullet",
            "surface": "table-cell",
            "valueExpr": "row.slaValue",
            "targetExpr": "row.target",
            "fallbackTextExpr": { "cat": ["SLA ", { "var": "row.slaValue" }, "%"] }
          }
        }
      }
    }
  ],
  "behavior": {
    "localDataMode": { "enabled": true },
    "expansion": {
      "enabled": true,
      "detail": {
        "schemaContract": {
          "kind": "praxis.detail.schema",
          "allowedNodes": ["card", "list", "timeline", "chartRef", "actionBar"]
        },
        "source": { "mode": "inline" }
      }
    }
  },
  "detailNode": {
    "type": "chartRef",
    "renderMode": "inline",
    "schemaId": "operation-risk-trend",
    "chartDocumentRef": "charts/operation-risk-trend",
    "emptyText": "Fallback: abrir o chart no cockpit do host."
  }
}

Aprenda neste exemplo

  • Células normais podem carregar pequenos gráficos sem EChartsOption na coluna.
  • A expansão adiciona contexto sem virar HTML livre dentro da tabela.
  • O formulário em apresentação materializa o mesmo registro como detalhe governado.

8. Avatar e status operacional

Avatar cobre identidade com fallback: imagem quando existir, iniciais quando faltar foto, tamanho, shape e cores controlados pela configuração.

O que você vê: A prévia compara foto circular, iniciais arredondadas coloridas, avatar compacto e status operacional sem código de template por coluna.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/funcionarios/filter GET /schemas/filtered?path=/api/human-resources/funcionarios/filter&operation=post&schemaType=response

Arquivos

  • table.config.json (json)
  • example.html (html)
  • editor.patch.json (json)

table.config.json

{
  "columns": [
    {
      "field": "fotoUrl",
      "header": "Foto circular",
      "renderer": {
        "type": "avatar",
        "avatar": { "srcField": "fotoUrl", "initialsField": "nome", "shape": "circle", "size": 44 }
      }
    },
    {
      "field": "avatarIniciais",
      "header": "Iniciais coloridas",
      "renderer": {
        "type": "avatar",
        "avatar": {
          "initialsField": "nome",
          "shape": "rounded",
          "size": 36,
          "backgroundColor": "#2563eb",
          "textColor": "#eff6ff"
        }
      }
    }
  ]
}

Aprenda neste exemplo

  • Avatar não precisa ser uma coluna de imagem manual.
  • Status e identidade podem conviver na mesma tabela com renderers declarativos.
  • O exemplo compara variações para mostrar que tamanho, forma e cor são authoráveis.

8. Colunas calculadas

Colunas calculadas derivam leituras a partir dos dados recebidos. O exemplo mostra saldo aberto sem duplicar expressao no template Angular.

O que você vê: Indicadores de risco calculam saldo aberto a partir de indenizações e total pago.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/risk-intelligence/vw-indicadores-incidentes/filter GET /schemas/filtered?path=/api/risk-intelligence/vw-indicadores-incidentes/filter&operation=post&schemaType=response

Arquivos

  • table.config.json (json)
  • computed.notes.md (md)
  • example.html (html)

table.config.json

{
  "columns": [
    { "field": "totalIndenizacoes", "header": "Indenizações", "type": "currency", "format": "BRL|symbol|2" },
    { "field": "totalPago", "header": "Pago", "type": "currency", "format": "BRL|symbol|2" },
    {
      "field": "saldoAberto",
      "header": "Saldo aberto",
      "type": "currency",
      "format": "BRL|symbol|2",
      "computed": {
        "expression": "totalIndenizacoes - totalPago",
        "outputType": "number",
        "dependencies": ["totalIndenizacoes", "totalPago"]
      }
    }
  ]
}

Aprenda neste exemplo

  • Coluna calculada evita duplicar expressão no template Angular.
  • O cálculo fica auditável dentro do TableConfig.
  • A mesma coluna derivada pode aparecer como valor, badge, progress ou regra visual.

9. Dashboard financeiro

Uma visão de risco pode virar cockpit financeiro quando valores, saldo aberto, severidade e destaque visual ficam juntos na configuração da tabela.

O que você vê: A mesma superfície combina schema remoto, computed fields, progress, renderer condicional, formato monetário, estilo por célula e animação de linha.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/risk-intelligence/vw-indicadores-incidentes/filter POST /api/risk-intelligence/vw-indicadores-incidentes/filter/cursor GET /schemas/filtered?path=/api/risk-intelligence/vw-indicadores-incidentes/filter&operation=post&schemaType=response

Arquivos

  • table.config.json (json)
  • example.html (html)
  • styling.css (css)

table.config.json

{
  "appearance": {
    "density": "compact",
    "animations": { "enabled": true, "specific": { "row": true, "cell": true } }
  },
  "columns": [
    {
      "field": "saldoAberto",
      "header": "Saldo aberto",
      "type": "currency",
      "format": "BRL|symbol|2",
      "computed": {
        "expression": { "-": [{ "var": "totalIndenizacoes" }, { "var": "totalPago" }] },
        "outputType": "number",
        "dependencies": ["totalIndenizacoes", "totalPago"]
      },
      "conditionalStyles": [
        {
          "condition": { ">": [{ "var": "computed.saldoAberto" }, 100000] },
          "style": { "background": "rgba(248, 113, 113, 0.16)", "color": "#fecaca" },
          "tooltip": { "text": "Saldo aberto relevante para acompanhamento financeiro." }
        }
      ]
    },
    {
      "field": "probabilidade",
      "header": "Probabilidade",
      "renderer": {
        "type": "progress",
        "progress": { "valueExpr": "= probabilidade * 100", "showLabel": true }
      }
    },
    {
      "field": "severidade",
      "header": "Severidade",
      "renderer": { "type": "badge", "badge": { "textField": "severidade", "variant": "soft" } },
      "conditionalRenderers": [
        {
          "condition": { "===": [{ "var": "severidade" }, "CRITICA"] },
          "renderer": { "type": "badge", "badge": { "text": "CRÍTICA", "color": "warn", "variant": "soft", "icon": "priority_high" } }
        }
      ]
    }
  ],
  "rowConditionalStyles": [
    { "condition": { "===": [{ "var": "severidade" }, "CRITICA"] }, "cssClass": "row--danger" }
  ],
  "rowConditionalRenderers": [
    {
      "condition": { "===": [{ "var": "severidade" }, "CRITICA"] },
      "animation": { "preset": "risk-critical", "trigger": "onAppear", "intensity": "subtle", "repeat": "once" }
    }
  ]
}

Aprenda neste exemplo

  • A mesma tabela pode evoluir de grade para cockpit sem trocar componente.
  • Financeiro, risco e operação podem compartilhar a mesma linguagem de renderização.
  • O contrato reúne apresentação, cálculo e alerta visual de forma versionável.

10. Formatação condicional com JSON Logic

Condições visuais ficam declarativas. JSON Logic permite destacar linhas e células por score, risco ou faixa de valor sem ifs no template.

O que você vê: Ranking de reputação destaca registros fortes ou críticos por score, sem espalhar if no template.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/vw-ranking-reputacao/filter GET /schemas/filtered?path=/api/human-resources/vw-ranking-reputacao/filter&operation=post&schemaType=response

Arquivos

  • rules.json (json)
  • table.config.json (json)
  • example.html (html)

rules.json

{
  "rowConditionalStyles": [
    { "condition": { ">=": [{ "var": "scoreReputacao" }, 90] }, "cssClass": "row--success" },
    { "condition": { "<": [{ "var": "scoreReputacao" }, 40] }, "cssClass": "row--danger" },
    {
      "condition": {
        "and": [
          { ">=": [{ "var": "incidentes" }, 3] },
          { "<": [{ "var": "scoreReputacao" }, 70] }
        ]
      },
      "cssClass": "row--warning"
    }
  ],
  "appearance": {
    "animations": {
      "enabled": true,
      "duration": 650,
      "specific": { "row": true, "cell": true }
    }
  }
}

Aprenda neste exemplo

  • Formatação condicional é boa para risco, score, SLA, aging e qualquer sinal operacional recorrente.
  • A mesma regra pode ser editada, versionada e revisada sem recompilar a tela.
  • O backend continua dono da regra de negócio; a tabela governa a leitura visual do estado publicado.

11. Renderers condicionais

A regra também pode trocar o renderer da célula. Score, risco ou status escolhem badge, icon, progress ou compose pelo contrato.

O que você vê: Score, risco ou status alteram badge, icon, progress ou compose sem mudar o template Angular.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/vw-ranking-reputacao/filter GET /schemas/filtered?path=/api/human-resources/vw-ranking-reputacao/filter&operation=post&schemaType=response

Arquivos

  • conditional-renderers.json (json)
  • rules-editor.patch.json (json)
  • example.html (html)

conditional-renderers.json

{
  "columns": [
    {
      "field": "scoreReputacao",
      "header": "Score",
      "conditionalRenderers": [
        {
          "condition": { ">=": [{ "var": "scoreReputacao" }, 90] },
          "renderer": {
            "type": "badge",
            "badge": {
              "text": "Excelente",
              "color": "success",
              "variant": "soft",
              "icon": "workspace_premium"
            }
          },
          "animation": { "preset": "pulse-soft", "trigger": "onAppear", "repeat": "once" }
        },
        {
          "condition": { "<": [{ "var": "scoreReputacao" }, 40] },
          "renderer": {
            "type": "badge",
            "badge": {
              "text": "Crítico",
              "color": "warn",
              "variant": "soft",
              "icon": "priority_high"
            }
          },
          "animation": { "preset": "warning-attention", "trigger": "onAppear", "repeat": "once" }
        }
      ]
    }
  ]
}

Aprenda neste exemplo

  • Não é necessário criar um componente Angular para cada estado visual.
  • O contrato preserva fallback: se nenhuma condição bater, a coluna usa o renderer padrão.
  • Renderer condicional é útil para status, risco, prioridade, tendência, aprovação e qualidade de dados.

12. Rastreador de SLA

SLA combina prioridade, idade e risco em leitura operacional imediata. A tabela deixa claro o que precisa de atenção sem criar uma tela especializada.

O que você vê: Missões agregadas mostram status, prioridade e idade operacional com destaque visual.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/operations/vw-resumo-missoes/filter GET /schemas/filtered?path=/api/operations/vw-resumo-missoes/filter&operation=post&schemaType=response

Arquivos

  • table.config.json (json)
  • sla.rules.json (json)
  • example.html (html)

sla.rules.json

{
  "columns": [
    {
      "field": "ageDays",
      "header": "Idade",
      "computed": { "expression": { "daysSince": [{ "var": "createdAt" }] }, "outputType": "number" }
    }
  ],
  "rowConditionalStyles": [
    { "condition": { ">": [{ "var": "computed.ageDays" }, 5] }, "cssClass": "row--warning" },
    {
      "condition": {
        "and": [
          { "===": [{ "var": "prioridade" }, "CRITICA"] },
          { ">=": [{ "var": "risco" }, 85] }
        ]
      },
      "cssClass": "row--danger"
    }
  ]
}

Aprenda neste exemplo

  • Computed fields servem como ponte entre dado cru e decisão visual.
  • O mesmo valor calculado pode ser exibido, filtrado visualmente e usado em regra condicional.
  • SLA fica legível na primeira leitura: prioridade, idade e risco apontam onde agir.

13. Filtros server-side

Filtro, paginação e sort passam pelo backend da aplicação. A UI materializa multi-selects, lookup, ranges e atalhos publicados por /schemas/filtered.

O que você vê: A tabela usa o DTO real de operations.missoes para exibir status, prioridade, período previsto e ameaça como filtros removíveis na toolbar.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/operations/missoes/filter?page=0&size=20&sort=prioridade,desc GET /schemas/filtered?path=/api/operations/missoes/filter&operation=post&schemaType=request

Arquivos

  • filter.payload.json (json)
  • example.html (html)
  • table.config.json (json)

filter.payload.json

{
  "statusIn": ["PAUSADA", "EM_ANDAMENTO"],
  "prioridadeIn": ["ALTA", "CRITICA"],
  "inicioPrevBetween": {
    "startDate": "2026-04-01T00:00:00Z",
    "endDate": "2026-04-30T23:59:59Z"
  },
  "ameacaId": 8
}

Aprenda neste exemplo

  • Server-side continua dono de filtro, paginação e sort.
  • O botão de adicionar gerencia selectedFieldIds; filtros pré-exibidos podem ser removidos sem duplicar campos.
  • O mesmo contrato alimenta toolbar compacta, painel avançado e payload final enviado para /filter.

14. Filtros inline na toolbar

Campos frequentes aparecem direto na toolbar. O mesmo DTO suporta busca textual, multi-select, lookup, período relativo e ranges sem formulário manual.

O que você vê: Título, status, prioridade, período previsto e preset de início aparecem como controles compactos acima da tabela, com opções vindas do DTO real.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/operations/missoes/filter GET /schemas/filtered?path=/api/operations/missoes/filter&operation=post&schemaType=request POST /api/risk-intelligence/ameacas/options/filter

Arquivos

  • filter.settings.json (json)
  • example.html (html)
  • payload.json (json)

filter.settings.json

{
  "behavior": {
    "filtering": {
      "enabled": true,
      "advancedFilters": {
        "enabled": true,
        "settings": {
          "selectedFieldIds": ["titulo", "statusIn", "prioridadeIn", "inicioPrevBetween", "inicioPrevPreset"],
          "advancedOpenMode": "modal",
          "allowSaveTags": true,
          "changeDebounceMs": 0
        }
      }
    }
  }
}

Aprenda neste exemplo

  • Filtros inline são ótimos para decisões recorrentes, sem esconder o restante do DTO.
  • Campos densos continuam disponíveis no painel avançado pelo mesmo contrato.
  • allowSaveTags permite transformar uma busca útil em atalho reutilizável na toolbar.

15. Configuração de filtro avançado

O filtro avançado mostra ranges, lookups, atalhos salvos e payload auditável como parte da experiência governada da tabela.

O que você vê: O painel avançado pode expor lookup de ameaça, status, prioridade e ranges de início/término sem sobrecarregar a toolbar principal.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/operations/missoes/filter GET /schemas/filtered?path=/api/operations/missoes/filter&operation=post&schemaType=request POST /api/risk-intelligence/ameacas/options/filter

Arquivos

  • filter.payload.json (json)
  • shortcuts.json (json)
  • example.html (html)

filter.payload.json

{
  "statusIn": ["PAUSADA", "EM_ANDAMENTO"],
  "prioridadeIn": ["ALTA", "CRITICA"],
  "ameacaId": 8,
  "inicioPrevBetween": {
    "startDate": "2026-04-01T00:00:00Z",
    "endDate": "2026-04-30T23:59:59Z"
  },
  "fimPrevBetween": {
    "startDate": "2026-04-20T00:00:00Z",
    "endDate": "2026-05-10T23:59:59Z"
  }
}

Aprenda neste exemplo

  • O filtro deixa de ser dois selects soltos e vira uma superfície de consulta governada.
  • O painel avançado acomoda campos densos sem sobrecarregar a toolbar principal.
  • O payload final continua legível para auditoria e compatível com o backend.

16. Seleção e ações em lote

Seleção e bulk action formam um contrato de interação. A tabela captura a intenção, preserva os registros selecionados e abre o fluxo rico da aplicação.

O que você vê: A tabela permite selecionar missões, acionar comandos em lote e abrir ações por linha com contexto estruturado.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/operations/missoes/filter GET /api/operations/missoes/{id}/capabilities GET /schemas/actions?resource=operations.missoes

Arquivos

  • table.config.json (json)
  • example.html (html)
  • bulk-handler.ts (ts)

table.config.json

{
  "behavior": {
    "selection": { "enabled": true, "type": "multiple", "mode": "checkbox" }
  },
  "actions": {
    "row": {
      "enabled": true,
      "display": "buttons",
      "actions": [
        { "id": "summary", "label": "Resumo", "icon": "travel_explore", "action": "summary" },
        { "id": "capabilities", "label": "Capabilities", "icon": "security", "action": "capabilities" }
      ]
    },
    "bulk": {
      "enabled": true,
      "position": "toolbar",
      "actions": [
        { "id": "briefing", "label": "Briefing", "icon": "assignment", "action": "briefing", "minSelections": 1 },
        { "id": "reprioritize", "label": "Repriorizar", "icon": "published_with_changes", "action": "reprioritize", "minSelections": 1 }
      ]
    }
  }
}

Aprenda neste exemplo

  • O clique abre contexto rico com métricas, timeline e registros selecionados.
  • A tabela captura intenção estruturada; a aplicação executa workflow, confirmação e política.
  • O mesmo padrão serve para exportar, aprovar, delegar, auditar ou abrir surfaces do item.

17. Aprovação em lote segura

Ação em lote liga seleção, confirmação, endpoint real e feedback estruturado. A UI mostra a intenção; a aplicação valida e executa.

O que você vê: Um fluxo de briefing ou repriorização recebe a seleção e abre contexto rico antes de executar o workflow.

Modo: integration

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/operations/missoes/filter GET /api/operations/missoes/{id}/capabilities GET /schemas/actions?resource=operations.missoes

Arquivos

  • bulk-handler.ts (ts)
  • confirm-dialog.json (json)
  • workflow-response.json (json)

bulk-handler.ts

onBulkAction(event: { action: string; rows: unknown[] }) {
  if (event.action !== 'briefing' && event.action !== 'reprioritize') return;

  this.dialog.open(MissionWorkflowDialog, {
    data: {
      action: event.action,
      rows: event.rows,
      surface: 'operations.missoes.workflow'
    }
  });

  return this.http.post('/api/operations/missoes/actions/' + event.action, {
    ids: event.rows.map((row: any) => row.id),
    source: 'governed-table-action',
    evidence: {
      selectedCount: event.rows.length,
      priorities: event.rows.map((row: any) => row.prioridade),
      averageRisk: calculateAverageRisk(event.rows)
    }
  });
}

Aprenda neste exemplo

  • A ação em lote não deve executar no escuro: primeiro mostra contexto, risco e escopo.
  • Briefing e repriorização podem compartilhar o mesmo contrato de seleção.
  • A superfície rica ajuda o usuário a confirmar a intenção com confiança.

18. Linha expansível com conteúdo rico

Expansion abre contexto rico abaixo da linha: mediaBlock, detailList, cardGrid, timeline e actionBar aparecem por contrato.

O que você vê: Missões expandem para mostrar resumo, participantes, eventos recentes e ações contextuais.

Modo: quickstart

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/operations/missoes/filter GET /api/operations/missoes/{id}/capabilities GET /schemas/filtered?path=/api/operations/missoes/filter&operation=post&schemaType=response

Arquivos

  • expansion.config.json (json)
  • example.html (html)
  • detail-schema.json (json)

expansion.config.json

{
  "behavior": {
    "expansion": {
      "enabled": true,
      "interaction": { "trigger": "icon", "toggleOnRowClick": false },
      "limits": { "allowMultiple": true, "maxExpandedRows": 2 },
      "detail": {
        "schemaContract": {
          "kind": "praxis.detail.schema",
          "version": "1.0.0",
          "allowedNodes": ["mediaBlock", "cardGrid", "detailList", "timeline", "actionBar"]
        },
        "source": {
          "mode": "inline",
          "inlineSchema": {
            "layout": "stack",
            "items": [
              { "type": "mediaBlock" },
              { "type": "cardGrid", "title": "Resumo operacional" },
              { "type": "detailList", "field": "participantes" },
              { "type": "timeline", "field": "atividade" },
              { "type": "actionBar", "title": "Ações rápidas" }
            ]
          }
        },
        "rendering": { "strategy": "registry", "registryId": "praxis.detail.default" }
      }
    }
  }
}

Aprenda neste exemplo

  • Expansion mostra contexto sem tirar o usuário da tabela.
  • O mesmo contrato pode renderizar cards, listas, timeline, badges, avatares e actions.
  • A surface de detalhe é governada, cacheável e fechada para nós não permitidos.

19. Expansão por hypermedia e capabilities

O detail também pode nascer de _links.capabilities. Quando a aplicação não publica a affordance, a tabela fecha o caminho em vez de inventar contexto.

O que você vê: A tabela resolve surfaces e actions sob demanda ao expandir uma linha autorizada.

Modo: integration

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/operations/missoes/filter GET /api/operations/missoes/{id}/capabilities GET /schemas/surfaces?resource=operations.missoes

Arquivos

  • hypermedia.config.json (json)
  • capabilities.response.json (json)
  • example.html (html)

hypermedia.config.json

{
  "behavior": {
    "expansion": {
      "enabled": true,
      "detail": {
        "schemaContract": {
          "kind": "praxis.detail.schema",
          "version": "1.0.0"
        },
        "source": {
          "mode": "hypermedia",
          "hypermedia": { "rel": "capabilities" }
        },
        "rendering": { "strategy": "registry", "registryId": "praxis.detail.default" }
      }
    }
  }
}

Aprenda neste exemplo

  • Itens diferentes podem publicar surfaces diferentes sem redeploy da tela.
  • A tabela atua como runtime de discovery: ela busca, valida e materializa capabilities.
  • Capabilities agregam actions, views e read projections no contexto do item selecionado.

20. Editor visual de configuração

O editor visual transforma a tabela em superfície authorable: colunas, renderers, filtros, ações, regras, mensagens e aparência mudam em runtime.

O que você vê: O editor visual abre a configuração da tabela, aplica mudanças, salva e reabre sem perder o contrato.

Modo: integration

Preview ao vivo: requer JavaScript para materializar a tabela Angular.

Endpoints: POST /api/human-resources/funcionarios/filter GET /schemas/filtered?path=/api/human-resources/funcionarios/filter&operation=post&schemaType=response Config storage da aplicação para salvar TableAuthoringDocument

Arquivos

  • example.html (html)
  • table-authoring-document.json (json)
  • editor.patch.json (json)

example.html

<praxis-table
  tableId="employees-authorable-table"
  resourcePath="human-resources/funcionarios"
  [enableCustomization]="true"
  (configChange)="persistTableConfig($event)"
></praxis-table>