コンテンツへスキップ

元に戻すと履歴 ​

graph.history は、キャンバスが保持し、示しているもの — 持ち込まれたもの、 何が持ち出されたのか、何が隠されていたのか、そしてそれらを取り戻す方法。

これは、ライブラリが実行できるすべての突然変異の記録ではありません。ノードのデータはあなたのものに属します そのため、ライブラリは作成していないフィールドを元に戻すことを提案しません。何が話せるのか というのは構成であり、これはアナリストの推論でもあります: 12 個のノードが到着し、3 個のノードが到着しました 行きました、5つ隠れています。

以下で一貫して使用される語彙

  • entry: メニューの 1 行として、起こった 1 つの元に戻せる出来事
  • kind: 6 種類のエントリのどれであるか
  • span: 最新のエントリからクリックしたエントリまでの連続したブロック
  • persisted: コンシューマがバックエンドに書き込んだエントリ
  • sealed: 永続化されたdeletion — リストされ、元に戻されることはありません

6種類 ​

クローズドセット。図書館に記録されているものはすべてこれらの 1 つであり、それ以外は何も記録されていません。

種類それは何ですかどのように逆転するのか
pivot1 回の取り込み — ピボットとエンリッチメント を参照実行の保証は取り消され、他に何も保証されないものは失われる
deleteユーザーが開始したノードまたはエッジの削除要素、起源などすべてが戻ってきます
visibility耐久性のある表示または非表示 (queryEngine.excludeNode / includeNode)もう一つは
create手で描かれたノードまたはエッジ他の何かが保証しない限り、要素は消えます
removalgraph.removeBySource(source) の電話残ったものは戻ってきて、残ったものはソースの保証を取り戻します
group手動で作成、名前変更、または削除されたグループ (Simplify を参照)手作りのグループは元の状態に戻ります。ノードは追加または削除されません

意図的に記録されません:

  • プロパティの編集。 バックエンドの状態(上記と同様)。 onBeforeNodeEditCommitはあなたがいる場所です 自分で実装してください。
  • フィルターと凡例の状態。 アクションではなく独自のクリアを持つ設定。フィルター フォームはキーストロークごとにライブで適用されるため、domain と入力すると 6 つのエントリがプッシュされます。
  • 注。 グラフ作成というよりは編集に近い、作成されたテキスト。
  • graph.hideNode(). 次回フィルタが再導出されるときに消去されるため、そのエントリ すでに元に戻ったものを元に戻すことになります。 excludeNode はその皮です 生き残っていて、記録されているもの。
  • グループを開き、ノードを引き出し、Simplifyルールを切り替えます。 見方としては、 フィルターのように。

プログラムによる突然変異 (graph.addNode()、graph.removeNode()) もエントリではありません。 ジェスチャーのみに graph.removeBySource() を加えます。これが、アプリケーションが提供する方法です。 分析者は「このソースがもたらしたものを削除する」アクション、および graph.simplify.groupNodes()、 renameGroup() と ungroup()、グループ ジェスチャーの背後にある呼び出し。

元に戻すは連続しています ​

3 つ下の行を狙うと、その 3 つが 1 つ dataBatchChanged と 1 つとして取り消されます。 再レンダリングします。 1 つの古いエントリを単独で元に戻す方法はありません。つまり、スタックの中間部分を元に戻すことはできません。 プルアウトでは、グラフがどのようにしてこのようになったのかが説明されなくなりました。

「そのプロバイダーはジャンクを返したので、削除して残りを保管してください」の場合は、次のようにします。 graph.removeBySource(source)。 1 つのソースの保証を削除し、何も削除しないものだけを削除します else が保証するので、2 回目の実行でも見つかったノードは生き残り、一方の主張は軽くなります。それは 進む操作。巻き戻しではなく新しいエントリとして記録されます。

そのエントリは、ソースが何かを保証するたびに、たとえすべての要素が残っていたとしても記録されます。 なぜなら、別の情報源もそれを保証しているからです。主張はどちらにしても無効になり、その行には次のように書かれています キャンバスには何も残りません。これを元に戻すと、各要素の保証が元の状態に正確に復元されます。 その下の実行エントリはまだ完全なままであり、次の「元に戻す」ではその実行が元に戻ります。

Redo は厳密に線形であり、新しいアクションがあるとそれが空になります。元に戻された実行、そしてその後 後の仕事で立ち往生することはなくなりました。それを取り戻すということは、ピボットを再度実行することを意味します。

トップバーから ​

