Buscar K
Aparência
Aparência
No fim deste caminho você tem um Widget Svelte com os dez maiores vendedores, cada um com uma barra proporcional ao valor vendido. O Widget mostra carregando, erro e "sem dados" quando é o caso, funciona no tema claro e no escuro, e um clique num vendedor filtra o Dashboard inteiro.
Vendas, com as colunas VENDEDOR e VALOR; troque pelos nomes da sua.export let, {#if}, {#each}, on:click.No Catálogo de widgets, escolha Svelte e arraste para a grade. Dê pelo menos 4 colunas e 4 linhas: o ranking precisa de altura.
O Widget aparece vazio, porque ainda não tem código.
No configurador, aba Geral, em Código, clique em Editar Código.
O editor abre com uma aba, Main.svelte, vazia. No topo ficam Gerar com IA, Testar e Salvar e Sair.
Cole o script abaixo em Main.svelte. Ele consulta a Aplicação quando o Widget monta e guarda o resultado já formatado.
<script>
import { onMount } from 'svelte';
export let app;
const VENDEDOR = '[Vendas]."VENDEDOR":AGP';
const VALOR = '[Vendas]."VALOR":SUM';
let carregando = true;
let erro = null;
let linhas = [];
onMount(async () => {
try {
const res = await app.fetchMatrix({
columns: [VENDEDOR, VALOR],
orderBy: [`${VALOR}:DESC`],
limit: 10,
});
const maior = Math.max(...res.Result.map((r) => Number(r[1]) || 0), 1);
linhas = res.Result.map(([nome, valor]) => ({
nome,
texto: app.formatValue(valor, res.Columns[1]),
largura: Math.round(((Number(valor) || 0) / maior) * 100),
}));
} catch (e) {
erro = e?.message ?? String(e);
} finally {
carregando = false;
}
});
</script>Três escolhas desse script valem para qualquer Widget:
'[Vendas]."VALOR":SUM'), nunca pelo número da coluna, que muda de um Tenant para outro. Todo campo leva um sufixo, como :AGP ou :SUM; veja Referência de coluna.app.formatValue, que aplica a máscara da coluna (moeda, casas decimais) no idioma de quem vê. Número cru na tela fica diferente de todo o resto do Dashboard.try/catch. Um erro que escapa do onMount não aparece em lugar nenhum: o Widget fica em branco e ninguém sabe por quê.Você não passa os filtros do Dashboard: app.fetchMatrix já aplica os da barra e os pré-aplicados do Widget.
Abaixo do script, no mesmo arquivo, cole o markup:
{#if carregando}
<div class="flex h-full items-center justify-center text-sm text-slate-500 dark:text-navy-300">
Carregando…
</div>
{:else if erro}
<div class="flex h-full items-center justify-center p-4">
<p class="text-sm text-red-600 dark:text-red-400">{erro}</p>
</div>
{:else if linhas.length === 0}
<div class="flex h-full items-center justify-center text-sm text-slate-500 dark:text-navy-300">
Sem dados no período
</div>
{:else}
<ul class="w-full space-y-1 p-4 text-slate-800 dark:text-navy-100">
{#each linhas as l}
<li>
<button
class="w-full rounded px-2 py-1 text-left hover:bg-slate-100 dark:hover:bg-navy-700"
on:click={() => alternar(l.nome)}
>
<div class="flex justify-between text-sm">
<span>{l.nome}</span>
<span class="font-mono">{l.texto}</span>
</div>
<div class="mt-1 h-1.5 rounded bg-slate-200 dark:bg-navy-600">
<div class="h-1.5 rounded bg-indigo-500" style="width: {l.largura}%"></div>
</div>
</button>
</li>
{/each}
</ul>
{/if}Cada cor tem o par dark:, e no escuro as superfícies e os textos usam a escala navy, a mesma do Dashboard. Sem o par, o Widget fica claro no meio de um Dashboard escuro. A raiz da lista não leva h-full com overflow-auto: a célula do Widget já controla a altura e a rolagem, e essa combinação na raiz corta o conteúdo na exportação para PDF. As outras regras de tema e tamanho estão em Boas práticas.
O markup chama alternar, que ainda não existe. Acrescente esta função dentro do <script>, depois do onMount:
function alternar(nome) {
const coluna = app.columnFromString(VENDEDOR);
if (!coluna) return;
const atual = app.getFilter(coluna);
if (atual && atual.value === nome) {
app.addFilter(coluna, '=', false); // remove o filtro
} else {
app.addFilter(coluna, '=', nome);
}
}app.addFilter põe o filtro na barra do Dashboard, e todos os Widgets se atualizam, inclusive este. Valor false tira o filtro daquela coluna. Uma coluna que não está entre os filtros permitidos do Dashboard é ignorada sem aviso; veja Filtros.
Clique em Testar. O botão mostra "Compilando..." e, se o código compila, aparece "Código compilado com sucesso!". Se não compila, a mensagem diz a linha. Sintaxe de Svelte 5 como onclick={...} no lugar de on:click={...} nem sempre dá erro: o clique só não faz nada. Veja Boas práticas.
Clique em Salvar e Sair e salve o Dashboard. O Widget mostra "Carregando…" e, em seguida, o ranking.
VALOR.VALOR por um nome que não existe e testar, o Widget mostra a mensagem de erro da consulta no lugar do ranking.Gerar com IA abre um painel ao lado do código. Em Descreva o código que você quer gerar, escreva o que o Widget deve fazer ("Ex: Crie um gráfico de barras com os dados de vendas") e clique em Gerar. A IA conhece as tabelas da Aplicação e as regras do app. A mudança chega em Revisão de Mudanças, com o que muda linha a linha: Inserir código aplica, Rejeitar descarta. Copiar Prompt leva o mesmo contexto para uma IA externa.
Quando um Widget já salvo mostra Erro de compilação no editor do Dashboard, Corrigir com IA abre o editor com o erro já enviado ao painel.