wuic-framework-lib 1.0.19 → 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-C0OYuZoM.mjs → wuic-framework-lib-chart-list.component-C9_EDkGu.mjs} +73 -13
  2. package/fesm2022/{wuic-framework-lib-code-editor.component-B8OQ3Z0k.mjs → wuic-framework-lib-code-editor.component-D_p7LGSQ.mjs} +6 -6
  3. package/fesm2022/{wuic-framework-lib-designer.component-DsWgWtFj.mjs → wuic-framework-lib-designer.component-Dx6RraAn.mjs} +83 -50
  4. package/fesm2022/{wuic-framework-lib-first-run-wizard.component-wR_LrvPK.mjs → wuic-framework-lib-first-run-wizard.component-Cp8IKDb9.mjs} +9 -9
  5. package/fesm2022/{wuic-framework-lib-framework-docs.component-eyzu9tdV.mjs → wuic-framework-lib-framework-docs.component-CxckBsIX.mjs} +1205 -116
  6. package/fesm2022/{wuic-framework-lib-pivot-builder.component-BFdZW5Ch.mjs → wuic-framework-lib-pivot-builder.component-C-ceJi48.mjs} +269 -21
  7. package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-B583WbYe.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-DPZCgxOB.mjs} +6 -6
  8. package/fesm2022/{wuic-framework-lib-report-designer.component-HJUpslLX.mjs → wuic-framework-lib-report-designer.component-3-hUYft8.mjs} +5 -5
  9. package/fesm2022/{wuic-framework-lib-report-viewer.component-El32zpzi.mjs → wuic-framework-lib-report-viewer.component-D4QD_wPl.mjs} +5 -5
  10. package/fesm2022/{wuic-framework-lib-scheduler-list.component-E8s_e533.mjs → wuic-framework-lib-scheduler-list.component-C0nY8Wd6.mjs} +28 -5
  11. package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-CDn0qi_C.mjs → wuic-framework-lib-spreadsheet-list-sf.component-C9sWgq61.mjs} +449 -10
  12. package/fesm2022/{wuic-framework-lib-workflow-designer.component-hL7oKqYO.mjs → wuic-framework-lib-workflow-designer.component-8mv_Rbz9.mjs} +10 -10
  13. package/fesm2022/{wuic-framework-lib-wuic-framework-lib-ABS_G7lO.mjs → wuic-framework-lib-wuic-framework-lib-DJZAYFw8.mjs} +5882 -3545
  14. package/fesm2022/wuic-framework-lib.mjs +1 -1
  15. package/package.json +1 -1
  16. package/types/wuic-framework-lib.d.ts +1905 -998
@@ -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';
@@ -18,7 +18,7 @@ import { GoogleMap, MapInfoWindow, MapPolygon } from '@angular/google-maps';
18
18
  import { MarkerClusterer } from '@googlemaps/markerclusterer';
19
19
  import { SplitButton } from 'primeng/splitbutton';
20
20
  import { Menubar } from 'primeng/menubar';
21
- import { AutoCompleteCompleteEvent } from 'primeng/autocomplete';
21
+ import { AutoComplete, AutoCompleteCompleteEvent } from 'primeng/autocomplete';
22
22
  import { Select } from 'primeng/select';
23
23
  import { PrimeNG } from 'primeng/config';
24
24
  import { Popover } from 'primeng/popover';
