wuic-framework-lib 1.7.7 → 1.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{wuic-framework-lib-chart-list.component-KW1ENbNz.mjs → wuic-framework-lib-chart-list.component-Bz93lddX.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-code-editor.component-DB-794Vs.mjs → wuic-framework-lib-code-editor.component-CerH_Ptt.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-designer.component-D0b8yopf.mjs → wuic-framework-lib-designer.component-D-TDt9Yp.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-first-run-wizard.component-CAvnMJlk.mjs → wuic-framework-lib-first-run-wizard.component-DTd6aeZQ.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-framework-docs.component-Bi5Pm3vl.mjs → wuic-framework-lib-framework-docs.component-B2AdE4N0.mjs} +194 -104
- package/fesm2022/{wuic-framework-lib-pivot-builder.component-LPpFvPZE.mjs → wuic-framework-lib-pivot-builder.component-B0Y_UHcw.mjs} +16 -16
- package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-DQZcIZ1-.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-RLZTS8VK.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-report-designer.component-wlE9GKxY.mjs → wuic-framework-lib-report-designer.component-DMHg11S1.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-report-scaffold-dialog.component-CZGb5LoN.mjs → wuic-framework-lib-report-scaffold-dialog.component-Dz-0CKFf.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-report-viewer.component-Dy_YSPNc.mjs → wuic-framework-lib-report-viewer.component-DcjeKFl3.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-scene3d-designer.component-Bn6YNlOi.mjs → wuic-framework-lib-scene3d-designer.component-DkFSmqjd.mjs} +5 -5
- package/fesm2022/{wuic-framework-lib-scene3d-light-baker-gpu-B0nVJ53g.mjs → wuic-framework-lib-scene3d-light-baker-gpu-CDOGvkje.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-scene3d-viewer.component-BFQClLb6.mjs → wuic-framework-lib-scene3d-viewer.component-CXzEo7SW.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-scheduler-list.component-BcgxT67p.mjs → wuic-framework-lib-scheduler-list.component-BWwp_Y2n.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-CxLrlB-k.mjs → wuic-framework-lib-spreadsheet-list-sf.component-C7XVqrk-.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-timeline-list.component-CugxjeYa.mjs → wuic-framework-lib-timeline-list.component-BPCARDTv.mjs} +4 -4
- package/fesm2022/{wuic-framework-lib-workflow-designer.component-CrUsFuXR.mjs → wuic-framework-lib-workflow-designer.component-BOTf2H42.mjs} +14 -14
- package/fesm2022/{wuic-framework-lib-wuic-framework-lib-DfDsWPDO.mjs → wuic-framework-lib-wuic-framework-lib-CNl2-wAT.mjs} +11422 -11134
- package/fesm2022/wuic-framework-lib.mjs +1 -1
- package/package.json +1 -1
- package/types/wuic-framework-lib.d.ts +143 -3
|
@@ -16,12 +16,12 @@ import * as i1$3 from 'primeng/image';
|
|
|
16
16
|
import { ImageModule } from 'primeng/image';
|
|
17
17
|
import * as i8$1 from '@ngx-translate/core';
|
|
18
18
|
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
19
|
-
import { v as getThemeOptions, T as TranslationManagerService, U as UserInfoService } from './wuic-framework-lib-wuic-framework-lib-
|
|
19
|
+
import { v as getThemeOptions, T as TranslationManagerService, U as UserInfoService } from './wuic-framework-lib-wuic-framework-lib-CNl2-wAT.mjs';
|
|
20
20
|
import * as i1 from '@angular/router';
|
|
21
21
|
|
|
22
22
|
const frameworkDocsContent = {
|
|
23
23
|
"version": "1.0.0",
|
|
24
|
-
"generatedAt": "2026-09-
|
|
24
|
+
"generatedAt": "2026-09-17T18:27:06.604Z",
|
|
25
25
|
"groups": [
|
|
26
26
|
{
|
|
27
27
|
"id": "primi-passi",
|
|
@@ -1147,13 +1147,17 @@ const frameworkDocsContent = {
|
|
|
1147
1147
|
{
|
|
1148
1148
|
"id": "sec_4",
|
|
1149
1149
|
"title": "Quick Start — primo componente"
|
|
1150
|
+
},
|
|
1151
|
+
{
|
|
1152
|
+
"id": "sec_5",
|
|
1153
|
+
"title": "Le prime liste mostrano 20 record: e' la modalita' Trial"
|
|
1150
1154
|
}
|
|
1151
1155
|
],
|
|
1152
1156
|
"sections": [
|
|
1153
1157
|
{
|
|
1154
1158
|
"id": "overview",
|
|
1155
1159
|
"title": "Overview",
|
|
1156
|
-
"html": "<h1>Panoramica Framework</h1><p>WUIC Framework e' una piattaforma metadata-driven per creare interfacce business in modo rapido e coerente.</p><h2>Cosa include</h2><ul><li>DataSource e DataRepeater per orchestrare dati e rendering.</li><li>Archetypes visuali (list, map, scheduler, chart, carousel).</li><li>Designer runtime per dashboard e template dinamici.</li><li>Workflow designer/runner per processi operativi.</li><li>RAG Chatbot per interrogare la codebase in linguaggio naturale.</li><li>Multi-DBMS: SQL Server, MySQL, PostgreSQL e Oracle tramite provider drop-in (<code>dbms</code>: <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Avvio ambiente dev</h2><p>Lo stack WUIC e' composto da piu' servizi. Avviali nell'ordine indicato.</p><h3>Prerequisiti</h3><table><thead><tr><th>Cosa</th><th>Verifica</th><th>Note</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle per IIS in produzione</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>La 22 e' la versione con cui il pacchetto e' testato; con npm 10.9.x installa solo grazie al <code>package-lock.json</code> incluso</td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>La PowerShell preinstallata su Windows basta: <code>rename-project.ps1</code> e gli script <code>llm-workspace/</code> girano anche su 5.1. PowerShell 7 e' consigliata, non richiesta</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>Se manca, <strong>il one-liner lo installa da se'</strong> (SQL Server Express, o il motore scelto con <code>-Dbms</code>); su Windows Server no, vedi il riquadro sotto. 2019 basta per i pacchetti senza <code>.bak</code>; il tutorial <code>.bak</code> e' un backup di SQL Server 2022 e richiede <strong>2022 o superiore</strong></td></tr><tr><td>Linux (installer <code>install.sh</code>)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 o 24.04 LTS</strong> (24.04 raccomandata): sono le uniche Ubuntu su cui Microsoft supporta SQL Server, la <strong>26.04 non e' supportata</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Stessa raccomandazione con MySQL, PostgreSQL e Oracle, perche' l'installer e' provato su quelle</td></tr><tr><td>GPU NVIDIA (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Opzionale: accelera il RAG Chatbot (senza GPU gira su CPU)</td></tr></tbody></table><p>> <strong>Su Windows Server il database va installato prima.</strong> Il one-liner si procura i componenti</p><p>> mancanti tramite <code>winget</code>, che su Windows Server non e' presente: senza un'istanza gia'</p><p>> raggiungibile l'installazione si ferma con `No SQL Server instance reachable and winget is</p><p>> missing`. Installa quindi il motore prima di lanciare la riga - per SQL Server serve la</p><p>> <strong>2019 o superiore</strong> (la Express basta; <strong>2022 o superiore</strong> per il tutorial <code>.bak</code>), e una</p><p>> 2017 non viene accettata. Se l'istanza non e' quella predefinita, passala con</p><p>> <code>-SqlServer 'localhost\\NOMEISTANZA'</code>. Vale per tutti i motori, non solo SQL Server.</p><h3>1. Scarica il template di progetto</h3><p>Su Windows fai tutto con una riga di PowerShell: scarica il pacchetto, verifica .NET SDK 10 e Node.js 22</p><p>(installando cio' che manca), esegue <code>dotnet restore</code> e <code>npm install</code>, e installa</p><p>l'estensione WUIC Assistant in VS Code.</p><p>Snippet 1:</p><p>Opzioni utili sulla stessa riga: <code>-Dbms mysql</code> (oppure <code>postgres</code>, <code>oracle</code>) per un motore</p><p>diverso da SQL Server — che l'installer installa e configura da se' — e <code>-WithTutorial</code> per</p><p>scaricare anche il database di esempio.</p><p>Quando ha finito, l'ultima schermata e' gia' l'elenco delle cose da fare:</p><p>Snippet 2:</p><p>La stringa di connessione e' gia' pronta: al primo avvio il wizard non chiede altro. Con</p><p><code>-Dbms mysql</code> o <code>-Dbms postgres</code> la riga cambia di conseguenza e porta dentro di se' utente e</p><p>password, perche' la password del superutente <strong>la genera l'installer</strong>; la stessa password</p><p>viene salvata in <code>wuic-secrets.json</code>, accanto all'installazione, ed e' l'unico posto in cui</p><p>resta scritta.</p><p>Il percorso manuale resta valido e funziona su qualunque sistema:</p><p>Parti dal pacchetto <code>WuicTest-src-*.zip</code> (link nella sezione <strong>Download</strong> del sito).</p><p>Estrailo in una cartella di lavoro, es. <code>C:\\dev\\WuicTest</code> (i file vanno direttamente nella root,</p><p>NON dentro una sottocartella <code>src/</code>). Il pacchetto contiene:</p><ul><li><code>WuicTest.csproj</code> → progetto host con <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → app Angular con <code>package.json</code> che referenzia <code>wuic-framework-lib</code> da npm registry</li><li><code>appsettings.json</code> preconfigurato in modalita' <code>firstRun = "true"</code> con placeholder <code>__SET_*__</code></li><li><code>appsettings-samples/</code> → 6 template pronti (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>Non serve clonare il repository del framework</strong>: <code>WuicCore</code> arriva come pacchetto NuGet da</p><p>> <code>nuget.org</code> e <code>wuic-framework-lib</code> come pacchetto npm da npm registry. Il sorgente del framework</p><p>> serve solo se vuoi modificarlo — tipicamente non e' il tuo caso.</p><p>> <strong>npm 10.9.x e i pacchetti precedenti alla 1.7.1</strong>: quei pacchetti non contengono</p><p>> <code>package-lock.json</code>, e senza lock npm 10.9.x (quello che installa Node 22 LTS) si ferma con</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> mentre risolve i peer. Scarica il lock</p><p>> pubblicato accanto alla release — <code>https://wuic-framework.com/downloads/locks/<nome-zip>.package-lock.json</code></p><p>> — mettilo in <code>wwwroot/</code> e rilancia <code>npm install</code>. Il one-liner <code>-Src</code> lo fa da solo.</p><h3>2. Database</h3><p>Serve un'istanza del motore raggiungibile. <strong>Con il one-liner non devi fare niente</strong>: la</p><p>installa e la configura lui, e la stringa di connessione da incollare nel wizard e' l'ultima</p><p>cosa che stampa. Nel percorso manuale l'istanza deve essere gia' presente.</p><p>Connessioni in <code>appsettings.json</code>:</p><ul><li><code>MetaDataSQLConnection</code> — DB metadata (menu, tabelle, colonne, board, utenti)</li><li><code>DataSQLConnection</code> — DB dati applicativi</li></ul><p>Se e' la prima installazione (<code>AppSettings.firstRun = "true"</code> nel template),</p><p>il wizard di scaffolding al primo avvio crea lo schema metadata e popola il DB dati.</p><p>Vedi la pagina <em>Scaffolding iniziale</em> per il flusso guidato.</p><h3>3. Backend (.NET)</h3><p>Dalla root della cartella estratta (es. <code>C:\\dev\\WuicTest</code>):</p><p>Snippet 3:</p><p>Il backend espone le API su <code>http://localhost:5000</code>.</p><h3>4. Frontend (Angular)</h3><p>In una seconda shell, dalla sottocartella <code>wwwroot/</code>:</p><p>Snippet 4:</p><p>Il frontend e' disponibile su <code>http://localhost:4200</code>.</p><p>Login di default (post-firstRun): <code>admin</code> / <code>admin</code>.</p><h3>5. RAG Chatbot (opzionale)</h3><p>Il RAG Chatbot (<code>Amministrazione > RAG Chat</code>) gira <strong>dentro il backend .NET</strong>:</p><p>il motore di retrieval (<code>rag-engine/WuicRagEngine.dll</code>, ONNX Runtime</p><p>in-process) viene caricato dal backend quando <code>AppSettings.rag-use-dotnet-engine</code></p><p>e' <code>"true"</code> (default nei pacchetti di release). **Niente Python, niente venv,</p><p>nessun server separato da avviare.**</p><p>Alla <strong>prima</strong> apertura del chatbot (o a fine first-run) il backend scarica da</p><p>solo modelli ONNX (<code>bge-m3</code> + reranker), tokenizer e indice (~4,5 GB) da</p><p><code>rag-engine-models-url</code> (default <code>https://wuic-framework.com/rag-models</code>) in</p><p><code>rag-engine/artifacts/</code>. Serve una connessione internet una sola volta; il</p><p>download gira in background (1-5 min) e a inizio/fine download arriva una</p><p>notifica in-app. Nel frattempo il componente mostra lo stato <strong>RAG offline</strong> e</p><p>il resto dell'applicazione funziona normalmente.</p><p>Chiavi <code>AppSettings</code> rilevanti (tutte con default gia' pronti):</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — attiva l'engine .NET (<code>false</code> = fallback Python, vedi sotto)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code>: con GPU NVIDIA (CUDA 12.x + cuDNN 9) ~1 s/query, su CPU ~15-25 s/query</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = sorgenti framework solo come firma; <code>internal</code> = indice integrale</li><li><code>rag-engine-models-url</code> — sorgente del download al primo avvio</li><li><code>rag-engine-cuda-path</code> = (vuoto) — cartella delle DLL CUDA/cuDNN se non installate a livello di sistema</li></ul><p>Per la chat con LLM valorizza <code>rag-llm-provider</code> + <code>rag-llm-api-key</code> (Claude</p><p>via Anthropic, oppure un modello locale via Ollama con <code>rag-llm-base-url</code>).</p><p>Senza provider funziona solo la modalita' retrieval (ricerca snippet).</p><p>Dettaglio delle chiavi nella pagina <em>AppSettings</em>.</p><p>> Lo stack storico Python (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> su</p><p>> <code>127.0.0.1:8765</code>) resta utilizzabile solo come fallback con</p><p>> <code>rag-use-dotnet-engine = "false"</code> e non e' incluso nei pacchetti di release.</p><h2>Riepilogo servizi</h2><table><thead><tr><th>Servizio</th><th>Porta</th><th>Obbligatorio</th><th>Comando rapido</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>si</td><td>(servizio Windows)</td></tr><tr><td>Backend .NET</td><td>5000</td><td>si</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Frontend Angular</td><td>4200</td><td>si</td><td><code>npm run serve:dev</code></td></tr><tr><td>Engine RAG .NET (ONNX)</td><td>in-process</td><td>no</td><td>caricato dal backend alla prima chat</td></tr></tbody></table><h2>Quick Start — primo componente</h2><p>1. Configura endpoint AsmxProxy.</p><p>2. Definisci route metadata e colonne.</p><p>3. Monta <code>wuic-data-source</code> + <code>wuic-data-repeater</code>.</p><p>Snippet 5:</p>",
|
|
1160
|
+
"html": "<h1>Panoramica Framework</h1><p>WUIC Framework e' una piattaforma metadata-driven per creare interfacce business in modo rapido e coerente.</p><h2>Cosa include</h2><ul><li>DataSource e DataRepeater per orchestrare dati e rendering.</li><li>Archetypes visuali (list, map, scheduler, chart, carousel).</li><li>Designer runtime per dashboard e template dinamici.</li><li>Workflow designer/runner per processi operativi.</li><li>RAG Chatbot per interrogare la codebase in linguaggio naturale.</li><li>Multi-DBMS: SQL Server, MySQL, PostgreSQL e Oracle tramite provider drop-in (<code>dbms</code>: <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Avvio ambiente dev</h2><p>Lo stack WUIC e' composto da piu' servizi. Avviali nell'ordine indicato.</p><h3>Prerequisiti</h3><table><thead><tr><th>Cosa</th><th>Verifica</th><th>Note</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle per IIS in produzione</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>La 22 e' la versione con cui il pacchetto e' testato; con npm 10.9.x installa solo grazie al <code>package-lock.json</code> incluso</td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>La PowerShell preinstallata su Windows basta: <code>rename-project.ps1</code> e gli script <code>llm-workspace/</code> girano anche su 5.1. PowerShell 7 e' consigliata, non richiesta</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>Se manca, <strong>il one-liner lo installa da se'</strong> (SQL Server Express, o il motore scelto con <code>-Dbms</code>); su Windows Server no, vedi il riquadro sotto. 2019 basta per i pacchetti senza <code>.bak</code>; il tutorial <code>.bak</code> e' un backup di SQL Server 2022 e richiede <strong>2022 o superiore</strong></td></tr><tr><td>Linux (installer <code>install.sh</code>)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 o 24.04 LTS</strong> (24.04 raccomandata): sono le uniche Ubuntu su cui Microsoft supporta SQL Server, la <strong>26.04 non e' supportata</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Stessa raccomandazione con MySQL, PostgreSQL e Oracle, perche' l'installer e' provato su quelle</td></tr><tr><td>GPU NVIDIA (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Opzionale: accelera il RAG Chatbot (senza GPU gira su CPU)</td></tr></tbody></table><p>> <strong>Su Windows Server il database va installato prima.</strong> Il one-liner si procura i componenti</p><p>> mancanti tramite <code>winget</code>, che su Windows Server non e' presente: senza un'istanza gia'</p><p>> raggiungibile l'installazione si ferma con `No SQL Server instance reachable and winget is</p><p>> missing`. Installa quindi il motore prima di lanciare la riga - per SQL Server serve la</p><p>> <strong>2019 o superiore</strong> (la Express basta; <strong>2022 o superiore</strong> per il tutorial <code>.bak</code>), e una</p><p>> 2017 non viene accettata. Se l'istanza non e' quella predefinita, passala con</p><p>> <code>-SqlServer 'localhost\\NOMEISTANZA'</code>. Vale per tutti i motori, non solo SQL Server.</p><h3>1. Scarica il template di progetto</h3><p>Su Windows fai tutto con una riga di PowerShell: scarica il pacchetto, verifica .NET SDK 10 e Node.js 22</p><p>(installando cio' che manca), esegue <code>dotnet restore</code> e <code>npm install</code>, e installa</p><p>l'estensione WUIC Assistant in VS Code.</p><p>Snippet 1:</p><p>Opzioni utili sulla stessa riga: <code>-Dbms mysql</code> (oppure <code>postgres</code>, <code>oracle</code>) per un motore</p><p>diverso da SQL Server — che l'installer installa e configura da se' — e <code>-WithTutorial</code> per</p><p>scaricare anche il database di esempio.</p><p>Quando ha finito, l'ultima schermata e' gia' l'elenco delle cose da fare:</p><p>Snippet 2:</p><p>La stringa di connessione e' gia' pronta: al primo avvio il wizard non chiede altro. Con</p><p><code>-Dbms mysql</code> o <code>-Dbms postgres</code> la riga cambia di conseguenza e porta dentro di se' utente e</p><p>password, perche' la password del superutente <strong>la genera l'installer</strong>; la stessa password</p><p>viene salvata in <code>wuic-secrets.json</code>, accanto all'installazione, ed e' l'unico posto in cui</p><p>resta scritta.</p><p>Il percorso manuale resta valido e funziona su qualunque sistema:</p><p>Parti dal pacchetto <code>WuicTest-src-*.zip</code> (link nella sezione <strong>Download</strong> del sito).</p><p>Estrailo in una cartella di lavoro, es. <code>C:\\dev\\WuicTest</code> (i file vanno direttamente nella root,</p><p>NON dentro una sottocartella <code>src/</code>). Il pacchetto contiene:</p><ul><li><code>WuicTest.csproj</code> → progetto host con <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → app Angular con <code>package.json</code> che referenzia <code>wuic-framework-lib</code> da npm registry</li><li><code>appsettings.json</code> preconfigurato in modalita' <code>firstRun = "true"</code> con placeholder <code>__SET_*__</code></li><li><code>appsettings-samples/</code> → 6 template pronti (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>Non serve clonare il repository del framework</strong>: <code>WuicCore</code> arriva come pacchetto NuGet da</p><p>> <code>nuget.org</code> e <code>wuic-framework-lib</code> come pacchetto npm da npm registry. Il sorgente del framework</p><p>> serve solo se vuoi modificarlo — tipicamente non e' il tuo caso.</p><p>> <strong>npm 10.9.x e i pacchetti precedenti alla 1.7.1</strong>: quei pacchetti non contengono</p><p>> <code>package-lock.json</code>, e senza lock npm 10.9.x (quello che installa Node 22 LTS) si ferma con</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> mentre risolve i peer. Scarica il lock</p><p>> pubblicato accanto alla release — <code>https://wuic-framework.com/downloads/locks/<nome-zip>.package-lock.json</code></p><p>> — mettilo in <code>wwwroot/</code> e rilancia <code>npm install</code>. Il one-liner <code>-Src</code> lo fa da solo.</p><h3>2. Database</h3><p>Serve un'istanza del motore raggiungibile. <strong>Con il one-liner non devi fare niente</strong>: la</p><p>installa e la configura lui, e la stringa di connessione da incollare nel wizard e' l'ultima</p><p>cosa che stampa. Nel percorso manuale l'istanza deve essere gia' presente.</p><p>Connessioni in <code>appsettings.json</code>:</p><ul><li><code>MetaDataSQLConnection</code> — DB metadata (menu, tabelle, colonne, board, utenti)</li><li><code>DataSQLConnection</code> — DB dati applicativi</li></ul><p>Se e' la prima installazione (<code>AppSettings.firstRun = "true"</code> nel template),</p><p>il wizard di scaffolding al primo avvio crea lo schema metadata e popola il DB dati.</p><p>Vedi la pagina <em>Scaffolding iniziale</em> per il flusso guidato.</p><p>#### Cosa chiede il wizard di primo avvio</p><p>Al primo avvio l'applicazione non mostra il login ma la pagina **Configurazione iniziale</p><p>progetto**. Si compila una volta sola: al termine <code>firstRun</code> passa a <code>false</code> e la pagina non</p><p>ricompare piu'.</p><ul><li><strong>Modalita' setup</strong> — due voci: <strong>DB esistente</strong>, che registra un database gia' tuo, e</li></ul><p> <strong>Tutorial WideWorldImporters</strong>, che installa il database di esempio. La seconda compare</p><p> solo se il pacchetto porta con se' il tutorial (<code>tutorialAvailable</code>): nei pacchetti senza</p><p> tutorial la tendina non c'e' affatto e la modalita' e' "DB esistente".</p><ul><li><strong>DBMS</strong> — il motore. Cambiandolo, la stringa di connessione sotto viene riscritta nella</li></ul><p> forma del provider scelto.</p><ul><li><strong>DataSQLConnection</strong> — la stringa verso il DB dati, ed e' il campo da cui dipende tutto il</li></ul><p> resto: finche' non premi <strong>Test connessione e carica DB</strong> l'elenco dei database resta</p><p> disabilitato. Il test verifica le credenziali, elenca i database del server e, su SQL</p><p> Server, corregge da se' i parametri dei certificati</p><p> (<code>Encrypt=False;TrustServerCertificate=True</code>) dicendotelo. <code>Integrated Security</code> vale solo</p><p> su SQL Server: sugli altri motori servono utente e password.</p><ul><li><strong>Database dati</strong> e <strong>Nome DB metadati</strong> — il primo si sceglie dall'elenco caricato dal</li></ul><p> test (in modalita' tutorial e' un campo libero, default <code>WideWorldImporters</code>); il secondo e'</p><p> il nome del database metadati da creare (default <code>metadataDB</code>, <code>MetadataCRM</code> in modalita'</p><p> tutorial). Se quel database esiste gia', il wizard chiede conferma prima di ricrearlo.</p><ul><li><strong>Esegui scaffold automatico delle tabelle</strong> (solo "DB esistente") — popola</li></ul><p> <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> da tutte le tabelle del database scelto. E' la</p><p> voce che allunga di piu' il provisioning su database con molte tabelle.</p><ul><li><strong>Utente admin iniziale</strong> — username (default <code>admin</code>), password (minimo 4 caratteri) e</li></ul><p> lingua. Non esiste una password predefinita: quella scritta qui e' l'unica con cui entrerai</p><p> al primo login. La lingua scelta viene applicata all'utente admin e a questa pagina stessa.</p><ul><li><strong>RAG Chatbot</strong> — solo la chiave Anthropic, opzionale. Niente da installare: vedi il punto 5.</li></ul><p>Premuto <strong>Conferma e genera metadataDB</strong> il provisioning va avanti da solo, con una barra e il</p><p>numero di batch elaborati. Quanto dura, misurato sulle installazioni di prova: <strong>30 s - 2 min</strong></p><p>in modalita' tutorial, <strong>1-4 min</strong> su un database esistente con lo scaffold automatico attivo.</p><p>Finito, la pagina lascia il posto al form di login.</p><h3>3. Backend (.NET)</h3><p>Dalla root della cartella estratta (es. <code>C:\\dev\\WuicTest</code>):</p><p>Snippet 3:</p><p>Il backend espone le API su <code>http://localhost:5000</code>.</p><h3>4. Frontend (Angular)</h3><p>In una seconda shell, dalla sottocartella <code>wwwroot/</code>:</p><p>Snippet 4:</p><p>Il frontend e' disponibile su <code>http://localhost:4200</code>.</p><p>Le credenziali sono quelle dell'utente admin scelto nel wizard di primo avvio: lo username e'</p><p><code>admin</code> se non l'hai cambiato, la password e' quella che hai scritto tu (non esiste una</p><p>password predefinita).</p><h3>5. RAG Chatbot (opzionale)</h3><p>Il RAG Chatbot (<code>Amministrazione > RAG Chat</code>) gira <strong>dentro il backend .NET</strong>:</p><p>il motore di retrieval (<code>rag-engine/WuicRagEngine.dll</code>, ONNX Runtime</p><p>in-process) viene caricato dal backend quando <code>AppSettings.rag-use-dotnet-engine</code></p><p>e' <code>"true"</code> (default nei pacchetti di release). **Niente Python, niente venv,</p><p>nessun server separato da avviare.**</p><p>Alla <strong>prima</strong> apertura del chatbot (o a fine first-run) il backend scarica da</p><p>solo modelli ONNX (<code>bge-m3</code> + reranker), tokenizer e indice (~4,5 GB) da</p><p><code>rag-engine-models-url</code> (default <code>https://wuic-framework.com/rag-models</code>) in</p><p><code>rag-engine/artifacts/</code>. Serve una connessione internet una sola volta; il</p><p>download gira in background (1-5 min) e a inizio/fine download arriva una</p><p>notifica in-app. Nel frattempo il componente mostra lo stato <strong>RAG offline</strong> e</p><p>il resto dell'applicazione funziona normalmente.</p><p>Chiavi <code>AppSettings</code> rilevanti (tutte con default gia' pronti):</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — attiva l'engine .NET (<code>false</code> = fallback Python, vedi sotto)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code>: con GPU NVIDIA (CUDA 12.x + cuDNN 9) ~1 s/query, su CPU ~15-25 s/query</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = sorgenti framework solo come firma; <code>internal</code> = indice integrale</li><li><code>rag-engine-models-url</code> — sorgente del download al primo avvio</li><li><code>rag-engine-cuda-path</code> = (vuoto) — cartella delle DLL CUDA/cuDNN se non installate a livello di sistema</li></ul><p>Per la chat con LLM valorizza <code>rag-llm-provider</code> + <code>rag-llm-api-key</code> (Claude</p><p>via Anthropic, oppure un modello locale via Ollama con <code>rag-llm-base-url</code>).</p><p>Senza provider funziona solo la modalita' retrieval (ricerca snippet).</p><p>Dettaglio delle chiavi nella pagina <em>AppSettings</em>.</p><p>> Lo stack storico Python (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> su</p><p>> <code>127.0.0.1:8765</code>) resta utilizzabile solo come fallback con</p><p>> <code>rag-use-dotnet-engine = "false"</code> e non e' incluso nei pacchetti di release.</p><h2>Riepilogo servizi</h2><table><thead><tr><th>Servizio</th><th>Porta</th><th>Obbligatorio</th><th>Comando rapido</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>si</td><td>(servizio Windows)</td></tr><tr><td>Backend .NET</td><td>5000</td><td>si</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Frontend Angular</td><td>4200</td><td>si</td><td><code>npm run serve:dev</code></td></tr><tr><td>Engine RAG .NET (ONNX)</td><td>in-process</td><td>no</td><td>caricato dal backend alla prima chat</td></tr></tbody></table><h2>Quick Start — primo componente</h2><p>1. Configura endpoint AsmxProxy.</p><p>2. Definisci route metadata e colonne.</p><p>3. Monta <code>wuic-data-source</code> + <code>wuic-data-repeater</code>.</p><p>Snippet 5:</p><h2>Le prime liste mostrano 20 record: e' la modalita' Trial</h2><p>Un'installazione appena fatta gira <strong>senza licenza</strong>, cioe' in modalita' Trial, e in quella</p><p>modalita' <strong>ogni query e' limitata a 20 record</strong>. Non e' un errore ne' un limite del database:</p><p>una lista che dichiara "20 di 20" su una tabella con migliaia di righe sta semplicemente</p><p>girando senza licenza.</p><p>Come confermarlo in un secondo:</p><p>Snippet 6:</p><p><code>licenseValid: false</code> conferma la Trial, e <code>licenseReason</code> dice perche' (<code>invalid_signature</code>,</p><p><code>license_expired</code>, <code>machine_fingerprint_not_authorized</code>, ...).</p><p>Come uscirne: si incolla la licenza da <strong>Amministrazione > Editor AppSettings</strong>, scheda Licensing,</p><p>ed e' valida subito — non serve riavviare il backend. I dettagli, compresi i limiti che la</p><p>Trial impone oltre al numero di record, stanno nella pagina <a href=\"licensing.md\">Licensing</a>.</p>",
|
|
1157
1161
|
"codeSamples": [
|
|
1158
1162
|
{
|
|
1159
1163
|
"id": "code_1",
|
|
@@ -1184,6 +1188,12 @@ const frameworkDocsContent = {
|
|
|
1184
1188
|
"title": "Snippet 5",
|
|
1185
1189
|
"language": "html",
|
|
1186
1190
|
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\n<wuic-data-repeater [hardcodedAction]=\"'list'\"></wuic-data-repeater>"
|
|
1191
|
+
},
|
|
1192
|
+
{
|
|
1193
|
+
"id": "code_6",
|
|
1194
|
+
"title": "Snippet 6",
|
|
1195
|
+
"language": "bash",
|
|
1196
|
+
"code": "curl -s http://localhost:5000/api/Meta/LicenseStatus"
|
|
1187
1197
|
}
|
|
1188
1198
|
]
|
|
1189
1199
|
}
|
|
@@ -1218,18 +1228,22 @@ const frameworkDocsContent = {
|
|
|
1218
1228
|
"toc": [
|
|
1219
1229
|
{
|
|
1220
1230
|
"id": "sec_1",
|
|
1221
|
-
"title": "
|
|
1231
|
+
"title": "Con il pacchetto tutorial non c'e' niente da scaffoldare"
|
|
1222
1232
|
},
|
|
1223
1233
|
{
|
|
1224
1234
|
"id": "sec_2",
|
|
1225
|
-
"title": "
|
|
1235
|
+
"title": "Quando usarlo"
|
|
1226
1236
|
},
|
|
1227
1237
|
{
|
|
1228
1238
|
"id": "sec_3",
|
|
1229
|
-
"title": "
|
|
1239
|
+
"title": "Comportamento con firstRun=true"
|
|
1230
1240
|
},
|
|
1231
1241
|
{
|
|
1232
1242
|
"id": "sec_4",
|
|
1243
|
+
"title": "Operazioni tipiche"
|
|
1244
|
+
},
|
|
1245
|
+
{
|
|
1246
|
+
"id": "sec_5",
|
|
1233
1247
|
"title": "Dopo il provisioning"
|
|
1234
1248
|
}
|
|
1235
1249
|
],
|
|
@@ -1237,7 +1251,7 @@ const frameworkDocsContent = {
|
|
|
1237
1251
|
{
|
|
1238
1252
|
"id": "overview",
|
|
1239
1253
|
"title": "Overview",
|
|
1240
|
-
"html": "<h1>Scaffolding iniziale</h1><p>Questa pagina descrive il bootstrap iniziale quando <code>AppSettings.firstRun = true</code>.</p><h2>Quando usarlo</h2><ul><li>Nuova installazione (DB metadata/dati non ancora pronti).</li><li>Ambiente locale da riallineare con setup iniziale.</li><li>Primo avvio dopo deploy dove vuoi forzare la procedura guidata di provisioning.</li></ul><h2>Comportamento con firstRun=true</h2><ul><li>L'endpoint <code>GET /api/Meta/FirstRunStatus</code> espone <code>firstRun: true</code>.</li><li>In login compare il flusso di primo avvio (es. azione <code>Aggiorna</code> nello screen).</li><li>Il setup applica le configurazioni base (connessioni, impostazioni runtime, bootstrap metadata).</li></ul><h2>Operazioni tipiche</h2><ul><li>Verifica <code>AppSettings.firstRun</code> a <code>true</code> in <code>appsettings.{Environment}.json</code> dell'host che stai eseguendo.</li><li>Avvia applicazione e completa la procedura di scaffolding iniziale da UI.</li><li>Controlla che connessioni e parametri principali risultino coerenti (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>Dopo il provisioning</h2><ul><li>La procedura di setup porta <code>firstRun</code> a <code>false</code> per evitare riesecuzioni ad ogni avvio.</li><li>Esegui login standard e valida l'accesso alle route principali.</li></ul>",
|
|
1254
|
+
"html": "<h1>Scaffolding iniziale</h1><p>Questa pagina descrive il bootstrap iniziale quando <code>AppSettings.firstRun = true</code>.</p><h2>Con il pacchetto tutorial non c'e' niente da scaffoldare</h2><p>Lo scaffolding di cui parla questa pagina — leggere le tabelle di un database e registrarle in</p><p><code>_metadati__tabelle</code> / <code>_metadati__colonne</code> — riguarda <strong>solo</strong> la modalita' "DB esistente" del</p><p>wizard di primo avvio: e' li' che compare la casella *Esegui scaffold automatico delle tabelle</p><p>del DB selezionato*.</p><p>Nei pacchetti <strong>tutorial</strong> quella casella non esiste. Il database metadati arriva gia' popolato</p><p>(route, colonne, menu, traduzioni, dashboard di esempio) e il wizard si limita a ripristinarlo e</p><p>a creare l'utente admin. Vedere route gia' pronte subito dopo il primo avvio non e' quindi il</p><p>risultato di uno scaffolding: e' il contenuto del tutorial.</p><table><thead><tr><th>Modalita' del wizard</th><th>Cosa succede ai metadata</th></tr></thead><tbody><tr><td>Tutorial WideWorldImporters</td><td>Metadata gia' pronti, ripristinati dal pacchetto. Nessuno scaffolding.</td></tr><tr><td>DB esistente, casella spenta</td><td>DB metadati creato vuoto: le route si registrano a mano, o dopo dalla pagina Scaffolding.</td></tr><tr><td>DB esistente, casella accesa</td><td>A fine installazione ogni tabella del database scelto viene registrata come route.</td></tr></tbody></table><p>Il resto di questa pagina vale per le ultime due righe della tabella.</p><h2>Quando usarlo</h2><ul><li>Nuova installazione (DB metadata/dati non ancora pronti).</li><li>Ambiente locale da riallineare con setup iniziale.</li><li>Primo avvio dopo deploy dove vuoi forzare la procedura guidata di provisioning.</li></ul><h2>Comportamento con firstRun=true</h2><ul><li>L'endpoint <code>GET /api/Meta/FirstRunStatus</code> espone <code>firstRun: true</code>.</li><li>In login compare il flusso di primo avvio (es. azione <code>Aggiorna</code> nello screen).</li><li>Il setup applica le configurazioni base (connessioni, impostazioni runtime, bootstrap metadata).</li></ul><h2>Operazioni tipiche</h2><ul><li>Verifica <code>AppSettings.firstRun</code> a <code>true</code> in <code>appsettings.{Environment}.json</code> dell'host che stai eseguendo.</li><li>Avvia applicazione e completa la procedura di scaffolding iniziale da UI.</li><li>Controlla che connessioni e parametri principali risultino coerenti (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>Dopo il provisioning</h2><ul><li>La procedura di setup porta <code>firstRun</code> a <code>false</code> per evitare riesecuzioni ad ogni avvio.</li><li>Esegui login standard e valida l'accesso alle route principali.</li></ul>",
|
|
1241
1255
|
"codeSamples": []
|
|
1242
1256
|
}
|
|
1243
1257
|
],
|
|
@@ -1296,7 +1310,7 @@ const frameworkDocsContent = {
|
|
|
1296
1310
|
{
|
|
1297
1311
|
"id": "overview",
|
|
1298
1312
|
"title": "Overview",
|
|
1299
|
-
"html": "<h1>Licensing</h1><p>Questa pagina spiega il licensing dal punto di vista utente finale: cosa serve, come ottenere la licenza e come applicarla.</p><h2>Come ottenere una licenza</h2><p>Consulta i piani, le feature incluse per ciascun tier (Developer / Professional / Software House) e procedi all'acquisto sul sito pubblico:</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">Pricing e piani WUIC — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Contatti commerciali</a> — la prova non richiede licenza: senza licenza il framework gira in modalita' Trial (20 record per query)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">Homepage WUIC</a></li></ul><p>Dopo l'acquisto riceverai una mail con <code>license-payload</code> + <code>license-signature</code> da installare come descritto nella "Procedura utente finale" qui sotto.</p><h2>Come funziona</h2><ul><li>La licenza e valida solo se:</li><li>firma corretta.</li><li><code>machineFingerprint</code> del server corrente presente nella lista <code>machineFingerprints</code> del payload firmato.</li><li>Se la licenza non e valida, la lettura dati (<code>getFlatRecordData</code>) viene limitata a massimo 20 record. Inoltre l'hook host <code>customizeSelect</code> viene bypassato (non invocato).</li></ul><h2>Dove trovo il machineFingerprint</h2><p>Endpoint backend:</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → campo <code>machineFingerprint</code> (sempre disponibile, anche senza licenza).</li><li>Durante il first-run lo espone anche <code>GET /api/Meta/FirstRunStatus</code>.</li></ul><h2>Procedura utente finale</h2><p>1. Recupera <code>machineFingerprint</code> dal tuo host.</p><p>2. Invia il valore al fornitore/licensor.</p><p>3. Ricevi i valori licenza:</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (se previsto dalla tua installazione)</li></ul><p>4.
|
|
1313
|
+
"html": "<h1>Licensing</h1><p>Questa pagina spiega il licensing dal punto di vista utente finale: cosa serve, come ottenere la licenza e come applicarla.</p><h2>Come ottenere una licenza</h2><p>Consulta i piani, le feature incluse per ciascun tier (Developer / Professional / Software House) e procedi all'acquisto sul sito pubblico:</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">Pricing e piani WUIC — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Contatti commerciali</a> — la prova non richiede licenza: senza licenza il framework gira in modalita' Trial (20 record per query)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">Homepage WUIC</a></li></ul><p>Dopo l'acquisto riceverai una mail con <code>license-payload</code> + <code>license-signature</code> da installare come descritto nella "Procedura utente finale" qui sotto.</p><h2>Come funziona</h2><ul><li>La licenza e valida solo se:</li><li>firma corretta.</li><li><code>machineFingerprint</code> del server corrente presente nella lista <code>machineFingerprints</code> del payload firmato.</li><li>Se la licenza non e valida, la lettura dati (<code>getFlatRecordData</code>) viene limitata a massimo 20 record. Inoltre l'hook host <code>customizeSelect</code> viene bypassato (non invocato).</li></ul><h2>Dove trovo il machineFingerprint</h2><p>Endpoint backend:</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → campo <code>machineFingerprint</code> (sempre disponibile, anche senza licenza).</li><li>Durante il first-run lo espone anche <code>GET /api/Meta/FirstRunStatus</code>.</li></ul><h2>Procedura utente finale</h2><p>1. Recupera <code>machineFingerprint</code> dal tuo host.</p><p>2. Invia il valore al fornitore/licensor.</p><p>3. Ricevi i valori licenza:</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (se previsto dalla tua installazione)</li></ul><p>4. Incolla i valori dall'interfaccia: <strong>Amministrazione > Editor AppSettings</strong>, sezione</p><p> <strong>License</strong> (campi <code>License email</code>, <code>License payload</code>, <code>License signature</code>,</p><p> <code>Public key (PEM)</code>), poi salva. In alternativa si possono scrivere a mano nella sezione</p><p> <code>AppSettings</code> del file <code>appsettings.{Environment}.json</code> dell'host in esecuzione.</p><p>5. Verifica lo stato licenza:</p><ul><li>da API: <code>GET /api/Meta/LicenseStatus</code>, atteso <code>licenseValid = true</code>;</li><li>oppure dalla pagina stessa, che rilegge la licenza subito dopo il salvataggio.</li></ul><p><strong>Riavviare il backend non serve, se passi dall'editor.</strong> Salvando <code>license-payload</code> /</p><p><code>license-signature</code> dall'AppSettings Editor il backend ricarica da se' il servizio di</p><p>validazione, e la licenza vale dalla richiesta successiva. Il riavvio serve solo nell'altro</p><p>caso, quando i valori vengono scritti a mano nel file: quello viene riletto all'avvio.</p><h2>Licenza multi-macchina</h2><p>Un'unica licenza puo autorizzare piu macchine includendo piu valori in <code>machineFingerprints</code>.</p><h2>Troubleshooting rapido</h2><ul><li><code>licenseReason = invalid_signature</code>:</li><li>payload/firma non coerenti tra loro oppure public key diversa.</li><li><code>licenseReason = machine_fingerprint_not_authorized</code>:</li><li>il fingerprint della macchina corrente non e presente nella licenza ricevuta.</li><li><code>licenseReason = machine_fingerprint_missing</code>:</li><li>il runtime non riesce a calcolare il fingerprint locale.</li><li><code>licenseReason = license_expired</code>:</li><li>la licenza e scaduta, richiedi rinnovo.</li></ul>",
|
|
1300
1314
|
"codeSamples": []
|
|
1301
1315
|
}
|
|
1302
1316
|
],
|
|
@@ -1971,42 +1985,46 @@ const frameworkDocsContent = {
|
|
|
1971
1985
|
},
|
|
1972
1986
|
{
|
|
1973
1987
|
"id": "sec_2",
|
|
1974
|
-
"title": "
|
|
1988
|
+
"title": "Cosa mostra la toolbar di default"
|
|
1975
1989
|
},
|
|
1976
1990
|
{
|
|
1977
1991
|
"id": "sec_3",
|
|
1978
|
-
"title": "
|
|
1992
|
+
"title": "Screenshot reference (manuale utente)"
|
|
1979
1993
|
},
|
|
1980
1994
|
{
|
|
1981
1995
|
"id": "sec_4",
|
|
1982
|
-
"title": "
|
|
1996
|
+
"title": "Metadati inline editing"
|
|
1983
1997
|
},
|
|
1984
1998
|
{
|
|
1985
1999
|
"id": "sec_5",
|
|
1986
|
-
"title": "
|
|
2000
|
+
"title": "Toolbar export/import"
|
|
1987
2001
|
},
|
|
1988
2002
|
{
|
|
1989
2003
|
"id": "sec_6",
|
|
1990
|
-
"title": "
|
|
2004
|
+
"title": "Config metadata"
|
|
1991
2005
|
},
|
|
1992
2006
|
{
|
|
1993
2007
|
"id": "sec_7",
|
|
1994
|
-
"title": "md_props_bag:
|
|
2008
|
+
"title": "md_props_bag: toolbar"
|
|
1995
2009
|
},
|
|
1996
2010
|
{
|
|
1997
2011
|
"id": "sec_8",
|
|
1998
|
-
"title": "
|
|
2012
|
+
"title": "md_props_bag: archetypes.list"
|
|
1999
2013
|
},
|
|
2000
2014
|
{
|
|
2001
2015
|
"id": "sec_9",
|
|
2002
|
-
"title": "
|
|
2016
|
+
"title": "Paging: md_pagesize e md_page_size_choice"
|
|
2003
2017
|
},
|
|
2004
2018
|
{
|
|
2005
2019
|
"id": "sec_10",
|
|
2006
|
-
"title": "
|
|
2020
|
+
"title": "Forzatura virtualizzazione su page size alto"
|
|
2007
2021
|
},
|
|
2008
2022
|
{
|
|
2009
2023
|
"id": "sec_11",
|
|
2024
|
+
"title": "Eventi e subscriptions (host)"
|
|
2025
|
+
},
|
|
2026
|
+
{
|
|
2027
|
+
"id": "sec_12",
|
|
2010
2028
|
"title": "`rowCustomSelect` — signature reale (gotcha)"
|
|
2011
2029
|
}
|
|
2012
2030
|
],
|
|
@@ -2014,7 +2032,7 @@ const frameworkDocsContent = {
|
|
|
2014
2032
|
{
|
|
2015
2033
|
"id": "overview",
|
|
2016
2034
|
"title": "Overview",
|
|
2017
|
-
"html": "<h1>List Grid</h1><p>Componente principale per liste tabellari con filtri, sorting, paging server-side e azioni riga.</p><h2>Use cases</h2><ul><li>CRUD tabellari enterprise.</li><li>Report operativi con filtri multi-colonna.</li><li>Dataset molto grandi con <code>cursorMode</code>.</li></ul><h2>Screenshot reference (manuale utente)</h2><ul><li><code>manual__grid__01.png</code>: modalita <code>inline cell edit</code> in list-grid.</li><li><code>manual__grid__02.png</code>: modalita <code>inline edit</code> (row-level) in list-grid.</li></ul><h2>Metadati inline editing</h2><p>Configurazione nel <code>md_props_bag</code> della tabella metadata:</p><ul><li><code>md_inline_edit</code></li></ul><p> - abilita l'editing inline della riga in list-grid (celle editabili in contesto riga, senza apertura popup).</p><p> - utile quando vuoi mantenere la UX di tabella con editing rapido per record.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - abilita l'editing inline "cell-by-cell" (focus sulla singola cella).</p><p> - nota: nelle configurazioni legacy puo comparire come <code>md_inline_cell_editing</code>; il comportamento runtime e lo stesso.</p><p> - <strong>promozione runtime</strong>: quando <code>md_inline_cell_edit</code> e <code>true</code>, il componente forza</p><p> a runtime anche <code>md_inline_edit = true</code> indipendentemente dal valore in DB.</p><p> Entrambe le UX hanno bisogno della action column visibile, quindi sono mutualmente</p><p> non-esclusive a livello di rendering.</p><ul><li><code>md_batch_save</code></li></ul><p> - abilita il salvataggio batch delle modifiche pendenti (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - se usato insieme a inline-cell, le modifiche restano pending fino al salvataggio esplicito.</p><p> - <strong>prerequisito</strong>: <code>md_batch_save</code> ha effetto <strong>solo</strong> se <code>md_inline_cell_edit</code> e <code>true</code>.</p><p> Con <code>md_inline_cell_edit:false</code> il flag viene ignorato a runtime e i bottoni</p><p> "Salva modifiche / Annulla modifiche" non vengono renderizzati.</p><h3>Combinazioni valide</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Risultato runtime</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>qualsiasi</td><td>Row-level inline edit con pencil. <code>md_batch_save</code> ignorato.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Cell-by-cell autosave on blur. <code>md_inline_edit</code> forzato a <code>true</code> a runtime.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Cell-by-cell con buffer pending + toolbar <code>Salva / Annulla modifiche</code>.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>qualsiasi</td><td>Nessun inline editing. <code>md_batch_save</code> ignorato.</td></tr></tbody></table><p>Esempio row-level inline edit:</p><p>Snippet 1:</p><p>Esempio cell-by-cell con batch save:</p><p>Snippet 2:</p><h2>Toolbar export/import</h2><ul><li>Export XLS:</li></ul><p> - mostra dialog di progress con percentuale realtime;</p><p> - azioni: <code>Continua in background</code>, <code>Annulla task</code>, <code>Interrompi e scarica parziale</code>;</p><p> - in background crea una notifica con progress; click riapre il dialog.</p><ul><li>Import XLS/XLSX (se <code>md_importable = true</code>):</li></ul><p> - dialog di progress dopo la conferma;</p><p> - azioni: <code>Continua in background</code>, <code>Annulla import (rollback)</code>, <code>Stop e commit parziale</code>;</p><p> - a fine import crea una notifica di riepilogo che porta alla route.</p><h2>Config metadata</h2><p>Impostazioni chiave in <code>md_props_bag</code> e metadati colonna.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Flag opt-in che nascondono blocchi della toolbar della list-grid (<code>caption-bar</code>). Tutti sotto <code>md_props_bag.toolbar.*</code> (parsato in runtime come <code>tableMetadata.extraProps.toolbar</code>).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, default <code>false</code>): nasconde nella <strong>caption-right</strong> il bottone "Gestione stato" (icona bookmark) + la <code><select></code> degli stati salvati. Utile per route hardcoded / demo dove il saved-state feature (persistenza per <code>user_id</code> + route via <code>MetaService</code>) non ha senso — es. Pattern 3 puro OData senza route metadata registrata.</li><li><code>hideBatchActions</code> (boolean, default <code>false</code>): nasconde nella <strong>caption-left</strong> i pulsanti "Salva modifiche" (<code>pi-save</code>) + "Annulla modifiche" (<code>pi-times</code>) + l'indicatore conteggio changes (<code>grid-changes-indicator</code>, badge pencil + count). Generati dal framework quando <code>md_inline_cell_editing</code> + <code>md_batch_save</code> sono attivi. Pensato per <strong>nested grid in parametric-dialog</strong>: il save/cancel del padre persiste master + righe in un colpo via batch save framework, e i pulsanti duplicati sulla nested grid confondono l'UX.</li></ul><p>Esempio nested rows in custom edit-form (runtime patch):</p><p>Snippet 5:</p><p>Tipo TS in <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (proprieta <code>extraProps.toolbar</code>). I flag NON disabilitano la logica <code>md_batch_save</code> sottostante (changes restano tracciate); rimuovono solo l'UI toolbar — il save effettivo passa dal flusso del padre.</p><h2>md_props_bag: archetypes.list</h2><p>Il componente legge <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code>:</li><li>tipo: boolean (con parser tollerante)</li><li>valori accettati: <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>default runtime: <code>true</code> quando assente o vuoto</li><li>effetto: distribuisce le larghezze colonna in percentuale (anziche px) quando non ci sono larghezze utente persistite.</li></ul><ul><li><code>virtualize</code>:</li><li>tipo: <code>boolean</code> oppure <code>object</code></li><li>valori accettati:</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>object con <code>enabled</code> (opzionale) e <code>itemSize</code> (opzionale)</li><li>default runtime: disabilitato (<code>false</code>) quando assente</li><li><code>enabled</code>:</li><li>default: <code>true</code> se il nodo <code>virtualize</code> e object senza <code>enabled</code>, altrimenti parser tollerante</li><li>effetto: abilita <code>virtualScroll</code> su <code>p-table</code></li><li><code>itemSize</code>:</li><li>default: <code>44</code></li><li>effetto: imposta <code>virtualScrollItemSize</code> (altezza riga virtuale in px)</li></ul><ul><li><code>advancedFilter</code>:</li><li>tipo: boolean (con parser tollerante)</li><li>default runtime: <code>false</code></li><li>effetto:</li><li>quando <code>true</code>, la griglia nasconde le icone filtro colonna (<code>p-columnFilter</code>) e usa la <code>wuic-filter-bar</code> sopra la tabella (a livello <code>data-repeater</code>/<code>bounded-repeater</code>) per applicare i filtri.</li></ul><p>Nota operativa:</p><ul><li>il suggest <code>md_props_bag</code> nel metadata editor espone anche il nodo checkabile <code>archetypes.list.advancedFilter</code>.</li></ul><h2>Paging: md_pagesize e md_page_size_choice</h2><p>La griglia usa <code>md_pagesize</code> come dimensione pagina di default e <code>md_page_size_choice</code> come elenco valori selezionabili nel paginator.</p><p>Regole runtime:</p><ul><li>se <code>md_pagesize</code> e maggiore del valore massimo presente in <code>md_page_size_choice</code>, il framework aggiunge automaticamente <code>md_pagesize</code> alla lista opzioni;</li><li>la lista viene normalizzata (numeri validi, deduplica, ordinamento crescente).</li></ul><p>Esempio:</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>risultato runtime: <code>10,25,50,100,200</code></li></ul><h2>Forzatura virtualizzazione su page size alto</h2><p>Quando l'utente seleziona nel paginator un valore <code>pageSize >= 1000</code>:</p><ul><li>la virtualizzazione viene forzata automaticamente anche se <code>md_props_bag.archetypes.list.virtualize</code> e assente o disabilitato;</li><li><code>virtualScrollItemSize</code> viene forzato al valore predefinito <code>44</code>.</li></ul><p>Questo comportamento protegge la resa della tabella su pagine molto grandi.</p><h2>Eventi e subscriptions (host)</h2><p><code>wuic-list-grid</code> espone eventi runtime utili per intercettare ciclo render e callback p-table lato progetto host.</p><p>Eventi disponibili:</p><ul><li><code>onAfterRender</code>: emesso a fine binding dati della griglia (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code>: emesso prima del rendering logico della singola riga; supporta cancel tramite <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code>: emesso dopo il rendering logico della singola riga.</li><li><code>onPaging</code>: emesso sugli eventi paging (<code>p-table onPage</code>).</li><li><code>onSorting</code>: emesso sugli eventi sorting (<code>p-table onSort</code>).</li><li><code>onFiltering</code>: emesso sugli eventi filtering (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code>: emesso su cambio selezione righe.</li><li><code>onPTableRowExpand</code>: emesso su expand riga.</li><li><code>onPTableRowCollapse</code>: emesso su collapse riga.</li><li><code>onPTableColumnResize</code>: emesso su resize colonna.</li><li><code>onPTableColumnReorder</code>: emesso su reorder colonne.</li></ul><h3>Esempio 1: binding diretto nel template</h3><p>Snippet 7:</p><h3>Esempio 2: subscribe via ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — signature reale (gotcha)</h2><p><code><wuic-list-grid></code> accetta un input <code>[rowCustomSelect]</code> per intercettare la selezione di una riga (apertura dialog "scegli documento", master-detail, ecc.). La firma TypeScript dichiarata in <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> è:</p><p>Snippet 9:</p><p><strong>Pero' a runtime la callback viene invocata con argomenti invertiti</strong> — il framework chiama <code>rowCustomSelect($event, rowData, dt)</code> (vedi <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> e <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Sintomo se sbagli ordine: <code>rowData?.id</code> e' undefined → guard precoce nel handler → la callback ritorna senza side-effect e la dialog/azione non parte. Nessun errore in console.</p><p>Forma corretta (allineata all'invocazione runtime):</p><p>Snippet 10:</p><p>Esempio integrato nel template:</p><p>Snippet 11:</p><p>> Note: i test in <code>designer.component.spec.ts</code> (es. riga 512) chiamano la callback con <code>({currentTarget: rowCell}, {id: 42}, null)</code> confermando l'ordine <code>($event, rowData, dt)</code>. Se in futuro il framework dovesse uniformare la signature dichiarata, si aggiornera' anche questa pagina.</p>",
|
|
2035
|
+
"html": "<h1>List Grid</h1><p>Componente principale per liste tabellari con filtri, sorting, paging server-side e azioni riga.</p><h2>Use cases</h2><ul><li>CRUD tabellari enterprise.</li><li>Report operativi con filtri multi-colonna.</li><li>Dataset molto grandi con <code>cursorMode</code>.</li></ul><h2>Cosa mostra la toolbar di default</h2><p>Aprendo una route appena scaffoldata, sopra la griglia c'e' la caption-bar. A sinistra:</p><table><thead><tr><th>Pulsante</th><th>Quando compare</th></tr></thead><tbody><tr><td><strong>Aggiorna</strong></td><td>sempre, salvo <code>md_hide_refresh</code></td></tr><tr><td><strong>Aggiungi</strong></td><td>con <code>md_insertable</code></td></tr><tr><td><strong>Azioni</strong></td><td>se la tabella ha custom action</td></tr><tr><td>Import / Export</td><td>sempre; il ramo import solo con <code>md_importable</code></td></tr><tr><td><strong>Report</strong></td><td>se alla route e' associato almeno un report</td></tr><tr><td><strong>Salva modifiche</strong> / <strong>Annulla modifiche</strong></td><td>solo con <code>md_inline_cell_edit</code> <strong>e</strong> <code>md_batch_save</code></td></tr></tbody></table><p>A destra: <strong>Gestione stato</strong> (preceduto dalla tendina degli stati salvati, se ce ne sono),</p><p><strong>Pulisci filtri</strong> quando i filtri stanno sulle colonne, e <strong>Performance</strong> se l'inspector e'</p><p>abilitato sulla route.</p><p>> Le didascalie citate piu' sotto in questa pagina <strong>non si trovano su questo schermo</strong>, e non</p><p>> e' un difetto: quelle di export/import (<em>Continua in background</em>, <em>Annulla task</em>, *Interrompi</p><p>> e scarica parziale<em>, </em>Annulla import (rollback)<em>, </em>Stop e commit parziale*) vivono nella</p><p>> dialog di avanzamento, che esiste solo mentre un export o un import e' in corso; *Salva</p><p>> modifiche<em> e </em>Annulla modifiche* compaiono solo con i due flag qui sopra. Appartengono a</p><p>> momenti diversi dalla prima apertura della lista.</p><h2>Screenshot reference (manuale utente)</h2><ul><li><code>manual__grid__01.png</code>: modalita <code>inline cell edit</code> in list-grid.</li><li><code>manual__grid__02.png</code>: modalita <code>inline edit</code> (row-level) in list-grid.</li></ul><h2>Metadati inline editing</h2><p>Configurazione nel <code>md_props_bag</code> della tabella metadata:</p><ul><li><code>md_inline_edit</code></li></ul><p> - abilita l'editing inline della riga in list-grid (celle editabili in contesto riga, senza apertura popup).</p><p> - utile quando vuoi mantenere la UX di tabella con editing rapido per record.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - abilita l'editing inline "cell-by-cell" (focus sulla singola cella).</p><p> - nota: nelle configurazioni legacy puo comparire come <code>md_inline_cell_editing</code>; il comportamento runtime e lo stesso.</p><p> - <strong>promozione runtime</strong>: quando <code>md_inline_cell_edit</code> e <code>true</code>, il componente forza</p><p> a runtime anche <code>md_inline_edit = true</code> indipendentemente dal valore in DB.</p><p> Entrambe le UX hanno bisogno della action column visibile, quindi sono mutualmente</p><p> non-esclusive a livello di rendering.</p><ul><li><code>md_batch_save</code></li></ul><p> - abilita il salvataggio batch delle modifiche pendenti (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - se usato insieme a inline-cell, le modifiche restano pending fino al salvataggio esplicito.</p><p> - <strong>prerequisito</strong>: <code>md_batch_save</code> ha effetto <strong>solo</strong> se <code>md_inline_cell_edit</code> e <code>true</code>.</p><p> Con <code>md_inline_cell_edit:false</code> il flag viene ignorato a runtime e i bottoni</p><p> "Salva modifiche / Annulla modifiche" non vengono renderizzati.</p><h3>Combinazioni valide</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Risultato runtime</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>qualsiasi</td><td>Row-level inline edit con pencil. <code>md_batch_save</code> ignorato.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Cell-by-cell autosave on blur. <code>md_inline_edit</code> forzato a <code>true</code> a runtime.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Cell-by-cell con buffer pending + toolbar <code>Salva / Annulla modifiche</code>.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>qualsiasi</td><td>Nessun inline editing. <code>md_batch_save</code> ignorato.</td></tr></tbody></table><p>Esempio row-level inline edit:</p><p>Snippet 1:</p><p>Esempio cell-by-cell con batch save:</p><p>Snippet 2:</p><h2>Toolbar export/import</h2><ul><li>Export XLS:</li></ul><p> - mostra dialog di progress con percentuale realtime;</p><p> - azioni: <code>Continua in background</code>, <code>Annulla task</code>, <code>Interrompi e scarica parziale</code>;</p><p> - in background crea una notifica con progress; click riapre il dialog.</p><ul><li>Import XLS/XLSX (se <code>md_importable = true</code>):</li></ul><p> - dialog di progress dopo la conferma;</p><p> - azioni: <code>Continua in background</code>, <code>Annulla import (rollback)</code>, <code>Stop e commit parziale</code>;</p><p> - a fine import crea una notifica di riepilogo che porta alla route.</p><h2>Config metadata</h2><p>Impostazioni chiave in <code>md_props_bag</code> e metadati colonna.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Flag opt-in che nascondono blocchi della toolbar della list-grid (<code>caption-bar</code>). Tutti sotto <code>md_props_bag.toolbar.*</code> (parsato in runtime come <code>tableMetadata.extraProps.toolbar</code>).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, default <code>false</code>): nasconde nella <strong>caption-right</strong> il bottone "Gestione stato" (icona bookmark) + la <code><select></code> degli stati salvati. Utile per route hardcoded / demo dove il saved-state feature (persistenza per <code>user_id</code> + route via <code>MetaService</code>) non ha senso — es. Pattern 3 puro OData senza route metadata registrata.</li><li><code>hideBatchActions</code> (boolean, default <code>false</code>): nasconde nella <strong>caption-left</strong> i pulsanti "Salva modifiche" (<code>pi-save</code>) + "Annulla modifiche" (<code>pi-times</code>) + l'indicatore conteggio changes (<code>grid-changes-indicator</code>, badge pencil + count). Generati dal framework quando <code>md_inline_cell_editing</code> + <code>md_batch_save</code> sono attivi. Pensato per <strong>nested grid in parametric-dialog</strong>: il save/cancel del padre persiste master + righe in un colpo via batch save framework, e i pulsanti duplicati sulla nested grid confondono l'UX.</li></ul><p>Esempio nested rows in custom edit-form (runtime patch):</p><p>Snippet 5:</p><p>Tipo TS in <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (proprieta <code>extraProps.toolbar</code>). I flag NON disabilitano la logica <code>md_batch_save</code> sottostante (changes restano tracciate); rimuovono solo l'UI toolbar — il save effettivo passa dal flusso del padre.</p><h2>md_props_bag: archetypes.list</h2><p>Il componente legge <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code>:</li><li>tipo: boolean (con parser tollerante)</li><li>valori accettati: <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>default runtime: <code>true</code> quando assente o vuoto</li><li>effetto: distribuisce le larghezze colonna in percentuale (anziche px) quando non ci sono larghezze utente persistite.</li></ul><ul><li><code>virtualize</code>:</li><li>tipo: <code>boolean</code> oppure <code>object</code></li><li>valori accettati:</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>object con <code>enabled</code> (opzionale) e <code>itemSize</code> (opzionale)</li><li>default runtime: disabilitato (<code>false</code>) quando assente</li><li><code>enabled</code>:</li><li>default: <code>true</code> se il nodo <code>virtualize</code> e object senza <code>enabled</code>, altrimenti parser tollerante</li><li>effetto: abilita <code>virtualScroll</code> su <code>p-table</code></li><li><code>itemSize</code>:</li><li>default: <code>44</code></li><li>effetto: imposta <code>virtualScrollItemSize</code> (altezza riga virtuale in px)</li></ul><ul><li><code>advancedFilter</code>:</li><li>tipo: boolean (con parser tollerante)</li><li>default runtime: <code>false</code></li><li>effetto:</li><li>quando <code>true</code>, la griglia nasconde le icone filtro colonna (<code>p-columnFilter</code>) e usa la <code>wuic-filter-bar</code> sopra la tabella (a livello <code>data-repeater</code>/<code>bounded-repeater</code>) per applicare i filtri.</li></ul><p>Nota operativa:</p><ul><li>il suggest <code>md_props_bag</code> nel metadata editor espone anche il nodo checkabile <code>archetypes.list.advancedFilter</code>.</li></ul><h2>Paging: md_pagesize e md_page_size_choice</h2><p>La griglia usa <code>md_pagesize</code> come dimensione pagina di default e <code>md_page_size_choice</code> come elenco valori selezionabili nel paginator.</p><p>Regole runtime:</p><ul><li>se <code>md_pagesize</code> e maggiore del valore massimo presente in <code>md_page_size_choice</code>, il framework aggiunge automaticamente <code>md_pagesize</code> alla lista opzioni;</li><li>la lista viene normalizzata (numeri validi, deduplica, ordinamento crescente).</li></ul><p>Esempio:</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>risultato runtime: <code>10,25,50,100,200</code></li></ul><h2>Forzatura virtualizzazione su page size alto</h2><p>Quando l'utente seleziona nel paginator un valore <code>pageSize >= 1000</code>:</p><ul><li>la virtualizzazione viene forzata automaticamente anche se <code>md_props_bag.archetypes.list.virtualize</code> e assente o disabilitato;</li><li><code>virtualScrollItemSize</code> viene forzato al valore predefinito <code>44</code>.</li></ul><p>Questo comportamento protegge la resa della tabella su pagine molto grandi.</p><h2>Eventi e subscriptions (host)</h2><p><code>wuic-list-grid</code> espone eventi runtime utili per intercettare ciclo render e callback p-table lato progetto host.</p><p>Eventi disponibili:</p><ul><li><code>onAfterRender</code>: emesso a fine binding dati della griglia (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code>: emesso prima del rendering logico della singola riga; supporta cancel tramite <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code>: emesso dopo il rendering logico della singola riga.</li><li><code>onPaging</code>: emesso sugli eventi paging (<code>p-table onPage</code>).</li><li><code>onSorting</code>: emesso sugli eventi sorting (<code>p-table onSort</code>).</li><li><code>onFiltering</code>: emesso sugli eventi filtering (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code>: emesso su cambio selezione righe.</li><li><code>onPTableRowExpand</code>: emesso su expand riga.</li><li><code>onPTableRowCollapse</code>: emesso su collapse riga.</li><li><code>onPTableColumnResize</code>: emesso su resize colonna.</li><li><code>onPTableColumnReorder</code>: emesso su reorder colonne.</li></ul><h3>Esempio 1: binding diretto nel template</h3><p>Snippet 7:</p><h3>Esempio 2: subscribe via ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — signature reale (gotcha)</h2><p><code><wuic-list-grid></code> accetta un input <code>[rowCustomSelect]</code> per intercettare la selezione di una riga (apertura dialog "scegli documento", master-detail, ecc.). La firma TypeScript dichiarata in <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> è:</p><p>Snippet 9:</p><p><strong>Pero' a runtime la callback viene invocata con argomenti invertiti</strong> — il framework chiama <code>rowCustomSelect($event, rowData, dt)</code> (vedi <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> e <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Sintomo se sbagli ordine: <code>rowData?.id</code> e' undefined → guard precoce nel handler → la callback ritorna senza side-effect e la dialog/azione non parte. Nessun errore in console.</p><p>Forma corretta (allineata all'invocazione runtime):</p><p>Snippet 10:</p><p>Esempio integrato nel template:</p><p>Snippet 11:</p><p>> Note: i test in <code>designer.component.spec.ts</code> (es. riga 512) chiamano la callback con <code>({currentTarget: rowCell}, {id: 42}, null)</code> confermando l'ordine <code>($event, rowData, dt)</code>. Se in futuro il framework dovesse uniformare la signature dichiarata, si aggiornera' anche questa pagina.</p>",
|
|
2018
2036
|
"codeSamples": [
|
|
2019
2037
|
{
|
|
2020
2038
|
"id": "code_1",
|
|
@@ -3740,7 +3758,7 @@ const frameworkDocsContent = {
|
|
|
3740
3758
|
{
|
|
3741
3759
|
"id": "overview",
|
|
3742
3760
|
"title": "Overview",
|
|
3743
|
-
"html": "<h1>Designer</h1><p>Editor visuale per dashboard metadata-driven su route <code>#/cities/dashboard</code>.</p><h2>Scope</h2><ul><li>Composizione board via drag-and-drop di nodi e blocchi UI.</li><li>Layout e styling pilotati da <code>boardcontent</code> e metadata tabella/colonna.</li><li>Editing property panel senza hardcode nei componenti runtime.</li></ul><h2>Palette Designer</h2><
|
|
3761
|
+
"html": "<h1>Designer</h1><p>Editor visuale per dashboard metadata-driven su route <code>#/cities/dashboard</code>.</p><h2>Scope</h2><ul><li>Composizione board via drag-and-drop di nodi e blocchi UI.</li><li>Layout e styling pilotati da <code>boardcontent</code> e metadata tabella/colonna.</li><li>Editing property panel senza hardcode nei componenti runtime.</li></ul><h2>Palette Designer</h2><p>La palette e' divisa in tre gruppi. I nomi qui sotto sono quelli che leggi nella palette,</p><p>maiuscoli come li scrive il designer.</p><p><strong>HTML</strong> — i mattoni di markup:</p><table><thead><tr><th>Tool</th><th>A cosa serve</th></tr></thead><tbody><tr><td><code>TABLE</code></td><td>griglia di celle. <code>TR</code> e <code>TD</code> esistono come tool ma non si trascinano: li crea la tabella</td></tr><tr><td><code>DIV</code></td><td>contenitore libero, il blocco strutturale piu' usato</td></tr><tr><td><code>SPAN</code>, <code>LABEL</code>, <code>Hx</code></td><td>testo databound; <code>Hx</code> sceglie il livello da h1 a h6</td></tr><tr><td><code>ANCHOR</code>, <code>IMG</code>, <code>IMAGE</code>, <code>IFRAME</code></td><td>link, immagini, contenuto esterno</td></tr><tr><td><code>UL</code></td><td>elenco</td></tr><tr><td><code>BUTTON</code></td><td>pulsante con callback</td></tr><tr><td><code>INPUT</code>, <code>TEXTAREA</code>, <code>CHECKBOX</code>, <code>SELECT</code>, <code>MULTISELECT</code>, <code>DATE</code></td><td>campi di input</td></tr><tr><td><code>KPI</code></td><td>valore singolo in evidenza</td></tr><tr><td><code>SEPARATOR</code>, <code>HR</code></td><td>separatori</td></tr></tbody></table><p><strong>DATA</strong> — i nodi collegati al backend:</p><table><thead><tr><th>Tool</th><th>A cosa serve</th></tr></thead><tbody><tr><td><code>DATASOURCE</code></td><td>sorgente dati metadata (<code>route</code>, filtri, sort, paging)</td></tr><tr><td><code>DATAREPEATER</code></td><td>visualizzazione lista/card collegata a un datasource</td></tr><tr><td><code>FILTERBAR</code></td><td>barra filtri sopra il repeater</td></tr><tr><td><code>PAGER</code></td><td>paginatore</td></tr></tbody></table><p><strong>CONTAINER</strong> — i layout:</p><table><thead><tr><th>Tool</th><th>A cosa serve</th></tr></thead><tbody><tr><td><code>TABVIEW</code> + <code>TABPANEL</code></td><td>schede</td></tr><tr><td><code>SPLITTER</code> + <code>SPLITTER-AREA</code></td><td>pannelli ridimensionabili</td></tr><tr><td><code>ACCORDION</code> + <code>ACCORDION-AREA</code></td><td>sezioni a fisarmonica</td></tr></tbody></table><p>Due nomi che si cercano invano: <strong>non esiste un tool "Dynamic Template"</strong> — il template dinamico</p><p>e' cio' che il <code>DATAREPEATER</code> renderizza, si configura dalle sue proprieta' e non si trascina; e</p><p><strong>"Container" / "Layout" sono il nome del gruppo</strong>, non voci selezionabili.</p><p>A questi si aggiungono i tool custom registrati dal progetto host</p><p>(<code>MetadataProviderService.customDesignerTools</code>), che compaiono in coda con il gruppo che</p><p>dichiarano.</p><h2>Feature principali</h2><ul><li>Drag-and-drop nodi sulla canvas con persistenza nel <code>boardcontent</code>.</li><li>Property panel contestuale con input coerenti ai componenti selezionati.</li><li>Binding tra nodi (<code>datasource -> repeater/template</code>) con validazione minima.</li><li>Preview runtime integrata e riallineamento layout.</li><li>Gestione pending changes con guard prima dell'uscita.</li></ul><h2>Context menu sugli elementi</h2><p>Right-click su un elemento del canvas, una voce del breadcrumb in basso o un nodo dell'albero gerarchia mostra un context menu con tre voci:</p><ul><li><strong>Modifica proprietà</strong> (pi-cog) — seleziona l'elemento come "current tool" e ne mostra il property panel a destra; equivalente al click nell'albero. Utile per editare proprietà di elementi annidati senza dover cercare la voce nella gerarchia.</li><li><strong>Rinomina</strong> (solo breadcrumb in basso) — apre dialog per rinominare il <code>displayName</code>.</li><li><strong>Rimuovi</strong> — elimina l'elemento dalla board.</li></ul><h2>Flusso operativo consigliato</h2><ul><li>Aprire route dashboard target.</li><li>Inserire/collegare nodi dalla palette.</li><li>Configurare <code>inputs</code> essenziali (es. <code>route</code>, <code>action</code>, <code>datasource</code>).</li><li>Salvare e validare il risultato in runtime.</li></ul><h2>Note operative</h2><ul><li>Per fix specifici dashboard, privilegiare patch del <code>boardcontent</code> invece di modifiche globali.</li><li>Evitare proprietà duplicate tra <code>inputs</code> e stile inline non coerente.</li><li>Verificare sempre che i datasource abbiano <code>inputs.route</code> valorizzata.</li></ul>",
|
|
3744
3762
|
"codeSamples": []
|
|
3745
3763
|
}
|
|
3746
3764
|
],
|
|
@@ -7855,13 +7873,17 @@ const frameworkDocsContent = {
|
|
|
7855
7873
|
{
|
|
7856
7874
|
"id": "sec_4",
|
|
7857
7875
|
"title": "Quick Start — First Component"
|
|
7876
|
+
},
|
|
7877
|
+
{
|
|
7878
|
+
"id": "sec_5",
|
|
7879
|
+
"title": "The first lists show 20 records: that is Trial mode"
|
|
7858
7880
|
}
|
|
7859
7881
|
],
|
|
7860
7882
|
"sections": [
|
|
7861
7883
|
{
|
|
7862
7884
|
"id": "overview",
|
|
7863
7885
|
"title": "Overview",
|
|
7864
|
-
"html": "<h1>Framework Overview</h1><p>WUIC Framework is a metadata-driven platform for building business interfaces quickly and consistently.</p><h2>What It Includes</h2><ul><li>DataSource and DataRepeater for orchestrating data and rendering.</li><li>Visual archetypes (list, map, scheduler, chart, carousel).</li><li>Runtime designer for dashboards and dynamic templates.</li><li>Workflow designer/runner for operational processes.</li><li>RAG Chatbot for querying the codebase in natural language.</li><li>Multi-DBMS: SQL Server, MySQL, PostgreSQL and Oracle via drop-in providers (<code>dbms</code>: <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Starting the Dev Environment</h2><p>The WUIC stack is composed of several services. Start them in the order below.</p><h3>Prerequisites</h3><table><thead><tr><th>What</th><th>Check</th><th>Notes</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle for IIS in production</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>22 is the version the package is tested with; on npm 10.9.x it installs thanks to the bundled <code>package-lock.json</code></td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>The Windows PowerShell that ships with Windows is enough: <code>rename-project.ps1</code> and the <code>llm-workspace/</code> scripts run on 5.1 too. PowerShell 7 is recommended, not required</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>If missing, <strong>the one-liner installs it for you</strong> (SQL Server Express, or the engine chosen with <code>-Dbms</code>); not on Windows Server, see the box below. 2019 is enough for the packages without <code>.bak</code>; the <code>.bak</code> tutorial is a SQL Server 2022 backup and needs <strong>2022 or newer</strong></td></tr><tr><td>Linux (<code>install.sh</code> installer)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 or 24.04 LTS</strong> (24.04 recommended): they are the only Ubuntu releases Microsoft supports for SQL Server, and <strong>26.04 is not supported</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Same recommendation with MySQL, PostgreSQL and Oracle, because the installer is tested on those releases</td></tr><tr><td>NVIDIA GPU (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Optional: speeds up the RAG Chatbot (runs on CPU without it)</td></tr></tbody></table><p>> <strong>On Windows Server the database must be installed first.</strong> The one-liner pulls missing</p><p>> components through <code>winget</code>, which is not present on Windows Server: without an instance</p><p>> already reachable the installation stops with `No SQL Server instance reachable and winget is</p><p>> missing`. Install the engine before running the line - SQL Server must be <strong>2019 or newer</strong></p><p>> (Express is enough; <strong>2022 or newer</strong> for the <code>.bak</code> tutorial), and a 2017 instance is not</p><p>> accepted. If the instance is not the default one, pass it with</p><p>> <code>-SqlServer 'localhost\\INSTANCENAME'</code>. This applies to every engine, not just SQL Server.</p><h3>1. Download the project template</h3><p>On Windows one PowerShell line does all of it: it downloads the package, checks the .NET SDK 10</p><p>and Node.js 22 (installing what is missing), runs <code>dotnet restore</code> and <code>npm install</code>,</p><p>and installs the WUIC Assistant extension in VS Code.</p><p>Snippet 1:</p><p>Useful options on the same line: <code>-Dbms mysql</code> (or <code>postgres</code>, <code>oracle</code>) for an engine other</p><p>than SQL Server — the installer installs and configures it for you — and <code>-WithTutorial</code> to</p><p>download the sample database as well.</p><p>When it is done, the last screen is already your to-do list:</p><p>Snippet 2:</p><p>The connection string is ready to use: at first start the wizard asks for nothing else. With</p><p><code>-Dbms mysql</code> or <code>-Dbms postgres</code> that line changes accordingly and carries user and password</p><p>inside it, because the superuser password is <strong>generated by the installer</strong>; the same password</p><p>is saved in <code>wuic-secrets.json</code>, next to the installation, and that is the only place where it</p><p>stays written.</p><p>The manual path still works, on any operating system:</p><p>Start from the <code>WuicTest-src-*.zip</code> package (link in the <strong>Download</strong> section of the site).</p><p>Extract it to a working folder, e.g. <code>C:\\dev\\WuicTest</code> (files go directly at the root —</p><p>NOT inside a <code>src/</code> subfolder). The package contains:</p><ul><li><code>WuicTest.csproj</code> → host project with <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → Angular app whose <code>package.json</code> references <code>wuic-framework-lib</code> from the npm registry</li><li><code>appsettings.json</code> preconfigured in <code>firstRun = "true"</code> mode with <code>__SET_*__</code> placeholders</li><li><code>appsettings-samples/</code> → 6 ready templates (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>No need to clone the framework repository</strong>: <code>WuicCore</code> ships as a NuGet package from</p><p>> <code>nuget.org</code> and <code>wuic-framework-lib</code> as an npm package from the npm registry. The framework</p><p>> source is only needed if you want to modify it — typically not your case.</p><p>> <strong>npm 10.9.x and packages older than 1.7.1</strong>: those packages carry no <code>package-lock.json</code>, and</p><p>> without a lock npm 10.9.x (the version Node 22 LTS installs) stops with</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> while resolving peer dependencies.</p><p>> Download the lock published next to the release —</p><p>> <code>https://wuic-framework.com/downloads/locks/<zip-name>.package-lock.json</code> — drop it in <code>wwwroot/</code></p><p>> and run <code>npm install</code> again. The <code>-Src</code> one-liner does it for you.</p><h3>2. Database</h3><p>You need a reachable engine instance. <strong>With the one-liner there is nothing to do</strong>: it</p><p>installs and configures the instance, and the connection string to paste into the wizard is the</p><p>last thing it prints. On the manual path the instance must already exist.</p><p>Connections in <code>appsettings.json</code>:</p><ul><li><code>MetaDataSQLConnection</code> — metadata DB (menu, tables, columns, boards, users)</li><li><code>DataSQLConnection</code> — application data DB</li></ul><p>If this is the first installation (<code>AppSettings.firstRun = "true"</code> in the template),</p><p>the scaffolding wizard on first startup creates the metadata schema and populates the data DB.</p><p>See the <em>Initial Scaffolding</em> page for the guided flow.</p><h3>3. Backend (.NET)</h3><p>From the root of the extracted folder (e.g. <code>C:\\dev\\WuicTest</code>):</p><p>Snippet 3:</p><p>The backend exposes APIs on <code>http://localhost:5000</code>.</p><h3>4. Frontend (Angular)</h3><p>In a second shell, from the <code>wwwroot/</code> subfolder:</p><p>Snippet 4:</p><p>The frontend is available on <code>http://localhost:4200</code>.</p><p>Default login (post-firstRun): <code>admin</code> / <code>admin</code>.</p><h3>5. RAG Chatbot (optional)</h3><p>The RAG Chatbot (<code>Administration > RAG Chat</code>) runs <strong>inside the .NET backend</strong>:</p><p>the retrieval engine (<code>rag-engine/WuicRagEngine.dll</code>, in-process ONNX Runtime)</p><p>is loaded by the backend when <code>AppSettings.rag-use-dotnet-engine</code> is <code>"true"</code></p><p>(the default in release packages). **No Python, no venv, no separate server</p><p>to start.**</p><p>The <strong>first</strong> time the chatbot is opened (or at the end of the first run) the</p><p>backend downloads by itself the ONNX models (<code>bge-m3</code> + reranker), tokenizer</p><p>and index (~4.5 GB) from <code>rag-engine-models-url</code> (default</p><p><code>https://wuic-framework.com/rag-models</code>) into <code>rag-engine/artifacts/</code>. An</p><p>internet connection is needed only once; the download runs in the background</p><p>(1-5 min) and an in-app notification is sent when it starts and when it ends.</p><p>Meanwhile the component shows the <strong>RAG offline</strong> status and the rest of the</p><p>application works normally.</p><p>Relevant <code>AppSettings</code> keys (all with ready defaults):</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — enables the .NET engine (<code>false</code> = Python fallback, see below)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code>: with an NVIDIA GPU (CUDA 12.x + cuDNN 9) ~1 s/query, on CPU ~15-25 s/query</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = framework sources as signatures only; <code>internal</code> = full index</li><li><code>rag-engine-models-url</code> — download source on first start</li><li><code>rag-engine-cuda-path</code> = (empty) — folder of the CUDA/cuDNN DLLs when they are not installed system-wide</li></ul><p>For LLM chat set <code>rag-llm-provider</code> + <code>rag-llm-api-key</code> (Claude via Anthropic,</p><p>or a local model via Ollama with <code>rag-llm-base-url</code>). Without a provider only</p><p>the retrieval mode (snippet search) works. Key details on the <em>AppSettings</em></p><p>page.</p><p>> The legacy Python stack (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> on</p><p>> <code>127.0.0.1:8765</code>) is only usable as a fallback with</p><p>> <code>rag-use-dotnet-engine = "false"</code> and is not shipped in release packages.</p><h2>Services Summary</h2><table><thead><tr><th>Service</th><th>Port</th><th>Required</th><th>Quick command</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>yes</td><td>(Windows service)</td></tr><tr><td>.NET Backend</td><td>5000</td><td>yes</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Angular Frontend</td><td>4200</td><td>yes</td><td><code>npm run serve:dev</code></td></tr><tr><td>.NET RAG engine (ONNX)</td><td>in-process</td><td>no</td><td>loaded by the backend on the first chat</td></tr></tbody></table><h2>Quick Start — First Component</h2><p>1. Configure the AsmxProxy endpoint.</p><p>2. Define route metadata and columns.</p><p>3. Mount <code>wuic-data-source</code> + <code>wuic-data-repeater</code>.</p><p>Snippet 5:</p>",
|
|
7886
|
+
"html": "<h1>Framework Overview</h1><p>WUIC Framework is a metadata-driven platform for building business interfaces quickly and consistently.</p><h2>What It Includes</h2><ul><li>DataSource and DataRepeater for orchestrating data and rendering.</li><li>Visual archetypes (list, map, scheduler, chart, carousel).</li><li>Runtime designer for dashboards and dynamic templates.</li><li>Workflow designer/runner for operational processes.</li><li>RAG Chatbot for querying the codebase in natural language.</li><li>Multi-DBMS: SQL Server, MySQL, PostgreSQL and Oracle via drop-in providers (<code>dbms</code>: <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Starting the Dev Environment</h2><p>The WUIC stack is composed of several services. Start them in the order below.</p><h3>Prerequisites</h3><table><thead><tr><th>What</th><th>Check</th><th>Notes</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle for IIS in production</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>22 is the version the package is tested with; on npm 10.9.x it installs thanks to the bundled <code>package-lock.json</code></td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>The Windows PowerShell that ships with Windows is enough: <code>rename-project.ps1</code> and the <code>llm-workspace/</code> scripts run on 5.1 too. PowerShell 7 is recommended, not required</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>If missing, <strong>the one-liner installs it for you</strong> (SQL Server Express, or the engine chosen with <code>-Dbms</code>); not on Windows Server, see the box below. 2019 is enough for the packages without <code>.bak</code>; the <code>.bak</code> tutorial is a SQL Server 2022 backup and needs <strong>2022 or newer</strong></td></tr><tr><td>Linux (<code>install.sh</code> installer)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 or 24.04 LTS</strong> (24.04 recommended): they are the only Ubuntu releases Microsoft supports for SQL Server, and <strong>26.04 is not supported</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Same recommendation with MySQL, PostgreSQL and Oracle, because the installer is tested on those releases</td></tr><tr><td>NVIDIA GPU (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Optional: speeds up the RAG Chatbot (runs on CPU without it)</td></tr></tbody></table><p>> <strong>On Windows Server the database must be installed first.</strong> The one-liner pulls missing</p><p>> components through <code>winget</code>, which is not present on Windows Server: without an instance</p><p>> already reachable the installation stops with `No SQL Server instance reachable and winget is</p><p>> missing`. Install the engine before running the line - SQL Server must be <strong>2019 or newer</strong></p><p>> (Express is enough; <strong>2022 or newer</strong> for the <code>.bak</code> tutorial), and a 2017 instance is not</p><p>> accepted. If the instance is not the default one, pass it with</p><p>> <code>-SqlServer 'localhost\\INSTANCENAME'</code>. This applies to every engine, not just SQL Server.</p><h3>1. Download the project template</h3><p>On Windows one PowerShell line does all of it: it downloads the package, checks the .NET SDK 10</p><p>and Node.js 22 (installing what is missing), runs <code>dotnet restore</code> and <code>npm install</code>,</p><p>and installs the WUIC Assistant extension in VS Code.</p><p>Snippet 1:</p><p>Useful options on the same line: <code>-Dbms mysql</code> (or <code>postgres</code>, <code>oracle</code>) for an engine other</p><p>than SQL Server — the installer installs and configures it for you — and <code>-WithTutorial</code> to</p><p>download the sample database as well.</p><p>When it is done, the last screen is already your to-do list:</p><p>Snippet 2:</p><p>The connection string is ready to use: at first start the wizard asks for nothing else. With</p><p><code>-Dbms mysql</code> or <code>-Dbms postgres</code> that line changes accordingly and carries user and password</p><p>inside it, because the superuser password is <strong>generated by the installer</strong>; the same password</p><p>is saved in <code>wuic-secrets.json</code>, next to the installation, and that is the only place where it</p><p>stays written.</p><p>The manual path still works, on any operating system:</p><p>Start from the <code>WuicTest-src-*.zip</code> package (link in the <strong>Download</strong> section of the site).</p><p>Extract it to a working folder, e.g. <code>C:\\dev\\WuicTest</code> (files go directly at the root —</p><p>NOT inside a <code>src/</code> subfolder). The package contains:</p><ul><li><code>WuicTest.csproj</code> → host project with <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → Angular app whose <code>package.json</code> references <code>wuic-framework-lib</code> from the npm registry</li><li><code>appsettings.json</code> preconfigured in <code>firstRun = "true"</code> mode with <code>__SET_*__</code> placeholders</li><li><code>appsettings-samples/</code> → 6 ready templates (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>No need to clone the framework repository</strong>: <code>WuicCore</code> ships as a NuGet package from</p><p>> <code>nuget.org</code> and <code>wuic-framework-lib</code> as an npm package from the npm registry. The framework</p><p>> source is only needed if you want to modify it — typically not your case.</p><p>> <strong>npm 10.9.x and packages older than 1.7.1</strong>: those packages carry no <code>package-lock.json</code>, and</p><p>> without a lock npm 10.9.x (the version Node 22 LTS installs) stops with</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> while resolving peer dependencies.</p><p>> Download the lock published next to the release —</p><p>> <code>https://wuic-framework.com/downloads/locks/<zip-name>.package-lock.json</code> — drop it in <code>wwwroot/</code></p><p>> and run <code>npm install</code> again. The <code>-Src</code> one-liner does it for you.</p><h3>2. Database</h3><p>You need a reachable engine instance. <strong>With the one-liner there is nothing to do</strong>: it</p><p>installs and configures the instance, and the connection string to paste into the wizard is the</p><p>last thing it prints. On the manual path the instance must already exist.</p><p>Connections in <code>appsettings.json</code>:</p><ul><li><code>MetaDataSQLConnection</code> — metadata DB (menu, tables, columns, boards, users)</li><li><code>DataSQLConnection</code> — application data DB</li></ul><p>If this is the first installation (<code>AppSettings.firstRun = "true"</code> in the template),</p><p>the scaffolding wizard on first startup creates the metadata schema and populates the data DB.</p><p>See the <em>Initial Scaffolding</em> page for the guided flow.</p><p>#### What the first-run wizard asks for</p><p>On the first start the application does not show the login form but the **Initial project</p><p>setup** page. You fill it in once: when it finishes <code>firstRun</code> flips to <code>false</code> and the page</p><p>never comes back.</p><ul><li><strong>Setup mode</strong> — two entries: <strong>Existing database</strong>, which registers a database of your own,</li></ul><p> and <strong>Tutorial WideWorldImporters</strong>, which installs the sample database. The second one only</p><p> appears when the package ships the tutorial (<code>tutorialAvailable</code>): in packages without it the</p><p> dropdown is not rendered at all and the mode is "Existing database".</p><ul><li><strong>DBMS</strong> — the engine. Changing it rewrites the connection string below in the shape of the</li></ul><p> chosen provider.</p><ul><li><strong>DataSQLConnection</strong> — the string to the data database, and the field everything else</li></ul><p> depends on: until you press <strong>Test connection and load databases</strong> the database list stays</p><p> disabled. The test validates the credentials, lists the databases on the server and, on SQL</p><p> Server, fixes the certificate parameters for you</p><p> (<code>Encrypt=False;TrustServerCertificate=True</code>), telling you it did. <code>Integrated Security</code></p><p> only works on SQL Server: the other engines need a user and a password.</p><ul><li><strong>Data database</strong> and <strong>Metadata database name</strong> — the first is picked from the list the test</li></ul><p> loaded (in tutorial mode it is a free-text field, <code>WideWorldImporters</code> by default); the</p><p> second is the name of the metadata database to create (<code>metadataDB</code> by default,</p><p> <code>MetadataCRM</code> in tutorial mode). If that database already exists, the wizard asks before</p><p> recreating it.</p><ul><li><strong>Scaffold the tables automatically</strong> (only in "Existing database") — fills</li></ul><p> <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> from every table of the chosen database. It is</p><p> what lengthens provisioning the most on databases with many tables.</p><ul><li><strong>Initial admin user</strong> — username (<code>admin</code> by default), password (at least 4 characters) and</li></ul><p> language. There is no default password: the one you type here is the only one that will let</p><p> you in at the first login. The language you pick is applied to the admin user and to this</p><p> page itself.</p><ul><li><strong>RAG Chatbot</strong> — only the Anthropic key, and it is optional. Nothing to install: see step 5.</li></ul><p>Once you press <strong>Confirm and create the metadata database</strong> provisioning runs on its own, with</p><p>a progress bar and the number of batches processed. How long it takes, measured on the test</p><p>installations: <strong>30 s - 2 min</strong> in tutorial mode, <strong>1-4 min</strong> on an existing database with</p><p>automatic scaffolding enabled. When it ends, the page gives way to the login form.</p><h3>3. Backend (.NET)</h3><p>From the root of the extracted folder (e.g. <code>C:\\dev\\WuicTest</code>):</p><p>Snippet 3:</p><p>The backend exposes APIs on <code>http://localhost:5000</code>.</p><h3>4. Frontend (Angular)</h3><p>In a second shell, from the <code>wwwroot/</code> subfolder:</p><p>Snippet 4:</p><p>The frontend is available on <code>http://localhost:4200</code>.</p><p>The credentials are those of the admin user you chose in the first-run wizard: the username</p><p>is <code>admin</code> unless you changed it, and the password is the one you typed (there is no default</p><p>password).</p><h3>5. RAG Chatbot (optional)</h3><p>The RAG Chatbot (<code>Administration > RAG Chat</code>) runs <strong>inside the .NET backend</strong>:</p><p>the retrieval engine (<code>rag-engine/WuicRagEngine.dll</code>, in-process ONNX Runtime)</p><p>is loaded by the backend when <code>AppSettings.rag-use-dotnet-engine</code> is <code>"true"</code></p><p>(the default in release packages). **No Python, no venv, no separate server</p><p>to start.**</p><p>The <strong>first</strong> time the chatbot is opened (or at the end of the first run) the</p><p>backend downloads by itself the ONNX models (<code>bge-m3</code> + reranker), tokenizer</p><p>and index (~4.5 GB) from <code>rag-engine-models-url</code> (default</p><p><code>https://wuic-framework.com/rag-models</code>) into <code>rag-engine/artifacts/</code>. An</p><p>internet connection is needed only once; the download runs in the background</p><p>(1-5 min) and an in-app notification is sent when it starts and when it ends.</p><p>Meanwhile the component shows the <strong>RAG offline</strong> status and the rest of the</p><p>application works normally.</p><p>Relevant <code>AppSettings</code> keys (all with ready defaults):</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — enables the .NET engine (<code>false</code> = Python fallback, see below)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code>: with an NVIDIA GPU (CUDA 12.x + cuDNN 9) ~1 s/query, on CPU ~15-25 s/query</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = framework sources as signatures only; <code>internal</code> = full index</li><li><code>rag-engine-models-url</code> — download source on first start</li><li><code>rag-engine-cuda-path</code> = (empty) — folder of the CUDA/cuDNN DLLs when they are not installed system-wide</li></ul><p>For LLM chat set <code>rag-llm-provider</code> + <code>rag-llm-api-key</code> (Claude via Anthropic,</p><p>or a local model via Ollama with <code>rag-llm-base-url</code>). Without a provider only</p><p>the retrieval mode (snippet search) works. Key details on the <em>AppSettings</em></p><p>page.</p><p>> The legacy Python stack (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> on</p><p>> <code>127.0.0.1:8765</code>) is only usable as a fallback with</p><p>> <code>rag-use-dotnet-engine = "false"</code> and is not shipped in release packages.</p><h2>Services Summary</h2><table><thead><tr><th>Service</th><th>Port</th><th>Required</th><th>Quick command</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>yes</td><td>(Windows service)</td></tr><tr><td>.NET Backend</td><td>5000</td><td>yes</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Angular Frontend</td><td>4200</td><td>yes</td><td><code>npm run serve:dev</code></td></tr><tr><td>.NET RAG engine (ONNX)</td><td>in-process</td><td>no</td><td>loaded by the backend on the first chat</td></tr></tbody></table><h2>Quick Start — First Component</h2><p>1. Configure the AsmxProxy endpoint.</p><p>2. Define route metadata and columns.</p><p>3. Mount <code>wuic-data-source</code> + <code>wuic-data-repeater</code>.</p><p>Snippet 5:</p><h2>The first lists show 20 records: that is Trial mode</h2><p>A fresh install runs <strong>without a license</strong>, that is, in Trial mode, and in that mode</p><p><strong>every query is capped at 20 records</strong>. It is neither a bug nor a database limit: a list</p><p>that reads "20 of 20" on a table with thousands of rows is simply running unlicensed.</p><p>How to confirm it in a second:</p><p>Snippet 6:</p><p><code>licenseValid: false</code> confirms the Trial, and <code>licenseReason</code> says why</p><p>(<code>invalid_signature</code>, <code>license_expired</code>, <code>machine_fingerprint_not_authorized</code>, ...).</p><p>How to get out of it: paste the license from <strong>Administration > AppSettings Editor</strong>, Licensing</p><p>tab, and it takes effect immediately - no backend restart needed. The details, including the</p><p>limits the Trial imposes beyond the record count, are in the <a href=\"licensing.md\">Licensing</a> page.</p>",
|
|
7865
7887
|
"codeSamples": [
|
|
7866
7888
|
{
|
|
7867
7889
|
"id": "code_1",
|
|
@@ -7873,25 +7895,31 @@ const frameworkDocsContent = {
|
|
|
7873
7895
|
"id": "code_2",
|
|
7874
7896
|
"title": "Snippet 2",
|
|
7875
7897
|
"language": "text",
|
|
7876
|
-
"code": "Developer workspace ready: C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\
|
|
7898
|
+
"code": "Developer workspace ready: C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\n\n code \"C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\\WuicTest.code-workspace\"\n then F5 > 'Fullstack: WuicTest + Chrome' (backend http://localhost:5000, frontend http://localhost:4200)\n\nFirst start opens the first-run wizard: paste this connection string (Windows authentication)\n Data Source=localhost\\SQLEXPRESS;Integrated Security=SSPI;Initial Catalog=WuicData;Encrypt=False;TrustServerCertificate=True\nRename the project: .\\rename-project.ps1 -Name MyApp"
|
|
7877
7899
|
},
|
|
7878
7900
|
{
|
|
7879
7901
|
"id": "code_3",
|
|
7880
7902
|
"title": "Snippet 3",
|
|
7881
7903
|
"language": "powershell",
|
|
7882
|
-
"code": "# First run: restore NuGet packages (pulls WuicCore + deps from nuget.org, ~30 s)\
|
|
7904
|
+
"code": "# First run: restore NuGet packages (pulls WuicCore + deps from nuget.org, ~30 s)\ndotnet restore\n\n# Start dev with hot reload\n$env:ASPNETCORE_ENVIRONMENT = 'Development'\ndotnet watch run\n\n# Or one-shot start (no hot reload)\ndotnet run"
|
|
7883
7905
|
},
|
|
7884
7906
|
{
|
|
7885
7907
|
"id": "code_4",
|
|
7886
7908
|
"title": "Snippet 4",
|
|
7887
7909
|
"language": "powershell",
|
|
7888
|
-
"code": "cd wwwroot\
|
|
7910
|
+
"code": "cd wwwroot\n\n# First run: restore npm dependencies (pulls wuic-framework-lib from npm registry, ~2 min)\nnpm install\n\n# Start dev server\nnpm run serve:dev"
|
|
7889
7911
|
},
|
|
7890
7912
|
{
|
|
7891
7913
|
"id": "code_5",
|
|
7892
7914
|
"title": "Snippet 5",
|
|
7893
7915
|
"language": "html",
|
|
7894
|
-
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\
|
|
7916
|
+
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\n<wuic-data-repeater [hardcodedAction]=\"'list'\"></wuic-data-repeater>"
|
|
7917
|
+
},
|
|
7918
|
+
{
|
|
7919
|
+
"id": "code_6",
|
|
7920
|
+
"title": "Snippet 6",
|
|
7921
|
+
"language": "bash",
|
|
7922
|
+
"code": "curl -s http://localhost:5000/api/Meta/LicenseStatus"
|
|
7895
7923
|
}
|
|
7896
7924
|
]
|
|
7897
7925
|
}
|
|
@@ -7926,18 +7954,22 @@ const frameworkDocsContent = {
|
|
|
7926
7954
|
"toc": [
|
|
7927
7955
|
{
|
|
7928
7956
|
"id": "sec_1",
|
|
7929
|
-
"title": "
|
|
7957
|
+
"title": "With a tutorial package there is nothing to scaffold"
|
|
7930
7958
|
},
|
|
7931
7959
|
{
|
|
7932
7960
|
"id": "sec_2",
|
|
7933
|
-
"title": "
|
|
7961
|
+
"title": "When to Use It"
|
|
7934
7962
|
},
|
|
7935
7963
|
{
|
|
7936
7964
|
"id": "sec_3",
|
|
7937
|
-
"title": "
|
|
7965
|
+
"title": "Behavior with firstRun=true"
|
|
7938
7966
|
},
|
|
7939
7967
|
{
|
|
7940
7968
|
"id": "sec_4",
|
|
7969
|
+
"title": "Typical Operations"
|
|
7970
|
+
},
|
|
7971
|
+
{
|
|
7972
|
+
"id": "sec_5",
|
|
7941
7973
|
"title": "After Provisioning"
|
|
7942
7974
|
}
|
|
7943
7975
|
],
|
|
@@ -7945,7 +7977,7 @@ const frameworkDocsContent = {
|
|
|
7945
7977
|
{
|
|
7946
7978
|
"id": "overview",
|
|
7947
7979
|
"title": "Overview",
|
|
7948
|
-
"html": "<h1>Initial Scaffolding</h1><p>This page describes the initial bootstrap when <code>AppSettings.firstRun = true</code>.</p><h2>When to Use It</h2><ul><li>New installation (metadata/data DB not yet ready).</li><li>Local environment to realign with initial setup.</li><li>First launch after deploy where you want to force the guided provisioning procedure.</li></ul><h2>Behavior with firstRun=true</h2><ul><li>The <code>GET /api/Meta/FirstRunStatus</code> endpoint exposes <code>firstRun: true</code>.</li><li>At login, the first run flow appears (e.g., <code>Update</code> action on the screen).</li><li>The setup applies base configurations (connections, runtime settings, metadata bootstrap).</li></ul><h2>Typical Operations</h2><ul><li>Verify <code>AppSettings.firstRun</code> is <code>true</code> in <code>appsettings.{Environment}.json</code> of the host you are running.</li><li>Start the application and complete the initial scaffolding procedure from the UI.</li><li>Check that connections and main parameters are consistent (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>After Provisioning</h2><ul><li>The setup procedure sets <code>firstRun</code> to <code>false</code> to avoid re-executions on each start.</li><li>Perform a standard login and validate access to the main routes.</li></ul>",
|
|
7980
|
+
"html": "<h1>Initial Scaffolding</h1><p>This page describes the initial bootstrap when <code>AppSettings.firstRun = true</code>.</p><h2>With a tutorial package there is nothing to scaffold</h2><p>The scaffolding this page is about — reading the tables of a database and registering them in</p><p><code>_metadati__tabelle</code> / <code>_metadati__colonne</code> — applies <strong>only</strong> to the "Existing database" mode of</p><p>the first-run wizard: that is where the *Scaffold the tables of the selected database</p><p>automatically* checkbox lives.</p><p>In <strong>tutorial</strong> packages that checkbox does not exist. The metadata database arrives already</p><p>populated (routes, columns, menu, translations, sample dashboards) and the wizard only restores</p><p>it and creates the admin user. Seeing ready-made routes right after the first start is therefore</p><p>not the result of scaffolding: it is the content of the tutorial.</p><table><thead><tr><th>Wizard mode</th><th>What happens to the metadata</th></tr></thead><tbody><tr><td>Tutorial WideWorldImporters</td><td>Metadata already built, restored from the package. No scaffolding at all.</td></tr><tr><td>Existing database, checkbox off</td><td>An empty metadata database: you register the routes yourself, by hand or later from the Scaffolding page.</td></tr><tr><td>Existing database, checkbox on</td><td>At the end of the installation every table of the chosen database is registered as a route.</td></tr></tbody></table><p>The rest of this page applies to the last two rows of that table.</p><h2>When to Use It</h2><ul><li>New installation (metadata/data DB not yet ready).</li><li>Local environment to realign with initial setup.</li><li>First launch after deploy where you want to force the guided provisioning procedure.</li></ul><h2>Behavior with firstRun=true</h2><ul><li>The <code>GET /api/Meta/FirstRunStatus</code> endpoint exposes <code>firstRun: true</code>.</li><li>At login, the first run flow appears (e.g., <code>Update</code> action on the screen).</li><li>The setup applies base configurations (connections, runtime settings, metadata bootstrap).</li></ul><h2>Typical Operations</h2><ul><li>Verify <code>AppSettings.firstRun</code> is <code>true</code> in <code>appsettings.{Environment}.json</code> of the host you are running.</li><li>Start the application and complete the initial scaffolding procedure from the UI.</li><li>Check that connections and main parameters are consistent (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>After Provisioning</h2><ul><li>The setup procedure sets <code>firstRun</code> to <code>false</code> to avoid re-executions on each start.</li><li>Perform a standard login and validate access to the main routes.</li></ul>",
|
|
7949
7981
|
"codeSamples": []
|
|
7950
7982
|
}
|
|
7951
7983
|
],
|
|
@@ -8004,7 +8036,7 @@ const frameworkDocsContent = {
|
|
|
8004
8036
|
{
|
|
8005
8037
|
"id": "overview",
|
|
8006
8038
|
"title": "Overview",
|
|
8007
|
-
"html": "<h1>Licensing</h1><p>This page explains licensing from the end user's perspective: what is needed, how to obtain the license, and how to apply it.</p><h2>How to obtain a license</h2><p>Review plans, included features per tier (Developer / Professional / Software House) and purchase on the public site:</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">WUIC pricing and plans — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Contact sales</a> — no license is needed to evaluate: without one the framework runs in Trial mode (20 records per query)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">WUIC homepage</a></li></ul><p>After purchase you will receive an email with <code>license-payload</code> + <code>license-signature</code> to install as described in the "End User Procedure" below.</p><h2>How It Works</h2><ul><li>The license is valid only if:</li><li>correct signature.</li><li><code>machineFingerprint</code> of the current server is present in the <code>machineFingerprints</code> list of the signed payload.</li><li>If the license is not valid, data reading (<code>getFlatRecordData</code>) is limited to a maximum of 20 records. Additionally, the host hook <code>customizeSelect</code> is bypassed (not invoked).</li></ul><h2>Where to Find the machineFingerprint</h2><p>Backend endpoint:</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → field <code>machineFingerprint</code> (always available, even without a license).</li><li>During the first run it is also exposed by <code>GET /api/Meta/FirstRunStatus</code>.</li></ul><p>Note: the local file <code>installation.id</code> is no longer used by licensing.</p><h2>End User Procedure</h2><p>1. Retrieve <code>machineFingerprint</code> from your host.</p><p>2. Send the value to the vendor/licensor.</p><p>3. Receive the license values:</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (if required by your installation)</li></ul><p>4.
|
|
8039
|
+
"html": "<h1>Licensing</h1><p>This page explains licensing from the end user's perspective: what is needed, how to obtain the license, and how to apply it.</p><h2>How to obtain a license</h2><p>Review plans, included features per tier (Developer / Professional / Software House) and purchase on the public site:</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">WUIC pricing and plans — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Contact sales</a> — no license is needed to evaluate: without one the framework runs in Trial mode (20 records per query)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">WUIC homepage</a></li></ul><p>After purchase you will receive an email with <code>license-payload</code> + <code>license-signature</code> to install as described in the "End User Procedure" below.</p><h2>How It Works</h2><ul><li>The license is valid only if:</li><li>correct signature.</li><li><code>machineFingerprint</code> of the current server is present in the <code>machineFingerprints</code> list of the signed payload.</li><li>If the license is not valid, data reading (<code>getFlatRecordData</code>) is limited to a maximum of 20 records. Additionally, the host hook <code>customizeSelect</code> is bypassed (not invoked).</li></ul><h2>Where to Find the machineFingerprint</h2><p>Backend endpoint:</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → field <code>machineFingerprint</code> (always available, even without a license).</li><li>During the first run it is also exposed by <code>GET /api/Meta/FirstRunStatus</code>.</li></ul><p>Note: the local file <code>installation.id</code> is no longer used by licensing.</p><h2>End User Procedure</h2><p>1. Retrieve <code>machineFingerprint</code> from your host.</p><p>2. Send the value to the vendor/licensor.</p><p>3. Receive the license values:</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (if required by your installation)</li></ul><p>4. Paste the values from the UI: <strong>Administration > AppSettings Editor</strong>, <strong>License</strong> section</p><p> (fields <code>License email</code>, <code>License payload</code>, <code>License signature</code>, <code>Public key (PEM)</code>), then</p><p> save. Alternatively you can write them by hand in the <code>AppSettings</code> section of the running</p><p> host's <code>appsettings.{Environment}.json</code>.</p><p>5. Verify the license status:</p><ul><li>from the API: <code>GET /api/Meta/LicenseStatus</code>, expected <code>licenseValid = true</code>;</li><li>or from the page itself, which re-reads the license right after saving.</li></ul><p><strong>No backend restart is needed when you go through the editor.</strong> Saving <code>license-payload</code> /</p><p><code>license-signature</code> from the AppSettings Editor makes the backend refresh the validation</p><p>service on its own, and the license applies from the next request. A restart is only needed in</p><p>the other case, when the values are written by hand in the file: that one is read at startup.</p><h2>Multi-Machine License</h2><p>A single license can authorize multiple machines by including multiple values in <code>machineFingerprints</code>.</p><h2>Quick Troubleshooting</h2><ul><li><code>licenseReason = invalid_signature</code>:</li><li>payload/signature are not consistent with each other or the public key is different.</li><li><code>licenseReason = machine_fingerprint_not_authorized</code>:</li><li>the current machine's fingerprint is not present in the received license.</li><li><code>licenseReason = machine_fingerprint_missing</code>:</li><li>the runtime cannot calculate the local fingerprint.</li><li><code>licenseReason = license_expired</code>:</li><li>the license has expired, request renewal.</li></ul>",
|
|
8008
8040
|
"codeSamples": []
|
|
8009
8041
|
}
|
|
8010
8042
|
],
|
|
@@ -8679,42 +8711,46 @@ const frameworkDocsContent = {
|
|
|
8679
8711
|
},
|
|
8680
8712
|
{
|
|
8681
8713
|
"id": "sec_2",
|
|
8682
|
-
"title": "
|
|
8714
|
+
"title": "What the toolbar shows by default"
|
|
8683
8715
|
},
|
|
8684
8716
|
{
|
|
8685
8717
|
"id": "sec_3",
|
|
8686
|
-
"title": "
|
|
8718
|
+
"title": "Screenshot Reference (User Manual)"
|
|
8687
8719
|
},
|
|
8688
8720
|
{
|
|
8689
8721
|
"id": "sec_4",
|
|
8690
|
-
"title": "
|
|
8722
|
+
"title": "Inline Editing Metadata"
|
|
8691
8723
|
},
|
|
8692
8724
|
{
|
|
8693
8725
|
"id": "sec_5",
|
|
8694
|
-
"title": "
|
|
8726
|
+
"title": "Toolbar Export/Import"
|
|
8695
8727
|
},
|
|
8696
8728
|
{
|
|
8697
8729
|
"id": "sec_6",
|
|
8698
|
-
"title": "
|
|
8730
|
+
"title": "Metadata Config"
|
|
8699
8731
|
},
|
|
8700
8732
|
{
|
|
8701
8733
|
"id": "sec_7",
|
|
8702
|
-
"title": "md_props_bag:
|
|
8734
|
+
"title": "md_props_bag: toolbar"
|
|
8703
8735
|
},
|
|
8704
8736
|
{
|
|
8705
8737
|
"id": "sec_8",
|
|
8706
|
-
"title": "
|
|
8738
|
+
"title": "md_props_bag: archetypes.list"
|
|
8707
8739
|
},
|
|
8708
8740
|
{
|
|
8709
8741
|
"id": "sec_9",
|
|
8710
|
-
"title": "
|
|
8742
|
+
"title": "Paging: md_pagesize and md_page_size_choice"
|
|
8711
8743
|
},
|
|
8712
8744
|
{
|
|
8713
8745
|
"id": "sec_10",
|
|
8714
|
-
"title": "
|
|
8746
|
+
"title": "Forced Virtualization on High Page Size"
|
|
8715
8747
|
},
|
|
8716
8748
|
{
|
|
8717
8749
|
"id": "sec_11",
|
|
8750
|
+
"title": "Events and Subscriptions (Host)"
|
|
8751
|
+
},
|
|
8752
|
+
{
|
|
8753
|
+
"id": "sec_12",
|
|
8718
8754
|
"title": "`rowCustomSelect` — actual signature (gotcha)"
|
|
8719
8755
|
}
|
|
8720
8756
|
],
|
|
@@ -8722,7 +8758,7 @@ const frameworkDocsContent = {
|
|
|
8722
8758
|
{
|
|
8723
8759
|
"id": "overview",
|
|
8724
8760
|
"title": "Overview",
|
|
8725
|
-
"html": "<h1>List Grid</h1><p>Main component for tabular lists with filters, sorting, server-side paging, and row actions.</p><h2>Use Cases</h2><ul><li>Enterprise tabular CRUD.</li><li>Operational reports with multi-column filters.</li><li>Very large datasets with <code>cursorMode</code>.</li></ul><h2>Screenshot Reference (User Manual)</h2><ul><li><code>manual__grid__01.png</code>: <code>inline cell edit</code> mode in list-grid.</li><li><code>manual__grid__02.png</code>: <code>inline edit</code> (row-level) mode in list-grid.</li></ul><h2>Inline Editing Metadata</h2><p>Configuration in the table metadata <code>md_props_bag</code>:</p><ul><li><code>md_inline_edit</code></li></ul><p> - Enables inline row editing in list-grid (editable cells in row context, without opening a popup).</p><p> - Useful when you want to maintain the table UX with quick editing per record.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - Enables "cell-by-cell" inline editing (focus on the individual cell).</p><p> - Note: in legacy configurations it may appear as <code>md_inline_cell_editing</code>; the runtime behavior is the same.</p><p> - <strong>Runtime promotion</strong>: when <code>md_inline_cell_edit</code> is <code>true</code>, the component forces</p><p> <code>md_inline_edit = true</code> at runtime regardless of the DB value.</p><p> Both UX modes need the action column visible, so they are mutually</p><p> non-exclusive at the rendering level.</p><ul><li><code>md_batch_save</code></li></ul><p> - Enables batch saving of pending changes (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - When used with inline-cell, changes remain pending until explicit save.</p><p> - <strong>Prerequisite</strong>: <code>md_batch_save</code> takes effect <strong>only</strong> if <code>md_inline_cell_edit</code> is <code>true</code>.</p><p> With <code>md_inline_cell_edit:false</code> the flag is ignored at runtime and the</p><p> "Save changes / Cancel changes" buttons are not rendered.</p><h3>Valid Combinations</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Runtime Result</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>any</td><td>Row-level inline edit with pencil. <code>md_batch_save</code> ignored.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Cell-by-cell autosave on blur. <code>md_inline_edit</code> forced to <code>true</code> at runtime.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Cell-by-cell with pending buffer + <code>Save / Cancel changes</code> toolbar.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>any</td><td>No inline editing. <code>md_batch_save</code> ignored.</td></tr></tbody></table><p>Row-level inline edit example:</p><p>Snippet 1:</p><p>Cell-by-cell with batch save example:</p><p>Snippet 2:</p><h2>Toolbar Export/Import</h2><ul><li>Export XLS:</li></ul><p> - Shows a progress dialog with real-time percentage;</p><p> - Actions: <code>Continue in background</code>, <code>Cancel task</code>, <code>Stop and download partial</code>;</p><p> - In background creates a notification with progress; click reopens the dialog.</p><ul><li>Import XLS/XLSX (if <code>md_importable = true</code>):</li></ul><p> - Progress dialog after confirmation;</p><p> - Actions: <code>Continue in background</code>, <code>Cancel import (rollback)</code>, <code>Stop and partial commit</code>;</p><p> - At the end of import creates a summary notification that navigates to the route.</p><h2>Metadata Config</h2><p>Key settings in <code>md_props_bag</code> and column metadata.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Opt-in flags that hide blocks of the list-grid toolbar (<code>caption-bar</code>). All under <code>md_props_bag.toolbar.*</code> (parsed at runtime as <code>tableMetadata.extraProps.toolbar</code>).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, default <code>false</code>): hides in the <strong>caption-right</strong> the "Manage state" button (bookmark icon) + the saved-states <code><select></code>. Useful for hardcoded / demo routes where the saved-state feature (persistence per <code>user_id</code> + route via <code>MetaService</code>) doesn't make sense — e.g. Pattern 3 pure OData without registered route metadata.</li><li><code>hideBatchActions</code> (boolean, default <code>false</code>): hides in the <strong>caption-left</strong> the "Save changes" (<code>pi-save</code>) + "Discard changes" (<code>pi-times</code>) buttons + the changes count indicator (<code>grid-changes-indicator</code>, pencil badge + count). Generated by the framework when <code>md_inline_cell_editing</code> + <code>md_batch_save</code> are active. Designed for <strong>nested grids inside a parametric-dialog</strong>: the parent's save/cancel persists master + rows in one shot via the framework batch save, and the duplicate buttons on the nested grid confuse the UX.</li></ul><p>Example nested rows in custom edit-form (runtime patch):</p><p>Snippet 5:</p><p>TS type in <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (<code>extraProps.toolbar</code> property). The flags do NOT disable the underlying <code>md_batch_save</code> logic (changes are still tracked); they only remove the toolbar UI — the actual save flows through the parent.</p><h2>md_props_bag: archetypes.list</h2><p>The component reads <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code>:</li><li>type: boolean (with tolerant parser)</li><li>accepted values: <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>runtime default: <code>true</code> when absent or empty</li><li>effect: distributes column widths proportionally (instead of px) when no user-persisted widths exist.</li></ul><ul><li><code>virtualize</code>:</li><li>type: <code>boolean</code> or <code>object</code></li><li>accepted values:</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>object with <code>enabled</code> (optional) and <code>itemSize</code> (optional)</li><li>runtime default: disabled (<code>false</code>) when absent</li><li><code>enabled</code>:</li><li>default: <code>true</code> if the <code>virtualize</code> node is an object without <code>enabled</code>, otherwise tolerant parser</li><li>effect: enables <code>virtualScroll</code> on <code>p-table</code></li><li><code>itemSize</code>:</li><li>default: <code>44</code></li><li>effect: sets <code>virtualScrollItemSize</code> (virtual row height in px)</li></ul><ul><li><code>advancedFilter</code>:</li><li>type: boolean (with tolerant parser)</li><li>runtime default: <code>false</code></li><li>effect:</li><li>when <code>true</code>, the grid hides column filter icons (<code>p-columnFilter</code>) and uses the <code>wuic-filter-bar</code> above the table (at <code>data-repeater</code>/<code>bounded-repeater</code> level) to apply filters.</li></ul><p>Operational note:</p><ul><li>The <code>md_props_bag</code> suggest in the metadata editor also exposes the checkable <code>archetypes.list.advancedFilter</code> node.</li></ul><h2>Paging: md_pagesize and md_page_size_choice</h2><p>The grid uses <code>md_pagesize</code> as the default page size and <code>md_page_size_choice</code> as the list of selectable values in the paginator.</p><p>Runtime rules:</p><ul><li>If <code>md_pagesize</code> is greater than the maximum value present in <code>md_page_size_choice</code>, the framework automatically adds <code>md_pagesize</code> to the options list;</li><li>The list is normalized (valid numbers, deduplication, ascending sort).</li></ul><p>Example:</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>runtime result: <code>10,25,50,100,200</code></li></ul><h2>Forced Virtualization on High Page Size</h2><p>When the user selects in the paginator a <code>pageSize >= 1000</code>:</p><ul><li>virtualization is automatically forced even if <code>md_props_bag.archetypes.list.virtualize</code> is absent or disabled;</li><li><code>virtualScrollItemSize</code> is forced to the default value <code>44</code>.</li></ul><p>This behavior protects the table rendering on very large pages.</p><h2>Events and Subscriptions (Host)</h2><p><code>wuic-list-grid</code> exposes runtime events useful for intercepting the render cycle and p-table callbacks on the host project side.</p><p>Available events:</p><ul><li><code>onAfterRender</code>: emitted at the end of grid data binding (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code>: emitted before the logical rendering of a single row; supports cancel via <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code>: emitted after the logical rendering of a single row.</li><li><code>onPaging</code>: emitted on paging events (<code>p-table onPage</code>).</li><li><code>onSorting</code>: emitted on sorting events (<code>p-table onSort</code>).</li><li><code>onFiltering</code>: emitted on filtering events (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code>: emitted on row selection change.</li><li><code>onPTableRowExpand</code>: emitted on row expand.</li><li><code>onPTableRowCollapse</code>: emitted on row collapse.</li><li><code>onPTableColumnResize</code>: emitted on column resize.</li><li><code>onPTableColumnReorder</code>: emitted on column reorder.</li></ul><h3>Example 1: Direct Binding in Template</h3><p>Snippet 7:</p><h3>Example 2: Subscribe via ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — actual signature (gotcha)</h2><p><code><wuic-list-grid></code> accepts a <code>[rowCustomSelect]</code> input to hook into row selection (opening a "pick a document" dialog, master-detail flow, etc.). The TypeScript signature declared in <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> reads:</p><p>Snippet 9:</p><p><strong>However at runtime the callback is invoked with arguments reversed</strong> — the framework calls <code>rowCustomSelect($event, rowData, dt)</code> (see <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> and <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Symptom of wrong arg order: <code>rowData?.id</code> is undefined → early-return guard in your handler → the callback returns silently and your dialog/action never fires. No console error.</p><p>Correct form (matches runtime invocation):</p><p>Snippet 10:</p><p>Template usage:</p><p>Snippet 11:</p><p>> Note: tests in <code>designer.component.spec.ts</code> (e.g. line 512) invoke the callback with <code>({currentTarget: rowCell}, {id: 42}, null)</code>, confirming the <code>($event, rowData, dt)</code> order. If the framework eventually aligns the declared signature, this page will be updated as well.</p>",
|
|
8761
|
+
"html": "<h1>List Grid</h1><p>Main component for tabular lists with filters, sorting, server-side paging, and row actions.</p><h2>Use Cases</h2><ul><li>Enterprise tabular CRUD.</li><li>Operational reports with multi-column filters.</li><li>Very large datasets with <code>cursorMode</code>.</li></ul><h2>What the toolbar shows by default</h2><p>When you open a freshly scaffolded route, the caption bar sits above the grid. On the left:</p><table><thead><tr><th>Button</th><th>When it appears</th></tr></thead><tbody><tr><td><strong>Refresh</strong></td><td>always, unless <code>md_hide_refresh</code></td></tr><tr><td><strong>Add</strong></td><td>with <code>md_insertable</code></td></tr><tr><td><strong>Actions</strong></td><td>if the table has custom actions</td></tr><tr><td>Import / Export</td><td>always; the import branch only with <code>md_importable</code></td></tr><tr><td><strong>Reports</strong></td><td>if at least one report is bound to the route</td></tr><tr><td><strong>Save changes</strong> / <strong>Discard changes</strong></td><td>only with <code>md_inline_cell_edit</code> <strong>and</strong> <code>md_batch_save</code></td></tr></tbody></table><p>On the right: <strong>Manage state</strong> (preceded by the saved-states dropdown, when there are any),</p><p><strong>Clear filters</strong> when filters live on the columns, and <strong>Performance</strong> if the inspector is</p><p>enabled on the route.</p><p>> The captions quoted further down this page <strong>are not on that screen</strong>, and that is not a</p><p>> defect: the export/import ones (<em>Continue in background</em>, <em>Cancel task</em>, *Stop and download</p><p>> partial<em>, </em>Cancel import (rollback)<em>, </em>Stop and commit partial*) live in the progress dialog,</p><p>> which only exists while an export or import is running; <em>Save changes</em> and <em>Discard changes</em></p><p>> only appear with the two flags above. They belong to moments other than first opening the</p><p>> list.</p><h2>Screenshot Reference (User Manual)</h2><ul><li><code>manual__grid__01.png</code>: <code>inline cell edit</code> mode in list-grid.</li><li><code>manual__grid__02.png</code>: <code>inline edit</code> (row-level) mode in list-grid.</li></ul><h2>Inline Editing Metadata</h2><p>Configuration in the table metadata <code>md_props_bag</code>:</p><ul><li><code>md_inline_edit</code></li></ul><p> - Enables inline row editing in list-grid (editable cells in row context, without opening a popup).</p><p> - Useful when you want to maintain the table UX with quick editing per record.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - Enables "cell-by-cell" inline editing (focus on the individual cell).</p><p> - Note: in legacy configurations it may appear as <code>md_inline_cell_editing</code>; the runtime behavior is the same.</p><p> - <strong>Runtime promotion</strong>: when <code>md_inline_cell_edit</code> is <code>true</code>, the component forces</p><p> <code>md_inline_edit = true</code> at runtime regardless of the DB value.</p><p> Both UX modes need the action column visible, so they are mutually</p><p> non-exclusive at the rendering level.</p><ul><li><code>md_batch_save</code></li></ul><p> - Enables batch saving of pending changes (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - When used with inline-cell, changes remain pending until explicit save.</p><p> - <strong>Prerequisite</strong>: <code>md_batch_save</code> takes effect <strong>only</strong> if <code>md_inline_cell_edit</code> is <code>true</code>.</p><p> With <code>md_inline_cell_edit:false</code> the flag is ignored at runtime and the</p><p> "Save changes / Cancel changes" buttons are not rendered.</p><h3>Valid Combinations</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Runtime Result</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>any</td><td>Row-level inline edit with pencil. <code>md_batch_save</code> ignored.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Cell-by-cell autosave on blur. <code>md_inline_edit</code> forced to <code>true</code> at runtime.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Cell-by-cell with pending buffer + <code>Save / Cancel changes</code> toolbar.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>any</td><td>No inline editing. <code>md_batch_save</code> ignored.</td></tr></tbody></table><p>Row-level inline edit example:</p><p>Snippet 1:</p><p>Cell-by-cell with batch save example:</p><p>Snippet 2:</p><h2>Toolbar Export/Import</h2><ul><li>Export XLS:</li></ul><p> - Shows a progress dialog with real-time percentage;</p><p> - Actions: <code>Continue in background</code>, <code>Cancel task</code>, <code>Stop and download partial</code>;</p><p> - In background creates a notification with progress; click reopens the dialog.</p><ul><li>Import XLS/XLSX (if <code>md_importable = true</code>):</li></ul><p> - Progress dialog after confirmation;</p><p> - Actions: <code>Continue in background</code>, <code>Cancel import (rollback)</code>, <code>Stop and partial commit</code>;</p><p> - At the end of import creates a summary notification that navigates to the route.</p><h2>Metadata Config</h2><p>Key settings in <code>md_props_bag</code> and column metadata.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Opt-in flags that hide blocks of the list-grid toolbar (<code>caption-bar</code>). All under <code>md_props_bag.toolbar.*</code> (parsed at runtime as <code>tableMetadata.extraProps.toolbar</code>).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, default <code>false</code>): hides in the <strong>caption-right</strong> the "Manage state" button (bookmark icon) + the saved-states <code><select></code>. Useful for hardcoded / demo routes where the saved-state feature (persistence per <code>user_id</code> + route via <code>MetaService</code>) doesn't make sense — e.g. Pattern 3 pure OData without registered route metadata.</li><li><code>hideBatchActions</code> (boolean, default <code>false</code>): hides in the <strong>caption-left</strong> the "Save changes" (<code>pi-save</code>) + "Discard changes" (<code>pi-times</code>) buttons + the changes count indicator (<code>grid-changes-indicator</code>, pencil badge + count). Generated by the framework when <code>md_inline_cell_editing</code> + <code>md_batch_save</code> are active. Designed for <strong>nested grids inside a parametric-dialog</strong>: the parent's save/cancel persists master + rows in one shot via the framework batch save, and the duplicate buttons on the nested grid confuse the UX.</li></ul><p>Example nested rows in custom edit-form (runtime patch):</p><p>Snippet 5:</p><p>TS type in <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (<code>extraProps.toolbar</code> property). The flags do NOT disable the underlying <code>md_batch_save</code> logic (changes are still tracked); they only remove the toolbar UI — the actual save flows through the parent.</p><h2>md_props_bag: archetypes.list</h2><p>The component reads <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code>:</li><li>type: boolean (with tolerant parser)</li><li>accepted values: <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>runtime default: <code>true</code> when absent or empty</li><li>effect: distributes column widths proportionally (instead of px) when no user-persisted widths exist.</li></ul><ul><li><code>virtualize</code>:</li><li>type: <code>boolean</code> or <code>object</code></li><li>accepted values:</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>object with <code>enabled</code> (optional) and <code>itemSize</code> (optional)</li><li>runtime default: disabled (<code>false</code>) when absent</li><li><code>enabled</code>:</li><li>default: <code>true</code> if the <code>virtualize</code> node is an object without <code>enabled</code>, otherwise tolerant parser</li><li>effect: enables <code>virtualScroll</code> on <code>p-table</code></li><li><code>itemSize</code>:</li><li>default: <code>44</code></li><li>effect: sets <code>virtualScrollItemSize</code> (virtual row height in px)</li></ul><ul><li><code>advancedFilter</code>:</li><li>type: boolean (with tolerant parser)</li><li>runtime default: <code>false</code></li><li>effect:</li><li>when <code>true</code>, the grid hides column filter icons (<code>p-columnFilter</code>) and uses the <code>wuic-filter-bar</code> above the table (at <code>data-repeater</code>/<code>bounded-repeater</code> level) to apply filters.</li></ul><p>Operational note:</p><ul><li>The <code>md_props_bag</code> suggest in the metadata editor also exposes the checkable <code>archetypes.list.advancedFilter</code> node.</li></ul><h2>Paging: md_pagesize and md_page_size_choice</h2><p>The grid uses <code>md_pagesize</code> as the default page size and <code>md_page_size_choice</code> as the list of selectable values in the paginator.</p><p>Runtime rules:</p><ul><li>If <code>md_pagesize</code> is greater than the maximum value present in <code>md_page_size_choice</code>, the framework automatically adds <code>md_pagesize</code> to the options list;</li><li>The list is normalized (valid numbers, deduplication, ascending sort).</li></ul><p>Example:</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>runtime result: <code>10,25,50,100,200</code></li></ul><h2>Forced Virtualization on High Page Size</h2><p>When the user selects in the paginator a <code>pageSize >= 1000</code>:</p><ul><li>virtualization is automatically forced even if <code>md_props_bag.archetypes.list.virtualize</code> is absent or disabled;</li><li><code>virtualScrollItemSize</code> is forced to the default value <code>44</code>.</li></ul><p>This behavior protects the table rendering on very large pages.</p><h2>Events and Subscriptions (Host)</h2><p><code>wuic-list-grid</code> exposes runtime events useful for intercepting the render cycle and p-table callbacks on the host project side.</p><p>Available events:</p><ul><li><code>onAfterRender</code>: emitted at the end of grid data binding (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code>: emitted before the logical rendering of a single row; supports cancel via <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code>: emitted after the logical rendering of a single row.</li><li><code>onPaging</code>: emitted on paging events (<code>p-table onPage</code>).</li><li><code>onSorting</code>: emitted on sorting events (<code>p-table onSort</code>).</li><li><code>onFiltering</code>: emitted on filtering events (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code>: emitted on row selection change.</li><li><code>onPTableRowExpand</code>: emitted on row expand.</li><li><code>onPTableRowCollapse</code>: emitted on row collapse.</li><li><code>onPTableColumnResize</code>: emitted on column resize.</li><li><code>onPTableColumnReorder</code>: emitted on column reorder.</li></ul><h3>Example 1: Direct Binding in Template</h3><p>Snippet 7:</p><h3>Example 2: Subscribe via ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — actual signature (gotcha)</h2><p><code><wuic-list-grid></code> accepts a <code>[rowCustomSelect]</code> input to hook into row selection (opening a "pick a document" dialog, master-detail flow, etc.). The TypeScript signature declared in <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> reads:</p><p>Snippet 9:</p><p><strong>However at runtime the callback is invoked with arguments reversed</strong> — the framework calls <code>rowCustomSelect($event, rowData, dt)</code> (see <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> and <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Symptom of wrong arg order: <code>rowData?.id</code> is undefined → early-return guard in your handler → the callback returns silently and your dialog/action never fires. No console error.</p><p>Correct form (matches runtime invocation):</p><p>Snippet 10:</p><p>Template usage:</p><p>Snippet 11:</p><p>> Note: tests in <code>designer.component.spec.ts</code> (e.g. line 512) invoke the callback with <code>({currentTarget: rowCell}, {id: 42}, null)</code>, confirming the <code>($event, rowData, dt)</code> order. If the framework eventually aligns the declared signature, this page will be updated as well.</p>",
|
|
8726
8762
|
"codeSamples": [
|
|
8727
8763
|
{
|
|
8728
8764
|
"id": "code_1",
|
|
@@ -10448,7 +10484,7 @@ const frameworkDocsContent = {
|
|
|
10448
10484
|
{
|
|
10449
10485
|
"id": "overview",
|
|
10450
10486
|
"title": "Overview",
|
|
10451
|
-
"html": "<h1>Designer</h1><p>Visual editor for metadata-driven dashboards on route <code>#/cities/dashboard</code>.</p><h2>Scope</h2><ul><li>Board composition via drag-and-drop of nodes and UI blocks.</li><li>Layout and styling driven by <code>boardcontent</code> and table/column metadata.</li><li>Property panel editing without hardcoding in runtime components.</li></ul><h2>Designer Palette</h2><
|
|
10487
|
+
"html": "<h1>Designer</h1><p>Visual editor for metadata-driven dashboards on route <code>#/cities/dashboard</code>.</p><h2>Scope</h2><ul><li>Board composition via drag-and-drop of nodes and UI blocks.</li><li>Layout and styling driven by <code>boardcontent</code> and table/column metadata.</li><li>Property panel editing without hardcoding in runtime components.</li></ul><h2>Designer Palette</h2><p>The palette is split into three groups. The names below are the ones you read in the palette,</p><p>uppercase exactly as the designer writes them.</p><p><strong>HTML</strong> — the markup building blocks:</p><table><thead><tr><th>Tool</th><th>What it is for</th></tr></thead><tbody><tr><td><code>TABLE</code></td><td>a grid of cells. <code>TR</code> and <code>TD</code> exist as tools but are not draggable: the table creates them</td></tr><tr><td><code>DIV</code></td><td>free-form container, the structural block you use most</td></tr><tr><td><code>SPAN</code>, <code>LABEL</code>, <code>Hx</code></td><td>databound text; <code>Hx</code> picks the level from h1 to h6</td></tr><tr><td><code>ANCHOR</code>, <code>IMG</code>, <code>IMAGE</code>, <code>IFRAME</code></td><td>links, images, external content</td></tr><tr><td><code>UL</code></td><td>list</td></tr><tr><td><code>BUTTON</code></td><td>button with a callback</td></tr><tr><td><code>INPUT</code>, <code>TEXTAREA</code>, <code>CHECKBOX</code>, <code>SELECT</code>, <code>MULTISELECT</code>, <code>DATE</code></td><td>input fields</td></tr><tr><td><code>KPI</code></td><td>a single highlighted value</td></tr><tr><td><code>SEPARATOR</code>, <code>HR</code></td><td>separators</td></tr></tbody></table><p><strong>DATA</strong> — the nodes wired to the backend:</p><table><thead><tr><th>Tool</th><th>What it is for</th></tr></thead><tbody><tr><td><code>DATASOURCE</code></td><td>metadata data source (<code>route</code>, filters, sort, paging)</td></tr><tr><td><code>DATAREPEATER</code></td><td>list/card view connected to a datasource</td></tr><tr><td><code>FILTERBAR</code></td><td>filter bar above the repeater</td></tr><tr><td><code>PAGER</code></td><td>paginator</td></tr></tbody></table><p><strong>CONTAINER</strong> — the layouts:</p><table><thead><tr><th>Tool</th><th>What it is for</th></tr></thead><tbody><tr><td><code>TABVIEW</code> + <code>TABPANEL</code></td><td>tabs</td></tr><tr><td><code>SPLITTER</code> + <code>SPLITTER-AREA</code></td><td>resizable panes</td></tr><tr><td><code>ACCORDION</code> + <code>ACCORDION-AREA</code></td><td>accordion sections</td></tr></tbody></table><p>Two names you will look for in vain: <strong>there is no "Dynamic Template" tool</strong> — the dynamic</p><p>template is what the <code>DATAREPEATER</code> renders, you configure it from its properties and you never</p><p>drag it; and <strong>"Container" / "Layout" are the group name</strong>, not selectable entries.</p><p>On top of these come the custom tools registered by the host project</p><p>(<code>MetadataProviderService.customDesignerTools</code>), which appear at the end under the group they</p><p>declare.</p><h2>Main Features</h2><ul><li>Drag-and-drop nodes onto the canvas with persistence in <code>boardcontent</code>.</li><li>Contextual property panel with inputs consistent with the selected components.</li><li>Binding between nodes (<code>datasource -> repeater/template</code>) with minimal validation.</li><li>Integrated runtime preview and layout realignment.</li><li>Pending changes management with guard before exit.</li></ul><h2>Element context menu</h2><p>Right-click on a canvas element, a breadcrumb item at the bottom or a node in the hierarchy tree shows a context menu with three items:</p><ul><li><strong>Edit properties</strong> (pi-cog) — selects the element as the "current tool" and shows its property panel on the right; equivalent to clicking in the tree. Useful to edit properties of nested elements without hunting for them in the hierarchy.</li><li><strong>Rename</strong> (breadcrumb only) — opens a dialog to rename the <code>displayName</code>.</li><li><strong>Remove</strong> — deletes the element from the board.</li></ul><h2>Recommended Operational Flow</h2><ul><li>Open the target dashboard route.</li><li>Insert/connect nodes from the palette.</li><li>Configure essential <code>inputs</code> (e.g., <code>route</code>, <code>action</code>, <code>datasource</code>).</li><li>Save and validate the result at runtime.</li></ul><h2>Operational Notes</h2><ul><li>For specific dashboard fixes, prefer <code>boardcontent</code> patches instead of global changes.</li><li>Avoid duplicate properties between <code>inputs</code> and inconsistent inline styles.</li><li>Always verify that datasources have a populated <code>inputs.route</code>.</li></ul>",
|
|
10452
10488
|
"codeSamples": []
|
|
10453
10489
|
}
|
|
10454
10490
|
],
|
|
@@ -14563,13 +14599,17 @@ const frameworkDocsContent = {
|
|
|
14563
14599
|
{
|
|
14564
14600
|
"id": "sec_4",
|
|
14565
14601
|
"title": "Quick Start — premier composant"
|
|
14602
|
+
},
|
|
14603
|
+
{
|
|
14604
|
+
"id": "sec_5",
|
|
14605
|
+
"title": "Les premieres listes affichent 20 enregistrements : c'est le mode Trial"
|
|
14566
14606
|
}
|
|
14567
14607
|
],
|
|
14568
14608
|
"sections": [
|
|
14569
14609
|
{
|
|
14570
14610
|
"id": "overview",
|
|
14571
14611
|
"title": "Overview",
|
|
14572
|
-
"html": "<h1>Panorama du Framework</h1><p>WUIC Framework est une plateforme pilotee par metadata pour creer des interfaces metier de maniere rapide et coherente.</p><h2>Contenu</h2><ul><li>DataSource et DataRepeater pour orchestrer les donnees et le rendu.</li><li>Archetypes visuels (list, map, scheduler, chart, carousel).</li><li>Designer runtime pour les dashboards et les templates dynamiques.</li><li>Workflow designer/runner pour les processus operationnels.</li><li>RAG Chatbot pour interroger la codebase en langage naturel.</li><li>Multi-SGBD : SQL Server, MySQL, PostgreSQL et Oracle via des providers drop-in (<code>dbms</code> : <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Demarrage de l'environnement dev</h2><p>La stack WUIC est composee de plusieurs services. Demarrez-les dans l'ordre indique.</p><h3>Prerequis</h3><table><thead><tr><th>Element</th><th>Verification</th><th>Notes</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle pour IIS en production</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>La 22 est la version avec laquelle le paquet est teste ; avec npm 10.9.x l'installation passe grace au <code>package-lock.json</code> inclus</td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>Le Windows PowerShell livre avec Windows suffit : <code>rename-project.ps1</code> et les scripts <code>llm-workspace/</code> fonctionnent aussi sur 5.1. PowerShell 7 est recommande, pas requis</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>S'il manque, <strong>la ligne unique l'installe elle-meme</strong> (SQL Server Express, ou le moteur choisi avec <code>-Dbms</code>) ; pas sur Windows Server, voir l'encadre ci-dessous. 2019 suffit pour les packages sans <code>.bak</code> ; le tutoriel <code>.bak</code> est une sauvegarde SQL Server 2022 et exige <strong>2022 ou plus recent</strong></td></tr><tr><td>Linux (installeur <code>install.sh</code>)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 ou 24.04 LTS</strong> (24.04 recommandee) : ce sont les seules versions d'Ubuntu supportees par Microsoft pour SQL Server, la <strong>26.04 n'est pas supportee</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Meme recommandation avec MySQL, PostgreSQL et Oracle, car l'installeur est teste sur ces versions</td></tr><tr><td>GPU NVIDIA (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Optionnel : accelere le RAG Chatbot (sans GPU il tourne sur CPU)</td></tr></tbody></table><p>> <strong>Sur Windows Server la base de donnees doit etre installee avant.</strong> La ligne unique recupere</p><p>> les composants manquants via <code>winget</code>, absent sur Windows Server : sans une instance deja</p><p>> joignable, l'installation s'arrete avec `No SQL Server instance reachable and winget is</p><p>> missing`. Installe donc le moteur avant de lancer la ligne - SQL Server doit etre **2019 ou</p><p>> superieur<strong> (Express suffit ; </strong>2022 ou superieur** pour le tutoriel <code>.bak</code>), et une 2017</p><p>> n'est pas acceptee. Si l'instance n'est pas celle par defaut, passe-la avec</p><p>> <code>-SqlServer 'localhost\\NOMINSTANCE'</code>. Cela vaut pour tous les moteurs, pas seulement SQL Server.</p><h3>1. Telecharger le template de projet</h3><p>Sous Windows, une seule ligne PowerShell fait tout : elle telecharge le paquet, verifie le SDK .NET 10</p><p>et Node.js 22 (en installant ce qui manque), execute <code>dotnet restore</code> et <code>npm install</code>,</p><p>et installe l'extension WUIC Assistant dans VS Code.</p><p>Snippet 1:</p><p>Options utiles sur la meme ligne : <code>-Dbms mysql</code> (ou <code>postgres</code>, <code>oracle</code>) pour un moteur</p><p>autre que SQL Server — l'installeur l'installe et le configure lui-meme — et <code>-WithTutorial</code></p><p>pour telecharger aussi la base de donnees d'exemple.</p><p>Quand c'est termine, le dernier ecran est deja votre liste de taches :</p><p>Snippet 2:</p><p>La chaine de connexion est prete a l'emploi : au premier demarrage le wizard ne demande rien</p><p>d'autre. Avec <code>-Dbms mysql</code> ou <code>-Dbms postgres</code> cette ligne change en consequence et porte en</p><p>elle l'utilisateur et le mot de passe, parce que le mot de passe du superutilisateur est</p><p><strong>genere par l'installeur</strong> ; ce meme mot de passe est enregistre dans <code>wuic-secrets.json</code>, a</p><p>cote de l'installation, et c'est le seul endroit ou il reste ecrit.</p><p>Le chemin manuel reste valable, sur n'importe quel systeme :</p><p>Partez du paquet <code>WuicTest-src-*.zip</code> (lien dans la section <strong>Download</strong> du site).</p><p>Extrayez-le dans un dossier de travail, ex. <code>C:\\dev\\WuicTest</code> (les fichiers vont directement</p><p>a la racine, PAS dans un sous-dossier <code>src/</code>). Le paquet contient :</p><ul><li><code>WuicTest.csproj</code> → projet host avec <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → app Angular avec <code>package.json</code> qui reference <code>wuic-framework-lib</code> depuis le registre npm</li><li><code>appsettings.json</code> preconfigure en mode <code>firstRun = "true"</code> avec placeholders <code>__SET_*__</code></li><li><code>appsettings-samples/</code> → 6 templates prets (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>Pas besoin de cloner le repository du framework</strong> : <code>WuicCore</code> arrive comme paquet NuGet</p><p>> depuis <code>nuget.org</code> et <code>wuic-framework-lib</code> comme paquet npm depuis le registre npm. Le source</p><p>> du framework n'est necessaire que si vous voulez le modifier — typiquement pas votre cas.</p><p>> <strong>npm 10.9.x et les paquets anterieurs a la 1.7.1</strong> : ces paquets ne contiennent pas de</p><p>> <code>package-lock.json</code>, et sans lock npm 10.9.x (la version installee par Node 22 LTS) s'arrete avec</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> pendant la resolution des peers.</p><p>> Telechargez le lock publie a cote de la release —</p><p>> <code>https://wuic-framework.com/downloads/locks/<nom-du-zip>.package-lock.json</code> — placez-le dans</p><p>> <code>wwwroot/</code> et relancez <code>npm install</code>. La ligne unique <code>-Src</code> le fait pour vous.</p><h3>2. Base de donnees</h3><p>Il faut une instance du moteur joignable. <strong>Avec la ligne unique, rien a faire</strong> : elle</p><p>installe et configure l'instance, et la chaine de connexion a coller dans le wizard est la</p><p>derniere chose qu'elle affiche. Sur le chemin manuel, l'instance doit deja exister.</p><p>Connexions dans <code>appsettings.json</code> :</p><ul><li><code>MetaDataSQLConnection</code> — DB metadata (menu, tables, colonnes, board, utilisateurs)</li><li><code>DataSQLConnection</code> — DB donnees applicatives</li></ul><p>S'il s'agit de la premiere installation (<code>AppSettings.firstRun = "true"</code> dans le template),</p><p>le wizard de scaffolding au premier demarrage cree le schema metadata et peuple le DB donnees.</p><p>Voir la page <em>Scaffolding initial</em> pour le flux guide.</p><h3>3. Backend (.NET)</h3><p>Depuis la racine du dossier extrait (ex. <code>C:\\dev\\WuicTest</code>) :</p><p>Snippet 3:</p><p>Le backend expose les API sur <code>http://localhost:5000</code>.</p><h3>4. Frontend (Angular)</h3><p>Dans un second shell, depuis le sous-dossier <code>wwwroot/</code> :</p><p>Snippet 4:</p><p>Le frontend est disponible sur <code>http://localhost:4200</code>.</p><p>Login par defaut (post-firstRun) : <code>admin</code> / <code>admin</code>.</p><h3>5. RAG Chatbot (optionnel)</h3><p>Le RAG Chatbot (<code>Administration > RAG Chat</code>) tourne <strong>dans le backend .NET</strong> :</p><p>le moteur de retrieval (<code>rag-engine/WuicRagEngine.dll</code>, ONNX Runtime</p><p>in-process) est charge par le backend quand <code>AppSettings.rag-use-dotnet-engine</code></p><p>vaut <code>"true"</code> (valeur par defaut des packages de release). **Pas de Python, pas</p><p>de venv, aucun serveur separe a demarrer.**</p><p>A la <strong>premiere</strong> ouverture du chatbot (ou a la fin du first-run) le backend</p><p>telecharge seul les modeles ONNX (<code>bge-m3</code> + reranker), le tokenizer et</p><p>l'index (~4,5 Go) depuis <code>rag-engine-models-url</code> (par defaut</p><p><code>https://wuic-framework.com/rag-models</code>) dans <code>rag-engine/artifacts/</code>. Une</p><p>connexion internet n'est necessaire qu'une seule fois ; le telechargement</p><p>tourne en arriere-plan (1-5 min) et une notification in-app arrive au debut</p><p>et a la fin. Entre-temps le composant affiche l'etat <strong>RAG offline</strong> et le</p><p>reste de l'application fonctionne normalement.</p><p>Cles <code>AppSettings</code> pertinentes (toutes avec des valeurs par defaut pretes) :</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — active le moteur .NET (<code>false</code> = fallback Python, voir ci-dessous)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code> : avec GPU NVIDIA (CUDA 12.x + cuDNN 9) ~1 s/requete, sur CPU ~15-25 s/requete</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = sources du framework en signature seulement ; <code>internal</code> = index integral</li><li><code>rag-engine-models-url</code> — source du telechargement au premier demarrage</li><li><code>rag-engine-cuda-path</code> = (vide) — dossier des DLL CUDA/cuDNN si elles ne sont pas installees au niveau systeme</li></ul><p>Pour le chat avec LLM, renseignez <code>rag-llm-provider</code> + <code>rag-llm-api-key</code></p><p>(Claude via Anthropic, ou un modele local via Ollama avec <code>rag-llm-base-url</code>).</p><p>Sans provider, seul le mode retrieval (recherche de snippets) fonctionne.</p><p>Detail des cles sur la page <em>AppSettings</em>.</p><p>> L'ancien stack Python (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> sur</p><p>> <code>127.0.0.1:8765</code>) n'est utilisable qu'en fallback avec</p><p>> <code>rag-use-dotnet-engine = "false"</code> et n'est pas inclus dans les packages de release.</p><h2>Recapitulatif des services</h2><table><thead><tr><th>Service</th><th>Port</th><th>Obligatoire</th><th>Commande rapide</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>oui</td><td>(service Windows)</td></tr><tr><td>Backend .NET</td><td>5000</td><td>oui</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Frontend Angular</td><td>4200</td><td>oui</td><td><code>npm run serve:dev</code></td></tr><tr><td>Engine RAG .NET (ONNX)</td><td>in-process</td><td>non</td><td>charge par le backend au premier chat</td></tr></tbody></table><h2>Quick Start — premier composant</h2><p>1. Configurez l'endpoint AsmxProxy.</p><p>2. Definissez la route metadata et les colonnes.</p><p>3. Montez <code>wuic-data-source</code> + <code>wuic-data-repeater</code>.</p><p>Snippet 5:</p>",
|
|
14612
|
+
"html": "<h1>Panorama du Framework</h1><p>WUIC Framework est une plateforme pilotee par metadata pour creer des interfaces metier de maniere rapide et coherente.</p><h2>Contenu</h2><ul><li>DataSource et DataRepeater pour orchestrer les donnees et le rendu.</li><li>Archetypes visuels (list, map, scheduler, chart, carousel).</li><li>Designer runtime pour les dashboards et les templates dynamiques.</li><li>Workflow designer/runner pour les processus operationnels.</li><li>RAG Chatbot pour interroger la codebase en langage naturel.</li><li>Multi-SGBD : SQL Server, MySQL, PostgreSQL et Oracle via des providers drop-in (<code>dbms</code> : <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Demarrage de l'environnement dev</h2><p>La stack WUIC est composee de plusieurs services. Demarrez-les dans l'ordre indique.</p><h3>Prerequis</h3><table><thead><tr><th>Element</th><th>Verification</th><th>Notes</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle pour IIS en production</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>La 22 est la version avec laquelle le paquet est teste ; avec npm 10.9.x l'installation passe grace au <code>package-lock.json</code> inclus</td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>Le Windows PowerShell livre avec Windows suffit : <code>rename-project.ps1</code> et les scripts <code>llm-workspace/</code> fonctionnent aussi sur 5.1. PowerShell 7 est recommande, pas requis</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>S'il manque, <strong>la ligne unique l'installe elle-meme</strong> (SQL Server Express, ou le moteur choisi avec <code>-Dbms</code>) ; pas sur Windows Server, voir l'encadre ci-dessous. 2019 suffit pour les packages sans <code>.bak</code> ; le tutoriel <code>.bak</code> est une sauvegarde SQL Server 2022 et exige <strong>2022 ou plus recent</strong></td></tr><tr><td>Linux (installeur <code>install.sh</code>)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 ou 24.04 LTS</strong> (24.04 recommandee) : ce sont les seules versions d'Ubuntu supportees par Microsoft pour SQL Server, la <strong>26.04 n'est pas supportee</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Meme recommandation avec MySQL, PostgreSQL et Oracle, car l'installeur est teste sur ces versions</td></tr><tr><td>GPU NVIDIA (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Optionnel : accelere le RAG Chatbot (sans GPU il tourne sur CPU)</td></tr></tbody></table><p>> <strong>Sur Windows Server la base de donnees doit etre installee avant.</strong> La ligne unique recupere</p><p>> les composants manquants via <code>winget</code>, absent sur Windows Server : sans une instance deja</p><p>> joignable, l'installation s'arrete avec `No SQL Server instance reachable and winget is</p><p>> missing`. Installe donc le moteur avant de lancer la ligne - SQL Server doit etre **2019 ou</p><p>> superieur<strong> (Express suffit ; </strong>2022 ou superieur** pour le tutoriel <code>.bak</code>), et une 2017</p><p>> n'est pas acceptee. Si l'instance n'est pas celle par defaut, passe-la avec</p><p>> <code>-SqlServer 'localhost\\NOMINSTANCE'</code>. Cela vaut pour tous les moteurs, pas seulement SQL Server.</p><h3>1. Telecharger le template de projet</h3><p>Sous Windows, une seule ligne PowerShell fait tout : elle telecharge le paquet, verifie le SDK .NET 10</p><p>et Node.js 22 (en installant ce qui manque), execute <code>dotnet restore</code> et <code>npm install</code>,</p><p>et installe l'extension WUIC Assistant dans VS Code.</p><p>Snippet 1:</p><p>Options utiles sur la meme ligne : <code>-Dbms mysql</code> (ou <code>postgres</code>, <code>oracle</code>) pour un moteur</p><p>autre que SQL Server — l'installeur l'installe et le configure lui-meme — et <code>-WithTutorial</code></p><p>pour telecharger aussi la base de donnees d'exemple.</p><p>Quand c'est termine, le dernier ecran est deja votre liste de taches :</p><p>Snippet 2:</p><p>La chaine de connexion est prete a l'emploi : au premier demarrage le wizard ne demande rien</p><p>d'autre. Avec <code>-Dbms mysql</code> ou <code>-Dbms postgres</code> cette ligne change en consequence et porte en</p><p>elle l'utilisateur et le mot de passe, parce que le mot de passe du superutilisateur est</p><p><strong>genere par l'installeur</strong> ; ce meme mot de passe est enregistre dans <code>wuic-secrets.json</code>, a</p><p>cote de l'installation, et c'est le seul endroit ou il reste ecrit.</p><p>Le chemin manuel reste valable, sur n'importe quel systeme :</p><p>Partez du paquet <code>WuicTest-src-*.zip</code> (lien dans la section <strong>Download</strong> du site).</p><p>Extrayez-le dans un dossier de travail, ex. <code>C:\\dev\\WuicTest</code> (les fichiers vont directement</p><p>a la racine, PAS dans un sous-dossier <code>src/</code>). Le paquet contient :</p><ul><li><code>WuicTest.csproj</code> → projet host avec <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → app Angular avec <code>package.json</code> qui reference <code>wuic-framework-lib</code> depuis le registre npm</li><li><code>appsettings.json</code> preconfigure en mode <code>firstRun = "true"</code> avec placeholders <code>__SET_*__</code></li><li><code>appsettings-samples/</code> → 6 templates prets (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>Pas besoin de cloner le repository du framework</strong> : <code>WuicCore</code> arrive comme paquet NuGet</p><p>> depuis <code>nuget.org</code> et <code>wuic-framework-lib</code> comme paquet npm depuis le registre npm. Le source</p><p>> du framework n'est necessaire que si vous voulez le modifier — typiquement pas votre cas.</p><p>> <strong>npm 10.9.x et les paquets anterieurs a la 1.7.1</strong> : ces paquets ne contiennent pas de</p><p>> <code>package-lock.json</code>, et sans lock npm 10.9.x (la version installee par Node 22 LTS) s'arrete avec</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> pendant la resolution des peers.</p><p>> Telechargez le lock publie a cote de la release —</p><p>> <code>https://wuic-framework.com/downloads/locks/<nom-du-zip>.package-lock.json</code> — placez-le dans</p><p>> <code>wwwroot/</code> et relancez <code>npm install</code>. La ligne unique <code>-Src</code> le fait pour vous.</p><h3>2. Base de donnees</h3><p>Il faut une instance du moteur joignable. <strong>Avec la ligne unique, rien a faire</strong> : elle</p><p>installe et configure l'instance, et la chaine de connexion a coller dans le wizard est la</p><p>derniere chose qu'elle affiche. Sur le chemin manuel, l'instance doit deja exister.</p><p>Connexions dans <code>appsettings.json</code> :</p><ul><li><code>MetaDataSQLConnection</code> — DB metadata (menu, tables, colonnes, board, utilisateurs)</li><li><code>DataSQLConnection</code> — DB donnees applicatives</li></ul><p>S'il s'agit de la premiere installation (<code>AppSettings.firstRun = "true"</code> dans le template),</p><p>le wizard de scaffolding au premier demarrage cree le schema metadata et peuple le DB donnees.</p><p>Voir la page <em>Scaffolding initial</em> pour le flux guide.</p><p>#### Ce que demande le wizard de premier demarrage</p><p>Au premier demarrage l'application n'affiche pas le formulaire de connexion mais la page</p><p><strong>Configuration initiale du projet</strong>. On la remplit une seule fois : a la fin <code>firstRun</code> passe</p><p>a <code>false</code> et la page ne revient plus.</p><ul><li><strong>Mode d'installation</strong> — deux entrees : <strong>Base existante</strong>, qui enregistre une base a vous,</li></ul><p> et <strong>Tutorial WideWorldImporters</strong>, qui installe la base d'exemple. La seconde n'apparait que</p><p> si le paquet embarque le tutoriel (<code>tutorialAvailable</code>) : dans les paquets sans tutoriel la</p><p> liste deroulante n'existe pas et le mode est "Base existante".</p><ul><li><strong>SGBD</strong> — le moteur. En le changeant, la chaine de connexion ci-dessous est reecrite dans la</li></ul><p> forme du provider choisi.</p><ul><li><strong>DataSQLConnection</strong> — la chaine vers la base de donnees, et le champ dont depend tout le</li></ul><p> reste : tant que vous n'avez pas appuye sur <strong>Tester la connexion et charger les bases</strong>, la</p><p> liste des bases reste desactivee. Le test valide les identifiants, liste les bases du serveur</p><p> et, sur SQL Server, corrige lui-meme les parametres de certificat</p><p> (<code>Encrypt=False;TrustServerCertificate=True</code>) en vous le signalant. <code>Integrated Security</code> ne</p><p> vaut que sur SQL Server : les autres moteurs exigent un utilisateur et un mot de passe.</p><ul><li><strong>Base de donnees</strong> et <strong>Nom de la base de metadonnees</strong> — la premiere se choisit dans la</li></ul><p> liste chargee par le test (en mode tutoriel c'est un champ libre, <code>WideWorldImporters</code> par</p><p> defaut) ; la seconde est le nom de la base de metadonnees a creer (<code>metadataDB</code> par defaut,</p><p> <code>MetadataCRM</code> en mode tutoriel). Si cette base existe deja, le wizard demande confirmation</p><p> avant de la recreer.</p><ul><li><strong>Generer automatiquement les metadonnees des tables</strong> (uniquement en "Base existante") —</li></ul><p> remplit <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> a partir de toutes les tables de la base</p><p> choisie. C'est ce qui allonge le plus le provisioning sur une base comptant beaucoup de</p><p> tables.</p><ul><li><strong>Utilisateur administrateur initial</strong> — nom d'utilisateur (<code>admin</code> par defaut), mot de passe</li></ul><p> (4 caracteres minimum) et langue. Il n'y a pas de mot de passe par defaut : celui saisi ici</p><p> est le seul qui ouvrira la premiere session. La langue choisie est appliquee a</p><p> l'administrateur et a cette page elle-meme.</p><ul><li><strong>RAG Chatbot</strong> — uniquement la cle Anthropic, facultative. Rien a installer : voir l'etape 5.</li></ul><p>Une fois <strong>Confirmer et creer la base de metadonnees</strong> presse, le provisioning se deroule seul,</p><p>avec une barre de progression et le nombre de lots traites. Duree mesuree sur les installations</p><p>de test : <strong>30 s - 2 min</strong> en mode tutoriel, <strong>1-4 min</strong> sur une base existante avec la</p><p>generation automatique activee. A la fin, la page laisse place au formulaire de connexion.</p><h3>3. Backend (.NET)</h3><p>Depuis la racine du dossier extrait (ex. <code>C:\\dev\\WuicTest</code>) :</p><p>Snippet 3:</p><p>Le backend expose les API sur <code>http://localhost:5000</code>.</p><h3>4. Frontend (Angular)</h3><p>Dans un second shell, depuis le sous-dossier <code>wwwroot/</code> :</p><p>Snippet 4:</p><p>Le frontend est disponible sur <code>http://localhost:4200</code>.</p><p>Les identifiants sont ceux de l'administrateur choisi dans le wizard de premier demarrage :</p><p>le nom d'utilisateur est <code>admin</code> si vous ne l'avez pas change, et le mot de passe est celui que</p><p>vous avez saisi (il n'y a pas de mot de passe par defaut).</p><h3>5. RAG Chatbot (optionnel)</h3><p>Le RAG Chatbot (<code>Administration > RAG Chat</code>) tourne <strong>dans le backend .NET</strong> :</p><p>le moteur de retrieval (<code>rag-engine/WuicRagEngine.dll</code>, ONNX Runtime</p><p>in-process) est charge par le backend quand <code>AppSettings.rag-use-dotnet-engine</code></p><p>vaut <code>"true"</code> (valeur par defaut des packages de release). **Pas de Python, pas</p><p>de venv, aucun serveur separe a demarrer.**</p><p>A la <strong>premiere</strong> ouverture du chatbot (ou a la fin du first-run) le backend</p><p>telecharge seul les modeles ONNX (<code>bge-m3</code> + reranker), le tokenizer et</p><p>l'index (~4,5 Go) depuis <code>rag-engine-models-url</code> (par defaut</p><p><code>https://wuic-framework.com/rag-models</code>) dans <code>rag-engine/artifacts/</code>. Une</p><p>connexion internet n'est necessaire qu'une seule fois ; le telechargement</p><p>tourne en arriere-plan (1-5 min) et une notification in-app arrive au debut</p><p>et a la fin. Entre-temps le composant affiche l'etat <strong>RAG offline</strong> et le</p><p>reste de l'application fonctionne normalement.</p><p>Cles <code>AppSettings</code> pertinentes (toutes avec des valeurs par defaut pretes) :</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — active le moteur .NET (<code>false</code> = fallback Python, voir ci-dessous)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code> : avec GPU NVIDIA (CUDA 12.x + cuDNN 9) ~1 s/requete, sur CPU ~15-25 s/requete</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = sources du framework en signature seulement ; <code>internal</code> = index integral</li><li><code>rag-engine-models-url</code> — source du telechargement au premier demarrage</li><li><code>rag-engine-cuda-path</code> = (vide) — dossier des DLL CUDA/cuDNN si elles ne sont pas installees au niveau systeme</li></ul><p>Pour le chat avec LLM, renseignez <code>rag-llm-provider</code> + <code>rag-llm-api-key</code></p><p>(Claude via Anthropic, ou un modele local via Ollama avec <code>rag-llm-base-url</code>).</p><p>Sans provider, seul le mode retrieval (recherche de snippets) fonctionne.</p><p>Detail des cles sur la page <em>AppSettings</em>.</p><p>> L'ancien stack Python (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> sur</p><p>> <code>127.0.0.1:8765</code>) n'est utilisable qu'en fallback avec</p><p>> <code>rag-use-dotnet-engine = "false"</code> et n'est pas inclus dans les packages de release.</p><h2>Recapitulatif des services</h2><table><thead><tr><th>Service</th><th>Port</th><th>Obligatoire</th><th>Commande rapide</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>oui</td><td>(service Windows)</td></tr><tr><td>Backend .NET</td><td>5000</td><td>oui</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Frontend Angular</td><td>4200</td><td>oui</td><td><code>npm run serve:dev</code></td></tr><tr><td>Engine RAG .NET (ONNX)</td><td>in-process</td><td>non</td><td>charge par le backend au premier chat</td></tr></tbody></table><h2>Quick Start — premier composant</h2><p>1. Configurez l'endpoint AsmxProxy.</p><p>2. Definissez la route metadata et les colonnes.</p><p>3. Montez <code>wuic-data-source</code> + <code>wuic-data-repeater</code>.</p><p>Snippet 5:</p><h2>Les premieres listes affichent 20 enregistrements : c'est le mode Trial</h2><p>Une installation neuve fonctionne <strong>sans licence</strong>, donc en mode Trial, et dans ce mode</p><p><strong>chaque requete est limitee a 20 enregistrements</strong>. Ce n'est ni une anomalie ni une limite</p><p>de la base de donnees : une liste qui affiche "20 sur 20" sur une table de plusieurs milliers</p><p>de lignes tourne tout simplement sans licence.</p><p>Comment le confirmer en une seconde :</p><p>Snippet 6:</p><p><code>licenseValid: false</code> confirme le mode Trial, et <code>licenseReason</code> en donne la raison</p><p>(<code>invalid_signature</code>, <code>license_expired</code>, <code>machine_fingerprint_not_authorized</code>, ...).</p><p>Comment en sortir : on colle la licence depuis <strong>Administration > Editeur AppSettings</strong>, onglet</p><p>Licensing, et elle prend effet immediatement - aucun redemarrage du backend n'est necessaire.</p><p>Les details, y compris les limites que le mode Trial impose au-dela du nombre</p><p>d'enregistrements, se trouvent sur la page <a href=\"licensing.md\">Licensing</a>.</p>",
|
|
14573
14613
|
"codeSamples": [
|
|
14574
14614
|
{
|
|
14575
14615
|
"id": "code_1",
|
|
@@ -14581,25 +14621,31 @@ const frameworkDocsContent = {
|
|
|
14581
14621
|
"id": "code_2",
|
|
14582
14622
|
"title": "Snippet 2",
|
|
14583
14623
|
"language": "text",
|
|
14584
|
-
"code": "Developer workspace ready: C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\
|
|
14624
|
+
"code": "Developer workspace ready: C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\n\n code \"C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\\WuicTest.code-workspace\"\n then F5 > 'Fullstack: WuicTest + Chrome' (backend http://localhost:5000, frontend http://localhost:4200)\n\nFirst start opens the first-run wizard: paste this connection string (Windows authentication)\n Data Source=localhost\\SQLEXPRESS;Integrated Security=SSPI;Initial Catalog=WuicData;Encrypt=False;TrustServerCertificate=True\nRename the project: .\\rename-project.ps1 -Name MyApp"
|
|
14585
14625
|
},
|
|
14586
14626
|
{
|
|
14587
14627
|
"id": "code_3",
|
|
14588
14628
|
"title": "Snippet 3",
|
|
14589
14629
|
"language": "powershell",
|
|
14590
|
-
"code": "# Premiere fois : restore des paquets NuGet (pulls WuicCore + deps depuis nuget.org, ~30 s)\
|
|
14630
|
+
"code": "# Premiere fois : restore des paquets NuGet (pulls WuicCore + deps depuis nuget.org, ~30 s)\ndotnet restore\n\n# Demarrage dev avec hot reload\n$env:ASPNETCORE_ENVIRONMENT = 'Development'\ndotnet watch run\n\n# Ou demarrage one-shot (sans hot reload)\ndotnet run"
|
|
14591
14631
|
},
|
|
14592
14632
|
{
|
|
14593
14633
|
"id": "code_4",
|
|
14594
14634
|
"title": "Snippet 4",
|
|
14595
14635
|
"language": "powershell",
|
|
14596
|
-
"code": "cd wwwroot\
|
|
14636
|
+
"code": "cd wwwroot\n\n# Premiere fois : restore des dependances npm (pulls wuic-framework-lib depuis npm registry, ~2 min)\nnpm install\n\n# Demarrage dev server\nnpm run serve:dev"
|
|
14597
14637
|
},
|
|
14598
14638
|
{
|
|
14599
14639
|
"id": "code_5",
|
|
14600
14640
|
"title": "Snippet 5",
|
|
14601
14641
|
"language": "html",
|
|
14602
|
-
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\
|
|
14642
|
+
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\n<wuic-data-repeater [hardcodedAction]=\"'list'\"></wuic-data-repeater>"
|
|
14643
|
+
},
|
|
14644
|
+
{
|
|
14645
|
+
"id": "code_6",
|
|
14646
|
+
"title": "Snippet 6",
|
|
14647
|
+
"language": "bash",
|
|
14648
|
+
"code": "curl -s http://localhost:5000/api/Meta/LicenseStatus"
|
|
14603
14649
|
}
|
|
14604
14650
|
]
|
|
14605
14651
|
}
|
|
@@ -14634,18 +14680,22 @@ const frameworkDocsContent = {
|
|
|
14634
14680
|
"toc": [
|
|
14635
14681
|
{
|
|
14636
14682
|
"id": "sec_1",
|
|
14637
|
-
"title": "
|
|
14683
|
+
"title": "Avec un paquet tutoriel il n'y a rien a scaffolder"
|
|
14638
14684
|
},
|
|
14639
14685
|
{
|
|
14640
14686
|
"id": "sec_2",
|
|
14641
|
-
"title": "
|
|
14687
|
+
"title": "Quand l'utiliser"
|
|
14642
14688
|
},
|
|
14643
14689
|
{
|
|
14644
14690
|
"id": "sec_3",
|
|
14645
|
-
"title": "
|
|
14691
|
+
"title": "Comportement avec firstRun=true"
|
|
14646
14692
|
},
|
|
14647
14693
|
{
|
|
14648
14694
|
"id": "sec_4",
|
|
14695
|
+
"title": "Operations typiques"
|
|
14696
|
+
},
|
|
14697
|
+
{
|
|
14698
|
+
"id": "sec_5",
|
|
14649
14699
|
"title": "Apres le provisionnement"
|
|
14650
14700
|
}
|
|
14651
14701
|
],
|
|
@@ -14653,7 +14703,7 @@ const frameworkDocsContent = {
|
|
|
14653
14703
|
{
|
|
14654
14704
|
"id": "overview",
|
|
14655
14705
|
"title": "Overview",
|
|
14656
|
-
"html": "<h1>Scaffolding initial</h1><p>Cette page decrit le bootstrap initial lorsque <code>AppSettings.firstRun = true</code>.</p><h2>Quand l'utiliser</h2><ul><li>Nouvelle installation (base de donnees metadata/donnees pas encore prete).</li><li>Environnement local a realigner avec le setup initial.</li><li>Premier demarrage apres un deploiement ou vous souhaitez forcer la procedure guidee de provisionnement.</li></ul><h2>Comportement avec firstRun=true</h2><ul><li>L'endpoint <code>GET /api/Meta/FirstRunStatus</code> expose <code>firstRun: true</code>.</li><li>Au login apparait le flux de premier demarrage (ex. action <code>Aggiorna</code> dans l'ecran).</li><li>Le setup applique les configurations de base (connexions, parametres runtime, bootstrap metadata).</li></ul><h2>Operations typiques</h2><ul><li>Verifier que <code>AppSettings.firstRun</code> est a <code>true</code> dans <code>appsettings.{Environment}.json</code> de l'hote que vous executez.</li><li>Demarrer l'application et completer la procedure de scaffolding initial depuis l'interface.</li><li>Controler que les connexions et parametres principaux sont coherents (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>Apres le provisionnement</h2><ul><li>La procedure de setup met <code>firstRun</code> a <code>false</code> pour eviter les re-executions a chaque demarrage.</li><li>Effectuer un login standard et valider l'acces aux routes principales.</li></ul>",
|
|
14706
|
+
"html": "<h1>Scaffolding initial</h1><p>Cette page decrit le bootstrap initial lorsque <code>AppSettings.firstRun = true</code>.</p><h2>Avec un paquet tutoriel il n'y a rien a scaffolder</h2><p>Le scaffolding dont parle cette page — lire les tables d'une base et les enregistrer dans</p><p><code>_metadati__tabelle</code> / <code>_metadati__colonne</code> — ne concerne <strong>que</strong> le mode "Base existante" du</p><p>wizard de premier demarrage : c'est la que se trouve la case *Generer automatiquement les</p><p>metadonnees des tables de la base choisie*.</p><p>Dans les paquets <strong>tutoriel</strong> cette case n'existe pas. La base de metadonnees arrive deja</p><p>remplie (routes, colonnes, menu, traductions, tableaux de bord d'exemple) et le wizard se</p><p>contente de la restaurer et de creer l'utilisateur administrateur. Voir des routes toutes</p><p>pretes juste apres le premier demarrage n'est donc pas le resultat d'un scaffolding : c'est le</p><p>contenu du tutoriel.</p><table><thead><tr><th>Mode du wizard</th><th>Ce qui arrive aux metadonnees</th></tr></thead><tbody><tr><td>Tutorial WideWorldImporters</td><td>Metadonnees deja construites, restaurees depuis le paquet. Aucun scaffolding.</td></tr><tr><td>Base existante, case decochee</td><td>Base de metadonnees vide : les routes s'enregistrent a la main, ou plus tard depuis la page Scaffolding.</td></tr><tr><td>Base existante, case cochee</td><td>En fin d'installation, chaque table de la base choisie est enregistree comme route.</td></tr></tbody></table><p>Le reste de cette page concerne les deux dernieres lignes de ce tableau.</p><h2>Quand l'utiliser</h2><ul><li>Nouvelle installation (base de donnees metadata/donnees pas encore prete).</li><li>Environnement local a realigner avec le setup initial.</li><li>Premier demarrage apres un deploiement ou vous souhaitez forcer la procedure guidee de provisionnement.</li></ul><h2>Comportement avec firstRun=true</h2><ul><li>L'endpoint <code>GET /api/Meta/FirstRunStatus</code> expose <code>firstRun: true</code>.</li><li>Au login apparait le flux de premier demarrage (ex. action <code>Aggiorna</code> dans l'ecran).</li><li>Le setup applique les configurations de base (connexions, parametres runtime, bootstrap metadata).</li></ul><h2>Operations typiques</h2><ul><li>Verifier que <code>AppSettings.firstRun</code> est a <code>true</code> dans <code>appsettings.{Environment}.json</code> de l'hote que vous executez.</li><li>Demarrer l'application et completer la procedure de scaffolding initial depuis l'interface.</li><li>Controler que les connexions et parametres principaux sont coherents (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>Apres le provisionnement</h2><ul><li>La procedure de setup met <code>firstRun</code> a <code>false</code> pour eviter les re-executions a chaque demarrage.</li><li>Effectuer un login standard et valider l'acces aux routes principales.</li></ul>",
|
|
14657
14707
|
"codeSamples": []
|
|
14658
14708
|
}
|
|
14659
14709
|
],
|
|
@@ -14712,7 +14762,7 @@ const frameworkDocsContent = {
|
|
|
14712
14762
|
{
|
|
14713
14763
|
"id": "overview",
|
|
14714
14764
|
"title": "Overview",
|
|
14715
|
-
"html": "<h1>Licensing</h1><p>Cette page explique le licensing du point de vue de l'utilisateur final : ce qui est necessaire, comment obtenir la licence et comment l'appliquer.</p><h2>Comment obtenir une licence</h2><p>Consultez les plans, les fonctionnalites incluses par niveau (Developer / Professional / Software House) et procedez a l'achat sur le site public :</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">Tarifs et plans WUIC — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Contact commercial</a> — aucune licence n'est requise pour evaluer : sans licence le framework tourne en mode Trial (20 enregistrements par requete)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">Page d'accueil WUIC</a></li></ul><p>Apres l'achat, vous recevrez un email avec <code>license-payload</code> + <code>license-signature</code> a installer comme decrit dans la "Procedure utilisateur final" ci-dessous.</p><h2>Comment ca fonctionne</h2><ul><li>La licence n'est valide que si :</li><li>la signature est correcte.</li><li>le <code>machineFingerprint</code> du serveur courant est present dans la liste <code>machineFingerprints</code> du payload signe.</li><li>Si la licence n'est pas valide, la lecture des donnees (<code>getFlatRecordData</code>) est limitee a un maximum de 20 enregistrements. De plus, le hook hote <code>customizeSelect</code> est contourne (non invoque).</li></ul><h2>Ou trouver le machineFingerprint</h2><p>Endpoint backend :</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → champ <code>machineFingerprint</code> (toujours disponible, meme sans licence).</li><li>Pendant le first-run, <code>GET /api/Meta/FirstRunStatus</code> l'expose aussi.</li></ul><p>Note : le fichier local <code>installation.id</code> n'est plus utilise par le licensing.</p><h2>Procedure utilisateur final</h2><p>1. Recuperez le <code>machineFingerprint</code> de votre hote.</p><p>2. Envoyez la valeur au fournisseur/licencieur.</p><p>3. Recevez les valeurs de licence :</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (si prevu par votre installation)</li></ul><p>4.
|
|
14765
|
+
"html": "<h1>Licensing</h1><p>Cette page explique le licensing du point de vue de l'utilisateur final : ce qui est necessaire, comment obtenir la licence et comment l'appliquer.</p><h2>Comment obtenir une licence</h2><p>Consultez les plans, les fonctionnalites incluses par niveau (Developer / Professional / Software House) et procedez a l'achat sur le site public :</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">Tarifs et plans WUIC — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Contact commercial</a> — aucune licence n'est requise pour evaluer : sans licence le framework tourne en mode Trial (20 enregistrements par requete)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">Page d'accueil WUIC</a></li></ul><p>Apres l'achat, vous recevrez un email avec <code>license-payload</code> + <code>license-signature</code> a installer comme decrit dans la "Procedure utilisateur final" ci-dessous.</p><h2>Comment ca fonctionne</h2><ul><li>La licence n'est valide que si :</li><li>la signature est correcte.</li><li>le <code>machineFingerprint</code> du serveur courant est present dans la liste <code>machineFingerprints</code> du payload signe.</li><li>Si la licence n'est pas valide, la lecture des donnees (<code>getFlatRecordData</code>) est limitee a un maximum de 20 enregistrements. De plus, le hook hote <code>customizeSelect</code> est contourne (non invoque).</li></ul><h2>Ou trouver le machineFingerprint</h2><p>Endpoint backend :</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → champ <code>machineFingerprint</code> (toujours disponible, meme sans licence).</li><li>Pendant le first-run, <code>GET /api/Meta/FirstRunStatus</code> l'expose aussi.</li></ul><p>Note : le fichier local <code>installation.id</code> n'est plus utilise par le licensing.</p><h2>Procedure utilisateur final</h2><p>1. Recuperez le <code>machineFingerprint</code> de votre hote.</p><p>2. Envoyez la valeur au fournisseur/licencieur.</p><p>3. Recevez les valeurs de licence :</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (si prevu par votre installation)</li></ul><p>4. Collez les valeurs depuis l'interface : <strong>Administration > Editeur AppSettings</strong>, section</p><p> <strong>License</strong> (champs <code>License email</code>, <code>License payload</code>, <code>License signature</code>,</p><p> <code>Public key (PEM)</code>), puis enregistrez. On peut aussi les ecrire a la main dans la section</p><p> <code>AppSettings</code> du fichier <code>appsettings.{Environment}.json</code> de l'hote en cours d'execution.</p><p>5. Verifiez le statut de la licence :</p><ul><li>via l'API : <code>GET /api/Meta/LicenseStatus</code>, attendu <code>licenseValid = true</code> ;</li><li>ou depuis la page elle-meme, qui relit la licence juste apres l'enregistrement.</li></ul><p><strong>Aucun redemarrage du backend n'est necessaire si vous passez par l'editeur.</strong> En enregistrant</p><p><code>license-payload</code> / <code>license-signature</code> depuis l'Editeur AppSettings, le backend recharge</p><p>lui-meme le service de validation et la licence s'applique des la requete suivante. Le</p><p>redemarrage n'est requis que dans l'autre cas, quand les valeurs sont ecrites a la main dans le</p><p>fichier : celui-ci est relu au demarrage.</p><h2>Licence multi-machine</h2><p>Une seule licence peut autoriser plusieurs machines en incluant plusieurs valeurs dans <code>machineFingerprints</code>.</p><h2>Depannage rapide</h2><ul><li><code>licenseReason = invalid_signature</code> :</li><li>payload/signature non coherents entre eux ou cle publique differente.</li><li><code>licenseReason = machine_fingerprint_not_authorized</code> :</li><li>le fingerprint de la machine courante n'est pas present dans la licence recue.</li><li><code>licenseReason = machine_fingerprint_missing</code> :</li><li>le runtime ne parvient pas a calculer le fingerprint local.</li><li><code>licenseReason = license_expired</code> :</li><li>la licence a expire, demandez un renouvellement.</li></ul>",
|
|
14716
14766
|
"codeSamples": []
|
|
14717
14767
|
}
|
|
14718
14768
|
],
|
|
@@ -15387,42 +15437,46 @@ const frameworkDocsContent = {
|
|
|
15387
15437
|
},
|
|
15388
15438
|
{
|
|
15389
15439
|
"id": "sec_2",
|
|
15390
|
-
"title": "
|
|
15440
|
+
"title": "Ce que la toolbar affiche par defaut"
|
|
15391
15441
|
},
|
|
15392
15442
|
{
|
|
15393
15443
|
"id": "sec_3",
|
|
15394
|
-
"title": "
|
|
15444
|
+
"title": "Reference de capture d'ecran (manuel utilisateur)"
|
|
15395
15445
|
},
|
|
15396
15446
|
{
|
|
15397
15447
|
"id": "sec_4",
|
|
15398
|
-
"title": "
|
|
15448
|
+
"title": "Metadonnees inline editing"
|
|
15399
15449
|
},
|
|
15400
15450
|
{
|
|
15401
15451
|
"id": "sec_5",
|
|
15402
|
-
"title": "
|
|
15452
|
+
"title": "Barre d'outils export/import"
|
|
15403
15453
|
},
|
|
15404
15454
|
{
|
|
15405
15455
|
"id": "sec_6",
|
|
15406
|
-
"title": "
|
|
15456
|
+
"title": "Config metadata"
|
|
15407
15457
|
},
|
|
15408
15458
|
{
|
|
15409
15459
|
"id": "sec_7",
|
|
15410
|
-
"title": "md_props_bag:
|
|
15460
|
+
"title": "md_props_bag: toolbar"
|
|
15411
15461
|
},
|
|
15412
15462
|
{
|
|
15413
15463
|
"id": "sec_8",
|
|
15414
|
-
"title": "
|
|
15464
|
+
"title": "md_props_bag: archetypes.list"
|
|
15415
15465
|
},
|
|
15416
15466
|
{
|
|
15417
15467
|
"id": "sec_9",
|
|
15418
|
-
"title": "
|
|
15468
|
+
"title": "Pagination : md_pagesize et md_page_size_choice"
|
|
15419
15469
|
},
|
|
15420
15470
|
{
|
|
15421
15471
|
"id": "sec_10",
|
|
15422
|
-
"title": "
|
|
15472
|
+
"title": "Activation forcee de la virtualisation sur une taille de page elevee"
|
|
15423
15473
|
},
|
|
15424
15474
|
{
|
|
15425
15475
|
"id": "sec_11",
|
|
15476
|
+
"title": "Evenements et subscriptions (host)"
|
|
15477
|
+
},
|
|
15478
|
+
{
|
|
15479
|
+
"id": "sec_12",
|
|
15426
15480
|
"title": "`rowCustomSelect` — signature reelle (piege)"
|
|
15427
15481
|
}
|
|
15428
15482
|
],
|
|
@@ -15430,7 +15484,7 @@ const frameworkDocsContent = {
|
|
|
15430
15484
|
{
|
|
15431
15485
|
"id": "overview",
|
|
15432
15486
|
"title": "Overview",
|
|
15433
|
-
"html": "<h1>List Grid</h1><p>Composant principal pour les listes tabulaires avec filtres, tri, pagination cote serveur et actions sur les lignes.</p><h2>Cas d'utilisation</h2><ul><li>CRUD tabulaires enterprise.</li><li>Rapports operationnels avec filtres multi-colonnes.</li><li>Jeux de donnees tres volumineux avec <code>cursorMode</code>.</li></ul><h2>Reference de capture d'ecran (manuel utilisateur)</h2><ul><li><code>manual__grid__01.png</code> : mode <code>inline cell edit</code> dans list-grid.</li><li><code>manual__grid__02.png</code> : mode <code>inline edit</code> (au niveau ligne) dans list-grid.</li></ul><h2>Metadonnees inline editing</h2><p>Configuration dans le <code>md_props_bag</code> de la table metadata :</p><ul><li><code>md_inline_edit</code></li></ul><p> - active l'edition inline de la ligne dans list-grid (cellules editables dans le contexte de la ligne, sans ouverture de popup).</p><p> - utile lorsque vous souhaitez conserver l'UX tabulaire avec une edition rapide par enregistrement.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - active l'edition inline "cellule par cellule" (focus sur la cellule individuelle).</p><p> - note : dans les configurations legacy, il peut apparaitre sous le nom <code>md_inline_cell_editing</code> ; le comportement runtime est le meme.</p><p> - <strong>promotion runtime</strong> : lorsque <code>md_inline_cell_edit</code> est <code>true</code>, le composant force</p><p> a runtime egalement <code>md_inline_edit = true</code> independamment de la valeur en DB.</p><p> Les deux UX necessitent que la colonne d'actions soit visible, elles sont donc mutuellement</p><p> non exclusives au niveau du rendu.</p><ul><li><code>md_batch_save</code></li></ul><p> - active la sauvegarde batch des modifications en attente (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - si utilise conjointement avec inline-cell, les modifications restent en attente jusqu'a la sauvegarde explicite.</p><p> - <strong>prerequis</strong> : <code>md_batch_save</code> n'a d'effet <strong>que</strong> si <code>md_inline_cell_edit</code> est <code>true</code>.</p><p> Avec <code>md_inline_cell_edit:false</code>, le flag est ignore a runtime et les boutons</p><p> "Sauvegarder les modifications / Annuler les modifications" ne sont pas affiches.</p><h3>Combinaisons valides</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Resultat runtime</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>quelconque</td><td>Edition inline au niveau ligne avec crayon. <code>md_batch_save</code> ignore.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Autosave cellule par cellule au blur. <code>md_inline_edit</code> force a <code>true</code> a runtime.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Cellule par cellule avec buffer en attente + barre d'outils <code>Sauvegarder / Annuler les modifications</code>.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>quelconque</td><td>Aucune edition inline. <code>md_batch_save</code> ignore.</td></tr></tbody></table><p>Exemple edition inline au niveau ligne :</p><p>Snippet 1:</p><p>Exemple cellule par cellule avec sauvegarde batch :</p><p>Snippet 2:</p><h2>Barre d'outils export/import</h2><ul><li>Export XLS :</li></ul><p> - affiche une boite de dialogue de progression avec pourcentage en temps reel ;</p><p> - actions : <code>Continuer en arriere-plan</code>, <code>Annuler la tache</code>, <code>Interrompre et telecharger le partiel</code> ;</p><p> - en arriere-plan, cree une notification avec progression ; un clic rouvre la boite de dialogue.</p><ul><li>Import XLS/XLSX (si <code>md_importable = true</code>) :</li></ul><p> - boite de dialogue de progression apres la confirmation ;</p><p> - actions : <code>Continuer en arriere-plan</code>, <code>Annuler l'import (rollback)</code>, <code>Arreter et commit partiel</code> ;</p><p> - a la fin de l'import, cree une notification recapitulative qui redirige vers la route.</p><h2>Config metadata</h2><p>Parametres cles dans <code>md_props_bag</code> et metadonnees de colonnes.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Flags opt-in qui masquent des blocs de la barre d'outils de la list-grid (<code>caption-bar</code>). Tous sous <code>md_props_bag.toolbar.*</code> (parse au runtime comme <code>tableMetadata.extraProps.toolbar</code>).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, defaut <code>false</code>) : masque dans la <strong>caption-right</strong> le bouton "Gestion etat" (icone bookmark) + le <code><select></code> des etats enregistres. Utile pour les routes hardcoded / demo ou la fonctionnalite saved-state (persistance par <code>user_id</code> + route via <code>MetaService</code>) n'a pas de sens — par ex. Pattern 3 pur OData sans route metadata enregistree.</li><li><code>hideBatchActions</code> (boolean, defaut <code>false</code>) : masque dans la <strong>caption-left</strong> les boutons "Enregistrer les modifications" (<code>pi-save</code>) + "Annuler les modifications" (<code>pi-times</code>) + l'indicateur de comptage des changements (<code>grid-changes-indicator</code>, badge pencil + count). Generes par le framework quand <code>md_inline_cell_editing</code> + <code>md_batch_save</code> sont actifs. Concu pour les <strong>grids imbriquees dans un parametric-dialog</strong> : le save/cancel du parent persiste le master + les lignes en un seul coup via le batch save framework, et les boutons en double sur la grid imbriquee perturbent l'UX.</li></ul><p>Exemple de lignes imbriquees dans un edit-form custom (patch runtime) :</p><p>Snippet 5:</p><p>Type TS dans <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (propriete <code>extraProps.toolbar</code>). Les flags ne desactivent PAS la logique <code>md_batch_save</code> sous-jacente (les changements restent traces) ; ils suppriment uniquement l'UI de la barre d'outils — le save effectif passe par le flux du parent.</p><h2>md_props_bag: archetypes.list</h2><p>Le composant lit <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code> :</li><li>type : boolean (avec parser tolerant)</li><li>valeurs acceptees : <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>valeur par defaut runtime : <code>true</code> lorsqu'absent ou vide</li><li>effet : distribue les largeurs de colonnes en pourcentage (au lieu de px) lorsqu'il n'y a pas de largeurs utilisateur persistees.</li></ul><ul><li><code>virtualize</code> :</li><li>type : <code>boolean</code> ou <code>object</code></li><li>valeurs acceptees :</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>object avec <code>enabled</code> (optionnel) et <code>itemSize</code> (optionnel)</li><li>valeur par defaut runtime : desactive (<code>false</code>) lorsqu'absent</li><li><code>enabled</code> :</li><li>par defaut : <code>true</code> si le noeud <code>virtualize</code> est un objet sans <code>enabled</code>, sinon parser tolerant</li><li>effet : active <code>virtualScroll</code> sur <code>p-table</code></li><li><code>itemSize</code> :</li><li>par defaut : <code>44</code></li><li>effet : definit <code>virtualScrollItemSize</code> (hauteur de la ligne virtuelle en px)</li></ul><ul><li><code>advancedFilter</code> :</li><li>type : boolean (avec parser tolerant)</li><li>valeur par defaut runtime : <code>false</code></li><li>effet :</li><li>lorsque <code>true</code>, la grille masque les icones de filtre de colonne (<code>p-columnFilter</code>) et utilise la <code>wuic-filter-bar</code> au-dessus de la table (au niveau <code>data-repeater</code>/<code>bounded-repeater</code>) pour appliquer les filtres.</li></ul><p>Note operationnelle :</p><ul><li>le suggest <code>md_props_bag</code> dans le metadata editor expose egalement le noeud cochable <code>archetypes.list.advancedFilter</code>.</li></ul><h2>Pagination : md_pagesize et md_page_size_choice</h2><p>La grille utilise <code>md_pagesize</code> comme taille de page par defaut et <code>md_page_size_choice</code> comme liste de valeurs selectionnables dans le paginateur.</p><p>Regles runtime :</p><ul><li>si <code>md_pagesize</code> est superieur a la valeur maximale presente dans <code>md_page_size_choice</code>, le framework ajoute automatiquement <code>md_pagesize</code> a la liste d'options ;</li><li>la liste est normalisee (nombres valides, deduplication, tri croissant).</li></ul><p>Exemple :</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>resultat runtime : <code>10,25,50,100,200</code></li></ul><h2>Activation forcee de la virtualisation sur une taille de page elevee</h2><p>Lorsque l'utilisateur selectionne dans le paginateur une valeur <code>pageSize >= 1000</code> :</p><ul><li>la virtualisation est forcee automatiquement meme si <code>md_props_bag.archetypes.list.virtualize</code> est absent ou desactive ;</li><li><code>virtualScrollItemSize</code> est force a la valeur par defaut <code>44</code>.</li></ul><p>Ce comportement protege le rendu de la table sur des pages tres volumineuses.</p><h2>Evenements et subscriptions (host)</h2><p><code>wuic-list-grid</code> expose des evenements runtime utiles pour intercepter le cycle de rendu et les callbacks p-table cote projet host.</p><p>Evenements disponibles :</p><ul><li><code>onAfterRender</code> : emis a la fin du binding des donnees de la grille (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code> : emis avant le rendu logique de la ligne individuelle ; supporte l'annulation via <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code> : emis apres le rendu logique de la ligne individuelle.</li><li><code>onPaging</code> : emis sur les evenements de pagination (<code>p-table onPage</code>).</li><li><code>onSorting</code> : emis sur les evenements de tri (<code>p-table onSort</code>).</li><li><code>onFiltering</code> : emis sur les evenements de filtrage (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code> : emis lors du changement de selection des lignes.</li><li><code>onPTableRowExpand</code> : emis lors de l'expansion d'une ligne.</li><li><code>onPTableRowCollapse</code> : emis lors de la reduction d'une ligne.</li><li><code>onPTableColumnResize</code> : emis lors du redimensionnement d'une colonne.</li><li><code>onPTableColumnReorder</code> : emis lors de la reorganisation des colonnes.</li></ul><h3>Exemple 1 : binding direct dans le template</h3><p>Snippet 7:</p><h3>Exemple 2 : subscribe via ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — signature reelle (piege)</h2><p><code><wuic-list-grid></code> accepte une entree <code>[rowCustomSelect]</code> pour intercepter la selection d'une ligne (ouverture d'une dialog "choisir un document", flux master-detail, etc.). La signature TypeScript declaree dans <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> est :</p><p>Snippet 9:</p><p><strong>Mais au runtime la callback est invoquee avec les arguments inverses</strong> — le framework appelle <code>rowCustomSelect($event, rowData, dt)</code> (voir <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> et <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Symptome en cas d'ordre incorrect : <code>rowData?.id</code> est undefined → guard precoce dans votre handler → la callback retourne silencieusement et votre dialog/action ne demarre pas. Aucune erreur en console.</p><p>Forme correcte (alignee a l'invocation runtime) :</p><p>Snippet 10:</p><p>Utilisation dans le template :</p><p>Snippet 11:</p><p>> Note : les tests dans <code>designer.component.spec.ts</code> (par ex. ligne 512) invoquent la callback avec <code>({currentTarget: rowCell}, {id: 42}, null)</code>, confirmant l'ordre <code>($event, rowData, dt)</code>. Si le framework finit par aligner la signature declaree, cette page sera mise a jour.</p>",
|
|
15487
|
+
"html": "<h1>List Grid</h1><p>Composant principal pour les listes tabulaires avec filtres, tri, pagination cote serveur et actions sur les lignes.</p><h2>Cas d'utilisation</h2><ul><li>CRUD tabulaires enterprise.</li><li>Rapports operationnels avec filtres multi-colonnes.</li><li>Jeux de donnees tres volumineux avec <code>cursorMode</code>.</li></ul><h2>Ce que la toolbar affiche par defaut</h2><p>En ouvrant une route fraichement scaffoldee, la caption-bar se trouve au-dessus de la grille.</p><p>A gauche :</p><table><thead><tr><th>Bouton</th><th>Quand il apparait</th></tr></thead><tbody><tr><td><strong>Actualiser</strong></td><td>toujours, sauf <code>md_hide_refresh</code></td></tr><tr><td><strong>Ajouter</strong></td><td>avec <code>md_insertable</code></td></tr><tr><td><strong>Actes</strong></td><td>si la table a des actions custom</td></tr><tr><td>Import / Export</td><td>toujours ; la branche import seulement avec <code>md_importable</code></td></tr><tr><td><strong>Rapports</strong></td><td>si au moins un rapport est associe a la route</td></tr><tr><td><strong>Enregistrer les modifications</strong> / <strong>Annuler les modifications</strong></td><td>seulement avec <code>md_inline_cell_edit</code> <strong>et</strong> <code>md_batch_save</code></td></tr></tbody></table><p>A droite : <strong>Gerer l'etat</strong> (precede de la liste des etats sauvegardes, s'il y en a),</p><p><strong>Effacer les filtres</strong> quand les filtres sont sur les colonnes, et <strong>Performance</strong> si</p><p>l'inspector est active sur la route.</p><p>> Les libelles cites plus bas dans cette page <strong>ne sont pas sur cet ecran</strong>, et ce n'est pas un</p><p>> defaut : ceux de l'export/import (<em>Continuer en arriere-plan</em>, <em>Annuler la tache</em>, *Arreter et</p><p>> telecharger partiel<em>, </em>Annuler l'import (rollback)<em>, </em>Arreter et valider partiel*) vivent dans</p><p>> la boite de progression, qui n'existe que pendant un export ou un import ; *Enregistrer les</p><p>> modifications<em> et </em>Annuler les modifications* n'apparaissent qu'avec les deux flags ci-dessus.</p><p>> Ils appartiennent a d'autres moments que la premiere ouverture de la liste.</p><h2>Reference de capture d'ecran (manuel utilisateur)</h2><ul><li><code>manual__grid__01.png</code> : mode <code>inline cell edit</code> dans list-grid.</li><li><code>manual__grid__02.png</code> : mode <code>inline edit</code> (au niveau ligne) dans list-grid.</li></ul><h2>Metadonnees inline editing</h2><p>Configuration dans le <code>md_props_bag</code> de la table metadata :</p><ul><li><code>md_inline_edit</code></li></ul><p> - active l'edition inline de la ligne dans list-grid (cellules editables dans le contexte de la ligne, sans ouverture de popup).</p><p> - utile lorsque vous souhaitez conserver l'UX tabulaire avec une edition rapide par enregistrement.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - active l'edition inline "cellule par cellule" (focus sur la cellule individuelle).</p><p> - note : dans les configurations legacy, il peut apparaitre sous le nom <code>md_inline_cell_editing</code> ; le comportement runtime est le meme.</p><p> - <strong>promotion runtime</strong> : lorsque <code>md_inline_cell_edit</code> est <code>true</code>, le composant force</p><p> a runtime egalement <code>md_inline_edit = true</code> independamment de la valeur en DB.</p><p> Les deux UX necessitent que la colonne d'actions soit visible, elles sont donc mutuellement</p><p> non exclusives au niveau du rendu.</p><ul><li><code>md_batch_save</code></li></ul><p> - active la sauvegarde batch des modifications en attente (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - si utilise conjointement avec inline-cell, les modifications restent en attente jusqu'a la sauvegarde explicite.</p><p> - <strong>prerequis</strong> : <code>md_batch_save</code> n'a d'effet <strong>que</strong> si <code>md_inline_cell_edit</code> est <code>true</code>.</p><p> Avec <code>md_inline_cell_edit:false</code>, le flag est ignore a runtime et les boutons</p><p> "Sauvegarder les modifications / Annuler les modifications" ne sont pas affiches.</p><h3>Combinaisons valides</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Resultat runtime</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>quelconque</td><td>Edition inline au niveau ligne avec crayon. <code>md_batch_save</code> ignore.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Autosave cellule par cellule au blur. <code>md_inline_edit</code> force a <code>true</code> a runtime.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Cellule par cellule avec buffer en attente + barre d'outils <code>Sauvegarder / Annuler les modifications</code>.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>quelconque</td><td>Aucune edition inline. <code>md_batch_save</code> ignore.</td></tr></tbody></table><p>Exemple edition inline au niveau ligne :</p><p>Snippet 1:</p><p>Exemple cellule par cellule avec sauvegarde batch :</p><p>Snippet 2:</p><h2>Barre d'outils export/import</h2><ul><li>Export XLS :</li></ul><p> - affiche une boite de dialogue de progression avec pourcentage en temps reel ;</p><p> - actions : <code>Continuer en arriere-plan</code>, <code>Annuler la tache</code>, <code>Interrompre et telecharger le partiel</code> ;</p><p> - en arriere-plan, cree une notification avec progression ; un clic rouvre la boite de dialogue.</p><ul><li>Import XLS/XLSX (si <code>md_importable = true</code>) :</li></ul><p> - boite de dialogue de progression apres la confirmation ;</p><p> - actions : <code>Continuer en arriere-plan</code>, <code>Annuler l'import (rollback)</code>, <code>Arreter et commit partiel</code> ;</p><p> - a la fin de l'import, cree une notification recapitulative qui redirige vers la route.</p><h2>Config metadata</h2><p>Parametres cles dans <code>md_props_bag</code> et metadonnees de colonnes.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Flags opt-in qui masquent des blocs de la barre d'outils de la list-grid (<code>caption-bar</code>). Tous sous <code>md_props_bag.toolbar.*</code> (parse au runtime comme <code>tableMetadata.extraProps.toolbar</code>).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, defaut <code>false</code>) : masque dans la <strong>caption-right</strong> le bouton "Gestion etat" (icone bookmark) + le <code><select></code> des etats enregistres. Utile pour les routes hardcoded / demo ou la fonctionnalite saved-state (persistance par <code>user_id</code> + route via <code>MetaService</code>) n'a pas de sens — par ex. Pattern 3 pur OData sans route metadata enregistree.</li><li><code>hideBatchActions</code> (boolean, defaut <code>false</code>) : masque dans la <strong>caption-left</strong> les boutons "Enregistrer les modifications" (<code>pi-save</code>) + "Annuler les modifications" (<code>pi-times</code>) + l'indicateur de comptage des changements (<code>grid-changes-indicator</code>, badge pencil + count). Generes par le framework quand <code>md_inline_cell_editing</code> + <code>md_batch_save</code> sont actifs. Concu pour les <strong>grids imbriquees dans un parametric-dialog</strong> : le save/cancel du parent persiste le master + les lignes en un seul coup via le batch save framework, et les boutons en double sur la grid imbriquee perturbent l'UX.</li></ul><p>Exemple de lignes imbriquees dans un edit-form custom (patch runtime) :</p><p>Snippet 5:</p><p>Type TS dans <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (propriete <code>extraProps.toolbar</code>). Les flags ne desactivent PAS la logique <code>md_batch_save</code> sous-jacente (les changements restent traces) ; ils suppriment uniquement l'UI de la barre d'outils — le save effectif passe par le flux du parent.</p><h2>md_props_bag: archetypes.list</h2><p>Le composant lit <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code> :</li><li>type : boolean (avec parser tolerant)</li><li>valeurs acceptees : <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>valeur par defaut runtime : <code>true</code> lorsqu'absent ou vide</li><li>effet : distribue les largeurs de colonnes en pourcentage (au lieu de px) lorsqu'il n'y a pas de largeurs utilisateur persistees.</li></ul><ul><li><code>virtualize</code> :</li><li>type : <code>boolean</code> ou <code>object</code></li><li>valeurs acceptees :</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>object avec <code>enabled</code> (optionnel) et <code>itemSize</code> (optionnel)</li><li>valeur par defaut runtime : desactive (<code>false</code>) lorsqu'absent</li><li><code>enabled</code> :</li><li>par defaut : <code>true</code> si le noeud <code>virtualize</code> est un objet sans <code>enabled</code>, sinon parser tolerant</li><li>effet : active <code>virtualScroll</code> sur <code>p-table</code></li><li><code>itemSize</code> :</li><li>par defaut : <code>44</code></li><li>effet : definit <code>virtualScrollItemSize</code> (hauteur de la ligne virtuelle en px)</li></ul><ul><li><code>advancedFilter</code> :</li><li>type : boolean (avec parser tolerant)</li><li>valeur par defaut runtime : <code>false</code></li><li>effet :</li><li>lorsque <code>true</code>, la grille masque les icones de filtre de colonne (<code>p-columnFilter</code>) et utilise la <code>wuic-filter-bar</code> au-dessus de la table (au niveau <code>data-repeater</code>/<code>bounded-repeater</code>) pour appliquer les filtres.</li></ul><p>Note operationnelle :</p><ul><li>le suggest <code>md_props_bag</code> dans le metadata editor expose egalement le noeud cochable <code>archetypes.list.advancedFilter</code>.</li></ul><h2>Pagination : md_pagesize et md_page_size_choice</h2><p>La grille utilise <code>md_pagesize</code> comme taille de page par defaut et <code>md_page_size_choice</code> comme liste de valeurs selectionnables dans le paginateur.</p><p>Regles runtime :</p><ul><li>si <code>md_pagesize</code> est superieur a la valeur maximale presente dans <code>md_page_size_choice</code>, le framework ajoute automatiquement <code>md_pagesize</code> a la liste d'options ;</li><li>la liste est normalisee (nombres valides, deduplication, tri croissant).</li></ul><p>Exemple :</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>resultat runtime : <code>10,25,50,100,200</code></li></ul><h2>Activation forcee de la virtualisation sur une taille de page elevee</h2><p>Lorsque l'utilisateur selectionne dans le paginateur une valeur <code>pageSize >= 1000</code> :</p><ul><li>la virtualisation est forcee automatiquement meme si <code>md_props_bag.archetypes.list.virtualize</code> est absent ou desactive ;</li><li><code>virtualScrollItemSize</code> est force a la valeur par defaut <code>44</code>.</li></ul><p>Ce comportement protege le rendu de la table sur des pages tres volumineuses.</p><h2>Evenements et subscriptions (host)</h2><p><code>wuic-list-grid</code> expose des evenements runtime utiles pour intercepter le cycle de rendu et les callbacks p-table cote projet host.</p><p>Evenements disponibles :</p><ul><li><code>onAfterRender</code> : emis a la fin du binding des donnees de la grille (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code> : emis avant le rendu logique de la ligne individuelle ; supporte l'annulation via <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code> : emis apres le rendu logique de la ligne individuelle.</li><li><code>onPaging</code> : emis sur les evenements de pagination (<code>p-table onPage</code>).</li><li><code>onSorting</code> : emis sur les evenements de tri (<code>p-table onSort</code>).</li><li><code>onFiltering</code> : emis sur les evenements de filtrage (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code> : emis lors du changement de selection des lignes.</li><li><code>onPTableRowExpand</code> : emis lors de l'expansion d'une ligne.</li><li><code>onPTableRowCollapse</code> : emis lors de la reduction d'une ligne.</li><li><code>onPTableColumnResize</code> : emis lors du redimensionnement d'une colonne.</li><li><code>onPTableColumnReorder</code> : emis lors de la reorganisation des colonnes.</li></ul><h3>Exemple 1 : binding direct dans le template</h3><p>Snippet 7:</p><h3>Exemple 2 : subscribe via ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — signature reelle (piege)</h2><p><code><wuic-list-grid></code> accepte une entree <code>[rowCustomSelect]</code> pour intercepter la selection d'une ligne (ouverture d'une dialog "choisir un document", flux master-detail, etc.). La signature TypeScript declaree dans <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> est :</p><p>Snippet 9:</p><p><strong>Mais au runtime la callback est invoquee avec les arguments inverses</strong> — le framework appelle <code>rowCustomSelect($event, rowData, dt)</code> (voir <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> et <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Symptome en cas d'ordre incorrect : <code>rowData?.id</code> est undefined → guard precoce dans votre handler → la callback retourne silencieusement et votre dialog/action ne demarre pas. Aucune erreur en console.</p><p>Forme correcte (alignee a l'invocation runtime) :</p><p>Snippet 10:</p><p>Utilisation dans le template :</p><p>Snippet 11:</p><p>> Note : les tests dans <code>designer.component.spec.ts</code> (par ex. ligne 512) invoquent la callback avec <code>({currentTarget: rowCell}, {id: 42}, null)</code>, confirmant l'ordre <code>($event, rowData, dt)</code>. Si le framework finit par aligner la signature declaree, cette page sera mise a jour.</p>",
|
|
15434
15488
|
"codeSamples": [
|
|
15435
15489
|
{
|
|
15436
15490
|
"id": "code_1",
|
|
@@ -17156,7 +17210,7 @@ const frameworkDocsContent = {
|
|
|
17156
17210
|
{
|
|
17157
17211
|
"id": "overview",
|
|
17158
17212
|
"title": "Overview",
|
|
17159
|
-
"html": "<h1>Designer</h1><p>Editeur visuel pour les dashboards pilotes par metadata sur la route <code>#/cities/dashboard</code>.</p><h2>Scope</h2><ul><li>Composition de board par glisser-deposer de noeuds et blocs UI.</li><li>Mise en page et styles pilotes par <code>boardcontent</code> et metadata table/colonne.</li><li>Edition via le panneau de proprietes sans codage en dur dans les composants runtime.</li></ul><h2>Palette Designer</h2><
|
|
17213
|
+
"html": "<h1>Designer</h1><p>Editeur visuel pour les dashboards pilotes par metadata sur la route <code>#/cities/dashboard</code>.</p><h2>Scope</h2><ul><li>Composition de board par glisser-deposer de noeuds et blocs UI.</li><li>Mise en page et styles pilotes par <code>boardcontent</code> et metadata table/colonne.</li><li>Edition via le panneau de proprietes sans codage en dur dans les composants runtime.</li></ul><h2>Palette Designer</h2><p>La palette est divisee en trois groupes. Les noms ci-dessous sont ceux que vous lisez dans la</p><p>palette, en majuscules comme le designer les ecrit.</p><p><strong>HTML</strong> — les briques de balisage :</p><table><thead><tr><th>Tool</th><th>A quoi ca sert</th></tr></thead><tbody><tr><td><code>TABLE</code></td><td>grille de cellules. <code>TR</code> et <code>TD</code> existent comme tools mais ne se glissent pas : c'est la table qui les cree</td></tr><tr><td><code>DIV</code></td><td>conteneur libre, le bloc structurel le plus utilise</td></tr><tr><td><code>SPAN</code>, <code>LABEL</code>, <code>Hx</code></td><td>texte databound ; <code>Hx</code> choisit le niveau de h1 a h6</td></tr><tr><td><code>ANCHOR</code>, <code>IMG</code>, <code>IMAGE</code>, <code>IFRAME</code></td><td>liens, images, contenu externe</td></tr><tr><td><code>UL</code></td><td>liste</td></tr><tr><td><code>BUTTON</code></td><td>bouton avec callback</td></tr><tr><td><code>INPUT</code>, <code>TEXTAREA</code>, <code>CHECKBOX</code>, <code>SELECT</code>, <code>MULTISELECT</code>, <code>DATE</code></td><td>champs de saisie</td></tr><tr><td><code>KPI</code></td><td>une valeur unique mise en avant</td></tr><tr><td><code>SEPARATOR</code>, <code>HR</code></td><td>separateurs</td></tr></tbody></table><p><strong>DATA</strong> — les noeuds relies au backend :</p><table><thead><tr><th>Tool</th><th>A quoi ca sert</th></tr></thead><tbody><tr><td><code>DATASOURCE</code></td><td>source de donnees metadata (<code>route</code>, filtres, tri, pagination)</td></tr><tr><td><code>DATAREPEATER</code></td><td>visualisation liste/carte liee a une datasource</td></tr><tr><td><code>FILTERBAR</code></td><td>barre de filtres au-dessus du repeater</td></tr><tr><td><code>PAGER</code></td><td>paginateur</td></tr></tbody></table><p><strong>CONTAINER</strong> — les mises en page :</p><table><thead><tr><th>Tool</th><th>A quoi ca sert</th></tr></thead><tbody><tr><td><code>TABVIEW</code> + <code>TABPANEL</code></td><td>onglets</td></tr><tr><td><code>SPLITTER</code> + <code>SPLITTER-AREA</code></td><td>panneaux redimensionnables</td></tr><tr><td><code>ACCORDION</code> + <code>ACCORDION-AREA</code></td><td>sections en accordeon</td></tr></tbody></table><p>Deux noms que l'on cherche en vain : <strong>il n'existe aucun tool "Dynamic Template"</strong> — le template</p><p>dynamique est ce que le <code>DATAREPEATER</code> rend, il se configure depuis ses proprietes et ne se</p><p>glisse pas ; et <strong>"Container" / "Layout" sont le nom du groupe</strong>, pas des entrees selectionnables.</p><p>S'y ajoutent les tools custom enregistres par le projet hote</p><p>(<code>MetadataProviderService.customDesignerTools</code>), qui apparaissent en fin de liste sous le groupe</p><p>qu'ils declarent.</p><h2>Fonctionnalites principales</h2><ul><li>Glisser-deposer de noeuds sur le canvas avec persistance dans le <code>boardcontent</code>.</li><li>Panneau de proprietes contextuel avec des inputs coherents aux composants selectionnes.</li><li>Liaison entre noeuds (<code>datasource -> repeater/template</code>) avec validation minimale.</li><li>Apercu runtime integre et realignement de la mise en page.</li><li>Gestion des modifications en attente avec guard avant la sortie.</li></ul><h2>Menu contextuel des elements</h2><p>Le clic droit sur un element du canvas, sur un element du fil d'Ariane en bas ou sur un noeud de l'arbre de hierarchie affiche un menu contextuel avec trois entrees :</p><ul><li><strong>Modifier les proprietes</strong> (pi-cog) - selectionne l'element comme "current tool" et affiche son panneau de proprietes a droite ; equivalent au clic dans l'arbre. Utile pour editer les proprietes d'elements imbriques sans devoir les chercher dans la hierarchie.</li><li><strong>Renommer</strong> (uniquement fil d'Ariane) - ouvre une boite de dialogue pour renommer le <code>displayName</code>.</li><li><strong>Supprimer</strong> - retire l'element du board.</li></ul><h2>Flux operationnel conseille</h2><ul><li>Ouvrir la route dashboard cible.</li><li>Inserer/relier les noeuds depuis la palette.</li><li>Configurer les <code>inputs</code> essentiels (ex. <code>route</code>, <code>action</code>, <code>datasource</code>).</li><li>Sauvegarder et valider le resultat en runtime.</li></ul><h2>Notes operationnelles</h2><ul><li>Pour les correctifs specifiques a un dashboard, privilegier la patch du <code>boardcontent</code> plutot que des modifications globales.</li><li>Eviter les proprietes dupliquees entre <code>inputs</code> et le style inline incoherent.</li><li>Toujours verifier que les datasources ont <code>inputs.route</code> renseignee.</li></ul>",
|
|
17160
17214
|
"codeSamples": []
|
|
17161
17215
|
}
|
|
17162
17216
|
],
|
|
@@ -21271,13 +21325,17 @@ const frameworkDocsContent = {
|
|
|
21271
21325
|
{
|
|
21272
21326
|
"id": "sec_4",
|
|
21273
21327
|
"title": "Quick Start — primer componente"
|
|
21328
|
+
},
|
|
21329
|
+
{
|
|
21330
|
+
"id": "sec_5",
|
|
21331
|
+
"title": "Las primeras listas muestran 20 registros: es el modo Trial"
|
|
21274
21332
|
}
|
|
21275
21333
|
],
|
|
21276
21334
|
"sections": [
|
|
21277
21335
|
{
|
|
21278
21336
|
"id": "overview",
|
|
21279
21337
|
"title": "Overview",
|
|
21280
|
-
"html": "<h1>Panorámica del Framework</h1><p>WUIC Framework es una plataforma metadata-driven para crear interfaces de negocio de forma rápida y coherente.</p><h2>Qué incluye</h2><ul><li>DataSource y DataRepeater para orquestar datos y renderizado.</li><li>Archetypes visuales (list, map, scheduler, chart, carousel).</li><li>Designer runtime para dashboards y templates dinámicos.</li><li>Workflow designer/runner para procesos operativos.</li><li>RAG Chatbot para consultar la codebase en lenguaje natural.</li><li>Multi-SGBD: SQL Server, MySQL, PostgreSQL y Oracle mediante providers drop-in (<code>dbms</code>: <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Arranque del entorno dev</h2><p>El stack WUIC está compuesto por varios servicios. Arráncalos en el orden indicado.</p><h3>Prerrequisitos</h3><table><thead><tr><th>Qué</th><th>Verificación</th><th>Notas</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle para IIS en producción</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>La 22 es la version con la que se prueba el paquete; con npm 10.9.x la instalacion funciona gracias al <code>package-lock.json</code> incluido</td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>El Windows PowerShell preinstalado es suficiente: <code>rename-project.ps1</code> y los scripts <code>llm-workspace/</code> tambien funcionan en 5.1. PowerShell 7 es recomendable, no obligatorio</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>Si falta, <strong>la línea única lo instala por su cuenta</strong> (SQL Server Express, o el motor elegido con <code>-Dbms</code>); en Windows Server no, ver el recuadro de abajo. 2019 basta para los paquetes sin <code>.bak</code>; el tutorial <code>.bak</code> es una copia de SQL Server 2022 y requiere <strong>2022 o superior</strong></td></tr><tr><td>Linux (instalador <code>install.sh</code>)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 o 24.04 LTS</strong> (24.04 recomendada): son las unicas versiones de Ubuntu que Microsoft soporta para SQL Server, la <strong>26.04 no esta soportada</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Misma recomendacion con MySQL, PostgreSQL y Oracle, porque el instalador esta probado en esas versiones</td></tr><tr><td>GPU NVIDIA (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Opcional: acelera el RAG Chatbot (sin GPU funciona en CPU)</td></tr></tbody></table><p>> <strong>En Windows Server la base de datos debe instalarse antes.</strong> La linea unica obtiene los</p><p>> componentes que faltan mediante <code>winget</code>, que no esta presente en Windows Server: sin una</p><p>> instancia ya accesible la instalacion se detiene con `No SQL Server instance reachable and</p><p>> winget is missing`. Instala el motor antes de ejecutar la linea - SQL Server debe ser **2019 o</p><p>> superior<strong> (Express es suficiente; </strong>2022 o superior** para el tutorial <code>.bak</code>), y una 2017 no</p><p>> se acepta. Si la instancia no es la predeterminada, pasala con</p><p>> <code>-SqlServer 'localhost\\NOMBREINSTANCIA'</code>. Vale para todos los motores, no solo SQL Server.</p><h3>1. Descarga el template de proyecto</h3><p>En Windows una sola linea de PowerShell lo hace todo: descarga el paquete, comprueba el SDK de .NET 10</p><p>y Node.js 22 (instalando lo que falte), ejecuta <code>dotnet restore</code> y <code>npm install</code>,</p><p>e instala la extension WUIC Assistant en VS Code.</p><p>Snippet 1:</p><p>Opciones útiles en la misma línea: <code>-Dbms mysql</code> (o <code>postgres</code>, <code>oracle</code>) para un motor</p><p>distinto de SQL Server — el instalador lo instala y lo configura él mismo — y <code>-WithTutorial</code></p><p>para descargar también la base de datos de ejemplo.</p><p>Cuando termina, la última pantalla ya es tu lista de tareas:</p><p>Snippet 2:</p><p>La cadena de conexión ya está lista: en el primer arranque el wizard no pide nada más. Con</p><p><code>-Dbms mysql</code> o <code>-Dbms postgres</code> esa línea cambia en consecuencia y lleva dentro usuario y</p><p>contraseña, porque la contraseña del superusuario <strong>la genera el instalador</strong>; esa misma</p><p>contraseña se guarda en <code>wuic-secrets.json</code>, junto a la instalación, y es el único sitio donde</p><p>queda escrita.</p><p>La via manual sigue siendo valida, en cualquier sistema:</p><p>Parte del paquete <code>WuicTest-src-*.zip</code> (enlace en la sección <strong>Download</strong> del sitio).</p><p>Extráelo en una carpeta de trabajo, p. ej. <code>C:\\dev\\WuicTest</code> (los archivos van directamente</p><p>en la raíz, NO dentro de una subcarpeta <code>src/</code>). El paquete contiene:</p><ul><li><code>WuicTest.csproj</code> → proyecto host con <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → app Angular cuyo <code>package.json</code> referencia <code>wuic-framework-lib</code> desde el registry npm</li><li><code>appsettings.json</code> preconfigurado en modo <code>firstRun = "true"</code> con placeholders <code>__SET_*__</code></li><li><code>appsettings-samples/</code> → 6 templates listos (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>No hace falta clonar el repositorio del framework</strong>: <code>WuicCore</code> llega como paquete NuGet</p><p>> desde <code>nuget.org</code> y <code>wuic-framework-lib</code> como paquete npm desde el registry npm. El código</p><p>> fuente del framework solo se necesita si quieres modificarlo — típicamente no es tu caso.</p><p>> <strong>npm 10.9.x y los paquetes anteriores a 1.7.1</strong>: esos paquetes no incluyen <code>package-lock.json</code>, y</p><p>> sin lock npm 10.9.x (la version que instala Node 22 LTS) se detiene con</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> al resolver las dependencias peer.</p><p>> Descarga el lock publicado junto a la release —</p><p>> <code>https://wuic-framework.com/downloads/locks/<nombre-del-zip>.package-lock.json</code> — colocalo en</p><p>> <code>wwwroot/</code> y ejecuta <code>npm install</code> otra vez. La linea unica <code>-Src</code> lo hace por ti.</p><h3>2. Database</h3><p>Hace falta una instancia del motor accesible. <strong>Con la línea única no hay nada que hacer</strong>:</p><p>la instala y la configura ella, y la cadena de conexión que hay que pegar en el wizard es lo</p><p>último que imprime. En la vía manual la instancia debe existir ya.</p><p>Conexiones en <code>appsettings.json</code>:</p><ul><li><code>MetaDataSQLConnection</code> — DB metadata (menú, tablas, columnas, boards, usuarios)</li><li><code>DataSQLConnection</code> — DB datos de la aplicación</li></ul><p>Si es la primera instalación (<code>AppSettings.firstRun = "true"</code> en el template),</p><p>el wizard de scaffolding en el primer arranque crea el esquema metadata y puebla el DB datos.</p><p>Ver la página <em>Scaffolding inicial</em> para el flujo guiado.</p><h3>3. Backend (.NET)</h3><p>Desde la raíz de la carpeta extraída (p. ej. <code>C:\\dev\\WuicTest</code>):</p><p>Snippet 3:</p><p>El backend expone las API en <code>http://localhost:5000</code>.</p><h3>4. Frontend (Angular)</h3><p>En una segunda shell, desde la subcarpeta <code>wwwroot/</code>:</p><p>Snippet 4:</p><p>El frontend está disponible en <code>http://localhost:4200</code>.</p><p>Login por defecto (post-firstRun): <code>admin</code> / <code>admin</code>.</p><h3>5. RAG Chatbot (opcional)</h3><p>El RAG Chatbot (<code>Administración > RAG Chat</code>) se ejecuta **dentro del backend</p><p>.NET**: el motor de retrieval (<code>rag-engine/WuicRagEngine.dll</code>, ONNX Runtime</p><p>in-process) lo carga el backend cuando <code>AppSettings.rag-use-dotnet-engine</code> es</p><p><code>"true"</code> (valor por defecto en los paquetes de release). **Sin Python, sin</p><p>venv, ningún servidor separado que arrancar.**</p><p>La <strong>primera</strong> vez que se abre el chatbot (o al final del first-run) el</p><p>backend descarga por sí solo los modelos ONNX (<code>bge-m3</code> + reranker), el</p><p>tokenizer y el índice (~4,5 GB) desde <code>rag-engine-models-url</code> (por defecto</p><p><code>https://wuic-framework.com/rag-models</code>) en <code>rag-engine/artifacts/</code>. Solo hace</p><p>falta conexión a internet una vez; la descarga corre en segundo plano (1-5 min)</p><p>y llega una notificación in-app al inicio y al final. Mientras tanto el</p><p>componente muestra el estado <strong>RAG offline</strong> y el resto de la aplicación</p><p>funciona con normalidad.</p><p>Claves <code>AppSettings</code> relevantes (todas con valores por defecto listos):</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — activa el motor .NET (<code>false</code> = fallback Python, ver abajo)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code>: con GPU NVIDIA (CUDA 12.x + cuDNN 9) ~1 s/consulta, en CPU ~15-25 s/consulta</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = fuentes del framework solo como firma; <code>internal</code> = índice completo</li><li><code>rag-engine-models-url</code> — origen de la descarga en el primer arranque</li><li><code>rag-engine-cuda-path</code> = (vacío) — carpeta de las DLL CUDA/cuDNN si no están instaladas a nivel de sistema</li></ul><p>Para el chat con LLM configura <code>rag-llm-provider</code> + <code>rag-llm-api-key</code> (Claude</p><p>vía Anthropic, o un modelo local vía Ollama con <code>rag-llm-base-url</code>). Sin</p><p>provider solo funciona la modalidad retrieval (búsqueda de snippets). Detalle</p><p>de las claves en la página <em>AppSettings</em>.</p><p>> El stack histórico Python (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> en</p><p>> <code>127.0.0.1:8765</code>) solo puede usarse como fallback con</p><p>> <code>rag-use-dotnet-engine = "false"</code> y no se incluye en los paquetes de release.</p><h2>Resumen de servicios</h2><table><thead><tr><th>Servicio</th><th>Puerto</th><th>Obligatorio</th><th>Comando rápido</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>sí</td><td>(servicio Windows)</td></tr><tr><td>Backend .NET</td><td>5000</td><td>sí</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Frontend Angular</td><td>4200</td><td>sí</td><td><code>npm run serve:dev</code></td></tr><tr><td>Engine RAG .NET (ONNX)</td><td>in-process</td><td>no</td><td>cargado por el backend en el primer chat</td></tr></tbody></table><h2>Quick Start — primer componente</h2><p>1. Configura el endpoint AsmxProxy.</p><p>2. Define route metadata y columnas.</p><p>3. Monta <code>wuic-data-source</code> + <code>wuic-data-repeater</code>.</p><p>Snippet 5:</p>",
|
|
21338
|
+
"html": "<h1>Panorámica del Framework</h1><p>WUIC Framework es una plataforma metadata-driven para crear interfaces de negocio de forma rápida y coherente.</p><h2>Qué incluye</h2><ul><li>DataSource y DataRepeater para orquestar datos y renderizado.</li><li>Archetypes visuales (list, map, scheduler, chart, carousel).</li><li>Designer runtime para dashboards y templates dinámicos.</li><li>Workflow designer/runner para procesos operativos.</li><li>RAG Chatbot para consultar la codebase en lenguaje natural.</li><li>Multi-SGBD: SQL Server, MySQL, PostgreSQL y Oracle mediante providers drop-in (<code>dbms</code>: <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Arranque del entorno dev</h2><p>El stack WUIC está compuesto por varios servicios. Arráncalos en el orden indicado.</p><h3>Prerrequisitos</h3><table><thead><tr><th>Qué</th><th>Verificación</th><th>Notas</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle para IIS en producción</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>La 22 es la version con la que se prueba el paquete; con npm 10.9.x la instalacion funciona gracias al <code>package-lock.json</code> incluido</td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>El Windows PowerShell preinstalado es suficiente: <code>rename-project.ps1</code> y los scripts <code>llm-workspace/</code> tambien funcionan en 5.1. PowerShell 7 es recomendable, no obligatorio</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>Si falta, <strong>la línea única lo instala por su cuenta</strong> (SQL Server Express, o el motor elegido con <code>-Dbms</code>); en Windows Server no, ver el recuadro de abajo. 2019 basta para los paquetes sin <code>.bak</code>; el tutorial <code>.bak</code> es una copia de SQL Server 2022 y requiere <strong>2022 o superior</strong></td></tr><tr><td>Linux (instalador <code>install.sh</code>)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 o 24.04 LTS</strong> (24.04 recomendada): son las unicas versiones de Ubuntu que Microsoft soporta para SQL Server, la <strong>26.04 no esta soportada</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Misma recomendacion con MySQL, PostgreSQL y Oracle, porque el instalador esta probado en esas versiones</td></tr><tr><td>GPU NVIDIA (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Opcional: acelera el RAG Chatbot (sin GPU funciona en CPU)</td></tr></tbody></table><p>> <strong>En Windows Server la base de datos debe instalarse antes.</strong> La linea unica obtiene los</p><p>> componentes que faltan mediante <code>winget</code>, que no esta presente en Windows Server: sin una</p><p>> instancia ya accesible la instalacion se detiene con `No SQL Server instance reachable and</p><p>> winget is missing`. Instala el motor antes de ejecutar la linea - SQL Server debe ser **2019 o</p><p>> superior<strong> (Express es suficiente; </strong>2022 o superior** para el tutorial <code>.bak</code>), y una 2017 no</p><p>> se acepta. Si la instancia no es la predeterminada, pasala con</p><p>> <code>-SqlServer 'localhost\\NOMBREINSTANCIA'</code>. Vale para todos los motores, no solo SQL Server.</p><h3>1. Descarga el template de proyecto</h3><p>En Windows una sola linea de PowerShell lo hace todo: descarga el paquete, comprueba el SDK de .NET 10</p><p>y Node.js 22 (instalando lo que falte), ejecuta <code>dotnet restore</code> y <code>npm install</code>,</p><p>e instala la extension WUIC Assistant en VS Code.</p><p>Snippet 1:</p><p>Opciones útiles en la misma línea: <code>-Dbms mysql</code> (o <code>postgres</code>, <code>oracle</code>) para un motor</p><p>distinto de SQL Server — el instalador lo instala y lo configura él mismo — y <code>-WithTutorial</code></p><p>para descargar también la base de datos de ejemplo.</p><p>Cuando termina, la última pantalla ya es tu lista de tareas:</p><p>Snippet 2:</p><p>La cadena de conexión ya está lista: en el primer arranque el wizard no pide nada más. Con</p><p><code>-Dbms mysql</code> o <code>-Dbms postgres</code> esa línea cambia en consecuencia y lleva dentro usuario y</p><p>contraseña, porque la contraseña del superusuario <strong>la genera el instalador</strong>; esa misma</p><p>contraseña se guarda en <code>wuic-secrets.json</code>, junto a la instalación, y es el único sitio donde</p><p>queda escrita.</p><p>La via manual sigue siendo valida, en cualquier sistema:</p><p>Parte del paquete <code>WuicTest-src-*.zip</code> (enlace en la sección <strong>Download</strong> del sitio).</p><p>Extráelo en una carpeta de trabajo, p. ej. <code>C:\\dev\\WuicTest</code> (los archivos van directamente</p><p>en la raíz, NO dentro de una subcarpeta <code>src/</code>). El paquete contiene:</p><ul><li><code>WuicTest.csproj</code> → proyecto host con <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → app Angular cuyo <code>package.json</code> referencia <code>wuic-framework-lib</code> desde el registry npm</li><li><code>appsettings.json</code> preconfigurado en modo <code>firstRun = "true"</code> con placeholders <code>__SET_*__</code></li><li><code>appsettings-samples/</code> → 6 templates listos (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>No hace falta clonar el repositorio del framework</strong>: <code>WuicCore</code> llega como paquete NuGet</p><p>> desde <code>nuget.org</code> y <code>wuic-framework-lib</code> como paquete npm desde el registry npm. El código</p><p>> fuente del framework solo se necesita si quieres modificarlo — típicamente no es tu caso.</p><p>> <strong>npm 10.9.x y los paquetes anteriores a 1.7.1</strong>: esos paquetes no incluyen <code>package-lock.json</code>, y</p><p>> sin lock npm 10.9.x (la version que instala Node 22 LTS) se detiene con</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> al resolver las dependencias peer.</p><p>> Descarga el lock publicado junto a la release —</p><p>> <code>https://wuic-framework.com/downloads/locks/<nombre-del-zip>.package-lock.json</code> — colocalo en</p><p>> <code>wwwroot/</code> y ejecuta <code>npm install</code> otra vez. La linea unica <code>-Src</code> lo hace por ti.</p><h3>2. Database</h3><p>Hace falta una instancia del motor accesible. <strong>Con la línea única no hay nada que hacer</strong>:</p><p>la instala y la configura ella, y la cadena de conexión que hay que pegar en el wizard es lo</p><p>último que imprime. En la vía manual la instancia debe existir ya.</p><p>Conexiones en <code>appsettings.json</code>:</p><ul><li><code>MetaDataSQLConnection</code> — DB metadata (menú, tablas, columnas, boards, usuarios)</li><li><code>DataSQLConnection</code> — DB datos de la aplicación</li></ul><p>Si es la primera instalación (<code>AppSettings.firstRun = "true"</code> en el template),</p><p>el wizard de scaffolding en el primer arranque crea el esquema metadata y puebla el DB datos.</p><p>Ver la página <em>Scaffolding inicial</em> para el flujo guiado.</p><p>#### Qué pide el asistente de primer arranque</p><p>En el primer arranque la aplicación no muestra el formulario de acceso sino la página</p><p><strong>Configuración inicial del proyecto</strong>. Se rellena una sola vez: al terminar <code>firstRun</code> pasa a</p><p><code>false</code> y la página no vuelve a aparecer.</p><ul><li><strong>Modo de instalación</strong> — dos entradas: <strong>Base de datos existente</strong>, que registra una base de</li></ul><p> datos tuya, y <strong>Tutorial WideWorldImporters</strong>, que instala la base de ejemplo. La segunda solo</p><p> aparece si el paquete trae el tutorial (<code>tutorialAvailable</code>): en los paquetes sin tutorial el</p><p> desplegable no se muestra y el modo es "Base de datos existente".</p><ul><li><strong>SGBD</strong> — el motor. Al cambiarlo, la cadena de conexión de abajo se reescribe con la forma</li></ul><p> del proveedor elegido.</p><ul><li><strong>DataSQLConnection</strong> — la cadena hacia la base de datos, y el campo del que depende todo lo</li></ul><p> demás: hasta que no pulses <strong>Probar conexión y cargar bases de datos</strong> la lista de bases</p><p> permanece deshabilitada. La prueba valida las credenciales, enumera las bases del servidor y,</p><p> en SQL Server, corrige por su cuenta los parámetros de certificado</p><p> (<code>Encrypt=False;TrustServerCertificate=True</code>) avisándote. <code>Integrated Security</code> solo vale en</p><p> SQL Server: los demás motores necesitan usuario y contraseña.</p><ul><li><strong>Base de datos</strong> y <strong>Nombre de la base de metadatos</strong> — la primera se elige de la lista que</li></ul><p> cargó la prueba (en modo tutorial es un campo libre, <code>WideWorldImporters</code> por defecto); la</p><p> segunda es el nombre de la base de metadatos a crear (<code>metadataDB</code> por defecto, <code>MetadataCRM</code></p><p> en modo tutorial). Si esa base ya existe, el asistente pide confirmación antes de recrearla.</p><ul><li><strong>Generar automáticamente los metadatos de las tablas</strong> (solo en "Base de datos existente") —</li></ul><p> rellena <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> a partir de todas las tablas de la base</p><p> elegida. Es lo que más alarga el aprovisionamiento en bases con muchas tablas.</p><ul><li><strong>Usuario admin inicial</strong> — nombre de usuario (<code>admin</code> por defecto), contraseña (mínimo 4</li></ul><p> caracteres) e idioma. No hay contraseña predeterminada: la que escribas aquí es la única con</p><p> la que entrarás en el primer acceso. El idioma elegido se aplica al usuario admin y a esta</p><p> misma página.</p><ul><li><strong>RAG Chatbot</strong> — solo la clave de Anthropic, opcional. Nada que instalar: ver el paso 5.</li></ul><p>Al pulsar <strong>Confirmar y crear la base de metadatos</strong> el aprovisionamiento continúa solo, con una</p><p>barra de progreso y el número de lotes procesados. Cuánto dura, medido en las instalaciones de</p><p>prueba: <strong>30 s - 2 min</strong> en modo tutorial, <strong>1-4 min</strong> sobre una base existente con el scaffold</p><p>automático activado. Al terminar, la página deja paso al formulario de acceso.</p><h3>3. Backend (.NET)</h3><p>Desde la raíz de la carpeta extraída (p. ej. <code>C:\\dev\\WuicTest</code>):</p><p>Snippet 3:</p><p>El backend expone las API en <code>http://localhost:5000</code>.</p><h3>4. Frontend (Angular)</h3><p>En una segunda shell, desde la subcarpeta <code>wwwroot/</code>:</p><p>Snippet 4:</p><p>El frontend está disponible en <code>http://localhost:4200</code>.</p><p>Las credenciales son las del usuario admin elegido en el asistente de primer arranque: el</p><p>nombre de usuario es <code>admin</code> si no lo cambiaste, y la contraseña es la que escribiste (no hay</p><p>contraseña predeterminada).</p><h3>5. RAG Chatbot (opcional)</h3><p>El RAG Chatbot (<code>Administración > RAG Chat</code>) se ejecuta **dentro del backend</p><p>.NET**: el motor de retrieval (<code>rag-engine/WuicRagEngine.dll</code>, ONNX Runtime</p><p>in-process) lo carga el backend cuando <code>AppSettings.rag-use-dotnet-engine</code> es</p><p><code>"true"</code> (valor por defecto en los paquetes de release). **Sin Python, sin</p><p>venv, ningún servidor separado que arrancar.**</p><p>La <strong>primera</strong> vez que se abre el chatbot (o al final del first-run) el</p><p>backend descarga por sí solo los modelos ONNX (<code>bge-m3</code> + reranker), el</p><p>tokenizer y el índice (~4,5 GB) desde <code>rag-engine-models-url</code> (por defecto</p><p><code>https://wuic-framework.com/rag-models</code>) en <code>rag-engine/artifacts/</code>. Solo hace</p><p>falta conexión a internet una vez; la descarga corre en segundo plano (1-5 min)</p><p>y llega una notificación in-app al inicio y al final. Mientras tanto el</p><p>componente muestra el estado <strong>RAG offline</strong> y el resto de la aplicación</p><p>funciona con normalidad.</p><p>Claves <code>AppSettings</code> relevantes (todas con valores por defecto listos):</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — activa el motor .NET (<code>false</code> = fallback Python, ver abajo)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code>: con GPU NVIDIA (CUDA 12.x + cuDNN 9) ~1 s/consulta, en CPU ~15-25 s/consulta</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = fuentes del framework solo como firma; <code>internal</code> = índice completo</li><li><code>rag-engine-models-url</code> — origen de la descarga en el primer arranque</li><li><code>rag-engine-cuda-path</code> = (vacío) — carpeta de las DLL CUDA/cuDNN si no están instaladas a nivel de sistema</li></ul><p>Para el chat con LLM configura <code>rag-llm-provider</code> + <code>rag-llm-api-key</code> (Claude</p><p>vía Anthropic, o un modelo local vía Ollama con <code>rag-llm-base-url</code>). Sin</p><p>provider solo funciona la modalidad retrieval (búsqueda de snippets). Detalle</p><p>de las claves en la página <em>AppSettings</em>.</p><p>> El stack histórico Python (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> en</p><p>> <code>127.0.0.1:8765</code>) solo puede usarse como fallback con</p><p>> <code>rag-use-dotnet-engine = "false"</code> y no se incluye en los paquetes de release.</p><h2>Resumen de servicios</h2><table><thead><tr><th>Servicio</th><th>Puerto</th><th>Obligatorio</th><th>Comando rápido</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>sí</td><td>(servicio Windows)</td></tr><tr><td>Backend .NET</td><td>5000</td><td>sí</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Frontend Angular</td><td>4200</td><td>sí</td><td><code>npm run serve:dev</code></td></tr><tr><td>Engine RAG .NET (ONNX)</td><td>in-process</td><td>no</td><td>cargado por el backend en el primer chat</td></tr></tbody></table><h2>Quick Start — primer componente</h2><p>1. Configura el endpoint AsmxProxy.</p><p>2. Define route metadata y columnas.</p><p>3. Monta <code>wuic-data-source</code> + <code>wuic-data-repeater</code>.</p><p>Snippet 5:</p><h2>Las primeras listas muestran 20 registros: es el modo Trial</h2><p>Una instalacion recien hecha funciona <strong>sin licencia</strong>, es decir, en modo Trial, y en ese</p><p>modo <strong>cada consulta esta limitada a 20 registros</strong>. No es un error ni un limite de la base</p><p>de datos: una lista que indica "20 de 20" sobre una tabla con miles de filas simplemente</p><p>esta funcionando sin licencia.</p><p>Como confirmarlo en un segundo:</p><p>Snippet 6:</p><p><code>licenseValid: false</code> confirma el modo Trial, y <code>licenseReason</code> dice por que</p><p>(<code>invalid_signature</code>, <code>license_expired</code>, <code>machine_fingerprint_not_authorized</code>, ...).</p><p>Como salir: se pega la licencia desde <strong>Administracion > Editor AppSettings</strong>, pestana Licensing,</p><p>y tiene efecto de inmediato: no hace falta reiniciar el backend. Los detalles, incluidos los</p><p>limites que el modo Trial impone mas alla del numero de registros, estan en la pagina</p><p><a href=\"licensing.md\">Licensing</a>.</p>",
|
|
21281
21339
|
"codeSamples": [
|
|
21282
21340
|
{
|
|
21283
21341
|
"id": "code_1",
|
|
@@ -21289,25 +21347,31 @@ const frameworkDocsContent = {
|
|
|
21289
21347
|
"id": "code_2",
|
|
21290
21348
|
"title": "Snippet 2",
|
|
21291
21349
|
"language": "text",
|
|
21292
|
-
"code": "Developer workspace ready: C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\
|
|
21350
|
+
"code": "Developer workspace ready: C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\n\n code \"C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\\WuicTest.code-workspace\"\n then F5 > 'Fullstack: WuicTest + Chrome' (backend http://localhost:5000, frontend http://localhost:4200)\n\nFirst start opens the first-run wizard: paste this connection string (Windows authentication)\n Data Source=localhost\\SQLEXPRESS;Integrated Security=SSPI;Initial Catalog=WuicData;Encrypt=False;TrustServerCertificate=True\nRename the project: .\\rename-project.ps1 -Name MyApp"
|
|
21293
21351
|
},
|
|
21294
21352
|
{
|
|
21295
21353
|
"id": "code_3",
|
|
21296
21354
|
"title": "Snippet 3",
|
|
21297
21355
|
"language": "powershell",
|
|
21298
|
-
"code": "# Primera vez: restore paquetes NuGet (pulls WuicCore + deps desde nuget.org, ~30 s)\
|
|
21356
|
+
"code": "# Primera vez: restore paquetes NuGet (pulls WuicCore + deps desde nuget.org, ~30 s)\ndotnet restore\n\n# Arranque dev con hot reload\n$env:ASPNETCORE_ENVIRONMENT = 'Development'\ndotnet watch run\n\n# O arranque one-shot (sin hot reload)\ndotnet run"
|
|
21299
21357
|
},
|
|
21300
21358
|
{
|
|
21301
21359
|
"id": "code_4",
|
|
21302
21360
|
"title": "Snippet 4",
|
|
21303
21361
|
"language": "powershell",
|
|
21304
|
-
"code": "cd wwwroot\
|
|
21362
|
+
"code": "cd wwwroot\n\n# Primera vez: restore dependencias npm (pulls wuic-framework-lib desde npm registry, ~2 min)\nnpm install\n\n# Arranque dev server\nnpm run serve:dev"
|
|
21305
21363
|
},
|
|
21306
21364
|
{
|
|
21307
21365
|
"id": "code_5",
|
|
21308
21366
|
"title": "Snippet 5",
|
|
21309
21367
|
"language": "html",
|
|
21310
|
-
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\
|
|
21368
|
+
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\n<wuic-data-repeater [hardcodedAction]=\"'list'\"></wuic-data-repeater>"
|
|
21369
|
+
},
|
|
21370
|
+
{
|
|
21371
|
+
"id": "code_6",
|
|
21372
|
+
"title": "Snippet 6",
|
|
21373
|
+
"language": "bash",
|
|
21374
|
+
"code": "curl -s http://localhost:5000/api/Meta/LicenseStatus"
|
|
21311
21375
|
}
|
|
21312
21376
|
]
|
|
21313
21377
|
}
|
|
@@ -21342,18 +21406,22 @@ const frameworkDocsContent = {
|
|
|
21342
21406
|
"toc": [
|
|
21343
21407
|
{
|
|
21344
21408
|
"id": "sec_1",
|
|
21345
|
-
"title": "
|
|
21409
|
+
"title": "Con un paquete tutorial no hay nada que scaffoldar"
|
|
21346
21410
|
},
|
|
21347
21411
|
{
|
|
21348
21412
|
"id": "sec_2",
|
|
21349
|
-
"title": "
|
|
21413
|
+
"title": "Cuándo usarlo"
|
|
21350
21414
|
},
|
|
21351
21415
|
{
|
|
21352
21416
|
"id": "sec_3",
|
|
21353
|
-
"title": "
|
|
21417
|
+
"title": "Comportamiento con firstRun=true"
|
|
21354
21418
|
},
|
|
21355
21419
|
{
|
|
21356
21420
|
"id": "sec_4",
|
|
21421
|
+
"title": "Operaciones típicas"
|
|
21422
|
+
},
|
|
21423
|
+
{
|
|
21424
|
+
"id": "sec_5",
|
|
21357
21425
|
"title": "Después del provisioning"
|
|
21358
21426
|
}
|
|
21359
21427
|
],
|
|
@@ -21361,7 +21429,7 @@ const frameworkDocsContent = {
|
|
|
21361
21429
|
{
|
|
21362
21430
|
"id": "overview",
|
|
21363
21431
|
"title": "Overview",
|
|
21364
|
-
"html": "<h1>Scaffolding inicial</h1><p>Esta página describe el bootstrap inicial cuando <code>AppSettings.firstRun = true</code>.</p><h2>Cuándo usarlo</h2><ul><li>Nueva instalación (DB metadata/datos aún no preparados).</li><li>Entorno local a realinear con la configuración inicial.</li><li>Primer arranque después del deploy donde se quiere forzar el procedimiento guiado de provisioning.</li></ul><h2>Comportamiento con firstRun=true</h2><ul><li>El endpoint <code>GET /api/Meta/FirstRunStatus</code> expone <code>firstRun: true</code>.</li><li>En el login aparece el flujo de primer arranque (por ejemplo, la acción <code>Aggiorna</code> en la pantalla).</li><li>El setup aplica las configuraciones base (conexiones, ajustes runtime, bootstrap metadata).</li></ul><h2>Operaciones típicas</h2><ul><li>Verifica que <code>AppSettings.firstRun</code> esté a <code>true</code> en <code>appsettings.{Environment}.json</code> del host que estás ejecutando.</li><li>Arranca la aplicación y completa el procedimiento de scaffolding inicial desde la UI.</li><li>Comprueba que las conexiones y los parámetros principales sean coherentes (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>Después del provisioning</h2><ul><li>El procedimiento de setup pone <code>firstRun</code> a <code>false</code> para evitar reejecuciones en cada arranque.</li><li>Realiza login estándar y valida el acceso a las routes principales.</li></ul>",
|
|
21432
|
+
"html": "<h1>Scaffolding inicial</h1><p>Esta página describe el bootstrap inicial cuando <code>AppSettings.firstRun = true</code>.</p><h2>Con un paquete tutorial no hay nada que scaffoldar</h2><p>El scaffolding del que habla esta página — leer las tablas de una base de datos y registrarlas</p><p>en <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> — afecta <strong>solo</strong> al modo "Base de datos</p><p>existente" del asistente de primer arranque: ahí es donde aparece la casilla *Generar</p><p>automáticamente los metadatos de las tablas de la base elegida*.</p><p>En los paquetes <strong>tutorial</strong> esa casilla no existe. La base de metadatos llega ya poblada</p><p>(rutas, columnas, menú, traducciones, cuadros de mando de ejemplo) y el asistente se limita a</p><p>restaurarla y a crear el usuario admin. Ver rutas ya listas justo después del primer arranque no</p><p>es, por tanto, resultado de un scaffolding: es el contenido del tutorial.</p><table><thead><tr><th>Modo del asistente</th><th>Qué pasa con los metadatos</th></tr></thead><tbody><tr><td>Tutorial WideWorldImporters</td><td>Metadatos ya construidos, restaurados desde el paquete. Ningún scaffolding.</td></tr><tr><td>Base existente, casilla apagada</td><td>Base de metadatos vacía: las rutas se registran a mano, o después desde la página Scaffolding.</td></tr><tr><td>Base existente, casilla encendida</td><td>Al final de la instalación cada tabla de la base elegida se registra como ruta.</td></tr></tbody></table><p>El resto de esta página se aplica a las dos últimas filas de esa tabla.</p><h2>Cuándo usarlo</h2><ul><li>Nueva instalación (DB metadata/datos aún no preparados).</li><li>Entorno local a realinear con la configuración inicial.</li><li>Primer arranque después del deploy donde se quiere forzar el procedimiento guiado de provisioning.</li></ul><h2>Comportamiento con firstRun=true</h2><ul><li>El endpoint <code>GET /api/Meta/FirstRunStatus</code> expone <code>firstRun: true</code>.</li><li>En el login aparece el flujo de primer arranque (por ejemplo, la acción <code>Aggiorna</code> en la pantalla).</li><li>El setup aplica las configuraciones base (conexiones, ajustes runtime, bootstrap metadata).</li></ul><h2>Operaciones típicas</h2><ul><li>Verifica que <code>AppSettings.firstRun</code> esté a <code>true</code> en <code>appsettings.{Environment}.json</code> del host que estás ejecutando.</li><li>Arranca la aplicación y completa el procedimiento de scaffolding inicial desde la UI.</li><li>Comprueba que las conexiones y los parámetros principales sean coherentes (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>Después del provisioning</h2><ul><li>El procedimiento de setup pone <code>firstRun</code> a <code>false</code> para evitar reejecuciones en cada arranque.</li><li>Realiza login estándar y valida el acceso a las routes principales.</li></ul>",
|
|
21365
21433
|
"codeSamples": []
|
|
21366
21434
|
}
|
|
21367
21435
|
],
|
|
@@ -21420,7 +21488,7 @@ const frameworkDocsContent = {
|
|
|
21420
21488
|
{
|
|
21421
21489
|
"id": "overview",
|
|
21422
21490
|
"title": "Overview",
|
|
21423
|
-
"html": "<h1>Licensing</h1><p>Esta página explica el licenciamiento desde el punto de vista del usuario final: qué se necesita, cómo obtener la licencia y cómo aplicarla.</p><h2>Cómo obtener una licencia</h2><p>Consulta los planes, las funcionalidades incluidas por nivel (Developer / Professional / Software House) y procede a la compra en el sitio público:</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">Precios y planes WUIC — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Contacto comercial</a> — no hace falta licencia para evaluar: sin licencia el framework funciona en modo Trial (20 registros por consulta)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">Página principal WUIC</a></li></ul><p>Tras la compra recibirás un correo con <code>license-payload</code> + <code>license-signature</code> para instalar como se describe en el "Procedimiento del usuario final" a continuación.</p><h2>Cómo funciona</h2><ul><li>La licencia es válida solo si:</li><li>firma correcta.</li><li><code>machineFingerprint</code> del servidor actual presente en la lista <code>machineFingerprints</code> del payload firmado.</li><li>Si la licencia no es válida, la lectura de datos (<code>getFlatRecordData</code>) se limita a un máximo de 20 registros. Además, el hook host <code>customizeSelect</code> se omite (no se invoca).</li></ul><h2>Dónde encontrar el machineFingerprint</h2><p>Endpoint backend:</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → campo <code>machineFingerprint</code> (siempre disponible, incluso sin licencia).</li><li>Durante el first-run también lo expone <code>GET /api/Meta/FirstRunStatus</code>.</li></ul><p>Nota: el archivo local <code>installation.id</code> ya no se usa para el licenciamiento.</p><h2>Procedimiento para el usuario final</h2><p>1. Recupera <code>machineFingerprint</code> desde tu host.</p><p>2. Envía el valor al proveedor/licenciante.</p><p>3. Recibe los valores de licencia:</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (si lo requiere tu instalación)</li></ul><p>4.
|
|
21491
|
+
"html": "<h1>Licensing</h1><p>Esta página explica el licenciamiento desde el punto de vista del usuario final: qué se necesita, cómo obtener la licencia y cómo aplicarla.</p><h2>Cómo obtener una licencia</h2><p>Consulta los planes, las funcionalidades incluidas por nivel (Developer / Professional / Software House) y procede a la compra en el sitio público:</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">Precios y planes WUIC — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Contacto comercial</a> — no hace falta licencia para evaluar: sin licencia el framework funciona en modo Trial (20 registros por consulta)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">Página principal WUIC</a></li></ul><p>Tras la compra recibirás un correo con <code>license-payload</code> + <code>license-signature</code> para instalar como se describe en el "Procedimiento del usuario final" a continuación.</p><h2>Cómo funciona</h2><ul><li>La licencia es válida solo si:</li><li>firma correcta.</li><li><code>machineFingerprint</code> del servidor actual presente en la lista <code>machineFingerprints</code> del payload firmado.</li><li>Si la licencia no es válida, la lectura de datos (<code>getFlatRecordData</code>) se limita a un máximo de 20 registros. Además, el hook host <code>customizeSelect</code> se omite (no se invoca).</li></ul><h2>Dónde encontrar el machineFingerprint</h2><p>Endpoint backend:</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → campo <code>machineFingerprint</code> (siempre disponible, incluso sin licencia).</li><li>Durante el first-run también lo expone <code>GET /api/Meta/FirstRunStatus</code>.</li></ul><p>Nota: el archivo local <code>installation.id</code> ya no se usa para el licenciamiento.</p><h2>Procedimiento para el usuario final</h2><p>1. Recupera <code>machineFingerprint</code> desde tu host.</p><p>2. Envía el valor al proveedor/licenciante.</p><p>3. Recibe los valores de licencia:</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (si lo requiere tu instalación)</li></ul><p>4. Pega los valores desde la interfaz: <strong>Administracion > Editor AppSettings</strong>, sección</p><p> <strong>License</strong> (campos <code>License email</code>, <code>License payload</code>, <code>License signature</code>,</p><p> <code>Public key (PEM)</code>), y guarda. También se pueden escribir a mano en la sección</p><p> <code>AppSettings</code> del archivo <code>appsettings.{Environment}.json</code> del host en ejecución.</p><p>5. Verifica el estado de la licencia:</p><ul><li>desde la API: <code>GET /api/Meta/LicenseStatus</code>, esperado <code>licenseValid = true</code>;</li><li>o desde la propia página, que vuelve a leer la licencia justo después de guardar.</li></ul><p><strong>No hace falta reiniciar el backend si pasas por el editor.</strong> Al guardar <code>license-payload</code> /</p><p><code>license-signature</code> desde el Editor AppSettings el backend recarga por su cuenta el servicio de</p><p>validación, y la licencia vale desde la siguiente petición. El reinicio solo se necesita en el</p><p>otro caso, cuando los valores se escriben a mano en el archivo: ese se lee al arrancar.</p><h2>Licencia multi-máquina</h2><p>Una única licencia puede autorizar múltiples máquinas incluyendo varios valores en <code>machineFingerprints</code>.</p><h2>Solución rápida de problemas</h2><ul><li><code>licenseReason = invalid_signature</code>:</li><li>payload/firma no coherentes entre sí o public key diferente.</li><li><code>licenseReason = machine_fingerprint_not_authorized</code>:</li><li>el fingerprint de la máquina actual no está presente en la licencia recibida.</li><li><code>licenseReason = machine_fingerprint_missing</code>:</li><li>el runtime no puede calcular el fingerprint local.</li><li><code>licenseReason = license_expired</code>:</li><li>la licencia ha expirado, solicita la renovación.</li></ul>",
|
|
21424
21492
|
"codeSamples": []
|
|
21425
21493
|
}
|
|
21426
21494
|
],
|
|
@@ -22095,42 +22163,46 @@ const frameworkDocsContent = {
|
|
|
22095
22163
|
},
|
|
22096
22164
|
{
|
|
22097
22165
|
"id": "sec_2",
|
|
22098
|
-
"title": "
|
|
22166
|
+
"title": "Qué muestra la toolbar por defecto"
|
|
22099
22167
|
},
|
|
22100
22168
|
{
|
|
22101
22169
|
"id": "sec_3",
|
|
22102
|
-
"title": "
|
|
22170
|
+
"title": "Screenshot de referencia (manual de usuario)"
|
|
22103
22171
|
},
|
|
22104
22172
|
{
|
|
22105
22173
|
"id": "sec_4",
|
|
22106
|
-
"title": "
|
|
22174
|
+
"title": "Metadatos de inline editing"
|
|
22107
22175
|
},
|
|
22108
22176
|
{
|
|
22109
22177
|
"id": "sec_5",
|
|
22110
|
-
"title": "
|
|
22178
|
+
"title": "Toolbar export/import"
|
|
22111
22179
|
},
|
|
22112
22180
|
{
|
|
22113
22181
|
"id": "sec_6",
|
|
22114
|
-
"title": "
|
|
22182
|
+
"title": "Config metadata"
|
|
22115
22183
|
},
|
|
22116
22184
|
{
|
|
22117
22185
|
"id": "sec_7",
|
|
22118
|
-
"title": "md_props_bag:
|
|
22186
|
+
"title": "md_props_bag: toolbar"
|
|
22119
22187
|
},
|
|
22120
22188
|
{
|
|
22121
22189
|
"id": "sec_8",
|
|
22122
|
-
"title": "
|
|
22190
|
+
"title": "md_props_bag: archetypes.list"
|
|
22123
22191
|
},
|
|
22124
22192
|
{
|
|
22125
22193
|
"id": "sec_9",
|
|
22126
|
-
"title": "
|
|
22194
|
+
"title": "Paging: md_pagesize y md_page_size_choice"
|
|
22127
22195
|
},
|
|
22128
22196
|
{
|
|
22129
22197
|
"id": "sec_10",
|
|
22130
|
-
"title": "
|
|
22198
|
+
"title": "Forzado de virtualización en page size alto"
|
|
22131
22199
|
},
|
|
22132
22200
|
{
|
|
22133
22201
|
"id": "sec_11",
|
|
22202
|
+
"title": "Eventos y subscriptions (host)"
|
|
22203
|
+
},
|
|
22204
|
+
{
|
|
22205
|
+
"id": "sec_12",
|
|
22134
22206
|
"title": "`rowCustomSelect` — firma real (gotcha)"
|
|
22135
22207
|
}
|
|
22136
22208
|
],
|
|
@@ -22138,7 +22210,7 @@ const frameworkDocsContent = {
|
|
|
22138
22210
|
{
|
|
22139
22211
|
"id": "overview",
|
|
22140
22212
|
"title": "Overview",
|
|
22141
|
-
"html": "<h1>List Grid</h1><p>Componente principal para listas tabulares con filtros, sorting, paging server-side y acciones de fila.</p><h2>Casos de uso</h2><ul><li>CRUD tabulares enterprise.</li><li>Informes operativos con filtros multi-columna.</li><li>Datasets muy grandes con <code>cursorMode</code>.</li></ul><h2>Screenshot de referencia (manual de usuario)</h2><ul><li><code>manual__grid__01.png</code>: modalidad <code>inline cell edit</code> en list-grid.</li><li><code>manual__grid__02.png</code>: modalidad <code>inline edit</code> (row-level) en list-grid.</li></ul><h2>Metadatos de inline editing</h2><p>Configuración en el <code>md_props_bag</code> de la tabla metadata:</p><ul><li><code>md_inline_edit</code></li></ul><p> - habilita el editing inline de la fila en list-grid (celdas editables en contexto de fila, sin apertura de popup).</p><p> - útil cuando se quiere mantener la UX de tabla con edición rápida por registro.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - habilita el editing inline "celda por celda" (foco en la celda individual).</p><p> - nota: en configuraciones legacy puede aparecer como <code>md_inline_cell_editing</code>; el comportamiento runtime es el mismo.</p><p> - <strong>promoción runtime</strong>: cuando <code>md_inline_cell_edit</code> es <code>true</code>, el componente fuerza</p><p> en runtime también <code>md_inline_edit = true</code> independientemente del valor en DB.</p><p> Ambas UX necesitan la action column visible, por lo que son mutuamente</p><p> no-exclusivas a nivel de renderizado.</p><ul><li><code>md_batch_save</code></li></ul><p> - habilita el guardado batch de los cambios pendientes (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - si se usa junto con inline-cell, los cambios quedan pending hasta el guardado explícito.</p><p> - <strong>prerequisito</strong>: <code>md_batch_save</code> tiene efecto <strong>solo</strong> si <code>md_inline_cell_edit</code> es <code>true</code>.</p><p> Con <code>md_inline_cell_edit:false</code> el flag se ignora en runtime y los botones</p><p> "Guardar cambios / Cancelar cambios" no se renderizan.</p><h3>Combinaciones válidas</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Resultado runtime</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>cualquiera</td><td>Inline edit a nivel de fila con pencil. <code>md_batch_save</code> ignorado.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Cell-by-cell autosave on blur. <code>md_inline_edit</code> forzado a <code>true</code> en runtime.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Cell-by-cell con buffer pending + toolbar <code>Guardar / Cancelar cambios</code>.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>cualquiera</td><td>Sin inline editing. <code>md_batch_save</code> ignorado.</td></tr></tbody></table><p>Ejemplo row-level inline edit:</p><p>Snippet 1:</p><p>Ejemplo cell-by-cell con batch save:</p><p>Snippet 2:</p><h2>Toolbar export/import</h2><ul><li>Export XLS:</li></ul><p> - muestra diálogo de progreso con porcentaje en tiempo real;</p><p> - acciones: <code>Continuar en background</code>, <code>Cancelar tarea</code>, <code>Interrumpir y descargar parcial</code>;</p><p> - en background crea una notificación con progreso; el clic reabre el diálogo.</p><ul><li>Import XLS/XLSX (si <code>md_importable = true</code>):</li></ul><p> - diálogo de progreso tras la confirmación;</p><p> - acciones: <code>Continuar en background</code>, <code>Cancelar import (rollback)</code>, <code>Detener y commit parcial</code>;</p><p> - al finalizar el import crea una notificación de resumen que lleva a la route.</p><h2>Config metadata</h2><p>Ajustes clave en <code>md_props_bag</code> y metadatos de columna.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Flags opt-in que ocultan bloques de la toolbar de la list-grid (<code>caption-bar</code>). Todos bajo <code>md_props_bag.toolbar.*</code> (parseado en runtime como <code>tableMetadata.extraProps.toolbar</code>).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, default <code>false</code>): oculta en la <strong>caption-right</strong> el botón "Gestionar estado" (icono bookmark) + el <code><select></code> de estados guardados. Útil para rutas hardcoded / demo donde el feature saved-state (persistencia por <code>user_id</code> + ruta vía <code>MetaService</code>) no tiene sentido — p. ej. Pattern 3 puro OData sin route metadata registrada.</li><li><code>hideBatchActions</code> (boolean, default <code>false</code>): oculta en la <strong>caption-left</strong> los botones "Guardar cambios" (<code>pi-save</code>) + "Descartar cambios" (<code>pi-times</code>) + el indicador de conteo de changes (<code>grid-changes-indicator</code>, badge pencil + count). Generados por el framework cuando <code>md_inline_cell_editing</code> + <code>md_batch_save</code> están activos. Diseñado para <strong>nested grids dentro de un parametric-dialog</strong>: el save/cancel del padre persiste master + filas en un golpe vía batch save framework, y los botones duplicados en la nested grid confunden la UX.</li></ul><p>Ejemplo nested rows en custom edit-form (runtime patch):</p><p>Snippet 5:</p><p>Tipo TS en <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (propiedad <code>extraProps.toolbar</code>). Los flags NO deshabilitan la lógica <code>md_batch_save</code> subyacente (los changes siguen siendo trackeados); solo eliminan la UI de la toolbar — el save efectivo pasa por el flujo del padre.</p><h2>md_props_bag: archetypes.list</h2><p>El componente lee <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code>:</li><li>tipo: boolean (con parser tolerante)</li><li>valores aceptados: <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>default runtime: <code>true</code> cuando ausente o vacío</li><li>efecto: distribuye los anchos de columna en porcentaje (en lugar de px) cuando no hay anchos de usuario persistidos.</li></ul><ul><li><code>virtualize</code>:</li><li>tipo: <code>boolean</code> o <code>object</code></li><li>valores aceptados:</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>object con <code>enabled</code> (opcional) y <code>itemSize</code> (opcional)</li><li>default runtime: deshabilitado (<code>false</code>) cuando ausente</li><li><code>enabled</code>:</li><li>default: <code>true</code> si el nodo <code>virtualize</code> es un object sin <code>enabled</code>, de lo contrario parser tolerante</li><li>efecto: habilita <code>virtualScroll</code> en <code>p-table</code></li><li><code>itemSize</code>:</li><li>default: <code>44</code></li><li>efecto: establece <code>virtualScrollItemSize</code> (altura de fila virtual en px)</li></ul><ul><li><code>advancedFilter</code>:</li><li>tipo: boolean (con parser tolerante)</li><li>default runtime: <code>false</code></li><li>efecto:</li><li>cuando <code>true</code>, la grilla oculta los iconos de filtro de columna (<code>p-columnFilter</code>) y usa la <code>wuic-filter-bar</code> sobre la tabla (a nivel <code>data-repeater</code>/<code>bounded-repeater</code>) para aplicar los filtros.</li></ul><p>Nota operativa:</p><ul><li>el suggest <code>md_props_bag</code> en el metadata editor expone también el nodo checkeable <code>archetypes.list.advancedFilter</code>.</li></ul><h2>Paging: md_pagesize y md_page_size_choice</h2><p>La grilla usa <code>md_pagesize</code> como tamaño de página por defecto y <code>md_page_size_choice</code> como lista de valores seleccionables en el paginador.</p><p>Reglas runtime:</p><ul><li>si <code>md_pagesize</code> es mayor que el valor máximo presente en <code>md_page_size_choice</code>, el framework agrega automáticamente <code>md_pagesize</code> a la lista de opciones;</li><li>la lista se normaliza (números válidos, deduplicación, orden ascendente).</li></ul><p>Ejemplo:</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>resultado runtime: <code>10,25,50,100,200</code></li></ul><h2>Forzado de virtualización en page size alto</h2><p>Cuando el usuario selecciona en el paginador un valor <code>pageSize >= 1000</code>:</p><ul><li>la virtualización se fuerza automáticamente aunque <code>md_props_bag.archetypes.list.virtualize</code> esté ausente o deshabilitado;</li><li><code>virtualScrollItemSize</code> se fuerza al valor predeterminado <code>44</code>.</li></ul><p>Este comportamiento protege el rendimiento de la tabla en páginas muy grandes.</p><h2>Eventos y subscriptions (host)</h2><p><code>wuic-list-grid</code> expone eventos runtime útiles para interceptar el ciclo de render y callbacks de p-table en el proyecto host.</p><p>Eventos disponibles:</p><ul><li><code>onAfterRender</code>: emitido al finalizar el binding de datos de la grilla (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code>: emitido antes del renderizado lógico de la fila individual; soporta cancelación mediante <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code>: emitido después del renderizado lógico de la fila individual.</li><li><code>onPaging</code>: emitido en los eventos de paging (<code>p-table onPage</code>).</li><li><code>onSorting</code>: emitido en los eventos de sorting (<code>p-table onSort</code>).</li><li><code>onFiltering</code>: emitido en los eventos de filtering (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code>: emitido al cambiar la selección de filas.</li><li><code>onPTableRowExpand</code>: emitido al expandir una fila.</li><li><code>onPTableRowCollapse</code>: emitido al colapsar una fila.</li><li><code>onPTableColumnResize</code>: emitido al redimensionar una columna.</li><li><code>onPTableColumnReorder</code>: emitido al reordenar columnas.</li></ul><h3>Ejemplo 1: binding directo en el template</h3><p>Snippet 7:</p><h3>Ejemplo 2: subscribe vía ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — firma real (gotcha)</h2><p><code><wuic-list-grid></code> acepta una entrada <code>[rowCustomSelect]</code> para interceptar la seleccion de una fila (apertura de un dialog "elige un documento", flujo master-detail, etc.). La firma TypeScript declarada en <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> es:</p><p>Snippet 9:</p><p><strong>Pero en runtime la callback se invoca con argumentos invertidos</strong> — el framework llama <code>rowCustomSelect($event, rowData, dt)</code> (ver <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> y <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Sintoma cuando el orden es erroneo: <code>rowData?.id</code> es undefined → guard temprano en tu handler → la callback retorna silenciosamente y tu dialog/accion no arranca. Ningun error en consola.</p><p>Forma correcta (alineada con la invocacion runtime):</p><p>Snippet 10:</p><p>Uso en el template:</p><p>Snippet 11:</p><p>> Nota: los tests en <code>designer.component.spec.ts</code> (p. ej. linea 512) invocan la callback con <code>({currentTarget: rowCell}, {id: 42}, null)</code>, confirmando el orden <code>($event, rowData, dt)</code>. Si en el futuro el framework alinea la firma declarada, esta pagina se actualizara.</p>",
|
|
22213
|
+
"html": "<h1>List Grid</h1><p>Componente principal para listas tabulares con filtros, sorting, paging server-side y acciones de fila.</p><h2>Casos de uso</h2><ul><li>CRUD tabulares enterprise.</li><li>Informes operativos con filtros multi-columna.</li><li>Datasets muy grandes con <code>cursorMode</code>.</li></ul><h2>Qué muestra la toolbar por defecto</h2><p>Al abrir una ruta recién scaffoldada, la caption-bar está encima de la rejilla. A la izquierda:</p><table><thead><tr><th>Botón</th><th>Cuándo aparece</th></tr></thead><tbody><tr><td><strong>Actualizar</strong></td><td>siempre, salvo <code>md_hide_refresh</code></td></tr><tr><td><strong>Agregar</strong></td><td>con <code>md_insertable</code></td></tr><tr><td><strong>Comportamiento</strong></td><td>si la tabla tiene acciones personalizadas</td></tr><tr><td>Import / Export</td><td>siempre; la rama de import solo con <code>md_importable</code></td></tr><tr><td><strong>Informes</strong></td><td>si hay al menos un informe asociado a la ruta</td></tr><tr><td><strong>Guardar cambios</strong> / <strong>Descartar cambios</strong></td><td>solo con <code>md_inline_cell_edit</code> <strong>y</strong> <code>md_batch_save</code></td></tr></tbody></table><p>A la derecha: <strong>Gestionar estado</strong> (precedido por el desplegable de estados guardados, si los</p><p>hay), <strong>Limpiar filtros</strong> cuando los filtros están en las columnas, y <strong>Rendimiento</strong> si el</p><p>inspector está habilitado en la ruta.</p><p>> Las etiquetas citadas más abajo en esta página <strong>no están en esa pantalla</strong>, y no es un</p><p>> defecto: las de export/import (<em>Continuar en segundo plano</em>, <em>Cancelar tarea</em>, *Detener y</p><p>> descargar parcial<em>, </em>Cancelar import (rollback)<em>, </em>Detener y confirmar parcial*) viven en el</p><p>> diálogo de progreso, que solo existe mientras un export o un import está en curso; *Guardar</p><p>> cambios<em> y </em>Descartar cambios* solo aparecen con los dos flags de arriba. Pertenecen a</p><p>> momentos distintos de la primera apertura de la lista.</p><h2>Screenshot de referencia (manual de usuario)</h2><ul><li><code>manual__grid__01.png</code>: modalidad <code>inline cell edit</code> en list-grid.</li><li><code>manual__grid__02.png</code>: modalidad <code>inline edit</code> (row-level) en list-grid.</li></ul><h2>Metadatos de inline editing</h2><p>Configuración en el <code>md_props_bag</code> de la tabla metadata:</p><ul><li><code>md_inline_edit</code></li></ul><p> - habilita el editing inline de la fila en list-grid (celdas editables en contexto de fila, sin apertura de popup).</p><p> - útil cuando se quiere mantener la UX de tabla con edición rápida por registro.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - habilita el editing inline "celda por celda" (foco en la celda individual).</p><p> - nota: en configuraciones legacy puede aparecer como <code>md_inline_cell_editing</code>; el comportamiento runtime es el mismo.</p><p> - <strong>promoción runtime</strong>: cuando <code>md_inline_cell_edit</code> es <code>true</code>, el componente fuerza</p><p> en runtime también <code>md_inline_edit = true</code> independientemente del valor en DB.</p><p> Ambas UX necesitan la action column visible, por lo que son mutuamente</p><p> no-exclusivas a nivel de renderizado.</p><ul><li><code>md_batch_save</code></li></ul><p> - habilita el guardado batch de los cambios pendientes (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - si se usa junto con inline-cell, los cambios quedan pending hasta el guardado explícito.</p><p> - <strong>prerequisito</strong>: <code>md_batch_save</code> tiene efecto <strong>solo</strong> si <code>md_inline_cell_edit</code> es <code>true</code>.</p><p> Con <code>md_inline_cell_edit:false</code> el flag se ignora en runtime y los botones</p><p> "Guardar cambios / Cancelar cambios" no se renderizan.</p><h3>Combinaciones válidas</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Resultado runtime</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>cualquiera</td><td>Inline edit a nivel de fila con pencil. <code>md_batch_save</code> ignorado.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Cell-by-cell autosave on blur. <code>md_inline_edit</code> forzado a <code>true</code> en runtime.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Cell-by-cell con buffer pending + toolbar <code>Guardar / Cancelar cambios</code>.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>cualquiera</td><td>Sin inline editing. <code>md_batch_save</code> ignorado.</td></tr></tbody></table><p>Ejemplo row-level inline edit:</p><p>Snippet 1:</p><p>Ejemplo cell-by-cell con batch save:</p><p>Snippet 2:</p><h2>Toolbar export/import</h2><ul><li>Export XLS:</li></ul><p> - muestra diálogo de progreso con porcentaje en tiempo real;</p><p> - acciones: <code>Continuar en background</code>, <code>Cancelar tarea</code>, <code>Interrumpir y descargar parcial</code>;</p><p> - en background crea una notificación con progreso; el clic reabre el diálogo.</p><ul><li>Import XLS/XLSX (si <code>md_importable = true</code>):</li></ul><p> - diálogo de progreso tras la confirmación;</p><p> - acciones: <code>Continuar en background</code>, <code>Cancelar import (rollback)</code>, <code>Detener y commit parcial</code>;</p><p> - al finalizar el import crea una notificación de resumen que lleva a la route.</p><h2>Config metadata</h2><p>Ajustes clave en <code>md_props_bag</code> y metadatos de columna.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Flags opt-in que ocultan bloques de la toolbar de la list-grid (<code>caption-bar</code>). Todos bajo <code>md_props_bag.toolbar.*</code> (parseado en runtime como <code>tableMetadata.extraProps.toolbar</code>).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, default <code>false</code>): oculta en la <strong>caption-right</strong> el botón "Gestionar estado" (icono bookmark) + el <code><select></code> de estados guardados. Útil para rutas hardcoded / demo donde el feature saved-state (persistencia por <code>user_id</code> + ruta vía <code>MetaService</code>) no tiene sentido — p. ej. Pattern 3 puro OData sin route metadata registrada.</li><li><code>hideBatchActions</code> (boolean, default <code>false</code>): oculta en la <strong>caption-left</strong> los botones "Guardar cambios" (<code>pi-save</code>) + "Descartar cambios" (<code>pi-times</code>) + el indicador de conteo de changes (<code>grid-changes-indicator</code>, badge pencil + count). Generados por el framework cuando <code>md_inline_cell_editing</code> + <code>md_batch_save</code> están activos. Diseñado para <strong>nested grids dentro de un parametric-dialog</strong>: el save/cancel del padre persiste master + filas en un golpe vía batch save framework, y los botones duplicados en la nested grid confunden la UX.</li></ul><p>Ejemplo nested rows en custom edit-form (runtime patch):</p><p>Snippet 5:</p><p>Tipo TS en <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (propiedad <code>extraProps.toolbar</code>). Los flags NO deshabilitan la lógica <code>md_batch_save</code> subyacente (los changes siguen siendo trackeados); solo eliminan la UI de la toolbar — el save efectivo pasa por el flujo del padre.</p><h2>md_props_bag: archetypes.list</h2><p>El componente lee <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code>:</li><li>tipo: boolean (con parser tolerante)</li><li>valores aceptados: <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>default runtime: <code>true</code> cuando ausente o vacío</li><li>efecto: distribuye los anchos de columna en porcentaje (en lugar de px) cuando no hay anchos de usuario persistidos.</li></ul><ul><li><code>virtualize</code>:</li><li>tipo: <code>boolean</code> o <code>object</code></li><li>valores aceptados:</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>object con <code>enabled</code> (opcional) y <code>itemSize</code> (opcional)</li><li>default runtime: deshabilitado (<code>false</code>) cuando ausente</li><li><code>enabled</code>:</li><li>default: <code>true</code> si el nodo <code>virtualize</code> es un object sin <code>enabled</code>, de lo contrario parser tolerante</li><li>efecto: habilita <code>virtualScroll</code> en <code>p-table</code></li><li><code>itemSize</code>:</li><li>default: <code>44</code></li><li>efecto: establece <code>virtualScrollItemSize</code> (altura de fila virtual en px)</li></ul><ul><li><code>advancedFilter</code>:</li><li>tipo: boolean (con parser tolerante)</li><li>default runtime: <code>false</code></li><li>efecto:</li><li>cuando <code>true</code>, la grilla oculta los iconos de filtro de columna (<code>p-columnFilter</code>) y usa la <code>wuic-filter-bar</code> sobre la tabla (a nivel <code>data-repeater</code>/<code>bounded-repeater</code>) para aplicar los filtros.</li></ul><p>Nota operativa:</p><ul><li>el suggest <code>md_props_bag</code> en el metadata editor expone también el nodo checkeable <code>archetypes.list.advancedFilter</code>.</li></ul><h2>Paging: md_pagesize y md_page_size_choice</h2><p>La grilla usa <code>md_pagesize</code> como tamaño de página por defecto y <code>md_page_size_choice</code> como lista de valores seleccionables en el paginador.</p><p>Reglas runtime:</p><ul><li>si <code>md_pagesize</code> es mayor que el valor máximo presente en <code>md_page_size_choice</code>, el framework agrega automáticamente <code>md_pagesize</code> a la lista de opciones;</li><li>la lista se normaliza (números válidos, deduplicación, orden ascendente).</li></ul><p>Ejemplo:</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>resultado runtime: <code>10,25,50,100,200</code></li></ul><h2>Forzado de virtualización en page size alto</h2><p>Cuando el usuario selecciona en el paginador un valor <code>pageSize >= 1000</code>:</p><ul><li>la virtualización se fuerza automáticamente aunque <code>md_props_bag.archetypes.list.virtualize</code> esté ausente o deshabilitado;</li><li><code>virtualScrollItemSize</code> se fuerza al valor predeterminado <code>44</code>.</li></ul><p>Este comportamiento protege el rendimiento de la tabla en páginas muy grandes.</p><h2>Eventos y subscriptions (host)</h2><p><code>wuic-list-grid</code> expone eventos runtime útiles para interceptar el ciclo de render y callbacks de p-table en el proyecto host.</p><p>Eventos disponibles:</p><ul><li><code>onAfterRender</code>: emitido al finalizar el binding de datos de la grilla (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code>: emitido antes del renderizado lógico de la fila individual; soporta cancelación mediante <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code>: emitido después del renderizado lógico de la fila individual.</li><li><code>onPaging</code>: emitido en los eventos de paging (<code>p-table onPage</code>).</li><li><code>onSorting</code>: emitido en los eventos de sorting (<code>p-table onSort</code>).</li><li><code>onFiltering</code>: emitido en los eventos de filtering (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code>: emitido al cambiar la selección de filas.</li><li><code>onPTableRowExpand</code>: emitido al expandir una fila.</li><li><code>onPTableRowCollapse</code>: emitido al colapsar una fila.</li><li><code>onPTableColumnResize</code>: emitido al redimensionar una columna.</li><li><code>onPTableColumnReorder</code>: emitido al reordenar columnas.</li></ul><h3>Ejemplo 1: binding directo en el template</h3><p>Snippet 7:</p><h3>Ejemplo 2: subscribe vía ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — firma real (gotcha)</h2><p><code><wuic-list-grid></code> acepta una entrada <code>[rowCustomSelect]</code> para interceptar la seleccion de una fila (apertura de un dialog "elige un documento", flujo master-detail, etc.). La firma TypeScript declarada en <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> es:</p><p>Snippet 9:</p><p><strong>Pero en runtime la callback se invoca con argumentos invertidos</strong> — el framework llama <code>rowCustomSelect($event, rowData, dt)</code> (ver <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> y <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Sintoma cuando el orden es erroneo: <code>rowData?.id</code> es undefined → guard temprano en tu handler → la callback retorna silenciosamente y tu dialog/accion no arranca. Ningun error en consola.</p><p>Forma correcta (alineada con la invocacion runtime):</p><p>Snippet 10:</p><p>Uso en el template:</p><p>Snippet 11:</p><p>> Nota: los tests en <code>designer.component.spec.ts</code> (p. ej. linea 512) invocan la callback con <code>({currentTarget: rowCell}, {id: 42}, null)</code>, confirmando el orden <code>($event, rowData, dt)</code>. Si en el futuro el framework alinea la firma declarada, esta pagina se actualizara.</p>",
|
|
22142
22214
|
"codeSamples": [
|
|
22143
22215
|
{
|
|
22144
22216
|
"id": "code_1",
|
|
@@ -23864,7 +23936,7 @@ const frameworkDocsContent = {
|
|
|
23864
23936
|
{
|
|
23865
23937
|
"id": "overview",
|
|
23866
23938
|
"title": "Overview",
|
|
23867
|
-
"html": "<h1>Designer</h1><p>Editor visual para dashboards metadata-driven en la route <code>#/cities/dashboard</code>.</p><h2>Scope</h2><ul><li>Composición de boards mediante drag-and-drop de nodos y bloques UI.</li><li>Layout y estilos controlados por <code>boardcontent</code> y metadata de tabla/columna.</li><li>Edición en el panel de propiedades sin hardcode en los componentes runtime.</li></ul><h2>Palette Designer</h2><
|
|
23939
|
+
"html": "<h1>Designer</h1><p>Editor visual para dashboards metadata-driven en la route <code>#/cities/dashboard</code>.</p><h2>Scope</h2><ul><li>Composición de boards mediante drag-and-drop de nodos y bloques UI.</li><li>Layout y estilos controlados por <code>boardcontent</code> y metadata de tabla/columna.</li><li>Edición en el panel de propiedades sin hardcode en los componentes runtime.</li></ul><h2>Palette Designer</h2><p>La paleta está dividida en tres grupos. Los nombres de abajo son los que se leen en la paleta,</p><p>en mayúsculas tal como los escribe el designer.</p><p><strong>HTML</strong> — los ladrillos de marcado:</p><table><thead><tr><th>Tool</th><th>Para qué sirve</th></tr></thead><tbody><tr><td><code>TABLE</code></td><td>rejilla de celdas. <code>TR</code> y <code>TD</code> existen como tools pero no se arrastran: los crea la tabla</td></tr><tr><td><code>DIV</code></td><td>contenedor libre, el bloque estructural más usado</td></tr><tr><td><code>SPAN</code>, <code>LABEL</code>, <code>Hx</code></td><td>texto databound; <code>Hx</code> elige el nivel de h1 a h6</td></tr><tr><td><code>ANCHOR</code>, <code>IMG</code>, <code>IMAGE</code>, <code>IFRAME</code></td><td>enlaces, imágenes, contenido externo</td></tr><tr><td><code>UL</code></td><td>lista</td></tr><tr><td><code>BUTTON</code></td><td>botón con callback</td></tr><tr><td><code>INPUT</code>, <code>TEXTAREA</code>, <code>CHECKBOX</code>, <code>SELECT</code>, <code>MULTISELECT</code>, <code>DATE</code></td><td>campos de entrada</td></tr><tr><td><code>KPI</code></td><td>un único valor destacado</td></tr><tr><td><code>SEPARATOR</code>, <code>HR</code></td><td>separadores</td></tr></tbody></table><p><strong>DATA</strong> — los nodos conectados al backend:</p><table><thead><tr><th>Tool</th><th>Para qué sirve</th></tr></thead><tbody><tr><td><code>DATASOURCE</code></td><td>fuente de datos metadata (<code>route</code>, filtros, orden, paginación)</td></tr><tr><td><code>DATAREPEATER</code></td><td>visualización de lista/tarjeta vinculada a un datasource</td></tr><tr><td><code>FILTERBAR</code></td><td>barra de filtros sobre el repeater</td></tr><tr><td><code>PAGER</code></td><td>paginador</td></tr></tbody></table><p><strong>CONTAINER</strong> — los layouts:</p><table><thead><tr><th>Tool</th><th>Para qué sirve</th></tr></thead><tbody><tr><td><code>TABVIEW</code> + <code>TABPANEL</code></td><td>pestañas</td></tr><tr><td><code>SPLITTER</code> + <code>SPLITTER-AREA</code></td><td>paneles redimensionables</td></tr><tr><td><code>ACCORDION</code> + <code>ACCORDION-AREA</code></td><td>secciones en acordeón</td></tr></tbody></table><p>Dos nombres que se buscan en vano: <strong>no existe ningún tool "Dynamic Template"</strong> — la plantilla</p><p>dinámica es lo que renderiza el <code>DATAREPEATER</code>, se configura desde sus propiedades y no se</p><p>arrastra; y <strong>"Container" / "Layout" son el nombre del grupo</strong>, no entradas seleccionables.</p><p>A estos se suman los tools personalizados registrados por el proyecto anfitrión</p><p>(<code>MetadataProviderService.customDesignerTools</code>), que aparecen al final bajo el grupo que</p><p>declaran.</p><h2>Funcionalidades principales</h2><ul><li>Drag-and-drop de nodos sobre el canvas con persistencia en el <code>boardcontent</code>.</li><li>Panel de propiedades contextual con inputs coherentes con los componentes seleccionados.</li><li>Binding entre nodos (<code>datasource -> repeater/template</code>) con validación mínima.</li><li>Preview runtime integrada y realineamiento de layout.</li><li>Gestión de cambios pendientes con guard antes de salir.</li></ul><h2>Menú contextual de los elementos</h2><p>Clic derecho sobre un elemento del canvas, sobre un elemento del breadcrumb inferior o sobre un nodo del árbol de jerarquía muestra un menú contextual con tres opciones:</p><ul><li><strong>Editar propiedades</strong> (pi-cog) — selecciona el elemento como "current tool" y muestra su panel de propiedades a la derecha; equivalente al clic en el árbol. Útil para editar propiedades de elementos anidados sin tener que buscarlos en la jerarquía.</li><li><strong>Renombrar</strong> (solo breadcrumb) — abre un diálogo para renombrar el <code>displayName</code>.</li><li><strong>Eliminar</strong> — borra el elemento del board.</li></ul><h2>Flujo operativo recomendado</h2><ul><li>Abrir la route del dashboard objetivo.</li><li>Insertar/vincular nodos desde la palette.</li><li>Configurar los <code>inputs</code> esenciales (ej. <code>route</code>, <code>action</code>, <code>datasource</code>).</li><li>Guardar y validar el resultado en runtime.</li></ul><h2>Notas operativas</h2><ul><li>Para correcciones específicas del dashboard, privilegiar patches del <code>boardcontent</code> en lugar de modificaciones globales.</li><li>Evitar propiedades duplicadas entre <code>inputs</code> y estilos inline no coherentes.</li><li>Verificar siempre que los datasources tengan <code>inputs.route</code> valorizada.</li></ul>",
|
|
23868
23940
|
"codeSamples": []
|
|
23869
23941
|
}
|
|
23870
23942
|
],
|
|
@@ -27979,13 +28051,17 @@ const frameworkDocsContent = {
|
|
|
27979
28051
|
{
|
|
27980
28052
|
"id": "sec_4",
|
|
27981
28053
|
"title": "Quick Start — erste Komponente"
|
|
28054
|
+
},
|
|
28055
|
+
{
|
|
28056
|
+
"id": "sec_5",
|
|
28057
|
+
"title": "Die ersten Listen zeigen 20 Datensaetze: das ist der Trial-Modus"
|
|
27982
28058
|
}
|
|
27983
28059
|
],
|
|
27984
28060
|
"sections": [
|
|
27985
28061
|
{
|
|
27986
28062
|
"id": "overview",
|
|
27987
28063
|
"title": "Overview",
|
|
27988
|
-
"html": "<h1>Framework-Uebersicht</h1><p>WUIC Framework ist eine metadata-gesteuerte Plattform zum schnellen und konsistenten Erstellen von Business-Oberflaechen.</p><h2>Was ist enthalten</h2><ul><li>DataSource und DataRepeater zur Orchestrierung von Daten und Rendering.</li><li>Visuelle Archetypes (list, map, scheduler, chart, carousel).</li><li>Runtime-Designer fuer Dashboards und dynamische Templates.</li><li>Workflow-Designer/Runner fuer operative Prozesse.</li><li>RAG Chatbot zum Abfragen der Codebasis in natuerlicher Sprache.</li><li>Multi-DBMS: SQL Server, MySQL, PostgreSQL und Oracle ueber Drop-in-Provider (<code>dbms</code>: <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Dev-Umgebung starten</h2><p>Der WUIC-Stack besteht aus mehreren Diensten. Starte sie in der angegebenen Reihenfolge.</p><h3>Voraussetzungen</h3><table><thead><tr><th>Was</th><th>Verifikation</th><th>Hinweise</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle fuer IIS in Produktion</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>Mit 22 wird das Paket getestet; unter npm 10.9.x gelingt die Installation dank der mitgelieferten <code>package-lock.json</code></td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>Die vorinstallierte Windows PowerShell genuegt: <code>rename-project.ps1</code> und die <code>llm-workspace/</code>-Skripte laufen auch unter 5.1. PowerShell 7 wird empfohlen, ist nicht erforderlich</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>Fehlt er, <strong>installiert ihn der Einzeiler selbst</strong> (SQL Server Express, oder die mit <code>-Dbms</code> gewaehlte Engine); auf Windows Server nicht, siehe Kasten unten. 2019 reicht fuer die Pakete ohne <code>.bak</code>; das <code>.bak</code>-Tutorial ist ein SQL Server 2022-Backup und benoetigt <strong>2022 oder neuer</strong></td></tr><tr><td>Linux (Installer <code>install.sh</code>)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 oder 24.04 LTS</strong> (24.04 empfohlen): nur diese Ubuntu-Versionen werden von Microsoft fuer SQL Server unterstuetzt, die <strong>26.04 wird nicht unterstuetzt</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Gleiche Empfehlung mit MySQL, PostgreSQL und Oracle, da der Installer auf diesen Versionen getestet ist</td></tr><tr><td>NVIDIA-GPU (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Optional: beschleunigt den RAG Chatbot (ohne GPU laeuft er auf CPU)</td></tr></tbody></table><p>> <strong>Auf Windows Server muss die Datenbank vorher installiert werden.</strong> Der Einzeiler beschafft</p><p>> fehlende Komponenten ueber <code>winget</code>, das auf Windows Server nicht vorhanden ist: ohne eine</p><p>> bereits erreichbare Instanz bricht die Installation mit `No SQL Server instance reachable and</p><p>> winget is missing` ab. Installiere die Engine also vor dem Ausfuehren der Zeile - SQL Server</p><p>> muss <strong>2019 oder neuer</strong> sein (Express genuegt; <strong>2022 oder neuer</strong> fuer das <code>.bak</code>-Tutorial),</p><p>> eine 2017 wird nicht akzeptiert. Ist es nicht die Standardinstanz, uebergib sie mit</p><p>> <code>-SqlServer 'localhost\\INSTANZNAME'</code>. Das gilt fuer alle Engines, nicht nur SQL Server.</p><h3>1. Projekt-Template herunterladen</h3><p>Unter Windows erledigt eine PowerShell-Zeile alles: sie laedt das Paket, prueft .NET SDK 10</p><p>und Node.js 22 (und installiert, was fehlt), fuehrt <code>dotnet restore</code> und <code>npm install</code> aus</p><p>und installiert die Erweiterung WUIC Assistant in VS Code.</p><p>Snippet 1:</p><p>Nuetzliche Optionen auf derselben Zeile: <code>-Dbms mysql</code> (oder <code>postgres</code>, <code>oracle</code>) fuer eine</p><p>andere Engine als SQL Server — der Installer installiert und konfiguriert sie selbst — und</p><p><code>-WithTutorial</code>, um auch die Beispieldatenbank herunterzuladen.</p><p>Wenn er fertig ist, ist der letzte Bildschirm bereits die Aufgabenliste:</p><p>Snippet 2:</p><p>Die Verbindungszeichenfolge ist fertig: beim ersten Start fragt der Wizard nach nichts</p><p>weiterem. Mit <code>-Dbms mysql</code> oder <code>-Dbms postgres</code> aendert sich diese Zeile entsprechend und</p><p>traegt Benutzer und Passwort in sich, denn das Superuser-Passwort <strong>erzeugt der Installer</strong>;</p><p>dasselbe Passwort wird in <code>wuic-secrets.json</code> neben der Installation gespeichert, und das ist</p><p>der einzige Ort, an dem es geschrieben bleibt.</p><p>Der manuelle Weg bleibt gueltig, auf jedem System:</p><p>Starten Sie mit dem Paket <code>WuicTest-src-*.zip</code> (Link im <strong>Download</strong>-Bereich der Website).</p><p>Entpacken Sie es in einen Arbeitsordner, z.B. <code>C:\\dev\\WuicTest</code> (die Dateien kommen direkt</p><p>in den Root, NICHT in einen <code>src/</code>-Unterordner). Das Paket enthaelt:</p><ul><li><code>WuicTest.csproj</code> → Host-Projekt mit <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → Angular-App, deren <code>package.json</code> <code>wuic-framework-lib</code> aus der npm-Registry referenziert</li><li><code>appsettings.json</code> vorkonfiguriert im <code>firstRun = "true"</code>-Modus mit <code>__SET_*__</code>-Platzhaltern</li><li><code>appsettings-samples/</code> → 6 fertige Templates (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>Kein Klonen des Framework-Repositories noetig</strong>: <code>WuicCore</code> kommt als NuGet-Paket von</p><p>> <code>nuget.org</code> und <code>wuic-framework-lib</code> als npm-Paket aus der npm-Registry. Der Framework-</p><p>> Quellcode wird nur benoetigt, wenn Sie ihn modifizieren wollen — typischerweise nicht Ihr Fall.</p><p>> <strong>npm 10.9.x und Pakete aelter als 1.7.1</strong>: diese Pakete enthalten keine <code>package-lock.json</code>, und</p><p>> ohne Lock bricht npm 10.9.x (die Version, die Node 22 LTS mitbringt) mit</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> bei der Peer-Aufloesung ab.</p><p>> Laden Sie den neben der Release veroeffentlichten Lock herunter —</p><p>> <code>https://wuic-framework.com/downloads/locks/<zip-name>.package-lock.json</code> — legen Sie ihn in</p><p>> <code>wwwroot/</code> und starten Sie <code>npm install</code> erneut. Der <code>-Src</code>-Einzeiler erledigt das selbst.</p><h3>2. Datenbank</h3><p>Es braucht eine erreichbare Instanz der Engine. <strong>Mit dem Einzeiler ist nichts zu tun</strong>: er</p><p>installiert und konfiguriert die Instanz, und die Verbindungszeichenfolge zum Einfuegen in den</p><p>Wizard ist das Letzte, was er ausgibt. Auf dem manuellen Weg muss die Instanz bereits</p><p>vorhanden sein.</p><p>Verbindungen in <code>appsettings.json</code>:</p><ul><li><code>MetaDataSQLConnection</code> — Metadata-DB (Menue, Tabellen, Spalten, Board, Benutzer)</li><li><code>DataSQLConnection</code> — Anwendungsdaten-DB</li></ul><p>Bei Erstinstallation (<code>AppSettings.firstRun = "true"</code> im Template) erstellt der Scaffolding-</p><p>Wizard beim ersten Start das Metadata-Schema und befuellt die Daten-DB.</p><p>Siehe Seite <em>Initial Scaffolding</em> fuer den gefuehrten Flow.</p><h3>3. Backend (.NET)</h3><p>Aus dem Root des entpackten Ordners (z.B. <code>C:\\dev\\WuicTest</code>):</p><p>Snippet 3:</p><p>Das Backend stellt die APIs auf <code>http://localhost:5000</code> bereit.</p><h3>4. Frontend (Angular)</h3><p>In einer zweiten Shell, aus dem Unterordner <code>wwwroot/</code>:</p><p>Snippet 4:</p><p>Das Frontend ist auf <code>http://localhost:4200</code> verfuegbar.</p><p>Standard-Login (post-firstRun): <code>admin</code> / <code>admin</code>.</p><h3>5. RAG Chatbot (optional)</h3><p>Der RAG Chatbot (<code>Amministrazione > RAG Chat</code>) laeuft <strong>im .NET-Backend</strong>: die</p><p>Retrieval-Engine (<code>rag-engine/WuicRagEngine.dll</code>, ONNX Runtime in-process) wird</p><p>vom Backend geladen, wenn <code>AppSettings.rag-use-dotnet-engine</code> auf <code>"true"</code></p><p>steht (Default in den Release-Paketen). **Kein Python, keine venv, kein</p><p>separater Server, der gestartet werden muss.**</p><p>Beim <strong>ersten</strong> Oeffnen des Chatbots (oder am Ende des First-Run) laedt das</p><p>Backend selbststaendig die ONNX-Modelle (<code>bge-m3</code> + Reranker), den Tokenizer</p><p>und den Index (~4,5 GB) von <code>rag-engine-models-url</code> (Default</p><p><code>https://wuic-framework.com/rag-models</code>) nach <code>rag-engine/artifacts/</code>. Eine</p><p>Internetverbindung wird nur einmal benoetigt; der Download laeuft im</p><p>Hintergrund (1-5 Min.) und eine In-App-Benachrichtigung erscheint zu Beginn</p><p>und am Ende. Solange zeigt die Komponente den Status <strong>RAG offline</strong>, der Rest</p><p>der Anwendung funktioniert normal.</p><p>Relevante <code>AppSettings</code>-Schluessel (alle mit fertigen Defaults):</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — aktiviert die .NET-Engine (<code>false</code> = Python-Fallback, siehe unten)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code>: mit NVIDIA-GPU (CUDA 12.x + cuDNN 9) ~1 s/Abfrage, auf CPU ~15-25 s/Abfrage</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = Framework-Quellen nur als Signatur; <code>internal</code> = vollstaendiger Index</li><li><code>rag-engine-models-url</code> — Download-Quelle beim ersten Start</li><li><code>rag-engine-cuda-path</code> = (leer) — Ordner der CUDA/cuDNN-DLLs, falls nicht systemweit installiert</li></ul><p>Fuer den Chat mit LLM <code>rag-llm-provider</code> + <code>rag-llm-api-key</code> setzen (Claude</p><p>via Anthropic oder ein lokales Modell via Ollama mit <code>rag-llm-base-url</code>). Ohne</p><p>Provider funktioniert nur der Retrieval-Modus (Snippet-Suche). Details zu den</p><p>Schluesseln auf der Seite <em>AppSettings</em>.</p><p>> Der historische Python-Stack (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> auf</p><p>> <code>127.0.0.1:8765</code>) ist nur als Fallback mit <code>rag-use-dotnet-engine = "false"</code></p><p>> nutzbar und ist in den Release-Paketen nicht enthalten.</p><h2>Dienste-Zusammenfassung</h2><table><thead><tr><th>Dienst</th><th>Port</th><th>Erforderlich</th><th>Schnellbefehl</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>ja</td><td>(Windows-Dienst)</td></tr><tr><td>Backend .NET</td><td>5000</td><td>ja</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Frontend Angular</td><td>4200</td><td>ja</td><td><code>npm run serve:dev</code></td></tr><tr><td>RAG-Engine .NET (ONNX)</td><td>in-process</td><td>nein</td><td>wird vom Backend beim ersten Chat geladen</td></tr></tbody></table><h2>Quick Start — erste Komponente</h2><p>1. AsmxProxy-Endpoint konfigurieren.</p><p>2. Route-Metadata und Spalten definieren.</p><p>3. <code>wuic-data-source</code> + <code>wuic-data-repeater</code> montieren.</p><p>Snippet 5:</p>",
|
|
28064
|
+
"html": "<h1>Framework-Uebersicht</h1><p>WUIC Framework ist eine metadata-gesteuerte Plattform zum schnellen und konsistenten Erstellen von Business-Oberflaechen.</p><h2>Was ist enthalten</h2><ul><li>DataSource und DataRepeater zur Orchestrierung von Daten und Rendering.</li><li>Visuelle Archetypes (list, map, scheduler, chart, carousel).</li><li>Runtime-Designer fuer Dashboards und dynamische Templates.</li><li>Workflow-Designer/Runner fuer operative Prozesse.</li><li>RAG Chatbot zum Abfragen der Codebasis in natuerlicher Sprache.</li><li>Multi-DBMS: SQL Server, MySQL, PostgreSQL und Oracle ueber Drop-in-Provider (<code>dbms</code>: <code>mssql</code> | <code>mysql</code> | <code>postgresql</code> | <code>oracle</code>).</li></ul><h2>First Steps — Dev-Umgebung starten</h2><p>Der WUIC-Stack besteht aus mehreren Diensten. Starte sie in der angegebenen Reihenfolge.</p><h3>Voraussetzungen</h3><table><thead><tr><th>Was</th><th>Verifikation</th><th>Hinweise</th></tr></thead><tbody><tr><td>.NET 10 SDK</td><td><code>dotnet --version</code></td><td>Hosting Bundle fuer IIS in Produktion</td></tr><tr><td>Node.js 22 LTS</td><td><code>node --version</code></td><td>Mit 22 wird das Paket getestet; unter npm 10.9.x gelingt die Installation dank der mitgelieferten <code>package-lock.json</code></td></tr><tr><td>PowerShell 5.1+</td><td><code>$PSVersionTable.PSVersion</code></td><td>Die vorinstallierte Windows PowerShell genuegt: <code>rename-project.ps1</code> und die <code>llm-workspace/</code>-Skripte laufen auch unter 5.1. PowerShell 7 wird empfohlen, ist nicht erforderlich</td></tr><tr><td>SQL Server 2019+</td><td><code>sqlcmd -S localhost\\sqlexpress -E -C -Q "SELECT 1"</code></td><td>Fehlt er, <strong>installiert ihn der Einzeiler selbst</strong> (SQL Server Express, oder die mit <code>-Dbms</code> gewaehlte Engine); auf Windows Server nicht, siehe Kasten unten. 2019 reicht fuer die Pakete ohne <code>.bak</code>; das <code>.bak</code>-Tutorial ist ein SQL Server 2022-Backup und benoetigt <strong>2022 oder neuer</strong></td></tr><tr><td>Linux (Installer <code>install.sh</code>)</td><td><code>lsb_release -ds</code></td><td><strong>Ubuntu 22.04 oder 24.04 LTS</strong> (24.04 empfohlen): nur diese Ubuntu-Versionen werden von Microsoft fuer SQL Server unterstuetzt, die <strong>26.04 wird nicht unterstuetzt</strong> (<a href=\"https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener noreferrer\">Supported platforms</a>). Gleiche Empfehlung mit MySQL, PostgreSQL und Oracle, da der Installer auf diesen Versionen getestet ist</td></tr><tr><td>NVIDIA-GPU (CUDA 12.x + cuDNN 9)</td><td><code>nvidia-smi</code></td><td>Optional: beschleunigt den RAG Chatbot (ohne GPU laeuft er auf CPU)</td></tr></tbody></table><p>> <strong>Auf Windows Server muss die Datenbank vorher installiert werden.</strong> Der Einzeiler beschafft</p><p>> fehlende Komponenten ueber <code>winget</code>, das auf Windows Server nicht vorhanden ist: ohne eine</p><p>> bereits erreichbare Instanz bricht die Installation mit `No SQL Server instance reachable and</p><p>> winget is missing` ab. Installiere die Engine also vor dem Ausfuehren der Zeile - SQL Server</p><p>> muss <strong>2019 oder neuer</strong> sein (Express genuegt; <strong>2022 oder neuer</strong> fuer das <code>.bak</code>-Tutorial),</p><p>> eine 2017 wird nicht akzeptiert. Ist es nicht die Standardinstanz, uebergib sie mit</p><p>> <code>-SqlServer 'localhost\\INSTANZNAME'</code>. Das gilt fuer alle Engines, nicht nur SQL Server.</p><h3>1. Projekt-Template herunterladen</h3><p>Unter Windows erledigt eine PowerShell-Zeile alles: sie laedt das Paket, prueft .NET SDK 10</p><p>und Node.js 22 (und installiert, was fehlt), fuehrt <code>dotnet restore</code> und <code>npm install</code> aus</p><p>und installiert die Erweiterung WUIC Assistant in VS Code.</p><p>Snippet 1:</p><p>Nuetzliche Optionen auf derselben Zeile: <code>-Dbms mysql</code> (oder <code>postgres</code>, <code>oracle</code>) fuer eine</p><p>andere Engine als SQL Server — der Installer installiert und konfiguriert sie selbst — und</p><p><code>-WithTutorial</code>, um auch die Beispieldatenbank herunterzuladen.</p><p>Wenn er fertig ist, ist der letzte Bildschirm bereits die Aufgabenliste:</p><p>Snippet 2:</p><p>Die Verbindungszeichenfolge ist fertig: beim ersten Start fragt der Wizard nach nichts</p><p>weiterem. Mit <code>-Dbms mysql</code> oder <code>-Dbms postgres</code> aendert sich diese Zeile entsprechend und</p><p>traegt Benutzer und Passwort in sich, denn das Superuser-Passwort <strong>erzeugt der Installer</strong>;</p><p>dasselbe Passwort wird in <code>wuic-secrets.json</code> neben der Installation gespeichert, und das ist</p><p>der einzige Ort, an dem es geschrieben bleibt.</p><p>Der manuelle Weg bleibt gueltig, auf jedem System:</p><p>Starten Sie mit dem Paket <code>WuicTest-src-*.zip</code> (Link im <strong>Download</strong>-Bereich der Website).</p><p>Entpacken Sie es in einen Arbeitsordner, z.B. <code>C:\\dev\\WuicTest</code> (die Dateien kommen direkt</p><p>in den Root, NICHT in einen <code>src/</code>-Unterordner). Das Paket enthaelt:</p><ul><li><code>WuicTest.csproj</code> → Host-Projekt mit <code><PackageReference Include="WuicCore" Version="..." /></code></li><li><code>wwwroot/</code> → Angular-App, deren <code>package.json</code> <code>wuic-framework-lib</code> aus der npm-Registry referenziert</li><li><code>appsettings.json</code> vorkonfiguriert im <code>firstRun = "true"</code>-Modus mit <code>__SET_*__</code>-Platzhaltern</li><li><code>appsettings-samples/</code> → 6 fertige Templates (<code>mssql</code>/<code>mysql</code>, firstRun/post-firstRun, <code>Development</code>)</li></ul><p>> <strong>Kein Klonen des Framework-Repositories noetig</strong>: <code>WuicCore</code> kommt als NuGet-Paket von</p><p>> <code>nuget.org</code> und <code>wuic-framework-lib</code> als npm-Paket aus der npm-Registry. Der Framework-</p><p>> Quellcode wird nur benoetigt, wenn Sie ihn modifizieren wollen — typischerweise nicht Ihr Fall.</p><p>> <strong>npm 10.9.x und Pakete aelter als 1.7.1</strong>: diese Pakete enthalten keine <code>package-lock.json</code>, und</p><p>> ohne Lock bricht npm 10.9.x (die Version, die Node 22 LTS mitbringt) mit</p><p>> <code>Cannot read properties of null (reading 'edgesOut')</code> bei der Peer-Aufloesung ab.</p><p>> Laden Sie den neben der Release veroeffentlichten Lock herunter —</p><p>> <code>https://wuic-framework.com/downloads/locks/<zip-name>.package-lock.json</code> — legen Sie ihn in</p><p>> <code>wwwroot/</code> und starten Sie <code>npm install</code> erneut. Der <code>-Src</code>-Einzeiler erledigt das selbst.</p><h3>2. Datenbank</h3><p>Es braucht eine erreichbare Instanz der Engine. <strong>Mit dem Einzeiler ist nichts zu tun</strong>: er</p><p>installiert und konfiguriert die Instanz, und die Verbindungszeichenfolge zum Einfuegen in den</p><p>Wizard ist das Letzte, was er ausgibt. Auf dem manuellen Weg muss die Instanz bereits</p><p>vorhanden sein.</p><p>Verbindungen in <code>appsettings.json</code>:</p><ul><li><code>MetaDataSQLConnection</code> — Metadata-DB (Menue, Tabellen, Spalten, Board, Benutzer)</li><li><code>DataSQLConnection</code> — Anwendungsdaten-DB</li></ul><p>Bei Erstinstallation (<code>AppSettings.firstRun = "true"</code> im Template) erstellt der Scaffolding-</p><p>Wizard beim ersten Start das Metadata-Schema und befuellt die Daten-DB.</p><p>Siehe Seite <em>Initial Scaffolding</em> fuer den gefuehrten Flow.</p><p>#### Was der First-Run-Wizard abfragt</p><p>Beim ersten Start zeigt die Anwendung nicht das Login, sondern die Seite **Initiale</p><p>Projektkonfiguration**. Sie wird genau einmal ausgefuellt: danach steht <code>firstRun</code> auf <code>false</code></p><p>und die Seite erscheint nicht wieder.</p><ul><li><strong>Setup-Modus</strong> — zwei Eintraege: <strong>Bestehende Datenbank</strong>, die eine eigene Datenbank</li></ul><p> registriert, und <strong>Tutorial WideWorldImporters</strong>, das die Beispieldatenbank installiert. Der</p><p> zweite erscheint nur, wenn das Paket das Tutorial mitbringt (<code>tutorialAvailable</code>): in Paketen</p><p> ohne Tutorial gibt es die Auswahl gar nicht, und der Modus ist "Bestehende Datenbank".</p><ul><li><strong>DBMS</strong> — die Engine. Beim Wechsel wird die Verbindungszeichenfolge darunter in der Form des</li></ul><p> gewaehlten Providers neu geschrieben.</p><ul><li><strong>DataSQLConnection</strong> — die Zeichenfolge zur Daten-DB und das Feld, von dem alles Weitere</li></ul><p> abhaengt: bis <strong>Verbindung testen und Datenbanken laden</strong> gedrueckt wurde, bleibt die</p><p> Datenbankliste deaktiviert. Der Test prueft die Zugangsdaten, listet die Datenbanken des</p><p> Servers und korrigiert auf SQL Server selbsttaetig die Zertifikatsparameter</p><p> (<code>Encrypt=False;TrustServerCertificate=True</code>) und sagt es Ihnen. <code>Integrated Security</code> gilt</p><p> nur auf SQL Server: die anderen Engines brauchen Benutzer und Passwort.</p><ul><li><strong>Daten-Datenbank</strong> und <strong>Name der Metadaten-DB</strong> — die erste wird aus der vom Test geladenen</li></ul><p> Liste gewaehlt (im Tutorial-Modus ist es ein freies Textfeld, Standard <code>WideWorldImporters</code>);</p><p> die zweite ist der Name der anzulegenden Metadaten-DB (Standard <code>metadataDB</code>, im</p><p> Tutorial-Modus <code>MetadataCRM</code>). Existiert diese Datenbank bereits, fragt der Wizard vor dem</p><p> Neuanlegen nach.</p><ul><li><strong>Tabellen automatisch scaffolden</strong> (nur bei "Bestehende Datenbank") — befuellt</li></ul><p> <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> aus allen Tabellen der gewaehlten Datenbank. Das</p><p> verlaengert das Provisioning bei Datenbanken mit vielen Tabellen am staerksten.</p><ul><li><strong>Initialer Admin-Benutzer</strong> — Benutzername (Standard <code>admin</code>), Passwort (mindestens 4</li></ul><p> Zeichen) und Sprache. Es gibt kein Standardpasswort: das hier eingegebene ist das einzige, mit</p><p> dem die erste Anmeldung gelingt. Die gewaehlte Sprache gilt fuer den Admin-Benutzer und fuer</p><p> diese Seite selbst.</p><ul><li><strong>RAG Chatbot</strong> — nur der Anthropic-Schluessel, optional. Nichts zu installieren: siehe</li></ul><p> Schritt 5.</p><p>Nach <strong>Bestaetigen und Metadaten-DB erzeugen</strong> laeuft das Provisioning selbstaendig weiter, mit</p><p>Fortschrittsbalken und der Zahl verarbeiteter Batches. Dauer, gemessen auf den</p><p>Test-Installationen: <strong>30 s - 2 min</strong> im Tutorial-Modus, <strong>1-4 min</strong> auf einer bestehenden</p><p>Datenbank mit aktiviertem automatischem Scaffolding. Am Ende weicht die Seite dem Login-Formular.</p><h3>3. Backend (.NET)</h3><p>Aus dem Root des entpackten Ordners (z.B. <code>C:\\dev\\WuicTest</code>):</p><p>Snippet 3:</p><p>Das Backend stellt die APIs auf <code>http://localhost:5000</code> bereit.</p><h3>4. Frontend (Angular)</h3><p>In einer zweiten Shell, aus dem Unterordner <code>wwwroot/</code>:</p><p>Snippet 4:</p><p>Das Frontend ist auf <code>http://localhost:4200</code> verfuegbar.</p><p>Die Zugangsdaten sind die des im First-Run-Wizard gewaehlten Admin-Benutzers: der</p><p>Benutzername ist <code>admin</code>, sofern nicht geaendert, und das Passwort ist das selbst gesetzte (ein</p><p>Standardpasswort gibt es nicht).</p><h3>5. RAG Chatbot (optional)</h3><p>Der RAG Chatbot (<code>Amministrazione > RAG Chat</code>) laeuft <strong>im .NET-Backend</strong>: die</p><p>Retrieval-Engine (<code>rag-engine/WuicRagEngine.dll</code>, ONNX Runtime in-process) wird</p><p>vom Backend geladen, wenn <code>AppSettings.rag-use-dotnet-engine</code> auf <code>"true"</code></p><p>steht (Default in den Release-Paketen). **Kein Python, keine venv, kein</p><p>separater Server, der gestartet werden muss.**</p><p>Beim <strong>ersten</strong> Oeffnen des Chatbots (oder am Ende des First-Run) laedt das</p><p>Backend selbststaendig die ONNX-Modelle (<code>bge-m3</code> + Reranker), den Tokenizer</p><p>und den Index (~4,5 GB) von <code>rag-engine-models-url</code> (Default</p><p><code>https://wuic-framework.com/rag-models</code>) nach <code>rag-engine/artifacts/</code>. Eine</p><p>Internetverbindung wird nur einmal benoetigt; der Download laeuft im</p><p>Hintergrund (1-5 Min.) und eine In-App-Benachrichtigung erscheint zu Beginn</p><p>und am Ende. Solange zeigt die Komponente den Status <strong>RAG offline</strong>, der Rest</p><p>der Anwendung funktioniert normal.</p><p>Relevante <code>AppSettings</code>-Schluessel (alle mit fertigen Defaults):</p><ul><li><code>rag-use-dotnet-engine</code> = <code>true</code> — aktiviert die .NET-Engine (<code>false</code> = Python-Fallback, siehe unten)</li><li><code>rag-engine-device</code> = <code>auto</code> — <code>auto</code> | <code>cuda</code> | <code>cpu</code>: mit NVIDIA-GPU (CUDA 12.x + cuDNN 9) ~1 s/Abfrage, auf CPU ~15-25 s/Abfrage</li><li><code>rag-engine-profile</code> = <code>release</code> — <code>release</code> = Framework-Quellen nur als Signatur; <code>internal</code> = vollstaendiger Index</li><li><code>rag-engine-models-url</code> — Download-Quelle beim ersten Start</li><li><code>rag-engine-cuda-path</code> = (leer) — Ordner der CUDA/cuDNN-DLLs, falls nicht systemweit installiert</li></ul><p>Fuer den Chat mit LLM <code>rag-llm-provider</code> + <code>rag-llm-api-key</code> setzen (Claude</p><p>via Anthropic oder ein lokales Modell via Ollama mit <code>rag-llm-base-url</code>). Ohne</p><p>Provider funktioniert nur der Retrieval-Modus (Snippet-Suche). Details zu den</p><p>Schluesseln auf der Seite <em>AppSettings</em>.</p><p>> Der historische Python-Stack (<code>scripts/rag-setup.ps1</code> + <code>rag_server.py</code> auf</p><p>> <code>127.0.0.1:8765</code>) ist nur als Fallback mit <code>rag-use-dotnet-engine = "false"</code></p><p>> nutzbar und ist in den Release-Paketen nicht enthalten.</p><h2>Dienste-Zusammenfassung</h2><table><thead><tr><th>Dienst</th><th>Port</th><th>Erforderlich</th><th>Schnellbefehl</th></tr></thead><tbody><tr><td>SQL Server</td><td>1433</td><td>ja</td><td>(Windows-Dienst)</td></tr><tr><td>Backend .NET</td><td>5000</td><td>ja</td><td><code>dotnet watch ... run</code></td></tr><tr><td>Frontend Angular</td><td>4200</td><td>ja</td><td><code>npm run serve:dev</code></td></tr><tr><td>RAG-Engine .NET (ONNX)</td><td>in-process</td><td>nein</td><td>wird vom Backend beim ersten Chat geladen</td></tr></tbody></table><h2>Quick Start — erste Komponente</h2><p>1. AsmxProxy-Endpoint konfigurieren.</p><p>2. Route-Metadata und Spalten definieren.</p><p>3. <code>wuic-data-source</code> + <code>wuic-data-repeater</code> montieren.</p><p>Snippet 5:</p><h2>Die ersten Listen zeigen 20 Datensaetze: das ist der Trial-Modus</h2><p>Eine frische Installation laeuft <strong>ohne Lizenz</strong>, also im Trial-Modus, und in diesem Modus</p><p>ist <strong>jede Abfrage auf 20 Datensaetze begrenzt</strong>. Das ist weder ein Fehler noch eine Grenze</p><p>der Datenbank: Eine Liste, die bei einer Tabelle mit Tausenden von Zeilen "20 von 20"</p><p>anzeigt, laeuft schlicht ohne Lizenz.</p><p>So laesst es sich in einer Sekunde bestaetigen:</p><p>Snippet 6:</p><p><code>licenseValid: false</code> bestaetigt den Trial-Modus, und <code>licenseReason</code> nennt den Grund</p><p>(<code>invalid_signature</code>, <code>license_expired</code>, <code>machine_fingerprint_not_authorized</code>, ...).</p><p>So kommt man heraus: Die Lizenz unter <strong>Verwaltung > AppSettings-Editor</strong>, Reiter Licensing,</p><p>einfuegen - sie gilt sofort, ein Neustart des Backends ist nicht noetig. Die Details,</p><p>einschliesslich der Grenzen, die der Trial ueber die Datensatzzahl hinaus setzt, stehen auf</p><p>der Seite <a href=\"licensing.md\">Licensing</a>.</p>",
|
|
27989
28065
|
"codeSamples": [
|
|
27990
28066
|
{
|
|
27991
28067
|
"id": "code_1",
|
|
@@ -27997,25 +28073,31 @@ const frameworkDocsContent = {
|
|
|
27997
28073
|
"id": "code_2",
|
|
27998
28074
|
"title": "Snippet 2",
|
|
27999
28075
|
"language": "text",
|
|
28000
|
-
"code": "Developer workspace ready: C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\
|
|
28076
|
+
"code": "Developer workspace ready: C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\n\n code \"C:\\Users\\<user>\\AppData\\Local\\WUIC\\app\\WuicTest.code-workspace\"\n then F5 > 'Fullstack: WuicTest + Chrome' (backend http://localhost:5000, frontend http://localhost:4200)\n\nFirst start opens the first-run wizard: paste this connection string (Windows authentication)\n Data Source=localhost\\SQLEXPRESS;Integrated Security=SSPI;Initial Catalog=WuicData;Encrypt=False;TrustServerCertificate=True\nRename the project: .\\rename-project.ps1 -Name MyApp"
|
|
28001
28077
|
},
|
|
28002
28078
|
{
|
|
28003
28079
|
"id": "code_3",
|
|
28004
28080
|
"title": "Snippet 3",
|
|
28005
28081
|
"language": "powershell",
|
|
28006
|
-
"code": "# Erstes Mal: NuGet-Pakete wiederherstellen (holt WuicCore + deps von nuget.org, ~30 s)\
|
|
28082
|
+
"code": "# Erstes Mal: NuGet-Pakete wiederherstellen (holt WuicCore + deps von nuget.org, ~30 s)\ndotnet restore\n\n# Dev-Start mit Hot Reload\n$env:ASPNETCORE_ENVIRONMENT = 'Development'\ndotnet watch run\n\n# Oder One-Shot-Start (ohne Hot Reload)\ndotnet run"
|
|
28007
28083
|
},
|
|
28008
28084
|
{
|
|
28009
28085
|
"id": "code_4",
|
|
28010
28086
|
"title": "Snippet 4",
|
|
28011
28087
|
"language": "powershell",
|
|
28012
|
-
"code": "cd wwwroot\
|
|
28088
|
+
"code": "cd wwwroot\n\n# Erstes Mal: npm-Abhaengigkeiten wiederherstellen (holt wuic-framework-lib aus npm-Registry, ~2 Min.)\nnpm install\n\n# Dev-Server starten\nnpm run serve:dev"
|
|
28013
28089
|
},
|
|
28014
28090
|
{
|
|
28015
28091
|
"id": "code_5",
|
|
28016
28092
|
"title": "Snippet 5",
|
|
28017
28093
|
"language": "html",
|
|
28018
|
-
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\
|
|
28094
|
+
"code": "<wuic-data-source [hardcodedRoute]=\"'cities'\"></wuic-data-source>\n<wuic-data-repeater [hardcodedAction]=\"'list'\"></wuic-data-repeater>"
|
|
28095
|
+
},
|
|
28096
|
+
{
|
|
28097
|
+
"id": "code_6",
|
|
28098
|
+
"title": "Snippet 6",
|
|
28099
|
+
"language": "bash",
|
|
28100
|
+
"code": "curl -s http://localhost:5000/api/Meta/LicenseStatus"
|
|
28019
28101
|
}
|
|
28020
28102
|
]
|
|
28021
28103
|
}
|
|
@@ -28050,18 +28132,22 @@ const frameworkDocsContent = {
|
|
|
28050
28132
|
"toc": [
|
|
28051
28133
|
{
|
|
28052
28134
|
"id": "sec_1",
|
|
28053
|
-
"title": "
|
|
28135
|
+
"title": "Mit einem Tutorial-Paket gibt es nichts zu scaffolden"
|
|
28054
28136
|
},
|
|
28055
28137
|
{
|
|
28056
28138
|
"id": "sec_2",
|
|
28057
|
-
"title": "
|
|
28139
|
+
"title": "Wann verwenden"
|
|
28058
28140
|
},
|
|
28059
28141
|
{
|
|
28060
28142
|
"id": "sec_3",
|
|
28061
|
-
"title": "
|
|
28143
|
+
"title": "Verhalten bei firstRun=true"
|
|
28062
28144
|
},
|
|
28063
28145
|
{
|
|
28064
28146
|
"id": "sec_4",
|
|
28147
|
+
"title": "Typische Vorgaenge"
|
|
28148
|
+
},
|
|
28149
|
+
{
|
|
28150
|
+
"id": "sec_5",
|
|
28065
28151
|
"title": "Nach dem Provisioning"
|
|
28066
28152
|
}
|
|
28067
28153
|
],
|
|
@@ -28069,7 +28155,7 @@ const frameworkDocsContent = {
|
|
|
28069
28155
|
{
|
|
28070
28156
|
"id": "overview",
|
|
28071
28157
|
"title": "Overview",
|
|
28072
|
-
"html": "<h1>Initiales Scaffolding</h1><p>Diese Seite beschreibt den initialen Bootstrap, wenn <code>AppSettings.firstRun = true</code>.</p><h2>Wann verwenden</h2><ul><li>Neuinstallation (Metadata-/Daten-DB noch nicht bereit).</li><li>Lokale Umgebung, die mit dem initialen Setup neu ausgerichtet werden soll.</li><li>Erster Start nach einem Deploy, bei dem die gefuehrte Provisioning-Prozedur erzwungen werden soll.</li></ul><h2>Verhalten bei firstRun=true</h2><ul><li>Der Endpoint <code>GET /api/Meta/FirstRunStatus</code> gibt <code>firstRun: true</code> zurueck.</li><li>Beim Login erscheint der Erststart-Flow (z.B. Aktion <code>Aktualisieren</code> im Screen).</li><li>Das Setup wendet die Basiskonfigurationen an (Verbindungen, Runtime-Einstellungen, Metadata-Bootstrap).</li></ul><h2>Typische Vorgaenge</h2><ul><li>Pruefen, dass <code>AppSettings.firstRun</code> auf <code>true</code> in <code>appsettings.{Environment}.json</code> des ausgefuehrten Hosts steht.</li><li>Anwendung starten und die initiale Scaffolding-Prozedur ueber die UI abschliessen.</li><li>Sicherstellen, dass Verbindungen und Hauptparameter konsistent sind (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>Nach dem Provisioning</h2><ul><li>Die Setup-Prozedur setzt <code>firstRun</code> auf <code>false</code>, um eine erneute Ausfuehrung bei jedem Start zu vermeiden.</li><li>Standard-Login durchfuehren und den Zugriff auf die Hauptrouten validieren.</li></ul>",
|
|
28158
|
+
"html": "<h1>Initiales Scaffolding</h1><p>Diese Seite beschreibt den initialen Bootstrap, wenn <code>AppSettings.firstRun = true</code>.</p><h2>Mit einem Tutorial-Paket gibt es nichts zu scaffolden</h2><p>Das Scaffolding, um das es auf dieser Seite geht — die Tabellen einer Datenbank lesen und in</p><p><code>_metadati__tabelle</code> / <code>_metadati__colonne</code> registrieren — betrifft <strong>nur</strong> den Modus</p><p>"Bestehende Datenbank" des First-Run-Wizards: dort steht die Checkbox *Tabellen der gewaehlten</p><p>Datenbank automatisch scaffolden*.</p><p>In <strong>Tutorial</strong>-Paketen gibt es diese Checkbox nicht. Die Metadaten-DB kommt bereits befuellt</p><p>(Routen, Spalten, Menue, Uebersetzungen, Beispiel-Dashboards), und der Wizard stellt sie nur</p><p>wieder her und legt den Admin-Benutzer an. Fertige Routen direkt nach dem ersten Start sind also</p><p>nicht das Ergebnis eines Scaffoldings, sondern der Inhalt des Tutorials.</p><table><thead><tr><th>Wizard-Modus</th><th>Was mit den Metadaten passiert</th></tr></thead><tbody><tr><td>Tutorial WideWorldImporters</td><td>Metadaten bereits fertig, aus dem Paket wiederhergestellt. Kein Scaffolding.</td></tr><tr><td>Bestehende Datenbank, Checkbox aus</td><td>Leere Metadaten-DB: die Routen werden selbst registriert, von Hand oder spaeter ueber die Seite Scaffolding.</td></tr><tr><td>Bestehende Datenbank, Checkbox an</td><td>Am Ende der Installation wird jede Tabelle der gewaehlten Datenbank als Route registriert.</td></tr></tbody></table><p>Der Rest dieser Seite gilt fuer die letzten beiden Zeilen dieser Tabelle.</p><h2>Wann verwenden</h2><ul><li>Neuinstallation (Metadata-/Daten-DB noch nicht bereit).</li><li>Lokale Umgebung, die mit dem initialen Setup neu ausgerichtet werden soll.</li><li>Erster Start nach einem Deploy, bei dem die gefuehrte Provisioning-Prozedur erzwungen werden soll.</li></ul><h2>Verhalten bei firstRun=true</h2><ul><li>Der Endpoint <code>GET /api/Meta/FirstRunStatus</code> gibt <code>firstRun: true</code> zurueck.</li><li>Beim Login erscheint der Erststart-Flow (z.B. Aktion <code>Aktualisieren</code> im Screen).</li><li>Das Setup wendet die Basiskonfigurationen an (Verbindungen, Runtime-Einstellungen, Metadata-Bootstrap).</li></ul><h2>Typische Vorgaenge</h2><ul><li>Pruefen, dass <code>AppSettings.firstRun</code> auf <code>true</code> in <code>appsettings.{Environment}.json</code> des ausgefuehrten Hosts steht.</li><li>Anwendung starten und die initiale Scaffolding-Prozedur ueber die UI abschliessen.</li><li>Sicherstellen, dass Verbindungen und Hauptparameter konsistent sind (<code>dbms</code>, <code>DataDBName</code>, <code>ConnectionStrings</code>).</li></ul><h2>Nach dem Provisioning</h2><ul><li>Die Setup-Prozedur setzt <code>firstRun</code> auf <code>false</code>, um eine erneute Ausfuehrung bei jedem Start zu vermeiden.</li><li>Standard-Login durchfuehren und den Zugriff auf die Hauptrouten validieren.</li></ul>",
|
|
28073
28159
|
"codeSamples": []
|
|
28074
28160
|
}
|
|
28075
28161
|
],
|
|
@@ -28128,7 +28214,7 @@ const frameworkDocsContent = {
|
|
|
28128
28214
|
{
|
|
28129
28215
|
"id": "overview",
|
|
28130
28216
|
"title": "Overview",
|
|
28131
|
-
"html": "<h1>Lizenzierung</h1><p>Diese Seite erklaert die Lizenzierung aus der Sicht des Endbenutzers: was benoetigt wird, wie man die Lizenz erhaelt und wie man sie anwendet.</p><h2>Wie erhalte ich eine Lizenz</h2><p>Schauen Sie sich die Plaene, die enthaltenen Funktionen pro Stufe (Developer / Professional / Software House) an und kaufen Sie auf der oeffentlichen Website:</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">WUIC Preise und Plaene — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Vertriebskontakt</a> — zum Evaluieren ist keine Lizenz noetig: ohne Lizenz laeuft das Framework im Trial-Modus (20 Datensaetze pro Abfrage)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">WUIC Startseite</a></li></ul><p>Nach dem Kauf erhalten Sie eine E-Mail mit <code>license-payload</code> + <code>license-signature</code>, die Sie wie im Abschnitt "Endbenutzer-Verfahren" unten beschrieben installieren.</p><h2>Funktionsweise</h2><ul><li>Die Lizenz ist nur gueltig, wenn:</li><li>Korrekte Signatur.</li><li><code>machineFingerprint</code> des aktuellen Servers in der Liste <code>machineFingerprints</code> des signierten Payloads vorhanden ist.</li><li>Wenn die Lizenz nicht gueltig ist, wird das Lesen von Daten (<code>getFlatRecordData</code>) auf maximal 20 Datensaetze beschraenkt. Zusaetzlich wird der Host-Hook <code>customizeSelect</code> umgangen (nicht aufgerufen).</li></ul><h2>Wo finde ich den machineFingerprint</h2><p>Backend-Endpunkt:</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → Feld <code>machineFingerprint</code> (immer verfuegbar, auch ohne Lizenz).</li><li>Waehrend des First-Run liefert es auch <code>GET /api/Meta/FirstRunStatus</code>.</li></ul><p>Hinweis: Die lokale Datei <code>installation.id</code> wird nicht mehr fuer die Lizenzierung verwendet.</p><h2>Vorgehensweise fuer den Endbenutzer</h2><p>1. Rufen Sie <code>machineFingerprint</code> von Ihrem Host ab.</p><p>2. Senden Sie den Wert an den Anbieter/Lizenzgeber.</p><p>3. Erhalten Sie die Lizenzwerte:</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (falls fuer Ihre Installation vorgesehen)</li></ul><p>4.
|
|
28217
|
+
"html": "<h1>Lizenzierung</h1><p>Diese Seite erklaert die Lizenzierung aus der Sicht des Endbenutzers: was benoetigt wird, wie man die Lizenz erhaelt und wie man sie anwendet.</p><h2>Wie erhalte ich eine Lizenz</h2><p>Schauen Sie sich die Plaene, die enthaltenen Funktionen pro Stufe (Developer / Professional / Software House) an und kaufen Sie auf der oeffentlichen Website:</p><ul><li><a href=\"https://wuic-framework.com/pricing\" target=\"_blank\" rel=\"noopener noreferrer\">WUIC Preise und Plaene — wuic-framework.com/pricing</a></li><li><a href=\"mailto:licensing@wuic-framework.com\">Vertriebskontakt</a> — zum Evaluieren ist keine Lizenz noetig: ohne Lizenz laeuft das Framework im Trial-Modus (20 Datensaetze pro Abfrage)</li><li><a href=\"https://wuic-framework.com\" target=\"_blank\" rel=\"noopener noreferrer\">WUIC Startseite</a></li></ul><p>Nach dem Kauf erhalten Sie eine E-Mail mit <code>license-payload</code> + <code>license-signature</code>, die Sie wie im Abschnitt "Endbenutzer-Verfahren" unten beschrieben installieren.</p><h2>Funktionsweise</h2><ul><li>Die Lizenz ist nur gueltig, wenn:</li><li>Korrekte Signatur.</li><li><code>machineFingerprint</code> des aktuellen Servers in der Liste <code>machineFingerprints</code> des signierten Payloads vorhanden ist.</li><li>Wenn die Lizenz nicht gueltig ist, wird das Lesen von Daten (<code>getFlatRecordData</code>) auf maximal 20 Datensaetze beschraenkt. Zusaetzlich wird der Host-Hook <code>customizeSelect</code> umgangen (nicht aufgerufen).</li></ul><h2>Wo finde ich den machineFingerprint</h2><p>Backend-Endpunkt:</p><ul><li><code>GET /api/Meta/LicenseStatus</code> → Feld <code>machineFingerprint</code> (immer verfuegbar, auch ohne Lizenz).</li><li>Waehrend des First-Run liefert es auch <code>GET /api/Meta/FirstRunStatus</code>.</li></ul><p>Hinweis: Die lokale Datei <code>installation.id</code> wird nicht mehr fuer die Lizenzierung verwendet.</p><h2>Vorgehensweise fuer den Endbenutzer</h2><p>1. Rufen Sie <code>machineFingerprint</code> von Ihrem Host ab.</p><p>2. Senden Sie den Wert an den Anbieter/Lizenzgeber.</p><p>3. Erhalten Sie die Lizenzwerte:</p><ul><li><code>license-payload</code></li><li><code>license-signature</code></li><li><code>license-public-key-pem</code> (falls fuer Ihre Installation vorgesehen)</li></ul><p>4. Fuegen Sie die Werte ueber die Oberflaeche ein: <strong>Verwaltung > AppSettings-Editor</strong>,</p><p> Abschnitt <strong>License</strong> (Felder <code>License email</code>, <code>License payload</code>, <code>License signature</code>,</p><p> <code>Public key (PEM)</code>), dann speichern. Alternativ koennen sie von Hand im Abschnitt</p><p> <code>AppSettings</code> der Datei <code>appsettings.{Environment}.json</code> des laufenden Hosts stehen.</p><p>5. Ueberpruefen Sie den Lizenzstatus:</p><ul><li>ueber die API: <code>GET /api/Meta/LicenseStatus</code>, erwartet <code>licenseValid = true</code>;</li><li>oder auf der Seite selbst, die die Lizenz direkt nach dem Speichern neu einliest.</li></ul><p><strong>Ein Neustart des Backends ist nicht noetig, wenn Sie den Editor benutzen.</strong> Beim Speichern von</p><p><code>license-payload</code> / <code>license-signature</code> im AppSettings-Editor laedt das Backend den</p><p>Validierungsdienst selbst neu, und die Lizenz gilt ab der naechsten Anfrage. Ein Neustart ist nur</p><p>im anderen Fall noetig, wenn die Werte von Hand in die Datei geschrieben werden: die wird beim</p><p>Start gelesen.</p><h2>Multi-Maschinen-Lizenz</h2><p>Eine einzelne Lizenz kann mehrere Maschinen autorisieren, indem mehrere Werte in <code>machineFingerprints</code> aufgenommen werden.</p><h2>Schnelle Fehlerbehebung</h2><ul><li><code>licenseReason = invalid_signature</code>:</li><li>Payload/Signatur stimmen nicht ueberein oder der oeffentliche Schluessel ist abweichend.</li><li><code>licenseReason = machine_fingerprint_not_authorized</code>:</li><li>Der Fingerprint der aktuellen Maschine ist nicht in der erhaltenen Lizenz enthalten.</li><li><code>licenseReason = machine_fingerprint_missing</code>:</li><li>Die Laufzeitumgebung kann den lokalen Fingerprint nicht berechnen.</li><li><code>licenseReason = license_expired</code>:</li><li>Die Lizenz ist abgelaufen, fordern Sie eine Erneuerung an.</li></ul>",
|
|
28132
28218
|
"codeSamples": []
|
|
28133
28219
|
}
|
|
28134
28220
|
],
|
|
@@ -28803,42 +28889,46 @@ const frameworkDocsContent = {
|
|
|
28803
28889
|
},
|
|
28804
28890
|
{
|
|
28805
28891
|
"id": "sec_2",
|
|
28806
|
-
"title": "
|
|
28892
|
+
"title": "Was die Toolbar standardmaessig zeigt"
|
|
28807
28893
|
},
|
|
28808
28894
|
{
|
|
28809
28895
|
"id": "sec_3",
|
|
28810
|
-
"title": "
|
|
28896
|
+
"title": "Screenshot-Referenz (Benutzerhandbuch)"
|
|
28811
28897
|
},
|
|
28812
28898
|
{
|
|
28813
28899
|
"id": "sec_4",
|
|
28814
|
-
"title": "
|
|
28900
|
+
"title": "Metadaten Inline-Editing"
|
|
28815
28901
|
},
|
|
28816
28902
|
{
|
|
28817
28903
|
"id": "sec_5",
|
|
28818
|
-
"title": "
|
|
28904
|
+
"title": "Toolbar Export/Import"
|
|
28819
28905
|
},
|
|
28820
28906
|
{
|
|
28821
28907
|
"id": "sec_6",
|
|
28822
|
-
"title": "
|
|
28908
|
+
"title": "Config Metadata"
|
|
28823
28909
|
},
|
|
28824
28910
|
{
|
|
28825
28911
|
"id": "sec_7",
|
|
28826
|
-
"title": "md_props_bag:
|
|
28912
|
+
"title": "md_props_bag: toolbar"
|
|
28827
28913
|
},
|
|
28828
28914
|
{
|
|
28829
28915
|
"id": "sec_8",
|
|
28830
|
-
"title": "
|
|
28916
|
+
"title": "md_props_bag: archetypes.list"
|
|
28831
28917
|
},
|
|
28832
28918
|
{
|
|
28833
28919
|
"id": "sec_9",
|
|
28834
|
-
"title": "
|
|
28920
|
+
"title": "Paging: md_pagesize und md_page_size_choice"
|
|
28835
28921
|
},
|
|
28836
28922
|
{
|
|
28837
28923
|
"id": "sec_10",
|
|
28838
|
-
"title": "
|
|
28924
|
+
"title": "Erzwungene Virtualisierung bei hoher Seitengroesse"
|
|
28839
28925
|
},
|
|
28840
28926
|
{
|
|
28841
28927
|
"id": "sec_11",
|
|
28928
|
+
"title": "Events und Subscriptions (Host)"
|
|
28929
|
+
},
|
|
28930
|
+
{
|
|
28931
|
+
"id": "sec_12",
|
|
28842
28932
|
"title": "`rowCustomSelect` — tatsachliche Signatur (Falle)"
|
|
28843
28933
|
}
|
|
28844
28934
|
],
|
|
@@ -28846,7 +28936,7 @@ const frameworkDocsContent = {
|
|
|
28846
28936
|
{
|
|
28847
28937
|
"id": "overview",
|
|
28848
28938
|
"title": "Overview",
|
|
28849
|
-
"html": "<h1>List Grid</h1><p>Hauptkomponente fuer tabellarische Listen mit Filtern, Sortierung, serverseitigem Paging und Zeilenaktionen.</p><h2>Anwendungsfaelle</h2><ul><li>Enterprise-CRUD-Tabellen.</li><li>Operative Reports mit Multi-Spalten-Filtern.</li><li>Sehr grosse Datasets mit <code>cursorMode</code>.</li></ul><h2>Screenshot-Referenz (Benutzerhandbuch)</h2><ul><li><code>manual__grid__01.png</code>: Modus <code>inline cell edit</code> im List-Grid.</li><li><code>manual__grid__02.png</code>: Modus <code>inline edit</code> (Row-Level) im List-Grid.</li></ul><h2>Metadaten Inline-Editing</h2><p>Konfiguration im <code>md_props_bag</code> der Tabellen-Metadata:</p><ul><li><code>md_inline_edit</code></li></ul><p> - aktiviert das Inline-Editing der Zeile im List-Grid (editierbare Zellen im Zeilenkontext, ohne Popup-Oeffnung).</p><p> - nuetzlich wenn die Tabellen-UX mit schnellem Editing pro Datensatz beibehalten werden soll.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - aktiviert das Inline-Editing "Zelle fuer Zelle" (Fokus auf einzelne Zelle).</p><p> - Hinweis: in Legacy-Konfigurationen kann dies als <code>md_inline_cell_editing</code> erscheinen; das Runtime-Verhalten ist identisch.</p><p> - <strong>Runtime-Promotion</strong>: wenn <code>md_inline_cell_edit</code> <code>true</code> ist, erzwingt die Komponente</p><p> zur Laufzeit auch <code>md_inline_edit = true</code>, unabhaengig vom DB-Wert.</p><p> Beide UX benoetigen die sichtbare Action-Spalte, daher sind sie auf Rendering-Ebene</p><p> nicht gegenseitig ausschliessend.</p><ul><li><code>md_batch_save</code></li></ul><p> - aktiviert das Batch-Speichern der ausstehenden Aenderungen (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - bei Verwendung zusammen mit Inline-Cell bleiben die Aenderungen ausstehend bis zum expliziten Speichern.</p><p> - <strong>Voraussetzung</strong>: <code>md_batch_save</code> wirkt <strong>nur</strong> wenn <code>md_inline_cell_edit</code> <code>true</code> ist.</p><p> Mit <code>md_inline_cell_edit:false</code> wird das Flag zur Laufzeit ignoriert und die Buttons</p><p> "Aenderungen speichern / Aenderungen verwerfen" werden nicht gerendert.</p><h3>Gueltige Kombinationen</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Runtime-Ergebnis</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>beliebig</td><td>Row-Level Inline-Edit mit Pencil. <code>md_batch_save</code> ignoriert.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Zelle-fuer-Zelle Autosave bei Blur. <code>md_inline_edit</code> wird zur Laufzeit auf <code>true</code> erzwungen.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Zelle-fuer-Zelle mit Pending-Buffer + Toolbar <code>Speichern / Aenderungen verwerfen</code>.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>beliebig</td><td>Kein Inline-Editing. <code>md_batch_save</code> ignoriert.</td></tr></tbody></table><p>Beispiel Row-Level Inline-Edit:</p><p>Snippet 1:</p><p>Beispiel Zelle-fuer-Zelle mit Batch-Save:</p><p>Snippet 2:</p><h2>Toolbar Export/Import</h2><ul><li>Export XLS:</li></ul><p> - zeigt Fortschrittsdialog mit Echtzeit-Prozentsatz;</p><p> - Aktionen: <code>Im Hintergrund fortsetzen</code>, <code>Task abbrechen</code>, <code>Unterbrechen und teilweise herunterladen</code>;</p><p> - im Hintergrund wird eine Benachrichtigung mit Fortschritt erstellt; Klick oeffnet den Dialog erneut.</p><ul><li>Import XLS/XLSX (wenn <code>md_importable = true</code>):</li></ul><p> - Fortschrittsdialog nach Bestaetigung;</p><p> - Aktionen: <code>Im Hintergrund fortsetzen</code>, <code>Import abbrechen (Rollback)</code>, <code>Stop und teilweise Commit</code>;</p><p> - nach Import-Ende wird eine Zusammenfassungs-Benachrichtigung erstellt, die zur Route fuehrt.</p><h2>Config Metadata</h2><p>Schluessel-Einstellungen in <code>md_props_bag</code> und Spalten-Metadaten.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Opt-in-Flags, die Bloecke der list-grid Toolbar (<code>caption-bar</code>) ausblenden. Alle unter <code>md_props_bag.toolbar.*</code> (zur Laufzeit als <code>tableMetadata.extraProps.toolbar</code> geparst).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, default <code>false</code>): blendet in der <strong>caption-right</strong> den Button "Status verwalten" (Bookmark-Icon) + das <code><select></code> der gespeicherten Zustaende aus. Nuetzlich fuer hardcoded / Demo-Routes, bei denen das Saved-State-Feature (Persistenz pro <code>user_id</code> + Route via <code>MetaService</code>) keinen Sinn ergibt — z.B. Pattern 3 reines OData ohne registrierte Route-Metadaten.</li><li><code>hideBatchActions</code> (boolean, default <code>false</code>): blendet in der <strong>caption-left</strong> die Buttons "Aenderungen speichern" (<code>pi-save</code>) + "Aenderungen verwerfen" (<code>pi-times</code>) + den Aenderungs-Zaehler-Indikator (<code>grid-changes-indicator</code>, Pencil-Badge + Count) aus. Vom Framework generiert, wenn <code>md_inline_cell_editing</code> + <code>md_batch_save</code> aktiv sind. Konzipiert fuer <strong>verschachtelte Grids in einem parametric-dialog</strong>: Save/Cancel des Parents persistiert Master + Zeilen in einem Schritt via Framework Batch Save, und die Duplikat-Buttons auf der nested Grid verwirren die UX.</li></ul><p>Beispiel nested rows in custom edit-form (Runtime-Patch):</p><p>Snippet 5:</p><p>TS-Typ in <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (<code>extraProps.toolbar</code> Property). Die Flags deaktivieren NICHT die zugrundeliegende <code>md_batch_save</code>-Logik (Aenderungen werden weiterhin getrackt); sie entfernen nur die Toolbar-UI — der eigentliche Save laeuft ueber den Parent-Flow.</p><h2>md_props_bag: archetypes.list</h2><p>Die Komponente liest <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code>:</li><li>Typ: boolean (mit tolerantem Parser)</li><li>akzeptierte Werte: <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>Runtime-Default: <code>true</code> wenn absent oder leer</li><li>Effekt: verteilt die Spaltenbreiten prozentual (anstelle von px), wenn keine vom Benutzer persistierten Breiten vorhanden sind.</li></ul><ul><li><code>virtualize</code>:</li><li>Typ: <code>boolean</code> oder <code>object</code></li><li>akzeptierte Werte:</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>Object mit <code>enabled</code> (optional) und <code>itemSize</code> (optional)</li><li>Runtime-Default: deaktiviert (<code>false</code>) wenn absent</li><li><code>enabled</code>:</li><li>Default: <code>true</code> wenn der <code>virtualize</code>-Knoten ein Object ohne <code>enabled</code> ist, sonst toleranter Parser</li><li>Effekt: aktiviert <code>virtualScroll</code> auf <code>p-table</code></li><li><code>itemSize</code>:</li><li>Default: <code>44</code></li><li>Effekt: setzt <code>virtualScrollItemSize</code> (virtuelle Zeilenhoehe in px)</li></ul><ul><li><code>advancedFilter</code>:</li><li>Typ: boolean (mit tolerantem Parser)</li><li>Runtime-Default: <code>false</code></li><li>Effekt:</li><li>wenn <code>true</code>, blendet das Grid die Spalten-Filter-Icons (<code>p-columnFilter</code>) aus und verwendet die <code>wuic-filter-bar</code> ueber der Tabelle (auf <code>data-repeater</code>/<code>bounded-repeater</code>-Ebene), um die Filter anzuwenden.</li></ul><p>Betriebshinweis:</p><ul><li>der <code>md_props_bag</code>-Suggest im Metadata-Editor stellt auch den checkbaren Knoten <code>archetypes.list.advancedFilter</code> bereit.</li></ul><h2>Paging: md_pagesize und md_page_size_choice</h2><p>Das Grid verwendet <code>md_pagesize</code> als Standard-Seitengroesse und <code>md_page_size_choice</code> als Liste der im Paginator auswaehlbaren Werte.</p><p>Runtime-Regeln:</p><ul><li>wenn <code>md_pagesize</code> groesser als der maximale Wert in <code>md_page_size_choice</code> ist, fuegt das Framework <code>md_pagesize</code> automatisch zur Optionsliste hinzu;</li><li>die Liste wird normalisiert (gueltige Zahlen, Deduplizierung, aufsteigende Sortierung).</li></ul><p>Beispiel:</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>Runtime-Ergebnis: <code>10,25,50,100,200</code></li></ul><h2>Erzwungene Virtualisierung bei hoher Seitengroesse</h2><p>Wenn der Benutzer im Paginator einen Wert <code>pageSize >= 1000</code> auswaehlt:</p><ul><li>wird die Virtualisierung automatisch erzwungen, auch wenn <code>md_props_bag.archetypes.list.virtualize</code> absent oder deaktiviert ist;</li><li><code>virtualScrollItemSize</code> wird auf den Standardwert <code>44</code> gesetzt.</li></ul><p>Dieses Verhalten schuetzt das Rendering der Tabelle bei sehr grossen Seiten.</p><h2>Events und Subscriptions (Host)</h2><p><code>wuic-list-grid</code> stellt Runtime-Events bereit, die nuetzlich sind, um den Render-Zyklus und die p-table-Callbacks auf der Host-Projektseite zu intercepten.</p><p>Verfuegbare Events:</p><ul><li><code>onAfterRender</code>: wird am Ende des Datenbindings des Grids emittiert (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code>: wird vor dem logischen Rendering der einzelnen Zeile emittiert; unterstuetzt Cancel via <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code>: wird nach dem logischen Rendering der einzelnen Zeile emittiert.</li><li><code>onPaging</code>: wird bei Paging-Events emittiert (<code>p-table onPage</code>).</li><li><code>onSorting</code>: wird bei Sorting-Events emittiert (<code>p-table onSort</code>).</li><li><code>onFiltering</code>: wird bei Filtering-Events emittiert (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code>: wird bei Aenderung der Zeilenauswahl emittiert.</li><li><code>onPTableRowExpand</code>: wird beim Expandieren einer Zeile emittiert.</li><li><code>onPTableRowCollapse</code>: wird beim Collapsen einer Zeile emittiert.</li><li><code>onPTableColumnResize</code>: wird beim Spalten-Resize emittiert.</li><li><code>onPTableColumnReorder</code>: wird beim Spalten-Reorder emittiert.</li></ul><h3>Beispiel 1: direktes Binding im Template</h3><p>Snippet 7:</p><h3>Beispiel 2: Subscribe via ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — tatsachliche Signatur (Falle)</h2><p><code><wuic-list-grid></code> akzeptiert ein <code>[rowCustomSelect]</code>-Input zum Abfangen der Zeilenauswahl (Offnen eines "Dokument auswahlen"-Dialogs, Master-Detail-Flow, etc.). Die TypeScript-Signatur in <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> lautet:</p><p>Snippet 9:</p><p><strong>Zur Laufzeit wird der Callback jedoch mit umgekehrten Argumenten aufgerufen</strong> — das Framework ruft <code>rowCustomSelect($event, rowData, dt)</code> auf (siehe <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> und <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Symptom bei falscher Reihenfolge: <code>rowData?.id</code> ist undefined → fruhzeitiger Guard im Handler → der Callback kehrt stillschweigend zuruck und der Dialog/die Aktion startet nicht. Kein Konsolenfehler.</p><p>Korrekte Form (auf Laufzeit-Invocation abgestimmt):</p><p>Snippet 10:</p><p>Verwendung im Template:</p><p>Snippet 11:</p><p>> Hinweis: Die Tests in <code>designer.component.spec.ts</code> (z.B. Zeile 512) rufen den Callback mit <code>({currentTarget: rowCell}, {id: 42}, null)</code> auf und bestatigen die Reihenfolge <code>($event, rowData, dt)</code>. Sollte das Framework die deklarierte Signatur kunftig angleichen, wird auch diese Seite aktualisiert.</p>",
|
|
28939
|
+
"html": "<h1>List Grid</h1><p>Hauptkomponente fuer tabellarische Listen mit Filtern, Sortierung, serverseitigem Paging und Zeilenaktionen.</p><h2>Anwendungsfaelle</h2><ul><li>Enterprise-CRUD-Tabellen.</li><li>Operative Reports mit Multi-Spalten-Filtern.</li><li>Sehr grosse Datasets mit <code>cursorMode</code>.</li></ul><h2>Was die Toolbar standardmaessig zeigt</h2><p>Beim Oeffnen einer frisch gescaffoldeten Route sitzt die Caption-Bar ueber dem Grid. Links:</p><table><thead><tr><th>Schaltflaeche</th><th>Wann sie erscheint</th></tr></thead><tbody><tr><td><strong>Aktualisieren</strong></td><td>immer, ausser bei <code>md_hide_refresh</code></td></tr><tr><td><strong>Hinzufuegen</strong></td><td>mit <code>md_insertable</code></td></tr><tr><td><strong>Aktionen</strong></td><td>wenn die Tabelle Custom Actions hat</td></tr><tr><td>Import / Export</td><td>immer; der Import-Zweig nur mit <code>md_importable</code></td></tr><tr><td><strong>Berichte</strong></td><td>wenn der Route mindestens ein Report zugeordnet ist</td></tr><tr><td><strong>Aenderungen speichern</strong> / <strong>Aenderungen verwerfen</strong></td><td>nur mit <code>md_inline_cell_edit</code> <strong>und</strong> <code>md_batch_save</code></td></tr></tbody></table><p>Rechts: <strong>Status verwalten</strong> (davor die Auswahl der gespeicherten Zustaende, falls vorhanden),</p><p><strong>Filter loeschen</strong>, wenn die Filter auf den Spalten sitzen, und <strong>Performance</strong>, wenn der</p><p>Inspector fuer die Route aktiviert ist.</p><p>> Die weiter unten auf dieser Seite zitierten Beschriftungen **stehen nicht auf diesem</p><p>> Bildschirm*<em>, und das ist kein Fehler: die von Export/Import (</em>Im Hintergrund fortfahren*,</p><p>> <em>Task abbrechen</em>, <em>Stoppen und teilweise herunterladen</em>, <em>Import abbrechen (Rollback)</em>,</p><p>> <em>Stoppen und teilweise committen</em>) leben im Fortschrittsdialog, den es nur waehrend eines</p><p>> laufenden Exports oder Imports gibt; <em>Aenderungen speichern</em> und <em>Aenderungen verwerfen</em></p><p>> erscheinen nur mit den beiden Flags oben. Sie gehoeren zu anderen Momenten als dem ersten</p><p>> Oeffnen der Liste.</p><h2>Screenshot-Referenz (Benutzerhandbuch)</h2><ul><li><code>manual__grid__01.png</code>: Modus <code>inline cell edit</code> im List-Grid.</li><li><code>manual__grid__02.png</code>: Modus <code>inline edit</code> (Row-Level) im List-Grid.</li></ul><h2>Metadaten Inline-Editing</h2><p>Konfiguration im <code>md_props_bag</code> der Tabellen-Metadata:</p><ul><li><code>md_inline_edit</code></li></ul><p> - aktiviert das Inline-Editing der Zeile im List-Grid (editierbare Zellen im Zeilenkontext, ohne Popup-Oeffnung).</p><p> - nuetzlich wenn die Tabellen-UX mit schnellem Editing pro Datensatz beibehalten werden soll.</p><ul><li><code>md_inline_cell_edit</code></li></ul><p> - aktiviert das Inline-Editing "Zelle fuer Zelle" (Fokus auf einzelne Zelle).</p><p> - Hinweis: in Legacy-Konfigurationen kann dies als <code>md_inline_cell_editing</code> erscheinen; das Runtime-Verhalten ist identisch.</p><p> - <strong>Runtime-Promotion</strong>: wenn <code>md_inline_cell_edit</code> <code>true</code> ist, erzwingt die Komponente</p><p> zur Laufzeit auch <code>md_inline_edit = true</code>, unabhaengig vom DB-Wert.</p><p> Beide UX benoetigen die sichtbare Action-Spalte, daher sind sie auf Rendering-Ebene</p><p> nicht gegenseitig ausschliessend.</p><ul><li><code>md_batch_save</code></li></ul><p> - aktiviert das Batch-Speichern der ausstehenden Aenderungen (<code>Save changes</code> / <code>Cancel changes</code>).</p><p> - bei Verwendung zusammen mit Inline-Cell bleiben die Aenderungen ausstehend bis zum expliziten Speichern.</p><p> - <strong>Voraussetzung</strong>: <code>md_batch_save</code> wirkt <strong>nur</strong> wenn <code>md_inline_cell_edit</code> <code>true</code> ist.</p><p> Mit <code>md_inline_cell_edit:false</code> wird das Flag zur Laufzeit ignoriert und die Buttons</p><p> "Aenderungen speichern / Aenderungen verwerfen" werden nicht gerendert.</p><h3>Gueltige Kombinationen</h3><table><thead><tr><th><code>md_inline_edit</code></th><th><code>md_inline_cell_edit</code></th><th><code>md_batch_save</code></th><th>Runtime-Ergebnis</th></tr></thead><tbody><tr><td><code>true</code></td><td><code>false</code></td><td>beliebig</td><td>Row-Level Inline-Edit mit Pencil. <code>md_batch_save</code> ignoriert.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td><td>Zelle-fuer-Zelle Autosave bei Blur. <code>md_inline_edit</code> wird zur Laufzeit auf <code>true</code> erzwungen.</td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>true</code></td><td>Zelle-fuer-Zelle mit Pending-Buffer + Toolbar <code>Speichern / Aenderungen verwerfen</code>.</td></tr><tr><td><code>false</code></td><td><code>false</code></td><td>beliebig</td><td>Kein Inline-Editing. <code>md_batch_save</code> ignoriert.</td></tr></tbody></table><p>Beispiel Row-Level Inline-Edit:</p><p>Snippet 1:</p><p>Beispiel Zelle-fuer-Zelle mit Batch-Save:</p><p>Snippet 2:</p><h2>Toolbar Export/Import</h2><ul><li>Export XLS:</li></ul><p> - zeigt Fortschrittsdialog mit Echtzeit-Prozentsatz;</p><p> - Aktionen: <code>Im Hintergrund fortsetzen</code>, <code>Task abbrechen</code>, <code>Unterbrechen und teilweise herunterladen</code>;</p><p> - im Hintergrund wird eine Benachrichtigung mit Fortschritt erstellt; Klick oeffnet den Dialog erneut.</p><ul><li>Import XLS/XLSX (wenn <code>md_importable = true</code>):</li></ul><p> - Fortschrittsdialog nach Bestaetigung;</p><p> - Aktionen: <code>Im Hintergrund fortsetzen</code>, <code>Import abbrechen (Rollback)</code>, <code>Stop und teilweise Commit</code>;</p><p> - nach Import-Ende wird eine Zusammenfassungs-Benachrichtigung erstellt, die zur Route fuehrt.</p><h2>Config Metadata</h2><p>Schluessel-Einstellungen in <code>md_props_bag</code> und Spalten-Metadaten.</p><p>Snippet 3:</p><h2>md_props_bag: toolbar</h2><p>Opt-in-Flags, die Bloecke der list-grid Toolbar (<code>caption-bar</code>) ausblenden. Alle unter <code>md_props_bag.toolbar.*</code> (zur Laufzeit als <code>tableMetadata.extraProps.toolbar</code> geparst).</p><p>Snippet 4:</p><ul><li><code>hideManageState</code> (boolean, default <code>false</code>): blendet in der <strong>caption-right</strong> den Button "Status verwalten" (Bookmark-Icon) + das <code><select></code> der gespeicherten Zustaende aus. Nuetzlich fuer hardcoded / Demo-Routes, bei denen das Saved-State-Feature (Persistenz pro <code>user_id</code> + Route via <code>MetaService</code>) keinen Sinn ergibt — z.B. Pattern 3 reines OData ohne registrierte Route-Metadaten.</li><li><code>hideBatchActions</code> (boolean, default <code>false</code>): blendet in der <strong>caption-left</strong> die Buttons "Aenderungen speichern" (<code>pi-save</code>) + "Aenderungen verwerfen" (<code>pi-times</code>) + den Aenderungs-Zaehler-Indikator (<code>grid-changes-indicator</code>, Pencil-Badge + Count) aus. Vom Framework generiert, wenn <code>md_inline_cell_editing</code> + <code>md_batch_save</code> aktiv sind. Konzipiert fuer <strong>verschachtelte Grids in einem parametric-dialog</strong>: Save/Cancel des Parents persistiert Master + Zeilen in einem Schritt via Framework Batch Save, und die Duplikat-Buttons auf der nested Grid verwirren die UX.</li></ul><p>Beispiel nested rows in custom edit-form (Runtime-Patch):</p><p>Snippet 5:</p><p>TS-Typ in <a href=\"../api/wuic-framework-lib.metadatitabella.html\">`metadati_tabella.ts`</a> (<code>extraProps.toolbar</code> Property). Die Flags deaktivieren NICHT die zugrundeliegende <code>md_batch_save</code>-Logik (Aenderungen werden weiterhin getrackt); sie entfernen nur die Toolbar-UI — der eigentliche Save laeuft ueber den Parent-Flow.</p><h2>md_props_bag: archetypes.list</h2><p>Die Komponente liest <code>md_props_bag.archetypes.list</code>.</p><p>Snippet 6:</p><ul><li><code>proportionalColwidth</code>:</li><li>Typ: boolean (mit tolerantem Parser)</li><li>akzeptierte Werte: <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>"true"</code>, <code>"false"</code>, <code>"1"</code>, <code>"0"</code></li><li>Runtime-Default: <code>true</code> wenn absent oder leer</li><li>Effekt: verteilt die Spaltenbreiten prozentual (anstelle von px), wenn keine vom Benutzer persistierten Breiten vorhanden sind.</li></ul><ul><li><code>virtualize</code>:</li><li>Typ: <code>boolean</code> oder <code>object</code></li><li>akzeptierte Werte:</li><li><code>true</code>/<code>false</code>, <code>1</code>/<code>0</code>, <code>"true"</code>/<code>"false"</code>, <code>"1"</code>/<code>"0"</code></li><li>Object mit <code>enabled</code> (optional) und <code>itemSize</code> (optional)</li><li>Runtime-Default: deaktiviert (<code>false</code>) wenn absent</li><li><code>enabled</code>:</li><li>Default: <code>true</code> wenn der <code>virtualize</code>-Knoten ein Object ohne <code>enabled</code> ist, sonst toleranter Parser</li><li>Effekt: aktiviert <code>virtualScroll</code> auf <code>p-table</code></li><li><code>itemSize</code>:</li><li>Default: <code>44</code></li><li>Effekt: setzt <code>virtualScrollItemSize</code> (virtuelle Zeilenhoehe in px)</li></ul><ul><li><code>advancedFilter</code>:</li><li>Typ: boolean (mit tolerantem Parser)</li><li>Runtime-Default: <code>false</code></li><li>Effekt:</li><li>wenn <code>true</code>, blendet das Grid die Spalten-Filter-Icons (<code>p-columnFilter</code>) aus und verwendet die <code>wuic-filter-bar</code> ueber der Tabelle (auf <code>data-repeater</code>/<code>bounded-repeater</code>-Ebene), um die Filter anzuwenden.</li></ul><p>Betriebshinweis:</p><ul><li>der <code>md_props_bag</code>-Suggest im Metadata-Editor stellt auch den checkbaren Knoten <code>archetypes.list.advancedFilter</code> bereit.</li></ul><h2>Paging: md_pagesize und md_page_size_choice</h2><p>Das Grid verwendet <code>md_pagesize</code> als Standard-Seitengroesse und <code>md_page_size_choice</code> als Liste der im Paginator auswaehlbaren Werte.</p><p>Runtime-Regeln:</p><ul><li>wenn <code>md_pagesize</code> groesser als der maximale Wert in <code>md_page_size_choice</code> ist, fuegt das Framework <code>md_pagesize</code> automatisch zur Optionsliste hinzu;</li><li>die Liste wird normalisiert (gueltige Zahlen, Deduplizierung, aufsteigende Sortierung).</li></ul><p>Beispiel:</p><ul><li><code>md_pagesize = 200</code></li><li><code>md_page_size_choice = "10,25,50,100"</code></li><li>Runtime-Ergebnis: <code>10,25,50,100,200</code></li></ul><h2>Erzwungene Virtualisierung bei hoher Seitengroesse</h2><p>Wenn der Benutzer im Paginator einen Wert <code>pageSize >= 1000</code> auswaehlt:</p><ul><li>wird die Virtualisierung automatisch erzwungen, auch wenn <code>md_props_bag.archetypes.list.virtualize</code> absent oder deaktiviert ist;</li><li><code>virtualScrollItemSize</code> wird auf den Standardwert <code>44</code> gesetzt.</li></ul><p>Dieses Verhalten schuetzt das Rendering der Tabelle bei sehr grossen Seiten.</p><h2>Events und Subscriptions (Host)</h2><p><code>wuic-list-grid</code> stellt Runtime-Events bereit, die nuetzlich sind, um den Render-Zyklus und die p-table-Callbacks auf der Host-Projektseite zu intercepten.</p><p>Verfuegbare Events:</p><ul><li><code>onAfterRender</code>: wird am Ende des Datenbindings des Grids emittiert (<code>rows</code>, <code>totalRecords</code>, <code>metaInfo</code>, <code>datasource</code>).</li><li><code>onBeforeRowRender</code>: wird vor dem logischen Rendering der einzelnen Zeile emittiert; unterstuetzt Cancel via <code>event.cancelRender()</code>.</li><li><code>onAfterRowRender</code>: wird nach dem logischen Rendering der einzelnen Zeile emittiert.</li><li><code>onPaging</code>: wird bei Paging-Events emittiert (<code>p-table onPage</code>).</li><li><code>onSorting</code>: wird bei Sorting-Events emittiert (<code>p-table onSort</code>).</li><li><code>onFiltering</code>: wird bei Filtering-Events emittiert (<code>p-table onFilter</code>).</li><li><code>onPTableSelectionChange</code>: wird bei Aenderung der Zeilenauswahl emittiert.</li><li><code>onPTableRowExpand</code>: wird beim Expandieren einer Zeile emittiert.</li><li><code>onPTableRowCollapse</code>: wird beim Collapsen einer Zeile emittiert.</li><li><code>onPTableColumnResize</code>: wird beim Spalten-Resize emittiert.</li><li><code>onPTableColumnReorder</code>: wird beim Spalten-Reorder emittiert.</li></ul><h3>Beispiel 1: direktes Binding im Template</h3><p>Snippet 7:</p><h3>Beispiel 2: Subscribe via ViewChild</h3><p>Snippet 8:</p><h2><code>rowCustomSelect</code> — tatsachliche Signatur (Falle)</h2><p><code><wuic-list-grid></code> akzeptiert ein <code>[rowCustomSelect]</code>-Input zum Abfangen der Zeilenauswahl (Offnen eines "Dokument auswahlen"-Dialogs, Master-Detail-Flow, etc.). Die TypeScript-Signatur in <a href=\"../../src/lib/component/list-grid/list-grid.component.ts#L140\">list-grid.component.ts:140</a> lautet:</p><p>Snippet 9:</p><p><strong>Zur Laufzeit wird der Callback jedoch mit umgekehrten Argumenten aufgerufen</strong> — das Framework ruft <code>rowCustomSelect($event, rowData, dt)</code> auf (siehe <a href=\"../../src/lib/component/dynamic-template/dynamic-template.component.ts#L447\">dynamic-template.component.ts:447</a> und <a href=\"../../src/lib/component/dynamic-template/dynamic-card-template.component.ts#L205\">dynamic-card-template.component.ts:205</a>).</p><p>Symptom bei falscher Reihenfolge: <code>rowData?.id</code> ist undefined → fruhzeitiger Guard im Handler → der Callback kehrt stillschweigend zuruck und der Dialog/die Aktion startet nicht. Kein Konsolenfehler.</p><p>Korrekte Form (auf Laufzeit-Invocation abgestimmt):</p><p>Snippet 10:</p><p>Verwendung im Template:</p><p>Snippet 11:</p><p>> Hinweis: Die Tests in <code>designer.component.spec.ts</code> (z.B. Zeile 512) rufen den Callback mit <code>({currentTarget: rowCell}, {id: 42}, null)</code> auf und bestatigen die Reihenfolge <code>($event, rowData, dt)</code>. Sollte das Framework die deklarierte Signatur kunftig angleichen, wird auch diese Seite aktualisiert.</p>",
|
|
28850
28940
|
"codeSamples": [
|
|
28851
28941
|
{
|
|
28852
28942
|
"id": "code_1",
|
|
@@ -30572,7 +30662,7 @@ const frameworkDocsContent = {
|
|
|
30572
30662
|
{
|
|
30573
30663
|
"id": "overview",
|
|
30574
30664
|
"title": "Overview",
|
|
30575
|
-
"html": "<h1>Designer</h1><p>Visueller Editor fuer metadata-gesteuerte Dashboards auf Route <code>#/cities/dashboard</code>.</p><h2>Geltungsbereich</h2><ul><li>Board-Komposition via Drag-and-Drop von Knoten und UI-Bloecken.</li><li>Layout und Styling gesteuert durch <code>boardcontent</code> und Tabellen-/Spalten-Metadata.</li><li>Property-Panel-Editing ohne Hardcoding in den Runtime-Komponenten.</li></ul><h2>Designer-Palette</h2><
|
|
30665
|
+
"html": "<h1>Designer</h1><p>Visueller Editor fuer metadata-gesteuerte Dashboards auf Route <code>#/cities/dashboard</code>.</p><h2>Geltungsbereich</h2><ul><li>Board-Komposition via Drag-and-Drop von Knoten und UI-Bloecken.</li><li>Layout und Styling gesteuert durch <code>boardcontent</code> und Tabellen-/Spalten-Metadata.</li><li>Property-Panel-Editing ohne Hardcoding in den Runtime-Komponenten.</li></ul><h2>Designer-Palette</h2><p>Die Palette ist in drei Gruppen geteilt. Die Namen unten sind die, die in der Palette stehen —</p><p>in Grossbuchstaben, genau wie der Designer sie schreibt.</p><p><strong>HTML</strong> — die Markup-Bausteine:</p><table><thead><tr><th>Tool</th><th>Wofuer</th></tr></thead><tbody><tr><td><code>TABLE</code></td><td>Zellenraster. <code>TR</code> und <code>TD</code> gibt es als Tools, sie lassen sich aber nicht ziehen: die Tabelle erzeugt sie</td></tr><tr><td><code>DIV</code></td><td>freier Container, der meistgenutzte Strukturblock</td></tr><tr><td><code>SPAN</code>, <code>LABEL</code>, <code>Hx</code></td><td>databound Text; <code>Hx</code> waehlt die Ebene von h1 bis h6</td></tr><tr><td><code>ANCHOR</code>, <code>IMG</code>, <code>IMAGE</code>, <code>IFRAME</code></td><td>Links, Bilder, externe Inhalte</td></tr><tr><td><code>UL</code></td><td>Liste</td></tr><tr><td><code>BUTTON</code></td><td>Schaltflaeche mit Callback</td></tr><tr><td><code>INPUT</code>, <code>TEXTAREA</code>, <code>CHECKBOX</code>, <code>SELECT</code>, <code>MULTISELECT</code>, <code>DATE</code></td><td>Eingabefelder</td></tr><tr><td><code>KPI</code></td><td>einzelner hervorgehobener Wert</td></tr><tr><td><code>SEPARATOR</code>, <code>HR</code></td><td>Trenner</td></tr></tbody></table><p><strong>DATA</strong> — die mit dem Backend verbundenen Knoten:</p><table><thead><tr><th>Tool</th><th>Wofuer</th></tr></thead><tbody><tr><td><code>DATASOURCE</code></td><td>Metadata-Datenquelle (<code>route</code>, Filter, Sortierung, Paging)</td></tr><tr><td><code>DATAREPEATER</code></td><td>Listen-/Karten-Visualisierung verbunden mit einer Datasource</td></tr><tr><td><code>FILTERBAR</code></td><td>Filterleiste ueber dem Repeater</td></tr><tr><td><code>PAGER</code></td><td>Paginator</td></tr></tbody></table><p><strong>CONTAINER</strong> — die Layouts:</p><table><thead><tr><th>Tool</th><th>Wofuer</th></tr></thead><tbody><tr><td><code>TABVIEW</code> + <code>TABPANEL</code></td><td>Reiter</td></tr><tr><td><code>SPLITTER</code> + <code>SPLITTER-AREA</code></td><td>groessenveraenderbare Bereiche</td></tr><tr><td><code>ACCORDION</code> + <code>ACCORDION-AREA</code></td><td>Akkordeon-Abschnitte</td></tr></tbody></table><p>Zwei Namen, die man vergeblich sucht: <strong>ein Tool "Dynamic Template" gibt es nicht</strong> — das</p><p>dynamische Template ist das, was der <code>DATAREPEATER</code> rendert; es wird ueber dessen Eigenschaften</p><p>konfiguriert und nicht gezogen. Und <strong>"Container" / "Layout" sind der Gruppenname</strong>, keine</p><p>auswaehlbaren Eintraege.</p><p>Dazu kommen die vom Host-Projekt registrierten Custom-Tools</p><p>(<code>MetadataProviderService.customDesignerTools</code>), die am Ende unter der von ihnen deklarierten</p><p>Gruppe erscheinen.</p><h2>Hauptfunktionen</h2><ul><li>Drag-and-Drop von Knoten auf die Canvas mit Persistierung im <code>boardcontent</code>.</li><li>Kontextbezogenes Property-Panel mit zu den ausgewaehlten Komponenten konsistenten Inputs.</li><li>Binding zwischen Knoten (<code>datasource -> repeater/template</code>) mit Minimalvalidierung.</li><li>Integrierte Runtime-Vorschau und Layout-Neuausrichtung.</li><li>Verwaltung ausstehender Aenderungen mit Guard vor dem Verlassen.</li></ul><h2>Kontextmenue der Elemente</h2><p>Rechtsklick auf ein Element der Canvas, auf einen Eintrag der unteren Breadcrumb oder auf einen Knoten im Hierarchiebaum zeigt ein Kontextmenue mit drei Eintraegen:</p><ul><li><strong>Eigenschaften bearbeiten</strong> (pi-cog) - waehlt das Element als "current tool" aus und zeigt sein Property-Panel rechts; entspricht dem Klick im Baum. Nuetzlich, um Eigenschaften verschachtelter Elemente zu bearbeiten, ohne sie in der Hierarchie suchen zu muessen.</li><li><strong>Umbenennen</strong> (nur Breadcrumb) - oeffnet einen Dialog zum Umbenennen des <code>displayName</code>.</li><li><strong>Entfernen</strong> - loescht das Element vom Board.</li></ul><h2>Empfohlener operativer Ablauf</h2><ul><li>Ziel-Dashboard-Route oeffnen.</li><li>Knoten aus der Palette einfuegen/verbinden.</li><li>Wesentliche <code>inputs</code> konfigurieren (z.B. <code>route</code>, <code>action</code>, <code>datasource</code>).</li><li>Speichern und Ergebnis in der Runtime validieren.</li></ul><h2>Betriebshinweise</h2><ul><li>Fuer dashboard-spezifische Fixes <code>boardcontent</code>-Patches gegenueber globalen Aenderungen bevorzugen.</li><li>Doppelte Eigenschaften zwischen <code>inputs</code> und inkonsistentem Inline-Stil vermeiden.</li><li>Immer ueberpruefen, dass Datasources eine gesetzte <code>inputs.route</code> haben.</li></ul>",
|
|
30576
30666
|
"codeSamples": []
|
|
30577
30667
|
}
|
|
30578
30668
|
],
|
|
@@ -35168,4 +35258,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
35168
35258
|
}] } });
|
|
35169
35259
|
|
|
35170
35260
|
export { FrameworkDocsComponent };
|
|
35171
|
-
//# sourceMappingURL=wuic-framework-lib-framework-docs.component-
|
|
35261
|
+
//# sourceMappingURL=wuic-framework-lib-framework-docs.component-B2AdE4N0.mjs.map
|