wuic-framework-lib 0.1.0 → 0.3.1

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.
@@ -3,7 +3,7 @@ import { ErrorHandler, Injector, OnInit, OnDestroy, AfterViewInit, EventEmitter,
3
3
  import * as rxjs from 'rxjs';
4
4
  import { BehaviorSubject, Subject, Observable, Subscription } from 'rxjs';
5
5
  import { MenuItem, MessageService, ConfirmationService, Confirmation, TreeNode, MegaMenuItem } from 'primeng/api';
6
- import { HttpClient } from '@angular/common/http';
6
+ import { HttpClient, HttpInterceptorFn } from '@angular/common/http';
7
7
  import { Router, ActivatedRoute, CanDeactivateFn, CanActivateFn, CanMatchFn, Routes } from '@angular/router';
8
8
  import { CookieService } from 'ngx-cookie-service';
9
9
  import { TranslateService } from '@ngx-translate/core';
@@ -27,10 +27,10 @@ import { Select } from 'primeng/select';
27
27
  import { PrimeNG } from 'primeng/config';
28
28
  import { MonacoEditorComponent, MonacoEditorLoaderService } from '@materia-ui/ngx-monaco-editor';
29
29
  import { Popover } from 'primeng/popover';
30
+ import * as wuic_framework_lib from 'wuic-framework-lib';
30
31
  import { StimulsoftDesignerComponent } from 'stimulsoft-designer-angular';
31
32
  import { StimulsoftViewerComponent } from 'stimulsoft-viewer-angular';
32
33
  import { CdkDragDrop } from '@angular/cdk/drag-drop';
33
- import * as wuic_framework_lib from 'wuic-framework-lib';
34
34
 
35
35
  declare class CustomException {
36
36
  title: string;
@@ -113,6 +113,8 @@ declare class FilterItem {
113
113
  __extra?: boolean;
114
114
  __descriptorManaged?: boolean;
115
115
  __querystring?: boolean;
116
+ __routefilter?: boolean;
117
+ __nestedroute?: boolean;
116
118
  nestedFilters?: FilterInfo;
117
119
  operator?: string;
118
120
  constructor(params: {
@@ -122,6 +124,8 @@ declare class FilterItem {
122
124
  fixed?: boolean;
123
125
  __extra?: boolean;
124
126
  __descriptorManaged?: boolean;
127
+ __routefilter?: boolean;
128
+ __nestedroute?: boolean;
125
129
  });
126
130
  }
127
131
 
@@ -172,12 +176,26 @@ declare class UserInfoService {
172
176
  private cookieService;
173
177
  constructor(cookieService: CookieService);
174
178
  /**
175
- * Valuta una condizione booleana sullo stato o sull'input corrente.
176
- * @returns Valore restituito dal metodo (boolean).
179
+ * Reads the user-info snapshot from sessionStorage. Returns `null` when
180
+ * absent or malformed. Used as the primary cache — the `k-user` cookie
181
+ * may be HttpOnly (server-managed mode) and is therefore not readable
182
+ * from JS.
183
+ */
184
+ private readFromStorage;
185
+ private writeToStorage;
186
+ private removeFromStorage;
187
+ /**
188
+ * Returns `true` when the UI has a cached user snapshot. Checks
189
+ * sessionStorage FIRST (works in both legacy and server-managed cookie
190
+ * modes) and falls back to the readable cookie (legacy-only path).
177
191
  */
178
192
  hasStoredUserInfo(): boolean;
179
193
  /**
180
- * Pulisce lo stato runtime e le cache associate.
194
+ * Clears UI-side user state. Removes the sessionStorage snapshot and the
195
+ * JS-readable cookie. NOTE: when the backend runs in server-managed mode
196
+ * the HttpOnly `k-user` cookie cannot be deleted from JavaScript — the
197
+ * server-side logout endpoint (`MetaService.logoutSession`) must be
198
+ * invoked to emit a proper `Set-Cookie` delete header.
181
199
  */
182
200
  clearUserInfo(): void;
183
201
  /**
@@ -199,7 +217,22 @@ declare class UserInfoService {
199
217
  }[];
200
218
  } | null): boolean;
201
219
  /**
202
- * Normalizza un payload utente eterogeneo e lo salva nel cookie `k-user` usato dal framework legacy.
220
+ * Normalizza un payload utente eterogeneo e lo salva come snapshot UI.
221
+ *
222
+ * Cambio di semantica vs la versione pre-cookie-auth-hardening:
223
+ * - PRIMA scriveva solo nel cookie `k-user` via `CookieService.set`;
224
+ * - ORA scrive PRIMA in sessionStorage (source of truth per la UI,
225
+ * leggibile anche quando il cookie e' HttpOnly), POI prova a
226
+ * scrivere anche il cookie — se il cookie HttpOnly esiste gia'
227
+ * (server-managed mode), la scrittura JS viene silenziosamente
228
+ * droppata dal browser senza errori, e non ci interessa: il cookie
229
+ * di autenticazione e' gia' quello settato dal backend via
230
+ * Set-Cookie.
231
+ *
232
+ * In legacy mode questa logica e' trasparente: la scrittura JS del
233
+ * cookie funziona ancora, il cookie e' l'autenticazione, sessionStorage
234
+ * e' solo un mirror per velocita'.
235
+ *
203
236
  * @param userLike Oggetto utente in formato libero (server/legacy/client).
204
237
  */
205
238
  setUserInfoCookie(userLike: any): void;
@@ -213,9 +246,12 @@ declare class UserInfoService {
213
246
  */
214
247
  getuserInfo(): UserInfo;
215
248
  /**
216
- * Legge e deserializza il cookie `k-user` restituendo il profilo utente persistito dal login legacy.
217
- * @returns Profilo utente oppure `null` se cookie assente/non valido.
218
- */
249
+ * Read path: prefer sessionStorage (source of truth, works in both cookie
250
+ * modes) and fall back to the JS-readable cookie when sessionStorage is
251
+ * empty. In server-managed mode the cookie is HttpOnly and this fallback
252
+ * always returns `null`, so the caller must hydrate via
253
+ * `MetaService.me` at boot (see `AuthSessionService.refreshAll`).
254
+ */
219
255
  getStoredUserInfo(): UserInfo | null;
220
256
  setUserLanguage(languageId: string): UserInfo | null;
221
257
  static ɵfac: i0.ɵɵFactoryDeclaration<UserInfoService, never>;
@@ -1624,6 +1660,15 @@ declare class MetadatiTabella {
1624
1660
  ProjectMetadataVersion: number;
1625
1661
  md_id: number;
1626
1662
  md_nome_tabella: string;
1663
+ /**
1664
+ * True quando la route metadata punta a una stored procedure invece di
1665
+ * una tabella/vista. In questo caso il datasource fetcher dispatcha la
1666
+ * read verso `MetaService.getFlatDataFromStored` invece di
1667
+ * `MetaService.getFlatRecordData`, e i `parameterInfo` (derivati da
1668
+ * `md_props_bag.parameters`) vengono inviati come `filterElement[]`
1669
+ * con i placeholder `{{currentUser.*}}` interpolati lato client.
1670
+ */
1671
+ md_is_stored: boolean;
1627
1672
  md_editable: boolean;
1628
1673
  md_deletable: boolean;
1629
1674
  md_insertable: boolean;
@@ -2317,6 +2362,17 @@ declare class MetadataProviderService {
2317
2362
  castDate?: boolean;
2318
2363
  groupBy?: string;
2319
2364
  }>): Promise<any>;
2365
+ /**
2366
+ * Creates a DB VIEW from a multi-table view definition built by the
2367
+ * View Builder canvas. Scaffolds the view as a new route so the
2368
+ * existing pivot builder can operate on it.
2369
+ */
2370
+ createViewFromDefinition(viewDefinition: any, viewName?: string, targetSchema?: string, createMenu?: boolean, parentMenuId?: number, overwriteIfExists?: boolean, scaffold?: boolean, manualSql?: string): Promise<any>;
2371
+ /**
2372
+ * Executes a SELECT query from a ViewDefinition without creating a DB view.
2373
+ * Returns { ok, sql, columns, rows }.
2374
+ */
2375
+ previewViewDefinition(viewDefinition: any, maxRows?: number, generateOnly?: boolean, filterInfo?: any, manualSql?: string): Promise<any>;
2320
2376
  createPivotView(route: string, rowColumns: string[], columnColumns: string[], valueColumns: string[] | string, aggregateFunction?: string, valueDefinitions?: Array<{
2321
2377
  alias: string;
2322
2378
  aggregateFunction?: string;
@@ -2366,6 +2422,10 @@ declare class MetadataProviderService {
2366
2422
  * @returns Payload backend normalizzato.
2367
2423
  */
2368
2424
  listPivotConfigurations(route?: string | null): Promise<any>;
2425
+ getViewBuilderForeignKeys(): Promise<{
2426
+ source: string;
2427
+ target: string;
2428
+ }[]>;
2369
2429
  private tryParseJsonPayload;
2370
2430
  /**
2371
2431
  * Esegue il bootstrap dei custom settings in localStorage subito dopo login/session bootstrap.
@@ -2496,10 +2556,43 @@ declare class DataProviderOdataService {
2496
2556
  declare class DataProviderMetaService {
2497
2557
  private _http;
2498
2558
  http: HttpClient;
2559
+ private userInfoService;
2499
2560
  /**
2500
2561
  * Inizializza il provider dati metadata con l'istanza `HttpClient` usata da tutti gli endpoint `MetaService.*`.
2501
2562
  */
2502
2563
  constructor(_http: HttpClient);
2564
+ /**
2565
+ * Risolve i placeholder di tipo `{{path.to.value}}` su un oggetto sorgente.
2566
+ * Supporta path annidati con dot-notation. Esempi:
2567
+ * - `{{currentUser.lingua.id}}` -> `userInfo.lingua.id`
2568
+ * - `{{currentUser.user_id}}` -> `userInfo.user_id`
2569
+ * Se il valore non e una stringa o non contiene placeholder, viene
2570
+ * ritornato invariato. Se la risoluzione fallisce, il placeholder viene
2571
+ * lasciato vuoto (stringa vuota) per evitare di propagare il template
2572
+ * letterale al backend.
2573
+ *
2574
+ * Usato per interpolare i `parameters[].value` di una SP route prima di
2575
+ * inviarli a `MetaService.getFlatDataFromStored`.
2576
+ */
2577
+ private interpolateUserPlaceholders;
2578
+ /**
2579
+ * Costruisce la lista `filterElement[]` per un fetch SP-route a partire
2580
+ * dai `parameterInfo` (derivati da `md_props_bag.parameters`) gia
2581
+ * popolati in `tableMetadata.parameterInfo` da `MetadataProviderService.prepareMetadatas`.
2582
+ *
2583
+ * Per ogni parameter declarato:
2584
+ * 1. legge il `value` dal raw `md_props_bag.parameters[i].value` (gli
2585
+ * `extraProps.parameters` raw sono accessibili via
2586
+ * `tableMetadata.extraProps.parameters`),
2587
+ * 2. interpola i placeholder `{{currentUser.*}}`,
2588
+ * 3. emette un `filterElement` con `field=Name`, `value=interpolated`,
2589
+ * `Type`, `isOut`.
2590
+ *
2591
+ * Il backend `GetFlatDataFromStored` matcha il `field` (case-insensitive,
2592
+ * con/senza `@` prefix) col parameter Name in `mdpropsbag.parameters` e
2593
+ * lo bind via Dapper DynamicParameters.
2594
+ */
2595
+ private buildStoredParametersPayload;
2503
2596
  /**
2504
2597
  * Pulisce la cache localStorage preservando le traduzioni gia caricate.
2505
2598
  * Evita regressioni UX dove, dopo save metadata non-translation, le label tornano alle chiavi raw.
@@ -4031,6 +4124,7 @@ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDa
4031
4124
  private trslSrv;
4032
4125
  private cd;
4033
4126
  userInfo: UserInfoService;
4127
+ private elementRef;
4034
4128
  private static readonly FORCED_VIRTUALIZATION_PAGE_SIZE_THRESHOLD;
4035
4129
  private static readonly FORCED_VIRTUALIZATION_ITEM_SIZE;
4036
4130
  private static readonly ACTION_BUTTON_VISIBLE_ROWS_OVERSCAN;
@@ -4097,6 +4191,9 @@ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDa
4097
4191
  columnCtxMenu: ContextMenu;
4098
4192
  metadataColumnsDatasource: DataSourceComponent;
4099
4193
  gridContainerRef?: ElementRef<HTMLElement>;
4194
+ /** ResizeObserver per esporre --wuic-outer-thead-h alle nested grid figlie. */
4195
+ private outerTheadResizeObserver?;
4196
+ private outerTheadObserveRetryTimer?;
4100
4197
  records: any[];
4101
4198
  cols: any[];
4102
4199
  metas: MetadatiColonna[];
@@ -4205,7 +4302,7 @@ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDa
4205
4302
  * @param cd Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
4206
4303
  * @param userInfo Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
4207
4304
  */
4208
- constructor(metaSrv: MetadataProviderService, sanitizer: DomSanitizer, route: ActivatedRoute, router: Router, location: Location, titleService: Title, trslSrv: TranslationManagerService, cd: ChangeDetectorRef, userInfo: UserInfoService);
4305
+ constructor(metaSrv: MetadataProviderService, sanitizer: DomSanitizer, route: ActivatedRoute, router: Router, location: Location, titleService: Title, trslSrv: TranslationManagerService, cd: ChangeDetectorRef, userInfo: UserInfoService, elementRef: ElementRef<HTMLElement>);
4209
4306
  /**
4210
4307
  * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
4211
4308
  */
@@ -4218,6 +4315,15 @@ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDa
4218
4315
  * Completa inizializzazione dopo il rendering della view e collega riferimenti UI.
4219
4316
  */
4220
4317
  ngAfterViewInit(): void;
4318
+ /**
4319
+ * Espone l'altezza del thead OUTER (top-level grid) come CSS var `--wuic-outer-thead-h`
4320
+ * sull'host element, per permettere a `position: sticky; top: var(...)` sull'inner thead
4321
+ * di lasciare spazio sotto l'header outer (anch'esso sticky a top:0).
4322
+ *
4323
+ * Si attiva SOLO sulla grid root (non nested): le inner ListGridComponent leggono la var
4324
+ * via cascade CSS dall'ancestor `wuic-list-grid` piu vicino, che corrisponde all'outer.
4325
+ */
4326
+ private observeOuterTheadHeight;
4221
4327
  /**
4222
4328
  * Ricalcola l'altezza disponibile della grid al resize finestra.
4223
4329
  */
@@ -4245,6 +4351,7 @@ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDa
4245
4351
  * Restituisce le classi della p-table includendo il profilo inline-cell-editing.
4246
4352
  */
4247
4353
  getTableStyleClass(): string;
4354
+ private isNestedGridInstance;
4248
4355
  private isInlineEditEnabled;
4249
4356
  /**
4250
4357
  * Gestisce la logica operativa di `subscribeToDS` in modo coerente con l'implementazione corrente.
@@ -4933,6 +5040,11 @@ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDa
4933
5040
  * @param stateId Identificativo tecnico usato per lookup, match o aggiornamento mirato.
4934
5041
  */
4935
5042
  applySelectedGridState(stateId?: string): Promise<void>;
5043
+ /**
5044
+ * Unisce i filtri dello stato salvato con i filtri runtime "fissi" (route/nested),
5045
+ * evitando che apply state perda il vincolo master-detail.
5046
+ */
5047
+ private mergeSavedFilterInfoWithRuntimeFixedFilters;
4936
5048
  /**
4937
5049
  * Apre il popup di rinomina per lo stato corrente selezionato.
4938
5050
  */
@@ -5510,6 +5622,11 @@ interface AdvancedFilterRule {
5510
5622
  type AdvancedFilterNode = AdvancedFilterRule | {
5511
5623
  nestedFilters: AdvancedFilterGroup;
5512
5624
  };
5625
+ interface MultiDatasourceMeta {
5626
+ tableAlias: string;
5627
+ tableCaption: string;
5628
+ metaInfo: MetaInfo;
5629
+ }
5513
5630
  declare class FilterBarComponent implements OnInit, OnChanges, OnDestroy {
5514
5631
  private router;
5515
5632
  private aroute;
@@ -5517,6 +5634,7 @@ declare class FilterBarComponent implements OnInit, OnChanges, OnDestroy {
5517
5634
  private trnsl;
5518
5635
  datasource: BehaviorSubject<DataSourceComponent>;
5519
5636
  hardcodedDatasource: DataSourceComponent;
5637
+ multiDatasourceMetas: MultiDatasourceMeta[];
5520
5638
  filterApplied: EventEmitter<void>;
5521
5639
  onFilterApplied: EventEmitter<{
5522
5640
  mode: "basic" | "advanced" | "clear";
@@ -5582,11 +5700,14 @@ declare class FilterBarComponent implements OnInit, OnChanges, OnDestroy {
5582
5700
  constructor(router: Router, aroute: ActivatedRoute, location: Location, trnsl: TranslationManagerService);
5583
5701
  ngOnInit(): void;
5584
5702
  ngOnChanges(changes: SimpleChanges): void;
5703
+ private mergeMultiDatasourceColumns;
5704
+ get isMultiDatasourceMode(): boolean;
5585
5705
  ngOnDestroy(): void;
5586
5706
  private bindToDatasource;
5587
5707
  private subscribeToDatasource;
5588
5708
  private isFilterable;
5589
5709
  filter(): Promise<void>;
5710
+ private buildMultiDatasourceFilterInfo;
5590
5711
  clearFilter(): Promise<void>;
5591
5712
  addGroupField(): void;
5592
5713
  addAggregateField(): void;
@@ -5650,7 +5771,7 @@ declare class FilterBarComponent implements OnInit, OnChanges, OnDestroy {
5650
5771
  private syncGridStateQueryString;
5651
5772
  private resetCursorPagingState;
5652
5773
  static ɵfac: i0.ɵɵFactoryDeclaration<FilterBarComponent, never>;
5653
- static ɵcmp: i0.ɵɵComponentDeclaration<FilterBarComponent, "wuic-filter-bar", never, { "datasource": { "alias": "datasource"; "required": false; }; "hardcodedDatasource": { "alias": "hardcodedDatasource"; "required": false; }; }, { "filterApplied": "filterApplied"; "onFilterApplied": "onFilterApplied"; "onSortingApplied": "onSortingApplied"; "onPageSizeApplied": "onPageSizeApplied"; "onGroupingChanged": "onGroupingChanged"; "onFilterBarCollapseChanged": "onFilterBarCollapseChanged"; }, never, never, true, never>;
5774
+ static ɵcmp: i0.ɵɵComponentDeclaration<FilterBarComponent, "wuic-filter-bar", never, { "datasource": { "alias": "datasource"; "required": false; }; "hardcodedDatasource": { "alias": "hardcodedDatasource"; "required": false; }; "multiDatasourceMetas": { "alias": "multiDatasourceMetas"; "required": false; }; }, { "filterApplied": "filterApplied"; "onFilterApplied": "onFilterApplied"; "onSortingApplied": "onSortingApplied"; "onPageSizeApplied": "onPageSizeApplied"; "onGroupingChanged": "onGroupingChanged"; "onFilterBarCollapseChanged": "onFilterBarCollapseChanged"; }, never, never, true, never>;
5654
5775
  }
5655
5776
 
5656
5777
  declare class DynamicGenericTemplateComponent {
@@ -5658,6 +5779,10 @@ declare class DynamicGenericTemplateComponent {
5658
5779
  * Input dal componente padre per row data; usata nella configurazione e nel rendering del componente.
5659
5780
  */
5660
5781
  rowData: any;
5782
+ /**
5783
+ * Input dal componente padre per record (alias di rowData); usata nella configurazione e nel rendering del componente.
5784
+ */
5785
+ record: any;
5661
5786
  /**
5662
5787
  * Input dal componente padre per columns; usata nella configurazione e nel rendering del componente.
5663
5788
  */
@@ -5683,31 +5808,31 @@ declare class DynamicGenericTemplateComponent {
5683
5808
  */
5684
5809
  MetadatiColonna: typeof MetadatiColonna;
5685
5810
  /**
5686
- * Individua l'elemento richiesto in `findColumn` applicando i criteri di matching implementati.
5687
- * @param columnName Parametro utilizzato dal metodo nel flusso elaborativo.
5688
- * @returns Valore di tipo `MetadatiColonna | null` prodotto da `findColumn`.
5689
- */
5811
+ * Individua l'elemento richiesto in `findColumn` applicando i criteri di matching implementati.
5812
+ * @param columnName Parametro utilizzato dal metodo nel flusso elaborativo.
5813
+ * @returns Valore di tipo `MetadatiColonna | null` prodotto da `findColumn`.
5814
+ */
5690
5815
  findColumn(columnName: string): MetadatiColonna | null;
5691
5816
  /**
5692
- * Recupera i dati/valori richiesti da `getFieldValue`.
5693
- * @param record Dato/record su cui il metodo applica elaborazioni o aggiornamenti.
5694
- * @param fieldName Parametro utilizzato dal metodo nel flusso elaborativo.
5695
- * @returns Valore risolto da `getFieldValue` in base ai criteri implementati.
5696
- */
5817
+ * Recupera i dati/valori richiesti da `getFieldValue`.
5818
+ * @param record Dato/record su cui il metodo applica elaborazioni o aggiornamenti.
5819
+ * @param fieldName Parametro utilizzato dal metodo nel flusso elaborativo.
5820
+ * @returns Valore risolto da `getFieldValue` in base ai criteri implementati.
5821
+ */
5697
5822
  getFieldValue(record: any, fieldName: string): any;
5698
5823
  /**
5699
- * Gestisce la logica operativa di `classes` usando metadati di tabella/colonna allineati al modello server `_Metadati_*`.
5700
- * @returns Valore calcolato dinamicamente a partire dallo stato corrente del componente.
5701
- */
5824
+ * Gestisce la logica operativa di `classes` usando metadati di tabella/colonna allineati al modello server `_Metadati_*`.
5825
+ * @returns Valore calcolato dinamicamente a partire dallo stato corrente del componente.
5826
+ */
5702
5827
  get classes(): string | null;
5703
5828
  /**
5704
- * Recupera i dati/valori richiesti da `getComponentFromTemplate`.
5705
- * @param template Parametro utilizzato dal metodo nel flusso elaborativo.
5706
- * @returns Valore risolto da `getComponentFromTemplate` in base ai criteri implementati.
5707
- */
5829
+ * Recupera i dati/valori richiesti da `getComponentFromTemplate`.
5830
+ * @param template Parametro utilizzato dal metodo nel flusso elaborativo.
5831
+ * @returns Valore risolto da `getComponentFromTemplate` in base ai criteri implementati.
5832
+ */
5708
5833
  static getComponentFromTemplate(template: string): typeof DynamicGenericTemplateComponent;
5709
5834
  static ɵfac: i0.ɵɵFactoryDeclaration<DynamicGenericTemplateComponent, never>;
5710
- static ɵcmp: i0.ɵɵComponentDeclaration<DynamicGenericTemplateComponent, "wuic-dynamic-generic-template", never, { "rowData": { "alias": "rowData"; "required": false; }; "columns": { "alias": "columns"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; "metaInfo": { "alias": "metaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "getDescription": { "alias": "getDescription"; "required": false; }; "MetadatiColonna": { "alias": "MetadatiColonna"; "required": false; }; }, {}, never, never, false, never>;
5835
+ static ɵcmp: i0.ɵɵComponentDeclaration<DynamicGenericTemplateComponent, "wuic-dynamic-generic-template", never, { "rowData": { "alias": "rowData"; "required": false; }; "record": { "alias": "record"; "required": false; }; "columns": { "alias": "columns"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; "metaInfo": { "alias": "metaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "getDescription": { "alias": "getDescription"; "required": false; }; "MetadatiColonna": { "alias": "MetadatiColonna"; "required": false; }; }, {}, never, never, false, never>;
5711
5836
  }
5712
5837
 
5713
5838
  interface IBindable {
@@ -6985,11 +7110,20 @@ declare class MapListComponent implements OnInit, IBindable, IDesigner<MapOption
6985
7110
  private setPolygonEditability;
6986
7111
  private getVerticesFromMapPolygon;
6987
7112
  /**
6988
- * Converte una geometria WKT polygon (es. `POLYGON((lng lat,...))` o `POLYGON ((lng lat,...))`)
6989
- * in un array di vertici Google Maps (`{lat,lng}`), scartando coordinate invalide.
7113
+ * Converte una geometria WKT polygon (`POLYGON((lng lat,...))`,
7114
+ * `POLYGON((outer),(hole))`) o multi-polygon
7115
+ * (`MULTIPOLYGON(((p1)),((p2),(hole)))`) in un array di RING di vertici
7116
+ * Google Maps (`LatLngLiteral[][]`), scartando coordinate invalide.
7117
+ *
7118
+ * Ogni ring e' una sequenza chiusa: outer, holes e sub-polygon vengono
7119
+ * appiattiti a livello di array di array, in modo che possa essere passato
7120
+ * direttamente a `<map-polygon [paths]>`. Cosi' una singola istanza di
7121
+ * map-polygon disegna correttamente sub-polygon disgiunti (es. esclavi,
7122
+ * isole) e holes, senza tracciare linee diagonali "ponte" tra i ring.
7123
+ *
6990
7124
  * Compatibile con output MySQL/SQLServer e con prefisso opzionale `SRID=...;`.
6991
7125
  */
6992
- private parsePolygonVertices;
7126
+ private parsePolygonRings;
6993
7127
  /**
6994
7128
  * Serializza una lista vertici `{lat,lng}` nel formato WKT `POLYGON` usato per il salvataggio.
6995
7129
  * @param vertices Vertici del poligono in ordine di percorrenza.
@@ -7219,10 +7353,10 @@ declare class CarouselListComponent implements IBindable, IDesigner<CarouselOpti
7219
7353
  */
7220
7354
  ngOnDestroy(): void;
7221
7355
  /**
7222
- * Interpreta e normalizza input/configurazione in `parseData` per l'utilizzo nel componente.
7223
- * @param dato Collezione in ingresso processata dal metodo.
7224
- * @returns Struttura dati prodotta da `parseData` dopo normalizzazione/elaborazione.
7225
- */
7356
+ * Interpreta e normalizza input/configurazione in `parseData` per l'utilizzo nel componente.
7357
+ * @param dato Collezione in ingresso processata dal metodo.
7358
+ * @returns Struttura dati prodotta da `parseData` dopo normalizzazione/elaborazione.
7359
+ */
7226
7360
  parseData(dato: any[]): any[];
7227
7361
  /**
7228
7362
  * Apre il popup di configurazione caricando prima i valori correnti dal `md_props_bag`
@@ -7230,9 +7364,9 @@ declare class CarouselListComponent implements IBindable, IDesigner<CarouselOpti
7230
7364
  */
7231
7365
  openConfigDialog(): void;
7232
7366
  /**
7233
- * Applica aggiornamenti di stato tramite `applyConfig` mantenendo coerenti UI e dati.
7234
- * @param nextConfig Parametro utilizzato dal metodo nel flusso elaborativo.
7235
- */
7367
+ * Applica aggiornamenti di stato tramite `applyConfig` mantenendo coerenti UI e dati.
7368
+ * @param nextConfig Parametro utilizzato dal metodo nel flusso elaborativo.
7369
+ */
7236
7370
  applyConfig(nextConfig?: any): void;
7237
7371
  /**
7238
7372
  * Salva nel metadata tabella (`md_props_bag`) la configurazione carousel corrente
@@ -7262,9 +7396,9 @@ declare class CarouselListComponent implements IBindable, IDesigner<CarouselOpti
7262
7396
  */
7263
7397
  suggestItemTemplate(): void;
7264
7398
  /**
7265
- * Applica aggiornamenti di stato tramite `applyPageSizeChange` preparando/aggiornando il dataset visualizzato.
7266
- * @param value Valore in ingresso elaborato o normalizzato dal metodo.
7267
- */
7399
+ * Applica aggiornamenti di stato tramite `applyPageSizeChange` preparando/aggiornando il dataset visualizzato.
7400
+ * @param value Valore in ingresso elaborato o normalizzato dal metodo.
7401
+ */
7268
7402
  applyPageSizeChange(value?: number): void;
7269
7403
  /**
7270
7404
  * Allinea la bozza `configDraft` alle opzioni effettive del carousel,
@@ -7288,10 +7422,10 @@ declare class CarouselListComponent implements IBindable, IDesigner<CarouselOpti
7288
7422
  */
7289
7423
  private ensureMergedExtraProps;
7290
7424
  /**
7291
- * Carica dati e li armonizza per l'uso nel componente usando i metadati per determinare campi, chiavi e comportamento runtime, allineando i record al formato atteso dal framework, coordinando chiamate verso servizi applicativi.
7292
- * @param userId Identificativo tecnico usato per lookup, confronto o aggiornamento mirato.
7293
- * @returns Promise che completa il flusso asincrono e restituisce un risultato di tipo `Promise<any | null>`.
7294
- */
7425
+ * Carica dati e li armonizza per l'uso nel componente usando i metadati per determinare campi, chiavi e comportamento runtime, allineando i record al formato atteso dal framework, coordinando chiamate verso servizi applicativi.
7426
+ * @param userId Identificativo tecnico usato per lookup, confronto o aggiornamento mirato.
7427
+ * @returns Promise che completa il flusso asincrono e restituisce un risultato di tipo `Promise<any | null>`.
7428
+ */
7295
7429
  private loadCurrentTableMetadataRecord;
7296
7430
  private scheduleVisibilitySync;
7297
7431
  private refreshItemVisibilityObserver;
@@ -8465,6 +8599,119 @@ declare class ParametricDialogComponent implements OnDestroy, IDataBoundHostComp
8465
8599
  static ɵcmp: i0.ɵɵComponentDeclaration<ParametricDialogComponent, "wuic-parametric-dialog", never, { "datasource": { "alias": "datasource"; "required": false; }; "hardcodedDatasource": { "alias": "hardcodedDatasource"; "required": false; }; "hideToolbar": { "alias": "hideToolbar"; "required": false; }; "isWizard": { "alias": "isWizard"; "required": false; }; "isEditForm": { "alias": "isEditForm"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; }, { "onDialogDataBound": "onDialogDataBound"; "onDialogTabChange": "onDialogTabChange"; "onWizardStepChange": "onWizardStepChange"; "onDialogCustomAction": "onDialogCustomAction"; "onDialogSubmit": "onDialogSubmit"; "onDialogRollback": "onDialogRollback"; "onDialogCloseRequested": "onDialogCloseRequested"; }, never, never, true, never>;
8466
8600
  }
8467
8601
 
8602
+ /**
8603
+ * Tipo di campo riconosciuto dal renderer. Allineato alla `FieldType` enum
8604
+ * del backend `AppSettingsController`.
8605
+ */
8606
+ type FieldType = 'string' | 'bool' | 'int' | 'password' | 'longtext';
8607
+ /**
8608
+ * Livello di impatto di una modifica. Allineato alla `ChangeImpact` enum del
8609
+ * backend, in lower-case (serializzazione JSON di ToString().ToLowerInvariant()).
8610
+ */
8611
+ type ChangeImpact = 'hotreload' | 'restart' | 'restartandlogout';
8612
+ interface AppSettingFieldDef {
8613
+ key: string;
8614
+ label: string;
8615
+ type: FieldType;
8616
+ impact: ChangeImpact;
8617
+ description?: string | null;
8618
+ value: any;
8619
+ /**
8620
+ * If non-empty, render a `<p-select>` constrained to these values instead
8621
+ * of the free-text input dictated by `type`. The backend populates this
8622
+ * for enum-like settings (dbms, encriptionMethod, log levels, etc.) so the
8623
+ * user can't accidentally write `mssqll` and brick the next backend boot.
8624
+ */
8625
+ options?: string[] | null;
8626
+ }
8627
+ interface AppSettingSection {
8628
+ name: string;
8629
+ label: string;
8630
+ icon: string;
8631
+ fields: AppSettingFieldDef[];
8632
+ }
8633
+ interface SaveChange {
8634
+ key: string;
8635
+ oldValue: any;
8636
+ newValue: any;
8637
+ }
8638
+ /**
8639
+ * Editor visuale per `appsettings.json` organizzato in tab per sezione.
8640
+ *
8641
+ * Architettura: il componente carica lo schema (campi + valori correnti) da
8642
+ * `GET /api/AppSettings/Get`, mantiene un `pristine` snapshot per calcolare il
8643
+ * diff, e su "Save & Apply" POSTa solo le modifiche a `POST /api/AppSettings/Save`.
8644
+ *
8645
+ * Il backend classifica le modifiche in tre livelli (`hotreload`, `restart`,
8646
+ * `restartandlogout`) — il componente reagisce di conseguenza:
8647
+ * - **hotreload**: mostra toast di successo, aggiorna pristine, end of story.
8648
+ * - **restart**: mostra overlay "Backend is restarting...", polla `Health` ogni
8649
+ * 500ms fino a che il backend torna su, ricarica lo schema, mostra toast.
8650
+ * - **restartandlogout**: come `restart`, ma al ritorno forza il logout
8651
+ * chiamando `AuthSessionService.legacyLogout()` + redirect a `/`.
8652
+ *
8653
+ * NOTA architetturale: questo NON e' un metadata-bound parametric-dialog perche'
8654
+ * `appsettings.json` non ha backing DB e creare una route metadata fittizia con
8655
+ * tabella DB virtuale + 50 colonne in `_metadati__colonne` aggiungerebbe ~3x il
8656
+ * codice senza alcun vantaggio funzionale. La UI usa lo stesso `<p-tabs>` di
8657
+ * PrimeNG che usa il parametric-dialog, quindi visivamente sono indistinguibili.
8658
+ */
8659
+ declare class AppSettingsEditorComponent implements OnInit {
8660
+ private readonly http;
8661
+ private readonly authSession;
8662
+ private readonly router;
8663
+ readonly loading: i0.WritableSignal<boolean>;
8664
+ readonly saving: i0.WritableSignal<boolean>;
8665
+ readonly waitingRestart: i0.WritableSignal<boolean>;
8666
+ readonly errorMsg: i0.WritableSignal<string>;
8667
+ readonly sections: i0.WritableSignal<AppSettingSection[]>;
8668
+ readonly filePath: i0.WritableSignal<string>;
8669
+ private pristine;
8670
+ current: Map<string, any>;
8671
+ readonly activeTabValue: i0.WritableSignal<number>;
8672
+ readonly pendingChanges: i0.Signal<SaveChange[]>;
8673
+ readonly hasPendingChanges: i0.Signal<boolean>;
8674
+ readonly pendingChangesCount: i0.Signal<number>;
8675
+ private readonly changeTick;
8676
+ ngOnInit(): Promise<void>;
8677
+ private apiUrl;
8678
+ private buildApiBaseUrl;
8679
+ private loadSchema;
8680
+ private rebuildMaps;
8681
+ /**
8682
+ * Trasforma il valore raw che arriva dal backend in un valore tipizzato
8683
+ * stabile per il binding ngModel. Questo evita falsi diff dovuti a
8684
+ * confronto string-vs-number o "true"-vs-true.
8685
+ */
8686
+ private normalizeValueForType;
8687
+ private valuesEqual;
8688
+ /**
8689
+ * Bind handler per ngModel sui field. Aggiorna current e bumpa il tick
8690
+ * cosi' il computed pendingChanges si rivaluta.
8691
+ */
8692
+ onFieldChange(key: string, newValue: any): void;
8693
+ fieldValue(key: string): any;
8694
+ impactSeverity(impact: ChangeImpact): 'success' | 'warn' | 'danger';
8695
+ impactLabel(impact: ChangeImpact): string;
8696
+ /**
8697
+ * Custom action "Save & Apply": calcola il diff (== _changes), lo POSTa,
8698
+ * legge la classification dalla response e reagisce di conseguenza.
8699
+ *
8700
+ * - hotreload: toast + aggiorna pristine.
8701
+ * - restart: overlay + poll Health + reload schema.
8702
+ * - restartandlogout: overlay + poll Health + force logout.
8703
+ */
8704
+ onSaveAndApply(): Promise<void>;
8705
+ onResetChanges(): Promise<void>;
8706
+ onReload(): Promise<void>;
8707
+ private confirmDiscardChanges;
8708
+ private sleep;
8709
+ private waitForHealth;
8710
+ private forceLogout;
8711
+ static ɵfac: i0.ɵɵFactoryDeclaration<AppSettingsEditorComponent, never>;
8712
+ static ɵcmp: i0.ɵɵComponentDeclaration<AppSettingsEditorComponent, "wuic-app-settings-editor", never, {}, {}, never, never, true, never>;
8713
+ }
8714
+
8468
8715
  declare class DataActionButtonComponent implements AfterViewInit, OnDestroy {
8469
8716
  private trslSrv;
8470
8717
  private cd;
@@ -8689,6 +8936,29 @@ declare class AuthSessionService {
8689
8936
  * @param force Se `true` forza una nuova inizializzazione anche se gia avvenuta.
8690
8937
  */
8691
8938
  initialize(force?: boolean): Promise<void>;
8939
+ /**
8940
+ * Hydrates the UI-side user snapshot from the backend when sessionStorage
8941
+ * is empty but a server-managed HttpOnly `k-user` cookie might still be
8942
+ * valid. This is the critical step for `enableCookieAuthentication=true`:
8943
+ * after a browser restart (or new tab) sessionStorage is gone, the cookie
8944
+ * is HttpOnly and invisible to JS, so without this call the guard would
8945
+ * wrongly redirect to `/unauthorized` despite a valid session.
8946
+ *
8947
+ * Flow:
8948
+ * 1. If sessionStorage already has a snapshot → no hydration needed.
8949
+ * 2. Otherwise call `MetaService.me` with `withCredentials:true`. The
8950
+ * backend reads the HttpOnly cookie server-side and returns the
8951
+ * public user fields (and `cookieAuthEnabled` for introspection).
8952
+ * 3. If `me()` returns a populated payload, write it to sessionStorage
8953
+ * via `userInfoService.setUserInfoCookie` so subsequent calls see
8954
+ * the user. If `me()` returns an empty object `{}` (no valid
8955
+ * cookie) the hydration is a no-op and the UI stays logged out.
8956
+ *
8957
+ * Errors are swallowed on purpose: if `me()` throws (network, backend
8958
+ * down, legacy backend without the endpoint), we fall back to whatever
8959
+ * the cookie/sessionStorage already has without blocking the boot.
8960
+ */
8961
+ private hydrateFromServerCookie;
8692
8962
  /**
8693
8963
  * Ricalcola lo stato autenticazione combinando configurazione OAuth, endpoint `Auth/Enabled`, endpoint `Auth/Me`
8694
8964
  * e fallback sessione legacy (`k-user`), poi sincronizza eventuali custom settings utente.
@@ -8717,7 +8987,29 @@ declare class AuthSessionService {
8717
8987
  */
8718
8988
  legacyLogin(username: string, password: string, captchaToken?: string): Promise<boolean>;
8719
8989
  /**
8720
- * Esegue logout legacy via `MetaService.logout` (se presente utente), poi ripulisce runtime locale e ricarica stato sessione.
8990
+ * Logout flow that works in BOTH cookie modes:
8991
+ *
8992
+ * - **Server-managed mode** (`enableCookieAuthentication=true`): the
8993
+ * `k-user` cookie is HttpOnly, so the only way to delete it is via a
8994
+ * `Set-Cookie` delete header from the server. We call
8995
+ * `MetaService.logoutSession` (parameterless) which:
8996
+ * 1. derives the user from the cookie server-side,
8997
+ * 2. wipes the DB session token via the existing `logout(user)`
8998
+ * per-DBMS dispatcher,
8999
+ * 3. emits the `Set-Cookie` delete with matching CookieOptions.
9000
+ *
9001
+ * - **Legacy mode** (`enableCookieAuthentication=false`): we still call
9002
+ * `logoutSession` because the server-side helper is idempotent in
9003
+ * legacy mode and always wipes the DB token. The local
9004
+ * `userInfoService.clearUserInfo()` then deletes the JS-readable
9005
+ * cookie + sessionStorage snapshot.
9006
+ *
9007
+ * Why not call the legacy `MetaService.logout(user)` overload? It only
9008
+ * runs the per-DBMS DB cleanup; it does NOT emit the cookie delete
9009
+ * header, so the HttpOnly cookie would survive the logout in
9010
+ * server-managed mode and the next page load would re-hydrate the
9011
+ * supposedly-logged-out user via `MetaService.me`. The new
9012
+ * `logoutSession` does both atomically.
8721
9013
  */
8722
9014
  legacyLogout(): Promise<void>;
8723
9015
  /**
@@ -8767,6 +9059,21 @@ declare class AuthSessionService {
8767
9059
  * Applica un aggiornamento parziale allo stato `AuthSessionState` preservando le proprieta non toccate.
8768
9060
  * @param partial Delta stato da fondere con lo stato corrente.
8769
9061
  */
9062
+ /**
9063
+ * Sets a user-visible error message in the auth state.
9064
+ * Used by the auth-expired interceptor to communicate the logout
9065
+ * reason (e.g. "session replaced by another login") after the
9066
+ * logout flow has completed and the login form is visible.
9067
+ */
9068
+ setError(message: string): void;
9069
+ /** User-facing messages keyed by server reason code. */
9070
+ private static readonly REASON_MESSAGES;
9071
+ /**
9072
+ * Reads and removes the redirect reason left by the auth-expired
9073
+ * interceptor in localStorage, then sets the corresponding error
9074
+ * message in the auth state so the login form displays it.
9075
+ */
9076
+ private applyRedirectReason;
8770
9077
  private patchState;
8771
9078
  /**
8772
9079
  * Costruisce una struttura derivata a partire dallo stato corrente.
@@ -13540,6 +13847,7 @@ interface DocsSection {
13540
13847
  }
13541
13848
  interface DocsPage {
13542
13849
  slug: string;
13850
+ lang: string;
13543
13851
  title: string;
13544
13852
  description: string;
13545
13853
  audience: DocsAudience[];
@@ -13556,6 +13864,7 @@ interface DocsPage {
13556
13864
  interface DocsNavItem {
13557
13865
  slug: string;
13558
13866
  title: string;
13867
+ titles?: Record<string, string>;
13559
13868
  icon?: string;
13560
13869
  status?: DocsStatus;
13561
13870
  audience?: DocsAudience[];
@@ -13563,6 +13872,7 @@ interface DocsNavItem {
13563
13872
  interface DocsNavGroup {
13564
13873
  id: string;
13565
13874
  title: string;
13875
+ titles?: Record<string, string>;
13566
13876
  items: DocsNavItem[];
13567
13877
  }
13568
13878
  interface DocsContentManifest {
@@ -13572,17 +13882,6 @@ interface DocsContentManifest {
13572
13882
  pages: DocsPage[];
13573
13883
  }
13574
13884
 
13575
- type ThemePresetName = 'aura' | 'lara' | 'nora' | 'material';
13576
- type ThemePrimaryName = 'blue' | 'emerald' | 'violet' | 'amber' | 'cyan' | 'teal' | 'indigo' | 'rose' | 'pink' | 'lime';
13577
- interface ThemeOption {
13578
- label: string;
13579
- value: string;
13580
- preset: ThemePresetName;
13581
- primary: ThemePrimaryName;
13582
- primaryHex: string;
13583
- isHighContrast?: boolean;
13584
- }
13585
-
13586
13885
  declare class FrameworkDocsComponent {
13587
13886
  private router;
13588
13887
  private route;
@@ -13591,16 +13890,35 @@ declare class FrameworkDocsComponent {
13591
13890
  readonly query: i0.WritableSignal<string>;
13592
13891
  readonly dark: i0.WritableSignal<boolean>;
13593
13892
  readonly currentSlug: i0.WritableSignal<string>;
13594
- readonly allThemes: ThemeOption[];
13893
+ readonly currentLang: i0.WritableSignal<string>;
13894
+ readonly allThemes: wuic_framework_lib.ThemeOption[];
13595
13895
  private readonly collapsedCodeMaxLines;
13596
13896
  private readonly expandedSamples;
13597
13897
  private readonly highlightedHtmlCache;
13598
- readonly pagesBySlug: Map<string, DocsPage>;
13898
+ private trslSrv;
13899
+ private ngxTranslate;
13900
+ readonly langPages: i0.Signal<DocsPage[]>;
13901
+ readonly pagesBySlug: i0.Signal<Map<string, DocsPage>>;
13599
13902
  private readonly searchIndexBySlug;
13600
13903
  private readonly sectionPartsCache;
13601
- readonly filteredGroups: i0.Signal<DocsNavGroup[]>;
13904
+ readonly filteredGroups: i0.Signal<{
13905
+ title: any;
13906
+ items: {
13907
+ title: any;
13908
+ slug: string;
13909
+ titles?: Record<string, string>;
13910
+ icon?: string;
13911
+ status?: DocsStatus;
13912
+ audience?: DocsAudience[];
13913
+ }[];
13914
+ id: string;
13915
+ titles?: Record<string, string>;
13916
+ }[]>;
13602
13917
  readonly currentPage: i0.Signal<DocsPage>;
13603
13918
  readonly breadcrumbs: i0.Signal<string[]>;
13919
+ private static readonly SUPPORTED_LANGS;
13920
+ t(key: string, fallback: string): string;
13921
+ private resolveLang;
13604
13922
  constructor(router: Router, route: ActivatedRoute);
13605
13923
  openPage(slug: string): void;
13606
13924
  toggleTheme(): void;
@@ -13661,6 +13979,182 @@ declare class DesignerRouteComponent implements OnInit {
13661
13979
  static ɵcmp: i0.ɵɵComponentDeclaration<DesignerRouteComponent, "wuic-designer-route", never, {}, {}, never, never, true, never>;
13662
13980
  }
13663
13981
 
13982
+ /**
13983
+ * Data model for the multi-table View Builder (Tab 1 of the pivot-builder).
13984
+ *
13985
+ * The ViewDefinition is the contract between the view-builder canvas and
13986
+ * the pivot configuration (Tab 2). It serializes cleanly to JSON for
13987
+ * save/load persistence inside `pivot_config_json`.
13988
+ */
13989
+ /** A column from a table in the view builder. */
13990
+ interface ViewColumn {
13991
+ /** mc_nome_colonna */
13992
+ alias: string;
13993
+ /** mc_real_column_name */
13994
+ realName: string;
13995
+ /** mc_display_string_in_view */
13996
+ label: string;
13997
+ /** mc_db_column_type */
13998
+ dbType: string;
13999
+ /** mc_ui_column_type */
14000
+ uiType: string;
14001
+ /** Route of the table this column belongs to */
14002
+ tableRoute: string;
14003
+ /** SQL alias for the table (e.g., "t0", "t1") */
14004
+ tableAlias: string;
14005
+ /** "TableCaption.ColumnLabel" — used in Tab 2 to distinguish same-named columns */
14006
+ qualifiedLabel: string;
14007
+ /** Whether user selected this column for the view */
14008
+ selected: boolean;
14009
+ /** True when the column exists only in metadata (e.g. button) and has no physical DB column */
14010
+ virtual?: boolean;
14011
+ /** If this is a lookupByID column, the target entity route */
14012
+ lookupEntityName?: string;
14013
+ /** If this is a lookupByID column, the FK value field */
14014
+ lookupDataValueField?: string;
14015
+ /** If this is a lookupByID column, the display text field on the target */
14016
+ lookupDataTextField?: string;
14017
+ /** Whether this column is filterable in the filter-bar (from mc_show_in_filters) */
14018
+ showInFilters?: boolean;
14019
+ /** Custom SQL formula to use instead of the column reference (e.g. "YEAR(t0.ValidFrom)") */
14020
+ formula?: string;
14021
+ /** Custom alias for the formula output */
14022
+ formulaAlias?: string;
14023
+ }
14024
+ /** A table node placed on the view-builder Rete.js canvas. */
14025
+ interface ViewTableNode {
14026
+ /** Rete node ID */
14027
+ nodeId: string;
14028
+ /** Scaffolded route name */
14029
+ route: string;
14030
+ /** Metadata table ID (_metadati__tabelle.md_id) */
14031
+ mdId: number | null;
14032
+ /** Physical table name (md_nome_tabella) */
14033
+ tableName: string;
14034
+ /** Schema (default 'dbo') */
14035
+ schemaName: string;
14036
+ /** Human-readable caption */
14037
+ caption: string;
14038
+ /** SQL alias assigned (t0, t1, t2, ...) */
14039
+ tableAlias: string;
14040
+ /** All columns, each with a `selected` flag */
14041
+ columns: ViewColumn[];
14042
+ /** Canvas X position */
14043
+ x: number;
14044
+ /** Canvas Y position */
14045
+ y: number;
14046
+ /** Whether the node is collapsed in the canvas */
14047
+ collapsed?: boolean;
14048
+ }
14049
+ /** A JOIN edge between two table nodes. */
14050
+ interface ViewJoinEdge {
14051
+ /** Rete connection ID */
14052
+ edgeId: string;
14053
+ /** FK source node ID */
14054
+ sourceNodeId: string;
14055
+ /** FK source route */
14056
+ sourceRoute: string;
14057
+ /** FK column alias on the source table */
14058
+ sourceColumn: string;
14059
+ /** PK target node ID */
14060
+ targetNodeId: string;
14061
+ /** PK target route */
14062
+ targetRoute: string;
14063
+ /** PK column on the target table */
14064
+ targetColumn: string;
14065
+ /** JOIN type */
14066
+ joinType: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
14067
+ /** true if created automatically from lookupByID metadata */
14068
+ autoDetected: boolean;
14069
+ }
14070
+ /** Complete view definition — the output of Tab 1, input to Tab 2 and backend. */
14071
+ interface ViewDefinition {
14072
+ tables: ViewTableNode[];
14073
+ joins: ViewJoinEdge[];
14074
+ }
14075
+
14076
+ type RouteOption$1 = {
14077
+ label: string;
14078
+ value: string;
14079
+ mdId: number | null;
14080
+ };
14081
+ declare class ViewBuilderComponent implements AfterViewInit, OnDestroy {
14082
+ private injector;
14083
+ private dataSrv;
14084
+ private metaSrv;
14085
+ viewDefinitionChange: EventEmitter<ViewDefinition>;
14086
+ canvasRef?: ElementRef<HTMLDivElement>;
14087
+ private editor?;
14088
+ private area?;
14089
+ routeOptions: RouteOption$1[];
14090
+ filteredRouteOptions: RouteOption$1[];
14091
+ selectedRouteOption?: RouteOption$1;
14092
+ private tableAliasCounter;
14093
+ showRelatedOnly: boolean;
14094
+ private fkRelationships;
14095
+ joinTypeOptions: {
14096
+ label: string;
14097
+ value: string;
14098
+ }[];
14099
+ joinBadges: {
14100
+ connId: string;
14101
+ x: number;
14102
+ y: number;
14103
+ type: string;
14104
+ label: string;
14105
+ glyph: string;
14106
+ }[];
14107
+ contextMenuVisible: boolean;
14108
+ contextMenuX: number;
14109
+ contextMenuY: number;
14110
+ contextMenuConnectionId: string | null;
14111
+ private http;
14112
+ private userInfo;
14113
+ private cdr;
14114
+ private trslSrv;
14115
+ constructor(injector: Injector, dataSrv: DataProviderService, metaSrv: MetadataProviderService);
14116
+ t(key: string, fallback: string): string;
14117
+ /** True when at least one table is on the canvas */
14118
+ get hasCanvasNodes(): boolean;
14119
+ /** Routes shown in the palette (filtered by FK when checkbox is on) */
14120
+ get displayedRouteOptions(): RouteOption$1[];
14121
+ ngAfterViewInit(): Promise<void>;
14122
+ ngOnDestroy(): void;
14123
+ private loadRouteOptions;
14124
+ private loadForeignKeys;
14125
+ filterRouteOptions(event: AutoCompleteCompleteEvent): void;
14126
+ onPaletteDragStart(event: DragEvent, option: RouteOption$1): void;
14127
+ onCanvasDragOver(event: DragEvent): void;
14128
+ onCanvasDrop(event: DragEvent): Promise<void>;
14129
+ /** Adds a table via the autocomplete "Add" button (positioned at center) */
14130
+ addSelectedRoute(): Promise<void>;
14131
+ private addTableNode;
14132
+ private refreshConnectedSockets;
14133
+ private routeMatch;
14134
+ private autoDetectJoins;
14135
+ removeNode(nodeId: string): Promise<void>;
14136
+ /** Map connection ID → join type (default LEFT) */
14137
+ private connectionJoinTypes;
14138
+ private findConnectionIdFromSvg;
14139
+ private findConnectionIdFromElement;
14140
+ showConnectionContextMenu(x: number, y: number, connId: string): void;
14141
+ setJoinType(type: string): void;
14142
+ getJoinType(connId: string): string;
14143
+ removeConnection(): Promise<void>;
14144
+ private showDropRejection;
14145
+ hideContextMenu(): void;
14146
+ private emitDebounceTimer;
14147
+ private emitViewDefinition;
14148
+ private updateJoinGlyphs;
14149
+ private emitViewDefinitionNow;
14150
+ serializeViewDefinition(): ViewDefinition | null;
14151
+ restoreFromDefinition(def: ViewDefinition): Promise<void>;
14152
+ private buildApiBaseUrl;
14153
+ zoomToFit(): Promise<void>;
14154
+ static ɵfac: i0.ɵɵFactoryDeclaration<ViewBuilderComponent, never>;
14155
+ static ɵcmp: i0.ɵɵComponentDeclaration<ViewBuilderComponent, "wuic-view-builder", never, {}, { "viewDefinitionChange": "viewDefinitionChange"; }, never, never, true, never>;
14156
+ }
14157
+
13664
14158
  type RouteOption = {
13665
14159
  label: string;
13666
14160
  value: string;
@@ -13692,9 +14186,11 @@ declare class PivotBuilderComponent implements OnInit, AfterViewInit {
13692
14186
  private metaSrv;
13693
14187
  private trslSrv;
13694
14188
  private aRoute;
14189
+ activeTab: number;
13695
14190
  activeFilterPanel: string;
13696
14191
  pivotName: string;
13697
14192
  routeOptions: RouteOption[];
14193
+ viewDefinition: ViewDefinition | null;
13698
14194
  filteredRouteOptions: RouteOption[];
13699
14195
  selectedRouteOption?: RouteOption;
13700
14196
  selectedRouteName: string;
@@ -13713,6 +14209,12 @@ declare class PivotBuilderComponent implements OnInit, AfterViewInit {
13713
14209
  label: string;
13714
14210
  value: string;
13715
14211
  }[];
14212
+ /** True when the view builder has at least one table with selected columns. */
14213
+ get hasViewDefinition(): boolean;
14214
+ /** True when enough context exists for pivot actions (Tab 1). */
14215
+ get canExecutePivot(): boolean;
14216
+ /** True when enough context for either tab. Used internally. */
14217
+ get canExecute(): boolean;
13716
14218
  generatedSql: string;
13717
14219
  loadingRouteColumns: boolean;
13718
14220
  generatingSql: boolean;
@@ -13720,8 +14222,15 @@ declare class PivotBuilderComponent implements OnInit, AfterViewInit {
13720
14222
  executingQuery: boolean;
13721
14223
  creatingView: boolean;
13722
14224
  creatingMaterializedTable: boolean;
14225
+ creatingViewFromDef: boolean;
14226
+ generatingViewDefSql: boolean;
14227
+ executingViewDefQuery: boolean;
14228
+ autoGenerateQuery: boolean;
14229
+ manualSqlMode: boolean;
14230
+ createdViewName: string;
13723
14231
  draggingColumn?: PivotColumn;
13724
14232
  nestedSource?: DataSourceComponent;
14233
+ viewBuilderRef?: ViewBuilderComponent;
13725
14234
  pivotDatasource?: DataSourceComponent;
13726
14235
  pivotDatasourceSub?: Subscription;
13727
14236
  persistedFilterInfo?: any;
@@ -13737,18 +14246,40 @@ declare class PivotBuilderComponent implements OnInit, AfterViewInit {
13737
14246
  reopeningPivotList: boolean;
13738
14247
  savedPivotOptions: SavedPivotOption[];
13739
14248
  reopenDialogSelectedPivotName: string | null;
13740
- readonly sqlEditorOptions: {
13741
- theme: string;
13742
- language: string;
13743
- automaticLayout: boolean;
13744
- minimap: {
13745
- enabled: boolean;
13746
- };
13747
- readOnly: boolean;
13748
- };
14249
+ sqlEditorOptions: any;
13749
14250
  constructor(dataSrv: DataProviderService, metaSrv: MetadataProviderService, trslSrv: TranslationManagerService, aRoute: ActivatedRoute);
13750
- private t;
14251
+ t(key: string, fallback: string): string;
13751
14252
  private buildDateGroupByOptions;
14253
+ /** Route of the first table in the View Builder — drives the filter-bar datasource */
14254
+ viewBuilderFilterRoute: string;
14255
+ viewBuilderFilterMetas: MultiDatasourceMeta[];
14256
+ multiDatasourceFilterInfo: FilterInfo | null;
14257
+ onViewDefinitionChange(def: ViewDefinition | null): void;
14258
+ onManualSqlModeChange(enabled: boolean): Promise<void>;
14259
+ private autoGenerateDebounce;
14260
+ /** When true, all columns are shown in filter-bar regardless of mc_show_in_filters */
14261
+ forceAllColumnsFilterable: boolean;
14262
+ onForceAllColumnsFilterableChange(): void;
14263
+ private buildMetaInfoFromViewTable;
14264
+ onViewBuilderFilterApplied(): void;
14265
+ onViewBuilderMultiFilterApplied(event: {
14266
+ mode: string;
14267
+ filterInfo: FilterInfo | null;
14268
+ }): void;
14269
+ /**
14270
+ * Creates a DB VIEW from the multi-table view definition (Tab 0 action).
14271
+ * After creation, the scaffolded view appears as a route in Tab 1.
14272
+ */
14273
+ createViewFromDefinition(): Promise<void>;
14274
+ /**
14275
+ * Calls the backend to generate a SELECT SQL from the ViewDefinition
14276
+ * (generate only, no execution).
14277
+ */
14278
+ generateSqlFromViewDefinition(): Promise<void>;
14279
+ /**
14280
+ * Calls the backend to generate and execute the SELECT query.
14281
+ */
14282
+ executeViewDefinitionQuery(): Promise<void>;
13752
14283
  ngOnInit(): Promise<void>;
13753
14284
  ngAfterViewInit(): void;
13754
14285
  loadRouteOptions(): Promise<void>;
@@ -13802,6 +14333,9 @@ declare class PivotBuilderComponent implements OnInit, AfterViewInit {
13802
14333
  private requestCreatePivotMaterializedTable;
13803
14334
  onFilterBarApplied(): void;
13804
14335
  savePivotConfiguration(): Promise<void>;
14336
+ saveViewBuilderDefinition(silent?: boolean): Promise<void>;
14337
+ viewBuilderOpenMode: boolean;
14338
+ openViewBuilderDefinition(): Promise<void>;
13805
14339
  openReopenPivotDialog(): Promise<void>;
13806
14340
  cancelReopenPivotDialog(): void;
13807
14341
  confirmReopenPivotDialog(): Promise<void>;
@@ -14362,6 +14896,297 @@ declare const boundedRepeaterPendingChangesGuard: CanDeactivateFn<BoundedRepeate
14362
14896
  declare const menuRouteAccessCanMatchGuard: CanMatchFn;
14363
14897
  declare const menuRouteAccessCanActivateGuard: CanActivateFn;
14364
14898
 
14899
+ /**
14900
+ * Singolo "source" (chunk del codebase) restituito dal RAG.
14901
+ *
14902
+ * Mappa 1:1 il payload `RagSourceOut` di `rag_server.py`.
14903
+ */
14904
+ interface RagSource {
14905
+ rank: number;
14906
+ chunk_id?: string | null;
14907
+ rel_path?: string | null;
14908
+ symbol_name?: string | null;
14909
+ symbol_type?: string | null;
14910
+ start_line?: number | null;
14911
+ end_line?: number | null;
14912
+ score_vector?: number | null;
14913
+ score_bm25?: number | null;
14914
+ snippet: string;
14915
+ }
14916
+ /**
14917
+ * Turno della cronologia chat passato al modello LLM in modalita' RAG+LLM.
14918
+ */
14919
+ interface RagChatTurn {
14920
+ role: 'user' | 'assistant';
14921
+ content: string;
14922
+ }
14923
+ /** Payload `POST /api/Rag/Query`. */
14924
+ interface RagQueryRequest {
14925
+ query: string;
14926
+ top_k?: number;
14927
+ use_lora?: boolean;
14928
+ }
14929
+ /** Risposta `POST /api/Rag/Query`. */
14930
+ interface RagQueryResponse {
14931
+ results: RagSource[];
14932
+ }
14933
+ /** Payload `POST /api/Rag/Chat`. */
14934
+ interface RagChatRequest {
14935
+ query: string;
14936
+ history?: RagChatTurn[];
14937
+ top_k?: number;
14938
+ model?: string;
14939
+ }
14940
+ /**
14941
+ * Risposta `POST /api/Rag/Chat`.
14942
+ *
14943
+ * Quando `mode === 'retrieval-only'`, il backend ha trovato `ANTHROPIC_API_KEY`
14944
+ * mancante o ha avuto un errore di chiamata Claude: `answer` e' null e
14945
+ * `warning` contiene la causa. I `sources` sono comunque popolati.
14946
+ */
14947
+ interface RagChatResponse {
14948
+ mode: 'rag-llm' | 'retrieval-only';
14949
+ answer: string | null;
14950
+ sources: RagSource[];
14951
+ warning?: string | null;
14952
+ model?: string | null;
14953
+ tokens_in?: number | null;
14954
+ tokens_out?: number | null;
14955
+ }
14956
+ /** Risposta `GET /api/Rag/Health`. */
14957
+ interface RagHealthResponse {
14958
+ status: string;
14959
+ llm_enabled: boolean;
14960
+ docs_loaded: number;
14961
+ translate_cache_size: number;
14962
+ loaded_at?: number | null;
14963
+ default_model: string;
14964
+ }
14965
+ /**
14966
+ * Service tipizzato sopra `RagController` C# che a sua volta proxa il server
14967
+ * Python `rag_server.py`. Tutte le chiamate viaggiano con il cookie di sessione
14968
+ * `k-user` (auth gia' enforced dal middleware globale di KonvergenceCore).
14969
+ *
14970
+ * Il path API e' hardcoded su `/api/Rag/...` (path-relative al backend WUIC),
14971
+ * coerente con la skill `rag-chatbot-creation` che richiede WUIC-specific
14972
+ * deployment, non OEM.
14973
+ */
14974
+ declare class WuicRagService {
14975
+ private http;
14976
+ constructor(http: HttpClient);
14977
+ /**
14978
+ * Esegue una query di sola retrieval (top-K chunk) sul codebase.
14979
+ *
14980
+ * @param query Testo della query (italiano o inglese; il server traduce IT->EN dalla cache).
14981
+ * @param options `top_k` (default 8), `use_lora` (default true).
14982
+ */
14983
+ query(query: string, options?: {
14984
+ topK?: number;
14985
+ useLora?: boolean;
14986
+ }): Observable<RagQueryResponse>;
14987
+ /** Variant Promise di {@link query}. */
14988
+ queryAsync(query: string, options?: {
14989
+ topK?: number;
14990
+ useLora?: boolean;
14991
+ }): Promise<RagQueryResponse>;
14992
+ /**
14993
+ * Esegue una chat completa (RAG + Claude). Se il server non ha
14994
+ * `ANTHROPIC_API_KEY`, il backend degrada automaticamente in
14995
+ * modalita' `retrieval-only` (controlla `response.mode`).
14996
+ *
14997
+ * @param query Domanda dell'utente.
14998
+ * @param history Cronologia di messaggi precedenti (per multi-turn).
14999
+ * @param options `top_k` (default 5), `model` (default `claude-haiku-4-5-20251001`).
15000
+ */
15001
+ chat(query: string, history?: RagChatTurn[], options?: {
15002
+ topK?: number;
15003
+ model?: string;
15004
+ }): Observable<RagChatResponse>;
15005
+ /** Variant Promise di {@link chat}. */
15006
+ chatAsync(query: string, history?: RagChatTurn[], options?: {
15007
+ topK?: number;
15008
+ model?: string;
15009
+ }): Promise<RagChatResponse>;
15010
+ /**
15011
+ * Stato del server RAG (status, LLM enabled, chunks indicizzati).
15012
+ *
15013
+ * Usato dal componente `<wuic-rag-chatbot>` per decidere se mostrare il
15014
+ * badge "RAG+LLM" o "retrieval-only" e per disabilitare la mode `chat` se
15015
+ * il backend non ha la API key configurata.
15016
+ */
15017
+ health(): Observable<RagHealthResponse>;
15018
+ /** Variant Promise di {@link health}. */
15019
+ healthAsync(): Promise<RagHealthResponse>;
15020
+ /**
15021
+ * Forza il reload dell'indice + LoRA del server Python. Da chiamare dopo
15022
+ * la skill `rag-rebuild-pipeline` per evitare di dover restartare il
15023
+ * processo uvicorn.
15024
+ */
15025
+ reload(): Observable<{
15026
+ status: string;
15027
+ docs_loaded: number;
15028
+ llm_enabled: boolean;
15029
+ }>;
15030
+ /**
15031
+ * Costruisce l'URL `<api_base>Rag/<action>` rispettando l'eventuale
15032
+ * `WtoolboxService.appSettings.api_url` configurato lato runtime (stesso
15033
+ * pattern di NotificationRealtimeService).
15034
+ */
15035
+ private buildUrl;
15036
+ private buildApiBaseUrl;
15037
+ static ɵfac: i0.ɵɵFactoryDeclaration<WuicRagService, never>;
15038
+ static ɵprov: i0.ɵɵInjectableDeclaration<WuicRagService>;
15039
+ }
15040
+
15041
+ /**
15042
+ * Singolo turno della conversazione visualizzato nel chatbot.
15043
+ *
15044
+ * Differenza con `RagChatTurn` (passato all'API): qui ci sono anche i meta
15045
+ * per il rendering UI -- sources, modalita' del backend, warning, errori,
15046
+ * stato di loading.
15047
+ */
15048
+ interface RagChatbotTurn {
15049
+ role: 'user' | 'assistant';
15050
+ content: string;
15051
+ loading?: boolean;
15052
+ mode?: 'rag-llm' | 'retrieval-only' | null;
15053
+ sources?: RagSource[];
15054
+ warning?: string | null;
15055
+ errorMessage?: string | null;
15056
+ tokensIn?: number | null;
15057
+ tokensOut?: number | null;
15058
+ }
15059
+ /**
15060
+ * Componente standalone che espone una chat sopra il RAG del codebase WUIC.
15061
+ *
15062
+ * Modalita':
15063
+ * - `auto` : usa chat (RAG+LLM) se il backend ha l'API key Claude, altrimenti retrieval pure
15064
+ * - `chat` : forza la modalita' RAG+LLM (mostra errore se LLM non disponibile)
15065
+ * - `retrieval`: forza la modalita' retrieval pure (top-K snippets)
15066
+ *
15067
+ * Auth: tutte le chiamate passano per `WuicRagService` che a sua volta usa
15068
+ * `withCredentials: true` per inviare il cookie di sessione `k-user`.
15069
+ *
15070
+ * Per uso, vedi la skill `rag-chatbot-creation` e la pagina di docs framework.
15071
+ */
15072
+ declare class WuicRagChatbotComponent implements OnInit {
15073
+ private readonly ragService;
15074
+ /** Titolo mostrato nell'header del chatbot. */
15075
+ title: string;
15076
+ /** Modalita' operativa: vedi nota nella classDoc. */
15077
+ mode: 'auto' | 'chat' | 'retrieval';
15078
+ /** Numero di chunk top-K da chiedere al RAG (default 5). */
15079
+ topK: number;
15080
+ /** Mostra/nasconde i source chip nei messaggi assistant. */
15081
+ showSources: boolean;
15082
+ /** Numero massimo di turni di history mantenuti (default 20). */
15083
+ maxHistory: number;
15084
+ /** Placeholder dell'input. */
15085
+ placeholder: string;
15086
+ /** Modello Claude da usare in modalita' chat (default haiku 4.5). */
15087
+ model: string;
15088
+ /** Altezza fissa dell'area chat in CSS units (default `420px`). */
15089
+ chatHeight: string;
15090
+ /** Mostra il bottone "Svuota cronologia" nell'header. */
15091
+ showClearButton: boolean;
15092
+ /** Emette quando l'utente clicca su un source chip. */
15093
+ resultSelected: EventEmitter<RagSource>;
15094
+ /** Emette in caso di errore HTTP non recuperabile. */
15095
+ errorOccurred: EventEmitter<{
15096
+ message: string;
15097
+ details?: unknown;
15098
+ }>;
15099
+ /** Emette dopo ogni turno (user o assistant) aggiunto alla history. */
15100
+ turnAdded: EventEmitter<RagChatbotTurn>;
15101
+ history: RagChatbotTurn[];
15102
+ inputValue: string;
15103
+ loading: boolean;
15104
+ healthInfo: RagHealthResponse | null;
15105
+ healthError: string | null;
15106
+ inputTextarea?: ElementRef<HTMLTextAreaElement>;
15107
+ scrollContainer?: ElementRef<HTMLElement>;
15108
+ constructor(ragService: WuicRagService);
15109
+ ngOnInit(): void;
15110
+ /**
15111
+ * Modalita' effettivamente usata per la prossima chiamata, dopo aver
15112
+ * considerato il valore di `mode` e lo stato di `healthInfo.llm_enabled`.
15113
+ */
15114
+ get effectiveMode(): 'rag-llm' | 'retrieval-only';
15115
+ /** Etichetta del badge in alto a destra. */
15116
+ get modeBadgeLabel(): string;
15117
+ /** Severity del badge (PrimeNG severity). */
15118
+ get modeBadgeSeverity(): 'success' | 'info' | 'warn' | 'danger';
15119
+ /** Disabilita il send button quando appropriato. */
15120
+ get sendDisabled(): boolean;
15121
+ /**
15122
+ * Invia la query corrente al backend secondo `effectiveMode` e aggiunge
15123
+ * il turno utente + il turno assistant (placeholder loading) alla history.
15124
+ */
15125
+ onSend(): Promise<void>;
15126
+ /**
15127
+ * Svuota la cronologia chat. Usa `WtoolboxService.promptDialog` come da
15128
+ * regola 12 di AGENTS (no native confirm/prompt).
15129
+ */
15130
+ onClearHistory(): Promise<void>;
15131
+ /**
15132
+ * Click su un source chip: emette il source verso il padre e tenta di
15133
+ * aprire VS Code via deep-link `vscode://file/<abs>:<line>` se disponibile.
15134
+ * Il padre puo' override-are il comportamento intercettando l'output.
15135
+ */
15136
+ onSourceClick(source: RagSource): void;
15137
+ /** Etichetta breve per un source (path::symbol oppure solo path). */
15138
+ sourceLabel(source: RagSource): string;
15139
+ /** Tooltip esteso per un source (path completo + line). */
15140
+ sourceTooltip(source: RagSource): string;
15141
+ /** Gestisce Enter (send) vs Shift+Enter (newline). */
15142
+ onKeyDown(event: KeyboardEvent): void;
15143
+ private runChatTurn;
15144
+ private runRetrievalTurn;
15145
+ /**
15146
+ * Costruisce un summary testuale dei top-K chunk in modalita' retrieval-only.
15147
+ * Usato sia quando il backend e' senza Claude sia per la modalita' `mode='retrieval'`.
15148
+ */
15149
+ private buildRetrievalSummary;
15150
+ private trimHistory;
15151
+ private scheduleScrollToBottom;
15152
+ private focusInput;
15153
+ private extractErrorMessage;
15154
+ static ɵfac: i0.ɵɵFactoryDeclaration<WuicRagChatbotComponent, never>;
15155
+ static ɵcmp: i0.ɵɵComponentDeclaration<WuicRagChatbotComponent, "wuic-rag-chatbot", never, { "title": { "alias": "title"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "topK": { "alias": "topK"; "required": false; }; "showSources": { "alias": "showSources"; "required": false; }; "maxHistory": { "alias": "maxHistory"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "model": { "alias": "model"; "required": false; }; "chatHeight": { "alias": "chatHeight"; "required": false; }; "showClearButton": { "alias": "showClearButton"; "required": false; }; }, { "resultSelected": "resultSelected"; "errorOccurred": "errorOccurred"; "turnAdded": "turnAdded"; }, never, never, true, never>;
15156
+ }
15157
+
15158
+ /**
15159
+ * localStorage key used to pass the logout reason across the full
15160
+ * page reload so the login form can display a user-friendly message.
15161
+ * Written in the `finally` callback AFTER legacyLogout (which clears
15162
+ * localStorage) but BEFORE the redirect. Read and removed by
15163
+ * AuthSessionService.initialize on the next page load.
15164
+ */
15165
+ declare const AUTH_REDIRECT_REASON_KEY = "wuic_auth_redirect_reason";
15166
+ /**
15167
+ * HTTP interceptor that detects 401 (Unauthorized) responses and
15168
+ * triggers an automatic logout + full page redirect to `/`.
15169
+ *
15170
+ * This is critical for `enableCookieAuthentication=true`: the
15171
+ * server-managed HttpOnly cookie can expire (via `sessionTimeoutMinutes`)
15172
+ * while the client-side session snapshot in sessionStorage is still
15173
+ * populated. Without this interceptor, expired sessions produce a
15174
+ * generic error dialog instead of a clean redirect to login.
15175
+ *
15176
+ * When the 401 carries a `session_replaced` reason (another browser
15177
+ * logged in with the same user, overwriting the token), the reason is
15178
+ * persisted to localStorage (survives the session clear) and displayed
15179
+ * by the login form after the redirect.
15180
+ *
15181
+ * Auth-related endpoints (login, logout, me) are excluded to avoid
15182
+ * infinite loops when the logout call itself returns 401.
15183
+ *
15184
+ * ALL 401 responses on non-auth endpoints are swallowed (including
15185
+ * concurrent ones while logout is in progress) to prevent the
15186
+ * GlobalHandler from showing error dialogs during the redirect.
15187
+ */
15188
+ declare const authExpiredInterceptor: HttpInterceptorFn;
15189
+
14365
15190
  declare const routes: Routes;
14366
15191
 
14367
15192
  declare function loadTextEditorComponent(): Promise<typeof wuic_framework_lib.TextEditorComponent>;
@@ -14416,5 +15241,20 @@ declare class GetSrcUploadPreviewPipe implements PipeTransform {
14416
15241
  static ɵpipe: i0.ɵɵPipeDeclaration<GetSrcUploadPreviewPipe, "getSrcUploadPreview", true>;
14417
15242
  }
14418
15243
 
14419
- export { AuthSessionService, BooleanEditorComponent, BoundedRepeaterComponent, ButtonEditorComponent, CallbackPipe, CallbackPipe2, CarouselListComponent, ChartListComponent, CodeAreaEditorComponent, CodeEditorComponent, ColorEditorComponent, CustomException, DataActionButtonComponent, DataRepeaterComponent, DataSourceComponent, DateEditorComponent, DesignerRouteComponent, DictionaryEditorComponent, DynamicRowTemplateComponent, EditorOptions, FieldEditorComponent, FilterBarComponent, FormatGridViewValuePipe, FrameworkDocsComponent, GetSrcUploadPreviewPipe, GlobalHandler, HtmlEditorComponent, ImageWrapperComponent, ImportExportButtonComponent, IsSelectedRowPipe, KanbanListComponent, KanbanOptions, KanbanStatusColumnItem, LazyDataActionButtonComponent, LazyDataSourceComponent, LazyFieldEditorComponent, LazyImageWrapperComponent, LazyKanbanListComponent, LazyMetaMenuComponent, ListGridComponent, LookupEditorComponent, MapListComponent, MetaInfo, MetaMenuComponent, MetadataEditorService, MetadataProviderService, MetadatiColonna, NotificationBellComponent, NotificationRealtimeService, NumberEditorComponent, PagerComponent, ParametricDialogComponent, PivotBuilderComponent, PropertyArrayEditorComponent, PropertyObjectEditorComponent, ReportDesignerComponent, ReportViewerComponent, SchedulerListComponent, SpreadsheetListComponent, TextAreaEditorComponent, TextEditorComponent, TranslationManagerService, TreeListComponent, TreeViewSelectorComponent, UploadEditorComponent, ValidationRule, ValueChangedPayload, VisibleFieldListPipe, WidgetDefinition, WorkflowDesignerComponent, WorkflowDesignerRouteComponent, WorkflowRunnerComponent, WorkflowRuntimeMetadataService, WtoolboxService, boundedRepeaterPendingChangesGuard, loadBooleanEditorComponent, loadButtonEditorComponent, loadCodeAreaEditorComponent, loadColorEditorComponent, loadDateEditorComponent, loadDictionaryEditorComponent, loadHtmlEditorComponent, loadLookupEditorComponent, loadNumberEditorComponent, loadPropertyArrayEditorComponent, loadPropertyObjectEditorComponent, loadTextAreaEditorComponent, loadTextEditorComponent, loadTreeViewSelectorComponent, loadUploadEditorComponent, menuRouteAccessCanActivateGuard, menuRouteAccessCanMatchGuard, routes };
14420
- export type { AuthSessionState, DataSourceAfterSyncEvent, DataSourceBeforeSyncEvent, DataSourceSyncOperation, IDataBoundHostComponent, IFieldEditor, KanbanStatusColumn, ListGridAfterRenderEvent, ListGridAfterRowRenderEvent, ListGridBeforeRowRenderEvent, NotificationItem, RealtimeProgressEvent, WorkflowRuntimeLinkedActionRouteMetadataEntry, WorkflowRuntimePreviousRouteNodeEntry, WorkflowRuntimeRouteMetadataEntry, WorkflowRuntimeRouteNodePayloadEntry };
15244
+ type ThemePresetName = 'aura' | 'lara' | 'nora' | 'material';
15245
+ type ThemePrimaryName = 'blue' | 'emerald' | 'violet' | 'amber' | 'cyan' | 'teal' | 'indigo' | 'rose' | 'pink' | 'lime';
15246
+ interface ThemeOption {
15247
+ label: string;
15248
+ value: string;
15249
+ preset: ThemePresetName;
15250
+ primary: ThemePrimaryName;
15251
+ primaryHex: string;
15252
+ isHighContrast?: boolean;
15253
+ }
15254
+ declare const PRIMARY_PALETTES: Record<ThemePrimaryName, Record<string, string>>;
15255
+ declare const THEME_OPTIONS: ThemeOption[];
15256
+ declare function getThemeOptions(): ThemeOption[];
15257
+ declare function getThemePrimaryHex(value: string): string;
15258
+
15259
+ export { AUTH_REDIRECT_REASON_KEY, AppSettingsEditorComponent, AuthSessionService, BooleanEditorComponent, BoundedRepeaterComponent, ButtonEditorComponent, CallbackPipe, CallbackPipe2, CarouselListComponent, ChartListComponent, CodeAreaEditorComponent, CodeEditorComponent, ColorEditorComponent, CustomException, DataActionButtonComponent, DataRepeaterComponent, DataSourceComponent, DateEditorComponent, DesignerRouteComponent, DictionaryEditorComponent, DynamicRowTemplateComponent, EditorOptions, FieldEditorComponent, FilterBarComponent, FormatGridViewValuePipe, FrameworkDocsComponent, GetSrcUploadPreviewPipe, GlobalHandler, HtmlEditorComponent, ImageWrapperComponent, ImportExportButtonComponent, IsSelectedRowPipe, KanbanListComponent, KanbanOptions, KanbanStatusColumnItem, LazyDataActionButtonComponent, LazyDataSourceComponent, LazyFieldEditorComponent, LazyImageWrapperComponent, LazyKanbanListComponent, LazyMetaMenuComponent, ListGridComponent, LookupEditorComponent, MapListComponent, MetaInfo, MetaMenuComponent, MetadataEditorService, MetadataProviderService, MetadatiColonna, NotificationBellComponent, NotificationRealtimeService, NumberEditorComponent, PRIMARY_PALETTES, PagerComponent, ParametricDialogComponent, PivotBuilderComponent, PropertyArrayEditorComponent, PropertyObjectEditorComponent, ReportDesignerComponent, ReportViewerComponent, SchedulerListComponent, SpreadsheetListComponent, THEME_OPTIONS, TextAreaEditorComponent, TextEditorComponent, TranslationManagerService, TreeListComponent, TreeViewSelectorComponent, UploadEditorComponent, UserInfoService, ValidationRule, ValueChangedPayload, VisibleFieldListPipe, WidgetDefinition, WorkflowDesignerComponent, WorkflowDesignerRouteComponent, WorkflowRunnerComponent, WorkflowRuntimeMetadataService, WtoolboxService, WuicRagChatbotComponent, WuicRagService, authExpiredInterceptor, boundedRepeaterPendingChangesGuard, getThemeOptions, getThemePrimaryHex, loadBooleanEditorComponent, loadButtonEditorComponent, loadCodeAreaEditorComponent, loadColorEditorComponent, loadDateEditorComponent, loadDictionaryEditorComponent, loadHtmlEditorComponent, loadLookupEditorComponent, loadNumberEditorComponent, loadPropertyArrayEditorComponent, loadPropertyObjectEditorComponent, loadTextAreaEditorComponent, loadTextEditorComponent, loadTreeViewSelectorComponent, loadUploadEditorComponent, menuRouteAccessCanActivateGuard, menuRouteAccessCanMatchGuard, routes };
15260
+ export type { AuthSessionState, DataSourceAfterSyncEvent, DataSourceBeforeSyncEvent, DataSourceSyncOperation, IDataBoundHostComponent, IFieldEditor, KanbanStatusColumn, ListGridAfterRenderEvent, ListGridAfterRowRenderEvent, ListGridBeforeRowRenderEvent, MultiDatasourceMeta, NotificationItem, RagChatRequest, RagChatResponse, RagChatTurn, RagChatbotTurn, RagHealthResponse, RagQueryRequest, RagQueryResponse, RagSource, RealtimeProgressEvent, ThemeOption, ThemePresetName, ThemePrimaryName, WorkflowRuntimeLinkedActionRouteMetadataEntry, WorkflowRuntimePreviousRouteNodeEntry, WorkflowRuntimeRouteMetadataEntry, WorkflowRuntimeRouteNodePayloadEntry };