@@ -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
@@ -1834,6 +1896,19 @@ declare class DataSourceComponent implements OnInit, OnDestroy {
1834
1896
  */
1835
1897
  private refreshPristineFromCurrent;
1836
1898
  /**
1899
+ * Rebase: sposta la pristine baseline al record corrente e azzera il tracker
1900
+ * dei pending changes. Usato dai custom edit-form component dopo aver
1901
+ * applicato `mc_default_value_callback` async (es. progressivo da stored)
1902
+ * sul record gia' BS-wrappato — senza questo refresh il record `__new=true`
1903
+ * risulterebbe `hasPendingChanges()=true` al primo open del dialog Insert
1904
+ * (i BS.next dei default callback vengono tracciati come edit utente).
1905
+ *
1906
+ * NB: usare SOLO se il record e' `__new=true` (modalita' Insert) e i valori
1907
+ * applicati sono default-set, non user-edit. Su record gia' persistente
1908
+ * questo metodo cancella i changes pendenti -> rischio data loss.
1909
+ */
1910
+ rebasePristineAfterDefaults(): void;
1911
+ /**
1837
1912
  * Pubblica uno stato locale aggiornato su `fetchInfo$` per riallineare i consumer del datasource.
1838
1913
  */
1839
1914
  private publishLocalStateUpdate;
@@ -1965,18 +2040,103 @@ declare class MapOptions implements IDesignerProperties {
1965
2040
  useCurrentLocation: boolean;
1966
2041
  useClusterer: boolean;
1967
2042
  filterByBoundaries: boolean;
2043
+ /**
2044
+ * Pass-through al `google.maps.MapOptions.clickableIcons`. Quando `false`,
2045
+ * Google Maps NON apre la propria info window built-in sui POI cliccati
2046
+ * (negozi, fermate, indirizzi, ecc.) — utile quando l'app deve gestire
2047
+ * solo i click dei marker custom (l'info window del POI di Google
2048
+ * intercetta i click che dovrebbero arrivare al marker e copre l'info
2049
+ * window del framework). Default `undefined` (= comportamento Google,
2050
+ * `true`).
2051
+ */
2052
+ clickableIcons?: boolean;
1968
2053
  customMarkerImageSrc: string;
1969
2054
  customMarkerImageSrcField: string;
1970
2055
  markerContentCallback: string;
2056
+ /**
2057
+ * Campo del record che contiene il colore (CSS string `#rrggbb`) da usare
2058
+ * sul `PinElement` del marker. Ignorato se il record ha
2059
+ * `customMarkerImageSrcField` valorizzato (immagine/SVG ha precedenza).
2060
+ */
2061
+ markerColorField?: string;
1971
2062
  titleField: string;
1972
2063
  infoField: string;
1973
2064
  infoFunction: string;
1974
2065
  itemTemplateString: string;
2066
+ /**
2067
+ * Polyline overlay configurabile via `mdpropsbag.archetypes.map.polyline`.
2068
+ * Quando `enabled=true`, il componente raggruppa i record per `groupByField`,
2069
+ * li ordina per `orderByField` e disegna una `<map-polyline>` per ogni gruppo
2070
+ * unendo i punti `{lat: record[latField], lng: record[lngField]}`.
2071
+ * Caso d'uso: tracciamento percorsi GPS (mezzi, persone, asset) dove ogni
2072
+ * record e' una posizione storicizzata.
2073
+ */
2074
+ polyline?: PolylineOverlayOptions;
1975
2075
  constructor();
1976
2076
  init(metaInfo: MetaInfo): void;
1977
2077
  archetypePropName: string;
1978
2078
  getDesignerProps(metaInfo: MetaInfo, action: BehaviorSubject<any>): MetaInfo;
1979
2079
  }
2080
+ /**
2081
+ * Configurazione overlay polyline per archetype map. Permette di trasformare un
2082
+ * elenco di record (es. posizioni GPS storicizzate) in una o piu' polyline,
2083
+ * raggruppate per un campo (es. mezzo_id) e ordinate per un campo (es. timestamp).
2084
+ *
2085
+ * Le coordinate vengono lette dalla colonna `point` esistente sulla tabella/view
2086
+ * (auto-detect: la stessa colonna che il map-list usa per i marker). Per usarla,
2087
+ * la tabella DEVE avere una colonna con `mc_ui_column_type='point'` contenente
2088
+ * JSON `{"lat":..,"lng":..}`.
2089
+ *
2090
+ * Quando `snapToRoads=true` il componente usa Google DirectionsService per
2091
+ * snappare i waypoint alle strade reali (max 25 waypoint per chiamata; se ci
2092
+ * sono piu' punti viene fatto batching automatico).
2093
+ */
2094
+ interface PolylineOverlayOptions {
2095
+ enabled: boolean;
2096
+ /** Campo record per raggruppare (es. 'mezzo_id'). Se omesso → 1 sola polyline globale. */
2097
+ groupByField?: string;
2098
+ /** Campo record per ordinare i punti dentro ogni gruppo (es. 'timestamp_pos'). */
2099
+ orderByField?: string;
2100
+ /**
2101
+ * Campo record alternativo per leggere le coordinate (auto-detect via
2102
+ * colonna `point` se omesso). Utile se la tabella/view ha piu' colonne
2103
+ * point e vuoi specificare quale usare per la polyline.
2104
+ */
2105
+ pointField?: string;
2106
+ /**
2107
+ * Campo record che contiene il colore della polyline (CSS string `#rrggbb`).
2108
+ * Quando valorizzato, il colore viene letto dal primo record del gruppo
2109
+ * (assume omogeneita' per gruppo) e sovrascrive `strokeColor` /
2110
+ * `strokeColorByGroup`. Tipico use-case: colore configurato sul mezzo
2111
+ * (FK lookup) e portato nella view sorgente.
2112
+ */
2113
+ colorField?: string;
2114
+ /** Colore tratto polyline (default `#1d4ed8`). */
2115
+ strokeColor?: string;
2116
+ /** Se true, ogni gruppo riceve un colore distinto (palette interna). */
2117
+ strokeColorByGroup?: boolean;
2118
+ /** Spessore tratto in pixel (default 4). */
2119
+ strokeWeight?: number;
2120
+ /** Opacita 0..1 (default 0.85). */
2121
+ strokeOpacity?: number;
2122
+ /** Se true, snappa la polyline alle strade reali via Google DirectionsService. */
2123
+ snapToRoads?: boolean;
2124
+ /** Se false, nasconde i marker (mostra solo la polyline). Default true. */
2125
+ showMarkers?: boolean;
2126
+ /** Modalita di viaggio per snapToRoads (`DRIVING` default, `WALKING`, `BICYCLING`). */
2127
+ travelMode?: 'DRIVING' | 'WALKING' | 'BICYCLING';
2128
+ /**
2129
+ * Se true, oltre alla polyline disegna un dot (`<map-circle>`) sulle
2130
+ * coordinate originali di ciascun record. Utile per distinguere visivamente
2131
+ * i punti GPS realmente storicizzati dal path interpolato/snapped.
2132
+ * Default false.
2133
+ */
2134
+ showWaypointDots?: boolean;
2135
+ /**
2136
+ * Raggio in metri del dot (cerchio reale, scala con lo zoom). Default 8.
2137
+ */
2138
+ waypointDotRadius?: number;
2139
+ }
1980
2140
  declare class Point {
1981
2141
  lat: number;
1982
2142
  lng: number;
@@ -2236,6 +2396,24 @@ declare class MetadatiTabella {
2236
2396
  md_inline_cell_editing: boolean;
2237
2397
  md_batch_save: boolean;
2238
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;
2239
2417
  md_hide_select_all_check: boolean;
2240
2418
  md_multiple_radio_selection: boolean;
2241
2419
  md_persist_row_selection_accross_paging: boolean;
@@ -2378,7 +2556,7 @@ declare class MetadatiTabella {
2378
2556
  * Flag toolbar-level controllati da `md_props_bag.toolbar.*` (JSON).
2379
2557
  * Cambiabili per-route senza toccare lo schema SQL di
2380
2558
  * `_metadati__tabelle`. Esempio in `md_props_bag`:
2381
- * { "toolbar": { "hideManageState": true } }
2559
+ * { "toolbar": { "hideManageState": true, "hideBatchActions": true } }
2382
2560
  *
2383
2561
  * - `hideManageState`: nasconde il bottone "Gestione stato"
2384
2562
  * (icona bookmark) + la select degli stati salvati nella
@@ -2386,9 +2564,18 @@ declare class MetadatiTabella {
2386
2564
  * demo dove il saved-state feature (persistenza user_id +
2387
2565
  * route via MetaService) non ha senso — es. Pattern 3 puro
2388
2566
  * OData senza route metadata registrata.
2567
+ * - `hideBatchActions`: nasconde dalla caption-left i pulsanti
2568
+ * "Salva modifiche" / "Annulla modifiche" + l'indicatore
2569
+ * conteggio changes (badge pencil + count) generati quando
2570
+ * `md_inline_cell_editing` + `md_batch_save` sono attivi.
2571
+ * Utile per nested grid (es. righe documento dentro un
2572
+ * parametric-dialog) dove il save/cancel del padre persiste
2573
+ * master + righe in un colpo via batch save framework e i
2574
+ * duplicati toolbar sulla nested confondono l'UX.
2389
2575
  */
2390
2576
  toolbar?: {
2391
2577
  hideManageState?: boolean;
2578
+ hideBatchActions?: boolean;
2392
2579
  };
2393
2580
  /**
2394
2581
  * Tuning server-side letto da `DataProviderMetaService.select`
@@ -2652,6 +2839,33 @@ declare class MetadataProviderService {
2652
2839
  * @returns Istanza Dexie `MetaDB`.
2653
2840
  */
2654
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>;
2655
2869
  /**
2656
2870
  * Inizializza (o riusa) il database Dexie `MetaDB` con lo schema metadata richiesto dalla versione passata.
2657
2871
  * Configura tabelle/indici per colonne, tabelle, stili, autorizzazioni, condition group e custom actions.
@@ -2703,7 +2917,17 @@ declare class MetadataProviderService {
2703
2917
  */
2704
2918
  private isClientSideCrudModeEnabled;
2705
2919
  /**
2706
- * 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.
2707
2931
  * @param userId Identificativo utente usato per contesto e persistenza.
2708
2932
  * @returns Chiave localStorage della cache menu.
2709
2933
  */
@@ -2794,7 +3018,7 @@ declare class MetadataProviderService {
2794
3018
  * @param col Metadato colonna da analizzare.
2795
3019
  * @returns Nome tipo TypeScript stimato (`string`, `number`, `boolean`, `Date`, `any`).
2796
3020
  */
2797
- static getTSTypeFromMetaColumn(col: MetadatiColonna): "string" | "any" | "boolean" | "number" | "Date";
3021
+ static getTSTypeFromMetaColumn(col: MetadatiColonna): "string" | "number" | "any" | "boolean" | "Date";
2798
3022
  /**
2799
3023
  * Normalizza e arricchisce i metadata colonna/tabella: ordina campi, inizializza callback dinamiche, parse di bag JSON
2800
3024
  * e garantisce fallback robusti per funzioni custom non compilabili.
@@ -3354,6 +3578,18 @@ declare class DataProviderMetaService {
3354
3578
  * additional columns alongside the text field).
3355
3579
  */
3356
3580
  static buildSlimComboRestriction(field: MetadatiColonna | null | undefined): string[];
3581
+ /**
3582
+ * Sanitize di un body HTTP rimuovendo qualunque BehaviorSubject (e
3583
+ * BS-of-BS) che potrebbe essere finito dentro `filterInfo`,
3584
+ * `currentRecord`, slot di un record BS-wrapped, ecc. Pre-serializza
3585
+ * con replacer BS-aware e parse back: il risultato e' un body plain
3586
+ * che Angular `HttpRequest.serializeBody` puo' stringificare senza
3587
+ * "Converting circular structure to JSON" (SafeSubscriber →
3588
+ * Subscription._finalizers → _parentage). Da usare in tutti i
3589
+ * `http.post`/`http.put` che possono ricevere payload provenienti da
3590
+ * datasource reattive.
3591
+ */
3592
+ static sanitizeBodyForHttp(body: any): any;
3357
3593
  /**
3358
3594
  * Carica i dati della route corrente chiamando `MetaService.getFlatRecordData` (`MetadataProviderService.readUri`).
3359
3595
  * Invia paginazione/ordinamenti/gruppi/filtri/aggregazioni e `has_server_operation`, poi mappa la risposta
@@ -3606,6 +3842,17 @@ declare class ClientSideCrudService {
3606
3842
  private db?;
3607
3843
  private dbInitPromise?;
3608
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;
3609
3856
  /**
3610
3857
  * Inizializza una sola volta il database Dexie locale (`WuicClientSideCrudDB`) e ne riusa l'istanza.
3611
3858
  * @returns Istanza DB locale usata per cache/sync CRUD client-side.
@@ -3663,6 +3910,12 @@ declare class ClientSideCrudService {
3663
3910
  * @param userId Identificativo utente usato per contesto e persistenza.
3664
3911
  * @returns Chiave storage del flag modalita locale.
3665
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;
3666
3919
  private getModeKey;
3667
3920
  /**
3668
3921
  * Attiva/disattiva il flag modalita CRUD locale per route+utente in localStorage.
@@ -4409,6 +4662,36 @@ declare class WtoolboxService {
4409
4662
  suggestColumnMD(record: {
4410
4663
  [key: string]: BehaviorSubject<any>;
4411
4664
  }, field: MetadatiColonna, type: string, routeRef?: string): Promise<void>;
4665
+ /**
4666
+ * Suggest del campo `mc_ui_lookup_computed_dataTextField` (Lookup
4667
+ * Computed Data Text Field — formula display nella grid del parent):
4668
+ * apre albero da `MetaService.getLookupListByIDLevelUP` (root = tabella
4669
+ * proprietaria di mc_id, con i lookup edges per navigare alle target)
4670
+ * e genera il select con `appendOnly=2` (JOIN alias `<colFK>_<target>`
4671
+ * coerente con quello costruito da JoinBuilder a runtime nella query
4672
+ * della grid). Vedi anche `suggestLookupComputedEdit` per il caso
4673
+ * speculare nel field-editor.
4674
+ * @param record Record metadata corrente (`mc_id` usato dal backend).
4675
+ * @param field Campo formula da aggiornare.
4676
+ */
4677
+ suggestLookupComputed(record: {
4678
+ [key: string]: BehaviorSubject<any>;
4679
+ }, field: MetadatiColonna): Promise<void>;
4680
+ /**
4681
+ * Suggest del campo `mc_ui_lookup_combo_text_edit_computed_dataTextField`
4682
+ * (Lookup Edit Text Computed Formula — testo del lookup nel field-editor):
4683
+ * apre albero da `MetaService.getLookupListFromLookupTarget` con root
4684
+ * spostata sulla TABELLA TARGET del lookup (es. mc_id=`prodotto_id` -> root
4685
+ * `prodotti` con i suoi campi `codice`/`descrizione`/...). Genera il
4686
+ * select con `appendOnly=3` -> qualifier `[<targetTable>].[<col>]`
4687
+ * (es. `[prodotti].[codice]`), perche' la formula gira in un SELECT
4688
+ * diretto sulla target nel field-editor, senza JOIN alias.
4689
+ * @param record Record metadata corrente (`mc_id` usato dal backend).
4690
+ * @param field Campo formula da aggiornare.
4691
+ */
4692
+ suggestLookupComputedEdit(record: {
4693
+ [key: string]: BehaviorSubject<any>;
4694
+ }, field: MetadatiColonna): Promise<void>;
4412
4695
  /**
4413
4696
  * Costruisce formula computed partendo da gerarchia lookup: apre albero da
4414
4697
  * `MetaService.getLookupListByIDLevelUP` e invia la selezione a `getClauseByLookupHierarchy`
@@ -5113,584 +5396,1181 @@ declare class LazyDataSourceComponent implements OnInit {
5113
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>;
5114
5397
  }
5115
5398
 
5116
- declare class DeviceAwarenessService implements OnDestroy {
5117
- private static readonly DEFAULT_BREAKPOINT_PX;
5118
- private mediaQueryList?;
5119
- private mediaQueryListener?;
5120
- private readonly isMobileSubject;
5121
- readonly isMobile$: Observable<boolean>;
5122
- constructor();
5123
- get isMobile(): boolean;
5124
- ngOnDestroy(): void;
5125
- private resolveBreakpointPx;
5126
- static ɵfac: i0.ɵɵFactoryDeclaration<DeviceAwarenessService, never>;
5127
- static ɵprov: i0.ɵɵInjectableDeclaration<DeviceAwarenessService>;
5128
- }
5129
-
5130
- interface ListGridSavedState {
5131
- id: string;
5132
- name: string;
5133
- description: string;
5134
- isDefault: boolean;
5135
- createdAt: string;
5136
- filterInfo: any;
5137
- sortInfo: any[];
5138
- pageInfo: {
5139
- currentPage: number;
5140
- pageSize: number;
5141
- };
5142
- columnWidths: {
5143
- [field: string]: number;
5144
- };
5145
- columnLayout?: ListGridColumnLayout;
5146
- }
5147
- interface ListGridColumnLayout {
5148
- order: string[];
5149
- hidden: string[];
5150
- pinnedLeft: string[];
5151
- pinnedRight: string[];
5152
- }
5153
- interface ReportVariableInput {
5154
- name: string;
5155
- alias: string;
5156
- value: string;
5157
- type?: string;
5158
- }
5159
- interface GridPendingChangeItem {
5160
- id: string;
5161
- change: TrackedChange;
5162
- label: string;
5163
- details: string;
5164
- selected: boolean;
5165
- }
5166
- interface ListGridBeforeRowRenderEvent {
5167
- row: any;
5168
- rowIndex: number;
5169
- cancel: boolean;
5170
- cancelRender: () => void;
5171
- }
5172
- interface ListGridAfterRowRenderEvent {
5173
- row: any;
5174
- rowIndex: number;
5175
- }
5176
- interface ListGridAfterRenderEvent {
5177
- rows: any[];
5178
- totalRecords: number;
5179
- metaInfo: MetaInfo;
5180
- 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;
5181
5417
  }
5182
- declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDataBoundHostComponent {
5183
- private metaSrv;
5184
- private sanitizer;
5185
- private route;
5186
- private router;
5187
- private location;
5188
- private titleService;
5189
- private trslSrv;
5190
- private cd;
5191
- userInfo: UserInfoService;
5192
- private elementRef;
5193
- deviceAwareness: DeviceAwarenessService;
5194
- private static readonly FORCED_VIRTUALIZATION_PAGE_SIZE_THRESHOLD;
5195
- private static readonly FORCED_VIRTUALIZATION_ITEM_SIZE;
5196
- private static readonly ACTION_BUTTON_VISIBLE_ROWS_OVERSCAN;
5197
- private static readonly ACTION_BUTTON_INITIAL_VISIBLE_ROWS_FALLBACK;
5198
- private static readonly GRID_VIEW_STATES_SETTINGS_KEY;
5199
- private static readonly GRID_COLUMN_LAYOUT_SETTINGS_KEY;
5200
- private static selectButtonGuardInstalled;
5201
- private columnFilterRenderEpochByField;
5202
- private actionButtonsVisibleStartIndex;
5203
- private actionButtonsVisibleEndIndex;
5204
- private actionButtonsLimitToVisibleRows;
5205
- private actionButtonsPreLimitBeforeContainerReady;
5206
- private actionButtonsScrollContainer;
5207
- private actionButtonsScrollRafToken;
5208
- private actionButtonsScrollHandler;
5209
- private inlineCellSaveInFlightByRowKey;
5210
- private inlineCellSaveDebounceByRowKey;
5211
- private inlineCellLastChangedFieldByRowKey;
5212
- private inlineBatchOriginalByRowKey;
5213
- private inlineGridRuntimeFieldCacheByKey;
5214
- private suppressNextInlineFetchInfoRebind;
5215
- getRuntimeGridFieldMetaFn: (metaColumn: MetadatiColonna, rowData: any) => MetadatiColonna;
5216
- hardcodedRoute: string;
5217
- parentRecord: any;
5218
- parentMetaInfo: MetaInfo;
5219
- datasource: BehaviorSubject<DataSourceComponent>;
5220
- hardcodedDatasource: DataSourceComponent;
5221
- rowCustomSelect: (rowData: any, $event: any, dt: Table) => void;
5222
- 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);
5223
5434
  /**
5224
- * Provider letto da `<wuic-import-export-button>` al click su Export XLS.
5225
- * Arrow function (NON metodo) per preservare il binding di `this` quando
5226
- * passata come Input — un metodo verrebbe richiamato col `this` del child.
5227
- * Ritorna lo stato filtri LIVE del datasource: include i filtri applicati
5228
- * 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.
5229
5444
  */
5230
- getCurrentFilterInfoForExport: () => any;
5445
+ private applyUserLanguageToTranslations;
5231
5446
  /**
5232
- * Evento emesso subito prima del rendering logico della singola riga.
5233
- * 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.
5234
5449
  */
5235
- onBeforeRowRender: EventEmitter<ListGridBeforeRowRenderEvent>;
5450
+ initialize(force?: boolean): Promise<void>;
5236
5451
  /**
5237
- * 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.
5238
5472
  */
5239
- onAfterRowRender: EventEmitter<ListGridAfterRowRenderEvent>;
5473
+ private hydrateFromServerCookie;
5240
5474
  /**
5241
- * 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.
5242
5477
  */
5243
- onAfterRender: EventEmitter<ListGridAfterRenderEvent>;
5478
+ refreshAll(): Promise<void>;
5244
5479
  /**
5245
- * 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.
5246
5482
  */
5247
- onPaging: EventEmitter<any>;
5483
+ setReturnUrl(returnUrl: string): void;
5248
5484
  /**
5249
- * 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.
5250
5487
  */
5251
- onSorting: EventEmitter<any>;
5488
+ login(returnUrl?: string): void;
5252
5489
  /**
5253
- * 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.
5254
5492
  */
5255
- onFiltering: EventEmitter<any>;
5493
+ logout(returnUrl?: string): Promise<void>;
5256
5494
  /**
5257
- * Evento emesso dopo un refresh esplicito (click su bottone "Aggiorna"
5258
- * del toolbar o invocazione di `refresh()` da codice). Gli host in Pattern 3
5259
- * 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.
5260
5499
  */
5261
- onRefresh: EventEmitter<void>;
5500
+ legacyLogin(username: string, password: string, captchaToken?: string): Promise<boolean>;
5262
5501
  /**
5263
- * Eventi p-table esposti lato host.
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.
5264
5525
  */
5265
- onPTableSelectionChange: EventEmitter<any>;
5266
- onPTableRowExpand: EventEmitter<TableRowExpandEvent<any>>;
5267
- onPTableRowCollapse: EventEmitter<TableRowCollapseEvent>;
5268
- onPTableColumnResize: EventEmitter<any>;
5269
- onPTableColumnReorder: EventEmitter<any>;
5270
- table: Table;
5271
- columnCtxMenu: ContextMenu;
5272
- metadataColumnsDatasource: DataSourceComponent;
5273
- gridContainerRef?: ElementRef<HTMLElement>;
5274
- tableActionsMenu: any;
5275
- /** ResizeObserver per esporre --wuic-outer-thead-h alle nested grid figlie. */
5276
- private outerTheadResizeObserver?;
5277
- private outerTheadObserveRetryTimer?;
5278
- records: any[];
5279
- cols: any[];
5526
+ legacyLogout(): Promise<void>;
5280
5527
  /**
5281
- * Constant CSS value for `<col>`/`<th>` min-width binding. Pulled into a
5282
- * field (instead of `getColumnMinWidthCss()` method) so the template binding
5283
- * `[style.min-width]="columnMinWidthCss"` resolves to a property read
5284
- * (no function call) and Angular's change-detection short-circuits when
5285
- * the value didn't change. Saves ~3 function calls per column per CD cycle
5286
- * (template uses it on `<col>`, header `<th>`, and filter row `<th>`).
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.
5287
5543
  */
5288
- readonly columnMinWidthCss = "10px";
5289
- metas: MetadatiColonna[];
5290
- metaInfo: MetaInfo;
5291
- routeName: string;
5292
- actionName: string;
5293
- totalRecords: number;
5294
- pageSize: number;
5295
- rowNumber: number;
5296
- orderColumn: string;
5297
- orderDir: 'asc' | 'desc';
5298
- loading: BehaviorSubject<boolean>;
5299
- pageIndex: number;
5300
- globalFilterFields: string[];
5301
- searchValue: string;
5302
- rowTemplate: any;
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
+ }>>;
5303
5561
  /**
5304
- * Tracks whether the currently compiled `rowTemplate` is the **mobile card**
5305
- * variant (vs desktop). Decoupled from live `deviceAwareness.isMobile$`:
5306
- * il viewport puo' attraversare la soglia (es. utente ridimensiona DevTools)
5307
- * senza che il template sia ancora stato ricompilato. La classe CSS
5308
- * `wuic-list-grid-mobile` (che nasconde thead/footer/paginator e rompe la
5309
- * semantica table) deve seguire **lo stato del template compilato**, non il
5310
- * viewport live, altrimenti si vede una hybrid view (desktop header + card rows).
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>).
5311
5565
  */
5312
- gridLayoutIsMobile: boolean;
5313
- /** @deprecated 2026-04-23 — mobile ora riusa rowTemplate del desktop. Field ancora esposto per backward-compat con host che lo leggevano. */
5314
- mobileCardComponent: any;
5315
- /** Subscription a `isMobile$` per ricompilare il rowTemplate quando il viewport attraversa la soglia mobile. */
5316
- private isMobileSubscription?;
5317
- selectedItems: any[];
5318
- expandedRows: {};
5319
- aggregates: any[];
5320
- private nestedLongDescriptionRawCache;
5321
- private nestedLongDescriptionSafeCache;
5566
+ private clearClientRuntimeState;
5322
5567
  /**
5323
- * Collezione dati per pending change items, consumata dal rendering e dalle operazioni del componente.
5568
+ * Pulisce lo stato runtime e le cache associate.
5569
+ * Legge/scrive dati persistenti su storage browser.
5324
5570
  */
5325
- pendingChangeItems: GridPendingChangeItem[];
5326
- private syncFilterInfoQueryTimer;
5327
- private syncGridStateQueryTimer;
5328
- private suppressGridStateUrlPush;
5329
- private releaseGridStateUrlPushTimer;
5330
- private navigationTriggeredByPopstate;
5331
- private suppressNextPageOnlyQuerySync;
5332
- clientSideCrudToggleBusy: boolean;
5333
- private persistedColumnWidthsByRoute;
5334
- private persistedColumnLayoutByRoute;
5335
- private manualResizeDisablesProportionalByRoute;
5336
- private remoteColumnLayoutHydrationInFlight;
5337
- private persistedGridStatesByRoute;
5338
- private remoteGridStatesHydrationInFlight;
5339
- currentRouteSavedStates: ListGridSavedState[];
5340
- selectedSavedStateId: string;
5341
- private applyingSavedState;
5342
- readonly NEW_GRID_STATE_OPTION_ID = "__new__";
5343
- saveGridStateDialogVisible: boolean;
5344
- saveGridStateDialogSelectedId: string;
5345
- saveGridStateDialogNewName: string;
5346
- saveGridStateDialogSetAsDefault: boolean;
5347
- renameGridStateDialogVisible: boolean;
5348
- renameGridStateDialogName: string;
5349
- columnLayoutDialogVisible: boolean;
5350
- columnLayoutDraft: Array<{
5351
- field: string;
5352
- header: string;
5353
- visible: boolean;
5354
- }>;
5355
- saveStateMenuItems: MenuItem[];
5356
- columnContextMenuItems: MenuItem[];
5357
- selectedColumnForContextMenu?: MetadatiColonna;
5358
- availableReports: {
5359
- path: string;
5360
- name: string;
5361
- }[];
5362
- reportMenuItems: MenuItem[];
5363
- tableActionMenuItems: MenuItem[];
5364
- reportVariableDialogVisible: boolean;
5365
- reportVariableDialogLoading: boolean;
5366
- selectedReportNameForVariables: string;
5367
- selectedReportVariables: ReportVariableInput[];
5368
- changesDialogVisible: boolean;
5369
- changesDialogBusy: boolean;
5571
+ private clearBrowserStorage;
5370
5572
  /**
5371
- * Proprieta di stato del componente per pending preferred state auto apply, 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>).
5372
5577
  */
5373
- private pendingPreferredStateAutoApply;
5578
+ private deleteDexieDatabase;
5374
5579
  /**
5375
- * Proprieta di stato del componente per query param 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>).
5376
5584
  */
5377
- private queryParamSubscription?;
5585
+ private deleteIndexedDbByName;
5378
5586
  /**
5379
- * Proprieta di stato del componente per router events 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.
5380
5588
  */
5381
- private routerEventsSubscription?;
5589
+ private bootstrapUserCustomSettings;
5382
5590
  /**
5383
- * Proprieta di stato del componente per datasource ready subscription, usata dalla logica interna e dal template.
5591
+ * Configura il timeout di sessione in minuti. Chiamato dal meta-menu dopo aver letto AuthConfig.
5384
5592
  */
5385
- private datasourceReadySubscription?;
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;
5386
5601
  /**
5387
- * Proprieta di stato del componente per fetch info subscription, usata dalla logica interna e dal template.
5602
+ * Avvia/riavvia i timer di sessione. Chiamato dopo login e ad ogni attività HTTP.
5388
5603
  */
5389
- private fetchInfoSubscription?;
5604
+ resetSessionTimer(): void;
5605
+ private startSessionExpiryCountdown;
5606
+ private handleSessionExpired;
5607
+ private clearSessionTimers;
5608
+ private isUserAuthenticated;
5390
5609
  /**
5391
- * Proprieta di stato del componente per width defined, 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.
5392
5612
  */
5393
- width_defined: string;
5394
5613
  /**
5395
- * Proprieta di stato del componente per metadati colonna, usata dalla logica interna e dal template.
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.
5396
5618
  */
5397
- MetadatiColonna: typeof MetadatiColonna;
5619
+ setError(message: string): void;
5620
+ /** User-facing messages keyed by server reason code. */
5621
+ private static readonly REASON_MESSAGES;
5398
5622
  /**
5399
- * function Object() { [native code] }
5400
- * @param metaSrv Metadati correnti usati per guidare mapping, validazioni e comportamento runtime.
5401
- * @param route Informazione di navigazione usata per risolvere la route di destinazione.
5402
- * @param router Informazione di navigazione usata per risolvere la route di destinazione.
5403
- * @param location Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5404
- * @param titleService Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5405
- * @param trslSrv Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5406
- * @param cd Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
5407
- * @param userInfo Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
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.
5408
5626
  */
5409
- constructor(metaSrv: MetadataProviderService, sanitizer: DomSanitizer, route: ActivatedRoute, router: Router, location: Location, titleService: Title, trslSrv: TranslationManagerService, cd: ChangeDetectorRef, userInfo: UserInfoService, elementRef: ElementRef<HTMLElement>, deviceAwareness: DeviceAwarenessService);
5627
+ private applyRedirectReason;
5628
+ private patchState;
5410
5629
  /**
5411
- * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
5630
+ * Costruisce una struttura derivata a partire dallo stato corrente.
5631
+ * @param action Azione richiesta nel flusso corrente.
5412
5632
  */
5413
- ngOnInit(): void;
5633
+ private buildEndpoint;
5414
5634
  /**
5415
- * Gestisce la logica operativa di `ensureSelectButtonGuard` orchestrando le chiamate `call`.
5635
+ * Costruisce una struttura derivata a partire dallo stato corrente.
5636
+ * @param fullMethodName Nome completo metodo legacy (es. `MetaService.login`).
5416
5637
  */
5417
- private ensureSelectButtonGuard;
5638
+ private buildMetaAsmxEndpoint;
5418
5639
  /**
5419
- * Completa inizializzazione dopo il rendering della view e collega riferimenti UI.
5640
+ * Risolve la base URL API usata dal servizio: preferisce `appSettings.api_url`, fallback su `${window.location.origin}/api/`.
5420
5641
  */
5421
- ngAfterViewInit(): void;
5642
+ private getApiBaseUrl;
5422
5643
  /**
5423
- * Applica direttamente in DOM (senza Angular binding) la `<table style.width
5424
- * + min-width>` salvata in `persistedColumnWidthsByRoute` come `__tableTotalWidth`.
5425
- *
5426
- * Why direct DOM e non `[tableStyle]` binding:
5427
- * - Durante il drag PrimeNG (`columnResizeMode="expand"`) modifica
5428
- * `<table style.width>` inline. Se anche Angular setta lo stesso prop
5429
- * via binding, i due meccanismi entrano in race → comportamento di
5430
- * spalmamento osservato (il delta del drag si distribuisce tra tutte
5431
- * le colonne invece di concentrarsi su quella trascinata).
5432
- * - Direct DOM bypassa Angular CD. Lo applichiamo SOLO al boot
5433
- * (ngAfterViewInit) e dopo `parseColumns` su data refresh — non durante
5434
- * il drag — quindi nessun conflitto.
5435
- * - Senza la table.style.width esplicita, al refresh il browser fitta il
5436
- * table al container (default `min-width: 100%` PrimeNG) e shrinkka
5437
- * le colonne → la scrollbar svanisce.
5644
+ * Valuta una condizione booleana sullo stato o sull'input corrente.
5645
+ * @returns Valore restituito dal metodo (boolean).
5438
5646
  */
5439
- private scheduleApplyPersistedTableWidth;
5440
- private applyPersistedTableWidth;
5647
+ private isOAuthEnabledInSettings;
5441
5648
  /**
5442
- * Ritorna la `<table style.width>` da applicare al refresh per riprodurre
5443
- * il layout end-of-drag.
5444
- *
5445
- * Strategia:
5446
- * 1. Se esiste `__tableWidth` persistito (chiave speciale catturata in
5447
- * `captureResizedColumnWidth`), usa quello — e' il valore esatto
5448
- * `oldTableWidth + delta` che PrimeNG ha applicato a fine drag.
5449
- * 2. Fallback: somma persisted col widths + frozen widths reali (DOM)
5450
- * per il caso di stati legacy salvati prima del fix.
5451
- */
5452
- private computePersistedTableTotalWidth;
5453
- /**
5454
- * Espone l'altezza del thead OUTER (top-level grid) come CSS var `--wuic-outer-thead-h`
5455
- * sull'host element, per permettere a `position: sticky; top: var(...)` sull'inner thead
5456
- * di lasciare spazio sotto l'header outer (anch'esso sticky a top:0).
5457
- *
5458
- * Si attiva SOLO sulla grid root (non nested): le inner ListGridComponent leggono la var
5459
- * 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.
5460
5651
  */
5461
- private observeOuterTheadHeight;
5652
+ private normalizeReturnUrl;
5462
5653
  /**
5463
- * Ricalcola l'altezza disponibile della grid al resize finestra.
5654
+ * Ritorna l'URL browser corrente usato come `returnUrl` predefinito in login/logout.
5464
5655
  */
5465
- onWindowResizeForGridLayout(): void;
5656
+ private getCurrentLocalUrl;
5466
5657
  /**
5467
- * 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).
5468
5661
  */
5469
- private scheduleGridViewportHeightSync;
5662
+ private parseLegacyLoginResponse;
5470
5663
  /**
5471
- * 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`.
5472
5668
  */
5473
- private applyGridViewportHeight;
5669
+ private extractLegacyLoginError;
5474
5670
  /**
5475
- * 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`.
5476
5674
  */
5477
- ngOnDestroy(): void;
5478
- getNestedLongDescriptionSafeHtml(nestedSource?: DataSourceComponent): SafeHtml | '';
5479
- private stripScriptTags;
5675
+ private readMessage;
5480
5676
  /**
5481
- * Restituisce una chiave stabile per il tracking colonne nel template,
5482
- * 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.
5483
5680
  */
5484
- 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;
5485
5715
  /**
5486
- * Inline style per la `<p-table>` che replica il behavior runtime di PrimeNG
5487
- * `columnResizeMode="expand"`: setta `width: <sum>; min-width: <sum>` sul
5488
- * `<table>` quando esistono persisted column widths.
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`.
5489
5719
  *
5490
- * Why: PrimeNG durante il resize "expand" applica esplicitamente questi
5491
- * stili per forzare il `<table>` a essere piu' largo del container e
5492
- * generare la scrollbar. Al refresh quegli inline styles spariscono e il
5493
- * default `table-layout: auto + min-width: 100%` fa shrinkare le colonne
5494
- * per fittare il container — la scrollbar svanisce e le widths persistite
5495
- * (settate via `<col style.width>`) vengono ignorate dal browser.
5496
- *
5497
- * Con questo binding, la `<table>` riceve gli stessi stili che PrimeNG
5498
- * applicherebbe a fine drag → table-layout puo' restare `auto` + i `<col>`
5499
- * widths vengono rispettati come hint di partenza, e il browser distribuisce
5500
- * la larghezza totale tra di loro proporzionalmente alle widths richieste.
5501
- *
5502
- * Ritorna `null` quando non ci sono persisted widths (default proportional).
5503
- */
5504
- getTableStyle(): {
5505
- [key: string]: string;
5506
- } | null;
5507
- /**
5508
- * Restituisce le classi della p-table includendo il profilo inline-cell-editing.
5509
- */
5510
- getTableStyleClass(): string;
5511
- private isNestedGridInstance;
5512
- private isInlineEditEnabled;
5513
- /**
5514
- * Gestisce la logica operativa di `subscribeToDS` in modo coerente con l'implementazione corrente.
5515
- * @returns Risultato elaborato da `subscribeToDS` e restituito al chiamante.
5516
- */
5517
- subscribeToDS(): void;
5518
- /**
5519
- * Recupera e prepara i dati richiesti dal chiamante usando i metadati per determinare chiavi, campi e comportamento runtime.
5520
- * @param metaInfo Metadati del contesto corrente usati per guidare filtri, mapping e comportamento runtime.
5521
- * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale) in base al contesto corrente.
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).
5522
5726
  */
5727
+ visible: boolean;
5523
5728
  /**
5524
- * Compila il `rowTemplate` corrente in base a `metaInfo` e al viewport mobile/desktop
5525
- * live (`deviceAwareness.isMobile`). Aggiorna anche il flag `gridLayoutIsMobile` che
5526
- * pilota la classe CSS `wuic-list-grid-mobile` (nasconde thead/footer/paginator e rompe
5527
- * la semantica table). Estratto in metodo dedicato per poter essere richiamato anche
5528
- * dalla subscription `isMobile$` in `ngOnInit` quando il viewport attraversa la soglia.
5529
- */
5530
- private compileGridRowTemplate;
5531
- private getEffectiveGridRowTemplate;
5532
- /**
5533
- * Costruisce il row template per mobile: UNA sola <td colspan="N"> contenente
5534
- * il card layout (label/value per colonna + action button). Il row subclass
5535
- * resta compilato dallo stesso `DynamicRowTemplateComponent.
5536
- * getComponentFromTemplate` usato in desktop (selector 'tr'), solo il template
5537
- * 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.
5538
5733
  *
5539
- * `colspan` = numero totale di colonne del grid desktop, cosi' la <td> occupa
5540
- * tutta la larghezza della row. Il CSS `@media (max-width: 768px)` nel
5541
- * list-grid.component.scss setta `display: block` su <tr> / <td.wuic-mobile-
5542
- * 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.
5543
5736
  */
5544
- private buildMobileCardAsRowTemplate;
5737
+ get hostHidden(): string | null;
5545
5738
  /**
5546
- * 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.
5547
5743
  */
5548
- private getHostOverriddenGridRowTemplate;
5744
+ companies: Array<{
5745
+ ID_Azienda: number;
5746
+ Nome_Azienda: string;
5747
+ LogoFileName?: string | null;
5748
+ }>;
5549
5749
  /**
5550
- * Cascata mobile: host `WidgetDefinition.mobileCardTemplate` -> library default.
5551
- * 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/`).
5552
5752
  */
5553
- private getEffectiveMobileCardTemplate;
5753
+ private static readonly LOGO_BASE;
5554
5754
  /**
5555
- * Costruisce il template default per la card mobile: una card per record, con
5556
- * `data-action-button` in testa e una riga `label/value` per ogni colonna visibile.
5557
- * Riusa gli stessi switch case dei custom cell template del desktop.
5558
- * 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.
5559
5757
  */
5560
- private buildDefaultMobileCardTemplate;
5758
+ selectedAziendaId: number;
5561
5759
  /**
5562
- * Costruisce una struttura di output a partire dal contesto corrente usando i metadati per determinare chiavi, campi e comportamento runtime.
5563
- * @param columns Collezione di input processata dal metodo (normalizzazione, filtri e mapping).
5564
- * @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.
5565
5762
  */
5566
- private buildDefaultGridRowTemplateWithColumnTemplates;
5763
+ switching: boolean;
5567
5764
  /**
5568
- * Costruisce una struttura di output a partire dal contesto corrente normalizzando e trasformando collezioni di record.
5569
- * @param columns Collezione di input processata dal metodo (normalizzazione, filtri e mapping).
5570
- * @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.
5571
5767
  */
5572
- private buildGridColumnTemplateSwitchCases;
5768
+ errorMessage: string | null;
5573
5769
  /**
5574
- * Verifica una condizione di stato o di validita orchestrando le chiamate `trim` e `String`.
5575
- * @param template Valore testuale usato come chiave, nome campo, criterio o frammento di configurazione.
5576
- * @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`.
5577
5773
  */
5578
- private isAngularCellMarkupTemplate;
5774
+ currentLabel: string;
5579
5775
  /**
5580
- * Trasforma i dati in una forma coerente con il rendering o con il payload richiesto orchestrando le chiamate `trim` e `String`.
5581
- * @param template Valore testuale usato come chiave, nome campo, criterio o frammento di configurazione.
5582
- * @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.
5583
5777
  */
5584
- private normalizeGridCellTemplate;
5778
+ currentLogoUrl: string | null;
5779
+ constructor(userInfoService: UserInfoService, authSessionService: AuthSessionService, cdr: ChangeDetectorRef);
5780
+ ngOnInit(): Promise<void>;
5585
5781
  /**
5586
- * 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…".
5587
5786
  */
5588
- private syncTableFilterUiFromDatasource;
5787
+ private refreshCurrentLabel;
5589
5788
  /**
5590
- * 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.
5591
5792
  */
5592
- private syncTableSortUiFromDatasource;
5793
+ get noSelection(): boolean;
5593
5794
  /**
5594
- * Interpreta e normalizza input/configurazione in `parseData` per l'utilizzo nel componente.
5595
- * @param data Dato/record su cui il metodo applica elaborazioni o aggiornamenti.
5596
- * @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.
5597
5799
  */
5598
- parseData(data: any): any;
5800
+ logoUrlFor(c: {
5801
+ LogoFileName?: string | null;
5802
+ } | undefined | null): string | null;
5599
5803
  /**
5600
- * 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.
5601
5808
  */
5602
- reEvaluateActionEnabledStates(): void;
5809
+ defaultIconClassFor(idAzienda: number | undefined | null): string;
5603
5810
  /**
5604
- * 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.
5605
5813
  */
5606
- private rebuildTableActionMenuItems;
5814
+ onLogoError(): void;
5607
5815
  /**
5608
- * Gestisce la logica operativa di `onColumnHeaderContextMenu` in modo coerente con l'implementazione corrente.
5609
- * @param event Evento che innesca il comportamento del metodo.
5610
- * @param col Parametro utilizzato dal metodo nel flusso elaborativo.
5611
- * @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.
5612
5818
  */
5613
- 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;
5614
5917
  /**
5615
- * Determina se la colonna `col` puo' essere pinned a sinistra. Regola
5616
- * simmetrica a `canPinRight`: pin-left e' consentito SOLO se la colonna
5617
- * e' la prima visibile, oppure tutte le colonne visibili prima di essa
5618
- * sono gia' pinned left.
5619
- *
5620
- * Why: pin-left sticky CSS funziona correttamente solo per colonne in
5621
- * testa: una colonna pinned-left con altre col non-pinned prima crea un
5622
- * gap visivo e disallinea il sticky offset (style.left viene calcolato
5623
- * sommando le sibling precedenti, ma quelle non-pinned scrollano →
5624
- * la cella pinned salta di posizione durante scroll orizzontale).
5625
- *
5626
- * Se la colonna e' gia' pinned a sinistra, ritorna `false` (l'azione
5627
- * "Pin left" sarebbe no-op — usare "Unpin" invece).
5918
+ * Cache per (context+scope) → applicable definitions.
5919
+ * Invalidata su `clearCache()` (es. dopo invalidate-metadata-runtime).
5628
5920
  */
5629
- 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;
5630
5952
  /**
5631
- * Determina se la colonna `col` puo' essere pinned a destra. Regola:
5632
- * il pin-right e' consentito SOLO se la colonna e' l'ultima visibile,
5633
- * oppure tutte le colonne visibili dopo di essa sono gia' pinned right.
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.
5634
5956
  *
5635
- * Why: pin-right sticky CSS funziona correttamente solo per colonne in
5636
- * coda: una colonna pinned-right con altre col non-pinned dopo crea un
5637
- * gap visivo e disallinea il sticky offset (style.right viene calcolato
5638
- * sommando le sibling successive, ma quelle non-pinned scrollano →
5639
- * la cella pinned salta di posizione durante scroll orizzontale).
5957
+ * Pattern legacy: `CA_<attribute_code>___<value>` AND `CS_<attribute_code>___<sortdir>`.
5640
5958
  *
5641
- * Se la colonna e' gia' pinned a destra, ritorna `false` (l'azione
5642
- * "Pin right" sarebbe no-op — usare "Unpin" invece).
5643
- */
5644
- canPinRight(col: any): boolean;
5645
- /**
5646
- * Imposta pin/frozen della colonna nel lato richiesto e persiste il layout utente.
5647
- */
5648
- private pinColumnFromContextMenu;
5649
- /**
5650
- * Rimuove pin/frozen dalla colonna selezionata e persiste il layout utente.
5651
- */
5652
- private unpinColumnFromContextMenu;
5653
- /**
5654
- * Rimuove pin/frozen da tutte le colonne e persiste il layout utente.
5655
- */
5656
- private unpinAllColumnsFromContextMenu;
5657
- /**
5658
- * Gestisce la logica operativa di `ensureMetadataColumnsDatasourceRoute` propagando aggiornamenti sui flussi reattivi usati dalla UI.
5659
- */
5660
- private ensureMetadataColumnsDatasourceRoute;
5661
- /**
5662
- * Inizializza (una sola volta) il datasource dedicato alle colonne metadato, caricando schema e configurazione necessari alle operazioni di update metadati.
5663
- */
5664
- private ensureMetadataColumnsDatasourceSchema;
5665
- /**
5666
- * Recupera dal datasource metadati il record colonna corrispondente a `mc_id`, usato per modifiche puntuali alle proprietà della colonna.
5667
- * @param mcId Identificativo `mc_id` della colonna metadato da leggere nel datasource amministrativo.
5668
- * @returns Promise che completa il flusso asincrono restituendo un risultato di tipo `Promise<any | null>`.
5669
- */
5670
- private fetchMetadataColumnRecord;
5671
- /**
5672
- * Apre il form editor dei metadati colonna per la `mc_id` selezionata e, alla chiusura con salvataggio, ricarica schema/dati della griglia.
5673
- * @param metaColumn Metadato colonna su cui aprire l'editor; la ricerca del record avviene tramite `mc_id`.
5674
- */
5675
- private openColumnMetadataEditor;
5676
- /**
5677
- * 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à.
5678
- * @param metaColumn Metadato colonna selezionato; viene usato `mc_id` per recuperare il record persistito e aggiornare `mc_hide_in_list`.
5679
- */
5680
- private hideColumnByMetadata;
5681
- /**
5682
- * 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.
5683
- * @param metaColumn Metadato colonna selezionato; viene usato `mc_id` per aggiornare `mc_display_string_in_view` e `mc_display_string_in_edit`.
5684
- */
5685
- private editColumnDisplayStrings;
5686
- /**
5687
- * Interpreta e normalizza input/configurazione in `parseColumns` per l'utilizzo nel componente.
5688
- * @param columns Collezione in ingresso processata dal metodo.
5689
- * @returns Struttura dati prodotta da `parseColumns` dopo normalizzazione/elaborazione.
5690
- */
5691
- parseColumns(columns: MetadatiColonna[]): any[];
5692
- /**
5693
- * Gestisce la logica di `onColumnResize` orchestrando le chiamate `captureResizedColumnWidth` e `detectChanges`.
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`.
5694
6574
  * @param event Evento UI/payload evento che innesca la logica del metodo.
5695
6575
  */
5696
6576
  onColumnResize(event: any): Promise<void>;
@@ -6560,7 +7440,7 @@ declare class ListGridComponent implements AfterViewInit, OnInit, OnDestroy, IDa
6560
7440
  * @returns Valore numerico derivato dai calcoli interni (conteggio, indice, priorita o metrica operativa).
6561
7441
  */
6562
7442
  private getWidthFromResizeEvent;
6563
- 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; }]>;
6564
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>;
6565
7445
  }
6566
7446
 
@@ -7454,6 +8334,34 @@ declare class MapListComponent implements OnInit, AfterViewInit, OnDestroy, IBin
7454
8334
  * Collezione dati per data, consumata dal rendering e dalle operazioni del componente.
7455
8335
  */
7456
8336
  data: any[];
8337
+ /**
8338
+ * Polyline overlay calcolate da `parseData` quando
8339
+ * `archetypeOptions.polyline.enabled=true`. Una polyline per gruppo
8340
+ * (`groupByField`), ordinate per `orderByField`. Renderizzate via
8341
+ * `<map-polyline>` nel template.
8342
+ */
8343
+ polylines: {
8344
+ path: {
8345
+ lat: number;
8346
+ lng: number;
8347
+ }[];
8348
+ options: any;
8349
+ group: any;
8350
+ }[];
8351
+ /**
8352
+ * Dot sui waypoint originali (coordinate reali dei record) renderizzati
8353
+ * via `<map-circle>` quando `archetypeOptions.polyline.showWaypointDots=true`.
8354
+ * Utile per distinguere i punti GPS storicizzati dal path interpolato/snapped.
8355
+ */
8356
+ polylineDots: {
8357
+ center: {
8358
+ lat: number;
8359
+ lng: number;
8360
+ };
8361
+ options: any;
8362
+ group: any;
8363
+ record: any;
8364
+ }[];
7457
8365
  /**
7458
8366
  * Configurazione di presentazione per item template string, usata nel rendering del componente.
7459
8367
  */
@@ -7654,11 +8562,54 @@ declare class MapListComponent implements OnInit, AfterViewInit, OnDestroy, IBin
7654
8562
  */
7655
8563
  parseData(data: any): any;
7656
8564
  /**
8565
+ * Costruisce le polyline overlay dai record applicando
8566
+ * `archetypeOptions.polyline`. Ogni gruppo (`groupByField`) → 1 polyline
8567
+ * con path ordinato per `orderByField`. Estende `bounds` cosi' fitBounds
8568
+ * include i punti del percorso.
8569
+ *
8570
+ * Se `snapToRoads=true`, dopo il render iniziale (path = punti raw) viene
8571
+ * lanciato `snapPolylinesToRoads()` async che chiama Google DirectionsService
8572
+ * e sostituisce ogni `path` con `overview_path` della rotta calcolata.
8573
+ */
8574
+ buildPolylines(data: any[], bounds: google.maps.LatLngBounds): {
8575
+ path: {
8576
+ lat: number;
8577
+ lng: number;
8578
+ }[];
8579
+ options: any;
8580
+ group: any;
8581
+ }[];
8582
+ /**
8583
+ * Snap async delle polyline alle strade reali. Usa la nuova
8584
+ * **Routes API** (`google.maps.routes.Route.computeRoutes`) che sostituisce
8585
+ * `DirectionsService` deprecato dal 2026-02-25. Fallback automatico a
8586
+ * `DirectionsService` legacy se la libreria `routes` non e' disponibile
8587
+ * o la chiamata fallisce (key senza "Routes API" abilitata, ecc.).
8588
+ *
8589
+ * Migration guide: https://developers.google.com/maps/documentation/javascript/routes/routes-js-migration
8590
+ *
8591
+ * Limite waypoint per chiamata = 25 (origin + 23 intermediates + destination):
8592
+ * polyline piu' lunghe vengono chunkate.
8593
+ *
8594
+ * Travel mode legacy → routes mapping: DRIVING→DRIVE, WALKING→WALK,
8595
+ * BICYCLING→BICYCLE.
8596
+ */
8597
+ private snapPolylinesToRoads;
8598
+ /**
7657
8599
  * Recupera i dati/valori richiesti da `getMarkerContent`.
7658
8600
  * @param record Dato/record su cui il metodo applica elaborazioni o aggiornamenti.
7659
8601
  * @returns Valore risolto da `getMarkerContent` in base ai criteri implementati.
7660
8602
  */
7661
8603
  getMarkerContent(record: any): any;
8604
+ /**
8605
+ * Costruisce un HTMLElement marker-content da una stringa che puo' essere:
8606
+ * - SVG inline (`<svg ...>...</svg>`) → wrappato in un `<div>` per renderlo
8607
+ * un AdvancedMarker content valido (deve essere un Element, non un
8608
+ * DocumentFragment). Dimensioni controllate dal viewBox dell'SVG.
8609
+ * - URL immagine (http/https/data:image/...) → `<img src>`.
8610
+ * - Stringa vuota / null → null (caller usa il fallback successivo).
8611
+ */
8612
+ private buildMarkerVisualFromValue;
7662
8613
  /**
7663
8614
  * Restituisce una Promise che wrappa `navigator.geolocation.getCurrentPosition`.
7664
8615
  * @returns Posizione geolocalizzata del browser oppure errore se non disponibile/negata.
@@ -7818,6 +8769,15 @@ declare class MapListComponent implements OnInit, AfterViewInit, OnDestroy, IBin
7818
8769
  * Apre l'info window del marker selezionato valorizzando `infoContent` con il template record.
7819
8770
  */
7820
8771
  openInfo(markerElem: any, marker: any): void;
8772
+ /**
8773
+ * Apre l'info window su un waypoint (`<map-circle>`) della polyline overlay.
8774
+ * Riusa lo stesso `itemTemplate` del marker principale: il record del
8775
+ * waypoint contiene tutti i campi (incluso `timestamp_pos`, `velocita_kmh`,
8776
+ * `note`, ecc.) che il template puo' leggere via `rowData.record?.<field>`.
8777
+ * L'anchor non e' un marker — passiamo la posizione esplicita via
8778
+ * `infoWindowOptions.position`.
8779
+ */
8780
+ openWaypointInfo(dot: any, $event?: any): void;
7821
8781
  /**
7822
8782
  * Apre la stessa info window usata dai marker quando l'utente clicca un poligono.
7823
8783
  * Se non e disponibile un anchor marker, usa la posizione click o il centro geometrico del poligono.
@@ -8178,8 +9138,9 @@ declare class CarouselListComponent implements IBindable, IDesigner<CarouselOpti
8178
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>;
8179
9139
  }
8180
9140
 
8181
- declare class LazySpreadsheetListSfComponent implements OnInit {
9141
+ declare class LazySpreadsheetListSfComponent implements OnInit, OnDestroy, AfterViewChecked {
8182
9142
  private readonly cdr;
9143
+ private readonly activatedRoute;
8183
9144
  innerOutlet?: NgComponentOutlet;
8184
9145
  hardcodedRoute: string;
8185
9146
  parentRecord: any;
@@ -8187,9 +9148,46 @@ declare class LazySpreadsheetListSfComponent implements OnInit {
8187
9148
  datasource: BehaviorSubject<DataSourceComponent>;
8188
9149
  hardcodedDatasource: DataSourceComponent;
8189
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>;
8190
9183
  loadedComponent: any;
8191
- constructor(cdr: ChangeDetectorRef);
9184
+ private routeQuerySub?;
9185
+ constructor(cdr: ChangeDetectorRef, activatedRoute: ActivatedRoute);
8192
9186
  ngOnInit(): Promise<void>;
9187
+ ngOnDestroy(): void;
9188
+ private lockEventSubs;
9189
+ private innerHooked;
9190
+ ngAfterViewChecked(): void;
8193
9191
  componentInputs(): {
8194
9192
  hardcodedRoute: string;
8195
9193
  parentRecord: any;
@@ -8197,9 +9195,14 @@ declare class LazySpreadsheetListSfComponent implements OnInit {
8197
9195
  datasource: BehaviorSubject<DataSourceComponent>;
8198
9196
  hardcodedDatasource: DataSourceComponent;
8199
9197
  hideToolbar: boolean;
9198
+ enableLockAwareness: boolean;
9199
+ lockScope: Record<string, any>;
9200
+ heartbeatIntervalSec: number;
9201
+ showFormulaBar: boolean;
9202
+ showRibbon: boolean;
8200
9203
  };
8201
9204
  static ɵfac: i0.ɵɵFactoryDeclaration<LazySpreadsheetListSfComponent, never>;
8202
- 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>;
8203
9206
  }
8204
9207
 
8205
9208
  declare class TreeListComponent implements OnInit, OnDestroy, IDataBoundHostComponent {
@@ -8420,6 +9423,7 @@ declare class ParametricDialogComponent implements OnInit, AfterViewInit, OnDest
8420
9423
  private router;
8421
9424
  private trnsl;
8422
9425
  private hostElementRef;
9426
+ private customAttributesService;
8423
9427
  private dialogService?;
8424
9428
  /**
8425
9429
  * Input dal componente padre per datasource; usata nella configurazione e nel rendering del componente.
@@ -8520,6 +9524,32 @@ declare class ParametricDialogComponent implements OnInit, AfterViewInit, OnDest
8520
9524
  * Configurazione di presentazione per form template, usata nel rendering del componente.
8521
9525
  */
8522
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
+ }>;
8523
9553
  /**
8524
9554
  * Flag di stato che governa il comportamento UI/logico relativo a cloning.
8525
9555
  */
@@ -8596,7 +9626,8 @@ declare class ParametricDialogComponent implements OnInit, AfterViewInit, OnDest
8596
9626
  * @param route Informazione di navigazione usata per risolvere la route di destinazione.
8597
9627
  * @param router Informazione di navigazione usata per risolvere la route di destinazione.
8598
9628
  */
8599
- 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);
8600
9631
  /**
8601
9632
  * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
8602
9633
  */
