Aller au contenu

Tableau de données ​

UI.table divise un data dock du bas du canevas : les nœuds et les bords du graphique sous la forme d'une grille triable et sélectionnable. Cela existe parce qu'une disposition des forces est structurellement mauvaise dans trois domaines que les gens font constamment : lire des valeurs exactes, sélectionner à grande échelle et déterminer par où commencer.

La boucle prévue est table à trouver, canevas à comprendre, barre latérale à lire : triez par degré pour repérer les hubs, maj-cliquez sur les vingt premiers et agissez dessus avec les actions groupées de la barre latérale.

ts
const options = {
    UI: { mode: 'full' },
}

C'est tout ce qu'il faut. En mode full, le dock se trouve en bas plié sur sa barre d'en-tête ; cliquez sur son chevron — ou appuyez sur Shift+T — pour afficher le tableau. UI.table: false le supprime entièrement.

Il n'y a délibérément aucun bouton dans la barre d'outils pour cela. La barre est le contrôle : les pilules dans la barre supérieure ouvrent toutes quelque chose sur la toile, tandis que le dock est une région divisée qui vous montre déjà son propre chevron.

Le dock est uniquement en mode full : il s'agit d'une ligne de grille à côté de la barre latérale, et les autres modes promettent un canevas sans autant de chrome.

La table ne change rien de ce que vous lui avez demandé

Le dock ne mute rien. Il reflète le graphique et pilote la sélection ; le masquage et l'épinglage restent avec les actions groupées de la barre latérale, et la restauration d'un nœud caché reste avec le panneau de filtrage. Ce que le dock ajoute, c'est un bien meilleur instrument pour construire la sélection sur laquelle ceux-ci agissent.

La seule chose qu'il peut changer est ce que le canevas affiche, et uniquement sur demande : le bouton Appliquer au graphique masque les éléments que vos filtres de colonne oublient. Jusqu'à ce que vous appuyiez dessus, le rétrécissement d'une colonne est une lecture et non un filtrage.

Il répertorie tout le graphique ​

Le tableau ne reflète pas le canevas. Il répertorie tous les nœuds - et dans l'onglet Bords, chaque bord - y compris ceux actuellement masqués, et la première colonne Visibility indique où se trouve chacun :

ValeurStylesSignification
visiblesilencieux, sans teinteSur la toile maintenant
filteredpuce d'ambreCaché par un filtre — un filtre de nœud, ou pour un bord son layer étant désactivé. Changez le filtre pour le récupérer
excludedpuce rougeUn nœud caché à la main ; restaurez-le à partir de la liste des nœuds cachés du panneau de filtrage
nestedcontour en pointillésUn nœud à l'intérieur d'un cluster que le canevas a fermé, ou un bord avec une extrémité en un : sa ligne est tracée vers le cluster. Rien ne le filtrait ; ouvrez le cluster pour le voir
endpointcontour neutreUn bord dont la fin a été filtrée. Rien n'a été fait au bord lui-même

Chaque état diffère en termes de poids, de bordure ainsi que de couleur, de sorte que la colonne se lit sans se fier à la teinte. La rangée entière d'un élément caché recule également, gardant un œil sur ce qui est réellement dessiné.

Un bord lit endpoint de préférence à filtered, car c'est la raison pour laquelle vous devez d'abord corriger : alors qu'un nœud qu'il touche a disparu, la réactivation de sa couche ne peut pas ramener le bord.

C'est délibéré. "23 nœuds cachés" est une affirmation que vous devriez pouvoir inspecter, et une table qui supprime silencieusement les lignes que vous recherchez est pire que pas de table. Triez par Visibility pour voir exactement ce qu'un filtre a supprimé.

Nœuds à l'intérieur des clusters ​

