wuic-framework-lib 1.0.20 → 1.1.0

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-B44k_wZe.mjs → wuic-framework-lib-chart-list.component-C9_EDkGu.mjs} +2 -2
  2. package/fesm2022/{wuic-framework-lib-code-editor.component-D1dy4Dl9.mjs → wuic-framework-lib-code-editor.component-D_p7LGSQ.mjs} +4 -4
  3. package/fesm2022/{wuic-framework-lib-designer.component-CnOQbvEH.mjs → wuic-framework-lib-designer.component-Dx6RraAn.mjs} +4 -4
  4. package/fesm2022/{wuic-framework-lib-first-run-wizard.component-C9lswoxG.mjs → wuic-framework-lib-first-run-wizard.component-Cp8IKDb9.mjs} +4 -4
  5. package/fesm2022/{wuic-framework-lib-framework-docs.component-B6qNTs5H.mjs → wuic-framework-lib-framework-docs.component-CxckBsIX.mjs} +406 -10
  6. package/fesm2022/{wuic-framework-lib-pivot-builder.component-DMk26H0M.mjs → wuic-framework-lib-pivot-builder.component-C-ceJi48.mjs} +10 -10
  7. package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-y3shST6g.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-DPZCgxOB.mjs} +3 -3
  8. package/fesm2022/{wuic-framework-lib-report-designer.component-BnngR2eL.mjs → wuic-framework-lib-report-designer.component-3-hUYft8.mjs} +2 -2
  9. package/fesm2022/{wuic-framework-lib-report-viewer.component-LGNRIQh2.mjs → wuic-framework-lib-report-viewer.component-D4QD_wPl.mjs} +2 -2
  10. package/fesm2022/{wuic-framework-lib-scheduler-list.component-DbcFMwx5.mjs → wuic-framework-lib-scheduler-list.component-C0nY8Wd6.mjs} +2 -2
  11. package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-DXyRX0YK.mjs → wuic-framework-lib-spreadsheet-list-sf.component-C9sWgq61.mjs} +443 -4
  12. package/fesm2022/{wuic-framework-lib-workflow-designer.component-Bm719AWV.mjs → wuic-framework-lib-workflow-designer.component-8mv_Rbz9.mjs} +4 -4
  13. package/fesm2022/{wuic-framework-lib-wuic-framework-lib-CGCZvtKK.mjs → wuic-framework-lib-wuic-framework-lib-DJZAYFw8.mjs} +4887 -3819
  14. package/fesm2022/wuic-framework-lib.mjs +1 -1
  15. package/package.json +1 -1
  16. package/types/wuic-framework-lib.d.ts +1575 -1005
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { ErrorHandler, Injector, OnInit, OnDestroy, ChangeDetectorRef, AfterViewInit, EventEmitter, ElementRef, NgZone, OnChanges, SimpleChanges, QueryList, ViewContainerRef, AfterViewChecked, DoCheck, TemplateRef, Type, NgModuleRef, PipeTransform } from '@angular/core';
2
+ import { ErrorHandler, Injector, OnInit, OnDestroy, ChangeDetectorRef, NgZone, AfterViewInit, EventEmitter, ElementRef, OnChanges, SimpleChanges, QueryList, AfterViewChecked, ViewContainerRef, DoCheck, TemplateRef, Type, NgModuleRef, PipeTransform } from '@angular/core';
3
3
  import * as rxjs from 'rxjs';
4
4
  import { BehaviorSubject, Subject, Observable } from 'rxjs';
5
5
  import { MenuItem, MessageService, ConfirmationService, Confirmation, TreeNode, MegaMenuItem } from 'primeng/api';