@@ -8799,8 +9830,25 @@ declare class ParametricDialogComponent implements OnInit, AfterViewInit, OnDest
8799
9830
  * quando la schermata viene riaperta subito dopo.
8800
9831
  */
8801
9832
  private reloadTranslationsIfMetadataSave;
8802
- static ɵfac: i0.ɵɵFactoryDeclaration<ParametricDialogComponent, [{ optional: true; }, { optional: true; }, null, null, null, null, { optional: true; }]>;
8803
- 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>;
8804
9852
  }
8805
9853
 
8806
9854
  /**
@@ -9030,575 +10078,329 @@ declare class AppSettingsEditorComponent implements OnInit {
9030
10078
  * ANCM/NSSM la finestra e' molto stretta e il caller (`saveAndApply`)
9031
10079
  * gia' fa un `sleep(Math.max(800, restartDelayMs+200))` prima di chiamare
9032
10080
  * questo metodo, coprendo il caso normale.
9033
- */
9034
- private waitForHealthSimple;
9035
- /**
9036
- * Wrapper legacy mantenuto per back-compat: alias di
9037
- * `waitForHealthSimple`. Eventuali consumer storici che chiamavano
9038
- * `waitForHealth(ms)` continuano a vedere il polling semplice (non il
9039
- * 4-phase) — coerente con ambienti prod dove il supervisor gestisce
9040
- * il restart.
9041
- */
9042
- private waitForHealth;
9043
- private forceLogout;
9044
- static ɵfac: i0.ɵɵFactoryDeclaration<AppSettingsEditorComponent, never>;
9045
- static ɵcmp: i0.ɵɵComponentDeclaration<AppSettingsEditorComponent, "wuic-app-settings-editor", never, {}, {}, never, never, true, never>;
9046
- }
9047
-
9048
- declare class DataActionButtonComponent implements AfterViewInit, OnDestroy {
9049
- private trslSrv;
9050
- private cd;
9051
- private messageService;
9052
- private confirmationService;
9053
- private router;
9054
- private http;
9055
- private metadataProvider;
9056
- private static readonly ACTION_KEY_EDIT;
9057
- data: any;
9058
- metaInfo: MetaInfo;
9059
- datasource: BehaviorSubject<DataSourceComponent>;
9060
- filter?: () => void;
9061
- simplified: boolean;
9062
- parentField: string;
9063
- btn: SplitButton;
9064
- simpleMenu?: Menu;
9065
- simplifiedMenuOpen: boolean;
9066
- items: MenuItem[];
9067
- selectedValue: any;
9068
- pkName: string;
9069
- inlineItems: any[];
9070
- nonInlineEditingItems: MenuItem[];
9071
- private translationsLoadedSub?;
9072
- constructor(trslSrv: TranslationManagerService, cd: ChangeDetectorRef, messageService: MessageService, confirmationService: ConfirmationService, router: Router, http: HttpClient, metadataProvider: MetadataProviderService);
9073
- /**
9074
- * Hook di debug locale per ispezionare l'evento click sul pulsante azioni.
9075
- * @param $event Evento UI ricevuto dal template.
9076
- */
9077
- test($event: any): void;
9078
- /**
9079
- * Inizializza il menu azioni in base ai metadati tabella/colonna (`md_editable`, `md_deletable`, `md_inline_edit`, colonne `button`).
9080
- * Calcola anche la PK corrente per le azioni route-based.
9081
- */
9082
- ngAfterViewInit(): void;
9083
- ngOnDestroy(): void;
9084
- private rebuildActionMenus;
9085
- private translateLabel;
9086
- /**
9087
- * Esegue il comando dell'item selezionato se non disabilitato.
9088
- * @param item Voce menu azione.
9089
- */
9090
- select(item: any): void;
9091
- /**
9092
- * Aggiunge al menu le azioni dinamiche derivate dalle colonne metadata di tipo `button`.
9093
- * @param target Collezione menu da arricchire.
9094
- */
9095
- private appendMetadataButtonItems;
9096
- private getButtonActionRecord;
9097
- /**
9098
- * Valuta se un bottone metadata e attivo verificando callback azione e condizione visibilita (`mc_button_visibility_condition`).
9099
- * @param col Metadato colonna di tipo button.
9100
- * @returns `true` se il bottone e eseguibile.
9101
- */
9102
- private isMetadataButtonEnabled;
9103
- /**
9104
- * Esegue l'azione custom del bottone metadata, con eventuale conferma (`mc_button_confirm_message`) e gestione errori centralizzata.
9105
- * @param col Metadato colonna button.
9106
- * @param record Record osservabile corrente.
9107
- * @param event Evento UI di invocazione.
9108
- */
9109
- private executeMetadataButton;
9110
- /**
9111
- * Avvia il flusso edit del record corrente:
9112
- * inline edit, popup `EditFormComponent` oppure navigazione route `/{route}/edit/{pk}`.
9113
- */
9114
- edit(): void;
9115
- /**
9116
- * Richiede conferma e, in caso positivo, elimina il record via `datasource.syncData(..., true)` ricaricando la griglia.
9117
- */
9118
- delete(): Promise<void>;
9119
- private canRestoreFromChangeMaster;
9120
- private appendRestoreFromChangeMasterActionAsync;
9121
- private isLogicalDeleteSupportedRoute;
9122
- private getRecordFieldIgnoreCase;
9123
- private restoreFromChangeMaster;
9124
- /**
9125
- * Apre il record in modalita sola lettura tramite `EditFormComponent` con `readOnly: true`.
9126
- */
9127
- detail(): void;
9128
- /**
9129
- * Apre `EditFormComponent` in modalita cloning per creare una copia del record corrente.
9130
- */
9131
- clone(): void;
9132
- /**
9133
- * Salva modifiche inline sincronizzando il record osservabile con backend e riallineando il modello riga in tabella.
9134
- */
9135
- save(): Promise<void>;
9136
- /**
9137
- * Annulla l'inline edit locale della riga corrente.
9138
- */
9139
- cancelEdit(): Promise<void>;
9140
- /**
9141
- * Hook evento click principale (attualmente usato come placeholder/debug).
9142
- * @param $event Evento click.
9143
- */
9144
- onClick($event: any): void;
9145
- /**
9146
- * Hook richiamato alla chiusura del menu split button.
9147
- * @param $event Evento PrimeNG.
9148
- */
9149
- onMenuHide($event: any): void;
9150
- /**
9151
- * Hook richiamato all'apertura del menu split button.
9152
- * @param $event Evento PrimeNG.
9153
- */
9154
- onMenuShow($event: any): void;
9155
- /**
9156
- * Hook click dropdown del pulsante azioni (punto estensione per custom behavior).
9157
- * @param $event Evento click dropdown.
9158
- */
9159
- onDropdownClick($event: any): void;
9160
- /**
9161
- * Ferma la propagazione dell'evento per evitare side effects sul contenitore (es. row click/select).
9162
- * @param $event Evento DOM.
9163
- */
9164
- fix($event: any): void;
9165
- /**
9166
- * Apre/chiude il popup menu in modalita semplificata con overlay appeso al body.
9167
- * Evita clipping dentro i contenitori FullCalendar.
9168
- * @param event Evento click del trigger.
9169
- */
9170
- onSimplifiedMenuClick(event: Event): void;
9171
- onSimplifiedMenuShow(): void;
9172
- onSimplifiedMenuHide(): void;
9173
- /**
9174
- * Abilita modalita inline-cell-editing via metadata tabella (con fallback legacy).
9175
- */
9176
- isInlineCellEditingEnabled(): boolean;
9177
- /**
9178
- * In inline-cell-editing, anche se la riga e marcata editing, mostra menu standard senza "edit".
9179
- */
9180
- showInlineEditingMenu(): boolean;
9181
- /**
9182
- * Modello menu effettivo da renderizzare nel pulsante azioni.
9183
- */
9184
- getActionMenuModel(): MenuItem[];
9185
- private toBooleanLoose;
9186
- addRecord(): void;
9187
- static ɵfac: i0.ɵɵFactoryDeclaration<DataActionButtonComponent, never>;
9188
- 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>;
9189
- }
9190
-
9191
- declare class LazyDataActionButtonComponent implements OnInit {
9192
- private readonly cdr;
9193
- /**
9194
- * Input dal componente padre per data; usata nella configurazione e nel rendering del componente.
9195
- */
9196
- data: any;
9197
- /**
9198
- * Input dal componente padre per meta info; usata nella configurazione e nel rendering del componente.
9199
- */
9200
- metaInfo: MetaInfo;
9201
- /**
9202
- * Input dal componente padre per datasource; usata nella configurazione e nel rendering del componente.
9203
- */
9204
- datasource: BehaviorSubject<any>;
9205
- /**
9206
- * Input dal componente padre per filter; usata nella configurazione e nel rendering del componente.
9207
- */
9208
- filter?: () => void;
9209
- /**
9210
- * Input dal componente padre per simplified; usata nella configurazione e nel rendering del componente.
9211
- */
9212
- simplified: boolean;
9213
- parentField: string;
9214
- /**
9215
- * Proprieta di stato del componente per loaded component, usata dalla logica interna e dal template.
9216
- */
9217
- loadedComponent: any;
9218
- constructor(cdr: ChangeDetectorRef);
9219
- /**
9220
- * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
9221
- */
9222
- ngOnInit(): Promise<void>;
9223
- /**
9224
- * Gestisce la logica di `componentInputs` con regole guidate dai metadati server `_Metadati_*` (tabella/colonna).
9225
- * @returns Oggetto risultato costruito dal metodo per il passo successivo del flusso.
9226
- */
9227
- componentInputs(): {
9228
- data: any;
9229
- metaInfo: MetaInfo;
9230
- datasource: BehaviorSubject<any>;
9231
- filter: () => void;
9232
- simplified: boolean;
9233
- parentField: string;
9234
- };
9235
- static ɵfac: i0.ɵɵFactoryDeclaration<LazyDataActionButtonComponent, never>;
9236
- 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>;
9237
- }
9238
-
9239
- /**
9240
- * Shape of the response returned by `/api/Meta/LicenseStatus` (GET).
9241
- * The endpoint is defined in `Controllers/MetaController.cs` LicenseStatus action.
9242
- */
9243
- interface LicenseStatusResponse {
9244
- machineFingerprint?: string;
9245
- licenseValid?: boolean;
9246
- licenseReason?: string;
9247
- licenseExpiryUtc?: string | null;
9248
- licenseEmail?: string;
9249
- maintenanceExpiryUtc?: string | null;
9250
- tier?: string;
9251
- features?: string[];
9252
- /**
9253
- * DBMS utilizzato dal backend per il **DB DATI** (`AppSettings.dbms`):
9254
- * `'mssql'` o `'mysql'`. Aggiunto 2026-04-28 per il tooltip license del
9255
- * meta-menu — sysadmin vede a colpo d'occhio su quale provider gira il
9256
- * deploy.
9257
- */
9258
- dataDbms?: string;
9259
- /**
9260
- * DBMS utilizzato dal backend per il **DB METADATI** (`AppSettings.meta-dbms`).
9261
- * Tipicamente uguale a `dataDbms` ma puo' divergere quando
9262
- * `allowMultipleDBMS=true` (es. data MySQL + metadata MSSQL).
9263
- */
9264
- metaDbms?: string;
9265
- }
9266
- /**
9267
- * Client-side view of the current license. Exposes synchronous `has(feature)`
9268
- * predicate for use in templates, directives, guards, and components.
9269
- *
9270
- * Lifecycle:
9271
- * 1) App bootstrap calls `refresh()` once.
9272
- * 2) All `*wuicFeature` directives and `FeatureRouteGuard` read from the
9273
- * cached snapshot via `has()`.
9274
- * 3) On license change (upgrade via new appsettings.json) restart the app
9275
- * OR call `refresh()` again to re-fetch.
9276
- *
9277
- * IMPORTANT: this service is a UX layer only. The real security is server-side
9278
- * (see `SanitizeBoardContent` + `[RequireFeature]` + data-decoration in
9279
- * `AsmxCrudRead`). A client can patch this service and unlock everything locally,
9280
- * but the server will still refuse premium operations.
9281
- */
9282
- declare class LicenseFeatureService {
10081
+ */
10082
+ private waitForHealthSimple;
10083
+ /**
10084
+ * Wrapper legacy mantenuto per back-compat: alias di
10085
+ * `waitForHealthSimple`. Eventuali consumer storici che chiamavano
10086
+ * `waitForHealth(ms)` continuano a vedere il polling semplice (non il
10087
+ * 4-phase) — coerente con ambienti prod dove il supervisor gestisce
10088
+ * il restart.
10089
+ */
10090
+ private waitForHealth;
10091
+ private forceLogout;
10092
+ static ɵfac: i0.ɵɵFactoryDeclaration<AppSettingsEditorComponent, never>;
10093
+ static ɵcmp: i0.ɵɵComponentDeclaration<AppSettingsEditorComponent, "wuic-app-settings-editor", never, {}, {}, never, never, true, never>;
10094
+ }
10095
+
10096
+ declare class DataActionButtonComponent implements AfterViewInit, OnDestroy {
10097
+ private trslSrv;
10098
+ private cd;
10099
+ private messageService;
10100
+ private confirmationService;
10101
+ private router;
9283
10102
  private http;
9284
- private static readonly ALWAYS_ALLOWED_ARCHETYPES;
9285
- private statusSubject;
9286
- private loadedOnce;
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);
9287
10121
  /**
9288
- * Promise risolta dopo il PRIMO `refresh()` (success or fail-closed).
9289
- * Usata dai route guard per attendere che lo snapshot iniziale sia
9290
- * disponibile prima di decidere access → evita race post-refresh pagina
9291
- * dove il guard partiva con `statusSubject.value === null` e denyava la
9292
- * feature anche con licenza valida.
10122
+ * Hook di debug locale per ispezionare l'evento click sul pulsante azioni.
10123
+ * @param $event Evento UI ricevuto dal template.
9293
10124
  */
