@esfaenza/flow-builder 20.3.51 → 20.3.53
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 +30 -1
- package/fesm2022/esfaenza-flow-builder.mjs +175 -5
- package/fesm2022/esfaenza-flow-builder.mjs.map +1 -1
- package/index.d.ts +143 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -394,11 +394,40 @@ Tre conseguenze nell'editor:
|
|
|
394
394
|
- **la coppia si legge in un posto solo**, `FlowDictionaryStore.flowTypeOf`. Tre dei sei tipi sono
|
|
395
395
|
`AutoLaunched`, quindi ogni domanda posta al solo `processType` da qui in avanti risponde male: e'
|
|
396
396
|
il motivo per cui la palette decide di offrire gli screen da `allowsScreens` e non piu' dal
|
|
397
|
-
`processType`, e per cui lo Start propone i soli `triggerTypes` del tipo scelto
|
|
397
|
+
`processType`, e per cui lo Start propone i soli `triggerTypes` del tipo scelto — e su un flow
|
|
398
|
+
innescato da un record nemmeno quelli, vedi qui sotto;
|
|
398
399
|
- `flowType` compare **derivato** nell'elenco dei flow, nelle versioni e nell'outline, e vale `null`
|
|
399
400
|
per cio' che non e' uno dei sei (un `Evaluation`, un'orchestrazione senza trigger): lì si mostra il
|
|
400
401
|
`processType`, e non e' un difetto da correggere.
|
|
401
402
|
|
|
403
|
+
**Quando parte un flow innescato da un record (§3.4).** I campi sono due — `recordTriggerType` è
|
|
404
|
+
l'**operazione**, `triggerType` il **momento** rispetto alla scrittura — ma non sono due assi liberi,
|
|
405
|
+
perché l'eliminazione ha un momento solo: le coppie che significano qualcosa sono sei. Da due tendine
|
|
406
|
+
indipendenti si dichiara «prima dell'eliminazione» insieme a «alla creazione», e il runtime la legge
|
|
407
|
+
come un'eliminazione — con `RecordBeforeDelete` l'operazione la dice il trigger e `recordTriggerType`
|
|
408
|
+
non viene guardato — cioè il flow parte su un'operazione che nessuno ha scelto.
|
|
409
|
+
|
|
410
|
+
Quindi su questi flow l'inspector dello Start **non ha la tendina «quando parte»**: chiede
|
|
411
|
+
l'oggetto, poi l'**operazione**, poi i criteri, poi il **momento** fra i soli che l'operazione
|
|
412
|
+
ammette. Quali siano lo dice la voce di `recordTriggerTypes` nei dizionari — `triggerTypes`,
|
|
413
|
+
`defaultTriggerType`, `allowsTimingChoice`, `usesPriorRecord` — e sono gli stessi flag che applica il
|
|
414
|
+
backend: proporre i `triggerTypes` di primo livello significa proporre coppie che la validazione
|
|
415
|
+
rifiuta. Quattro conseguenze:
|
|
416
|
+
|
|
417
|
+
- i due campi si scrivono **insieme, in una sola mutazione**: con due, l'annulla riporterebbe
|
|
418
|
+
indietro il momento lasciando l'operazione nuova, cioè una coppia che non è nessuna delle sei;
|
|
419
|
+
- dove il momento è unico la domanda **non si pone** e il campo si scrive comunque, perché il
|
|
420
|
+
contratto chiede entrambi;
|
|
421
|
+
- `doesRequireRecordChangedToMeetCriteria` compare **solo** dove l'operazione porta
|
|
422
|
+
`usesPriorRecord`: alla creazione e all'eliminazione non c'è un «prima» da confrontare, e il flag
|
|
423
|
+
resterebbe inerte;
|
|
424
|
+
- `START_TRIGGER_MISMATCH` da questa sequenza **non è esprimibile**. Lo si incontra solo aprendo un
|
|
425
|
+
documento scritto altrove, e lì l'editor lo **dice** e offre il comando per rimettere il momento fra
|
|
426
|
+
quelli ammessi, invece di correggerlo da sé — quale metà della coppia sia quella voluta non lo sa.
|
|
427
|
+
Gli altri due rilievi sono avvisi: operazione assente su un trigger di salvataggio vale «ogni
|
|
428
|
+
salvataggio» (`START_RECORD_TRIGGER_MISSING`), operazione su un flow che non è innescato da un
|
|
429
|
+
record è inerte (`START_RECORD_TRIGGER_IGNORED`).
|
|
430
|
+
|
|
402
431
|
**L'attivazione, e la sua seconda meta' (§8).** I tre tipi che non partono da soli vanno **presi in
|
|
403
432
|
carico** dall'infrastruttura dell'ospite — uno scheduler, un bus, un intercettore delle scritture — e
|
|
404
433
|
il backend li registra prima di attivare. Da lì due esiti che il pannello dei problemi non spiega,
|
|
@@ -3885,6 +3885,7 @@ class FlowDictionaryStore {
|
|
|
3885
3885
|
globalVariables = computed(() => this._dictionaries().globalVariables ?? [], ...(ngDevMode ? [{ debugName: "globalVariables" }] : []));
|
|
3886
3886
|
processTypes = computed(() => this._dictionaries().processTypes ?? [], ...(ngDevMode ? [{ debugName: "processTypes" }] : []));
|
|
3887
3887
|
triggerTypes = computed(() => this._dictionaries().triggerTypes ?? [], ...(ngDevMode ? [{ debugName: "triggerTypes" }] : []));
|
|
3888
|
+
/** §3.4 — le quattro operazioni che innescano un flow da un record, coi momenti che ammettono. */
|
|
3888
3889
|
recordTriggerTypes = computed(() => this._dictionaries().recordTriggerTypes ?? [], ...(ngDevMode ? [{ debugName: "recordTriggerTypes" }] : []));
|
|
3889
3890
|
// -------------------------------------------------------------------------
|
|
3890
3891
|
// §3.4 — il tipo di flow
|
|
@@ -3924,6 +3925,73 @@ class FlowDictionaryStore {
|
|
|
3924
3925
|
flowTypeOfDefinition(definition) {
|
|
3925
3926
|
return this.flowTypeOf(definition?.processType, definition?.start?.[0]?.triggerType);
|
|
3926
3927
|
}
|
|
3928
|
+
// -------------------------------------------------------------------------
|
|
3929
|
+
// §3.4 — l'operazione e il momento di un trigger su record
|
|
3930
|
+
// -------------------------------------------------------------------------
|
|
3931
|
+
/**
|
|
3932
|
+
* La voce di un'operazione (`recordTriggerType`). Voce assente = nessun flag, cioe' «non lo so»:
|
|
3933
|
+
* chi legge torna a proporre i momenti del tipo di flow invece di togliere opzioni.
|
|
3934
|
+
*/
|
|
3935
|
+
recordTriggerType(value) {
|
|
3936
|
+
return value ? this.recordTriggerTypes().find((entry) => entry.value === value) : undefined;
|
|
3937
|
+
}
|
|
3938
|
+
/**
|
|
3939
|
+
* §3.4 — i **momenti** che un'operazione ammette, ed e' l'unico elenco da cui proporli: quello di
|
|
3940
|
+
* primo livello proporrebbe coppie che la validazione rifiuta (`START_TRIGGER_MISMATCH`).
|
|
3941
|
+
*
|
|
3942
|
+
* Qui sta la normalizzazione delle due forme in cui le voci arrivano — il solo valore oppure la
|
|
3943
|
+
* voce intera — perche' un host puo' serializzarle in entrambi i modi e riconoscerne una sola
|
|
3944
|
+
* significa funzionare con meta' dei dizionari senza che nulla lo dica. Dove arriva il solo
|
|
3945
|
+
* valore, etichetta e descrizione si ripescano dal dizionario `triggerTypes`, che e' dove stanno
|
|
3946
|
+
* comunque; dove non c'e' nemmeno quello resta il valore grezzo, che e' meglio di una riga vuota.
|
|
3947
|
+
*
|
|
3948
|
+
* Elenco vuoto = il dizionario non li dichiara, **non** «nessun momento ammesso».
|
|
3949
|
+
*/
|
|
3950
|
+
recordTriggerTimings(value) {
|
|
3951
|
+
const declared = this.recordTriggerType(value)?.triggerTypes ?? [];
|
|
3952
|
+
return declared.map((timing) => {
|
|
3953
|
+
if (typeof timing !== 'string') {
|
|
3954
|
+
return timing;
|
|
3955
|
+
}
|
|
3956
|
+
const known = this.triggerTypes().find((entry) => entry.value === timing);
|
|
3957
|
+
return known ?? { value: timing, label: timing };
|
|
3958
|
+
});
|
|
3959
|
+
}
|
|
3960
|
+
/**
|
|
3961
|
+
* Il momento da scrivere quando non si sceglie — l'eliminazione — o quando quello in mano non e'
|
|
3962
|
+
* ammesso dall'operazione appena scelta. Ripiega sul primo dichiarato: `defaultTriggerType` e'
|
|
3963
|
+
* facoltativo, e un'operazione con un momento solo non ha bisogno di dichiararlo due volte.
|
|
3964
|
+
*/
|
|
3965
|
+
defaultTimingOf(value) {
|
|
3966
|
+
const entry = this.recordTriggerType(value);
|
|
3967
|
+
return entry?.defaultTriggerType ?? this.recordTriggerTimings(value)[0]?.value;
|
|
3968
|
+
}
|
|
3969
|
+
/**
|
|
3970
|
+
* La domanda all'incontrario: quali operazioni ammettono questo momento. Serve dove il momento si
|
|
3971
|
+
* sceglie per primo — cioe' solo nel ripiego, su un documento il cui tipo di flow non si
|
|
3972
|
+
* riconosce — per rimettere a posto l'operazione invece di lasciare una coppia impossibile.
|
|
3973
|
+
*/
|
|
3974
|
+
recordTriggerTypesFor(trigger) {
|
|
3975
|
+
if (!trigger) {
|
|
3976
|
+
return [];
|
|
3977
|
+
}
|
|
3978
|
+
return this.recordTriggerTypes().filter((entry) => this.recordTriggerTimings(entry.value).some((timing) => timing.value === trigger));
|
|
3979
|
+
}
|
|
3980
|
+
/**
|
|
3981
|
+
* §3.4 — se la coppia operazione + momento e' una delle sei.
|
|
3982
|
+
*
|
|
3983
|
+
* `unknown` e' il caso normale su un dizionario che non dichiara i momenti, e non e' un difetto:
|
|
3984
|
+
* accusare una coppia senza avere la tabella con cui giudicarla e' peggio che tacere. Un editor
|
|
3985
|
+
* che rende la sequenza — l'operazione prima, il momento dopo — `mismatch` non lo produce mai: lo
|
|
3986
|
+
* incontra solo su un documento scritto altrove.
|
|
3987
|
+
*/
|
|
3988
|
+
recordTriggerPair(operation, trigger) {
|
|
3989
|
+
const timings = this.recordTriggerTimings(operation);
|
|
3990
|
+
if (!operation || !trigger || !timings.length) {
|
|
3991
|
+
return 'unknown';
|
|
3992
|
+
}
|
|
3993
|
+
return timings.some((timing) => timing.value === trigger) ? 'ok' : 'mismatch';
|
|
3994
|
+
}
|
|
3927
3995
|
startFrequencies = computed(() => this._dictionaries().startFrequencies ?? [], ...(ngDevMode ? [{ debugName: "startFrequencies" }] : []));
|
|
3928
3996
|
offsetUnits = computed(() => this._dictionaries().offsetUnits ?? [], ...(ngDevMode ? [{ debugName: "offsetUnits" }] : []));
|
|
3929
3997
|
sortOrders = computed(() => this._dictionaries().sortOrders ?? [], ...(ngDevMode ? [{ debugName: "sortOrders" }] : []));
|
|
@@ -14256,6 +14324,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
|
|
|
14256
14324
|
* Con un trigger su record il flow espone `$Record` e `$Record__Prior`; senza, quei
|
|
14257
14325
|
* riferimenti non sono disponibili e la validazione lo segnala. Il form lo dice, perche' e'
|
|
14258
14326
|
* la differenza fra un riferimento che funziona e uno che no.
|
|
14327
|
+
*
|
|
14328
|
+
* **Su un trigger da record il «quando parte» non e' una tendina, e' una sequenza** (§3.4). I campi
|
|
14329
|
+
* sono due — `recordTriggerType` e' l'**operazione**, `triggerType` il **momento** rispetto alla
|
|
14330
|
+
* scrittura — ma non sono due assi liberi: l'eliminazione ha un momento solo, e le coppie che
|
|
14331
|
+
* significano qualcosa sono sei. Due tendine indipendenti lascerebbero dichiarare «prima
|
|
14332
|
+
* dell'eliminazione» insieme a «alla creazione»: il runtime la legge come un'eliminazione — con
|
|
14333
|
+
* `RecordBeforeDelete` l'operazione la dice il trigger e `recordTriggerType` non viene guardato —
|
|
14334
|
+
* cioe' il flow parte su qualcosa che nessuno ha scelto. Quindi si chiede l'oggetto, poi
|
|
14335
|
+
* l'operazione, poi i criteri, poi il momento **fra quelli che l'operazione ammette**, e da quella
|
|
14336
|
+
* sequenza la coppia impossibile non e' esprimibile (`START_TRIGGER_MISMATCH` non si incontra mai,
|
|
14337
|
+
* se non aprendo un documento scritto altrove). I momenti li dichiara la voce dell'operazione nei
|
|
14338
|
+
* dizionari, non un elenco cablato: proporre i `triggerTypes` di primo livello significa proporre
|
|
14339
|
+
* coppie che la validazione rifiuta.
|
|
14259
14340
|
*/
|
|
14260
14341
|
/** I trigger che lavorano su un record e abilitano `$Record`. */
|
|
14261
14342
|
const RECORD_TRIGGERS = new Set(['RecordBeforeSave', 'RecordAfterSave', 'RecordBeforeDelete']);
|
|
@@ -14303,6 +14384,51 @@ class StartInspectorComponent {
|
|
|
14303
14384
|
: '';
|
|
14304
14385
|
}, ...(ngDevMode ? [{ debugName: "registrationLabel" }] : []));
|
|
14305
14386
|
recordTriggerTypes = computed(() => this.dictionaries.recordTriggerTypes(), ...(ngDevMode ? [{ debugName: "recordTriggerTypes" }] : []));
|
|
14387
|
+
/**
|
|
14388
|
+
* §3.4 — dove il tipo di flow **e'** innescato da un record, la tendina «quando parte» sparisce:
|
|
14389
|
+
* i suoi tre valori sono il *momento*, e il momento si sceglie per ultimo e fra quelli che
|
|
14390
|
+
* l'operazione ammette. Il ripiego — un documento il cui tipo non si riconosce, dove i trigger
|
|
14391
|
+
* proponibili sono tutti e sei — tiene la tendina e chiede l'operazione accanto: togliere la
|
|
14392
|
+
* scelta a chi ha in mano una coppia fuori dalle sei lo bloccherebbe sul valore che ha.
|
|
14393
|
+
*/
|
|
14394
|
+
isRecordFlowType = computed(() => {
|
|
14395
|
+
const proposable = this.triggerTypes();
|
|
14396
|
+
return proposable.length > 0 && proposable.every((entry) => RECORD_TRIGGERS.has(entry.value));
|
|
14397
|
+
}, ...(ngDevMode ? [{ debugName: "isRecordFlowType" }] : []));
|
|
14398
|
+
/** La voce dell'operazione dichiarata dal documento, coi suoi flag (§6.4). */
|
|
14399
|
+
recordOperation = computed(() => this.dictionaries.recordTriggerType(this.start().recordTriggerType), ...(ngDevMode ? [{ debugName: "recordOperation" }] : []));
|
|
14400
|
+
/**
|
|
14401
|
+
* I momenti proponibili: quelli **dell'operazione scelta**. Dove il dizionario non li dichiara —
|
|
14402
|
+
* o l'operazione non e' ancora scelta — si torna ai trigger su record del tipo di flow, che e' il
|
|
14403
|
+
* comportamento di prima: elenco vuoto significa «non lo so», non «nessun momento ammesso».
|
|
14404
|
+
*/
|
|
14405
|
+
timingOptions = computed(() => {
|
|
14406
|
+
const declared = this.dictionaries.recordTriggerTimings(this.start().recordTriggerType);
|
|
14407
|
+
return declared.length
|
|
14408
|
+
? declared
|
|
14409
|
+
: this.triggerTypes().filter((entry) => RECORD_TRIGGERS.has(entry.value));
|
|
14410
|
+
}, ...(ngDevMode ? [{ debugName: "timingOptions" }] : []));
|
|
14411
|
+
/**
|
|
14412
|
+
* Dove l'operazione ammette un momento solo — l'eliminazione — **la domanda non si pone affatto**
|
|
14413
|
+
* e il momento si scrive comunque: il contratto chiede entrambi i campi anche lì. Il controllo
|
|
14414
|
+
* `allowsTimingChoice !== false` e' la cintura: un dizionario che non lo dichiara decide sul
|
|
14415
|
+
* numero di opzioni, che e' la stessa risposta.
|
|
14416
|
+
*/
|
|
14417
|
+
showTimingChoice = computed(() => this.recordOperation()?.allowsTimingChoice !== false && this.timingOptions().length > 1, ...(ngDevMode ? [{ debugName: "showTimingChoice" }] : []));
|
|
14418
|
+
/** La voce del momento in mano, per mostrarne l'etichetta dove non c'e' niente da scegliere. */
|
|
14419
|
+
currentTiming = computed(() => this.timingOptions().find((entry) => entry.value === this.triggerType()), ...(ngDevMode ? [{ debugName: "currentTiming" }] : []));
|
|
14420
|
+
/**
|
|
14421
|
+
* §3.4 — `doesRequireRecordChangedToMeetCriteria` ha senso solo dove c'e' un «prima» da
|
|
14422
|
+
* confrontare: alla creazione e all'eliminazione il flag resta inerte, e con esso `IsChanged` non
|
|
14423
|
+
* decide nulla. Flag non dichiarato = lo si mostra: e' il ripiego di sempre.
|
|
14424
|
+
*/
|
|
14425
|
+
showRequireChanged = computed(() => this.recordOperation()?.usesPriorRecord !== false, ...(ngDevMode ? [{ debugName: "showRequireChanged" }] : []));
|
|
14426
|
+
/**
|
|
14427
|
+
* La coppia che il documento dichiara non e' una delle sei. Dalla sequenza non e' esprimibile,
|
|
14428
|
+
* quindi arriva da un documento scritto altrove: si **dice**, e la correzione e' un comando.
|
|
14429
|
+
*/
|
|
14430
|
+
hasTriggerMismatch = computed(() => this.dictionaries.recordTriggerPair(this.start().recordTriggerType, this.triggerType()) ===
|
|
14431
|
+
'mismatch', ...(ngDevMode ? [{ debugName: "hasTriggerMismatch" }] : []));
|
|
14306
14432
|
frequencies = computed(() => this.dictionaries.startFrequencies(), ...(ngDevMode ? [{ debugName: "frequencies" }] : []));
|
|
14307
14433
|
offsetUnits = computed(() => this.dictionaries.offsetUnits(), ...(ngDevMode ? [{ debugName: "offsetUnits" }] : []));
|
|
14308
14434
|
triggerType = computed(() => this.start().triggerType ?? 'None', ...(ngDevMode ? [{ debugName: "triggerType" }] : []));
|
|
@@ -14316,7 +14442,20 @@ class StartInspectorComponent {
|
|
|
14316
14442
|
setTriggerType(value) {
|
|
14317
14443
|
this.store.updateStart((start) => {
|
|
14318
14444
|
start.triggerType = value === 'None' ? undefined : value;
|
|
14319
|
-
if (
|
|
14445
|
+
if (RECORD_TRIGGERS.has(value)) {
|
|
14446
|
+
/*
|
|
14447
|
+
* §3.4 — operazione e momento non sono due assi liberi. Qui il momento si sceglie per primo
|
|
14448
|
+
* (e' il ripiego: dalla sequenza si passa da `setRecordOperation`), quindi se l'operazione
|
|
14449
|
+
* in mano non ammette questo momento va rimessa a posto — all'unica che lo ammette dove ce
|
|
14450
|
+
* n'e' una sola (l'eliminazione), altrimenti tolta. Lasciarla sarebbe la coppia che il
|
|
14451
|
+
* runtime legge al contrario di come e' scritta.
|
|
14452
|
+
*/
|
|
14453
|
+
const allowed = this.dictionaries.recordTriggerTypesFor(value);
|
|
14454
|
+
if (allowed.length && !allowed.some((entry) => entry.value === start.recordTriggerType)) {
|
|
14455
|
+
start.recordTriggerType = allowed.length === 1 ? allowed[0].value : undefined;
|
|
14456
|
+
}
|
|
14457
|
+
}
|
|
14458
|
+
else {
|
|
14320
14459
|
// Campi che appartengono ai **soli** trigger su record: tenerli sarebbe rumore che il
|
|
14321
14460
|
// motore ignora e che sporca il diff.
|
|
14322
14461
|
delete start.recordTriggerType;
|
|
@@ -14363,11 +14502,42 @@ class StartInspectorComponent {
|
|
|
14363
14502
|
delete start.filters;
|
|
14364
14503
|
});
|
|
14365
14504
|
}
|
|
14366
|
-
|
|
14505
|
+
/**
|
|
14506
|
+
* §3.4 — l'operazione, che e' la domanda **prima** del momento, e scrive tutti e due i campi in
|
|
14507
|
+
* **una** mutazione: con due, l'annulla riporterebbe indietro il momento lasciando l'operazione
|
|
14508
|
+
* nuova, cioe' una coppia che non e' nessuna delle sei. Il momento si tocca solo se quello in
|
|
14509
|
+
* mano non e' ammesso — cambiare operazione non deve buttare via una scelta ancora valida.
|
|
14510
|
+
*/
|
|
14511
|
+
setRecordOperation(value) {
|
|
14367
14512
|
this.store.updateStart((start) => {
|
|
14368
|
-
|
|
14513
|
+
if (!value) {
|
|
14514
|
+
delete start.recordTriggerType;
|
|
14515
|
+
return;
|
|
14516
|
+
}
|
|
14517
|
+
start.recordTriggerType = value;
|
|
14518
|
+
const timings = this.dictionaries.recordTriggerTimings(value).map((entry) => entry.value);
|
|
14519
|
+
const fallback = this.dictionaries.defaultTimingOf(value);
|
|
14520
|
+
if (timings.length && !timings.includes(start.triggerType ?? '') && fallback) {
|
|
14521
|
+
start.triggerType = fallback;
|
|
14522
|
+
}
|
|
14523
|
+
// Il flag del «prima» e' inerte dove l'operazione non ha un prima: tenerlo sarebbe una
|
|
14524
|
+
// condizione scritta che il motore non guarda.
|
|
14525
|
+
if (this.dictionaries.recordTriggerType(value)?.usesPriorRecord === false) {
|
|
14526
|
+
delete start.doesRequireRecordChangedToMeetCriteria;
|
|
14527
|
+
}
|
|
14369
14528
|
});
|
|
14370
14529
|
}
|
|
14530
|
+
/**
|
|
14531
|
+
* Rimette il momento fra quelli che l'operazione ammette. E' un **comando** e non una correzione
|
|
14532
|
+
* automatica: su un documento scritto altrove non si sa quale meta' della coppia sia quella
|
|
14533
|
+
* voluta, e cambiarne una di soppiatto e' una modifica che nessuno ha chiesto.
|
|
14534
|
+
*/
|
|
14535
|
+
useDefaultTiming() {
|
|
14536
|
+
const timing = this.dictionaries.defaultTimingOf(this.start().recordTriggerType);
|
|
14537
|
+
if (timing) {
|
|
14538
|
+
this.setTriggerType(timing);
|
|
14539
|
+
}
|
|
14540
|
+
}
|
|
14371
14541
|
setRequireChanged(value) {
|
|
14372
14542
|
this.store.updateStart((start) => {
|
|
14373
14543
|
if (value) {
|
|
@@ -14445,7 +14615,7 @@ class StartInspectorComponent {
|
|
|
14445
14615
|
this.store.setConnector('$start', event.outletKey, event.target, event.isGoTo);
|
|
14446
14616
|
}
|
|
14447
14617
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: StartInspectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14448
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: StartInspectorComponent, isStandalone: true, selector: "fb-start-inspector", ngImport: i0, template: "@if (!hasEntryPoint()) {\r\n <p class=\"fb-callout fb-callout--error\">\r\n Lo Start non punta a nessun elemento: il flow non ha un punto di ingresso e non e\u2019 eseguibile\r\n (START_NO_ENTRY_POINT).\r\n </p>\r\n}\r\n\r\n<div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Quando parte</label>\r\n <!--\r\n \u00A73.4 \u2014 i trigger sono quelli del **tipo di flow** scelto alla creazione, non tutti: la coppia\r\n `processType` + `triggerType` **e'** il tipo, e cambiarla qui vorrebbe dire cambiarlo.\r\n -->\r\n <select class=\"fb-select\" [fbValue]=\"triggerType()\" (change)=\"setTriggerType($any($event.target).value)\">\r\n @for (trigger of triggerTypes(); track trigger.value) {\r\n <option [value]=\"trigger.value\">{{ trigger.label }}</option>\r\n }\r\n </select>\r\n @if (flowType(); as type) {\r\n <p class=\"fb-field__hint\">\r\n Tipo di flow: <strong>{{ type.label }}</strong\r\n >{{ type.description ? ' \u2014 ' + type.description : '' }}\r\n </p>\r\n }\r\n @if (requiresRegistration()) {\r\n <!--\r\n \u00A78 \u2014 l'unico caso in cui una definizione **valida** puo' non essere attivabile: il flow non\r\n parte da solo, e l'infrastruttura dell'ospite deve prenderlo in carico. Dirlo qui, dove si\r\n sceglie il trigger, e' dirlo prima che l'attivazione fallisca.\r\n -->\r\n <p class=\"fb-callout\">\r\n Questo flow non parte da solo: attivandolo,\r\n {{ registrationLabel() ? 'il servizio \u00AB' + registrationLabel() + '\u00BB' : 'l\u2019infrastruttura dell\u2019ambiente' }}\r\n deve <strong>prenderlo in carico</strong>. Se non c\u2019e\u2019 chi lo faccia, l\u2019attivazione non riesce\r\n anche con la definizione a posto.\r\n </p>\r\n }\r\n</div>\r\n\r\n@if (isRecordTrigger()) {\r\n <p class=\"fb-callout\">\r\n Con un trigger su record il flow espone <code>$Record</code> e <code>$Record__Prior</code>.\r\n </p>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Oggetto che innesca</label>\r\n <fb-object-picker\r\n [value]=\"start().object\"\r\n label=\"Oggetto che innesca\"\r\n placeholder=\"Scrivi o scegli un oggetto\"\r\n (valueChange)=\"setObject($event ?? '')\"\r\n />\r\n @if (!start().object) {\r\n <p class=\"fb-field__error\">Obbligatorio con i trigger su record (START_OBJECT_MISSING).</p>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Su quale operazione</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"start().recordTriggerType || ''\"\r\n (change)=\"setRecordTriggerType($any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014 scegli \u2014</option>\r\n @for (type of recordTriggerTypes(); track type.value) {\r\n <option [value]=\"type.value\">{{ type.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n <fb-record-filter-editor\r\n [holder]=\"$any(start())\"\r\n [object]=\"start().object\"\r\n title=\"Criteri di ingresso\"\r\n usage=\"filterable\"\r\n [supportsLogic]=\"true\"\r\n [supportsFormula]=\"true\"\r\n emptyWarning=\"Senza criteri il flow parte su ogni record.\"\r\n (changed)=\"onFiltersChanged($event)\"\r\n />\r\n\r\n <label class=\"fb-check\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"start().doesRequireRecordChangedToMeetCriteria === true\"\r\n (change)=\"setRequireChanged($any($event.target).checked)\"\r\n />\r\n Solo se il record <em>non</em> soddisfaceva i criteri prima del salvataggio\r\n </label>\r\n}\r\n\r\n@if (isScheduled()) {\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Pianificazione</legend>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Frequenza</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"start().schedule?.frequency || ''\"\r\n (change)=\"setFrequency($any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014 scegli \u2014</option>\r\n @for (frequency of frequencies(); track frequency.value) {\r\n <option [value]=\"frequency.value\">{{ frequency.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n <div class=\"fb-field__row\">\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Data di inizio</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"date\"\r\n [value]=\"startDateValue()\"\r\n (input)=\"setStartDate($any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Ora</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"time\"\r\n [value]=\"startTimeValue()\"\r\n (input)=\"setStartTime($any($event.target).value)\"\r\n />\r\n </div>\r\n </div>\r\n @if (!start().schedule?.frequency) {\r\n <p class=\"fb-field__error\">La pianificazione e\u2019 obbligatoria con questo trigger (START_SCHEDULE_MISSING).</p>\r\n }\r\n </fieldset>\r\n\r\n <!--\r\n \u00A73.4 \u2014 su uno schedulato l'oggetto e' **facoltativo** e vuol dire un'altra cosa che sui trigger\r\n su record: non \u00ABl'entita' che innesca\u00BB ma \u00ABun'esecuzione per ogni record che soddisfa i filtri\u00BB.\r\n Senza, il flow gira una volta sola.\r\n -->\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Un\u2019esecuzione per record</legend>\r\n <p class=\"fb-section__note\">\r\n Facoltativo. Indicando un\u2019entita\u2019, il flow gira <strong>una volta per ogni record</strong> che\r\n soddisfa i filtri invece di una volta sola.\r\n </p>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Entita\u2019</label>\r\n <fb-object-picker\r\n [value]=\"start().object\"\r\n label=\"Entita\u2019\"\r\n placeholder=\"Nessuna: una sola esecuzione\"\r\n (valueChange)=\"setObject($event ?? '')\"\r\n />\r\n </div>\r\n @if (start().object) {\r\n <fb-record-filter-editor\r\n [holder]=\"$any(start())\"\r\n [object]=\"start().object\"\r\n title=\"Quali record\"\r\n usage=\"filterable\"\r\n [supportsLogic]=\"true\"\r\n [supportsFormula]=\"true\"\r\n emptyWarning=\"Senza criteri il flow gira su ogni record dell\u2019entita\u2019.\"\r\n (changed)=\"onFiltersChanged($event)\"\r\n />\r\n }\r\n </fieldset>\r\n\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Percorsi differiti</legend>\r\n <p class=\"fb-section__note\">\r\n Ogni percorso e\u2019 un ramo che parte dopo un intervallo, calcolato da un istante di riferimento.\r\n </p>\r\n\r\n <div class=\"fb-list\">\r\n @for (path of scheduledPaths(); track $index) {\r\n <div class=\"fb-list__item\">\r\n <div class=\"fb-list__header\">\r\n <span class=\"fb-list__index\">{{ $index + 1 }}</span>\r\n <span class=\"fb-list__spacer\"></span>\r\n <button\r\n type=\"button\"\r\n class=\"fb-btn fb-btn--ghost fb-btn--icon\"\r\n aria-label=\"Rimuovi il percorso\"\r\n (click)=\"removeScheduledPath($index)\"\r\n >\r\n \u00D7\r\n </button>\r\n </div>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Etichetta</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.label || ''\"\r\n (input)=\"setPathField($index, 'label', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Nome tecnico</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"path.name || ''\"\r\n (input)=\"setPathField($index, 'name', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field__row\">\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Dopo</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"number\"\r\n [value]=\"path.offsetNumber ?? ''\"\r\n (input)=\"setPathOffsetNumber($index, $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Unita\u2019</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"path.offsetUnit || ''\"\r\n (change)=\"setPathField($index, 'offsetUnit', $any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014</option>\r\n @for (unit of offsetUnits(); track unit.value) {\r\n <option [value]=\"unit.value\">{{ unit.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Istante di riferimento</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.timeSource || ''\"\r\n placeholder=\"Es. RecordTriggerEvent\"\r\n (input)=\"setPathField($index, 'timeSource', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Campo data del record</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.recordField || ''\"\r\n (input)=\"setPathField($index, 'recordField', $any($event.target).value)\"\r\n />\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"fb-empty\">Nessun percorso differito.</p>\r\n }\r\n </div>\r\n <button type=\"button\" class=\"fb-btn\" (click)=\"addScheduledPath()\">Aggiungi percorso</button>\r\n </fieldset>\r\n}\r\n\r\n@if (triggerType() === 'None') {\r\n <p class=\"fb-field__hint\">\r\n Il flow parte solo su richiesta. I valori iniziali si passano nelle variabili di input.\r\n </p>\r\n}\r\n\r\n@if (isEvent()) {\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Evento</legend>\r\n <p class=\"fb-section__note\">\r\n Il flow parte alla ricezione di un evento: e\u2019 a questo che l\u2019host si sottoscrive quando la\r\n versione viene attivata (\u00A78).\r\n </p>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Tipo di evento</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"start().eventType || ''\"\r\n placeholder=\"Es. OrdineEvaso\"\r\n (input)=\"setEventField('eventType', $any($event.target).value)\"\r\n />\r\n @if (!start().eventType) {\r\n <p class=\"fb-field__error\">Obbligatorio con questo trigger (START_EVENT_MISSING).</p>\r\n }\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Nome dell\u2019evento</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"start().eventName || ''\"\r\n (input)=\"setEventField('eventName', $any($event.target).value)\"\r\n />\r\n <p class=\"fb-field__hint\">Facoltativo: serve dove il tipo da solo non identifica l\u2019evento.</p>\r\n </div>\r\n </fieldset>\r\n}\r\n\r\n<fb-connector-editor\r\n [nodeName]=\"'$start'\"\r\n [node]=\"startNode()\"\r\n [outlets]=\"outlets()\"\r\n title=\"Da dove comincia\"\r\n (connectorChanged)=\"onConnectorChanged($event)\"\r\n/>\r\n", dependencies: [{ kind: "component", type: ConnectorEditorComponent, selector: "fb-connector-editor", inputs: ["nodeName", "node", "outlets", "title"], outputs: ["connectorChanged"] }, { kind: "component", type: ObjectPickerComponent, selector: "fb-object-picker", inputs: ["value", "label", "placeholder", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: RecordFilterEditorComponent, selector: "fb-record-filter-editor", inputs: ["holder", "object", "title", "usage", "fieldOptions", "supportsLogic", "supportsFormula", "emptyWarning", "emptyWarningSeverity"], outputs: ["changed"] }, { kind: "directive", type: SelectValueDirective, selector: "select[fbValue]", inputs: ["fbValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14618
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: StartInspectorComponent, isStandalone: true, selector: "fb-start-inspector", ngImport: i0, template: "@if (!hasEntryPoint()) {\r\n <p class=\"fb-callout fb-callout--error\">\r\n Lo Start non punta a nessun elemento: il flow non ha un punto di ingresso e non e\u2019 eseguibile\r\n (START_NO_ENTRY_POINT).\r\n </p>\r\n}\r\n\r\n<!--\r\n \u00A73.4 \u2014 su un flow innescato da un record la tendina non c'e': i suoi tre valori sono il *momento*,\r\n e il momento e' l'ultima domanda della sequenza qui sotto, posta fra i soli momenti che\r\n l'operazione scelta ammette. Altrove i trigger sono quelli del **tipo di flow** scelto alla\r\n creazione, non tutti: la coppia `processType` + `triggerType` **e'** il tipo, e cambiarla qui\r\n vorrebbe dire cambiarlo.\r\n-->\r\n@if (!isRecordFlowType()) {\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Quando parte</label>\r\n <select class=\"fb-select\" [fbValue]=\"triggerType()\" (change)=\"setTriggerType($any($event.target).value)\">\r\n @for (trigger of triggerTypes(); track trigger.value) {\r\n <option [value]=\"trigger.value\">{{ trigger.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n}\r\n\r\n@if (flowType(); as type) {\r\n <p class=\"fb-field__hint\">\r\n Tipo di flow: <strong>{{ type.label }}</strong\r\n >{{ type.description ? ' \u2014 ' + type.description : '' }}\r\n </p>\r\n}\r\n@if (requiresRegistration()) {\r\n <!--\r\n \u00A78 \u2014 l'unico caso in cui una definizione **valida** puo' non essere attivabile: il flow non\r\n parte da solo, e l'infrastruttura dell'ospite deve prenderlo in carico. Dirlo qui, dove si\r\n sceglie il trigger, e' dirlo prima che l'attivazione fallisca.\r\n -->\r\n <p class=\"fb-callout\">\r\n Questo flow non parte da solo: attivandolo,\r\n {{ registrationLabel() ? 'il servizio \u00AB' + registrationLabel() + '\u00BB' : 'l\u2019infrastruttura dell\u2019ambiente' }}\r\n deve <strong>prenderlo in carico</strong>. Se non c\u2019e\u2019 chi lo faccia, l\u2019attivazione non riesce\r\n anche con la definizione a posto.\r\n </p>\r\n}\r\n\r\n@if (isRecordTrigger()) {\r\n <p class=\"fb-callout\">\r\n Con un trigger su record il flow espone <code>$Record</code> e <code>$Record__Prior</code>.\r\n </p>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Oggetto che innesca</label>\r\n <fb-object-picker\r\n [value]=\"start().object\"\r\n label=\"Oggetto che innesca\"\r\n placeholder=\"Scrivi o scegli un oggetto\"\r\n (valueChange)=\"setObject($event ?? '')\"\r\n />\r\n @if (!start().object) {\r\n <p class=\"fb-field__error\">Obbligatorio con i trigger su record (START_OBJECT_MISSING).</p>\r\n }\r\n </div>\r\n\r\n <!--\r\n \u00A73.4 \u2014 **l'operazione prima, il momento dopo**: sono due campi ma non due assi liberi, e da due\r\n tendine indipendenti si dichiara \u00ABprima dell'eliminazione\u00BB insieme a \u00ABalla creazione\u00BB, che il\r\n runtime legge come un'eliminazione. Qui quella coppia non e' esprimibile.\r\n -->\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Su quale operazione</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"start().recordTriggerType || ''\"\r\n (change)=\"setRecordOperation($any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014 scegli \u2014</option>\r\n @for (type of recordTriggerTypes(); track type.value) {\r\n <option [value]=\"type.value\" [title]=\"type.description || type.label\">{{ type.label }}</option>\r\n }\r\n </select>\r\n @if (recordOperation()?.description; as description) {\r\n <p class=\"fb-field__hint\">{{ description }}</p>\r\n }\r\n @if (!start().recordTriggerType) {\r\n <!-- Avviso e non errore: il motore lo legge come \u00ABogni salvataggio\u00BB (\u00A73.4). -->\r\n <p class=\"fb-field__hint fb-field__hint--warn\">\r\n Senza operazione il flow parte su <strong>ogni</strong> salvataggio, creazioni e\r\n aggiornamenti (START_RECORD_TRIGGER_MISSING).\r\n </p>\r\n }\r\n </div>\r\n\r\n <fb-record-filter-editor\r\n [holder]=\"$any(start())\"\r\n [object]=\"start().object\"\r\n title=\"Criteri di ingresso\"\r\n usage=\"filterable\"\r\n [supportsLogic]=\"true\"\r\n [supportsFormula]=\"true\"\r\n emptyWarning=\"Senza criteri il flow parte su ogni record.\"\r\n (changed)=\"onFiltersChanged($event)\"\r\n />\r\n\r\n @if (showRequireChanged()) {\r\n <!--\r\n \u00A73.4 \u2014 il \u00ABprima\u00BB da confrontare c'e' solo dove l'operazione lo porta (`usesPriorRecord`):\r\n alla creazione e all'eliminazione questo flag \u2014 e con lui l'operatore `IsChanged` \u2014 non decide\r\n nulla, quindi la domanda non si pone.\r\n -->\r\n <label class=\"fb-check\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"start().doesRequireRecordChangedToMeetCriteria === true\"\r\n (change)=\"setRequireChanged($any($event.target).checked)\"\r\n />\r\n Solo se il record <em>non</em> soddisfaceva i criteri prima del salvataggio\r\n </label>\r\n } @else if (start().doesRequireRecordChangedToMeetCriteria === true) {\r\n <!--\r\n Il flag c'e' ma l'operazione non ha un \u00ABprima\u00BB: arriva da un documento scritto altrove, o da\r\n un'operazione cambiata prima di questa versione dell'editor. Nasconderlo e basta lo\r\n toglierebbe dalla vista lasciandolo scritto \u2014 si dice, e la ripulitura e' un comando.\r\n -->\r\n <p class=\"fb-callout fb-callout--warn\">\r\n Il documento chiede che il record <strong>non</strong> soddisfacesse i criteri prima del\r\n salvataggio, ma con questa operazione non c\u2019e\u2019 un \u00ABprima\u00BB da confrontare: il motore lo ignora.\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost\" (click)=\"setRequireChanged(false)\">\r\n Togli la condizione\r\n </button>\r\n </p>\r\n }\r\n\r\n <!--\r\n Il momento e' l'**ultima** domanda, e sta qui solo dove la tendina in cima non c'e': nel ripiego\r\n il `triggerType` lo governa quella, e due controlli sullo stesso campo si contraddicono a vista.\r\n -->\r\n @if (isRecordFlowType()) {\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">In che momento</label>\r\n @if (showTimingChoice()) {\r\n <select class=\"fb-select\" [fbValue]=\"triggerType()\" (change)=\"setTriggerType($any($event.target).value)\">\r\n @for (timing of timingOptions(); track timing.value) {\r\n <option [value]=\"timing.value\" [title]=\"timing.description || timing.label\">{{ timing.label }}</option>\r\n }\r\n </select>\r\n @if (currentTiming()?.description; as description) {\r\n <p class=\"fb-field__hint\">{{ description }}</p>\r\n }\r\n } @else {\r\n <!--\r\n Momento unico (`allowsTimingChoice: false`, l'eliminazione): la domanda non si pone, ma il\r\n campo si scrive lo stesso \u2014 il contratto chiede **entrambi**.\r\n -->\r\n <p class=\"fb-field__hint\">\r\n <strong>{{ currentTiming()?.label || triggerType() }}</strong> \u2014 con questa operazione e\u2019\r\n l\u2019unico momento possibile, e viene scritto comunque nel documento.\r\n </p>\r\n }\r\n </div>\r\n }\r\n\r\n @if (hasTriggerMismatch()) {\r\n <p class=\"fb-callout fb-callout--error\">\r\n L\u2019operazione e il momento scritti nel documento non stanno insieme (START_TRIGGER_MISMATCH):\r\n il flow parte su un\u2019operazione diversa da quella scelta, e l\u2019attivazione non riesce.\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost\" (click)=\"useDefaultTiming()\">\r\n Riporta il momento fra quelli ammessi\r\n </button>\r\n </p>\r\n }\r\n}\r\n\r\n@if (isScheduled()) {\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Pianificazione</legend>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Frequenza</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"start().schedule?.frequency || ''\"\r\n (change)=\"setFrequency($any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014 scegli \u2014</option>\r\n @for (frequency of frequencies(); track frequency.value) {\r\n <option [value]=\"frequency.value\">{{ frequency.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n <div class=\"fb-field__row\">\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Data di inizio</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"date\"\r\n [value]=\"startDateValue()\"\r\n (input)=\"setStartDate($any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Ora</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"time\"\r\n [value]=\"startTimeValue()\"\r\n (input)=\"setStartTime($any($event.target).value)\"\r\n />\r\n </div>\r\n </div>\r\n @if (!start().schedule?.frequency) {\r\n <p class=\"fb-field__error\">La pianificazione e\u2019 obbligatoria con questo trigger (START_SCHEDULE_MISSING).</p>\r\n }\r\n </fieldset>\r\n\r\n <!--\r\n \u00A73.4 \u2014 su uno schedulato l'oggetto e' **facoltativo** e vuol dire un'altra cosa che sui trigger\r\n su record: non \u00ABl'entita' che innesca\u00BB ma \u00ABun'esecuzione per ogni record che soddisfa i filtri\u00BB.\r\n Senza, il flow gira una volta sola.\r\n -->\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Un\u2019esecuzione per record</legend>\r\n <p class=\"fb-section__note\">\r\n Facoltativo. Indicando un\u2019entita\u2019, il flow gira <strong>una volta per ogni record</strong> che\r\n soddisfa i filtri invece di una volta sola.\r\n </p>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Entita\u2019</label>\r\n <fb-object-picker\r\n [value]=\"start().object\"\r\n label=\"Entita\u2019\"\r\n placeholder=\"Nessuna: una sola esecuzione\"\r\n (valueChange)=\"setObject($event ?? '')\"\r\n />\r\n </div>\r\n @if (start().object) {\r\n <fb-record-filter-editor\r\n [holder]=\"$any(start())\"\r\n [object]=\"start().object\"\r\n title=\"Quali record\"\r\n usage=\"filterable\"\r\n [supportsLogic]=\"true\"\r\n [supportsFormula]=\"true\"\r\n emptyWarning=\"Senza criteri il flow gira su ogni record dell\u2019entita\u2019.\"\r\n (changed)=\"onFiltersChanged($event)\"\r\n />\r\n }\r\n </fieldset>\r\n\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Percorsi differiti</legend>\r\n <p class=\"fb-section__note\">\r\n Ogni percorso e\u2019 un ramo che parte dopo un intervallo, calcolato da un istante di riferimento.\r\n </p>\r\n\r\n <div class=\"fb-list\">\r\n @for (path of scheduledPaths(); track $index) {\r\n <div class=\"fb-list__item\">\r\n <div class=\"fb-list__header\">\r\n <span class=\"fb-list__index\">{{ $index + 1 }}</span>\r\n <span class=\"fb-list__spacer\"></span>\r\n <button\r\n type=\"button\"\r\n class=\"fb-btn fb-btn--ghost fb-btn--icon\"\r\n aria-label=\"Rimuovi il percorso\"\r\n (click)=\"removeScheduledPath($index)\"\r\n >\r\n \u00D7\r\n </button>\r\n </div>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Etichetta</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.label || ''\"\r\n (input)=\"setPathField($index, 'label', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Nome tecnico</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"path.name || ''\"\r\n (input)=\"setPathField($index, 'name', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field__row\">\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Dopo</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"number\"\r\n [value]=\"path.offsetNumber ?? ''\"\r\n (input)=\"setPathOffsetNumber($index, $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Unita\u2019</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"path.offsetUnit || ''\"\r\n (change)=\"setPathField($index, 'offsetUnit', $any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014</option>\r\n @for (unit of offsetUnits(); track unit.value) {\r\n <option [value]=\"unit.value\">{{ unit.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Istante di riferimento</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.timeSource || ''\"\r\n placeholder=\"Es. RecordTriggerEvent\"\r\n (input)=\"setPathField($index, 'timeSource', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Campo data del record</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.recordField || ''\"\r\n (input)=\"setPathField($index, 'recordField', $any($event.target).value)\"\r\n />\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"fb-empty\">Nessun percorso differito.</p>\r\n }\r\n </div>\r\n <button type=\"button\" class=\"fb-btn\" (click)=\"addScheduledPath()\">Aggiungi percorso</button>\r\n </fieldset>\r\n}\r\n\r\n@if (triggerType() === 'None') {\r\n <p class=\"fb-field__hint\">\r\n Il flow parte solo su richiesta. I valori iniziali si passano nelle variabili di input.\r\n </p>\r\n}\r\n\r\n@if (isEvent()) {\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Evento</legend>\r\n <p class=\"fb-section__note\">\r\n Il flow parte alla ricezione di un evento: e\u2019 a questo che l\u2019host si sottoscrive quando la\r\n versione viene attivata (\u00A78).\r\n </p>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Tipo di evento</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"start().eventType || ''\"\r\n placeholder=\"Es. OrdineEvaso\"\r\n (input)=\"setEventField('eventType', $any($event.target).value)\"\r\n />\r\n @if (!start().eventType) {\r\n <p class=\"fb-field__error\">Obbligatorio con questo trigger (START_EVENT_MISSING).</p>\r\n }\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Nome dell\u2019evento</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"start().eventName || ''\"\r\n (input)=\"setEventField('eventName', $any($event.target).value)\"\r\n />\r\n <p class=\"fb-field__hint\">Facoltativo: serve dove il tipo da solo non identifica l\u2019evento.</p>\r\n </div>\r\n </fieldset>\r\n}\r\n\r\n<fb-connector-editor\r\n [nodeName]=\"'$start'\"\r\n [node]=\"startNode()\"\r\n [outlets]=\"outlets()\"\r\n title=\"Da dove comincia\"\r\n (connectorChanged)=\"onConnectorChanged($event)\"\r\n/>\r\n", dependencies: [{ kind: "component", type: ConnectorEditorComponent, selector: "fb-connector-editor", inputs: ["nodeName", "node", "outlets", "title"], outputs: ["connectorChanged"] }, { kind: "component", type: ObjectPickerComponent, selector: "fb-object-picker", inputs: ["value", "label", "placeholder", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: RecordFilterEditorComponent, selector: "fb-record-filter-editor", inputs: ["holder", "object", "title", "usage", "fieldOptions", "supportsLogic", "supportsFormula", "emptyWarning", "emptyWarningSeverity"], outputs: ["changed"] }, { kind: "directive", type: SelectValueDirective, selector: "select[fbValue]", inputs: ["fbValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14449
14619
|
}
|
|
14450
14620
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: StartInspectorComponent, decorators: [{
|
|
14451
14621
|
type: Component,
|
|
@@ -14454,7 +14624,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
|
|
|
14454
14624
|
ObjectPickerComponent,
|
|
14455
14625
|
RecordFilterEditorComponent,
|
|
14456
14626
|
SelectValueDirective,
|
|
14457
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!hasEntryPoint()) {\r\n <p class=\"fb-callout fb-callout--error\">\r\n Lo Start non punta a nessun elemento: il flow non ha un punto di ingresso e non e\u2019 eseguibile\r\n (START_NO_ENTRY_POINT).\r\n </p>\r\n}\r\n\r\n<div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Quando parte</label>\r\n <!--\r\n \u00A73.4 \u2014 i trigger sono quelli del **tipo di flow** scelto alla creazione, non tutti: la coppia\r\n `processType` + `triggerType` **e'** il tipo, e cambiarla qui vorrebbe dire cambiarlo.\r\n -->\r\n <select class=\"fb-select\" [fbValue]=\"triggerType()\" (change)=\"setTriggerType($any($event.target).value)\">\r\n @for (trigger of triggerTypes(); track trigger.value) {\r\n <option [value]=\"trigger.value\">{{ trigger.label }}</option>\r\n }\r\n </select>\r\n @if (flowType(); as type) {\r\n <p class=\"fb-field__hint\">\r\n Tipo di flow: <strong>{{ type.label }}</strong\r\n >{{ type.description ? ' \u2014 ' + type.description : '' }}\r\n </p>\r\n }\r\n @if (requiresRegistration()) {\r\n <!--\r\n \u00A78 \u2014 l'unico caso in cui una definizione **valida** puo' non essere attivabile: il flow non\r\n parte da solo, e l'infrastruttura dell'ospite deve prenderlo in carico. Dirlo qui, dove si\r\n sceglie il trigger, e' dirlo prima che l'attivazione fallisca.\r\n -->\r\n <p class=\"fb-callout\">\r\n Questo flow non parte da solo: attivandolo,\r\n {{ registrationLabel() ? 'il servizio \u00AB' + registrationLabel() + '\u00BB' : 'l\u2019infrastruttura dell\u2019ambiente' }}\r\n deve <strong>prenderlo in carico</strong>. Se non c\u2019e\u2019 chi lo faccia, l\u2019attivazione non riesce\r\n anche con la definizione a posto.\r\n </p>\r\n }\r\n</div>\r\n\r\n@if (isRecordTrigger()) {\r\n <p class=\"fb-callout\">\r\n Con un trigger su record il flow espone <code>$Record</code> e <code>$Record__Prior</code>.\r\n </p>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Oggetto che innesca</label>\r\n <fb-object-picker\r\n [value]=\"start().object\"\r\n label=\"Oggetto che innesca\"\r\n placeholder=\"Scrivi o scegli un oggetto\"\r\n (valueChange)=\"setObject($event ?? '')\"\r\n />\r\n @if (!start().object) {\r\n <p class=\"fb-field__error\">Obbligatorio con i trigger su record (START_OBJECT_MISSING).</p>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Su quale operazione</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"start().recordTriggerType || ''\"\r\n (change)=\"setRecordTriggerType($any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014 scegli \u2014</option>\r\n @for (type of recordTriggerTypes(); track type.value) {\r\n <option [value]=\"type.value\">{{ type.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n <fb-record-filter-editor\r\n [holder]=\"$any(start())\"\r\n [object]=\"start().object\"\r\n title=\"Criteri di ingresso\"\r\n usage=\"filterable\"\r\n [supportsLogic]=\"true\"\r\n [supportsFormula]=\"true\"\r\n emptyWarning=\"Senza criteri il flow parte su ogni record.\"\r\n (changed)=\"onFiltersChanged($event)\"\r\n />\r\n\r\n <label class=\"fb-check\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"start().doesRequireRecordChangedToMeetCriteria === true\"\r\n (change)=\"setRequireChanged($any($event.target).checked)\"\r\n />\r\n Solo se il record <em>non</em> soddisfaceva i criteri prima del salvataggio\r\n </label>\r\n}\r\n\r\n@if (isScheduled()) {\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Pianificazione</legend>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Frequenza</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"start().schedule?.frequency || ''\"\r\n (change)=\"setFrequency($any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014 scegli \u2014</option>\r\n @for (frequency of frequencies(); track frequency.value) {\r\n <option [value]=\"frequency.value\">{{ frequency.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n <div class=\"fb-field__row\">\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Data di inizio</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"date\"\r\n [value]=\"startDateValue()\"\r\n (input)=\"setStartDate($any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Ora</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"time\"\r\n [value]=\"startTimeValue()\"\r\n (input)=\"setStartTime($any($event.target).value)\"\r\n />\r\n </div>\r\n </div>\r\n @if (!start().schedule?.frequency) {\r\n <p class=\"fb-field__error\">La pianificazione e\u2019 obbligatoria con questo trigger (START_SCHEDULE_MISSING).</p>\r\n }\r\n </fieldset>\r\n\r\n <!--\r\n \u00A73.4 \u2014 su uno schedulato l'oggetto e' **facoltativo** e vuol dire un'altra cosa che sui trigger\r\n su record: non \u00ABl'entita' che innesca\u00BB ma \u00ABun'esecuzione per ogni record che soddisfa i filtri\u00BB.\r\n Senza, il flow gira una volta sola.\r\n -->\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Un\u2019esecuzione per record</legend>\r\n <p class=\"fb-section__note\">\r\n Facoltativo. Indicando un\u2019entita\u2019, il flow gira <strong>una volta per ogni record</strong> che\r\n soddisfa i filtri invece di una volta sola.\r\n </p>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Entita\u2019</label>\r\n <fb-object-picker\r\n [value]=\"start().object\"\r\n label=\"Entita\u2019\"\r\n placeholder=\"Nessuna: una sola esecuzione\"\r\n (valueChange)=\"setObject($event ?? '')\"\r\n />\r\n </div>\r\n @if (start().object) {\r\n <fb-record-filter-editor\r\n [holder]=\"$any(start())\"\r\n [object]=\"start().object\"\r\n title=\"Quali record\"\r\n usage=\"filterable\"\r\n [supportsLogic]=\"true\"\r\n [supportsFormula]=\"true\"\r\n emptyWarning=\"Senza criteri il flow gira su ogni record dell\u2019entita\u2019.\"\r\n (changed)=\"onFiltersChanged($event)\"\r\n />\r\n }\r\n </fieldset>\r\n\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Percorsi differiti</legend>\r\n <p class=\"fb-section__note\">\r\n Ogni percorso e\u2019 un ramo che parte dopo un intervallo, calcolato da un istante di riferimento.\r\n </p>\r\n\r\n <div class=\"fb-list\">\r\n @for (path of scheduledPaths(); track $index) {\r\n <div class=\"fb-list__item\">\r\n <div class=\"fb-list__header\">\r\n <span class=\"fb-list__index\">{{ $index + 1 }}</span>\r\n <span class=\"fb-list__spacer\"></span>\r\n <button\r\n type=\"button\"\r\n class=\"fb-btn fb-btn--ghost fb-btn--icon\"\r\n aria-label=\"Rimuovi il percorso\"\r\n (click)=\"removeScheduledPath($index)\"\r\n >\r\n \u00D7\r\n </button>\r\n </div>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Etichetta</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.label || ''\"\r\n (input)=\"setPathField($index, 'label', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Nome tecnico</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"path.name || ''\"\r\n (input)=\"setPathField($index, 'name', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field__row\">\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Dopo</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"number\"\r\n [value]=\"path.offsetNumber ?? ''\"\r\n (input)=\"setPathOffsetNumber($index, $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Unita\u2019</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"path.offsetUnit || ''\"\r\n (change)=\"setPathField($index, 'offsetUnit', $any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014</option>\r\n @for (unit of offsetUnits(); track unit.value) {\r\n <option [value]=\"unit.value\">{{ unit.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Istante di riferimento</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.timeSource || ''\"\r\n placeholder=\"Es. RecordTriggerEvent\"\r\n (input)=\"setPathField($index, 'timeSource', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Campo data del record</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.recordField || ''\"\r\n (input)=\"setPathField($index, 'recordField', $any($event.target).value)\"\r\n />\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"fb-empty\">Nessun percorso differito.</p>\r\n }\r\n </div>\r\n <button type=\"button\" class=\"fb-btn\" (click)=\"addScheduledPath()\">Aggiungi percorso</button>\r\n </fieldset>\r\n}\r\n\r\n@if (triggerType() === 'None') {\r\n <p class=\"fb-field__hint\">\r\n Il flow parte solo su richiesta. I valori iniziali si passano nelle variabili di input.\r\n </p>\r\n}\r\n\r\n@if (isEvent()) {\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Evento</legend>\r\n <p class=\"fb-section__note\">\r\n Il flow parte alla ricezione di un evento: e\u2019 a questo che l\u2019host si sottoscrive quando la\r\n versione viene attivata (\u00A78).\r\n </p>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Tipo di evento</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"start().eventType || ''\"\r\n placeholder=\"Es. OrdineEvaso\"\r\n (input)=\"setEventField('eventType', $any($event.target).value)\"\r\n />\r\n @if (!start().eventType) {\r\n <p class=\"fb-field__error\">Obbligatorio con questo trigger (START_EVENT_MISSING).</p>\r\n }\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Nome dell\u2019evento</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"start().eventName || ''\"\r\n (input)=\"setEventField('eventName', $any($event.target).value)\"\r\n />\r\n <p class=\"fb-field__hint\">Facoltativo: serve dove il tipo da solo non identifica l\u2019evento.</p>\r\n </div>\r\n </fieldset>\r\n}\r\n\r\n<fb-connector-editor\r\n [nodeName]=\"'$start'\"\r\n [node]=\"startNode()\"\r\n [outlets]=\"outlets()\"\r\n title=\"Da dove comincia\"\r\n (connectorChanged)=\"onConnectorChanged($event)\"\r\n/>\r\n" }]
|
|
14627
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!hasEntryPoint()) {\r\n <p class=\"fb-callout fb-callout--error\">\r\n Lo Start non punta a nessun elemento: il flow non ha un punto di ingresso e non e\u2019 eseguibile\r\n (START_NO_ENTRY_POINT).\r\n </p>\r\n}\r\n\r\n<!--\r\n \u00A73.4 \u2014 su un flow innescato da un record la tendina non c'e': i suoi tre valori sono il *momento*,\r\n e il momento e' l'ultima domanda della sequenza qui sotto, posta fra i soli momenti che\r\n l'operazione scelta ammette. Altrove i trigger sono quelli del **tipo di flow** scelto alla\r\n creazione, non tutti: la coppia `processType` + `triggerType` **e'** il tipo, e cambiarla qui\r\n vorrebbe dire cambiarlo.\r\n-->\r\n@if (!isRecordFlowType()) {\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Quando parte</label>\r\n <select class=\"fb-select\" [fbValue]=\"triggerType()\" (change)=\"setTriggerType($any($event.target).value)\">\r\n @for (trigger of triggerTypes(); track trigger.value) {\r\n <option [value]=\"trigger.value\">{{ trigger.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n}\r\n\r\n@if (flowType(); as type) {\r\n <p class=\"fb-field__hint\">\r\n Tipo di flow: <strong>{{ type.label }}</strong\r\n >{{ type.description ? ' \u2014 ' + type.description : '' }}\r\n </p>\r\n}\r\n@if (requiresRegistration()) {\r\n <!--\r\n \u00A78 \u2014 l'unico caso in cui una definizione **valida** puo' non essere attivabile: il flow non\r\n parte da solo, e l'infrastruttura dell'ospite deve prenderlo in carico. Dirlo qui, dove si\r\n sceglie il trigger, e' dirlo prima che l'attivazione fallisca.\r\n -->\r\n <p class=\"fb-callout\">\r\n Questo flow non parte da solo: attivandolo,\r\n {{ registrationLabel() ? 'il servizio \u00AB' + registrationLabel() + '\u00BB' : 'l\u2019infrastruttura dell\u2019ambiente' }}\r\n deve <strong>prenderlo in carico</strong>. Se non c\u2019e\u2019 chi lo faccia, l\u2019attivazione non riesce\r\n anche con la definizione a posto.\r\n </p>\r\n}\r\n\r\n@if (isRecordTrigger()) {\r\n <p class=\"fb-callout\">\r\n Con un trigger su record il flow espone <code>$Record</code> e <code>$Record__Prior</code>.\r\n </p>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Oggetto che innesca</label>\r\n <fb-object-picker\r\n [value]=\"start().object\"\r\n label=\"Oggetto che innesca\"\r\n placeholder=\"Scrivi o scegli un oggetto\"\r\n (valueChange)=\"setObject($event ?? '')\"\r\n />\r\n @if (!start().object) {\r\n <p class=\"fb-field__error\">Obbligatorio con i trigger su record (START_OBJECT_MISSING).</p>\r\n }\r\n </div>\r\n\r\n <!--\r\n \u00A73.4 \u2014 **l'operazione prima, il momento dopo**: sono due campi ma non due assi liberi, e da due\r\n tendine indipendenti si dichiara \u00ABprima dell'eliminazione\u00BB insieme a \u00ABalla creazione\u00BB, che il\r\n runtime legge come un'eliminazione. Qui quella coppia non e' esprimibile.\r\n -->\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Su quale operazione</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"start().recordTriggerType || ''\"\r\n (change)=\"setRecordOperation($any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014 scegli \u2014</option>\r\n @for (type of recordTriggerTypes(); track type.value) {\r\n <option [value]=\"type.value\" [title]=\"type.description || type.label\">{{ type.label }}</option>\r\n }\r\n </select>\r\n @if (recordOperation()?.description; as description) {\r\n <p class=\"fb-field__hint\">{{ description }}</p>\r\n }\r\n @if (!start().recordTriggerType) {\r\n <!-- Avviso e non errore: il motore lo legge come \u00ABogni salvataggio\u00BB (\u00A73.4). -->\r\n <p class=\"fb-field__hint fb-field__hint--warn\">\r\n Senza operazione il flow parte su <strong>ogni</strong> salvataggio, creazioni e\r\n aggiornamenti (START_RECORD_TRIGGER_MISSING).\r\n </p>\r\n }\r\n </div>\r\n\r\n <fb-record-filter-editor\r\n [holder]=\"$any(start())\"\r\n [object]=\"start().object\"\r\n title=\"Criteri di ingresso\"\r\n usage=\"filterable\"\r\n [supportsLogic]=\"true\"\r\n [supportsFormula]=\"true\"\r\n emptyWarning=\"Senza criteri il flow parte su ogni record.\"\r\n (changed)=\"onFiltersChanged($event)\"\r\n />\r\n\r\n @if (showRequireChanged()) {\r\n <!--\r\n \u00A73.4 \u2014 il \u00ABprima\u00BB da confrontare c'e' solo dove l'operazione lo porta (`usesPriorRecord`):\r\n alla creazione e all'eliminazione questo flag \u2014 e con lui l'operatore `IsChanged` \u2014 non decide\r\n nulla, quindi la domanda non si pone.\r\n -->\r\n <label class=\"fb-check\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"start().doesRequireRecordChangedToMeetCriteria === true\"\r\n (change)=\"setRequireChanged($any($event.target).checked)\"\r\n />\r\n Solo se il record <em>non</em> soddisfaceva i criteri prima del salvataggio\r\n </label>\r\n } @else if (start().doesRequireRecordChangedToMeetCriteria === true) {\r\n <!--\r\n Il flag c'e' ma l'operazione non ha un \u00ABprima\u00BB: arriva da un documento scritto altrove, o da\r\n un'operazione cambiata prima di questa versione dell'editor. Nasconderlo e basta lo\r\n toglierebbe dalla vista lasciandolo scritto \u2014 si dice, e la ripulitura e' un comando.\r\n -->\r\n <p class=\"fb-callout fb-callout--warn\">\r\n Il documento chiede che il record <strong>non</strong> soddisfacesse i criteri prima del\r\n salvataggio, ma con questa operazione non c\u2019e\u2019 un \u00ABprima\u00BB da confrontare: il motore lo ignora.\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost\" (click)=\"setRequireChanged(false)\">\r\n Togli la condizione\r\n </button>\r\n </p>\r\n }\r\n\r\n <!--\r\n Il momento e' l'**ultima** domanda, e sta qui solo dove la tendina in cima non c'e': nel ripiego\r\n il `triggerType` lo governa quella, e due controlli sullo stesso campo si contraddicono a vista.\r\n -->\r\n @if (isRecordFlowType()) {\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">In che momento</label>\r\n @if (showTimingChoice()) {\r\n <select class=\"fb-select\" [fbValue]=\"triggerType()\" (change)=\"setTriggerType($any($event.target).value)\">\r\n @for (timing of timingOptions(); track timing.value) {\r\n <option [value]=\"timing.value\" [title]=\"timing.description || timing.label\">{{ timing.label }}</option>\r\n }\r\n </select>\r\n @if (currentTiming()?.description; as description) {\r\n <p class=\"fb-field__hint\">{{ description }}</p>\r\n }\r\n } @else {\r\n <!--\r\n Momento unico (`allowsTimingChoice: false`, l'eliminazione): la domanda non si pone, ma il\r\n campo si scrive lo stesso \u2014 il contratto chiede **entrambi**.\r\n -->\r\n <p class=\"fb-field__hint\">\r\n <strong>{{ currentTiming()?.label || triggerType() }}</strong> \u2014 con questa operazione e\u2019\r\n l\u2019unico momento possibile, e viene scritto comunque nel documento.\r\n </p>\r\n }\r\n </div>\r\n }\r\n\r\n @if (hasTriggerMismatch()) {\r\n <p class=\"fb-callout fb-callout--error\">\r\n L\u2019operazione e il momento scritti nel documento non stanno insieme (START_TRIGGER_MISMATCH):\r\n il flow parte su un\u2019operazione diversa da quella scelta, e l\u2019attivazione non riesce.\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost\" (click)=\"useDefaultTiming()\">\r\n Riporta il momento fra quelli ammessi\r\n </button>\r\n </p>\r\n }\r\n}\r\n\r\n@if (isScheduled()) {\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Pianificazione</legend>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Frequenza</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"start().schedule?.frequency || ''\"\r\n (change)=\"setFrequency($any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014 scegli \u2014</option>\r\n @for (frequency of frequencies(); track frequency.value) {\r\n <option [value]=\"frequency.value\">{{ frequency.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n <div class=\"fb-field__row\">\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Data di inizio</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"date\"\r\n [value]=\"startDateValue()\"\r\n (input)=\"setStartDate($any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Ora</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"time\"\r\n [value]=\"startTimeValue()\"\r\n (input)=\"setStartTime($any($event.target).value)\"\r\n />\r\n </div>\r\n </div>\r\n @if (!start().schedule?.frequency) {\r\n <p class=\"fb-field__error\">La pianificazione e\u2019 obbligatoria con questo trigger (START_SCHEDULE_MISSING).</p>\r\n }\r\n </fieldset>\r\n\r\n <!--\r\n \u00A73.4 \u2014 su uno schedulato l'oggetto e' **facoltativo** e vuol dire un'altra cosa che sui trigger\r\n su record: non \u00ABl'entita' che innesca\u00BB ma \u00ABun'esecuzione per ogni record che soddisfa i filtri\u00BB.\r\n Senza, il flow gira una volta sola.\r\n -->\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Un\u2019esecuzione per record</legend>\r\n <p class=\"fb-section__note\">\r\n Facoltativo. Indicando un\u2019entita\u2019, il flow gira <strong>una volta per ogni record</strong> che\r\n soddisfa i filtri invece di una volta sola.\r\n </p>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Entita\u2019</label>\r\n <fb-object-picker\r\n [value]=\"start().object\"\r\n label=\"Entita\u2019\"\r\n placeholder=\"Nessuna: una sola esecuzione\"\r\n (valueChange)=\"setObject($event ?? '')\"\r\n />\r\n </div>\r\n @if (start().object) {\r\n <fb-record-filter-editor\r\n [holder]=\"$any(start())\"\r\n [object]=\"start().object\"\r\n title=\"Quali record\"\r\n usage=\"filterable\"\r\n [supportsLogic]=\"true\"\r\n [supportsFormula]=\"true\"\r\n emptyWarning=\"Senza criteri il flow gira su ogni record dell\u2019entita\u2019.\"\r\n (changed)=\"onFiltersChanged($event)\"\r\n />\r\n }\r\n </fieldset>\r\n\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Percorsi differiti</legend>\r\n <p class=\"fb-section__note\">\r\n Ogni percorso e\u2019 un ramo che parte dopo un intervallo, calcolato da un istante di riferimento.\r\n </p>\r\n\r\n <div class=\"fb-list\">\r\n @for (path of scheduledPaths(); track $index) {\r\n <div class=\"fb-list__item\">\r\n <div class=\"fb-list__header\">\r\n <span class=\"fb-list__index\">{{ $index + 1 }}</span>\r\n <span class=\"fb-list__spacer\"></span>\r\n <button\r\n type=\"button\"\r\n class=\"fb-btn fb-btn--ghost fb-btn--icon\"\r\n aria-label=\"Rimuovi il percorso\"\r\n (click)=\"removeScheduledPath($index)\"\r\n >\r\n \u00D7\r\n </button>\r\n </div>\r\n\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Etichetta</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.label || ''\"\r\n (input)=\"setPathField($index, 'label', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Nome tecnico</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"path.name || ''\"\r\n (input)=\"setPathField($index, 'name', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field__row\">\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Dopo</label>\r\n <input\r\n class=\"fb-input\"\r\n type=\"number\"\r\n [value]=\"path.offsetNumber ?? ''\"\r\n (input)=\"setPathOffsetNumber($index, $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Unita\u2019</label>\r\n <select\r\n class=\"fb-select\"\r\n [fbValue]=\"path.offsetUnit || ''\"\r\n (change)=\"setPathField($index, 'offsetUnit', $any($event.target).value)\"\r\n >\r\n <option value=\"\">\u2014</option>\r\n @for (unit of offsetUnits(); track unit.value) {\r\n <option [value]=\"unit.value\">{{ unit.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Istante di riferimento</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.timeSource || ''\"\r\n placeholder=\"Es. RecordTriggerEvent\"\r\n (input)=\"setPathField($index, 'timeSource', $any($event.target).value)\"\r\n />\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Campo data del record</label>\r\n <input\r\n class=\"fb-input\"\r\n [value]=\"path.recordField || ''\"\r\n (input)=\"setPathField($index, 'recordField', $any($event.target).value)\"\r\n />\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"fb-empty\">Nessun percorso differito.</p>\r\n }\r\n </div>\r\n <button type=\"button\" class=\"fb-btn\" (click)=\"addScheduledPath()\">Aggiungi percorso</button>\r\n </fieldset>\r\n}\r\n\r\n@if (triggerType() === 'None') {\r\n <p class=\"fb-field__hint\">\r\n Il flow parte solo su richiesta. I valori iniziali si passano nelle variabili di input.\r\n </p>\r\n}\r\n\r\n@if (isEvent()) {\r\n <fieldset class=\"fb-section\">\r\n <legend class=\"fb-section__title\">Evento</legend>\r\n <p class=\"fb-section__note\">\r\n Il flow parte alla ricezione di un evento: e\u2019 a questo che l\u2019host si sottoscrive quando la\r\n versione viene attivata (\u00A78).\r\n </p>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label fb-field__label--required\">Tipo di evento</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"start().eventType || ''\"\r\n placeholder=\"Es. OrdineEvaso\"\r\n (input)=\"setEventField('eventType', $any($event.target).value)\"\r\n />\r\n @if (!start().eventType) {\r\n <p class=\"fb-field__error\">Obbligatorio con questo trigger (START_EVENT_MISSING).</p>\r\n }\r\n </div>\r\n <div class=\"fb-field\">\r\n <label class=\"fb-field__label\">Nome dell\u2019evento</label>\r\n <input\r\n class=\"fb-input fb-input--mono\"\r\n [value]=\"start().eventName || ''\"\r\n (input)=\"setEventField('eventName', $any($event.target).value)\"\r\n />\r\n <p class=\"fb-field__hint\">Facoltativo: serve dove il tipo da solo non identifica l\u2019evento.</p>\r\n </div>\r\n </fieldset>\r\n}\r\n\r\n<fb-connector-editor\r\n [nodeName]=\"'$start'\"\r\n [node]=\"startNode()\"\r\n [outlets]=\"outlets()\"\r\n title=\"Da dove comincia\"\r\n (connectorChanged)=\"onConnectorChanged($event)\"\r\n/>\r\n" }]
|
|
14458
14628
|
}] });
|
|
14459
14629
|
|
|
14460
14630
|
/**
|