Tabela de dados
Um layout de força é ruim em três coisas que as pessoas fazem constantemente: ler valores exatos, selecionar em escala e decidir por onde começar. UI.table divide um data dock na parte inferior da tela para responder a todos os três - as linhas do gráfico, classificáveis e selecionáveis.
O loop é tabela para encontrar, tela para entender, barra lateral para ler:
- A tabela é aberta ordenada por solicitações, portanto o serviço mais ocupado é a primeira linha.
- Clique em qualquer título para reclassificar; clique novamente para reverter.
- Clique em uma linha para selecioná-la,
Ctrl+Clickpara adicionar uma, ouShift+Clickpara obter um intervalo na ordem mostrada — então atue no lote com as ações em massa da barra lateral. - Em vez disso, prenda um grupo com elástico na tela e as linhas correspondentes acenderão.
- Limite as linhas dos cabeçalhos - o controle segue a coluna: digite Service, escolha Kind, defina limites em Requests / day. Isso nunca toca a tela: o próprio filtro do gráfico fica com o painel de filtros, então os dois não podem brigar.
- Nodes / Edges alterna o que está listado. CSV e JSON escrevem exatamente o que está na tela - esta guia, essas colunas, esse tipo, esse filtro.
O dock também lista os nós que o gráfico está atualmente ocultando, com uma coluna Visibility informando se um filtro ou uma ocultação manual é responsável - portanto, "23 nós ocultos" é algo que você pode inspecionar em vez de confiar.
Arraste a divisória para redimensioná-la ou dobre-a na barra de cabeçalho com a divisa. Nenhum dos dois move o gráfico: a simulação se ajusta ao contêiner, não à tela, portanto, a abertura e o fechamento do Chrome nunca podem alterar um layout.
Consulte Tabela de dados para o conjunto completo de opções.
// import { ColorPaletteMapper, tableColumns } from 'pivotick'
//
// The data dock comes with `mode: 'full'`, folded to its header bar — click the chevron
// or press Shift+T. `open: true` below starts it expanded instead. Everything here is
// optional; `UI: { mode: 'full' }` alone gets you a dock.
//
// Columns are derived when you don't declare any: the graph-aware ones lead (Label,
// Degree, Visibility) and the data keys follow, ordered by how many nodes carry them.
// They are declared here instead, to put `requests` on the right and give three columns
// a row filter — one of each kind, since the control follows the column's `type`.
// `tableColumns` holds the graph-aware ones — clone one to relabel it.
const options = {
UI: {
mode: 'full',
// Full mode's minimap would sit in the corner this card wants for the dock,
// and the dock is the subject — see the Minimap card for that one.
minimap: false,
// Top-left, because this embed is 560px tall and the dock takes 42% of it: the
// canvas that's left is shorter than the mode rail, so the bottom-left corner has
// no column to give. A bottom-left legend would shrink to its header here.
legend: { position: 'top-left' },
table: {
open: true,
height: 0.42,
// Busiest first — the question you actually arrive with.
sort: { key: 'requests', direction: 'desc' },
columns: [
{ ...tableColumns.label, label: 'Service', filterable: true },
{ key: 'kind', label: 'Kind', type: 'select', filterable: true },
{ key: 'owner', label: 'Owner', type: 'select' },
{ key: 'tier', label: 'Tier', type: 'select' },
{ key: 'requests', label: 'Requests / day', type: 'numberRange', align: 'right', filterable: true },
{ ...tableColumns.degree, label: 'Links' },
],
},
},
// Colour by the same `kind` the table shows, so a row and a dot can be matched by
// eye. Declaring `nodeTypeAccessor` is also what earns the canvas its legend.
render: {
nodeTypeAccessor: (node) => node.getData().kind,
defaultNodeStyle: {
color: (node) => palette.getColor(node.getData().kind),
},
},
}const data = {
nodes: [
{ id: 'api', data: { label: 'api-gateway', kind: 'service', owner: 'Platform', requests: 48200, tier: 'edge' } },
{ id: 'auth', data: { label: 'auth-service', kind: 'service', owner: 'Identity', requests: 31400, tier: 'core' } },
{ id: 'billing', data: { label: 'billing-service', kind: 'service', owner: 'Payments', requests: 8600, tier: 'core' } },
{ id: 'search', data: { label: 'search-service', kind: 'service', owner: 'Discovery', requests: 22750, tier: 'core' } },
{ id: 'users-db', data: { label: 'users-db', kind: 'datastore', owner: 'Identity', requests: 39900, tier: 'data' } },
{ id: 'orders-db', data: { label: 'orders-db', kind: 'datastore', owner: 'Payments', requests: 12300, tier: 'data' } },
{ id: 'index', data: { label: 'search-index', kind: 'datastore', owner: 'Discovery', requests: 20100, tier: 'data' } },
{ id: 'cache', data: { label: 'edge-cache', kind: 'datastore', owner: 'Platform', requests: 51000, tier: 'edge' } },
{ id: 'mailer', data: { label: 'mailer', kind: 'worker', owner: 'Payments', requests: 1450, tier: 'async' } },
{ id: 'reindexer', data: { label: 'reindexer', kind: 'worker', owner: 'Discovery', requests: 980, tier: 'async' } },
],
edges: [
{ from: 'api', to: 'auth', data: { label: 'authenticates' } },
{ from: 'api', to: 'search', data: { label: 'queries' } },
{ from: 'api', to: 'billing', data: { label: 'charges' } },
{ from: 'api', to: 'cache', data: { label: 'reads' } },
{ from: 'auth', to: 'users-db', data: { label: 'reads' } },
{ from: 'billing', to: 'orders-db', data: { label: 'writes' } },
{ from: 'billing', to: 'mailer', data: { label: 'enqueues' } },
{ from: 'search', to: 'index', data: { label: 'reads' } },
{ from: 'reindexer', to: 'index', data: { label: 'writes' } },
{ from: 'reindexer', to: 'orders-db', data: { label: 'reads' } },
],
}