ヘッダーの 2 つのボタンはそれぞれ分割ボタンです。アイコンは 1 回ステップし、キャレットは 1 回進みます。 歴史を開きます。 Ctrl+Z と Ctrl+Shift+Z (macOS の ⌘Z と ⌘⇧Z) は同じ 2 に到達します ヘッダーなしでステップを実行し、テキスト フィールドがある間はブラウザー独自のテキストの取り消しにフォールスルーします。 焦点があります。両方のボタンは、ヘッダーがあるfull および light モードで動作します。 UI.history: { enabled: false } はドロップダウンと 2 つのショートカットを取り除き、 消費者は独自のクロムから取り消しを実行します — graph.history はどちらの方法でも記録を続けます。

ドロップダウンはいずれかのボタンからの 1 つのリストで、最新のものが一番上にあり、now の行が続きます。 それ: 上の行は元に戻されていますが、下の行はまだ元に戻せるものです。をクリックしてください これは両方向で同じジェスチャーです。

各行には、その種類のアイコン、そのラベル、および クリックで移動するステップ数 が含まれます。 この番号はフッターに記載されている番号であるため、リストとフッターが一致しないことはありません。の フッターには、何かがコミットされる前の正確な最終的な効果が記載されています。矢印キーで狙いを定め、Enter 旅行、エスケープは閉じます。

キャンバスも答えます ​

行 ** にカーソルを置くと、キャンバス上の変更** が予測され、要素以外は何も変更されません。 クリックすると、ドレインが立っている場所が取り除かれ、ノードが一緒に隠れます。 それが持ち帰るものは何であれ、着地する場所の概要が示されています — グラフには存在しないノード まだ保持し、離れた位置にリングとして描画されます。この最後の部分が、やり直しの内容のほとんどです と言うのと、予測がハイライトではない理由: 注目を集めるために後退するものは何もない 要素が目立つのは、行がどの要素に名前を付けるかではなく、何が変更されるかが問題だからです。

輪郭は推測ではありません。元に戻すには、各要素が削除されたときにどこにあったかが記録されます。 キャンバスに移動し、やり直すとそこに戻ります。つまり、予測で描画されるのは、クリックがどこに到達するかです。 物事。ピボットは、座標を持たないプロバイダーの生データから再生します。 そうしないと、取り込みは新しい場所に散在して戻ってきます。

preview() は、forecast および graph.showForecast(…) のデータと同じものを返します / graph.clearForecast() ペイント — 消費者自身の履歴 UI、またはその他のあらゆるものをペイントします。 「もしも」を尋ねたい場合は、キャンバス言語を無料で入手します。

バックエンドに書き込まれる操作 ​

操作がバックエンドに書き込まれたことを知ることができるのはコンシューマーだけです。 消費者はそう言えます。それぞれonBeforeNodeCreate、onBeforeEdgeCreate、onBeforeDelete persisted の決定を受け入れる:

js
callbacks: {
    onBeforeNodeCreate: async (ctx) => {
        const values = await ctx.promptData({ fields: [{ key: 'value', label: 'Value', type: 'text' }] })
        if (!values) return false
        const saved = await myBackend.create(values)
        return { accept: true, id: saved.uuid, data: values, persisted: true }
    },
}

Undo は補償書き込みを発行しないため、そのようなエントリに対してどのような処理が行われるかは方法によって異なります。 書き込みは完了しました。

永続的な creation は依然として逆転します。キャンバスはバックエンドが保持していたものを失います。 再フェッチすると元に戻されるため、エントリは保留されるのではなく saved とマークされ、フッターがカウントされます。 クリックする前にそれを指定します: Undoes 2 steps · 1 item saved upstream。

永続化された deletion は sealed: キャンバスの取得方法の一部であるため、リストされています。 この方向ですが、決して逆向きではありません。それを復元すると、バックエンドに存在しなくなったノードが元に戻されます。 そして、その後のキャンバス上には、そのことを示すものは何もありませんでした。 1 を含むスパンはむしろその上を通過します そこで立ち止まるのではなく、最初にそう言います:Undoes 2 of 3 · 1 saved item kept。

js
const [newest] = graph.history.entries()
newest.persisted   // the consumer wrote it through
newest.sealed      // …and it was a deletion, so undo will not take it back

すべてのエントリが触れた特定の要素に名前を付けるため、スキップが機能します。 状態の差分が狂います。 6種類が非公開で消費者に提供されていないのもそのためです。 独自のエントリを記録できません: スタック内の任意のコールバックが途中でスローされる可能性があります 歴史は知る由もありません。

取り込みを取り戻す ​

