Pular para o conteúdo

Salvando resultados dinâmicos ​

Pivots & enriquecimento termina com uma ingestão: os candidatos escolhidos estão na tela, marcados com o pivô que os trouxe, e em nenhum outro lugar. save é o retrocesso — o pivô grava seus próprios resultados no sistema de onde vieram, e a biblioteca mantém os livros sobre o que foi cruzado.

summarize  →  fetch  →  triage  →  ingest  →  save
  "2,143"     the 210    the 12    on canvas   in the source system

A biblioteca nunca escreve em nenhum lugar e não possui credenciais. O que contribui é a contabilidade – quais elementos uma corrida criou, se foram escritos, quais falharam e o que uma nova tentativa deve conter – porque essa é a parte que só ela conhece.

Declarando um ​

js
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,
        }
    },
}

A carga útil consiste em objetos gráficos dinâmicos, não em fragmentos brutos:

CampoO que isso contém
originem que o pivô foi executado - "a qual evento isso está anexado"
nodesos nós que esta execução criou
childrenconteúdo do contêiner adicionado por união, achatado; cada um acessível a partir de seu contêiner através de parentNode
edgesas bordas que esta corrida criou
vouchedo que já estava na tela antes desta execução
attempt1 na primeira vez, maior na nova tentativa

Omita save e os resultados do pivô serão não salváveis. Eles nunca entram no razão, nunca são contados como não salvos e nenhum Salvar aparece para eles. Essa é a declaração correta para um pivô sobre dados derivados - a saída de um mecanismo de correlação não é sua para escrever de volta - e é o que impede um "210 não salvo" permanente sem solução.

O que você devolve ​

DevolvidoMeios
undefined / truetoda a carga útil foi escrita
false, ou jogandonada disso foi; o erro chega ao brinde de nova tentativa
{ savedNodeIds, savedEdgeIds }uma gravação parcial — qualquer coisa não nomeada permanece não salva
{ canonicalIds }identifica o sistema de origem atribuído, codificado pelo ID local
{ message }mostrado literalmente no brinde do resultado
{ cancelled: true }o analista recuou: nada registrado, nem brinde, nem tentativa

savedNodeIds cobre nodes e children juntos. Um id que nomeia um elemento que esta execução não criou é ignorado: um pivô nunca escreve o que não produziu, portanto também não pode reportar o que foi escrito.

Um salvamento que relata uma borda escrita, mas não os nós que ela conecta, é considerado pelo valor nominal. O que o sistema de origem diz que escreveu não deve ser ignorado pela biblioteca.

Perguntando primeiro ao analista ​

Às vezes, uma gravação precisa de uma resposta antes de prosseguir, como qual relacionamento vincula cada resultado ao nó do qual foi enriquecido. ctx.promptData abre o modal próprio da biblioteca, com as mesmas opções daquele por trás da criação de nós e arestas: declarativo fields ou render + getValues para o seu próprio HTML. Ele resolve os valores ou null no cancelamento.

js
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 })
},

O modal é intitulado e enviado com Save, a menos que title e submitLabel digam o contrário. Retornar { cancelled: true } deixa a execução exatamente como estava antes do clique: ainda não salva, sem brinde, sem nova tentativa e a próxima tentativa ainda é attempt: 1. Um salvamento de várias execuções é interrompido no primeiro cancelamento e o relatório o conta como cancelled em vez de como uma falha. Uma nova tentativa cancelada coloca o brinde de volta como estava.

Somente um salvamento em que alguém clicou pode perguntar. O Salvar do painel Dinâmico, o Salvar do painel Revisão e a passagem de Nova Tentativa interactive: true do brinde; autoSave e um graph.pivots.save() simples não, então seu promptData resolve null de uma vez sem nada desenhado. Um host com um botão Salvar próprio também passa a bandeira:

js
await graph.pivots.save(undefined, { interactive: true })

Pedindo um ​

js
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

Parte de uma corrida ​

js
const selected = graph.renderer.getGraphInteraction().getSelectedNodeIDs() ?? []
await graph.pivots.save({ elements: selected })   // Nodes, Edges or their ids