9294
- private readyResolve;
9295
- private readyPromise;
9296
- constructor(http: HttpClient);
10125
+ test($event: any): void;
9297
10126
  /**
9298
- * Ritorna una Promise che risolve quando il primo `refresh()` ha completato
9299
- * (con successo o con fail-closed fallback). Dopo il primo load, ritorna
9300
- * una Promise gia' risolta → overhead zero. Il guard la await per decidere
9301
- * solo con snapshot reale, non con `null` iniziale.
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.
9302
10129
  */
9303
- ready(): Promise<void>;
10130
+ ngAfterViewInit(): void;
10131
+ ngOnDestroy(): void;
10132
+ private rebuildActionMenus;
10133
+ private translateLabel;
9304
10134
  /**
9305
- * Observable of the current license status snapshot. Emits `null` until the
9306
- * first `refresh()` completes.
10135
+ * Esegue il comando dell'item selezionato se non disabilitato.
10136
+ * @param item Voce menu azione.
9307
10137
  */
9308
- status$(): Observable<LicenseStatusResponse | null>;
10138
+ select(item: any): void;
9309
10139
  /**
9310
- * Synchronous accessor to the cached snapshot. Returns `null` if not yet loaded.
10140
+ * Aggiunge al menu le azioni dinamiche derivate dalle colonne metadata di tipo `button`.
10141
+ * @param target Collezione menu da arricchire.
9311
10142
  */
