@esfaenza/dpe-builder 20.3.2 → 20.3.3
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 +172 -65
- package/fesm2022/esfaenza-dpe-builder.mjs.map +1 -1
- package/index.d.ts +1 -1
- package/package.json +1 -1
- package/styles/dpe-builder.css +1760 -22
|
@@ -2106,7 +2106,7 @@ function dpeNodeIconFamily(collection) {
|
|
|
2106
2106
|
}
|
|
2107
2107
|
/** Classe CSS della famiglia: un solo posto la costruisce, cosi' i fogli restano allineati. */
|
|
2108
2108
|
function dpeNodeIconFamilyClass(collection) {
|
|
2109
|
-
return `dpe-
|
|
2109
|
+
return `dpe-family--${dpeNodeIconFamily(collection)}`;
|
|
2110
2110
|
}
|
|
2111
2111
|
/**
|
|
2112
2112
|
* I tracciati, per collezione. Ogni voce e' l'elenco degli attributi `d` di un `<path>`; il
|
|
@@ -2418,11 +2418,15 @@ class DpeNodeIconComponent {
|
|
|
2418
2418
|
<path [attr.d]="path" />
|
|
2419
2419
|
}
|
|
2420
2420
|
</svg>
|
|
2421
|
-
`, isInline: true,
|
|
2421
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2422
2422
|
}
|
|
2423
2423
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeNodeIconComponent, decorators: [{
|
|
2424
2424
|
type: Component,
|
|
2425
|
-
args: [{
|
|
2425
|
+
args: [{
|
|
2426
|
+
selector: 'dpe-node-icon',
|
|
2427
|
+
standalone: true,
|
|
2428
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2429
|
+
template: `
|
|
2426
2430
|
<svg
|
|
2427
2431
|
viewBox="0 0 24 24"
|
|
2428
2432
|
width="16"
|
|
@@ -2439,7 +2443,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
2439
2443
|
<path [attr.d]="path" />
|
|
2440
2444
|
}
|
|
2441
2445
|
</svg>
|
|
2442
|
-
`,
|
|
2446
|
+
`,
|
|
2447
|
+
}]
|
|
2443
2448
|
}], propDecorators: { collection: [{ type: i0.Input, args: [{ isSignal: true, alias: "collection", required: true }] }] } });
|
|
2444
2449
|
|
|
2445
2450
|
/**
|
|
@@ -2886,11 +2891,11 @@ class DpeCanvasComponent {
|
|
|
2886
2891
|
return this.store.selectedNodeNameSet().has(node.name);
|
|
2887
2892
|
}
|
|
2888
2893
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeCanvasComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2889
|
-
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<f-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", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden;background:var(--dpe-canvas-bg, #f4f5f7)}f-flow{display:block;width:100%;height:100%}.dpe-minimap{position:absolute;right:12px;bottom:12px;width:180px;height:120px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:var(--dpe-radius, 10px);background:var(--dpe-surface, #fff);box-shadow:var(--dpe-shadow-md, 0 6px 18px rgb(16 24 40 / 10%));overflow:hidden}.dpe-viewport-reset{position:absolute;right:12px;bottom:140px;z-index:1;padding:5px 10px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:var(--dpe-radius-xs, 6px);background:var(--dpe-surface, #fff);box-shadow:var(--dpe-shadow-md, 0 6px 18px rgb(16 24 40 / 10%));color:var(--dpe-text-muted, #6b7086);font:inherit;font-size:11px;cursor:pointer;transition:opacity .15s ease,visibility .15s ease}.dpe-viewport-reset--hidden{opacity:0;visibility:hidden}.dpe-node{position:absolute;display:flex;flex-direction:column;box-sizing:border-box;width:230px;border:1px solid var(--dpe-border, #e2e5eb);border-left:4px solid var(--dpe-border-strong, #cfd4de);border-radius:var(--dpe-radius-lg, 12px);background:var(--dpe-surface, #fff);box-shadow:var(--dpe-shadow-sm, 0 1px 2px rgb(16 24 40 / 6%));color:var(--dpe-text, #1a1c23);font:inherit;text-align:left;cursor:grab;-webkit-user-select:none;user-select:none;transition:box-shadow .12s ease,border-color .12s ease}.dpe-node--ports-2{width:260px}.dpe-node--ports-3{width:320px}.dpe-node--ports-4{width:380px}.dpe-node:hover{box-shadow:var(--dpe-shadow-md, 0 6px 18px rgb(16 24 40 / 10%))}.dpe-node--selected{border-color:var(--dpe-accent, #2f7d8f);box-shadow:0 0 0 3px color-mix(in srgb,var(--dpe-accent, #2f7d8f) 22%,transparent)}.dpe-node--error{border-color:var(--dpe-error, #dc2626)}.dpe-node--warning{border-color:var(--dpe-warning, #b7791f)}.dpe-node--not-compilable{border-color:var(--dpe-not-compilable, #7c5cd6);border-style:dashed}.dpe-node{border-left-color:var(--dpe-cat, var(--dpe-border-strong, #cfd4de))}.dpe-node__ports{display:flex;justify-content:space-around;gap:6px;padding:0 10px;margin-top:-6px;min-height:6px}.dpe-node__ports--labelled{min-height:18px}.dpe-port{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:0}.dpe-port__label{max-width:96px;overflow:hidden;color:var(--dpe-text-subtle, #98a2b3);font-size:9px;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.02em;text-transform:uppercase}.dpe-connector{box-sizing:border-box;flex:0 0 auto;cursor:crosshair;transition:transform .12s ease,background-color .12s ease}f-flow .dpe-connector--in{position:relative;inset:auto;width:22px;height:6px;border:0;border-radius:3px;background:var(--dpe-border-strong, #cfd4de)}f-flow .dpe-connector--in:hover{background:var(--dpe-accent, #2f7d8f);transform:scaleY(1.6)}f-flow .dpe-connector--in.dpe-connector--broken{background:var(--dpe-edge-broken, #dc2626)}.dpe-node__out{display:flex;justify-content:center;padding-bottom:0}f-flow .dpe-connector--out{position:relative;inset:auto;width:12px;height:12px;border:2px solid var(--dpe-surface, #fff);border-radius:50%;background:var(--dpe-border-strong, #cfd4de);margin-bottom:-6px;--ff-connector-connected-color: var(--dpe-accent, #2f7d8f)}f-flow .dpe-connector--out:hover{transform:scale(1.25);background:var(--dpe-accent, #2f7d8f)}.dpe-node__head{display:flex;align-items:center;gap:8px;padding:8px 8px 2px 10px}.dpe-node__icon{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;width:26px;height:26px;border-radius:var(--dpe-radius-sm, 8px);background:var(--dpe-cat-soft, #eef0f4);color:var(--dpe-cat, #6b7086)}.dpe-cat--source{--dpe-cat: var(--dpe-cat-source, #2f7d8f);--dpe-cat-soft: var(--dpe-cat-source-soft, #dbecf0)}.dpe-cat--transform{--dpe-cat: var(--dpe-cat-transform, #3b6fd4);--dpe-cat-soft: var(--dpe-cat-transform-soft, #e2eafb)}.dpe-cat--sink{--dpe-cat: var(--dpe-cat-sink, #1c8a5c);--dpe-cat-soft: var(--dpe-cat-sink-soft, #dcf1e8)}.dpe-cat--uncompilable{--dpe-cat: var(--dpe-cat-uncompilable, #7c5cd6);--dpe-cat-soft: var(--dpe-cat-uncompilable-soft, #ebe6fa)}.dpe-node__text{display:flex;flex-direction:column;min-width:0;flex:1 1 auto}.dpe-node__title{overflow:hidden;font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.dpe-node__sub{overflow:hidden;color:var(--dpe-text-muted, #6b7086);font-size:11px;text-overflow:ellipsis;white-space:nowrap}.dpe-node__dot{padding:0 4px;color:var(--dpe-text-subtle, #98a2b3)}.dpe-node__btn{flex:0 0 auto;width:20px;height:20px;padding:0;border:1px solid transparent;border-radius:var(--dpe-radius-xs, 6px);background:transparent;color:var(--dpe-text-muted, #6b7086);font:inherit;font-size:12px;line-height:1;cursor:pointer}.dpe-node__btn:hover{border-color:var(--dpe-border, #e2e5eb);background:var(--dpe-surface-alt, #f7f8fa);color:var(--dpe-text, #1a1c23)}.dpe-node__btn--remove:hover{border-color:var(--dpe-error, #dc2626);color:var(--dpe-error, #dc2626)}.dpe-node__meta{display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:0 10px 8px;min-height:18px}.dpe-node__name{overflow:hidden;max-width:130px;color:var(--dpe-text-subtle, #98a2b3);font-family:var(--dpe-font-mono, monospace);font-size:10px;text-overflow:ellipsis;white-space:nowrap}.dpe-badge{padding:1px 6px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:999px;background:var(--dpe-surface-alt, #f7f8fa);color:var(--dpe-text-muted, #6b7086);font-size:10px;white-space:nowrap}.dpe-badge--error{border-color:var(--dpe-error, #dc2626);color:var(--dpe-error, #dc2626)}.dpe-badge--warning{border-color:var(--dpe-warning, #b7791f);color:var(--dpe-warning, #b7791f)}.dpe-badge--info{border-color:var(--dpe-info, #3b6fd4);color:var(--dpe-info, #3b6fd4)}.dpe-badge--not-compilable{border-color:var(--dpe-not-compilable, #7c5cd6);color:var(--dpe-not-compilable, #7c5cd6)}\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 });
|
|
2894
|
+
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 });
|
|
2890
2895
|
}
|
|
2891
2896
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeCanvasComponent, decorators: [{
|
|
2892
2897
|
type: Component,
|
|
2893
|
-
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<f-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", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden;background:var(--dpe-canvas-bg, #f4f5f7)}f-flow{display:block;width:100%;height:100%}.dpe-minimap{position:absolute;right:12px;bottom:12px;width:180px;height:120px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:var(--dpe-radius, 10px);background:var(--dpe-surface, #fff);box-shadow:var(--dpe-shadow-md, 0 6px 18px rgb(16 24 40 / 10%));overflow:hidden}.dpe-viewport-reset{position:absolute;right:12px;bottom:140px;z-index:1;padding:5px 10px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:var(--dpe-radius-xs, 6px);background:var(--dpe-surface, #fff);box-shadow:var(--dpe-shadow-md, 0 6px 18px rgb(16 24 40 / 10%));color:var(--dpe-text-muted, #6b7086);font:inherit;font-size:11px;cursor:pointer;transition:opacity .15s ease,visibility .15s ease}.dpe-viewport-reset--hidden{opacity:0;visibility:hidden}.dpe-node{position:absolute;display:flex;flex-direction:column;box-sizing:border-box;width:230px;border:1px solid var(--dpe-border, #e2e5eb);border-left:4px solid var(--dpe-border-strong, #cfd4de);border-radius:var(--dpe-radius-lg, 12px);background:var(--dpe-surface, #fff);box-shadow:var(--dpe-shadow-sm, 0 1px 2px rgb(16 24 40 / 6%));color:var(--dpe-text, #1a1c23);font:inherit;text-align:left;cursor:grab;-webkit-user-select:none;user-select:none;transition:box-shadow .12s ease,border-color .12s ease}.dpe-node--ports-2{width:260px}.dpe-node--ports-3{width:320px}.dpe-node--ports-4{width:380px}.dpe-node:hover{box-shadow:var(--dpe-shadow-md, 0 6px 18px rgb(16 24 40 / 10%))}.dpe-node--selected{border-color:var(--dpe-accent, #2f7d8f);box-shadow:0 0 0 3px color-mix(in srgb,var(--dpe-accent, #2f7d8f) 22%,transparent)}.dpe-node--error{border-color:var(--dpe-error, #dc2626)}.dpe-node--warning{border-color:var(--dpe-warning, #b7791f)}.dpe-node--not-compilable{border-color:var(--dpe-not-compilable, #7c5cd6);border-style:dashed}.dpe-node{border-left-color:var(--dpe-cat, var(--dpe-border-strong, #cfd4de))}.dpe-node__ports{display:flex;justify-content:space-around;gap:6px;padding:0 10px;margin-top:-6px;min-height:6px}.dpe-node__ports--labelled{min-height:18px}.dpe-port{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:0}.dpe-port__label{max-width:96px;overflow:hidden;color:var(--dpe-text-subtle, #98a2b3);font-size:9px;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.02em;text-transform:uppercase}.dpe-connector{box-sizing:border-box;flex:0 0 auto;cursor:crosshair;transition:transform .12s ease,background-color .12s ease}f-flow .dpe-connector--in{position:relative;inset:auto;width:22px;height:6px;border:0;border-radius:3px;background:var(--dpe-border-strong, #cfd4de)}f-flow .dpe-connector--in:hover{background:var(--dpe-accent, #2f7d8f);transform:scaleY(1.6)}f-flow .dpe-connector--in.dpe-connector--broken{background:var(--dpe-edge-broken, #dc2626)}.dpe-node__out{display:flex;justify-content:center;padding-bottom:0}f-flow .dpe-connector--out{position:relative;inset:auto;width:12px;height:12px;border:2px solid var(--dpe-surface, #fff);border-radius:50%;background:var(--dpe-border-strong, #cfd4de);margin-bottom:-6px;--ff-connector-connected-color: var(--dpe-accent, #2f7d8f)}f-flow .dpe-connector--out:hover{transform:scale(1.25);background:var(--dpe-accent, #2f7d8f)}.dpe-node__head{display:flex;align-items:center;gap:8px;padding:8px 8px 2px 10px}.dpe-node__icon{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;width:26px;height:26px;border-radius:var(--dpe-radius-sm, 8px);background:var(--dpe-cat-soft, #eef0f4);color:var(--dpe-cat, #6b7086)}.dpe-cat--source{--dpe-cat: var(--dpe-cat-source, #2f7d8f);--dpe-cat-soft: var(--dpe-cat-source-soft, #dbecf0)}.dpe-cat--transform{--dpe-cat: var(--dpe-cat-transform, #3b6fd4);--dpe-cat-soft: var(--dpe-cat-transform-soft, #e2eafb)}.dpe-cat--sink{--dpe-cat: var(--dpe-cat-sink, #1c8a5c);--dpe-cat-soft: var(--dpe-cat-sink-soft, #dcf1e8)}.dpe-cat--uncompilable{--dpe-cat: var(--dpe-cat-uncompilable, #7c5cd6);--dpe-cat-soft: var(--dpe-cat-uncompilable-soft, #ebe6fa)}.dpe-node__text{display:flex;flex-direction:column;min-width:0;flex:1 1 auto}.dpe-node__title{overflow:hidden;font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.dpe-node__sub{overflow:hidden;color:var(--dpe-text-muted, #6b7086);font-size:11px;text-overflow:ellipsis;white-space:nowrap}.dpe-node__dot{padding:0 4px;color:var(--dpe-text-subtle, #98a2b3)}.dpe-node__btn{flex:0 0 auto;width:20px;height:20px;padding:0;border:1px solid transparent;border-radius:var(--dpe-radius-xs, 6px);background:transparent;color:var(--dpe-text-muted, #6b7086);font:inherit;font-size:12px;line-height:1;cursor:pointer}.dpe-node__btn:hover{border-color:var(--dpe-border, #e2e5eb);background:var(--dpe-surface-alt, #f7f8fa);color:var(--dpe-text, #1a1c23)}.dpe-node__btn--remove:hover{border-color:var(--dpe-error, #dc2626);color:var(--dpe-error, #dc2626)}.dpe-node__meta{display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:0 10px 8px;min-height:18px}.dpe-node__name{overflow:hidden;max-width:130px;color:var(--dpe-text-subtle, #98a2b3);font-family:var(--dpe-font-mono, monospace);font-size:10px;text-overflow:ellipsis;white-space:nowrap}.dpe-badge{padding:1px 6px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:999px;background:var(--dpe-surface-alt, #f7f8fa);color:var(--dpe-text-muted, #6b7086);font-size:10px;white-space:nowrap}.dpe-badge--error{border-color:var(--dpe-error, #dc2626);color:var(--dpe-error, #dc2626)}.dpe-badge--warning{border-color:var(--dpe-warning, #b7791f);color:var(--dpe-warning, #b7791f)}.dpe-badge--info{border-color:var(--dpe-info, #3b6fd4);color:var(--dpe-info, #3b6fd4)}.dpe-badge--not-compilable{border-color:var(--dpe-not-compilable, #7c5cd6);color:var(--dpe-not-compilable, #7c5cd6)}\n"] }]
|
|
2898
|
+
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" }]
|
|
2894
2899
|
}], 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 }] }] } });
|
|
2895
2900
|
|
|
2896
2901
|
/**
|
|
@@ -3022,11 +3027,15 @@ class DpeDiagnosticsPanelComponent {
|
|
|
3022
3027
|
}
|
|
3023
3028
|
</button>
|
|
3024
3029
|
}
|
|
3025
|
-
`, isInline: true,
|
|
3030
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3026
3031
|
}
|
|
3027
3032
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeDiagnosticsPanelComponent, decorators: [{
|
|
3028
3033
|
type: Component,
|
|
3029
|
-
args: [{
|
|
3034
|
+
args: [{
|
|
3035
|
+
selector: 'dpe-diagnostics-panel',
|
|
3036
|
+
standalone: true,
|
|
3037
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3038
|
+
template: `
|
|
3030
3039
|
<div class="dpe-diag__head">
|
|
3031
3040
|
<strong>Diagnostiche</strong>
|
|
3032
3041
|
<span class="dpe-diag__count">
|
|
@@ -3084,7 +3093,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
3084
3093
|
}
|
|
3085
3094
|
</button>
|
|
3086
3095
|
}
|
|
3087
|
-
`,
|
|
3096
|
+
`,
|
|
3097
|
+
}]
|
|
3088
3098
|
}], propDecorators: { navigate: [{ type: i0.Output, args: ["navigate"] }] } });
|
|
3089
3099
|
|
|
3090
3100
|
/**
|
|
@@ -3375,11 +3385,16 @@ class DpeAggregateInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3375
3385
|
</p>
|
|
3376
3386
|
</section>
|
|
3377
3387
|
</div>
|
|
3378
|
-
`, isInline: true,
|
|
3388
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3379
3389
|
}
|
|
3380
3390
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeAggregateInspectorComponent, decorators: [{
|
|
3381
3391
|
type: Component,
|
|
3382
|
-
args: [{
|
|
3392
|
+
args: [{
|
|
3393
|
+
selector: 'dpe-aggregate-inspector',
|
|
3394
|
+
standalone: true,
|
|
3395
|
+
imports: [DpeSelectValueDirective],
|
|
3396
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3397
|
+
template: `
|
|
3383
3398
|
<div class="dpe-form">
|
|
3384
3399
|
<div class="dpe-field">
|
|
3385
3400
|
<label class="dpe-field__label" for="agg-group">Raggruppa per</label>
|
|
@@ -3474,7 +3489,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
3474
3489
|
</p>
|
|
3475
3490
|
</section>
|
|
3476
3491
|
</div>
|
|
3477
|
-
`,
|
|
3492
|
+
`,
|
|
3493
|
+
}]
|
|
3478
3494
|
}] });
|
|
3479
3495
|
|
|
3480
3496
|
/**
|
|
@@ -3542,11 +3558,15 @@ class DpeAppendInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3542
3558
|
<p class="dpe-field__hint">Le sorgenti si collegano trascinando un arco sulle porte in alto.</p>
|
|
3543
3559
|
</section>
|
|
3544
3560
|
</div>
|
|
3545
|
-
`, isInline: true,
|
|
3561
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3546
3562
|
}
|
|
3547
3563
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeAppendInspectorComponent, decorators: [{
|
|
3548
3564
|
type: Component,
|
|
3549
|
-
args: [{
|
|
3565
|
+
args: [{
|
|
3566
|
+
selector: 'dpe-append-inspector',
|
|
3567
|
+
standalone: true,
|
|
3568
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3569
|
+
template: `
|
|
3550
3570
|
<div class="dpe-form">
|
|
3551
3571
|
<label class="dpe-check">
|
|
3552
3572
|
<input
|
|
@@ -3589,7 +3609,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
3589
3609
|
<p class="dpe-field__hint">Le sorgenti si collegano trascinando un arco sulle porte in alto.</p>
|
|
3590
3610
|
</section>
|
|
3591
3611
|
</div>
|
|
3592
|
-
`,
|
|
3612
|
+
`,
|
|
3613
|
+
}]
|
|
3593
3614
|
}] });
|
|
3594
3615
|
|
|
3595
3616
|
/**
|
|
@@ -3730,11 +3751,16 @@ class DpeAtomicWritebackInspectorComponent extends DpeNodeInspectorBase {
|
|
|
3730
3751
|
</div>
|
|
3731
3752
|
</section>
|
|
3732
3753
|
</div>
|
|
3733
|
-
`, isInline: true,
|
|
3754
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3734
3755
|
}
|
|
3735
3756
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeAtomicWritebackInspectorComponent, decorators: [{
|
|
3736
3757
|
type: Component,
|
|
3737
|
-
args: [{
|
|
3758
|
+
args: [{
|
|
3759
|
+
selector: 'dpe-atomic-writeback-inspector',
|
|
3760
|
+
standalone: true,
|
|
3761
|
+
imports: [DpeSelectValueDirective],
|
|
3762
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3763
|
+
template: `
|
|
3738
3764
|
<div class="dpe-form">
|
|
3739
3765
|
<p class="dpe-note">
|
|
3740
3766
|
La libreria non apre transazioni: questo gruppo <strong>dichiara</strong> che le scritture
|
|
@@ -3843,7 +3869,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
3843
3869
|
</div>
|
|
3844
3870
|
</section>
|
|
3845
3871
|
</div>
|
|
3846
|
-
`,
|
|
3872
|
+
`,
|
|
3873
|
+
}]
|
|
3847
3874
|
}] });
|
|
3848
3875
|
|
|
3849
3876
|
/**
|
|
@@ -3959,11 +3986,16 @@ class DpeColumnTypeEditorComponent {
|
|
|
3959
3986
|
/>
|
|
3960
3987
|
</div>
|
|
3961
3988
|
}
|
|
3962
|
-
`, isInline: true,
|
|
3989
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3963
3990
|
}
|
|
3964
3991
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeColumnTypeEditorComponent, decorators: [{
|
|
3965
3992
|
type: Component,
|
|
3966
|
-
args: [{
|
|
3993
|
+
args: [{
|
|
3994
|
+
selector: 'dpe-column-type-editor',
|
|
3995
|
+
standalone: true,
|
|
3996
|
+
imports: [DpeSelectValueDirective],
|
|
3997
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3998
|
+
template: `
|
|
3967
3999
|
<div class="dpe-row">
|
|
3968
4000
|
<div class="dpe-field">
|
|
3969
4001
|
<label class="dpe-field__label" [attr.for]="controlId() + '-kind'">Tipo</label>
|
|
@@ -4023,7 +4055,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
4023
4055
|
/>
|
|
4024
4056
|
</div>
|
|
4025
4057
|
}
|
|
4026
|
-
`,
|
|
4058
|
+
`,
|
|
4059
|
+
}]
|
|
4027
4060
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], controlId: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlId", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
4028
4061
|
|
|
4029
4062
|
/**
|
|
@@ -4191,11 +4224,16 @@ class DpeCustomNodeInspectorComponent extends DpeNodeInspectorBase {
|
|
|
4191
4224
|
</div>
|
|
4192
4225
|
</section>
|
|
4193
4226
|
</div>
|
|
4194
|
-
`, isInline: true,
|
|
4227
|
+
`, isInline: true, dependencies: [{ kind: "component", type: DpeColumnTypeEditorComponent, selector: "dpe-column-type-editor", inputs: ["value", "controlId"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4195
4228
|
}
|
|
4196
4229
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeCustomNodeInspectorComponent, decorators: [{
|
|
4197
4230
|
type: Component,
|
|
4198
|
-
args: [{
|
|
4231
|
+
args: [{
|
|
4232
|
+
selector: 'dpe-custom-node-inspector',
|
|
4233
|
+
standalone: true,
|
|
4234
|
+
imports: [DpeColumnTypeEditorComponent],
|
|
4235
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4236
|
+
template: `
|
|
4199
4237
|
<div class="dpe-form">
|
|
4200
4238
|
<p class="dpe-note dpe-note--not-compilable">
|
|
4201
4239
|
Nodo modellato per intero ma <strong>non traducibile in SQL</strong> nella versione 1.
|
|
@@ -4313,7 +4351,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
4313
4351
|
</div>
|
|
4314
4352
|
</section>
|
|
4315
4353
|
</div>
|
|
4316
|
-
`,
|
|
4354
|
+
`,
|
|
4355
|
+
}]
|
|
4317
4356
|
}] });
|
|
4318
4357
|
|
|
4319
4358
|
/**
|
|
@@ -4561,11 +4600,16 @@ class DpeDataSourceInspectorComponent extends DpeNodeInspectorBase {
|
|
|
4561
4600
|
</div>
|
|
4562
4601
|
</section>
|
|
4563
4602
|
</div>
|
|
4564
|
-
`, isInline: true,
|
|
4603
|
+
`, 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 });
|
|
4565
4604
|
}
|
|
4566
4605
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeDataSourceInspectorComponent, decorators: [{
|
|
4567
4606
|
type: Component,
|
|
4568
|
-
args: [{
|
|
4607
|
+
args: [{
|
|
4608
|
+
selector: 'dpe-data-source-inspector',
|
|
4609
|
+
standalone: true,
|
|
4610
|
+
imports: [DpeColumnTypeEditorComponent, DpeSelectValueDirective],
|
|
4611
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4612
|
+
template: `
|
|
4569
4613
|
<div class="dpe-form">
|
|
4570
4614
|
<div class="dpe-field">
|
|
4571
4615
|
<label class="dpe-field__label" for="ds-kind">Tipo di sorgente</label>
|
|
@@ -4729,7 +4773,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
4729
4773
|
</div>
|
|
4730
4774
|
</section>
|
|
4731
4775
|
</div>
|
|
4732
|
-
`,
|
|
4776
|
+
`,
|
|
4777
|
+
}]
|
|
4733
4778
|
}], ctorParameters: () => [] });
|
|
4734
4779
|
|
|
4735
4780
|
/**
|
|
@@ -4958,11 +5003,16 @@ class DpeFilterInspectorComponent extends DpeNodeInspectorBase {
|
|
|
4958
5003
|
</div>
|
|
4959
5004
|
}
|
|
4960
5005
|
</div>
|
|
4961
|
-
`, isInline: true,
|
|
5006
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4962
5007
|
}
|
|
4963
5008
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeFilterInspectorComponent, decorators: [{
|
|
4964
5009
|
type: Component,
|
|
4965
|
-
args: [{
|
|
5010
|
+
args: [{
|
|
5011
|
+
selector: 'dpe-filter-inspector',
|
|
5012
|
+
standalone: true,
|
|
5013
|
+
imports: [DpeSelectValueDirective],
|
|
5014
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5015
|
+
template: `
|
|
4966
5016
|
<div class="dpe-form">
|
|
4967
5017
|
<label class="dpe-check">
|
|
4968
5018
|
<input
|
|
@@ -5115,7 +5165,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
5115
5165
|
</div>
|
|
5116
5166
|
}
|
|
5117
5167
|
</div>
|
|
5118
|
-
`,
|
|
5168
|
+
`,
|
|
5169
|
+
}]
|
|
5119
5170
|
}] });
|
|
5120
5171
|
|
|
5121
5172
|
/**
|
|
@@ -5385,11 +5436,16 @@ class DpeForecastInspectorComponent extends DpeNodeInspectorBase {
|
|
|
5385
5436
|
}
|
|
5386
5437
|
</datalist>
|
|
5387
5438
|
</div>
|
|
5388
|
-
`, isInline: true,
|
|
5439
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5389
5440
|
}
|
|
5390
5441
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeForecastInspectorComponent, decorators: [{
|
|
5391
5442
|
type: Component,
|
|
5392
|
-
args: [{
|
|
5443
|
+
args: [{
|
|
5444
|
+
selector: 'dpe-forecast-inspector',
|
|
5445
|
+
standalone: true,
|
|
5446
|
+
imports: [DpeSelectValueDirective],
|
|
5447
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5448
|
+
template: `
|
|
5393
5449
|
<div class="dpe-form">
|
|
5394
5450
|
<p class="dpe-note dpe-note--not-compilable">
|
|
5395
5451
|
Nodo modellato per intero ma <strong>non traducibile in SQL</strong> nella versione 1:
|
|
@@ -5579,7 +5635,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
5579
5635
|
}
|
|
5580
5636
|
</datalist>
|
|
5581
5637
|
</div>
|
|
5582
|
-
`,
|
|
5638
|
+
`,
|
|
5639
|
+
}]
|
|
5583
5640
|
}] });
|
|
5584
5641
|
|
|
5585
5642
|
/**
|
|
@@ -5763,11 +5820,15 @@ class DpeHierarchyPathInspectorComponent extends DpeNodeInspectorBase {
|
|
|
5763
5820
|
}
|
|
5764
5821
|
</datalist>
|
|
5765
5822
|
</div>
|
|
5766
|
-
`, isInline: true,
|
|
5823
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5767
5824
|
}
|
|
5768
5825
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeHierarchyPathInspectorComponent, decorators: [{
|
|
5769
5826
|
type: Component,
|
|
5770
|
-
args: [{
|
|
5827
|
+
args: [{
|
|
5828
|
+
selector: 'dpe-hierarchy-path-inspector',
|
|
5829
|
+
standalone: true,
|
|
5830
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5831
|
+
template: `
|
|
5771
5832
|
<div class="dpe-form">
|
|
5772
5833
|
<p class="dpe-note">
|
|
5773
5834
|
Richiede le CTE ricorsive del dialetto di destinazione: se il dialetto scelto non le
|
|
@@ -5911,7 +5972,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
5911
5972
|
}
|
|
5912
5973
|
</datalist>
|
|
5913
5974
|
</div>
|
|
5914
|
-
`,
|
|
5975
|
+
`,
|
|
5976
|
+
}]
|
|
5915
5977
|
}] });
|
|
5916
5978
|
|
|
5917
5979
|
/**
|
|
@@ -6156,11 +6218,16 @@ class DpeJoinInspectorComponent extends DpeNodeInspectorBase {
|
|
|
6156
6218
|
}
|
|
6157
6219
|
</datalist>
|
|
6158
6220
|
</div>
|
|
6159
|
-
`, isInline: true,
|
|
6221
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: DpeSelectValueDirective, selector: "select[dpeValue]", inputs: ["dpeValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6160
6222
|
}
|
|
6161
6223
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeJoinInspectorComponent, decorators: [{
|
|
6162
6224
|
type: Component,
|
|
6163
|
-
args: [{
|
|
6225
|
+
args: [{
|
|
6226
|
+
selector: 'dpe-join-inspector',
|
|
6227
|
+
standalone: true,
|
|
6228
|
+
imports: [DpeSelectValueDirective],
|
|
6229
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
6230
|
+
template: `
|
|
6164
6231
|
<div class="dpe-form">
|
|
6165
6232
|
<div class="dpe-field">
|
|
6166
6233
|
<label class="dpe-field__label" for="join-kind">Tipo di join</label>
|
|
@@ -6348,7 +6415,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
6348
6415
|
}
|
|
6349
6416
|
</datalist>
|
|
6350
6417
|
</div>
|
|
6351
|
-
`,
|
|
6418
|
+
`,
|
|
6419
|
+
}]
|
|
6352
6420
|
}] });
|
|
6353
6421
|
|
|
6354
6422
|
/**
|
|
@@ -6412,11 +6480,15 @@ class DpeExpressionEditorComponent {
|
|
|
6412
6480
|
<p class="dpe-field__hint">Colonne in ingresso: {{ columnHint() }}</p>
|
|
6413
6481
|
}
|
|
6414
6482
|
</div>
|
|
6415
|
-
`, isInline: true,
|
|
6483
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6416
6484
|
}
|
|
6417
6485
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeExpressionEditorComponent, decorators: [{
|
|
6418
6486
|
type: Component,
|
|
6419
|
-
args: [{
|
|
6487
|
+
args: [{
|
|
6488
|
+
selector: 'dpe-expression-editor',
|
|
6489
|
+
standalone: true,
|
|
6490
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
6491
|
+
template: `
|
|
6420
6492
|
<div class="dpe-field">
|
|
6421
6493
|
<label class="dpe-field__label" [attr.for]="controlId()">{{ label() }}</label>
|
|
6422
6494
|
<textarea
|
|
@@ -6437,7 +6509,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
6437
6509
|
<p class="dpe-field__hint">Colonne in ingresso: {{ columnHint() }}</p>
|
|
6438
6510
|
}
|
|
6439
6511
|
</div>
|
|
6440
|
-
`,
|
|
6512
|
+
`,
|
|
6513
|
+
}]
|
|
6441
6514
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], dialect: [{ type: i0.Input, args: [{ isSignal: true, alias: "dialect", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], controlId: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlId", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
6442
6515
|
|
|
6443
6516
|
/**
|
|
@@ -6640,11 +6713,16 @@ class DpeTransformInspectorComponent extends DpeNodeInspectorBase {
|
|
|
6640
6713
|
}
|
|
6641
6714
|
</datalist>
|
|
6642
6715
|
</div>
|
|
6643
|
-
`, isInline: true,
|
|
6716
|
+
`, 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 });
|
|
6644
6717
|
}
|
|
6645
6718
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeTransformInspectorComponent, decorators: [{
|
|
6646
6719
|
type: Component,
|
|
6647
|
-
args: [{
|
|
6720
|
+
args: [{
|
|
6721
|
+
selector: 'dpe-transform-inspector',
|
|
6722
|
+
standalone: true,
|
|
6723
|
+
imports: [DpeColumnTypeEditorComponent, DpeExpressionEditorComponent, DpeSelectValueDirective],
|
|
6724
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
6725
|
+
template: `
|
|
6648
6726
|
<div class="dpe-form">
|
|
6649
6727
|
<div class="dpe-field">
|
|
6650
6728
|
<label class="dpe-field__label" for="tr-kind">Tipo di trasformazione</label>
|
|
@@ -6778,7 +6856,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
6778
6856
|
}
|
|
6779
6857
|
</datalist>
|
|
6780
6858
|
</div>
|
|
6781
|
-
`,
|
|
6859
|
+
`,
|
|
6860
|
+
}]
|
|
6782
6861
|
}] });
|
|
6783
6862
|
|
|
6784
6863
|
/**
|
|
@@ -7084,11 +7163,16 @@ class DpeWritebackInspectorComponent extends DpeNodeInspectorBase {
|
|
|
7084
7163
|
</div>
|
|
7085
7164
|
</section>
|
|
7086
7165
|
</div>
|
|
7087
|
-
`, isInline: true,
|
|
7166
|
+
`, 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 });
|
|
7088
7167
|
}
|
|
7089
7168
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeWritebackInspectorComponent, decorators: [{
|
|
7090
7169
|
type: Component,
|
|
7091
|
-
args: [{
|
|
7170
|
+
args: [{
|
|
7171
|
+
selector: 'dpe-writeback-inspector',
|
|
7172
|
+
standalone: true,
|
|
7173
|
+
imports: [DpeExpressionEditorComponent, DpeSelectValueDirective],
|
|
7174
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
7175
|
+
template: `
|
|
7092
7176
|
<div class="dpe-form">
|
|
7093
7177
|
<div class="dpe-row">
|
|
7094
7178
|
<div class="dpe-field">
|
|
@@ -7314,7 +7398,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
7314
7398
|
</div>
|
|
7315
7399
|
</section>
|
|
7316
7400
|
</div>
|
|
7317
|
-
`,
|
|
7401
|
+
`,
|
|
7402
|
+
}]
|
|
7318
7403
|
}] });
|
|
7319
7404
|
|
|
7320
7405
|
/**
|
|
@@ -7621,11 +7706,14 @@ class DpeNodeInspectorComponent {
|
|
|
7621
7706
|
} @else {
|
|
7622
7707
|
<p class="dpe-empty">Nessun nodo selezionato.</p>
|
|
7623
7708
|
}
|
|
7624
|
-
`, isInline: true,
|
|
7709
|
+
`, 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" }, { kind: "component", type: DpeNodeIconComponent, selector: "dpe-node-icon", inputs: ["collection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7625
7710
|
}
|
|
7626
7711
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeNodeInspectorComponent, decorators: [{
|
|
7627
7712
|
type: Component,
|
|
7628
|
-
args: [{
|
|
7713
|
+
args: [{
|
|
7714
|
+
selector: 'dpe-node-inspector',
|
|
7715
|
+
standalone: true,
|
|
7716
|
+
imports: [
|
|
7629
7717
|
DpeAggregateInspectorComponent,
|
|
7630
7718
|
DpeAppendInspectorComponent,
|
|
7631
7719
|
DpeAtomicWritebackInspectorComponent,
|
|
@@ -7638,7 +7726,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
7638
7726
|
DpeTransformInspectorComponent,
|
|
7639
7727
|
DpeWritebackInspectorComponent,
|
|
7640
7728
|
DpeNodeIconComponent,
|
|
7641
|
-
],
|
|
7729
|
+
],
|
|
7730
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
7731
|
+
template: `
|
|
7642
7732
|
@if (selectedNames().length > 1) {
|
|
7643
7733
|
<!--
|
|
7644
7734
|
Selezione multipla: si dice quanti sono e si offre solo cio' che ha senso su molti. Nessun
|
|
@@ -7821,7 +7911,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
7821
7911
|
} @else {
|
|
7822
7912
|
<p class="dpe-empty">Nessun nodo selezionato.</p>
|
|
7823
7913
|
}
|
|
7824
|
-
`,
|
|
7914
|
+
`,
|
|
7915
|
+
}]
|
|
7825
7916
|
}], ctorParameters: () => [], propDecorators: { layoutRequested: [{ type: i0.Output, args: ["layoutRequested"] }] } });
|
|
7826
7917
|
|
|
7827
7918
|
/**
|
|
@@ -7937,11 +8028,16 @@ class DpeNodePaletteComponent {
|
|
|
7937
8028
|
@if (visible().length === 0) {
|
|
7938
8029
|
<p class="dpe-palette__empty">Nessun nodo corrisponde alla ricerca.</p>
|
|
7939
8030
|
}
|
|
7940
|
-
`, isInline: true,
|
|
8031
|
+
`, 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 });
|
|
7941
8032
|
}
|
|
7942
8033
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeNodePaletteComponent, decorators: [{
|
|
7943
8034
|
type: Component,
|
|
7944
|
-
args: [{
|
|
8035
|
+
args: [{
|
|
8036
|
+
selector: 'dpe-node-palette',
|
|
8037
|
+
standalone: true,
|
|
8038
|
+
imports: [FFlowModule, DpeNodeIconComponent],
|
|
8039
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8040
|
+
template: `
|
|
7945
8041
|
<h3>Nodi</h3>
|
|
7946
8042
|
<input
|
|
7947
8043
|
type="search"
|
|
@@ -7986,7 +8082,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
7986
8082
|
@if (visible().length === 0) {
|
|
7987
8083
|
<p class="dpe-palette__empty">Nessun nodo corrisponde alla ricerca.</p>
|
|
7988
8084
|
}
|
|
7989
|
-
`,
|
|
8085
|
+
`,
|
|
8086
|
+
}]
|
|
7990
8087
|
}], propDecorators: { nodeRequested: [{ type: i0.Output, args: ["nodeRequested"] }] } });
|
|
7991
8088
|
|
|
7992
8089
|
/**
|
|
@@ -8107,11 +8204,15 @@ class DpeSqlPreviewComponent {
|
|
|
8107
8204
|
} @else {
|
|
8108
8205
|
<p class="dpe-sql__empty">Nessuna anteprima richiesta.</p>
|
|
8109
8206
|
}
|
|
8110
|
-
`, isInline: true,
|
|
8207
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8111
8208
|
}
|
|
8112
8209
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeSqlPreviewComponent, decorators: [{
|
|
8113
8210
|
type: Component,
|
|
8114
|
-
args: [{
|
|
8211
|
+
args: [{
|
|
8212
|
+
selector: 'dpe-sql-preview',
|
|
8213
|
+
standalone: true,
|
|
8214
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8215
|
+
template: `
|
|
8115
8216
|
<div class="dpe-sql__bar">
|
|
8116
8217
|
<button
|
|
8117
8218
|
type="button"
|
|
@@ -8185,7 +8286,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
8185
8286
|
} @else {
|
|
8186
8287
|
<p class="dpe-sql__empty">Nessuna anteprima richiesta.</p>
|
|
8187
8288
|
}
|
|
8188
|
-
`,
|
|
8289
|
+
`,
|
|
8290
|
+
}]
|
|
8189
8291
|
}] });
|
|
8190
8292
|
|
|
8191
8293
|
/**
|
|
@@ -8307,11 +8409,15 @@ class DpeSchemaPanelComponent {
|
|
|
8307
8409
|
calcolate) e barrate quelle che non arrivano a valle. Tratteggiate le nullabili.
|
|
8308
8410
|
</p>
|
|
8309
8411
|
}
|
|
8310
|
-
`, isInline: true,
|
|
8412
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8311
8413
|
}
|
|
8312
8414
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeSchemaPanelComponent, decorators: [{
|
|
8313
8415
|
type: Component,
|
|
8314
|
-
args: [{
|
|
8416
|
+
args: [{
|
|
8417
|
+
selector: 'dpe-schema-panel',
|
|
8418
|
+
standalone: true,
|
|
8419
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8420
|
+
template: `
|
|
8315
8421
|
@if (!hasResult()) {
|
|
8316
8422
|
<p class="dpe-schema__empty">In attesa della propagazione dello schema dal backend…</p>
|
|
8317
8423
|
}
|
|
@@ -8367,7 +8473,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
8367
8473
|
calcolate) e barrate quelle che non arrivano a valle. Tratteggiate le nullabili.
|
|
8368
8474
|
</p>
|
|
8369
8475
|
}
|
|
8370
|
-
`,
|
|
8476
|
+
`,
|
|
8477
|
+
}]
|
|
8371
8478
|
}] });
|
|
8372
8479
|
/** I nodi fuori dall'ordine di esecuzione (irraggiungibili) finiscono in coda, non in testa. */
|
|
8373
8480
|
function indexOrLast(order, name) {
|
|
@@ -8530,7 +8637,7 @@ class DpeBuilderComponent {
|
|
|
8530
8637
|
this.store.markSaved();
|
|
8531
8638
|
}
|
|
8532
8639
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8533
|
-
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 : 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 @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", styles: [":host{display:block;width:100%;height:100%;max-height:100%;min-height:0;overflow:hidden;color:var(--dpe-text, #1a1c23);font:inherit}.dpe-shell{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;overflow:hidden;background:var(--dpe-surface-alt, #f7f8fa)}.dpe-shell__bar{display:flex;flex:0 0 auto;align-items:center;gap:16px;padding:8px 12px;border-bottom:1px solid var(--dpe-border, #e2e5eb);background:var(--dpe-surface, #fff)}.dpe-shell__title{display:flex;align-items:baseline;gap:8px;min-width:0}.dpe-shell__sub,.dpe-shell__label{color:var(--dpe-text-muted, #6b7086);font-size:11px}.dpe-shell__dirty{flex:0 0 auto;color:var(--dpe-text-subtle, #98a2b3);font-size:11px;white-space:nowrap}.dpe-shell__dirty--on{color:var(--dpe-warning, #b7791f);font-weight:600}.dpe-shell__group{display:flex;align-items:center;gap:6px}.dpe-shell__status{margin-left:auto}.dpe-shell__group--primary{padding-left:14px;border-left:1px solid var(--dpe-border, #e2e5eb)}.dpe-shell__dialect{flex:0 0 auto;padding:3px 8px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:999px;background:var(--dpe-surface-alt, #f7f8fa);color:var(--dpe-text-muted, #6b7086);font-size:11px;white-space:nowrap;cursor:help}.dpe-shell__dialect strong{color:var(--dpe-text, #1a1c23)}.dpe-shell__toast{flex:0 0 auto;padding:2px 8px;border:1px solid var(--dpe-success, #22a06b);border-radius:999px;color:var(--dpe-success, #22a06b);font-size:11px;font-weight:600;white-space:nowrap}.dpe-shell__btn{padding:4px 9px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:var(--dpe-radius-xs, 6px);background:var(--dpe-surface, #fff);color:var(--dpe-text, #1a1c23);font:inherit;font-size:11px;cursor:pointer}.dpe-shell__btn:hover:not(:disabled){background:var(--dpe-surface-alt, #f7f8fa)}.dpe-shell__btn:disabled{opacity:.45;cursor:not-allowed}.dpe-shell__btn--primary{border-color:var(--dpe-accent, #2f7d8f);background:var(--dpe-accent, #2f7d8f);color:var(--dpe-accent-contrast, #fff)}.dpe-shell__pill{padding:2px 8px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:999px;background:var(--dpe-surface-alt, #f7f8fa);color:var(--dpe-text-muted, #6b7086);font-size:11px}.dpe-shell__pill--ok{border-color:var(--dpe-success, #22a06b);color:var(--dpe-success, #22a06b)}.dpe-shell__pill--error{border-color:var(--dpe-error, #dc2626);color:var(--dpe-error, #dc2626)}.dpe-shell__pill--busy{border-color:var(--dpe-info, #3b6fd4);color:var(--dpe-info, #3b6fd4)}.dpe-shell__btn--primary:hover:not(:disabled){border-color:var(--dpe-accent-strong, #226270);background:var(--dpe-accent-strong, #226270)}.dpe-shell__warn{display:flex;flex:0 0 auto;flex-direction:column;gap:6px;padding:10px 12px;border-bottom:1px solid var(--dpe-warning, #b7791f);background:color-mix(in srgb,var(--dpe-warning, #b7791f) 10%,var(--dpe-surface, #fff));font-size:12px}.dpe-shell__warn--error{border-bottom-color:var(--dpe-error, #dc2626);background:color-mix(in srgb,var(--dpe-error, #dc2626) 8%,var(--dpe-surface, #fff))}.dpe-shell__warn p{margin:0;line-height:1.5}.dpe-shell__body{display:grid;flex:1 1 auto;grid-template-columns:210px minmax(0,1fr) 340px;min-height:0;border-bottom:1px solid var(--dpe-border, #e2e5eb)}.dpe-shell__palette,.dpe-shell__inspector{min-height:0;max-height:100%}.dpe-shell__inspector{border-left:1px solid var(--dpe-border, #e2e5eb);background:var(--dpe-surface, #fff)}.dpe-shell__canvas{display:block;min-width:0;min-height:0;height:100%}.dpe-shell__bottom{display:flex;flex:0 0 280px;flex-direction:column;min-height:0;background:var(--dpe-surface, #fff)}.dpe-shell__tabs{display:flex;flex:0 0 auto;gap:2px;padding:0 8px;border-bottom:1px solid var(--dpe-border, #e2e5eb);background:var(--dpe-surface-alt, #f7f8fa)}.dpe-shell__tab{padding:6px 10px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dpe-text-muted, #6b7086);font:inherit;font-size:11px;cursor:pointer}.dpe-shell__tab--active{border-bottom-color:var(--dpe-accent, #2f7d8f);color:var(--dpe-text, #1a1c23);font-weight:600}.dpe-shell__panel{flex:1 1 auto;min-height:0;overflow:hidden}\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 });
|
|
8640
|
+
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 : 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 @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 });
|
|
8534
8641
|
}
|
|
8535
8642
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeBuilderComponent, decorators: [{
|
|
8536
8643
|
type: Component,
|
|
@@ -8541,7 +8648,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
|
|
|
8541
8648
|
DpeNodePaletteComponent,
|
|
8542
8649
|
DpeSchemaPanelComponent,
|
|
8543
8650
|
DpeSqlPreviewComponent,
|
|
8544
|
-
], 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 : 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 @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", styles: [":host{display:block;width:100%;height:100%;max-height:100%;min-height:0;overflow:hidden;color:var(--dpe-text, #1a1c23);font:inherit}.dpe-shell{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;overflow:hidden;background:var(--dpe-surface-alt, #f7f8fa)}.dpe-shell__bar{display:flex;flex:0 0 auto;align-items:center;gap:16px;padding:8px 12px;border-bottom:1px solid var(--dpe-border, #e2e5eb);background:var(--dpe-surface, #fff)}.dpe-shell__title{display:flex;align-items:baseline;gap:8px;min-width:0}.dpe-shell__sub,.dpe-shell__label{color:var(--dpe-text-muted, #6b7086);font-size:11px}.dpe-shell__dirty{flex:0 0 auto;color:var(--dpe-text-subtle, #98a2b3);font-size:11px;white-space:nowrap}.dpe-shell__dirty--on{color:var(--dpe-warning, #b7791f);font-weight:600}.dpe-shell__group{display:flex;align-items:center;gap:6px}.dpe-shell__status{margin-left:auto}.dpe-shell__group--primary{padding-left:14px;border-left:1px solid var(--dpe-border, #e2e5eb)}.dpe-shell__dialect{flex:0 0 auto;padding:3px 8px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:999px;background:var(--dpe-surface-alt, #f7f8fa);color:var(--dpe-text-muted, #6b7086);font-size:11px;white-space:nowrap;cursor:help}.dpe-shell__dialect strong{color:var(--dpe-text, #1a1c23)}.dpe-shell__toast{flex:0 0 auto;padding:2px 8px;border:1px solid var(--dpe-success, #22a06b);border-radius:999px;color:var(--dpe-success, #22a06b);font-size:11px;font-weight:600;white-space:nowrap}.dpe-shell__btn{padding:4px 9px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:var(--dpe-radius-xs, 6px);background:var(--dpe-surface, #fff);color:var(--dpe-text, #1a1c23);font:inherit;font-size:11px;cursor:pointer}.dpe-shell__btn:hover:not(:disabled){background:var(--dpe-surface-alt, #f7f8fa)}.dpe-shell__btn:disabled{opacity:.45;cursor:not-allowed}.dpe-shell__btn--primary{border-color:var(--dpe-accent, #2f7d8f);background:var(--dpe-accent, #2f7d8f);color:var(--dpe-accent-contrast, #fff)}.dpe-shell__pill{padding:2px 8px;border:1px solid var(--dpe-border, #e2e5eb);border-radius:999px;background:var(--dpe-surface-alt, #f7f8fa);color:var(--dpe-text-muted, #6b7086);font-size:11px}.dpe-shell__pill--ok{border-color:var(--dpe-success, #22a06b);color:var(--dpe-success, #22a06b)}.dpe-shell__pill--error{border-color:var(--dpe-error, #dc2626);color:var(--dpe-error, #dc2626)}.dpe-shell__pill--busy{border-color:var(--dpe-info, #3b6fd4);color:var(--dpe-info, #3b6fd4)}.dpe-shell__btn--primary:hover:not(:disabled){border-color:var(--dpe-accent-strong, #226270);background:var(--dpe-accent-strong, #226270)}.dpe-shell__warn{display:flex;flex:0 0 auto;flex-direction:column;gap:6px;padding:10px 12px;border-bottom:1px solid var(--dpe-warning, #b7791f);background:color-mix(in srgb,var(--dpe-warning, #b7791f) 10%,var(--dpe-surface, #fff));font-size:12px}.dpe-shell__warn--error{border-bottom-color:var(--dpe-error, #dc2626);background:color-mix(in srgb,var(--dpe-error, #dc2626) 8%,var(--dpe-surface, #fff))}.dpe-shell__warn p{margin:0;line-height:1.5}.dpe-shell__body{display:grid;flex:1 1 auto;grid-template-columns:210px minmax(0,1fr) 340px;min-height:0;border-bottom:1px solid var(--dpe-border, #e2e5eb)}.dpe-shell__palette,.dpe-shell__inspector{min-height:0;max-height:100%}.dpe-shell__inspector{border-left:1px solid var(--dpe-border, #e2e5eb);background:var(--dpe-surface, #fff)}.dpe-shell__canvas{display:block;min-width:0;min-height:0;height:100%}.dpe-shell__bottom{display:flex;flex:0 0 280px;flex-direction:column;min-height:0;background:var(--dpe-surface, #fff)}.dpe-shell__tabs{display:flex;flex:0 0 auto;gap:2px;padding:0 8px;border-bottom:1px solid var(--dpe-border, #e2e5eb);background:var(--dpe-surface-alt, #f7f8fa)}.dpe-shell__tab{padding:6px 10px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dpe-text-muted, #6b7086);font:inherit;font-size:11px;cursor:pointer}.dpe-shell__tab--active{border-bottom-color:var(--dpe-accent, #2f7d8f);color:var(--dpe-text, #1a1c23);font-weight:600}.dpe-shell__panel{flex:1 1 auto;min-height:0;overflow:hidden}\n"] }]
|
|
8651
|
+
], 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 : 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 @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" }]
|
|
8545
8652
|
}], 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 }] }] } });
|
|
8546
8653
|
|
|
8547
8654
|
/**
|
|
@@ -8687,11 +8794,11 @@ class DpeCatalogComponent {
|
|
|
8687
8794
|
return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleDateString();
|
|
8688
8795
|
}
|
|
8689
8796
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeCatalogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8690
|
-
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", styles: [":host{display:block;height:100%;min-height:0;overflow:hidden;font-family:var(--dpe-font);color:var(--dpe-text)}.dpe-cat{display:flex;flex-direction:column;height:100%;background:var(--dpe-surface-alt)}.dpe-cat__bar{display:flex;flex:0 0 auto;align-items:center;gap:10px;padding:10px 14px;border-bottom:1px solid var(--dpe-border);background:var(--dpe-surface)}.dpe-cat__title{margin:0;font-size:14px;font-weight:600}.dpe-cat__count{color:var(--dpe-text-muted);font-size:11px}.dpe-cat__filter{flex:0 1 260px;margin-left:auto;padding:5px 8px;border:1px solid var(--dpe-border-strong);border-radius:var(--dpe-radius-xs);background:var(--dpe-surface);color:inherit;font:inherit;font-size:12px}.dpe-cat__btn{padding:4px 9px;border:1px solid var(--dpe-border-strong);border-radius:var(--dpe-radius-xs);background:var(--dpe-surface);color:inherit;font:inherit;font-size:11px;white-space:nowrap;cursor:pointer}.dpe-cat__btn:hover:not(:disabled){border-color:var(--dpe-accent);color:var(--dpe-accent-strong)}.dpe-cat__btn:disabled{color:var(--dpe-text-subtle);cursor:not-allowed}.dpe-cat__btn--primary:not(:disabled){border-color:var(--dpe-accent-strong);background:var(--dpe-accent);color:var(--dpe-accent-contrast);font-weight:600}.dpe-cat__btn--danger:not(:disabled){border-color:var(--dpe-error);color:var(--dpe-error)}.dpe-cat__btn:focus-visible,.dpe-cat__filter:focus-visible,.dpe-cat__input:focus-visible,.dpe-cat__open:focus-visible{outline:2px solid var(--dpe-accent);outline-offset:-2px}.dpe-cat__error{display:flex;gap:8px;align-items:baseline;margin:0;padding:7px 14px;border-bottom:1px solid var(--dpe-border);background:color-mix(in srgb,var(--dpe-error) 10%,var(--dpe-surface));color:var(--dpe-error);font-size:11px}.dpe-cat__dismiss{margin-left:auto;border:0;background:transparent;color:inherit;font:inherit;cursor:pointer}.dpe-cat__list{flex:1 1 auto;min-height:0;margin:0;padding:8px 10px;overflow:auto;list-style:none}.dpe-cat__item{margin-bottom:6px;border:1px solid var(--dpe-border);border-radius:var(--dpe-radius);background:var(--dpe-surface);box-shadow:var(--dpe-shadow-sm)}.dpe-cat__item--busy{opacity:.72}.dpe-cat__row{display:flex;align-items:center;gap:10px;padding:6px 10px}.dpe-cat__open{display:grid;flex:1 1 auto;gap:2px;padding:5px 4px;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.dpe-cat__label{font-size:13px;font-weight:600}.dpe-cat__meta,.dpe-cat__desc{color:var(--dpe-text-muted);font-size:11px}.dpe-cat__name{font-family:var(--dpe-font-mono);font-size:10px}.dpe-cat__dot{color:var(--dpe-text-subtle)}.dpe-cat__flag{flex:0 0 auto;padding:2px 7px;border:1px solid var(--dpe-border-strong);border-radius:var(--dpe-radius-xs);color:var(--dpe-text-muted);font-size:10px}.dpe-cat__flag--errors{border-color:var(--dpe-error);background:color-mix(in srgb,var(--dpe-error) 8%,transparent);color:var(--dpe-error)}.dpe-cat__actions,.dpe-cat__confirm{display:flex;flex:0 0 auto;gap:6px;align-items:center;font-size:11px}.dpe-cat__empty{padding:18px 12px;color:var(--dpe-text-muted);font-size:12px;text-align:center}.dpe-cat__foot{flex:0 0 auto;padding:10px 14px;border-top:1px solid var(--dpe-border);background:var(--dpe-surface)}.dpe-cat__form{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end}.dpe-cat__form--inline{padding:8px 12px 10px;border-top:1px solid var(--dpe-border-subtle);background:var(--dpe-surface-sunken);border-radius:0 0 var(--dpe-radius) var(--dpe-radius)}.dpe-cat__field{display:grid;gap:3px;font-size:11px;color:var(--dpe-text-muted)}.dpe-cat__input{width:200px;padding:5px 8px;border:1px solid var(--dpe-border-strong);border-radius:var(--dpe-radius-xs);background:var(--dpe-surface);color:var(--dpe-text);font:inherit;font-size:12px}.dpe-cat__input:disabled{background:var(--dpe-surface-sunken);color:var(--dpe-text-subtle)}.dpe-cat__hint{margin:8px 0 0;color:var(--dpe-text-muted);font-size:11px;line-height:1.45}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8797
|
+
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 });
|
|
8691
8798
|
}
|
|
8692
8799
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: DpeCatalogComponent, decorators: [{
|
|
8693
8800
|
type: Component,
|
|
8694
|
-
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", styles: [":host{display:block;height:100%;min-height:0;overflow:hidden;font-family:var(--dpe-font);color:var(--dpe-text)}.dpe-cat{display:flex;flex-direction:column;height:100%;background:var(--dpe-surface-alt)}.dpe-cat__bar{display:flex;flex:0 0 auto;align-items:center;gap:10px;padding:10px 14px;border-bottom:1px solid var(--dpe-border);background:var(--dpe-surface)}.dpe-cat__title{margin:0;font-size:14px;font-weight:600}.dpe-cat__count{color:var(--dpe-text-muted);font-size:11px}.dpe-cat__filter{flex:0 1 260px;margin-left:auto;padding:5px 8px;border:1px solid var(--dpe-border-strong);border-radius:var(--dpe-radius-xs);background:var(--dpe-surface);color:inherit;font:inherit;font-size:12px}.dpe-cat__btn{padding:4px 9px;border:1px solid var(--dpe-border-strong);border-radius:var(--dpe-radius-xs);background:var(--dpe-surface);color:inherit;font:inherit;font-size:11px;white-space:nowrap;cursor:pointer}.dpe-cat__btn:hover:not(:disabled){border-color:var(--dpe-accent);color:var(--dpe-accent-strong)}.dpe-cat__btn:disabled{color:var(--dpe-text-subtle);cursor:not-allowed}.dpe-cat__btn--primary:not(:disabled){border-color:var(--dpe-accent-strong);background:var(--dpe-accent);color:var(--dpe-accent-contrast);font-weight:600}.dpe-cat__btn--danger:not(:disabled){border-color:var(--dpe-error);color:var(--dpe-error)}.dpe-cat__btn:focus-visible,.dpe-cat__filter:focus-visible,.dpe-cat__input:focus-visible,.dpe-cat__open:focus-visible{outline:2px solid var(--dpe-accent);outline-offset:-2px}.dpe-cat__error{display:flex;gap:8px;align-items:baseline;margin:0;padding:7px 14px;border-bottom:1px solid var(--dpe-border);background:color-mix(in srgb,var(--dpe-error) 10%,var(--dpe-surface));color:var(--dpe-error);font-size:11px}.dpe-cat__dismiss{margin-left:auto;border:0;background:transparent;color:inherit;font:inherit;cursor:pointer}.dpe-cat__list{flex:1 1 auto;min-height:0;margin:0;padding:8px 10px;overflow:auto;list-style:none}.dpe-cat__item{margin-bottom:6px;border:1px solid var(--dpe-border);border-radius:var(--dpe-radius);background:var(--dpe-surface);box-shadow:var(--dpe-shadow-sm)}.dpe-cat__item--busy{opacity:.72}.dpe-cat__row{display:flex;align-items:center;gap:10px;padding:6px 10px}.dpe-cat__open{display:grid;flex:1 1 auto;gap:2px;padding:5px 4px;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.dpe-cat__label{font-size:13px;font-weight:600}.dpe-cat__meta,.dpe-cat__desc{color:var(--dpe-text-muted);font-size:11px}.dpe-cat__name{font-family:var(--dpe-font-mono);font-size:10px}.dpe-cat__dot{color:var(--dpe-text-subtle)}.dpe-cat__flag{flex:0 0 auto;padding:2px 7px;border:1px solid var(--dpe-border-strong);border-radius:var(--dpe-radius-xs);color:var(--dpe-text-muted);font-size:10px}.dpe-cat__flag--errors{border-color:var(--dpe-error);background:color-mix(in srgb,var(--dpe-error) 8%,transparent);color:var(--dpe-error)}.dpe-cat__actions,.dpe-cat__confirm{display:flex;flex:0 0 auto;gap:6px;align-items:center;font-size:11px}.dpe-cat__empty{padding:18px 12px;color:var(--dpe-text-muted);font-size:12px;text-align:center}.dpe-cat__foot{flex:0 0 auto;padding:10px 14px;border-top:1px solid var(--dpe-border);background:var(--dpe-surface)}.dpe-cat__form{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end}.dpe-cat__form--inline{padding:8px 12px 10px;border-top:1px solid var(--dpe-border-subtle);background:var(--dpe-surface-sunken);border-radius:0 0 var(--dpe-radius) var(--dpe-radius)}.dpe-cat__field{display:grid;gap:3px;font-size:11px;color:var(--dpe-text-muted)}.dpe-cat__input{width:200px;padding:5px 8px;border:1px solid var(--dpe-border-strong);border-radius:var(--dpe-radius-xs);background:var(--dpe-surface);color:var(--dpe-text);font:inherit;font-size:12px}.dpe-cat__input:disabled{background:var(--dpe-surface-sunken);color:var(--dpe-text-subtle)}.dpe-cat__hint{margin:8px 0 0;color:var(--dpe-text-muted);font-size:11px;line-height:1.45}\n"] }]
|
|
8801
|
+
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" }]
|
|
8695
8802
|
}], propDecorators: { open: [{ type: i0.Output, args: ["open"] }], duplicateNameField: [{ type: i0.ViewChild, args: ['duplicateNameField', { isSignal: true }] }] } });
|
|
8696
8803
|
|
|
8697
8804
|
/*
|