wuic-framework-lib 1.0.7 → 1.0.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.
Files changed (16) hide show
  1. package/fesm2022/{wuic-framework-lib-chart-list.component-j1eRaGZV.mjs → wuic-framework-lib-chart-list.component-Cjdbe3i0.mjs} +56 -4
  2. package/fesm2022/{wuic-framework-lib-code-editor.component-CNREC7r_.mjs → wuic-framework-lib-code-editor.component-xbC6-KoE.mjs} +4 -4
  3. package/fesm2022/{wuic-framework-lib-designer.component-Bb4B6eDu.mjs → wuic-framework-lib-designer.component-ChMnwQH_.mjs} +49 -33
  4. package/fesm2022/{wuic-framework-lib-first-run-wizard.component-CQTs6hR6.mjs → wuic-framework-lib-first-run-wizard.component-DoVifTlj.mjs} +31 -12
  5. package/fesm2022/{wuic-framework-lib-framework-docs.component-CzyQHVAV.mjs → wuic-framework-lib-framework-docs.component-Cqhp5yIg.mjs} +484 -13
  6. package/fesm2022/{wuic-framework-lib-pivot-builder.component-ms-x0Yob.mjs → wuic-framework-lib-pivot-builder.component-ala8bb7P.mjs} +29 -16
  7. package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-mXhyuLAE.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-CdRKaYSG.mjs} +2 -2
  8. package/fesm2022/{wuic-framework-lib-report-designer.component-BjUmOBU3.mjs → wuic-framework-lib-report-designer.component-BeEWCPy0.mjs} +2 -2
  9. package/fesm2022/{wuic-framework-lib-report-viewer.component-BOenTSd2.mjs → wuic-framework-lib-report-viewer.component-CWamvZrx.mjs} +2 -2
  10. package/fesm2022/{wuic-framework-lib-scheduler-list.component-DHcLQ_X7.mjs → wuic-framework-lib-scheduler-list.component-BvrjIVRY.mjs} +12 -4
  11. package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-AFm6hAX4.mjs → wuic-framework-lib-spreadsheet-list-sf.component-CRg47ux6.mjs} +10 -4
  12. package/fesm2022/{wuic-framework-lib-workflow-designer.component-Bn6ocOVw.mjs → wuic-framework-lib-workflow-designer.component-CKFG_J6E.mjs} +29 -3
  13. package/fesm2022/{wuic-framework-lib-wuic-framework-lib-KFbUlRIT.mjs → wuic-framework-lib-wuic-framework-lib-WQiFu5aA.mjs} +2047 -489
  14. package/fesm2022/wuic-framework-lib.mjs +1 -1
  15. package/package.json +1 -1
  16. package/types/wuic-framework-lib.d.ts +448 -14
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { EventEmitter, Output, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import * as i2$2 from '@angular/common';
3
+ import * as i1$2 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i1$1 from '@angular/forms';
6
6
  import { FormsModule } from '@angular/forms';
@@ -13,11 +13,11 @@ import * as i6 from 'primeng/select';
13
13
  import { SelectModule } from 'primeng/select';
14
14
  import * as i11 from 'primeng/progressbar';
15
15
  import { ProgressBarModule } from 'primeng/progressbar';
16
- import * as i3 from 'primeng/tooltip';
16
+ import * as i3$1 from 'primeng/tooltip';
17
17
  import { TooltipModule } from 'primeng/tooltip';
18
- import { l as AuthSessionService, W as WtoolboxService, U as UserInfoService } from './wuic-framework-lib-wuic-framework-lib-KFbUlRIT.mjs';
18
+ import { n as AuthSessionService, W as WtoolboxService, U as UserInfoService } from './wuic-framework-lib-wuic-framework-lib-WQiFu5aA.mjs';
19
19
  import * as i1 from '@angular/common/http';
20
- import * as i2$1 from 'primeng/api';
20
+ import * as i3 from 'primeng/api';
21
21
 
22
22
  /**
23
23
  * Componente standalone framework che incapsula l'INTERO workflow di firstRun:
@@ -124,7 +124,16 @@ class WuicFirstRunWizardComponent {
124
124
  scaffoldExistingDatabase: false,
125
125
  installRag: false,
126
126
  useCuda: false,
127
- anthropicApiKey: ''
127
+ anthropicApiKey: '',
128
+ // Crash reporting opt-in (skill crash-reporting Commit 8). OFF by default
129
+ // per GDPR: l'utente lo abilita esplicitamente in fase di first-install
130
+ // dopo aver letto il disclaimer (link/expand inline nel template). Se
131
+ // abilitato qui, il backend writer di appsettings setta
132
+ // `CrashReporting.Enabled=true` e `DisclaimerAcceptedVersion="1.0"` +
133
+ // `DisclaimerAcceptedAt=<now>` (audit trail) — equivalente al flusso
134
+ // appsettings-editor (Commit 9), centralizzato cosi' che il primo
135
+ // boot non richieda un secondo round-trip dialog.
136
+ enableCrashReporting: false,
128
137
  };
129
138
  firstRunDataDbOptions = [];
130
139
  firstRunRealPath = '';
@@ -539,7 +548,14 @@ class WuicFirstRunWizardComponent {
539
548
  adminLanguage: this.firstRunForm.adminLanguage,
540
549
  installRag: this.firstRunForm.installRag ? 'true' : 'false',
541
550
  useCuda: this.firstRunForm.useCuda ? 'true' : 'false',
542
- anthropicApiKey: (this.firstRunForm.anthropicApiKey || '').trim()
551
+ anthropicApiKey: (this.firstRunForm.anthropicApiKey || '').trim(),
552
+ // Crash reporting opt-in (skill crash-reporting Commit 8). Quando true,
553
+ // configure_wuic deve scrivere `CrashReporting.Enabled=true`,
554
+ // `DisclaimerAcceptedVersion="1.0"` e `DisclaimerAcceptedAt=<now>` in
555
+ // appsettings.json. Quando false (default), niente da fare — la
556
+ // sezione resta a Enabled=false e l'utente potra' attivarla in
557
+ // seguito dall'appsettings-editor (Commit 9).
558
+ enableCrashReporting: this.firstRunForm.enableCrashReporting ? 'true' : 'false'
543
559
  }));
544
560
  await this.clearClientStateForFirstRunLogin();
545
561
  await this.waitForBackendReady();
@@ -565,7 +581,10 @@ class WuicFirstRunWizardComponent {
565
581
  { label: 'Sì', value: 'yes' }
566
582
  ]
567
583
  }
568
- ], '620px');
584
+ // width='620px', height='400px' (auto-fit ~350px + 50px richiesti per
585
+ // dare respiro alla caption con nome DB lungo + radio group + footer
586
+ // OK/Cancel senza scroll interno).
587
+ ], '620px', '400px');
569
588
  const rawConfirm = promptResult?.confirmDrop;
570
589
  let confirmDropValue = rawConfirm;
571
590
  if (rawConfirm && typeof rawConfirm === 'object' && 'value' in rawConfirm && typeof rawConfirm.value !== 'function') {
@@ -1073,8 +1092,8 @@ class WuicFirstRunWizardComponent {
1073
1092
  void this.translate.use(resolvedLang);
1074
1093
  }
1075
1094
  }
1076
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WuicFirstRunWizardComponent, deps: [{ token: i1.HttpClient }, { token: i2.TranslateService }, { token: i2$1.MessageService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
1077
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WuicFirstRunWizardComponent, isStandalone: true, selector: "wuic-first-run-wizard-impl", outputs: { complete: "complete" }, ngImport: i0, template: "@if (showFirstRunInstall) {\n<div class=\"first-run-overlay\">\n <div class=\"first-run-card first-run-card-wide\">\n <div class=\"first-run-title\">Configurazione iniziale progetto</div>\n <div class=\"first-run-subtitle\">Seleziona DBMS, connessione dati e nome database metadati.</div>\n\n <!-- BODY scrollabile: header (title/subtitle) e footer (progress + CTA)\n restano sempre visibili, solo questo blocco scrolla quando il form\n e' piu' alto della viewport. -->\n <div class=\"first-run-body\">\n\n <!-- Grid 2 colonne: sx = connessione + scaffold / dx = admin + RAG.\n Su viewport stretti (< 720px) il grid collassa a 1 colonna. -->\n <div class=\"first-run-grid\">\n\n <!-- \u2500\u2500 COLONNA SINISTRA: Database + Setup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"first-run-col\">\n\n @if (firstRunSetupModeOptions.length > 1) {\n <div class=\"first-run-field\">\n <label for=\"first-run-mode\">Modalit\u00E0 setup</label>\n <p-select [options]=\"firstRunSetupModeOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.setupMode\" (ngModelChange)=\"onFirstRunSetupModeChanged($event)\"\n [disabled]=\"firstRunInstalling\" [style]=\"{ width: '100%' }\" inputId=\"first-run-mode\"></p-select>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-dbms\">DBMS</label>\n <p-select [options]=\"firstRunDbmsOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.dbms\" (ngModelChange)=\"onFirstRunDbmsChanged($event)\"\n [disabled]=\"firstRunInstalling\" [style]=\"{ width: '100%' }\" inputId=\"first-run-dbms\"></p-select>\n </div>\n\n @if (firstRunForm.setupMode === 'tutorial') {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.createTutorialIfMissing\"\n (ngModelChange)=\"firstRunForm.createTutorialIfMissing = !!$event\" [disabled]=\"firstRunInstalling\" />\n Crea tutorial se manca\n </label>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-datasql\">DataSQLConnection</label>\n <input id=\"first-run-datasql\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.dataConnectionString\" (ngModelChange)=\"onFirstRunConnectionChanged($event)\"\n [disabled]=\"firstRunInstalling\"\n placeholder=\"es. data source=localhost\\sqlexpress;User ID=sa;Password=...;initial catalog=WideWorldImporters\" />\n </div>\n\n <div class=\"first-run-field\">\n <p-button label=\"Test connessione e carica DB\" severity=\"secondary\" [outlined]=\"true\"\n [loading]=\"firstRunConnectionTesting\"\n [disabled]=\"firstRunInstalling || firstRunLoading || !firstRunForm.dataConnectionString\"\n (onClick)=\"testFirstRunConnectionAndLoadDatabases()\"></p-button>\n </div>\n\n @if (firstRunForm.setupMode === 'tutorial') {\n <div class=\"first-run-field\">\n <label for=\"first-run-datadb\">Database dati tutorial</label>\n <input id=\"first-run-datadb\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.tutorialDataDbName\"\n (ngModelChange)=\"firstRunForm.tutorialDataDbName = $event; firstRunForm.dataDbName = $event\"\n [disabled]=\"firstRunInstalling || !firstRunConnectionValid\"\n placeholder=\"WideWorldImporters\" />\n </div>\n } @else {\n <div class=\"first-run-field\">\n <label for=\"first-run-datadb\">Database dati</label>\n <p-select [options]=\"firstRunDataDbOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.dataDbName\" (ngModelChange)=\"firstRunForm.dataDbName = $event\"\n [disabled]=\"firstRunInstalling || firstRunDbLoading || !firstRunConnectionValid\" [filter]=\"true\"\n [editable]=\"true\" [style]=\"{ width: '100%' }\" inputId=\"first-run-datadb\"\n placeholder=\"Seleziona o digita database\"></p-select>\n <div style=\"margin-top: 0.5rem;\">\n <p-button label=\"Aggiorna elenco DB\" severity=\"secondary\" [outlined]=\"true\" size=\"small\"\n [loading]=\"firstRunDbLoading\" [disabled]=\"firstRunInstalling || !firstRunConnectionValid\"\n (onClick)=\"testFirstRunConnectionAndLoadDatabases()\"></p-button>\n </div>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-metadb\">@if (firstRunForm.setupMode === 'tutorial') {Nome DB metadati tutorial} @else {Nome DB metadati}</label>\n <input id=\"first-run-metadb\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.setupMode === 'tutorial' ? firstRunForm.tutorialMetadataDbName : firstRunForm.metadataDbName\"\n (ngModelChange)=\"firstRunForm.metadataDbName = $event; firstRunForm.tutorialMetadataDbName = $event\"\n [disabled]=\"firstRunInstalling\"\n placeholder=\"metadataDB\" />\n </div>\n\n @if (firstRunForm.setupMode !== 'tutorial') {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.scaffoldExistingDatabase\"\n (ngModelChange)=\"firstRunForm.scaffoldExistingDatabase = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n Esegui scaffold automatico delle tabelle del DB selezionato\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Popola <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> al termine dell'installazione.\n Operazione potenzialmente lunga su DB con molte tabelle.\n </small>\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 COLONNA DESTRA: Admin + RAG \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"first-run-col\">\n\n <div class=\"first-run-section-title\">Utente admin iniziale</div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-username\">Username admin iniziale</label>\n <input id=\"first-run-admin-username\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.adminUsername\"\n (ngModelChange)=\"firstRunForm.adminUsername = $event\"\n [disabled]=\"firstRunInstalling\" autocomplete=\"off\"\n placeholder=\"admin\" />\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-password\">Password admin iniziale</label>\n <input id=\"first-run-admin-password\" class=\"first-run-input\" type=\"password\"\n [ngModel]=\"firstRunForm.adminPassword\"\n (ngModelChange)=\"firstRunForm.adminPassword = $event\"\n [disabled]=\"firstRunInstalling\" autocomplete=\"new-password\"\n placeholder=\"(min 4 caratteri)\" />\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-language\">Lingua admin iniziale</label>\n <p-select [options]=\"firstRunAdminLanguageOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.adminLanguage\"\n (ngModelChange)=\"firstRunForm.adminLanguage = $event\"\n [disabled]=\"firstRunInstalling\"\n [style]=\"{ width: '100%' }\" inputId=\"first-run-admin-language\"></p-select>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Lingua applicata all'utente admin dopo il primo login. Puoi cambiarla in seguito dal profilo utente.\n </small>\n </div>\n\n <div class=\"first-run-section-title first-run-section-title-rag\">RAG Chatbot (opzionale)</div>\n\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.installRag\"\n (ngModelChange)=\"firstRunForm.installRag = !!$event\"\n [disabled]=\"firstRunInstalling || !firstRunPythonInstalled\" />\n Installa e avvia il server RAG\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.installTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n @if (firstRunPythonInstalled && firstRunPythonSupported) {\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Python {{ firstRunPythonVersion || '3.12' }} rilevato \u2713. Al primo login post-wizard, crea <code>.venv</code>,\n installa torch + transformers + FastAPI, avvia il server su <code>:8765</code>.\n Richiede ~5-10 min + ~200 MB di download (CPU).\n </small>\n } @else if (firstRunPythonInstalled && !firstRunPythonSupported) {\n <div class=\"first-run-python-note\">\n <strong>\u24D8 Python {{ firstRunPythonVersion }} rilevato \u2014 versione non testata</strong>\n <div style=\"margin-top:4px;\">\n WUIC \u00E8 pinnato a <strong>Python 3.12.x</strong> (wheels torch / transformers / LoRA pi\u00F9 stabili).\n Procedere con <code>{{ firstRunPythonVersion }}</code> pu\u00F2 funzionare ma non \u00E8 testato:\n se <code>pip install torch</code> fallisce con \"no matching distribution\", installa\n <a href=\"https://www.python.org/downloads/release/python-3120/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"first-run-python-warning-link\">Python 3.12</a>\n a fianco e metti la sua cartella prima di quella di {{ firstRunPythonVersion }} nel PATH.\n </div>\n </div>\n } @else {\n <div class=\"first-run-python-warning\">\n <strong>\u26A0 Python 3.12 non rilevato sul sistema</strong>\n <div style=\"margin-top:6px;\">\n Il setup RAG richiede Python 3.12. Lo zip di deploy include l'installer embeddable + uno script\n che fa tutto: estrae Python in <code>C:\\Python312</code>, installa pip, aggiorna PATH, riavvia IIS.\n </div>\n <ol style=\"margin:8px 0 4px 20px; padding:0;\">\n <li>\n Vai nella cartella dove hai estratto il deploy zip (dove c'\u00E8 <code>WuicCore.dll</code>).\n </li>\n <li>\n <strong>Right-click su <code>rag-setup.ps1</code> \u2192 \"Esegui come amministratore\"</strong>,\n oppure da pwsh-admin: <code>pwsh -ExecutionPolicy Bypass -File .\\rag-setup.ps1</code>.\n Lo script si auto-eleva via UAC se non gi\u00E0 elevato.\n </li>\n <li>\n Ricarica questa pagina (Ctrl+F5) \u2014 la checkbox si abilita automaticamente.\n </li>\n </ol>\n <div style=\"margin-top:4px; opacity:0.8;\">\n Lo script gestisce anche l'edge case GPO <code>DisableMSI</code> su Windows Server (usa il bundle\n embeddable zip, non MSI). Per il download manuale di Python da python.org:\n <a href=\"https://www.python.org/downloads/release/python-3120/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"first-run-python-warning-link\">\n python.org/downloads/release/python-3120/\n <i class=\"pi pi-external-link\" style=\"font-size:0.75rem; margin-left:3px;\"></i>\n </a>.\n Dettagli in <code>FIRST_STEPS.md</code> accanto al deploy. Il resto del setup (DB, admin user)\n pu\u00F2 procedere senza Python \u2014 installa il RAG dopo.\n </div>\n </div>\n }\n </div>\n\n @if (firstRunForm.installRag) {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.useCuda\"\n (ngModelChange)=\"firstRunForm.useCuda = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n Usa CUDA (GPU NVIDIA)\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.cudaTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Attiva torch GPU (CUDA 12.1, ~2.5 GB download) invece di CPU (~200 MB).\n Richiede una GPU NVIDIA + driver CUDA installati lato sistema.\n </small>\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-anthropic-key\">\n Anthropic API Key (opzionale)\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.apiKeyTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n <textarea id=\"first-run-anthropic-key\" class=\"first-run-input first-run-textarea\"\n [ngModel]=\"firstRunForm.anthropicApiKey\"\n (ngModelChange)=\"firstRunForm.anthropicApiKey = $event\"\n [disabled]=\"firstRunInstalling\"\n rows=\"2\" autocomplete=\"off\"\n placeholder=\"sk-ant-...\"></textarea>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Senza chiave il server RAG funziona solo in modalit\u00E0 retrieval (ricerca snippet).\n Con chiave abilita la chat LLM via Claude.\n </small>\n </div>\n }\n </div>\n </div>\n\n </div><!-- /.first-run-body -->\n\n <!-- FOOTER sticky: error (se presente) + riga progress|CTA sempre visibile. -->\n <div class=\"first-run-footer\">\n @if (firstRunError && !firstRunErrorDismissed) {\n <div class=\"first-run-error\" role=\"alert\">\n <button type=\"button\"\n class=\"first-run-error__close\"\n (click)=\"dismissFirstRunError()\"\n aria-label=\"Chiudi errore\"\n title=\"Chiudi\">\u00D7</button>\n <div class=\"first-run-error__body\">{{ firstRunError }}</div>\n </div>\n }\n\n <div class=\"first-run-footer-row\">\n @if (firstRunInstalling && firstRunProgress.active) {\n <div class=\"first-run-progress\">\n <div class=\"first-run-progress-label\">\n <strong>{{ firstRunProgress.phase }}</strong>\n @if (firstRunProgress.total > 0 && !firstRunProgress.phase.includes('.restore')) {\n <span class=\"first-run-progress-count\">\n \u2014 batch {{ firstRunProgress.current }} / {{ firstRunProgress.total }}\n </span>\n }\n @if (firstRunProgress.elapsedMs > 0) {\n <span class=\"first-run-progress-count\">\n \u00B7 {{ (firstRunProgress.elapsedMs / 1000) | number:'1.0-0' }}s\n </span>\n }\n </div>\n @if (firstRunProgress.phase.includes('.restore') && firstRunProgress.percent < 5) {\n <p-progressBar mode=\"indeterminate\" [style]=\"{'height': '1rem'}\"></p-progressBar>\n } @else {\n <p-progressBar [value]=\"firstRunProgress.percent\" [showValue]=\"true\" [style]=\"{'height': '1rem'}\"></p-progressBar>\n }\n @if (firstRunProgress.message) {\n <div class=\"first-run-progress-message\">{{ firstRunProgress.message }}</div>\n }\n </div>\n } @else {\n <div class=\"first-run-progress-placeholder\"></div>\n }\n\n <div class=\"first-run-actions\">\n <p-button label=\"Conferma e genera metadataDB\" [loading]=\"firstRunInstalling\"\n [disabled]=\"firstRunInstalling || firstRunLoading\" (onClick)=\"submitFirstRunInstall()\"></p-button>\n </div>\n </div>\n </div>\n </div>\n</div>\n}\n", styles: [".first-run-overlay{position:fixed;inset:0;z-index:900;display:flex;align-items:center;justify-content:center;padding:24px;background:linear-gradient(135deg,#081221d9,#16294acc)}.first-run-card-wide{width:min(1180px,100%)!important}.first-run-card{width:min(860px,100%);min-height:min(720px,100vh - 48px);max-height:calc(100vh - 48px);display:flex;flex-direction:column;overflow:hidden;border-radius:14px;padding:22px;background:var(--p-surface-0);box-shadow:0 18px 48px #00000059;border:1px solid var(--p-content-border-color)}.first-run-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:4px;margin-right:-4px}.first-run-footer{flex:0 0 auto;margin-top:12px;padding-top:12px;border-top:1px solid var(--p-content-border-color);display:flex;flex-direction:column;gap:10px}.first-run-footer-row{display:flex;align-items:center;gap:16px}.first-run-title{font-size:1.25rem;font-weight:700}.first-run-subtitle{margin-top:6px;margin-bottom:18px;opacity:.8}.first-run-field{margin-bottom:14px}.first-run-field label{display:block;margin-bottom:6px;font-weight:600}.first-run-checkbox-row label{display:inline-flex;align-items:center;gap:.5rem;margin-bottom:0;font-weight:500}.first-run-input{width:100%;height:40px;border-radius:8px;border:1px solid var(--p-content-border-color);padding:8px 12px;font-size:.95rem;background:var(--p-surface-0);color:var(--p-text-color)}.first-run-textarea{height:auto;min-height:56px;resize:vertical;font-family:var(--p-font-family);line-height:1.4}.first-run-grid{display:grid;grid-template-columns:1fr 1fr;column-gap:28px;row-gap:0}@media(max-width:860px){.first-run-grid{grid-template-columns:1fr}}.first-run-col{display:flex;flex-direction:column;min-width:0}.first-run-section-title{margin-top:4px;margin-bottom:12px;padding-bottom:6px;font-size:.95rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;opacity:.8;border-bottom:1px solid var(--p-content-border-color)}.first-run-section-title-rag{margin-top:18px}.first-run-python-warning{margin-top:8px;padding:10px 12px;background:#fef3c7;border:1px solid #fcd34d;border-radius:6px;color:#78350f;font-size:.85rem;line-height:1.4}.first-run-python-warning strong{color:#78350f}.first-run-python-warning code{background:#00000014;padding:1px 4px;border-radius:3px;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.82rem}.first-run-python-warning ol li+li{margin-top:4px}.first-run-python-warning-link{color:#92400e;text-decoration:underline;font-weight:600}.first-run-python-warning-link:hover{color:#78350f}.first-run-python-warning-link:visited{color:#92400e}.first-run-python-note{margin-top:8px;padding:10px 12px;background:#dbeafe;border:1px solid #93c5fd;border-radius:6px;color:#1e3a8a;font-size:.85rem;line-height:1.4}.first-run-python-note strong{color:#1e3a8a}.first-run-python-note code{background:#00000014;padding:1px 4px;border-radius:3px;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.82rem}.first-run-info-icon{margin-left:6px;font-size:.95rem;color:var(--p-primary-color, #3b82f6);cursor:help;vertical-align:middle;opacity:.85}.first-run-info-icon:hover{opacity:1}::ng-deep .p-tooltip.first-run-tooltip{max-width:440px}::ng-deep .p-tooltip.first-run-tooltip .p-tooltip-text{white-space:pre-line;font-size:.85rem;line-height:1.45}.first-run-input:focus{outline:2px solid rgba(59,130,246,.25);border-color:#3b82f6}.first-run-error{position:relative;margin:8px 0 14px;color:#7f1d1d;background:#fee2e2;border:1px solid #fca5a5;border-radius:8px;padding:10px 36px 10px 12px}.first-run-error__body{max-height:200px;overflow-y:auto;word-break:break-word;white-space:pre-wrap;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.85rem;line-height:1.4}.first-run-error__close{position:absolute;top:6px;right:8px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:transparent;border:0;border-radius:4px;color:inherit;font-size:1.25rem;line-height:1;cursor:pointer;opacity:.75;transition:background-color .12s ease,opacity .12s ease}.first-run-error__close:hover,.first-run-error__close:focus-visible{opacity:1;background:#7f1d1d1f;outline:none}.first-run-error__close:active{background:#7f1d1d33}.first-run-actions{flex:0 0 auto;display:flex;justify-content:flex-end}.first-run-progress{flex:1 1 auto;min-width:0;padding:8px 12px;background:var(--p-surface-50);border:1px solid var(--p-content-border-color);border-radius:8px;display:flex;flex-direction:column;gap:4px}.first-run-progress-placeholder{flex:1 1 auto;min-width:0}.first-run-progress-label{font-size:.9rem}.first-run-progress-label strong{font-weight:600}.first-run-progress-label .first-run-progress-count{opacity:.7;margin-left:4px}.first-run-progress-message{font-size:.8rem;opacity:.75;font-family:ui-monospace,Cascadia Code,Consolas,monospace}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i6.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i11.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "pipe", type: i2$2.DecimalPipe, name: "number" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
1095
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WuicFirstRunWizardComponent, deps: [{ token: i1.HttpClient }, { token: i2.TranslateService }, { token: i3.MessageService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
1096
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WuicFirstRunWizardComponent, isStandalone: true, selector: "wuic-first-run-wizard-impl", outputs: { complete: "complete" }, ngImport: i0, template: "@if (showFirstRunInstall) {\n<div class=\"first-run-overlay\">\n <div class=\"first-run-card first-run-card-wide\">\n <div class=\"first-run-title\">Configurazione iniziale progetto</div>\n <div class=\"first-run-subtitle\">Seleziona DBMS, connessione dati e nome database metadati.</div>\n\n <!-- BODY scrollabile: header (title/subtitle) e footer (progress + CTA)\n restano sempre visibili, solo questo blocco scrolla quando il form\n e' piu' alto della viewport. -->\n <div class=\"first-run-body\">\n\n <!-- Grid 2 colonne: sx = connessione + scaffold / dx = admin + RAG.\n Su viewport stretti (< 720px) il grid collassa a 1 colonna. -->\n <div class=\"first-run-grid\">\n\n <!-- \u2500\u2500 COLONNA SINISTRA: Database + Setup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"first-run-col\">\n\n @if (firstRunSetupModeOptions.length > 1) {\n <div class=\"first-run-field\">\n <label for=\"first-run-mode\">Modalit\u00E0 setup</label>\n <p-select [options]=\"firstRunSetupModeOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.setupMode\" (ngModelChange)=\"onFirstRunSetupModeChanged($event)\"\n [disabled]=\"firstRunInstalling\" [style]=\"{ width: '100%' }\" inputId=\"first-run-mode\"></p-select>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-dbms\">DBMS</label>\n <p-select [options]=\"firstRunDbmsOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.dbms\" (ngModelChange)=\"onFirstRunDbmsChanged($event)\"\n [disabled]=\"firstRunInstalling\" [style]=\"{ width: '100%' }\" inputId=\"first-run-dbms\"></p-select>\n </div>\n\n @if (firstRunForm.setupMode === 'tutorial') {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.createTutorialIfMissing\"\n (ngModelChange)=\"firstRunForm.createTutorialIfMissing = !!$event\" [disabled]=\"firstRunInstalling\" />\n Crea tutorial se manca\n </label>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-datasql\">DataSQLConnection</label>\n <input id=\"first-run-datasql\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.dataConnectionString\" (ngModelChange)=\"onFirstRunConnectionChanged($event)\"\n [disabled]=\"firstRunInstalling\"\n placeholder=\"es. data source=localhost\\sqlexpress;User ID=sa;Password=...;initial catalog=WideWorldImporters\" />\n </div>\n\n <div class=\"first-run-field\">\n <p-button label=\"Test connessione e carica DB\" severity=\"secondary\" [outlined]=\"true\"\n [loading]=\"firstRunConnectionTesting\"\n [disabled]=\"firstRunInstalling || firstRunLoading || !firstRunForm.dataConnectionString\"\n (onClick)=\"testFirstRunConnectionAndLoadDatabases()\"></p-button>\n </div>\n\n @if (firstRunForm.setupMode === 'tutorial') {\n <div class=\"first-run-field\">\n <label for=\"first-run-datadb\">Database dati tutorial</label>\n <input id=\"first-run-datadb\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.tutorialDataDbName\"\n (ngModelChange)=\"firstRunForm.tutorialDataDbName = $event; firstRunForm.dataDbName = $event\"\n [disabled]=\"firstRunInstalling || !firstRunConnectionValid\"\n placeholder=\"WideWorldImporters\" />\n </div>\n } @else {\n <div class=\"first-run-field\">\n <label for=\"first-run-datadb\">Database dati</label>\n <p-select [options]=\"firstRunDataDbOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.dataDbName\" (ngModelChange)=\"firstRunForm.dataDbName = $event\"\n [disabled]=\"firstRunInstalling || firstRunDbLoading || !firstRunConnectionValid\" [filter]=\"true\"\n [editable]=\"true\" [style]=\"{ width: '100%' }\" inputId=\"first-run-datadb\"\n placeholder=\"Seleziona o digita database\"></p-select>\n <div style=\"margin-top: 0.5rem;\">\n <p-button label=\"Aggiorna elenco DB\" severity=\"secondary\" [outlined]=\"true\" size=\"small\"\n [loading]=\"firstRunDbLoading\" [disabled]=\"firstRunInstalling || !firstRunConnectionValid\"\n (onClick)=\"testFirstRunConnectionAndLoadDatabases()\"></p-button>\n </div>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-metadb\">@if (firstRunForm.setupMode === 'tutorial') {Nome DB metadati tutorial} @else {Nome DB metadati}</label>\n <input id=\"first-run-metadb\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.setupMode === 'tutorial' ? firstRunForm.tutorialMetadataDbName : firstRunForm.metadataDbName\"\n (ngModelChange)=\"firstRunForm.metadataDbName = $event; firstRunForm.tutorialMetadataDbName = $event\"\n [disabled]=\"firstRunInstalling\"\n placeholder=\"metadataDB\" />\n </div>\n\n @if (firstRunForm.setupMode !== 'tutorial') {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.scaffoldExistingDatabase\"\n (ngModelChange)=\"firstRunForm.scaffoldExistingDatabase = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n Esegui scaffold automatico delle tabelle del DB selezionato\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Popola <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> al termine dell'installazione.\n Operazione potenzialmente lunga su DB con molte tabelle.\n </small>\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 COLONNA DESTRA: Admin + RAG \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"first-run-col\">\n\n <div class=\"first-run-section-title\">Utente admin iniziale</div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-username\">Username admin iniziale</label>\n <input id=\"first-run-admin-username\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.adminUsername\"\n (ngModelChange)=\"firstRunForm.adminUsername = $event\"\n [disabled]=\"firstRunInstalling\" autocomplete=\"off\"\n placeholder=\"admin\" />\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-password\">Password admin iniziale</label>\n <input id=\"first-run-admin-password\" class=\"first-run-input\" type=\"password\"\n [ngModel]=\"firstRunForm.adminPassword\"\n (ngModelChange)=\"firstRunForm.adminPassword = $event\"\n [disabled]=\"firstRunInstalling\" autocomplete=\"new-password\"\n placeholder=\"(min 4 caratteri)\" />\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-language\">Lingua admin iniziale</label>\n <p-select [options]=\"firstRunAdminLanguageOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.adminLanguage\"\n (ngModelChange)=\"firstRunForm.adminLanguage = $event\"\n [disabled]=\"firstRunInstalling\"\n [style]=\"{ width: '100%' }\" inputId=\"first-run-admin-language\"></p-select>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Lingua applicata all'utente admin dopo il primo login. Puoi cambiarla in seguito dal profilo utente.\n </small>\n </div>\n\n <div class=\"first-run-section-title first-run-section-title-rag\">RAG Chatbot (opzionale)</div>\n\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.installRag\"\n (ngModelChange)=\"firstRunForm.installRag = !!$event\"\n [disabled]=\"firstRunInstalling || !firstRunPythonInstalled\" />\n Installa e avvia il server RAG\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.installTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n @if (firstRunPythonInstalled && firstRunPythonSupported) {\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Python {{ firstRunPythonVersion || '3.12' }} rilevato \u2713. Al primo login post-wizard, crea <code>.venv</code>,\n installa torch + transformers + FastAPI, avvia il server su <code>:8765</code>.\n Richiede ~5-10 min + ~200 MB di download (CPU).\n </small>\n } @else if (firstRunPythonInstalled && !firstRunPythonSupported) {\n <div class=\"first-run-python-note\">\n <strong>\u24D8 Python {{ firstRunPythonVersion }} rilevato \u2014 versione non testata</strong>\n <div style=\"margin-top:4px;\">\n WUIC \u00E8 pinnato a <strong>Python 3.12.x</strong> (wheels torch / transformers / LoRA pi\u00F9 stabili).\n Procedere con <code>{{ firstRunPythonVersion }}</code> pu\u00F2 funzionare ma non \u00E8 testato:\n se <code>pip install torch</code> fallisce con \"no matching distribution\", installa\n <a href=\"https://www.python.org/downloads/release/python-3120/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"first-run-python-warning-link\">Python 3.12</a>\n a fianco e metti la sua cartella prima di quella di {{ firstRunPythonVersion }} nel PATH.\n </div>\n </div>\n } @else {\n <div class=\"first-run-python-warning\">\n <strong>\u26A0 Python 3.12 non rilevato sul sistema</strong>\n <div style=\"margin-top:6px;\">\n Il setup RAG richiede Python 3.12. Lo zip di deploy include l'installer embeddable + uno script\n che fa tutto: estrae Python in <code>C:\\Python312</code>, installa pip, aggiorna PATH, riavvia IIS.\n </div>\n <ol style=\"margin:8px 0 4px 20px; padding:0;\">\n <li>\n Vai nella cartella dove hai estratto il deploy zip (dove c'\u00E8 <code>WuicCore.dll</code>).\n </li>\n <li>\n <strong>Right-click su <code>rag-setup.ps1</code> \u2192 \"Esegui come amministratore\"</strong>,\n oppure da pwsh-admin: <code>pwsh -ExecutionPolicy Bypass -File .\\rag-setup.ps1</code>.\n Lo script si auto-eleva via UAC se non gi\u00E0 elevato.\n </li>\n <li>\n Ricarica questa pagina (Ctrl+F5) \u2014 la checkbox si abilita automaticamente.\n </li>\n </ol>\n <div style=\"margin-top:4px; opacity:0.8;\">\n Lo script gestisce anche l'edge case GPO <code>DisableMSI</code> su Windows Server (usa il bundle\n embeddable zip, non MSI). Per il download manuale di Python da python.org:\n <a href=\"https://www.python.org/downloads/release/python-3120/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"first-run-python-warning-link\">\n python.org/downloads/release/python-3120/\n <i class=\"pi pi-external-link\" style=\"font-size:0.75rem; margin-left:3px;\"></i>\n </a>.\n Dettagli in <code>FIRST_STEPS.md</code> accanto al deploy. Il resto del setup (DB, admin user)\n pu\u00F2 procedere senza Python \u2014 installa il RAG dopo.\n </div>\n </div>\n }\n </div>\n\n @if (firstRunForm.installRag) {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.useCuda\"\n (ngModelChange)=\"firstRunForm.useCuda = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n Usa CUDA (GPU NVIDIA)\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.cudaTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Attiva torch GPU (CUDA 12.1, ~2.5 GB download) invece di CPU (~200 MB).\n Richiede una GPU NVIDIA + driver CUDA installati lato sistema.\n </small>\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-anthropic-key\">\n Anthropic API Key (opzionale)\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.apiKeyTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n <textarea id=\"first-run-anthropic-key\" class=\"first-run-input first-run-textarea\"\n [ngModel]=\"firstRunForm.anthropicApiKey\"\n (ngModelChange)=\"firstRunForm.anthropicApiKey = $event\"\n [disabled]=\"firstRunInstalling\"\n rows=\"2\" autocomplete=\"off\"\n placeholder=\"sk-ant-...\"></textarea>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Senza chiave il server RAG funziona solo in modalit\u00E0 retrieval (ricerca snippet).\n Con chiave abilita la chat LLM via Claude.\n </small>\n </div>\n }\n </div>\n\n <!-- Crash reporting opt-in (skill crash-reporting Commit 8). Default OFF.\n Il consenso GDPR e' inline (testo breve + link). Quando flaggato,\n configure_wuic scrive `CrashReporting.Enabled=true` +\n DisclaimerAcceptedVersion=\"1.0\" in appsettings \u2014 equivalente al\n flusso appsettings-editor (Commit 9). -->\n <div class=\"first-run-section-title first-run-section-title-crash-reporting\">{{ 'crash_reporting.disclaimer.title' | translate }}</div>\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.enableCrashReporting\"\n (ngModelChange)=\"firstRunForm.enableCrashReporting = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n {{ 'crash_reporting.disclaimer.checkbox_accept' | translate }}\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.85; font-size:0.85rem; line-height:1.45;\">\n {{ 'crash_reporting.disclaimer.intro' | translate }}\n </small>\n <small style=\"display:block; margin-top:6px; opacity:0.75; font-size:0.8rem; line-height:1.4;\">\n <strong>{{ 'crash_reporting.disclaimer.what_we_send' | translate }}</strong><br>\n {{ 'crash_reporting.disclaimer.what_we_dont_send' | translate }}<br>\n {{ 'crash_reporting.disclaimer.where_it_goes' | translate }}<br>\n {{ 'crash_reporting.disclaimer.retention' | translate }}<br>\n {{ 'crash_reporting.disclaimer.legal_basis' | translate }}<br>\n {{ 'crash_reporting.disclaimer.how_to_disable' | translate }}\n </small>\n </div>\n </div>\n\n </div><!-- /.first-run-body -->\n\n <!-- FOOTER sticky: error (se presente) + riga progress|CTA sempre visibile. -->\n <div class=\"first-run-footer\">\n @if (firstRunError && !firstRunErrorDismissed) {\n <div class=\"first-run-error\" role=\"alert\">\n <button type=\"button\"\n class=\"first-run-error__close\"\n (click)=\"dismissFirstRunError()\"\n aria-label=\"Chiudi errore\"\n title=\"Chiudi\">\u00D7</button>\n <div class=\"first-run-error__body\">{{ firstRunError }}</div>\n </div>\n }\n\n <div class=\"first-run-footer-row\">\n @if (firstRunInstalling && firstRunProgress.active) {\n <div class=\"first-run-progress\">\n <div class=\"first-run-progress-label\">\n <strong>{{ firstRunProgress.phase }}</strong>\n @if (firstRunProgress.total > 0 && !firstRunProgress.phase.includes('.restore')) {\n <span class=\"first-run-progress-count\">\n \u2014 batch {{ firstRunProgress.current }} / {{ firstRunProgress.total }}\n </span>\n }\n @if (firstRunProgress.elapsedMs > 0) {\n <span class=\"first-run-progress-count\">\n \u00B7 {{ (firstRunProgress.elapsedMs / 1000) | number:'1.0-0' }}s\n </span>\n }\n </div>\n @if (firstRunProgress.phase.includes('.restore') && firstRunProgress.percent < 5) {\n <p-progressBar mode=\"indeterminate\" [style]=\"{'height': '1rem'}\"></p-progressBar>\n } @else {\n <p-progressBar [value]=\"firstRunProgress.percent\" [showValue]=\"true\" [style]=\"{'height': '1rem'}\"></p-progressBar>\n }\n @if (firstRunProgress.message) {\n <div class=\"first-run-progress-message\">{{ firstRunProgress.message }}</div>\n }\n </div>\n } @else {\n <div class=\"first-run-progress-placeholder\"></div>\n }\n\n <div class=\"first-run-actions\">\n <p-button label=\"Conferma e genera metadataDB\" [loading]=\"firstRunInstalling\"\n [disabled]=\"firstRunInstalling || firstRunLoading\" (onClick)=\"submitFirstRunInstall()\"></p-button>\n </div>\n </div>\n </div>\n </div>\n</div>\n}\n", styles: [".first-run-overlay{position:fixed;inset:0;z-index:900;display:flex;align-items:center;justify-content:center;padding:24px;background:linear-gradient(135deg,#081221d9,#16294acc)}.first-run-card-wide{width:min(1180px,100%)!important}.first-run-card{width:min(860px,100%);min-height:min(720px,100vh - 48px);max-height:calc(100vh - 48px);display:flex;flex-direction:column;overflow:hidden;border-radius:14px;padding:22px;background:var(--p-surface-0);box-shadow:0 18px 48px #00000059;border:1px solid var(--p-content-border-color)}.first-run-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:4px;margin-right:-4px}.first-run-footer{flex:0 0 auto;margin-top:12px;padding-top:12px;border-top:1px solid var(--p-content-border-color);display:flex;flex-direction:column;gap:10px}.first-run-footer-row{display:flex;align-items:center;gap:16px}.first-run-title{font-size:1.25rem;font-weight:700}.first-run-subtitle{margin-top:6px;margin-bottom:18px;opacity:.8}.first-run-field{margin-bottom:14px}.first-run-field label{display:block;margin-bottom:6px;font-weight:600}.first-run-checkbox-row label{display:inline-flex;align-items:center;gap:.5rem;margin-bottom:0;font-weight:500}.first-run-input{width:100%;height:40px;border-radius:8px;border:1px solid var(--p-content-border-color);padding:8px 12px;font-size:.95rem;background:var(--p-surface-0);color:var(--p-text-color)}.first-run-textarea{height:auto;min-height:56px;resize:vertical;font-family:var(--p-font-family);line-height:1.4}.first-run-grid{display:grid;grid-template-columns:1fr 1fr;column-gap:28px;row-gap:0}@media(max-width:860px){.first-run-grid{grid-template-columns:1fr}}.first-run-col{display:flex;flex-direction:column;min-width:0}.first-run-section-title{margin-top:4px;margin-bottom:12px;padding-bottom:6px;font-size:.95rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;opacity:.8;border-bottom:1px solid var(--p-content-border-color)}.first-run-section-title-rag{margin-top:18px}.first-run-python-warning{margin-top:8px;padding:10px 12px;background:#fef3c7;border:1px solid #fcd34d;border-radius:6px;color:#78350f;font-size:.85rem;line-height:1.4}.first-run-python-warning strong{color:#78350f}.first-run-python-warning code{background:#00000014;padding:1px 4px;border-radius:3px;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.82rem}.first-run-python-warning ol li+li{margin-top:4px}.first-run-python-warning-link{color:#92400e;text-decoration:underline;font-weight:600}.first-run-python-warning-link:hover{color:#78350f}.first-run-python-warning-link:visited{color:#92400e}.first-run-python-note{margin-top:8px;padding:10px 12px;background:#dbeafe;border:1px solid #93c5fd;border-radius:6px;color:#1e3a8a;font-size:.85rem;line-height:1.4}.first-run-python-note strong{color:#1e3a8a}.first-run-python-note code{background:#00000014;padding:1px 4px;border-radius:3px;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.82rem}.first-run-info-icon{margin-left:6px;font-size:.95rem;color:var(--p-primary-color, #3b82f6);cursor:help;vertical-align:middle;opacity:.85}.first-run-info-icon:hover{opacity:1}::ng-deep .p-tooltip.first-run-tooltip{max-width:440px}::ng-deep .p-tooltip.first-run-tooltip .p-tooltip-text{white-space:pre-line;font-size:.85rem;line-height:1.45}.first-run-input:focus{outline:2px solid rgba(59,130,246,.25);border-color:#3b82f6}.first-run-error{position:relative;margin:8px 0 14px;color:#7f1d1d;background:#fee2e2;border:1px solid #fca5a5;border-radius:8px;padding:10px 36px 10px 12px}.first-run-error__body{max-height:200px;overflow-y:auto;word-break:break-word;white-space:pre-wrap;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.85rem;line-height:1.4}.first-run-error__close{position:absolute;top:6px;right:8px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:transparent;border:0;border-radius:4px;color:inherit;font-size:1.25rem;line-height:1;cursor:pointer;opacity:.75;transition:background-color .12s ease,opacity .12s ease}.first-run-error__close:hover,.first-run-error__close:focus-visible{opacity:1;background:#7f1d1d1f;outline:none}.first-run-error__close:active{background:#7f1d1d33}.first-run-actions{flex:0 0 auto;display:flex;justify-content:flex-end}.first-run-progress{flex:1 1 auto;min-width:0;padding:8px 12px;background:var(--p-surface-50);border:1px solid var(--p-content-border-color);border-radius:8px;display:flex;flex-direction:column;gap:4px}.first-run-progress-placeholder{flex:1 1 auto;min-width:0}.first-run-progress-label{font-size:.9rem}.first-run-progress-label strong{font-weight:600}.first-run-progress-label .first-run-progress-count{opacity:.7;margin-left:4px}.first-run-progress-message{font-size:.8rem;opacity:.75;font-family:ui-monospace,Cascadia Code,Consolas,monospace}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i6.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i11.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "pipe", type: i1$2.DecimalPipe, name: "number" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
1078
1097
  }
1079
1098
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WuicFirstRunWizardComponent, decorators: [{
1080
1099
  type: Component,
@@ -1086,10 +1105,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1086
1105
  SelectModule,
1087
1106
  ProgressBarModule,
1088
1107
  TooltipModule
1089
- ], changeDetection: ChangeDetectionStrategy.Default, template: "@if (showFirstRunInstall) {\n<div class=\"first-run-overlay\">\n <div class=\"first-run-card first-run-card-wide\">\n <div class=\"first-run-title\">Configurazione iniziale progetto</div>\n <div class=\"first-run-subtitle\">Seleziona DBMS, connessione dati e nome database metadati.</div>\n\n <!-- BODY scrollabile: header (title/subtitle) e footer (progress + CTA)\n restano sempre visibili, solo questo blocco scrolla quando il form\n e' piu' alto della viewport. -->\n <div class=\"first-run-body\">\n\n <!-- Grid 2 colonne: sx = connessione + scaffold / dx = admin + RAG.\n Su viewport stretti (< 720px) il grid collassa a 1 colonna. -->\n <div class=\"first-run-grid\">\n\n <!-- \u2500\u2500 COLONNA SINISTRA: Database + Setup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"first-run-col\">\n\n @if (firstRunSetupModeOptions.length > 1) {\n <div class=\"first-run-field\">\n <label for=\"first-run-mode\">Modalit\u00E0 setup</label>\n <p-select [options]=\"firstRunSetupModeOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.setupMode\" (ngModelChange)=\"onFirstRunSetupModeChanged($event)\"\n [disabled]=\"firstRunInstalling\" [style]=\"{ width: '100%' }\" inputId=\"first-run-mode\"></p-select>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-dbms\">DBMS</label>\n <p-select [options]=\"firstRunDbmsOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.dbms\" (ngModelChange)=\"onFirstRunDbmsChanged($event)\"\n [disabled]=\"firstRunInstalling\" [style]=\"{ width: '100%' }\" inputId=\"first-run-dbms\"></p-select>\n </div>\n\n @if (firstRunForm.setupMode === 'tutorial') {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.createTutorialIfMissing\"\n (ngModelChange)=\"firstRunForm.createTutorialIfMissing = !!$event\" [disabled]=\"firstRunInstalling\" />\n Crea tutorial se manca\n </label>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-datasql\">DataSQLConnection</label>\n <input id=\"first-run-datasql\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.dataConnectionString\" (ngModelChange)=\"onFirstRunConnectionChanged($event)\"\n [disabled]=\"firstRunInstalling\"\n placeholder=\"es. data source=localhost\\sqlexpress;User ID=sa;Password=...;initial catalog=WideWorldImporters\" />\n </div>\n\n <div class=\"first-run-field\">\n <p-button label=\"Test connessione e carica DB\" severity=\"secondary\" [outlined]=\"true\"\n [loading]=\"firstRunConnectionTesting\"\n [disabled]=\"firstRunInstalling || firstRunLoading || !firstRunForm.dataConnectionString\"\n (onClick)=\"testFirstRunConnectionAndLoadDatabases()\"></p-button>\n </div>\n\n @if (firstRunForm.setupMode === 'tutorial') {\n <div class=\"first-run-field\">\n <label for=\"first-run-datadb\">Database dati tutorial</label>\n <input id=\"first-run-datadb\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.tutorialDataDbName\"\n (ngModelChange)=\"firstRunForm.tutorialDataDbName = $event; firstRunForm.dataDbName = $event\"\n [disabled]=\"firstRunInstalling || !firstRunConnectionValid\"\n placeholder=\"WideWorldImporters\" />\n </div>\n } @else {\n <div class=\"first-run-field\">\n <label for=\"first-run-datadb\">Database dati</label>\n <p-select [options]=\"firstRunDataDbOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.dataDbName\" (ngModelChange)=\"firstRunForm.dataDbName = $event\"\n [disabled]=\"firstRunInstalling || firstRunDbLoading || !firstRunConnectionValid\" [filter]=\"true\"\n [editable]=\"true\" [style]=\"{ width: '100%' }\" inputId=\"first-run-datadb\"\n placeholder=\"Seleziona o digita database\"></p-select>\n <div style=\"margin-top: 0.5rem;\">\n <p-button label=\"Aggiorna elenco DB\" severity=\"secondary\" [outlined]=\"true\" size=\"small\"\n [loading]=\"firstRunDbLoading\" [disabled]=\"firstRunInstalling || !firstRunConnectionValid\"\n (onClick)=\"testFirstRunConnectionAndLoadDatabases()\"></p-button>\n </div>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-metadb\">@if (firstRunForm.setupMode === 'tutorial') {Nome DB metadati tutorial} @else {Nome DB metadati}</label>\n <input id=\"first-run-metadb\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.setupMode === 'tutorial' ? firstRunForm.tutorialMetadataDbName : firstRunForm.metadataDbName\"\n (ngModelChange)=\"firstRunForm.metadataDbName = $event; firstRunForm.tutorialMetadataDbName = $event\"\n [disabled]=\"firstRunInstalling\"\n placeholder=\"metadataDB\" />\n </div>\n\n @if (firstRunForm.setupMode !== 'tutorial') {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.scaffoldExistingDatabase\"\n (ngModelChange)=\"firstRunForm.scaffoldExistingDatabase = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n Esegui scaffold automatico delle tabelle del DB selezionato\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Popola <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> al termine dell'installazione.\n Operazione potenzialmente lunga su DB con molte tabelle.\n </small>\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 COLONNA DESTRA: Admin + RAG \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"first-run-col\">\n\n <div class=\"first-run-section-title\">Utente admin iniziale</div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-username\">Username admin iniziale</label>\n <input id=\"first-run-admin-username\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.adminUsername\"\n (ngModelChange)=\"firstRunForm.adminUsername = $event\"\n [disabled]=\"firstRunInstalling\" autocomplete=\"off\"\n placeholder=\"admin\" />\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-password\">Password admin iniziale</label>\n <input id=\"first-run-admin-password\" class=\"first-run-input\" type=\"password\"\n [ngModel]=\"firstRunForm.adminPassword\"\n (ngModelChange)=\"firstRunForm.adminPassword = $event\"\n [disabled]=\"firstRunInstalling\" autocomplete=\"new-password\"\n placeholder=\"(min 4 caratteri)\" />\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-language\">Lingua admin iniziale</label>\n <p-select [options]=\"firstRunAdminLanguageOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.adminLanguage\"\n (ngModelChange)=\"firstRunForm.adminLanguage = $event\"\n [disabled]=\"firstRunInstalling\"\n [style]=\"{ width: '100%' }\" inputId=\"first-run-admin-language\"></p-select>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Lingua applicata all'utente admin dopo il primo login. Puoi cambiarla in seguito dal profilo utente.\n </small>\n </div>\n\n <div class=\"first-run-section-title first-run-section-title-rag\">RAG Chatbot (opzionale)</div>\n\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.installRag\"\n (ngModelChange)=\"firstRunForm.installRag = !!$event\"\n [disabled]=\"firstRunInstalling || !firstRunPythonInstalled\" />\n Installa e avvia il server RAG\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.installTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n @if (firstRunPythonInstalled && firstRunPythonSupported) {\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Python {{ firstRunPythonVersion || '3.12' }} rilevato \u2713. Al primo login post-wizard, crea <code>.venv</code>,\n installa torch + transformers + FastAPI, avvia il server su <code>:8765</code>.\n Richiede ~5-10 min + ~200 MB di download (CPU).\n </small>\n } @else if (firstRunPythonInstalled && !firstRunPythonSupported) {\n <div class=\"first-run-python-note\">\n <strong>\u24D8 Python {{ firstRunPythonVersion }} rilevato \u2014 versione non testata</strong>\n <div style=\"margin-top:4px;\">\n WUIC \u00E8 pinnato a <strong>Python 3.12.x</strong> (wheels torch / transformers / LoRA pi\u00F9 stabili).\n Procedere con <code>{{ firstRunPythonVersion }}</code> pu\u00F2 funzionare ma non \u00E8 testato:\n se <code>pip install torch</code> fallisce con \"no matching distribution\", installa\n <a href=\"https://www.python.org/downloads/release/python-3120/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"first-run-python-warning-link\">Python 3.12</a>\n a fianco e metti la sua cartella prima di quella di {{ firstRunPythonVersion }} nel PATH.\n </div>\n </div>\n } @else {\n <div class=\"first-run-python-warning\">\n <strong>\u26A0 Python 3.12 non rilevato sul sistema</strong>\n <div style=\"margin-top:6px;\">\n Il setup RAG richiede Python 3.12. Lo zip di deploy include l'installer embeddable + uno script\n che fa tutto: estrae Python in <code>C:\\Python312</code>, installa pip, aggiorna PATH, riavvia IIS.\n </div>\n <ol style=\"margin:8px 0 4px 20px; padding:0;\">\n <li>\n Vai nella cartella dove hai estratto il deploy zip (dove c'\u00E8 <code>WuicCore.dll</code>).\n </li>\n <li>\n <strong>Right-click su <code>rag-setup.ps1</code> \u2192 \"Esegui come amministratore\"</strong>,\n oppure da pwsh-admin: <code>pwsh -ExecutionPolicy Bypass -File .\\rag-setup.ps1</code>.\n Lo script si auto-eleva via UAC se non gi\u00E0 elevato.\n </li>\n <li>\n Ricarica questa pagina (Ctrl+F5) \u2014 la checkbox si abilita automaticamente.\n </li>\n </ol>\n <div style=\"margin-top:4px; opacity:0.8;\">\n Lo script gestisce anche l'edge case GPO <code>DisableMSI</code> su Windows Server (usa il bundle\n embeddable zip, non MSI). Per il download manuale di Python da python.org:\n <a href=\"https://www.python.org/downloads/release/python-3120/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"first-run-python-warning-link\">\n python.org/downloads/release/python-3120/\n <i class=\"pi pi-external-link\" style=\"font-size:0.75rem; margin-left:3px;\"></i>\n </a>.\n Dettagli in <code>FIRST_STEPS.md</code> accanto al deploy. Il resto del setup (DB, admin user)\n pu\u00F2 procedere senza Python \u2014 installa il RAG dopo.\n </div>\n </div>\n }\n </div>\n\n @if (firstRunForm.installRag) {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.useCuda\"\n (ngModelChange)=\"firstRunForm.useCuda = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n Usa CUDA (GPU NVIDIA)\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.cudaTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Attiva torch GPU (CUDA 12.1, ~2.5 GB download) invece di CPU (~200 MB).\n Richiede una GPU NVIDIA + driver CUDA installati lato sistema.\n </small>\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-anthropic-key\">\n Anthropic API Key (opzionale)\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.apiKeyTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n <textarea id=\"first-run-anthropic-key\" class=\"first-run-input first-run-textarea\"\n [ngModel]=\"firstRunForm.anthropicApiKey\"\n (ngModelChange)=\"firstRunForm.anthropicApiKey = $event\"\n [disabled]=\"firstRunInstalling\"\n rows=\"2\" autocomplete=\"off\"\n placeholder=\"sk-ant-...\"></textarea>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Senza chiave il server RAG funziona solo in modalit\u00E0 retrieval (ricerca snippet).\n Con chiave abilita la chat LLM via Claude.\n </small>\n </div>\n }\n </div>\n </div>\n\n </div><!-- /.first-run-body -->\n\n <!-- FOOTER sticky: error (se presente) + riga progress|CTA sempre visibile. -->\n <div class=\"first-run-footer\">\n @if (firstRunError && !firstRunErrorDismissed) {\n <div class=\"first-run-error\" role=\"alert\">\n <button type=\"button\"\n class=\"first-run-error__close\"\n (click)=\"dismissFirstRunError()\"\n aria-label=\"Chiudi errore\"\n title=\"Chiudi\">\u00D7</button>\n <div class=\"first-run-error__body\">{{ firstRunError }}</div>\n </div>\n }\n\n <div class=\"first-run-footer-row\">\n @if (firstRunInstalling && firstRunProgress.active) {\n <div class=\"first-run-progress\">\n <div class=\"first-run-progress-label\">\n <strong>{{ firstRunProgress.phase }}</strong>\n @if (firstRunProgress.total > 0 && !firstRunProgress.phase.includes('.restore')) {\n <span class=\"first-run-progress-count\">\n \u2014 batch {{ firstRunProgress.current }} / {{ firstRunProgress.total }}\n </span>\n }\n @if (firstRunProgress.elapsedMs > 0) {\n <span class=\"first-run-progress-count\">\n \u00B7 {{ (firstRunProgress.elapsedMs / 1000) | number:'1.0-0' }}s\n </span>\n }\n </div>\n @if (firstRunProgress.phase.includes('.restore') && firstRunProgress.percent < 5) {\n <p-progressBar mode=\"indeterminate\" [style]=\"{'height': '1rem'}\"></p-progressBar>\n } @else {\n <p-progressBar [value]=\"firstRunProgress.percent\" [showValue]=\"true\" [style]=\"{'height': '1rem'}\"></p-progressBar>\n }\n @if (firstRunProgress.message) {\n <div class=\"first-run-progress-message\">{{ firstRunProgress.message }}</div>\n }\n </div>\n } @else {\n <div class=\"first-run-progress-placeholder\"></div>\n }\n\n <div class=\"first-run-actions\">\n <p-button label=\"Conferma e genera metadataDB\" [loading]=\"firstRunInstalling\"\n [disabled]=\"firstRunInstalling || firstRunLoading\" (onClick)=\"submitFirstRunInstall()\"></p-button>\n </div>\n </div>\n </div>\n </div>\n</div>\n}\n", styles: [".first-run-overlay{position:fixed;inset:0;z-index:900;display:flex;align-items:center;justify-content:center;padding:24px;background:linear-gradient(135deg,#081221d9,#16294acc)}.first-run-card-wide{width:min(1180px,100%)!important}.first-run-card{width:min(860px,100%);min-height:min(720px,100vh - 48px);max-height:calc(100vh - 48px);display:flex;flex-direction:column;overflow:hidden;border-radius:14px;padding:22px;background:var(--p-surface-0);box-shadow:0 18px 48px #00000059;border:1px solid var(--p-content-border-color)}.first-run-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:4px;margin-right:-4px}.first-run-footer{flex:0 0 auto;margin-top:12px;padding-top:12px;border-top:1px solid var(--p-content-border-color);display:flex;flex-direction:column;gap:10px}.first-run-footer-row{display:flex;align-items:center;gap:16px}.first-run-title{font-size:1.25rem;font-weight:700}.first-run-subtitle{margin-top:6px;margin-bottom:18px;opacity:.8}.first-run-field{margin-bottom:14px}.first-run-field label{display:block;margin-bottom:6px;font-weight:600}.first-run-checkbox-row label{display:inline-flex;align-items:center;gap:.5rem;margin-bottom:0;font-weight:500}.first-run-input{width:100%;height:40px;border-radius:8px;border:1px solid var(--p-content-border-color);padding:8px 12px;font-size:.95rem;background:var(--p-surface-0);color:var(--p-text-color)}.first-run-textarea{height:auto;min-height:56px;resize:vertical;font-family:var(--p-font-family);line-height:1.4}.first-run-grid{display:grid;grid-template-columns:1fr 1fr;column-gap:28px;row-gap:0}@media(max-width:860px){.first-run-grid{grid-template-columns:1fr}}.first-run-col{display:flex;flex-direction:column;min-width:0}.first-run-section-title{margin-top:4px;margin-bottom:12px;padding-bottom:6px;font-size:.95rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;opacity:.8;border-bottom:1px solid var(--p-content-border-color)}.first-run-section-title-rag{margin-top:18px}.first-run-python-warning{margin-top:8px;padding:10px 12px;background:#fef3c7;border:1px solid #fcd34d;border-radius:6px;color:#78350f;font-size:.85rem;line-height:1.4}.first-run-python-warning strong{color:#78350f}.first-run-python-warning code{background:#00000014;padding:1px 4px;border-radius:3px;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.82rem}.first-run-python-warning ol li+li{margin-top:4px}.first-run-python-warning-link{color:#92400e;text-decoration:underline;font-weight:600}.first-run-python-warning-link:hover{color:#78350f}.first-run-python-warning-link:visited{color:#92400e}.first-run-python-note{margin-top:8px;padding:10px 12px;background:#dbeafe;border:1px solid #93c5fd;border-radius:6px;color:#1e3a8a;font-size:.85rem;line-height:1.4}.first-run-python-note strong{color:#1e3a8a}.first-run-python-note code{background:#00000014;padding:1px 4px;border-radius:3px;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.82rem}.first-run-info-icon{margin-left:6px;font-size:.95rem;color:var(--p-primary-color, #3b82f6);cursor:help;vertical-align:middle;opacity:.85}.first-run-info-icon:hover{opacity:1}::ng-deep .p-tooltip.first-run-tooltip{max-width:440px}::ng-deep .p-tooltip.first-run-tooltip .p-tooltip-text{white-space:pre-line;font-size:.85rem;line-height:1.45}.first-run-input:focus{outline:2px solid rgba(59,130,246,.25);border-color:#3b82f6}.first-run-error{position:relative;margin:8px 0 14px;color:#7f1d1d;background:#fee2e2;border:1px solid #fca5a5;border-radius:8px;padding:10px 36px 10px 12px}.first-run-error__body{max-height:200px;overflow-y:auto;word-break:break-word;white-space:pre-wrap;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.85rem;line-height:1.4}.first-run-error__close{position:absolute;top:6px;right:8px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:transparent;border:0;border-radius:4px;color:inherit;font-size:1.25rem;line-height:1;cursor:pointer;opacity:.75;transition:background-color .12s ease,opacity .12s ease}.first-run-error__close:hover,.first-run-error__close:focus-visible{opacity:1;background:#7f1d1d1f;outline:none}.first-run-error__close:active{background:#7f1d1d33}.first-run-actions{flex:0 0 auto;display:flex;justify-content:flex-end}.first-run-progress{flex:1 1 auto;min-width:0;padding:8px 12px;background:var(--p-surface-50);border:1px solid var(--p-content-border-color);border-radius:8px;display:flex;flex-direction:column;gap:4px}.first-run-progress-placeholder{flex:1 1 auto;min-width:0}.first-run-progress-label{font-size:.9rem}.first-run-progress-label strong{font-weight:600}.first-run-progress-label .first-run-progress-count{opacity:.7;margin-left:4px}.first-run-progress-message{font-size:.8rem;opacity:.75;font-family:ui-monospace,Cascadia Code,Consolas,monospace}\n"] }]
1090
- }], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.TranslateService }, { type: i2$1.MessageService }, { type: i0.Injector }], propDecorators: { complete: [{
1108
+ ], changeDetection: ChangeDetectionStrategy.Default, template: "@if (showFirstRunInstall) {\n<div class=\"first-run-overlay\">\n <div class=\"first-run-card first-run-card-wide\">\n <div class=\"first-run-title\">Configurazione iniziale progetto</div>\n <div class=\"first-run-subtitle\">Seleziona DBMS, connessione dati e nome database metadati.</div>\n\n <!-- BODY scrollabile: header (title/subtitle) e footer (progress + CTA)\n restano sempre visibili, solo questo blocco scrolla quando il form\n e' piu' alto della viewport. -->\n <div class=\"first-run-body\">\n\n <!-- Grid 2 colonne: sx = connessione + scaffold / dx = admin + RAG.\n Su viewport stretti (< 720px) il grid collassa a 1 colonna. -->\n <div class=\"first-run-grid\">\n\n <!-- \u2500\u2500 COLONNA SINISTRA: Database + Setup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"first-run-col\">\n\n @if (firstRunSetupModeOptions.length > 1) {\n <div class=\"first-run-field\">\n <label for=\"first-run-mode\">Modalit\u00E0 setup</label>\n <p-select [options]=\"firstRunSetupModeOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.setupMode\" (ngModelChange)=\"onFirstRunSetupModeChanged($event)\"\n [disabled]=\"firstRunInstalling\" [style]=\"{ width: '100%' }\" inputId=\"first-run-mode\"></p-select>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-dbms\">DBMS</label>\n <p-select [options]=\"firstRunDbmsOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.dbms\" (ngModelChange)=\"onFirstRunDbmsChanged($event)\"\n [disabled]=\"firstRunInstalling\" [style]=\"{ width: '100%' }\" inputId=\"first-run-dbms\"></p-select>\n </div>\n\n @if (firstRunForm.setupMode === 'tutorial') {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.createTutorialIfMissing\"\n (ngModelChange)=\"firstRunForm.createTutorialIfMissing = !!$event\" [disabled]=\"firstRunInstalling\" />\n Crea tutorial se manca\n </label>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-datasql\">DataSQLConnection</label>\n <input id=\"first-run-datasql\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.dataConnectionString\" (ngModelChange)=\"onFirstRunConnectionChanged($event)\"\n [disabled]=\"firstRunInstalling\"\n placeholder=\"es. data source=localhost\\sqlexpress;User ID=sa;Password=...;initial catalog=WideWorldImporters\" />\n </div>\n\n <div class=\"first-run-field\">\n <p-button label=\"Test connessione e carica DB\" severity=\"secondary\" [outlined]=\"true\"\n [loading]=\"firstRunConnectionTesting\"\n [disabled]=\"firstRunInstalling || firstRunLoading || !firstRunForm.dataConnectionString\"\n (onClick)=\"testFirstRunConnectionAndLoadDatabases()\"></p-button>\n </div>\n\n @if (firstRunForm.setupMode === 'tutorial') {\n <div class=\"first-run-field\">\n <label for=\"first-run-datadb\">Database dati tutorial</label>\n <input id=\"first-run-datadb\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.tutorialDataDbName\"\n (ngModelChange)=\"firstRunForm.tutorialDataDbName = $event; firstRunForm.dataDbName = $event\"\n [disabled]=\"firstRunInstalling || !firstRunConnectionValid\"\n placeholder=\"WideWorldImporters\" />\n </div>\n } @else {\n <div class=\"first-run-field\">\n <label for=\"first-run-datadb\">Database dati</label>\n <p-select [options]=\"firstRunDataDbOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.dataDbName\" (ngModelChange)=\"firstRunForm.dataDbName = $event\"\n [disabled]=\"firstRunInstalling || firstRunDbLoading || !firstRunConnectionValid\" [filter]=\"true\"\n [editable]=\"true\" [style]=\"{ width: '100%' }\" inputId=\"first-run-datadb\"\n placeholder=\"Seleziona o digita database\"></p-select>\n <div style=\"margin-top: 0.5rem;\">\n <p-button label=\"Aggiorna elenco DB\" severity=\"secondary\" [outlined]=\"true\" size=\"small\"\n [loading]=\"firstRunDbLoading\" [disabled]=\"firstRunInstalling || !firstRunConnectionValid\"\n (onClick)=\"testFirstRunConnectionAndLoadDatabases()\"></p-button>\n </div>\n </div>\n }\n\n <div class=\"first-run-field\">\n <label for=\"first-run-metadb\">@if (firstRunForm.setupMode === 'tutorial') {Nome DB metadati tutorial} @else {Nome DB metadati}</label>\n <input id=\"first-run-metadb\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.setupMode === 'tutorial' ? firstRunForm.tutorialMetadataDbName : firstRunForm.metadataDbName\"\n (ngModelChange)=\"firstRunForm.metadataDbName = $event; firstRunForm.tutorialMetadataDbName = $event\"\n [disabled]=\"firstRunInstalling\"\n placeholder=\"metadataDB\" />\n </div>\n\n @if (firstRunForm.setupMode !== 'tutorial') {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.scaffoldExistingDatabase\"\n (ngModelChange)=\"firstRunForm.scaffoldExistingDatabase = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n Esegui scaffold automatico delle tabelle del DB selezionato\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Popola <code>_metadati__tabelle</code> / <code>_metadati__colonne</code> al termine dell'installazione.\n Operazione potenzialmente lunga su DB con molte tabelle.\n </small>\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 COLONNA DESTRA: Admin + RAG \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"first-run-col\">\n\n <div class=\"first-run-section-title\">Utente admin iniziale</div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-username\">Username admin iniziale</label>\n <input id=\"first-run-admin-username\" class=\"first-run-input\" type=\"text\"\n [ngModel]=\"firstRunForm.adminUsername\"\n (ngModelChange)=\"firstRunForm.adminUsername = $event\"\n [disabled]=\"firstRunInstalling\" autocomplete=\"off\"\n placeholder=\"admin\" />\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-password\">Password admin iniziale</label>\n <input id=\"first-run-admin-password\" class=\"first-run-input\" type=\"password\"\n [ngModel]=\"firstRunForm.adminPassword\"\n (ngModelChange)=\"firstRunForm.adminPassword = $event\"\n [disabled]=\"firstRunInstalling\" autocomplete=\"new-password\"\n placeholder=\"(min 4 caratteri)\" />\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-admin-language\">Lingua admin iniziale</label>\n <p-select [options]=\"firstRunAdminLanguageOptions\" optionLabel=\"label\" optionValue=\"value\"\n [ngModel]=\"firstRunForm.adminLanguage\"\n (ngModelChange)=\"firstRunForm.adminLanguage = $event\"\n [disabled]=\"firstRunInstalling\"\n [style]=\"{ width: '100%' }\" inputId=\"first-run-admin-language\"></p-select>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Lingua applicata all'utente admin dopo il primo login. Puoi cambiarla in seguito dal profilo utente.\n </small>\n </div>\n\n <div class=\"first-run-section-title first-run-section-title-rag\">RAG Chatbot (opzionale)</div>\n\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.installRag\"\n (ngModelChange)=\"firstRunForm.installRag = !!$event\"\n [disabled]=\"firstRunInstalling || !firstRunPythonInstalled\" />\n Installa e avvia il server RAG\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.installTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n @if (firstRunPythonInstalled && firstRunPythonSupported) {\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Python {{ firstRunPythonVersion || '3.12' }} rilevato \u2713. Al primo login post-wizard, crea <code>.venv</code>,\n installa torch + transformers + FastAPI, avvia il server su <code>:8765</code>.\n Richiede ~5-10 min + ~200 MB di download (CPU).\n </small>\n } @else if (firstRunPythonInstalled && !firstRunPythonSupported) {\n <div class=\"first-run-python-note\">\n <strong>\u24D8 Python {{ firstRunPythonVersion }} rilevato \u2014 versione non testata</strong>\n <div style=\"margin-top:4px;\">\n WUIC \u00E8 pinnato a <strong>Python 3.12.x</strong> (wheels torch / transformers / LoRA pi\u00F9 stabili).\n Procedere con <code>{{ firstRunPythonVersion }}</code> pu\u00F2 funzionare ma non \u00E8 testato:\n se <code>pip install torch</code> fallisce con \"no matching distribution\", installa\n <a href=\"https://www.python.org/downloads/release/python-3120/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"first-run-python-warning-link\">Python 3.12</a>\n a fianco e metti la sua cartella prima di quella di {{ firstRunPythonVersion }} nel PATH.\n </div>\n </div>\n } @else {\n <div class=\"first-run-python-warning\">\n <strong>\u26A0 Python 3.12 non rilevato sul sistema</strong>\n <div style=\"margin-top:6px;\">\n Il setup RAG richiede Python 3.12. Lo zip di deploy include l'installer embeddable + uno script\n che fa tutto: estrae Python in <code>C:\\Python312</code>, installa pip, aggiorna PATH, riavvia IIS.\n </div>\n <ol style=\"margin:8px 0 4px 20px; padding:0;\">\n <li>\n Vai nella cartella dove hai estratto il deploy zip (dove c'\u00E8 <code>WuicCore.dll</code>).\n </li>\n <li>\n <strong>Right-click su <code>rag-setup.ps1</code> \u2192 \"Esegui come amministratore\"</strong>,\n oppure da pwsh-admin: <code>pwsh -ExecutionPolicy Bypass -File .\\rag-setup.ps1</code>.\n Lo script si auto-eleva via UAC se non gi\u00E0 elevato.\n </li>\n <li>\n Ricarica questa pagina (Ctrl+F5) \u2014 la checkbox si abilita automaticamente.\n </li>\n </ol>\n <div style=\"margin-top:4px; opacity:0.8;\">\n Lo script gestisce anche l'edge case GPO <code>DisableMSI</code> su Windows Server (usa il bundle\n embeddable zip, non MSI). Per il download manuale di Python da python.org:\n <a href=\"https://www.python.org/downloads/release/python-3120/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"first-run-python-warning-link\">\n python.org/downloads/release/python-3120/\n <i class=\"pi pi-external-link\" style=\"font-size:0.75rem; margin-left:3px;\"></i>\n </a>.\n Dettagli in <code>FIRST_STEPS.md</code> accanto al deploy. Il resto del setup (DB, admin user)\n pu\u00F2 procedere senza Python \u2014 installa il RAG dopo.\n </div>\n </div>\n }\n </div>\n\n @if (firstRunForm.installRag) {\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.useCuda\"\n (ngModelChange)=\"firstRunForm.useCuda = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n Usa CUDA (GPU NVIDIA)\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.cudaTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Attiva torch GPU (CUDA 12.1, ~2.5 GB download) invece di CPU (~200 MB).\n Richiede una GPU NVIDIA + driver CUDA installati lato sistema.\n </small>\n </div>\n\n <div class=\"first-run-field\">\n <label for=\"first-run-anthropic-key\">\n Anthropic API Key (opzionale)\n <i class=\"pi pi-info-circle first-run-info-icon\"\n [pTooltip]=\"'firstrun.rag.apiKeyTooltip' | translate\"\n tooltipPosition=\"right\"\n [tooltipStyleClass]=\"'first-run-tooltip'\"\n [escape]=\"false\"></i>\n </label>\n <textarea id=\"first-run-anthropic-key\" class=\"first-run-input first-run-textarea\"\n [ngModel]=\"firstRunForm.anthropicApiKey\"\n (ngModelChange)=\"firstRunForm.anthropicApiKey = $event\"\n [disabled]=\"firstRunInstalling\"\n rows=\"2\" autocomplete=\"off\"\n placeholder=\"sk-ant-...\"></textarea>\n <small style=\"display:block; margin-top:4px; opacity:0.75; font-size:0.8rem; line-height:1.35;\">\n Senza chiave il server RAG funziona solo in modalit\u00E0 retrieval (ricerca snippet).\n Con chiave abilita la chat LLM via Claude.\n </small>\n </div>\n }\n </div>\n\n <!-- Crash reporting opt-in (skill crash-reporting Commit 8). Default OFF.\n Il consenso GDPR e' inline (testo breve + link). Quando flaggato,\n configure_wuic scrive `CrashReporting.Enabled=true` +\n DisclaimerAcceptedVersion=\"1.0\" in appsettings \u2014 equivalente al\n flusso appsettings-editor (Commit 9). -->\n <div class=\"first-run-section-title first-run-section-title-crash-reporting\">{{ 'crash_reporting.disclaimer.title' | translate }}</div>\n <div class=\"first-run-field first-run-checkbox-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"firstRunForm.enableCrashReporting\"\n (ngModelChange)=\"firstRunForm.enableCrashReporting = !!$event\"\n [disabled]=\"firstRunInstalling\" />\n {{ 'crash_reporting.disclaimer.checkbox_accept' | translate }}\n </label>\n <small style=\"display:block; margin-top:4px; opacity:0.85; font-size:0.85rem; line-height:1.45;\">\n {{ 'crash_reporting.disclaimer.intro' | translate }}\n </small>\n <small style=\"display:block; margin-top:6px; opacity:0.75; font-size:0.8rem; line-height:1.4;\">\n <strong>{{ 'crash_reporting.disclaimer.what_we_send' | translate }}</strong><br>\n {{ 'crash_reporting.disclaimer.what_we_dont_send' | translate }}<br>\n {{ 'crash_reporting.disclaimer.where_it_goes' | translate }}<br>\n {{ 'crash_reporting.disclaimer.retention' | translate }}<br>\n {{ 'crash_reporting.disclaimer.legal_basis' | translate }}<br>\n {{ 'crash_reporting.disclaimer.how_to_disable' | translate }}\n </small>\n </div>\n </div>\n\n </div><!-- /.first-run-body -->\n\n <!-- FOOTER sticky: error (se presente) + riga progress|CTA sempre visibile. -->\n <div class=\"first-run-footer\">\n @if (firstRunError && !firstRunErrorDismissed) {\n <div class=\"first-run-error\" role=\"alert\">\n <button type=\"button\"\n class=\"first-run-error__close\"\n (click)=\"dismissFirstRunError()\"\n aria-label=\"Chiudi errore\"\n title=\"Chiudi\">\u00D7</button>\n <div class=\"first-run-error__body\">{{ firstRunError }}</div>\n </div>\n }\n\n <div class=\"first-run-footer-row\">\n @if (firstRunInstalling && firstRunProgress.active) {\n <div class=\"first-run-progress\">\n <div class=\"first-run-progress-label\">\n <strong>{{ firstRunProgress.phase }}</strong>\n @if (firstRunProgress.total > 0 && !firstRunProgress.phase.includes('.restore')) {\n <span class=\"first-run-progress-count\">\n \u2014 batch {{ firstRunProgress.current }} / {{ firstRunProgress.total }}\n </span>\n }\n @if (firstRunProgress.elapsedMs > 0) {\n <span class=\"first-run-progress-count\">\n \u00B7 {{ (firstRunProgress.elapsedMs / 1000) | number:'1.0-0' }}s\n </span>\n }\n </div>\n @if (firstRunProgress.phase.includes('.restore') && firstRunProgress.percent < 5) {\n <p-progressBar mode=\"indeterminate\" [style]=\"{'height': '1rem'}\"></p-progressBar>\n } @else {\n <p-progressBar [value]=\"firstRunProgress.percent\" [showValue]=\"true\" [style]=\"{'height': '1rem'}\"></p-progressBar>\n }\n @if (firstRunProgress.message) {\n <div class=\"first-run-progress-message\">{{ firstRunProgress.message }}</div>\n }\n </div>\n } @else {\n <div class=\"first-run-progress-placeholder\"></div>\n }\n\n <div class=\"first-run-actions\">\n <p-button label=\"Conferma e genera metadataDB\" [loading]=\"firstRunInstalling\"\n [disabled]=\"firstRunInstalling || firstRunLoading\" (onClick)=\"submitFirstRunInstall()\"></p-button>\n </div>\n </div>\n </div>\n </div>\n</div>\n}\n", styles: [".first-run-overlay{position:fixed;inset:0;z-index:900;display:flex;align-items:center;justify-content:center;padding:24px;background:linear-gradient(135deg,#081221d9,#16294acc)}.first-run-card-wide{width:min(1180px,100%)!important}.first-run-card{width:min(860px,100%);min-height:min(720px,100vh - 48px);max-height:calc(100vh - 48px);display:flex;flex-direction:column;overflow:hidden;border-radius:14px;padding:22px;background:var(--p-surface-0);box-shadow:0 18px 48px #00000059;border:1px solid var(--p-content-border-color)}.first-run-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:4px;margin-right:-4px}.first-run-footer{flex:0 0 auto;margin-top:12px;padding-top:12px;border-top:1px solid var(--p-content-border-color);display:flex;flex-direction:column;gap:10px}.first-run-footer-row{display:flex;align-items:center;gap:16px}.first-run-title{font-size:1.25rem;font-weight:700}.first-run-subtitle{margin-top:6px;margin-bottom:18px;opacity:.8}.first-run-field{margin-bottom:14px}.first-run-field label{display:block;margin-bottom:6px;font-weight:600}.first-run-checkbox-row label{display:inline-flex;align-items:center;gap:.5rem;margin-bottom:0;font-weight:500}.first-run-input{width:100%;height:40px;border-radius:8px;border:1px solid var(--p-content-border-color);padding:8px 12px;font-size:.95rem;background:var(--p-surface-0);color:var(--p-text-color)}.first-run-textarea{height:auto;min-height:56px;resize:vertical;font-family:var(--p-font-family);line-height:1.4}.first-run-grid{display:grid;grid-template-columns:1fr 1fr;column-gap:28px;row-gap:0}@media(max-width:860px){.first-run-grid{grid-template-columns:1fr}}.first-run-col{display:flex;flex-direction:column;min-width:0}.first-run-section-title{margin-top:4px;margin-bottom:12px;padding-bottom:6px;font-size:.95rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;opacity:.8;border-bottom:1px solid var(--p-content-border-color)}.first-run-section-title-rag{margin-top:18px}.first-run-python-warning{margin-top:8px;padding:10px 12px;background:#fef3c7;border:1px solid #fcd34d;border-radius:6px;color:#78350f;font-size:.85rem;line-height:1.4}.first-run-python-warning strong{color:#78350f}.first-run-python-warning code{background:#00000014;padding:1px 4px;border-radius:3px;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.82rem}.first-run-python-warning ol li+li{margin-top:4px}.first-run-python-warning-link{color:#92400e;text-decoration:underline;font-weight:600}.first-run-python-warning-link:hover{color:#78350f}.first-run-python-warning-link:visited{color:#92400e}.first-run-python-note{margin-top:8px;padding:10px 12px;background:#dbeafe;border:1px solid #93c5fd;border-radius:6px;color:#1e3a8a;font-size:.85rem;line-height:1.4}.first-run-python-note strong{color:#1e3a8a}.first-run-python-note code{background:#00000014;padding:1px 4px;border-radius:3px;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.82rem}.first-run-info-icon{margin-left:6px;font-size:.95rem;color:var(--p-primary-color, #3b82f6);cursor:help;vertical-align:middle;opacity:.85}.first-run-info-icon:hover{opacity:1}::ng-deep .p-tooltip.first-run-tooltip{max-width:440px}::ng-deep .p-tooltip.first-run-tooltip .p-tooltip-text{white-space:pre-line;font-size:.85rem;line-height:1.45}.first-run-input:focus{outline:2px solid rgba(59,130,246,.25);border-color:#3b82f6}.first-run-error{position:relative;margin:8px 0 14px;color:#7f1d1d;background:#fee2e2;border:1px solid #fca5a5;border-radius:8px;padding:10px 36px 10px 12px}.first-run-error__body{max-height:200px;overflow-y:auto;word-break:break-word;white-space:pre-wrap;font-family:ui-monospace,Cascadia Code,Consolas,monospace;font-size:.85rem;line-height:1.4}.first-run-error__close{position:absolute;top:6px;right:8px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:transparent;border:0;border-radius:4px;color:inherit;font-size:1.25rem;line-height:1;cursor:pointer;opacity:.75;transition:background-color .12s ease,opacity .12s ease}.first-run-error__close:hover,.first-run-error__close:focus-visible{opacity:1;background:#7f1d1d1f;outline:none}.first-run-error__close:active{background:#7f1d1d33}.first-run-actions{flex:0 0 auto;display:flex;justify-content:flex-end}.first-run-progress{flex:1 1 auto;min-width:0;padding:8px 12px;background:var(--p-surface-50);border:1px solid var(--p-content-border-color);border-radius:8px;display:flex;flex-direction:column;gap:4px}.first-run-progress-placeholder{flex:1 1 auto;min-width:0}.first-run-progress-label{font-size:.9rem}.first-run-progress-label strong{font-weight:600}.first-run-progress-label .first-run-progress-count{opacity:.7;margin-left:4px}.first-run-progress-message{font-size:.8rem;opacity:.75;font-family:ui-monospace,Cascadia Code,Consolas,monospace}\n"] }]
1109
+ }], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.TranslateService }, { type: i3.MessageService }, { type: i0.Injector }], propDecorators: { complete: [{
1091
1110
  type: Output
1092
1111
  }] } });
1093
1112
 
1094
1113
  export { WuicFirstRunWizardComponent };
1095
- //# sourceMappingURL=wuic-framework-lib-first-run-wizard.component-CQTs6hR6.mjs.map
1114
+ //# sourceMappingURL=wuic-framework-lib-first-run-wizard.component-DoVifTlj.mjs.map