@esfaenza/flow-builder 20.3.9 → 20.3.10
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 +20 -0
- package/fesm2022/esfaenza-flow-builder.mjs +179 -18
- package/fesm2022/esfaenza-flow-builder.mjs.map +1 -1
- package/index.d.ts +61 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -254,6 +254,26 @@ Restano fuori i percorsi radicati sul risultato **automatico** di un elemento
|
|
|
254
254
|
(`Leggi_Contatti.Owner.Name`): la validazione non li verifica, e l'editor non accusa cio' che il
|
|
255
255
|
backend non verifica.
|
|
256
256
|
|
|
257
|
+
Il filtro di tipo di un campo (§6.4) guarda il tipo della **radice**, e quindi non basta: in un
|
|
258
|
+
parametro `String` una variabile `Structure` non e' compatibile, ma `Richiesta.Ragione` sì. Per
|
|
259
|
+
questo `<fb-reference-picker>`, dove un filtro c'e', chiede al backend **anche** l'elenco non
|
|
260
|
+
filtrato, e ne ricava due cose: i contenitori compaiono come righe in cui si **entra** — cliccarle
|
|
261
|
+
apre il percorso invece di scegliere un valore del tipo sbagliato — e le radici si riconoscono
|
|
262
|
+
tutte, così un `Leggi_Ordine.Numero` già scritto in un campo `String` non viene accusato di non
|
|
263
|
+
esistere. Le proposte le filtra il backend come prima; i segmenti di un percorso li filtra
|
|
264
|
+
l'editor con la stessa regola, tenendo comunque quelli da cui si scende.
|
|
265
|
+
|
|
266
|
+
**Le globali si navigano come le risorse.** Un percorso dichiarato dall'host puo' portare un
|
|
267
|
+
contenitore, e allora `objectType` dice di che tipo: `$User.Anagrafica.Citta` si propone e si
|
|
268
|
+
verifica come `Richiesta.Ragione`. La regola da non sbagliare e' che vince il **prefisso dichiarato
|
|
269
|
+
piu' lungo** — non tutto cio' che segue lo scope — perche' altrimenti un percorso giusto viene
|
|
270
|
+
segnalato come rotto (§4.1). Dove il catalogo dichiara il contenitore ma non il tipo il rilievo e'
|
|
271
|
+
`PATH_NOT_VERIFIABLE`, e la correzione sta nel catalogo dell'host; navigare uno scalare
|
|
272
|
+
(`$User.Email.Dominio`) e' invece `GLOBAL_UNKNOWN`. Sulle **destinazioni** non cambia niente da
|
|
273
|
+
sapere: le globali sono di sola lettura, membri compresi — le assegnabili sono `$Flow.CurrentStage`,
|
|
274
|
+
`$Flow.ActiveStages` e i campi di `$Record` — e il picker lo dice con `TARGET_NOT_WRITABLE` invece
|
|
275
|
+
di far sembrare il nome inesistente (§5.2).
|
|
276
|
+
|
|
257
277
|
Su una destinazione la colonna che decide non e' la stessa nei due mondi: un membro porta il proprio
|
|
258
278
|
`isWritable`, un campo no. Fuori da un Create o da un Update il contesto non c'e' — un Assignment su
|
|
259
279
|
`Cliente.Codice` non sa se quel record verra' creato o aggiornato — quindi lì basta `isCreateable`
|
|
@@ -3739,6 +3739,20 @@ class ReferencePickerComponent {
|
|
|
3739
3739
|
elementsOnly = input(false, ...(ngDevMode ? [{ debugName: "elementsOnly" }] : []));
|
|
3740
3740
|
valueChange = output();
|
|
3741
3741
|
references = signal([], ...(ngDevMode ? [{ debugName: "references" }] : []));
|
|
3742
|
+
/**
|
|
3743
|
+
* L'elenco **senza** il filtro di tipo, che serve solo a riconoscere le radici dei percorsi.
|
|
3744
|
+
*
|
|
3745
|
+
* Il filtro (§6.4) guarda il tipo della **radice**, e una radice scartata si porta via anche cio'
|
|
3746
|
+
* che sta sotto: in un parametro `String` una variabile `Structure` non e' compatibile, ma
|
|
3747
|
+
* `Richiesta.Ragione` lo e', e `Leggi_Ordine` non e' un `String` mentre `Leggi_Ordine.Numero` lo
|
|
3748
|
+
* e'. Senza questo elenco il primo membro non si puo' proporre e il secondo viene accusato di non
|
|
3749
|
+
* esistere pur essendo un riferimento valido (§4.5).
|
|
3750
|
+
*
|
|
3751
|
+
* Vuoto dove il filtro non c'e': lì {@link references} e' già l'elenco completo.
|
|
3752
|
+
*/
|
|
3753
|
+
unfiltered = signal([], ...(ngDevMode ? [{ debugName: "unfiltered" }] : []));
|
|
3754
|
+
/** Tutto cio' che puo' essere la radice di un percorso, filtrato o no. */
|
|
3755
|
+
roots = computed(() => [...this.references(), ...this.unfiltered()], ...(ngDevMode ? [{ debugName: "roots" }] : []));
|
|
3742
3756
|
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
3743
3757
|
loadError = signal(null, ...(ngDevMode ? [{ debugName: "loadError" }] : []));
|
|
3744
3758
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
@@ -3754,6 +3768,7 @@ class ReferencePickerComponent {
|
|
|
3754
3768
|
const objectType = this.objectType();
|
|
3755
3769
|
if (this.elementsOnly()) {
|
|
3756
3770
|
// I node li conosce già il documento: nessuna richiesta necessaria.
|
|
3771
|
+
this.unfiltered.set([]);
|
|
3757
3772
|
this.references.set(this.store.nodes().map((reference) => ({
|
|
3758
3773
|
name: reference.name,
|
|
3759
3774
|
label: reference.node.label ?? null,
|
|
@@ -3786,8 +3801,53 @@ class ReferencePickerComponent {
|
|
|
3786
3801
|
this.references.set([]);
|
|
3787
3802
|
})
|
|
3788
3803
|
.finally(() => this.isLoading.set(false));
|
|
3804
|
+
/**
|
|
3805
|
+
* Seconda richiesta **senza filtri**, per le sole radici: chi filtra le proposte resta il
|
|
3806
|
+
* backend — da qui non entra nessun valore del tipo sbagliato, entrano i contenitori in cui
|
|
3807
|
+
* scendere e i nomi da non accusare.
|
|
3808
|
+
*
|
|
3809
|
+
* Non filtrata vuol dire anche `getReferences` e non `getWritableReferences`, pure in un campo
|
|
3810
|
+
* di destinazione: la scrivibilita' e' del **percorso**, non della radice, e le radici scartate
|
|
3811
|
+
* sono quelle che servono per dire la cosa giusta — un `$User.Anagrafica.Citta` scritto a mano
|
|
3812
|
+
* e' `TARGET_NOT_WRITABLE`, non un nome che non esiste. Dove non c'e' filtro **ne'** vincolo di
|
|
3813
|
+
* scrittura la prima richiesta le contiene già, e la seconda non si fa.
|
|
3814
|
+
*/
|
|
3815
|
+
const hasTypeFilter = !!query.dataType || query.isCollection != null || !!query.objectType;
|
|
3816
|
+
if (!hasTypeFilter && !writable) {
|
|
3817
|
+
this.unfiltered.set([]);
|
|
3818
|
+
return;
|
|
3819
|
+
}
|
|
3820
|
+
void this.api
|
|
3821
|
+
.getReferences({ definition })
|
|
3822
|
+
.then((list) => this.unfiltered.set(list ?? []))
|
|
3823
|
+
// Una radice in meno degrada le proposte, non il campo: nessun messaggio.
|
|
3824
|
+
.catch(() => this.unfiltered.set([]));
|
|
3789
3825
|
});
|
|
3790
3826
|
}
|
|
3827
|
+
/**
|
|
3828
|
+
* Il riferimento dichiarato piu' **lungo** che sia un prefisso del valore, sui confini del punto.
|
|
3829
|
+
*
|
|
3830
|
+
* Non basta il primo segmento: un nome dichiarato puo' contenere il punto. Le globali sono il caso
|
|
3831
|
+
* per cui la regola esiste — di `$User.Anagrafica.Citta` il dizionario dichiara `$User.Anagrafica`,
|
|
3832
|
+
* e cercare la corrispondenza esatta di tutto cio' che segue lo scope segnalerebbe come rotto un
|
|
3833
|
+
* percorso giusto (§4.1: vince il prefisso dichiarato piu' lungo).
|
|
3834
|
+
*/
|
|
3835
|
+
declaredPrefix = computed(() => {
|
|
3836
|
+
const value = (this.value() ?? '')?.trim();
|
|
3837
|
+
if (!value) {
|
|
3838
|
+
return undefined;
|
|
3839
|
+
}
|
|
3840
|
+
let best;
|
|
3841
|
+
for (const candidate of this.roots()) {
|
|
3842
|
+
if (value !== candidate.name && !value.startsWith(`${candidate.name}.`)) {
|
|
3843
|
+
continue;
|
|
3844
|
+
}
|
|
3845
|
+
if (!best || candidate.name.length > best.name.length) {
|
|
3846
|
+
best = candidate;
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
return best;
|
|
3850
|
+
}, ...(ngDevMode ? [{ debugName: "declaredPrefix" }] : []));
|
|
3791
3851
|
/**
|
|
3792
3852
|
* La risorsa da cui il valore corrente sta navigando, quando la sua forma e' **dichiarata**: una
|
|
3793
3853
|
* `Structure` con la classe, un record con l'entita'. È cio' che rende il percorso verificabile.
|
|
@@ -3797,11 +3857,9 @@ class ReferencePickerComponent {
|
|
|
3797
3857
|
* l'editor non deve accusare cio' che il backend non verifica.
|
|
3798
3858
|
*/
|
|
3799
3859
|
navigableRoot = computed(() => {
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
}
|
|
3804
|
-
const reference = this.references().find((candidate) => candidate.name === root);
|
|
3860
|
+
// Fra tutte le radici: quella di `Richiesta.Ragione` in un campo `String` sta solo nell'elenco
|
|
3861
|
+
// non filtrato.
|
|
3862
|
+
const reference = this.declaredPrefix();
|
|
3805
3863
|
if (!reference || reference.kind === 'ElementOutput' || !reference.objectType || reference.isCollection) {
|
|
3806
3864
|
return undefined;
|
|
3807
3865
|
}
|
|
@@ -3830,6 +3888,16 @@ class ReferencePickerComponent {
|
|
|
3830
3888
|
* segmento di sola lettura non si propone in un campo di destinazione, a meno che da lì il
|
|
3831
3889
|
* percorso continui: `Richiesta.Cliente` non si assegna, ma `Richiesta.Cliente.Email` sì (§5.7).
|
|
3832
3890
|
*/
|
|
3891
|
+
/**
|
|
3892
|
+
* §5.2 — dentro una globale dell'host **niente** e' scrivibile, per quanto il membro si dichiari
|
|
3893
|
+
* tale: le globali le risolve un componente che non ha modo di scriverle, e proporle come
|
|
3894
|
+
* destinazione farebbe attivare un flow che poi fallisce davanti all'utente. L'eccezione sono i
|
|
3895
|
+
* campi del record che innesca, che si assegnano (§4.1).
|
|
3896
|
+
*/
|
|
3897
|
+
isReadOnlyPath = computed(() => {
|
|
3898
|
+
const name = this.navigableRoot()?.reference.name;
|
|
3899
|
+
return !!name && isGlobalReference(name) && referenceRoot(name) !== '$Record';
|
|
3900
|
+
}, ...(ngDevMode ? [{ debugName: "isReadOnlyPath" }] : []));
|
|
3833
3901
|
pathReferences = computed(() => {
|
|
3834
3902
|
const root = this.navigableRoot();
|
|
3835
3903
|
const tail = this.tail();
|
|
@@ -3839,7 +3907,9 @@ class ReferencePickerComponent {
|
|
|
3839
3907
|
const prefix = tail.prefix ? `${root.reference.name}.${tail.prefix}` : root.reference.name;
|
|
3840
3908
|
const kind = tail.level.container.kind === 'object' ? 'RecordField' : 'StructureMember';
|
|
3841
3909
|
return tail.level.entries
|
|
3910
|
+
.map((entry) => (this.isReadOnlyPath() ? { ...entry, isWritable: false } : entry))
|
|
3842
3911
|
.filter((entry) => !this.writableOnly() || entry.isWritable || !!entry.next)
|
|
3912
|
+
.filter((entry) => this.matchesTarget(entry))
|
|
3843
3913
|
.map((entry) => ({
|
|
3844
3914
|
name: `${prefix}.${entry.name}`,
|
|
3845
3915
|
label: entry.label ?? null,
|
|
@@ -3851,12 +3921,53 @@ class ReferencePickerComponent {
|
|
|
3851
3921
|
description: entry.isWritable ? (entry.description ?? null) : 'sola lettura',
|
|
3852
3922
|
}));
|
|
3853
3923
|
}, ...(ngDevMode ? [{ debugName: "pathReferences" }] : []));
|
|
3924
|
+
/**
|
|
3925
|
+
* Lo stesso filtro che il backend applica alle radici (§6.4), applicato ai segmenti di un
|
|
3926
|
+
* percorso: in un parametro `String` non si propone un membro `Date`. Un segmento da cui si
|
|
3927
|
+
* scende resta comunque proposto anche se il suo tipo non combacia — e' la strada per arrivare
|
|
3928
|
+
* al membro che combacia.
|
|
3929
|
+
*/
|
|
3930
|
+
matchesTarget(entry) {
|
|
3931
|
+
if (entry.next) {
|
|
3932
|
+
return true;
|
|
3933
|
+
}
|
|
3934
|
+
const dataType = this.dataType();
|
|
3935
|
+
if (dataType && entry.dataType && entry.dataType !== dataType) {
|
|
3936
|
+
return false;
|
|
3937
|
+
}
|
|
3938
|
+
const isCollection = this.isCollection();
|
|
3939
|
+
if (isCollection != null && entry.isCollection != null && !!entry.isCollection !== isCollection) {
|
|
3940
|
+
return false;
|
|
3941
|
+
}
|
|
3942
|
+
const objectType = this.objectType();
|
|
3943
|
+
return !(objectType && entry.objectType && entry.objectType !== objectType);
|
|
3944
|
+
}
|
|
3945
|
+
/**
|
|
3946
|
+
* I contenitori che il filtro di tipo ha scartato: si mostrano per **entrarci**, non per
|
|
3947
|
+
* scegliersi. Quelli che il filtro ha tenuto stanno già fra le proposte normali.
|
|
3948
|
+
*/
|
|
3949
|
+
containerOptions = computed(() => {
|
|
3950
|
+
const proposed = new Set(this.references().map((reference) => reference.name));
|
|
3951
|
+
return this.unfiltered().filter((candidate) => {
|
|
3952
|
+
if (proposed.has(candidate.name) || !this.canDescend(candidate)) {
|
|
3953
|
+
return false;
|
|
3954
|
+
}
|
|
3955
|
+
// In un campo di destinazione una globale dell'host non porta a niente di assegnabile (§5.2):
|
|
3956
|
+
// proporre di entrarci sarebbe un vicolo cieco. Resta nelle radici, per il messaggio giusto.
|
|
3957
|
+
return !(this.writableOnly() &&
|
|
3958
|
+
isGlobalReference(candidate.name) &&
|
|
3959
|
+
referenceRoot(candidate.name) !== '$Record');
|
|
3960
|
+
});
|
|
3961
|
+
}, ...(ngDevMode ? [{ debugName: "containerOptions" }] : []));
|
|
3962
|
+
/** `true` → questa riga apre il percorso e non e' un valore valido per il campo. */
|
|
3963
|
+
isContainerOnly(reference) {
|
|
3964
|
+
return this.containerOptions().some((candidate) => candidate.name === reference.name);
|
|
3965
|
+
}
|
|
3854
3966
|
options = computed(() => {
|
|
3855
3967
|
const needle = this.query()?.trim().toLowerCase();
|
|
3856
|
-
// Le globali assegnabili — `$Flow.CurrentStage
|
|
3857
|
-
//
|
|
3858
|
-
|
|
3859
|
-
const all = [...this.references(), ...this.pathReferences()];
|
|
3968
|
+
// Le due globali assegnabili — `$Flow.CurrentStage` e `$Flow.ActiveStages` — le comprende già
|
|
3969
|
+
// `POST /flows/references/writable`: aggiungerle qui le duplicherebbe (§5.2, §6.4).
|
|
3970
|
+
const all = [...this.references(), ...this.containerOptions(), ...this.pathReferences()];
|
|
3860
3971
|
if (!needle) {
|
|
3861
3972
|
return all;
|
|
3862
3973
|
}
|
|
@@ -3913,11 +4024,16 @@ class ReferencePickerComponent {
|
|
|
3913
4024
|
* elemento): il percorso resta fuori dalla validazione, quindi si accetta senza segnalare;
|
|
3914
4025
|
* - `host`: scope del sistema ospite che **non dichiara percorsi**: non verificabile (§4.1);
|
|
3915
4026
|
* - `member`: percorso dentro una forma dichiarata, verificato fino in fondo (§4.4, §4.7.1);
|
|
4027
|
+
* - `containerRoot`: il contenitore da solo in un campo che vuole un altro tipo: il valore e' un
|
|
4028
|
+
* suo membro, non lui;
|
|
3916
4029
|
* - `memberUnknown`: un segmento non esiste nella sua tappa: `STRUCTURE_MEMBER_UNKNOWN` su una
|
|
3917
4030
|
* classe, `FIELD_UNKNOWN` su un'entita', e a differenza di prima si sa per certo;
|
|
3918
4031
|
* - `memberNotWritable`: il segmento esiste, non e' scrivibile, e questo campo vuole una
|
|
3919
4032
|
* destinazione: `TARGET_NOT_WRITABLE`;
|
|
3920
4033
|
* - `pathUnverified`: la catena si interrompe (`PATH_NOT_VERIFIABLE`): avviso, non errore;
|
|
4034
|
+
* - `globalPathUntyped`: percorso globale che porta un contenitore senza dichiararne il tipo:
|
|
4035
|
+
* `PATH_NOT_VERIFIABLE`, e la correzione sta nel catalogo dell'host, non nel flow (§4.1);
|
|
4036
|
+
* - `globalPathInvalid`: si naviga un percorso globale scalare o una collection: `GLOBAL_UNKNOWN`;
|
|
3921
4037
|
* - `unknown`: nessuna corrispondenza: si avvisa, senza bloccare. Ci finisce anche il
|
|
3922
4038
|
* percorso inesistente di uno scope che i percorsi li dichiara, perche' lì il backend
|
|
3923
4039
|
* risponderebbe `GLOBAL_UNKNOWN`.
|
|
@@ -3937,6 +4053,11 @@ class ReferencePickerComponent {
|
|
|
3937
4053
|
}
|
|
3938
4054
|
// Dentro una forma dichiarata il percorso e' verificabile: dirlo "non verificato" sarebbe falso.
|
|
3939
4055
|
if (this.navigableRoot()) {
|
|
4056
|
+
// Il contenitore da solo: non e' fra le proposte (lo avrebbe intercettato `known`), quindi il
|
|
4057
|
+
// filtro del campo lo ha scartato — e il valore giusto e' un suo membro, non lui.
|
|
4058
|
+
if (!this.navigatedPath()) {
|
|
4059
|
+
return 'containerRoot';
|
|
4060
|
+
}
|
|
3940
4061
|
const resolution = this.resolution();
|
|
3941
4062
|
switch (resolution?.status) {
|
|
3942
4063
|
case 'unknown':
|
|
@@ -3944,13 +4065,30 @@ class ReferencePickerComponent {
|
|
|
3944
4065
|
case 'unverifiable':
|
|
3945
4066
|
return 'pathUnverified';
|
|
3946
4067
|
case 'resolved':
|
|
3947
|
-
return this.writableOnly() && !resolution.last?.isWritable
|
|
4068
|
+
return this.writableOnly() && (this.isReadOnlyPath() || !resolution.last?.isWritable)
|
|
4069
|
+
? 'memberNotWritable'
|
|
4070
|
+
: 'member';
|
|
3948
4071
|
default:
|
|
3949
4072
|
// Percorso ancora aperto (`Richiesta.`) o risposta non arrivata: non si accusa nessuno.
|
|
3950
4073
|
return 'empty';
|
|
3951
4074
|
}
|
|
3952
4075
|
}
|
|
3953
|
-
|
|
4076
|
+
/**
|
|
4077
|
+
* §4.1 — un percorso globale dichiarato che non porta a un contenitore. I due esiti sono
|
|
4078
|
+
* diversi e vanno detti diversi: senza `objectType` si sa che c'e' un contenitore ma non di che
|
|
4079
|
+
* tipo (`PATH_NOT_VERIFIABLE`, avviso), mentre su uno scalare o una collection non c'e'
|
|
4080
|
+
* proprio niente da navigare (`GLOBAL_UNKNOWN`, errore).
|
|
4081
|
+
*/
|
|
4082
|
+
const prefix = this.declaredPrefix();
|
|
4083
|
+
if (prefix && prefix.name !== value && isGlobalReference(prefix.name)) {
|
|
4084
|
+
const isContainer = this.dictionaries.isStructure(prefix.dataType) || prefix.dataType === 'Object';
|
|
4085
|
+
return isContainer && !prefix.objectType && !prefix.isCollection
|
|
4086
|
+
? 'globalPathUntyped'
|
|
4087
|
+
: 'globalPathInvalid';
|
|
4088
|
+
}
|
|
4089
|
+
// Fra **tutte** le radici: `Leggi_Ordine` non e' un `String`, ma `Leggi_Ordine.Numero` sì, e
|
|
4090
|
+
// accusarlo di non esistere sarebbe falso (§4.5).
|
|
4091
|
+
if (this.roots().some((reference) => reference.name === root)) {
|
|
3954
4092
|
return 'navigated';
|
|
3955
4093
|
}
|
|
3956
4094
|
// Se l'elenco non e' arrivato, non si accusa nessuno.
|
|
@@ -3976,6 +4114,10 @@ class ReferencePickerComponent {
|
|
|
3976
4114
|
const what = this.tailIsObject() ? 'Campo' : 'Membro';
|
|
3977
4115
|
return `${what} di ${this.tailContainer()}: il percorso e’ verificato fino in fondo.`;
|
|
3978
4116
|
}
|
|
4117
|
+
case 'containerRoot':
|
|
4118
|
+
return this.tailIsObject()
|
|
4119
|
+
? 'Questo e’ il record intero, e il campo vuole un altro tipo: scegli un suo campo.'
|
|
4120
|
+
: 'Questa e’ l’istanza di classe, e il campo vuole un altro tipo: scegli un suo membro.';
|
|
3979
4121
|
case 'memberUnknown': {
|
|
3980
4122
|
if (!resolution) {
|
|
3981
4123
|
return null;
|
|
@@ -3988,19 +4130,29 @@ class ReferencePickerComponent {
|
|
|
3988
4130
|
return names ? `${head} Disponibili: ${names}.` : head;
|
|
3989
4131
|
}
|
|
3990
4132
|
case 'memberNotWritable':
|
|
4133
|
+
// Il motivo cambia la correzione: dentro una globale non c'e' niente da rendere scrivibile.
|
|
4134
|
+
if (this.isReadOnlyPath()) {
|
|
4135
|
+
return 'Le variabili globali sono di sola lettura, membri compresi: assegnarlo e’ TARGET_NOT_WRITABLE.';
|
|
4136
|
+
}
|
|
3991
4137
|
return this.tailIsObject()
|
|
3992
4138
|
? 'Questo campo non si scrive ne’ creando ne’ aggiornando un record: assegnarlo e’ TARGET_NOT_WRITABLE.'
|
|
3993
4139
|
: 'Questo membro e’ calcolato: si legge, ma assegnarlo e’ TARGET_NOT_WRITABLE.';
|
|
3994
4140
|
case 'pathUnverified':
|
|
3995
4141
|
return resolution ? pathNotVerifiableMessage(resolution) : null;
|
|
4142
|
+
case 'globalPathUntyped':
|
|
4143
|
+
return `«${this.declaredPrefix()?.name}» porta un contenitore, ma il catalogo non ne dichiara il tipo: il percorso non e’ verificabile (PATH_NOT_VERIFIABLE).`;
|
|
4144
|
+
case 'globalPathInvalid':
|
|
4145
|
+
return `«${this.declaredPrefix()?.name}» e’ un valore, non un contenitore: dopo il punto non c’e’ niente da navigare (GLOBAL_UNKNOWN).`;
|
|
3996
4146
|
case 'unknown':
|
|
3997
4147
|
return 'Questo nome non e’ fra i riferimenti disponibili: la validazione lo segnalerebbe.';
|
|
3998
4148
|
default:
|
|
3999
4149
|
return null;
|
|
4000
4150
|
}
|
|
4001
4151
|
}, ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
4002
|
-
/**
|
|
4003
|
-
|
|
4152
|
+
/** Gli stati che sono avvisi: «non lo so», o un valore da correggere che non blocca. */
|
|
4153
|
+
isHintWarning = computed(() => ['unknown', 'containerRoot', 'globalPathUntyped'].includes(this.valueState()), ...(ngDevMode ? [{ debugName: "isHintWarning" }] : []));
|
|
4154
|
+
/** Gli stati che sono errori e non avvisi: il colore deve dirlo. */
|
|
4155
|
+
isHintError = computed(() => ['memberUnknown', 'memberNotWritable', 'globalPathInvalid'].includes(this.valueState()), ...(ngDevMode ? [{ debugName: "isHintError" }] : []));
|
|
4004
4156
|
errorMessage = computed(() => this.loadError(), ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
4005
4157
|
open() {
|
|
4006
4158
|
if (this.disabled()) {
|
|
@@ -4019,6 +4171,11 @@ class ReferencePickerComponent {
|
|
|
4019
4171
|
this.query.set(value);
|
|
4020
4172
|
}
|
|
4021
4173
|
choose(reference) {
|
|
4174
|
+
// Un contenitore fuori tipo non e' un valore: cliccarlo vuol dire entrarci.
|
|
4175
|
+
if (this.isContainerOnly(reference)) {
|
|
4176
|
+
this.descend(reference);
|
|
4177
|
+
return;
|
|
4178
|
+
}
|
|
4022
4179
|
this.valueChange.emit(reference.name);
|
|
4023
4180
|
this.close();
|
|
4024
4181
|
}
|
|
@@ -4056,14 +4213,18 @@ class ReferencePickerComponent {
|
|
|
4056
4213
|
if (reference.description) {
|
|
4057
4214
|
parts.push(reference.description);
|
|
4058
4215
|
}
|
|
4216
|
+
if (this.isContainerOnly(reference)) {
|
|
4217
|
+
// Dirlo: la riga c'e' ma il valore non e' quello, e senza spiegazione sembra un errore.
|
|
4218
|
+
parts.push(reference.dataType === 'Object' ? 'entra e scegli un campo' : 'entra e scegli un membro');
|
|
4219
|
+
}
|
|
4059
4220
|
return parts.join(' · ');
|
|
4060
4221
|
}
|
|
4061
4222
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: ReferencePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4062
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.27", type: ReferencePickerComponent, isStandalone: true, selector: "fb-reference-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: true, isRequired: false, transformFunction: null }, isCollection: { classPropertyName: "isCollection", publicName: "isCollection", isSignal: true, isRequired: false, transformFunction: null }, objectType: { classPropertyName: "objectType", publicName: "objectType", isSignal: true, isRequired: false, transformFunction: null }, writableOnly: { classPropertyName: "writableOnly", publicName: "writableOnly", isSignal: true, isRequired: false, transformFunction: null }, elementsOnly: { classPropertyName: "elementsOnly", publicName: "elementsOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"fb-ref\" [class.fb-ref--open]=\"isOpen()\">\r\n <div class=\"fb-ref__control\">\r\n <input\r\n class=\"fb-ref__input\"\r\n type=\"text\"\r\n [value]=\"value() || ''\"\r\n [placeholder]=\"placeholder()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (input)=\"onManualInput($any($event.target).value)\"\r\n (focus)=\"open()\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__toggle\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-label=\"Mostra i riferimenti disponibili\"\r\n (click)=\"toggle()\"\r\n >\r\n \u25BE\r\n </button>\r\n @if (value()) {\r\n <button type=\"button\" class=\"fb-ref__clear\" aria-label=\"Svuota\" (click)=\"clear()\">\u00D7</button>\r\n }\r\n </div>\r\n\r\n @if (hint()) {\r\n <!-- Un membro inesistente o non scrivibile e' un **errore**: mostrarlo come avviso direbbe il falso. -->\r\n <p\r\n class=\"fb-ref__hint\"\r\n [class.fb-ref__hint--warn]=\"
|
|
4223
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.27", type: ReferencePickerComponent, isStandalone: true, selector: "fb-reference-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: true, isRequired: false, transformFunction: null }, isCollection: { classPropertyName: "isCollection", publicName: "isCollection", isSignal: true, isRequired: false, transformFunction: null }, objectType: { classPropertyName: "objectType", publicName: "objectType", isSignal: true, isRequired: false, transformFunction: null }, writableOnly: { classPropertyName: "writableOnly", publicName: "writableOnly", isSignal: true, isRequired: false, transformFunction: null }, elementsOnly: { classPropertyName: "elementsOnly", publicName: "elementsOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"fb-ref\" [class.fb-ref--open]=\"isOpen()\">\r\n <div class=\"fb-ref__control\">\r\n <input\r\n class=\"fb-ref__input\"\r\n type=\"text\"\r\n [value]=\"value() || ''\"\r\n [placeholder]=\"placeholder()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (input)=\"onManualInput($any($event.target).value)\"\r\n (focus)=\"open()\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__toggle\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-label=\"Mostra i riferimenti disponibili\"\r\n (click)=\"toggle()\"\r\n >\r\n \u25BE\r\n </button>\r\n @if (value()) {\r\n <button type=\"button\" class=\"fb-ref__clear\" aria-label=\"Svuota\" (click)=\"clear()\">\u00D7</button>\r\n }\r\n </div>\r\n\r\n @if (hint()) {\r\n <!-- Un membro inesistente o non scrivibile e' un **errore**: mostrarlo come avviso direbbe il falso. -->\r\n <p\r\n class=\"fb-ref__hint\"\r\n [class.fb-ref__hint--warn]=\"isHintWarning()\"\r\n [class.fb-ref__hint--error]=\"isHintError()\"\r\n >\r\n {{ hint() }}\r\n </p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"fb-ref__hint fb-ref__hint--warn\">\r\n Elenco dei riferimenti non disponibile: puoi scrivere il nome a mano.\r\n </p>\r\n }\r\n\r\n @if (isOpen()) {\r\n <div class=\"fb-ref__panel\" role=\"listbox\">\r\n <input\r\n class=\"fb-ref__search\"\r\n type=\"search\"\r\n placeholder=\"Filtra\"\r\n aria-label=\"Filtra i riferimenti\"\r\n (input)=\"onQuery($any($event.target).value)\"\r\n />\r\n @if (groups().length === 0) {\r\n <p class=\"fb-ref__empty\">Nessun riferimento compatibile.</p>\r\n }\r\n @for (group of groups(); track group.kind) {\r\n <div class=\"fb-ref__group\">\r\n <span class=\"fb-ref__group-label\">{{ group.label }}</span>\r\n @for (item of group.items; track item.name) {\r\n <!-- Due bottoni dove il percorso continua: scegliere il riferimento e scendere di un\r\n livello sono cose diverse, e su una Structure o un record servono entrambe. -->\r\n <div class=\"fb-ref__row\">\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__option\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"item.name === value()\"\r\n [title]=\"isContainerOnly(item) ? 'Il tipo non e\u2019 quello del campo: entra e scegli dentro' : ''\"\r\n (click)=\"choose(item)\"\r\n >\r\n <span class=\"fb-ref__name\">{{ item.name }}</span>\r\n <span class=\"fb-ref__meta\">{{ describe(item) }}</span>\r\n </button>\r\n @if (canDescend(item)) {\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__into\"\r\n [attr.aria-label]=\"'Entra in ' + item.name\"\r\n title=\"Entra e proponi i segmenti\"\r\n (click)=\"descend(item)\"\r\n >\r\n \u203A\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"fb-ref__close\" (click)=\"close()\">Chiudi</button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}.fb-ref{position:relative}.fb-ref__control{display:flex;align-items:stretch;gap:0;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);overflow:hidden}.fb-ref--open .fb-ref__control{border-color:var(--fb-accent, #2f6feb)}.fb-ref__input{flex:1;min-width:0;padding:5px 7px;border:0;background:transparent;color:var(--fb-text, #1d2939);font:inherit;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.fb-ref__input:focus-visible{outline:none}.fb-ref__toggle,.fb-ref__clear{flex:0 0 auto;padding:0 7px;border:0;border-left:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:12px;cursor:pointer}.fb-ref__toggle:hover,.fb-ref__clear:hover{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__hint{margin:3px 0 0;font-size:10px;line-height:1.35;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__hint--warn{color:var(--fb-warning, #b7791f)}.fb-ref__hint--error{color:var(--fb-error, #c9372c)}.fb-ref__panel{position:absolute;z-index:30;top:calc(100% + 3px);left:0;right:0;max-height:260px;overflow-y:auto;padding:6px;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);box-shadow:0 6px 18px #10182829}.fb-ref__search{box-sizing:border-box;width:100%;margin-bottom:6px;padding:4px 6px;border:1px solid var(--fb-border, #d6dae1);border-radius:5px;font:inherit;font-size:12px}.fb-ref__group{margin-bottom:6px}.fb-ref__group-label{display:block;padding:2px 4px;font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__row{display:flex;align-items:stretch;gap:2px}.fb-ref__into{flex:0 0 auto;padding:0 7px;border:0;border-radius:4px;background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:13px;cursor:pointer}.fb-ref__into:hover{background:var(--fb-surface-alt, #f8f9fb);color:var(--fb-accent, #2f6feb)}.fb-ref__option{display:flex;flex:1;flex-direction:column;min-width:0;width:100%;padding:4px 6px;border:0;border-radius:4px;background:transparent;color:var(--fb-text, #1d2939);font:inherit;text-align:left;cursor:pointer}.fb-ref__option:hover,.fb-ref__option[aria-selected=true]{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.fb-ref__meta{font-size:10px;color:var(--fb-text-muted, #667085)}.fb-ref__empty{margin:4px;font-size:11px;color:var(--fb-text-muted, #667085)}.fb-ref__close{width:100%;margin-top:4px;padding:4px;border:0;border-top:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:11px;cursor:pointer}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4063
4224
|
}
|
|
4064
4225
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: ReferencePickerComponent, decorators: [{
|
|
4065
4226
|
type: Component,
|
|
4066
|
-
args: [{ selector: 'fb-reference-picker', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-ref\" [class.fb-ref--open]=\"isOpen()\">\r\n <div class=\"fb-ref__control\">\r\n <input\r\n class=\"fb-ref__input\"\r\n type=\"text\"\r\n [value]=\"value() || ''\"\r\n [placeholder]=\"placeholder()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (input)=\"onManualInput($any($event.target).value)\"\r\n (focus)=\"open()\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__toggle\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-label=\"Mostra i riferimenti disponibili\"\r\n (click)=\"toggle()\"\r\n >\r\n \u25BE\r\n </button>\r\n @if (value()) {\r\n <button type=\"button\" class=\"fb-ref__clear\" aria-label=\"Svuota\" (click)=\"clear()\">\u00D7</button>\r\n }\r\n </div>\r\n\r\n @if (hint()) {\r\n <!-- Un membro inesistente o non scrivibile e' un **errore**: mostrarlo come avviso direbbe il falso. -->\r\n <p\r\n class=\"fb-ref__hint\"\r\n [class.fb-ref__hint--warn]=\"
|
|
4227
|
+
args: [{ selector: 'fb-reference-picker', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-ref\" [class.fb-ref--open]=\"isOpen()\">\r\n <div class=\"fb-ref__control\">\r\n <input\r\n class=\"fb-ref__input\"\r\n type=\"text\"\r\n [value]=\"value() || ''\"\r\n [placeholder]=\"placeholder()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (input)=\"onManualInput($any($event.target).value)\"\r\n (focus)=\"open()\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__toggle\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-label=\"Mostra i riferimenti disponibili\"\r\n (click)=\"toggle()\"\r\n >\r\n \u25BE\r\n </button>\r\n @if (value()) {\r\n <button type=\"button\" class=\"fb-ref__clear\" aria-label=\"Svuota\" (click)=\"clear()\">\u00D7</button>\r\n }\r\n </div>\r\n\r\n @if (hint()) {\r\n <!-- Un membro inesistente o non scrivibile e' un **errore**: mostrarlo come avviso direbbe il falso. -->\r\n <p\r\n class=\"fb-ref__hint\"\r\n [class.fb-ref__hint--warn]=\"isHintWarning()\"\r\n [class.fb-ref__hint--error]=\"isHintError()\"\r\n >\r\n {{ hint() }}\r\n </p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"fb-ref__hint fb-ref__hint--warn\">\r\n Elenco dei riferimenti non disponibile: puoi scrivere il nome a mano.\r\n </p>\r\n }\r\n\r\n @if (isOpen()) {\r\n <div class=\"fb-ref__panel\" role=\"listbox\">\r\n <input\r\n class=\"fb-ref__search\"\r\n type=\"search\"\r\n placeholder=\"Filtra\"\r\n aria-label=\"Filtra i riferimenti\"\r\n (input)=\"onQuery($any($event.target).value)\"\r\n />\r\n @if (groups().length === 0) {\r\n <p class=\"fb-ref__empty\">Nessun riferimento compatibile.</p>\r\n }\r\n @for (group of groups(); track group.kind) {\r\n <div class=\"fb-ref__group\">\r\n <span class=\"fb-ref__group-label\">{{ group.label }}</span>\r\n @for (item of group.items; track item.name) {\r\n <!-- Due bottoni dove il percorso continua: scegliere il riferimento e scendere di un\r\n livello sono cose diverse, e su una Structure o un record servono entrambe. -->\r\n <div class=\"fb-ref__row\">\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__option\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"item.name === value()\"\r\n [title]=\"isContainerOnly(item) ? 'Il tipo non e\u2019 quello del campo: entra e scegli dentro' : ''\"\r\n (click)=\"choose(item)\"\r\n >\r\n <span class=\"fb-ref__name\">{{ item.name }}</span>\r\n <span class=\"fb-ref__meta\">{{ describe(item) }}</span>\r\n </button>\r\n @if (canDescend(item)) {\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__into\"\r\n [attr.aria-label]=\"'Entra in ' + item.name\"\r\n title=\"Entra e proponi i segmenti\"\r\n (click)=\"descend(item)\"\r\n >\r\n \u203A\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"fb-ref__close\" (click)=\"close()\">Chiudi</button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}.fb-ref{position:relative}.fb-ref__control{display:flex;align-items:stretch;gap:0;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);overflow:hidden}.fb-ref--open .fb-ref__control{border-color:var(--fb-accent, #2f6feb)}.fb-ref__input{flex:1;min-width:0;padding:5px 7px;border:0;background:transparent;color:var(--fb-text, #1d2939);font:inherit;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.fb-ref__input:focus-visible{outline:none}.fb-ref__toggle,.fb-ref__clear{flex:0 0 auto;padding:0 7px;border:0;border-left:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:12px;cursor:pointer}.fb-ref__toggle:hover,.fb-ref__clear:hover{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__hint{margin:3px 0 0;font-size:10px;line-height:1.35;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__hint--warn{color:var(--fb-warning, #b7791f)}.fb-ref__hint--error{color:var(--fb-error, #c9372c)}.fb-ref__panel{position:absolute;z-index:30;top:calc(100% + 3px);left:0;right:0;max-height:260px;overflow-y:auto;padding:6px;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);box-shadow:0 6px 18px #10182829}.fb-ref__search{box-sizing:border-box;width:100%;margin-bottom:6px;padding:4px 6px;border:1px solid var(--fb-border, #d6dae1);border-radius:5px;font:inherit;font-size:12px}.fb-ref__group{margin-bottom:6px}.fb-ref__group-label{display:block;padding:2px 4px;font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__row{display:flex;align-items:stretch;gap:2px}.fb-ref__into{flex:0 0 auto;padding:0 7px;border:0;border-radius:4px;background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:13px;cursor:pointer}.fb-ref__into:hover{background:var(--fb-surface-alt, #f8f9fb);color:var(--fb-accent, #2f6feb)}.fb-ref__option{display:flex;flex:1;flex-direction:column;min-width:0;width:100%;padding:4px 6px;border:0;border-radius:4px;background:transparent;color:var(--fb-text, #1d2939);font:inherit;text-align:left;cursor:pointer}.fb-ref__option:hover,.fb-ref__option[aria-selected=true]{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.fb-ref__meta{font-size:10px;color:var(--fb-text-muted, #667085)}.fb-ref__empty{margin:4px;font-size:11px;color:var(--fb-text-muted, #667085)}.fb-ref__close{width:100%;margin-top:4px;padding:4px;border:0;border-top:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:11px;cursor:pointer}\n"] }]
|
|
4067
4228
|
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dataType: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataType", required: false }] }], isCollection: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCollection", required: false }] }], objectType: [{ type: i0.Input, args: [{ isSignal: true, alias: "objectType", required: false }] }], writableOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "writableOnly", required: false }] }], elementsOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "elementsOnly", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
4068
4229
|
|
|
4069
4230
|
/**
|
|
@@ -6118,9 +6279,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
6118
6279
|
* 1. **Le operazioni sono eseguite nell'ordine dichiarato**, quindi devono essere
|
|
6119
6280
|
* riordinabili: un'interfaccia che le presenta come un insieme nasconde la semantica.
|
|
6120
6281
|
* 2. **Cosa puo' stare in `assignToReference`**: una variabile, un campo di una variabile
|
|
6121
|
-
* record, un campo di `$Record` e, fra le globali, `$Flow.CurrentStage
|
|
6122
|
-
* `$Flow.ActiveStages`
|
|
6123
|
-
*
|
|
6282
|
+
* record, un campo di `$Record` e, fra le globali, soltanto `$Flow.CurrentStage` e
|
|
6283
|
+
* `$Flow.ActiveStages` — le propone già `POST /flows/references/writable`. Tutto il resto e'
|
|
6284
|
+
* di sola lettura, comprese le globali dell'host e i loro membri (§5.2).
|
|
6124
6285
|
* 3. Gli operatori marcati `expectsCollection` hanno senso **solo** su destinazioni
|
|
6125
6286
|
* collection: su una variabile singola non falliscono, non fanno nulla.
|
|
6126
6287
|
*/
|