9312
- snapshot(): LicenseStatusResponse | null;
10143
+ private appendMetadataButtonItems;
10144
+ private getButtonActionRecord;
9313
10145
  /**
9314
- * Fetches `/api/Meta/LicenseStatus` and caches the result. Returns the promise
9315
- * so callers (like an APP_INITIALIZER) can await it.
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.
9316
10149
  */
9317
- refresh(): Promise<LicenseStatusResponse | null>;
9318
- /** Idempotent: il primo refresh risolve `readyPromise`; i successivi no-op. */
9319
- private signalReady;
10150
+ private isMetadataButtonEnabled;
9320
10151
  /**
9321
- * Returns true when the current license includes the given feature flag.
9322
- * Returns `false` when:
9323
- * - license not yet loaded (conservative default);
9324
- * - license is invalid;
9325
- * - feature is not in the `features` array.
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.
9326
10156
  */
9327
- has(feature: string): boolean;
10157
+ private executeMetadataButton;
9328
10158
  /**
9329
- * Returns true when the archetype (e.g. "spreadsheet", "pivot-grid", "list")
9330
- * is permitted by the current license. Archetypes in the always-allowed set
9331
- * (list, kanban, chart, ...) return true unconditionally.
10159
+ * Avvia il flusso edit del record corrente:
10160
+ * inline edit, popup `EditFormComponent` oppure navigazione route `/{route}/edit/{pk}`.
9332
10161
  */
