Overview

Workflow Designer

Designer visuale workflow su route #/workflow-designer. Modella un processo come

grafo di nodi e connessioni, lo salva come metadata e lo esegue tramite il

workflow runner (#/workflow-runner/<graph-id>).

Scope

  • Modellazione grafo workflow con nodi, connessioni e metadata operativi.
  • Authoring assistito: template di partenza, validazione del grafo, dialog di

configurazione guidati, guida in linea.

  • Configurazione di processi riusabili eseguiti dal workflow runner.

Palette Workflow

  • Start: nodo di ingresso del processo (con voce di menu opzionale).
  • Route: uno step su cui gli utenti lavorano i record di una lista dell'app.
  • Action: operazione applicativa (azione di tabella, di riga o interna

concatenata) innescata da uno step.

  • Condition: biforcazione logica con rami vero/falso su un'espressione del record.
  • Switch: biforcazione a N rami — una formula JS calcola un valore e ogni

condizione lo confronta (token resultExpression); il primo ramo il cui test

è vero instrada il flusso, altrimenti si segue else. Ogni condizione

aggiunta crea un nuovo socket di uscita (vertice del poligono, tooltip con la

condizione).

  • Timer: promemoria / SLA su uno stato, proiettato sullo scheduler.
  • Split ∥ / Join ∥: gateway paralleli — lo split genera task in parallelo su

una route, il join prosegue quando tutti i task sono chiusi.

  • End: chiusura esplicita del flusso.

Authoring assistito

Il designer accompagna la costruzione di un workflow da zero:

  • Template di partenza: "Nuovo da template" genera un grafo pronto per i

pattern comuni (approvazione semplice, coda claim/release, catena a soglie,

task paralleli). Basta scegliere la route principale e — dove serve — il campo

di stato: il grafo, le azioni e le transizioni vengono create già collegate.

  • Validazione del grafo (lint): "Valida grafo" segnala i problemi prima del

salvataggio (start senza sbocchi, nodi irraggiungibili, azione senza target,

condition vuota, ramo morto, timer/split incompleti, permesso con ruolo

inesistente). Cliccando un rilievo il canvas inquadra il nodo interessato. Il

salvataggio non è mai bloccato: con problemi aperti compare un riepilogo con

"Salva comunque".

  • Configurazioni guidate: i dialog di timer e split usano dropdown e un

autocompletamento delle route (sulla stessa sorgente delle proprietà del

designer), invece di campi liberi da digitare a memoria.

  • Onboarding e guida: su un canvas nuovo appare una checklist dei primi passi;

la palette ha tooltip descrittivi; la voce "Guida rapida" mostra la legenda

delle forme e un glossario (bundle, transizione, guardia, permesso, azione interna).

Transizioni e permessi

  • Una transizione è metadata autorato su una connessione (click sul

quadratino a metà arco): evento, guardia (espressione JS sul record) e permesso.

  • I permessi funzionano in due modi: su un arco route→action nascondono

l'azione ai ruoli non ammessi; sul cammino di navigazione bloccano la

transizione. Modalità granting (solo i ruoli selezionati) o denying (tutti

tranne i selezionati).

  • Al salvataggio le transizioni vengono proiettate su una tabella interrogabile;

il grafo resta comunque la fonte di verità.

Catena di azioni e payload

Collegando il socket di uscita di un'azione ad altre azioni interne

(scope "Interna (concatenata)") si costruisce una catena che si esegue in

ordine dopo il click, passandosi un payload di anello in anello.

Il contratto del payload

  • Azione trigger (il bottone di toolbar): il corpo del callback vive dentro

una Promise — il payload si consegna con `resolve(valore)`, NON con

return (un return esce dall'executor senza risolvere: il payload

arriverebbe undefined).

  • Azioni interne: il callback riceve in scope la variabile `payload`

(il valore dell'anello precedente) oltre a `datasource, metaInfo, record,

wtoolbox. Un **return valore`** qui funziona e diventa il payload

dell'anello successivo; nessun return (o undefined) = pass-through

(il payload precedente prosegue invariato).

  • La catena segue solo azioni con scope "Interna" (più lo Split ∥, che

riceve il payload e lo ritorna arricchito di tasksCreated): un'azione

normale collegata a valle non viene auto-eseguita — quell'arco ha semantica

di navigazione/transizione, e la catena si ferma lì.

  • Un errore in un'azione interna viene notificato ma non blocca il resto

della catena.

  • Ogni anello salva il proprio payload per nodo: da qualsiasi callback si può

rileggere con wtoolbox.getWorkflowRouteNodePayload('<nodeId>') (utile per

recuperare il valore del trigger in una catena lunga).

Esempio:

Snippet 1js
// callback dell'azione TRIGGER (bottone toolbar)
const row = wtoolbox.unwrapEntity(record);
const esito = await wtoolbox.dataService.update(
  Object.assign({}, row, { po_stato: 'APPROVATO' }), row, datasource);
resolve(esito);                       // <-- consegna il payload alla catena

// callback di un'azione INTERNA collegata al suo socket out

Gli editor dei callback e delle formule (condition/switch) sono Monaco: tasto destro → Snippets inserisce blocchi pronti (CRUD, notifiche, email, skeleton), incluso il payload di un nodo del grafo scelto per nome — l'id si compila da solo. Per i CRUD usare wtoolbox.dataService.update/insert/delete(entity[, pristine], datasource): con scope = datasource il provider e il routeContext del workflow si risolvono da soli (AsmxProxy manuale solo per route diverse da quella dello step).

Payload nelle espressioni di condition e switch

Anche le espressioni-guardia dei nodi Condition e Switch hanno in

scope, oltre a record (la riga corrente), la variabile `payload`: il

valore prodotto dall'azione precedente della catena. Per renderlo disponibile,

il callback lo passa come terzo argomento di navigateToNextStep

(tipicamente lo stesso valore poi consegnato a resolve):

Snippet 2js
// callback dell'azione: il ramo lo sceglie il grafo, in base a record E payload
const esito = await wtoolbox.dataService.update(entity, row, datasource);
wtoolbox.navigateToNextStep(record, null, esito);
resolve(esito);
  • Condition: payload.stato === 'approvato' — o espressioni miste

record.totale > 1000 && payload.ok.

  • Switch: la formula può usare entrambi (return payload.score), e anche le

condizioni dei case (resultExpression > payload.soglia).

  • Nota sul gate pre-click: le guardie vengono valutate anche PRIMA che

l'azione giri (per bloccare subito la navigazione non consentita); a quel

punto il payload non esiste ancora, quindi le espressioni che citano

payload sono deferite — non contano al gate e vengono applicate al

momento della scelta del ramo in navigateToNextStep.

Pilotare il designer dalla chat (assistente)

L'assistente RAG (il pulsante fluttuante presente su ogni pagina) può creare

e modificare il grafo da un prompt in linguaggio naturale, come già fa per il

dashboard designer e lo scene 3D. Esempi: "crea uno scheletro di approvazione

sulla route cities", "aggiungi un nodo condizione dopo la route cities",

"inserisci un'azione tra la route e la fine", "configura la formula dello

switch". L'assistente propone un'azione strutturata; il chip Applica la

esegue sul canvas — nulla è persistito finché non salvi il grafo. Copre

l'aggiunta di ogni tipo di nodo, l'inserimento in punti intermedi, la

configurazione dei nodi (condizione/switch/timer/callback), rimozione e

collegamenti. I nomi route provengono dalle route reali dell'app.

Versioning

  • Salva versione crea uno snapshot; Storico permette di riaprire una

versione precedente. Il titolo del designer riporta la versione corrente.

Runtime (workflow runner)

Il runner esegue il grafo passo-passo e applica il comportamento configurato:

  • Timeline di istanza: le transizioni di stato dei record vengono registrate

e mostrate come cronologia.

  • Timer / SLA: i nodi timer generano promemoria o escalation sullo scheduler.
  • Assegnatari: risoluzione dell'assegnatario da gerarchia/campo e delega.
  • Task paralleli (split/join): materializzazione dei task e prosecuzione al

completamento di tutti.

  • Email: invio (o accodamento) di notifiche dagli step del processo.
  • Badge di menu: la voce di menu del runner può mostrare un contatore (es.

elementi in coda).

Integrazione client/server

  • Client:

- disegno grafo, interazioni canvas, configurazione nodi e transizioni;

- validazione del grafo e authoring assistito.

  • Server:

- persistenza della struttura workflow e dei metadati esecutivi;

- esecuzione runtime del grafo tramite workflow runner.

Note operative

  • Mantenere nomenclatura nodi semantica e stabile per il debugging.
  • Usare "Valida grafo" prima di pubblicare: evita rami orfani, condition vuote e

configurazioni incomplete.

  • Verificare il runner dopo ogni modifica strutturale importante.

Screenshot

workflow-designer / Grafo completo con palette nodi (Approvazione Ordini d'Acquisto)
workflow-designer / Grafo completo con palette nodi (Approvazione Ordini d'Acquisto)
workflow-designer / Zoom nodi + menu Azioni grafo (versioning, valida, re-layout)
workflow-designer / Zoom nodi + menu Azioni grafo (versioning, valida, re-layout)