保存拓展结果
拓展和充实以摄取结束:选定的候选者位于画布上,标记有带来它们的拓展,而不是其他地方。 save 是后退一步——拓展将自己的结果写入它们来自的系统,图书馆保留有关交叉内容的书籍。
summarize → fetch → triage → ingest → save
"2,143" the 210 the 12 on canvas in the source system该库本身从不写入任何内容,也没有任何凭证。它所做的贡献是簿记——一次运行创建了哪些元素,它们是否已被写入,哪些失败了,以及重试应该携带什么——因为这是只有它知道的部分。
宣布一
const objects = {
id: 'objects',
label: 'Objects & attributes',
fetch: (nodes, narrowing, ctx) => api.objects(nodes[0].id, { signal: ctx.signal }),
save: async ({ origin, nodes, children, edges }, ctx) => {
const written = await api.createObjects(origin[0].id, [...nodes, ...children], {
signal: ctx.signal,
})
return {
savedNodeIds: written.ok.map(o => o.localId),
savedEdgeIds: edges.map(e => e.id),
canonicalIds: Object.fromEntries(written.ok.map(o => [o.localId, o.uuid])),
message: written.failed.length ? `${written.failed.length} refused` : undefined,
}
},
}有效负载是实时图形对象,而不是原始片段:
| 领域 | 它包含什么 |
|---|---|
origin | 拓展表运行的内容 - “该事件附加到哪个事件” |
nodes | 本次运行创建的节点 |
children | 联合添加容器内容物,压扁;每个都可以通过 parentNode 从其容器到达 |
edges | 这次运行创建的边缘 |
vouched | 这次运行之前画布上已经有什么 |
attempt | 第一次1,重试时更高 |
省略save,并且拓展的结果是不可保存。它们永远不会进入分类帐,永远不会被视为未保存,并且不会为它们显示保存。这是导出数据的正确声明——关联引擎的输出不是你可以写回的——并且它可以阻止永久的“210 未保存”且无法补救。
您返回的内容
| 已返回 | 手段 |
|---|---|
undefined / true | 整个有效负载已写入 |
false,或投掷 | 没有一个是;错误到达重试 toast |
{ savedNodeIds, savedEdgeIds } | 部分写入 — 任何未命名的内容均未保存 |
{ canonicalIds } | 源系统分配的 ids,由本地 id 键入 |
{ message } | 在结果 toast 中逐字显示 |
{ cancelled: true } | 分析师反驳道:没有任何记录,没有祝酒,没有尝试 |
savedNodeIds 一起覆盖nodes 和children。命名此运行未创建的元素的 id 将被忽略:拓展永远不会写入它未生成的内容,因此它也无法报告已写入的内容。
报告已写入边但不报告其连接的节点的保存是按表面值获取的。源系统所说的内容不是图书馆可以推翻的。
先询问分析师
一次写入有时需要一个答案才能进行,例如哪个关系将每个结果与其丰富的节点联系起来。 ctx.promptData 打开库自己的模态,具有与节点和边创建后面的选项相同的选项:声明式fields,或为您自己的HTML使用render + getValues。它解析为值,或取消时为 null。
save: async (payload, ctx) => {
const answer = await ctx.promptData({
fields: [{ key: 'relationship', label: 'Relationship', type: 'text', defaultValue: 'related-to' }],
})
if (!answer) return { cancelled: true }
await api.attach(payload, answer.relationship, { signal: ctx.signal })
},模态标题为 Save,除非 title 和 submitLabel 另有说明。返回 { cancelled: true } 使运行与单击之前完全相同:仍然未保存,没有 toast,没有重试,并且下一次尝试仍然是 attempt: 1。多次运行的保存在第一次取消时停止,报告将其计入cancelled,而不是失败。取消的重试会将其 Toast 恢复到原来的状态。
只有有人点击的保存才能询问。透视面板的保存、审阅面板的保存和 toast 的重试传递 interactive: true; autoSave 和普通的 graph.pivots.save() 则不然,因此它们的 promptData 会立即解析 null,而不会绘制任何内容。拥有自己的“保存”按钮的主机也会传递该标志:
await graph.pivots.save(undefined, { interactive: true })求一份
await graph.pivots.save() // every savable run with something still unsaved
await graph.pivots.save(runId) // one run
await graph.pivots.save(pivotId) // every unsaved run of one pivot
graph.pivots.unsaved() // the runs still waiting
graph.pivots.unsavedCount() // { nodes, edges } — exact, not advisory
graph.pivots.unsavedCount(pivotId) // one pivot's share of it
graph.pivots.isSaved(node) // false for the unsaved *and* the not-savable
graph.pivots.isSavable(node) // which of those two it is跑步的一部分
const selected = graph.renderer.getGraphInteraction().getSelectedNodeIDs() ?? []
await graph.pivots.save({ elements: selected }) // Nodes, Edges or their ids每次创建指定元素之一的运行都会被询问一次,有效负载会缩小到指定的范围。命名节点将待处理的子节点置于其下方,当一端被命名并且另一端也被命名时,一条边就会出现,或者不会被保留下来:原点、已保存的节点、分类帐不等待的任何内容。未处理的待处理节点的边缘会留在其后面,因此写入永远不会将一行发送到任何内容。没有任何等待的命名元素将被忽略,并且该调用每次请求运行时都会获得一次祝酒。
其余的保持悬而未决,并且计数、重试和 canonicalIds 的工作方式与整个运行一样。仅当没有任何内容可供写入时,才会将运行标记为保留在历史记录中。 isSavable(el) 和 isSaved(el) 表示像 Save selected 这样的菜单项是否有任何作用。
一次运行一次,每次仅发送尚未保存的内容 - 因此重试是相同的调用。结果以 Toast 形式到达:Saved 12 nodes 或 Saved 9 of 12,其中 Retry 接管同一个 Toast,而不是堆叠第二个 Toast。
在 UI 中,计数和按钮位于“拓展”面板的底部,“审阅”窗格在其标题中包含其自己的提供商的份额。当数字为零时,什么也不会出现。
两者都写了所有未决的内容,无法选择。提供在其他位置保存的应用程序(例如节点菜单中的 Save selected 条目)可以将其关闭:
new Pivotick(el, data, { pivots: [objects], pivotSaveControls: false })
graph.pivots.saveControls = true // and back, at runtime只有两个控件可以运行。账本、计数、save(...)、其 toast 和重试以及canonicalIds 都像以前一样工作。
autoSave: true 在每次运行落地时立即写入,无需任何手势。它在摄取解析后运行,而不是在摄取解析后运行,因此缓慢的后端永远不会支撑画布,并且通过通知程序报告故障并将数据保留在原处。将其与 autoIngest: true 配对,形成端到端的不干涉的拓展 — 将事件扩展为源自己的对象。
源系统铸币厂的 ID
保存通常会创建一些东西,并且创建的东西通常会获得源系统选择的 ID,而不是您的提供者在候选时使用的 ID。明天的运行会在 ids dedup 无法识别的情况下返回相同的对象,并且分析师会获得他们昨天保存的内容的 12 个重复项。
返回 canonicalIds 并且库保留别名。摄取重复数据删除,子联合和边缘端点都参考它,因此重新运行时会显示 12 已经在画布上 了。
graph.pivots.canonicalId(node) // 'a1b2…' — the id the source assigned为什么节点会保留其登陆时的 id
重新键入将涉及边缘、集群、选择、查询引擎、来源和历史记录,以获得别名已经在重要的地方提供的好处。诚实成本:graph.getNode(canonicalId)仍然未命中,canonicalId()是未命中的读取。
撤消未到达源系统
撤消已保存的运行将从画布中删除其节点。它确实不是从写入它们的系统中删除任何内容,并且库不会发出补偿写入:撤消本地视图不是跨两个系统的事务。
历史是这么说的,而不是让您去发现:标记为已写完的运行会被打碎已保存,并且菜单的页脚会计算跨度会留下的内容。 PivotRun 带有 saved 计数,表示要在单击之前发出警告的表面。请参阅撤消和历史了解它如何处理持久条目。
失败的保存也不会触及画布。分析师接受了这十二个节点;后端拒绝是有关后端的信息,而不是逆转他们的决定。它们会留下来,保持未保存状态,并且保持可重试状态。
标记未保存的节点
new Pivotick(el, data, { pivots: [objects], pivotMarkUnsaved: true })在运行创建且尚未写回的每个节点上放置一个 pvt-node-unsaved 类,样式表可以拾取该类 - 默认为虚线边缘。默认情况下关闭,并且是一个类而不是边缘徽章:一个节点有四个边缘角,一旦有子节点,只有两个,并且将声明的潜力推离边缘的标记的成本比它所说的要高。