9333
- isArchetypeAllowed(archetype: string): boolean;
10162
+ edit(): void;
9334
10163
  /**
9335
- * Mirrors the server-side `LicenseFeatureMap.ArchetypeFeatureMap`. Kept
9336
- * hardcoded on both sides so a patched client gets UX unlock, but the
9337
- * server-side gate (boardcontent sanitizer + data-decoration) still enforces.
10164
+ * Richiede conferma e, in caso positivo, elimina il record via `datasource.syncData(..., true)` ricaricando la griglia.
9338
10165
  */
9339
- private archetypeToFeature;
10166
+ delete(): Promise<void>;
10167
+ private canRestoreFromChangeMaster;
10168
+ private appendRestoreFromChangeMasterActionAsync;
10169
+ private isLogicalDeleteSupportedRoute;
10170
+ private getRecordFieldIgnoreCase;
10171
+ private restoreFromChangeMaster;
9340
10172
  /**
9341
- * Builds the LicenseStatus endpoint URL from `global_root_url`. The root is
9342
- * typically `"/api/Meta/AsmxProxy/"` (AsmxProxy pattern) or `"/api/Meta/"`
9343
- * (direct). LicenseStatus is a direct GET action on MetaController, so we
9344
- * strip any trailing `AsmxProxy/` segment before appending the action name.
10173
+ * Apre il record in modalita sola lettura tramite `EditFormComponent` con `readOnly: true`.
9345
10174
  */