@@ -385,6 +385,29 @@ declare class UserInfo {
385
385
  lingua: Lingua;
386
386
  language?: string;
387
387
  optimisticCheckEnabled?: boolean;
388
+ /**
389
+ * Multi-tenant: id azienda attiva per la sessione corrente. Quando il
390
+ * server gira con `multiConnectionEnabled=true` e l'utente ha un
391
+ * `utenti.id_azienda` impostato (o e' un superadmin che ha selezionato
392
+ * un'azienda via `MetaService.switchAzienda`), questo campo riflette
393
+ * l'azienda. Valore `0` = "no tenant scope" (single-tenant mode oppure
394
+ * superadmin senza azienda selezionata).
395
+ *
396
+ * Usato dal client per:
397
+ * - costruire il nome del DB Dexie (`MetaDB__a${azienda_id}`,
398
+ * `WuicClientSideCrudDB__a${azienda_id}`);
399
+ * - suffissare le chiavi `localStorage` di metadata / settings utente;
400
+ * - decidere se mostrare il componente `<wuic-azienda-switcher>`
401
+ * (solo se `isSuperAdmin === true`).
402
+ */
403
+ azienda_id?: number;
404
+ /**
405
+ * Mirror del flag server `Cms.multiConnectionEnabled`. Se `true`, il
406
+ * client applica lo scoping per tenant (Dexie name, localStorage keys);
407
+ * se `false`/undefined, mantiene il comportamento single-tenant
408
+ * bit-identico al pre-rollout.
409
+ */
410
+ multiConnectionEnabled?: boolean;
388
411
  constructor(params: {
389
412
  user_id: number;
390
413
  user_name: string;
@@ -396,6 +419,8 @@ declare class UserInfo {
396
419
  lingua: Lingua;
397
420
  language?: string;
398
421
  optimisticCheckEnabled?: boolean;
422
+ azienda_id?: number;
423
+ multiConnectionEnabled?: boolean;
399
424
  });
400
425
  }
401
426
 
@@ -481,6 +506,24 @@ declare class UserInfoService {
481
506
  * @returns Profilo utente corrente.
482
507
  */
483
508
  getuserInfo(): UserInfo;
509
+ /**
510
+ * Multi-tenant: ritorna l'`id_azienda` attivo per la sessione corrente,
511
+ * oppure `0` se non c'e' tenant scope (single-tenant mode oppure
512
+ * superadmin senza azienda selezionata). Wrapper safe in tutti gli stati
513
+ * (no user logged in, multiConnectionEnabled=false, ecc).
514
+ */
515
+ getCurrentAziendaId(): number;
516
+ /**
517
+ * `true` SOLO se il server e' in modalita' multi-connection E l'utente
518
+ * corrente ha un tenant scope attivo (`azienda_id > 0`). Usato dal client
519
+ * per decidere il suffisso `__a{id}` su Dexie / localStorage.
520
+ */
521
+ isTenantScoped(): boolean;
522
+ /**
523
+ * Suffisso univoco per chiavi storage / nomi Dexie quando l'utente e'
524
+ * tenant-scoped. Stringa vuota altrimenti → backward compat dei naming.
525
+ */
526
+ getTenantSuffix(): string;
484
527
  /**
485
528
  * Read path: prefer sessionStorage (source of truth, works in both cookie
486
529
  * modes) and fall back to the JS-readable cookie when sessionStorage is
@@ -620,6 +663,25 @@ declare class TranslationManagerService {
620
663
  * Legge/scrive dati persistenti su storage browser.
621
664
  */
622
665
  loadTranslations(): Promise<void>;
666
+ /**
667
+ * Revalidate background: rifetcha la tabella traduzioni dal backend SENZA
668
+ * bloccare l'UI. Confronta size + contenuto (hash leggero su `id,resource,
669
+ * translation`) con la tabella attualmente in memoria; se differente,
670
+ * sostituisce + `syncNgxTranslate()` cosi' il translate pipe rivaluta
671
+ * automaticamente via evento `onTranslationChange`. Usato dal branch cache-
672
+ * hit di `ensureTranslationsLoaded` per propagare key aggiunte/modificate
673
+ * lato DB dopo la prima sessione (es. scaffolding di una route nuova che
674
+ * aggiunge `menu.x.y` in `_wuic_translations`).
675
+ *
676
+ * Best-effort: errori network NON propagano. L'UI ha gia' la cache come
677
+ * fallback funzionante, una revalidate fallita non e' peggio della cache.
678
+ */
679
+ private revalidateCacheInBackground;
680
+ /**
681
+ * Fingerprint deterministico di una tabella traduzioni. Usato per decidere
682
+ * se la cache differisce dal backend senza confronto byte-a-byte.
683
+ */
684
+ private computeTableFingerprint;
623
685
  /**
624
686
  * Controlla che la translationTable contenga le chiavi indispensabili per
625
687
  * renderizzare il form di login senza chiavi grezze visibili. Se anche una
@@ -2334,6 +2396,24 @@ declare class MetadatiTabella {
2334
2396
  md_inline_cell_editing: boolean;
2335
2397
  md_batch_save: boolean;
2336
2398
  md_props_bag: any;
2399
+ /**
2400
+ * Phase I.3 — Custom Attributes integration (W0.1 = A full parity).
2401
+ * Quando valorizzato (es. 'program', 'project', 'resource', 'scenario',
2402
+ * 'xbs_node'), il framework attiva il pattern "custom attributes runtime"
2403
+ * per questa route:
2404
+ * - `<wuic-parametric-dialog>` renderizza inline i CA della entity corrente
2405
+ * chiamando `CustomAttributesService.resolve(context, scope)`.
2406
+ * - `<wuic-list-grid>` accetta filter tokens `CA_<code>___value` e
2407
+ * `CS_<code>___order` per filtrare/ordinare per Custom Value.
2408
+ * - Save batch su entity invoca anche `CustomAttributesService.upsert()`
2409
+ * per gli eventuali CV editati.
2410
+ *
2411
+ * App-side: ogni app che vuole usare i CA deve avere le 5 tabelle
2412
+ * `core.custom_attribute*` (Phase I.1 schema) + endpoint
2413
+ * `/api/custom-attributes/*` (Phase I.2 controller). Backward-compat:
2414
+ * route che NON settano questo campo si comportano esattamente come prima.
2415
+ */
2416
+ custom_attribute_context: string;
2337
2417
  md_hide_select_all_check: boolean;
2338
2418
  md_multiple_radio_selection: boolean;
2339
2419
  md_persist_row_selection_accross_paging: boolean;
@@ -2759,6 +2839,33 @@ declare class MetadataProviderService {
2759
2839
  * @returns Istanza Dexie `MetaDB`.
2760
2840
  */
2761
2841
  static getMetaDB(): Promise<any>;
2842
+ /**
2843
+ * Calcola il nome del DB Dexie metadata tenant-scoped per l'utente
2844
+ * corrente. Read-only, statico, niente Angular DI: leggiamo direttamente
2845
+ * lo snapshot UserInfo da `sessionStorage` (chiave `k-user-memory`,
2846
+ * mirror-ata anche da UserInfoService).
2847
+ *
2848
+ * Regola: `MetaDB__a{azienda_id}` quando
2849
+ * `userInfo.multiConnectionEnabled === true` E `azienda_id > 0`. In tutti
2850
+ * gli altri casi (single-tenant, utente non loggato, superadmin senza
2851
+ * azienda selezionata) ritorna `MetaDB` — backward compat con installazioni
2852
+ * pre-multi-tenant.
2853
+ *
2854
+ * Inline helper qui dentro evita di importare `UserInfoService` (che ha
2855
+ * dipendenze su CookieService) in un metodo statico.
2856
+ */
2857
+ static resolveTenantDbName(baseName?: string): string;
2858
+ /**
2859
+ * Cleanup orfani di Dexie tenant-scoped. Drop di tutti i DB
2860
+ * `MetaDB__a*` e `WuicClientSideCrudDB__a*` il cui suffisso non
2861
+ * corrisponde all'azienda attiva. Da invocare all'avvio app (post-`me()`
2862
+ * hydration) per evitare accumulo di DB di tenant precedenti quando un
2863
+ * superadmin switcha frequentemente.
2864
+ *
2865
+ * No-op se `indexedDB.databases()` non e' supportato (Safari < 15) — in
2866
+ * quel caso i DB orfani restano ma non si rompe nulla.
2867
+ */
2868
+ static cleanupOrphanTenantDbs(currentAziendaId: number): Promise<void>;
2762
2869
  /**
2763
2870
  * Inizializza (o riusa) il database Dexie `MetaDB` con lo schema metadata richiesto dalla versione passata.
2764
2871
  * Configura tabelle/indici per colonne, tabelle, stili, autorizzazioni, condition group e custom actions.
@@ -2810,7 +2917,17 @@ declare class MetadataProviderService {
2810
2917
  */
2811
2918
  private isClientSideCrudModeEnabled;
2812
2919
  /**
2813
- * Costruisce la chiave cache menu utente (`menu_{userId}`) usata per persistenza localStorage.
2920
+ * Multi-tenant: suffisso tenant per la chiave locale corrente. Mirror di
2921
+ * `UserInfoService.getTenantSuffix()` ma legge sessionStorage direttamente
2922
+ * per evitare DI Angular in metodi statici / helper privati. Empty quando
2923
+ * il flag server `multiConnectionEnabled` e' off oppure non c'e' tenant
2924
+ * scope (`azienda_id = 0`) → backward compat keys originali.
2925
+ */
2926
+ private getTenantSuffix;
2927
+ /**
2928
+ * Costruisce la chiave cache menu utente. Tenant-scoped quando l'utente
2929
+ * e' su un tenant (`menu_{userId}__a{aziendaId}`), plain altrimenti
2930
+ * (`menu_{userId}`) per backward compat single-tenant.
2814
2931
  * @param userId Identificativo utente usato per contesto e persistenza.
2815
2932
  * @returns Chiave localStorage della cache menu.
2816
2933
  */
@@ -2901,7 +3018,7 @@ declare class MetadataProviderService {
2901
3018
  * @param col Metadato colonna da analizzare.
2902
3019
  * @returns Nome tipo TypeScript stimato (`string`, `number`, `boolean`, `Date`, `any`).
2903
3020
  */
2904
- static getTSTypeFromMetaColumn(col: MetadatiColonna): "string" | "any" | "boolean" | "number" | "Date";
3021
+ static getTSTypeFromMetaColumn(col: MetadatiColonna): "string" | "number" | "any" | "boolean" | "Date";
2905
3022
  /**
2906
3023
  * Normalizza e arricchisce i metadata colonna/tabella: ordina campi, inizializza callback dinamiche, parse di bag JSON
2907
3024
  * e garantisce fallback robusti per funzioni custom non compilabili.
@@ -3725,6 +3842,17 @@ declare class ClientSideCrudService {
3725
3842
  private db?;
3726
3843
  private dbInitPromise?;
3727
3844
  private readonly localModePrefix;
3845
+ /**
3846
+ * Multi-tenant: ritorna il nome Dexie tenant-scoped per l'utente corrente.
3847
+ * Mirror di `MetadataProviderService.resolveTenantDbName` per evitare un
3848
+ * import cross-service (questi due servizi non dovrebbero dipendere
3849
+ * l'uno dall'altro).
3850
+ *
3851
+ * `<baseName>__a{azienda_id}` quando `multiConnectionEnabled` e' attivo
3852
+ * e l'utente ha `azienda_id > 0`. Altrimenti `<baseName>` → backward
3853
+ * compat bit-identica.
3854
+ */
3855
+ static resolveTenantDbName(baseName: string): string;
3728
3856
  /**
3729
3857
  * Inizializza una sola volta il database Dexie locale (`WuicClientSideCrudDB`) e ne riusa l'istanza.
3730
3858
  * @returns Istanza DB locale usata per cache/sync CRUD client-side.
@@ -3782,6 +3910,12 @@ declare class ClientSideCrudService {
3782
3910
  * @param userId Identificativo utente usato per contesto e persistenza.
3783
3911
  * @returns Chiave storage del flag modalita locale.
3784
3912
  */
3913
+ /**
3914
+ * Suffisso tenant per la chiave locale (`__a{azienda_id}`) quando l'utente
3915
+ * e' su un tenant + server in modalita' multi-connection. Stringa vuota
3916
+ * altrimenti → backward compat single-tenant.
3917
+ */
3918
+ private getTenantSuffix;
3785
3919
  private getModeKey;
3786
3920
  /**
3787
3921
  * Attiva/disattiva il flag modalita CRUD locale per route+utente in localStorage.
@@ -5262,611 +5396,1208 @@ declare class LazyDataSourceComponent implements OnInit {
5262
5396
  static ɵcmp: i0.ɵɵComponentDeclaration<LazyDataSourceComponent, "wuic-data-source-lazy", never, { "route": { "alias": "route"; "required": false; }; "routeFromRouting": { "alias": "routeFromRouting"; "required": false; }; "hardcodedRoute": { "alias": "hardcodedRoute"; "required": false; }; "autoload": { "alias": "autoload"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "changeTracking": { "alias": "changeTracking"; "required": false; }; "parentRecord": { "alias": "parentRecord"; "required": false; }; "parentMetaInfo": { "alias": "parentMetaInfo"; "required": false; }; "parentDatasource": { "alias": "parentDatasource"; "required": false; }; "componentRef": { "alias": "componentRef"; "required": false; }; }, {}, never, never, true, never>;
5263
5397
  }
5264
5398
 
5265
- declare class DeviceAwarenessService implements OnDestroy {
5266
- private static readonly DEFAULT_BREAKPOINT_PX;
5267
- private mediaQueryList?;
5268
- private mediaQueryListener?;
5269
- private readonly isMobileSubject;
5270
- readonly isMobile$: Observable<boolean>;
5271
- constructor();
5272
- get isMobile(): boolean;
5273
- ngOnDestroy(): void;
5274
- private resolveBreakpointPx;
5275
- static ɵfac: i0.ɵɵFactoryDeclaration<DeviceAwarenessService, never>;
5276
- static ɵprov: i0.ɵɵInjectableDeclaration<DeviceAwarenessService>;
5277
- }
5278
-
5279
- interface ListGridSavedState {
5280
- id: string;
5281
- name: string;
5282
- description: string;
5283
- isDefault: boolean;
5284
- createdAt: string;
5285
- filterInfo: any;
5286
- sortInfo: any[];
5287
- pageInfo: {
5288
- currentPage: number;
5289
- pageSize: number;
5290
- };
5291
- columnWidths: {
5292
- [field: string]: number;
5293
- };
5294
- columnLayout?: ListGridColumnLayout;
5295
- }
5296
- interface ListGridColumnLayout {
5297
- order: string[];
5298
- hidden: string[];
5299
- pinnedLeft: string[];
5300
- pinnedRight: string[];
5301
- }
5302
- interface ReportVariableInput {
5303
- name: string;
5304
- alias: string;
5305
- value: string;
5306
- type?: string;
5307
- }
5308
- interface GridPendingChangeItem {
5309
- id: string;
5310
- change: TrackedChange;
5311
- label: string;
5312
- details: string;
5313
- selected: boolean;
5314
- }
5315
- interface ListGridBeforeRowRenderEvent {
5316
- row: any;
5317
- rowIndex: number;
5318
- cancel: boolean;
5319
- cancelRender: () => void;
5320
- }
5321
- interface ListGridAfterRowRenderEvent {
5322
- row: any;
5323
- rowIndex: number;
5324
- }
5325
- interface ListGridAfterRenderEvent {
5326
- rows: any[];
5327
- totalRecords: number;
5328
- metaInfo: MetaInfo;
5329
- datasource?: DataSourceComponent;
5399
+ interface AuthSessionState {
5400
+ initialized: boolean;
5401
+ loading: boolean;
5402
+ enabled: boolean;
5403
+ authenticated: boolean;
5404
+ legacyAuthenticated: boolean;
5405
+ provider?: string;
5406
+ name?: string;
5407
+ legacyName?: string;
5408
+ legacyRole?: string;
5409
+ claims?: {
5410
+ type: string;
5411
+ value: string;
5412
+ }[];
5413
+ error?: string;
5414
+ returnUrl: string;
5415
+ sessionExpiring?: boolean;
5416
+ sessionExpiresInSeconds?: number;
5330
5417
  }
5331
- declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDataBoundHostComponent {
5332
- private metaSrv;
5333
- private sanitizer;
5334
- private route;
5335
- private router;
5336
- private location;
5337
- private titleService;
5338
- private trslSrv;
5339
- private cd;
5340
- userInfo: UserInfoService;
5341
- private elementRef;
5342
- deviceAwareness: DeviceAwarenessService;
5343
- private static readonly FORCED_VIRTUALIZATION_PAGE_SIZE_THRESHOLD;
5344
- private static readonly FORCED_VIRTUALIZATION_ITEM_SIZE;
5345
- private static readonly ACTION_BUTTON_VISIBLE_ROWS_OVERSCAN;
5346
- private static readonly ACTION_BUTTON_INITIAL_VISIBLE_ROWS_FALLBACK;
5347
- private static readonly GRID_VIEW_STATES_SETTINGS_KEY;
5348
- private static readonly GRID_COLUMN_LAYOUT_SETTINGS_KEY;
5349
- private static selectButtonGuardInstalled;
5350
- private columnFilterRenderEpochByField;
5351
- private actionButtonsVisibleStartIndex;
5352
- private actionButtonsVisibleEndIndex;
5353
- private actionButtonsLimitToVisibleRows;
5354
- private actionButtonsPreLimitBeforeContainerReady;
5355
- private actionButtonsScrollContainer;
5356
- private actionButtonsScrollRafToken;
5357
- private actionButtonsScrollHandler;
5358
- private inlineCellSaveInFlightByRowKey;
5359
- private inlineCellSaveDebounceByRowKey;
5360
- private inlineCellLastChangedFieldByRowKey;
5361
- private inlineBatchOriginalByRowKey;
5362
- private inlineGridRuntimeFieldCacheByKey;
5363
- private suppressNextInlineFetchInfoRebind;
5364
- getRuntimeGridFieldMetaFn: (metaColumn: MetadatiColonna, rowData: any) => MetadatiColonna;
5365
- hardcodedRoute: string;
5366
- parentRecord: any;
5367
- parentMetaInfo: MetaInfo;
5368
- datasource: BehaviorSubject<DataSourceComponent>;
5369
- hardcodedDatasource: DataSourceComponent;
5370
- rowCustomSelect: (rowData: any, $event: any, dt: Table) => void;
5371
- hideToolbar: boolean;
5418
+ declare class AuthSessionService {
5419
+ private http;
5420
+ private userInfoService;
5421
+ private metadataProvider;
5422
+ private translationManager;
5423
+ private ngZone;
5424
+ private initialized;
5425
+ private sessionTimeoutMs;
5426
+ private sessionWarningMs;
5427
+ private sessionTimer;
5428
+ private sessionWarningTimer;
5429
+ private sessionCountdownTimer;
5430
+ private readonly stateSubject;
5431
+ readonly state$: rxjs.Observable<AuthSessionState>;
5432
+ get snapshot(): AuthSessionState;
5433
+ constructor(http: HttpClient, userInfoService: UserInfoService, metadataProvider: MetadataProviderService, translationManager: TranslationManagerService, ngZone: NgZone);
5372
5434
  /**
5373
- * Provider letto da `<wuic-import-export-button>` al click su Export XLS.
5374
- * Arrow function (NON metodo) per preservare il binding di `this` quando
5375
- * passata come Input — un metodo verrebbe richiamato col `this` del child.
5376
- * Ritorna lo stato filtri LIVE del datasource: include i filtri applicati
5377
- * via header/filter-bar che NON vengono propagati nella URL query string.
5435
+ * Allinea ngx-translate alla lingua dell'utente appena autenticato/hydratato.
5436
+ * Necessario perche' il TranslationManagerService bootstrap risolve la lingua
5437
+ * via `userInfoService.getuserInfo()` quando NESSUN utente e' ancora loggato,
5438
+ * finendo di default su `navigator.language` o 'it-IT'. Senza questa call
5439
+ * esplicita post-login, le traduzioni rese dal primo render (toolbar, menu,
5440
+ * dialog) restano "appiccicate" alla lingua di bootstrap finche' l'utente
5441
+ * non cambia lingua manualmente dal selettore, che invece chiama direttamente
5442
+ * `useLanguage()`. Chiamata best-effort: fallisce silenzioso se la lingua non
5443
+ * e' supportata o la tabella traduzioni non e' ancora pronta.
5378
5444
  */
5379
- getCurrentFilterInfoForExport: () => any;
5445
+ private applyUserLanguageToTranslations;
5380
5446
  /**
5381
- * Evento emesso subito prima del rendering logico della singola riga.
5382
- * Il consumer puo annullare la riga chiamando `cancelRender()`.
5447
+ * Inizializza il servizio una sola volta (o forzatamente) e carica lo stato sessione corrente via `refreshAll`.
5448
+ * @param force Se `true` forza una nuova inizializzazione anche se gia avvenuta.
5383
5449
  */
5384
- onBeforeRowRender: EventEmitter<ListGridBeforeRowRenderEvent>;
5450
+ initialize(force?: boolean): Promise<void>;
5385
5451
  /**
5386
- * Evento emesso subito dopo il rendering logico della singola riga.
5452
+ * Hydrates the UI-side user snapshot from the backend when sessionStorage
5453
+ * is empty but a server-managed HttpOnly `k-user` cookie might still be
5454
+ * valid. This is the critical step for `enableCookieAuthentication=true`:
5455
+ * after a browser restart (or new tab) sessionStorage is gone, the cookie
5456
+ * is HttpOnly and invisible to JS, so without this call the guard would
5457
+ * wrongly redirect to `/unauthorized` despite a valid session.
5458
+ *
5459
+ * Flow:
5460
+ * 1. If sessionStorage already has a snapshot → no hydration needed.
5461
+ * 2. Otherwise call `MetaService.me` with `withCredentials:true`. The
5462
+ * backend reads the HttpOnly cookie server-side and returns the
5463
+ * public user fields (and `cookieAuthEnabled` for introspection).
5464
+ * 3. If `me()` returns a populated payload, write it to sessionStorage
5465
+ * via `userInfoService.setUserInfoCookie` so subsequent calls see
5466
+ * the user. If `me()` returns an empty object `{}` (no valid
5467
+ * cookie) the hydration is a no-op and the UI stays logged out.
5468
+ *
5469
+ * Errors are swallowed on purpose: if `me()` throws (network, backend
5470
+ * down, legacy backend without the endpoint), we fall back to whatever
5471
+ * the cookie/sessionStorage already has without blocking the boot.
5387
5472
  */
5388
- onAfterRowRender: EventEmitter<ListGridAfterRowRenderEvent>;
5473
+ private hydrateFromServerCookie;
5389
5474
  /**
5390
- * Evento emesso al termine del ciclo di binding dati della griglia.
5475
+ * Ricalcola lo stato autenticazione combinando configurazione OAuth, endpoint `Auth/Enabled`, endpoint `Auth/Me`
5476
+ * e fallback sessione legacy (`k-user`), poi sincronizza eventuali custom settings utente.
5391
5477
  */
5392
- onAfterRender: EventEmitter<ListGridAfterRenderEvent>;
5478
+ refreshAll(): Promise<void>;
5393
5479
  /**
5394
- * Evento emesso su paging (evento p-table onPage).
5480
+ * Aggiorna il `returnUrl` nello stato sessione applicando normalizzazione anti-open-redirect.
5481
+ * @param returnUrl URL di ritorno post login/logout.
5395
5482
  */
5396
- onPaging: EventEmitter<any>;
5483
+ setReturnUrl(returnUrl: string): void;
5397
5484
  /**
5398
- * Evento emesso su sorting (evento p-table onSort).
5485
+ * Avvia il login OAuth reindirizzando il browser a `Auth/Login` con `returnUrl` codificato.
5486
+ * @param returnUrl URL di ritorno post login/logout.
5399
5487
  */
5400
- onSorting: EventEmitter<any>;
5488
+ login(returnUrl?: string): void;
5401
5489
  /**
5402
- * Evento emesso su filtering (evento p-table onFilter).
5490
+ * Esegue logout OAuth: pulisce prima stato client (storage + DB locali) e custom settings, poi redirect a `Auth/Logout`.
5491
+ * @param returnUrl URL di ritorno post login/logout.
5403
5492
  */
5404
- onFiltering: EventEmitter<any>;
5493
+ logout(returnUrl?: string): Promise<void>;
5405
5494
  /**
5406
- * Evento emesso dopo un refresh esplicito (click su bottone "Aggiorna"
5407
- * del toolbar o invocazione di `refresh()` da codice). Gli host in Pattern 3
5408
- * server-side possono usarlo per ri-fetchare dal loro backend custom.
5495
+ * Esegue login legacy via `MetaService.login`, interpreta le varianti payload storiche (`isLogged`, `value`, JSON string)
5496
+ * e in caso positivo salva l'utente nel cookie `k-user`.
5497
+ * @param username Username credenziale di autenticazione.
5498
+ * @param password Password credenziale di autenticazione.
5409
5499
  */
5410
- onRefresh: EventEmitter<void>;
5500
+ legacyLogin(username: string, password: string, captchaToken?: string): Promise<boolean>;
5411
5501
  /**
5412
- * Eventi p-table esposti lato host.
5413
- */
5414
- onPTableSelectionChange: EventEmitter<any>;
5415
- onPTableRowExpand: EventEmitter<TableRowExpandEvent<any>>;
5416
- onPTableRowCollapse: EventEmitter<TableRowCollapseEvent>;
5417
- onPTableColumnResize: EventEmitter<any>;
5418
- onPTableColumnReorder: EventEmitter<any>;
5419
- table: Table;
5420
- columnCtxMenu: ContextMenu;
5421
- metadataColumnsDatasource: DataSourceComponent;
5422
- gridContainerRef?: ElementRef<HTMLElement>;
5423
- tableActionsMenu: any;
5424
- /** ResizeObserver per esporre --wuic-outer-thead-h alle nested grid figlie. */
5425
- private outerTheadResizeObserver?;
5426
- private outerTheadObserveRetryTimer?;
5427
- records: any[];
5428
- cols: any[];
5429
- /**
5430
- * Constant CSS value for `<col>`/`<th>` min-width binding. Pulled into a
5431
- * field (instead of `getColumnMinWidthCss()` method) so the template binding
5432
- * `[style.min-width]="columnMinWidthCss"` resolves to a property read
5433
- * (no function call) and Angular's change-detection short-circuits when
5434
- * the value didn't change. Saves ~3 function calls per column per CD cycle
5435
- * (template uses it on `<col>`, header `<th>`, and filter row `<th>`).
5502
+ * Logout flow that works in BOTH cookie modes:
5503
+ *
5504
+ * - **Server-managed mode** (`enableCookieAuthentication=true`): the
5505
+ * `k-user` cookie is HttpOnly, so the only way to delete it is via a
5506
+ * `Set-Cookie` delete header from the server. We call
5507
+ * `MetaService.logoutSession` (parameterless) which:
5508
+ * 1. derives the user from the cookie server-side,
5509
+ * 2. wipes the DB session token via the existing `logout(user)`
5510
+ * per-DBMS dispatcher,
5511
+ * 3. emits the `Set-Cookie` delete with matching CookieOptions.
5512
+ *
5513
+ * - **Legacy mode** (`enableCookieAuthentication=false`): we still call
5514
+ * `logoutSession` because the server-side helper is idempotent in
5515
+ * legacy mode and always wipes the DB token. The local
5516
+ * `userInfoService.clearUserInfo()` then deletes the JS-readable
5517
+ * cookie + sessionStorage snapshot.
5518
+ *
5519
+ * Why not call the legacy `MetaService.logout(user)` overload? It only
5520
+ * runs the per-DBMS DB cleanup; it does NOT emit the cookie delete
5521
+ * header, so the HttpOnly cookie would survive the logout in
5522
+ * server-managed mode and the next page load would re-hydrate the
5523
+ * supposedly-logged-out user via `MetaService.me`. The new
5524
+ * `logoutSession` does both atomically.
5436
5525
  */
5437
- readonly columnMinWidthCss = "10px";
5438
- metas: MetadatiColonna[];
5439
- metaInfo: MetaInfo;
5440
- routeName: string;
5441
- actionName: string;
5442
- totalRecords: number;
5443
- pageSize: number;
5444
- rowNumber: number;
5445
- orderColumn: string;
5446
- orderDir: 'asc' | 'desc';
5447
- loading: BehaviorSubject<boolean>;
5448
- pageIndex: number;
5449
- globalFilterFields: string[];
5450
- searchValue: string;
5451
- rowTemplate: any;
5526
+ legacyLogout(): Promise<void>;
5452
5527
  /**
5453
- * Tracks whether the currently compiled `rowTemplate` is the **mobile card**
5454
- * variant (vs desktop). Decoupled from live `deviceAwareness.isMobile$`:
5455
- * il viewport puo' attraversare la soglia (es. utente ridimensiona DevTools)
5456
- * senza che il template sia ancora stato ricompilato. La classe CSS
5457
- * `wuic-list-grid-mobile` (che nasconde thead/footer/paginator e rompe la
5458
- * semantica table) deve seguire **lo stato del template compilato**, non il
5459
- * viewport live, altrimenti si vede una hybrid view (desktop header + card rows).
5528
+ * Multi-tenant: invoca `MetaService.switchAzienda` lato server per
5529
+ * cambiare l'azienda attiva della sessione corrente. Solo i superadmin
5530
+ * possono usarla — il server ritorna 401 altrimenti.
5531
+ *
5532
+ * Dopo lo switch e' OBBLIGATORIO un `window.location.reload()`:
5533
+ * - il cookie `k-user` e' stato riemesso con il nuovo `azienda_id`,
5534
+ * ma `UserInfoService` ha ancora in cache la vecchia copia;
5535
+ * - il singleton Dexie `MetaDB` punta al DB del tenant precedente,
5536
+ * `cleanupOrphanTenantDbs` lo droppa al boot successivo;
5537
+ * - tutte le pagine aperte vanno ricaricate per rifrescare menu /
5538
+ * metadata / cache locali con la tenant nuova.
5539
+ *
5540
+ * Convenzione: `idAzienda = 0` significa "torna al DB primario" (no
5541
+ * tenant scope) — utile a superadmin per amministrare il livello
5542
+ * primario senza loggare con un altro account.
5460
5543
  */
5461
- gridLayoutIsMobile: boolean;
5462
- /** @deprecated 2026-04-23 — mobile ora riusa rowTemplate del desktop. Field ancora esposto per backward-compat con host che lo leggevano. */
5463
- mobileCardComponent: any;
5464
- /** Subscription a `isMobile$` per ricompilare il rowTemplate quando il viewport attraversa la soglia mobile. */
5465
- private isMobileSubscription?;
5466
- selectedItems: any[];
5467
- expandedRows: {};
5468
- aggregates: any[];
5469
- private nestedLongDescriptionRawCache;
5470
- private nestedLongDescriptionSafeCache;
5544
+ switchAzienda(idAzienda: number): Promise<{
5545
+ ok: boolean;
5546
+ azienda_id: number;
5547
+ azienda_id_previous: number;
5548
+ } | null>;
5549
+ /**
5550
+ * Multi-tenant: legge la lista delle aziende disponibili dal server.
5551
+ * Usa l'endpoint AsmxProxy `MetaService.getCompaniesList` (legge da
5552
+ * tabella `aziende` sul DB metadati primario). Il server filtra alle
5553
+ * aziende con mapping di connessione valido (colonne
5554
+ * `Aziende.Connessione_DB_Dati` / `CONNESSIONE_DB_Meta` valorizzate)
5555
+ * quando il flag `multiConnectionEnabled` e' on.
5556
+ */
5557
+ getAvailableCompanies(): Promise<Array<{
5558
+ ID_Azienda: number;
5559
+ Nome_Azienda: string;
5560
+ }>>;
5471
5561
  /**
5472
- * Collezione dati per pending change items, consumata dal rendering e dalle operazioni del componente.
5562
+ * Pulisce lo stato runtime e le cache associate.
5563
+ * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
5564
+ * @returns Valore restituito dal metodo (Promise<void>).
5473
5565
  */
5474
- pendingChangeItems: GridPendingChangeItem[];
5475
- private syncFilterInfoQueryTimer;
5476
- private syncGridStateQueryTimer;
5477
- private suppressGridStateUrlPush;
5478
- private releaseGridStateUrlPushTimer;
5479
- private navigationTriggeredByPopstate;
5480
- private suppressNextPageOnlyQuerySync;
5481
- clientSideCrudToggleBusy: boolean;
5482
- private persistedColumnWidthsByRoute;
5483
- private persistedColumnLayoutByRoute;
5484
- private manualResizeDisablesProportionalByRoute;
5485
- private remoteColumnLayoutHydrationInFlight;
5486
- private persistedGridStatesByRoute;
5487
- private remoteGridStatesHydrationInFlight;
5488
- currentRouteSavedStates: ListGridSavedState[];
5489
- selectedSavedStateId: string;
5490
- private applyingSavedState;
5491
- readonly NEW_GRID_STATE_OPTION_ID = "__new__";
5492
- saveGridStateDialogVisible: boolean;
5493
- saveGridStateDialogSelectedId: string;
5494
- saveGridStateDialogNewName: string;
5495
- saveGridStateDialogSetAsDefault: boolean;
5496
- renameGridStateDialogVisible: boolean;
5497
- renameGridStateDialogName: string;
5498
- columnLayoutDialogVisible: boolean;
5499
- columnLayoutDraft: Array<{
5500
- field: string;
5501
- header: string;
5502
- visible: boolean;
5503
- }>;
5504
- saveStateMenuItems: MenuItem[];
5505
- columnContextMenuItems: MenuItem[];
5506
- selectedColumnForContextMenu?: MetadatiColonna;
5507
- availableReports: {
5508
- path: string;
5509
- name: string;
5510
- }[];
5511
- reportMenuItems: MenuItem[];
5512
- tableActionMenuItems: MenuItem[];
5513
- reportVariableDialogVisible: boolean;
5514
- reportVariableDialogLoading: boolean;
5515
- selectedReportNameForVariables: string;
5516
- selectedReportVariables: ReportVariableInput[];
5517
- changesDialogVisible: boolean;
5518
- changesDialogBusy: boolean;
5566
+ private clearClientRuntimeState;
5519
5567
  /**
5520
- * Proprieta di stato del componente per pending preferred state auto apply, usata dalla logica interna e dal template.
5568
+ * Pulisce lo stato runtime e le cache associate.
5569
+ * Legge/scrive dati persistenti su storage browser.
5521
5570
  */
5522
- private pendingPreferredStateAutoApply;
5571
+ private clearBrowserStorage;
5523
5572
  /**
5524
- * Proprieta di stato del componente per query param subscription, usata dalla logica interna e dal template.
5573
+ * Rimuove i dati target aggiornando lo stato del servizio.
5574
+ * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
5575
+ * @param dbName Nome database locale/remote da trattare.
5576
+ * @returns Valore restituito dal metodo (Promise<void>).
5525
5577
  */
5526
- private queryParamSubscription?;
5578
+ private deleteDexieDatabase;
5527
5579
  /**
5528
- * Proprieta di stato del componente per router events subscription, usata dalla logica interna e dal template.
5580
+ * Rimuove i dati target aggiornando lo stato del servizio.
5581
+ * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
5582
+ * @param dbName Nome database locale/remote da trattare.
5583
+ * @returns Valore restituito dal metodo (Promise<void>).
5529
5584
  */
5530
- private routerEventsSubscription?;
5585
+ private deleteIndexedDbByName;
5531
5586
  /**
5532
- * Proprieta di stato del componente per datasource ready subscription, usata dalla logica interna e dal template.
5587
+ * Carica e cache-a i custom settings dell'utente loggato in localStorage allineando il bootstrap sessione con MetadataProvider.
5533
5588
  */
5534
- private datasourceReadySubscription?;
5589
+ private bootstrapUserCustomSettings;
5535
5590
  /**
5536
- * Proprieta di stato del componente per fetch info subscription, usata dalla logica interna e dal template.
5591
+ * Configura il timeout di sessione in minuti. Chiamato dal meta-menu dopo aver letto AuthConfig.
5537
5592
  */
5538
- private fetchInfoSubscription?;
5593
+ setSessionTimeout(minutes: number, warningMinutes?: number): void;
5594
+ private activityListenersAttached;
5595
+ /** Timestamp dell'ultimo reset throttled, in ms epoch. */
5596
+ private lastActivityResetAt;
5597
+ /** Min intervallo tra reset throttled (mousemove/scroll). 1s e' un buon compromesso
5598
+ * tra responsiveness al "vero" idle e overhead da event flood. */
5599
+ private static readonly ACTIVITY_RESET_THROTTLE_MS;
5600
+ private setupActivityListeners;
5539
5601
  /**
5540
- * Proprieta di stato del componente per width defined, usata dalla logica interna e dal template.
5602
+ * Avvia/riavvia i timer di sessione. Chiamato dopo login e ad ogni attività HTTP.
5541
5603
  */
5542
- width_defined: string;
5604
+ resetSessionTimer(): void;
5605
+ private startSessionExpiryCountdown;
5606
+ private handleSessionExpired;
5607
+ private clearSessionTimers;
5608
+ private isUserAuthenticated;
5543
5609
  /**
5544
- * Proprieta di stato del componente per metadati colonna, usata dalla logica interna e dal template.
5610
+ * Applica un aggiornamento parziale allo stato `AuthSessionState` preservando le proprieta non toccate.
5611
+ * @param partial Delta stato da fondere con lo stato corrente.
5545
5612
  */
5546
- MetadatiColonna: typeof MetadatiColonna;
5547
5613
  /**
5548
- * function Object() { [native code] }
5549
- * @param metaSrv Metadati correnti usati per guidare mapping, validazioni e comportamento runtime.
5550
- * @param route Informazione di navigazione usata per risolvere la route di destinazione.
5551
- * @param router Informazione di navigazione usata per risolvere la route di destinazione.
5552
- * @param location Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5553
- * @param titleService Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5554
- * @param trslSrv Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5555
- * @param cd Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5556
- * @param userInfo Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5614
+ * Sets a user-visible error message in the auth state.
5615
+ * Used by the auth-expired interceptor to communicate the logout
5616
+ * reason (e.g. "session replaced by another login") after the
5617
+ * logout flow has completed and the login form is visible.
5557
5618
  */
5558
- constructor(metaSrv: MetadataProviderService, sanitizer: DomSanitizer, route: ActivatedRoute, router: Router, location: Location, titleService: Title, trslSrv: TranslationManagerService, cd: ChangeDetectorRef, userInfo: UserInfoService, elementRef: ElementRef<HTMLElement>, deviceAwareness: DeviceAwarenessService);
5619
+ setError(message: string): void;
5620
+ /** User-facing messages keyed by server reason code. */
5621
+ private static readonly REASON_MESSAGES;
5559
5622
  /**
5560
- * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
5623
+ * Reads and removes the redirect reason left by the auth-expired
5624
+ * interceptor in localStorage, then sets the corresponding error
5625
+ * message in the auth state so the login form displays it.
5561
5626
  */
5562
- ngOnInit(): void;
5627
+ private applyRedirectReason;
5628
+ private patchState;
5563
5629
  /**
5564
- * Gestisce la logica operativa di `ensureSelectButtonGuard` orchestrando le chiamate `call`.
5630
+ * Costruisce una struttura derivata a partire dallo stato corrente.
5631
+ * @param action Azione richiesta nel flusso corrente.
5565
5632
  */
5566
- private ensureSelectButtonGuard;
5633
+ private buildEndpoint;
5567
5634
  /**
5568
- * Completa inizializzazione dopo il rendering della view e collega riferimenti UI.
5635
+ * Costruisce una struttura derivata a partire dallo stato corrente.
5636
+ * @param fullMethodName Nome completo metodo legacy (es. `MetaService.login`).
5569
5637
  */
5570
- ngAfterViewInit(): void;
5638
+ private buildMetaAsmxEndpoint;
5571
5639
  /**
5572
- * Applica direttamente in DOM (senza Angular binding) la `<table style.width
5573
- * + min-width>` salvata in `persistedColumnWidthsByRoute` come `__tableTotalWidth`.
5574
- *
5575
- * Why direct DOM e non `[tableStyle]` binding:
5576
- * - Durante il drag PrimeNG (`columnResizeMode="expand"`) modifica
5577
- * `<table style.width>` inline. Se anche Angular setta lo stesso prop
5578
- * via binding, i due meccanismi entrano in race → comportamento di
5579
- * spalmamento osservato (il delta del drag si distribuisce tra tutte
5580
- * le colonne invece di concentrarsi su quella trascinata).
5581
- * - Direct DOM bypassa Angular CD. Lo applichiamo SOLO al boot
5582
- * (ngAfterViewInit) e dopo `parseColumns` su data refresh — non durante
5583
- * il drag — quindi nessun conflitto.
5584
- * - Senza la table.style.width esplicita, al refresh il browser fitta il
5585
- * table al container (default `min-width: 100%` PrimeNG) e shrinkka
5586
- * le colonne → la scrollbar svanisce.
5640
+ * Risolve la base URL API usata dal servizio: preferisce `appSettings.api_url`, fallback su `${window.location.origin}/api/`.
5587
5641
  */
5588
- private scheduleApplyPersistedTableWidth;
5589
- private applyPersistedTableWidth;
5642
+ private getApiBaseUrl;
5590
5643
  /**
5591
- * Ritorna la `<table style.width>` da applicare al refresh per riprodurre
5592
- * il layout end-of-drag.
5593
- *
5594
- * Strategia:
5595
- * 1. Se esiste `__tableWidth` persistito (chiave speciale catturata in
5596
- * `captureResizedColumnWidth`), usa quello — e' il valore esatto
5597
- * `oldTableWidth + delta` che PrimeNG ha applicato a fine drag.
5598
- * 2. Fallback: somma persisted col widths + frozen widths reali (DOM)
5599
- * per il caso di stati legacy salvati prima del fix.
5644
+ * Valuta una condizione booleana sullo stato o sull'input corrente.
5645
+ * @returns Valore restituito dal metodo (boolean).
5600
5646
  */
5601
- private computePersistedTableTotalWidth;
5647
+ private isOAuthEnabledInSettings;
5602
5648
  /**
5603
- * Espone l'altezza del thead OUTER (top-level grid) come CSS var `--wuic-outer-thead-h`
5604
- * sull'host element, per permettere a `position: sticky; top: var(...)` sull'inner thead
5605
- * di lasciare spazio sotto l'header outer (anch'esso sticky a top:0).
5606
- *
5607
- * Si attiva SOLO sulla grid root (non nested): le inner ListGridComponent leggono la var
5608
- * via cascade CSS dall'ancestor `wuic-list-grid` piu vicino, che corrisponde all'outer.
5649
+ * Normalizza il payload in una forma coerente per i passaggi successivi.
5650
+ * @param returnUrl URL di ritorno post login/logout.
5609
5651
  */
5610
- private observeOuterTheadHeight;
5652
+ private normalizeReturnUrl;
5611
5653
  /**
5612
- * Ricalcola l'altezza disponibile della grid al resize finestra.
5654
+ * Ritorna l'URL browser corrente usato come `returnUrl` predefinito in login/logout.
5613
5655
  */
5614
- onWindowResizeForGridLayout(): void;
5656
+ private getCurrentLocalUrl;
5615
5657
  /**
5616
- * Pianifica piu pass di sync layout per gestire render asincrono PrimeNG/pager.
5658
+ * Esegue il parsing del valore in ingresso con fallback sicuro.
5659
+ * @param raw Payload legacy da interpretare (stringa JSON, oggetto o wrapper con `value`).
5660
+ * @returns Valore restituito dal metodo (any).
5617
5661
  */
5618
- private scheduleGridViewportHeightSync;
5662
+ private parseLegacyLoginResponse;
5619
5663
  /**
5620
- * Vincola la griglia all'altezza disponibile in viewport, lasciando lo scroll al body p-table.
5664
+ * Estrae un messaggio errore leggibile da payload legacy eterogenei (raw/parsing/error/value) del login storico.
5665
+ * @param raw Payload grezzo risposta/errore.
5666
+ * @param parsed Payload gia interpretato.
5667
+ * @returns Messaggio errore normalizzato oppure `null`.
5621
5668
  */
5622
- private applyGridViewportHeight;
5669
+ private extractLegacyLoginError;
5623
5670
  /**
5624
- * Rilascia risorse e sottoscrizioni per evitare leak e stati pendenti.
5671
+ * Prova a leggere un messaggio errore da stringhe plain/JSON o da oggetti con chiavi comuni (`message`, `error`, `ExceptionMessage`).
5672
+ * @param candidate Sorgente messaggio da analizzare.
5673
+ * @returns Messaggio trovato oppure `null`.
5625
5674
  */
5626
- ngOnDestroy(): void;
5627
- getNestedLongDescriptionSafeHtml(nestedSource?: DataSourceComponent): SafeHtml | '';
5628
- private stripScriptTags;
5675
+ private readMessage;
5629
5676
  /**
5630
- * Restituisce una chiave stabile per il tracking colonne nel template,
5631
- * evitando re-render completi quando l'array visibile viene ricreato.
5677
+ * Log diagnostico opzionale del flusso login legacy, attivo solo con `appSettings.debugLegacyLogin === true`.
5678
+ * @param kind Tipo evento (`response` o `error`).
5679
+ * @param payload Payload da tracciare in console.
5632
5680
  */
5633
- getStableColumnTrackKey(col: any, index: number): string;
5681
+ private debugLegacyLogin;
5682
+ static ɵfac: i0.ɵɵFactoryDeclaration<AuthSessionService, never>;
5683
+ static ɵprov: i0.ɵɵInjectableDeclaration<AuthSessionService>;
5684
+ }
5685
+
5686
+ /**
5687
+ * Multi-tenant azienda switcher.
5688
+ *
5689
+ * Componente standalone visibile SOLO ai superadmin quando il server e' in
5690
+ * modalita' `multiConnectionEnabled`. Espone una dropdown con le aziende
5691
+ * disponibili (lette da `MetaService.getCompaniesList`, intersect con
5692
+ * mapping connection valido su Aziende) + un'opzione "Nessuna azienda" (id=0) che
5693
+ * fa tornare il superadmin al DB metadati primario (no tenant scope,
5694
+ * comportamento single-tenant).
5695
+ *
5696
+ * Lifecyle:
5697
+ * - alla creazione legge `UserInfoService` per determinare se mostrarsi;
5698
+ * - fetcha la lista aziende dal server una sola volta;
5699
+ * - su change → invoca `AuthSessionService.switchAzienda(id)` che riemette
5700
+ * il cookie e fa `window.location.reload()`.
5701
+ *
5702
+ * Drop-in usage (esempio in CrmApp / WuicTest topbar):
5703
+ * <code>&lt;wuic-azienda-switcher /&gt;</code>
5704
+ *
5705
+ * Performance:
5706
+ * - OnPush change detection;
5707
+ * - fetch one-shot al mount, niente polling;
5708
+ * - early return invisibile quando l'utente non e' superadmin → costo
5709
+ * trascurabile sulle shell che lo includono incondizionatamente.
5710
+ */
5711
+ declare class WuicAziendaSwitcherComponent implements OnInit {
5712
+ private userInfoService;
5713
+ private authSessionService;
5714
+ private cdr;
5634
5715
  /**
5635
- * Inline style per la `<p-table>` che replica il behavior runtime di PrimeNG
5636
- * `columnResizeMode="expand"`: setta `width: <sum>; min-width: <sum>` sul
5637
- * `<table>` quando esistono persisted column widths.
5638
- *
5639
- * Why: PrimeNG durante il resize "expand" applica esplicitamente questi
5640
- * stili per forzare il `<table>` a essere piu' largo del container e
5641
- * generare la scrollbar. Al refresh quegli inline styles spariscono e il
5642
- * default `table-layout: auto + min-width: 100%` fa shrinkare le colonne
5643
- * per fittare il container — la scrollbar svanisce e le widths persistite
5644
- * (settate via `<col style.width>`) vengono ignorate dal browser.
5645
- *
5646
- * Con questo binding, la `<table>` riceve gli stessi stili che PrimeNG
5647
- * applicherebbe a fine drag → table-layout puo' restare `auto` + i `<col>`
5648
- * widths vengono rispettati come hint di partenza, e il browser distribuisce
5649
- * la larghezza totale tra di loro proporzionalmente alle widths richieste.
5716
+ * True se il componente deve renderizzare la dropdown. False per
5717
+ * (a) utenti non superadmin, (b) flag `multiConnectionEnabled=false`,
5718
+ * (c) sessione anonima. Calcolato una volta a `ngOnInit`.
5650
5719
  *
5651
- * Ritorna `null` quando non ci sono persisted widths (default proportional).
5652
- */
5653
- getTableStyle(): {
5654
- [key: string]: string;
5655
- } | null;
5656
- /**
5657
- * Restituisce le classi della p-table includendo il profilo inline-cell-editing.
5658
- */
5659
- getTableStyleClass(): string;
5660
- private isNestedGridInstance;
5661
- private isInlineEditEnabled;
5662
- /**
5663
- * Gestisce la logica operativa di `subscribeToDS` in modo coerente con l'implementazione corrente.
5664
- * @returns Risultato elaborato da `subscribeToDS` e restituito al chiamante.
5665
- */
5666
- subscribeToDS(): void;
5667
- /**
5668
- * Recupera e prepara i dati richiesti dal chiamante usando i metadati per determinare chiavi, campi e comportamento runtime.
5669
- * @param metaInfo Metadati del contesto corrente usati per guidare filtri, mapping e comportamento runtime.
5670
- * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
5671
- */
5672
- /**
5673
- * Compila il `rowTemplate` corrente in base a `metaInfo` e al viewport mobile/desktop
5674
- * live (`deviceAwareness.isMobile`). Aggiorna anche il flag `gridLayoutIsMobile` che
5675
- * pilota la classe CSS `wuic-list-grid-mobile` (nasconde thead/footer/paginator e rompe
5676
- * la semantica table). Estratto in metodo dedicato per poter essere richiamato anche
5677
- * dalla subscription `isMobile$` in `ngOnInit` quando il viewport attraversa la soglia.
5720
+ * Quando `false`, l'**host element** stesso viene nascosto via
5721
+ * <see cref="hostHidden"/> HostBinding: niente margine, niente spazio
5722
+ * occupato. Cosi' chi embedda `<wuic-azienda-switcher />` in una topbar
5723
+ * non deve gestire la visibilita' del wrapper esternamente (regola DRY:
5724
+ * la condizione di mostrare/nascondere il widget e' una proprieta'
5725
+ * intrinseca del widget, non del consumer).
5678
5726
  */
5679
- private compileGridRowTemplate;
5680
- private getEffectiveGridRowTemplate;
5727
+ visible: boolean;
5681
5728
  /**
5682
- * Costruisce il row template per mobile: UNA sola <td colspan="N"> contenente
5683
- * il card layout (label/value per colonna + action button). Il row subclass
5684
- * resta compilato dallo stesso `DynamicRowTemplateComponent.
5685
- * getComponentFromTemplate` usato in desktop (selector 'tr'), solo il template
5686
- * string cambia.
5729
+ * HostBinding: applica l'attributo HTML `hidden` sull'host quando il
5730
+ * widget non deve mostrarsi. `hidden` e' un attributo standard W3C che
5731
+ * imposta `display: none` di default → l'elemento collassa dal layout
5732
+ * (margini inclusi) e non e' nemmeno tab-navigable.
5687
5733
  *
5688
- * `colspan` = numero totale di colonne del grid desktop, cosi' la <td> occupa
5689
- * tutta la larghezza della row. Il CSS `@media (max-width: 768px)` nel
5690
- * list-grid.component.scss setta `display: block` su <tr> / <td.wuic-mobile-
5691
- * card-cell> liberando dalla semantica table.
5734
+ * Ritorno: stringa vuota (presente) o null (assente). Angular gestisce
5735
+ * la presenza/assenza dell'attributo in base al valore.
5692
5736
  */
5693
- private buildMobileCardAsRowTemplate;
5737
+ get hostHidden(): string | null;
5694
5738
  /**
5695
- * Restituisce il template host solo se realmente sovrascritto rispetto al default libreria.
5739
+ * Lista delle aziende disponibili. Sempre include `{ ID_Azienda: 0,
5740
+ * Nome_Azienda: 'Nessuna azienda (DB primario)' }` come prima opzione.
5741
+ * Ogni entry puo' avere `LogoFileName` (relativo a `/assets/azienda-logos/`)
5742
+ * — quando null/missing il client fa fallback alle iniziali del nome.
5696
5743
  */
5697
- private getHostOverriddenGridRowTemplate;
5744
+ companies: Array<{
5745
+ ID_Azienda: number;
5746
+ Nome_Azienda: string;
5747
+ LogoFileName?: string | null;
5748
+ }>;
5698
5749
  /**
5699
- * Cascata mobile: host `WidgetDefinition.mobileCardTemplate` -> library default.
5700
- * Nessuna lettura da `metaInfo.tableMetadata` (no per-tabella).
5750
+ * Base path per le immagini logo aziendali. `/assets/azienda-logos/` =
5751
+ * servito staticamente da ASP.NET Core (`wwwroot/assets/azienda-logos/`).
5701
5752
  */
5702
- private getEffectiveMobileCardTemplate;
5753
+ private static readonly LOGO_BASE;
5703
5754
  /**
5704
- * Costruisce il template default per la card mobile: una card per record, con
5705
- * `data-action-button` in testa e una riga `label/value` per ogni colonna visibile.
5706
- * Riusa gli stessi switch case dei custom cell template del desktop.
5707
- * Inline editing escluso per scelta (regola: su mobile l'edit apre sempre il form).
5755
+ * ID dell'azienda attualmente selezionata. Bind two-way con la dropdown
5756
+ * PrimeNG. Inizializzato dall'`UserInfo.azienda_id` cached.
5708
5757
  */
5709
- private buildDefaultMobileCardTemplate;
5758
+ selectedAziendaId: number;
5710
5759
  /**
5711
- * Costruisce una struttura di output a partire dal contesto corrente usando i metadati per determinare chiavi, campi e comportamento runtime.
5712
- * @param columns Collezione di input processata dal metodo (normalizzazione, filtri e mapping).
5713
- * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
5760
+ * True mentre la chiamata HTTP `switchAzienda` e' in volo. Previene click
5761
+ * doppi che scatenerebbero due reload.
5714
5762
  */
5715
- private buildDefaultGridRowTemplateWithColumnTemplates;
5763
+ switching: boolean;
5716
5764
  /**
5717
- * Costruisce una struttura di output a partire dal contesto corrente normalizzando e trasformando collezioni di record.
5718
- * @param columns Collezione di input processata dal metodo (normalizzazione, filtri e mapping).
5719
- * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
5765
+ * Eventuale messaggio di errore da mostrare sotto la dropdown. Reset al
5766
+ * prossimo tentativo.
5720
5767
  */
5721
- private buildGridColumnTemplateSwitchCases;
5768
+ errorMessage: string | null;
5722
5769
  /**
5723
- * Verifica una condizione di stato o di validita orchestrando le chiamate `trim` e `String`.
5724
- * @param template Valore testuale usato come chiave, nome campo, criterio o frammento di configurazione.
5725
- * @returns Esito booleano dell'elaborazione svolta dal metodo.
5770
+ * Label leggibile dell'azienda attiva nella sessione corrente. Mostrato
5771
+ * come tooltip al hover sul widget icon-only. Aggiornato al boot e ad
5772
+ * ogni `onAziendaChange`.
5726
5773
  */
5727
- private isAngularCellMarkupTemplate;
5774
+ currentLabel: string;
5728
5775
  /**
5729
- * Trasforma i dati in una forma coerente con il rendering o con il payload richiesto orchestrando le chiamate `trim` e `String`.
5730
- * @param template Valore testuale usato come chiave, nome campo, criterio o frammento di configurazione.
5731
- * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
5776
+ * URL del logo dell'azienda attiva, oppure null per fallback icona.
5732
5777
  */
5733
- private normalizeGridCellTemplate;
5778
+ currentLogoUrl: string | null;
5779
+ constructor(userInfoService: UserInfoService, authSessionService: AuthSessionService, cdr: ChangeDetectorRef);
5780
+ ngOnInit(): Promise<void>;
5734
5781
  /**
5735
- * Esegue operazioni di persistenza/sincronizzazione in `syncTableFilterUiFromDatasource` trasformando e filtrando collezioni dati.
5782
+ * Aggiorna `currentLabel`, `currentLogoUrl` dal `selectedAziendaId`
5783
+ * corrente. Chiamato dopo fetch lista e dopo cambio selezione. Quando
5784
+ * `selectedAziendaId` non corrisponde a nessuna azienda (tipicamente 0
5785
+ * = mai assegnato), tooltip + display mostrano "Seleziona azienda…".
5736
5786
  */
5737
- private syncTableFilterUiFromDatasource;
5787
+ private refreshCurrentLabel;
5738
5788
  /**
5739
- * Allinea il sort visuale della p-table con `datasource.sortInfo`, inclusa la rimozione esplicita del descriptor.
5789
+ * True se non c'e' un'azienda selezionata valida (selectedAziendaId=0
5790
+ * o id non presente nella lista). Usato dal template per swap
5791
+ * icona/placeholder.
5740
5792
  */
5741
- private syncTableSortUiFromDatasource;
5793
+ get noSelection(): boolean;
5742
5794
  /**
5743
- * Interpreta e normalizza input/configurazione in `parseData` per l'utilizzo nel componente.
5744
- * @param data Dato/record su cui il metodo applica elaborazioni o aggiornamenti.
5745
- * @returns Struttura dati prodotta da `parseData` dopo normalizzazione/elaborazione.
5795
+ * Costruisce l'URL dell'immagine logo per l'azienda passata, o null se
5796
+ * non c'e' `LogoFileName`. URL e' assoluto relativo al root del frontend
5797
+ * (`/assets/azienda-logos/<file>`) — il dev server Angular proxa lo
5798
+ * stesso path da `wwwroot/assets/azienda-logos/` in prod.
5746
5799
  */
5747
- parseData(data: any): any;
5800
+ logoUrlFor(c: {
5801
+ LogoFileName?: string | null;
5802
+ } | undefined | null): string | null;
5748
5803
  /**
5749
- * Ricalcola lo stato `_disabled` delle azioni tabella valutando i callback di disabilitazione contro `resultInfo.current` e il contesto UI corrente.
5804
+ * Classe icona PrimeIcons di fallback quando l'azienda non ha `LogoFileName`
5805
+ * (o il file non si carica). Per le aziende reali sempre `pi-building`.
5806
+ * Per `id=0` (mai assegnato / lista vuota) `pi-question` come hint che
5807
+ * l'utente DEVE selezionare un'azienda.
5750
5808
  */
5751
- reEvaluateActionEnabledStates(): void;
5809
+ defaultIconClassFor(idAzienda: number | undefined | null): string;
5752
5810
  /**
5753
- * Ricostruisce il menu azioni tabella includendo solo le voci autorizzate/visibili e riallineando caption, stato disabled e comandi eseguibili.
5811
+ * onerror handler dell'<img> nel selectedItem template. Se il logo
5812
+ * fallisce a caricarsi (404 o broken), ricadiamo sull'icona predefinita.
5754
5813
  */
5755
- private rebuildTableActionMenuItems;
5814
+ onLogoError(): void;
5756
5815
  /**
5757
- * Gestisce la logica operativa di `onColumnHeaderContextMenu` in modo coerente con l'implementazione corrente.
5758
- * @param event Evento che innesca il comportamento del metodo.
5759
- * @param col Parametro utilizzato dal metodo nel flusso elaborativo.
5760
- * @param menu Parametro utilizzato dal metodo nel flusso elaborativo.
5816
+ * Handler del change PrimeNG. Filtra no-op (stesso valore) per evitare
5817
+ * reload infiniti se PrimeNG emette change al mount.
5761
5818
  */
5762
- onColumnHeaderContextMenu(event: MouseEvent, col: any, menu: ContextMenu): void;
5819
+ onAziendaChange(event: {
5820
+ value: number;
5821
+ }): Promise<void>;
5822
+ static ɵfac: i0.ɵɵFactoryDeclaration<WuicAziendaSwitcherComponent, never>;
5823
+ static ɵcmp: i0.ɵɵComponentDeclaration<WuicAziendaSwitcherComponent, "wuic-azienda-switcher", never, {}, {}, never, never, true, never>;
5824
+ }
5825
+
5826
+ /**
5827
+ * Phase I.3 — CustomAttributesService (framework, additive feature flag).
5828
+ *
5829
+ * Service centralizzato per leggere/scrivere Custom Attributes/Values/Lookup
5830
+ * per una entity in una route. Attivato per route con
5831
+ * `MetadatiTabella.custom_attribute_context` valorizzato.
5832
+ *
5833
+ * Backend contract (app-level, es. CostCnh `CustomAttributesController.cs`):
5834
+ * GET /api/custom-attributes/definitions?context=program
5835
+ * GET /api/custom-attributes/resolve?context=program&siteId=N&projectClassId=M
5836
+ * GET /api/custom-attributes/values?entitySchema=core&entityName=program&entityId=42
5837
+ * POST /api/custom-attributes/values (upsert batch)
5838
+ * DELETE /api/custom-attributes/values/{cvId}
5839
+ * GET /api/custom-attributes/lookup/{attributeId}
5840
+ * POST /api/custom-attributes/lookup (upsert option)
5841
+ *
5842
+ * App-side: per usare questo service, l'app deve esporre i 7 endpoint sopra.
5843
+ * Vedi `CostCnh.Controllers.CustomAttributesController` come reference impl.
5844
+ */
5845
+ interface CustomAttributeDefinition {
5846
+ id: number;
5847
+ context: string;
5848
+ code: string;
5849
+ display_name: string;
5850
+ description?: string;
5851
+ value_type: 'text' | 'number' | 'date' | 'bool' | 'lookup' | 'currency' | 'structure';
5852
+ allow_multiple: boolean;
5853
+ has_lookup: boolean;
5854
+ is_required: boolean;
5855
+ is_readonly: boolean;
5856
+ edit_order: number;
5857
+ is_time_based: boolean;
5858
+ mode: number;
5859
+ external_system?: string;
5860
+ external_code?: string;
5861
+ }
5862
+ interface CustomAttributeResolved extends CustomAttributeDefinition {
5863
+ attribute_id: number;
5864
+ mapping_id?: number;
5865
+ label_loc?: string;
5866
+ year_from?: number;
5867
+ year_to?: number;
5868
+ is_visible: boolean;
5869
+ effective_order: number;
5870
+ }
5871
+ interface CustomValue {
5872
+ cv_id: number;
5873
+ attribute_id: number;
5874
+ attribute_code: string;
5875
+ attribute_label: string;
5876
+ value_type: string;
5877
+ has_lookup: boolean;
5878
+ allow_multiple: boolean;
5879
+ value_text?: string | null;
5880
+ value_number?: number | null;
5881
+ value_date?: string | null;
5882
+ value_bool?: boolean | null;
5883
+ custom_lookup_id?: number | null;
5884
+ lookup_code?: string | null;
5885
+ lookup_value?: string | null;
5886
+ lookup_descr?: string | null;
5887
+ year_num?: number | null;
5888
+ ref_object_id?: string | null;
5889
+ }
5890
+ interface CustomLookupOption {
5891
+ id: number;
5892
+ custom_attribute_id: number;
5893
+ code: string;
5894
+ value: string;
5895
+ descr?: string;
5896
+ sort_order: number;
5897
+ is_active: boolean;
5898
+ external_id?: string;
5899
+ }
5900
+ interface CvUpsertItem {
5901
+ attributeId: number;
5902
+ entitySchema: string;
5903
+ entityName: string;
5904
+ entityId: string;
5905
+ valueText?: string | null;
5906
+ valueNumber?: number | null;
5907
+ valueDate?: string | null;
5908
+ valueBool?: boolean | null;
5909
+ customLookupId?: number | null;
5910
+ yearNum?: number | null;
5911
+ existingCvId?: number | null;
5912
+ }
5913
+ declare class CustomAttributesService {
5914
+ private http;
5915
+ /** Endpoint base. Override-abile via DI/config se l'app usa path diverso. */
5916
+ endpointBase: string;
5763
5917
  /**
5764
- * Determina se la colonna `col` puo' essere pinned a sinistra. Regola
5765
- * simmetrica a `canPinRight`: pin-left e' consentito SOLO se la colonna
5766
- * e' la prima visibile, oppure tutte le colonne visibili prima di essa
5767
- * sono gia' pinned left.
5768
- *
5769
- * Why: pin-left sticky CSS funziona correttamente solo per colonne in
5770
- * testa: una colonna pinned-left con altre col non-pinned prima crea un
5771
- * gap visivo e disallinea il sticky offset (style.left viene calcolato
5772
- * sommando le sibling precedenti, ma quelle non-pinned scrollano →
5773
- * la cella pinned salta di posizione durante scroll orizzontale).
5774
- *
5775
- * Se la colonna e' gia' pinned a sinistra, ritorna `false` (l'azione
5776
- * "Pin left" sarebbe no-op — usare "Unpin" invece).
5918
+ * Cache per (context+scope) → applicable definitions.
5919
+ * Invalidata su `clearCache()` (es. dopo invalidate-metadata-runtime).
5777
5920
  */
5778
- canPinLeft(col: any): boolean;
5921
+ private resolveCache;
5922
+ /** Cache per (attribute_id) → lookup options. */
5923
+ private lookupCache;
5924
+ constructor(http: HttpClient);
5925
+ /** Lista tutte le definizioni di un context (admin UI). */
5926
+ listDefinitions(context?: string): Promise<CustomAttributeDefinition[]>;
5927
+ /**
5928
+ * Risolve le CA applicabili a una entity in uno scope (site, project_class, tree_kind).
5929
+ * Usata da `<wuic-parametric-dialog>` per sapere quali field inline mostrare.
5930
+ */
5931
+ resolve(context: string, siteId?: number, projectClassId?: number, treeKindId?: number): Promise<CustomAttributeResolved[]>;
5932
+ /** Leggi i CV correnti di una entity specifica. */
5933
+ getValues(entitySchema: string, entityName: string, entityId: string | number, yearNum?: number): Promise<CustomValue[]>;
5934
+ /** Upsert batch (INSERT new + UPDATE existing via `existingCvId`). */
5935
+ upsertValues(items: CvUpsertItem[]): Promise<{
5936
+ upserted: number;
5937
+ }>;
5938
+ /** Soft delete di un CV. */
5939
+ deleteValue(cvId: number): Promise<{
5940
+ deleted: number;
5941
+ }>;
5942
+ /** Lookup options di un attribute (cached). */
5943
+ getLookupOptions(attributeId: number): Promise<CustomLookupOption[]>;
5944
+ /** Upsert lookup option (admin UI). Trigger cascade rename gestito server-side. */
5945
+ upsertLookup(option: Omit<CustomLookupOption, 'id' | 'is_active'> & {
5946
+ attributeId: number;
5947
+ }): Promise<{
5948
+ affected: number;
5949
+ }>;
5950
+ /** Reset cache (chiamato dopo `invalidateMetadataRuntime`). */
5951
+ clearCache(): void;
5779
5952
  /**
5780
- * Determina se la colonna `col` puo' essere pinned a destra. Regola:
5781
- * il pin-right e' consentito SOLO se la colonna e' l'ultima visibile,
5782
- * oppure tutte le colonne visibili dopo di essa sono gia' pinned right.
5783
- *
5784
- * Why: pin-right sticky CSS funziona correttamente solo per colonne in
5785
- * coda: una colonna pinned-right con altre col non-pinned dopo crea un
5786
- * gap visivo e disallinea il sticky offset (style.right viene calcolato
5787
- * sommando le sibling successive, ma quelle non-pinned scrollano →
5788
- * la cella pinned salta di posizione durante scroll orizzontale).
5953
+ * Estrae i CA token da una filter string e produce un payload separato
5954
+ * `wherestringCA` / `wherevaluesCA` da passare al backend, lasciando i
5955
+ * filter standard sui campi nativi non alterati.
5789
5956
  *
5790
- * Se la colonna e' gia' pinned a destra, ritorna `false` (l'azione
5791
- * "Pin right" sarebbe no-op — usare "Unpin" invece).
5792
- */
5793
- canPinRight(col: any): boolean;
5794
- /**
5795
- * Imposta pin/frozen della colonna nel lato richiesto e persiste il layout utente.
5796
- */
5797
- private pinColumnFromContextMenu;
5798
- /**
5799
- * Rimuove pin/frozen dalla colonna selezionata e persiste il layout utente.
5800
- */
5801
- private unpinColumnFromContextMenu;
5802
- /**
5803
- * Rimuove pin/frozen da tutte le colonne e persiste il layout utente.
5804
- */
5805
- private unpinAllColumnsFromContextMenu;
5806
- /**
5807
- * Gestisce la logica operativa di `ensureMetadataColumnsDatasourceRoute` propagando aggiornamenti sui flussi reattivi usati dalla UI.
5808
- */
5809
- private ensureMetadataColumnsDatasourceRoute;
5810
- /**
5811
- * Inizializza (una sola volta) il datasource dedicato alle colonne metadato, caricando schema e configurazione necessari alle operazioni di update metadati.
5812
- */
5813
- private ensureMetadataColumnsDatasourceSchema;
5814
- /**
5815
- * Recupera dal datasource metadati il record colonna corrispondente a `mc_id`, usato per modifiche puntuali alle proprietà della colonna.
5816
- * @param mcId Identificativo `mc_id` della colonna metadato da leggere nel datasource amministrativo.
5817
- * @returns Promise che completa il flusso asincrono restituendo un risultato di tipo `Promise<any | null>`.
5818
- */
5819
- private fetchMetadataColumnRecord;
5820
- /**
5821
- * Apre il form editor dei metadati colonna per la `mc_id` selezionata e, alla chiusura con salvataggio, ricarica schema/dati della griglia.
5822
- * @param metaColumn Metadato colonna su cui aprire l'editor; la ricerca del record avviene tramite `mc_id`.
5823
- */
5824
- private openColumnMetadataEditor;
5825
- /**
5826
- * Imposta `mc_hide_in_list = true` sulla colonna selezionata (risolta via `mc_id`), salva il record metadato e ricarica la griglia per applicare la nuova visibilità.
5827
- * @param metaColumn Metadato colonna selezionato; viene usato `mc_id` per recuperare il record persistito e aggiornare `mc_hide_in_list`.
5828
- */
5829
- private hideColumnByMetadata;
5830
- /**
5831
- * Aggiorna i testi di colonna `mc_display_string_in_view` e `mc_display_string_in_edit` tramite prompt, persiste il record metadato e ricarica lo schema.
5832
- * @param metaColumn Metadato colonna selezionato; viene usato `mc_id` per aggiornare `mc_display_string_in_view` e `mc_display_string_in_edit`.
5833
- */
5834
- private editColumnDisplayStrings;
5835
- /**
5836
- * Interpreta e normalizza input/configurazione in `parseColumns` per l'utilizzo nel componente.
5837
- * @param columns Collezione in ingresso processata dal metodo.
5838
- * @returns Struttura dati prodotta da `parseColumns` dopo normalizzazione/elaborazione.
5839
- */
5840
- parseColumns(columns: MetadatiColonna[]): any[];
5841
- /**
5842
- * Gestisce la logica di `onColumnResize` orchestrando le chiamate `captureResizedColumnWidth` e `detectChanges`.
5843
- * @param event Evento UI/payload evento che innesca la logica del metodo.
5844
- */
5845
- onColumnResize(event: any): Promise<void>;
5846
- /**
5847
- * Re-misura POST-CD le widths di tutte le data cols + la `<table style.width>`
5848
- * dal DOM e le sovrascrive in `persistedColumnWidthsByRoute[routeKey]`.
5957
+ * Pattern legacy: `CA_<attribute_code>___<value>` AND `CS_<attribute_code>___<sortdir>`.
5849
5958
  *
5850
- * Why post-CD: durante l'evento `onColResize` PrimeNG fa il drag e setta
5851
- * inline `<table style.width>` + `<th style.width>` solo per la colonna
5852
- * trascinata. L'Angular CD successiva riapplica via binding `<col style.width>`
5853
- * e `<th style.width>` da `cols[i].width`. Solo dopo CD + paint il browser
5854
- * ha distribuito definitivamente le widths. Misurando qui catturiamo
5855
- * il visual state finale, NON quello transitorio durante l'evento.
5856
- */
5857
- private captureAllSiblingsAndTableWidthFromDom;
5858
- /**
5859
- * Rigenera il menu "Salva stato" con azioni contestuali sullo stato selezionato.
5860
- */
5861
- onSaveStateMenuToggle(event: Event, saveStateMenu: {
5862
- toggle: (e: Event) => void;
5863
- }): void;
5864
- private refreshSaveStateMenuItems;
5865
- /**
5866
- * Riallinea la larghezza della colonna leggendo il valore finale dal DOM della tabella.
5867
- * Utile quando l'evento resize espone una width intermedia/non definitiva.
5868
- */
5869
- private captureColumnWidthFromTableDomByField;
5959
+ * @returns { nativeFilter, caTokens: { code, value, op }[] }
5960
+ */
5961
+ parseFilterTokens(rawFilter: string | null | undefined): {
5962
+ nativeFilter: string;
5963
+ caTokens: {
5964
+ code: string;
5965
+ value: string;
5966
+ op: 'eq' | 'contains';
5967
+ }[];
5968
+ };
5969
+ static ɵfac: i0.ɵɵFactoryDeclaration<CustomAttributesService, never>;
5970
+ static ɵprov: i0.ɵɵInjectableDeclaration<CustomAttributesService>;
5971
+ }
5972
+
5973
+ declare class DeviceAwarenessService implements OnDestroy {
5974
+ private static readonly DEFAULT_BREAKPOINT_PX;
5975
+ private mediaQueryList?;
5976
+ private mediaQueryListener?;
5977
+ private readonly isMobileSubject;
5978
+ readonly isMobile$: Observable<boolean>;
5979
+ constructor();
5980
+ get isMobile(): boolean;
5981
+ ngOnDestroy(): void;
5982
+ private resolveBreakpointPx;
5983
+ static ɵfac: i0.ɵɵFactoryDeclaration<DeviceAwarenessService, never>;
5984
+ static ɵprov: i0.ɵɵInjectableDeclaration<DeviceAwarenessService>;
5985
+ }
5986
+
5987
+ interface ListGridSavedState {
5988
+ id: string;
5989
+ name: string;
5990
+ description: string;
5991
+ isDefault: boolean;
5992
+ createdAt: string;
5993
+ filterInfo: any;
5994
+ sortInfo: any[];
5995
+ pageInfo: {
5996
+ currentPage: number;
5997
+ pageSize: number;
5998
+ };
5999
+ columnWidths: {
6000
+ [field: string]: number;
6001
+ };
6002
+ columnLayout?: ListGridColumnLayout;
6003
+ }
6004
+ interface ListGridColumnLayout {
6005
+ order: string[];
6006
+ hidden: string[];
6007
+ pinnedLeft: string[];
6008
+ pinnedRight: string[];
6009
+ }
6010
+ interface ReportVariableInput {
6011
+ name: string;
6012
+ alias: string;
6013
+ value: string;
6014
+ type?: string;
6015
+ }
6016
+ interface GridPendingChangeItem {
6017
+ id: string;
6018
+ change: TrackedChange;
6019
+ label: string;
6020
+ details: string;
6021
+ selected: boolean;
6022
+ }
6023
+ interface ListGridBeforeRowRenderEvent {
6024
+ row: any;
6025
+ rowIndex: number;
6026
+ cancel: boolean;
6027
+ cancelRender: () => void;
6028
+ }
6029
+ interface ListGridAfterRowRenderEvent {
6030
+ row: any;
6031
+ rowIndex: number;
6032
+ }
6033
+ interface ListGridAfterRenderEvent {
6034
+ rows: any[];
6035
+ totalRecords: number;
6036
+ metaInfo: MetaInfo;
6037
+ datasource?: DataSourceComponent;
6038
+ }
6039
+ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDataBoundHostComponent {
6040
+ private metaSrv;
6041
+ private sanitizer;
6042
+ private route;
6043
+ private router;
6044
+ private location;
6045
+ private titleService;
6046
+ private trslSrv;
6047
+ private cd;
6048
+ userInfo: UserInfoService;
6049
+ private elementRef;
6050
+ deviceAwareness: DeviceAwarenessService;
6051
+ private customAttributesService?;
6052
+ private static readonly FORCED_VIRTUALIZATION_PAGE_SIZE_THRESHOLD;
6053
+ private static readonly FORCED_VIRTUALIZATION_ITEM_SIZE;
6054
+ private static readonly ACTION_BUTTON_VISIBLE_ROWS_OVERSCAN;
6055
+ private static readonly ACTION_BUTTON_INITIAL_VISIBLE_ROWS_FALLBACK;
6056
+ private static readonly GRID_VIEW_STATES_SETTINGS_KEY;
6057
+ private static readonly GRID_COLUMN_LAYOUT_SETTINGS_KEY;
6058
+ private static selectButtonGuardInstalled;
6059
+ private columnFilterRenderEpochByField;
6060
+ private actionButtonsVisibleStartIndex;
6061
+ private actionButtonsVisibleEndIndex;
6062
+ private actionButtonsLimitToVisibleRows;
6063
+ private actionButtonsPreLimitBeforeContainerReady;
6064
+ private actionButtonsScrollContainer;
6065
+ private actionButtonsScrollRafToken;
6066
+ private actionButtonsScrollHandler;
6067
+ private inlineCellSaveInFlightByRowKey;
6068
+ private inlineCellSaveDebounceByRowKey;
6069
+ private inlineCellLastChangedFieldByRowKey;
6070
+ private inlineBatchOriginalByRowKey;
6071
+ private inlineGridRuntimeFieldCacheByKey;
6072
+ private suppressNextInlineFetchInfoRebind;
6073
+ getRuntimeGridFieldMetaFn: (metaColumn: MetadatiColonna, rowData: any) => MetadatiColonna;
6074
+ hardcodedRoute: string;
6075
+ parentRecord: any;
6076
+ parentMetaInfo: MetaInfo;
6077
+ datasource: BehaviorSubject<DataSourceComponent>;
6078
+ hardcodedDatasource: DataSourceComponent;
6079
+ rowCustomSelect: (rowData: any, $event: any, dt: Table) => void;
6080
+ hideToolbar: boolean;
6081
+ /**
6082
+ * Provider letto da `<wuic-import-export-button>` al click su Export XLS.
6083
+ * Arrow function (NON metodo) per preservare il binding di `this` quando
6084
+ * passata come Input — un metodo verrebbe richiamato col `this` del child.
6085
+ * Ritorna lo stato filtri LIVE del datasource: include i filtri applicati
6086
+ * via header/filter-bar che NON vengono propagati nella URL query string.
6087
+ */
6088
+ getCurrentFilterInfoForExport: () => any;
6089
+ /**
6090
+ * Evento emesso subito prima del rendering logico della singola riga.
6091
+ * Il consumer puo annullare la riga chiamando `cancelRender()`.
6092
+ */
6093
+ onBeforeRowRender: EventEmitter<ListGridBeforeRowRenderEvent>;
6094
+ /**
6095
+ * Evento emesso subito dopo il rendering logico della singola riga.
6096
+ */
6097
+ onAfterRowRender: EventEmitter<ListGridAfterRowRenderEvent>;
6098
+ /**
6099
+ * Evento emesso al termine del ciclo di binding dati della griglia.
6100
+ */
6101
+ onAfterRender: EventEmitter<ListGridAfterRenderEvent>;
6102
+ /**
6103
+ * Evento emesso su paging (evento p-table onPage).
6104
+ */
6105
+ onPaging: EventEmitter<any>;
6106
+ /**
6107
+ * Evento emesso su sorting (evento p-table onSort).
6108
+ */
6109
+ onSorting: EventEmitter<any>;
6110
+ /**
6111
+ * Evento emesso su filtering (evento p-table onFilter).
6112
+ */
6113
+ onFiltering: EventEmitter<any>;
6114
+ /**
6115
+ * Evento emesso dopo un refresh esplicito (click su bottone "Aggiorna"
6116
+ * del toolbar o invocazione di `refresh()` da codice). Gli host in Pattern 3
6117
+ * server-side possono usarlo per ri-fetchare dal loro backend custom.
6118
+ */
6119
+ onRefresh: EventEmitter<void>;
6120
+ /**
6121
+ * Eventi p-table esposti lato host.
6122
+ */
6123
+ onPTableSelectionChange: EventEmitter<any>;
6124
+ onPTableRowExpand: EventEmitter<TableRowExpandEvent<any>>;
6125
+ onPTableRowCollapse: EventEmitter<TableRowCollapseEvent>;
6126
+ onPTableColumnResize: EventEmitter<any>;
6127
+ onPTableColumnReorder: EventEmitter<any>;
6128
+ table: Table;
6129
+ columnCtxMenu: ContextMenu;
6130
+ metadataColumnsDatasource: DataSourceComponent;
6131
+ gridContainerRef?: ElementRef<HTMLElement>;
6132
+ tableActionsMenu: any;
6133
+ /** ResizeObserver per esporre --wuic-outer-thead-h alle nested grid figlie. */
6134
+ private outerTheadResizeObserver?;
6135
+ private outerTheadObserveRetryTimer?;
6136
+ records: any[];
6137
+ cols: any[];
6138
+ /**
6139
+ * Constant CSS value for `<col>`/`<th>` min-width binding. Pulled into a
6140
+ * field (instead of `getColumnMinWidthCss()` method) so the template binding
6141
+ * `[style.min-width]="columnMinWidthCss"` resolves to a property read
6142
+ * (no function call) and Angular's change-detection short-circuits when
6143
+ * the value didn't change. Saves ~3 function calls per column per CD cycle
6144
+ * (template uses it on `<col>`, header `<th>`, and filter row `<th>`).
6145
+ */
6146
+ readonly columnMinWidthCss = "10px";
6147
+ metas: MetadatiColonna[];
6148
+ metaInfo: MetaInfo;
6149
+ routeName: string;
6150
+ actionName: string;
6151
+ totalRecords: number;
6152
+ pageSize: number;
6153
+ rowNumber: number;
6154
+ orderColumn: string;
6155
+ orderDir: 'asc' | 'desc';
6156
+ loading: BehaviorSubject<boolean>;
6157
+ pageIndex: number;
6158
+ globalFilterFields: string[];
6159
+ searchValue: string;
6160
+ rowTemplate: any;
6161
+ /**
6162
+ * Tracks whether the currently compiled `rowTemplate` is the **mobile card**
6163
+ * variant (vs desktop). Decoupled from live `deviceAwareness.isMobile$`:
6164
+ * il viewport puo' attraversare la soglia (es. utente ridimensiona DevTools)
6165
+ * senza che il template sia ancora stato ricompilato. La classe CSS
6166
+ * `wuic-list-grid-mobile` (che nasconde thead/footer/paginator e rompe la
6167
+ * semantica table) deve seguire **lo stato del template compilato**, non il
6168
+ * viewport live, altrimenti si vede una hybrid view (desktop header + card rows).
6169
+ */
6170
+ gridLayoutIsMobile: boolean;
6171
+ /** @deprecated 2026-04-23 — mobile ora riusa rowTemplate del desktop. Field ancora esposto per backward-compat con host che lo leggevano. */
6172
+ mobileCardComponent: any;
6173
+ /** Subscription a `isMobile$` per ricompilare il rowTemplate quando il viewport attraversa la soglia mobile. */
6174
+ private isMobileSubscription?;
6175
+ selectedItems: any[];
6176
+ expandedRows: {};
6177
+ aggregates: any[];
6178
+ private nestedLongDescriptionRawCache;
6179
+ private nestedLongDescriptionSafeCache;
6180
+ /**
6181
+ * Collezione dati per pending change items, consumata dal rendering e dalle operazioni del componente.
6182
+ */
6183
+ pendingChangeItems: GridPendingChangeItem[];
6184
+ private syncFilterInfoQueryTimer;
6185
+ private syncGridStateQueryTimer;
6186
+ private suppressGridStateUrlPush;
6187
+ private releaseGridStateUrlPushTimer;
6188
+ private navigationTriggeredByPopstate;
6189
+ private suppressNextPageOnlyQuerySync;
6190
+ clientSideCrudToggleBusy: boolean;
6191
+ private persistedColumnWidthsByRoute;
6192
+ private persistedColumnLayoutByRoute;
6193
+ private manualResizeDisablesProportionalByRoute;
6194
+ private remoteColumnLayoutHydrationInFlight;
6195
+ private persistedGridStatesByRoute;
6196
+ private remoteGridStatesHydrationInFlight;
6197
+ currentRouteSavedStates: ListGridSavedState[];
6198
+ selectedSavedStateId: string;
6199
+ private applyingSavedState;
6200
+ readonly NEW_GRID_STATE_OPTION_ID = "__new__";
6201
+ saveGridStateDialogVisible: boolean;
6202
+ saveGridStateDialogSelectedId: string;
6203
+ saveGridStateDialogNewName: string;
6204
+ saveGridStateDialogSetAsDefault: boolean;
6205
+ renameGridStateDialogVisible: boolean;
6206
+ renameGridStateDialogName: string;
6207
+ columnLayoutDialogVisible: boolean;
6208
+ columnLayoutDraft: Array<{
6209
+ field: string;
6210
+ header: string;
6211
+ visible: boolean;
6212
+ }>;
6213
+ saveStateMenuItems: MenuItem[];
6214
+ columnContextMenuItems: MenuItem[];
6215
+ selectedColumnForContextMenu?: MetadatiColonna;
6216
+ availableReports: {
6217
+ path: string;
6218
+ name: string;
6219
+ }[];
6220
+ reportMenuItems: MenuItem[];
6221
+ tableActionMenuItems: MenuItem[];
6222
+ reportVariableDialogVisible: boolean;
6223
+ reportVariableDialogLoading: boolean;
6224
+ selectedReportNameForVariables: string;
6225
+ selectedReportVariables: ReportVariableInput[];
6226
+ changesDialogVisible: boolean;
6227
+ changesDialogBusy: boolean;
6228
+ /**
6229
+ * Proprieta di stato del componente per pending preferred state auto apply, usata dalla logica interna e dal template.
6230
+ */
6231
+ private pendingPreferredStateAutoApply;
6232
+ /**
6233
+ * Proprieta di stato del componente per query param subscription, usata dalla logica interna e dal template.
6234
+ */
6235
+ private queryParamSubscription?;
6236
+ /**
6237
+ * Proprieta di stato del componente per router events subscription, usata dalla logica interna e dal template.
6238
+ */
6239
+ private routerEventsSubscription?;
6240
+ /**
6241
+ * Proprieta di stato del componente per datasource ready subscription, usata dalla logica interna e dal template.
6242
+ */
6243
+ private datasourceReadySubscription?;
6244
+ /**
6245
+ * Proprieta di stato del componente per fetch info subscription, usata dalla logica interna e dal template.
6246
+ */
6247
+ private fetchInfoSubscription?;
6248
+ /**
6249
+ * Proprieta di stato del componente per width defined, usata dalla logica interna e dal template.
6250
+ */
6251
+ width_defined: string;
6252
+ /**
6253
+ * Proprieta di stato del componente per metadati colonna, usata dalla logica interna e dal template.
6254
+ */
6255
+ MetadatiColonna: typeof MetadatiColonna;
6256
+ /**
6257
+ * function Object() { [native code] }
6258
+ * @param metaSrv Metadati correnti usati per guidare mapping, validazioni e comportamento runtime.
6259
+ * @param route Informazione di navigazione usata per risolvere la route di destinazione.
6260
+ * @param router Informazione di navigazione usata per risolvere la route di destinazione.
6261
+ * @param location Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
6262
+ * @param titleService Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
6263
+ * @param trslSrv Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
6264
+ * @param cd Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
6265
+ * @param userInfo Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
6266
+ */
6267
+ constructor(metaSrv: MetadataProviderService, sanitizer: DomSanitizer, route: ActivatedRoute, router: Router, location: Location, titleService: Title, trslSrv: TranslationManagerService, cd: ChangeDetectorRef, userInfo: UserInfoService, elementRef: ElementRef<HTMLElement>, deviceAwareness: DeviceAwarenessService, customAttributesService?: CustomAttributesService);
6268
+ /**
6269
+ * Phase I.3 — Estrae i CA token (CA_<code>___value / CS_<code>___order) dalla
6270
+ * filter string corrente, ritornandoli separati per il backend SP che
6271
+ * costruisce il JOIN dinamico su core.custom_value.
6272
+ *
6273
+ * Pattern legacy `Filter_ApplyProjects.sql` con `wherestringCA`/`wherevaluesCA`.
6274
+ *
6275
+ * Backward-compat: se nessun CA token presente, ritorna `caTokens: []`.
6276
+ * Le app possono usare questo getter per accodare i CA token al payload
6277
+ * delle chiamate stored procedure (es. via `_extra` field di filterInfo).
6278
+ */
6279
+ getCustomAttributeFilterTokens(): {
6280
+ code: string;
6281
+ value: string;
6282
+ op: 'eq' | 'contains';
6283
+ }[];
6284
+ /**
6285
+ * Helper interno: serializza i filtri attivi in una stringa con tokens CA_X / CS_X.
6286
+ * Cerca tra i filterInfo.filters quelli con field name del tipo `ca:code`
6287
+ * o `cs:code` (convenzione opt-in) e li emette in formato CA_code___value.
6288
+ */
6289
+ private serializeFilterInfoToTokenString;
6290
+ /**
6291
+ * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
6292
+ */
6293
+ ngOnInit(): void;
6294
+ /**
6295
+ * Gestisce la logica operativa di `ensureSelectButtonGuard` orchestrando le chiamate `call`.
6296
+ */
6297
+ private ensureSelectButtonGuard;
6298
+ /**
6299
+ * Completa inizializzazione dopo il rendering della view e collega riferimenti UI.
6300
+ */
6301
+ ngAfterViewInit(): void;
6302
+ /**
6303
+ * Applica direttamente in DOM (senza Angular binding) la `<table style.width
6304
+ * + min-width>` salvata in `persistedColumnWidthsByRoute` come `__tableTotalWidth`.
6305
+ *
6306
+ * Why direct DOM e non `[tableStyle]` binding:
6307
+ * - Durante il drag PrimeNG (`columnResizeMode="expand"`) modifica
6308
+ * `<table style.width>` inline. Se anche Angular setta lo stesso prop
6309
+ * via binding, i due meccanismi entrano in race → comportamento di
6310
+ * spalmamento osservato (il delta del drag si distribuisce tra tutte
6311
+ * le colonne invece di concentrarsi su quella trascinata).
6312
+ * - Direct DOM bypassa Angular CD. Lo applichiamo SOLO al boot
6313
+ * (ngAfterViewInit) e dopo `parseColumns` su data refresh — non durante
6314
+ * il drag — quindi nessun conflitto.
6315
+ * - Senza la table.style.width esplicita, al refresh il browser fitta il
6316
+ * table al container (default `min-width: 100%` PrimeNG) e shrinkka
6317
+ * le colonne → la scrollbar svanisce.
6318
+ */
6319
+ private scheduleApplyPersistedTableWidth;
6320
+ private applyPersistedTableWidth;
6321
+ /**
6322
+ * Ritorna la `<table style.width>` da applicare al refresh per riprodurre
6323
+ * il layout end-of-drag.
6324
+ *
6325
+ * Strategia:
6326
+ * 1. Se esiste `__tableWidth` persistito (chiave speciale catturata in
6327
+ * `captureResizedColumnWidth`), usa quello — e' il valore esatto
6328
+ * `oldTableWidth + delta` che PrimeNG ha applicato a fine drag.
6329
+ * 2. Fallback: somma persisted col widths + frozen widths reali (DOM)
6330
+ * per il caso di stati legacy salvati prima del fix.
6331
+ */
6332
+ private computePersistedTableTotalWidth;
6333
+ /**
6334
+ * Espone l'altezza del thead OUTER (top-level grid) come CSS var `--wuic-outer-thead-h`
6335
+ * sull'host element, per permettere a `position: sticky; top: var(...)` sull'inner thead
6336
+ * di lasciare spazio sotto l'header outer (anch'esso sticky a top:0).
6337
+ *
6338
+ * Si attiva SOLO sulla grid root (non nested): le inner ListGridComponent leggono la var
6339
+ * via cascade CSS dall'ancestor `wuic-list-grid` piu vicino, che corrisponde all'outer.
6340
+ */
6341
+ private observeOuterTheadHeight;
6342
+ /**
6343
+ * Ricalcola l'altezza disponibile della grid al resize finestra.
6344
+ */
6345
+ onWindowResizeForGridLayout(): void;
6346
+ /**
6347
+ * Pianifica piu pass di sync layout per gestire render asincrono PrimeNG/pager.
6348
+ */
6349
+ private scheduleGridViewportHeightSync;
6350
+ /**
6351
+ * Vincola la griglia all'altezza disponibile in viewport, lasciando lo scroll al body p-table.
6352
+ */
6353
+ private applyGridViewportHeight;
6354
+ /**
6355
+ * Rilascia risorse e sottoscrizioni per evitare leak e stati pendenti.
6356
+ */
6357
+ ngOnDestroy(): void;
6358
+ getNestedLongDescriptionSafeHtml(nestedSource?: DataSourceComponent): SafeHtml | '';
6359
+ private stripScriptTags;
6360
+ /**
6361
+ * Restituisce una chiave stabile per il tracking colonne nel template,
6362
+ * evitando re-render completi quando l'array visibile viene ricreato.
6363
+ */
6364
+ getStableColumnTrackKey(col: any, index: number): string;
6365
+ /**
6366
+ * Inline style per la `<p-table>` che replica il behavior runtime di PrimeNG
6367
+ * `columnResizeMode="expand"`: setta `width: <sum>; min-width: <sum>` sul
6368
+ * `<table>` quando esistono persisted column widths.
6369
+ *
6370
+ * Why: PrimeNG durante il resize "expand" applica esplicitamente questi
6371
+ * stili per forzare il `<table>` a essere piu' largo del container e
6372
+ * generare la scrollbar. Al refresh quegli inline styles spariscono e il
6373
+ * default `table-layout: auto + min-width: 100%` fa shrinkare le colonne
6374
+ * per fittare il container — la scrollbar svanisce e le widths persistite
6375
+ * (settate via `<col style.width>`) vengono ignorate dal browser.
6376
+ *
6377
+ * Con questo binding, la `<table>` riceve gli stessi stili che PrimeNG
6378
+ * applicherebbe a fine drag → table-layout puo' restare `auto` + i `<col>`
6379
+ * widths vengono rispettati come hint di partenza, e il browser distribuisce
6380
+ * la larghezza totale tra di loro proporzionalmente alle widths richieste.
6381
+ *
6382
+ * Ritorna `null` quando non ci sono persisted widths (default proportional).
6383
+ */
6384
+ getTableStyle(): {
6385
+ [key: string]: string;
6386
+ } | null;
6387
+ /**
6388
+ * Restituisce le classi della p-table includendo il profilo inline-cell-editing.
6389
+ */
6390
+ getTableStyleClass(): string;
6391
+ private isNestedGridInstance;
6392
+ private isInlineEditEnabled;
6393
+ /**
6394
+ * Gestisce la logica operativa di `subscribeToDS` in modo coerente con l'implementazione corrente.
6395
+ * @returns Risultato elaborato da `subscribeToDS` e restituito al chiamante.
6396
+ */
6397
+ subscribeToDS(): void;
6398
+ /**
6399
+ * Recupera e prepara i dati richiesti dal chiamante usando i metadati per determinare chiavi, campi e comportamento runtime.
6400
+ * @param metaInfo Metadati del contesto corrente usati per guidare filtri, mapping e comportamento runtime.
6401
+ * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
6402
+ */
6403
+ /**
6404
+ * Compila il `rowTemplate` corrente in base a `metaInfo` e al viewport mobile/desktop
6405
+ * live (`deviceAwareness.isMobile`). Aggiorna anche il flag `gridLayoutIsMobile` che
6406
+ * pilota la classe CSS `wuic-list-grid-mobile` (nasconde thead/footer/paginator e rompe
6407
+ * la semantica table). Estratto in metodo dedicato per poter essere richiamato anche
6408
+ * dalla subscription `isMobile$` in `ngOnInit` quando il viewport attraversa la soglia.
6409
+ */
6410
+ private compileGridRowTemplate;
6411
+ private getEffectiveGridRowTemplate;
6412
+ /**
6413
+ * Costruisce il row template per mobile: UNA sola <td colspan="N"> contenente
6414
+ * il card layout (label/value per colonna + action button). Il row subclass
6415
+ * resta compilato dallo stesso `DynamicRowTemplateComponent.
6416
+ * getComponentFromTemplate` usato in desktop (selector 'tr'), solo il template
6417
+ * string cambia.
6418
+ *
6419
+ * `colspan` = numero totale di colonne del grid desktop, cosi' la <td> occupa
6420
+ * tutta la larghezza della row. Il CSS `@media (max-width: 768px)` nel
6421
+ * list-grid.component.scss setta `display: block` su <tr> / <td.wuic-mobile-
6422
+ * card-cell> liberando dalla semantica table.
6423
+ */
6424
+ private buildMobileCardAsRowTemplate;
6425
+ /**
6426
+ * Restituisce il template host solo se realmente sovrascritto rispetto al default libreria.
6427
+ */
6428
+ private getHostOverriddenGridRowTemplate;
6429
+ /**
6430
+ * Cascata mobile: host `WidgetDefinition.mobileCardTemplate` -> library default.
6431
+ * Nessuna lettura da `metaInfo.tableMetadata` (no per-tabella).
6432
+ */
6433
+ private getEffectiveMobileCardTemplate;
6434
+ /**
6435
+ * Costruisce il template default per la card mobile: una card per record, con
6436
+ * `data-action-button` in testa e una riga `label/value` per ogni colonna visibile.
6437
+ * Riusa gli stessi switch case dei custom cell template del desktop.
6438
+ * Inline editing escluso per scelta (regola: su mobile l'edit apre sempre il form).
6439
+ */
6440
+ private buildDefaultMobileCardTemplate;
6441
+ /**
6442
+ * Costruisce una struttura di output a partire dal contesto corrente usando i metadati per determinare chiavi, campi e comportamento runtime.
6443
+ * @param columns Collezione di input processata dal metodo (normalizzazione, filtri e mapping).
6444
+ * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
6445
+ */
6446
+ private buildDefaultGridRowTemplateWithColumnTemplates;
6447
+ /**
6448
+ * Costruisce una struttura di output a partire dal contesto corrente normalizzando e trasformando collezioni di record.
6449
+ * @param columns Collezione di input processata dal metodo (normalizzazione, filtri e mapping).
6450
+ * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
6451
+ */
6452
+ private buildGridColumnTemplateSwitchCases;
6453
+ /**
6454
+ * Verifica una condizione di stato o di validita orchestrando le chiamate `trim` e `String`.
6455
+ * @param template Valore testuale usato come chiave, nome campo, criterio o frammento di configurazione.
6456
+ * @returns Esito booleano dell'elaborazione svolta dal metodo.
6457
+ */
6458
+ private isAngularCellMarkupTemplate;
6459
+ /**
6460
+ * Trasforma i dati in una forma coerente con il rendering o con il payload richiesto orchestrando le chiamate `trim` e `String`.
6461
+ * @param template Valore testuale usato come chiave, nome campo, criterio o frammento di configurazione.
6462
+ * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
6463
+ */
6464
+ private normalizeGridCellTemplate;
6465
+ /**
6466
+ * Esegue operazioni di persistenza/sincronizzazione in `syncTableFilterUiFromDatasource` trasformando e filtrando collezioni dati.
6467
+ */
6468
+ private syncTableFilterUiFromDatasource;
6469
+ /**
6470
+ * Allinea il sort visuale della p-table con `datasource.sortInfo`, inclusa la rimozione esplicita del descriptor.
6471
+ */
6472
+ private syncTableSortUiFromDatasource;
6473
+ /**
6474
+ * Interpreta e normalizza input/configurazione in `parseData` per l'utilizzo nel componente.
6475
+ * @param data Dato/record su cui il metodo applica elaborazioni o aggiornamenti.
6476
+ * @returns Struttura dati prodotta da `parseData` dopo normalizzazione/elaborazione.
6477
+ */
6478
+ parseData(data: any): any;
6479
+ /**
6480
+ * Ricalcola lo stato `_disabled` delle azioni tabella valutando i callback di disabilitazione contro `resultInfo.current` e il contesto UI corrente.
6481
+ */
6482
+ reEvaluateActionEnabledStates(): void;
6483
+ /**
6484
+ * Ricostruisce il menu azioni tabella includendo solo le voci autorizzate/visibili e riallineando caption, stato disabled e comandi eseguibili.
6485
+ */
6486
+ private rebuildTableActionMenuItems;
6487
+ /**
6488
+ * Gestisce la logica operativa di `onColumnHeaderContextMenu` in modo coerente con l'implementazione corrente.
6489
+ * @param event Evento che innesca il comportamento del metodo.
6490
+ * @param col Parametro utilizzato dal metodo nel flusso elaborativo.
6491
+ * @param menu Parametro utilizzato dal metodo nel flusso elaborativo.
6492
+ */
6493
+ onColumnHeaderContextMenu(event: MouseEvent, col: any, menu: ContextMenu): void;
6494
+ /**
6495
+ * Determina se la colonna `col` puo' essere pinned a sinistra. Regola
6496
+ * simmetrica a `canPinRight`: pin-left e' consentito SOLO se la colonna
6497
+ * e' la prima visibile, oppure tutte le colonne visibili prima di essa
6498
+ * sono gia' pinned left.
6499
+ *
6500
+ * Why: pin-left sticky CSS funziona correttamente solo per colonne in
6501
+ * testa: una colonna pinned-left con altre col non-pinned prima crea un
6502
+ * gap visivo e disallinea il sticky offset (style.left viene calcolato
6503
+ * sommando le sibling precedenti, ma quelle non-pinned scrollano →
6504
+ * la cella pinned salta di posizione durante scroll orizzontale).
6505
+ *
6506
+ * Se la colonna e' gia' pinned a sinistra, ritorna `false` (l'azione
6507
+ * "Pin left" sarebbe no-op — usare "Unpin" invece).
6508
+ */
6509
+ canPinLeft(col: any): boolean;
6510
+ /**
6511
+ * Determina se la colonna `col` puo' essere pinned a destra. Regola:
6512
+ * il pin-right e' consentito SOLO se la colonna e' l'ultima visibile,
6513
+ * oppure tutte le colonne visibili dopo di essa sono gia' pinned right.
6514
+ *
6515
+ * Why: pin-right sticky CSS funziona correttamente solo per colonne in
6516
+ * coda: una colonna pinned-right con altre col non-pinned dopo crea un
6517
+ * gap visivo e disallinea il sticky offset (style.right viene calcolato
6518
+ * sommando le sibling successive, ma quelle non-pinned scrollano →
6519
+ * la cella pinned salta di posizione durante scroll orizzontale).
6520
+ *
6521
+ * Se la colonna e' gia' pinned a destra, ritorna `false` (l'azione
6522
+ * "Pin right" sarebbe no-op — usare "Unpin" invece).
6523
+ */
6524
+ canPinRight(col: any): boolean;
6525
+ /**
6526
+ * Imposta pin/frozen della colonna nel lato richiesto e persiste il layout utente.
6527
+ */
6528
+ private pinColumnFromContextMenu;
6529
+ /**
6530
+ * Rimuove pin/frozen dalla colonna selezionata e persiste il layout utente.
6531
+ */
6532
+ private unpinColumnFromContextMenu;
6533
+ /**
6534
+ * Rimuove pin/frozen da tutte le colonne e persiste il layout utente.
6535
+ */
6536
+ private unpinAllColumnsFromContextMenu;
6537
+ /**
6538
+ * Gestisce la logica operativa di `ensureMetadataColumnsDatasourceRoute` propagando aggiornamenti sui flussi reattivi usati dalla UI.
6539
+ */
6540
+ private ensureMetadataColumnsDatasourceRoute;
6541
+ /**
6542
+ * Inizializza (una sola volta) il datasource dedicato alle colonne metadato, caricando schema e configurazione necessari alle operazioni di update metadati.
6543
+ */
6544
+ private ensureMetadataColumnsDatasourceSchema;
6545
+ /**
6546
+ * Recupera dal datasource metadati il record colonna corrispondente a `mc_id`, usato per modifiche puntuali alle proprietà della colonna.
6547
+ * @param mcId Identificativo `mc_id` della colonna metadato da leggere nel datasource amministrativo.
6548
+ * @returns Promise che completa il flusso asincrono restituendo un risultato di tipo `Promise<any | null>`.
6549
+ */
6550
+ private fetchMetadataColumnRecord;
6551
+ /**
6552
+ * Apre il form editor dei metadati colonna per la `mc_id` selezionata e, alla chiusura con salvataggio, ricarica schema/dati della griglia.
6553
+ * @param metaColumn Metadato colonna su cui aprire l'editor; la ricerca del record avviene tramite `mc_id`.
6554
+ */
6555
+ private openColumnMetadataEditor;
6556
+ /**
6557
+ * Imposta `mc_hide_in_list = true` sulla colonna selezionata (risolta via `mc_id`), salva il record metadato e ricarica la griglia per applicare la nuova visibilità.
6558
+ * @param metaColumn Metadato colonna selezionato; viene usato `mc_id` per recuperare il record persistito e aggiornare `mc_hide_in_list`.
6559
+ */
6560
+ private hideColumnByMetadata;
6561
+ /**
6562
+ * Aggiorna i testi di colonna `mc_display_string_in_view` e `mc_display_string_in_edit` tramite prompt, persiste il record metadato e ricarica lo schema.
6563
+ * @param metaColumn Metadato colonna selezionato; viene usato `mc_id` per aggiornare `mc_display_string_in_view` e `mc_display_string_in_edit`.
6564
+ */
6565
+ private editColumnDisplayStrings;
6566
+ /**
6567
+ * Interpreta e normalizza input/configurazione in `parseColumns` per l'utilizzo nel componente.
6568
+ * @param columns Collezione in ingresso processata dal metodo.
6569
+ * @returns Struttura dati prodotta da `parseColumns` dopo normalizzazione/elaborazione.
6570
+ */
6571
+ parseColumns(columns: MetadatiColonna[]): any[];
6572
+ /**
6573
+ * Gestisce la logica di `onColumnResize` orchestrando le chiamate `captureResizedColumnWidth` e `detectChanges`.
6574
+ * @param event Evento UI/payload evento che innesca la logica del metodo.
6575
+ */
6576
+ onColumnResize(event: any): Promise<void>;
6577
+ /**
6578
+ * Re-misura POST-CD le widths di tutte le data cols + la `<table style.width>`
6579
+ * dal DOM e le sovrascrive in `persistedColumnWidthsByRoute[routeKey]`.
6580
+ *
6581
+ * Why post-CD: durante l'evento `onColResize` PrimeNG fa il drag e setta
6582
+ * inline `<table style.width>` + `<th style.width>` solo per la colonna
6583
+ * trascinata. L'Angular CD successiva riapplica via binding `<col style.width>`
6584
+ * e `<th style.width>` da `cols[i].width`. Solo dopo CD + paint il browser
6585
+ * ha distribuito definitivamente le widths. Misurando qui catturiamo
6586
+ * il visual state finale, NON quello transitorio durante l'evento.
6587
+ */
6588
+ private captureAllSiblingsAndTableWidthFromDom;
6589
+ /**
6590
+ * Rigenera il menu "Salva stato" con azioni contestuali sullo stato selezionato.
6591
+ */
6592
+ onSaveStateMenuToggle(event: Event, saveStateMenu: {
6593
+ toggle: (e: Event) => void;
6594
+ }): void;
6595
+ private refreshSaveStateMenuItems;
6596
+ /**
6597
+ * Riallinea la larghezza della colonna leggendo il valore finale dal DOM della tabella.
6598
+ * Utile quando l'evento resize espone una width intermedia/non definitiva.
6599
+ */
6600
+ private captureColumnWidthFromTableDomByField;
5870
6601
  /**
5871
6602
  * Gestisce la logica di `onColumnReorder` trasformando e filtrando collezioni dati.
5872
6603
  * @param event Evento UI/payload evento che innesca la logica del metodo.
@@ -6709,7 +7440,7 @@ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDa
6709
7440
  * @returns Valore numerico derivato dai calcoli interni (conteggio, indice, priorita o metrica operativa).
6710
7441
  */
6711
7442
  private getWidthFromResizeEvent;
6712
- static ɵfac: i0.ɵɵFactoryDeclaration<ListGridComponent, never>;
7443
+ static ɵfac: i0.ɵɵFactoryDeclaration<ListGridComponent, [null, null, null, null, null, null, null, null, null, null, null, { optional: true; }]>;
6713
7444
  static ɵcmp: i0.ɵɵComponentDeclaration<ListGridComponent, "wuic-list-grid", never, { "hardcodedRoute": { "alias": "hardcodedRoute"; "required": false; }; "parentRecord": { "alias": "parentRecord"; "required": false; }; "parentMetaInfo": { "alias": "parentMetaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "hardcodedDatasource": { "alias": "hardcodedDatasource"; "required": false; }; "rowCustomSelect": { "alias": "rowCustomSelect"; "required": false; }; "hideToolbar": { "alias": "hideToolbar"; "required": false; }; }, { "onBeforeRowRender": "onBeforeRowRender"; "onAfterRowRender": "onAfterRowRender"; "onAfterRender": "onAfterRender"; "onPaging": "onPaging"; "onSorting": "onSorting"; "onFiltering": "onFiltering"; "onRefresh": "onRefresh"; "onPTableSelectionChange": "onPTableSelectionChange"; "onPTableRowExpand": "onPTableRowExpand"; "onPTableRowCollapse": "onPTableRowCollapse"; "onPTableColumnResize": "onPTableColumnResize"; "onPTableColumnReorder": "onPTableColumnReorder"; }, never, never, true, never>;
6714
7445
  }
6715
7446
 
@@ -8407,8 +9138,9 @@ declare class CarouselListComponent implements IBindable, IDesigner<CarouselOpti
8407
9138
  static ɵcmp: i0.ɵɵComponentDeclaration<CarouselListComponent, "wuic-carousel-list", never, { "hardcodedRoute": { "alias": "hardcodedRoute"; "required": false; }; "parentRecord": { "alias": "parentRecord"; "required": false; }; "parentMetaInfo": { "alias": "parentMetaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "hardcodedDatasource": { "alias": "hardcodedDatasource"; "required": false; }; "hideToolbar": { "alias": "hideToolbar"; "required": false; }; }, { "onCarouselPage": "onCarouselPage"; "onCarouselItemClick": "onCarouselItemClick"; "onCarouselDataBound": "onCarouselDataBound"; }, never, never, true, never>;
8408
9139
  }
8409
9140
 
8410
- declare class LazySpreadsheetListSfComponent implements OnInit {
9141
+ declare class LazySpreadsheetListSfComponent implements OnInit, OnDestroy, AfterViewChecked {
8411
9142
  private readonly cdr;
9143
+ private readonly activatedRoute;
8412
9144
  innerOutlet?: NgComponentOutlet;
8413
9145
  hardcodedRoute: string;
8414
9146
  parentRecord: any;
@@ -8416,9 +9148,46 @@ declare class LazySpreadsheetListSfComponent implements OnInit {
8416
9148
  datasource: BehaviorSubject<DataSourceComponent>;
8417
9149
  hardcodedDatasource: DataSourceComponent;
8418
9150
  hideToolbar: boolean;
9151
+ /** Override esplicito che forza l'attivazione lock-awareness. Default false. */
9152
+ enableLockAwareness: boolean;
9153
+ /**
9154
+ * Scope di lock generico. Se non valorizzato dal parent, viene auto-popolato
9155
+ * dalla URL: tutti i query param vengono caricati come key→value (numeric
9156
+ * coercion best-effort). La mdpropsbag della route definisce quali field sono
9157
+ * "primary" (URL path segment) e quali sono required.
9158
+ */
9159
+ lockScope: Record<string, any>;
9160
+ /**
9161
+ * Override heartbeat in secondi. Se omesso, viene preso dalla
9162
+ * `mdpropsbag.archetypes.spreadsheet.lock.heartbeatIntervalSec` (default 60).
9163
+ */
9164
+ heartbeatIntervalSec?: number;
9165
+ /** Mostra formula bar Syncfusion. Default false (BC). Override anche via URL `?show_formula_bar=1`. */
9166
+ showFormulaBar: boolean;
9167
+ /** Mostra ribbon Syncfusion completo. Default false. Override anche via URL `?show_ribbon=1`. */
9168
+ showRibbon: boolean;
9169
+ onLockAcquired: EventEmitter<{
9170
+ lockToken: string;
9171
+ lockId: number;
9172
+ lockExpiresUtc: Date;
9173
+ outcome: "acquired" | "refreshed";
9174
+ }>;
9175
+ onLockConflict: EventEmitter<{
9176
+ conflictUserId: number | null;
9177
+ lockExpiresUtc: Date | null;
9178
+ }>;
9179
+ onLockReleased: EventEmitter<{
9180
+ released: number;
9181
+ }>;
9182
+ onLockExpired: EventEmitter<void>;
8419
9183
  loadedComponent: any;
8420
- constructor(cdr: ChangeDetectorRef);
9184
+ private routeQuerySub?;
9185
+ constructor(cdr: ChangeDetectorRef, activatedRoute: ActivatedRoute);
8421
9186
  ngOnInit(): Promise<void>;
9187
+ ngOnDestroy(): void;
9188
+ private lockEventSubs;
9189
+ private innerHooked;
9190
+ ngAfterViewChecked(): void;
8422
9191
  componentInputs(): {
8423
9192
  hardcodedRoute: string;
8424
9193
  parentRecord: any;
@@ -8426,9 +9195,14 @@ declare class LazySpreadsheetListSfComponent implements OnInit {
8426
9195
  datasource: BehaviorSubject<DataSourceComponent>;
8427
9196
  hardcodedDatasource: DataSourceComponent;
8428
9197
  hideToolbar: boolean;
9198
+ enableLockAwareness: boolean;
9199
+ lockScope: Record<string, any>;
9200
+ heartbeatIntervalSec: number;
9201
+ showFormulaBar: boolean;
9202
+ showRibbon: boolean;
8429
9203
  };
8430
9204
  static ɵfac: i0.ɵɵFactoryDeclaration<LazySpreadsheetListSfComponent, never>;
8431
- static ɵcmp: i0.ɵɵComponentDeclaration<LazySpreadsheetListSfComponent, "wuic-spreadsheet-list-sf-lazy", never, { "hardcodedRoute": { "alias": "hardcodedRoute"; "required": false; }; "parentRecord": { "alias": "parentRecord"; "required": false; }; "parentMetaInfo": { "alias": "parentMetaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "hardcodedDatasource": { "alias": "hardcodedDatasource"; "required": false; }; "hideToolbar": { "alias": "hideToolbar"; "required": false; }; }, {}, never, never, true, never>;
9205
+ static ɵcmp: i0.ɵɵComponentDeclaration<LazySpreadsheetListSfComponent, "wuic-spreadsheet-list-sf-lazy", never, { "hardcodedRoute": { "alias": "hardcodedRoute"; "required": false; }; "parentRecord": { "alias": "parentRecord"; "required": false; }; "parentMetaInfo": { "alias": "parentMetaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "hardcodedDatasource": { "alias": "hardcodedDatasource"; "required": false; }; "hideToolbar": { "alias": "hideToolbar"; "required": false; }; "enableLockAwareness": { "alias": "enableLockAwareness"; "required": false; }; "lockScope": { "alias": "lockScope"; "required": false; }; "heartbeatIntervalSec": { "alias": "heartbeatIntervalSec"; "required": false; }; "showFormulaBar": { "alias": "showFormulaBar"; "required": false; }; "showRibbon": { "alias": "showRibbon"; "required": false; }; }, { "onLockAcquired": "onLockAcquired"; "onLockConflict": "onLockConflict"; "onLockReleased": "onLockReleased"; "onLockExpired": "onLockExpired"; }, never, never, true, never>;
8432
9206
  }
8433
9207
 
8434
9208
  declare class TreeListComponent implements OnInit, OnDestroy, IDataBoundHostComponent {
@@ -8649,6 +9423,7 @@ declare class ParametricDialogComponent implements OnInit, AfterViewInit, OnDest
8649
9423
  private router;
8650
9424
  private trnsl;
8651
9425
  private hostElementRef;
9426
+ private customAttributesService;
8652
9427
  private dialogService?;
8653
9428
  /**
8654
9429
  * Input dal componente padre per datasource; usata nella configurazione e nel rendering del componente.
@@ -8749,6 +9524,32 @@ declare class ParametricDialogComponent implements OnInit, AfterViewInit, OnDest
8749
9524
  * Configurazione di presentazione per form template, usata nel rendering del componente.
8750
9525
  */
8751
9526
  formTemplate: any;
9527
+ /**
9528
+ * Phase I.3 — Custom Attributes runtime state.
9529
+ * Popolato in `applyDatasourceSnapshot` quando `tableMetadata.custom_attribute_context`
9530
+ * e' valorizzato. Le definitions resolved vengono iniettate come MetadatiColonna sintetiche
9531
+ * (prefisso `__ca_<code>__`) in `metaInfo.columnMetadata`; i values esistenti vengono
9532
+ * caricati in `record['__ca_<code>__']`. Al save, l'app-level hook va connesso a
9533
+ * `(onCustomAttributesSave)` con `CustomAttributesService.upsertValues()`.
9534
+ */
9535
+ customAttributesResolved: CustomAttributeResolved[];
9536
+ customAttributesValues: CustomValue[];
9537
+ /** Emesso quando l'utente conferma il save: l'app dovrebbe chiamare `caService.upsertValues()`. */
9538
+ onCustomAttributesSave: EventEmitter<{
9539
+ items: {
9540
+ attributeId: number;
9541
+ entitySchema: string;
9542
+ entityName: string;
9543
+ entityId: string;
9544
+ valueText?: string;
9545
+ valueNumber?: number;
9546
+ valueDate?: string;
9547
+ valueBool?: boolean;
9548
+ customLookupId?: number;
9549
+ yearNum?: number;
9550
+ existingCvId?: number;
9551
+ }[];
9552
+ }>;
8752
9553
  /**
8753
9554
  * Flag di stato che governa il comportamento UI/logico relativo a cloning.
8754
9555
  */
@@ -8825,7 +9626,8 @@ declare class ParametricDialogComponent implements OnInit, AfterViewInit, OnDest
8825
9626
  * @param route Informazione di navigazione usata per risolvere la route di destinazione.
8826
9627
  * @param router Informazione di navigazione usata per risolvere la route di destinazione.
8827
9628
  */
8828
- constructor(ref: DynamicDialogRef | null, config: DynamicDialogConfig | null, route: ActivatedRoute, router: Router, trnsl: TranslationManagerService, hostElementRef: ElementRef<HTMLElement>, dialogService?: DialogService);
9629
+ constructor(ref: DynamicDialogRef | null, config: DynamicDialogConfig | null, route: ActivatedRoute, router: Router, trnsl: TranslationManagerService, hostElementRef: ElementRef<HTMLElement>, customAttributesService: CustomAttributesService | null, // Phase I.3
9630
+ dialogService?: DialogService);
8829
9631
  /**
8830
9632
  * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
8831
9633
  */
@@ -9028,8 +9830,25 @@ declare class ParametricDialogComponent implements OnInit, AfterViewInit, OnDest
9028
9830
  * quando la schermata viene riaperta subito dopo.
9029
9831
  */
9030
9832
  private reloadTranslationsIfMetadataSave;
9031
- static ɵfac: i0.ɵɵFactoryDeclaration<ParametricDialogComponent, [{ optional: true; }, { optional: true; }, null, null, null, null, { optional: true; }]>;
9032
- 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>;
9833
+ /**
9834
+ * Se la route ha `tableMetadata.custom_attribute_context` valorizzato e il
9835
+ * `CustomAttributesService` è injectabile, carica:
9836
+ * 1. Le definitions applicable allo scope (resolve TVF)
9837
+ * 2. I CV correnti della entity (getValues TVF)
9838
+ * I CV vengono mergiati in `record` con chiave `__ca_<code>__` cosi' che
9839
+ * eventuali template/form a livello app possano renderizzarli.
9840
+ * Feature flag: senza `custom_attribute_context` settato (default), NO-OP.
9841
+ */
9842
+ private tryLoadCustomAttributes;
9843
+ /**
9844
+ * Helper esposto per app-level form/template: collect i valori CA correnti
9845
+ * dal record e emette `onCustomAttributesSave`. L'app deve chiamare
9846
+ * `CustomAttributesService.upsertValues(items)` come step post-save standard.
9847
+ * Backward-compat: se il listener non e' attaccato, no-op silenzioso.
9848
+ */
9849
+ collectAndEmitCustomAttributesSave(): void;
9850
+ static ɵfac: i0.ɵɵFactoryDeclaration<ParametricDialogComponent, [{ optional: true; }, { optional: true; }, null, null, null, null, { optional: true; }, { optional: true; }]>;
9851
+ 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"; "onCustomAttributesSave": "onCustomAttributesSave"; }, never, never, true, never>;
9033
9852
  }
9034
9853
 
9035
9854
  /**
@@ -9274,560 +10093,314 @@ declare class AppSettingsEditorComponent implements OnInit {
9274
10093
  static ɵcmp: i0.ɵɵComponentDeclaration<AppSettingsEditorComponent, "wuic-app-settings-editor", never, {}, {}, never, never, true, never>;
9275
10094
  }
9276
10095
 
9277
- declare class DataActionButtonComponent implements AfterViewInit, OnDestroy {
9278
- private trslSrv;
9279
- private cd;
9280
- private messageService;
9281
- private confirmationService;
9282
- private router;
9283
- private http;
9284
- private metadataProvider;
9285
- private static readonly ACTION_KEY_EDIT;
9286
- data: any;
9287
- metaInfo: MetaInfo;
9288
- datasource: BehaviorSubject<DataSourceComponent>;
9289
- filter?: () => void;
9290
- simplified: boolean;
9291
- parentField: string;
9292
- btn: SplitButton;
9293
- simpleMenu?: Menu;
9294
- simplifiedMenuOpen: boolean;
9295
- items: MenuItem[];
9296
- selectedValue: any;
9297
- pkName: string;
9298
- inlineItems: any[];
9299
- nonInlineEditingItems: MenuItem[];
9300
- private translationsLoadedSub?;
9301
- constructor(trslSrv: TranslationManagerService, cd: ChangeDetectorRef, messageService: MessageService, confirmationService: ConfirmationService, router: Router, http: HttpClient, metadataProvider: MetadataProviderService);
9302
- /**
9303
- * Hook di debug locale per ispezionare l'evento click sul pulsante azioni.
9304
- * @param $event Evento UI ricevuto dal template.
9305
- */
9306
- test($event: any): void;
9307
- /**
9308
- * Inizializza il menu azioni in base ai metadati tabella/colonna (`md_editable`, `md_deletable`, `md_inline_edit`, colonne `button`).
9309
- * Calcola anche la PK corrente per le azioni route-based.
9310
- */
9311
- ngAfterViewInit(): void;
9312
- ngOnDestroy(): void;
9313
- private rebuildActionMenus;
9314
- private translateLabel;
9315
- /**
9316
- * Esegue il comando dell'item selezionato se non disabilitato.
9317
- * @param item Voce menu azione.
9318
- */
9319
- select(item: any): void;
9320
- /**
9321
- * Aggiunge al menu le azioni dinamiche derivate dalle colonne metadata di tipo `button`.
9322
- * @param target Collezione menu da arricchire.
9323
- */
9324
- private appendMetadataButtonItems;
9325
- private getButtonActionRecord;
9326
- /**
9327
- * Valuta se un bottone metadata e attivo verificando callback azione e condizione visibilita (`mc_button_visibility_condition`).
9328
- * @param col Metadato colonna di tipo button.
9329
- * @returns `true` se il bottone e eseguibile.
9330
- */
9331
- private isMetadataButtonEnabled;
9332
- /**
9333
- * Esegue l'azione custom del bottone metadata, con eventuale conferma (`mc_button_confirm_message`) e gestione errori centralizzata.
9334
- * @param col Metadato colonna button.
9335
- * @param record Record osservabile corrente.
9336
- * @param event Evento UI di invocazione.
9337
- */
9338
- private executeMetadataButton;
9339
- /**
9340
- * Avvia il flusso edit del record corrente:
9341
- * inline edit, popup `EditFormComponent` oppure navigazione route `/{route}/edit/{pk}`.
9342
- */
9343
- edit(): void;
9344
- /**
9345
- * Richiede conferma e, in caso positivo, elimina il record via `datasource.syncData(..., true)` ricaricando la griglia.
9346
- */
9347
- delete(): Promise<void>;
9348
- private canRestoreFromChangeMaster;
9349
- private appendRestoreFromChangeMasterActionAsync;
9350
- private isLogicalDeleteSupportedRoute;
9351
- private getRecordFieldIgnoreCase;
9352
- private restoreFromChangeMaster;
9353
- /**
9354
- * Apre il record in modalita sola lettura tramite `EditFormComponent` con `readOnly: true`.
9355
- */
9356
- detail(): void;
9357
- /**
9358
- * Apre `EditFormComponent` in modalita cloning per creare una copia del record corrente.
9359
- */
9360
- clone(): void;
9361
- /**
9362
- * Salva modifiche inline sincronizzando il record osservabile con backend e riallineando il modello riga in tabella.
9363
- */
9364
- save(): Promise<void>;
9365
- /**
9366
- * Annulla l'inline edit locale della riga corrente.
9367
- */
9368
- cancelEdit(): Promise<void>;
9369
- /**
9370
- * Hook evento click principale (attualmente usato come placeholder/debug).
9371
- * @param $event Evento click.
9372
- */
9373
- onClick($event: any): void;
9374
- /**
9375
- * Hook richiamato alla chiusura del menu split button.
9376
- * @param $event Evento PrimeNG.
9377
- */
9378
- onMenuHide($event: any): void;
9379
- /**
9380
- * Hook richiamato all'apertura del menu split button.
9381
- * @param $event Evento PrimeNG.
9382
- */
9383
- onMenuShow($event: any): void;
9384
- /**
9385
- * Hook click dropdown del pulsante azioni (punto estensione per custom behavior).
9386
- * @param $event Evento click dropdown.
9387
- */
9388
- onDropdownClick($event: any): void;
9389
- /**
9390
- * Ferma la propagazione dell'evento per evitare side effects sul contenitore (es. row click/select).
9391
- * @param $event Evento DOM.
9392
- */
9393
- fix($event: any): void;
9394
- /**
9395
- * Apre/chiude il popup menu in modalita semplificata con overlay appeso al body.
9396
- * Evita clipping dentro i contenitori FullCalendar.
9397
- * @param event Evento click del trigger.
9398
- */
9399
- onSimplifiedMenuClick(event: Event): void;
9400
- onSimplifiedMenuShow(): void;
9401
- onSimplifiedMenuHide(): void;
9402
- /**
9403
- * Abilita modalita inline-cell-editing via metadata tabella (con fallback legacy).
9404
- */
9405
- isInlineCellEditingEnabled(): boolean;
9406
- /**
9407
- * In inline-cell-editing, anche se la riga e marcata editing, mostra menu standard senza "edit".
9408
- */
9409
- showInlineEditingMenu(): boolean;
9410
- /**
9411
- * Modello menu effettivo da renderizzare nel pulsante azioni.
9412
- */
9413
- getActionMenuModel(): MenuItem[];
9414
- private toBooleanLoose;
9415
- addRecord(): void;
9416
- static ɵfac: i0.ɵɵFactoryDeclaration<DataActionButtonComponent, never>;
9417
- static ɵcmp: i0.ɵɵComponentDeclaration<DataActionButtonComponent, "wuic-data-action-button", never, { "data": { "alias": "data"; "required": false; }; "metaInfo": { "alias": "metaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "filter": { "alias": "filter"; "required": false; }; "simplified": { "alias": "simplified"; "required": false; }; "parentField": { "alias": "parentField"; "required": false; }; }, {}, never, never, true, never>;
9418
- }
9419
-
9420
- declare class LazyDataActionButtonComponent implements OnInit {
9421
- private readonly cdr;
9422
- /**
9423
- * Input dal componente padre per data; usata nella configurazione e nel rendering del componente.
9424
- */
9425
- data: any;
9426
- /**
9427
- * Input dal componente padre per meta info; usata nella configurazione e nel rendering del componente.
9428
- */
9429
- metaInfo: MetaInfo;
9430
- /**
9431
- * Input dal componente padre per datasource; usata nella configurazione e nel rendering del componente.
9432
- */
9433
- datasource: BehaviorSubject<any>;
9434
- /**
9435
- * Input dal componente padre per filter; usata nella configurazione e nel rendering del componente.
9436
- */
9437
- filter?: () => void;
9438
- /**
9439
- * Input dal componente padre per simplified; usata nella configurazione e nel rendering del componente.
9440
- */
9441
- simplified: boolean;
9442
- parentField: string;
9443
- /**
9444
- * Proprieta di stato del componente per loaded component, usata dalla logica interna e dal template.
9445
- */
9446
- loadedComponent: any;
9447
- constructor(cdr: ChangeDetectorRef);
9448
- /**
9449
- * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
9450
- */
9451
- ngOnInit(): Promise<void>;
9452
- /**
9453
- * Gestisce la logica di `componentInputs` con regole guidate dai metadati server `_Metadati_*` (tabella/colonna).
9454
- * @returns Oggetto risultato costruito dal metodo per il passo successivo del flusso.
9455
- */
9456
- componentInputs(): {
9457
- data: any;
9458
- metaInfo: MetaInfo;
9459
- datasource: BehaviorSubject<any>;
9460
- filter: () => void;
9461
- simplified: boolean;
9462
- parentField: string;
9463
- };
9464
- static ɵfac: i0.ɵɵFactoryDeclaration<LazyDataActionButtonComponent, never>;
9465
- static ɵcmp: i0.ɵɵComponentDeclaration<LazyDataActionButtonComponent, "wuic-data-action-button-lazy", never, { "data": { "alias": "data"; "required": false; }; "metaInfo": { "alias": "metaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "filter": { "alias": "filter"; "required": false; }; "simplified": { "alias": "simplified"; "required": false; }; "parentField": { "alias": "parentField"; "required": false; }; }, {}, never, never, true, never>;
9466
- }
9467
-
9468
- /**
9469
- * Shape of the response returned by `/api/Meta/LicenseStatus` (GET).
9470
- * The endpoint is defined in `Controllers/MetaController.cs` LicenseStatus action.
9471
- */
9472
- interface LicenseStatusResponse {
9473
- machineFingerprint?: string;
9474
- licenseValid?: boolean;
9475
- licenseReason?: string;
9476
- licenseExpiryUtc?: string | null;
9477
- licenseEmail?: string;
9478
- maintenanceExpiryUtc?: string | null;
9479
- tier?: string;
9480
- features?: string[];
10096
+ declare class DataActionButtonComponent implements AfterViewInit, OnDestroy {
10097
+ private trslSrv;
10098
+ private cd;
10099
+ private messageService;
10100
+ private confirmationService;
10101
+ private router;
10102
+ private http;
10103
+ private metadataProvider;
10104
+ private static readonly ACTION_KEY_EDIT;
10105
+ data: any;
10106
+ metaInfo: MetaInfo;
10107
+ datasource: BehaviorSubject<DataSourceComponent>;
10108
+ filter?: () => void;
10109
+ simplified: boolean;
10110
+ parentField: string;
10111
+ btn: SplitButton;
10112
+ simpleMenu?: Menu;
10113
+ simplifiedMenuOpen: boolean;
10114
+ items: MenuItem[];
10115
+ selectedValue: any;
10116
+ pkName: string;
10117
+ inlineItems: any[];
10118
+ nonInlineEditingItems: MenuItem[];
10119
+ private translationsLoadedSub?;
10120
+ constructor(trslSrv: TranslationManagerService, cd: ChangeDetectorRef, messageService: MessageService, confirmationService: ConfirmationService, router: Router, http: HttpClient, metadataProvider: MetadataProviderService);
9481
10121
  /**
9482
- * DBMS utilizzato dal backend per il **DB DATI** (`AppSettings.dbms`):
9483
- * `'mssql'` o `'mysql'`. Aggiunto 2026-04-28 per il tooltip license del
9484
- * meta-menu — sysadmin vede a colpo d'occhio su quale provider gira il
9485
- * deploy.
10122
+ * Hook di debug locale per ispezionare l'evento click sul pulsante azioni.
10123
+ * @param $event Evento UI ricevuto dal template.
9486
10124
  */
9487
- dataDbms?: string;
10125
+ test($event: any): void;
9488
10126
  /**
9489
- * DBMS utilizzato dal backend per il **DB METADATI** (`AppSettings.meta-dbms`).
9490
- * Tipicamente uguale a `dataDbms` ma puo' divergere quando
9491
- * `allowMultipleDBMS=true` (es. data MySQL + metadata MSSQL).
10127
+ * Inizializza il menu azioni in base ai metadati tabella/colonna (`md_editable`, `md_deletable`, `md_inline_edit`, colonne `button`).
10128
+ * Calcola anche la PK corrente per le azioni route-based.
9492
10129
  */
9493
- metaDbms?: string;
9494
- }
9495
- /**
9496
- * Client-side view of the current license. Exposes synchronous `has(feature)`
9497
- * predicate for use in templates, directives, guards, and components.
9498
- *
9499
- * Lifecycle:
9500
- * 1) App bootstrap calls `refresh()` once.
9501
- * 2) All `*wuicFeature` directives and `FeatureRouteGuard` read from the
9502
- * cached snapshot via `has()`.
9503
- * 3) On license change (upgrade via new appsettings.json) restart the app
9504
- * OR call `refresh()` again to re-fetch.
9505
- *
9506
- * IMPORTANT: this service is a UX layer only. The real security is server-side
9507
- * (see `SanitizeBoardContent` + `[RequireFeature]` + data-decoration in
9508
- * `AsmxCrudRead`). A client can patch this service and unlock everything locally,
9509
- * but the server will still refuse premium operations.
9510
- */
9511
- declare class LicenseFeatureService {
9512
- private http;
9513
- private static readonly ALWAYS_ALLOWED_ARCHETYPES;
9514
- private statusSubject;
9515
- private loadedOnce;
10130
+ ngAfterViewInit(): void;
10131
+ ngOnDestroy(): void;
10132
+ private rebuildActionMenus;
10133
+ private translateLabel;
9516
10134
  /**
9517
- * Promise risolta dopo il PRIMO `refresh()` (success or fail-closed).
9518
- * Usata dai route guard per attendere che lo snapshot iniziale sia
9519
- * disponibile prima di decidere access → evita race post-refresh pagina
9520
- * dove il guard partiva con `statusSubject.value === null` e denyava la
9521
- * feature anche con licenza valida.
10135
+ * Esegue il comando dell'item selezionato se non disabilitato.
10136
+ * @param item Voce menu azione.
9522
10137
  */
9523
- private readyResolve;
9524
- private readyPromise;
9525
- constructor(http: HttpClient);
10138
+ select(item: any): void;
9526
10139
  /**
9527
- * Ritorna una Promise che risolve quando il primo `refresh()` ha completato
9528
- * (con successo o con fail-closed fallback). Dopo il primo load, ritorna
9529
- * una Promise gia' risolta → overhead zero. Il guard la await per decidere
9530
- * solo con snapshot reale, non con `null` iniziale.
10140
+ * Aggiunge al menu le azioni dinamiche derivate dalle colonne metadata di tipo `button`.
10141
+ * @param target Collezione menu da arricchire.
9531
10142
  */
9532
- ready(): Promise<void>;
10143
+ private appendMetadataButtonItems;
10144
+ private getButtonActionRecord;
9533
10145
  /**
9534
- * Observable of the current license status snapshot. Emits `null` until the
9535
- * first `refresh()` completes.
10146
+ * Valuta se un bottone metadata e attivo verificando callback azione e condizione visibilita (`mc_button_visibility_condition`).
10147
+ * @param col Metadato colonna di tipo button.
10148
+ * @returns `true` se il bottone e eseguibile.
9536
10149
  */
9537
- status$(): Observable<LicenseStatusResponse | null>;
10150
+ private isMetadataButtonEnabled;
9538
10151
  /**
9539
- * Synchronous accessor to the cached snapshot. Returns `null` if not yet loaded.
10152
+ * Esegue l'azione custom del bottone metadata, con eventuale conferma (`mc_button_confirm_message`) e gestione errori centralizzata.
10153
+ * @param col Metadato colonna button.
10154
+ * @param record Record osservabile corrente.
10155
+ * @param event Evento UI di invocazione.
9540
10156
  */
9541
- snapshot(): LicenseStatusResponse | null;
10157
+ private executeMetadataButton;
9542
10158
  /**
9543
- * Fetches `/api/Meta/LicenseStatus` and caches the result. Returns the promise
9544
- * so callers (like an APP_INITIALIZER) can await it.
10159
+ * Avvia il flusso edit del record corrente:
10160
+ * inline edit, popup `EditFormComponent` oppure navigazione route `/{route}/edit/{pk}`.
9545
10161
  */
9546
- refresh(): Promise<LicenseStatusResponse | null>;
9547
- /** Idempotent: il primo refresh risolve `readyPromise`; i successivi no-op. */
9548
- private signalReady;
10162
+ edit(): void;
9549
10163
  /**
9550
- * Returns true when the current license includes the given feature flag.
9551
- * Returns `false` when:
9552
- * - license not yet loaded (conservative default);
9553
- * - license is invalid;
9554
- * - feature is not in the `features` array.
10164
+ * Richiede conferma e, in caso positivo, elimina il record via `datasource.syncData(..., true)` ricaricando la griglia.
9555
10165
  */
9556
- has(feature: string): boolean;
10166
+ delete(): Promise<void>;
10167
+ private canRestoreFromChangeMaster;
10168
+ private appendRestoreFromChangeMasterActionAsync;
10169
+ private isLogicalDeleteSupportedRoute;
10170
+ private getRecordFieldIgnoreCase;
10171
+ private restoreFromChangeMaster;
9557
10172
  /**
9558
- * Returns true when the archetype (e.g. "spreadsheet", "pivot-grid", "list")
9559
- * is permitted by the current license. Archetypes in the always-allowed set
9560
- * (list, kanban, chart, ...) return true unconditionally.
10173
+ * Apre il record in modalita sola lettura tramite `EditFormComponent` con `readOnly: true`.
9561
10174
  */
9562
- isArchetypeAllowed(archetype: string): boolean;
10175
+ detail(): void;
9563
10176
  /**
9564
- * Mirrors the server-side `LicenseFeatureMap.ArchetypeFeatureMap`. Kept
9565
- * hardcoded on both sides so a patched client gets UX unlock, but the
9566
- * server-side gate (boardcontent sanitizer + data-decoration) still enforces.
10177
+ * Apre `EditFormComponent` in modalita cloning per creare una copia del record corrente.
9567
10178
  */
9568
- private archetypeToFeature;
10179
+ clone(): void;
9569
10180
  /**
9570
- * Builds the LicenseStatus endpoint URL from `global_root_url`. The root is
9571
- * typically `"/api/Meta/AsmxProxy/"` (AsmxProxy pattern) or `"/api/Meta/"`
9572
- * (direct). LicenseStatus is a direct GET action on MetaController, so we
9573
- * strip any trailing `AsmxProxy/` segment before appending the action name.
10181
+ * Salva modifiche inline sincronizzando il record osservabile con backend e riallineando il modello riga in tabella.
9574
10182
  */
9575
- private resolveLicenseStatusUrl;
9576
- static ɵfac: i0.ɵɵFactoryDeclaration<LicenseFeatureService, never>;
9577
- static ɵprov: i0.ɵɵInjectableDeclaration<LicenseFeatureService>;
9578
- }
9579
-
9580
- interface AuthSessionState {
9581
- initialized: boolean;
9582
- loading: boolean;
9583
- enabled: boolean;
9584
- authenticated: boolean;
9585
- legacyAuthenticated: boolean;
9586
- provider?: string;
9587
- name?: string;
9588
- legacyName?: string;
9589
- legacyRole?: string;
9590
- claims?: {
9591
- type: string;
9592
- value: string;
9593
- }[];
9594
- error?: string;
9595
- returnUrl: string;
9596
- sessionExpiring?: boolean;
9597
- sessionExpiresInSeconds?: number;
9598
- }
9599
- declare class AuthSessionService {
9600
- private http;
9601
- private userInfoService;
9602
- private metadataProvider;
9603
- private translationManager;
9604
- private ngZone;
9605
- private initialized;
9606
- private sessionTimeoutMs;
9607
- private sessionWarningMs;
9608
- private sessionTimer;
9609
- private sessionWarningTimer;
9610
- private sessionCountdownTimer;
9611
- private readonly stateSubject;
9612
- readonly state$: rxjs.Observable<AuthSessionState>;
9613
- get snapshot(): AuthSessionState;
9614
- constructor(http: HttpClient, userInfoService: UserInfoService, metadataProvider: MetadataProviderService, translationManager: TranslationManagerService, ngZone: NgZone);
10183
+ save(): Promise<void>;
9615
10184
  /**
9616
- * Allinea ngx-translate alla lingua dell'utente appena autenticato/hydratato.
9617
- * Necessario perche' il TranslationManagerService bootstrap risolve la lingua
9618
- * via `userInfoService.getuserInfo()` quando NESSUN utente e' ancora loggato,
9619
- * finendo di default su `navigator.language` o 'it-IT'. Senza questa call
9620
- * esplicita post-login, le traduzioni rese dal primo render (toolbar, menu,
9621
- * dialog) restano "appiccicate" alla lingua di bootstrap finche' l'utente
9622
- * non cambia lingua manualmente dal selettore, che invece chiama direttamente
9623
- * `useLanguage()`. Chiamata best-effort: fallisce silenzioso se la lingua non
9624
- * e' supportata o la tabella traduzioni non e' ancora pronta.
10185
+ * Annulla l'inline edit locale della riga corrente.
9625
10186
  */
9626
- private applyUserLanguageToTranslations;
10187
+ cancelEdit(): Promise<void>;
9627
10188
  /**
9628
- * Inizializza il servizio una sola volta (o forzatamente) e carica lo stato sessione corrente via `refreshAll`.
9629
- * @param force Se `true` forza una nuova inizializzazione anche se gia avvenuta.
10189
+ * Hook evento click principale (attualmente usato come placeholder/debug).
10190
+ * @param $event Evento click.
9630
10191
  */
9631
- initialize(force?: boolean): Promise<void>;
10192
+ onClick($event: any): void;
9632
10193
  /**
9633
- * Hydrates the UI-side user snapshot from the backend when sessionStorage
9634
- * is empty but a server-managed HttpOnly `k-user` cookie might still be
9635
- * valid. This is the critical step for `enableCookieAuthentication=true`:
9636
- * after a browser restart (or new tab) sessionStorage is gone, the cookie
9637
- * is HttpOnly and invisible to JS, so without this call the guard would
9638
- * wrongly redirect to `/unauthorized` despite a valid session.
9639
- *
9640
- * Flow:
9641
- * 1. If sessionStorage already has a snapshot → no hydration needed.
9642
- * 2. Otherwise call `MetaService.me` with `withCredentials:true`. The
9643
- * backend reads the HttpOnly cookie server-side and returns the
9644
- * public user fields (and `cookieAuthEnabled` for introspection).
9645
- * 3. If `me()` returns a populated payload, write it to sessionStorage
9646
- * via `userInfoService.setUserInfoCookie` so subsequent calls see
9647
- * the user. If `me()` returns an empty object `{}` (no valid
9648
- * cookie) the hydration is a no-op and the UI stays logged out.
9649
- *
9650
- * Errors are swallowed on purpose: if `me()` throws (network, backend
9651
- * down, legacy backend without the endpoint), we fall back to whatever
9652
- * the cookie/sessionStorage already has without blocking the boot.
10194
+ * Hook richiamato alla chiusura del menu split button.
10195
+ * @param $event Evento PrimeNG.
9653
10196
  */
9654
- private hydrateFromServerCookie;
10197
+ onMenuHide($event: any): void;
9655
10198
  /**
9656
- * Ricalcola lo stato autenticazione combinando configurazione OAuth, endpoint `Auth/Enabled`, endpoint `Auth/Me`
9657
- * e fallback sessione legacy (`k-user`), poi sincronizza eventuali custom settings utente.
10199
+ * Hook richiamato all'apertura del menu split button.
10200
+ * @param $event Evento PrimeNG.
9658
10201
  */
9659
- refreshAll(): Promise<void>;
10202
+ onMenuShow($event: any): void;
9660
10203
  /**
9661
- * Aggiorna il `returnUrl` nello stato sessione applicando normalizzazione anti-open-redirect.
9662
- * @param returnUrl URL di ritorno post login/logout.
10204
+ * Hook click dropdown del pulsante azioni (punto estensione per custom behavior).
10205
+ * @param $event Evento click dropdown.
9663
10206
  */
9664
- setReturnUrl(returnUrl: string): void;
10207
+ onDropdownClick($event: any): void;
9665
10208
  /**
9666
- * Avvia il login OAuth reindirizzando il browser a `Auth/Login` con `returnUrl` codificato.
9667
- * @param returnUrl URL di ritorno post login/logout.
10209
+ * Ferma la propagazione dell'evento per evitare side effects sul contenitore (es. row click/select).
10210
+ * @param $event Evento DOM.
9668
10211
  */
9669
- login(returnUrl?: string): void;
10212
+ fix($event: any): void;
9670
10213
  /**
9671
- * Esegue logout OAuth: pulisce prima stato client (storage + DB locali) e custom settings, poi redirect a `Auth/Logout`.
9672
- * @param returnUrl URL di ritorno post login/logout.
10214
+ * Apre/chiude il popup menu in modalita semplificata con overlay appeso al body.
10215
+ * Evita clipping dentro i contenitori FullCalendar.
10216
+ * @param event Evento click del trigger.
9673
10217
  */
9674
- logout(returnUrl?: string): Promise<void>;
10218
+ onSimplifiedMenuClick(event: Event): void;
10219
+ onSimplifiedMenuShow(): void;
10220
+ onSimplifiedMenuHide(): void;
9675
10221
  /**
9676
- * Esegue login legacy via `MetaService.login`, interpreta le varianti payload storiche (`isLogged`, `value`, JSON string)
9677
- * e in caso positivo salva l'utente nel cookie `k-user`.
9678
- * @param username Username credenziale di autenticazione.
9679
- * @param password Password credenziale di autenticazione.
10222
+ * Abilita modalita inline-cell-editing via metadata tabella (con fallback legacy).
9680
10223
  */
9681
- legacyLogin(username: string, password: string, captchaToken?: string): Promise<boolean>;
10224
+ isInlineCellEditingEnabled(): boolean;
9682
10225
  /**
9683
- * Logout flow that works in BOTH cookie modes:
9684
- *
9685
- * - **Server-managed mode** (`enableCookieAuthentication=true`): the
9686
- * `k-user` cookie is HttpOnly, so the only way to delete it is via a
9687
- * `Set-Cookie` delete header from the server. We call
9688
- * `MetaService.logoutSession` (parameterless) which:
9689
- * 1. derives the user from the cookie server-side,
9690
- * 2. wipes the DB session token via the existing `logout(user)`
9691
- * per-DBMS dispatcher,
9692
- * 3. emits the `Set-Cookie` delete with matching CookieOptions.
9693
- *
9694
- * - **Legacy mode** (`enableCookieAuthentication=false`): we still call
9695
- * `logoutSession` because the server-side helper is idempotent in
9696
- * legacy mode and always wipes the DB token. The local
9697
- * `userInfoService.clearUserInfo()` then deletes the JS-readable
9698
- * cookie + sessionStorage snapshot.
9699
- *
9700
- * Why not call the legacy `MetaService.logout(user)` overload? It only
9701
- * runs the per-DBMS DB cleanup; it does NOT emit the cookie delete
9702
- * header, so the HttpOnly cookie would survive the logout in
9703
- * server-managed mode and the next page load would re-hydrate the
9704
- * supposedly-logged-out user via `MetaService.me`. The new
9705
- * `logoutSession` does both atomically.
10226
+ * In inline-cell-editing, anche se la riga e marcata editing, mostra menu standard senza "edit".
9706
10227
  */
9707
- legacyLogout(): Promise<void>;
10228
+ showInlineEditingMenu(): boolean;
9708
10229
  /**
9709
- * Pulisce lo stato runtime e le cache associate.
9710
- * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
9711
- * @returns Valore restituito dal metodo (Promise<void>).
10230
+ * Modello menu effettivo da renderizzare nel pulsante azioni.
9712
10231
  */
9713
- private clearClientRuntimeState;
10232
+ getActionMenuModel(): MenuItem[];
10233
+ private toBooleanLoose;
10234
+ addRecord(): void;
10235
+ static ɵfac: i0.ɵɵFactoryDeclaration<DataActionButtonComponent, never>;
10236
+ static ɵcmp: i0.ɵɵComponentDeclaration<DataActionButtonComponent, "wuic-data-action-button", never, { "data": { "alias": "data"; "required": false; }; "metaInfo": { "alias": "metaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "filter": { "alias": "filter"; "required": false; }; "simplified": { "alias": "simplified"; "required": false; }; "parentField": { "alias": "parentField"; "required": false; }; }, {}, never, never, true, never>;
10237
+ }
10238
+
10239
+ declare class LazyDataActionButtonComponent implements OnInit {
10240
+ private readonly cdr;
9714
10241
  /**
9715
- * Pulisce lo stato runtime e le cache associate.
9716
- * Legge/scrive dati persistenti su storage browser.
10242
+ * Input dal componente padre per data; usata nella configurazione e nel rendering del componente.
9717
10243
  */
9718
- private clearBrowserStorage;
10244
+ data: any;
9719
10245
  /**
9720
- * Rimuove i dati target aggiornando lo stato del servizio.
9721
- * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
9722
- * @param dbName Nome database locale/remote da trattare.
9723
- * @returns Valore restituito dal metodo (Promise<void>).
10246
+ * Input dal componente padre per meta info; usata nella configurazione e nel rendering del componente.
9724
10247
  */
9725
- private deleteDexieDatabase;
10248
+ metaInfo: MetaInfo;
9726
10249
  /**
9727
- * Rimuove i dati target aggiornando lo stato del servizio.
9728
- * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
9729
- * @param dbName Nome database locale/remote da trattare.
9730
- * @returns Valore restituito dal metodo (Promise<void>).
10250
+ * Input dal componente padre per datasource; usata nella configurazione e nel rendering del componente.
9731
10251
  */
9732
- private deleteIndexedDbByName;
10252
+ datasource: BehaviorSubject<any>;
9733
10253
  /**
9734
- * Carica e cache-a i custom settings dell'utente loggato in localStorage allineando il bootstrap sessione con MetadataProvider.
10254
+ * Input dal componente padre per filter; usata nella configurazione e nel rendering del componente.
9735
10255
  */
9736
- private bootstrapUserCustomSettings;
10256
+ filter?: () => void;
9737
10257
  /**
9738
- * Configura il timeout di sessione in minuti. Chiamato dal meta-menu dopo aver letto AuthConfig.
10258
+ * Input dal componente padre per simplified; usata nella configurazione e nel rendering del componente.
9739
10259
  */
9740
- setSessionTimeout(minutes: number, warningMinutes?: number): void;
9741
- private activityListenersAttached;
9742
- /** Timestamp dell'ultimo reset throttled, in ms epoch. */
9743
- private lastActivityResetAt;
9744
- /** Min intervallo tra reset throttled (mousemove/scroll). 1s e' un buon compromesso
9745
- * tra responsiveness al "vero" idle e overhead da event flood. */
9746
- private static readonly ACTIVITY_RESET_THROTTLE_MS;
9747
- private setupActivityListeners;
10260
+ simplified: boolean;
10261
+ parentField: string;
9748
10262
  /**
9749
- * Avvia/riavvia i timer di sessione. Chiamato dopo login e ad ogni attività HTTP.
10263
+ * Proprieta di stato del componente per loaded component, usata dalla logica interna e dal template.
9750
10264
  */
9751
- resetSessionTimer(): void;
9752
- private startSessionExpiryCountdown;
9753
- private handleSessionExpired;
9754
- private clearSessionTimers;
9755
- private isUserAuthenticated;
10265
+ loadedComponent: any;
10266
+ constructor(cdr: ChangeDetectorRef);
9756
10267
  /**
9757
- * Applica un aggiornamento parziale allo stato `AuthSessionState` preservando le proprieta non toccate.
9758
- * @param partial Delta stato da fondere con lo stato corrente.
10268
+ * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
9759
10269
  */
10270
+ ngOnInit(): Promise<void>;
9760
10271
  /**
9761
- * Sets a user-visible error message in the auth state.
9762
- * Used by the auth-expired interceptor to communicate the logout
9763
- * reason (e.g. "session replaced by another login") after the
9764
- * logout flow has completed and the login form is visible.
9765
- */
9766
- setError(message: string): void;
9767
- /** User-facing messages keyed by server reason code. */
9768
- private static readonly REASON_MESSAGES;
10272
+ * Gestisce la logica di `componentInputs` con regole guidate dai metadati server `_Metadati_*` (tabella/colonna).
10273
+ * @returns Oggetto risultato costruito dal metodo per il passo successivo del flusso.
10274
+ */
10275
+ componentInputs(): {
10276
+ data: any;
10277
+ metaInfo: MetaInfo;
10278
+ datasource: BehaviorSubject<any>;
10279
+ filter: () => void;
10280
+ simplified: boolean;
10281
+ parentField: string;
10282
+ };
10283
+ static ɵfac: i0.ɵɵFactoryDeclaration<LazyDataActionButtonComponent, never>;
10284
+ static ɵcmp: i0.ɵɵComponentDeclaration<LazyDataActionButtonComponent, "wuic-data-action-button-lazy", never, { "data": { "alias": "data"; "required": false; }; "metaInfo": { "alias": "metaInfo"; "required": false; }; "datasource": { "alias": "datasource"; "required": false; }; "filter": { "alias": "filter"; "required": false; }; "simplified": { "alias": "simplified"; "required": false; }; "parentField": { "alias": "parentField"; "required": false; }; }, {}, never, never, true, never>;
10285
+ }
10286
+
10287
+ /**
10288
+ * Shape of the response returned by `/api/Meta/LicenseStatus` (GET).
10289
+ * The endpoint is defined in `Controllers/MetaController.cs` LicenseStatus action.
10290
+ */
10291
+ interface LicenseStatusResponse {
10292
+ machineFingerprint?: string;
10293
+ licenseValid?: boolean;
10294
+ licenseReason?: string;
10295
+ licenseExpiryUtc?: string | null;
10296
+ licenseEmail?: string;
10297
+ maintenanceExpiryUtc?: string | null;
10298
+ tier?: string;
10299
+ features?: string[];
9769
10300
  /**
9770
- * Reads and removes the redirect reason left by the auth-expired
9771
- * interceptor in localStorage, then sets the corresponding error
9772
- * message in the auth state so the login form displays it.
10301
+ * DBMS utilizzato dal backend per il **DB DATI** (`AppSettings.dbms`):
10302
+ * `'mssql'` o `'mysql'`. Aggiunto 2026-04-28 per il tooltip license del
10303
+ * meta-menu — sysadmin vede a colpo d'occhio su quale provider gira il
10304
+ * deploy.
9773
10305
  */
9774
- private applyRedirectReason;
9775
- private patchState;
10306
+ dataDbms?: string;
9776
10307
  /**
9777
- * Costruisce una struttura derivata a partire dallo stato corrente.
9778
- * @param action Azione richiesta nel flusso corrente.
10308
+ * DBMS utilizzato dal backend per il **DB METADATI** (`AppSettings.meta-dbms`).
10309
+ * Tipicamente uguale a `dataDbms` ma puo' divergere quando
10310
+ * `allowMultipleDBMS=true` (es. data MySQL + metadata MSSQL).
9779
10311
  */
9780
- private buildEndpoint;
10312
+ metaDbms?: string;
10313
+ }
10314
+ /**
10315
+ * Client-side view of the current license. Exposes synchronous `has(feature)`
10316
+ * predicate for use in templates, directives, guards, and components.
10317
+ *
10318
+ * Lifecycle:
10319
+ * 1) App bootstrap calls `refresh()` once.
10320
+ * 2) All `*wuicFeature` directives and `FeatureRouteGuard` read from the
10321
+ * cached snapshot via `has()`.
10322
+ * 3) On license change (upgrade via new appsettings.json) restart the app
10323
+ * OR call `refresh()` again to re-fetch.
10324
+ *
10325
+ * IMPORTANT: this service is a UX layer only. The real security is server-side
10326
+ * (see `SanitizeBoardContent` + `[RequireFeature]` + data-decoration in
10327
+ * `AsmxCrudRead`). A client can patch this service and unlock everything locally,
10328
+ * but the server will still refuse premium operations.
10329
+ */
10330
+ declare class LicenseFeatureService {
10331
+ private http;
10332
+ private static readonly ALWAYS_ALLOWED_ARCHETYPES;
10333
+ private statusSubject;
10334
+ private loadedOnce;
9781
10335
  /**
9782
- * Costruisce una struttura derivata a partire dallo stato corrente.
9783
- * @param fullMethodName Nome completo metodo legacy (es. `MetaService.login`).
10336
+ * Promise risolta dopo il PRIMO `refresh()` (success or fail-closed).
10337
+ * Usata dai route guard per attendere che lo snapshot iniziale sia
10338
+ * disponibile prima di decidere access → evita race post-refresh pagina
10339
+ * dove il guard partiva con `statusSubject.value === null` e denyava la
10340
+ * feature anche con licenza valida.
9784
10341
  */
9785
- private buildMetaAsmxEndpoint;
10342
+ private readyResolve;
10343
+ private readyPromise;
10344
+ constructor(http: HttpClient);
9786
10345
  /**
9787
- * Risolve la base URL API usata dal servizio: preferisce `appSettings.api_url`, fallback su `${window.location.origin}/api/`.
10346
+ * Ritorna una Promise che risolve quando il primo `refresh()` ha completato
10347
+ * (con successo o con fail-closed fallback). Dopo il primo load, ritorna
10348
+ * una Promise gia' risolta → overhead zero. Il guard la await per decidere
10349
+ * solo con snapshot reale, non con `null` iniziale.
9788
10350
  */
9789
- private getApiBaseUrl;
10351
+ ready(): Promise<void>;
9790
10352
  /**
9791
- * Valuta una condizione booleana sullo stato o sull'input corrente.
9792
- * @returns Valore restituito dal metodo (boolean).
10353
+ * Observable of the current license status snapshot. Emits `null` until the
10354
+ * first `refresh()` completes.
9793
10355
  */
9794
- private isOAuthEnabledInSettings;
10356
+ status$(): Observable<LicenseStatusResponse | null>;
9795
10357
  /**
9796
- * Normalizza il payload in una forma coerente per i passaggi successivi.
9797
- * @param returnUrl URL di ritorno post login/logout.
10358
+ * Synchronous accessor to the cached snapshot. Returns `null` if not yet loaded.
9798
10359
  */
9799
- private normalizeReturnUrl;
10360
+ snapshot(): LicenseStatusResponse | null;
9800
10361
  /**
9801
- * Ritorna l'URL browser corrente usato come `returnUrl` predefinito in login/logout.
10362
+ * Fetches `/api/Meta/LicenseStatus` and caches the result. Returns the promise
10363
+ * so callers (like an APP_INITIALIZER) can await it.
9802
10364
  */
9803
- private getCurrentLocalUrl;
10365
+ refresh(): Promise<LicenseStatusResponse | null>;
10366
+ /** Idempotent: il primo refresh risolve `readyPromise`; i successivi no-op. */
10367
+ private signalReady;
9804
10368
  /**
9805
- * Esegue il parsing del valore in ingresso con fallback sicuro.
9806
- * @param raw Payload legacy da interpretare (stringa JSON, oggetto o wrapper con `value`).
9807
- * @returns Valore restituito dal metodo (any).
10369
+ * Returns true when the current license includes the given feature flag.
10370
+ * Returns `false` when:
10371
+ * - license not yet loaded (conservative default);
10372
+ * - license is invalid;
10373
+ * - feature is not in the `features` array.
10374
+ *
10375
+ * Wildcard `"*"` nel features array sblocca tutte le feature (usato dai
10376
+ * tier top-level "enterprise" / host-bound bundled e dal server-side
10377
+ * `LicenseFeatureMap.ExpandFeatures` per Pro tier). Senza questo branch
10378
+ * la licenza con `features:["*"]` falliva ogni `has('dashboard-designer'/
10379
+ * 'spreadsheet'/...)` e il client nascondeva tutte le voci di menu
10380
+ * archetype-gated nonostante `licenseValid:true` e tier `professional`.
9808
10381
  */
9809
- private parseLegacyLoginResponse;
10382
+ has(feature: string): boolean;
9810
10383
  /**
9811
- * Estrae un messaggio errore leggibile da payload legacy eterogenei (raw/parsing/error/value) del login storico.
9812
- * @param raw Payload grezzo risposta/errore.
9813
- * @param parsed Payload gia interpretato.
9814
- * @returns Messaggio errore normalizzato oppure `null`.
10384
+ * Returns true when the archetype (e.g. "spreadsheet", "pivot-grid", "list")
10385
+ * is permitted by the current license. Archetypes in the always-allowed set
10386
+ * (list, kanban, chart, ...) return true unconditionally.
9815
10387
  */
9816
- private extractLegacyLoginError;
10388
+ isArchetypeAllowed(archetype: string): boolean;
9817
10389
  /**
9818
- * Prova a leggere un messaggio errore da stringhe plain/JSON o da oggetti con chiavi comuni (`message`, `error`, `ExceptionMessage`).
9819
- * @param candidate Sorgente messaggio da analizzare.
9820
- * @returns Messaggio trovato oppure `null`.
10390
+ * Mirrors the server-side `LicenseFeatureMap.ArchetypeFeatureMap`. Kept
10391
+ * hardcoded on both sides so a patched client gets UX unlock, but the
10392
+ * server-side gate (boardcontent sanitizer + data-decoration) still enforces.
9821
10393
  */
9822
- private readMessage;
10394
+ private archetypeToFeature;
9823
10395
  /**
9824
- * Log diagnostico opzionale del flusso login legacy, attivo solo con `appSettings.debugLegacyLogin === true`.
9825
- * @param kind Tipo evento (`response` o `error`).
9826
- * @param payload Payload da tracciare in console.
10396
+ * Builds the LicenseStatus endpoint URL from `global_root_url`. The root is
10397
+ * typically `"/api/Meta/AsmxProxy/"` (AsmxProxy pattern) or `"/api/Meta/"`
10398
+ * (direct). LicenseStatus is a direct GET action on MetaController, so we
10399
+ * strip any trailing `AsmxProxy/` segment before appending the action name.
9827
10400
  */
9828
- private debugLegacyLogin;
9829
- static ɵfac: i0.ɵɵFactoryDeclaration<AuthSessionService, never>;
9830
- static ɵprov: i0.ɵɵInjectableDeclaration<AuthSessionService>;
10401
+ private resolveLicenseStatusUrl;
10402
+ static ɵfac: i0.ɵɵFactoryDeclaration<LicenseFeatureService, never>;
10403
+ static ɵprov: i0.ɵɵInjectableDeclaration<LicenseFeatureService>;
9831
10404
  }
9832
10405
 
9833
10406
  type WorkflowRuntimeMenuState = {
@@ -10293,17 +10866,6 @@ declare class MetaMenuComponent implements OnInit, AfterViewInit, OnDestroy {
10293
10866
  * altrimenti svuota il menu locale e interrompe il flusso.
10294
10867
  */
10295
10868
  private loadMenuIfAllowed;
10296
- /**
10297
- * Removes menu entries pointing to routes that require a license feature not
10298
- * included in the current license. Works recursively on nested items. The
10299
- * `route` shape of menu items comes from `mm_uri_menu` and matches the
10300
- * Angular route templates (e.g. `workflow-designer`, `<route>/spreadsheet`,
10301
- * `<route>/pivot-builder`, `<route>/dashboard`, `rag-chatbot`).
10302
- *
10303
- * UX layer only — server-side `SanitizeBoardContent` + `[RequireFeature]`
10304
- * are the authoritative gates.
10305
- */
10306
- private filterMenuByLicenseFeatures;
10307
10869
  /**
10308
10870
  * Ricompone `items` unendo menu base e runtime; quando `runtimeMenuExclusive` è attivo
10309
10871
  * mostra solo le voci runtime.
@@ -12439,6 +13001,14 @@ declare class NotificationBellComponent implements OnInit, OnDestroy {
12439
13001
  deleteNotificationTitle: string;
12440
13002
  private readonly sub;
12441
13003
  constructor(realtime: NotificationRealtimeService, router: Router, trslSrv: TranslationManagerService);
13004
+ /**
13005
+ * Risolve il valore di una translation key con fallback safe.
13006
+ * ngx-translate's `instant()` ritorna la chiave letterale quando la
13007
+ * traduzione non e' ancora caricata; senza il controllo `!== key` il
13008
+ * fallback `|| default` non scatta (la stringa "notification_bell.title"
13009
+ * e' truthy) e l'UI renderizza la chiave grezza.
13010
+ */
13011
+ private safeT;
12442
13012
  /** Risolve i label dalle traduzioni, rispettando eventuali @Input espliciti. */
12443
13013
  private resolveLabels;
12444
13014
  ngOnInit(): Promise<void>;
@@ -14410,5 +14980,5 @@ declare const THEME_OPTIONS: ThemeOption[];
14410
14980
  declare function getThemeOptions(): ThemeOption[];
14411
14981
  declare function getThemePrimaryHex(value: string): string;
14412
14982
 
14413
- export { AUTH_REDIRECT_REASON_KEY, AppSettingsEditorComponent, AuthSessionService, BooleanEditorComponent, BoundedRepeaterComponent, ButtonEditorComponent, CallbackPipe, CallbackPipe2, CarouselListComponent, CodeAreaEditorComponent, ColorEditorComponent, CrashReporterService, CustomException, DataActionButtonComponent, DataProviderOdataService, DataRepeaterComponent, DataSourceComponent, DateEditorComponent, DesignerRouteComponent, DictionaryEditorComponent, DynamicCompilerService, DynamicRowTemplateComponent, FieldEditorComponent, FilterBarComponent, FilterInfo, FormatGridViewValuePipe, GetSrcUploadPreviewPipe, GlobalHandler, HtmlEditorComponent, ImageWrapperComponent, ImportExportButtonComponent, IsSelectedRowPipe, KanbanListComponent, KanbanOptions, KanbanStatusColumnItem, LazyChartListComponent, LazyCodeEditorComponent, LazyDataActionButtonComponent, LazyDataSourceComponent, LazyFieldEditorComponent, LazyFirstRunWizardComponent, LazyImageWrapperComponent, LazyKanbanListComponent, LazyMetaMenuComponent, LazyPivotBuilderComponent, LazyReportDesignerComponent, LazyReportViewerComponent, LazySchedulerListComponent, LazySpreadsheetListSfComponent, LicenseFeatureService, ListGridComponent, LookupEditorComponent, MapListComponent, MetaInfo, MetaMenuComponent, MetadataEditorService, MetadataProviderService, MetadatiColonna, MetadatiTabella, NotificationBellComponent, NotificationRealtimeService, NumberEditorComponent, PRIMARY_PALETTES, PagerComponent, ParametricDialogComponent, PropertyArrayEditorComponent, PropertyObjectEditorComponent, THEME_OPTIONS, TextAreaEditorComponent, TextEditorComponent, TranslationManagerService, TreeListComponent, TreeViewSelectorComponent, UploadDialogComponent, UploadEditorComponent, UserInfoService, ValidationRule, ValueChangedPayload, VisibleFieldListPipe, WidgetDefinition, WorkflowDesignerRouteComponent, WorkflowRunnerComponent, WorkflowRuntimeMetadataService, WtoolboxService, WuicErrorDialogComponent, WuicErrorInterceptor, WuicFeatureDirective, WuicFrozenColumnDirective, WuicRagChatbotComponent, WuicRagChatbotFabComponent, WuicRagService, WuicRowTogglerDirective, _PRIMENG_TABLE_DIRECTIVES_NAMES, authExpiredInterceptor, boundedRepeaterPendingChangesGuard, featureRouteCanActivateGuard, featureRouteCanMatchGuard, getThemeOptions, getThemePrimaryHex, inferTemplateFieldFromBaseClass, loadBooleanEditorComponent, loadButtonEditorComponent, loadCodeAreaEditorComponent, loadColorEditorComponent, loadDateEditorComponent, loadDictionaryEditorComponent, loadHtmlEditorComponent, loadLookupEditorComponent, loadNumberEditorComponent, loadPropertyArrayEditorComponent, loadPropertyObjectEditorComponent, loadTextAreaEditorComponent, loadTextEditorComponent, loadTreeViewSelectorComponent, loadUploadEditorComponent, menuRouteAccessCanActivateGuard, menuRouteAccessCanMatchGuard, routes, wuicErrorInterceptor };
14414
- export type { AuthSessionState, Breadcrumb, CompileDynamicComponentOptions, CrashReportPayload, CrashReportingConfig, DataSourceAfterSyncEvent, DataSourceBeforeSyncEvent, DataSourceSyncOperation, ErrorDelegate, ErrorDelegateContext, IDataBoundHostComponent, IFieldEditor, KanbanStatusColumn, LicenseStatusResponse, ListGridAfterRenderEvent, ListGridAfterRowRenderEvent, ListGridBeforeRowRenderEvent, MultiDatasourceMeta, NotificationItem, NotifyOptions, RagAskAcceptedResponse, RagAskRequest, RagChatHistorySnapshot, RagChatMessageDto, RagChatMessageStatus, RagChatRequest, RagChatResponse, RagChatSessionDto, RagChatTurn, RagChatbotTurn, RagHealthResponse, RagQueryRequest, RagQueryResponse, RagSource, RealtimeProgressEvent, ThemeOption, ThemePresetName, ThemePrimaryName, WorkflowRuntimeLinkedActionRouteMetadataEntry, WorkflowRuntimePreviousRouteNodeEntry, WorkflowRuntimeRouteMetadataEntry, WorkflowRuntimeRouteNodePayloadEntry };
14983
+ export { AUTH_REDIRECT_REASON_KEY, AppSettingsEditorComponent, AuthSessionService, BooleanEditorComponent, BoundedRepeaterComponent, ButtonEditorComponent, CallbackPipe, CallbackPipe2, CarouselListComponent, CodeAreaEditorComponent, ColorEditorComponent, CrashReporterService, CustomAttributesService, CustomException, DataActionButtonComponent, DataProviderOdataService, DataRepeaterComponent, DataSourceComponent, DateEditorComponent, DesignerRouteComponent, DictionaryEditorComponent, DynamicCompilerService, DynamicRowTemplateComponent, FieldEditorComponent, FilterBarComponent, FilterInfo, FormatGridViewValuePipe, GetSrcUploadPreviewPipe, GlobalHandler, HtmlEditorComponent, ImageWrapperComponent, ImportExportButtonComponent, IsSelectedRowPipe, KanbanListComponent, KanbanOptions, KanbanStatusColumnItem, LazyChartListComponent, LazyCodeEditorComponent, LazyDataActionButtonComponent, LazyDataSourceComponent, LazyFieldEditorComponent, LazyFirstRunWizardComponent, LazyImageWrapperComponent, LazyKanbanListComponent, LazyMetaMenuComponent, LazyPivotBuilderComponent, LazyReportDesignerComponent, LazyReportViewerComponent, LazySchedulerListComponent, LazySpreadsheetListSfComponent, LicenseFeatureService, ListGridComponent, LookupEditorComponent, MapListComponent, MetaInfo, MetaMenuComponent, MetadataEditorService, MetadataProviderService, MetadatiColonna, MetadatiTabella, NotificationBellComponent, NotificationRealtimeService, NumberEditorComponent, PRIMARY_PALETTES, PagerComponent, ParametricDialogComponent, PropertyArrayEditorComponent, PropertyObjectEditorComponent, THEME_OPTIONS, TextAreaEditorComponent, TextEditorComponent, TranslationManagerService, TreeListComponent, TreeViewSelectorComponent, UploadDialogComponent, UploadEditorComponent, UserInfoService, ValidationRule, ValueChangedPayload, VisibleFieldListPipe, WidgetDefinition, WorkflowDesignerRouteComponent, WorkflowRunnerComponent, WorkflowRuntimeMetadataService, WtoolboxService, WuicAziendaSwitcherComponent, WuicErrorDialogComponent, WuicErrorInterceptor, WuicFeatureDirective, WuicFrozenColumnDirective, WuicRagChatbotComponent, WuicRagChatbotFabComponent, WuicRagService, WuicRowTogglerDirective, _PRIMENG_TABLE_DIRECTIVES_NAMES, authExpiredInterceptor, boundedRepeaterPendingChangesGuard, featureRouteCanActivateGuard, featureRouteCanMatchGuard, getThemeOptions, getThemePrimaryHex, inferTemplateFieldFromBaseClass, loadBooleanEditorComponent, loadButtonEditorComponent, loadCodeAreaEditorComponent, loadColorEditorComponent, loadDateEditorComponent, loadDictionaryEditorComponent, loadHtmlEditorComponent, loadLookupEditorComponent, loadNumberEditorComponent, loadPropertyArrayEditorComponent, loadPropertyObjectEditorComponent, loadTextAreaEditorComponent, loadTextEditorComponent, loadTreeViewSelectorComponent, loadUploadEditorComponent, menuRouteAccessCanActivateGuard, menuRouteAccessCanMatchGuard, routes, wuicErrorInterceptor };
14984
+ export type { AuthSessionState, Breadcrumb, CompileDynamicComponentOptions, CrashReportPayload, CrashReportingConfig, CustomAttributeDefinition, CustomAttributeResolved, CustomLookupOption, CustomValue, CvUpsertItem, DataSourceAfterSyncEvent, DataSourceBeforeSyncEvent, DataSourceSyncOperation, ErrorDelegate, ErrorDelegateContext, IDataBoundHostComponent, IFieldEditor, KanbanStatusColumn, LicenseStatusResponse, ListGridAfterRenderEvent, ListGridAfterRowRenderEvent, ListGridBeforeRowRenderEvent, MultiDatasourceMeta, NotificationItem, NotifyOptions, RagAskAcceptedResponse, RagAskRequest, RagChatHistorySnapshot, RagChatMessageDto, RagChatMessageStatus, RagChatRequest, RagChatResponse, RagChatSessionDto, RagChatTurn, RagChatbotTurn, RagHealthResponse, RagQueryRequest, RagQueryResponse, RagSource, RealtimeProgressEvent, ThemeOption, ThemePresetName, ThemePrimaryName, WorkflowRuntimeLinkedActionRouteMetadataEntry, WorkflowRuntimePreviousRouteNodeEntry, WorkflowRuntimeRouteMetadataEntry, WorkflowRuntimeRouteNodePayloadEntry };