wuic-framework-lib 1.0.7 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{wuic-framework-lib-chart-list.component-j1eRaGZV.mjs → wuic-framework-lib-chart-list.component-vuzmQW9F.mjs} +56 -4
- package/fesm2022/{wuic-framework-lib-code-editor.component-CNREC7r_.mjs → wuic-framework-lib-code-editor.component-BjbIkm4g.mjs} +4 -4
- package/fesm2022/wuic-framework-lib-core.mjs +1 -1
- package/fesm2022/{wuic-framework-lib-designer.component-Bb4B6eDu.mjs → wuic-framework-lib-designer.component-BM3elB-a.mjs} +49 -33
- package/fesm2022/{wuic-framework-lib-first-run-wizard.component-CQTs6hR6.mjs → wuic-framework-lib-first-run-wizard.component-5tcl67dK.mjs} +31 -12
- package/fesm2022/{wuic-framework-lib-framework-docs.component-CzyQHVAV.mjs → wuic-framework-lib-framework-docs.component-BGcJ7k1X.mjs} +484 -13
- package/fesm2022/{wuic-framework-lib-pivot-builder.component-ms-x0Yob.mjs → wuic-framework-lib-pivot-builder.component-ChNyMAfi.mjs} +29 -16
- package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-mXhyuLAE.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-DFLR_EmK.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-report-designer.component-BjUmOBU3.mjs → wuic-framework-lib-report-designer.component-B_SC7VkW.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-report-viewer.component-BOenTSd2.mjs → wuic-framework-lib-report-viewer.component-BTK-p8xF.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-scheduler-list.component-DHcLQ_X7.mjs → wuic-framework-lib-scheduler-list.component-CIoGVf4O.mjs} +12 -4
- package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-AFm6hAX4.mjs → wuic-framework-lib-spreadsheet-list-sf.component-DQ5OxO4j.mjs} +10 -4
- package/fesm2022/{wuic-framework-lib-workflow-designer.component-Bn6ocOVw.mjs → wuic-framework-lib-workflow-designer.component-BHLT4MER.mjs} +29 -3
- package/fesm2022/{wuic-framework-lib-wuic-framework-lib-KFbUlRIT.mjs → wuic-framework-lib-wuic-framework-lib-DDokY6wY.mjs} +2130 -491
- package/fesm2022/wuic-framework-lib.mjs +1 -1
- package/package.json +1 -1
- package/types/wuic-framework-lib-core.d.ts +1 -1
- package/types/wuic-framework-lib.d.ts +458 -15
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as i1$1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { signal, inject, computed, ViewChild, Component } from '@angular/core';
|
|
5
|
-
import * as i1$
|
|
5
|
+
import * as i1$2 from '@angular/forms';
|
|
6
6
|
import { FormsModule } from '@angular/forms';
|
|
7
7
|
import * as i4 from 'primeng/button';
|
|
8
8
|
import { ButtonModule } from 'primeng/button';
|
|
@@ -12,16 +12,16 @@ import * as i10 from 'primeng/tag';
|
|
|
12
12
|
import { TagModule } from 'primeng/tag';
|
|
13
13
|
import * as i3 from 'primeng/tooltip';
|
|
14
14
|
import { TooltipModule } from 'primeng/tooltip';
|
|
15
|
-
import * as i1$
|
|
15
|
+
import * as i1$3 from 'primeng/image';
|
|
16
16
|
import { ImageModule } from 'primeng/image';
|
|
17
|
-
import * as i2
|
|
17
|
+
import * as i2 from '@ngx-translate/core';
|
|
18
18
|
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
19
|
-
import {
|
|
19
|
+
import { q as getThemeOptions, T as TranslationManagerService, U as UserInfoService } from './wuic-framework-lib-wuic-framework-lib-DDokY6wY.mjs';
|
|
20
20
|
import * as i1 from '@angular/router';
|
|
21
21
|
|
|
22
22
|
const frameworkDocsContent = {
|
|
23
23
|
"version": "1.0.0",
|
|
24
|
-
"generatedAt": "2026-04-
|
|
24
|
+
"generatedAt": "2026-04-27T15:49:14.823Z",
|
|
25
25
|
"groups": [
|
|
26
26
|
{
|
|
27
27
|
"id": "primi-passi",
|
|
@@ -732,6 +732,22 @@ const frameworkDocsContent = {
|
|
|
732
732
|
"integration"
|
|
733
733
|
]
|
|
734
734
|
},
|
|
735
|
+
{
|
|
736
|
+
"slug": "custom-exception-handling",
|
|
737
|
+
"title": "Gestione eccezioni custom",
|
|
738
|
+
"titles": {
|
|
739
|
+
"en-US": "Custom Exception Handling",
|
|
740
|
+
"fr-FR": "Gestion personnalisée des exceptions",
|
|
741
|
+
"es-ES": "Gestión personalizada de excepciones",
|
|
742
|
+
"de-DE": "Benutzerdefinierte Ausnahmebehandlung"
|
|
743
|
+
},
|
|
744
|
+
"icon": "pi-exclamation-triangle",
|
|
745
|
+
"status": "stable",
|
|
746
|
+
"audience": [
|
|
747
|
+
"developer",
|
|
748
|
+
"integration"
|
|
749
|
+
]
|
|
750
|
+
},
|
|
735
751
|
{
|
|
736
752
|
"slug": "component-injection",
|
|
737
753
|
"title": "Component Injection",
|
|
@@ -4156,7 +4172,7 @@ const frameworkDocsContent = {
|
|
|
4156
4172
|
{
|
|
4157
4173
|
"id": "overview",
|
|
4158
4174
|
"title": "Overview",
|
|
4159
|
-
"html": "<h1>Catalogo Componenti</h1><p>Totale cartelle componenti rilevate:
|
|
4175
|
+
"html": "<h1>Catalogo Componenti</h1><p>Totale cartelle componenti rilevate: 48.</p><h2>Componenti disponibili</h2><ul><li>app-settings-editor</li><li>archetype-configurator</li><li>bounded-repeater</li><li>carousel-list</li><li>chart-list</li><li>code-editor</li><li>css-sheet-editor</li><li>dashboard</li><li>data-action-button</li><li>data-repeater</li><li>data-source</li><li>designer</li><li>dynamic-dashboard-template</li><li>dynamic-field-template</li><li>dynamic-form-template</li><li>dynamic-generic-template</li><li>dynamic-repeater-template</li><li>dynamic-template</li><li>field</li><li>filter-bar</li><li>first-run-wizard</li><li>framework-docs</li><li>image-wrapper</li><li>import-export-button</li><li>kanban-list</li><li>list-grid</li><li>map-list</li><li>meta-menu</li><li>metadata-editor</li><li>notification-bell</li><li>pager</li><li>parametric-dialog</li><li>pivot-builder</li><li>prompt-dialog-fallback-host</li><li>rag-chatbot</li><li>rag-chatbot-fab</li><li>report-designer</li><li>report-viewer</li><li>scheduler-list</li><li>split</li><li>split-area</li><li>spreadsheet-list-sf</li><li>tab-panel-wrapper</li><li>tab-view-wrapper</li><li>tree-list</li><li>upload-dialog</li><li>workflow-designer</li><li>workflow-runner</li></ul><h2>Export da public-api</h2><ul><li>data-source/data-source.component</li><li>list-grid/list-grid.component</li><li>import-export-button/import-export-button.component</li><li>pager/pager.component</li><li>filter-bar/filter-bar.component</li><li>map-list/map-list.component</li><li>carousel-list/carousel-list.component</li><li>tree-list/tree-list.component</li><li>parametric-dialog/parametric-dialog.component</li><li>upload-dialog/upload-dialog.component</li><li>app-settings-editor/app-settings-editor.component</li><li>data-action-button/data-action-button.component</li><li>meta-menu/meta-menu.component</li><li>field/text-editor/text-editor.component</li><li>field/text-area-editor/text-area-editor.component</li><li>field/number-editor/number-editor.component</li><li>field/lookup-editor/lookup-editor.component</li><li>field/dictionary-editor/dictionary-editor.component</li><li>field/boolean-editor/boolean-editor.component</li><li>field/date-editor/date-editor.component</li><li>field/html-editor/html-editor.component</li><li>field/upload-editor/upload-editor.component</li><li>field/button-editor/button-editor.component</li><li>field/field-editor/field-editor.component</li><li>field/code-area-editor/code-area-editor.component</li><li>dynamic-template/dynamic-template.component</li><li>image-wrapper/image-wrapper.component</li><li>field/color-editor/color-editor.component</li><li>field/property-array-editor/property-array-editor.component</li><li>field/property-object-editor/property-object-editor.component</li><li>field/tree-view-selector/tree-view-selector.component</li><li>workflow-designer/workflow-designer.component</li><li>workflow-runner/workflow-runner.component</li><li>notification-bell/notification-bell.component</li><li>bounded-repeater/bounded-repeater.component</li><li>framework-docs/framework-docs.component</li><li>designer/designer.route.component</li><li>workflow-designer/workflow-designer.route.component</li><li>kanban-list/kanban-list.component</li><li>data-repeater/data-repeater.component</li><li>bounded-repeater/bounded-repeater-pending-changes.guard</li><li>rag-chatbot/rag-chatbot.component</li><li>rag-chatbot-fab/rag-chatbot-fab.component</li></ul>",
|
|
4160
4176
|
"codeSamples": []
|
|
4161
4177
|
}
|
|
4162
4178
|
],
|
|
@@ -4753,6 +4769,97 @@ const frameworkDocsContent = {
|
|
|
4753
4769
|
}
|
|
4754
4770
|
]
|
|
4755
4771
|
},
|
|
4772
|
+
{
|
|
4773
|
+
"slug": "custom-exception-handling",
|
|
4774
|
+
"lang": "it-IT",
|
|
4775
|
+
"title": "Gestione eccezioni custom",
|
|
4776
|
+
"description": "Gestione eccezioni custom - documentazione operativa e tecnica",
|
|
4777
|
+
"audience": [
|
|
4778
|
+
"developer",
|
|
4779
|
+
"integration"
|
|
4780
|
+
],
|
|
4781
|
+
"status": "stable",
|
|
4782
|
+
"tags": [
|
|
4783
|
+
"advanced"
|
|
4784
|
+
],
|
|
4785
|
+
"keywords": [
|
|
4786
|
+
"Gestione eccezioni custom"
|
|
4787
|
+
],
|
|
4788
|
+
"toc": [
|
|
4789
|
+
{
|
|
4790
|
+
"id": "sec_1",
|
|
4791
|
+
"title": "Architettura attuale (riassunto)"
|
|
4792
|
+
},
|
|
4793
|
+
{
|
|
4794
|
+
"id": "sec_2",
|
|
4795
|
+
"title": "Punti di estensione"
|
|
4796
|
+
},
|
|
4797
|
+
{
|
|
4798
|
+
"id": "sec_3",
|
|
4799
|
+
"title": "Eccezioni server-side dal codice consumer"
|
|
4800
|
+
},
|
|
4801
|
+
{
|
|
4802
|
+
"id": "sec_4",
|
|
4803
|
+
"title": "Esempio completo nel progetto WuicTest"
|
|
4804
|
+
},
|
|
4805
|
+
{
|
|
4806
|
+
"id": "sec_5",
|
|
4807
|
+
"title": "Best practice"
|
|
4808
|
+
}
|
|
4809
|
+
],
|
|
4810
|
+
"sections": [
|
|
4811
|
+
{
|
|
4812
|
+
"id": "overview",
|
|
4813
|
+
"title": "Overview",
|
|
4814
|
+
"html": "<h1>Gestione eccezioni custom (consumer)</h1><p>Il framework WUIC fornisce una gestione eccezioni tipizzata e localizzata pronta all'uso. Il consumer puo' estenderla per aggiungere telemetria, filtrare rumore noto o emettere errori applicativi propri — senza riscrivere il flusso.</p><h2>Architettura attuale (riassunto)</h2><p>Lato server (<code>KonvergenceCore</code>):</p><ul><li><code>JsonExceptionFilter</code> cattura ogni eccezione di <code>MetaService.*</code> (e dell'AsmxProxy in generale) e produce un envelope JSON <code>{ ok:false, errorCode, args, traceId, fallbackMessage }</code>.</li><li><code>MetaExceptionTranslator</code> mappa eccezioni note (es. <code>JsonReaderException</code> → <code>errors.metadata.props_bag.malformed</code>, <code>OperationDisabledException</code> → <code>errors.auth.operation_disabled</code>, <code>SqlException</code> → <code>errors.db.sql_exception</code> con passthrough completo).</li><li>Il fallback generico e' <code>errors.server.unhandled</code> con <code>traceId</code> per correlazione log.</li></ul><p>Lato client (<code>wuic-framework-lib</code>):</p><ul><li><code>GlobalHandler</code> (implementa <code>ErrorHandler</code> di Angular) e' il dispatcher centrale. Branch ordinati: SQL passthrough → typed exceptions client → typed envelope server → NG04002 routing → template runtime errors → legacy → fallback.</li><li><code>WtoolboxService.runUserCallback</code> / <code>runUserCallbackSync</code> / <code>wrapArchetypeLifecycleSync</code> sono helper per wrappare codice JS proveniente da metadata utente (callback, archetype lifecycle) con typed envelope automatico.</li><li>Le traduzioni vengono caricate dalla tabella <code>_wuic_translations</code> via <code>TranslationManagerService</code> (cache localStorage) e supportano placeholder <code>{argName}</code> interpolati direttamente dal <code>GlobalHandler</code>.</li><li><code>BehaviorSubject GlobalHandler.messageNotification</code> emette ogni eccezione gia' tipizzata e localizzata: il consumer si aggancia qui per renderizzare il dialog (vedi <code>app.component.ts</code> di esempio).</li></ul><p>Wiring tipico nel consumer (<code>app.config.ts</code>):</p><p>Snippet 1:</p><h2>Punti di estensione</h2><h3>Pattern 1 — Subscribe (cross-cutting telemetry, CONSIGLIATO)</h3><p>Aggancia un secondo subscriber a <code>GlobalHandler.messageNotification</code> accanto a quello del dialog. Permette di inviare ogni eccezione (gia' tipizzata, gia' localizzata) a un sistema di analytics o logging custom.</p><p>Snippet 2:</p><p>Vantaggi:</p><ul><li>Non altera il flusso del framework.</li><li>Si aggiunge/rimuove senza tocchi al wiring DI.</li><li>Riceve l'eccezione DOPO la tipizzazione (errorCode + args interpolati).</li></ul><h3>Pattern 2 — Subclass <code>GlobalHandler</code> (override <code>handleError</code>)</h3><p>Quando serve intervenire PRIMA che il framework decida cosa fare con l'errore: filtrare errori noti non azionabili, arricchire <code>args</code> con context applicativo (versione build, ruolo utente), convertire un errore generico in tipizzato.</p><p>Snippet 3:</p><p>Wiring:</p><p>Snippet 4:</p><p>Vantaggi:</p><ul><li>Pieno controllo sul punto di entry.</li><li>Mantiene tutta la logica del framework chiamando <code>super.handleError(e)</code>.</li></ul><p>Attenzione:</p><ul><li>Se NON chiami <code>super.handleError</code>, perdi le typed envelopes — usa Pattern 3 solo se davvero necessario.</li></ul><h3>Pattern 3 — Replace completo (NON CONSIGLIATO)</h3><p>Implementare <code>ErrorHandler</code> da zero senza estendere <code>GlobalHandler</code> disabilita TUTTE le funzionalita' built-in: traduzioni, typed envelopes, SQL passthrough, dialog dedicati, NG04002 routing, error-tagging dei dynamic template. Usare solo se hai requisiti molto specifici e sei pronto a re-implementare il flusso end-to-end.</p><h3>Pattern 4 — Throw eccezioni tipizzate dal codice consumer</h3><p>Il consumer puo' EMETTERE eccezioni tipizzate proprie che riceveranno lo stesso trattamento (traduzione + dialog) delle eccezioni del framework. Importa <code>WuicClientException</code> e lancia con il tuo <code>errorCode</code> applicativo:</p><p>Snippet 5:</p><p>Aggiungi le traduzioni <code>errors.myapp.feature_disabled</code> nel tuo seed di <code>_wuic_translations</code> (it-IT + en-US e gli altri locale supportati). Da quel momento qualunque throw produrra' un dialog localizzato senza ulteriore wiring:</p><p>Snippet 6:</p><p>Il placeholder <code>{feature}</code> viene interpolato automaticamente dagli <code>args</code> passati alla <code>WuicClientException</code>.</p><h2>Eccezioni server-side dal codice consumer</h2><p>Lato server (controller/service consumer) il pattern e' analogo: lancia <code>WuicException</code> dal namespace del framework e il <code>JsonExceptionFilter</code> produce l'envelope JSON tipizzato che il client traduce.</p><p>Snippet 7:</p><p>L'<code>HttpStatus</code> controlla il codice HTTP della risposta; il <code>fallbackMessage</code> viene mostrato se la traduzione manca.</p><h2>Esempio completo nel progetto WuicTest</h2><p>Un esempio funzionante con tutti e 4 i pattern (con commenti, snippet inline, e wiring di esempio) e' presente in:</p><ul><li><a href=\"https://github.com/wuic/wuic-framework/blob/main/WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts\" target=\"_blank\" rel=\"noopener noreferrer\">`WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts`</a></li></ul><p>Il file e' incluso nel sorgente del progetto consumer di test e contiene 4 sezioni:</p><p>1. <code>installCustomTelemetry()</code> — Pattern 1 (subscribe), pronto da chiamare in <code>AppComponent.ngOnInit</code>.</p><p>2. <code>MyCustomErrorHandler</code> — Pattern 2 (subclass), pronto da wirare in <code>app.config.ts</code>.</p><p>3. Pattern 3 — esempio commentato (NON consigliato).</p><p>4. Pattern 4 — snippet di throw <code>WuicClientException</code> dal codice applicativo.</p><h2>Best practice</h2><ul><li><strong>Privilegia Pattern 1</strong> (subscribe) per telemetria/logging — non altera il flusso e si rimuove facilmente.</li><li><strong>Usa Pattern 2</strong> (subclass) solo se devi intervenire prima del default (filtro rumore, arricchimento args).</li><li><strong>Mai Pattern 3</strong> salvo requisiti enterprise specifici — perdi tutto il built-in.</li><li><strong>Sempre seed le traduzioni</strong> dei tuoi <code>errorCode</code> applicativi (it-IT + en-US minimo) prima di rilasciare in produzione, altrimenti il dialog mostra la chiave grezza.</li><li><strong>Usa `traceId` server-side</strong> nel template di traduzione (es. <code>"Codice: {traceId}"</code>) per facilitare la diagnostica condivisa fra utente e team supporto.</li></ul>",
|
|
4815
|
+
"codeSamples": [
|
|
4816
|
+
{
|
|
4817
|
+
"id": "code_1",
|
|
4818
|
+
"title": "Snippet 1",
|
|
4819
|
+
"language": "ts",
|
|
4820
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: GlobalHandler },\n ...\n]"
|
|
4821
|
+
},
|
|
4822
|
+
{
|
|
4823
|
+
"id": "code_2",
|
|
4824
|
+
"title": "Snippet 2",
|
|
4825
|
+
"language": "ts",
|
|
4826
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nGlobalHandler.messageNotification.subscribe((data) => {\n const exc = data?.exception;\n if (!exc?.errorCode) return;\n\n // Filtra rumore noto.\n if (String(exc.errorCode).startsWith('errors.client.archetype.')) return;\n\n // Invio a endpoint analytics (Sentry, App Insights, ecc.).\n fetch('/analytics/client-errors', {\n method: 'POST',\n body: JSON.stringify({\n errorCode: exc.errorCode,\n args: exc.args,\n traceId: exc.traceId,\n url: window.location.href,\n ts: new Date().toISOString(),\n }),\n credentials: 'include',\n });\n});"
|
|
4827
|
+
},
|
|
4828
|
+
{
|
|
4829
|
+
"id": "code_3",
|
|
4830
|
+
"title": "Snippet 3",
|
|
4831
|
+
"language": "ts",
|
|
4832
|
+
"code": "import { ErrorHandler, Injectable } from '@angular/core';\nimport { GlobalHandler } from './wuic-bridges/core';\n\n@Injectable()\nexport class MyCustomErrorHandler extends GlobalHandler {\n override handleError(e: any): void {\n // 1. Suppress noise non azionabile.\n const msg = (typeof e?.message === 'string' ? e.message : '') as string;\n if (msg.includes('ResizeObserver loop limit exceeded')) {\n console.debug('[MyCustomErrorHandler] suppressed:', msg);\n return;\n }\n\n // 2. Arricchisci args con context applicativo.\n if (typeof e?.error?.errorCode === 'string' && e?.error?.args) {\n e.error.args = {\n ...e.error.args,\n appVersion: (window as any).__myAppVersion || 'dev',\n userRole: (window as any).__myAppUserRole || 'unknown',\n };\n }\n\n // 3. Delega al default — tutte le typed envelopes, traduzioni,\n // dialog SQL passthrough, NG04002 routing continuano a funzionare.\n super.handleError(e);\n }\n}"
|
|
4833
|
+
},
|
|
4834
|
+
{
|
|
4835
|
+
"id": "code_4",
|
|
4836
|
+
"title": "Snippet 4",
|
|
4837
|
+
"language": "ts",
|
|
4838
|
+
"code": "// app.config.ts\nimport { MyCustomErrorHandler } from './exception-handling/custom-error-handler.example';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: MyCustomErrorHandler },\n ...\n]"
|
|
4839
|
+
},
|
|
4840
|
+
{
|
|
4841
|
+
"id": "code_5",
|
|
4842
|
+
"title": "Snippet 5",
|
|
4843
|
+
"language": "ts",
|
|
4844
|
+
"code": "import { WuicClientException } from 'wuic-framework-lib-src/exception/WuicClientException';\n\nif (!myConfig.exportEnabled) {\n throw new WuicClientException(\n 'errors.myapp.feature_disabled',\n { feature: 'export-pdf' },\n { surface: 'service', targetName: 'MyAppService.exportPdf' }\n );\n}"
|
|
4845
|
+
},
|
|
4846
|
+
{
|
|
4847
|
+
"id": "code_6",
|
|
4848
|
+
"title": "Snippet 6",
|
|
4849
|
+
"language": "sql",
|
|
4850
|
+
"code": "-- Esempio seed (idempotente, vedi scripts/upsert-wuic-translations.ps1).\nINSERT INTO _wuic_translations (translation_key, locale, translation_text)\nVALUES\n ('errors.myapp.feature_disabled', 'it-IT', \"Funzionalita' '{feature}' disabilitata in questa versione.\"),\n ('errors.myapp.feature_disabled', 'en-US', \"Feature ''{feature}'' is disabled in this build.\");"
|
|
4851
|
+
},
|
|
4852
|
+
{
|
|
4853
|
+
"id": "code_7",
|
|
4854
|
+
"title": "Snippet 7",
|
|
4855
|
+
"language": "csharp",
|
|
4856
|
+
"code": "using WEB_UI_CRAFTER.Helpers.Exceptions;\n\nif (!_myService.IsLicensed(\"export-pdf\"))\n{\n throw new WuicException(\n \"errors.myapp.license.missing\",\n new Dictionary<string, object>\n {\n [\"feature\"] = \"export-pdf\",\n [\"tier\"] = currentTier,\n })\n {\n HttpStatus = 403,\n FallbackMessage = $\"License missing for feature 'export-pdf' (tier '{currentTier}').\",\n };\n}"
|
|
4857
|
+
}
|
|
4858
|
+
]
|
|
4859
|
+
}
|
|
4860
|
+
],
|
|
4861
|
+
"images": []
|
|
4862
|
+
},
|
|
4756
4863
|
{
|
|
4757
4864
|
"slug": "component-injection",
|
|
4758
4865
|
"lang": "it-IT",
|
|
@@ -9058,7 +9165,7 @@ const frameworkDocsContent = {
|
|
|
9058
9165
|
{
|
|
9059
9166
|
"id": "overview",
|
|
9060
9167
|
"title": "Overview",
|
|
9061
|
-
"html": "<h1>Component Catalog</h1><p>Total component folders detected:
|
|
9168
|
+
"html": "<h1>Component Catalog</h1><p>Total component folders detected: 48.</p><h2>Available components</h2><ul><li>app-settings-editor</li><li>archetype-configurator</li><li>bounded-repeater</li><li>carousel-list</li><li>chart-list</li><li>code-editor</li><li>css-sheet-editor</li><li>dashboard</li><li>data-action-button</li><li>data-repeater</li><li>data-source</li><li>designer</li><li>dynamic-dashboard-template</li><li>dynamic-field-template</li><li>dynamic-form-template</li><li>dynamic-generic-template</li><li>dynamic-repeater-template</li><li>dynamic-template</li><li>field</li><li>filter-bar</li><li>first-run-wizard</li><li>framework-docs</li><li>image-wrapper</li><li>import-export-button</li><li>kanban-list</li><li>list-grid</li><li>map-list</li><li>meta-menu</li><li>metadata-editor</li><li>notification-bell</li><li>pager</li><li>parametric-dialog</li><li>pivot-builder</li><li>prompt-dialog-fallback-host</li><li>rag-chatbot</li><li>rag-chatbot-fab</li><li>report-designer</li><li>report-viewer</li><li>scheduler-list</li><li>split</li><li>split-area</li><li>spreadsheet-list-sf</li><li>tab-panel-wrapper</li><li>tab-view-wrapper</li><li>tree-list</li><li>upload-dialog</li><li>workflow-designer</li><li>workflow-runner</li></ul><h2>Exports from public-api</h2><ul><li>data-source/data-source.component</li><li>list-grid/list-grid.component</li><li>import-export-button/import-export-button.component</li><li>pager/pager.component</li><li>filter-bar/filter-bar.component</li><li>map-list/map-list.component</li><li>carousel-list/carousel-list.component</li><li>tree-list/tree-list.component</li><li>parametric-dialog/parametric-dialog.component</li><li>upload-dialog/upload-dialog.component</li><li>app-settings-editor/app-settings-editor.component</li><li>data-action-button/data-action-button.component</li><li>meta-menu/meta-menu.component</li><li>field/text-editor/text-editor.component</li><li>field/text-area-editor/text-area-editor.component</li><li>field/number-editor/number-editor.component</li><li>field/lookup-editor/lookup-editor.component</li><li>field/dictionary-editor/dictionary-editor.component</li><li>field/boolean-editor/boolean-editor.component</li><li>field/date-editor/date-editor.component</li><li>field/html-editor/html-editor.component</li><li>field/upload-editor/upload-editor.component</li><li>field/button-editor/button-editor.component</li><li>field/field-editor/field-editor.component</li><li>field/code-area-editor/code-area-editor.component</li><li>dynamic-template/dynamic-template.component</li><li>image-wrapper/image-wrapper.component</li><li>field/color-editor/color-editor.component</li><li>field/property-array-editor/property-array-editor.component</li><li>field/property-object-editor/property-object-editor.component</li><li>field/tree-view-selector/tree-view-selector.component</li><li>workflow-designer/workflow-designer.component</li><li>workflow-runner/workflow-runner.component</li><li>notification-bell/notification-bell.component</li><li>bounded-repeater/bounded-repeater.component</li><li>framework-docs/framework-docs.component</li><li>designer/designer.route.component</li><li>workflow-designer/workflow-designer.route.component</li><li>kanban-list/kanban-list.component</li><li>data-repeater/data-repeater.component</li><li>bounded-repeater/bounded-repeater-pending-changes.guard</li><li>rag-chatbot/rag-chatbot.component</li><li>rag-chatbot-fab/rag-chatbot-fab.component</li></ul>",
|
|
9062
9169
|
"codeSamples": []
|
|
9063
9170
|
}
|
|
9064
9171
|
],
|
|
@@ -9655,6 +9762,97 @@ const frameworkDocsContent = {
|
|
|
9655
9762
|
}
|
|
9656
9763
|
]
|
|
9657
9764
|
},
|
|
9765
|
+
{
|
|
9766
|
+
"slug": "custom-exception-handling",
|
|
9767
|
+
"lang": "en-US",
|
|
9768
|
+
"title": "Custom Exception Handling",
|
|
9769
|
+
"description": "Custom Exception Handling - documentazione operativa e tecnica",
|
|
9770
|
+
"audience": [
|
|
9771
|
+
"developer",
|
|
9772
|
+
"integration"
|
|
9773
|
+
],
|
|
9774
|
+
"status": "stable",
|
|
9775
|
+
"tags": [
|
|
9776
|
+
"advanced"
|
|
9777
|
+
],
|
|
9778
|
+
"keywords": [
|
|
9779
|
+
"Custom Exception Handling"
|
|
9780
|
+
],
|
|
9781
|
+
"toc": [
|
|
9782
|
+
{
|
|
9783
|
+
"id": "sec_1",
|
|
9784
|
+
"title": "Current architecture (summary)"
|
|
9785
|
+
},
|
|
9786
|
+
{
|
|
9787
|
+
"id": "sec_2",
|
|
9788
|
+
"title": "Extension points"
|
|
9789
|
+
},
|
|
9790
|
+
{
|
|
9791
|
+
"id": "sec_3",
|
|
9792
|
+
"title": "Server-side exceptions from consumer code"
|
|
9793
|
+
},
|
|
9794
|
+
{
|
|
9795
|
+
"id": "sec_4",
|
|
9796
|
+
"title": "Complete example in the WuicTest project"
|
|
9797
|
+
},
|
|
9798
|
+
{
|
|
9799
|
+
"id": "sec_5",
|
|
9800
|
+
"title": "Best practice"
|
|
9801
|
+
}
|
|
9802
|
+
],
|
|
9803
|
+
"sections": [
|
|
9804
|
+
{
|
|
9805
|
+
"id": "overview",
|
|
9806
|
+
"title": "Overview",
|
|
9807
|
+
"html": "<h1>Custom Exception Handling (consumer)</h1><p>The WUIC framework ships with typed, localized exception handling out of the box. The consumer can extend it to add telemetry, suppress known noise, or emit application-level errors — without rewriting the flow.</p><h2>Current architecture (summary)</h2><p>Server side (<code>KonvergenceCore</code>):</p><ul><li><code>JsonExceptionFilter</code> catches every <code>MetaService.*</code> (and AsmxProxy in general) exception and produces a JSON envelope <code>{ ok:false, errorCode, args, traceId, fallbackMessage }</code>.</li><li><code>MetaExceptionTranslator</code> maps known exceptions (e.g. <code>JsonReaderException</code> → <code>errors.metadata.props_bag.malformed</code>, <code>OperationDisabledException</code> → <code>errors.auth.operation_disabled</code>, <code>SqlException</code> → <code>errors.db.sql_exception</code> with full passthrough).</li><li>The generic fallback is <code>errors.server.unhandled</code> with a <code>traceId</code> for log correlation.</li></ul><p>Client side (<code>wuic-framework-lib</code>):</p><ul><li><code>GlobalHandler</code> (implements Angular's <code>ErrorHandler</code>) is the central dispatcher. Branches in order: SQL passthrough → typed client exceptions → typed server envelope → NG04002 routing → template runtime errors → legacy → fallback.</li><li><code>WtoolboxService.runUserCallback</code> / <code>runUserCallbackSync</code> / <code>wrapArchetypeLifecycleSync</code> are helpers to wrap user-supplied JS coming from metadata (callbacks, archetype lifecycle) with automatic typed envelopes.</li><li>Translations are loaded from <code>_wuic_translations</code> via <code>TranslationManagerService</code> (localStorage cache) and support <code>{argName}</code> placeholders interpolated by <code>GlobalHandler</code>.</li><li>The <code>BehaviorSubject GlobalHandler.messageNotification</code> emits each typed and localized exception: the consumer subscribes here to render the dialog (see the <code>app.component.ts</code> example).</li></ul><p>Typical wiring in the consumer (<code>app.config.ts</code>):</p><p>Snippet 1:</p><h2>Extension points</h2><h3>Pattern 1 — Subscribe (cross-cutting telemetry, RECOMMENDED)</h3><p>Add a second subscriber to <code>GlobalHandler.messageNotification</code> next to the dialog one. Lets you forward each (already-typed, already-localized) exception to a custom analytics/logging system.</p><p>Snippet 2:</p><p>Pros:</p><ul><li>Doesn't alter the framework flow.</li><li>Add/remove without DI wiring changes.</li><li>Receives the exception AFTER typing (errorCode + args interpolated).</li></ul><h3>Pattern 2 — Subclass <code>GlobalHandler</code> (override <code>handleError</code>)</h3><p>When you need to act BEFORE the framework decides what to do: filter known non-actionable errors, enrich <code>args</code> with app context (build version, user role), convert a generic error into a typed one.</p><p>Snippet 3:</p><p>Wiring:</p><p>Snippet 4:</p><p>Pros:</p><ul><li>Full control over the entry point.</li><li>Keeps all framework logic by calling <code>super.handleError(e)</code>.</li></ul><p>Caveat:</p><ul><li>If you DO NOT call <code>super.handleError</code>, you lose typed envelopes — only use Pattern 3 if truly necessary.</li></ul><h3>Pattern 3 — Full replace (NOT RECOMMENDED)</h3><p>Implementing <code>ErrorHandler</code> from scratch without extending <code>GlobalHandler</code> disables ALL built-in features: translations, typed envelopes, SQL passthrough, dedicated dialogs, NG04002 routing, dynamic-template error tagging. Only use it for very specific requirements where you're prepared to re-implement the end-to-end flow.</p><h3>Pattern 4 — Throw typed exceptions from consumer code</h3><p>The consumer can EMIT its own typed exceptions that receive the same treatment (translation + dialog) as framework exceptions. Import <code>WuicClientException</code> and throw with your own application <code>errorCode</code>:</p><p>Snippet 5:</p><p>Add the translations for <code>errors.myapp.feature_disabled</code> to your <code>_wuic_translations</code> seed (at least it-IT + en-US, plus other supported locales). From that point on any throw produces a localized dialog with no further wiring:</p><p>Snippet 6:</p><p>The <code>{feature}</code> placeholder is automatically interpolated from the <code>args</code> passed to the <code>WuicClientException</code>.</p><h2>Server-side exceptions from consumer code</h2><p>On the server (consumer controller/service) the pattern is analogous: throw a <code>WuicException</code> from the framework namespace and the <code>JsonExceptionFilter</code> produces the typed JSON envelope that the client localizes.</p><p>Snippet 7:</p><p><code>HttpStatus</code> controls the response HTTP code; <code>FallbackMessage</code> is shown when the translation is missing.</p><h2>Complete example in the WuicTest project</h2><p>A working example covering all 4 patterns (with comments, inline snippets, and example wiring) is available at:</p><ul><li><code>WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts</code></li></ul><p>The file is part of the test consumer project source and contains 4 sections:</p><p>1. <code>installCustomTelemetry()</code> — Pattern 1 (subscribe), ready to call from <code>AppComponent.ngOnInit</code>.</p><p>2. <code>MyCustomErrorHandler</code> — Pattern 2 (subclass), ready to wire in <code>app.config.ts</code>.</p><p>3. Pattern 3 — commented example (NOT recommended).</p><p>4. Pattern 4 — <code>WuicClientException</code> throw snippet from app code.</p><h2>Best practice</h2><ul><li><strong>Prefer Pattern 1</strong> (subscribe) for telemetry/logging — doesn't alter the flow and is easy to remove.</li><li><strong>Use Pattern 2</strong> (subclass) only when you need to intervene before the default (noise filtering, args enrichment).</li><li><strong>Never Pattern 3</strong> unless you have specific enterprise requirements — you lose all built-in functionality.</li><li><strong>Always seed translations</strong> for your application <code>errorCode</code>s (at least it-IT + en-US) before releasing to production, otherwise the dialog shows the raw key.</li><li><strong>Use server-side `traceId`</strong> in the translation template (e.g. <code>"Reference: {traceId}"</code>) to ease cross-team support diagnostics.</li></ul>",
|
|
9808
|
+
"codeSamples": [
|
|
9809
|
+
{
|
|
9810
|
+
"id": "code_1",
|
|
9811
|
+
"title": "Snippet 1",
|
|
9812
|
+
"language": "ts",
|
|
9813
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: GlobalHandler },\n ...\n]"
|
|
9814
|
+
},
|
|
9815
|
+
{
|
|
9816
|
+
"id": "code_2",
|
|
9817
|
+
"title": "Snippet 2",
|
|
9818
|
+
"language": "ts",
|
|
9819
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nGlobalHandler.messageNotification.subscribe((data) => {\n const exc = data?.exception;\n if (!exc?.errorCode) return;\n\n // Filter known noise.\n if (String(exc.errorCode).startsWith('errors.client.archetype.')) return;\n\n // Forward to analytics endpoint (Sentry, App Insights, etc.).\n fetch('/analytics/client-errors', {\n method: 'POST',\n body: JSON.stringify({\n errorCode: exc.errorCode,\n args: exc.args,\n traceId: exc.traceId,\n url: window.location.href,\n ts: new Date().toISOString(),\n }),\n credentials: 'include',\n });\n});"
|
|
9820
|
+
},
|
|
9821
|
+
{
|
|
9822
|
+
"id": "code_3",
|
|
9823
|
+
"title": "Snippet 3",
|
|
9824
|
+
"language": "ts",
|
|
9825
|
+
"code": "import { ErrorHandler, Injectable } from '@angular/core';\nimport { GlobalHandler } from './wuic-bridges/core';\n\n@Injectable()\nexport class MyCustomErrorHandler extends GlobalHandler {\n override handleError(e: any): void {\n // 1. Suppress non-actionable noise.\n const msg = (typeof e?.message === 'string' ? e.message : '') as string;\n if (msg.includes('ResizeObserver loop limit exceeded')) {\n console.debug('[MyCustomErrorHandler] suppressed:', msg);\n return;\n }\n\n // 2. Enrich args with app context.\n if (typeof e?.error?.errorCode === 'string' && e?.error?.args) {\n e.error.args = {\n ...e.error.args,\n appVersion: (window as any).__myAppVersion || 'dev',\n userRole: (window as any).__myAppUserRole || 'unknown',\n };\n }\n\n // 3. Delegate to the default — all typed envelopes, translations,\n // SQL passthrough dialog, NG04002 routing keep working.\n super.handleError(e);\n }\n}"
|
|
9826
|
+
},
|
|
9827
|
+
{
|
|
9828
|
+
"id": "code_4",
|
|
9829
|
+
"title": "Snippet 4",
|
|
9830
|
+
"language": "ts",
|
|
9831
|
+
"code": "// app.config.ts\nimport { MyCustomErrorHandler } from './exception-handling/custom-error-handler.example';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: MyCustomErrorHandler },\n ...\n]"
|
|
9832
|
+
},
|
|
9833
|
+
{
|
|
9834
|
+
"id": "code_5",
|
|
9835
|
+
"title": "Snippet 5",
|
|
9836
|
+
"language": "ts",
|
|
9837
|
+
"code": "import { WuicClientException } from 'wuic-framework-lib-src/exception/WuicClientException';\n\nif (!myConfig.exportEnabled) {\n throw new WuicClientException(\n 'errors.myapp.feature_disabled',\n { feature: 'export-pdf' },\n { surface: 'service', targetName: 'MyAppService.exportPdf' }\n );\n}"
|
|
9838
|
+
},
|
|
9839
|
+
{
|
|
9840
|
+
"id": "code_6",
|
|
9841
|
+
"title": "Snippet 6",
|
|
9842
|
+
"language": "sql",
|
|
9843
|
+
"code": "-- Example seed (idempotent, see scripts/upsert-wuic-translations.ps1).\nINSERT INTO _wuic_translations (translation_key, locale, translation_text)\nVALUES\n ('errors.myapp.feature_disabled', 'it-IT', \"Funzionalita' '{feature}' disabilitata in questa versione.\"),\n ('errors.myapp.feature_disabled', 'en-US', \"Feature ''{feature}'' is disabled in this build.\");"
|
|
9844
|
+
},
|
|
9845
|
+
{
|
|
9846
|
+
"id": "code_7",
|
|
9847
|
+
"title": "Snippet 7",
|
|
9848
|
+
"language": "csharp",
|
|
9849
|
+
"code": "using WEB_UI_CRAFTER.Helpers.Exceptions;\n\nif (!_myService.IsLicensed(\"export-pdf\"))\n{\n throw new WuicException(\n \"errors.myapp.license.missing\",\n new Dictionary<string, object>\n {\n [\"feature\"] = \"export-pdf\",\n [\"tier\"] = currentTier,\n })\n {\n HttpStatus = 403,\n FallbackMessage = $\"License missing for feature 'export-pdf' (tier '{currentTier}').\",\n };\n}"
|
|
9850
|
+
}
|
|
9851
|
+
]
|
|
9852
|
+
}
|
|
9853
|
+
],
|
|
9854
|
+
"images": []
|
|
9855
|
+
},
|
|
9658
9856
|
{
|
|
9659
9857
|
"slug": "component-injection",
|
|
9660
9858
|
"lang": "en-US",
|
|
@@ -13949,7 +14147,7 @@ const frameworkDocsContent = {
|
|
|
13949
14147
|
{
|
|
13950
14148
|
"id": "overview",
|
|
13951
14149
|
"title": "Overview",
|
|
13952
|
-
"html": "<h1>Component Catalog</h1><p>Total component folders detected:
|
|
14150
|
+
"html": "<h1>Component Catalog</h1><p>Total component folders detected: 48.</p><h2>Available components</h2><ul><li>app-settings-editor</li><li>archetype-configurator</li><li>bounded-repeater</li><li>carousel-list</li><li>chart-list</li><li>code-editor</li><li>css-sheet-editor</li><li>dashboard</li><li>data-action-button</li><li>data-repeater</li><li>data-source</li><li>designer</li><li>dynamic-dashboard-template</li><li>dynamic-field-template</li><li>dynamic-form-template</li><li>dynamic-generic-template</li><li>dynamic-repeater-template</li><li>dynamic-template</li><li>field</li><li>filter-bar</li><li>first-run-wizard</li><li>framework-docs</li><li>image-wrapper</li><li>import-export-button</li><li>kanban-list</li><li>list-grid</li><li>map-list</li><li>meta-menu</li><li>metadata-editor</li><li>notification-bell</li><li>pager</li><li>parametric-dialog</li><li>pivot-builder</li><li>prompt-dialog-fallback-host</li><li>rag-chatbot</li><li>rag-chatbot-fab</li><li>report-designer</li><li>report-viewer</li><li>scheduler-list</li><li>split</li><li>split-area</li><li>spreadsheet-list-sf</li><li>tab-panel-wrapper</li><li>tab-view-wrapper</li><li>tree-list</li><li>upload-dialog</li><li>workflow-designer</li><li>workflow-runner</li></ul><h2>Exports from public-api</h2><ul><li>data-source/data-source.component</li><li>list-grid/list-grid.component</li><li>import-export-button/import-export-button.component</li><li>pager/pager.component</li><li>filter-bar/filter-bar.component</li><li>map-list/map-list.component</li><li>carousel-list/carousel-list.component</li><li>tree-list/tree-list.component</li><li>parametric-dialog/parametric-dialog.component</li><li>upload-dialog/upload-dialog.component</li><li>app-settings-editor/app-settings-editor.component</li><li>data-action-button/data-action-button.component</li><li>meta-menu/meta-menu.component</li><li>field/text-editor/text-editor.component</li><li>field/text-area-editor/text-area-editor.component</li><li>field/number-editor/number-editor.component</li><li>field/lookup-editor/lookup-editor.component</li><li>field/dictionary-editor/dictionary-editor.component</li><li>field/boolean-editor/boolean-editor.component</li><li>field/date-editor/date-editor.component</li><li>field/html-editor/html-editor.component</li><li>field/upload-editor/upload-editor.component</li><li>field/button-editor/button-editor.component</li><li>field/field-editor/field-editor.component</li><li>field/code-area-editor/code-area-editor.component</li><li>dynamic-template/dynamic-template.component</li><li>image-wrapper/image-wrapper.component</li><li>field/color-editor/color-editor.component</li><li>field/property-array-editor/property-array-editor.component</li><li>field/property-object-editor/property-object-editor.component</li><li>field/tree-view-selector/tree-view-selector.component</li><li>workflow-designer/workflow-designer.component</li><li>workflow-runner/workflow-runner.component</li><li>notification-bell/notification-bell.component</li><li>bounded-repeater/bounded-repeater.component</li><li>framework-docs/framework-docs.component</li><li>designer/designer.route.component</li><li>workflow-designer/workflow-designer.route.component</li><li>kanban-list/kanban-list.component</li><li>data-repeater/data-repeater.component</li><li>bounded-repeater/bounded-repeater-pending-changes.guard</li><li>rag-chatbot/rag-chatbot.component</li><li>rag-chatbot-fab/rag-chatbot-fab.component</li></ul>",
|
|
13953
14151
|
"codeSamples": []
|
|
13954
14152
|
}
|
|
13955
14153
|
],
|
|
@@ -14546,6 +14744,97 @@ const frameworkDocsContent = {
|
|
|
14546
14744
|
}
|
|
14547
14745
|
]
|
|
14548
14746
|
},
|
|
14747
|
+
{
|
|
14748
|
+
"slug": "custom-exception-handling",
|
|
14749
|
+
"lang": "fr-FR",
|
|
14750
|
+
"title": "Gestion personnalisée des exceptions",
|
|
14751
|
+
"description": "Gestion personnalisée des exceptions - documentazione operativa e tecnica",
|
|
14752
|
+
"audience": [
|
|
14753
|
+
"developer",
|
|
14754
|
+
"integration"
|
|
14755
|
+
],
|
|
14756
|
+
"status": "stable",
|
|
14757
|
+
"tags": [
|
|
14758
|
+
"advanced"
|
|
14759
|
+
],
|
|
14760
|
+
"keywords": [
|
|
14761
|
+
"Gestion personnalisée des exceptions"
|
|
14762
|
+
],
|
|
14763
|
+
"toc": [
|
|
14764
|
+
{
|
|
14765
|
+
"id": "sec_1",
|
|
14766
|
+
"title": "Architettura attuale (riassunto)"
|
|
14767
|
+
},
|
|
14768
|
+
{
|
|
14769
|
+
"id": "sec_2",
|
|
14770
|
+
"title": "Punti di estensione"
|
|
14771
|
+
},
|
|
14772
|
+
{
|
|
14773
|
+
"id": "sec_3",
|
|
14774
|
+
"title": "Eccezioni server-side dal codice consumer"
|
|
14775
|
+
},
|
|
14776
|
+
{
|
|
14777
|
+
"id": "sec_4",
|
|
14778
|
+
"title": "Esempio completo nel progetto WuicTest"
|
|
14779
|
+
},
|
|
14780
|
+
{
|
|
14781
|
+
"id": "sec_5",
|
|
14782
|
+
"title": "Best practice"
|
|
14783
|
+
}
|
|
14784
|
+
],
|
|
14785
|
+
"sections": [
|
|
14786
|
+
{
|
|
14787
|
+
"id": "overview",
|
|
14788
|
+
"title": "Overview",
|
|
14789
|
+
"html": "<h1>Gestione eccezioni custom (consumer)</h1><p>Il framework WUIC fornisce una gestione eccezioni tipizzata e localizzata pronta all'uso. Il consumer puo' estenderla per aggiungere telemetria, filtrare rumore noto o emettere errori applicativi propri — senza riscrivere il flusso.</p><h2>Architettura attuale (riassunto)</h2><p>Lato server (<code>KonvergenceCore</code>):</p><ul><li><code>JsonExceptionFilter</code> cattura ogni eccezione di <code>MetaService.*</code> (e dell'AsmxProxy in generale) e produce un envelope JSON <code>{ ok:false, errorCode, args, traceId, fallbackMessage }</code>.</li><li><code>MetaExceptionTranslator</code> mappa eccezioni note (es. <code>JsonReaderException</code> → <code>errors.metadata.props_bag.malformed</code>, <code>OperationDisabledException</code> → <code>errors.auth.operation_disabled</code>, <code>SqlException</code> → <code>errors.db.sql_exception</code> con passthrough completo).</li><li>Il fallback generico e' <code>errors.server.unhandled</code> con <code>traceId</code> per correlazione log.</li></ul><p>Lato client (<code>wuic-framework-lib</code>):</p><ul><li><code>GlobalHandler</code> (implementa <code>ErrorHandler</code> di Angular) e' il dispatcher centrale. Branch ordinati: SQL passthrough → typed exceptions client → typed envelope server → NG04002 routing → template runtime errors → legacy → fallback.</li><li><code>WtoolboxService.runUserCallback</code> / <code>runUserCallbackSync</code> / <code>wrapArchetypeLifecycleSync</code> sono helper per wrappare codice JS proveniente da metadata utente (callback, archetype lifecycle) con typed envelope automatico.</li><li>Le traduzioni vengono caricate dalla tabella <code>_wuic_translations</code> via <code>TranslationManagerService</code> (cache localStorage) e supportano placeholder <code>{argName}</code> interpolati direttamente dal <code>GlobalHandler</code>.</li><li><code>BehaviorSubject GlobalHandler.messageNotification</code> emette ogni eccezione gia' tipizzata e localizzata: il consumer si aggancia qui per renderizzare il dialog (vedi <code>app.component.ts</code> di esempio).</li></ul><p>Wiring tipico nel consumer (<code>app.config.ts</code>):</p><p>Snippet 1:</p><h2>Punti di estensione</h2><h3>Pattern 1 — Subscribe (cross-cutting telemetry, CONSIGLIATO)</h3><p>Aggancia un secondo subscriber a <code>GlobalHandler.messageNotification</code> accanto a quello del dialog. Permette di inviare ogni eccezione (gia' tipizzata, gia' localizzata) a un sistema di analytics o logging custom.</p><p>Snippet 2:</p><p>Vantaggi:</p><ul><li>Non altera il flusso del framework.</li><li>Si aggiunge/rimuove senza tocchi al wiring DI.</li><li>Riceve l'eccezione DOPO la tipizzazione (errorCode + args interpolati).</li></ul><h3>Pattern 2 — Subclass <code>GlobalHandler</code> (override <code>handleError</code>)</h3><p>Quando serve intervenire PRIMA che il framework decida cosa fare con l'errore: filtrare errori noti non azionabili, arricchire <code>args</code> con context applicativo (versione build, ruolo utente), convertire un errore generico in tipizzato.</p><p>Snippet 3:</p><p>Wiring:</p><p>Snippet 4:</p><p>Vantaggi:</p><ul><li>Pieno controllo sul punto di entry.</li><li>Mantiene tutta la logica del framework chiamando <code>super.handleError(e)</code>.</li></ul><p>Attenzione:</p><ul><li>Se NON chiami <code>super.handleError</code>, perdi le typed envelopes — usa Pattern 3 solo se davvero necessario.</li></ul><h3>Pattern 3 — Replace completo (NON CONSIGLIATO)</h3><p>Implementare <code>ErrorHandler</code> da zero senza estendere <code>GlobalHandler</code> disabilita TUTTE le funzionalita' built-in: traduzioni, typed envelopes, SQL passthrough, dialog dedicati, NG04002 routing, error-tagging dei dynamic template. Usare solo se hai requisiti molto specifici e sei pronto a re-implementare il flusso end-to-end.</p><h3>Pattern 4 — Throw eccezioni tipizzate dal codice consumer</h3><p>Il consumer puo' EMETTERE eccezioni tipizzate proprie che riceveranno lo stesso trattamento (traduzione + dialog) delle eccezioni del framework. Importa <code>WuicClientException</code> e lancia con il tuo <code>errorCode</code> applicativo:</p><p>Snippet 5:</p><p>Aggiungi le traduzioni <code>errors.myapp.feature_disabled</code> nel tuo seed di <code>_wuic_translations</code> (it-IT + en-US e gli altri locale supportati). Da quel momento qualunque throw produrra' un dialog localizzato senza ulteriore wiring:</p><p>Snippet 6:</p><p>Il placeholder <code>{feature}</code> viene interpolato automaticamente dagli <code>args</code> passati alla <code>WuicClientException</code>.</p><h2>Eccezioni server-side dal codice consumer</h2><p>Lato server (controller/service consumer) il pattern e' analogo: lancia <code>WuicException</code> dal namespace del framework e il <code>JsonExceptionFilter</code> produce l'envelope JSON tipizzato che il client traduce.</p><p>Snippet 7:</p><p>L'<code>HttpStatus</code> controlla il codice HTTP della risposta; il <code>fallbackMessage</code> viene mostrato se la traduzione manca.</p><h2>Esempio completo nel progetto WuicTest</h2><p>Un esempio funzionante con tutti e 4 i pattern (con commenti, snippet inline, e wiring di esempio) e' presente in:</p><ul><li><a href=\"https://github.com/wuic/wuic-framework/blob/main/WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts\" target=\"_blank\" rel=\"noopener noreferrer\">`WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts`</a></li></ul><p>Il file e' incluso nel sorgente del progetto consumer di test e contiene 4 sezioni:</p><p>1. <code>installCustomTelemetry()</code> — Pattern 1 (subscribe), pronto da chiamare in <code>AppComponent.ngOnInit</code>.</p><p>2. <code>MyCustomErrorHandler</code> — Pattern 2 (subclass), pronto da wirare in <code>app.config.ts</code>.</p><p>3. Pattern 3 — esempio commentato (NON consigliato).</p><p>4. Pattern 4 — snippet di throw <code>WuicClientException</code> dal codice applicativo.</p><h2>Best practice</h2><ul><li><strong>Privilegia Pattern 1</strong> (subscribe) per telemetria/logging — non altera il flusso e si rimuove facilmente.</li><li><strong>Usa Pattern 2</strong> (subclass) solo se devi intervenire prima del default (filtro rumore, arricchimento args).</li><li><strong>Mai Pattern 3</strong> salvo requisiti enterprise specifici — perdi tutto il built-in.</li><li><strong>Sempre seed le traduzioni</strong> dei tuoi <code>errorCode</code> applicativi (it-IT + en-US minimo) prima di rilasciare in produzione, altrimenti il dialog mostra la chiave grezza.</li><li><strong>Usa `traceId` server-side</strong> nel template di traduzione (es. <code>"Codice: {traceId}"</code>) per facilitare la diagnostica condivisa fra utente e team supporto.</li></ul>",
|
|
14790
|
+
"codeSamples": [
|
|
14791
|
+
{
|
|
14792
|
+
"id": "code_1",
|
|
14793
|
+
"title": "Snippet 1",
|
|
14794
|
+
"language": "ts",
|
|
14795
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: GlobalHandler },\n ...\n]"
|
|
14796
|
+
},
|
|
14797
|
+
{
|
|
14798
|
+
"id": "code_2",
|
|
14799
|
+
"title": "Snippet 2",
|
|
14800
|
+
"language": "ts",
|
|
14801
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nGlobalHandler.messageNotification.subscribe((data) => {\n const exc = data?.exception;\n if (!exc?.errorCode) return;\n\n // Filtra rumore noto.\n if (String(exc.errorCode).startsWith('errors.client.archetype.')) return;\n\n // Invio a endpoint analytics (Sentry, App Insights, ecc.).\n fetch('/analytics/client-errors', {\n method: 'POST',\n body: JSON.stringify({\n errorCode: exc.errorCode,\n args: exc.args,\n traceId: exc.traceId,\n url: window.location.href,\n ts: new Date().toISOString(),\n }),\n credentials: 'include',\n });\n});"
|
|
14802
|
+
},
|
|
14803
|
+
{
|
|
14804
|
+
"id": "code_3",
|
|
14805
|
+
"title": "Snippet 3",
|
|
14806
|
+
"language": "ts",
|
|
14807
|
+
"code": "import { ErrorHandler, Injectable } from '@angular/core';\nimport { GlobalHandler } from './wuic-bridges/core';\n\n@Injectable()\nexport class MyCustomErrorHandler extends GlobalHandler {\n override handleError(e: any): void {\n // 1. Suppress noise non azionabile.\n const msg = (typeof e?.message === 'string' ? e.message : '') as string;\n if (msg.includes('ResizeObserver loop limit exceeded')) {\n console.debug('[MyCustomErrorHandler] suppressed:', msg);\n return;\n }\n\n // 2. Arricchisci args con context applicativo.\n if (typeof e?.error?.errorCode === 'string' && e?.error?.args) {\n e.error.args = {\n ...e.error.args,\n appVersion: (window as any).__myAppVersion || 'dev',\n userRole: (window as any).__myAppUserRole || 'unknown',\n };\n }\n\n // 3. Delega al default — tutte le typed envelopes, traduzioni,\n // dialog SQL passthrough, NG04002 routing continuano a funzionare.\n super.handleError(e);\n }\n}"
|
|
14808
|
+
},
|
|
14809
|
+
{
|
|
14810
|
+
"id": "code_4",
|
|
14811
|
+
"title": "Snippet 4",
|
|
14812
|
+
"language": "ts",
|
|
14813
|
+
"code": "// app.config.ts\nimport { MyCustomErrorHandler } from './exception-handling/custom-error-handler.example';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: MyCustomErrorHandler },\n ...\n]"
|
|
14814
|
+
},
|
|
14815
|
+
{
|
|
14816
|
+
"id": "code_5",
|
|
14817
|
+
"title": "Snippet 5",
|
|
14818
|
+
"language": "ts",
|
|
14819
|
+
"code": "import { WuicClientException } from 'wuic-framework-lib-src/exception/WuicClientException';\n\nif (!myConfig.exportEnabled) {\n throw new WuicClientException(\n 'errors.myapp.feature_disabled',\n { feature: 'export-pdf' },\n { surface: 'service', targetName: 'MyAppService.exportPdf' }\n );\n}"
|
|
14820
|
+
},
|
|
14821
|
+
{
|
|
14822
|
+
"id": "code_6",
|
|
14823
|
+
"title": "Snippet 6",
|
|
14824
|
+
"language": "sql",
|
|
14825
|
+
"code": "-- Esempio seed (idempotente, vedi scripts/upsert-wuic-translations.ps1).\nINSERT INTO _wuic_translations (translation_key, locale, translation_text)\nVALUES\n ('errors.myapp.feature_disabled', 'it-IT', \"Funzionalita' '{feature}' disabilitata in questa versione.\"),\n ('errors.myapp.feature_disabled', 'en-US', \"Feature ''{feature}'' is disabled in this build.\");"
|
|
14826
|
+
},
|
|
14827
|
+
{
|
|
14828
|
+
"id": "code_7",
|
|
14829
|
+
"title": "Snippet 7",
|
|
14830
|
+
"language": "csharp",
|
|
14831
|
+
"code": "using WEB_UI_CRAFTER.Helpers.Exceptions;\n\nif (!_myService.IsLicensed(\"export-pdf\"))\n{\n throw new WuicException(\n \"errors.myapp.license.missing\",\n new Dictionary<string, object>\n {\n [\"feature\"] = \"export-pdf\",\n [\"tier\"] = currentTier,\n })\n {\n HttpStatus = 403,\n FallbackMessage = $\"License missing for feature 'export-pdf' (tier '{currentTier}').\",\n };\n}"
|
|
14832
|
+
}
|
|
14833
|
+
]
|
|
14834
|
+
}
|
|
14835
|
+
],
|
|
14836
|
+
"images": []
|
|
14837
|
+
},
|
|
14549
14838
|
{
|
|
14550
14839
|
"slug": "component-injection",
|
|
14551
14840
|
"lang": "fr-FR",
|
|
@@ -18851,7 +19140,7 @@ const frameworkDocsContent = {
|
|
|
18851
19140
|
{
|
|
18852
19141
|
"id": "overview",
|
|
18853
19142
|
"title": "Overview",
|
|
18854
|
-
"html": "<h1>Component Catalog</h1><p>Total component folders detected:
|
|
19143
|
+
"html": "<h1>Component Catalog</h1><p>Total component folders detected: 48.</p><h2>Available components</h2><ul><li>app-settings-editor</li><li>archetype-configurator</li><li>bounded-repeater</li><li>carousel-list</li><li>chart-list</li><li>code-editor</li><li>css-sheet-editor</li><li>dashboard</li><li>data-action-button</li><li>data-repeater</li><li>data-source</li><li>designer</li><li>dynamic-dashboard-template</li><li>dynamic-field-template</li><li>dynamic-form-template</li><li>dynamic-generic-template</li><li>dynamic-repeater-template</li><li>dynamic-template</li><li>field</li><li>filter-bar</li><li>first-run-wizard</li><li>framework-docs</li><li>image-wrapper</li><li>import-export-button</li><li>kanban-list</li><li>list-grid</li><li>map-list</li><li>meta-menu</li><li>metadata-editor</li><li>notification-bell</li><li>pager</li><li>parametric-dialog</li><li>pivot-builder</li><li>prompt-dialog-fallback-host</li><li>rag-chatbot</li><li>rag-chatbot-fab</li><li>report-designer</li><li>report-viewer</li><li>scheduler-list</li><li>split</li><li>split-area</li><li>spreadsheet-list-sf</li><li>tab-panel-wrapper</li><li>tab-view-wrapper</li><li>tree-list</li><li>upload-dialog</li><li>workflow-designer</li><li>workflow-runner</li></ul><h2>Exports from public-api</h2><ul><li>data-source/data-source.component</li><li>list-grid/list-grid.component</li><li>import-export-button/import-export-button.component</li><li>pager/pager.component</li><li>filter-bar/filter-bar.component</li><li>map-list/map-list.component</li><li>carousel-list/carousel-list.component</li><li>tree-list/tree-list.component</li><li>parametric-dialog/parametric-dialog.component</li><li>upload-dialog/upload-dialog.component</li><li>app-settings-editor/app-settings-editor.component</li><li>data-action-button/data-action-button.component</li><li>meta-menu/meta-menu.component</li><li>field/text-editor/text-editor.component</li><li>field/text-area-editor/text-area-editor.component</li><li>field/number-editor/number-editor.component</li><li>field/lookup-editor/lookup-editor.component</li><li>field/dictionary-editor/dictionary-editor.component</li><li>field/boolean-editor/boolean-editor.component</li><li>field/date-editor/date-editor.component</li><li>field/html-editor/html-editor.component</li><li>field/upload-editor/upload-editor.component</li><li>field/button-editor/button-editor.component</li><li>field/field-editor/field-editor.component</li><li>field/code-area-editor/code-area-editor.component</li><li>dynamic-template/dynamic-template.component</li><li>image-wrapper/image-wrapper.component</li><li>field/color-editor/color-editor.component</li><li>field/property-array-editor/property-array-editor.component</li><li>field/property-object-editor/property-object-editor.component</li><li>field/tree-view-selector/tree-view-selector.component</li><li>workflow-designer/workflow-designer.component</li><li>workflow-runner/workflow-runner.component</li><li>notification-bell/notification-bell.component</li><li>bounded-repeater/bounded-repeater.component</li><li>framework-docs/framework-docs.component</li><li>designer/designer.route.component</li><li>workflow-designer/workflow-designer.route.component</li><li>kanban-list/kanban-list.component</li><li>data-repeater/data-repeater.component</li><li>bounded-repeater/bounded-repeater-pending-changes.guard</li><li>rag-chatbot/rag-chatbot.component</li><li>rag-chatbot-fab/rag-chatbot-fab.component</li></ul>",
|
|
18855
19144
|
"codeSamples": []
|
|
18856
19145
|
}
|
|
18857
19146
|
],
|
|
@@ -19448,6 +19737,97 @@ const frameworkDocsContent = {
|
|
|
19448
19737
|
}
|
|
19449
19738
|
]
|
|
19450
19739
|
},
|
|
19740
|
+
{
|
|
19741
|
+
"slug": "custom-exception-handling",
|
|
19742
|
+
"lang": "es-ES",
|
|
19743
|
+
"title": "Gestión personalizada de excepciones",
|
|
19744
|
+
"description": "Gestión personalizada de excepciones - documentazione operativa e tecnica",
|
|
19745
|
+
"audience": [
|
|
19746
|
+
"developer",
|
|
19747
|
+
"integration"
|
|
19748
|
+
],
|
|
19749
|
+
"status": "stable",
|
|
19750
|
+
"tags": [
|
|
19751
|
+
"advanced"
|
|
19752
|
+
],
|
|
19753
|
+
"keywords": [
|
|
19754
|
+
"Gestión personalizada de excepciones"
|
|
19755
|
+
],
|
|
19756
|
+
"toc": [
|
|
19757
|
+
{
|
|
19758
|
+
"id": "sec_1",
|
|
19759
|
+
"title": "Architettura attuale (riassunto)"
|
|
19760
|
+
},
|
|
19761
|
+
{
|
|
19762
|
+
"id": "sec_2",
|
|
19763
|
+
"title": "Punti di estensione"
|
|
19764
|
+
},
|
|
19765
|
+
{
|
|
19766
|
+
"id": "sec_3",
|
|
19767
|
+
"title": "Eccezioni server-side dal codice consumer"
|
|
19768
|
+
},
|
|
19769
|
+
{
|
|
19770
|
+
"id": "sec_4",
|
|
19771
|
+
"title": "Esempio completo nel progetto WuicTest"
|
|
19772
|
+
},
|
|
19773
|
+
{
|
|
19774
|
+
"id": "sec_5",
|
|
19775
|
+
"title": "Best practice"
|
|
19776
|
+
}
|
|
19777
|
+
],
|
|
19778
|
+
"sections": [
|
|
19779
|
+
{
|
|
19780
|
+
"id": "overview",
|
|
19781
|
+
"title": "Overview",
|
|
19782
|
+
"html": "<h1>Gestione eccezioni custom (consumer)</h1><p>Il framework WUIC fornisce una gestione eccezioni tipizzata e localizzata pronta all'uso. Il consumer puo' estenderla per aggiungere telemetria, filtrare rumore noto o emettere errori applicativi propri — senza riscrivere il flusso.</p><h2>Architettura attuale (riassunto)</h2><p>Lato server (<code>KonvergenceCore</code>):</p><ul><li><code>JsonExceptionFilter</code> cattura ogni eccezione di <code>MetaService.*</code> (e dell'AsmxProxy in generale) e produce un envelope JSON <code>{ ok:false, errorCode, args, traceId, fallbackMessage }</code>.</li><li><code>MetaExceptionTranslator</code> mappa eccezioni note (es. <code>JsonReaderException</code> → <code>errors.metadata.props_bag.malformed</code>, <code>OperationDisabledException</code> → <code>errors.auth.operation_disabled</code>, <code>SqlException</code> → <code>errors.db.sql_exception</code> con passthrough completo).</li><li>Il fallback generico e' <code>errors.server.unhandled</code> con <code>traceId</code> per correlazione log.</li></ul><p>Lato client (<code>wuic-framework-lib</code>):</p><ul><li><code>GlobalHandler</code> (implementa <code>ErrorHandler</code> di Angular) e' il dispatcher centrale. Branch ordinati: SQL passthrough → typed exceptions client → typed envelope server → NG04002 routing → template runtime errors → legacy → fallback.</li><li><code>WtoolboxService.runUserCallback</code> / <code>runUserCallbackSync</code> / <code>wrapArchetypeLifecycleSync</code> sono helper per wrappare codice JS proveniente da metadata utente (callback, archetype lifecycle) con typed envelope automatico.</li><li>Le traduzioni vengono caricate dalla tabella <code>_wuic_translations</code> via <code>TranslationManagerService</code> (cache localStorage) e supportano placeholder <code>{argName}</code> interpolati direttamente dal <code>GlobalHandler</code>.</li><li><code>BehaviorSubject GlobalHandler.messageNotification</code> emette ogni eccezione gia' tipizzata e localizzata: il consumer si aggancia qui per renderizzare il dialog (vedi <code>app.component.ts</code> di esempio).</li></ul><p>Wiring tipico nel consumer (<code>app.config.ts</code>):</p><p>Snippet 1:</p><h2>Punti di estensione</h2><h3>Pattern 1 — Subscribe (cross-cutting telemetry, CONSIGLIATO)</h3><p>Aggancia un secondo subscriber a <code>GlobalHandler.messageNotification</code> accanto a quello del dialog. Permette di inviare ogni eccezione (gia' tipizzata, gia' localizzata) a un sistema di analytics o logging custom.</p><p>Snippet 2:</p><p>Vantaggi:</p><ul><li>Non altera il flusso del framework.</li><li>Si aggiunge/rimuove senza tocchi al wiring DI.</li><li>Riceve l'eccezione DOPO la tipizzazione (errorCode + args interpolati).</li></ul><h3>Pattern 2 — Subclass <code>GlobalHandler</code> (override <code>handleError</code>)</h3><p>Quando serve intervenire PRIMA che il framework decida cosa fare con l'errore: filtrare errori noti non azionabili, arricchire <code>args</code> con context applicativo (versione build, ruolo utente), convertire un errore generico in tipizzato.</p><p>Snippet 3:</p><p>Wiring:</p><p>Snippet 4:</p><p>Vantaggi:</p><ul><li>Pieno controllo sul punto di entry.</li><li>Mantiene tutta la logica del framework chiamando <code>super.handleError(e)</code>.</li></ul><p>Attenzione:</p><ul><li>Se NON chiami <code>super.handleError</code>, perdi le typed envelopes — usa Pattern 3 solo se davvero necessario.</li></ul><h3>Pattern 3 — Replace completo (NON CONSIGLIATO)</h3><p>Implementare <code>ErrorHandler</code> da zero senza estendere <code>GlobalHandler</code> disabilita TUTTE le funzionalita' built-in: traduzioni, typed envelopes, SQL passthrough, dialog dedicati, NG04002 routing, error-tagging dei dynamic template. Usare solo se hai requisiti molto specifici e sei pronto a re-implementare il flusso end-to-end.</p><h3>Pattern 4 — Throw eccezioni tipizzate dal codice consumer</h3><p>Il consumer puo' EMETTERE eccezioni tipizzate proprie che riceveranno lo stesso trattamento (traduzione + dialog) delle eccezioni del framework. Importa <code>WuicClientException</code> e lancia con il tuo <code>errorCode</code> applicativo:</p><p>Snippet 5:</p><p>Aggiungi le traduzioni <code>errors.myapp.feature_disabled</code> nel tuo seed di <code>_wuic_translations</code> (it-IT + en-US e gli altri locale supportati). Da quel momento qualunque throw produrra' un dialog localizzato senza ulteriore wiring:</p><p>Snippet 6:</p><p>Il placeholder <code>{feature}</code> viene interpolato automaticamente dagli <code>args</code> passati alla <code>WuicClientException</code>.</p><h2>Eccezioni server-side dal codice consumer</h2><p>Lato server (controller/service consumer) il pattern e' analogo: lancia <code>WuicException</code> dal namespace del framework e il <code>JsonExceptionFilter</code> produce l'envelope JSON tipizzato che il client traduce.</p><p>Snippet 7:</p><p>L'<code>HttpStatus</code> controlla il codice HTTP della risposta; il <code>fallbackMessage</code> viene mostrato se la traduzione manca.</p><h2>Esempio completo nel progetto WuicTest</h2><p>Un esempio funzionante con tutti e 4 i pattern (con commenti, snippet inline, e wiring di esempio) e' presente in:</p><ul><li><a href=\"https://github.com/wuic/wuic-framework/blob/main/WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts\" target=\"_blank\" rel=\"noopener noreferrer\">`WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts`</a></li></ul><p>Il file e' incluso nel sorgente del progetto consumer di test e contiene 4 sezioni:</p><p>1. <code>installCustomTelemetry()</code> — Pattern 1 (subscribe), pronto da chiamare in <code>AppComponent.ngOnInit</code>.</p><p>2. <code>MyCustomErrorHandler</code> — Pattern 2 (subclass), pronto da wirare in <code>app.config.ts</code>.</p><p>3. Pattern 3 — esempio commentato (NON consigliato).</p><p>4. Pattern 4 — snippet di throw <code>WuicClientException</code> dal codice applicativo.</p><h2>Best practice</h2><ul><li><strong>Privilegia Pattern 1</strong> (subscribe) per telemetria/logging — non altera il flusso e si rimuove facilmente.</li><li><strong>Usa Pattern 2</strong> (subclass) solo se devi intervenire prima del default (filtro rumore, arricchimento args).</li><li><strong>Mai Pattern 3</strong> salvo requisiti enterprise specifici — perdi tutto il built-in.</li><li><strong>Sempre seed le traduzioni</strong> dei tuoi <code>errorCode</code> applicativi (it-IT + en-US minimo) prima di rilasciare in produzione, altrimenti il dialog mostra la chiave grezza.</li><li><strong>Usa `traceId` server-side</strong> nel template di traduzione (es. <code>"Codice: {traceId}"</code>) per facilitare la diagnostica condivisa fra utente e team supporto.</li></ul>",
|
|
19783
|
+
"codeSamples": [
|
|
19784
|
+
{
|
|
19785
|
+
"id": "code_1",
|
|
19786
|
+
"title": "Snippet 1",
|
|
19787
|
+
"language": "ts",
|
|
19788
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: GlobalHandler },\n ...\n]"
|
|
19789
|
+
},
|
|
19790
|
+
{
|
|
19791
|
+
"id": "code_2",
|
|
19792
|
+
"title": "Snippet 2",
|
|
19793
|
+
"language": "ts",
|
|
19794
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nGlobalHandler.messageNotification.subscribe((data) => {\n const exc = data?.exception;\n if (!exc?.errorCode) return;\n\n // Filtra rumore noto.\n if (String(exc.errorCode).startsWith('errors.client.archetype.')) return;\n\n // Invio a endpoint analytics (Sentry, App Insights, ecc.).\n fetch('/analytics/client-errors', {\n method: 'POST',\n body: JSON.stringify({\n errorCode: exc.errorCode,\n args: exc.args,\n traceId: exc.traceId,\n url: window.location.href,\n ts: new Date().toISOString(),\n }),\n credentials: 'include',\n });\n});"
|
|
19795
|
+
},
|
|
19796
|
+
{
|
|
19797
|
+
"id": "code_3",
|
|
19798
|
+
"title": "Snippet 3",
|
|
19799
|
+
"language": "ts",
|
|
19800
|
+
"code": "import { ErrorHandler, Injectable } from '@angular/core';\nimport { GlobalHandler } from './wuic-bridges/core';\n\n@Injectable()\nexport class MyCustomErrorHandler extends GlobalHandler {\n override handleError(e: any): void {\n // 1. Suppress noise non azionabile.\n const msg = (typeof e?.message === 'string' ? e.message : '') as string;\n if (msg.includes('ResizeObserver loop limit exceeded')) {\n console.debug('[MyCustomErrorHandler] suppressed:', msg);\n return;\n }\n\n // 2. Arricchisci args con context applicativo.\n if (typeof e?.error?.errorCode === 'string' && e?.error?.args) {\n e.error.args = {\n ...e.error.args,\n appVersion: (window as any).__myAppVersion || 'dev',\n userRole: (window as any).__myAppUserRole || 'unknown',\n };\n }\n\n // 3. Delega al default — tutte le typed envelopes, traduzioni,\n // dialog SQL passthrough, NG04002 routing continuano a funzionare.\n super.handleError(e);\n }\n}"
|
|
19801
|
+
},
|
|
19802
|
+
{
|
|
19803
|
+
"id": "code_4",
|
|
19804
|
+
"title": "Snippet 4",
|
|
19805
|
+
"language": "ts",
|
|
19806
|
+
"code": "// app.config.ts\nimport { MyCustomErrorHandler } from './exception-handling/custom-error-handler.example';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: MyCustomErrorHandler },\n ...\n]"
|
|
19807
|
+
},
|
|
19808
|
+
{
|
|
19809
|
+
"id": "code_5",
|
|
19810
|
+
"title": "Snippet 5",
|
|
19811
|
+
"language": "ts",
|
|
19812
|
+
"code": "import { WuicClientException } from 'wuic-framework-lib-src/exception/WuicClientException';\n\nif (!myConfig.exportEnabled) {\n throw new WuicClientException(\n 'errors.myapp.feature_disabled',\n { feature: 'export-pdf' },\n { surface: 'service', targetName: 'MyAppService.exportPdf' }\n );\n}"
|
|
19813
|
+
},
|
|
19814
|
+
{
|
|
19815
|
+
"id": "code_6",
|
|
19816
|
+
"title": "Snippet 6",
|
|
19817
|
+
"language": "sql",
|
|
19818
|
+
"code": "-- Esempio seed (idempotente, vedi scripts/upsert-wuic-translations.ps1).\nINSERT INTO _wuic_translations (translation_key, locale, translation_text)\nVALUES\n ('errors.myapp.feature_disabled', 'it-IT', \"Funzionalita' '{feature}' disabilitata in questa versione.\"),\n ('errors.myapp.feature_disabled', 'en-US', \"Feature ''{feature}'' is disabled in this build.\");"
|
|
19819
|
+
},
|
|
19820
|
+
{
|
|
19821
|
+
"id": "code_7",
|
|
19822
|
+
"title": "Snippet 7",
|
|
19823
|
+
"language": "csharp",
|
|
19824
|
+
"code": "using WEB_UI_CRAFTER.Helpers.Exceptions;\n\nif (!_myService.IsLicensed(\"export-pdf\"))\n{\n throw new WuicException(\n \"errors.myapp.license.missing\",\n new Dictionary<string, object>\n {\n [\"feature\"] = \"export-pdf\",\n [\"tier\"] = currentTier,\n })\n {\n HttpStatus = 403,\n FallbackMessage = $\"License missing for feature 'export-pdf' (tier '{currentTier}').\",\n };\n}"
|
|
19825
|
+
}
|
|
19826
|
+
]
|
|
19827
|
+
}
|
|
19828
|
+
],
|
|
19829
|
+
"images": []
|
|
19830
|
+
},
|
|
19451
19831
|
{
|
|
19452
19832
|
"slug": "component-injection",
|
|
19453
19833
|
"lang": "es-ES",
|
|
@@ -23753,7 +24133,7 @@ const frameworkDocsContent = {
|
|
|
23753
24133
|
{
|
|
23754
24134
|
"id": "overview",
|
|
23755
24135
|
"title": "Overview",
|
|
23756
|
-
"html": "<h1>Component Catalog</h1><p>Total component folders detected:
|
|
24136
|
+
"html": "<h1>Component Catalog</h1><p>Total component folders detected: 48.</p><h2>Available components</h2><ul><li>app-settings-editor</li><li>archetype-configurator</li><li>bounded-repeater</li><li>carousel-list</li><li>chart-list</li><li>code-editor</li><li>css-sheet-editor</li><li>dashboard</li><li>data-action-button</li><li>data-repeater</li><li>data-source</li><li>designer</li><li>dynamic-dashboard-template</li><li>dynamic-field-template</li><li>dynamic-form-template</li><li>dynamic-generic-template</li><li>dynamic-repeater-template</li><li>dynamic-template</li><li>field</li><li>filter-bar</li><li>first-run-wizard</li><li>framework-docs</li><li>image-wrapper</li><li>import-export-button</li><li>kanban-list</li><li>list-grid</li><li>map-list</li><li>meta-menu</li><li>metadata-editor</li><li>notification-bell</li><li>pager</li><li>parametric-dialog</li><li>pivot-builder</li><li>prompt-dialog-fallback-host</li><li>rag-chatbot</li><li>rag-chatbot-fab</li><li>report-designer</li><li>report-viewer</li><li>scheduler-list</li><li>split</li><li>split-area</li><li>spreadsheet-list-sf</li><li>tab-panel-wrapper</li><li>tab-view-wrapper</li><li>tree-list</li><li>upload-dialog</li><li>workflow-designer</li><li>workflow-runner</li></ul><h2>Exports from public-api</h2><ul><li>data-source/data-source.component</li><li>list-grid/list-grid.component</li><li>import-export-button/import-export-button.component</li><li>pager/pager.component</li><li>filter-bar/filter-bar.component</li><li>map-list/map-list.component</li><li>carousel-list/carousel-list.component</li><li>tree-list/tree-list.component</li><li>parametric-dialog/parametric-dialog.component</li><li>upload-dialog/upload-dialog.component</li><li>app-settings-editor/app-settings-editor.component</li><li>data-action-button/data-action-button.component</li><li>meta-menu/meta-menu.component</li><li>field/text-editor/text-editor.component</li><li>field/text-area-editor/text-area-editor.component</li><li>field/number-editor/number-editor.component</li><li>field/lookup-editor/lookup-editor.component</li><li>field/dictionary-editor/dictionary-editor.component</li><li>field/boolean-editor/boolean-editor.component</li><li>field/date-editor/date-editor.component</li><li>field/html-editor/html-editor.component</li><li>field/upload-editor/upload-editor.component</li><li>field/button-editor/button-editor.component</li><li>field/field-editor/field-editor.component</li><li>field/code-area-editor/code-area-editor.component</li><li>dynamic-template/dynamic-template.component</li><li>image-wrapper/image-wrapper.component</li><li>field/color-editor/color-editor.component</li><li>field/property-array-editor/property-array-editor.component</li><li>field/property-object-editor/property-object-editor.component</li><li>field/tree-view-selector/tree-view-selector.component</li><li>workflow-designer/workflow-designer.component</li><li>workflow-runner/workflow-runner.component</li><li>notification-bell/notification-bell.component</li><li>bounded-repeater/bounded-repeater.component</li><li>framework-docs/framework-docs.component</li><li>designer/designer.route.component</li><li>workflow-designer/workflow-designer.route.component</li><li>kanban-list/kanban-list.component</li><li>data-repeater/data-repeater.component</li><li>bounded-repeater/bounded-repeater-pending-changes.guard</li><li>rag-chatbot/rag-chatbot.component</li><li>rag-chatbot-fab/rag-chatbot-fab.component</li></ul>",
|
|
23757
24137
|
"codeSamples": []
|
|
23758
24138
|
}
|
|
23759
24139
|
],
|
|
@@ -24350,6 +24730,97 @@ const frameworkDocsContent = {
|
|
|
24350
24730
|
}
|
|
24351
24731
|
]
|
|
24352
24732
|
},
|
|
24733
|
+
{
|
|
24734
|
+
"slug": "custom-exception-handling",
|
|
24735
|
+
"lang": "de-DE",
|
|
24736
|
+
"title": "Benutzerdefinierte Ausnahmebehandlung",
|
|
24737
|
+
"description": "Benutzerdefinierte Ausnahmebehandlung - documentazione operativa e tecnica",
|
|
24738
|
+
"audience": [
|
|
24739
|
+
"developer",
|
|
24740
|
+
"integration"
|
|
24741
|
+
],
|
|
24742
|
+
"status": "stable",
|
|
24743
|
+
"tags": [
|
|
24744
|
+
"advanced"
|
|
24745
|
+
],
|
|
24746
|
+
"keywords": [
|
|
24747
|
+
"Benutzerdefinierte Ausnahmebehandlung"
|
|
24748
|
+
],
|
|
24749
|
+
"toc": [
|
|
24750
|
+
{
|
|
24751
|
+
"id": "sec_1",
|
|
24752
|
+
"title": "Architettura attuale (riassunto)"
|
|
24753
|
+
},
|
|
24754
|
+
{
|
|
24755
|
+
"id": "sec_2",
|
|
24756
|
+
"title": "Punti di estensione"
|
|
24757
|
+
},
|
|
24758
|
+
{
|
|
24759
|
+
"id": "sec_3",
|
|
24760
|
+
"title": "Eccezioni server-side dal codice consumer"
|
|
24761
|
+
},
|
|
24762
|
+
{
|
|
24763
|
+
"id": "sec_4",
|
|
24764
|
+
"title": "Esempio completo nel progetto WuicTest"
|
|
24765
|
+
},
|
|
24766
|
+
{
|
|
24767
|
+
"id": "sec_5",
|
|
24768
|
+
"title": "Best practice"
|
|
24769
|
+
}
|
|
24770
|
+
],
|
|
24771
|
+
"sections": [
|
|
24772
|
+
{
|
|
24773
|
+
"id": "overview",
|
|
24774
|
+
"title": "Overview",
|
|
24775
|
+
"html": "<h1>Gestione eccezioni custom (consumer)</h1><p>Il framework WUIC fornisce una gestione eccezioni tipizzata e localizzata pronta all'uso. Il consumer puo' estenderla per aggiungere telemetria, filtrare rumore noto o emettere errori applicativi propri — senza riscrivere il flusso.</p><h2>Architettura attuale (riassunto)</h2><p>Lato server (<code>KonvergenceCore</code>):</p><ul><li><code>JsonExceptionFilter</code> cattura ogni eccezione di <code>MetaService.*</code> (e dell'AsmxProxy in generale) e produce un envelope JSON <code>{ ok:false, errorCode, args, traceId, fallbackMessage }</code>.</li><li><code>MetaExceptionTranslator</code> mappa eccezioni note (es. <code>JsonReaderException</code> → <code>errors.metadata.props_bag.malformed</code>, <code>OperationDisabledException</code> → <code>errors.auth.operation_disabled</code>, <code>SqlException</code> → <code>errors.db.sql_exception</code> con passthrough completo).</li><li>Il fallback generico e' <code>errors.server.unhandled</code> con <code>traceId</code> per correlazione log.</li></ul><p>Lato client (<code>wuic-framework-lib</code>):</p><ul><li><code>GlobalHandler</code> (implementa <code>ErrorHandler</code> di Angular) e' il dispatcher centrale. Branch ordinati: SQL passthrough → typed exceptions client → typed envelope server → NG04002 routing → template runtime errors → legacy → fallback.</li><li><code>WtoolboxService.runUserCallback</code> / <code>runUserCallbackSync</code> / <code>wrapArchetypeLifecycleSync</code> sono helper per wrappare codice JS proveniente da metadata utente (callback, archetype lifecycle) con typed envelope automatico.</li><li>Le traduzioni vengono caricate dalla tabella <code>_wuic_translations</code> via <code>TranslationManagerService</code> (cache localStorage) e supportano placeholder <code>{argName}</code> interpolati direttamente dal <code>GlobalHandler</code>.</li><li><code>BehaviorSubject GlobalHandler.messageNotification</code> emette ogni eccezione gia' tipizzata e localizzata: il consumer si aggancia qui per renderizzare il dialog (vedi <code>app.component.ts</code> di esempio).</li></ul><p>Wiring tipico nel consumer (<code>app.config.ts</code>):</p><p>Snippet 1:</p><h2>Punti di estensione</h2><h3>Pattern 1 — Subscribe (cross-cutting telemetry, CONSIGLIATO)</h3><p>Aggancia un secondo subscriber a <code>GlobalHandler.messageNotification</code> accanto a quello del dialog. Permette di inviare ogni eccezione (gia' tipizzata, gia' localizzata) a un sistema di analytics o logging custom.</p><p>Snippet 2:</p><p>Vantaggi:</p><ul><li>Non altera il flusso del framework.</li><li>Si aggiunge/rimuove senza tocchi al wiring DI.</li><li>Riceve l'eccezione DOPO la tipizzazione (errorCode + args interpolati).</li></ul><h3>Pattern 2 — Subclass <code>GlobalHandler</code> (override <code>handleError</code>)</h3><p>Quando serve intervenire PRIMA che il framework decida cosa fare con l'errore: filtrare errori noti non azionabili, arricchire <code>args</code> con context applicativo (versione build, ruolo utente), convertire un errore generico in tipizzato.</p><p>Snippet 3:</p><p>Wiring:</p><p>Snippet 4:</p><p>Vantaggi:</p><ul><li>Pieno controllo sul punto di entry.</li><li>Mantiene tutta la logica del framework chiamando <code>super.handleError(e)</code>.</li></ul><p>Attenzione:</p><ul><li>Se NON chiami <code>super.handleError</code>, perdi le typed envelopes — usa Pattern 3 solo se davvero necessario.</li></ul><h3>Pattern 3 — Replace completo (NON CONSIGLIATO)</h3><p>Implementare <code>ErrorHandler</code> da zero senza estendere <code>GlobalHandler</code> disabilita TUTTE le funzionalita' built-in: traduzioni, typed envelopes, SQL passthrough, dialog dedicati, NG04002 routing, error-tagging dei dynamic template. Usare solo se hai requisiti molto specifici e sei pronto a re-implementare il flusso end-to-end.</p><h3>Pattern 4 — Throw eccezioni tipizzate dal codice consumer</h3><p>Il consumer puo' EMETTERE eccezioni tipizzate proprie che riceveranno lo stesso trattamento (traduzione + dialog) delle eccezioni del framework. Importa <code>WuicClientException</code> e lancia con il tuo <code>errorCode</code> applicativo:</p><p>Snippet 5:</p><p>Aggiungi le traduzioni <code>errors.myapp.feature_disabled</code> nel tuo seed di <code>_wuic_translations</code> (it-IT + en-US e gli altri locale supportati). Da quel momento qualunque throw produrra' un dialog localizzato senza ulteriore wiring:</p><p>Snippet 6:</p><p>Il placeholder <code>{feature}</code> viene interpolato automaticamente dagli <code>args</code> passati alla <code>WuicClientException</code>.</p><h2>Eccezioni server-side dal codice consumer</h2><p>Lato server (controller/service consumer) il pattern e' analogo: lancia <code>WuicException</code> dal namespace del framework e il <code>JsonExceptionFilter</code> produce l'envelope JSON tipizzato che il client traduce.</p><p>Snippet 7:</p><p>L'<code>HttpStatus</code> controlla il codice HTTP della risposta; il <code>fallbackMessage</code> viene mostrato se la traduzione manca.</p><h2>Esempio completo nel progetto WuicTest</h2><p>Un esempio funzionante con tutti e 4 i pattern (con commenti, snippet inline, e wiring di esempio) e' presente in:</p><ul><li><a href=\"https://github.com/wuic/wuic-framework/blob/main/WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts\" target=\"_blank\" rel=\"noopener noreferrer\">`WuicTest/wwwroot/src/app/exception-handling/custom-error-handler.example.ts`</a></li></ul><p>Il file e' incluso nel sorgente del progetto consumer di test e contiene 4 sezioni:</p><p>1. <code>installCustomTelemetry()</code> — Pattern 1 (subscribe), pronto da chiamare in <code>AppComponent.ngOnInit</code>.</p><p>2. <code>MyCustomErrorHandler</code> — Pattern 2 (subclass), pronto da wirare in <code>app.config.ts</code>.</p><p>3. Pattern 3 — esempio commentato (NON consigliato).</p><p>4. Pattern 4 — snippet di throw <code>WuicClientException</code> dal codice applicativo.</p><h2>Best practice</h2><ul><li><strong>Privilegia Pattern 1</strong> (subscribe) per telemetria/logging — non altera il flusso e si rimuove facilmente.</li><li><strong>Usa Pattern 2</strong> (subclass) solo se devi intervenire prima del default (filtro rumore, arricchimento args).</li><li><strong>Mai Pattern 3</strong> salvo requisiti enterprise specifici — perdi tutto il built-in.</li><li><strong>Sempre seed le traduzioni</strong> dei tuoi <code>errorCode</code> applicativi (it-IT + en-US minimo) prima di rilasciare in produzione, altrimenti il dialog mostra la chiave grezza.</li><li><strong>Usa `traceId` server-side</strong> nel template di traduzione (es. <code>"Codice: {traceId}"</code>) per facilitare la diagnostica condivisa fra utente e team supporto.</li></ul>",
|
|
24776
|
+
"codeSamples": [
|
|
24777
|
+
{
|
|
24778
|
+
"id": "code_1",
|
|
24779
|
+
"title": "Snippet 1",
|
|
24780
|
+
"language": "ts",
|
|
24781
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: GlobalHandler },\n ...\n]"
|
|
24782
|
+
},
|
|
24783
|
+
{
|
|
24784
|
+
"id": "code_2",
|
|
24785
|
+
"title": "Snippet 2",
|
|
24786
|
+
"language": "ts",
|
|
24787
|
+
"code": "import { GlobalHandler } from './wuic-bridges/core';\n\nGlobalHandler.messageNotification.subscribe((data) => {\n const exc = data?.exception;\n if (!exc?.errorCode) return;\n\n // Filtra rumore noto.\n if (String(exc.errorCode).startsWith('errors.client.archetype.')) return;\n\n // Invio a endpoint analytics (Sentry, App Insights, ecc.).\n fetch('/analytics/client-errors', {\n method: 'POST',\n body: JSON.stringify({\n errorCode: exc.errorCode,\n args: exc.args,\n traceId: exc.traceId,\n url: window.location.href,\n ts: new Date().toISOString(),\n }),\n credentials: 'include',\n });\n});"
|
|
24788
|
+
},
|
|
24789
|
+
{
|
|
24790
|
+
"id": "code_3",
|
|
24791
|
+
"title": "Snippet 3",
|
|
24792
|
+
"language": "ts",
|
|
24793
|
+
"code": "import { ErrorHandler, Injectable } from '@angular/core';\nimport { GlobalHandler } from './wuic-bridges/core';\n\n@Injectable()\nexport class MyCustomErrorHandler extends GlobalHandler {\n override handleError(e: any): void {\n // 1. Suppress noise non azionabile.\n const msg = (typeof e?.message === 'string' ? e.message : '') as string;\n if (msg.includes('ResizeObserver loop limit exceeded')) {\n console.debug('[MyCustomErrorHandler] suppressed:', msg);\n return;\n }\n\n // 2. Arricchisci args con context applicativo.\n if (typeof e?.error?.errorCode === 'string' && e?.error?.args) {\n e.error.args = {\n ...e.error.args,\n appVersion: (window as any).__myAppVersion || 'dev',\n userRole: (window as any).__myAppUserRole || 'unknown',\n };\n }\n\n // 3. Delega al default — tutte le typed envelopes, traduzioni,\n // dialog SQL passthrough, NG04002 routing continuano a funzionare.\n super.handleError(e);\n }\n}"
|
|
24794
|
+
},
|
|
24795
|
+
{
|
|
24796
|
+
"id": "code_4",
|
|
24797
|
+
"title": "Snippet 4",
|
|
24798
|
+
"language": "ts",
|
|
24799
|
+
"code": "// app.config.ts\nimport { MyCustomErrorHandler } from './exception-handling/custom-error-handler.example';\n\nproviders: [\n ...\n { provide: ErrorHandler, useClass: MyCustomErrorHandler },\n ...\n]"
|
|
24800
|
+
},
|
|
24801
|
+
{
|
|
24802
|
+
"id": "code_5",
|
|
24803
|
+
"title": "Snippet 5",
|
|
24804
|
+
"language": "ts",
|
|
24805
|
+
"code": "import { WuicClientException } from 'wuic-framework-lib-src/exception/WuicClientException';\n\nif (!myConfig.exportEnabled) {\n throw new WuicClientException(\n 'errors.myapp.feature_disabled',\n { feature: 'export-pdf' },\n { surface: 'service', targetName: 'MyAppService.exportPdf' }\n );\n}"
|
|
24806
|
+
},
|
|
24807
|
+
{
|
|
24808
|
+
"id": "code_6",
|
|
24809
|
+
"title": "Snippet 6",
|
|
24810
|
+
"language": "sql",
|
|
24811
|
+
"code": "-- Esempio seed (idempotente, vedi scripts/upsert-wuic-translations.ps1).\nINSERT INTO _wuic_translations (translation_key, locale, translation_text)\nVALUES\n ('errors.myapp.feature_disabled', 'it-IT', \"Funzionalita' '{feature}' disabilitata in questa versione.\"),\n ('errors.myapp.feature_disabled', 'en-US', \"Feature ''{feature}'' is disabled in this build.\");"
|
|
24812
|
+
},
|
|
24813
|
+
{
|
|
24814
|
+
"id": "code_7",
|
|
24815
|
+
"title": "Snippet 7",
|
|
24816
|
+
"language": "csharp",
|
|
24817
|
+
"code": "using WEB_UI_CRAFTER.Helpers.Exceptions;\n\nif (!_myService.IsLicensed(\"export-pdf\"))\n{\n throw new WuicException(\n \"errors.myapp.license.missing\",\n new Dictionary<string, object>\n {\n [\"feature\"] = \"export-pdf\",\n [\"tier\"] = currentTier,\n })\n {\n HttpStatus = 403,\n FallbackMessage = $\"License missing for feature 'export-pdf' (tier '{currentTier}').\",\n };\n}"
|
|
24818
|
+
}
|
|
24819
|
+
]
|
|
24820
|
+
}
|
|
24821
|
+
],
|
|
24822
|
+
"images": []
|
|
24823
|
+
},
|
|
24353
24824
|
{
|
|
24354
24825
|
"slug": "component-injection",
|
|
24355
24826
|
"lang": "de-DE",
|
|
@@ -25920,7 +26391,7 @@ class FrameworkDocsComponent {
|
|
|
25920
26391
|
return work;
|
|
25921
26392
|
}
|
|
25922
26393
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FrameworkDocsComponent, deps: [{ token: i1.Router }, { token: i1.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
|
|
25923
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FrameworkDocsComponent, isStandalone: true, selector: "wuic-framework-docs", viewQueries: [{ propertyName: "contentScroller", first: true, predicate: ["contentScroller"], descendants: true }], ngImport: i0, template: "<div class=\"fw-docs\" [class.dark]=\"dark()\">\n <aside class=\"sidebar\">\n <div class=\"brand\">\n <h2>{{ 'docs.title' | translate }}</h2>\n <p>{{ 'docs.subtitle' | translate }}</p>\n </div>\n\n <div class=\"search\">\n <input pInputText type=\"text\" [ngModel]=\"query()\" (ngModelChange)=\"query.set($event || '')\" [placeholder]=\"t('docs.search_placeholder','Search feature, tag, keyword')\" />\n <button pButton type=\"button\" icon=\"pi pi-sun\" *ngIf=\"dark()\" (click)=\"toggleTheme()\"></button>\n <button pButton type=\"button\" icon=\"pi pi-moon\" *ngIf=\"!dark()\" (click)=\"toggleTheme()\"></button>\n </div>\n\n <div class=\"nav-groups\">\n @for (group of filteredGroups(); track group.id) {\n <section>\n <h3>{{ group.title }}</h3>\n <ul>\n @for (item of group.items; track item.slug) {\n <li>\n <a [class.active]=\"item.slug === currentSlug()\" [href]=\"'#/docs/' + item.slug\" (click)=\"openPage(item.slug); $event.preventDefault()\">\n <i class=\"pi\" [ngClass]=\"item.icon || 'pi-file'\"></i>\n <span>{{ item.title }}</span>\n </a>\n </li>\n }\n </ul>\n </section>\n }\n </div>\n </aside>\n\n <main class=\"content\" #contentScroller *ngIf=\"currentPage() as page\">\n <nav class=\"breadcrumbs\">{{ breadcrumbs().join(' / ') }}</nav>\n\n <header>\n <h1>{{ page.title }}</h1>\n <p>{{ page.description }}</p>\n <div class=\"tags\">\n <p-tag *ngFor=\"let tag of page.tags\" [value]=\"tag\"></p-tag>\n <p-tag\n [value]=\"page.status\"\n [severity]=\"page.status === 'beta' ? 'warn' : 'success'\"\n [pTooltip]=\"page.status === 'beta' ? 'Feature in beta: API e comportamento possono cambiare senza preavviso' : ''\"\n tooltipPosition=\"top\"></p-tag>\n <p-tag *ngIf=\"page.tier === 'pro'\" value=\"Pro only\" styleClass=\"tier-tag tier-tag-pro\"></p-tag>\n <p-tag *ngIf=\"!page.tier || page.tier === 'dev-and-pro'\" value=\"Dev & Pro\" styleClass=\"tier-tag tier-tag-base\"></p-tag>\n </div>\n </header>\n\n <div class=\"body-grid\">\n <article>\n @for (section of page.sections; track section.id) {\n <section [attr.id]=\"section.id\" class=\"doc-section\">\n <h3>{{ section.title }}</h3>\n @for (part of sectionParts(section); track $index) {\n @if (part.kind === 'html') {\n <div class=\"section-html\" [innerHTML]=\"getHighlightedHtml(part.html)\"></div>\n } @else {\n @let sampleKey = getSampleKey(page.slug, section.id, part.sample.id);\n <div class=\"code-block\" [ngClass]=\"getSnippetLanguageClass(part.sample.language)\">\n <div class=\"code-header\">\n <div class=\"code-meta\">\n <span>{{ part.sample.title }}</span>\n <span class=\"snippet-lang\" [ngClass]=\"getSnippetLanguageClass(part.sample.language)\">\n <i class=\"pi\" [ngClass]=\"getSnippetLanguageIconClass(part.sample.language)\"></i>\n {{ getSnippetLanguageLabel(part.sample.language) }}\n </span>\n </div>\n <div class=\"code-actions\">\n @if (isSampleCollapsible(part.sample.code)) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n [icon]=\"isSampleExpanded(sampleKey) ? 'pi pi-chevron-up' : 'pi pi-chevron-down'\"\n [label]=\"isSampleExpanded(sampleKey) ? t('docs.collapse','Collapse') : (t('docs.expand','Expand') + ' (+' + getCollapsedHiddenLines(part.sample.code) + ')')\"\n (click)=\"toggleSampleExpanded(sampleKey)\">\n </button>\n }\n <button pButton type=\"button\" size=\"small\" icon=\"pi pi-copy\" [label]=\"t('docs.copy','Copy')\" (click)=\"copyCode(part.sample.code)\"></button>\n </div>\n </div>\n <pre><code [innerHTML]=\"getVisibleSampleHighlightedCode(part.sample.code, sampleKey, part.sample.language)\"></code></pre>\n </div>\n }\n }\n </section>\n }\n\n @if (page.slug === 'themes') {\n <section class=\"themes-catalog\">\n <h3>{{ 'docs.themes_catalog' | translate }}</h3>\n <div class=\"themes-catalog-grid\">\n @for (theme of allThemes; track theme.value) {\n <div class=\"themes-catalog-item\">\n <span class=\"theme-dot\" [style.backgroundColor]=\"theme.primaryHex\"></span>\n <span>{{ theme.label }}</span>\n </div>\n }\n </div>\n </section>\n }\n\n @if (page.images?.length) {\n <section class=\"screenshots\">\n <h3>{{ 'docs.feature_screenshots' | translate }}</h3>\n <div class=\"shots-grid\">\n @for (img of page.images; track img.id) {\n <figure>\n <p-image\n *ngIf=\"img.status === 'available'\"\n [preview]=\"true\"\n [src]=\"img.path\"\n [previewImageSrc]=\"img.path\"\n [alt]=\"img.caption\"\n />\n <div class=\"missing\" *ngIf=\"img.status !== 'available'\">{{ 'docs.snapshot_unavailable' | translate }}</div>\n <figcaption [innerHTML]=\"getHighlightedText(formatScreenshotCaption(img.caption))\"></figcaption>\n </figure>\n }\n </div>\n </section>\n }\n </article>\n\n <aside class=\"toc\">\n <h4>{{ 'docs.on_this_page' | translate }}</h4>\n <ul>\n @for (item of page.toc; track item.id) {\n <li><a [href]=\"'#' + item.id\" (click)=\"scrollToSection($event, item.id, item.title)\">{{ item.title }}</a></li>\n }\n </ul>\n </aside>\n </div>\n </main>\n</div>\n", styles: ["@charset \"UTF-8\";.fw-docs{--bg: linear-gradient(145deg, #f7f9ff 0%, #edf3ff 40%, #fefbf4 100%);--panel: rgba(255, 255, 255, .86);--text: #18304a;--muted: #4d6278;--accent: #0d6efd;--border: #dce7fb;height:calc(100vh - 70px);display:grid;grid-template-columns:320px 1fr;background:var(--bg);color:var(--text);overflow:hidden}.fw-docs.dark,:host-context(.theme-dark) .fw-docs,:host-context(.dark-theme) .fw-docs,:host-context([data-theme-mode=dark]) .fw-docs{--bg: linear-gradient(145deg, #121b2a 0%, #0f2233 55%, #222134 100%);--panel: rgba(22, 35, 55, .85);--text: #dbe8ff;--muted: #9eb4d2;--accent: #7eb2ff;--border: #294869}.sidebar{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:var(--panel);border-right:1px solid var(--border);padding:18px;position:sticky;top:0;height:calc(100vh - 70px);overflow:auto}.brand h1{margin:0;font-size:1.1rem}.brand p{margin:6px 0 14px;color:var(--muted);font-size:.88rem}.search{display:grid;grid-template-columns:1fr auto;gap:6px;margin-bottom:12px}.nav-groups h3{margin:14px 0 8px;font-size:.86rem;text-transform:uppercase;color:var(--muted);letter-spacing:.06em}.nav-groups ul{list-style:none;padding:0;margin:0}.nav-groups a{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:10px;color:inherit;text-decoration:none;cursor:pointer}.nav-groups a.active,.nav-groups a:hover{background:#0d6efd1f}.content{padding:26px 30px 36px;height:100%;overflow-y:scroll;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--p-content-border-color, #94a3b8) 80%,transparent) transparent;scrollbar-gutter:stable}.content::-webkit-scrollbar,.sidebar::-webkit-scrollbar{width:10px;height:10px}.content::-webkit-scrollbar-track,.sidebar::-webkit-scrollbar-track{background:transparent}.content::-webkit-scrollbar-thumb,.sidebar::-webkit-scrollbar-thumb{background-color:color-mix(in srgb,var(--p-content-border-color, #94a3b8) 65%,transparent);border-radius:6px;border:2px solid transparent;background-clip:content-box}.content::-webkit-scrollbar-thumb:hover,.sidebar::-webkit-scrollbar-thumb:hover{background-color:var(--p-text-muted-color, #64748b)}.sidebar{scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--p-content-border-color, #94a3b8) 80%,transparent) transparent}.breadcrumbs{font-size:.85rem;color:var(--muted);margin-bottom:10px}header h2{margin:0;font-size:2rem}header p{margin:8px 0 12px;color:var(--muted)}.tags{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:20px}::ng-deep .tier-tag.p-tag{font-weight:700;letter-spacing:.02em}::ng-deep .tier-tag-base.p-tag{background:color-mix(in srgb,#6366f1 15%,var(--panel, #fff));color:color-mix(in srgb,#4338ca 85%,var(--text, #0f172a));border:1px solid color-mix(in srgb,#6366f1 45%,transparent)}::ng-deep .tier-tag-pro.p-tag{background:color-mix(in srgb,#f59e0b 18%,var(--panel, #fff));color:color-mix(in srgb,#b45309 85%,var(--text, #0f172a));border:1px solid color-mix(in srgb,#f59e0b 55%,transparent)}.body-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(320px,360px);gap:20px}article{background:var(--panel);border:1px solid var(--border);border-radius:16px;padding:20px}.doc-section{padding:6px 0 16px;border-bottom:1px dashed var(--border)}.doc-section:last-child{border-bottom:0}.doc-section h3{margin:8px 0}.section-html{color:var(--text)}:host ::ng-deep .section-html p{line-height:1.58}:host ::ng-deep .section-html table{width:100%;border-collapse:collapse;margin:16px 0 24px;border:1px solid var(--border);border-radius:8px;overflow:hidden;font-size:.92rem;box-shadow:0 1px 2px color-mix(in srgb,var(--text) 6%,transparent)}:host ::ng-deep .section-html thead{background:color-mix(in srgb,var(--accent) 14%,var(--panel))}:host ::ng-deep .section-html thead th{text-align:left;color:var(--text);font-weight:700;padding:12px 16px;border:1px solid var(--border);border-bottom:2px solid color-mix(in srgb,var(--accent) 35%,var(--border));text-transform:uppercase;font-size:.78rem;letter-spacing:.4px;white-space:nowrap}:host ::ng-deep .section-html tbody td{padding:11px 16px;border:1px solid color-mix(in srgb,var(--border) 80%,transparent);vertical-align:top;line-height:1.55;color:var(--text)}:host ::ng-deep .section-html tbody tr:nth-child(odd) td{background:color-mix(in srgb,var(--panel) 92%,transparent)}:host ::ng-deep .section-html tbody tr:nth-child(2n) td{background:color-mix(in srgb,var(--panel) 100%,transparent)}:host ::ng-deep .section-html tbody tr:hover td{background:color-mix(in srgb,var(--accent) 8%,var(--panel))}:host ::ng-deep .section-html table code{font-size:.85em;padding:1px 5px}:host ::ng-deep .section-html strong{color:var(--text);font-weight:600}:host ::ng-deep .section-html em{font-style:italic}:host ::ng-deep .section-html a.wuic-demo-link{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;margin:0 2px;background:color-mix(in srgb,var(--accent) 14%,var(--panel));border:1px solid color-mix(in srgb,var(--accent) 35%,var(--border));border-radius:6px;color:var(--accent, #4f46e5);font-size:.85rem;font-weight:600;text-decoration:none;line-height:1.2;transition:background .15s ease}:host ::ng-deep .section-html a.wuic-demo-link:before{content:\"\\25b6\";font-size:.7rem;color:var(--accent, #4f46e5)}:host ::ng-deep .section-html a.wuic-demo-link:hover{background:color-mix(in srgb,var(--accent) 22%,var(--panel));text-decoration:none}:host ::ng-deep .section-html :where(ul,ol){margin:12px 0 16px;padding-left:0}:host ::ng-deep .section-html ul{list-style:none}:host ::ng-deep .section-html ul>li{position:relative;margin:8px 0;padding:8px 12px 8px 34px;border:1px solid color-mix(in srgb,var(--border) 78%,transparent);border-radius:10px;background:color-mix(in srgb,var(--panel) 90%,transparent);line-height:1.52}:host ::ng-deep .section-html ul>li:nth-child(odd){background:color-mix(in srgb,var(--panel) 94%,transparent)}:host ::ng-deep .section-html ul>li:nth-child(2n){background:color-mix(in srgb,var(--accent) 5%,var(--panel));border-color:color-mix(in srgb,var(--accent) 18%,var(--border))}:host ::ng-deep .section-html ul>li:before{content:\"\";position:absolute;left:12px;top:50%;width:10px;height:10px;border-radius:999px;transform:translateY(-50%);background:radial-gradient(circle at 35% 35%,#fff 0 24%,color-mix(in srgb,var(--accent) 80%,#4aa3ff) 25% 100%);box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 32%,transparent)}:host ::ng-deep .section-html ol{list-style:none;counter-reset:wuic-doc-step}:host ::ng-deep .section-html ol>li{position:relative;counter-increment:wuic-doc-step;margin:8px 0;padding:8px 12px 8px 42px;border-left:3px solid color-mix(in srgb,var(--accent) 55%,transparent);background:color-mix(in srgb,var(--accent) 7%,var(--panel));border-radius:10px;line-height:1.52}:host ::ng-deep .section-html ol>li:nth-child(odd){background:color-mix(in srgb,var(--accent) 7%,var(--panel))}:host ::ng-deep .section-html ol>li:nth-child(2n){background:color-mix(in srgb,var(--accent) 11%,var(--panel));border-left-color:color-mix(in srgb,var(--accent) 72%,transparent)}:host ::ng-deep .section-html ol>li:before{content:counter(wuic-doc-step);position:absolute;left:10px;top:50%;width:22px;height:22px;border-radius:999px;transform:translateY(-50%);display:grid;place-items:center;font-size:.78rem;font-weight:700;color:#fff;background:linear-gradient(160deg,color-mix(in srgb,var(--accent) 80%,#4aa3ff),color-mix(in srgb,var(--accent) 95%,#125dcc));box-shadow:0 2px 10px color-mix(in srgb,var(--accent) 35%,transparent)}:host ::ng-deep .section-html li>:where(ul,ol){margin-top:8px}.code-block{margin:10px 0;border:1px solid var(--border);border-radius:12px;overflow:hidden}.code-header{display:flex;justify-content:space-between;align-items:center;background:#0d6efd14;padding:8px 10px}.code-block pre{margin:0;padding:12px;overflow:auto;background:#1e1e1e}.code-block code{display:block;font-family:Consolas,Cascadia Code,Fira Code,Courier New,monospace;font-size:.88rem;line-height:1.55;color:#d4d4d4;white-space:pre}.code-actions{display:inline-flex;gap:8px;align-items:center}.code-meta{display:inline-flex;align-items:center;gap:10px}.snippet-lang{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:22px;padding:0 8px;border-radius:999px;font-size:.72rem;font-weight:700;letter-spacing:.04em;border:1px solid transparent;background:color-mix(in srgb,var(--text) 8%,transparent);color:var(--text)}.snippet-lang.lang-html{background:#e36c0924;border-color:#e36c0952;color:#b25d0e}.snippet-lang.lang-json{background:#00808024;border-color:#00808052;color:#0e6b6b}.snippet-lang.lang-ts{background:#3178c624;border-color:#3178c652;color:#1f5f9f}.snippet-lang.lang-cs{background:#68217a24;border-color:#68217a52;color:#6a2b82}.snippet-lang i{font-size:.72rem}:host ::ng-deep .code-block code .tok-comment{color:#6a9955}:host ::ng-deep .code-block code .tok-string{color:#ce9178}:host ::ng-deep .code-block code .tok-number{color:#b5cea8}:host ::ng-deep .code-block code .tok-keyword{color:#569cd6}:host ::ng-deep .code-block code .tok-type{color:#4ec9b0}:host ::ng-deep .code-block code .tok-fn{color:#dcdcaa}:host ::ng-deep .code-block code .tok-prop{color:#9cdcfe}:host ::ng-deep .code-block code .tok-op{color:#d4d4d4}:host ::ng-deep .code-block.lang-html code .tok-tag{color:#569cd6}:host ::ng-deep .code-block.lang-html code .tok-attr{color:#9cdcfe}:host ::ng-deep .code-block.lang-html code .tok-string{color:#ce9178}:host ::ng-deep .code-block.lang-json code .tok-key{color:#9cdcfe}:host ::ng-deep .code-block.lang-json code .tok-string{color:#ce9178}:host ::ng-deep .code-block.lang-json code .tok-keyword{color:#569cd6}:host ::ng-deep .code-block.lang-json code .tok-number{color:#b5cea8}:host ::ng-deep .code-block.lang-ts code .tok-keyword{color:#569cd6}:host ::ng-deep .code-block.lang-ts code .tok-type{color:#4ec9b0}:host ::ng-deep .code-block.lang-ts code .tok-fn{color:#dcdcaa}:host ::ng-deep .code-block.lang-ts code .tok-prop{color:#9cdcfe}:host ::ng-deep .code-block.lang-ts code .tok-string{color:#ce9178}:host ::ng-deep .code-block.lang-ts code .tok-comment{color:#6a9955}:host ::ng-deep .code-block.lang-ts code .tok-number{color:#b5cea8}:host ::ng-deep .code-block.lang-cs code .tok-keyword{color:#569cd6}:host ::ng-deep .code-block.lang-cs code .tok-fn{color:#dcdcaa}:host ::ng-deep .code-block.lang-cs code .tok-prop{color:#9cdcfe}:host ::ng-deep .code-block.lang-cs code .tok-string{color:#ce9178}:host ::ng-deep .code-block.lang-cs code .tok-comment{color:#6a9955}:host ::ng-deep .code-block.lang-cs code .tok-number{color:#b5cea8}.screenshots .shots-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px;align-items:start}.screenshots figure{margin:0;display:flex;flex-direction:column;gap:8px}.screenshots img{width:100%;border-radius:12px;border:1px solid var(--border)}:host ::ng-deep .screenshots .p-image,:host ::ng-deep .screenshots .p-image img{width:100%;display:block}:host ::ng-deep .screenshots .p-image{aspect-ratio:16/9;overflow:hidden;border-radius:12px;border:1px solid var(--border);background:color-mix(in srgb,var(--panel) 90%,transparent)}:host ::ng-deep .screenshots .p-image img{width:100%;height:100%;object-fit:contain;object-position:center;border:0}:host ::ng-deep .screenshots .p-image .p-image-preview-mask,:host ::ng-deep .screenshots .p-image .p-image-mask{inset:0;width:100%;height:100%}.missing{border:1px dashed var(--border);border-radius:12px;padding:36px 10px;text-align:center;color:var(--muted)}:host ::ng-deep .p-image-mask,:host ::ng-deep .p-image-preview-mask{background:none!important;backdrop-filter:none!important;-webkit-backdrop-filter:none!important}:host ::ng-deep .p-image-toolbar{background:#0c1220!important;backdrop-filter:none!important;-webkit-backdrop-filter:none!important;filter:none!important;border:1px solid rgba(255,255,255,.14)!important;box-shadow:0 8px 24px #00000059!important}:host ::ng-deep .p-image-action{color:#eaf1ff!important;opacity:1!important;text-shadow:none!important}:host ::ng-deep .p-image-preview{background:#7eb2ff2e!important}::ng-deep .p-image-mask.p-component-overlay,::ng-deep .p-image-preview-mask.p-component-overlay{background:#0c121efa!important;backdrop-filter:none!important;-webkit-backdrop-filter:none!important}:host ::ng-deep .screenshots .p-image .p-image-mask,:host ::ng-deep .screenshots .p-image .p-image-preview-indicator{background:#0c121e42!important}.themes-catalog{margin-top:14px;padding:6px 0 16px;border-top:1px dashed var(--border)}.themes-catalog-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:10px}.themes-catalog-item{display:inline-flex;align-items:center;gap:.55rem;min-height:2.25rem;padding:.45rem .65rem;border:1px solid var(--border);border-radius:10px;background:color-mix(in srgb,var(--panel) 92%,transparent)}.theme-dot{width:.8rem;height:.8rem;border-radius:999px;border:1px solid color-mix(in srgb,var(--text) 25%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,#ffffff 55%,transparent) inset;flex:0 0 auto}.toc{position:sticky;top:20px;max-height:calc(100vh - 120px);overflow-y:auto;background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:14px}.toc h4{margin:0 0 8px}.toc ul{margin:0;padding-left:18px;list-style-position:outside}.toc a{display:block;color:var(--text);text-decoration:none;line-height:1.25;overflow-wrap:anywhere;word-break:break-word}.toc li{margin:0 0 6px}.toc li:last-child{margin-bottom:0}@media(max-width:1360px)and (min-width:1101px){.body-grid{grid-template-columns:minmax(0,1fr) minmax(280px,320px)}}@media(max-width:1100px){.fw-docs{grid-template-columns:1fr;height:auto;overflow:visible}.sidebar{height:auto;position:static;border-right:0;border-bottom:1px solid var(--border)}.content{height:auto;overflow:visible}.body-grid{grid-template-columns:1fr}.toc{position:static}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i13.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i10.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: ImageModule }, { kind: "component", type: i1$2.Image, selector: "p-image", inputs: ["imageClass", "imageStyle", "styleClass", "src", "srcSet", "sizes", "previewImageSrc", "previewImageSrcSet", "previewImageSizes", "alt", "width", "height", "loading", "preview", "showTransitionOptions", "hideTransitionOptions", "modalEnterAnimation", "modalLeaveAnimation", "appendTo", "maskMotionOptions", "motionOptions"], outputs: ["onShow", "onHide", "onImageError"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2$1.TranslatePipe, name: "translate" }] });
|
|
26394
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FrameworkDocsComponent, isStandalone: true, selector: "wuic-framework-docs", viewQueries: [{ propertyName: "contentScroller", first: true, predicate: ["contentScroller"], descendants: true }], ngImport: i0, template: "<div class=\"fw-docs\" [class.dark]=\"dark()\">\n <aside class=\"sidebar\">\n <div class=\"brand\">\n <h2>{{ 'docs.title' | translate }}</h2>\n <p>{{ 'docs.subtitle' | translate }}</p>\n </div>\n\n <div class=\"search\">\n <input pInputText type=\"text\" [ngModel]=\"query()\" (ngModelChange)=\"query.set($event || '')\" [placeholder]=\"t('docs.search_placeholder','Search feature, tag, keyword')\" />\n <button pButton type=\"button\" icon=\"pi pi-sun\" *ngIf=\"dark()\" (click)=\"toggleTheme()\"></button>\n <button pButton type=\"button\" icon=\"pi pi-moon\" *ngIf=\"!dark()\" (click)=\"toggleTheme()\"></button>\n </div>\n\n <div class=\"nav-groups\">\n @for (group of filteredGroups(); track group.id) {\n <section>\n <h3>{{ group.title }}</h3>\n <ul>\n @for (item of group.items; track item.slug) {\n <li>\n <a [class.active]=\"item.slug === currentSlug()\" [href]=\"'#/docs/' + item.slug\" (click)=\"openPage(item.slug); $event.preventDefault()\">\n <i class=\"pi\" [ngClass]=\"item.icon || 'pi-file'\"></i>\n <span>{{ item.title }}</span>\n </a>\n </li>\n }\n </ul>\n </section>\n }\n </div>\n </aside>\n\n <main class=\"content\" #contentScroller *ngIf=\"currentPage() as page\">\n <nav class=\"breadcrumbs\">{{ breadcrumbs().join(' / ') }}</nav>\n\n <header>\n <h1>{{ page.title }}</h1>\n <p>{{ page.description }}</p>\n <div class=\"tags\">\n <p-tag *ngFor=\"let tag of page.tags\" [value]=\"tag\"></p-tag>\n <p-tag\n [value]=\"page.status\"\n [severity]=\"page.status === 'beta' ? 'warn' : 'success'\"\n [pTooltip]=\"page.status === 'beta' ? 'Feature in beta: API e comportamento possono cambiare senza preavviso' : ''\"\n tooltipPosition=\"top\"></p-tag>\n <p-tag *ngIf=\"page.tier === 'pro'\" value=\"Pro only\" styleClass=\"tier-tag tier-tag-pro\"></p-tag>\n <p-tag *ngIf=\"!page.tier || page.tier === 'dev-and-pro'\" value=\"Dev & Pro\" styleClass=\"tier-tag tier-tag-base\"></p-tag>\n </div>\n </header>\n\n <div class=\"body-grid\">\n <article>\n @for (section of page.sections; track section.id) {\n <section [attr.id]=\"section.id\" class=\"doc-section\">\n <h3>{{ section.title }}</h3>\n @for (part of sectionParts(section); track $index) {\n @if (part.kind === 'html') {\n <div class=\"section-html\" [innerHTML]=\"getHighlightedHtml(part.html)\"></div>\n } @else {\n @let sampleKey = getSampleKey(page.slug, section.id, part.sample.id);\n <div class=\"code-block\" [ngClass]=\"getSnippetLanguageClass(part.sample.language)\">\n <div class=\"code-header\">\n <div class=\"code-meta\">\n <span>{{ part.sample.title }}</span>\n <span class=\"snippet-lang\" [ngClass]=\"getSnippetLanguageClass(part.sample.language)\">\n <i class=\"pi\" [ngClass]=\"getSnippetLanguageIconClass(part.sample.language)\"></i>\n {{ getSnippetLanguageLabel(part.sample.language) }}\n </span>\n </div>\n <div class=\"code-actions\">\n @if (isSampleCollapsible(part.sample.code)) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n [icon]=\"isSampleExpanded(sampleKey) ? 'pi pi-chevron-up' : 'pi pi-chevron-down'\"\n [label]=\"isSampleExpanded(sampleKey) ? t('docs.collapse','Collapse') : (t('docs.expand','Expand') + ' (+' + getCollapsedHiddenLines(part.sample.code) + ')')\"\n (click)=\"toggleSampleExpanded(sampleKey)\">\n </button>\n }\n <button pButton type=\"button\" size=\"small\" icon=\"pi pi-copy\" [label]=\"t('docs.copy','Copy')\" (click)=\"copyCode(part.sample.code)\"></button>\n </div>\n </div>\n <pre><code [innerHTML]=\"getVisibleSampleHighlightedCode(part.sample.code, sampleKey, part.sample.language)\"></code></pre>\n </div>\n }\n }\n </section>\n }\n\n @if (page.slug === 'themes') {\n <section class=\"themes-catalog\">\n <h3>{{ 'docs.themes_catalog' | translate }}</h3>\n <div class=\"themes-catalog-grid\">\n @for (theme of allThemes; track theme.value) {\n <div class=\"themes-catalog-item\">\n <span class=\"theme-dot\" [style.backgroundColor]=\"theme.primaryHex\"></span>\n <span>{{ theme.label }}</span>\n </div>\n }\n </div>\n </section>\n }\n\n @if (page.images?.length) {\n <section class=\"screenshots\">\n <h3>{{ 'docs.feature_screenshots' | translate }}</h3>\n <div class=\"shots-grid\">\n @for (img of page.images; track img.id) {\n <figure>\n <p-image\n *ngIf=\"img.status === 'available'\"\n [preview]=\"true\"\n [src]=\"img.path\"\n [previewImageSrc]=\"img.path\"\n [alt]=\"img.caption\"\n />\n <div class=\"missing\" *ngIf=\"img.status !== 'available'\">{{ 'docs.snapshot_unavailable' | translate }}</div>\n <figcaption [innerHTML]=\"getHighlightedText(formatScreenshotCaption(img.caption))\"></figcaption>\n </figure>\n }\n </div>\n </section>\n }\n </article>\n\n <aside class=\"toc\">\n <h4>{{ 'docs.on_this_page' | translate }}</h4>\n <ul>\n @for (item of page.toc; track item.id) {\n <li><a [href]=\"'#' + item.id\" (click)=\"scrollToSection($event, item.id, item.title)\">{{ item.title }}</a></li>\n }\n </ul>\n </aside>\n </div>\n </main>\n</div>\n", styles: ["@charset \"UTF-8\";.fw-docs{--bg: linear-gradient(145deg, #f7f9ff 0%, #edf3ff 40%, #fefbf4 100%);--panel: rgba(255, 255, 255, .86);--text: #18304a;--muted: #4d6278;--accent: #0d6efd;--border: #dce7fb;height:calc(100vh - 70px);display:grid;grid-template-columns:320px 1fr;background:var(--bg);color:var(--text);overflow:hidden}.fw-docs.dark,:host-context(.theme-dark) .fw-docs,:host-context(.dark-theme) .fw-docs,:host-context([data-theme-mode=dark]) .fw-docs{--bg: linear-gradient(145deg, #121b2a 0%, #0f2233 55%, #222134 100%);--panel: rgba(22, 35, 55, .85);--text: #dbe8ff;--muted: #9eb4d2;--accent: #7eb2ff;--border: #294869}.sidebar{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:var(--panel);border-right:1px solid var(--border);padding:18px;position:sticky;top:0;height:calc(100vh - 70px);overflow:auto}.brand h1{margin:0;font-size:1.1rem}.brand p{margin:6px 0 14px;color:var(--muted);font-size:.88rem}.search{display:grid;grid-template-columns:1fr auto;gap:6px;margin-bottom:12px}.nav-groups h3{margin:14px 0 8px;font-size:.86rem;text-transform:uppercase;color:var(--muted);letter-spacing:.06em}.nav-groups ul{list-style:none;padding:0;margin:0}.nav-groups a{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:10px;color:inherit;text-decoration:none;cursor:pointer}.nav-groups a.active,.nav-groups a:hover{background:#0d6efd1f}.content{padding:26px 30px 36px;height:100%;overflow-y:scroll;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--p-content-border-color, #94a3b8) 80%,transparent) transparent;scrollbar-gutter:stable}.content::-webkit-scrollbar,.sidebar::-webkit-scrollbar{width:10px;height:10px}.content::-webkit-scrollbar-track,.sidebar::-webkit-scrollbar-track{background:transparent}.content::-webkit-scrollbar-thumb,.sidebar::-webkit-scrollbar-thumb{background-color:color-mix(in srgb,var(--p-content-border-color, #94a3b8) 65%,transparent);border-radius:6px;border:2px solid transparent;background-clip:content-box}.content::-webkit-scrollbar-thumb:hover,.sidebar::-webkit-scrollbar-thumb:hover{background-color:var(--p-text-muted-color, #64748b)}.sidebar{scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--p-content-border-color, #94a3b8) 80%,transparent) transparent}.breadcrumbs{font-size:.85rem;color:var(--muted);margin-bottom:10px}header h2{margin:0;font-size:2rem}header p{margin:8px 0 12px;color:var(--muted)}.tags{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:20px}::ng-deep .tier-tag.p-tag{font-weight:700;letter-spacing:.02em}::ng-deep .tier-tag-base.p-tag{background:color-mix(in srgb,#6366f1 15%,var(--panel, #fff));color:color-mix(in srgb,#4338ca 85%,var(--text, #0f172a));border:1px solid color-mix(in srgb,#6366f1 45%,transparent)}::ng-deep .tier-tag-pro.p-tag{background:color-mix(in srgb,#f59e0b 18%,var(--panel, #fff));color:color-mix(in srgb,#b45309 85%,var(--text, #0f172a));border:1px solid color-mix(in srgb,#f59e0b 55%,transparent)}.body-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(320px,360px);gap:20px}article{background:var(--panel);border:1px solid var(--border);border-radius:16px;padding:20px}.doc-section{padding:6px 0 16px;border-bottom:1px dashed var(--border)}.doc-section:last-child{border-bottom:0}.doc-section h3{margin:8px 0}.section-html{color:var(--text)}:host ::ng-deep .section-html p{line-height:1.58}:host ::ng-deep .section-html table{width:100%;border-collapse:collapse;margin:16px 0 24px;border:1px solid var(--border);border-radius:8px;overflow:hidden;font-size:.92rem;box-shadow:0 1px 2px color-mix(in srgb,var(--text) 6%,transparent)}:host ::ng-deep .section-html thead{background:color-mix(in srgb,var(--accent) 14%,var(--panel))}:host ::ng-deep .section-html thead th{text-align:left;color:var(--text);font-weight:700;padding:12px 16px;border:1px solid var(--border);border-bottom:2px solid color-mix(in srgb,var(--accent) 35%,var(--border));text-transform:uppercase;font-size:.78rem;letter-spacing:.4px;white-space:nowrap}:host ::ng-deep .section-html tbody td{padding:11px 16px;border:1px solid color-mix(in srgb,var(--border) 80%,transparent);vertical-align:top;line-height:1.55;color:var(--text)}:host ::ng-deep .section-html tbody tr:nth-child(odd) td{background:color-mix(in srgb,var(--panel) 92%,transparent)}:host ::ng-deep .section-html tbody tr:nth-child(2n) td{background:color-mix(in srgb,var(--panel) 100%,transparent)}:host ::ng-deep .section-html tbody tr:hover td{background:color-mix(in srgb,var(--accent) 8%,var(--panel))}:host ::ng-deep .section-html table code{font-size:.85em;padding:1px 5px}:host ::ng-deep .section-html strong{color:var(--text);font-weight:600}:host ::ng-deep .section-html em{font-style:italic}:host ::ng-deep .section-html a.wuic-demo-link{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;margin:0 2px;background:color-mix(in srgb,var(--accent) 14%,var(--panel));border:1px solid color-mix(in srgb,var(--accent) 35%,var(--border));border-radius:6px;color:var(--accent, #4f46e5);font-size:.85rem;font-weight:600;text-decoration:none;line-height:1.2;transition:background .15s ease}:host ::ng-deep .section-html a.wuic-demo-link:before{content:\"\\25b6\";font-size:.7rem;color:var(--accent, #4f46e5)}:host ::ng-deep .section-html a.wuic-demo-link:hover{background:color-mix(in srgb,var(--accent) 22%,var(--panel));text-decoration:none}:host ::ng-deep .section-html :where(ul,ol){margin:12px 0 16px;padding-left:0}:host ::ng-deep .section-html ul{list-style:none}:host ::ng-deep .section-html ul>li{position:relative;margin:8px 0;padding:8px 12px 8px 34px;border:1px solid color-mix(in srgb,var(--border) 78%,transparent);border-radius:10px;background:color-mix(in srgb,var(--panel) 90%,transparent);line-height:1.52}:host ::ng-deep .section-html ul>li:nth-child(odd){background:color-mix(in srgb,var(--panel) 94%,transparent)}:host ::ng-deep .section-html ul>li:nth-child(2n){background:color-mix(in srgb,var(--accent) 5%,var(--panel));border-color:color-mix(in srgb,var(--accent) 18%,var(--border))}:host ::ng-deep .section-html ul>li:before{content:\"\";position:absolute;left:12px;top:50%;width:10px;height:10px;border-radius:999px;transform:translateY(-50%);background:radial-gradient(circle at 35% 35%,#fff 0 24%,color-mix(in srgb,var(--accent) 80%,#4aa3ff) 25% 100%);box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 32%,transparent)}:host ::ng-deep .section-html ol{list-style:none;counter-reset:wuic-doc-step}:host ::ng-deep .section-html ol>li{position:relative;counter-increment:wuic-doc-step;margin:8px 0;padding:8px 12px 8px 42px;border-left:3px solid color-mix(in srgb,var(--accent) 55%,transparent);background:color-mix(in srgb,var(--accent) 7%,var(--panel));border-radius:10px;line-height:1.52}:host ::ng-deep .section-html ol>li:nth-child(odd){background:color-mix(in srgb,var(--accent) 7%,var(--panel))}:host ::ng-deep .section-html ol>li:nth-child(2n){background:color-mix(in srgb,var(--accent) 11%,var(--panel));border-left-color:color-mix(in srgb,var(--accent) 72%,transparent)}:host ::ng-deep .section-html ol>li:before{content:counter(wuic-doc-step);position:absolute;left:10px;top:50%;width:22px;height:22px;border-radius:999px;transform:translateY(-50%);display:grid;place-items:center;font-size:.78rem;font-weight:700;color:#fff;background:linear-gradient(160deg,color-mix(in srgb,var(--accent) 80%,#4aa3ff),color-mix(in srgb,var(--accent) 95%,#125dcc));box-shadow:0 2px 10px color-mix(in srgb,var(--accent) 35%,transparent)}:host ::ng-deep .section-html li>:where(ul,ol){margin-top:8px}.code-block{margin:10px 0;border:1px solid var(--border);border-radius:12px;overflow:hidden}.code-header{display:flex;justify-content:space-between;align-items:center;background:#0d6efd14;padding:8px 10px}.code-block pre{margin:0;padding:12px;overflow:auto;background:#1e1e1e}.code-block code{display:block;font-family:Consolas,Cascadia Code,Fira Code,Courier New,monospace;font-size:.88rem;line-height:1.55;color:#d4d4d4;white-space:pre}.code-actions{display:inline-flex;gap:8px;align-items:center}.code-meta{display:inline-flex;align-items:center;gap:10px}.snippet-lang{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:22px;padding:0 8px;border-radius:999px;font-size:.72rem;font-weight:700;letter-spacing:.04em;border:1px solid transparent;background:color-mix(in srgb,var(--text) 8%,transparent);color:var(--text)}.snippet-lang.lang-html{background:#e36c0924;border-color:#e36c0952;color:#b25d0e}.snippet-lang.lang-json{background:#00808024;border-color:#00808052;color:#0e6b6b}.snippet-lang.lang-ts{background:#3178c624;border-color:#3178c652;color:#1f5f9f}.snippet-lang.lang-cs{background:#68217a24;border-color:#68217a52;color:#6a2b82}.snippet-lang i{font-size:.72rem}:host ::ng-deep .code-block code .tok-comment{color:#6a9955}:host ::ng-deep .code-block code .tok-string{color:#ce9178}:host ::ng-deep .code-block code .tok-number{color:#b5cea8}:host ::ng-deep .code-block code .tok-keyword{color:#569cd6}:host ::ng-deep .code-block code .tok-type{color:#4ec9b0}:host ::ng-deep .code-block code .tok-fn{color:#dcdcaa}:host ::ng-deep .code-block code .tok-prop{color:#9cdcfe}:host ::ng-deep .code-block code .tok-op{color:#d4d4d4}:host ::ng-deep .code-block.lang-html code .tok-tag{color:#569cd6}:host ::ng-deep .code-block.lang-html code .tok-attr{color:#9cdcfe}:host ::ng-deep .code-block.lang-html code .tok-string{color:#ce9178}:host ::ng-deep .code-block.lang-json code .tok-key{color:#9cdcfe}:host ::ng-deep .code-block.lang-json code .tok-string{color:#ce9178}:host ::ng-deep .code-block.lang-json code .tok-keyword{color:#569cd6}:host ::ng-deep .code-block.lang-json code .tok-number{color:#b5cea8}:host ::ng-deep .code-block.lang-ts code .tok-keyword{color:#569cd6}:host ::ng-deep .code-block.lang-ts code .tok-type{color:#4ec9b0}:host ::ng-deep .code-block.lang-ts code .tok-fn{color:#dcdcaa}:host ::ng-deep .code-block.lang-ts code .tok-prop{color:#9cdcfe}:host ::ng-deep .code-block.lang-ts code .tok-string{color:#ce9178}:host ::ng-deep .code-block.lang-ts code .tok-comment{color:#6a9955}:host ::ng-deep .code-block.lang-ts code .tok-number{color:#b5cea8}:host ::ng-deep .code-block.lang-cs code .tok-keyword{color:#569cd6}:host ::ng-deep .code-block.lang-cs code .tok-fn{color:#dcdcaa}:host ::ng-deep .code-block.lang-cs code .tok-prop{color:#9cdcfe}:host ::ng-deep .code-block.lang-cs code .tok-string{color:#ce9178}:host ::ng-deep .code-block.lang-cs code .tok-comment{color:#6a9955}:host ::ng-deep .code-block.lang-cs code .tok-number{color:#b5cea8}.screenshots .shots-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px;align-items:start}.screenshots figure{margin:0;display:flex;flex-direction:column;gap:8px}.screenshots img{width:100%;border-radius:12px;border:1px solid var(--border)}:host ::ng-deep .screenshots .p-image,:host ::ng-deep .screenshots .p-image img{width:100%;display:block}:host ::ng-deep .screenshots .p-image{aspect-ratio:16/9;overflow:hidden;border-radius:12px;border:1px solid var(--border);background:color-mix(in srgb,var(--panel) 90%,transparent)}:host ::ng-deep .screenshots .p-image img{width:100%;height:100%;object-fit:contain;object-position:center;border:0}:host ::ng-deep .screenshots .p-image .p-image-preview-mask,:host ::ng-deep .screenshots .p-image .p-image-mask{inset:0;width:100%;height:100%}.missing{border:1px dashed var(--border);border-radius:12px;padding:36px 10px;text-align:center;color:var(--muted)}:host ::ng-deep .p-image-mask,:host ::ng-deep .p-image-preview-mask{background:none!important;backdrop-filter:none!important;-webkit-backdrop-filter:none!important}:host ::ng-deep .p-image-toolbar{background:#0c1220!important;backdrop-filter:none!important;-webkit-backdrop-filter:none!important;filter:none!important;border:1px solid rgba(255,255,255,.14)!important;box-shadow:0 8px 24px #00000059!important}:host ::ng-deep .p-image-action{color:#eaf1ff!important;opacity:1!important;text-shadow:none!important}:host ::ng-deep .p-image-preview{background:#7eb2ff2e!important}::ng-deep .p-image-mask.p-component-overlay,::ng-deep .p-image-preview-mask.p-component-overlay{background:#0c121efa!important;backdrop-filter:none!important;-webkit-backdrop-filter:none!important}:host ::ng-deep .screenshots .p-image .p-image-mask,:host ::ng-deep .screenshots .p-image .p-image-preview-indicator{background:#0c121e42!important}.themes-catalog{margin-top:14px;padding:6px 0 16px;border-top:1px dashed var(--border)}.themes-catalog-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:10px}.themes-catalog-item{display:inline-flex;align-items:center;gap:.55rem;min-height:2.25rem;padding:.45rem .65rem;border:1px solid var(--border);border-radius:10px;background:color-mix(in srgb,var(--panel) 92%,transparent)}.theme-dot{width:.8rem;height:.8rem;border-radius:999px;border:1px solid color-mix(in srgb,var(--text) 25%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,#ffffff 55%,transparent) inset;flex:0 0 auto}.toc{position:sticky;top:20px;max-height:calc(100vh - 120px);overflow-y:auto;background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:14px}.toc h4{margin:0 0 8px}.toc ul{margin:0;padding-left:18px;list-style-position:outside}.toc a{display:block;color:var(--text);text-decoration:none;line-height:1.25;overflow-wrap:anywhere;word-break:break-word}.toc li{margin:0 0 6px}.toc li:last-child{margin-bottom:0}@media(max-width:1360px)and (min-width:1101px){.body-grid{grid-template-columns:minmax(0,1fr) minmax(280px,320px)}}@media(max-width:1100px){.fw-docs{grid-template-columns:1fr;height:auto;overflow:visible}.sidebar{height:auto;position:static;border-right:0;border-bottom:1px solid var(--border)}.content{height:auto;overflow:visible}.body-grid{grid-template-columns:1fr}.toc{position:static}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i13.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i10.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: ImageModule }, { kind: "component", type: i1$3.Image, selector: "p-image", inputs: ["imageClass", "imageStyle", "styleClass", "src", "srcSet", "sizes", "previewImageSrc", "previewImageSrcSet", "previewImageSizes", "alt", "width", "height", "loading", "preview", "showTransitionOptions", "hideTransitionOptions", "modalEnterAnimation", "modalLeaveAnimation", "appendTo", "maskMotionOptions", "motionOptions"], outputs: ["onShow", "onHide", "onImageError"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
|
|
25924
26395
|
}
|
|
25925
26396
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FrameworkDocsComponent, decorators: [{
|
|
25926
26397
|
type: Component,
|
|
@@ -25931,4 +26402,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
25931
26402
|
}] } });
|
|
25932
26403
|
|
|
25933
26404
|
export { FrameworkDocsComponent };
|
|
25934
|
-
//# sourceMappingURL=wuic-framework-lib-framework-docs.component-
|
|
26405
|
+
//# sourceMappingURL=wuic-framework-lib-framework-docs.component-BGcJ7k1X.mjs.map
|