9346
- private resolveLicenseStatusUrl;
9347
- static ɵfac: i0.ɵɵFactoryDeclaration<LicenseFeatureService, never>;
9348
- static ɵprov: i0.ɵɵInjectableDeclaration<LicenseFeatureService>;
9349
- }
9350
-
9351
- interface AuthSessionState {
9352
- initialized: boolean;
9353
- loading: boolean;
9354
- enabled: boolean;
9355
- authenticated: boolean;
9356
- legacyAuthenticated: boolean;
9357
- provider?: string;
9358
- name?: string;
9359
- legacyName?: string;
9360
- legacyRole?: string;
9361
- claims?: {
9362
- type: string;
9363
- value: string;
9364
- }[];
9365
- error?: string;
9366
- returnUrl: string;
9367
- sessionExpiring?: boolean;
9368
- sessionExpiresInSeconds?: number;
9369
- }
9370
- declare class AuthSessionService {
9371
- private http;
9372
- private userInfoService;
9373
- private metadataProvider;
9374
- private translationManager;
9375
- private ngZone;
9376
- private initialized;
9377
- private sessionTimeoutMs;
9378
- private sessionWarningMs;
9379
- private sessionTimer;
9380
- private sessionWarningTimer;
9381
- private sessionCountdownTimer;
9382
- private readonly stateSubject;
9383
- readonly state$: rxjs.Observable<AuthSessionState>;
9384
- get snapshot(): AuthSessionState;
9385
- constructor(http: HttpClient, userInfoService: UserInfoService, metadataProvider: MetadataProviderService, translationManager: TranslationManagerService, ngZone: NgZone);
10175
+ detail(): void;
9386
10176
  /**
9387
- * Allinea ngx-translate alla lingua dell'utente appena autenticato/hydratato.
9388
- * Necessario perche' il TranslationManagerService bootstrap risolve la lingua
9389
- * via `userInfoService.getuserInfo()` quando NESSUN utente e' ancora loggato,
9390
- * finendo di default su `navigator.language` o 'it-IT'. Senza questa call
9391
- * esplicita post-login, le traduzioni rese dal primo render (toolbar, menu,
9392
- * dialog) restano "appiccicate" alla lingua di bootstrap finche' l'utente
9393
- * non cambia lingua manualmente dal selettore, che invece chiama direttamente
9394
- * `useLanguage()`. Chiamata best-effort: fallisce silenzioso se la lingua non
9395
- * e' supportata o la tabella traduzioni non e' ancora pronta.
10177
+ * Apre `EditFormComponent` in modalita cloning per creare una copia del record corrente.
9396
10178
  */
9397
- private applyUserLanguageToTranslations;
10179
+ clone(): void;
9398
10180
  /**
9399
- * Inizializza il servizio una sola volta (o forzatamente) e carica lo stato sessione corrente via `refreshAll`.
9400
- * @param force Se `true` forza una nuova inizializzazione anche se gia avvenuta.
10181
+ * Salva modifiche inline sincronizzando il record osservabile con backend e riallineando il modello riga in tabella.
9401
10182
  */
9402
- initialize(force?: boolean): Promise<void>;
10183
+ save(): Promise<void>;
9403
10184
  /**
9404
- * Hydrates the UI-side user snapshot from the backend when sessionStorage
9405
- * is empty but a server-managed HttpOnly `k-user` cookie might still be
9406
- * valid. This is the critical step for `enableCookieAuthentication=true`:
9407
- * after a browser restart (or new tab) sessionStorage is gone, the cookie
9408
- * is HttpOnly and invisible to JS, so without this call the guard would
9409
- * wrongly redirect to `/unauthorized` despite a valid session.
9410
- *
9411
- * Flow:
9412
- * 1. If sessionStorage already has a snapshot → no hydration needed.
9413
- * 2. Otherwise call `MetaService.me` with `withCredentials:true`. The
9414
- * backend reads the HttpOnly cookie server-side and returns the
9415
- * public user fields (and `cookieAuthEnabled` for introspection).
9416
- * 3. If `me()` returns a populated payload, write it to sessionStorage
9417
- * via `userInfoService.setUserInfoCookie` so subsequent calls see
9418
- * the user. If `me()` returns an empty object `{}` (no valid
9419
- * cookie) the hydration is a no-op and the UI stays logged out.
9420
- *
9421
- * Errors are swallowed on purpose: if `me()` throws (network, backend
9422
- * down, legacy backend without the endpoint), we fall back to whatever
9423
- * the cookie/sessionStorage already has without blocking the boot.
10185
+ * Annulla l'inline edit locale della riga corrente.
9424
10186
  */
9425
- private hydrateFromServerCookie;
10187
+ cancelEdit(): Promise<void>;
9426
10188
  /**
9427
- * Ricalcola lo stato autenticazione combinando configurazione OAuth, endpoint `Auth/Enabled`, endpoint `Auth/Me`
9428
- * e fallback sessione legacy (`k-user`), poi sincronizza eventuali custom settings utente.
10189
+ * Hook evento click principale (attualmente usato come placeholder/debug).
10190
+ * @param $event Evento click.
9429
10191
  */
9430
- refreshAll(): Promise<void>;
10192
+ onClick($event: any): void;
9431
10193
  /**
9432
- * Aggiorna il `returnUrl` nello stato sessione applicando normalizzazione anti-open-redirect.
9433
- * @param returnUrl URL di ritorno post login/logout.
10194
+ * Hook richiamato alla chiusura del menu split button.
10195
+ * @param $event Evento PrimeNG.
9434
10196
  */
9435
- setReturnUrl(returnUrl: string): void;
10197
+ onMenuHide($event: any): void;
9436
10198
  /**
9437
- * Avvia il login OAuth reindirizzando il browser a `Auth/Login` con `returnUrl` codificato.
9438
- * @param returnUrl URL di ritorno post login/logout.
10199
+ * Hook richiamato all'apertura del menu split button.
10200
+ * @param $event Evento PrimeNG.
9439
10201
  */
9440
- login(returnUrl?: string): void;
10202
+ onMenuShow($event: any): void;
9441
10203
  /**
9442
- * Esegue logout OAuth: pulisce prima stato client (storage + DB locali) e custom settings, poi redirect a `Auth/Logout`.
9443
- * @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.
9444
10206
  */
9445
- logout(returnUrl?: string): Promise<void>;
10207
+ onDropdownClick($event: any): void;
9446
10208
  /**
9447
- * Esegue login legacy via `MetaService.login`, interpreta le varianti payload storiche (`isLogged`, `value`, JSON string)
9448
- * e in caso positivo salva l'utente nel cookie `k-user`.
9449
- * @param username Username credenziale di autenticazione.
9450
- * @param password Password credenziale di autenticazione.
10209
+ * Ferma la propagazione dell'evento per evitare side effects sul contenitore (es. row click/select).
10210
+ * @param $event Evento DOM.
9451
10211
  */
9452
- legacyLogin(username: string, password: string, captchaToken?: string): Promise<boolean>;
10212
+ fix($event: any): void;
9453
10213
  /**
9454
- * Logout flow that works in BOTH cookie modes:
9455
- *
9456
- * - **Server-managed mode** (`enableCookieAuthentication=true`): the
9457
- * `k-user` cookie is HttpOnly, so the only way to delete it is via a
9458
- * `Set-Cookie` delete header from the server. We call
9459
- * `MetaService.logoutSession` (parameterless) which:
9460
- * 1. derives the user from the cookie server-side,
9461
- * 2. wipes the DB session token via the existing `logout(user)`
9462
- * per-DBMS dispatcher,
9463
- * 3. emits the `Set-Cookie` delete with matching CookieOptions.
9464
- *
9465
- * - **Legacy mode** (`enableCookieAuthentication=false`): we still call
9466
- * `logoutSession` because the server-side helper is idempotent in
9467
- * legacy mode and always wipes the DB token. The local
9468
- * `userInfoService.clearUserInfo()` then deletes the JS-readable
9469
- * cookie + sessionStorage snapshot.
9470
- *
9471
- * Why not call the legacy `MetaService.logout(user)` overload? It only
9472
- * runs the per-DBMS DB cleanup; it does NOT emit the cookie delete
9473
- * header, so the HttpOnly cookie would survive the logout in
9474
- * server-managed mode and the next page load would re-hydrate the
9475
- * supposedly-logged-out user via `MetaService.me`. The new
9476
- * `logoutSession` does both atomically.
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.
9477
10217
  */
9478
- legacyLogout(): Promise<void>;
10218
+ onSimplifiedMenuClick(event: Event): void;
10219
+ onSimplifiedMenuShow(): void;
10220
+ onSimplifiedMenuHide(): void;
9479
10221
  /**
9480
- * Pulisce lo stato runtime e le cache associate.
9481
- * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
9482
- * @returns Valore restituito dal metodo (Promise<void>).
10222
+ * Abilita modalita inline-cell-editing via metadata tabella (con fallback legacy).
9483
10223
  */
9484
- private clearClientRuntimeState;
10224
+ isInlineCellEditingEnabled(): boolean;
9485
10225
  /**
9486
- * Pulisce lo stato runtime e le cache associate.
9487
- * Legge/scrive dati persistenti su storage browser.
10226
+ * In inline-cell-editing, anche se la riga e marcata editing, mostra menu standard senza "edit".
9488
10227
  */
9489
- private clearBrowserStorage;
10228
+ showInlineEditingMenu(): boolean;
9490
10229
  /**
9491
- * Rimuove i dati target aggiornando lo stato del servizio.
9492
- * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
9493
- * @param dbName Nome database locale/remote da trattare.
9494
- * @returns Valore restituito dal metodo (Promise<void>).
10230
+ * Modello menu effettivo da renderizzare nel pulsante azioni.
9495
10231
  */
9496
- private deleteDexieDatabase;
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;
9497
10241
  /**
9498
- * Rimuove i dati target aggiornando lo stato del servizio.
9499
- * Gestisce anche persistenza locale su IndexedDB/Dexie quando prevista.
9500
- * @param dbName Nome database locale/remote da trattare.
9501
- * @returns Valore restituito dal metodo (Promise<void>).
10242
+ * Input dal componente padre per data; usata nella configurazione e nel rendering del componente.
9502
10243
  */
9503
- private deleteIndexedDbByName;
10244
+ data: any;
9504
10245
  /**
9505
- * Carica e cache-a i custom settings dell'utente loggato in localStorage allineando il bootstrap sessione con MetadataProvider.
10246
+ * Input dal componente padre per meta info; usata nella configurazione e nel rendering del componente.
9506
10247
  */
9507
- private bootstrapUserCustomSettings;
10248
+ metaInfo: MetaInfo;
9508
10249
  /**
9509
- * Configura il timeout di sessione in minuti. Chiamato dal meta-menu dopo aver letto AuthConfig.
10250
+ * Input dal componente padre per datasource; usata nella configurazione e nel rendering del componente.
9510
10251
  */
9511
- setSessionTimeout(minutes: number, warningMinutes?: number): void;
9512
- private activityListenersAttached;
9513
- /** Timestamp dell'ultimo reset throttled, in ms epoch. */
9514
- private lastActivityResetAt;
9515
- /** Min intervallo tra reset throttled (mousemove/scroll). 1s e' un buon compromesso
9516
- * tra responsiveness al "vero" idle e overhead da event flood. */
9517
- private static readonly ACTIVITY_RESET_THROTTLE_MS;
9518
- private setupActivityListeners;
10252
+ datasource: BehaviorSubject<any>;
9519
10253
  /**
9520
- * Avvia/riavvia i timer di sessione. Chiamato dopo login e ad ogni attività HTTP.
10254
+ * Input dal componente padre per filter; usata nella configurazione e nel rendering del componente.
9521
10255
  */
9522
- resetSessionTimer(): void;
9523
- private startSessionExpiryCountdown;
9524
- private handleSessionExpired;
9525
- private clearSessionTimers;
9526
- private isUserAuthenticated;
10256
+ filter?: () => void;
9527
10257
  /**
9528
- * Applica un aggiornamento parziale allo stato `AuthSessionState` preservando le proprieta non toccate.
9529
- * @param partial Delta stato da fondere con lo stato corrente.
10258
+ * Input dal componente padre per simplified; usata nella configurazione e nel rendering del componente.
9530
10259
  */
10260
+ simplified: boolean;
10261
+ parentField: string;
9531
10262
  /**
9532
- * Sets a user-visible error message in the auth state.
9533
- * Used by the auth-expired interceptor to communicate the logout
9534
- * reason (e.g. "session replaced by another login") after the
9535
- * logout flow has completed and the login form is visible.
10263
+ * Proprieta di stato del componente per loaded component, usata dalla logica interna e dal template.
9536
10264
  */
9537
- setError(message: string): void;
9538
- /** User-facing messages keyed by server reason code. */
9539
- private static readonly REASON_MESSAGES;
10265
+ loadedComponent: any;
10266
+ constructor(cdr: ChangeDetectorRef);
9540
10267
  /**
9541
- * Reads and removes the redirect reason left by the auth-expired
9542
- * interceptor in localStorage, then sets the corresponding error
9543
- * message in the auth state so the login form displays it.
10268
+ * Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
9544
10269
  */
9545
- private applyRedirectReason;
9546
- private patchState;
10270
+ ngOnInit(): Promise<void>;
9547
10271
  /**
9548
- * Costruisce una struttura derivata a partire dallo stato corrente.
9549
- * @param action Azione richiesta nel flusso corrente.
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[];
10300
+ /**
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.
9550
10305
  */
9551
- private buildEndpoint;
10306
+ dataDbms?: string;
9552
10307
  /**
9553
- * Costruisce una struttura derivata a partire dallo stato corrente.
9554
- * @param fullMethodName Nome completo metodo legacy (es. `MetaService.login`).
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).
9555
10311
  */
9556
- private buildMetaAsmxEndpoint;
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;
9557
10335
  /**
9558
- * Risolve la base URL API usata dal servizio: preferisce `appSettings.api_url`, fallback su `${window.location.origin}/api/`.
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.
9559
10341
  */
9560
- private getApiBaseUrl;
10342
+ private readyResolve;
10343
+ private readyPromise;
10344
+ constructor(http: HttpClient);
9561
10345
  /**
9562
- * Valuta una condizione booleana sullo stato o sull'input corrente.
9563
- * @returns Valore restituito dal metodo (boolean).
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.
9564
10350
  */
9565
- private isOAuthEnabledInSettings;
10351
+ ready(): Promise<void>;
9566
10352
  /**
9567
- * Normalizza il payload in una forma coerente per i passaggi successivi.
9568
- * @param returnUrl URL di ritorno post login/logout.
10353
+ * Observable of the current license status snapshot. Emits `null` until the
10354
+ * first `refresh()` completes.
9569
10355
  */
9570
- private normalizeReturnUrl;
10356
+ status$(): Observable<LicenseStatusResponse | null>;
9571
10357
  /**
9572
- * Ritorna l'URL browser corrente usato come `returnUrl` predefinito in login/logout.
10358
+ * Synchronous accessor to the cached snapshot. Returns `null` if not yet loaded.
9573
10359
  */
9574
- private getCurrentLocalUrl;
10360
+ snapshot(): LicenseStatusResponse | null;
9575
10361
  /**
9576
- * Esegue il parsing del valore in ingresso con fallback sicuro.
9577
- * @param raw Payload legacy da interpretare (stringa JSON, oggetto o wrapper con `value`).
9578
- * @returns Valore restituito dal metodo (any).
10362
+ * Fetches `/api/Meta/LicenseStatus` and caches the result. Returns the promise
10363
+ * so callers (like an APP_INITIALIZER) can await it.
9579
10364
  */
9580
- private parseLegacyLoginResponse;
10365
+ refresh(): Promise<LicenseStatusResponse | null>;
10366
+ /** Idempotent: il primo refresh risolve `readyPromise`; i successivi no-op. */
10367
+ private signalReady;
9581
10368
  /**
9582
- * Estrae un messaggio errore leggibile da payload legacy eterogenei (raw/parsing/error/value) del login storico.
9583
- * @param raw Payload grezzo risposta/errore.
9584
- * @param parsed Payload gia interpretato.
9585
- * @returns Messaggio errore normalizzato oppure `null`.
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`.
9586
10381
  */
9587
- private extractLegacyLoginError;
10382
+ has(feature: string): boolean;
9588
10383
  /**
9589
- * Prova a leggere un messaggio errore da stringhe plain/JSON o da oggetti con chiavi comuni (`message`, `error`, `ExceptionMessage`).
9590
- * @param candidate Sorgente messaggio da analizzare.
9591
- * @returns Messaggio trovato 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.
9592
10387
  */
9593
- private readMessage;
10388
+ isArchetypeAllowed(archetype: string): boolean;
9594
10389
  /**
9595
- * Log diagnostico opzionale del flusso login legacy, attivo solo con `appSettings.debugLegacyLogin === true`.
9596
- * @param kind Tipo evento (`response` o `error`).
9597
- * @param payload Payload da tracciare in console.
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.
9598
10393
  */
9599
- private debugLegacyLogin;
9600
- static ɵfac: i0.ɵɵFactoryDeclaration<AuthSessionService, never>;
9601
- static ɵprov: i0.ɵɵInjectableDeclaration<AuthSessionService>;
10394
+ private archetypeToFeature;
10395
+ /**
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.
10400
+ */
10401
+ private resolveLicenseStatusUrl;
10402
+ static ɵfac: i0.ɵɵFactoryDeclaration<LicenseFeatureService, never>;
10403
+ static ɵprov: i0.ɵɵInjectableDeclaration<LicenseFeatureService>;
9602
10404
  }
