@esfaenza/dpe-builder 20.3.7 → 20.3.9
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/fesm2022/esfaenza-dpe-builder.mjs +664 -320
- package/fesm2022/esfaenza-dpe-builder.mjs.map +1 -1
- package/index.d.ts +152 -19
- package/package.json +5 -5
- package/styles/dpe-builder.css +432 -59
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { throwError, defer, catchError, map, tap, EMPTY, switchMap, of, debounceTime } from 'rxjs';
|
|
1
|
+
import { throwError, defer, catchError, map, tap, EMPTY, switchMap, of, filter, debounceTime } from 'rxjs';
|
|
2
2
|
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { InjectionToken, inject, Injectable, makeEnvironmentProviders, signal, computed, DestroyRef, input, ChangeDetectionStrategy, Component, ElementRef, output, viewChild, effect, Directive, untracked, Injector, afterNextRender } from '@angular/core';
|
|
@@ -463,10 +463,10 @@ class HttpDpeBuilderApi extends DpeBuilderApi {
|
|
|
463
463
|
deleteDefinition(name) {
|
|
464
464
|
return this.request('deleteDefinition', () => this.httpDelete(`/definitions/${this.segment(this.requireKey(name, 'deleteDefinition', 'il nome della definizione'))}`));
|
|
465
465
|
}
|
|
466
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
467
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
466
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: HttpDpeBuilderApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
467
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: HttpDpeBuilderApi });
|
|
468
468
|
}
|
|
469
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
469
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: HttpDpeBuilderApi, decorators: [{
|
|
470
470
|
type: Injectable
|
|
471
471
|
}] });
|
|
472
472
|
/**
|
|
@@ -1446,7 +1446,20 @@ function dpeNodeSubtitle(collection, node) {
|
|
|
1446
1446
|
*/
|
|
1447
1447
|
/** Profondita' della cronologia: oltre, le istantanee piu' vecchie si buttano. */
|
|
1448
1448
|
const HISTORY_LIMIT = 100;
|
|
1449
|
-
/**
|
|
1449
|
+
/**
|
|
1450
|
+
* Una definizione vuota ma **leggibile**: `formatVersion` e `dialect` non sono opzionali.
|
|
1451
|
+
*
|
|
1452
|
+
* **Serve a `createDefinition`, non a montare l'editor.** E' il documento minimo che si manda al
|
|
1453
|
+
* backend per far nascere una definizione nel catalogo (ADR 0019), e da li' in poi quella che si
|
|
1454
|
+
* edita e' la definizione **caricata con `load(nome)`**.
|
|
1455
|
+
*
|
|
1456
|
+
* Montare l'editor su un documento costruito qui, o su uno costruito a mano senza nome, produce due
|
|
1457
|
+
* sintomi che sembrano scollegati e sono la stessa cosa: la validazione risponde
|
|
1458
|
+
* `DPE_MODEL_REQUIRED_MISSING` su `name` e `label` — per il backend una stringa vuota e un campo
|
|
1459
|
+
* assente sono lo stesso caso — e il salvataggio non ha una chiave per la rotta
|
|
1460
|
+
* `PUT /definitions/{name}`. L'editor lo dichiara in cima con un banner e disabilita «Salva», ma la
|
|
1461
|
+
* correzione e' a monte: creare dal catalogo e caricare.
|
|
1462
|
+
*/
|
|
1450
1463
|
function dpeEmptyDefinition(name, label, dialect) {
|
|
1451
1464
|
return { formatVersion: 1, name, label, dialect };
|
|
1452
1465
|
}
|
|
@@ -1461,6 +1474,16 @@ class DpeDocumentStore {
|
|
|
1461
1474
|
* sulla selezione.
|
|
1462
1475
|
*/
|
|
1463
1476
|
_selectedNodeNames = signal([], ...(ngDevMode ? [{ debugName: "_selectedNodeNames" }] : []));
|
|
1477
|
+
/**
|
|
1478
|
+
* La dialog di modifica del nodo e' aperta. **Un booleano**, non un secondo nome di nodo: il
|
|
1479
|
+
* nodo su cui si sta agendo resta `selectedNodeName()`, e due registrazioni dello stesso fatto
|
|
1480
|
+
* sono esattamente cio' che questo store dichiara di non voler avere (ci ha gia' rimesso una
|
|
1481
|
+
* volta con la doppia selezione di @foblex/flow).
|
|
1482
|
+
*
|
|
1483
|
+
* Non entra nella cronologia: aprire una finestra non e' una modifica del documento, e un undo
|
|
1484
|
+
* che aprisse o chiudesse finestre sarebbe un comando che fa due cose.
|
|
1485
|
+
*/
|
|
1486
|
+
_isNodeEditorOpen = signal(false, ...(ngDevMode ? [{ debugName: "_isNodeEditorOpen" }] : []));
|
|
1464
1487
|
_past = signal([], ...(ngDevMode ? [{ debugName: "_past" }] : []));
|
|
1465
1488
|
_future = signal([], ...(ngDevMode ? [{ debugName: "_future" }] : []));
|
|
1466
1489
|
/**
|
|
@@ -1471,8 +1494,18 @@ class DpeDocumentStore {
|
|
|
1471
1494
|
* — e tornare a "no" quando si annulla fino allo stato di partenza.
|
|
1472
1495
|
*/
|
|
1473
1496
|
_savedSnapshot = signal(JSON.stringify(dpeEmptyDefinition('', '', 'Sqlite')), ...(ngDevMode ? [{ debugName: "_savedSnapshot" }] : []));
|
|
1497
|
+
/**
|
|
1498
|
+
* Vero da quando un documento e' stato **caricato**. Distingue il segnaposto del costruttore da
|
|
1499
|
+
* una definizione vera, e serve a chi non deve lavorare sul segnaposto: la validazione non lo
|
|
1500
|
+
* manda al backend (`DpeValidationService`), perche' la risposta sarebbero i quattro rilievi di
|
|
1501
|
+
* una definizione vuota — `name`, `label`, `dataSources` e nessun writeback — che descrivono il
|
|
1502
|
+
* segnaposto e non il lavoro dell'utente, e che dall'editor nessuno puo' correggere.
|
|
1503
|
+
*/
|
|
1504
|
+
_hasDocument = signal(false, ...(ngDevMode ? [{ debugName: "_hasDocument" }] : []));
|
|
1474
1505
|
/** La definizione corrente: unica fonte di verita' per canvas, ispettori e pannelli. */
|
|
1475
1506
|
definition = this._definition.asReadonly();
|
|
1507
|
+
/** Vero da quando `load` ha portato un documento: prima c'e' solo il segnaposto. */
|
|
1508
|
+
hasDocument = this._hasDocument.asReadonly();
|
|
1476
1509
|
/** Nodi e archi derivati dalla definizione. Ricalcolati solo quando la definizione cambia. */
|
|
1477
1510
|
graph = computed(() => dpeBuildGraph(this._definition()), ...(ngDevMode ? [{ debugName: "graph" }] : []));
|
|
1478
1511
|
selectedNodeNames = this._selectedNodeNames.asReadonly();
|
|
@@ -1487,6 +1520,11 @@ class DpeDocumentStore {
|
|
|
1487
1520
|
const name = this.selectedNodeName();
|
|
1488
1521
|
return name === undefined ? undefined : dpeFindNode(this._definition(), name)?.node;
|
|
1489
1522
|
}, ...(ngDevMode ? [{ debugName: "selectedNode" }] : []));
|
|
1523
|
+
/**
|
|
1524
|
+
* La dialog di modifica del nodo e' aperta. Non e' una seconda identita': il nodo e'
|
|
1525
|
+
* `selectedNodeName()`.
|
|
1526
|
+
*/
|
|
1527
|
+
isNodeEditorOpen = this._isNodeEditorOpen.asReadonly();
|
|
1490
1528
|
// --- cio' che arriva dal backend ------------------------------------------
|
|
1491
1529
|
validateResult = this._validateResult.asReadonly();
|
|
1492
1530
|
compileResult = this._compileResult.asReadonly();
|
|
@@ -1543,11 +1581,16 @@ class DpeDocumentStore {
|
|
|
1543
1581
|
*/
|
|
1544
1582
|
load(definition) {
|
|
1545
1583
|
this._definition.set(definition);
|
|
1584
|
+
this._hasDocument.set(true);
|
|
1546
1585
|
// Cio' che e' appena arrivato **e'** lo stato salvato: aprire un documento non lo sporca.
|
|
1547
1586
|
this._savedSnapshot.set(JSON.stringify(definition));
|
|
1548
1587
|
this._past.set([]);
|
|
1549
1588
|
this._future.set([]);
|
|
1550
1589
|
this._selectedNodeNames.set([]);
|
|
1590
|
+
// Una dialog rimasta aperta guarderebbe un nodo di **un'altra** definizione: il nome potrebbe
|
|
1591
|
+
// anche esistere qui, e allora si starebbe modificando un nodo che nessuno ha aperto. E' il
|
|
1592
|
+
// caso che si dimentica, perche' non fallisce — mostra la cosa sbagliata.
|
|
1593
|
+
this._isNodeEditorOpen.set(false);
|
|
1551
1594
|
this._validateResult.set(undefined);
|
|
1552
1595
|
this._compileResult.set(undefined);
|
|
1553
1596
|
}
|
|
@@ -1583,6 +1626,24 @@ class DpeDocumentStore {
|
|
|
1583
1626
|
selectMany(nodeNames) {
|
|
1584
1627
|
this._selectedNodeNames.set(Array.from(new Set(nodeNames)));
|
|
1585
1628
|
}
|
|
1629
|
+
/**
|
|
1630
|
+
* Seleziona **solo** quel nodo e apre la dialog di modifica.
|
|
1631
|
+
*
|
|
1632
|
+
* La selezione **collassa a un nodo solo**: il gesto «apri questo» dichiara su chi si sta
|
|
1633
|
+
* agendo, e la regola gia' in vigore e' che con piu' di un nodo selezionato non si mostrano i
|
|
1634
|
+
* campi di uno.
|
|
1635
|
+
*
|
|
1636
|
+
* Le due scritture sono **esplicite** e non conseguenza di un `effect`: un effect che scrive
|
|
1637
|
+
* signal renderebbe l'ordine di questi due fatti dipendente dalla schedulazione, cioe' non
|
|
1638
|
+
* testabile.
|
|
1639
|
+
*/
|
|
1640
|
+
openNodeEditor(nodeName) {
|
|
1641
|
+
this.select(nodeName);
|
|
1642
|
+
this._isNodeEditorOpen.set(true);
|
|
1643
|
+
}
|
|
1644
|
+
closeNodeEditor() {
|
|
1645
|
+
this._isNodeEditorOpen.set(false);
|
|
1646
|
+
}
|
|
1586
1647
|
// -------------------------------------------------------------------------
|
|
1587
1648
|
// Mutazioni — sincrone e granulari
|
|
1588
1649
|
// -------------------------------------------------------------------------
|
|
@@ -1635,6 +1696,9 @@ class DpeDocumentStore {
|
|
|
1635
1696
|
if (!located) {
|
|
1636
1697
|
return;
|
|
1637
1698
|
}
|
|
1699
|
+
// Si legge **prima** della potatura della selezione: dopo, `selectedNodeName()` e' gia' un
|
|
1700
|
+
// altro nodo (o nessuno) e non si saprebbe piu' se la dialog stava guardando questo.
|
|
1701
|
+
const wasOpenOnIt = this._isNodeEditorOpen() && this.selectedNodeName() === nodeName;
|
|
1638
1702
|
const existing = (definition[located.collection] ?? []);
|
|
1639
1703
|
const next = existing.filter((node) => node.name !== nodeName);
|
|
1640
1704
|
this.commit(this.withCollection(definition, located.collection, next));
|
|
@@ -1645,6 +1709,13 @@ class DpeDocumentStore {
|
|
|
1645
1709
|
if (selected.includes(nodeName)) {
|
|
1646
1710
|
this._selectedNodeNames.set(selected.filter((name) => name !== nodeName));
|
|
1647
1711
|
}
|
|
1712
|
+
// Il bersaglio della dialog e' svanito: dopo l'eliminazione non c'e' piu' niente da
|
|
1713
|
+
// modificare. La chiusura sta qui e non nel componente perche' «Elimina il nodo» sta nel
|
|
1714
|
+
// piede della dialog, e un componente che si chiude da se' dopo aver chiesto una mutazione
|
|
1715
|
+
// sarebbe una seconda regola sullo stesso fatto.
|
|
1716
|
+
if (wasOpenOnIt) {
|
|
1717
|
+
this._isNodeEditorOpen.set(false);
|
|
1718
|
+
}
|
|
1648
1719
|
}
|
|
1649
1720
|
/**
|
|
1650
1721
|
* L'**unico** punto che rinomina un nodo (**I5**): delega alla funzione pura, che aggiorna
|
|
@@ -1806,10 +1877,10 @@ class DpeDocumentStore {
|
|
|
1806
1877
|
this._future.set([]);
|
|
1807
1878
|
this._definition.set(next);
|
|
1808
1879
|
}
|
|
1809
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
1810
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
1880
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeDocumentStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1881
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeDocumentStore });
|
|
1811
1882
|
}
|
|
1812
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
1883
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeDocumentStore, decorators: [{
|
|
1813
1884
|
type: Injectable
|
|
1814
1885
|
}] });
|
|
1815
1886
|
|
|
@@ -1994,10 +2065,10 @@ class DpeCatalogStore {
|
|
|
1994
2065
|
const message = error instanceof Error ? error.message : 'Errore inatteso dal backend.';
|
|
1995
2066
|
return new DpeApiError('Transport', message, error);
|
|
1996
2067
|
}
|
|
1997
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
1998
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
2068
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCatalogStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2069
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCatalogStore });
|
|
1999
2070
|
}
|
|
2000
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
2071
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCatalogStore, decorators: [{
|
|
2001
2072
|
type: Injectable
|
|
2002
2073
|
}], ctorParameters: () => [] });
|
|
2003
2074
|
|
|
@@ -2075,10 +2146,10 @@ class DpeLayoutService {
|
|
|
2075
2146
|
}
|
|
2076
2147
|
return positions;
|
|
2077
2148
|
}
|
|
2078
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
2079
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
2149
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeLayoutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2150
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeLayoutService });
|
|
2080
2151
|
}
|
|
2081
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
2152
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeLayoutService, decorators: [{
|
|
2082
2153
|
type: Injectable
|
|
2083
2154
|
}] });
|
|
2084
2155
|
|
|
@@ -2155,10 +2226,10 @@ class DpeMetadataStore {
|
|
|
2155
2226
|
next.set(tableName, state);
|
|
2156
2227
|
this._byName.set(next);
|
|
2157
2228
|
}
|
|
2158
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
2159
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
2229
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeMetadataStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2230
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeMetadataStore });
|
|
2160
2231
|
}
|
|
2161
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
2232
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeMetadataStore, decorators: [{
|
|
2162
2233
|
type: Injectable
|
|
2163
2234
|
}] });
|
|
2164
2235
|
|
|
@@ -2313,7 +2384,20 @@ class DpeValidationService {
|
|
|
2313
2384
|
hasResult = computed(() => this.store.validateResult() !== undefined, ...(ngDevMode ? [{ debugName: "hasResult" }] : []));
|
|
2314
2385
|
constructor() {
|
|
2315
2386
|
toObservable(this.store.definition)
|
|
2316
|
-
.pipe(
|
|
2387
|
+
.pipe(
|
|
2388
|
+
/*
|
|
2389
|
+
* **Non si valida il segnaposto.** Lo store nasce con `dpeEmptyDefinition('', '', 'Sqlite')`
|
|
2390
|
+
* e questo servizio si iscrive alla costruzione: se il documento vero arriva dopo la
|
|
2391
|
+
* finestra di debounce — un ospite che monta l'editor mentre `load(nome)` e' in volo, cioe'
|
|
2392
|
+
* il caso normale con una rete vera — la finestra si chiudeva sul segnaposto e l'editor
|
|
2393
|
+
* validava un documento che nessuno aveva fornito. La risposta era esatta e inutile:
|
|
2394
|
+
* `DPE_MODEL_REQUIRED_MISSING` su `name`, `label` e `dataSources` piu'
|
|
2395
|
+
* `DPE_GRAPH_NO_WRITEBACK` — quattro rilievi del segnaposto, che l'utente non puo'
|
|
2396
|
+
* correggere da qui e che sembrano riguardare la sua definizione appena creata.
|
|
2397
|
+
*
|
|
2398
|
+
* Il filtro sta **prima** del debounce: il segnaposto non deve nemmeno aprire la finestra.
|
|
2399
|
+
*/
|
|
2400
|
+
filter(() => this.store.hasDocument()), debounceTime(VALIDATE_DEBOUNCE_MS), tap(() => {
|
|
2317
2401
|
this._isValidating.set(true);
|
|
2318
2402
|
this._error.set(undefined);
|
|
2319
2403
|
}),
|
|
@@ -2440,10 +2524,10 @@ class DpeValidationService {
|
|
|
2440
2524
|
const message = error instanceof Error ? error.message : 'Errore inatteso dal backend.';
|
|
2441
2525
|
return new DpeApiError('Transport', message, error);
|
|
2442
2526
|
}
|
|
2443
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
2444
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
2527
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeValidationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2528
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeValidationService });
|
|
2445
2529
|
}
|
|
2446
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
2530
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeValidationService, decorators: [{
|
|
2447
2531
|
type: Injectable
|
|
2448
2532
|
}], ctorParameters: () => [] });
|
|
2449
2533
|
|
|
@@ -2488,8 +2572,8 @@ function dpeIsRectFullyVisible(target, view, margin = 0) {
|
|
|
2488
2572
|
class DpeNodeIconComponent {
|
|
2489
2573
|
collection = input.required(...(ngDevMode ? [{ debugName: "collection" }] : []));
|
|
2490
2574
|
paths = computed(() => dpeNodeIconPaths(this.collection()), ...(ngDevMode ? [{ debugName: "paths" }] : []));
|
|
2491
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
2492
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
2575
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2576
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeNodeIconComponent, isStandalone: true, selector: "dpe-node-icon", inputs: { collection: { classPropertyName: "collection", publicName: "collection", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
|
|
2493
2577
|
<svg
|
|
2494
2578
|
viewBox="0 0 24 24"
|
|
2495
2579
|
width="16"
|
|
@@ -2508,7 +2592,7 @@ class DpeNodeIconComponent {
|
|
|
2508
2592
|
</svg>
|
|
2509
2593
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2510
2594
|
}
|
|
2511
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
2595
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeIconComponent, decorators: [{
|
|
2512
2596
|
type: Component,
|
|
2513
2597
|
args: [{
|
|
2514
2598
|
selector: 'dpe-node-icon',
|
|
@@ -2978,10 +3062,10 @@ class DpeCanvasComponent {
|
|
|
2978
3062
|
isSelected(node) {
|
|
2979
3063
|
return this.store.selectedNodeNameSet().has(node.name);
|
|
2980
3064
|
}
|
|
2981
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
2982
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.27", type: DpeCanvasComponent, isStandalone: true, selector: "dpe-canvas", inputs: { isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeOpened: "nodeOpened", nodeDropped: "nodeDropped" }, providers: [provideFFlow(withA11y())], viewQueries: [{ propertyName: "canvas", first: true, predicate: FCanvasComponent, descendants: true, isSignal: true }, { propertyName: "flow", first: true, predicate: FFlowComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Gerarchia obbligatoria: f-flow > f-canvas > fNode / f-connection. I `@for` stanno\r\n direttamente dentro <f-canvas>: senza wrapper non serve `ngProjectAs`.\r\n-->\r\n<!--\r\n `dpe-flow`: classe nostra sul contenitore della libreria, e serve al **CSS**. Il tema di\r\n @foblex/flow stila la card con `.f-flow .f-node` (due classi): un nostro `.dpe-node` non la\r\n batte, e senza questa classe la card torna larga 120px e col testo centrato. Con `dpe-flow` i\r\n selettori del foglio diventano `dpe-canvas .dpe-flow .dpe-node`, che vince per specificita' e\r\n non per ordine di caricamento.\r\n-->\r\n<f-flow\r\n class=\"dpe-flow\"\r\n fDraggable\r\n (fCreateConnection)=\"onCreateConnection($event)\"\r\n (fReassignConnection)=\"onReassignConnection($event)\"\r\n (fMoveNodes)=\"onMoveNodes($event)\"\r\n (fSelectionChange)=\"onSelectionChange($event)\"\r\n (fDeleteSelected)=\"onDeleteSelected($event)\"\r\n (fCreateNode)=\"onCreateNode($event)\"\r\n (fNodesRendered)=\"onNodesRendered()\"\r\n>\r\n <f-canvas fZoom #canvas (fCanvasChange)=\"onCanvasChange()\">\r\n <f-background>\r\n <f-circle-pattern />\r\n </f-background>\r\n\r\n @for (edge of edges(); track edge.id) {\r\n <!--\r\n La classe porta lo **slot** di destinazione: la primaria e la secondaria di un join\r\n vanno distinte a vista, altrimenti l\u2019unico modo di sapere quale lato e\u2019 quale e\u2019 aprire\r\n l\u2019ispettore. I colori stanno nel CSS globale, non qui: i path SVG sono creati a runtime\r\n e non portano l\u2019attributo di scope.\r\n -->\r\n <f-connection\r\n [fConnectionId]=\"edge.id\"\r\n [fSourceId]=\"edge.sourceId\"\r\n [fTargetId]=\"edge.targetId\"\r\n fBehavior=\"floating\"\r\n fType=\"bezier\"\r\n [class]=\"'dpe-edge dpe-edge--' + edge.slot\"\r\n >\r\n <f-connection-marker-arrow [type]=\"markerEnd\" />\r\n </f-connection>\r\n }\r\n\r\n @for (node of nodes(); track node.id) {\r\n <!--\r\n Nessun `[style.*]` sul nodo: @foblex/flow riscrive l\u2019attributo `style` a ogni\r\n riposizionamento e lo cancellerebbe. La larghezza arriva da `node.widthClass`.\r\n -->\r\n <div\r\n fNode\r\n fDragHandle\r\n [fNodeId]=\"node.id\"\r\n [fNodePosition]=\"node.position\"\r\n [class]=\"\r\n 'dpe-node dpe-node--' + node.collection + ' ' + node.widthClass + ' ' + node.familyClass\r\n \"\r\n [class.dpe-node--selected]=\"isSelected(node)\"\r\n [class.dpe-node--error]=\"node.severity === 'Error'\"\r\n [class.dpe-node--warning]=\"node.severity === 'Warning'\"\r\n [class.dpe-node--not-compilable]=\"node.isNotCompilable\"\r\n [attr.aria-label]=\"node.categoryLabel + ' ' + node.label\"\r\n (dblclick)=\"onNodeDoubleClick(node.name)\"\r\n >\r\n <!--\r\n Le porte di ingresso stanno in fila sul bordo superiore, una per slot. Si renderizzano\r\n **sempre**: un connettore con `display: none` ha geometria 0x0 e l\u2019arco si attacca nel\r\n punto sbagliato. `fConnectorConnectableSide` e\u2019 dichiarato: senza, un arco che risale\r\n entrerebbe di fianco.\r\n -->\r\n @if (node.ports.length > 0) {\r\n <div class=\"dpe-node__ports\" [class.dpe-node__ports--labelled]=\"node.showsPortLabels\">\r\n @for (port of node.ports; track port.id) {\r\n <div class=\"dpe-port\">\r\n <div\r\n fConnector\r\n fConnectorType=\"target\"\r\n [fConnectorId]=\"port.id\"\r\n [fConnectorConnectableSide]=\"sides.TOP\"\r\n fConnectorMultiple=\"false\"\r\n class=\"dpe-connector dpe-connector--in\"\r\n [class.dpe-connector--broken]=\"port.isBroken\"\r\n [title]=\"port.label\"\r\n ></div>\r\n @if (node.showsPortLabels) {\r\n <span class=\"dpe-port__label\" [title]=\"port.label\">{{ port.label }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"dpe-node__head\">\r\n <!--\r\n La stessa pastiglia della palette: cio\u2019 che si trascina deve assomigliare a cio\u2019 che\r\n compare. La classe di famiglia porta i due token di colore.\r\n -->\r\n <span class=\"dpe-node__icon\">\r\n <dpe-node-icon [collection]=\"node.collection\" />\r\n </span>\r\n <div class=\"dpe-node__text\">\r\n <span class=\"dpe-node__title\" [title]=\"node.label\">{{ node.label }}</span>\r\n <span class=\"dpe-node__sub\">\r\n {{ node.categoryLabel }}\r\n @if (node.subtitle) {\r\n <span class=\"dpe-node__dot\">\u00B7</span>{{ node.subtitle }}\r\n }\r\n </span>\r\n </div>\r\n <!--\r\n `fDragBlocker` sui bottoni dentro un nodo: senza, il pointerdown diventa un\r\n trascinamento e aprire l\u2019ispettore sposta il nodo di qualche pixel.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-node__btn\"\r\n [attr.aria-label]=\"'Apri l\u2019ispettore di ' + node.label\"\r\n title=\"Apri l\u2019ispettore\"\r\n (click)=\"onEditClick($event, node.name)\"\r\n >\r\n \u270E\r\n </button>\r\n @if (isEditable() && isSelected(node)) {\r\n <!--\r\n Solo sul nodo selezionato: un comando distruttivo che compare sotto il puntatore\r\n mentre si attraversa il grafo si preme per sbaglio.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-node__btn dpe-node__btn--remove\"\r\n [attr.aria-label]=\"'Elimina ' + node.label\"\r\n title=\"Elimina (si annulla con \u21B6)\"\r\n (click)=\"onRemoveClick($event, node.name)\"\r\n >\r\n \u00D7\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"dpe-node__meta\">\r\n <span class=\"dpe-node__name\" [title]=\"'Nome tecnico: ' + node.name\">{{ node.name }}</span>\r\n @if (node.columnCount !== null) {\r\n <span class=\"dpe-badge\" [title]=\"'Colonne in uscita secondo il backend'\">\r\n {{ node.columnCount }} col.\r\n </span>\r\n }\r\n @if (node.isNotCompilable) {\r\n <!--\r\n Stato distinto dall\u2019errore: la definizione va bene, il compilatore non ci arriva\r\n (I10). Colore proprio, testo che non chiede di correggere niente.\r\n -->\r\n <span class=\"dpe-badge dpe-badge--not-compilable\" title=\"Valido, ma non compilabile: e\u2019 un limite nostro\">\r\n non compilabile\r\n </span>\r\n }\r\n @if (node.diagnosticCount > 0) {\r\n <span\r\n class=\"dpe-badge\"\r\n [class.dpe-badge--error]=\"node.severity === 'Error'\"\r\n [class.dpe-badge--warning]=\"node.severity === 'Warning'\"\r\n [class.dpe-badge--info]=\"node.severity === 'Info'\"\r\n [title]=\"node.diagnosticCount + ' rilievi dal backend'\"\r\n >\r\n {{ node.diagnosticCount }}\r\n </span>\r\n }\r\n @for (port of node.ports; track $index) {\r\n @if (port.isBroken) {\r\n <span class=\"dpe-badge dpe-badge--error\" [title]=\"'Riferimento non risolto: ' + port.sourceName\">\r\n \u26A0 {{ port.sourceName }}\r\n </span>\r\n }\r\n }\r\n </div>\r\n\r\n <!--\r\n L\u2019uscita e\u2019 una sola: lo schema prodotto e\u2019 uno. I sink non ne hanno, e la porta non\r\n si disegna affatto \u2014 qui non c\u2019e\u2019 niente da nascondere con `display: none`, il\r\n connettore semplicemente non esiste.\r\n -->\r\n @if (node.hasOutput) {\r\n <div class=\"dpe-node__out\">\r\n <div\r\n fConnector\r\n fConnectorType=\"source\"\r\n [fConnectorId]=\"node.outputPortId\"\r\n [fConnectorConnectableSide]=\"sides.BOTTOM\"\r\n class=\"dpe-connector dpe-connector--out\"\r\n title=\"Uscita\"\r\n ></div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <f-connection-for-create fBehavior=\"floating\" fType=\"bezier\" class=\"dpe-edge dpe-edge--creating\">\r\n <f-connection-marker-arrow [type]=\"markerEnd\" />\r\n </f-connection-for-create>\r\n\r\n <f-selection-area />\r\n </f-canvas>\r\n\r\n <!--\r\n Fuori da <f-canvas> come la minimappa: dentro, la trasformazione del canvas se lo\r\n porterebbe via insieme ai nodi.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-viewport-reset\"\r\n [class.dpe-viewport-reset--hidden]=\"!isFitCommandVisible()\"\r\n title=\"Rimetti il grafo interamente in vista\"\r\n (click)=\"resetViewport()\"\r\n >\r\n \u2922 Inquadra\r\n </button>\r\n\r\n <f-minimap [fMinSize]=\"1200\" class=\"dpe-minimap\" />\r\n</f-flow>\r\n", dependencies: [{ kind: "ngmodule", type: FFlowModule }, { kind: "component", type: i1.FFlowComponent, selector: "f-flow", inputs: ["fFlowId", "fCache"], outputs: ["fNodesRendered", "fFullRendered", "fLoaded"] }, { kind: "component", type: i1.FCanvasComponent, selector: "f-canvas", inputs: ["position", "scale", "debounceTime", "fLayers"], outputs: ["fCanvasChange"] }, { kind: "component", type: i1.FBackgroundComponent, selector: "f-background" }, { kind: "component", type: i1.FCirclePatternComponent, selector: "f-circle-pattern", inputs: ["id", "color", "radius"] }, { kind: "directive", type: i1.FZoomDirective, selector: "f-canvas[fZoom]", inputs: ["fZoom", "fWheelTrigger", "fDblClickTrigger", "fZoomMinimum", "fZoomMaximum", "fZoomStep", "fPinchStep", "fZoomDblClickStep"] }, { kind: "component", type: i1.FSelectionArea, selector: "f-selection-area", inputs: ["fTrigger"] }, { kind: "component", type: i1.FConnectionMarkerArrow, selector: "f-connection-marker-arrow", inputs: ["type"] }, { kind: "component", type: i1.FConnectionComponent, selector: "f-connection", inputs: ["fConnectionId", "fSourceId", "fTargetId", "fOutputId", "fInputId", "fRadius", "fOffset", "fBehavior", "fType", "fSelectionDisabled", "fReassignableStart", "fReassignDisabled", "fSourceSide", "fTargetSide", "fInputSide", "fOutputSide"], exportAs: ["fComponent"] }, { kind: "component", type: i1.FConnectionForCreateComponent, selector: "f-connection-for-create", inputs: ["fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "directive", type: i1.FConnectorDirective, selector: "[fConnector]", inputs: ["fConnectorId", "fConnectorType", "fConnectorDisabled", "fConnectorMultiple", "fConnectorCategory", "fConnectorConnectableSide", "fConnectorSelfConnectable", "fCanBeConnectedTo", "fConnectionFromOutlet"], exportAs: ["fConnector"] }, { kind: "component", type: i1.FMinimapComponent, selector: "f-minimap", inputs: ["fMinSize", "fNodeRenderLimit"], exportAs: ["fComponent"] }, { kind: "directive", type: i1.FNodeDirective, selector: "[fNode]", inputs: ["fNodeId", "fNodeParentId", "fNodePosition", "fNodeSize", "fNodeRotate", "fConnectOnNode", "fMinimapClass", "fNodeDraggingDisabled", "fNodeSelectionDisabled", "fIncludePadding", "fAutoExpandOnChildHit", "fAutoSizeToFitChildren"], outputs: ["fNodePositionChange", "fNodeSizeChange", "fNodeRotateChange"], exportAs: ["fComponent"] }, { kind: "directive", type: i1.FDragHandleDirective, selector: "[fDragHandle]" }, { kind: "directive", type: i1.FDragBlockerDirective, selector: "[fDragBlocker]" }, { kind: "directive", type: i1.FDraggableDirective, selector: "f-flow[fDraggable]", inputs: ["fDraggableDisabled", "fDropToGroup", "fMultiSelectTrigger", "fReassignConnectionTrigger", "fCreateConnectionTrigger", "fConnectionWaypointsTrigger", "fMoveControlPointTrigger", "fNodeResizeTrigger", "fNodeRotateTrigger", "fNodeMoveTrigger", "fCanvasMoveTrigger", "fExternalItemTrigger", "fEmitOnNodeIntersect", "vCellSize", "hCellSize", "fCellSizeWhileDragging"], outputs: ["fSelectionChange", "fDeleteSelected", "fNodeIntersectedWithConnections", "fNodeConnectionsIntersection", "fCreateNode", "fMoveNodes", "fReassignConnection", "fCreateConnection", "fConnectionWaypointsChanged", "fDropToGroup", "fDragStarted", "fDragEnded"], exportAs: ["fDraggable"] }, { kind: "component", type: DpeNodeIconComponent, selector: "dpe-node-icon", inputs: ["collection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3065
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCanvasComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3066
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeCanvasComponent, isStandalone: true, selector: "dpe-canvas", inputs: { isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeOpened: "nodeOpened", nodeDropped: "nodeDropped" }, providers: [provideFFlow(withA11y())], viewQueries: [{ propertyName: "canvas", first: true, predicate: FCanvasComponent, descendants: true, isSignal: true }, { propertyName: "flow", first: true, predicate: FFlowComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Gerarchia obbligatoria: f-flow > f-canvas > fNode / f-connection. I `@for` stanno\r\n direttamente dentro <f-canvas>: senza wrapper non serve `ngProjectAs`.\r\n-->\r\n<!--\r\n `dpe-flow`: classe nostra sul contenitore della libreria, e serve al **CSS**. Il tema di\r\n @foblex/flow stila la card con `.f-flow .f-node` (due classi): un nostro `.dpe-node` non la\r\n batte, e senza questa classe la card torna larga 120px e col testo centrato. Con `dpe-flow` i\r\n selettori del foglio diventano `dpe-canvas .dpe-flow .dpe-node`, che vince per specificita' e\r\n non per ordine di caricamento.\r\n-->\r\n<f-flow\r\n class=\"dpe-flow\"\r\n fDraggable\r\n (fCreateConnection)=\"onCreateConnection($event)\"\r\n (fReassignConnection)=\"onReassignConnection($event)\"\r\n (fMoveNodes)=\"onMoveNodes($event)\"\r\n (fSelectionChange)=\"onSelectionChange($event)\"\r\n (fDeleteSelected)=\"onDeleteSelected($event)\"\r\n (fCreateNode)=\"onCreateNode($event)\"\r\n (fNodesRendered)=\"onNodesRendered()\"\r\n>\r\n <f-canvas fZoom #canvas (fCanvasChange)=\"onCanvasChange()\">\r\n <f-background>\r\n <f-circle-pattern />\r\n </f-background>\r\n\r\n @for (edge of edges(); track edge.id) {\r\n <!--\r\n La classe porta lo **slot** di destinazione: la primaria e la secondaria di un join\r\n vanno distinte a vista, altrimenti l\u2019unico modo di sapere quale lato e\u2019 quale e\u2019 aprire\r\n l\u2019ispettore. I colori stanno nel CSS globale, non qui: i path SVG sono creati a runtime\r\n e non portano l\u2019attributo di scope.\r\n -->\r\n <f-connection\r\n [fConnectionId]=\"edge.id\"\r\n [fSourceId]=\"edge.sourceId\"\r\n [fTargetId]=\"edge.targetId\"\r\n fBehavior=\"floating\"\r\n fType=\"bezier\"\r\n [class]=\"'dpe-edge dpe-edge--' + edge.slot\"\r\n >\r\n <f-connection-marker-arrow [type]=\"markerEnd\" />\r\n </f-connection>\r\n }\r\n\r\n @for (node of nodes(); track node.id) {\r\n <!--\r\n Nessun `[style.*]` sul nodo: @foblex/flow riscrive l\u2019attributo `style` a ogni\r\n riposizionamento e lo cancellerebbe. La larghezza arriva da `node.widthClass`.\r\n -->\r\n <div\r\n fNode\r\n fDragHandle\r\n [fNodeId]=\"node.id\"\r\n [fNodePosition]=\"node.position\"\r\n [class]=\"\r\n 'dpe-node dpe-node--' + node.collection + ' ' + node.widthClass + ' ' + node.familyClass\r\n \"\r\n [class.dpe-node--selected]=\"isSelected(node)\"\r\n [class.dpe-node--error]=\"node.severity === 'Error'\"\r\n [class.dpe-node--warning]=\"node.severity === 'Warning'\"\r\n [class.dpe-node--not-compilable]=\"node.isNotCompilable\"\r\n [attr.aria-label]=\"node.categoryLabel + ' ' + node.label\"\r\n (dblclick)=\"onNodeDoubleClick(node.name)\"\r\n >\r\n <!--\r\n Le porte di ingresso stanno in fila sul bordo superiore, una per slot. Si renderizzano\r\n **sempre**: un connettore con `display: none` ha geometria 0x0 e l\u2019arco si attacca nel\r\n punto sbagliato. `fConnectorConnectableSide` e\u2019 dichiarato: senza, un arco che risale\r\n entrerebbe di fianco.\r\n -->\r\n @if (node.ports.length > 0) {\r\n <div class=\"dpe-node__ports\" [class.dpe-node__ports--labelled]=\"node.showsPortLabels\">\r\n @for (port of node.ports; track port.id) {\r\n <div class=\"dpe-port\">\r\n <div\r\n fConnector\r\n fConnectorType=\"target\"\r\n [fConnectorId]=\"port.id\"\r\n [fConnectorConnectableSide]=\"sides.TOP\"\r\n fConnectorMultiple=\"false\"\r\n class=\"dpe-connector dpe-connector--in\"\r\n [class.dpe-connector--broken]=\"port.isBroken\"\r\n [title]=\"port.label\"\r\n ></div>\r\n @if (node.showsPortLabels) {\r\n <span class=\"dpe-port__label\" [title]=\"port.label\">{{ port.label }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"dpe-node__head\">\r\n <!--\r\n La stessa pastiglia della palette: cio\u2019 che si trascina deve assomigliare a cio\u2019 che\r\n compare. La classe di famiglia porta i due token di colore.\r\n -->\r\n <span class=\"dpe-node__icon\">\r\n <dpe-node-icon [collection]=\"node.collection\" />\r\n </span>\r\n <div class=\"dpe-node__text\">\r\n <span class=\"dpe-node__title\" [title]=\"node.label\">{{ node.label }}</span>\r\n <span class=\"dpe-node__sub\">\r\n {{ node.categoryLabel }}\r\n @if (node.subtitle) {\r\n <span class=\"dpe-node__dot\">\u00B7</span>{{ node.subtitle }}\r\n }\r\n </span>\r\n </div>\r\n <!--\r\n `fDragBlocker` sui bottoni dentro un nodo: senza, il pointerdown diventa un\r\n trascinamento e aprire l\u2019ispettore sposta il nodo di qualche pixel.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-node__btn\"\r\n [attr.aria-label]=\"'Apri l\u2019ispettore di ' + node.label\"\r\n title=\"Apri l\u2019ispettore\"\r\n (click)=\"onEditClick($event, node.name)\"\r\n >\r\n \u270E\r\n </button>\r\n @if (isEditable() && isSelected(node)) {\r\n <!--\r\n Solo sul nodo selezionato: un comando distruttivo che compare sotto il puntatore\r\n mentre si attraversa il grafo si preme per sbaglio.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-node__btn dpe-node__btn--remove\"\r\n [attr.aria-label]=\"'Elimina ' + node.label\"\r\n title=\"Elimina (si annulla con \u21B6)\"\r\n (click)=\"onRemoveClick($event, node.name)\"\r\n >\r\n \u00D7\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"dpe-node__meta\">\r\n <span class=\"dpe-node__name\" [title]=\"'Nome tecnico: ' + node.name\">{{ node.name }}</span>\r\n @if (node.columnCount !== null) {\r\n <span class=\"dpe-badge\" [title]=\"'Colonne in uscita secondo il backend'\">\r\n {{ node.columnCount }} col.\r\n </span>\r\n }\r\n @if (node.isNotCompilable) {\r\n <!--\r\n Stato distinto dall\u2019errore: la definizione va bene, il compilatore non ci arriva\r\n (I10). Colore proprio, testo che non chiede di correggere niente.\r\n -->\r\n <span class=\"dpe-badge dpe-badge--not-compilable\" title=\"Valido, ma non compilabile: e\u2019 un limite nostro\">\r\n non compilabile\r\n </span>\r\n }\r\n @if (node.diagnosticCount > 0) {\r\n <span\r\n class=\"dpe-badge\"\r\n [class.dpe-badge--error]=\"node.severity === 'Error'\"\r\n [class.dpe-badge--warning]=\"node.severity === 'Warning'\"\r\n [class.dpe-badge--info]=\"node.severity === 'Info'\"\r\n [title]=\"node.diagnosticCount + ' rilievi dal backend'\"\r\n >\r\n {{ node.diagnosticCount }}\r\n </span>\r\n }\r\n @for (port of node.ports; track $index) {\r\n @if (port.isBroken) {\r\n <span class=\"dpe-badge dpe-badge--error\" [title]=\"'Riferimento non risolto: ' + port.sourceName\">\r\n \u26A0 {{ port.sourceName }}\r\n </span>\r\n }\r\n }\r\n </div>\r\n\r\n <!--\r\n L\u2019uscita e\u2019 una sola: lo schema prodotto e\u2019 uno. I sink non ne hanno, e la porta non\r\n si disegna affatto \u2014 qui non c\u2019e\u2019 niente da nascondere con `display: none`, il\r\n connettore semplicemente non esiste.\r\n -->\r\n @if (node.hasOutput) {\r\n <div class=\"dpe-node__out\">\r\n <div\r\n fConnector\r\n fConnectorType=\"source\"\r\n [fConnectorId]=\"node.outputPortId\"\r\n [fConnectorConnectableSide]=\"sides.BOTTOM\"\r\n class=\"dpe-connector dpe-connector--out\"\r\n title=\"Uscita\"\r\n ></div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <f-connection-for-create fBehavior=\"floating\" fType=\"bezier\" class=\"dpe-edge dpe-edge--creating\">\r\n <f-connection-marker-arrow [type]=\"markerEnd\" />\r\n </f-connection-for-create>\r\n\r\n <f-selection-area />\r\n </f-canvas>\r\n\r\n <!--\r\n Fuori da <f-canvas> come la minimappa: dentro, la trasformazione del canvas se lo\r\n porterebbe via insieme ai nodi.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-viewport-reset\"\r\n [class.dpe-viewport-reset--hidden]=\"!isFitCommandVisible()\"\r\n title=\"Rimetti il grafo interamente in vista\"\r\n (click)=\"resetViewport()\"\r\n >\r\n \u2922 Inquadra\r\n </button>\r\n\r\n <f-minimap [fMinSize]=\"1200\" class=\"dpe-minimap\" />\r\n</f-flow>\r\n", dependencies: [{ kind: "ngmodule", type: FFlowModule }, { kind: "component", type: i1.FFlowComponent, selector: "f-flow", inputs: ["fFlowId", "fCache"], outputs: ["fNodesRendered", "fFullRendered", "fLoaded"] }, { kind: "component", type: i1.FCanvasComponent, selector: "f-canvas", inputs: ["position", "scale", "debounceTime", "fLayers"], outputs: ["fCanvasChange"] }, { kind: "component", type: i1.FBackgroundComponent, selector: "f-background" }, { kind: "component", type: i1.FCirclePatternComponent, selector: "f-circle-pattern", inputs: ["id", "color", "radius"] }, { kind: "directive", type: i1.FZoomDirective, selector: "f-canvas[fZoom]", inputs: ["fZoom", "fWheelTrigger", "fDblClickTrigger", "fZoomMinimum", "fZoomMaximum", "fZoomStep", "fPinchStep", "fZoomDblClickStep"] }, { kind: "component", type: i1.FSelectionArea, selector: "f-selection-area", inputs: ["fTrigger"] }, { kind: "component", type: i1.FConnectionMarkerArrow, selector: "f-connection-marker-arrow", inputs: ["type"] }, { kind: "component", type: i1.FConnectionComponent, selector: "f-connection", inputs: ["fConnectionId", "fSourceId", "fTargetId", "fOutputId", "fInputId", "fRadius", "fOffset", "fBehavior", "fType", "fSelectionDisabled", "fReassignableStart", "fReassignDisabled", "fSourceSide", "fTargetSide", "fInputSide", "fOutputSide"], exportAs: ["fComponent"] }, { kind: "component", type: i1.FConnectionForCreateComponent, selector: "f-connection-for-create", inputs: ["fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "directive", type: i1.FConnectorDirective, selector: "[fConnector]", inputs: ["fConnectorId", "fConnectorType", "fConnectorDisabled", "fConnectorMultiple", "fConnectorCategory", "fConnectorConnectableSide", "fConnectorSelfConnectable", "fCanBeConnectedTo", "fConnectionFromOutlet"], exportAs: ["fConnector"] }, { kind: "component", type: i1.FMinimapComponent, selector: "f-minimap", inputs: ["fMinSize", "fNodeRenderLimit"], exportAs: ["fComponent"] }, { kind: "directive", type: i1.FNodeDirective, selector: "[fNode]", inputs: ["fNodeId", "fNodeParentId", "fNodePosition", "fNodeSize", "fNodeRotate", "fConnectOnNode", "fMinimapClass", "fNodeDraggingDisabled", "fNodeSelectionDisabled", "fIncludePadding", "fAutoExpandOnChildHit", "fAutoSizeToFitChildren"], outputs: ["fNodePositionChange", "fNodeSizeChange", "fNodeRotateChange"], exportAs: ["fComponent"] }, { kind: "directive", type: i1.FDragHandleDirective, selector: "[fDragHandle]" }, { kind: "directive", type: i1.FDragBlockerDirective, selector: "[fDragBlocker]" }, { kind: "directive", type: i1.FDraggableDirective, selector: "f-flow[fDraggable]", inputs: ["fDraggableDisabled", "fDropToGroup", "fMultiSelectTrigger", "fReassignConnectionTrigger", "fCreateConnectionTrigger", "fConnectionWaypointsTrigger", "fMoveControlPointTrigger", "fNodeResizeTrigger", "fNodeRotateTrigger", "fNodeMoveTrigger", "fCanvasMoveTrigger", "fExternalItemTrigger", "fEmitOnNodeIntersect", "vCellSize", "hCellSize", "fCellSizeWhileDragging"], outputs: ["fSelectionChange", "fDeleteSelected", "fNodeIntersectedWithConnections", "fNodeConnectionsIntersection", "fCreateNode", "fMoveNodes", "fReassignConnection", "fCreateConnection", "fConnectionWaypointsChanged", "fDropToGroup", "fDragStarted", "fDragEnded"], exportAs: ["fDraggable"] }, { kind: "component", type: DpeNodeIconComponent, selector: "dpe-node-icon", inputs: ["collection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2983
3067
|
}
|
|
2984
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
3068
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCanvasComponent, decorators: [{
|
|
2985
3069
|
type: Component,
|
|
2986
3070
|
args: [{ selector: 'dpe-canvas', standalone: true, imports: [FFlowModule, DpeNodeIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [provideFFlow(withA11y())], template: "<!--\r\n Gerarchia obbligatoria: f-flow > f-canvas > fNode / f-connection. I `@for` stanno\r\n direttamente dentro <f-canvas>: senza wrapper non serve `ngProjectAs`.\r\n-->\r\n<!--\r\n `dpe-flow`: classe nostra sul contenitore della libreria, e serve al **CSS**. Il tema di\r\n @foblex/flow stila la card con `.f-flow .f-node` (due classi): un nostro `.dpe-node` non la\r\n batte, e senza questa classe la card torna larga 120px e col testo centrato. Con `dpe-flow` i\r\n selettori del foglio diventano `dpe-canvas .dpe-flow .dpe-node`, che vince per specificita' e\r\n non per ordine di caricamento.\r\n-->\r\n<f-flow\r\n class=\"dpe-flow\"\r\n fDraggable\r\n (fCreateConnection)=\"onCreateConnection($event)\"\r\n (fReassignConnection)=\"onReassignConnection($event)\"\r\n (fMoveNodes)=\"onMoveNodes($event)\"\r\n (fSelectionChange)=\"onSelectionChange($event)\"\r\n (fDeleteSelected)=\"onDeleteSelected($event)\"\r\n (fCreateNode)=\"onCreateNode($event)\"\r\n (fNodesRendered)=\"onNodesRendered()\"\r\n>\r\n <f-canvas fZoom #canvas (fCanvasChange)=\"onCanvasChange()\">\r\n <f-background>\r\n <f-circle-pattern />\r\n </f-background>\r\n\r\n @for (edge of edges(); track edge.id) {\r\n <!--\r\n La classe porta lo **slot** di destinazione: la primaria e la secondaria di un join\r\n vanno distinte a vista, altrimenti l\u2019unico modo di sapere quale lato e\u2019 quale e\u2019 aprire\r\n l\u2019ispettore. I colori stanno nel CSS globale, non qui: i path SVG sono creati a runtime\r\n e non portano l\u2019attributo di scope.\r\n -->\r\n <f-connection\r\n [fConnectionId]=\"edge.id\"\r\n [fSourceId]=\"edge.sourceId\"\r\n [fTargetId]=\"edge.targetId\"\r\n fBehavior=\"floating\"\r\n fType=\"bezier\"\r\n [class]=\"'dpe-edge dpe-edge--' + edge.slot\"\r\n >\r\n <f-connection-marker-arrow [type]=\"markerEnd\" />\r\n </f-connection>\r\n }\r\n\r\n @for (node of nodes(); track node.id) {\r\n <!--\r\n Nessun `[style.*]` sul nodo: @foblex/flow riscrive l\u2019attributo `style` a ogni\r\n riposizionamento e lo cancellerebbe. La larghezza arriva da `node.widthClass`.\r\n -->\r\n <div\r\n fNode\r\n fDragHandle\r\n [fNodeId]=\"node.id\"\r\n [fNodePosition]=\"node.position\"\r\n [class]=\"\r\n 'dpe-node dpe-node--' + node.collection + ' ' + node.widthClass + ' ' + node.familyClass\r\n \"\r\n [class.dpe-node--selected]=\"isSelected(node)\"\r\n [class.dpe-node--error]=\"node.severity === 'Error'\"\r\n [class.dpe-node--warning]=\"node.severity === 'Warning'\"\r\n [class.dpe-node--not-compilable]=\"node.isNotCompilable\"\r\n [attr.aria-label]=\"node.categoryLabel + ' ' + node.label\"\r\n (dblclick)=\"onNodeDoubleClick(node.name)\"\r\n >\r\n <!--\r\n Le porte di ingresso stanno in fila sul bordo superiore, una per slot. Si renderizzano\r\n **sempre**: un connettore con `display: none` ha geometria 0x0 e l\u2019arco si attacca nel\r\n punto sbagliato. `fConnectorConnectableSide` e\u2019 dichiarato: senza, un arco che risale\r\n entrerebbe di fianco.\r\n -->\r\n @if (node.ports.length > 0) {\r\n <div class=\"dpe-node__ports\" [class.dpe-node__ports--labelled]=\"node.showsPortLabels\">\r\n @for (port of node.ports; track port.id) {\r\n <div class=\"dpe-port\">\r\n <div\r\n fConnector\r\n fConnectorType=\"target\"\r\n [fConnectorId]=\"port.id\"\r\n [fConnectorConnectableSide]=\"sides.TOP\"\r\n fConnectorMultiple=\"false\"\r\n class=\"dpe-connector dpe-connector--in\"\r\n [class.dpe-connector--broken]=\"port.isBroken\"\r\n [title]=\"port.label\"\r\n ></div>\r\n @if (node.showsPortLabels) {\r\n <span class=\"dpe-port__label\" [title]=\"port.label\">{{ port.label }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"dpe-node__head\">\r\n <!--\r\n La stessa pastiglia della palette: cio\u2019 che si trascina deve assomigliare a cio\u2019 che\r\n compare. La classe di famiglia porta i due token di colore.\r\n -->\r\n <span class=\"dpe-node__icon\">\r\n <dpe-node-icon [collection]=\"node.collection\" />\r\n </span>\r\n <div class=\"dpe-node__text\">\r\n <span class=\"dpe-node__title\" [title]=\"node.label\">{{ node.label }}</span>\r\n <span class=\"dpe-node__sub\">\r\n {{ node.categoryLabel }}\r\n @if (node.subtitle) {\r\n <span class=\"dpe-node__dot\">\u00B7</span>{{ node.subtitle }}\r\n }\r\n </span>\r\n </div>\r\n <!--\r\n `fDragBlocker` sui bottoni dentro un nodo: senza, il pointerdown diventa un\r\n trascinamento e aprire l\u2019ispettore sposta il nodo di qualche pixel.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-node__btn\"\r\n [attr.aria-label]=\"'Apri l\u2019ispettore di ' + node.label\"\r\n title=\"Apri l\u2019ispettore\"\r\n (click)=\"onEditClick($event, node.name)\"\r\n >\r\n \u270E\r\n </button>\r\n @if (isEditable() && isSelected(node)) {\r\n <!--\r\n Solo sul nodo selezionato: un comando distruttivo che compare sotto il puntatore\r\n mentre si attraversa il grafo si preme per sbaglio.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-node__btn dpe-node__btn--remove\"\r\n [attr.aria-label]=\"'Elimina ' + node.label\"\r\n title=\"Elimina (si annulla con \u21B6)\"\r\n (click)=\"onRemoveClick($event, node.name)\"\r\n >\r\n \u00D7\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"dpe-node__meta\">\r\n <span class=\"dpe-node__name\" [title]=\"'Nome tecnico: ' + node.name\">{{ node.name }}</span>\r\n @if (node.columnCount !== null) {\r\n <span class=\"dpe-badge\" [title]=\"'Colonne in uscita secondo il backend'\">\r\n {{ node.columnCount }} col.\r\n </span>\r\n }\r\n @if (node.isNotCompilable) {\r\n <!--\r\n Stato distinto dall\u2019errore: la definizione va bene, il compilatore non ci arriva\r\n (I10). Colore proprio, testo che non chiede di correggere niente.\r\n -->\r\n <span class=\"dpe-badge dpe-badge--not-compilable\" title=\"Valido, ma non compilabile: e\u2019 un limite nostro\">\r\n non compilabile\r\n </span>\r\n }\r\n @if (node.diagnosticCount > 0) {\r\n <span\r\n class=\"dpe-badge\"\r\n [class.dpe-badge--error]=\"node.severity === 'Error'\"\r\n [class.dpe-badge--warning]=\"node.severity === 'Warning'\"\r\n [class.dpe-badge--info]=\"node.severity === 'Info'\"\r\n [title]=\"node.diagnosticCount + ' rilievi dal backend'\"\r\n >\r\n {{ node.diagnosticCount }}\r\n </span>\r\n }\r\n @for (port of node.ports; track $index) {\r\n @if (port.isBroken) {\r\n <span class=\"dpe-badge dpe-badge--error\" [title]=\"'Riferimento non risolto: ' + port.sourceName\">\r\n \u26A0 {{ port.sourceName }}\r\n </span>\r\n }\r\n }\r\n </div>\r\n\r\n <!--\r\n L\u2019uscita e\u2019 una sola: lo schema prodotto e\u2019 uno. I sink non ne hanno, e la porta non\r\n si disegna affatto \u2014 qui non c\u2019e\u2019 niente da nascondere con `display: none`, il\r\n connettore semplicemente non esiste.\r\n -->\r\n @if (node.hasOutput) {\r\n <div class=\"dpe-node__out\">\r\n <div\r\n fConnector\r\n fConnectorType=\"source\"\r\n [fConnectorId]=\"node.outputPortId\"\r\n [fConnectorConnectableSide]=\"sides.BOTTOM\"\r\n class=\"dpe-connector dpe-connector--out\"\r\n title=\"Uscita\"\r\n ></div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <f-connection-for-create fBehavior=\"floating\" fType=\"bezier\" class=\"dpe-edge dpe-edge--creating\">\r\n <f-connection-marker-arrow [type]=\"markerEnd\" />\r\n </f-connection-for-create>\r\n\r\n <f-selection-area />\r\n </f-canvas>\r\n\r\n <!--\r\n Fuori da <f-canvas> come la minimappa: dentro, la trasformazione del canvas se lo\r\n porterebbe via insieme ai nodi.\r\n -->\r\n <button\r\n type=\"button\"\r\n fDragBlocker\r\n class=\"dpe-viewport-reset\"\r\n [class.dpe-viewport-reset--hidden]=\"!isFitCommandVisible()\"\r\n title=\"Rimetti il grafo interamente in vista\"\r\n (click)=\"resetViewport()\"\r\n >\r\n \u2922 Inquadra\r\n </button>\r\n\r\n <f-minimap [fMinSize]=\"1200\" class=\"dpe-minimap\" />\r\n</f-flow>\r\n" }]
|
|
2987
3071
|
}], ctorParameters: () => [], propDecorators: { isEditable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditable", required: false }] }], nodeOpened: [{ type: i0.Output, args: ["nodeOpened"] }], nodeDropped: [{ type: i0.Output, args: ["nodeDropped"] }], canvas: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FCanvasComponent), { isSignal: true }] }], flow: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FFlowComponent), { isSignal: true }] }] } });
|
|
@@ -3056,8 +3140,8 @@ class DpeDiagnosticsPanelComponent {
|
|
|
3056
3140
|
}
|
|
3057
3141
|
this.navigate.emit({ nodeName: row.nodeName, field: row.field });
|
|
3058
3142
|
}
|
|
3059
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
3060
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
3143
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeDiagnosticsPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3144
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeDiagnosticsPanelComponent, isStandalone: true, selector: "dpe-diagnostics-panel", outputs: { navigate: "navigate" }, ngImport: i0, template: `
|
|
3061
3145
|
<div class="dpe-diag__head">
|
|
3062
3146
|
<strong>Diagnostiche</strong>
|
|
3063
3147
|
<span class="dpe-diag__count">
|
|
@@ -3117,7 +3201,7 @@ class DpeDiagnosticsPanelComponent {
|
|
|
3117
3201
|
}
|
|
3118
3202
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3119
3203
|
}
|
|
3120
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
3204
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeDiagnosticsPanelComponent, decorators: [{
|
|
3121
3205
|
type: Component,
|
|
3122
3206
|
args: [{
|
|
3123
3207
|
selector: 'dpe-diagnostics-panel',
|
|
@@ -3185,6 +3269,165 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
3185
3269
|
}]
|
|
3186
3270
|
}], propDecorators: { navigate: [{ type: i0.Output, args: ["navigate"] }] } });
|
|
3187
3271
|
|
|
3272
|
+
/**
|
|
3273
|
+
* I **fatti dal backend** su un nodo: schema in uscita e rilievi che lo riguardano.
|
|
3274
|
+
*
|
|
3275
|
+
* Sono in un componente a se' perche' nella dialog di modifica (ADR 0026) non stanno dove stanno
|
|
3276
|
+
* i campi: i campi prendono la colonna larga, questi la colonna stretta di destra. Metterli **di
|
|
3277
|
+
* fianco** e non sopra il form evita in anticipo il muro di avvisi che spinge il primo campo
|
|
3278
|
+
* fuori dallo schermo — con i rilievi in colonna il muro non si forma, quindi si mostrano
|
|
3279
|
+
* **tutti** (**I6**: l'elenco della validazione e' esaustivo, e troncarlo sarebbe mentire).
|
|
3280
|
+
*
|
|
3281
|
+
* In testa sta lo stato **valido ma non compilabile** (**I10**), perche' e' il fatto che spiega gli
|
|
3282
|
+
* altri due: senza di esso una colonna che elenca i rilievi tace proprio sul motivo per cui da
|
|
3283
|
+
* questo nodo non uscira' nessun SQL. «Non compilabile» e «non valido» sono due significati
|
|
3284
|
+
* distinti, e l'editor li tiene distinti per decisione (ADR 0011).
|
|
3285
|
+
*
|
|
3286
|
+
* Non calcola niente. Lo schema arriva da `validate` (**I4**: la propagazione e' del backend) e i
|
|
3287
|
+
* rilievi arrivano gia' raggruppati per nodo: qui si legge e si rende.
|
|
3288
|
+
*/
|
|
3289
|
+
class DpeNodeFactsComponent {
|
|
3290
|
+
store = inject(DpeDocumentStore);
|
|
3291
|
+
/**
|
|
3292
|
+
* Il nodo di cui si mostrano i fatti. Arriva per input e non dalla selezione: chi monta questo
|
|
3293
|
+
* componente sa quale nodo sta guardando, e leggere qui la selezione lo farebbe cambiare
|
|
3294
|
+
* bersaglio sotto la dialog che lo contiene.
|
|
3295
|
+
*/
|
|
3296
|
+
nodeName = input.required(...(ngDevMode ? [{ debugName: "nodeName" }] : []));
|
|
3297
|
+
/**
|
|
3298
|
+
* Il nodo e' valido ma **non compilabile** (**I10**). Due rami, ed e' la **stessa espressione**
|
|
3299
|
+
* che `DpeNodeInspectorBase.isNotCompilable` usa gia': il codice diagnostico
|
|
3300
|
+
* `DPE_NODE_NOT_COMPILABLE` raggruppato per nodo, **oppure** lo schema che dichiara
|
|
3301
|
+
* `isCompilable: false`. Servono entrambi perche' il backend puo' dirlo per due vie — un rilievo
|
|
3302
|
+
* sul nodo, o la riga di schema — e riconoscerne una sola vorrebbe dire tacere nell'altro caso.
|
|
3303
|
+
*
|
|
3304
|
+
* Qui non si giudica niente: la decisione e' del compilatore, questa e' la sua risposta.
|
|
3305
|
+
*/
|
|
3306
|
+
isNotCompilable = computed(() => (this.store.diagnosticsByNode().get(this.nodeName())?.isNotCompilable ?? false) ||
|
|
3307
|
+
this.store.schemaByNode().get(this.nodeName())?.isCompilable === false, ...(ngDevMode ? [{ debugName: "isNotCompilable" }] : []));
|
|
3308
|
+
columns = computed(() => this.store.schemaByNode().get(this.nodeName())?.columns ?? [], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
3309
|
+
diagnostics = computed(() => this.store.diagnosticsByNode().get(this.nodeName())?.diagnostics ?? [], ...(ngDevMode ? [{ debugName: "diagnostics" }] : []));
|
|
3310
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeFactsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3311
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeNodeFactsComponent, isStandalone: true, selector: "dpe-node-facts", inputs: { nodeName: { classPropertyName: "nodeName", publicName: "nodeName", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
|
|
3312
|
+
@if (isNotCompilable()) {
|
|
3313
|
+
<!--
|
|
3314
|
+
Tono deliberatamente **non** da errore: colore proprio (ne’ rosso ne’ giallo) e le stesse
|
|
3315
|
+
parole degli ispettori di Forecast e CustomNode, perche’ e’ lo stesso fatto detto nello
|
|
3316
|
+
stesso linguaggio. Chiedere di correggere qualcosa qui sarebbe una bugia.
|
|
3317
|
+
-->
|
|
3318
|
+
<p class="dpe-note dpe-note--not-compilable">
|
|
3319
|
+
<span class="dpe-badge dpe-badge--not-compilable">non compilabile</span>
|
|
3320
|
+
Il nodo e’ <strong>valido</strong>: non c’e’ niente da correggere. Il compilatore non lo
|
|
3321
|
+
traduce in questa versione, quindi per questo nodo
|
|
3322
|
+
<strong>non verra’ generato SQL</strong>.
|
|
3323
|
+
</p>
|
|
3324
|
+
}
|
|
3325
|
+
|
|
3326
|
+
<section class="dpe-section">
|
|
3327
|
+
<h4 class="dpe-section__title">Schema in uscita</h4>
|
|
3328
|
+
@if (columns().length === 0) {
|
|
3329
|
+
<p class="dpe-empty">
|
|
3330
|
+
Nessuna colonna: il backend non ha (ancora) propagato uno schema per questo nodo.
|
|
3331
|
+
</p>
|
|
3332
|
+
} @else {
|
|
3333
|
+
<div class="dpe-columns">
|
|
3334
|
+
@for (column of columns(); track $index) {
|
|
3335
|
+
<span
|
|
3336
|
+
class="dpe-column"
|
|
3337
|
+
[class.dpe-column--nullable]="column.isNullable"
|
|
3338
|
+
[title]="column.type.kind + (column.isNullable ? ' · nullabile' : ' · non nulla')"
|
|
3339
|
+
>
|
|
3340
|
+
{{ column.name }}
|
|
3341
|
+
</span>
|
|
3342
|
+
}
|
|
3343
|
+
</div>
|
|
3344
|
+
<p class="dpe-field__hint">
|
|
3345
|
+
Tratteggiate le colonne nullabili. Lo schema arriva da <code>validate</code>: non lo
|
|
3346
|
+
calcoliamo qui.
|
|
3347
|
+
</p>
|
|
3348
|
+
}
|
|
3349
|
+
</section>
|
|
3350
|
+
|
|
3351
|
+
@if (diagnostics().length > 0) {
|
|
3352
|
+
<section class="dpe-section">
|
|
3353
|
+
<h4 class="dpe-section__title">Rilievi su questo nodo</h4>
|
|
3354
|
+
@for (diagnostic of diagnostics(); track $index) {
|
|
3355
|
+
<p
|
|
3356
|
+
class="dpe-field__issue"
|
|
3357
|
+
[class.dpe-field__issue--warning]="diagnostic.severity === 'Warning'"
|
|
3358
|
+
[class.dpe-field__issue--info]="diagnostic.severity === 'Info'"
|
|
3359
|
+
>
|
|
3360
|
+
<code>{{ diagnostic.code }}</code> — {{ diagnostic.message }}
|
|
3361
|
+
</p>
|
|
3362
|
+
}
|
|
3363
|
+
</section>
|
|
3364
|
+
}
|
|
3365
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3366
|
+
}
|
|
3367
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeFactsComponent, decorators: [{
|
|
3368
|
+
type: Component,
|
|
3369
|
+
args: [{
|
|
3370
|
+
selector: 'dpe-node-facts',
|
|
3371
|
+
standalone: true,
|
|
3372
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3373
|
+
template: `
|
|
3374
|
+
@if (isNotCompilable()) {
|
|
3375
|
+
<!--
|
|
3376
|
+
Tono deliberatamente **non** da errore: colore proprio (ne’ rosso ne’ giallo) e le stesse
|
|
3377
|
+
parole degli ispettori di Forecast e CustomNode, perche’ e’ lo stesso fatto detto nello
|
|
3378
|
+
stesso linguaggio. Chiedere di correggere qualcosa qui sarebbe una bugia.
|
|
3379
|
+
-->
|
|
3380
|
+
<p class="dpe-note dpe-note--not-compilable">
|
|
3381
|
+
<span class="dpe-badge dpe-badge--not-compilable">non compilabile</span>
|
|
3382
|
+
Il nodo e’ <strong>valido</strong>: non c’e’ niente da correggere. Il compilatore non lo
|
|
3383
|
+
traduce in questa versione, quindi per questo nodo
|
|
3384
|
+
<strong>non verra’ generato SQL</strong>.
|
|
3385
|
+
</p>
|
|
3386
|
+
}
|
|
3387
|
+
|
|
3388
|
+
<section class="dpe-section">
|
|
3389
|
+
<h4 class="dpe-section__title">Schema in uscita</h4>
|
|
3390
|
+
@if (columns().length === 0) {
|
|
3391
|
+
<p class="dpe-empty">
|
|
3392
|
+
Nessuna colonna: il backend non ha (ancora) propagato uno schema per questo nodo.
|
|
3393
|
+
</p>
|
|
3394
|
+
} @else {
|
|
3395
|
+
<div class="dpe-columns">
|
|
3396
|
+
@for (column of columns(); track $index) {
|
|
3397
|
+
<span
|
|
3398
|
+
class="dpe-column"
|
|
3399
|
+
[class.dpe-column--nullable]="column.isNullable"
|
|
3400
|
+
[title]="column.type.kind + (column.isNullable ? ' · nullabile' : ' · non nulla')"
|
|
3401
|
+
>
|
|
3402
|
+
{{ column.name }}
|
|
3403
|
+
</span>
|
|
3404
|
+
}
|
|
3405
|
+
</div>
|
|
3406
|
+
<p class="dpe-field__hint">
|
|
3407
|
+
Tratteggiate le colonne nullabili. Lo schema arriva da <code>validate</code>: non lo
|
|
3408
|
+
calcoliamo qui.
|
|
3409
|
+
</p>
|
|
3410
|
+
}
|
|
3411
|
+
</section>
|
|
3412
|
+
|
|
3413
|
+
@if (diagnostics().length > 0) {
|
|
3414
|
+
<section class="dpe-section">
|
|
3415
|
+
<h4 class="dpe-section__title">Rilievi su questo nodo</h4>
|
|
3416
|
+
@for (diagnostic of diagnostics(); track $index) {
|
|
3417
|
+
<p
|
|
3418
|
+
class="dpe-field__issue"
|
|
3419
|
+
[class.dpe-field__issue--warning]="diagnostic.severity === 'Warning'"
|
|
3420
|
+
[class.dpe-field__issue--info]="diagnostic.severity === 'Info'"
|
|
3421
|
+
>
|
|
3422
|
+
<code>{{ diagnostic.code }}</code> — {{ diagnostic.message }}
|
|
3423
|
+
</p>
|
|
3424
|
+
}
|
|
3425
|
+
</section>
|
|
3426
|
+
}
|
|
3427
|
+
`,
|
|
3428
|
+
}]
|
|
3429
|
+
}], propDecorators: { nodeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeName", required: true }] }] } });
|
|
3430
|
+
|
|
3188
3431
|
/**
|
|
3189
3432
|
* `[dpeValue]` su un `<select>`.
|
|
3190
3433
|
*
|
|
@@ -3209,10 +3452,10 @@ class DpeSelectValueDirective {
|
|
|
3209
3452
|
select.value = normalized;
|
|
3210
3453
|
}
|
|
3211
3454
|
}
|
|
3212
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
3213
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.
|
|
3455
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeSelectValueDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3456
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.31", type: DpeSelectValueDirective, isStandalone: true, selector: "select[dpeValue]", inputs: { dpeValue: { classPropertyName: "dpeValue", publicName: "dpeValue", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
3214
3457
|
}
|
|
3215
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
3458
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeSelectValueDirective, decorators: [{
|
|
3216
3459
|
type: Directive,
|
|
3217
3460
|
args: [{
|
|
3218
3461
|
selector: 'select[dpeValue]',
|
|
@@ -3318,10 +3561,10 @@ class DpeNodeInspectorBase {
|
|
|
3318
3561
|
checkedOf(event) {
|
|
3319
3562
|
return event.target.checked;
|
|
3320
3563
|
}
|
|
3321
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
3322
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.
|
|
3564
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeInspectorBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3565
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.31", type: DpeNodeInspectorBase, isStandalone: true, inputs: { nodeName: { classPropertyName: "nodeName", publicName: "nodeName", isSignal: true, isRequired: true, transformFunction: null }, node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
|
|
3323
3566
|
}
|
|
3324
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
3567
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeInspectorBase, decorators: [{
|
|
3325
3568
|
type: Directive
|
|
3326
3569
|
}], propDecorators: { nodeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeName", required: true }] }], node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }] } });
|
|
3327
3570
|
|
|
@@ -3377,8 +3620,8 @@ class DpeAggregateInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3377
3620
|
fields: this.fields().map((field, position) => position === index ? { ...field, ...patch } : field),
|
|
3378
3621
|
});
|
|
3379
3622
|
}
|
|
3380
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
3381
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
3623
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeAggregateInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3624
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeAggregateInspectorComponent, isStandalone: true, selector: "dpe-aggregate-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
3382
3625
|
<div class="dpe-form">
|
|
3383
3626
|
<div class="dpe-field">
|
|
3384
3627
|
<label class="dpe-field__label" for="agg-group">Raggruppa per</label>
|
|
@@ -3475,7 +3718,7 @@ class DpeAggregateInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3475
3718
|
</div>
|
|
3476
3719
|
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3477
3720
|
}
|
|
3478
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
3721
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeAggregateInspectorComponent, decorators: [{
|
|
3479
3722
|
type: Component,
|
|
3480
3723
|
args: [{
|
|
3481
3724
|
selector: 'dpe-aggregate-inspector',
|
|
@@ -3602,8 +3845,8 @@ class DpeAppendInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3602
3845
|
removeSource(index) {
|
|
3603
3846
|
this.patch({ sources: this.sources().filter((_, position) => position !== index) });
|
|
3604
3847
|
}
|
|
3605
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
3606
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
3848
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeAppendInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3849
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeAppendInspectorComponent, isStandalone: true, selector: "dpe-append-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
3607
3850
|
<div class="dpe-form">
|
|
3608
3851
|
<label class="dpe-check">
|
|
3609
3852
|
<input
|
|
@@ -3648,7 +3891,7 @@ class DpeAppendInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3648
3891
|
</div>
|
|
3649
3892
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3650
3893
|
}
|
|
3651
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
3894
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeAppendInspectorComponent, decorators: [{
|
|
3652
3895
|
type: Component,
|
|
3653
3896
|
args: [{
|
|
3654
3897
|
selector: 'dpe-append-inspector',
|
|
@@ -3729,8 +3972,8 @@ class DpeAtomicWritebackInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3729
3972
|
relationships: this.relationships().map((relationship, position) => position === index ? { ...relationship, ...patch } : relationship),
|
|
3730
3973
|
});
|
|
3731
3974
|
}
|
|
3732
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
3733
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
3975
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeAtomicWritebackInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3976
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeAtomicWritebackInspectorComponent, isStandalone: true, selector: "dpe-atomic-writeback-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
3734
3977
|
<div class="dpe-form">
|
|
3735
3978
|
<p class="dpe-note">
|
|
3736
3979
|
La libreria non apre transazioni: questo gruppo <strong>dichiara</strong> che le scritture
|
|
@@ -3841,7 +4084,7 @@ class DpeAtomicWritebackInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3841
4084
|
</div>
|
|
3842
4085
|
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3843
4086
|
}
|
|
3844
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
4087
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeAtomicWritebackInspectorComponent, decorators: [{
|
|
3845
4088
|
type: Component,
|
|
3846
4089
|
args: [{
|
|
3847
4090
|
selector: 'dpe-atomic-writeback-inspector',
|
|
@@ -4013,8 +4256,8 @@ class DpeColumnTypeEditorComponent {
|
|
|
4013
4256
|
text(event) {
|
|
4014
4257
|
return event.target.value;
|
|
4015
4258
|
}
|
|
4016
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
4017
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
4259
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeColumnTypeEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4260
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeColumnTypeEditorComponent, isStandalone: true, selector: "dpe-column-type-editor", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
|
|
4018
4261
|
<div class="dpe-row">
|
|
4019
4262
|
<div class="dpe-field">
|
|
4020
4263
|
<label class="dpe-field__label" [attr.for]="controlId() + '-kind'">Tipo</label>
|
|
@@ -4076,7 +4319,7 @@ class DpeColumnTypeEditorComponent {
|
|
|
4076
4319
|
}
|
|
4077
4320
|
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4078
4321
|
}
|
|
4079
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
4322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeColumnTypeEditorComponent, decorators: [{
|
|
4080
4323
|
type: Component,
|
|
4081
4324
|
args: [{
|
|
4082
4325
|
selector: 'dpe-column-type-editor',
|
|
@@ -4193,8 +4436,8 @@ class DpeCustomNodeInspectorComponent extends DpeNodeInspectorBase {
|
|
|
4193
4436
|
outputFields: this.outputFields().map((field, position) => position === index ? { ...field, ...patch } : field),
|
|
4194
4437
|
});
|
|
4195
4438
|
}
|
|
4196
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
4197
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
4439
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCustomNodeInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
4440
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeCustomNodeInspectorComponent, isStandalone: true, selector: "dpe-custom-node-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
4198
4441
|
<div class="dpe-form">
|
|
4199
4442
|
<p class="dpe-note dpe-note--not-compilable">
|
|
4200
4443
|
Nodo modellato per intero ma <strong>non traducibile in SQL</strong> nella versione 1.
|
|
@@ -4314,7 +4557,7 @@ class DpeCustomNodeInspectorComponent extends DpeNodeInspectorBase {
|
|
|
4314
4557
|
</div>
|
|
4315
4558
|
`, isInline: true, dependencies: [{ kind: "component", type: DpeColumnTypeEditorComponent, selector: "dpe-column-type-editor", inputs: ["value", "controlId"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4316
4559
|
}
|
|
4317
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
4560
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCustomNodeInspectorComponent, decorators: [{
|
|
4318
4561
|
type: Component,
|
|
4319
4562
|
args: [{
|
|
4320
4563
|
selector: 'dpe-custom-node-inspector',
|
|
@@ -4523,8 +4766,8 @@ class DpeDataSourceInspectorComponent extends DpeNodeInspectorBase {
|
|
|
4523
4766
|
csvOptions: { ...current, ...patch },
|
|
4524
4767
|
});
|
|
4525
4768
|
}
|
|
4526
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
4527
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
4769
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeDataSourceInspectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4770
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeDataSourceInspectorComponent, isStandalone: true, selector: "dpe-data-source-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
4528
4771
|
<div class="dpe-form">
|
|
4529
4772
|
<div class="dpe-field">
|
|
4530
4773
|
<label class="dpe-field__label" for="ds-kind">Tipo di sorgente</label>
|
|
@@ -4690,7 +4933,7 @@ class DpeDataSourceInspectorComponent extends DpeNodeInspectorBase {
|
|
|
4690
4933
|
</div>
|
|
4691
4934
|
`, isInline: true, dependencies: [{ kind: "component", type: DpeColumnTypeEditorComponent, selector: "dpe-column-type-editor", inputs: ["value", "controlId"], outputs: ["valueChange"] }, { kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4692
4935
|
}
|
|
4693
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
4936
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeDataSourceInspectorComponent, decorators: [{
|
|
4694
4937
|
type: Component,
|
|
4695
4938
|
args: [{
|
|
4696
4939
|
selector: 'dpe-data-source-inspector',
|
|
@@ -4937,8 +5180,8 @@ class DpeFilterInspectorComponent extends DpeNodeInspectorBase {
|
|
|
4937
5180
|
value: name === '' ? this.criteria()[index]?.value : undefined,
|
|
4938
5181
|
});
|
|
4939
5182
|
}
|
|
4940
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
4941
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
5183
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeFilterInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
5184
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeFilterInspectorComponent, isStandalone: true, selector: "dpe-filter-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
4942
5185
|
<div class="dpe-form">
|
|
4943
5186
|
<label class="dpe-check">
|
|
4944
5187
|
<input
|
|
@@ -5093,7 +5336,7 @@ class DpeFilterInspectorComponent extends DpeNodeInspectorBase {
|
|
|
5093
5336
|
</div>
|
|
5094
5337
|
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5095
5338
|
}
|
|
5096
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
5339
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeFilterInspectorComponent, decorators: [{
|
|
5097
5340
|
type: Component,
|
|
5098
5341
|
args: [{
|
|
5099
5342
|
selector: 'dpe-filter-inspector',
|
|
@@ -5333,8 +5576,8 @@ class DpeForecastInspectorComponent extends DpeNodeInspectorBase {
|
|
|
5333
5576
|
groupFields: this.groupFields().map((group, position) => position === index ? { ...group, ...patch } : group),
|
|
5334
5577
|
});
|
|
5335
5578
|
}
|
|
5336
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
5337
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
5579
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeForecastInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
5580
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeForecastInspectorComponent, isStandalone: true, selector: "dpe-forecast-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
5338
5581
|
<div class="dpe-form">
|
|
5339
5582
|
<p class="dpe-note dpe-note--not-compilable">
|
|
5340
5583
|
Nodo modellato per intero ma <strong>non traducibile in SQL</strong> nella versione 1:
|
|
@@ -5526,7 +5769,7 @@ class DpeForecastInspectorComponent extends DpeNodeInspectorBase {
|
|
|
5526
5769
|
</div>
|
|
5527
5770
|
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5528
5771
|
}
|
|
5529
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
5772
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeForecastInspectorComponent, decorators: [{
|
|
5530
5773
|
type: Component,
|
|
5531
5774
|
args: [{
|
|
5532
5775
|
selector: 'dpe-forecast-inspector',
|
|
@@ -5763,8 +6006,8 @@ class DpeHierarchyPathInspectorComponent extends DpeNodeInspectorBase {
|
|
|
5763
6006
|
aggregateFields: this.fields().map((field, position) => position === index ? { ...field, ...patch } : field),
|
|
5764
6007
|
});
|
|
5765
6008
|
}
|
|
5766
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
5767
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
6009
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeHierarchyPathInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
6010
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeHierarchyPathInspectorComponent, isStandalone: true, selector: "dpe-hierarchy-path-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
5768
6011
|
<div class="dpe-form">
|
|
5769
6012
|
<p class="dpe-note">
|
|
5770
6013
|
Richiede le CTE ricorsive del dialetto di destinazione: se il dialetto scelto non le
|
|
@@ -5910,7 +6153,7 @@ class DpeHierarchyPathInspectorComponent extends DpeNodeInspectorBase {
|
|
|
5910
6153
|
</div>
|
|
5911
6154
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5912
6155
|
}
|
|
5913
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
6156
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeHierarchyPathInspectorComponent, decorators: [{
|
|
5914
6157
|
type: Component,
|
|
5915
6158
|
args: [{
|
|
5916
6159
|
selector: 'dpe-hierarchy-path-inspector',
|
|
@@ -6117,8 +6360,8 @@ class DpeJoinInspectorComponent extends DpeNodeInspectorBase {
|
|
|
6117
6360
|
fields: this.fields().map((field, position) => position === index ? { ...field, ...patch } : field),
|
|
6118
6361
|
});
|
|
6119
6362
|
}
|
|
6120
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
6121
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
6363
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeJoinInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
6364
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeJoinInspectorComponent, isStandalone: true, selector: "dpe-join-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
6122
6365
|
<div class="dpe-form">
|
|
6123
6366
|
<div class="dpe-field">
|
|
6124
6367
|
<label class="dpe-field__label" for="join-kind">Tipo di join</label>
|
|
@@ -6308,7 +6551,7 @@ class DpeJoinInspectorComponent extends DpeNodeInspectorBase {
|
|
|
6308
6551
|
</div>
|
|
6309
6552
|
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6310
6553
|
}
|
|
6311
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
6554
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeJoinInspectorComponent, decorators: [{
|
|
6312
6555
|
type: Component,
|
|
6313
6556
|
args: [{
|
|
6314
6557
|
selector: 'dpe-join-inspector',
|
|
@@ -6546,8 +6789,8 @@ class DpeExpressionEditorComponent {
|
|
|
6546
6789
|
text(event) {
|
|
6547
6790
|
return event.target.value;
|
|
6548
6791
|
}
|
|
6549
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
6550
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
6792
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeExpressionEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6793
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeExpressionEditorComponent, isStandalone: true, selector: "dpe-expression-editor", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, dialect: { classPropertyName: "dialect", publicName: "dialect", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
|
|
6551
6794
|
<div class="dpe-field">
|
|
6552
6795
|
<label class="dpe-field__label" [attr.for]="controlId()">{{ label() }}</label>
|
|
6553
6796
|
<textarea
|
|
@@ -6570,7 +6813,7 @@ class DpeExpressionEditorComponent {
|
|
|
6570
6813
|
</div>
|
|
6571
6814
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6572
6815
|
}
|
|
6573
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
6816
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeExpressionEditorComponent, decorators: [{
|
|
6574
6817
|
type: Component,
|
|
6575
6818
|
args: [{
|
|
6576
6819
|
selector: 'dpe-expression-editor',
|
|
@@ -6666,8 +6909,8 @@ class DpeTransformInspectorComponent extends DpeNodeInspectorBase {
|
|
|
6666
6909
|
.filter((value) => value.length > 0);
|
|
6667
6910
|
return values.length > 0 ? values : undefined;
|
|
6668
6911
|
}
|
|
6669
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
6670
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
6912
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeTransformInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
6913
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeTransformInspectorComponent, isStandalone: true, selector: "dpe-transform-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
6671
6914
|
<div class="dpe-form">
|
|
6672
6915
|
<div class="dpe-field">
|
|
6673
6916
|
<label class="dpe-field__label" for="tr-kind">Tipo di trasformazione</label>
|
|
@@ -6803,7 +7046,7 @@ class DpeTransformInspectorComponent extends DpeNodeInspectorBase {
|
|
|
6803
7046
|
</div>
|
|
6804
7047
|
`, isInline: true, dependencies: [{ kind: "component", type: DpeColumnTypeEditorComponent, selector: "dpe-column-type-editor", inputs: ["value", "controlId"], outputs: ["valueChange"] }, { kind: "component", type: DpeExpressionEditorComponent, selector: "dpe-expression-editor", inputs: ["label", "value", "placeholder", "dialect", "columns", "controlId"], outputs: ["valueChange"] }, { kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6805
7048
|
}
|
|
6806
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
7049
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeTransformInspectorComponent, decorators: [{
|
|
6807
7050
|
type: Component,
|
|
6808
7051
|
args: [{
|
|
6809
7052
|
selector: 'dpe-transform-inspector',
|
|
@@ -7024,8 +7267,8 @@ class DpeWritebackInspectorComponent extends DpeNodeInspectorBase {
|
|
|
7024
7267
|
sourceFieldName: name === '' ? this.fields()[index]?.sourceFieldName : undefined,
|
|
7025
7268
|
});
|
|
7026
7269
|
}
|
|
7027
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
7028
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
7270
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeWritebackInspectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
7271
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeWritebackInspectorComponent, isStandalone: true, selector: "dpe-writeback-inspector", usesInheritance: true, ngImport: i0, template: `
|
|
7029
7272
|
<div class="dpe-form">
|
|
7030
7273
|
<div class="dpe-row">
|
|
7031
7274
|
<div class="dpe-field">
|
|
@@ -7253,7 +7496,7 @@ class DpeWritebackInspectorComponent extends DpeNodeInspectorBase {
|
|
|
7253
7496
|
</div>
|
|
7254
7497
|
`, isInline: true, dependencies: [{ kind: "component", type: DpeExpressionEditorComponent, selector: "dpe-expression-editor", inputs: ["label", "value", "placeholder", "dialect", "columns", "controlId"], outputs: ["valueChange"] }, { kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7255
7498
|
}
|
|
7256
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
7499
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeWritebackInspectorComponent, decorators: [{
|
|
7257
7500
|
type: Component,
|
|
7258
7501
|
args: [{
|
|
7259
7502
|
selector: 'dpe-writeback-inspector',
|
|
@@ -7491,48 +7734,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
7491
7734
|
}] });
|
|
7492
7735
|
|
|
7493
7736
|
/**
|
|
7494
|
-
*
|
|
7737
|
+
* **Solo** i campi modificabili di **un** nodo: i campi comuni, poi l'ispettore della categoria.
|
|
7738
|
+
*
|
|
7739
|
+
* Cio' che non c'e' piu', e dove e' andato (ADR 0026): la testata di identita' e' della dialog che
|
|
7740
|
+
* lo contiene, le due sezioni di fatti in sola lettura sono di `dpe-node-facts`, e il caso «piu' di
|
|
7741
|
+
* un nodo selezionato» e' una striscia contestuale del guscio. Non c'e' **nessun** booleano di
|
|
7742
|
+
* modalita' al loro posto: si e' spostato contenuto, non aggiunto un interruttore che cambia il
|
|
7743
|
+
* significato del componente.
|
|
7495
7744
|
*
|
|
7496
7745
|
* La **rinomina** sta qui e non nei singoli ispettori, per due ragioni. E' identica per tutte le
|
|
7497
7746
|
* categorie, e soprattutto e' un refactoring globale (**I5**): passa dall'unico punto che
|
|
7498
7747
|
* riscrive i riferimenti a valle, e prima di applicarla **dice quante occorrenze tocchera'**.
|
|
7499
|
-
* Rinominare non e' modificare un campo, e non deve sembrarlo.
|
|
7500
|
-
*
|
|
7501
|
-
* Con **piu' di un nodo selezionato** non si mostra l'editor del primo: si dichiara quanti sono e
|
|
7502
|
-
* si offrono solo le operazioni valide su molti. Mostrare i campi di uno mentre N sono evidenziati
|
|
7503
|
-
* e' la stessa bugia della doppia evidenziazione, detta piu' piano — l'utente crede di stare
|
|
7504
|
-
* agendo su cio' che vede selezionato.
|
|
7748
|
+
* Rinominare non e' modificare un campo, e non deve sembrarlo. E' anche l'unica eccezione al
|
|
7749
|
+
* commit dal vivo: ha una bozza locale perche' ha un bottone, non perche' sia in una dialog.
|
|
7505
7750
|
*/
|
|
7506
7751
|
class DpeNodeInspectorComponent {
|
|
7507
7752
|
store = inject(DpeDocumentStore);
|
|
7508
|
-
/**
|
|
7509
|
-
* Il riordino richiede le misure delle card, che le conosce il canvas: l'ispettore **chiede**,
|
|
7510
|
-
* non calcola. Componente stupido, orchestrazione fuori.
|
|
7511
|
-
*/
|
|
7512
|
-
layoutRequested = output();
|
|
7513
|
-
selectedNames = computed(() => this.store.selectedNodeNames(), ...(ngDevMode ? [{ debugName: "selectedNames" }] : []));
|
|
7514
7753
|
located = computed(() => {
|
|
7515
7754
|
const name = this.store.selectedNodeName();
|
|
7516
7755
|
return name === undefined ? undefined : dpeFindNode(this.store.definition(), name);
|
|
7517
7756
|
}, ...(ngDevMode ? [{ debugName: "located" }] : []));
|
|
7518
7757
|
nameDraft = signal('', ...(ngDevMode ? [{ debugName: "nameDraft" }] : []));
|
|
7519
|
-
categoryLabel = computed(() => {
|
|
7520
|
-
const entry = this.located();
|
|
7521
|
-
return entry ? dpeNodeCategory(entry.collection).label : '';
|
|
7522
|
-
}, ...(ngDevMode ? [{ debugName: "categoryLabel" }] : []));
|
|
7523
|
-
/** La classe di famiglia dell'icona: la stessa funzione che usano palette e canvas. */
|
|
7524
|
-
familyClass = computed(() => {
|
|
7525
|
-
const entry = this.located();
|
|
7526
|
-
return entry ? dpeNodeIconFamilyClass(entry.collection) : '';
|
|
7527
|
-
}, ...(ngDevMode ? [{ debugName: "familyClass" }] : []));
|
|
7528
|
-
columns = computed(() => {
|
|
7529
|
-
const entry = this.located();
|
|
7530
|
-
return entry ? (this.store.schemaByNode().get(entry.node.name)?.columns ?? []) : [];
|
|
7531
|
-
}, ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
7532
|
-
diagnostics = computed(() => {
|
|
7533
|
-
const entry = this.located();
|
|
7534
|
-
return entry ? (this.store.diagnosticsByNode().get(entry.node.name)?.diagnostics ?? []) : [];
|
|
7535
|
-
}, ...(ngDevMode ? [{ debugName: "diagnostics" }] : []));
|
|
7536
7758
|
referenceCount = computed(() => {
|
|
7537
7759
|
const entry = this.located();
|
|
7538
7760
|
return entry ? this.store.countReferences(entry.node.name) : 0;
|
|
@@ -7550,15 +7772,6 @@ class DpeNodeInspectorComponent {
|
|
|
7550
7772
|
this.nameDraft.set(entry?.node.name ?? '');
|
|
7551
7773
|
});
|
|
7552
7774
|
}
|
|
7553
|
-
/**
|
|
7554
|
-
* Elimina i nodi selezionati. Si itera su una **copia** dei nomi: `removeNode` pota la selezione
|
|
7555
|
-
* a ogni giro, e scorrere il signal mentre lo si svuota salterebbe la meta' dei nodi.
|
|
7556
|
-
*/
|
|
7557
|
-
removeSelected() {
|
|
7558
|
-
for (const name of [...this.selectedNames()]) {
|
|
7559
|
-
this.store.removeNode(name);
|
|
7560
|
-
}
|
|
7561
|
-
}
|
|
7562
7775
|
rename(currentName) {
|
|
7563
7776
|
this.store.renameNode(currentName, this.nameDraft().trim());
|
|
7564
7777
|
}
|
|
@@ -7610,60 +7823,9 @@ class DpeNodeInspectorComponent {
|
|
|
7610
7823
|
asAtomic(node) {
|
|
7611
7824
|
return node;
|
|
7612
7825
|
}
|
|
7613
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
7614
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
7615
|
-
@if (
|
|
7616
|
-
<!--
|
|
7617
|
-
Selezione multipla: si dice quanti sono e si offre solo cio' che ha senso su molti. Nessun
|
|
7618
|
-
campo del primo nodo, perche' non e' su quello che l’utente sta agendo.
|
|
7619
|
-
-->
|
|
7620
|
-
<div class="dpe-inspector__head">
|
|
7621
|
-
<strong>{{ selectedNames().length }} nodi selezionati</strong>
|
|
7622
|
-
<span class="dpe-inspector__category">selezione</span>
|
|
7623
|
-
</div>
|
|
7624
|
-
|
|
7625
|
-
<ul class="dpe-multi__names">
|
|
7626
|
-
@for (name of selectedNames(); track $index) {
|
|
7627
|
-
<li class="dpe-multi__name">{{ name }}</li>
|
|
7628
|
-
}
|
|
7629
|
-
</ul>
|
|
7630
|
-
|
|
7631
|
-
<p class="dpe-note">
|
|
7632
|
-
I campi di un singolo nodo si modificano con un nodo solo selezionato: mostrarli qui
|
|
7633
|
-
farebbe credere di agire su tutti.
|
|
7634
|
-
</p>
|
|
7635
|
-
|
|
7636
|
-
<div class="dpe-row">
|
|
7637
|
-
<button type="button" class="dpe-btn" (click)="removeSelected()">
|
|
7638
|
-
Elimina i {{ selectedNames().length }} nodi
|
|
7639
|
-
</button>
|
|
7640
|
-
<!--
|
|
7641
|
-
Il riordino e’ dichiaratamente **dell’intero grafo**: dagre su un sottografo sarebbe una
|
|
7642
|
-
funzione nuova, e chiamarla «riordina i selezionati» mentre riordina tutto sarebbe una
|
|
7643
|
-
bugia — la stessa classe di difetto che questo pannello esiste per evitare.
|
|
7644
|
-
-->
|
|
7645
|
-
<button type="button" class="dpe-btn" (click)="layoutRequested.emit()">
|
|
7646
|
-
Riordina il grafo
|
|
7647
|
-
</button>
|
|
7648
|
-
</div>
|
|
7649
|
-
|
|
7650
|
-
<p class="dpe-note dpe-note--warning">
|
|
7651
|
-
L’eliminazione lascia i riferimenti a valle così come sono: diventano riferimenti rotti, e
|
|
7652
|
-
il backend li segnala. Si annulla con ↶.
|
|
7653
|
-
</p>
|
|
7654
|
-
} @else if (located(); as entry) {
|
|
7655
|
-
<div class="dpe-inspector__head">
|
|
7656
|
-
<!--
|
|
7657
|
-
La stessa icona della palette e della card: il terzo posto in cui compare il tipo, e
|
|
7658
|
-
deve avere lo stesso aspetto degli altri due.
|
|
7659
|
-
-->
|
|
7660
|
-
<span class="dpe-inspector__icon" [class]="'dpe-inspector__icon ' + familyClass()">
|
|
7661
|
-
<dpe-node-icon [collection]="entry.collection" />
|
|
7662
|
-
</span>
|
|
7663
|
-
<strong class="dpe-inspector__name">{{ entry.node.label || entry.node.name }}</strong>
|
|
7664
|
-
<span class="dpe-inspector__category">{{ categoryLabel() }}</span>
|
|
7665
|
-
</div>
|
|
7666
|
-
|
|
7826
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeInspectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7827
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeNodeInspectorComponent, isStandalone: true, selector: "dpe-node-inspector", ngImport: i0, template: `
|
|
7828
|
+
@if (located(); as entry) {
|
|
7667
7829
|
<div class="dpe-form">
|
|
7668
7830
|
<div class="dpe-field">
|
|
7669
7831
|
<label class="dpe-field__label" for="node-name">Nome tecnico</label>
|
|
@@ -7751,52 +7913,12 @@ class DpeNodeInspectorComponent {
|
|
|
7751
7913
|
}
|
|
7752
7914
|
}
|
|
7753
7915
|
</section>
|
|
7754
|
-
|
|
7755
|
-
<section class="dpe-section">
|
|
7756
|
-
<h4 class="dpe-section__title">Schema in uscita</h4>
|
|
7757
|
-
@if (columns().length === 0) {
|
|
7758
|
-
<p class="dpe-empty">
|
|
7759
|
-
Nessuna colonna: il backend non ha (ancora) propagato uno schema per questo nodo.
|
|
7760
|
-
</p>
|
|
7761
|
-
} @else {
|
|
7762
|
-
<div class="dpe-columns">
|
|
7763
|
-
@for (column of columns(); track $index) {
|
|
7764
|
-
<span
|
|
7765
|
-
class="dpe-column"
|
|
7766
|
-
[class.dpe-column--nullable]="column.isNullable"
|
|
7767
|
-
[title]="column.type.kind + (column.isNullable ? ' · nullabile' : ' · non nulla')"
|
|
7768
|
-
>
|
|
7769
|
-
{{ column.name }}
|
|
7770
|
-
</span>
|
|
7771
|
-
}
|
|
7772
|
-
</div>
|
|
7773
|
-
<p class="dpe-field__hint">
|
|
7774
|
-
Tratteggiate le colonne nullabili. Lo schema arriva da <code>validate</code>: non lo
|
|
7775
|
-
calcoliamo qui.
|
|
7776
|
-
</p>
|
|
7777
|
-
}
|
|
7778
|
-
</section>
|
|
7779
|
-
|
|
7780
|
-
@if (diagnostics().length > 0) {
|
|
7781
|
-
<section class="dpe-section">
|
|
7782
|
-
<h4 class="dpe-section__title">Rilievi su questo nodo</h4>
|
|
7783
|
-
@for (diagnostic of diagnostics(); track $index) {
|
|
7784
|
-
<p
|
|
7785
|
-
class="dpe-field__issue"
|
|
7786
|
-
[class.dpe-field__issue--warning]="diagnostic.severity === 'Warning'"
|
|
7787
|
-
[class.dpe-field__issue--info]="diagnostic.severity === 'Info'"
|
|
7788
|
-
>
|
|
7789
|
-
<code>{{ diagnostic.code }}</code> — {{ diagnostic.message }}
|
|
7790
|
-
</p>
|
|
7791
|
-
}
|
|
7792
|
-
</section>
|
|
7793
|
-
}
|
|
7794
7916
|
} @else {
|
|
7795
7917
|
<p class="dpe-empty">Nessun nodo selezionato.</p>
|
|
7796
7918
|
}
|
|
7797
|
-
`, isInline: true, dependencies: [{ kind: "component", type: DpeAggregateInspectorComponent, selector: "dpe-aggregate-inspector" }, { kind: "component", type: DpeAppendInspectorComponent, selector: "dpe-append-inspector" }, { kind: "component", type: DpeAtomicWritebackInspectorComponent, selector: "dpe-atomic-writeback-inspector" }, { kind: "component", type: DpeCustomNodeInspectorComponent, selector: "dpe-custom-node-inspector" }, { kind: "component", type: DpeDataSourceInspectorComponent, selector: "dpe-data-source-inspector" }, { kind: "component", type: DpeFilterInspectorComponent, selector: "dpe-filter-inspector" }, { kind: "component", type: DpeForecastInspectorComponent, selector: "dpe-forecast-inspector" }, { kind: "component", type: DpeHierarchyPathInspectorComponent, selector: "dpe-hierarchy-path-inspector" }, { kind: "component", type: DpeJoinInspectorComponent, selector: "dpe-join-inspector" }, { kind: "component", type: DpeTransformInspectorComponent, selector: "dpe-transform-inspector" }, { kind: "component", type: DpeWritebackInspectorComponent, selector: "dpe-writeback-inspector" }
|
|
7919
|
+
`, isInline: true, dependencies: [{ kind: "component", type: DpeAggregateInspectorComponent, selector: "dpe-aggregate-inspector" }, { kind: "component", type: DpeAppendInspectorComponent, selector: "dpe-append-inspector" }, { kind: "component", type: DpeAtomicWritebackInspectorComponent, selector: "dpe-atomic-writeback-inspector" }, { kind: "component", type: DpeCustomNodeInspectorComponent, selector: "dpe-custom-node-inspector" }, { kind: "component", type: DpeDataSourceInspectorComponent, selector: "dpe-data-source-inspector" }, { kind: "component", type: DpeFilterInspectorComponent, selector: "dpe-filter-inspector" }, { kind: "component", type: DpeForecastInspectorComponent, selector: "dpe-forecast-inspector" }, { kind: "component", type: DpeHierarchyPathInspectorComponent, selector: "dpe-hierarchy-path-inspector" }, { kind: "component", type: DpeJoinInspectorComponent, selector: "dpe-join-inspector" }, { kind: "component", type: DpeTransformInspectorComponent, selector: "dpe-transform-inspector" }, { kind: "component", type: DpeWritebackInspectorComponent, selector: "dpe-writeback-inspector" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7798
7920
|
}
|
|
7799
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
7921
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeInspectorComponent, decorators: [{
|
|
7800
7922
|
type: Component,
|
|
7801
7923
|
args: [{
|
|
7802
7924
|
selector: 'dpe-node-inspector',
|
|
@@ -7813,62 +7935,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
7813
7935
|
DpeJoinInspectorComponent,
|
|
7814
7936
|
DpeTransformInspectorComponent,
|
|
7815
7937
|
DpeWritebackInspectorComponent,
|
|
7816
|
-
DpeNodeIconComponent,
|
|
7817
7938
|
],
|
|
7818
7939
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
7819
7940
|
template: `
|
|
7820
|
-
@if (
|
|
7821
|
-
<!--
|
|
7822
|
-
Selezione multipla: si dice quanti sono e si offre solo cio' che ha senso su molti. Nessun
|
|
7823
|
-
campo del primo nodo, perche' non e' su quello che l’utente sta agendo.
|
|
7824
|
-
-->
|
|
7825
|
-
<div class="dpe-inspector__head">
|
|
7826
|
-
<strong>{{ selectedNames().length }} nodi selezionati</strong>
|
|
7827
|
-
<span class="dpe-inspector__category">selezione</span>
|
|
7828
|
-
</div>
|
|
7829
|
-
|
|
7830
|
-
<ul class="dpe-multi__names">
|
|
7831
|
-
@for (name of selectedNames(); track $index) {
|
|
7832
|
-
<li class="dpe-multi__name">{{ name }}</li>
|
|
7833
|
-
}
|
|
7834
|
-
</ul>
|
|
7835
|
-
|
|
7836
|
-
<p class="dpe-note">
|
|
7837
|
-
I campi di un singolo nodo si modificano con un nodo solo selezionato: mostrarli qui
|
|
7838
|
-
farebbe credere di agire su tutti.
|
|
7839
|
-
</p>
|
|
7840
|
-
|
|
7841
|
-
<div class="dpe-row">
|
|
7842
|
-
<button type="button" class="dpe-btn" (click)="removeSelected()">
|
|
7843
|
-
Elimina i {{ selectedNames().length }} nodi
|
|
7844
|
-
</button>
|
|
7845
|
-
<!--
|
|
7846
|
-
Il riordino e’ dichiaratamente **dell’intero grafo**: dagre su un sottografo sarebbe una
|
|
7847
|
-
funzione nuova, e chiamarla «riordina i selezionati» mentre riordina tutto sarebbe una
|
|
7848
|
-
bugia — la stessa classe di difetto che questo pannello esiste per evitare.
|
|
7849
|
-
-->
|
|
7850
|
-
<button type="button" class="dpe-btn" (click)="layoutRequested.emit()">
|
|
7851
|
-
Riordina il grafo
|
|
7852
|
-
</button>
|
|
7853
|
-
</div>
|
|
7854
|
-
|
|
7855
|
-
<p class="dpe-note dpe-note--warning">
|
|
7856
|
-
L’eliminazione lascia i riferimenti a valle così come sono: diventano riferimenti rotti, e
|
|
7857
|
-
il backend li segnala. Si annulla con ↶.
|
|
7858
|
-
</p>
|
|
7859
|
-
} @else if (located(); as entry) {
|
|
7860
|
-
<div class="dpe-inspector__head">
|
|
7861
|
-
<!--
|
|
7862
|
-
La stessa icona della palette e della card: il terzo posto in cui compare il tipo, e
|
|
7863
|
-
deve avere lo stesso aspetto degli altri due.
|
|
7864
|
-
-->
|
|
7865
|
-
<span class="dpe-inspector__icon" [class]="'dpe-inspector__icon ' + familyClass()">
|
|
7866
|
-
<dpe-node-icon [collection]="entry.collection" />
|
|
7867
|
-
</span>
|
|
7868
|
-
<strong class="dpe-inspector__name">{{ entry.node.label || entry.node.name }}</strong>
|
|
7869
|
-
<span class="dpe-inspector__category">{{ categoryLabel() }}</span>
|
|
7870
|
-
</div>
|
|
7871
|
-
|
|
7941
|
+
@if (located(); as entry) {
|
|
7872
7942
|
<div class="dpe-form">
|
|
7873
7943
|
<div class="dpe-field">
|
|
7874
7944
|
<label class="dpe-field__label" for="node-name">Nome tecnico</label>
|
|
@@ -7956,52 +8026,302 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
7956
8026
|
}
|
|
7957
8027
|
}
|
|
7958
8028
|
</section>
|
|
8029
|
+
} @else {
|
|
8030
|
+
<p class="dpe-empty">Nessun nodo selezionato.</p>
|
|
8031
|
+
}
|
|
8032
|
+
`,
|
|
8033
|
+
}]
|
|
8034
|
+
}], ctorParameters: () => [] });
|
|
8035
|
+
|
|
8036
|
+
/**
|
|
8037
|
+
* La finestra di modifica di un nodo: elemento `<dialog>` **nativo**, aperto con `showModal()`
|
|
8038
|
+
* (ADR 0026).
|
|
8039
|
+
*
|
|
8040
|
+
* Perche' l'elemento nativo e non un overlay scritto a mano: **Esc**, il **focus trap** (con la
|
|
8041
|
+
* finestra aperta il Tab non esce), il **fondo inerte** per puntatore *e* tastiera, `::backdrop`
|
|
8042
|
+
* come pseudo-elemento standard e nessun `z-index` — il top layer sta sopra ogni stacking context
|
|
8043
|
+
* senza partecipare alla gara. Sono tutte cose che un overlay dovrebbe reimplementare, e il focus
|
|
8044
|
+
* trap in particolare non si scrive in due righe.
|
|
8045
|
+
*
|
|
8046
|
+
* **Una sola istanza** nel guscio, fratello di `.dpe-shell__body`. Resta nel sottoalbero DOM del
|
|
8047
|
+
* componente e non si trapianta in `document.body`: il top layer e' una promozione **visiva**, non
|
|
8048
|
+
* un trapianto, quindi gli eventi risalgono l'albero e il `Ctrl+S` del guscio continua a
|
|
8049
|
+
* funzionare.
|
|
8050
|
+
*
|
|
8051
|
+
* **Le modifiche si applicano dal vivo**: gli ispettori scrivono nello store a ogni `(change)`,
|
|
8052
|
+
* qui non esiste nessuna bozza locale e il piede ha «Chiudi», non «OK / Annulla». Una bozza
|
|
8053
|
+
* produrrebbe due nozioni di annullamento in disaccordo con ↶ e rilievi che descrivono un
|
|
8054
|
+
* documento diverso da quello mostrato. Conseguenza dichiarata in interfaccia: **chiudere non
|
|
8055
|
+
* annulla**.
|
|
8056
|
+
*
|
|
8057
|
+
* Il nodo **non arriva per input**: si rideriva da `selectedNodeName()`, cosi' se cambia sotto
|
|
8058
|
+
* (una rinomina) la dialog lo segue invece di guardare un nome che non esiste piu'.
|
|
8059
|
+
*/
|
|
8060
|
+
/**
|
|
8061
|
+
* Contatore di istanza per l'id dell'etichetta. Serve perche' `aria-labelledby` punta a un id, e
|
|
8062
|
+
* due editor nella stessa pagina sono due dialog: con un id fisso il documento avrebbe due
|
|
8063
|
+
* elementi con lo stesso id e il nome accessibile della seconda finestra sarebbe quello della
|
|
8064
|
+
* prima. Non e' una preferenza di stile — un id duplicato e' un difetto che solo uno screen
|
|
8065
|
+
* reader mostra.
|
|
8066
|
+
*/
|
|
8067
|
+
let nextLabelId = 0;
|
|
8068
|
+
class DpeNodeDialogComponent {
|
|
8069
|
+
store = inject(DpeDocumentStore);
|
|
8070
|
+
dialogRef = viewChild.required('dlg');
|
|
8071
|
+
labelId = `dpe-node-dialog-label-${(nextLabelId += 1)}`;
|
|
8072
|
+
/**
|
|
8073
|
+
* Il nodo corrente, **riderivato** dallo store come fa il dispatcher degli ispettori. Non si
|
|
8074
|
+
* conserva il nome: se il nodo viene rinominato, `selectedNodeName()` porta gia' il nome nuovo.
|
|
8075
|
+
*/
|
|
8076
|
+
located = computed(() => {
|
|
8077
|
+
const name = this.store.selectedNodeName();
|
|
8078
|
+
return name === undefined ? undefined : dpeFindNode(this.store.definition(), name);
|
|
8079
|
+
}, ...(ngDevMode ? [{ debugName: "located" }] : []));
|
|
8080
|
+
categoryLabel = computed(() => {
|
|
8081
|
+
const entry = this.located();
|
|
8082
|
+
return entry ? dpeNodeCategory(entry.collection).label : '';
|
|
8083
|
+
}, ...(ngDevMode ? [{ debugName: "categoryLabel" }] : []));
|
|
8084
|
+
familyClass = computed(() => {
|
|
8085
|
+
const entry = this.located();
|
|
8086
|
+
return entry ? dpeNodeIconFamilyClass(entry.collection) : '';
|
|
8087
|
+
}, ...(ngDevMode ? [{ debugName: "familyClass" }] : []));
|
|
8088
|
+
/**
|
|
8089
|
+
* Vero quando il fondo ha ricevuto il `pointerdown` di questo clic. Vedi `onDialogClick`: la
|
|
8090
|
+
* verifica di coppia non e' prudenza, e' la correzione di un difetto reale.
|
|
8091
|
+
*/
|
|
8092
|
+
pointerDownWasOnBackdrop = false;
|
|
8093
|
+
constructor() {
|
|
8094
|
+
effect(() => {
|
|
8095
|
+
const el = this.dialogRef().nativeElement;
|
|
8096
|
+
const shouldBeOpen = this.store.isNodeEditorOpen() && this.located() !== undefined;
|
|
8097
|
+
// La guardia su `el.open` **non e' cosmetica**: `showModal()` su una dialog gia' aperta
|
|
8098
|
+
// lancia `InvalidStateError`, e questo effect riesegue a ogni mutazione del documento
|
|
8099
|
+
// (legge `located()`). Senza, aprire e modificare un campo basterebbe a far comparire
|
|
8100
|
+
// l'eccezione in console.
|
|
8101
|
+
if (shouldBeOpen && !el.open) {
|
|
8102
|
+
el.showModal();
|
|
8103
|
+
}
|
|
8104
|
+
else if (!shouldBeOpen && el.open) {
|
|
8105
|
+
el.close();
|
|
8106
|
+
}
|
|
8107
|
+
});
|
|
8108
|
+
}
|
|
8109
|
+
/**
|
|
8110
|
+
* **Esc.** Il browser chiede di chiudere e la finestra e' ancora aperta: la richiesta riguarda
|
|
8111
|
+
* per definizione la sessione corrente, quindi si chiude e non serve nessuna verifica.
|
|
8112
|
+
*
|
|
8113
|
+
* Perche' `cancel` e' legato, contro cio' che sembra sufficiente: in Chrome 151 l'evento `close`
|
|
8114
|
+
* **arriva molto in ritardo** (vedi `onClose`), quindi con il solo `close` lo store restava
|
|
8115
|
+
* «aperta» dopo Esc — e il sintomo era che **riaprire lo stesso nodo non faceva niente**: il
|
|
8116
|
+
* signal non cambiava, l'effect non rieseguiva, `showModal()` non veniva mai chiamato. Sul
|
|
8117
|
+
* bottone del piede non si vedeva, perche' quella via passa dallo store.
|
|
8118
|
+
*
|
|
8119
|
+
* `cancel` sarebbe annullabile: non si annulla. La chiusura dell'elemento arriva comunque dal
|
|
8120
|
+
* browser, e la guardia su `el.open` nell'effect regge in entrambi gli ordini.
|
|
8121
|
+
*/
|
|
8122
|
+
onCancel() {
|
|
8123
|
+
this.store.closeNodeEditor();
|
|
8124
|
+
}
|
|
8125
|
+
/**
|
|
8126
|
+
* **L'elemento si e' chiuso.** La guardia non e' prudenza: Chrome accoda `close` come task
|
|
8127
|
+
* dell'elemento e lo consegna anche **dopo** una riapertura — misurato nella demo, la traccia
|
|
8128
|
+
* degli eventi mostra `close` con `open: true` subito dopo un `showModal()`. Senza la guardia
|
|
8129
|
+
* quel `close` in ritardo chiudeva la finestra appena aperta, e il sintomo era una dialog che
|
|
8130
|
+
* «non si apre a volte»: sparisce da sola dopo essere comparsa, e con la finestra aperta si
|
|
8131
|
+
* riapriva solo alla prima modifica del documento (l'unica cosa che faceva rieseguire l'effect).
|
|
8132
|
+
*
|
|
8133
|
+
* Se l'elemento risulta **aperto**, questo `close` riguarda una sessione precedente e si ignora.
|
|
8134
|
+
* Se risulta chiuso, la notifica e' di questa sessione — e allineare qui lo store e' anche cio'
|
|
8135
|
+
* che ripara una divergenza, se il browser chiudesse la finestra per vie sue.
|
|
8136
|
+
*/
|
|
8137
|
+
onClose() {
|
|
8138
|
+
if (this.dialogRef().nativeElement.open) {
|
|
8139
|
+
return;
|
|
8140
|
+
}
|
|
8141
|
+
this.store.closeNodeEditor();
|
|
8142
|
+
}
|
|
8143
|
+
onPointerDown(event) {
|
|
8144
|
+
this.pointerDownWasOnBackdrop = event.target === this.dialogRef().nativeElement;
|
|
8145
|
+
}
|
|
8146
|
+
/**
|
|
8147
|
+
* Chiusura al clic sul fondo, con la **verifica di coppia** e non con il solo controllo sul
|
|
8148
|
+
* click. I clic sul velo sono recapitati all'elemento `<dialog>` stesso — ma anche un
|
|
8149
|
+
* trascinamento di selezione del testo che **inizia** dentro una casella e **finisce** fuori
|
|
8150
|
+
* produce un `click` con `target` uguale alla dialog. Con la sola verifica sul click, selezionare
|
|
8151
|
+
* del testo chiuderebbe la finestra.
|
|
8152
|
+
*/
|
|
8153
|
+
onDialogClick(event) {
|
|
8154
|
+
if (this.pointerDownWasOnBackdrop && event.target === this.dialogRef().nativeElement) {
|
|
8155
|
+
this.store.closeNodeEditor();
|
|
8156
|
+
}
|
|
8157
|
+
}
|
|
8158
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8159
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeNodeDialogComponent, isStandalone: true, selector: "dpe-node-dialog", viewQueries: [{ propertyName: "dialogRef", first: true, predicate: ["dlg"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
8160
|
+
<!--
|
|
8161
|
+
L’elemento dialog sta **sempre** nel template, e solo il contenuto e’ condizionato: cosi’
|
|
8162
|
+
viewChild.required non puo’ fallire e l’effect che apre non deve difendersi da un riferimento
|
|
8163
|
+
assente. Una dialog vuota e chiusa non rende niente — il foglio dell’agente utente le da’
|
|
8164
|
+
display: none.
|
|
8165
|
+
-->
|
|
8166
|
+
<dialog
|
|
8167
|
+
#dlg
|
|
8168
|
+
class="dpe-dialog"
|
|
8169
|
+
[attr.aria-labelledby]="labelId"
|
|
8170
|
+
(close)="onClose()"
|
|
8171
|
+
(cancel)="onCancel()"
|
|
8172
|
+
(click)="onDialogClick($event)"
|
|
8173
|
+
(pointerdown)="onPointerDown($event)"
|
|
8174
|
+
>
|
|
8175
|
+
@if (located(); as entry) {
|
|
8176
|
+
<header class="dpe-dialog__head">
|
|
8177
|
+
<!--
|
|
8178
|
+
Quarto posto in cui compare il tipo di nodo (palette, card del canvas, ispettore, qui):
|
|
8179
|
+
stessa icona e stessa classe di famiglia, calcolate dalle stesse funzioni. Un tipo che
|
|
8180
|
+
cambia aspetto da un posto all’altro e’ un tipo che non si riconosce.
|
|
8181
|
+
-->
|
|
8182
|
+
<span class="dpe-dialog__icon" [class]="'dpe-dialog__icon ' + familyClass()">
|
|
8183
|
+
<dpe-node-icon [collection]="entry.collection" />
|
|
8184
|
+
</span>
|
|
8185
|
+
<strong class="dpe-dialog__label" [id]="labelId">
|
|
8186
|
+
{{ entry.node.label || entry.node.name }}
|
|
8187
|
+
</strong>
|
|
8188
|
+
<span class="dpe-dialog__category">{{ categoryLabel() }}</span>
|
|
8189
|
+
<code class="dpe-dialog__name">{{ entry.node.name }}</code>
|
|
8190
|
+
<button
|
|
8191
|
+
type="button"
|
|
8192
|
+
class="dpe-dialog__btn dpe-dialog__btn--icon"
|
|
8193
|
+
aria-label="Chiudi la finestra di modifica"
|
|
8194
|
+
title="Chiudi (Esc). Le modifiche sono già nel documento."
|
|
8195
|
+
(click)="store.closeNodeEditor()"
|
|
8196
|
+
>
|
|
8197
|
+
✕
|
|
8198
|
+
</button>
|
|
8199
|
+
</header>
|
|
8200
|
+
|
|
8201
|
+
<div class="dpe-dialog__body">
|
|
8202
|
+
<!-- Colonna larga: i campi. E’ la ragione per cui questa finestra esiste. -->
|
|
8203
|
+
<div class="dpe-dialog__main">
|
|
8204
|
+
<dpe-node-inspector />
|
|
8205
|
+
</div>
|
|
7959
8206
|
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
8207
|
+
<!--
|
|
8208
|
+
Colonna stretta: i fatti dal backend su **questo** nodo. Non entra cio’ che riguarda il
|
|
8209
|
+
grafo — diagnostiche di tutta la definizione, schema di tutti i nodi e SQL generato
|
|
8210
|
+
hanno gia’ le loro linguette nel pannello inferiore.
|
|
8211
|
+
-->
|
|
8212
|
+
<aside class="dpe-dialog__side">
|
|
8213
|
+
<dpe-node-facts [nodeName]="entry.node.name" />
|
|
8214
|
+
</aside>
|
|
8215
|
+
</div>
|
|
8216
|
+
|
|
8217
|
+
<footer class="dpe-dialog__foot">
|
|
8218
|
+
<p class="dpe-dialog__note">
|
|
8219
|
+
Le modifiche sono <strong>già nel documento</strong>: chiudere non le annulla. Si torna
|
|
8220
|
+
indietro con ↶ nella barra.
|
|
7965
8221
|
</p>
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
8222
|
+
<button
|
|
8223
|
+
type="button"
|
|
8224
|
+
class="dpe-dialog__btn dpe-dialog__btn--danger"
|
|
8225
|
+
title="Elimina il nodo: i riferimenti a valle restano e diventano riferimenti rotti. Si annulla con ↶."
|
|
8226
|
+
(click)="store.removeNode(entry.node.name)"
|
|
8227
|
+
>
|
|
8228
|
+
Elimina il nodo
|
|
8229
|
+
</button>
|
|
8230
|
+
<button type="button" class="dpe-dialog__btn" (click)="store.closeNodeEditor()">
|
|
8231
|
+
Chiudi
|
|
8232
|
+
</button>
|
|
8233
|
+
</footer>
|
|
8234
|
+
}
|
|
8235
|
+
</dialog>
|
|
8236
|
+
`, isInline: true, dependencies: [{ kind: "component", type: DpeNodeFactsComponent, selector: "dpe-node-facts", inputs: ["nodeName"] }, { kind: "component", type: DpeNodeInspectorComponent, selector: "dpe-node-inspector" }, { kind: "component", type: DpeNodeIconComponent, selector: "dpe-node-icon", inputs: ["collection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8237
|
+
}
|
|
8238
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodeDialogComponent, decorators: [{
|
|
8239
|
+
type: Component,
|
|
8240
|
+
args: [{
|
|
8241
|
+
selector: 'dpe-node-dialog',
|
|
8242
|
+
standalone: true,
|
|
8243
|
+
imports: [DpeNodeFactsComponent, DpeNodeInspectorComponent, DpeNodeIconComponent],
|
|
8244
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8245
|
+
template: `
|
|
8246
|
+
<!--
|
|
8247
|
+
L’elemento dialog sta **sempre** nel template, e solo il contenuto e’ condizionato: cosi’
|
|
8248
|
+
viewChild.required non puo’ fallire e l’effect che apre non deve difendersi da un riferimento
|
|
8249
|
+
assente. Una dialog vuota e chiusa non rende niente — il foglio dell’agente utente le da’
|
|
8250
|
+
display: none.
|
|
8251
|
+
-->
|
|
8252
|
+
<dialog
|
|
8253
|
+
#dlg
|
|
8254
|
+
class="dpe-dialog"
|
|
8255
|
+
[attr.aria-labelledby]="labelId"
|
|
8256
|
+
(close)="onClose()"
|
|
8257
|
+
(cancel)="onCancel()"
|
|
8258
|
+
(click)="onDialogClick($event)"
|
|
8259
|
+
(pointerdown)="onPointerDown($event)"
|
|
8260
|
+
>
|
|
8261
|
+
@if (located(); as entry) {
|
|
8262
|
+
<header class="dpe-dialog__head">
|
|
8263
|
+
<!--
|
|
8264
|
+
Quarto posto in cui compare il tipo di nodo (palette, card del canvas, ispettore, qui):
|
|
8265
|
+
stessa icona e stessa classe di famiglia, calcolate dalle stesse funzioni. Un tipo che
|
|
8266
|
+
cambia aspetto da un posto all’altro e’ un tipo che non si riconosce.
|
|
8267
|
+
-->
|
|
8268
|
+
<span class="dpe-dialog__icon" [class]="'dpe-dialog__icon ' + familyClass()">
|
|
8269
|
+
<dpe-node-icon [collection]="entry.collection" />
|
|
8270
|
+
</span>
|
|
8271
|
+
<strong class="dpe-dialog__label" [id]="labelId">
|
|
8272
|
+
{{ entry.node.label || entry.node.name }}
|
|
8273
|
+
</strong>
|
|
8274
|
+
<span class="dpe-dialog__category">{{ categoryLabel() }}</span>
|
|
8275
|
+
<code class="dpe-dialog__name">{{ entry.node.name }}</code>
|
|
8276
|
+
<button
|
|
8277
|
+
type="button"
|
|
8278
|
+
class="dpe-dialog__btn dpe-dialog__btn--icon"
|
|
8279
|
+
aria-label="Chiudi la finestra di modifica"
|
|
8280
|
+
title="Chiudi (Esc). Le modifiche sono già nel documento."
|
|
8281
|
+
(click)="store.closeNodeEditor()"
|
|
8282
|
+
>
|
|
8283
|
+
✕
|
|
8284
|
+
</button>
|
|
8285
|
+
</header>
|
|
8286
|
+
|
|
8287
|
+
<div class="dpe-dialog__body">
|
|
8288
|
+
<!-- Colonna larga: i campi. E’ la ragione per cui questa finestra esiste. -->
|
|
8289
|
+
<div class="dpe-dialog__main">
|
|
8290
|
+
<dpe-node-inspector />
|
|
7977
8291
|
</div>
|
|
7978
|
-
<p class="dpe-field__hint">
|
|
7979
|
-
Tratteggiate le colonne nullabili. Lo schema arriva da <code>validate</code>: non lo
|
|
7980
|
-
calcoliamo qui.
|
|
7981
|
-
</p>
|
|
7982
|
-
}
|
|
7983
|
-
</section>
|
|
7984
8292
|
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
8293
|
+
<!--
|
|
8294
|
+
Colonna stretta: i fatti dal backend su **questo** nodo. Non entra cio’ che riguarda il
|
|
8295
|
+
grafo — diagnostiche di tutta la definizione, schema di tutti i nodi e SQL generato
|
|
8296
|
+
hanno gia’ le loro linguette nel pannello inferiore.
|
|
8297
|
+
-->
|
|
8298
|
+
<aside class="dpe-dialog__side">
|
|
8299
|
+
<dpe-node-facts [nodeName]="entry.node.name" />
|
|
8300
|
+
</aside>
|
|
8301
|
+
</div>
|
|
8302
|
+
|
|
8303
|
+
<footer class="dpe-dialog__foot">
|
|
8304
|
+
<p class="dpe-dialog__note">
|
|
8305
|
+
Le modifiche sono <strong>già nel documento</strong>: chiudere non le annulla. Si torna
|
|
8306
|
+
indietro con ↶ nella barra.
|
|
8307
|
+
</p>
|
|
8308
|
+
<button
|
|
8309
|
+
type="button"
|
|
8310
|
+
class="dpe-dialog__btn dpe-dialog__btn--danger"
|
|
8311
|
+
title="Elimina il nodo: i riferimenti a valle restano e diventano riferimenti rotti. Si annulla con ↶."
|
|
8312
|
+
(click)="store.removeNode(entry.node.name)"
|
|
8313
|
+
>
|
|
8314
|
+
Elimina il nodo
|
|
8315
|
+
</button>
|
|
8316
|
+
<button type="button" class="dpe-dialog__btn" (click)="store.closeNodeEditor()">
|
|
8317
|
+
Chiudi
|
|
8318
|
+
</button>
|
|
8319
|
+
</footer>
|
|
7998
8320
|
}
|
|
7999
|
-
|
|
8000
|
-
<p class="dpe-empty">Nessun nodo selezionato.</p>
|
|
8001
|
-
}
|
|
8321
|
+
</dialog>
|
|
8002
8322
|
`,
|
|
8003
8323
|
}]
|
|
8004
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
8324
|
+
}], ctorParameters: () => [], propDecorators: { dialogRef: [{ type: i0.ViewChild, args: ['dlg', { isSignal: true }] }] } });
|
|
8005
8325
|
|
|
8006
8326
|
/**
|
|
8007
8327
|
* La palette dei nodi.
|
|
@@ -8070,8 +8390,8 @@ class DpeNodePaletteComponent {
|
|
|
8070
8390
|
text(event) {
|
|
8071
8391
|
return event.target.value;
|
|
8072
8392
|
}
|
|
8073
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
8074
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
8393
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodePaletteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8394
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeNodePaletteComponent, isStandalone: true, selector: "dpe-node-palette", outputs: { nodeRequested: "nodeRequested" }, ngImport: i0, template: `
|
|
8075
8395
|
<h3>Nodi</h3>
|
|
8076
8396
|
<input
|
|
8077
8397
|
type="search"
|
|
@@ -8118,7 +8438,7 @@ class DpeNodePaletteComponent {
|
|
|
8118
8438
|
}
|
|
8119
8439
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FFlowModule }, { kind: "directive", type: i1.FExternalItem, selector: "[fExternalItem]", inputs: ["fExternalItemId", "fData", "fDisabled", "fPreview", "fPreviewMatchSize", "fPlaceholder"], outputs: ["fPreviewChange", "fPlaceholderChange"] }, { kind: "component", type: DpeNodeIconComponent, selector: "dpe-node-icon", inputs: ["collection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8120
8440
|
}
|
|
8121
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
8441
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeNodePaletteComponent, decorators: [{
|
|
8122
8442
|
type: Component,
|
|
8123
8443
|
args: [{
|
|
8124
8444
|
selector: 'dpe-node-palette',
|
|
@@ -8217,8 +8537,8 @@ class DpeSqlPreviewComponent {
|
|
|
8217
8537
|
}
|
|
8218
8538
|
return typeof value === 'object' ? JSON.stringify(value) : String(value);
|
|
8219
8539
|
}
|
|
8220
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
8221
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
8540
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeSqlPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8541
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeSqlPreviewComponent, isStandalone: true, selector: "dpe-sql-preview", ngImport: i0, template: `
|
|
8222
8542
|
<div class="dpe-sql__bar">
|
|
8223
8543
|
<button
|
|
8224
8544
|
type="button"
|
|
@@ -8294,7 +8614,7 @@ class DpeSqlPreviewComponent {
|
|
|
8294
8614
|
}
|
|
8295
8615
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8296
8616
|
}
|
|
8297
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
8617
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeSqlPreviewComponent, decorators: [{
|
|
8298
8618
|
type: Component,
|
|
8299
8619
|
args: [{
|
|
8300
8620
|
selector: 'dpe-sql-preview',
|
|
@@ -8440,8 +8760,8 @@ class DpeSchemaPanelComponent {
|
|
|
8440
8760
|
};
|
|
8441
8761
|
});
|
|
8442
8762
|
}, ...(ngDevMode ? [{ debugName: "rows" }] : []));
|
|
8443
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
8444
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
8763
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeSchemaPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8764
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeSchemaPanelComponent, isStandalone: true, selector: "dpe-schema-panel", ngImport: i0, template: `
|
|
8445
8765
|
@if (!hasResult()) {
|
|
8446
8766
|
<p class="dpe-schema__empty">In attesa della propagazione dello schema dal backend…</p>
|
|
8447
8767
|
}
|
|
@@ -8499,7 +8819,7 @@ class DpeSchemaPanelComponent {
|
|
|
8499
8819
|
}
|
|
8500
8820
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8501
8821
|
}
|
|
8502
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
8822
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeSchemaPanelComponent, decorators: [{
|
|
8503
8823
|
type: Component,
|
|
8504
8824
|
args: [{
|
|
8505
8825
|
selector: 'dpe-schema-panel',
|
|
@@ -8649,6 +8969,8 @@ class DpeBuilderComponent {
|
|
|
8649
8969
|
this.store.isDirty() &&
|
|
8650
8970
|
this.hasKey(), ...(ngDevMode ? [{ debugName: "canSave" }] : []));
|
|
8651
8971
|
nodeCount = computed(() => dpeAllNodes(this.store.definition()).length, ...(ngDevMode ? [{ debugName: "nodeCount" }] : []));
|
|
8972
|
+
/** I nomi selezionati: la striscia contestuale compare da due in su. */
|
|
8973
|
+
selectedNames = computed(() => this.store.selectedNodeNames(), ...(ngDevMode ? [{ debugName: "selectedNames" }] : []));
|
|
8652
8974
|
constructor() {
|
|
8653
8975
|
// Caricamento: si reagisce all'**identita'** dell'input, non al suo contenuto. Lo store
|
|
8654
8976
|
// diventa la fonte di verita' da qui in poi.
|
|
@@ -8709,6 +9031,28 @@ class DpeBuilderComponent {
|
|
|
8709
9031
|
// mouse subito dopo averlo rilasciato e' un passaggio inutile.
|
|
8710
9032
|
this.store.select(name);
|
|
8711
9033
|
}
|
|
9034
|
+
/**
|
|
9035
|
+
* Doppio clic sul nodo, o bottone `✎` sulla card: i due gesti che il canvas emetteva su
|
|
9036
|
+
* `nodeOpened` e che **nessuno ascoltava** — il bottone non produceva nemmeno la selezione.
|
|
9037
|
+
*
|
|
9038
|
+
* Due cose, in quest'ordine. Si apre la dialog (che collassa la selezione a quel nodo) e si
|
|
9039
|
+
* **inquadra** il nodo: sotto il velo non si vede, ma alla chiusura si torna guardando il nodo su
|
|
9040
|
+
* cui si e' lavorato invece del punto dov'era il grafo prima.
|
|
9041
|
+
*/
|
|
9042
|
+
onNodeOpened(name) {
|
|
9043
|
+
this.store.openNodeEditor(name);
|
|
9044
|
+
this.canvas()?.revealNode(name);
|
|
9045
|
+
}
|
|
9046
|
+
/**
|
|
9047
|
+
* Elimina i nodi selezionati (striscia della selezione multipla). Si itera su una **copia** dei
|
|
9048
|
+
* nomi: `removeNode` pota la selezione a ogni giro, e scorrere il signal mentre lo si svuota
|
|
9049
|
+
* salterebbe la meta' dei nodi.
|
|
9050
|
+
*/
|
|
9051
|
+
removeSelectedNodes() {
|
|
9052
|
+
for (const name of [...this.selectedNames()]) {
|
|
9053
|
+
this.store.removeNode(name);
|
|
9054
|
+
}
|
|
9055
|
+
}
|
|
8712
9056
|
/** Clic sulla palette (via tastiera compresa): il nodo nasce in un punto libero e prevedibile. */
|
|
8713
9057
|
onNodeRequested(collection) {
|
|
8714
9058
|
const existing = this.store.positions();
|
|
@@ -8761,19 +9105,19 @@ class DpeBuilderComponent {
|
|
|
8761
9105
|
markSaved() {
|
|
8762
9106
|
this.store.markSaved();
|
|
8763
9107
|
}
|
|
8764
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
8765
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.27", type: DpeBuilderComponent, isStandalone: true, selector: "dpe-builder", inputs: { definition: { classPropertyName: "definition", publicName: "definition", isSignal: true, isRequired: true, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { definitionChange: "definitionChange" }, host: { listeners: { "keydown": "onKeyDown($event)" } }, providers: [DpeDocumentStore, DpeLayoutService, DpeValidationService, DpeMetadataStore], viewQueries: [{ propertyName: "canvas", first: true, predicate: DpeCanvasComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n `.dpe-builder` porta le variabili del tema: e\u2019 la classe radice su cui l\u2019app ospite le\r\n sovrascrive, e `data-dpe-theme=\"dark\"` sul contenitore ridefinisce i soli token.\r\n-->\r\n<div class=\"dpe-builder dpe-shell\">\r\n <header class=\"dpe-shell__bar\">\r\n <div class=\"dpe-shell__title\">\r\n <strong>{{ store.definition().label || store.definition().name || 'Definizione DPE' }}</strong>\r\n <span class=\"dpe-shell__sub\">{{ nodeCount() }} nodi</span>\r\n <!--\r\n Stato **sporco** rispetto all\u2019ultimo salvataggio, non un conteggio di operazioni: serve a\r\n decidere se salvare, e un contatore che sale quando si annulla risponde alla domanda\r\n sbagliata. Annullare fino allo stato di partenza torna qui a \u00ABnessuna modifica\u00BB.\r\n -->\r\n <span\r\n class=\"dpe-shell__dirty\"\r\n [class.dpe-shell__dirty--on]=\"store.isDirty()\"\r\n [title]=\"\r\n store.isDirty()\r\n ? 'Il documento differisce dall\u2019ultimo salvataggio'\r\n : 'Il documento coincide con l\u2019ultimo salvataggio'\r\n \"\r\n >\r\n @if (store.isDirty()) {\r\n \u25CF modificata\r\n } @else {\r\n \u25CB nessuna modifica\r\n }\r\n </span>\r\n </div>\r\n\r\n <!--\r\n Badge in **sola lettura** (ADR 0017): il dialetto e\u2019 dichiarato dall\u2019ambiente, non scelto\r\n qui. Mostra quello della definizione, che e\u2019 quello con cui il backend compilera\u2019 (ADR\r\n 0009). Il titolo dice le due cose che contano \u2014 chi lo decide, e che le espressioni sono\r\n SQL nativo di quel dialetto (ADR 0006).\r\n -->\r\n <span\r\n class=\"dpe-shell__dialect\"\r\n title=\"Il dialetto e\u2019 dichiarato dall\u2019ambiente e non si modifica dall\u2019editor. Le espressioni sono SQL nativo di questo dialetto: la definizione gli appartiene.\"\r\n >\r\n Dialetto \u00B7 <strong>{{ dialectLabels[dialect()] }}</strong>\r\n </span>\r\n\r\n <div class=\"dpe-shell__group\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn\"\r\n [disabled]=\"!store.canUndo()\"\r\n title=\"Annulla (la cronologia e\u2019 una conseguenza dell\u2019immutabilita\u2019 dello stato)\"\r\n (click)=\"store.undo()\"\r\n >\r\n \u21B6 Annulla\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn\"\r\n [disabled]=\"!store.canRedo()\"\r\n title=\"Ripeti\"\r\n (click)=\"store.redo()\"\r\n >\r\n \u21B7 Ripeti\r\n </button>\r\n <button type=\"button\" class=\"dpe-shell__btn\" title=\"Riordina il grafo\" (click)=\"runAutoLayout()\">\r\n \u2317 Riordina\r\n </button>\r\n </div>\r\n\r\n <!--\r\n Salvataggio attraverso il contratto (`DpeBuilderApi.save`, opzionale). E\u2019 il comando\r\n **primario**, separato dal gruppo annulla/ripeti/riordina: quelli disfano, questo scrive.\r\n\r\n **Sempre presente, mai nascosto.** Un bottone assente dice \u00ABquesto editor non salva\u00BB; un\r\n bottone disabilitato con il motivo dice \u00ABqui non si salva, ed ecco perche\u2019\u00BB \u2014 ed e\u2019 la\r\n verita\u2019 quando l\u2019host non espone `save()`. La disponibilita\u2019 si sa **prima del clic**\r\n (`core/dpe-capabilities.ts`), non dal primo fallimento.\r\n -->\r\n <div class=\"dpe-shell__group dpe-shell__group--primary\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn dpe-shell__btn--primary\"\r\n [disabled]=\"!canSave()\"\r\n [title]=\"\r\n !validation.isSaveAvailable()\r\n ? 'Salvataggio non disponibile su questo ambiente: l\u2019host non espone save()'\r\n : validation.isSaving()\r\n ? 'Salvataggio in corso'\r\n : !hasKey()\r\n ? 'Il documento non ha un nome: e\u2019 la chiave del catalogo, e va creato da la\u2019 (l\u2019aggiornamento e\u2019 PUT /definitions/{nome})'\r\n : store.isDirty()\r\n ? 'Salva la definizione (Ctrl+S)'\r\n : 'Nessuna modifica da salvare'\r\n \"\r\n (click)=\"validation.save()\"\r\n >\r\n @if (validation.isSaving()) {\r\n \u2913 Salvataggio\u2026\r\n } @else {\r\n \u2913 Salva\r\n }\r\n </button>\r\n @if (validation.justSaved()) {\r\n <!-- Avviso transitorio: il fatto durevole e\u2019 \u00ABnessuna modifica\u00BB nell\u2019indicatore. -->\r\n <span class=\"dpe-shell__toast\" role=\"status\">\u2713 Salvata</span>\r\n }\r\n </div>\r\n\r\n <div class=\"dpe-shell__status\">\r\n @if (validation.isValidating()) {\r\n <span class=\"dpe-shell__pill dpe-shell__pill--busy\">Validazione in corso\u2026</span>\r\n } @else if (validation.error(); as error) {\r\n <!--\r\n Un guasto di trasporto non cancella le diagnostiche precedenti: dire \u00ABva tutto bene\u00BB\r\n quando non lo sappiamo piu\u2019 e\u2019 peggio che mostrare un risultato vecchio dichiarandolo.\r\n -->\r\n <span class=\"dpe-shell__pill dpe-shell__pill--error\" [title]=\"error.message\">\r\n Backend non raggiungibile ({{ error.category }})\r\n </span>\r\n } @else if (store.validateResult()) {\r\n <span\r\n class=\"dpe-shell__pill\"\r\n [class.dpe-shell__pill--error]=\"store.validateResult()!.hasErrors\"\r\n [class.dpe-shell__pill--ok]=\"!store.validateResult()!.hasErrors\"\r\n >\r\n @if (store.validateResult()!.hasErrors) {\r\n Con errori\r\n } @else {\r\n Nessun errore\r\n }\r\n </span>\r\n }\r\n </div>\r\n </header>\r\n\r\n @if (dialectMismatch(); as declared) {\r\n <!--\r\n Disallineamento fra la dichiarazione dell\u2019ambiente e la definizione (ADR 0017). Si nominano\r\n **entrambi** i dialetti e non si offre di correggere: correggere significherebbe migrare le\r\n espressioni SQL native, ed e\u2019 dell\u2019host. Non e\u2019 una regola di dominio duplicata \u2014 non giudica\r\n la definizione, riporta il disaccordo fra due fatti che l\u2019ospite ha fornito.\r\n -->\r\n <div class=\"dpe-shell__warn\" role=\"alert\">\r\n <strong>\r\n L\u2019ambiente dichiara {{ dialectLabels[declared] }}, la definizione e\u2019 scritta per\r\n {{ dialectLabels[dialect()] }}.\r\n </strong>\r\n <p>\r\n Il backend compilera\u2019 con il dialetto <strong>della definizione</strong>. Allinearli e\u2019 una\r\n migrazione delle espressioni SQL native e non si fa da qui.\r\n </p>\r\n </div>\r\n }\r\n\r\n <!--\r\n Il documento ricevuto non e' una definizione. Banner **persistente** e in cima: e' un difetto\r\n dell'integrazione, non dell'utente, e un canvas vuoto da solo non lo dice \u2014 sembra una\r\n definizione senza nodi. Non si nasconde l'editor: cio' che c'e' resta visibile, e il salvataggio\r\n e' disabilitato da se' perche' la chiave manca.\r\n -->\r\n @if (documentProblem(); as problem) {\r\n <div class=\"dpe-shell__warn dpe-shell__warn--error\" role=\"alert\">\r\n <strong>Il documento ricevuto non e\u2019 una definizione: {{ problem }}.</strong>\r\n <p>\r\n L\u2019editor riceve il documento dall\u2019applicazione ospite, e questo non ha la forma di una\r\n <code>DpeDefinition</code>. Le tre cause reali: il backend restituisce l\u2019involucro di lettura\r\n (<code>{{ '{' }} definition, diagnostics {{ '}' }}</code>) invece del documento; l\u2019ospite\r\n passa il <strong>sommario</strong> del catalogo al posto della definizione caricata con\r\n <code>load(nome)</code>; la risposta e\u2019 in PascalCase (<code>Name</code> non e\u2019\r\n <code>name</code>).\r\n </p>\r\n </div>\r\n }\r\n\r\n @if (validation.saveError(); as error) {\r\n <!--\r\n Banner **persistente**: un salvataggio fallito in silenzio e\u2019 peggio di nessun salvataggio,\r\n perche\u2019 l\u2019indicatore \u00ABmodificata\u00BB sparirebbe per un\u2019operazione che non e\u2019 avvenuta. Qui non\r\n sparisce: `markSaved()` viene chiamato solo al successo.\r\n -->\r\n <div class=\"dpe-shell__warn dpe-shell__warn--error\" role=\"alert\">\r\n <strong>Salvataggio non riuscito ({{ error.category }})</strong>\r\n <p>{{ error.message }}</p>\r\n <div class=\"dpe-shell__group\">\r\n <button type=\"button\" class=\"dpe-shell__btn\" (click)=\"validation.dismissSaveError()\">\r\n Ho capito\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"dpe-shell__body\">\r\n <dpe-node-palette class=\"dpe-shell__palette\" (nodeRequested)=\"onNodeRequested($event)\" />\r\n\r\n <dpe-canvas\r\n class=\"dpe-shell__canvas\"\r\n [isEditable]=\"isEditable()\"\r\n (nodeDropped)=\"onNodeDropped($event)\"\r\n />\r\n\r\n <dpe-node-inspector class=\"dpe-shell__inspector\" (layoutRequested)=\"runAutoLayout()\" />\r\n </div>\r\n\r\n <div class=\"dpe-shell__bottom\">\r\n <div class=\"dpe-shell__tabs\" role=\"tablist\" aria-label=\"Pannelli\">\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'diagnostics'\"\r\n [attr.aria-selected]=\"bottomTab() === 'diagnostics'\"\r\n (click)=\"bottomTab.set('diagnostics')\"\r\n >\r\n Diagnostiche\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'schema'\"\r\n [attr.aria-selected]=\"bottomTab() === 'schema'\"\r\n (click)=\"bottomTab.set('schema')\"\r\n >\r\n Schema\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'sql'\"\r\n [attr.aria-selected]=\"bottomTab() === 'sql'\"\r\n (click)=\"bottomTab.set('sql')\"\r\n >\r\n SQL generato\r\n </button>\r\n </div>\r\n\r\n @switch (bottomTab()) {\r\n @case ('diagnostics') {\r\n <dpe-diagnostics-panel class=\"dpe-shell__panel\" (navigate)=\"onNavigate($event)\" />\r\n }\r\n @case ('schema') {\r\n <dpe-schema-panel class=\"dpe-shell__panel\" />\r\n }\r\n @case ('sql') {\r\n <dpe-sql-preview class=\"dpe-shell__panel\" />\r\n }\r\n }\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "component", type: DpeCanvasComponent, selector: "dpe-canvas", inputs: ["isEditable"], outputs: ["nodeOpened", "nodeDropped"] }, { kind: "component", type: DpeDiagnosticsPanelComponent, selector: "dpe-diagnostics-panel", outputs: ["navigate"] }, { kind: "component", type: DpeNodeInspectorComponent, selector: "dpe-node-inspector", outputs: ["layoutRequested"] }, { kind: "component", type: DpeNodePaletteComponent, selector: "dpe-node-palette", outputs: ["nodeRequested"] }, { kind: "component", type: DpeSchemaPanelComponent, selector: "dpe-schema-panel" }, { kind: "component", type: DpeSqlPreviewComponent, selector: "dpe-sql-preview" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9108
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9109
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeBuilderComponent, isStandalone: true, selector: "dpe-builder", inputs: { definition: { classPropertyName: "definition", publicName: "definition", isSignal: true, isRequired: true, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { definitionChange: "definitionChange" }, host: { listeners: { "keydown": "onKeyDown($event)" } }, providers: [DpeDocumentStore, DpeLayoutService, DpeValidationService, DpeMetadataStore], viewQueries: [{ propertyName: "canvas", first: true, predicate: DpeCanvasComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n `.dpe-builder` porta le variabili del tema: e\u2019 la classe radice su cui l\u2019app ospite le\r\n sovrascrive, e `data-dpe-theme=\"dark\"` sul contenitore ridefinisce i soli token.\r\n-->\r\n<div class=\"dpe-builder dpe-shell\">\r\n <header class=\"dpe-shell__bar\">\r\n <div class=\"dpe-shell__title\">\r\n <strong>{{ store.definition().label || store.definition().name || 'Definizione DPE' }}</strong>\r\n <span class=\"dpe-shell__sub\">{{ nodeCount() }} nodi</span>\r\n <!--\r\n Stato **sporco** rispetto all\u2019ultimo salvataggio, non un conteggio di operazioni: serve a\r\n decidere se salvare, e un contatore che sale quando si annulla risponde alla domanda\r\n sbagliata. Annullare fino allo stato di partenza torna qui a \u00ABnessuna modifica\u00BB.\r\n -->\r\n <span\r\n class=\"dpe-shell__dirty\"\r\n [class.dpe-shell__dirty--on]=\"store.isDirty()\"\r\n [title]=\"\r\n store.isDirty()\r\n ? 'Il documento differisce dall\u2019ultimo salvataggio'\r\n : 'Il documento coincide con l\u2019ultimo salvataggio'\r\n \"\r\n >\r\n @if (store.isDirty()) {\r\n \u25CF modificata\r\n } @else {\r\n \u25CB nessuna modifica\r\n }\r\n </span>\r\n </div>\r\n\r\n <!--\r\n Badge in **sola lettura** (ADR 0017): il dialetto e\u2019 dichiarato dall\u2019ambiente, non scelto\r\n qui. Mostra quello della definizione, che e\u2019 quello con cui il backend compilera\u2019 (ADR\r\n 0009). Il titolo dice le due cose che contano \u2014 chi lo decide, e che le espressioni sono\r\n SQL nativo di quel dialetto (ADR 0006).\r\n -->\r\n <span\r\n class=\"dpe-shell__dialect\"\r\n title=\"Il dialetto e\u2019 dichiarato dall\u2019ambiente e non si modifica dall\u2019editor. Le espressioni sono SQL nativo di questo dialetto: la definizione gli appartiene.\"\r\n >\r\n Dialetto \u00B7 <strong>{{ dialectLabels[dialect()] }}</strong>\r\n </span>\r\n\r\n <div class=\"dpe-shell__group\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn\"\r\n [disabled]=\"!store.canUndo()\"\r\n title=\"Annulla (la cronologia e\u2019 una conseguenza dell\u2019immutabilita\u2019 dello stato)\"\r\n (click)=\"store.undo()\"\r\n >\r\n \u21B6 Annulla\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn\"\r\n [disabled]=\"!store.canRedo()\"\r\n title=\"Ripeti\"\r\n (click)=\"store.redo()\"\r\n >\r\n \u21B7 Ripeti\r\n </button>\r\n <button type=\"button\" class=\"dpe-shell__btn\" title=\"Riordina il grafo\" (click)=\"runAutoLayout()\">\r\n \u2317 Riordina\r\n </button>\r\n </div>\r\n\r\n <!--\r\n Salvataggio attraverso il contratto (`DpeBuilderApi.save`, opzionale). E\u2019 il comando\r\n **primario**, separato dal gruppo annulla/ripeti/riordina: quelli disfano, questo scrive.\r\n\r\n **Sempre presente, mai nascosto.** Un bottone assente dice \u00ABquesto editor non salva\u00BB; un\r\n bottone disabilitato con il motivo dice \u00ABqui non si salva, ed ecco perche\u2019\u00BB \u2014 ed e\u2019 la\r\n verita\u2019 quando l\u2019host non espone `save()`. La disponibilita\u2019 si sa **prima del clic**\r\n (`core/dpe-capabilities.ts`), non dal primo fallimento.\r\n -->\r\n <div class=\"dpe-shell__group dpe-shell__group--primary\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn dpe-shell__btn--primary\"\r\n [disabled]=\"!canSave()\"\r\n [title]=\"\r\n !validation.isSaveAvailable()\r\n ? 'Salvataggio non disponibile su questo ambiente: l\u2019host non espone save()'\r\n : validation.isSaving()\r\n ? 'Salvataggio in corso'\r\n : !hasKey()\r\n ? 'Il documento non ha un nome: e\u2019 la chiave del catalogo, e va creato da la\u2019 (l\u2019aggiornamento e\u2019 PUT /definitions/{nome})'\r\n : store.isDirty()\r\n ? 'Salva la definizione (Ctrl+S)'\r\n : 'Nessuna modifica da salvare'\r\n \"\r\n (click)=\"validation.save()\"\r\n >\r\n @if (validation.isSaving()) {\r\n \u2913 Salvataggio\u2026\r\n } @else {\r\n \u2913 Salva\r\n }\r\n </button>\r\n @if (validation.justSaved()) {\r\n <!-- Avviso transitorio: il fatto durevole e\u2019 \u00ABnessuna modifica\u00BB nell\u2019indicatore. -->\r\n <span class=\"dpe-shell__toast\" role=\"status\">\u2713 Salvata</span>\r\n }\r\n </div>\r\n\r\n <div class=\"dpe-shell__status\">\r\n @if (validation.isValidating()) {\r\n <span class=\"dpe-shell__pill dpe-shell__pill--busy\">Validazione in corso\u2026</span>\r\n } @else if (validation.error(); as error) {\r\n <!--\r\n Un guasto di trasporto non cancella le diagnostiche precedenti: dire \u00ABva tutto bene\u00BB\r\n quando non lo sappiamo piu\u2019 e\u2019 peggio che mostrare un risultato vecchio dichiarandolo.\r\n -->\r\n <span class=\"dpe-shell__pill dpe-shell__pill--error\" [title]=\"error.message\">\r\n Backend non raggiungibile ({{ error.category }})\r\n </span>\r\n } @else if (store.validateResult()) {\r\n <span\r\n class=\"dpe-shell__pill\"\r\n [class.dpe-shell__pill--error]=\"store.validateResult()!.hasErrors\"\r\n [class.dpe-shell__pill--ok]=\"!store.validateResult()!.hasErrors\"\r\n >\r\n @if (store.validateResult()!.hasErrors) {\r\n Con errori\r\n } @else {\r\n Nessun errore\r\n }\r\n </span>\r\n }\r\n </div>\r\n </header>\r\n\r\n @if (dialectMismatch(); as declared) {\r\n <!--\r\n Disallineamento fra la dichiarazione dell\u2019ambiente e la definizione (ADR 0017). Si nominano\r\n **entrambi** i dialetti e non si offre di correggere: correggere significherebbe migrare le\r\n espressioni SQL native, ed e\u2019 dell\u2019host. Non e\u2019 una regola di dominio duplicata \u2014 non giudica\r\n la definizione, riporta il disaccordo fra due fatti che l\u2019ospite ha fornito.\r\n -->\r\n <div class=\"dpe-shell__warn\" role=\"alert\">\r\n <strong>\r\n L\u2019ambiente dichiara {{ dialectLabels[declared] }}, la definizione e\u2019 scritta per\r\n {{ dialectLabels[dialect()] }}.\r\n </strong>\r\n <p>\r\n Il backend compilera\u2019 con il dialetto <strong>della definizione</strong>. Allinearli e\u2019 una\r\n migrazione delle espressioni SQL native e non si fa da qui.\r\n </p>\r\n </div>\r\n }\r\n\r\n <!--\r\n Il documento ricevuto non e' una definizione. Banner **persistente** e in cima: e' un difetto\r\n dell'integrazione, non dell'utente, e un canvas vuoto da solo non lo dice \u2014 sembra una\r\n definizione senza nodi. Non si nasconde l'editor: cio' che c'e' resta visibile, e il salvataggio\r\n e' disabilitato da se' perche' la chiave manca.\r\n -->\r\n @if (documentProblem(); as problem) {\r\n <div class=\"dpe-shell__warn dpe-shell__warn--error\" role=\"alert\">\r\n <strong>Il documento ricevuto non e\u2019 una definizione: {{ problem }}.</strong>\r\n <p>\r\n L\u2019editor riceve il documento dall\u2019applicazione ospite, e questo non ha la forma di una\r\n <code>DpeDefinition</code>. Le tre cause reali: il backend restituisce l\u2019involucro di lettura\r\n (<code>{{ '{' }} definition, diagnostics {{ '}' }}</code>) invece del documento; l\u2019ospite\r\n passa il <strong>sommario</strong> del catalogo al posto della definizione caricata con\r\n <code>load(nome)</code>; la risposta e\u2019 in PascalCase (<code>Name</code> non e\u2019\r\n <code>name</code>).\r\n </p>\r\n </div>\r\n }\r\n\r\n @if (validation.saveError(); as error) {\r\n <!--\r\n Banner **persistente**: un salvataggio fallito in silenzio e\u2019 peggio di nessun salvataggio,\r\n perche\u2019 l\u2019indicatore \u00ABmodificata\u00BB sparirebbe per un\u2019operazione che non e\u2019 avvenuta. Qui non\r\n sparisce: `markSaved()` viene chiamato solo al successo.\r\n -->\r\n <div class=\"dpe-shell__warn dpe-shell__warn--error\" role=\"alert\">\r\n <strong>Salvataggio non riuscito ({{ error.category }})</strong>\r\n <p>{{ error.message }}</p>\r\n <div class=\"dpe-shell__group\">\r\n <button type=\"button\" class=\"dpe-shell__btn\" (click)=\"validation.dismissSaveError()\">\r\n Ho capito\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (selectedNames().length > 1) {\r\n <!--\r\n Striscia contestuale della **selezione multipla**. Sta qui, fra i banner di documento e il\r\n corpo, perche' e' un fatto che riguarda l\u2019insieme e non un nodo \u2014 ed e' dove l\u2019occhio guarda\r\n per i fatti dell\u2019insieme. Non mostra i campi di un nodo: mostrarli mentre N sono evidenziati\r\n e' la stessa bugia della doppia evidenziazione, detta piu' piano.\r\n -->\r\n <div class=\"dpe-shell__multi\">\r\n <div class=\"dpe-shell__multi-head\">\r\n <strong>{{ selectedNames().length }} nodi selezionati</strong>\r\n <ul class=\"dpe-multi__names\">\r\n @for (name of selectedNames(); track $index) {\r\n <li class=\"dpe-multi__name\">{{ name }}</li>\r\n }\r\n </ul>\r\n </div>\r\n\r\n <div class=\"dpe-shell__group\">\r\n <button type=\"button\" class=\"dpe-shell__btn\" (click)=\"removeSelectedNodes()\">\r\n Elimina i {{ selectedNames().length }} nodi\r\n </button>\r\n <!--\r\n Il riordino e\u2019 dichiaratamente **dell\u2019intero grafo**: dagre su un sottografo sarebbe una\r\n funzione nuova, e chiamarla \u00ABriordina i selezionati\u00BB mentre riordina tutto sarebbe una\r\n bugia \u2014 la stessa classe di difetto che questa striscia esiste per evitare.\r\n -->\r\n <button type=\"button\" class=\"dpe-shell__btn\" (click)=\"runAutoLayout()\">\r\n Riordina il grafo\r\n </button>\r\n </div>\r\n\r\n <p class=\"dpe-note dpe-note--warning\">\r\n L\u2019eliminazione lascia i riferimenti a valle cos\u00EC come sono: diventano riferimenti rotti, e\r\n il backend li segnala. Si annulla con \u21B6.\r\n </p>\r\n </div>\r\n }\r\n\r\n <div class=\"dpe-shell__body\">\r\n <dpe-node-palette class=\"dpe-shell__palette\" (nodeRequested)=\"onNodeRequested($event)\" />\r\n\r\n <dpe-canvas\r\n class=\"dpe-shell__canvas\"\r\n [isEditable]=\"isEditable()\"\r\n (nodeDropped)=\"onNodeDropped($event)\"\r\n (nodeOpened)=\"onNodeOpened($event)\"\r\n />\r\n </div>\r\n\r\n <!--\r\n **Una sola istanza**, fratello di `.dpe-shell__body`: non dentro il canvas (finirebbe nella\r\n trasformazione CSS di `f-canvas`) e non dentro il corpo (partecipererebbe alla griglia). Non\r\n partecipa al layout: `showModal()` la promuove nel top layer, quindi aprirla non produce\r\n nessun reflow del canvas e non c'e' nessuna inquadratura da rifare.\r\n -->\r\n <dpe-node-dialog />\r\n\r\n <div class=\"dpe-shell__bottom\">\r\n <div class=\"dpe-shell__tabs\" role=\"tablist\" aria-label=\"Pannelli\">\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'diagnostics'\"\r\n [attr.aria-selected]=\"bottomTab() === 'diagnostics'\"\r\n (click)=\"bottomTab.set('diagnostics')\"\r\n >\r\n Diagnostiche\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'schema'\"\r\n [attr.aria-selected]=\"bottomTab() === 'schema'\"\r\n (click)=\"bottomTab.set('schema')\"\r\n >\r\n Schema\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'sql'\"\r\n [attr.aria-selected]=\"bottomTab() === 'sql'\"\r\n (click)=\"bottomTab.set('sql')\"\r\n >\r\n SQL generato\r\n </button>\r\n </div>\r\n\r\n @switch (bottomTab()) {\r\n @case ('diagnostics') {\r\n <dpe-diagnostics-panel class=\"dpe-shell__panel\" (navigate)=\"onNavigate($event)\" />\r\n }\r\n @case ('schema') {\r\n <dpe-schema-panel class=\"dpe-shell__panel\" />\r\n }\r\n @case ('sql') {\r\n <dpe-sql-preview class=\"dpe-shell__panel\" />\r\n }\r\n }\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "component", type: DpeCanvasComponent, selector: "dpe-canvas", inputs: ["isEditable"], outputs: ["nodeOpened", "nodeDropped"] }, { kind: "component", type: DpeDiagnosticsPanelComponent, selector: "dpe-diagnostics-panel", outputs: ["navigate"] }, { kind: "component", type: DpeNodeDialogComponent, selector: "dpe-node-dialog" }, { kind: "component", type: DpeNodePaletteComponent, selector: "dpe-node-palette", outputs: ["nodeRequested"] }, { kind: "component", type: DpeSchemaPanelComponent, selector: "dpe-schema-panel" }, { kind: "component", type: DpeSqlPreviewComponent, selector: "dpe-sql-preview" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8766
9110
|
}
|
|
8767
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
9111
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeBuilderComponent, decorators: [{
|
|
8768
9112
|
type: Component,
|
|
8769
9113
|
args: [{ selector: 'dpe-builder', standalone: true, imports: [
|
|
8770
9114
|
DpeCanvasComponent,
|
|
8771
9115
|
DpeDiagnosticsPanelComponent,
|
|
8772
|
-
|
|
9116
|
+
DpeNodeDialogComponent,
|
|
8773
9117
|
DpeNodePaletteComponent,
|
|
8774
9118
|
DpeSchemaPanelComponent,
|
|
8775
9119
|
DpeSqlPreviewComponent,
|
|
8776
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [DpeDocumentStore, DpeLayoutService, DpeValidationService, DpeMetadataStore], host: { '(keydown)': 'onKeyDown($event)' }, template: "<!--\r\n `.dpe-builder` porta le variabili del tema: e\u2019 la classe radice su cui l\u2019app ospite le\r\n sovrascrive, e `data-dpe-theme=\"dark\"` sul contenitore ridefinisce i soli token.\r\n-->\r\n<div class=\"dpe-builder dpe-shell\">\r\n <header class=\"dpe-shell__bar\">\r\n <div class=\"dpe-shell__title\">\r\n <strong>{{ store.definition().label || store.definition().name || 'Definizione DPE' }}</strong>\r\n <span class=\"dpe-shell__sub\">{{ nodeCount() }} nodi</span>\r\n <!--\r\n Stato **sporco** rispetto all\u2019ultimo salvataggio, non un conteggio di operazioni: serve a\r\n decidere se salvare, e un contatore che sale quando si annulla risponde alla domanda\r\n sbagliata. Annullare fino allo stato di partenza torna qui a \u00ABnessuna modifica\u00BB.\r\n -->\r\n <span\r\n class=\"dpe-shell__dirty\"\r\n [class.dpe-shell__dirty--on]=\"store.isDirty()\"\r\n [title]=\"\r\n store.isDirty()\r\n ? 'Il documento differisce dall\u2019ultimo salvataggio'\r\n : 'Il documento coincide con l\u2019ultimo salvataggio'\r\n \"\r\n >\r\n @if (store.isDirty()) {\r\n \u25CF modificata\r\n } @else {\r\n \u25CB nessuna modifica\r\n }\r\n </span>\r\n </div>\r\n\r\n <!--\r\n Badge in **sola lettura** (ADR 0017): il dialetto e\u2019 dichiarato dall\u2019ambiente, non scelto\r\n qui. Mostra quello della definizione, che e\u2019 quello con cui il backend compilera\u2019 (ADR\r\n 0009). Il titolo dice le due cose che contano \u2014 chi lo decide, e che le espressioni sono\r\n SQL nativo di quel dialetto (ADR 0006).\r\n -->\r\n <span\r\n class=\"dpe-shell__dialect\"\r\n title=\"Il dialetto e\u2019 dichiarato dall\u2019ambiente e non si modifica dall\u2019editor. Le espressioni sono SQL nativo di questo dialetto: la definizione gli appartiene.\"\r\n >\r\n Dialetto \u00B7 <strong>{{ dialectLabels[dialect()] }}</strong>\r\n </span>\r\n\r\n <div class=\"dpe-shell__group\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn\"\r\n [disabled]=\"!store.canUndo()\"\r\n title=\"Annulla (la cronologia e\u2019 una conseguenza dell\u2019immutabilita\u2019 dello stato)\"\r\n (click)=\"store.undo()\"\r\n >\r\n \u21B6 Annulla\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn\"\r\n [disabled]=\"!store.canRedo()\"\r\n title=\"Ripeti\"\r\n (click)=\"store.redo()\"\r\n >\r\n \u21B7 Ripeti\r\n </button>\r\n <button type=\"button\" class=\"dpe-shell__btn\" title=\"Riordina il grafo\" (click)=\"runAutoLayout()\">\r\n \u2317 Riordina\r\n </button>\r\n </div>\r\n\r\n <!--\r\n Salvataggio attraverso il contratto (`DpeBuilderApi.save`, opzionale). E\u2019 il comando\r\n **primario**, separato dal gruppo annulla/ripeti/riordina: quelli disfano, questo scrive.\r\n\r\n **Sempre presente, mai nascosto.** Un bottone assente dice \u00ABquesto editor non salva\u00BB; un\r\n bottone disabilitato con il motivo dice \u00ABqui non si salva, ed ecco perche\u2019\u00BB \u2014 ed e\u2019 la\r\n verita\u2019 quando l\u2019host non espone `save()`. La disponibilita\u2019 si sa **prima del clic**\r\n (`core/dpe-capabilities.ts`), non dal primo fallimento.\r\n -->\r\n <div class=\"dpe-shell__group dpe-shell__group--primary\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn dpe-shell__btn--primary\"\r\n [disabled]=\"!canSave()\"\r\n [title]=\"\r\n !validation.isSaveAvailable()\r\n ? 'Salvataggio non disponibile su questo ambiente: l\u2019host non espone save()'\r\n : validation.isSaving()\r\n ? 'Salvataggio in corso'\r\n : !hasKey()\r\n ? 'Il documento non ha un nome: e\u2019 la chiave del catalogo, e va creato da la\u2019 (l\u2019aggiornamento e\u2019 PUT /definitions/{nome})'\r\n : store.isDirty()\r\n ? 'Salva la definizione (Ctrl+S)'\r\n : 'Nessuna modifica da salvare'\r\n \"\r\n (click)=\"validation.save()\"\r\n >\r\n @if (validation.isSaving()) {\r\n \u2913 Salvataggio\u2026\r\n } @else {\r\n \u2913 Salva\r\n }\r\n </button>\r\n @if (validation.justSaved()) {\r\n <!-- Avviso transitorio: il fatto durevole e\u2019 \u00ABnessuna modifica\u00BB nell\u2019indicatore. -->\r\n <span class=\"dpe-shell__toast\" role=\"status\">\u2713 Salvata</span>\r\n }\r\n </div>\r\n\r\n <div class=\"dpe-shell__status\">\r\n @if (validation.isValidating()) {\r\n <span class=\"dpe-shell__pill dpe-shell__pill--busy\">Validazione in corso\u2026</span>\r\n } @else if (validation.error(); as error) {\r\n <!--\r\n Un guasto di trasporto non cancella le diagnostiche precedenti: dire \u00ABva tutto bene\u00BB\r\n quando non lo sappiamo piu\u2019 e\u2019 peggio che mostrare un risultato vecchio dichiarandolo.\r\n -->\r\n <span class=\"dpe-shell__pill dpe-shell__pill--error\" [title]=\"error.message\">\r\n Backend non raggiungibile ({{ error.category }})\r\n </span>\r\n } @else if (store.validateResult()) {\r\n <span\r\n class=\"dpe-shell__pill\"\r\n [class.dpe-shell__pill--error]=\"store.validateResult()!.hasErrors\"\r\n [class.dpe-shell__pill--ok]=\"!store.validateResult()!.hasErrors\"\r\n >\r\n @if (store.validateResult()!.hasErrors) {\r\n Con errori\r\n } @else {\r\n Nessun errore\r\n }\r\n </span>\r\n }\r\n </div>\r\n </header>\r\n\r\n @if (dialectMismatch(); as declared) {\r\n <!--\r\n Disallineamento fra la dichiarazione dell\u2019ambiente e la definizione (ADR 0017). Si nominano\r\n **entrambi** i dialetti e non si offre di correggere: correggere significherebbe migrare le\r\n espressioni SQL native, ed e\u2019 dell\u2019host. Non e\u2019 una regola di dominio duplicata \u2014 non giudica\r\n la definizione, riporta il disaccordo fra due fatti che l\u2019ospite ha fornito.\r\n -->\r\n <div class=\"dpe-shell__warn\" role=\"alert\">\r\n <strong>\r\n L\u2019ambiente dichiara {{ dialectLabels[declared] }}, la definizione e\u2019 scritta per\r\n {{ dialectLabels[dialect()] }}.\r\n </strong>\r\n <p>\r\n Il backend compilera\u2019 con il dialetto <strong>della definizione</strong>. Allinearli e\u2019 una\r\n migrazione delle espressioni SQL native e non si fa da qui.\r\n </p>\r\n </div>\r\n }\r\n\r\n <!--\r\n Il documento ricevuto non e' una definizione. Banner **persistente** e in cima: e' un difetto\r\n dell'integrazione, non dell'utente, e un canvas vuoto da solo non lo dice \u2014 sembra una\r\n definizione senza nodi. Non si nasconde l'editor: cio' che c'e' resta visibile, e il salvataggio\r\n e' disabilitato da se' perche' la chiave manca.\r\n -->\r\n @if (documentProblem(); as problem) {\r\n <div class=\"dpe-shell__warn dpe-shell__warn--error\" role=\"alert\">\r\n <strong>Il documento ricevuto non e\u2019 una definizione: {{ problem }}.</strong>\r\n <p>\r\n L\u2019editor riceve il documento dall\u2019applicazione ospite, e questo non ha la forma di una\r\n <code>DpeDefinition</code>. Le tre cause reali: il backend restituisce l\u2019involucro di lettura\r\n (<code>{{ '{' }} definition, diagnostics {{ '}' }}</code>) invece del documento; l\u2019ospite\r\n passa il <strong>sommario</strong> del catalogo al posto della definizione caricata con\r\n <code>load(nome)</code>; la risposta e\u2019 in PascalCase (<code>Name</code> non e\u2019\r\n <code>name</code>).\r\n </p>\r\n </div>\r\n }\r\n\r\n @if (validation.saveError(); as error) {\r\n <!--\r\n Banner **persistente**: un salvataggio fallito in silenzio e\u2019 peggio di nessun salvataggio,\r\n perche\u2019 l\u2019indicatore \u00ABmodificata\u00BB sparirebbe per un\u2019operazione che non e\u2019 avvenuta. Qui non\r\n sparisce: `markSaved()` viene chiamato solo al successo.\r\n -->\r\n <div class=\"dpe-shell__warn dpe-shell__warn--error\" role=\"alert\">\r\n <strong>Salvataggio non riuscito ({{ error.category }})</strong>\r\n <p>{{ error.message }}</p>\r\n <div class=\"dpe-shell__group\">\r\n <button type=\"button\" class=\"dpe-shell__btn\" (click)=\"validation.dismissSaveError()\">\r\n Ho capito\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"dpe-shell__body\">\r\n <dpe-node-palette class=\"dpe-shell__palette\" (nodeRequested)=\"onNodeRequested($event)\" />\r\n\r\n <dpe-canvas\r\n class=\"dpe-shell__canvas\"\r\n [isEditable]=\"isEditable()\"\r\n (nodeDropped)=\"onNodeDropped($event)\"\r\n />\r\n\r\n <dpe-node-inspector class=\"dpe-shell__inspector\" (layoutRequested)=\"runAutoLayout()\" />\r\n </div>\r\n\r\n <div class=\"dpe-shell__bottom\">\r\n <div class=\"dpe-shell__tabs\" role=\"tablist\" aria-label=\"Pannelli\">\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'diagnostics'\"\r\n [attr.aria-selected]=\"bottomTab() === 'diagnostics'\"\r\n (click)=\"bottomTab.set('diagnostics')\"\r\n >\r\n Diagnostiche\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'schema'\"\r\n [attr.aria-selected]=\"bottomTab() === 'schema'\"\r\n (click)=\"bottomTab.set('schema')\"\r\n >\r\n Schema\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'sql'\"\r\n [attr.aria-selected]=\"bottomTab() === 'sql'\"\r\n (click)=\"bottomTab.set('sql')\"\r\n >\r\n SQL generato\r\n </button>\r\n </div>\r\n\r\n @switch (bottomTab()) {\r\n @case ('diagnostics') {\r\n <dpe-diagnostics-panel class=\"dpe-shell__panel\" (navigate)=\"onNavigate($event)\" />\r\n }\r\n @case ('schema') {\r\n <dpe-schema-panel class=\"dpe-shell__panel\" />\r\n }\r\n @case ('sql') {\r\n <dpe-sql-preview class=\"dpe-shell__panel\" />\r\n }\r\n }\r\n </div>\r\n</div>\r\n" }]
|
|
9120
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [DpeDocumentStore, DpeLayoutService, DpeValidationService, DpeMetadataStore], host: { '(keydown)': 'onKeyDown($event)' }, template: "<!--\r\n `.dpe-builder` porta le variabili del tema: e\u2019 la classe radice su cui l\u2019app ospite le\r\n sovrascrive, e `data-dpe-theme=\"dark\"` sul contenitore ridefinisce i soli token.\r\n-->\r\n<div class=\"dpe-builder dpe-shell\">\r\n <header class=\"dpe-shell__bar\">\r\n <div class=\"dpe-shell__title\">\r\n <strong>{{ store.definition().label || store.definition().name || 'Definizione DPE' }}</strong>\r\n <span class=\"dpe-shell__sub\">{{ nodeCount() }} nodi</span>\r\n <!--\r\n Stato **sporco** rispetto all\u2019ultimo salvataggio, non un conteggio di operazioni: serve a\r\n decidere se salvare, e un contatore che sale quando si annulla risponde alla domanda\r\n sbagliata. Annullare fino allo stato di partenza torna qui a \u00ABnessuna modifica\u00BB.\r\n -->\r\n <span\r\n class=\"dpe-shell__dirty\"\r\n [class.dpe-shell__dirty--on]=\"store.isDirty()\"\r\n [title]=\"\r\n store.isDirty()\r\n ? 'Il documento differisce dall\u2019ultimo salvataggio'\r\n : 'Il documento coincide con l\u2019ultimo salvataggio'\r\n \"\r\n >\r\n @if (store.isDirty()) {\r\n \u25CF modificata\r\n } @else {\r\n \u25CB nessuna modifica\r\n }\r\n </span>\r\n </div>\r\n\r\n <!--\r\n Badge in **sola lettura** (ADR 0017): il dialetto e\u2019 dichiarato dall\u2019ambiente, non scelto\r\n qui. Mostra quello della definizione, che e\u2019 quello con cui il backend compilera\u2019 (ADR\r\n 0009). Il titolo dice le due cose che contano \u2014 chi lo decide, e che le espressioni sono\r\n SQL nativo di quel dialetto (ADR 0006).\r\n -->\r\n <span\r\n class=\"dpe-shell__dialect\"\r\n title=\"Il dialetto e\u2019 dichiarato dall\u2019ambiente e non si modifica dall\u2019editor. Le espressioni sono SQL nativo di questo dialetto: la definizione gli appartiene.\"\r\n >\r\n Dialetto \u00B7 <strong>{{ dialectLabels[dialect()] }}</strong>\r\n </span>\r\n\r\n <div class=\"dpe-shell__group\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn\"\r\n [disabled]=\"!store.canUndo()\"\r\n title=\"Annulla (la cronologia e\u2019 una conseguenza dell\u2019immutabilita\u2019 dello stato)\"\r\n (click)=\"store.undo()\"\r\n >\r\n \u21B6 Annulla\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn\"\r\n [disabled]=\"!store.canRedo()\"\r\n title=\"Ripeti\"\r\n (click)=\"store.redo()\"\r\n >\r\n \u21B7 Ripeti\r\n </button>\r\n <button type=\"button\" class=\"dpe-shell__btn\" title=\"Riordina il grafo\" (click)=\"runAutoLayout()\">\r\n \u2317 Riordina\r\n </button>\r\n </div>\r\n\r\n <!--\r\n Salvataggio attraverso il contratto (`DpeBuilderApi.save`, opzionale). E\u2019 il comando\r\n **primario**, separato dal gruppo annulla/ripeti/riordina: quelli disfano, questo scrive.\r\n\r\n **Sempre presente, mai nascosto.** Un bottone assente dice \u00ABquesto editor non salva\u00BB; un\r\n bottone disabilitato con il motivo dice \u00ABqui non si salva, ed ecco perche\u2019\u00BB \u2014 ed e\u2019 la\r\n verita\u2019 quando l\u2019host non espone `save()`. La disponibilita\u2019 si sa **prima del clic**\r\n (`core/dpe-capabilities.ts`), non dal primo fallimento.\r\n -->\r\n <div class=\"dpe-shell__group dpe-shell__group--primary\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-shell__btn dpe-shell__btn--primary\"\r\n [disabled]=\"!canSave()\"\r\n [title]=\"\r\n !validation.isSaveAvailable()\r\n ? 'Salvataggio non disponibile su questo ambiente: l\u2019host non espone save()'\r\n : validation.isSaving()\r\n ? 'Salvataggio in corso'\r\n : !hasKey()\r\n ? 'Il documento non ha un nome: e\u2019 la chiave del catalogo, e va creato da la\u2019 (l\u2019aggiornamento e\u2019 PUT /definitions/{nome})'\r\n : store.isDirty()\r\n ? 'Salva la definizione (Ctrl+S)'\r\n : 'Nessuna modifica da salvare'\r\n \"\r\n (click)=\"validation.save()\"\r\n >\r\n @if (validation.isSaving()) {\r\n \u2913 Salvataggio\u2026\r\n } @else {\r\n \u2913 Salva\r\n }\r\n </button>\r\n @if (validation.justSaved()) {\r\n <!-- Avviso transitorio: il fatto durevole e\u2019 \u00ABnessuna modifica\u00BB nell\u2019indicatore. -->\r\n <span class=\"dpe-shell__toast\" role=\"status\">\u2713 Salvata</span>\r\n }\r\n </div>\r\n\r\n <div class=\"dpe-shell__status\">\r\n @if (validation.isValidating()) {\r\n <span class=\"dpe-shell__pill dpe-shell__pill--busy\">Validazione in corso\u2026</span>\r\n } @else if (validation.error(); as error) {\r\n <!--\r\n Un guasto di trasporto non cancella le diagnostiche precedenti: dire \u00ABva tutto bene\u00BB\r\n quando non lo sappiamo piu\u2019 e\u2019 peggio che mostrare un risultato vecchio dichiarandolo.\r\n -->\r\n <span class=\"dpe-shell__pill dpe-shell__pill--error\" [title]=\"error.message\">\r\n Backend non raggiungibile ({{ error.category }})\r\n </span>\r\n } @else if (store.validateResult()) {\r\n <span\r\n class=\"dpe-shell__pill\"\r\n [class.dpe-shell__pill--error]=\"store.validateResult()!.hasErrors\"\r\n [class.dpe-shell__pill--ok]=\"!store.validateResult()!.hasErrors\"\r\n >\r\n @if (store.validateResult()!.hasErrors) {\r\n Con errori\r\n } @else {\r\n Nessun errore\r\n }\r\n </span>\r\n }\r\n </div>\r\n </header>\r\n\r\n @if (dialectMismatch(); as declared) {\r\n <!--\r\n Disallineamento fra la dichiarazione dell\u2019ambiente e la definizione (ADR 0017). Si nominano\r\n **entrambi** i dialetti e non si offre di correggere: correggere significherebbe migrare le\r\n espressioni SQL native, ed e\u2019 dell\u2019host. Non e\u2019 una regola di dominio duplicata \u2014 non giudica\r\n la definizione, riporta il disaccordo fra due fatti che l\u2019ospite ha fornito.\r\n -->\r\n <div class=\"dpe-shell__warn\" role=\"alert\">\r\n <strong>\r\n L\u2019ambiente dichiara {{ dialectLabels[declared] }}, la definizione e\u2019 scritta per\r\n {{ dialectLabels[dialect()] }}.\r\n </strong>\r\n <p>\r\n Il backend compilera\u2019 con il dialetto <strong>della definizione</strong>. Allinearli e\u2019 una\r\n migrazione delle espressioni SQL native e non si fa da qui.\r\n </p>\r\n </div>\r\n }\r\n\r\n <!--\r\n Il documento ricevuto non e' una definizione. Banner **persistente** e in cima: e' un difetto\r\n dell'integrazione, non dell'utente, e un canvas vuoto da solo non lo dice \u2014 sembra una\r\n definizione senza nodi. Non si nasconde l'editor: cio' che c'e' resta visibile, e il salvataggio\r\n e' disabilitato da se' perche' la chiave manca.\r\n -->\r\n @if (documentProblem(); as problem) {\r\n <div class=\"dpe-shell__warn dpe-shell__warn--error\" role=\"alert\">\r\n <strong>Il documento ricevuto non e\u2019 una definizione: {{ problem }}.</strong>\r\n <p>\r\n L\u2019editor riceve il documento dall\u2019applicazione ospite, e questo non ha la forma di una\r\n <code>DpeDefinition</code>. Le tre cause reali: il backend restituisce l\u2019involucro di lettura\r\n (<code>{{ '{' }} definition, diagnostics {{ '}' }}</code>) invece del documento; l\u2019ospite\r\n passa il <strong>sommario</strong> del catalogo al posto della definizione caricata con\r\n <code>load(nome)</code>; la risposta e\u2019 in PascalCase (<code>Name</code> non e\u2019\r\n <code>name</code>).\r\n </p>\r\n </div>\r\n }\r\n\r\n @if (validation.saveError(); as error) {\r\n <!--\r\n Banner **persistente**: un salvataggio fallito in silenzio e\u2019 peggio di nessun salvataggio,\r\n perche\u2019 l\u2019indicatore \u00ABmodificata\u00BB sparirebbe per un\u2019operazione che non e\u2019 avvenuta. Qui non\r\n sparisce: `markSaved()` viene chiamato solo al successo.\r\n -->\r\n <div class=\"dpe-shell__warn dpe-shell__warn--error\" role=\"alert\">\r\n <strong>Salvataggio non riuscito ({{ error.category }})</strong>\r\n <p>{{ error.message }}</p>\r\n <div class=\"dpe-shell__group\">\r\n <button type=\"button\" class=\"dpe-shell__btn\" (click)=\"validation.dismissSaveError()\">\r\n Ho capito\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (selectedNames().length > 1) {\r\n <!--\r\n Striscia contestuale della **selezione multipla**. Sta qui, fra i banner di documento e il\r\n corpo, perche' e' un fatto che riguarda l\u2019insieme e non un nodo \u2014 ed e' dove l\u2019occhio guarda\r\n per i fatti dell\u2019insieme. Non mostra i campi di un nodo: mostrarli mentre N sono evidenziati\r\n e' la stessa bugia della doppia evidenziazione, detta piu' piano.\r\n -->\r\n <div class=\"dpe-shell__multi\">\r\n <div class=\"dpe-shell__multi-head\">\r\n <strong>{{ selectedNames().length }} nodi selezionati</strong>\r\n <ul class=\"dpe-multi__names\">\r\n @for (name of selectedNames(); track $index) {\r\n <li class=\"dpe-multi__name\">{{ name }}</li>\r\n }\r\n </ul>\r\n </div>\r\n\r\n <div class=\"dpe-shell__group\">\r\n <button type=\"button\" class=\"dpe-shell__btn\" (click)=\"removeSelectedNodes()\">\r\n Elimina i {{ selectedNames().length }} nodi\r\n </button>\r\n <!--\r\n Il riordino e\u2019 dichiaratamente **dell\u2019intero grafo**: dagre su un sottografo sarebbe una\r\n funzione nuova, e chiamarla \u00ABriordina i selezionati\u00BB mentre riordina tutto sarebbe una\r\n bugia \u2014 la stessa classe di difetto che questa striscia esiste per evitare.\r\n -->\r\n <button type=\"button\" class=\"dpe-shell__btn\" (click)=\"runAutoLayout()\">\r\n Riordina il grafo\r\n </button>\r\n </div>\r\n\r\n <p class=\"dpe-note dpe-note--warning\">\r\n L\u2019eliminazione lascia i riferimenti a valle cos\u00EC come sono: diventano riferimenti rotti, e\r\n il backend li segnala. Si annulla con \u21B6.\r\n </p>\r\n </div>\r\n }\r\n\r\n <div class=\"dpe-shell__body\">\r\n <dpe-node-palette class=\"dpe-shell__palette\" (nodeRequested)=\"onNodeRequested($event)\" />\r\n\r\n <dpe-canvas\r\n class=\"dpe-shell__canvas\"\r\n [isEditable]=\"isEditable()\"\r\n (nodeDropped)=\"onNodeDropped($event)\"\r\n (nodeOpened)=\"onNodeOpened($event)\"\r\n />\r\n </div>\r\n\r\n <!--\r\n **Una sola istanza**, fratello di `.dpe-shell__body`: non dentro il canvas (finirebbe nella\r\n trasformazione CSS di `f-canvas`) e non dentro il corpo (partecipererebbe alla griglia). Non\r\n partecipa al layout: `showModal()` la promuove nel top layer, quindi aprirla non produce\r\n nessun reflow del canvas e non c'e' nessuna inquadratura da rifare.\r\n -->\r\n <dpe-node-dialog />\r\n\r\n <div class=\"dpe-shell__bottom\">\r\n <div class=\"dpe-shell__tabs\" role=\"tablist\" aria-label=\"Pannelli\">\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'diagnostics'\"\r\n [attr.aria-selected]=\"bottomTab() === 'diagnostics'\"\r\n (click)=\"bottomTab.set('diagnostics')\"\r\n >\r\n Diagnostiche\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'schema'\"\r\n [attr.aria-selected]=\"bottomTab() === 'schema'\"\r\n (click)=\"bottomTab.set('schema')\"\r\n >\r\n Schema\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"dpe-shell__tab\"\r\n [class.dpe-shell__tab--active]=\"bottomTab() === 'sql'\"\r\n [attr.aria-selected]=\"bottomTab() === 'sql'\"\r\n (click)=\"bottomTab.set('sql')\"\r\n >\r\n SQL generato\r\n </button>\r\n </div>\r\n\r\n @switch (bottomTab()) {\r\n @case ('diagnostics') {\r\n <dpe-diagnostics-panel class=\"dpe-shell__panel\" (navigate)=\"onNavigate($event)\" />\r\n }\r\n @case ('schema') {\r\n <dpe-schema-panel class=\"dpe-shell__panel\" />\r\n }\r\n @case ('sql') {\r\n <dpe-sql-preview class=\"dpe-shell__panel\" />\r\n }\r\n }\r\n </div>\r\n</div>\r\n" }]
|
|
8777
9121
|
}], ctorParameters: () => [], propDecorators: { definition: [{ type: i0.Input, args: [{ isSignal: true, alias: "definition", required: true }] }], isEditable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditable", required: false }] }], definitionChange: [{ type: i0.Output, args: ["definitionChange"] }], canvas: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DpeCanvasComponent), { isSignal: true }] }] } });
|
|
8778
9122
|
|
|
8779
9123
|
/**
|
|
@@ -8918,10 +9262,10 @@ class DpeCatalogComponent {
|
|
|
8918
9262
|
const parsed = new Date(value);
|
|
8919
9263
|
return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleDateString();
|
|
8920
9264
|
}
|
|
8921
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
8922
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.27", type: DpeCatalogComponent, isStandalone: true, selector: "dpe-catalog", outputs: { open: "open" }, providers: [DpeCatalogStore], viewQueries: [{ propertyName: "duplicateNameField", first: true, predicate: ["duplicateNameField"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n `.dpe-theme` porta le variabili del tema anche fuori dall\u2019editor: il catalogo e\u2019 un componente\r\n **fratello**, quindi non puo\u2019 contare sulla classe radice di `<dpe-builder>`. La variante scura\r\n resta quella prevista, `data-dpe-theme=\"dark\"` su un contenitore dell\u2019ospite.\r\n-->\r\n<section class=\"dpe-theme dpe-cat\" aria-labelledby=\"dpe-cat-title\">\r\n <header class=\"dpe-cat__bar\">\r\n <h2 class=\"dpe-cat__title\" id=\"dpe-cat-title\">Definizioni DPE</h2>\r\n\r\n <span class=\"dpe-cat__count\">\r\n @if (store.isLoading()) {\r\n caricamento\u2026\r\n } @else if (!store.capabilities.listDefinitions) {\r\n elenco non disponibile\r\n } @else {\r\n {{ visible().length }} di {{ store.summaries().length }}\r\n }\r\n </span>\r\n\r\n <input\r\n class=\"dpe-cat__filter\"\r\n type=\"search\"\r\n placeholder=\"Filtra per nome o etichetta\"\r\n aria-label=\"Filtra le definizioni\"\r\n [value]=\"filter()\"\r\n (input)=\"filter.set($any($event.target).value)\"\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!store.capabilities.listDefinitions || store.isLoading()\"\r\n [title]=\"\r\n store.capabilities.listDefinitions\r\n ? 'Ricarica l\u2019elenco'\r\n : 'Questo ambiente non implementa listDefinitions.'\r\n \"\r\n (click)=\"refresh()\"\r\n >\r\n \u27F3 Aggiorna\r\n </button>\r\n </header>\r\n\r\n @if (store.error(); as error) {\r\n <!--\r\n Banner persistente: un errore di catalogo che svanisce lascia un elenco vecchio senza dire\r\n che e\u2019 vecchio. La categoria si mostra perche\u2019 distingue \u00ABriprova\u00BB da \u00ABchiedi all\u2019ospite\u00BB.\r\n -->\r\n <p class=\"dpe-cat__error\" role=\"alert\">\r\n <strong>{{ error.category }}</strong> {{ error.message }}\r\n <button type=\"button\" class=\"dpe-cat__dismiss\" aria-label=\"Chiudi\" (click)=\"store.dismissError()\">\r\n \u00D7\r\n </button>\r\n </p>\r\n }\r\n\r\n <ul class=\"dpe-cat__list\">\r\n @for (summary of visible(); track summary.name) {\r\n <li class=\"dpe-cat__item\" [class.dpe-cat__item--busy]=\"store.isMutating()\">\r\n <div class=\"dpe-cat__row\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__open\"\r\n [title]=\"'Apri ' + summary.label\"\r\n (click)=\"onOpen(summary.name)\"\r\n >\r\n <span class=\"dpe-cat__label\">{{ summary.label }}</span>\r\n <span class=\"dpe-cat__meta\">\r\n <!--\r\n Solo i fatti **presenti**: cio\u2019 che il sommario non porta non si stima. Contare i\r\n nodi lato client vorrebbe dire caricare tutte le definizioni per disegnare un\r\n elenco (ADR 0019).\r\n -->\r\n <code class=\"dpe-cat__name\">{{ summary.name }}</code>\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ dialectLabels[summary.dialect] }}\r\n @if (summary.status) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.status === 'Active' ? 'attiva' : 'non attiva' }}\r\n }\r\n @if (summary.runMode) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.runMode === 'Batch' ? 'batch' : 'a richiesta' }}\r\n }\r\n @if (summary.isTemplate) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n modello\r\n }\r\n @if (summary.nodeCount !== undefined) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.nodeCount }} {{ summary.nodeCount === 1 ? 'nodo' : 'nodi' }}\r\n }\r\n @if (summary.updatedAt) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ formatDate(summary.updatedAt) }}\r\n @if (summary.updatedBy) {\r\n \u00B7 {{ summary.updatedBy }}\r\n }\r\n }\r\n </span>\r\n @if (summary.description) {\r\n <span class=\"dpe-cat__desc\">{{ summary.description }}</span>\r\n }\r\n </button>\r\n\r\n <!--\r\n `hasErrors` e\u2019 **riportato, non ricalcolato** (ADR 0019): il frontend non valida\r\n niente. Per questo l\u2019etichetta dice \u00ABultima validazione nota\u00BB e non \u00ABinvalida\u00BB: puo\u2019\r\n essere vecchia, e spacciarla per verita\u2019 sarebbe una validazione fatta dal client per\r\n interposta persona. Assente, non compare nulla.\r\n -->\r\n @if (summary.hasErrors !== undefined) {\r\n <span\r\n class=\"dpe-cat__flag\"\r\n [class.dpe-cat__flag--errors]=\"summary.hasErrors\"\r\n [title]=\"\r\n summary.hasErrors\r\n ? 'Ultima validazione nota all\u2019ambiente: con errori. E\u2019 uno stato riportato, non ricalcolato qui.'\r\n : 'Ultima validazione nota all\u2019ambiente: senza errori. E\u2019 uno stato riportato, non ricalcolato qui.'\r\n \"\r\n >\r\n {{ summary.hasErrors ? 'con errori (stato noto)' : 'senza errori (stato noto)' }}\r\n </span>\r\n }\r\n\r\n <div class=\"dpe-cat__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!canDuplicate() || store.isMutating()\"\r\n [title]=\"duplicateReason()\"\r\n (click)=\"startDuplicate(summary)\"\r\n >\r\n Duplica\r\n </button>\r\n\r\n @if (pendingDelete() === summary.name) {\r\n <!-- Conferma in **due passi**: la prima pressione chiede, la seconda cancella. -->\r\n <span class=\"dpe-cat__confirm\">\r\n Eliminare \u00AB{{ summary.name }}\u00BB?\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--danger\"\r\n (click)=\"confirmDelete(summary.name)\"\r\n >\r\n Elimina\r\n </button>\r\n <button type=\"button\" class=\"dpe-cat__btn\" (click)=\"cancelDelete()\">Annulla</button>\r\n </span>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!store.capabilities.deleteDefinition || store.isMutating()\"\r\n [title]=\"\r\n store.capabilities.deleteDefinition\r\n ? 'Elimina (chiede conferma)'\r\n : 'Eliminazione non disponibile: questo ambiente non implementa deleteDefinition.'\r\n \"\r\n (click)=\"askDelete(summary.name)\"\r\n >\r\n Elimina\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (duplicateSource() === summary.name) {\r\n <!--\r\n Duplicare e\u2019 `load` piu\u2019 `createDefinition`: nessuna primitiva nuova sul contratto.\r\n Il dialetto resta quello della definizione copiata \u2014 le espressioni sono SQL nativo.\r\n -->\r\n <div class=\"dpe-cat__form dpe-cat__form--inline\">\r\n <label class=\"dpe-cat__field\">\r\n <span>Nome della copia</span>\r\n <input\r\n #duplicateNameField\r\n class=\"dpe-cat__input\"\r\n [value]=\"duplicateName()\"\r\n (input)=\"duplicateName.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <label class=\"dpe-cat__field\">\r\n <span>Etichetta della copia</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n [value]=\"duplicateLabel()\"\r\n (input)=\"duplicateLabel.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--primary\"\r\n [disabled]=\"!canSubmitDuplicate()\"\r\n (click)=\"confirmDuplicate()\"\r\n >\r\n Duplica\r\n </button>\r\n <button type=\"button\" class=\"dpe-cat__btn\" (click)=\"cancelDuplicate()\">Annulla</button>\r\n </div>\r\n }\r\n </li>\r\n } @empty {\r\n <li class=\"dpe-cat__empty\">\r\n @if (!store.capabilities.listDefinitions) {\r\n Questo ambiente non implementa <code>listDefinitions</code>: l\u2019elenco lo fornisce\r\n l\u2019applicazione ospite.\r\n } @else if (store.isLoading()) {\r\n Caricamento dell\u2019elenco\u2026\r\n } @else if (isFilteredEmpty()) {\r\n Nessuna definizione corrisponde al filtro.\r\n } @else if (store.hasLoaded()) {\r\n Nessuna definizione. Creane una qui sotto.\r\n } @else {\r\n Elenco non disponibile.\r\n }\r\n </li>\r\n }\r\n </ul>\r\n\r\n <footer class=\"dpe-cat__foot\">\r\n <div class=\"dpe-cat__form\">\r\n <label class=\"dpe-cat__field\">\r\n <span>Nome tecnico</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n placeholder=\"RiepilogoOrdini\"\r\n [value]=\"newName()\"\r\n [disabled]=\"!store.createCommand.isAvailable\"\r\n (input)=\"newName.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <label class=\"dpe-cat__field\">\r\n <!--\r\n Si chiedono **due** campi e non uno: passare il nome anche come etichetta produce per\r\n sempre un catalogo di nomi tecnici, e un default sbagliato non si corregge piu\u2019.\r\n -->\r\n <span>Etichetta</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n placeholder=\"Riepilogo ordini\"\r\n [value]=\"newLabel()\"\r\n [disabled]=\"!store.createCommand.isAvailable\"\r\n (input)=\"newLabel.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--primary\"\r\n [disabled]=\"!canSubmitNew()\"\r\n [title]=\"\r\n store.createCommand.reason ??\r\n 'Crea la definizione e la apre. Il dialetto viene dall\u2019ambiente, non si sceglie qui.'\r\n \"\r\n (click)=\"createNew()\"\r\n >\r\n + Crea e apri\r\n </button>\r\n </div>\r\n\r\n <p class=\"dpe-cat__hint\">\r\n @if (store.createCommand.isAvailable) {\r\n <!--\r\n Detto **al momento della creazione**, non lasciato scoprire: una definizione nuova non\r\n ha sorgenti ne\u2019 writeback, quindi l\u2019editor la segnalera\u2019 invalida. E\u2019 normale \u2014 il\r\n modello tollera l\u2019incompleto e la validazione lo racconta.\r\n -->\r\n Il dialetto della definizione nuova e\u2019 quello dichiarato dall\u2019ambiente\r\n @if (store.environmentDialect(); as declared) {\r\n (<strong>{{ dialectLabels[declared] }}</strong>)\r\n }\r\n e non si sceglie qui: le espressioni sono SQL nativo di quel dialetto. Una definizione appena creata\r\n e\u2019 <strong>invalida</strong> \u2014 servono almeno una sorgente e un writeback \u2014 ed e\u2019 normale.\r\n } @else {\r\n {{ store.createCommand.reason }}\r\n }\r\n </p>\r\n </footer>\r\n</section>\r\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9265
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCatalogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9266
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: DpeCatalogComponent, isStandalone: true, selector: "dpe-catalog", outputs: { open: "open" }, providers: [DpeCatalogStore], viewQueries: [{ propertyName: "duplicateNameField", first: true, predicate: ["duplicateNameField"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n `.dpe-theme` porta le variabili del tema anche fuori dall\u2019editor: il catalogo e\u2019 un componente\r\n **fratello**, quindi non puo\u2019 contare sulla classe radice di `<dpe-builder>`. La variante scura\r\n resta quella prevista, `data-dpe-theme=\"dark\"` su un contenitore dell\u2019ospite.\r\n-->\r\n<section class=\"dpe-theme dpe-cat\" aria-labelledby=\"dpe-cat-title\">\r\n <header class=\"dpe-cat__bar\">\r\n <h2 class=\"dpe-cat__title\" id=\"dpe-cat-title\">Definizioni DPE</h2>\r\n\r\n <span class=\"dpe-cat__count\">\r\n @if (store.isLoading()) {\r\n caricamento\u2026\r\n } @else if (!store.capabilities.listDefinitions) {\r\n elenco non disponibile\r\n } @else {\r\n {{ visible().length }} di {{ store.summaries().length }}\r\n }\r\n </span>\r\n\r\n <input\r\n class=\"dpe-cat__filter\"\r\n type=\"search\"\r\n placeholder=\"Filtra per nome o etichetta\"\r\n aria-label=\"Filtra le definizioni\"\r\n [value]=\"filter()\"\r\n (input)=\"filter.set($any($event.target).value)\"\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!store.capabilities.listDefinitions || store.isLoading()\"\r\n [title]=\"\r\n store.capabilities.listDefinitions\r\n ? 'Ricarica l\u2019elenco'\r\n : 'Questo ambiente non implementa listDefinitions.'\r\n \"\r\n (click)=\"refresh()\"\r\n >\r\n \u27F3 Aggiorna\r\n </button>\r\n </header>\r\n\r\n @if (store.error(); as error) {\r\n <!--\r\n Banner persistente: un errore di catalogo che svanisce lascia un elenco vecchio senza dire\r\n che e\u2019 vecchio. La categoria si mostra perche\u2019 distingue \u00ABriprova\u00BB da \u00ABchiedi all\u2019ospite\u00BB.\r\n -->\r\n <p class=\"dpe-cat__error\" role=\"alert\">\r\n <strong>{{ error.category }}</strong> {{ error.message }}\r\n <button type=\"button\" class=\"dpe-cat__dismiss\" aria-label=\"Chiudi\" (click)=\"store.dismissError()\">\r\n \u00D7\r\n </button>\r\n </p>\r\n }\r\n\r\n <ul class=\"dpe-cat__list\">\r\n @for (summary of visible(); track summary.name) {\r\n <li class=\"dpe-cat__item\" [class.dpe-cat__item--busy]=\"store.isMutating()\">\r\n <div class=\"dpe-cat__row\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__open\"\r\n [title]=\"'Apri ' + summary.label\"\r\n (click)=\"onOpen(summary.name)\"\r\n >\r\n <span class=\"dpe-cat__label\">{{ summary.label }}</span>\r\n <span class=\"dpe-cat__meta\">\r\n <!--\r\n Solo i fatti **presenti**: cio\u2019 che il sommario non porta non si stima. Contare i\r\n nodi lato client vorrebbe dire caricare tutte le definizioni per disegnare un\r\n elenco (ADR 0019).\r\n -->\r\n <code class=\"dpe-cat__name\">{{ summary.name }}</code>\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ dialectLabels[summary.dialect] }}\r\n @if (summary.status) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.status === 'Active' ? 'attiva' : 'non attiva' }}\r\n }\r\n @if (summary.runMode) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.runMode === 'Batch' ? 'batch' : 'a richiesta' }}\r\n }\r\n @if (summary.isTemplate) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n modello\r\n }\r\n @if (summary.nodeCount !== undefined) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.nodeCount }} {{ summary.nodeCount === 1 ? 'nodo' : 'nodi' }}\r\n }\r\n @if (summary.updatedAt) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ formatDate(summary.updatedAt) }}\r\n @if (summary.updatedBy) {\r\n \u00B7 {{ summary.updatedBy }}\r\n }\r\n }\r\n </span>\r\n @if (summary.description) {\r\n <span class=\"dpe-cat__desc\">{{ summary.description }}</span>\r\n }\r\n </button>\r\n\r\n <!--\r\n `hasErrors` e\u2019 **riportato, non ricalcolato** (ADR 0019): il frontend non valida\r\n niente. Per questo l\u2019etichetta dice \u00ABultima validazione nota\u00BB e non \u00ABinvalida\u00BB: puo\u2019\r\n essere vecchia, e spacciarla per verita\u2019 sarebbe una validazione fatta dal client per\r\n interposta persona. Assente, non compare nulla.\r\n -->\r\n @if (summary.hasErrors !== undefined) {\r\n <span\r\n class=\"dpe-cat__flag\"\r\n [class.dpe-cat__flag--errors]=\"summary.hasErrors\"\r\n [title]=\"\r\n summary.hasErrors\r\n ? 'Ultima validazione nota all\u2019ambiente: con errori. E\u2019 uno stato riportato, non ricalcolato qui.'\r\n : 'Ultima validazione nota all\u2019ambiente: senza errori. E\u2019 uno stato riportato, non ricalcolato qui.'\r\n \"\r\n >\r\n {{ summary.hasErrors ? 'con errori (stato noto)' : 'senza errori (stato noto)' }}\r\n </span>\r\n }\r\n\r\n <div class=\"dpe-cat__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!canDuplicate() || store.isMutating()\"\r\n [title]=\"duplicateReason()\"\r\n (click)=\"startDuplicate(summary)\"\r\n >\r\n Duplica\r\n </button>\r\n\r\n @if (pendingDelete() === summary.name) {\r\n <!-- Conferma in **due passi**: la prima pressione chiede, la seconda cancella. -->\r\n <span class=\"dpe-cat__confirm\">\r\n Eliminare \u00AB{{ summary.name }}\u00BB?\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--danger\"\r\n (click)=\"confirmDelete(summary.name)\"\r\n >\r\n Elimina\r\n </button>\r\n <button type=\"button\" class=\"dpe-cat__btn\" (click)=\"cancelDelete()\">Annulla</button>\r\n </span>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!store.capabilities.deleteDefinition || store.isMutating()\"\r\n [title]=\"\r\n store.capabilities.deleteDefinition\r\n ? 'Elimina (chiede conferma)'\r\n : 'Eliminazione non disponibile: questo ambiente non implementa deleteDefinition.'\r\n \"\r\n (click)=\"askDelete(summary.name)\"\r\n >\r\n Elimina\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (duplicateSource() === summary.name) {\r\n <!--\r\n Duplicare e\u2019 `load` piu\u2019 `createDefinition`: nessuna primitiva nuova sul contratto.\r\n Il dialetto resta quello della definizione copiata \u2014 le espressioni sono SQL nativo.\r\n -->\r\n <div class=\"dpe-cat__form dpe-cat__form--inline\">\r\n <label class=\"dpe-cat__field\">\r\n <span>Nome della copia</span>\r\n <input\r\n #duplicateNameField\r\n class=\"dpe-cat__input\"\r\n [value]=\"duplicateName()\"\r\n (input)=\"duplicateName.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <label class=\"dpe-cat__field\">\r\n <span>Etichetta della copia</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n [value]=\"duplicateLabel()\"\r\n (input)=\"duplicateLabel.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--primary\"\r\n [disabled]=\"!canSubmitDuplicate()\"\r\n (click)=\"confirmDuplicate()\"\r\n >\r\n Duplica\r\n </button>\r\n <button type=\"button\" class=\"dpe-cat__btn\" (click)=\"cancelDuplicate()\">Annulla</button>\r\n </div>\r\n }\r\n </li>\r\n } @empty {\r\n <li class=\"dpe-cat__empty\">\r\n @if (!store.capabilities.listDefinitions) {\r\n Questo ambiente non implementa <code>listDefinitions</code>: l\u2019elenco lo fornisce\r\n l\u2019applicazione ospite.\r\n } @else if (store.isLoading()) {\r\n Caricamento dell\u2019elenco\u2026\r\n } @else if (isFilteredEmpty()) {\r\n Nessuna definizione corrisponde al filtro.\r\n } @else if (store.hasLoaded()) {\r\n Nessuna definizione. Creane una qui sotto.\r\n } @else {\r\n Elenco non disponibile.\r\n }\r\n </li>\r\n }\r\n </ul>\r\n\r\n <footer class=\"dpe-cat__foot\">\r\n <div class=\"dpe-cat__form\">\r\n <label class=\"dpe-cat__field\">\r\n <span>Nome tecnico</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n placeholder=\"RiepilogoOrdini\"\r\n [value]=\"newName()\"\r\n [disabled]=\"!store.createCommand.isAvailable\"\r\n (input)=\"newName.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <label class=\"dpe-cat__field\">\r\n <!--\r\n Si chiedono **due** campi e non uno: passare il nome anche come etichetta produce per\r\n sempre un catalogo di nomi tecnici, e un default sbagliato non si corregge piu\u2019.\r\n -->\r\n <span>Etichetta</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n placeholder=\"Riepilogo ordini\"\r\n [value]=\"newLabel()\"\r\n [disabled]=\"!store.createCommand.isAvailable\"\r\n (input)=\"newLabel.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--primary\"\r\n [disabled]=\"!canSubmitNew()\"\r\n [title]=\"\r\n store.createCommand.reason ??\r\n 'Crea la definizione e la apre. Il dialetto viene dall\u2019ambiente, non si sceglie qui.'\r\n \"\r\n (click)=\"createNew()\"\r\n >\r\n + Crea e apri\r\n </button>\r\n </div>\r\n\r\n <p class=\"dpe-cat__hint\">\r\n @if (store.createCommand.isAvailable) {\r\n <!--\r\n Detto **al momento della creazione**, non lasciato scoprire: una definizione nuova non\r\n ha sorgenti ne\u2019 writeback, quindi l\u2019editor la segnalera\u2019 invalida. E\u2019 normale \u2014 il\r\n modello tollera l\u2019incompleto e la validazione lo racconta.\r\n -->\r\n Il dialetto della definizione nuova e\u2019 quello dichiarato dall\u2019ambiente\r\n @if (store.environmentDialect(); as declared) {\r\n (<strong>{{ dialectLabels[declared] }}</strong>)\r\n }\r\n e non si sceglie qui: le espressioni sono SQL nativo di quel dialetto. Una definizione appena creata\r\n e\u2019 <strong>invalida</strong> \u2014 servono almeno una sorgente e un writeback \u2014 ed e\u2019 normale.\r\n } @else {\r\n {{ store.createCommand.reason }}\r\n }\r\n </p>\r\n </footer>\r\n</section>\r\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8923
9267
|
}
|
|
8924
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
9268
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DpeCatalogComponent, decorators: [{
|
|
8925
9269
|
type: Component,
|
|
8926
9270
|
args: [{ selector: 'dpe-catalog', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [DpeCatalogStore], template: "<!--\r\n `.dpe-theme` porta le variabili del tema anche fuori dall\u2019editor: il catalogo e\u2019 un componente\r\n **fratello**, quindi non puo\u2019 contare sulla classe radice di `<dpe-builder>`. La variante scura\r\n resta quella prevista, `data-dpe-theme=\"dark\"` su un contenitore dell\u2019ospite.\r\n-->\r\n<section class=\"dpe-theme dpe-cat\" aria-labelledby=\"dpe-cat-title\">\r\n <header class=\"dpe-cat__bar\">\r\n <h2 class=\"dpe-cat__title\" id=\"dpe-cat-title\">Definizioni DPE</h2>\r\n\r\n <span class=\"dpe-cat__count\">\r\n @if (store.isLoading()) {\r\n caricamento\u2026\r\n } @else if (!store.capabilities.listDefinitions) {\r\n elenco non disponibile\r\n } @else {\r\n {{ visible().length }} di {{ store.summaries().length }}\r\n }\r\n </span>\r\n\r\n <input\r\n class=\"dpe-cat__filter\"\r\n type=\"search\"\r\n placeholder=\"Filtra per nome o etichetta\"\r\n aria-label=\"Filtra le definizioni\"\r\n [value]=\"filter()\"\r\n (input)=\"filter.set($any($event.target).value)\"\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!store.capabilities.listDefinitions || store.isLoading()\"\r\n [title]=\"\r\n store.capabilities.listDefinitions\r\n ? 'Ricarica l\u2019elenco'\r\n : 'Questo ambiente non implementa listDefinitions.'\r\n \"\r\n (click)=\"refresh()\"\r\n >\r\n \u27F3 Aggiorna\r\n </button>\r\n </header>\r\n\r\n @if (store.error(); as error) {\r\n <!--\r\n Banner persistente: un errore di catalogo che svanisce lascia un elenco vecchio senza dire\r\n che e\u2019 vecchio. La categoria si mostra perche\u2019 distingue \u00ABriprova\u00BB da \u00ABchiedi all\u2019ospite\u00BB.\r\n -->\r\n <p class=\"dpe-cat__error\" role=\"alert\">\r\n <strong>{{ error.category }}</strong> {{ error.message }}\r\n <button type=\"button\" class=\"dpe-cat__dismiss\" aria-label=\"Chiudi\" (click)=\"store.dismissError()\">\r\n \u00D7\r\n </button>\r\n </p>\r\n }\r\n\r\n <ul class=\"dpe-cat__list\">\r\n @for (summary of visible(); track summary.name) {\r\n <li class=\"dpe-cat__item\" [class.dpe-cat__item--busy]=\"store.isMutating()\">\r\n <div class=\"dpe-cat__row\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__open\"\r\n [title]=\"'Apri ' + summary.label\"\r\n (click)=\"onOpen(summary.name)\"\r\n >\r\n <span class=\"dpe-cat__label\">{{ summary.label }}</span>\r\n <span class=\"dpe-cat__meta\">\r\n <!--\r\n Solo i fatti **presenti**: cio\u2019 che il sommario non porta non si stima. Contare i\r\n nodi lato client vorrebbe dire caricare tutte le definizioni per disegnare un\r\n elenco (ADR 0019).\r\n -->\r\n <code class=\"dpe-cat__name\">{{ summary.name }}</code>\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ dialectLabels[summary.dialect] }}\r\n @if (summary.status) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.status === 'Active' ? 'attiva' : 'non attiva' }}\r\n }\r\n @if (summary.runMode) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.runMode === 'Batch' ? 'batch' : 'a richiesta' }}\r\n }\r\n @if (summary.isTemplate) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n modello\r\n }\r\n @if (summary.nodeCount !== undefined) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ summary.nodeCount }} {{ summary.nodeCount === 1 ? 'nodo' : 'nodi' }}\r\n }\r\n @if (summary.updatedAt) {\r\n <span class=\"dpe-cat__dot\"> \u00B7 </span>\r\n {{ formatDate(summary.updatedAt) }}\r\n @if (summary.updatedBy) {\r\n \u00B7 {{ summary.updatedBy }}\r\n }\r\n }\r\n </span>\r\n @if (summary.description) {\r\n <span class=\"dpe-cat__desc\">{{ summary.description }}</span>\r\n }\r\n </button>\r\n\r\n <!--\r\n `hasErrors` e\u2019 **riportato, non ricalcolato** (ADR 0019): il frontend non valida\r\n niente. Per questo l\u2019etichetta dice \u00ABultima validazione nota\u00BB e non \u00ABinvalida\u00BB: puo\u2019\r\n essere vecchia, e spacciarla per verita\u2019 sarebbe una validazione fatta dal client per\r\n interposta persona. Assente, non compare nulla.\r\n -->\r\n @if (summary.hasErrors !== undefined) {\r\n <span\r\n class=\"dpe-cat__flag\"\r\n [class.dpe-cat__flag--errors]=\"summary.hasErrors\"\r\n [title]=\"\r\n summary.hasErrors\r\n ? 'Ultima validazione nota all\u2019ambiente: con errori. E\u2019 uno stato riportato, non ricalcolato qui.'\r\n : 'Ultima validazione nota all\u2019ambiente: senza errori. E\u2019 uno stato riportato, non ricalcolato qui.'\r\n \"\r\n >\r\n {{ summary.hasErrors ? 'con errori (stato noto)' : 'senza errori (stato noto)' }}\r\n </span>\r\n }\r\n\r\n <div class=\"dpe-cat__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!canDuplicate() || store.isMutating()\"\r\n [title]=\"duplicateReason()\"\r\n (click)=\"startDuplicate(summary)\"\r\n >\r\n Duplica\r\n </button>\r\n\r\n @if (pendingDelete() === summary.name) {\r\n <!-- Conferma in **due passi**: la prima pressione chiede, la seconda cancella. -->\r\n <span class=\"dpe-cat__confirm\">\r\n Eliminare \u00AB{{ summary.name }}\u00BB?\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--danger\"\r\n (click)=\"confirmDelete(summary.name)\"\r\n >\r\n Elimina\r\n </button>\r\n <button type=\"button\" class=\"dpe-cat__btn\" (click)=\"cancelDelete()\">Annulla</button>\r\n </span>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn\"\r\n [disabled]=\"!store.capabilities.deleteDefinition || store.isMutating()\"\r\n [title]=\"\r\n store.capabilities.deleteDefinition\r\n ? 'Elimina (chiede conferma)'\r\n : 'Eliminazione non disponibile: questo ambiente non implementa deleteDefinition.'\r\n \"\r\n (click)=\"askDelete(summary.name)\"\r\n >\r\n Elimina\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (duplicateSource() === summary.name) {\r\n <!--\r\n Duplicare e\u2019 `load` piu\u2019 `createDefinition`: nessuna primitiva nuova sul contratto.\r\n Il dialetto resta quello della definizione copiata \u2014 le espressioni sono SQL nativo.\r\n -->\r\n <div class=\"dpe-cat__form dpe-cat__form--inline\">\r\n <label class=\"dpe-cat__field\">\r\n <span>Nome della copia</span>\r\n <input\r\n #duplicateNameField\r\n class=\"dpe-cat__input\"\r\n [value]=\"duplicateName()\"\r\n (input)=\"duplicateName.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <label class=\"dpe-cat__field\">\r\n <span>Etichetta della copia</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n [value]=\"duplicateLabel()\"\r\n (input)=\"duplicateLabel.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--primary\"\r\n [disabled]=\"!canSubmitDuplicate()\"\r\n (click)=\"confirmDuplicate()\"\r\n >\r\n Duplica\r\n </button>\r\n <button type=\"button\" class=\"dpe-cat__btn\" (click)=\"cancelDuplicate()\">Annulla</button>\r\n </div>\r\n }\r\n </li>\r\n } @empty {\r\n <li class=\"dpe-cat__empty\">\r\n @if (!store.capabilities.listDefinitions) {\r\n Questo ambiente non implementa <code>listDefinitions</code>: l\u2019elenco lo fornisce\r\n l\u2019applicazione ospite.\r\n } @else if (store.isLoading()) {\r\n Caricamento dell\u2019elenco\u2026\r\n } @else if (isFilteredEmpty()) {\r\n Nessuna definizione corrisponde al filtro.\r\n } @else if (store.hasLoaded()) {\r\n Nessuna definizione. Creane una qui sotto.\r\n } @else {\r\n Elenco non disponibile.\r\n }\r\n </li>\r\n }\r\n </ul>\r\n\r\n <footer class=\"dpe-cat__foot\">\r\n <div class=\"dpe-cat__form\">\r\n <label class=\"dpe-cat__field\">\r\n <span>Nome tecnico</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n placeholder=\"RiepilogoOrdini\"\r\n [value]=\"newName()\"\r\n [disabled]=\"!store.createCommand.isAvailable\"\r\n (input)=\"newName.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <label class=\"dpe-cat__field\">\r\n <!--\r\n Si chiedono **due** campi e non uno: passare il nome anche come etichetta produce per\r\n sempre un catalogo di nomi tecnici, e un default sbagliato non si corregge piu\u2019.\r\n -->\r\n <span>Etichetta</span>\r\n <input\r\n class=\"dpe-cat__input\"\r\n placeholder=\"Riepilogo ordini\"\r\n [value]=\"newLabel()\"\r\n [disabled]=\"!store.createCommand.isAvailable\"\r\n (input)=\"newLabel.set($any($event.target).value)\"\r\n />\r\n </label>\r\n <button\r\n type=\"button\"\r\n class=\"dpe-cat__btn dpe-cat__btn--primary\"\r\n [disabled]=\"!canSubmitNew()\"\r\n [title]=\"\r\n store.createCommand.reason ??\r\n 'Crea la definizione e la apre. Il dialetto viene dall\u2019ambiente, non si sceglie qui.'\r\n \"\r\n (click)=\"createNew()\"\r\n >\r\n + Crea e apri\r\n </button>\r\n </div>\r\n\r\n <p class=\"dpe-cat__hint\">\r\n @if (store.createCommand.isAvailable) {\r\n <!--\r\n Detto **al momento della creazione**, non lasciato scoprire: una definizione nuova non\r\n ha sorgenti ne\u2019 writeback, quindi l\u2019editor la segnalera\u2019 invalida. E\u2019 normale \u2014 il\r\n modello tollera l\u2019incompleto e la validazione lo racconta.\r\n -->\r\n Il dialetto della definizione nuova e\u2019 quello dichiarato dall\u2019ambiente\r\n @if (store.environmentDialect(); as declared) {\r\n (<strong>{{ dialectLabels[declared] }}</strong>)\r\n }\r\n e non si sceglie qui: le espressioni sono SQL nativo di quel dialetto. Una definizione appena creata\r\n e\u2019 <strong>invalida</strong> \u2014 servono almeno una sorgente e un writeback \u2014 ed e\u2019 normale.\r\n } @else {\r\n {{ store.createCommand.reason }}\r\n }\r\n </p>\r\n </footer>\r\n</section>\r\n" }]
|
|
8927
9271
|
}], propDecorators: { open: [{ type: i0.Output, args: ["open"] }], duplicateNameField: [{ type: i0.ViewChild, args: ['duplicateNameField', { isSignal: true }] }] } });
|
|
@@ -8939,5 +9283,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
8939
9283
|
* Generated bundle index. Do not edit.
|
|
8940
9284
|
*/
|
|
8941
9285
|
|
|
8942
|
-
export { DPE_API_ERROR_FALLBACK_MESSAGE, DPE_BUILDER_HTTP_CONFIG, DPE_DIALECT_LABELS, DPE_LAYOUT_KEY, DPE_NODE_CATEGORIES, DPE_NODE_COLLECTIONS, DPE_NODE_HEIGHT, DPE_NODE_ICON_PATHS, DPE_NODE_NOT_COMPILABLE, DPE_SOURCE_SLOTS, DpeApiError, DpeBuilderApi, DpeBuilderComponent, DpeCanvasComponent, DpeCatalogComponent, DpeCatalogStore, DpeColumnTypeEditorComponent, DpeDiagnosticsPanelComponent, DpeDocumentStore, DpeExpressionEditorComponent, DpeLayoutService, DpeMetadataStore, DpeNodeIconComponent, DpeNodeInspectorBase, DpeNodeInspectorComponent, DpeNodePaletteComponent, DpeSchemaPanelComponent, DpeSelectValueDirective, DpeSqlPreviewComponent, DpeValidationService, HttpDpeBuilderApi, diagnosticPathToString, dpeAllNodes, dpeBuildGraph, dpeCountReferences, dpeCreateCommandAvailability, dpeCreateNode, dpeDefinitionLevelDiagnostics, dpeDiagnosticField, dpeDiagnosticLocationLabel, dpeDiagnosticNodeName, dpeEdgeId, dpeEmptyDefinition, dpeFindNode, dpeGroupDiagnosticsByNode, dpeHasCompleteLayout, dpeInputPortId, dpeInputPorts, dpeIsDialectDiagnostic, dpeIsNotCompilable, dpeIsPrimitiveAvailable, dpeIsRectFullyVisible, dpeKnownNodeNames, dpeNodeCategory, dpeNodeIconFamily, dpeNodeIconFamilyClass, dpeNodeIconPaths, dpeNodeId, dpeNodeSourceReferences, dpeNodeSubtitle, dpeNodeWidth, dpeNodeWidthClass, dpeOutputPortId, dpeParseInputPortId, dpeParseNodeId, dpeParseOutputPortId, dpeProposeNodeName, dpeProposeWritebackSequence, dpeReadCapabilities, dpeReadNodePosition, dpeRenameNode, dpeWorstSeverity, dpeWriteNodePosition, dpeWriteSourceReference, provideDpeBuilderHttpApi };
|
|
9286
|
+
export { DPE_API_ERROR_FALLBACK_MESSAGE, DPE_BUILDER_HTTP_CONFIG, DPE_DIALECT_LABELS, DPE_LAYOUT_KEY, DPE_NODE_CATEGORIES, DPE_NODE_COLLECTIONS, DPE_NODE_HEIGHT, DPE_NODE_ICON_PATHS, DPE_NODE_NOT_COMPILABLE, DPE_SOURCE_SLOTS, DpeApiError, DpeBuilderApi, DpeBuilderComponent, DpeCanvasComponent, DpeCatalogComponent, DpeCatalogStore, DpeColumnTypeEditorComponent, DpeDiagnosticsPanelComponent, DpeDocumentStore, DpeExpressionEditorComponent, DpeLayoutService, DpeMetadataStore, DpeNodeDialogComponent, DpeNodeFactsComponent, DpeNodeIconComponent, DpeNodeInspectorBase, DpeNodeInspectorComponent, DpeNodePaletteComponent, DpeSchemaPanelComponent, DpeSelectValueDirective, DpeSqlPreviewComponent, DpeValidationService, HttpDpeBuilderApi, diagnosticPathToString, dpeAllNodes, dpeBuildGraph, dpeCountReferences, dpeCreateCommandAvailability, dpeCreateNode, dpeDefinitionLevelDiagnostics, dpeDiagnosticField, dpeDiagnosticLocationLabel, dpeDiagnosticNodeName, dpeEdgeId, dpeEmptyDefinition, dpeFindNode, dpeGroupDiagnosticsByNode, dpeHasCompleteLayout, dpeInputPortId, dpeInputPorts, dpeIsDialectDiagnostic, dpeIsNotCompilable, dpeIsPrimitiveAvailable, dpeIsRectFullyVisible, dpeKnownNodeNames, dpeNodeCategory, dpeNodeIconFamily, dpeNodeIconFamilyClass, dpeNodeIconPaths, dpeNodeId, dpeNodeSourceReferences, dpeNodeSubtitle, dpeNodeWidth, dpeNodeWidthClass, dpeOutputPortId, dpeParseInputPortId, dpeParseNodeId, dpeParseOutputPortId, dpeProposeNodeName, dpeProposeWritebackSequence, dpeReadCapabilities, dpeReadNodePosition, dpeRenameNode, dpeWorstSeverity, dpeWriteNodePosition, dpeWriteSourceReference, provideDpeBuilderHttpApi };
|
|
8943
9287
|
//# sourceMappingURL=esfaenza-dpe-builder.mjs.map
|