Cada execução que criou um dos elementos nomeados é solicitada uma vez, com uma carga útil restrita ao que foi nomeado. Um nó nomeado traz os filhos pendentes para baixo dele, e uma borda surge quando uma extremidade é nomeada e a outra também é nomeada ou não será deixada sem escrita: a origem, um nó já salvo, qualquer coisa que o livro-razão não esteja esperando. Uma borda de um nó pendente deixada de fora permanece com ele, portanto, uma gravação nunca envia uma linha para nada. Os elementos nomeados pelos quais nada está esperando são ignorados e a chamada recebe um brinde para cada execução solicitada.

O restante permanece pendente e conta, Repetir e canonicalIds funcionar como fazem durante uma execução inteira. Uma execução é marcada como persistente no histórico apenas quando nada resta para ser gravado. isSavable(el) e isSaved(el) dizem se uma entrada de menu como Salvar selecionados tem alguma coisa a ver.

As execuções acontecem uma de cada vez e cada uma recebe apenas o que ainda não foi salvo – portanto, uma nova tentativa é a mesma chamada. O resultado chega como um brinde: Saved 12 nodes, ou Saved 9 of 12 com um Retry que assume o mesmo brinde em vez de empilhar um segundo.

Na interface do usuário, a contagem e o botão ficam na parte inferior do painel dinâmico, e um painel Revisão carrega a participação do seu próprio provedor em seu cabeçalho. Nada aparece enquanto o número é zero.

Ambos escrevem tudo pendente, sem como escolher. Um aplicativo que oferece salvamento em outro lugar, como uma entrada Salvar selecionado no menu do nó, pode desativá-los:

js
new Pivotick(el, data, { pivots: [objects], pivotSaveControls: false })
graph.pivots.saveControls = true   // and back, at runtime

Apenas os dois controles funcionam. O razão, as contagens, save(...), seu brinde e nova tentativa e canonicalIds funcionam como antes.

autoSave: true escreve cada corrida no momento em que pousa, sem nenhum gesto. Ele é executado depois que a ingestão é resolvida, e não dentro dela, de modo que um back-end lento nunca retém a tela e uma falha é relatada por meio do notificador e deixa os dados onde estão. Combine-o com autoIngest: true para um pivô que não interage de ponta a ponta - expandindo um evento em objetos que já são da própria fonte.

Identifica o sistema de origem ​

Salvar geralmente cria algo, e a coisa criada geralmente recebe um ID escolhido pelo sistema de origem, e não aquele que seu provedor usou enquanto era candidato. A execução de amanhã retorna os mesmos objetos em ids que a desduplicação não reconhece, e o analista obtém doze duplicatas do que salvou ontem.

Retorne canonicalIds e a biblioteca mantém o alias. Ingerir a desduplicação, a união dos filhos e os endpoints de borda consultam-no, então a nova execução diz 12 já na tela.

js
graph.pivots.canonicalId(node)   // 'a1b2…' — the id the source assigned
Por que o nó mantém o ID sob o qual pousou

A recodificação alcançaria bordas, clusters, seleção, mecanismo de consulta, proveniência e histórico, para um benefício que o alias já oferece onde é importante. O custo honesto: graph.getNode(canonicalId) ainda erra e canonicalId() é a leitura que não erra.

Desfazer não alcança o sistema de origem ​

Desfazer uma execução salva remove seus nós da tela. Ele não remove nada do sistema em que foram gravados, e a biblioteca não emite nenhuma gravação compensatória: desfazer uma visualização local não é uma transação entre dois sistemas.

A história diz isso, em vez de deixar você descobrir: uma execução marcada como escrita é marcada como saved, e o rodapé do menu conta o que um intervalo deixaria para trás. PivotRun carrega uma contagem saved para uma superfície que deseja avisar antes do clique. Consulte Desfazer e histórico para saber como trata uma entrada persistente.

Uma falha no salvamento também nunca toca a tela. O analista aceitou esses doze nós; uma recusa de back-end é uma informação sobre o back-end, não uma reversão de sua decisão. Eles permanecem, não são salvos e podem ser repetidos.

Marcando nós não salvos ​

js
new Pivotick(el, data, { pivots: [objects], pivotMarkUnsaved: true })

Coloca uma classe pvt-node-unsaved em cada nó que uma execução criou e não escreveu de volta, que uma folha de estilo pode capturar - o padrão é uma borda tracejada. Desativado por padrão, e uma classe em vez de um emblema de aro: um nó tem quatro cantos de aro e apenas dois quando tem filhos, e um marcador que empurra um potencial declarado para fora do aro custa mais do que diz.