@esfaenza/flow-builder 20.3.17 → 20.3.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -8
- package/fesm2022/esfaenza-flow-builder.mjs +740 -110
- package/fesm2022/esfaenza-flow-builder.mjs.map +1 -1
- package/index.d.ts +320 -76
- package/package.json +1 -1
- package/styles/flow-builder.css +1 -1
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ l'attributo di scope di Angular, quindi un CSS incapsulato non li raggiunge.
|
|
|
94
94
|
|
|
95
95
|
| Output | Quando |
|
|
96
96
|
|---|---|
|
|
97
|
-
| `saved` | dopo un salvataggio riuscito, con `FlowSaveResult` |
|
|
97
|
+
| `saved` | dopo un salvataggio riuscito, con `FlowSaveResult`. Lo emette anche «Duplica», e in quel caso `flowName` e' quello della **copia**: la sessione si e' spostata su di essa, quindi l'host che tiene il nome da parte deve adottarlo |
|
|
98
98
|
| `activated` | dopo un'attivazione riuscita |
|
|
99
99
|
|
|
100
100
|
Il componente vuole un'altezza: `<fb-flow-builder style="height: 100vh">`, oppure un
|
|
@@ -123,7 +123,7 @@ sono opzionali e rifiutano con `MissingService` se non sovrascritti.
|
|
|
123
123
|
| `createVersion(flowName, request?)` | astratto |
|
|
124
124
|
| `activateVersion(flowName, version)` | astratto |
|
|
125
125
|
| `deactivateFlow(flowName)` | astratto |
|
|
126
|
-
| `cloneFlow`, `deleteVersion`, `deleteFlow` | opzionali |
|
|
126
|
+
| `cloneFlow`, `deleteVersion`, `deleteFlow` | opzionali — senza `cloneFlow` «Duplica» resta disponibile e ripiega su `createFlow` |
|
|
127
127
|
|
|
128
128
|
| §6.3 Validazione | |
|
|
129
129
|
|---|---|
|
|
@@ -149,7 +149,7 @@ sono opzionali e rifiutano con `MissingService` se non sovrascritti.
|
|
|
149
149
|
| §6.5 Esecuzione | |
|
|
150
150
|
|---|---|
|
|
151
151
|
| `startInterview`, `respondToScreen`, `resumeInterview`, `inspectInterview`, `abandonInterview` | opzionali — senza, il pannello «Prova» segnala che la funzione non c'e' |
|
|
152
|
-
| `completeStageStep(request)` | opzionale — conclude uno step di orchestrazione (§5.
|
|
152
|
+
| `completeStageStep(request)` | opzionale — conclude uno step di orchestrazione (§5.14) |
|
|
153
153
|
|
|
154
154
|
**Errori.** Ogni metodo, in caso di rifiuto, deve fallire con un `FlowApiError`
|
|
155
155
|
categorizzato (§10). L'editor si comporta in base alla `category`, mai leggendo il
|
|
@@ -215,7 +215,7 @@ orchestrazione ne resta fuori: la §7 non lo comprende.
|
|
|
215
215
|
|
|
216
216
|
Un tipo con un **discriminatore** compare come piu' voci, una per valore: il Collection
|
|
217
217
|
Processor e' «Ordina» e «Filtra», non «ordina o filtra». Sono due gesti diversi — un `Sort`
|
|
218
|
-
vuole `sortOptions`, un `Filter` vuole condizioni (§5.
|
|
218
|
+
vuole `sortOptions`, un `Filter` vuole condizioni (§5.6) — e sceglierli dalla palette evita di
|
|
219
219
|
sceglierli dopo, dentro il form. L'elemento nasce con il discriminatore già scritto, con la
|
|
220
220
|
label della variante (da cui viene anche il nome tecnico) e con il glifo della variante, lo
|
|
221
221
|
stesso che avra' sul canvas. `core/element-variants.ts` tiene la mappa tipo → campo del
|
|
@@ -254,6 +254,38 @@ Tre cose che il modello non mostra e il form dice:
|
|
|
254
254
|
Il riordino e l'annidamento si fanno trascinando (`@angular/cdk/drag-drop`, senza drop list: il
|
|
255
255
|
bersaglio si calcola dal DOM) oppure con i comandi «su / giu' / porta fuori».
|
|
256
256
|
|
|
257
|
+
**Screen action (§5.2).** Un campo che l'utente compila puo' **innescare un'action** i cui risultati
|
|
258
|
+
finiscono negli altri campi della stessa schermata: e' il caso «scrivi il codice fiscale e nome e
|
|
259
|
+
cognome compaiono da soli», e senza di essa lo si farebbe spezzando lo screen in due con un elemento
|
|
260
|
+
Action in mezzo. Si modellano nelle proprieta' della **schermata** (cliccare l'anteprima fuori dai
|
|
261
|
+
campi), in **due** elenchi che il contratto tiene separati — `actions` e `triggers` — perche' piu'
|
|
262
|
+
trigger possono invocare la stessa action. Identificazione e parametri sono quelli di un elemento
|
|
263
|
+
Action, `ACTION_UNKNOWN` e `PARAMETER_UNKNOWN` compresi.
|
|
264
|
+
|
|
265
|
+
Le tre cose che riguardano l'editor, e non il runtime:
|
|
266
|
+
|
|
267
|
+
- **il picker della destinazione e' allargato qui e solo qui.** L'`assignToReference` di un output
|
|
268
|
+
accetta anche i **campi di questa schermata**, che ovunque altrove sono di sola lettura:
|
|
269
|
+
`POST /flows/references/writable` continua a escluderli — e giustamente, un Assignment che ci
|
|
270
|
+
scrive resta `TARGET_NOT_WRITABLE`. L'allargamento e' quindi un parametro del chiamante
|
|
271
|
+
(`<fb-reference-picker [extraReferences]>`), non un comportamento del picker;
|
|
272
|
+
- **il nome dell'action sta nello spazio dei nomi del flow** (§3.3): con l'output automatico e' la
|
|
273
|
+
radice di `Cerca.nome`, quindi un'omonimia con una variabile — o con una `Structure` chiamata come
|
|
274
|
+
lei — renderebbe ambiguo quel riferimento. `usedNames` lo comprende, e il form lo dice con
|
|
275
|
+
`NAME_DUPLICATED` come per il nome di uno step;
|
|
276
|
+
- **un'action senza output e' un avviso** (`SCREEN_ACTION_WITHOUT_OUTPUTS`): viene invocata e il suo
|
|
277
|
+
risultato si perde. L'output automatico non e' la cura per tutti i casi — rende il risultato
|
|
278
|
+
leggibile come `Cerca.nome` ma **non scrive in nessun campo**: e' la forma per una condizione, non
|
|
279
|
+
per precompilare;
|
|
280
|
+
- **un trigger senza campo e senza `initBehavior` non scattera' mai**
|
|
281
|
+
(`SCREEN_TRIGGER_WITHOUT_CAUSE`), e l'unico `initBehavior` ammesso e' `runOnLoad` — il
|
|
282
|
+
`runOnRevisit` della specifica Salesforce e' `SCREEN_TRIGGER_INIT_BEHAVIOR_UNKNOWN`, e vale la
|
|
283
|
+
pena saperlo perche' chi arriva da quella specifica lo scrive per abitudine.
|
|
284
|
+
|
|
285
|
+
Le action si aprono **una alla volta**: i cataloghi delle action e dei loro parametri dipendono da
|
|
286
|
+
`actionType`/`actionName`, e tenerne N in volo sarebbe N volte la corsa fra risposte che l'inspector
|
|
287
|
+
dell'Action risolve scartando quelle superate.
|
|
288
|
+
|
|
257
289
|
Sullo stage di orchestrazione il form dice le tre cose che il modello non mostra: gli step
|
|
258
290
|
**non sono una sequenza** (le frecce riordinano l'esame, non l'esecuzione), ingresso e uscita
|
|
259
291
|
non sono simmetriche (ingresso falso = step saltato, uscita falsa = stage in **stallo**), e
|
|
@@ -275,7 +307,7 @@ membro calcolato si legge in una condizione ma assegnarlo e' `TARGET_NOT_WRITABL
|
|
|
275
307
|
vale dentro `<fb-reference-picker>`, dove `Richiesta.Ragione` si propone e si verifica
|
|
276
308
|
(`STRUCTURE_MEMBER_UNKNOWN`). Un Transform con target `Structure` compone l'istanza intera in un
|
|
277
309
|
elemento solo: lì `outputFieldApiName` e' il nome di un membro, e il form lo dice invece di far
|
|
278
|
-
indovinare (§5.
|
|
310
|
+
indovinare (§5.13).
|
|
279
311
|
|
|
280
312
|
**Percorsi annidati.** I percorsi con il punto non sono piu' un buco nero: la validazione li segue,
|
|
281
313
|
e quindi li segue l'editor. `core/path-navigation.ts` naviga la catena una tappa alla volta —
|
|
@@ -306,6 +338,13 @@ richieste — `getWritableReferences` per le proposte, `getReferences` per le ra
|
|
|
306
338
|
scrivibilita' e' del **percorso** e non della radice: un `$User.Anagrafica.Citta` scritto a mano e'
|
|
307
339
|
`TARGET_NOT_WRITABLE`, non un nome che non esiste.
|
|
308
340
|
|
|
341
|
+
C'e' **un** posto in cui alle proposte si aggiunge qualcosa che la primitiva non restituisce, e
|
|
342
|
+
`extraReferences` esiste solo per quello: l'output di una **screen action**, che si assegna a un campo
|
|
343
|
+
della schermata che si sta modificando (§5.2). Non e' una scorciatoia per riferimenti che il backend
|
|
344
|
+
non conosce — quei campi restano esclusi da `references/writable`, e altrove assegnarli e'
|
|
345
|
+
`TARGET_NOT_WRITABLE`: e' l'unico punto in cui la regola del contratto e' diversa, e per questo
|
|
346
|
+
l'elenco lo passa il chiamante.
|
|
347
|
+
|
|
309
348
|
**Le globali si navigano come le risorse.** Un percorso dichiarato dall'host puo' portare un
|
|
310
349
|
contenitore, e allora `objectType` dice di che tipo: `$User.Anagrafica.Citta` si propone e si
|
|
311
350
|
verifica come `Richiesta.Ragione`. La regola da non sbagliare e' che vince il **prefisso dichiarato
|
|
@@ -321,7 +360,7 @@ Su una destinazione la colonna che decide non e' la stessa nei due mondi: un mem
|
|
|
321
360
|
`isWritable`, un campo no. Fuori da un Create o da un Update il contesto non c'e' — un Assignment su
|
|
322
361
|
`Cliente.Codice` non sa se quel record verra' creato o aggiornato — quindi lì basta `isCreateable`
|
|
323
362
|
**oppure** `isUpdateable`, e un campo che non e' ne' l'uno ne' l'altro e' `TARGET_NOT_WRITABLE` in
|
|
324
|
-
qualunque contesto (§5.
|
|
363
|
+
qualunque contesto (§5.8).
|
|
325
364
|
|
|
326
365
|
Dei tre esiti di `describeStructure` il picker mostra tre messaggi diversi, perche' portano a
|
|
327
366
|
gesti opposti: con l'elenco autorevole un nome fuori elenco e' un errore; con `members: []` la
|
|
@@ -340,7 +379,7 @@ ma un nome fuori catalogo viene segnalato subito, prima che il backend risponda
|
|
|
340
379
|
dell'oggetto referenziato e l'ultimo segmento si verifica con l'uso richiesto (§4.4). Il campo si chiede sempre con l'uso giusto (`filterable`, `sortable`,
|
|
341
380
|
`updateable`, `createable`), che decide sia l'elenco sia il testo dell'avviso: "non filtrabile",
|
|
342
381
|
"non aggiornabile" e "non valorizzabile alla creazione" sono errori diversi. In particolare
|
|
343
|
-
`createable` e `updateable` **non** sono sinonimi (§5.
|
|
382
|
+
`createable` e `updateable` **non** sono sinonimi (§5.8): un Create propone i primi, un Update i
|
|
344
383
|
secondi, e il validatore usa il codice giusto per l'elemento (`FIELD_NOT_CREATEABLE` /
|
|
345
384
|
`FIELD_NOT_UPDATEABLE`). Per lo stesso motivo l'editor non da' per scontato che `Id` sia
|
|
346
385
|
filtrabile: su una chiave composta porta la forma canonica della chiave e non e' filtrabile,
|
|
@@ -431,6 +470,15 @@ non e' una garanzia di correttezza.
|
|
|
431
470
|
attivazione bloccata finche' ci sono errori, eliminazione dietro una conferma esplicita che
|
|
432
471
|
spiega il rischio per le esecuzioni sospese.
|
|
433
472
|
|
|
473
|
+
**Duplica.** Il flow salvato sotto un altro nome, alla versione 1 (§6.2): il comando chiede nome
|
|
474
|
+
tecnico e nome visibile della copia, e l'editor **continua sulla copia** — restare sull'originale
|
|
475
|
+
farebbe finire il salvataggio successivo nel flow sbagliato. Due strade, e la differenza conta:
|
|
476
|
+
su un documento pulito si usa `cloneFlow`, che copia lato backend; con modifiche non salvate la
|
|
477
|
+
copia si crea con `createFlow` mandando il documento in mano, perche' `cloneFlow` copierebbe la
|
|
478
|
+
versione **salvata** e le modifiche appena scritte spariscono senza dirlo. La stessa strada e' il
|
|
479
|
+
ripiego dove `cloneFlow` non c'e' (e' opzionale). Un nome già usato lo rifiuta il backend con
|
|
480
|
+
`AlreadyExists`, e il modulo resta aperto sul nome da correggere.
|
|
481
|
+
|
|
434
482
|
**Prova.** Interview con form generato dalle variabili di input, form generico per gli screen
|
|
435
483
|
(valori in ingresso più i campi da restituire), `canGoBack` / `canFinish` / `canPause` come
|
|
436
484
|
verita' runtime, traccia navigabile e tabella delle risorse — con l'avviso in chiaro che la
|
|
@@ -550,7 +598,7 @@ distribuire e nessuna dipendenza da un font di icone dell'applicazione ospite.
|
|
|
550
598
|
| 2 | `assignNextValueToReference` di un Collection Processor **non** e' la destinazione | `CollectionProcessorInspectorComponent`: il campo si chiama «Elemento in esame», e un callout dice che il risultato e' l'output automatico dell'elemento |
|
|
551
599
|
| 3 | Gli **output automatici** sono riferimenti validi anche se non dichiarati | `ReferencePickerComponent` chiede l'elenco a `POST /flows/references`, che li include; non ricostruisce nulla lato client |
|
|
552
600
|
| 4 | Cancellare una condizione richiede di **riscrivere `conditionLogic`** | `condition-logic.util.ts`: `removeCondition` e `moveCondition` rimappano gli indici 1-based; un termine rimasto orfano diventa `?` e viene segnalato |
|
|
553
|
-
| 5 | Node e risorse condividono **un unico spazio di nomi** | `FlowDocumentStore.usedNames` unisce
|
|
601
|
+
| 5 | Node e risorse condividono **un unico spazio di nomi** | `FlowDocumentStore.usedNames` unisce **cinque** insiemi — node, risorse, step di orchestrazione, campi di screen dinamico e screen action, cioe' tutto cio' il cui nome e' la radice di un riferimento (§3.3) — e `checkFlowName` confronta case-insensitive; pannello risorse e inspector usano lo stesso controllo |
|
|
554
602
|
| 6 | `processType` non e' decorativo | Banner in cima all'editor per `AutoLaunched` + screen, `Orchestration` senza stage, `Screen` senza screen; la palette segnala lo Screen incompatibile. Il `processType` viaggia anche a `getDictionaries`, perche' decide quali globali esistono |
|
|
555
603
|
| 7 | Le **regole di una Decision sono ordinate** | `DecisionInspectorComponent`: regole numerate, frecce di riordino, callout «valutate dall'alto verso il basso, si ferma alla prima vera» |
|
|
556
604
|
| 8 | **Rinominare non aggiorna i riferimenti** | `FlowDocumentStore.renameNode` cammina il documento e riscrive ogni campo di riferimento, incluso il caso navigato (`Vecchio.Campo` → `Nuovo.Campo`); l'inspector dice quante occorrenze verranno toccate |
|
|
@@ -564,6 +612,9 @@ distribuire e nessuna dipendenza da un font di icone dell'applicazione ospite.
|
|
|
564
612
|
| 16 | **`Structure` e `Object` non sono intercambiabili** | `StructurePickerComponent` per la classe (fuori catalogo = **errore**, `STRUCTURE_TYPE_UNKNOWN`) e `StructureMemberPickerComponent` per i membri, filtrati su `isWritable` dove serve una destinazione. Il pannello risorse mostra la classe come obbligatoria con severita' di errore e **non** mostra il valore iniziale, perche' un `structureValue` non esiste; `ReferencePickerComponent` propone `Variabile.Membro` e verifica il percorso **fino in fondo** con `core/path-navigation.ts`, con `PATH_NOT_VERIFIABLE` dove la catena si interrompe; il Transform con target classe chiede un membro invece di un campo. `FlowDictionaryStore.isStructure` legge il flag dal dizionario, non dal nome del tipo. La risposta dei membri e' la **descrizione della classe** (`{className, label, members}`), e i suoi tre esiti restano distinti fino alla UI: `FlowCatalogStore.describeStructure` li traduce in `declared` / `undeclared` / `unknown-class` / `unknown-catalog`, e solo `declared` autorizza a dire che un membro non esiste (§4.7.1) |
|
|
565
613
|
| 17 | **Due body diversi per due famiglie di primitive** | `HttpFlowBuilderApi`: le primitive che **analizzano** il documento — `validate`, `parse`, `references`, `references/writable`, `connector-targets`, `outline` — lo mandano **nudo alla radice**; l'involucro `{definition, flowName, …}` resta alle sole primitive di scrittura della §6.2. Sbagliare involucro non da' nessun errore: il backend legge un flow vuoto e risponde `200`. Per lo stesso motivo `getReferences`/`getWritableReferences` prendono la `FlowDefinition` e non un oggetto query: non c'e' nessun campo di filtro nel body, e il filtro di tipo lo applica l'editor con `core/reference-filter.util.ts` |
|
|
566
614
|
| 18 | **Gli enum si scrivono come stringhe** | Il modello e' fatto di unioni di stringhe letterali (`FlowDataType`, `FlowVersionStatus`, …) e non di enum numerici: `JSON.stringify` non ha modo di produrre un ordinale. Conta perche' `"status": 3` non e' `Draft` ma `InvalidDraft` e `"dataType": 0` e' `String`, non "non specificato" — nessun errore lo segnalerebbe. Chi scrive un'altra implementazione di `FlowBuilderApi` non traduca i valori in numeri |
|
|
615
|
+
| 19 | **Un campo di screen dinamico e' una risorsa, ma di sola lettura** | Lo restituisce `POST /flows/references` con `kind: "ScreenField"`, e il reference picker lo propone in un gruppo suo; nei selettori di **destinazione** non compare, perche' `references/writable` lo esclude. L'unica eccezione e' l'`assignToReference` di una **screen action**, dove il campo di *quella* schermata e' una destinazione e l'elenco lo passa il chiamante (`extraReferences`). Il nome entra in `FlowDocumentStore.usedNames`, quindi un campo omonimo di una variabile e' `NAME_DUPLICATED`, e `renameScreenField` riscrive i riferimenti come `renameNode` |
|
|
616
|
+
| 20 | **La validazione di uno screen dinamico la fa il server e non fa avanzare il flow** | Riguarda il runtime, non l'editor: `EXECUTION_FRONTEND.md` §5.5 e §6.2, e lato client `flow-execution` (`isValidationRetry`, `indexValidationErrors`). Qui l'editor fa la sua parte a monte: `validationRule` si scrive con `<fb-formula-editor>`, che la fa verificare mentre si digita (§6.3) |
|
|
617
|
+
| 21 | **Un campo nascosto viene azzerato all'invio** | L'inspector lo dice dove si scrive la `visibilityRule`: la regola si rivaluta sui valori appena inviati e il campo che sparisce **perde** il valore. È l'unica cosa che chi disegna il flow non puo' dedurre dal metadata, e per questo sta nel form e non solo in questa tabella |
|
|
567
618
|
|
|
568
619
|
Altre regole del contratto rispettate: liste vuote omesse invece di scritte come `[]` (§2),
|
|
569
620
|
`filterLogic` mostrato **solo** dove il modello lo prevede (§4.4), `fullName` / `status` mai
|