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:
// 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 outGli 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):
// 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

