@esfaenza/flow-builder 20.3.45 → 20.3.46
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 +2 -2
- package/fesm2022/esfaenza-flow-builder.mjs +92 -17
- package/fesm2022/esfaenza-flow-builder.mjs.map +1 -1
- package/index.d.ts +65 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -117,8 +117,8 @@ sono opzionali e rifiutano con `MissingService` se non sovrascritti.
|
|
|
117
117
|
| §6.1 Lettura | |
|
|
118
118
|
|---|---|
|
|
119
119
|
| `listFlows(query?)` | astratto |
|
|
120
|
-
| `listVersions(flowName)` | astratto |
|
|
121
|
-
| `loadFlow(flowName, version?)` | astratto |
|
|
120
|
+
| `listVersions(flowName)` | astratto — l'editor la chiama **prima** di `loadFlow` e ne ricava il numero di versione da aprire: senza, quel numero resterebbe da indovinare (il documento porta `status`, non il numero) |
|
|
121
|
+
| `loadFlow(flowName, version?)` | astratto — l'editor passa **sempre** la versione, tranne quando `listVersions` non risponde: lì ripiega su «senza versione» e deduce |
|
|
122
122
|
| `exportFlow(flowName, query?)` | opzionale |
|
|
123
123
|
| `parseFlow(definition)` | opzionale — serve all'import di un file |
|
|
124
124
|
|
|
@@ -4634,6 +4634,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.28", ngImpo
|
|
|
4634
4634
|
* - la distinzione fra "salvato" e "sano": il salvataggio riesce anche con errori, e
|
|
4635
4635
|
* l'esito si legge in `validation` (§6.2).
|
|
4636
4636
|
*/
|
|
4637
|
+
/**
|
|
4638
|
+
* §8 — la versione **attiva**, decisa in un posto solo.
|
|
4639
|
+
*
|
|
4640
|
+
* `isActive` e' una comodita' della riga, ma il campo su cui il contratto scrive il ciclo di vita e'
|
|
4641
|
+
* `status`: la tabella della §8 e' fatta di stati, non di flag. Un host che serializza l'uno e non
|
|
4642
|
+
* l'altro — il caso piu' comune e' `IsActive` in PascalCase, che diventa `undefined` senza dire
|
|
4643
|
+
* niente — farebbe credere all'editor che nessuna versione sia attiva, e da lì l'editor sceglierebbe
|
|
4644
|
+
* la piu' recente come «aperta» mentre il backend gli ha consegnato l'attiva.
|
|
4645
|
+
*
|
|
4646
|
+
* Il ripiego va in un verso solo: se il flag manca, decide lo stato. Se ci sono entrambi e si
|
|
4647
|
+
* contraddicono vince lo stato, per la stessa ragione.
|
|
4648
|
+
*/
|
|
4649
|
+
function isVersionActive(version) {
|
|
4650
|
+
return version?.status === 'Active' || version?.isActive === true;
|
|
4651
|
+
}
|
|
4637
4652
|
class FlowEditorSession {
|
|
4638
4653
|
api = inject(FlowBuilderApi);
|
|
4639
4654
|
documentStore = inject(FlowDocumentStore);
|
|
@@ -4685,7 +4700,7 @@ class FlowEditorSession {
|
|
|
4685
4700
|
}
|
|
4686
4701
|
return this.isEditable() ? 'save' : 'newVersion';
|
|
4687
4702
|
}, ...(ngDevMode ? [{ debugName: "primaryCommand" }] : []));
|
|
4688
|
-
isActiveVersion = computed(() => this.currentVersionSummary()
|
|
4703
|
+
isActiveVersion = computed(() => isVersionActive(this.currentVersionSummary()), ...(ngDevMode ? [{ debugName: "isActiveVersion" }] : []));
|
|
4689
4704
|
/** Attivare esige zero errori (§8.3): il comando resta disabilitato finche' ce ne sono. */
|
|
4690
4705
|
canActivate = computed(() => !this.isNew() && !this.isActiveVersion() && this.validation.canActivate(), ...(ngDevMode ? [{ debugName: "canActivate" }] : []));
|
|
4691
4706
|
setAuthor(author) {
|
|
@@ -4704,22 +4719,39 @@ class FlowEditorSession {
|
|
|
4704
4719
|
}
|
|
4705
4720
|
/**
|
|
4706
4721
|
* Carica una versione e conserva il suo `updatedAt` (§11, "Modificare", passo 1).
|
|
4707
|
-
*
|
|
4722
|
+
*
|
|
4723
|
+
* **La versione si chiede sempre esplicita**, anche quando il chiamante non la indica: la si
|
|
4724
|
+
* risolve prima dall'elenco, con la regola della §6.1 (la attiva, altrimenti l'ultima). Chiedere
|
|
4725
|
+
* la definizione «senza versione» e' comodo — decide il backend — ma lascia poi un numero da
|
|
4726
|
+
* indovinare, perche' il documento porta `status` e **non** il numero (§2): un host che sceglie
|
|
4727
|
+
* diversamente da come si e' dedotto fa evidenziare come «aperta» una riga diversa da quella che
|
|
4728
|
+
* si sta guardando e, molto peggio, conservare l'`updatedAt` di quella riga e mandarlo come
|
|
4729
|
+
* `expectedUpdatedAt` al salvataggio (§9).
|
|
4730
|
+
*
|
|
4731
|
+
* Costa un round trip solo quando serve: la richiesta dell'elenco parte comunque per prima, e la
|
|
4732
|
+
* si aspetta **solo** se il numero non ce l'abbiamo già. Se l'elenco non arriva — host che non
|
|
4733
|
+
* espone la primitiva, o elenco vuoto — si torna a chiedere senza versione e a dedurre
|
|
4734
|
+
* ({@link pickVersion}): degradare e' meglio che non aprire.
|
|
4708
4735
|
*/
|
|
4709
4736
|
async open(flowName, version) {
|
|
4710
4737
|
this._isBusy.set(true);
|
|
4711
4738
|
this._conflict.set(null);
|
|
4712
4739
|
try {
|
|
4740
|
+
const versionsRequest = this.api
|
|
4741
|
+
.listVersions(flowName)
|
|
4742
|
+
.catch(() => []);
|
|
4743
|
+
// Con un numero in mano il `??` non valuta il ramo destro, e le due letture restano parallele.
|
|
4744
|
+
const requested = version ?? FlowEditorSession.contractVersion(await versionsRequest)?.version;
|
|
4713
4745
|
const [definition, versions] = await Promise.all([
|
|
4714
|
-
this.api.loadFlow(flowName,
|
|
4715
|
-
|
|
4746
|
+
this.api.loadFlow(flowName, requested),
|
|
4747
|
+
versionsRequest,
|
|
4716
4748
|
]);
|
|
4717
4749
|
this.documentStore.load(definition);
|
|
4718
4750
|
this._flowName.set(flowName);
|
|
4719
4751
|
this._versions.set(versions);
|
|
4720
|
-
//
|
|
4721
|
-
//
|
|
4722
|
-
const resolved =
|
|
4752
|
+
// Con `requested` la versione e' nota **per costruzione**: e' quella che abbiamo chiesto.
|
|
4753
|
+
// Si deduce solo dove non si e' potuto chiedere, cioe' senza elenco.
|
|
4754
|
+
const resolved = requested ?? FlowEditorSession.pickVersion(versions, definition);
|
|
4723
4755
|
this._version.set(resolved ?? null);
|
|
4724
4756
|
this._expectedUpdatedAt.set(versions.find((entry) => entry.version === resolved)?.updatedAt);
|
|
4725
4757
|
this._lastSaveResult.set(null);
|
|
@@ -4730,13 +4762,48 @@ class FlowEditorSession {
|
|
|
4730
4762
|
this._isBusy.set(false);
|
|
4731
4763
|
}
|
|
4732
4764
|
}
|
|
4733
|
-
/**
|
|
4734
|
-
|
|
4735
|
-
|
|
4765
|
+
/**
|
|
4766
|
+
* Quale versione il backend ci ha consegnato, quando non gliel'abbiamo chiesta.
|
|
4767
|
+
*
|
|
4768
|
+
* Il documento non porta il numero (§2), quindi si deduce — ma **non si tira a indovinare**: lo
|
|
4769
|
+
* `status` del documento dice quale delle due strade della §6.1 ha preso il backend («la versione
|
|
4770
|
+
* attiva, altrimenti l'ultima»), e se una sola riga porta quello status la deduzione diventa una
|
|
4771
|
+
* constatazione. È il caso che conta: un flow con la **v1 attiva e la v2 in bozza** e' la forma
|
|
4772
|
+
* piu' comune che esista, ed e' quella in cui sbagliare significa evidenziare come «aperta» una
|
|
4773
|
+
* versione diversa da quella che si sta guardando — e, molto peggio, conservare l'`updatedAt`
|
|
4774
|
+
* della riga sbagliata e mandarlo come `expectedUpdatedAt` al salvataggio (§9).
|
|
4775
|
+
*
|
|
4776
|
+
* Il ripiego e' la regola del contratto, con due difese: «attiva» la decide
|
|
4777
|
+
* {@link isVersionActive} e non il solo flag, e «l'ultima» e' il **numero piu' alto** e non la
|
|
4778
|
+
* prima riga — l'elenco arriva dalla piu' recente (§6.1), ma e' una promessa dell'host, e un host
|
|
4779
|
+
* che ordina al contrario farebbe aprire la piu' vecchia senza che niente lo dica.
|
|
4780
|
+
*
|
|
4781
|
+
* Resta un caso che nessuna delle due strade risolve: piu' righe con lo stesso status del
|
|
4782
|
+
* documento e un host che non segue la §6.1. Lì si torna alla regola del contratto, che e' quanto
|
|
4783
|
+
* di meglio si possa dire di un backend che non la rispetta.
|
|
4784
|
+
*/
|
|
4785
|
+
static pickVersion(versions, loaded) {
|
|
4786
|
+
const matching = loaded.status
|
|
4787
|
+
? versions.filter((entry) => entry.status === loaded.status)
|
|
4788
|
+
: [];
|
|
4789
|
+
if (matching.length === 1) {
|
|
4790
|
+
return matching[0].version;
|
|
4791
|
+
}
|
|
4792
|
+
return FlowEditorSession.contractVersion(versions)?.version;
|
|
4793
|
+
}
|
|
4794
|
+
/**
|
|
4795
|
+
* La regola della §6.1 — «la versione attiva, altrimenti l'ultima» — applicata dal client, con due
|
|
4796
|
+
* difese: «attiva» la decide {@link isVersionActive} e non il solo flag, e «l'ultima» e' il
|
|
4797
|
+
* **numero piu' alto** e non la prima riga. L'elenco arriva dalla piu' recente (§6.1), ma e' una
|
|
4798
|
+
* promessa dell'host: un host che ordina al contrario farebbe aprire la piu' vecchia senza che
|
|
4799
|
+
* niente lo dica.
|
|
4800
|
+
*/
|
|
4801
|
+
static contractVersion(versions) {
|
|
4802
|
+
const active = versions.find(isVersionActive);
|
|
4736
4803
|
if (active) {
|
|
4737
|
-
return active
|
|
4804
|
+
return active;
|
|
4738
4805
|
}
|
|
4739
|
-
return versions
|
|
4806
|
+
return versions.reduce((latest, entry) => (latest === undefined || entry.version > latest.version ? entry : latest), undefined);
|
|
4740
4807
|
}
|
|
4741
4808
|
/**
|
|
4742
4809
|
* Ricarica l'elenco versioni: dopo un'attivazione la precedente e' `Obsolete` (§8.4).
|
|
@@ -4755,7 +4822,7 @@ class FlowEditorSession {
|
|
|
4755
4822
|
const versions = await this.api.listVersions(flowName);
|
|
4756
4823
|
this._versions.set(versions);
|
|
4757
4824
|
if (options?.adoptVersion && this._version() == null) {
|
|
4758
|
-
this._version.set(FlowEditorSession.pickVersion(versions) ?? null);
|
|
4825
|
+
this._version.set(FlowEditorSession.pickVersion(versions, this.documentStore.document()) ?? null);
|
|
4759
4826
|
}
|
|
4760
4827
|
const current = this._version();
|
|
4761
4828
|
if (current != null) {
|
|
@@ -17024,6 +17091,14 @@ class VersionPanelComponent {
|
|
|
17024
17091
|
isCurrent(version) {
|
|
17025
17092
|
return version.version === this.currentVersion();
|
|
17026
17093
|
}
|
|
17094
|
+
/**
|
|
17095
|
+
* §8 — attiva secondo lo **stato**, non il solo flag: e' la stessa regola con cui la sessione
|
|
17096
|
+
* decide quale versione ha in mano, e tenerne due farebbe una riga marcata attiva e un comando
|
|
17097
|
+
* «Attiva» offerto sopra di essa.
|
|
17098
|
+
*/
|
|
17099
|
+
isActive(version) {
|
|
17100
|
+
return isVersionActive(version);
|
|
17101
|
+
}
|
|
17027
17102
|
statusLabel(version) {
|
|
17028
17103
|
switch (version.status) {
|
|
17029
17104
|
case 'Draft':
|
|
@@ -17103,16 +17178,16 @@ class VersionPanelComponent {
|
|
|
17103
17178
|
});
|
|
17104
17179
|
}
|
|
17105
17180
|
}
|
|
17106
|
-
hasActiveVersion = computed(() => this.versions().some(
|
|
17181
|
+
hasActiveVersion = computed(() => this.versions().some(isVersionActive), ...(ngDevMode ? [{ debugName: "hasActiveVersion" }] : []));
|
|
17107
17182
|
close() {
|
|
17108
17183
|
this.closed.emit();
|
|
17109
17184
|
}
|
|
17110
17185
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.28", ngImport: i0, type: VersionPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
17111
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.28", type: VersionPanelComponent, isStandalone: true, selector: "fb-version-panel", outputs: { closed: "closed", versionOpened: "versionOpened", notice: "notice" }, ngImport: i0, template: "<header class=\"fb-ver__header\">\r\n <h2 class=\"fb-ver__title\">Versioni</h2>\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost fb-btn--icon\" aria-label=\"Chiudi\" (click)=\"close()\">\u00D7</button>\r\n</header>\r\n\r\n<div class=\"fb-ver__body\">\r\n <div class=\"fb-field__row\">\r\n <button type=\"button\" class=\"fb-btn\" [disabled]=\"isBusy()\" (click)=\"createNewVersion()\">\r\n Nuova versione dalla corrente\r\n </button>\r\n @if (hasActiveVersion()) {\r\n <button type=\"button\" class=\"fb-btn fb-btn--danger\" [disabled]=\"isBusy()\" (click)=\"deactivate()\">\r\n Disattiva\r\n </button>\r\n }\r\n </div>\r\n\r\n <ul class=\"fb-ver__list\">\r\n @for (version of versions(); track version.version) {\r\n <li class=\"fb-ver__item\" [class.fb-ver__item--current]=\"isCurrent(version)\">\r\n <div class=\"fb-ver__row\">\r\n <button type=\"button\" class=\"fb-ver__open\" (click)=\"open(version)\">\r\n <span class=\"fb-ver__number\">v{{ version.version }}</span>\r\n <span\r\n class=\"fb-ver__status\"\r\n [class.fb-ver__status--active]=\"version
|
|
17186
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.28", type: VersionPanelComponent, isStandalone: true, selector: "fb-version-panel", outputs: { closed: "closed", versionOpened: "versionOpened", notice: "notice" }, ngImport: i0, template: "<header class=\"fb-ver__header\">\r\n <h2 class=\"fb-ver__title\">Versioni</h2>\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost fb-btn--icon\" aria-label=\"Chiudi\" (click)=\"close()\">\u00D7</button>\r\n</header>\r\n\r\n<div class=\"fb-ver__body\">\r\n <div class=\"fb-field__row\">\r\n <button type=\"button\" class=\"fb-btn\" [disabled]=\"isBusy()\" (click)=\"createNewVersion()\">\r\n Nuova versione dalla corrente\r\n </button>\r\n @if (hasActiveVersion()) {\r\n <button type=\"button\" class=\"fb-btn fb-btn--danger\" [disabled]=\"isBusy()\" (click)=\"deactivate()\">\r\n Disattiva\r\n </button>\r\n }\r\n </div>\r\n\r\n <ul class=\"fb-ver__list\">\r\n @for (version of versions(); track version.version) {\r\n <li class=\"fb-ver__item\" [class.fb-ver__item--current]=\"isCurrent(version)\">\r\n <div class=\"fb-ver__row\">\r\n <button type=\"button\" class=\"fb-ver__open\" (click)=\"open(version)\">\r\n <span class=\"fb-ver__number\">v{{ version.version }}</span>\r\n <span\r\n class=\"fb-ver__status\"\r\n [class.fb-ver__status--active]=\"isActive(version)\"\r\n [class.fb-ver__status--invalid]=\"version.status === 'InvalidDraft'\"\r\n >\r\n {{ statusLabel(version) }}\r\n </span>\r\n @if (isCurrent(version)) {\r\n <span class=\"fb-ver__badge\">aperta</span>\r\n }\r\n </button>\r\n </div>\r\n\r\n <p class=\"fb-ver__meta\">\r\n @if (version.updatedAt) {\r\n aggiornata {{ version.updatedAt }}\r\n }\r\n @if (version.updatedBy) {\r\n da {{ version.updatedBy }}\r\n }\r\n </p>\r\n\r\n <div class=\"fb-ver__actions\">\r\n @if (version.isEditable) {\r\n <span class=\"fb-ver__hint\">Modificabile</span>\r\n } @else {\r\n <!-- Salvare su una versione Active o Obsolete verrebbe rifiutato con NotEditable. -->\r\n <span class=\"fb-ver__hint\">Sola lettura: per modificarla, creane una nuova</span>\r\n }\r\n\r\n @if (!isActive(version) && isCurrent(version)) {\r\n <button\r\n type=\"button\"\r\n class=\"fb-btn fb-btn--primary fb-btn--icon\"\r\n [disabled]=\"isBusy() || !canActivate()\"\r\n [title]=\"canActivate() ? 'Attiva questa versione' : 'Ci sono errori da correggere prima di attivare'\"\r\n (click)=\"activate(version)\"\r\n >\r\n Attiva\r\n </button>\r\n }\r\n\r\n @if (!isActive(version)) {\r\n @if (pendingDelete() === version.version) {\r\n <span class=\"fb-ver__confirm\">\r\n Le esecuzioni sospese nate su questo numero riprenderebbero su una definizione diversa.\r\n <button type=\"button\" class=\"fb-btn fb-btn--danger fb-btn--icon\" (click)=\"confirmDelete(version.version)\">\r\n Elimina comunque\r\n </button>\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost fb-btn--icon\" (click)=\"cancelDelete()\">\r\n Annulla\r\n </button>\r\n </span>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fb-btn fb-btn--ghost fb-btn--icon\"\r\n [disabled]=\"isBusy()\"\r\n (click)=\"requestDelete(version)\"\r\n >\r\n Elimina\r\n </button>\r\n }\r\n }\r\n </div>\r\n </li>\r\n } @empty {\r\n <li class=\"fb-empty\">Nessuna versione: il flow non e\u2019 ancora stato salvato.</li>\r\n }\r\n </ul>\r\n\r\n <p class=\"fb-ver__note\">\r\n Una sola versione e\u2019 attiva: attivarne una rende superata la precedente, senza doverla disattivare prima.\r\n Le versioni superate costano poco \u2014 lo stato \u00ABSuperata\u00BB esiste per questo.\r\n </p>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--fb-surface, #fff)}.fb-ver__header{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-bottom:1px solid var(--fb-border-subtle, #e6e9ee)}.fb-ver__title{margin:0;font-size:14px;font-weight:600;color:var(--fb-text, #1d2939)}.fb-ver__body{flex:1;min-height:0;overflow-y:auto;padding:10px 12px}.fb-ver__list{margin:12px 0 0;padding:0;list-style:none}.fb-ver__item{margin-bottom:6px;padding:8px;border:1px solid var(--fb-border-subtle, #e6e9ee);border-radius:6px;background:var(--fb-surface-alt, #f8f9fb)}.fb-ver__item--current{border-color:var(--fb-accent, #2f6feb);background:color-mix(in srgb,var(--fb-accent, #2f6feb) 5%,transparent)}.fb-ver__open{display:flex;align-items:center;gap:6px;width:100%;padding:0;border:0;background:transparent;color:var(--fb-text, #1d2939);font:inherit;text-align:left;cursor:pointer}.fb-ver__number{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;font-weight:700}.fb-ver__status{padding:1px 6px;border-radius:8px;background:var(--fb-border, #d6dae1);font-size:10px;font-weight:600;color:var(--fb-text, #1d2939)}.fb-ver__status--active{background:color-mix(in srgb,var(--fb-success, #3f8f5f) 18%,transparent);color:var(--fb-success, #3f8f5f)}.fb-ver__status--invalid{background:color-mix(in srgb,var(--fb-warning, #b7791f) 16%,transparent);color:var(--fb-warning, #b7791f)}.fb-ver__badge{font-size:9px;color:var(--fb-accent, #2f6feb);text-transform:uppercase;letter-spacing:.05em}.fb-ver__meta{margin:3px 0 0;font-size:10px;color:var(--fb-text-muted, #667085)}.fb-ver__actions{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px}.fb-ver__hint{font-size:10px;color:var(--fb-text-subtle, #98a2b3)}.fb-ver__confirm{display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:5px 7px;border-radius:5px;background:color-mix(in srgb,var(--fb-error, #c9372c) 8%,transparent);font-size:10px;color:var(--fb-error, #c9372c)}.fb-ver__note{margin:12px 0 0;font-size:10px;line-height:1.45;color:var(--fb-text-subtle, #98a2b3)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
17112
17187
|
}
|
|
17113
17188
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.28", ngImport: i0, type: VersionPanelComponent, decorators: [{
|
|
17114
17189
|
type: Component,
|
|
17115
|
-
args: [{ selector: 'fb-version-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"fb-ver__header\">\r\n <h2 class=\"fb-ver__title\">Versioni</h2>\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost fb-btn--icon\" aria-label=\"Chiudi\" (click)=\"close()\">\u00D7</button>\r\n</header>\r\n\r\n<div class=\"fb-ver__body\">\r\n <div class=\"fb-field__row\">\r\n <button type=\"button\" class=\"fb-btn\" [disabled]=\"isBusy()\" (click)=\"createNewVersion()\">\r\n Nuova versione dalla corrente\r\n </button>\r\n @if (hasActiveVersion()) {\r\n <button type=\"button\" class=\"fb-btn fb-btn--danger\" [disabled]=\"isBusy()\" (click)=\"deactivate()\">\r\n Disattiva\r\n </button>\r\n }\r\n </div>\r\n\r\n <ul class=\"fb-ver__list\">\r\n @for (version of versions(); track version.version) {\r\n <li class=\"fb-ver__item\" [class.fb-ver__item--current]=\"isCurrent(version)\">\r\n <div class=\"fb-ver__row\">\r\n <button type=\"button\" class=\"fb-ver__open\" (click)=\"open(version)\">\r\n <span class=\"fb-ver__number\">v{{ version.version }}</span>\r\n <span\r\n class=\"fb-ver__status\"\r\n [class.fb-ver__status--active]=\"version
|
|
17190
|
+
args: [{ selector: 'fb-version-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"fb-ver__header\">\r\n <h2 class=\"fb-ver__title\">Versioni</h2>\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost fb-btn--icon\" aria-label=\"Chiudi\" (click)=\"close()\">\u00D7</button>\r\n</header>\r\n\r\n<div class=\"fb-ver__body\">\r\n <div class=\"fb-field__row\">\r\n <button type=\"button\" class=\"fb-btn\" [disabled]=\"isBusy()\" (click)=\"createNewVersion()\">\r\n Nuova versione dalla corrente\r\n </button>\r\n @if (hasActiveVersion()) {\r\n <button type=\"button\" class=\"fb-btn fb-btn--danger\" [disabled]=\"isBusy()\" (click)=\"deactivate()\">\r\n Disattiva\r\n </button>\r\n }\r\n </div>\r\n\r\n <ul class=\"fb-ver__list\">\r\n @for (version of versions(); track version.version) {\r\n <li class=\"fb-ver__item\" [class.fb-ver__item--current]=\"isCurrent(version)\">\r\n <div class=\"fb-ver__row\">\r\n <button type=\"button\" class=\"fb-ver__open\" (click)=\"open(version)\">\r\n <span class=\"fb-ver__number\">v{{ version.version }}</span>\r\n <span\r\n class=\"fb-ver__status\"\r\n [class.fb-ver__status--active]=\"isActive(version)\"\r\n [class.fb-ver__status--invalid]=\"version.status === 'InvalidDraft'\"\r\n >\r\n {{ statusLabel(version) }}\r\n </span>\r\n @if (isCurrent(version)) {\r\n <span class=\"fb-ver__badge\">aperta</span>\r\n }\r\n </button>\r\n </div>\r\n\r\n <p class=\"fb-ver__meta\">\r\n @if (version.updatedAt) {\r\n aggiornata {{ version.updatedAt }}\r\n }\r\n @if (version.updatedBy) {\r\n da {{ version.updatedBy }}\r\n }\r\n </p>\r\n\r\n <div class=\"fb-ver__actions\">\r\n @if (version.isEditable) {\r\n <span class=\"fb-ver__hint\">Modificabile</span>\r\n } @else {\r\n <!-- Salvare su una versione Active o Obsolete verrebbe rifiutato con NotEditable. -->\r\n <span class=\"fb-ver__hint\">Sola lettura: per modificarla, creane una nuova</span>\r\n }\r\n\r\n @if (!isActive(version) && isCurrent(version)) {\r\n <button\r\n type=\"button\"\r\n class=\"fb-btn fb-btn--primary fb-btn--icon\"\r\n [disabled]=\"isBusy() || !canActivate()\"\r\n [title]=\"canActivate() ? 'Attiva questa versione' : 'Ci sono errori da correggere prima di attivare'\"\r\n (click)=\"activate(version)\"\r\n >\r\n Attiva\r\n </button>\r\n }\r\n\r\n @if (!isActive(version)) {\r\n @if (pendingDelete() === version.version) {\r\n <span class=\"fb-ver__confirm\">\r\n Le esecuzioni sospese nate su questo numero riprenderebbero su una definizione diversa.\r\n <button type=\"button\" class=\"fb-btn fb-btn--danger fb-btn--icon\" (click)=\"confirmDelete(version.version)\">\r\n Elimina comunque\r\n </button>\r\n <button type=\"button\" class=\"fb-btn fb-btn--ghost fb-btn--icon\" (click)=\"cancelDelete()\">\r\n Annulla\r\n </button>\r\n </span>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fb-btn fb-btn--ghost fb-btn--icon\"\r\n [disabled]=\"isBusy()\"\r\n (click)=\"requestDelete(version)\"\r\n >\r\n Elimina\r\n </button>\r\n }\r\n }\r\n </div>\r\n </li>\r\n } @empty {\r\n <li class=\"fb-empty\">Nessuna versione: il flow non e\u2019 ancora stato salvato.</li>\r\n }\r\n </ul>\r\n\r\n <p class=\"fb-ver__note\">\r\n Una sola versione e\u2019 attiva: attivarne una rende superata la precedente, senza doverla disattivare prima.\r\n Le versioni superate costano poco \u2014 lo stato \u00ABSuperata\u00BB esiste per questo.\r\n </p>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--fb-surface, #fff)}.fb-ver__header{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-bottom:1px solid var(--fb-border-subtle, #e6e9ee)}.fb-ver__title{margin:0;font-size:14px;font-weight:600;color:var(--fb-text, #1d2939)}.fb-ver__body{flex:1;min-height:0;overflow-y:auto;padding:10px 12px}.fb-ver__list{margin:12px 0 0;padding:0;list-style:none}.fb-ver__item{margin-bottom:6px;padding:8px;border:1px solid var(--fb-border-subtle, #e6e9ee);border-radius:6px;background:var(--fb-surface-alt, #f8f9fb)}.fb-ver__item--current{border-color:var(--fb-accent, #2f6feb);background:color-mix(in srgb,var(--fb-accent, #2f6feb) 5%,transparent)}.fb-ver__open{display:flex;align-items:center;gap:6px;width:100%;padding:0;border:0;background:transparent;color:var(--fb-text, #1d2939);font:inherit;text-align:left;cursor:pointer}.fb-ver__number{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;font-weight:700}.fb-ver__status{padding:1px 6px;border-radius:8px;background:var(--fb-border, #d6dae1);font-size:10px;font-weight:600;color:var(--fb-text, #1d2939)}.fb-ver__status--active{background:color-mix(in srgb,var(--fb-success, #3f8f5f) 18%,transparent);color:var(--fb-success, #3f8f5f)}.fb-ver__status--invalid{background:color-mix(in srgb,var(--fb-warning, #b7791f) 16%,transparent);color:var(--fb-warning, #b7791f)}.fb-ver__badge{font-size:9px;color:var(--fb-accent, #2f6feb);text-transform:uppercase;letter-spacing:.05em}.fb-ver__meta{margin:3px 0 0;font-size:10px;color:var(--fb-text-muted, #667085)}.fb-ver__actions{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px}.fb-ver__hint{font-size:10px;color:var(--fb-text-subtle, #98a2b3)}.fb-ver__confirm{display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:5px 7px;border-radius:5px;background:color-mix(in srgb,var(--fb-error, #c9372c) 8%,transparent);font-size:10px;color:var(--fb-error, #c9372c)}.fb-ver__note{margin:12px 0 0;font-size:10px;line-height:1.45;color:var(--fb-text-subtle, #98a2b3)}\n"] }]
|
|
17116
17191
|
}], propDecorators: { closed: [{ type: i0.Output, args: ["closed"] }], versionOpened: [{ type: i0.Output, args: ["versionOpened"] }], notice: [{ type: i0.Output, args: ["notice"] }] } });
|
|
17117
17192
|
|
|
17118
17193
|
/**
|
|
@@ -19114,5 +19189,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.28", ngImpo
|
|
|
19114
19189
|
* Generated bundle index. Do not edit.
|
|
19115
19190
|
*/
|
|
19116
19191
|
|
|
19117
|
-
export { ConditionEditorComponent, ConnectorEditorComponent, DebugPanelComponent, DynamicScreenInspectorComponent, ENUM_CHOICE_SET_DEFAULT_DISPLAY_FIELD, ENUM_CHOICE_SET_DEFAULT_VALUE_FIELD, ENUM_CHOICE_SET_FIELDS, ElementDialogComponent, ElementInspectorComponent, ElementPaletteComponent, EnumValuePickerComponent, FALLBACK_COLLECTION_BY_TYPE, FALLBACK_TYPE_LABEL, FLOW_BUILDER_HTTP_CONFIG, FLOW_CLIPBOARD_KIND, FLOW_CLIPBOARD_VERSION, FLOW_ELEMENT_ICONS, FLOW_ELEMENT_VARIANT_FIELDS, FLOW_ELEMENT_VARIANT_ICONS, FLOW_ERROR_FALLBACK_MESSAGE, FLOW_ERROR_HTTP_STATUS, FLOW_FOLD_HEIGHT, FLOW_FOLD_WIDTH, FLOW_GROUP_COLORS, FLOW_NAME_PATTERN, FLOW_NODE_COLLECTIONS, FLOW_NODE_HEIGHT, FLOW_NODE_WIDTH, FLOW_REFERENCE_FIELDS, FLOW_RESOURCE_COLLECTIONS, FLOW_VALUE_FIELDS, FLOW_VALUE_LITERAL_FIELDS, FieldAssignmentEditorComponent, FieldPickerComponent, FieldValuePickerComponent, FlowApiError, FlowBuilderApi, FlowBuilderComponent, FlowCanvasComponent, FlowCatalogStore, FlowClipboardService, FlowDictionaryStore, FlowDocumentStore, FlowEditorSession, FlowLayoutService, FlowValidationStore, FormulaEditorComponent, FormulaValidationService, GROUP_HEADER_HEIGHT, GROUP_MIN_HEIGHT, GROUP_MIN_WIDTH, GROUP_PADDING, GroupPanelComponent, HttpFlowBuilderApi, MergeTextEditorComponent, NamePickerComponent, NodeInspectorBase, ORCHESTRATION_CONDITION_OUTPUT, ObjectPickerComponent, OrchestratedStageInspectorComponent, ParameterEditorComponent, PasteDialogComponent, ProblemsPanelComponent, RecordFilterEditorComponent, ReferencePickerComponent, ResourceDialogComponent, ResourceFormComponent, ResourcePanelComponent, RunDialogComponent, SEVERITY_BUCKETS, SEVERITY_ICON, SEVERITY_LABEL, START_NODE_NAME, SelectValueDirective, StartInspectorComponent, StructureMemberPickerComponent, StructurePickerComponent, TYPES_WITH_AUTOMATIC_OUTPUT, TYPE_BY_COLLECTION, UNSUPPORTED_TYPES, ValueEditorComponent, VersionPanelComponent, allFieldsOf, applyPaste, areTypesComparable, boundsAround, buildClipboardPayload, canvasFoldId, canvasGroupId, canvasNodeId, checkConditionLogic, checkFlowName, choiceSetSourceOf, declaredChoiceSetSources, describeFieldPath, describePathEntry, duplicateField, elementIcon, emptyFlowDefinition, enumChoiceSetFieldType, fieldAt, filterReferences, flattenFields, flowNodeWidth, flowNodeWidthClass, foldSourceConnectorId, foldTargetConnectorId, groupColorClass, groupRect, hasAutoSize, innerNamesOf, insertField, isClipboardPayload, isCustomConditionLogic, isEmptyReferenceFilter, isFieldResource, isFoldReference, isGlobalReference, isNumericType, isPathInside, isTypeCheckedOperator, isUnknownEnumChoiceSetField, isValidFlowName, isValued, loadPathLevel, matchesReferenceFilter, membersInside, moveCondition, moveField, navigatePath, otherSourceFieldsOf, outletByKey, outletsOf, parseCanvasFoldId, parseCanvasGroupId, parseCanvasNodeId, parseFieldPath, parseInvariantNumber, parseSourceConnectorId, parseTargetConnectorId, pathAvailableNames, pathContainerLabel, pathKey, pathNotVerifiableMessage, planPaste, recomputeMembers, referenceRoot, referencedRootsOf, remapConditionLogic, removeCondition, removeField, repeatedFieldNames, repeatingSectionOf, resolvePath, resourceFieldsOf, rewriteReferences, sameMembers, samePath, screenActionNames, screenFieldNames, severityBucket, slugifyFlowName, sourceConnectorId, stageStepNames, stageStepOutputReferenced, stepsOf, targetConnectorId, typeOfCollection, uniqueFlowName, valuedFieldOf, valuedFieldsOf, variantFieldOf, variantOf, variantPresetOf };
|
|
19192
|
+
export { ConditionEditorComponent, ConnectorEditorComponent, DebugPanelComponent, DynamicScreenInspectorComponent, ENUM_CHOICE_SET_DEFAULT_DISPLAY_FIELD, ENUM_CHOICE_SET_DEFAULT_VALUE_FIELD, ENUM_CHOICE_SET_FIELDS, ElementDialogComponent, ElementInspectorComponent, ElementPaletteComponent, EnumValuePickerComponent, FALLBACK_COLLECTION_BY_TYPE, FALLBACK_TYPE_LABEL, FLOW_BUILDER_HTTP_CONFIG, FLOW_CLIPBOARD_KIND, FLOW_CLIPBOARD_VERSION, FLOW_ELEMENT_ICONS, FLOW_ELEMENT_VARIANT_FIELDS, FLOW_ELEMENT_VARIANT_ICONS, FLOW_ERROR_FALLBACK_MESSAGE, FLOW_ERROR_HTTP_STATUS, FLOW_FOLD_HEIGHT, FLOW_FOLD_WIDTH, FLOW_GROUP_COLORS, FLOW_NAME_PATTERN, FLOW_NODE_COLLECTIONS, FLOW_NODE_HEIGHT, FLOW_NODE_WIDTH, FLOW_REFERENCE_FIELDS, FLOW_RESOURCE_COLLECTIONS, FLOW_VALUE_FIELDS, FLOW_VALUE_LITERAL_FIELDS, FieldAssignmentEditorComponent, FieldPickerComponent, FieldValuePickerComponent, FlowApiError, FlowBuilderApi, FlowBuilderComponent, FlowCanvasComponent, FlowCatalogStore, FlowClipboardService, FlowDictionaryStore, FlowDocumentStore, FlowEditorSession, FlowLayoutService, FlowValidationStore, FormulaEditorComponent, FormulaValidationService, GROUP_HEADER_HEIGHT, GROUP_MIN_HEIGHT, GROUP_MIN_WIDTH, GROUP_PADDING, GroupPanelComponent, HttpFlowBuilderApi, MergeTextEditorComponent, NamePickerComponent, NodeInspectorBase, ORCHESTRATION_CONDITION_OUTPUT, ObjectPickerComponent, OrchestratedStageInspectorComponent, ParameterEditorComponent, PasteDialogComponent, ProblemsPanelComponent, RecordFilterEditorComponent, ReferencePickerComponent, ResourceDialogComponent, ResourceFormComponent, ResourcePanelComponent, RunDialogComponent, SEVERITY_BUCKETS, SEVERITY_ICON, SEVERITY_LABEL, START_NODE_NAME, SelectValueDirective, StartInspectorComponent, StructureMemberPickerComponent, StructurePickerComponent, TYPES_WITH_AUTOMATIC_OUTPUT, TYPE_BY_COLLECTION, UNSUPPORTED_TYPES, ValueEditorComponent, VersionPanelComponent, allFieldsOf, applyPaste, areTypesComparable, boundsAround, buildClipboardPayload, canvasFoldId, canvasGroupId, canvasNodeId, checkConditionLogic, checkFlowName, choiceSetSourceOf, declaredChoiceSetSources, describeFieldPath, describePathEntry, duplicateField, elementIcon, emptyFlowDefinition, enumChoiceSetFieldType, fieldAt, filterReferences, flattenFields, flowNodeWidth, flowNodeWidthClass, foldSourceConnectorId, foldTargetConnectorId, groupColorClass, groupRect, hasAutoSize, innerNamesOf, insertField, isClipboardPayload, isCustomConditionLogic, isEmptyReferenceFilter, isFieldResource, isFoldReference, isGlobalReference, isNumericType, isPathInside, isTypeCheckedOperator, isUnknownEnumChoiceSetField, isValidFlowName, isValued, isVersionActive, loadPathLevel, matchesReferenceFilter, membersInside, moveCondition, moveField, navigatePath, otherSourceFieldsOf, outletByKey, outletsOf, parseCanvasFoldId, parseCanvasGroupId, parseCanvasNodeId, parseFieldPath, parseInvariantNumber, parseSourceConnectorId, parseTargetConnectorId, pathAvailableNames, pathContainerLabel, pathKey, pathNotVerifiableMessage, planPaste, recomputeMembers, referenceRoot, referencedRootsOf, remapConditionLogic, removeCondition, removeField, repeatedFieldNames, repeatingSectionOf, resolvePath, resourceFieldsOf, rewriteReferences, sameMembers, samePath, screenActionNames, screenFieldNames, severityBucket, slugifyFlowName, sourceConnectorId, stageStepNames, stageStepOutputReferenced, stepsOf, targetConnectorId, typeOfCollection, uniqueFlowName, valuedFieldOf, valuedFieldsOf, variantFieldOf, variantOf, variantPresetOf };
|
|
19118
19193
|
//# sourceMappingURL=esfaenza-flow-builder.mjs.map
|