Le contenu d'un cluster reçoit également des lignes, comme pairs des propres nœuds du graphique, avec une colonne Cluster donnant le chemin d'où ils proviennent (Team B / Squad, le plus à l'extérieur en premier) et une colonne Children indiquant la taille de chaque cluster. Les deux colonnes apparaissent chaque fois que le graphique comporte des clusters. Le commutateur Nœuds imbriqués de l'en-tête supprime à nouveau ces lignes si vous ne voulez que le niveau supérieur, et UI.table.nested: false ne les propose jamais du tout.

Ils sont volontairement répertoriés à plat plutôt qu'en retrait sous leur cluster : le tableau existe pour répondre aux questions que le canevas ne peut pas répondre : quels nœuds sont les hubs, lesquels dépassent un seuil - et cela ne continue de fonctionner que si un tri ou un filtre atteint chaque ligne de manière égale. Un arbre ne peut trier que les frères et sœurs.

Ce qu'il faut savoir, c'est qu'un nœud imbriqué n'est pas dessiné par ce graphe. Un cluster ouvert restitue son propre sous-graphe, donc :

  • Visibility lit nested lorsque tout cluster au-dessus du nœud est fermé, et visible une fois qu'ils sont tous ouverts. Ce n'est jamais filtered — aucun filtre ne l'a mis là.
  • Degree compte les arêtes réelles du nœud. Pendant que son cluster est fermé, le canevas les attire vers le cluster, il s'agit donc du décompte du nœud plutôt que d'une description de l'image.
  • Cliquer sur la ligne sélectionne le nœud, afin que la barre latérale puisse l'afficher – souvent le seul moyen d'y accéder. La toile entoure l'amas fermé qui la représente. Un double-clic ouvre ce cluster, un niveau par pression. Avec render.enableNodeExpansion: false, le cluster reste fermé et la vue se centre dessus.

Tri et rétrécissement ​

Cliquez sur n’importe quel en-tête de colonne pour trier ; cliquez à nouveau pour inverser. Les colonnes filtrables développent un contrôle dans l'en-tête qui rétrécit les lignes — chaque colonne de l'ensemble dérivé en a un, et une colonne que vous vous déclarez en obtient une en demandant filterable: true.

Le contrôle que vous obtenez suit le type de la colonne, vous pouvez donc demander à une colonne ce à quoi elle est réellement capable de répondre :

typeContrôleMatchs
numberRangeune paire Min / Maxà l'intérieur de l'intervalle ; chaque extrémité peut être laissée vide
select · multiselect · booleanun dropdown des valeurs contenues dans la colonnecette valeur exactement, ou l'appartenance lorsque la cellule est une liste
text · regex · non typéune zone de texte ****sous-chaîne insensible à la casse

La liste déroulante est construite à partir des propres valeurs de la colonne plutôt qu'à partir d'une liste d'options déclarée, elle ne propose donc jamais de choix qui reviendrait vide. Au-dessus de 50 valeurs distinctes, il est laissé de côté pour la zone de texte - une liste déroulante aussi longue n'est pas un contrôle que quiconque peut utiliser.

Un filtre de lignes n'est pas le filtre du graphique. Cela change ce que vous lisez ** : le canevas est intact et la colonne Visibility continue de rapporter la vérité à côté, donc les deux peuvent être en désaccord sans que l'un ou l'autre ne se trompe. Pousser votre rétrécissement sur la toile est un acte distinct et explicite – voir ci-dessous.

Le nombre du quai reflète les deux : 40 nodes devient 12 of 40 nodes une fois que vous réduisez.

Application des filtres au graphique ​

Appliquer au graphique, dans la barre d'outils du dock, masque les éléments laissés de côté par vos filtres de colonnes. C'est le pont entre les deux types de filtrage : réduisez les lignes jusqu'à ce que le tableau répertorie ce qui vous intéresse, puis appuyez une fois dessus et le canevas affiche la même chose.

Il s'agit d'une simple pression, pas d'un lien en direct, et le bouton indique dans lequel des trois états vous vous trouvez :

BoutonSignification
Apply to graph, éteintRien n'est poussé. Désactivé jusqu'à ce qu'un filtre de colonne rétrécisse réellement quelque chose.
Clear, litLe graphique est filtré et il correspond à vos filtres. Appuyez pour le restaurer.
Apply to graph, litLe graphique est filtré par une poussée plus tôt et vos filtres ont évolué. Appuyez pour le mettre à jour.

Deux propriétés méritent d’être connues, car c’est elles qui rendent la poussée prévisible :

  • Il masque exactement les lignes que les filtres ont laissées de côté — ne jamais "afficher uniquement celles-ci". Ainsi, un nœud ajouté après le push reste sur le canevas. Ce que vous avez poussé est une déclaration concernant un instant, pas une question permanente. L'intérieur d'un cluster ouvert ne se rétrécit que dans la mesure où ses propres rangées faisaient partie de celles laissées de côté ; avec lignes imbriquées désactivées, rien ne les nomme et l'intérieur est intact.
  • La colonne Visibility fait partie jamais d'une poussée, même si elle rétrécit toujours les lignes comme les autres. Ses valeurs sont sont l'état du filtre du graphique, donc les pousser masquerait tout ce qui se trouve actuellement sur le canevas et serait alors en désaccord avec lui-même.

Pendant qu'un push est en direct, le décompte rapporte les deux moitiés - 12 of 40 nodes · 28 hidden - et le panneau de filtre développe une ligne à partir du tableau qui le nomme et peut l'effacer, donc un push n'est jamais un filtre que vous ne pouvez pas trouver une fois le dock replié.

Le push atterrit comme un filtre unique sous une touche réservée, ce qui signifie qu'il compose avec le panneau de filtres plutôt que de rivaliser avec lui : rien de ce que vous définissez dans la forme propre de ce panneau n'entrave jamais un push, et un push n'efface jamais les filtres du panneau. Les deux sont combinés, donc un nœud doit survivre aux deux.

Passez filterGraph: false pour un dock dont les commandes ne peuvent jamais toucher le canevas :

ts
const options = {
    UI: { mode: 'full', table: { filterGraph: false } },
}

Sélection de ​

GesteEffet
Cliquez sur une ligneSélectionnez cet élément
Ctrl / Cmd-clicAjouter ou supprimer une ligne
Maj+clicPrenez une plage, dans l'ordre actuellement indiqué
Tout sélectionnerChaque ligne actuellement répertoriée – post-tri, post-filtre
Double-cliquezSélectionnez et centrez la toile dessus
SurvolezMettez en surbrillance l'élément sur la toile
Clic droitLe menu contextuel de l'élément ; une ligne d'une multi-sélection ouvre la fenêtre de la sélection

Cela fonctionne dans les deux sens : élastiquez un groupe sur le canevas et les lignes correspondantes sont marquées et défilées. La sélection est la même que celle lue par les actions groupées de la barre latérale, de sorte que la boucle se ferme sans aucun câblage supplémentaire.

Les lignes masquées sont sélectionnées comme les autres — c'est le but de les lister.

Colonnes ​

Sans columns déclaré, le dock s'en charge pour vous, en trois niveaux :

  1. Déclaré — UI.table.columns gagne carrément.
  2. De vos facettes — sinon, si vous avez déclaré UI.filter.facets, les colonnes sont construites à partir d'elles. Décrivez vos données une fois et le panneau de filtrage et le tableau sont d'accord à ce sujet.
  3. Scanned — sinon les données sont lues, classées par coverage de sorte que les clés bien remplies viennent en premier et la queue clairsemée se trouve à l'extrême droite.

Quoi qu'il en soit, les colonnes prenant en charge les graphiques enveloppent les données. Pour les nœuds, Visibility et Label mènent – une gouttière d'état et le nom, les deux choses que vous parcourez pour trouver une ligne – rejoints par Cluster sur un graphique qui a des clusters, puisqu'un imbriqué row en a besoin pour dire d'où il vient. Les comptes le ferment : Degree, plus Children sur un graphique comportant des clusters. Les décomptes se trouvent à la fin car ils correspondent à l'arithmétique du graphique plutôt qu'aux données propres à l'élément, et ce sont des colonnes étroites à largeur fixe, de sorte que quelques chiffres ne prennent jamais la part de la ligne dont un nom a besoin. Les bords conservent la même gouttière Visibility puis se lisent comme une phrase — Source / Label / Target.

Le tri par défaut est la colonne Label, pas la première : le tri par Visibility à l'ouverture ne vous dit rien alors que chaque ligne indique toujours visible.

Tout est affiché par défaut et la grille défile latéralement plutôt que de laisser tomber quoi que ce soit. Sur les nœuds riches en propriétés, utilisez le sélecteur Columns pour désactiver ce dont vous n'avez pas besoin - ce qui supprime également son contrôle de filtre de l'en-tête.

Les colonnes dérivées sont filtrables. Leurs étiquettes, leurs types et leur alignement sont tous déjà déduits, et le filtre de ligne est déduit de ce même type — donc une table que vous n'avez jamais configurée est une table que vous pouvez toujours affiner. Les colonnes déclarées sont à l'opposé : vous obtenez exactement l'ensemble que vous avez écrit, filterable: false sauf indication contraire.

Les colonnes intégrées ​

tableColumns contient les colonnes qu'aucune grille générique ne pourrait calculer, car elles concernent la place d'un élément dans le graphique plutôt que ses données :

js
import { Pivotick, tableColumns } from 'pivotick'

new Pivotick(el, data, {
    UI: {
        mode: 'full',
        table: {
            open: true,
            // Reference a built-in's key through the object rather than typing it —
            // the key itself is namespaced so it can never clash with a data key.
            sort: { key: tableColumns.degree.key, direction: 'desc' },
            columns: [
                tableColumns.visibility,
                { ...tableColumns.degree, label: 'Links' },
                tableColumns.label,
                { key: 'severity', label: 'Severity', type: 'numberRange', filterable: true },
            ],
        },
    },
})

label · degree · degreeIn · degreeOut · visibility · pinned · children · cluster, plus source et target pour les bords. Clonez-en un pour l’ajuster, comme ci-dessus.

Un TableColumn est un FilterFacet avec quelques extras de présentation (width, align, sortable, filterable, hidden, format), c'est pourquoi une facette peut être utilisée comme colonne inchangée.

Exporter ​

Les boutons CSV et JSON écrivent exactement ce que vous regardez : cet onglet, ces colonnes visibles dans cet ordre, ce tri, ce filtre de ligne. Valeurs brutes, jamais la sortie format d'une colonne, donc le fichier reste lisible par la machine.

Pas tout le graphique - c'est graph.getNodes() pour toute personne possédant du code. Passez export: false pour laisser les boutons de côté.

Téléchargements dans une page intégrée

Une iframe en bac à sable peut bloquer complètement un téléchargement. Lorsque cela se produit, le dock le dit plutôt que de laisser un bouton qui semble ne rien faire.

Échelle ​

Au-dessus de virtualizeAbove lignes (200 par défaut), les lignes sont fenêtrées : seul ce qui correspond à la fenêtre d'affichage plus une marge est dans le DOM, tandis que la barre de défilement mesure toujours l'ensemble de données. Le tri réorganise le tableau sous-jacent, jamais le DOM, et une reconstruction conserve à la fois votre position de défilement et votre sélection.

En dessous du seuil, chaque ligne est rendue, ce qui simplifie l'inspection du cas ordinaire.

Options ​

OptionsValeur par défautCe que ça fait
enabledtruefalse (ou UI.table: false) supprime entièrement le dock
tabs['nodes', 'edges']Les propres vues de la table. On ne rend aucune bande intérieure
columns / edgeColumnsdérivéVoir Colonnes
opendésarméUnset commence plié à la barre ; true commence à être développé ; false ne laisse aucun quai (Shift+T l'apporte toujours)
collapsedpliéPlié à sa barre d'en-tête. Avec open: true, 'auto' suit la chambre disponible jusqu'à ce que vous choisissiez vous-même
height0.35Un nombre de pixels ou une fraction de la toile. Serré pour que la toile garde un minimum utilisable
sortla colonne Label{ key, direction }
rowActivate'select''selectAndCenter' déplace également le canevas ; 'none' rend les lignes inertes
filterGraphtrueOffre Appliquer au graphique. false pour un dock qui ne pourra jamais filtrer le canevas
nestedtrueRépertoriez le contenu d'un cluster sous forme de lignes distinctes. Voir Nœuds à l'intérieur des clusters
export['csv', 'json']false masque les boutons
virtualizeAbove200Nombre de lignes au-dessus desquelles les lignes sont fenêtrées

Le quai contient plus que la table ​

Le tableau est un volet dans le dock, et tout ce que vous enregistrez en est un autre :

js
const dispose = graph.UIManager.addDockTab({
    label: 'Audit',
    render: () => myAuditPane(),        // called once, the first time the pane is opened
    toolbar: () => [clearButton],       // rebuilt on every activation
})

La bande du quai indique alors Table │ Audit. La commutation permute le corps et des contrôles d'en-tête, puisque Select all, les exportations et Columns appartiennent à la table et ne signifient rien sur un autre volet. Un volet ne restitue aucune bande – rien ne doit pointer vers un commutateur avec un seul paramètre.

La table n'est pas un cas particulier : elle passe par le même addDockTab, donc un volet que vous enregistrez est son égal plutôt que son invité. order le place (des ordres égaux conservent l'ordre d'enregistrement, et un volet enregistré plus tard - comme c'est toujours le cas pour un plugin - atterrit après celui intégré). Le broyeur retourné l'enlève.

Il y a une région, donc une hauteur et un pli, quel que soit le nombre de volets qu'elle contient. Deux panneaux ne peuvent pas chacun constituer une bande redimensionnable et se battre pour la toile.

Un volet peut donc être ajouté sans être affiché : il rejoint le bandeau, barre pliée comprise, et attend d'être cliqué. activateDockTab est l'acte séparé consistant à en amener un à l'avant, et la seule chose qui déplie le quai.

Deux niveaux de commutation et pourquoi ils sont différents ​

Nodes et Edges sont les onglets de la table, pas ceux du dock. Il s'agit de deux vues d'un seul volet, elles ne sont donc pas répertoriées à côté de Audit — cela voudrait dire qu'une vue du tableau et un volet séparé sont le même genre de chose.

Les deux niveaux sont dessinés différemment afin qu'ils puissent être placés l'un à côté de l'autre tout en restant lisibles comme un extérieur et un intérieur :

On diraitClasse
Table │ Auditonglets pleine hauteur, soulignés lorsqu'ils sont actifs, fermés par une règlepvt-dock-tabs / pvt-dock-tab
Nodes │ Edgesun petit groupe de pilules segmentépvt-dock-views / pvt-dock-view

Un volet avec ses propres vues fait ce que fait la table : dessinez le commutateur dans son toolbar et appelez refresh() sur sa poignée pour changer de corps. Les classes internes sont publiques, votre commutateur est donc celui intégré plutôt que sa reformulation :

js
function viewSwitch(current, pick) {
    const strip = document.createElement('div')
    strip.className = 'pvt-dock-views'
    for (const view of VIEWS) {
        const button = document.createElement('button')
        button.className = 'pvt-dock-view'
        button.textContent = view.label
        button.classList.toggle('active', view.key === current)
        button.addEventListener('click', () => pick(view.key))
        strip.appendChild(button)
    }
    return strip
}

graph.UIManager.addDockTab({
    label: 'Audit',
    toolbar: (pane) => [viewSwitch(current, (key) => { current = key; pane.refresh() })],
    render: () => renderCurrentView(),
})

Les deux niveaux prennent leur accent actif de --pvt-theme-primary, donc un consommateur qui conserve le thème conserve le dock avec celui-ci ; remplacez l’une ou l’autre classe pour aller plus loin.

refresh() n'est pas une politesse facultative - le dock conserve l'élément render, donc un volet qui a échangé son propre DOM laisserait le dock rattacher un nœud obsolète la prochaine fois qu'il passerait au premier plan.

Voir la carte de galerie Ajouter un volet de dock pour une version en direct et Plugins pour l'itinéraire du plugin.

UI.dock — les paramètres propres à la région ​

open, collapsed et height décrivent la region, pas la table, et UI.dock est l'endroit où ils appartiennent :

js
// A dock holding only a plugin's pane, open on load
UI: { mode: 'full', table: false, dock: { open: true, height: 0.3 } }

UI.table comporte toujours les trois mêmes paramètres et l'a toujours fait ; ceux-ci sont honorés et UI.dock gagne là où les deux sont définis. Atteignez UI.dock lorsque la table est éteinte - c'est la seule porte vers un dock qu'un onglet de plugin apporte avec lui.

Contrôle programmatique ​

js
graph.openTable()
graph.closeTable()
graph.toggleTable()

Chacun est un non-op lorsqu'il n'y a pas de dock (n'importe quel mode sauf full ou UI.table: false). openTable() amène également le volet de la table au premier plan, donc un appel nommé pour la table vous en montre un. Pour conduire la région sans ça :

js
graph.UIManager.dock?.setOpen(true)        // the region
graph.UIManager.activateDockTab('table')   // a pane, unfolding the dock if need be
graph.UIManager.getDockTabs()              // what is registered, in strip order

Le dock pilote l'API de sélection ordinaire, donc tout ce qui lit une sélection voit ce que la table a construit :

js
graph.selectElements([nodeA, nodeB])   // replaces the selection
graph.addToSelection([nodeC])          // nodes only
graph.removeFromSelection([nodeA])

Redimensionner et plier ​

Faites glisser le séparateur le long du bord supérieur du dock pour le redimensionner. La toile conserve un sol quoi que vous demandiez : une toile sans hauteur n'est pas un graphique.

Le chevron d'effondrement plie le quai jusqu'à sa barre d'en-tête. Laissé seul, collapsed: 'auto' prend cette décision à votre place et replie le dock sur une disposition trop courte pour lui et pour une toile utilisable ; la première fois que vous le réduisez ou l'agrandissez à la main, ou que vous faites glisser le séparateur, il cesse de décider et vous le laisse.

La barre pliée nomme toujours ses volets et les contrôles actifs y restent - le nombre de lignes du tableau, une revue pivot indiquant qu'elle est en cours de récupération. C'est ce qui permet à une vitre d'arriver alors que le dock est plié et de se faire remarquer sans prendre l'écran pour le dire. Cliquer sur un volet ouvre le dock dessus.

Une vitre qui déplie le quai pour s'afficher rend la région lorsqu'elle est retirée, donc une vitre qui va et vient laisse un quai fermé fermé. Le plier, le redimensionner ou passer à un autre volet met fin à cela : chacune est une décision qui vous appartient concernant la région, et rien ne l'annule en votre nom.

L'ouverture du dock ne déplace jamais le graphique

La simulation s'adapte au conteneur, pas au canevas, donc l'ouverture et la fermeture de Chrome ne peuvent pas modifier une mise en page. Redimensionnez le dock autant que vous le souhaitez : le graphique reste en place et une nouvelle disposition donne le même résultat avec le dock ouvert ou fermé.