取り込み ** を元に戻すと、その候補 ** が再ステージングされ、行がレビュー ペインに戻ります。 それらの送信元、取り込みによってペインが閉じられていた場合はペインが再び開きます、以前の拒否はまだ保持されています、 そしてプロバイダーは呼び出されません。最後の部分がポイントです。代替案は 2 つを再フェッチすることです。 レート制限された API を介して何千もの相関を取得し、2 秒前に犯した間違いを修正します。

彼らはマークされたままではなく、トリアージされずに戻ってきます。ランを取り戻すのは通り抜けるため ワンクリックで同じ 12 を再着地させるためではなく、適切に設定します。

コンテキスト メニューからのワンクリック ピボットなど、レビューなしでランディングされた実行。 autoIngest を設定するプロバイダーはどのペインからも取得されていないため、元に戻すとノードが削除されるだけです。

これは、取り込みがまだ最新のエントリである場合 のみ発生します。何かがあれば それ以降、元に戻すとノードが削除され、ペインが表示されなくなり、ペインが再び復活してしまいます。 その後の作業は再フェッチよりも悪くなる可能性があります。

保持しているもの ​

30 件のエントリーがあり、最も古いものが排除されました。立ち退きは理解する価値があります。 対称: 古い実行を 削除 するのではなく、古い実行を 復元 する能力を失います。 来歴は要素自体に依存しているため、graph.removeBySource(pivotId) は依然として到達します 歴史が忘れてしまった走り。

履歴は セッションのみ です。リロードしても生き残れません。以前の状態を復元する グラフ全体は別の機能であり、この機能ではありません。

運転する ​

js
graph.history.entries()      // what can be undone, newest first — the order the menu renders
graph.history.redoable()     // what has been undone and can be redone, newest first
graph.history.canUndo()
graph.history.canRedo()

graph.history.undo()                  // the newest entry
graph.history.undo(entryId)           // the span from the newest through that entry
graph.history.redo(entryId)           // and back again

graph.history.preview(entryId)        // what that span would do, before doing it
graph.history.on(history => …)        // every change to either direction; returns a disposer
graph.history.clear()                 // forget everything; the canvas is left as it is

ピボット エントリの id ** は** の runId であるため、PivotRunOutcome はすでにハンドルを 独自の行:

js
const outcome = await graph.pivots.run('correlations', graph.getSelectedNodes())
// …later
graph.history.undo(outcome.runId)

preview(entryId, direction?) は注目に値します。エントリを要約するものではありません。 クリックと同じコードを通じて、グラフの状態のコピーに対してスパンを再生します。 コミットし、結果を比較します。

js
const { entries, skipped, canvasOnly, nodes, edges, effect, forecast } = graph.history.preview(entryId)
// entries    the span, newest first
// skipped    the sealed ones inside it, which will be left alone
// canvasOnly the ones it reverses that the backend keeps a copy of
// nodes      the elements it would touch that are on the canvas now
// effect     { nodesRemoved, nodesRestored, edgesRemoved, edgesRestored, nodesHidden, nodesShown }
// forecast   the same change as something to paint: { removing, hiding, touching, arriving }

graph.showForecast(forecast)   // …and take it back down with graph.clearForecast()

説明するのではなく実際にプレイするため、厄介なケースが何の意味もなく浮かび上がります。 後の非表示によってキャンセルされた非表示はネットをゼロにし、そのように言い、ノードの 2 番目のピボットも同様にします の保証は退出としてカウントされません。

来歴と削除がそれを覚えている理由 ​

すべてのノードとエッジは、それを保証する一連のソースを保持します: 'seed' ロードされ、ピボットがもたらしたものはピボットの ID、そして手で描かれたものは 'manual' です。あ 1 つのノード上で 2 つのピボットがオーバーラップするのが通常のケースであるため、スカラーではなく set です。

したがって、削除では、データだけでなく各要素の保証を記憶する必要があります。なし つまり、実行により 12 が追加され、アナリストが 3 を削除し、削除を元に戻すと、3 が追加されます。 行方不明孤児として戻った。その後実行を取り消してキャンバス上に残します それらを説明するものは何もありません。これにより、削除を元に戻し、実行が正確に終了します 前に何があったのか。

アップグレード時に知っておく価値のある結果の 1 つは、手動で作成されたノードが ['manual'] をレポートすることです。 ['seed']ではなく、getSources()から。それが graph.removeBySource('manual') の理由です 手描きの作品に到達し、作成を元に戻すと、何もない場合にのみ要素を削除できるようになります。 それ以外の場合はまだそれを保証します。