@esfaenza/flow-builder 20.3.38 → 20.3.40

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 CHANGED
@@ -235,6 +235,14 @@ il trascinamento sul canvas vuoto disegna il rettangolo di selezione invece di s
235
235
  un elemento, il canvas lo dice e dice **cosa farne**: «trascinane uno per spostarli tutti». Un
236
236
  gesto che nessuno annuncia non esiste.
237
237
 
238
+ **Risorse.** Il pannello «Risorse» e' un **elenco**: nome, tipo, quante volte e' usata, i rilievi
239
+ della riga. Aggiungerne una o cliccarne il nome apre una **finestra** dedicata con il form dentro,
240
+ come per il dettaglio di un elemento — e per la stessa ragione: il form di un dynamic choice set
241
+ (sorgente, due campi, ordinamento, limite, filtri) dentro la colonna laterale spingeva l'elenco
242
+ fuori dallo schermo, cioe' faceva sparire il contesto per cui l'elenco esiste. La finestra si
243
+ sposta prendendola per l'intestazione, non ha «Annulla» — le modifiche sono già nel documento, e
244
+ a tornare indietro e' l'annulla dell'editor — e si chiude da se' se la risorsa viene rimossa.
245
+
238
246
  *Quante volte e' usata.* Ogni risorsa porta il numero dei suoi usi, formule comprese; a zero
239
247
  occorrenze lo dice, ed e' l'unico modo di sapere quali delle venti variabili sono morte.
240
248
  Rimuovere una risorsa **usata** chiede conferma e dice quanti riferimenti resterebbero orfani:
@@ -481,6 +489,16 @@ sapere: le globali sono di sola lettura, membri compresi — le assegnabili sono
481
489
  `$Flow.ActiveStages` e i campi di `$Record` — e il picker lo dice con `TARGET_NOT_WRITABLE` invece
482
490
  di far sembrare il nome inesistente (§5.2).
483
491
 
492
+ **Uno scope puo' nominarsi da solo.** `$Profile` senza percorso e' un riferimento valido se — e solo
493
+ se — l'host lo dichiara così, con una voce **senza punto** che porta il suo `dataType` e il suo
494
+ `objectType` (§4.1): e' come un host espone l'utente corrente come un'unica istanza invece di
495
+ elencarne i campi, e da lì la navigazione riparte, quindi `$Profile.Livello` si verifica sui membri
496
+ della classe senza che il catalogo dichiari un percorso per ognuno. Il prefisso dichiarato piu' lungo
497
+ e' la stessa regola di prima: la voce senza punto e' il prefisso **vuoto**, cioe' quello che vince
498
+ solo quando nessun altro corrisponde. Dove lo scope dichiara percorsi ma non la voce senza punto,
499
+ `$Profile` da solo resta `GLOBAL_UNKNOWN`: nella demo e' la differenza fra `$Profile` (dichiarato
500
+ così) e `$User` (che dichiara i suoi campi).
501
+
484
502
  Su una destinazione la colonna che decide non e' la stessa nei due mondi: un membro porta il proprio
485
503
  `isWritable`, un campo no. Fuori da un Create o da un Update il contesto non c'e' — un Assignment su
486
504
  `Cliente.Codice` non sa se quel record verra' creato o aggiornato — quindi lì basta `isCreateable`
@@ -567,6 +585,19 @@ aggiunte. Tre esiti restano distinti e nessuno dei tre e' «formula valida»: pr
567
585
  stata controllata), `isValid` (verificata davvero, ed e' l'unico caso con la spunta verde) — una
568
586
  spunta su un'espressione mai controllata e' peggio di nessuna spunta.
569
587
 
