Ongedaan maken en geschiedenis
De twee knoppen in de bovenste balk zijn gesplitste knoppen: het pictogram stapt één keer, de cursor opent de hele geschiedenis. Het is één tijdlijn met een lijn now erdoorheen — de rijen erboven zijn ongedaan gemaakt, de rijen hieronder zijn wat nog steeds ongedaan kan worden gemaakt - en als u op een rij klikt, gaat u daarheen.
Schrijf wat geschiedenis en open het vervolgens:
- Verberg knooppunt of Verwijder knooppunt vanuit het rechtermuisknopmenu van een knooppunt
- Maken ▸ Voeg knooppunt toe aan de linkerrail en klik vervolgens op het canvas
- Voer een pivot uit, als je die hebt: een ingest is een invoer zoals alle andere
Beweeg de muis over een rij en markeer de periode die een klik zou omkeren, vermeldt het netto-effect in de voettekst, en voorspelt het op het doek: wat zou wegvloeien waar het staat, en wat zou komen achterkant is aangegeven waar het zou landen. Ctrl + Z stappen terug zonder het menu.
Ongedaan maken is aaneengesloten: door drie rijen naar beneden te richten, worden die drie omgedraaid, als één batch.
// Nothing here switches the history on: `graph.history` records the four kinds of
// composition change on its own, and the two split buttons in the header are wired to
// it. `mode: 'full'` is what brings the header the buttons live in, and the left rail's
// Create tool.
const options = {
UI: {
mode: 'full',
// Off: this card is about the top bar, and `full` mode's minimap and data dock
// are neither (see the Minimap and Data table cards for those).
minimap: false,
table: false
},
render: { nodeTypeAccessor: (node) => node.getData().kind }
}// A consumer that writes a change through to its own backend says so. Undo makes no
// compensating write, so it follows the direction of yours: a creation still reverses
// and the row is chipped `saved`, while a deletion is sealed — undoing it would put
// back a node your backend no longer has.
const writeThrough = {
callbacks: {
onBeforeNodeCreate: async (ctx) => {
const values = await ctx.promptData({
fields: [{ key: 'label', label: 'Name', type: 'text' }]
})
if (!values) return false
const saved = await myBackend.create(values)
return { accept: true, id: saved.uuid, data: values, persisted: true }
},
onBeforeDelete: async (ctx) => {
await myBackend.remove(ctx.nodes.map((node) => node.id))
return { accept: true, persisted: true }
}
}
}const data = {
nodes: [
{ id: 'gw', data: { label: 'gateway-01', kind: 'Host' } },
{ id: 'db', data: { label: 'orders-db', kind: 'Database' } },
{ id: 'api', data: { label: 'orders-api', kind: 'Service' } },
{ id: 'cache', data: { label: 'session-cache', kind: 'Service' } },
{ id: 'job', data: { label: 'nightly-export', kind: 'Job' } },
{ id: 'sftp', data: { label: 'partner-sftp', kind: 'Host' } }
],
edges: [
{ from: 'gw', to: 'api', data: { label: 'routes' } },
{ from: 'api', to: 'db', data: { label: 'reads' } },
{ from: 'api', to: 'cache', data: { label: 'reads' } },
{ from: 'job', to: 'db', data: { label: 'reads' } },
{ from: 'job', to: 'sftp', data: { label: 'writes' } }
]
}Ongedaan maken schrijft nooit naar uw backend, dus een wijziging die u hebt opgeschreven, volgt de richting waarin deze is opgeschreven ging. Een creatie draait nog steeds om: het canvas verliest wat de backend behoudt, en de voettekst telt het (Undoes 2 steps · 1 item saved upstream). Een verwijdering is verzegeld: vermeld, nooit omgekeerd, en een overspanning met daarin één gaat eroverheen (Undoes 2 of 3 · 1 saved item kept).
Zie Ongedaan maken en geschiedenis voor de vier soorten invoer, wat bewust niet is gedaan geregistreerd, en hoe het ongedaan maken van een opname de kandidaten terug in het triagevenster plaatst.