9603
10405
 
9604
10406
  type WorkflowRuntimeMenuState = {
@@ -10064,17 +10866,6 @@ declare class MetaMenuComponent implements OnInit, AfterViewInit, OnDestroy {
10064
10866
  * altrimenti svuota il menu locale e interrompe il flusso.
10065
10867
  */
10066
10868
  private loadMenuIfAllowed;
10067
- /**
10068
- * Removes menu entries pointing to routes that require a license feature not
10069
- * included in the current license. Works recursively on nested items. The
10070
- * `route` shape of menu items comes from `mm_uri_menu` and matches the
10071
- * Angular route templates (e.g. `workflow-designer`, `<route>/spreadsheet`,
10072
- * `<route>/pivot-builder`, `<route>/dashboard`, `rag-chatbot`).
10073
- *
10074
- * UX layer only — server-side `SanitizeBoardContent` + `[RequireFeature]`
10075
- * are the authoritative gates.
10076
- */
10077
- private filterMenuByLicenseFeatures;
10078
10869
  /**
10079
10870
  * Ricompone `items` unendo menu base e runtime; quando `runtimeMenuExclusive` è attivo
10080
10871
  * mostra solo le voci runtime.
@@ -10412,7 +11203,7 @@ declare class NumberEditorComponent implements IFieldEditor, AfterViewInit {
10412
11203
  static ɵcmp: i0.ɵɵComponentDeclaration<NumberEditorComponent, "wuic-number-editor", never, { "record": { "alias": "record"; "required": false; }; "field": { "alias": "field"; "required": false; }; "metaInfo": { "alias": "metaInfo"; "required": false; }; "isFilter": { "alias": "isFilter"; "required": false; }; "nestedIndex": { "alias": "nestedIndex"; "required": false; }; "triggerProp": { "alias": "triggerProp"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "tabIndex": { "alias": "tabIndex"; "required": false; }; }, {}, never, never, true, never>;
10413
11204
  }
10414
11205
 
10415
- declare class LookupEditorComponent implements IFieldEditor, AfterViewInit, AfterViewChecked, OnChanges {
11206
+ declare class LookupEditorComponent implements IFieldEditor, AfterViewInit, AfterViewChecked, OnChanges, OnDestroy {
10416
11207
  private trslSrv;
10417
11208
  private cd;
10418
11209
  private hostElementRef;
@@ -10459,6 +11250,14 @@ declare class LookupEditorComponent implements IFieldEditor, AfterViewInit, Afte
10459
11250
  * Riferimento a elementi o componenti figli usato dalla logica UI per nested source.
10460
11251
  */
10461
11252
  nestedSource: DataSourceComponent;
11253
+ /**
11254
+ * Riferimento al p-autoComplete PrimeNG, usato per re-triggerare l'apertura
11255
+ * della dropdown dopo che il layout di focus-expand inline-cell-editing ha
11256
+ * riposizionato l'input (cell -> 360px). Senza re-show, la prima onDropdownClick
11257
+ * calcola la posizione overlay sulla larghezza vecchia e l'overlay puo' restare
11258
+ * chiuso o ancorato male.
11259
+ */
11260
+ autoCompleteRef: AutoComplete;
10462
11261
  /**
10463
11262
  * Collezione dati per items, consumata dal rendering e dalle operazioni del componente.
10464
11263
  */
@@ -10487,6 +11286,7 @@ declare class LookupEditorComponent implements IFieldEditor, AfterViewInit, Afte
10487
11286
  */
10488
11287
  constructor(trslSrv: TranslationManagerService, cd: ChangeDetectorRef, hostElementRef: ElementRef<HTMLElement>);
10489
11288
  ngOnChanges(_changes: SimpleChanges): void;
11289
+ ngOnDestroy(): void;
10490
11290
  /**
10491
11291
  * Legge `mc_props_bag.lookup.virtualize` e determina se abilitare il virtual scroll del p-autocomplete.
10492
11292
  * Supporta boolean/number/string oppure object con `enabled`.
@@ -10501,6 +11301,52 @@ declare class LookupEditorComponent implements IFieldEditor, AfterViewInit, Afte
10501
11301
  * Completa inizializzazione dopo il rendering della view e collega riferimenti UI.
10502
11302
  */
10503
11303
  ngAfterViewInit(): void;
11304
+ /**
11305
+ * Subscribe a `record[mc_nome_colonna]` BehaviorSubject: quando un FK viene
11306
+ * settato programmaticamente (es. importazione documento sorgente, CAI
11307
+ * setRecordValue, custom callback) e il valore NON e' presente in `items`
11308
+ * — perche' la prima fetch e' avvenuta prima che il setRecordValue propagasse,
11309
+ * o il valore e' fuori dalla pagina corrente del combo — avviare una
11310
+ * second-stage fetch filtrata sul valore per recuperare il record correlato e
11311
+ * popolare `__lookup_obj` (cosi' il dropdown mostra il display text).
11312
+ *
11313
+ * Skip cases:
11314
+ * - lookupByID multi-value (isFilter operatore=eqor, multiple_check)
11315
+ * - prima emit del BS (init flow gia' coperto sopra)
11316
+ * - valore null/undefined (utente ha clearato)
11317
+ * - valore gia' nei items
11318
+ * - hasActiveLookupQuery true (utente sta typing una query manuale)
11319
+ */
11320
+ private installProgrammaticValueAutoFetch;
11321
+ /**
11322
+ * Workaround per inline-cell-editing + focus-expand:
11323
+ *
11324
+ * Quando la lookup vive dentro una <wuic-list-grid> con `md_inline_cell_editing=1`,
11325
+ * il primo click sul chevron (button.p-autocomplete-dropdown) genera questa sequenza:
11326
+ * 1. mousedown sul chevron alla posizione X
11327
+ * 2. PrimeNG sposta il focus sull'input
11328
+ * 3. il selector CSS `:focus-within` sul TD espande l'input da cell-width a 360px
11329
+ * 4. il chevron, che e' inline-flex accanto all'input, si sposta verso destra
11330
+ * 5. mouseup avviene alla posizione X originale, che ora e' DENTRO l'input
11331
+ * espanso (non piu' sul chevron)
11332
+ * 6. il browser NON emette `click` perche' mouseup-target != mousedown-target
11333
+ * 7. di conseguenza ne il PrimeNG handler interno ne il nostro
11334
+ * `(onDropdownClick)` ricevono mai l'evento -> overlay mai aperto
11335
+ *
11336
+ * Soluzione: ascoltare `mousedown` sul chevron (che PARTE prima di qualunque
11337
+ * reflow e si triggera regolarmente) e schedulare `show()` con un delay che
11338
+ * lascia stabilizzare il focus-expand. Cosi' l'overlay si aggancia al chevron
11339
+ * nella sua posizione finale, esattamente come ci si aspetta.
11340
+ */
11341
+ /**
11342
+ * Handler delegato dal template (`<p-autoComplete (mousedown)="onLookupHostMousedown($event)">`).
11343
+ * Si triggera al mousedown su qualunque punto dell'autoComplete, e in particolare
11344
+ * cattura il mousedown sul chevron PRIMA del reflow del focus-expand.
11345
+ *
11346
+ * Solo dentro inline-cell-editing: in normale edit form il click funziona gia'
11347
+ * nativamente (nessun focus-expand che muove il chevron) e qui ritorniamo NOOP.
11348
+ */
11349
+ onLookupHostMousedown(event: MouseEvent): void;
10504
11350
  ngAfterViewChecked(): void;
10505
11351
  private applyAriaLabelledByToInput;
10506
11352
  /**
@@ -10531,6 +11377,22 @@ declare class LookupEditorComponent implements IFieldEditor, AfterViewInit, Afte
10531
11377
  private restoreLookupInputFocusIfNeeded;
10532
11378
  onLookupOverlayShow(): void;
10533
11379
  onLookupOverlayHide(): void;
11380
+ /**
11381
+ * Re-triggera l'apertura della dropdown dopo un breve delay.
11382
+ *
11383
+ * Use case: quando la lookup vive dentro una <wuic-list-grid> con
11384
+ * `md_inline_cell_editing=1`, il click sul chevron mette il focus sull'input
11385
+ * e attiva la regola CSS `:focus-within` che espande l'input da cell-width a
11386
+ * 360px (Excel-like). PrimeNG calcola la posizione dell'overlay e fa il
11387
+ * primo `show()` PRIMA che il reflow CSS sia stato applicato, quindi
11388
+ * l'overlay puo' risultare chiuso, mal posizionato o riagganciato a
11389
+ * un'ancora di larghezza vecchia.
11390
+ *
11391
+ * Il delay di 120ms lascia che il reflow del focus-expand si stabilizzi,
11392
+ * poi forziamo un secondo `show()` che ricalcola posizione/larghezza
11393
+ * coerenti con l'input gia' espanso.
11394
+ */
11395
+ onDropdownClickHandler(_event: any): void;
10534
11396
  static ɵfac: i0.ɵɵFactoryDeclaration<LookupEditorComponent, never>;
10535
11397
  static ɵcmp: i0.ɵɵComponentDeclaration<LookupEditorComponent, "wuic-lookup-editor", never, { "record": { "alias": "record"; "required": false; }; "field": { "alias": "field"; "required": false; }; "metaInfo": { "alias": "metaInfo"; "required": false; }; "isFilter": { "alias": "isFilter"; "required": false; }; "nestedIndex": { "alias": "nestedIndex"; "required": false; }; "triggerProp": { "alias": "triggerProp"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "tabIndex": { "alias": "tabIndex"; "required": false; }; "ariaLabelledBy": { "alias": "ariaLabelledBy"; "required": false; }; }, {}, never, never, true, never>;
10536
11398
  }
@@ -11125,6 +11987,23 @@ declare class FieldEditorComponent implements OnInit, OnChanges, OnDestroy, DoCh
11125
11987
  * @returns Valore calcolato dinamicamente a partire dallo stato corrente del componente.
11126
11988
  */
11127
11989
  get classes(): string | null;
11990
+ /**
11991
+ * True quando il field-editor e' renderizzato dentro una cella di una
11992
+ * list-grid in `md_inline_cell_editing` mode. In quel contesto la
11993
+ * larghezza della cella e' governata dalla colonna del p-table (e da
11994
+ * `mc_ui_grid_size_width`), non dalla form-default `mc_ui_size_width`
11995
+ * — applicare 300px sull'editor o sul span readonly inflerebbe le
11996
+ * colonne. Il caller (list-grid row template) NON passa un input
11997
+ * dedicato: identifichiamo l'inline mode dal flag tableMetadata.
11998
+ */
11999
+ get isInlineCellHost(): boolean;
12000
+ /**
12001
+ * Width da applicare all'editor / span readonly. In inline cell host
12002
+ * usa `100%` (la cella ha gia' la sua larghezza dalla colonna). Fuori
12003
+ * inline-grid (form/dialog) usa la logica storica:
12004
+ * `mc_ui_size_width || widgetMap[type].width || undefined`.
12005
+ */
12006
+ get widgetWidth(): string | undefined;
11128
12007
  private syncDomAttrs;
11129
12008
  /**
11130
12009
  * function Object() { [native code] }
@@ -11145,6 +12024,16 @@ declare class FieldEditorComponent implements OnInit, OnChanges, OnDestroy, DoCh
11145
12024
  */
11146
12025
  ngOnChanges(_changes: SimpleChanges): void;
11147
12026
  ngOnDestroy(): void;
12027
+ /**
12028
+ * Valore formattato per il readonly span (template: `{{readonlySpanValue}}`).
12029
+ * Aggiornato reattivamente in setupReadonlySpanBinding subscribendo alla
12030
+ * BehaviorSubject del campo: quando un setRecordValue programmatico (es.
12031
+ * default async di sp_next_progressivo) chiama BS.next, lo span si
12032
+ * aggiorna senza dover rendere `formatGridViewValue` impure.
12033
+ */
12034
+ readonlySpanValue: unknown;
12035
+ private readonlySpanSub?;
12036
+ private setupReadonlySpanBinding;
11148
12037
  /**
11149
12038
  * Rileva mutazioni in-place del tipo widget (es. da text a dictionary nel designer)
11150
12039
  * e riallinea il componente editor visualizzato.
@@ -12112,6 +13001,14 @@ declare class NotificationBellComponent implements OnInit, OnDestroy {
12112
13001
  deleteNotificationTitle: string;
12113
13002
  private readonly sub;
12114
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;
12115
13012
  /** Risolve i label dalle traduzioni, rispettando eventuali @Input espliciti. */
12116
13013
  private resolveLabels;
12117
13014
  ngOnInit(): Promise<void>;
@@ -13929,8 +14826,18 @@ declare class WuicErrorDialogComponent implements OnInit, OnDestroy {
13929
14826
  private cdr;
13930
14827
  visible: boolean;
13931
14828
  currentException: CustomException | null;
14829
+ /**
14830
+ * Set di firme errori che l'utente ha gia' chiuso esplicitamente in
14831
+ * questa sessione (dismissedSignatures). Il dialog NON si riapre per
14832
+ * eventi successivi con stessa firma -> evita il loop "fetch fallisce
14833
+ * -> dialog si riapre" che impedisce all'utente di intervenire sulla
14834
+ * pagina sotto (es. aprire metadata-editor per riparare la causa).
14835
+ * Firma = `<traceId>` se presente, altrimenti `<title>::<body>`.
14836
+ */
14837
+ private dismissedSignatures;
13932
14838
  private sub?;
13933
14839
  constructor(cdr: ChangeDetectorRef);
14840
+ private signatureOf;
13934
14841
  ngOnInit(): void;
13935
14842
  ngOnDestroy(): void;
13936
14843
  formatParameters(params: Record<string, unknown> | undefined | null): string;
@@ -14073,5 +14980,5 @@ declare const THEME_OPTIONS: ThemeOption[];
14073
14980
  declare function getThemeOptions(): ThemeOption[];
14074
14981
  declare function getThemePrimaryHex(value: string): string;
14075
14982
 
14076
- 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 };
14077
- 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 };