588
+ **Testo con merge field (§5.12).** Il messaggio di un Custom Error non e' una casella di testo
589
+ qualunque: supporta i segnaposto `{!...}` come il testo di un text template e le scritte di uno screen
590
+ dinamico, e lì servono piu' che altrove — *«L'ordine e' già stato evaso»* senza il numero dell'ordine e'
591
+ meta' messaggio. Lo monta `<fb-merge-text-editor>`, ed e' un componente diverso dall'editor di formule
592
+ perche' il contenuto e' diverso: qui c'e' una **frase**, con dentro delle isole. Tre conseguenze. Offre
593
+ l'**inserimento** di un riferimento (un bottone con l'elenco, piu' i suggerimenti mentre si scrive dentro
594
+ un `{!` aperto), e scrive l'isola intera, graffe comprese: la sintassi non deve stare a memoria. Manda il
595
+ testo al motore **solo se contiene `{!`**, perche' una frase in italiano mandata a un motore di
596
+ espressioni si farebbe accusare parola per parola. E gli esiti restano i tre delle formule, con la stessa
597
+ regola: nessuna spunta su un testo che nessuno ha guardato. Lo stesso controllo avviene nella validazione
598
+ del documento, con `usage: "Text"` e il rilievo sul path `customErrorMessages[n].errorMessage`: un refuso
599
+ dentro una graffa non si scopre davanti a chi sta usando il flow.
600
+
570
601
  **Un campo a `null` e' assente.** Il valore ha un campo per tipo e va valorizzato **uno e un solo**
571
602
  campo (§4.2); la §2 dice che cio' che non c'e' si omette, ma un backend che serializza tutte le
572
603
  proprieta' — `System.Text.Json` senza `IgnoreNullValues` lo fa di default — manda
@@ -800,6 +831,10 @@ due misure sono token: `--fb-dialog-width` (1400px) e `--fb-dialog-height` (860p
800
831
  limitate allo spazio disponibile. La larghezza e' quella che serve al compositore dello screen
801
832
  dinamico, che e' a due pannelli.
802
833
 
834
+ La finestra di una **risorsa** ha una misura sua — `--fb-resource-dialog-width` (760px) e
835
+ `--fb-resource-dialog-height` (720px) — perche' dentro c'e' una colonna sola di campi: la misura
836
+ del compositore lascerebbe due terzi di bianco.
837
+
803
838
  Nota sugli archi: il colore si imposta valorizzando le custom properties del tema di
804
839
  @foblex/flow (`--ff-connection-color`, `--ff-marker-color`) invece di sovrascrivere le sue
805
840
  regole, perche' i selettori hanno la stessa specificita' e chi vince dipenderebbe dall'ordine
@@ -837,7 +872,7 @@ distribuire e nessuna dipendenza da un font di icone dell'applicazione ospite.
837
872
  | 13 | **Testo e numero non si confrontano** (`CONDITION_TYPE_MISMATCH`) | `ConditionEditorComponent` conosce il tipo del lato sinistro da `POST /flows/references`: filtra gli operatori applicabili, guida il campo del letterale del secondo operando e segnala la coppia vietata. La regola sta in `core/condition-types.util.ts`, che salta gli operatori con semantica propria (`Contains`, `In`, …). I numeri si scrivono in cultura invariante: `1234,50` viene tradotto in `1234.50`, non troncato |
838
873
  | 14 | **`None` non e' un operatore, e' un "da completare"** | Condizione evidenziata come incompleta, con il conteggio in testa alla sezione e la frase «la bozza si salva, l'attivazione no»; il validatore della demo lo emette come **errore** |
839
874
  | 15 | **Un valore data senza `Z` significa ora locale** | `ValueEditorComponent` ha un selettore «Ora locale / UTC (Z)», dice che cambiare fuso riscrive l'orario e non lo converte, e toglie il suffisso solo per il controllo `datetime-local`, che con il fuso resterebbe vuoto |
840
- | 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) |
875
+ | 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` **soltanto** con `usage="writable"`, cioe' dove serve una destinazione: un membro calcolato si legge — in una condizione, in una formula, in un valore — e filtrarlo ovunque renderebbe invisibili proprio i membri derivati (§13.16). 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) |
841
876
  | 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` |
842
877
  | 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 |
843
878
  | 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` |