wuic-framework-lib 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{wuic-framework-lib-chart-list.component-C9_EDkGu.mjs → wuic-framework-lib-chart-list.component-B1V8Q-Qq.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-code-editor.component-D_p7LGSQ.mjs → wuic-framework-lib-code-editor.component-4N95qt3D.mjs} +24 -3
- package/fesm2022/{wuic-framework-lib-designer.component-Dx6RraAn.mjs → wuic-framework-lib-designer.component-pW1YK-oY.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-first-run-wizard.component-Cp8IKDb9.mjs → wuic-framework-lib-first-run-wizard.component-CaGePYLi.mjs} +12 -2
- package/fesm2022/{wuic-framework-lib-framework-docs.component-CxckBsIX.mjs → wuic-framework-lib-framework-docs.component-m0IlS0Sl.mjs} +3 -3
- package/fesm2022/{wuic-framework-lib-pivot-builder.component-C-ceJi48.mjs → wuic-framework-lib-pivot-builder.component-VIs0CIH_.mjs} +11 -8
- package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-DPZCgxOB.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-Dm9GTZ07.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-report-designer.component-3-hUYft8.mjs → wuic-framework-lib-report-designer.component-FiAwNkPM.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-report-viewer.component-D4QD_wPl.mjs → wuic-framework-lib-report-viewer.component-DY0dGMrt.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-scheduler-list.component-C0nY8Wd6.mjs → wuic-framework-lib-scheduler-list.component-3E5m-9Qd.mjs} +31 -5
- package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-C9sWgq61.mjs → wuic-framework-lib-spreadsheet-list-sf.component-D9P9WbDl.mjs} +42 -22
- package/fesm2022/{wuic-framework-lib-workflow-designer.component-8mv_Rbz9.mjs → wuic-framework-lib-workflow-designer.component-4RC2EkGA.mjs} +23 -3
- package/fesm2022/{wuic-framework-lib-wuic-framework-lib-DJZAYFw8.mjs → wuic-framework-lib-wuic-framework-lib-BSyGhpM1.mjs} +251 -39
- package/fesm2022/wuic-framework-lib.mjs +1 -1
- package/package.json +1 -1
- package/types/wuic-framework-lib.d.ts +56 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, ApplicationRef, EnvironmentInjector, createComponent, NgModule, Component, createNgModule, inject, NgZone, Input, HostBinding, ChangeDetectionStrategy, Pipe, ViewChild, EventEmitter, Output, forwardRef, HostListener, Optional, ViewChildren, signal, computed, ViewContainerRef, Directive,
|
|
2
|
+
import { Injectable, ApplicationRef, EnvironmentInjector, createComponent, NgModule, Component, createNgModule, inject, NgZone, ElementRef, Input, HostBinding, ChangeDetectionStrategy, Pipe, ViewChild, EventEmitter, Output, forwardRef, HostListener, Optional, ViewChildren, signal, computed, ViewContainerRef, Directive, ViewEncapsulation } from '@angular/core';
|
|
3
3
|
import { BehaviorSubject, firstValueFrom, Subject, combineLatest, catchError, EMPTY, throwError, Subscription } from 'rxjs';
|
|
4
4
|
import * as i1$2 from '@angular/router';
|
|
5
5
|
import { Router, NavigationEnd, NavigationStart, RouterModule, RouterLink } from '@angular/router';
|
|
@@ -2707,7 +2707,7 @@ class WtoolboxService {
|
|
|
2707
2707
|
const appRef = resolvedInjector.get(ApplicationRef);
|
|
2708
2708
|
const environmentInjector = resolvedInjector.get(EnvironmentInjector);
|
|
2709
2709
|
const close$ = new Subject();
|
|
2710
|
-
const { PromptDialogFallbackHostComponent } = await import('./wuic-framework-lib-prompt-dialog-fallback-host.component-
|
|
2710
|
+
const { PromptDialogFallbackHostComponent } = await import('./wuic-framework-lib-prompt-dialog-fallback-host.component-Dm9GTZ07.mjs');
|
|
2711
2711
|
const hostRef = createComponent(PromptDialogFallbackHostComponent, { environmentInjector });
|
|
2712
2712
|
hostRef.instance.datasource = dialogConfig?.data?.datasource;
|
|
2713
2713
|
hostRef.instance.header = String(dialogConfig?.header || '');
|
|
@@ -3080,6 +3080,11 @@ class WtoolboxService {
|
|
|
3080
3080
|
*/
|
|
3081
3081
|
async suggestColumnMD(record, field, type, routeRef) {
|
|
3082
3082
|
const explicitRouteRef = String(routeRef || '').trim();
|
|
3083
|
+
// ATTENZIONE: niente trim() sul VALORE — le route system WUIC hanno leading/trailing
|
|
3084
|
+
// space significativi (es. ` metadati tabelle`). Vedi AGENTS.md regola 17:
|
|
3085
|
+
// "le route metadata possono contenere spazi significativi; non applicare trim() o
|
|
3086
|
+
// normalizzazioni che rimuovono/compattano spazi quando leggi/confronti route
|
|
3087
|
+
// metadata". Trim() qui causava server-side route lookup miss → results vuoto.
|
|
3083
3088
|
const resolveRecordValue = (name) => {
|
|
3084
3089
|
if (!name || !record) {
|
|
3085
3090
|
return '';
|
|
@@ -3089,13 +3094,13 @@ class WtoolboxService {
|
|
|
3089
3094
|
return '';
|
|
3090
3095
|
}
|
|
3091
3096
|
if (typeof raw === 'object' && raw && 'value' in raw) {
|
|
3092
|
-
return String(raw.value || '')
|
|
3097
|
+
return String(raw.value || '');
|
|
3093
3098
|
}
|
|
3094
|
-
return String(raw || '')
|
|
3099
|
+
return String(raw || '');
|
|
3095
3100
|
};
|
|
3096
3101
|
const explicitRoute = explicitRouteRef ? resolveRecordValue(explicitRouteRef) : '';
|
|
3097
3102
|
const fallbackRoute = resolveRecordValue('md_route_name');
|
|
3098
|
-
const routeFromMetadataEditorContext = String(WtoolboxService.metadataEditorContextRouteName || '')
|
|
3103
|
+
const routeFromMetadataEditorContext = String(WtoolboxService.metadataEditorContextRouteName || '');
|
|
3099
3104
|
const route = explicitRoute || fallbackRoute || routeFromMetadataEditorContext;
|
|
3100
3105
|
if (!route) {
|
|
3101
3106
|
WtoolboxService.messageNotificationService.add({ severity: 'info', summary: WtoolboxService.tr('common.not_found_summary', 'Not Found'), detail: WtoolboxService.tr('suggest.not_found_route_for_column', 'No route found for column suggestion.') });
|
|
@@ -3933,7 +3938,15 @@ class WtoolboxService {
|
|
|
3933
3938
|
usePreview: false
|
|
3934
3939
|
},
|
|
3935
3940
|
scheduler: {
|
|
3936
|
-
advancedFilter: false
|
|
3941
|
+
advancedFilter: false,
|
|
3942
|
+
// FIX 2026-05-22: allineamento con SchedulerOptions.ts class fields.
|
|
3943
|
+
// Il defaultPropsBag e' la fonte del suggest tree di md_props_bag —
|
|
3944
|
+
// se manca una property qui, l'admin non puo' selezionarla nel suggest.
|
|
3945
|
+
fromField: '',
|
|
3946
|
+
toField: '',
|
|
3947
|
+
titleField: '',
|
|
3948
|
+
itemTemplateString: '',
|
|
3949
|
+
titleFunction: ''
|
|
3937
3950
|
},
|
|
3938
3951
|
spreadsheet: {
|
|
3939
3952
|
advancedFilter: false
|
|
@@ -5578,6 +5591,16 @@ class GlobalHandler {
|
|
|
5578
5591
|
*/
|
|
5579
5592
|
handleLegacyError(e) {
|
|
5580
5593
|
let exc;
|
|
5594
|
+
// FirstRun polling endpoints — silent skip dei 503 transient durante
|
|
5595
|
+
// l'app-pool recycle che IIS triggera quando configure_wuic riscrive
|
|
5596
|
+
// appsettings.json (FileSystemWatcher → recycle). Il client fa polling
|
|
5597
|
+
// ogni 500ms su FirstRunProgress + FirstRunStatus durante install, e
|
|
5598
|
+
// i ~30s di shutdown→restart pool generavano 13+ dialog 503 concorrenti.
|
|
5599
|
+
// Questi endpoint sono design-by-retry: il chiamante (first-run-wizard
|
|
5600
|
+
// + waitForBackendReady) ha gia' try/catch silenzioso + retry loop —
|
|
5601
|
+
// il dialog modale del GlobalHandler e' rumore puro.
|
|
5602
|
+
const errUrl = String(e?.url || e?.error?.url || '');
|
|
5603
|
+
const isFirstRunPolling = /\/api\/Meta\/FirstRun(Progress|Status)\b/i.test(errUrl);
|
|
5581
5604
|
// Skill crash-reporting Commit 9b (Opzione B): generic HTTP/runtime
|
|
5582
5605
|
// error fallbacks. Coprono errori che NON hanno il typed envelope
|
|
5583
5606
|
// (chiamate a endpoint non-AsmxProxy: OAuth, file upload custom,
|
|
@@ -5587,6 +5610,15 @@ class GlobalHandler {
|
|
|
5587
5610
|
const httpStatus = (typeof e?.status === 'number')
|
|
5588
5611
|
? e.status
|
|
5589
5612
|
: (typeof e?.error?.status === 'number' ? e.error.status : undefined);
|
|
5613
|
+
// Silent-suppress firstrun polling errors (any HTTP status — typical
|
|
5614
|
+
// sequence: 503 Shutting Down → connection refused → 503 Starting Up).
|
|
5615
|
+
if (isFirstRunPolling) {
|
|
5616
|
+
try {
|
|
5617
|
+
console.debug('[GlobalHandler] suppress firstrun polling error', httpStatus, errUrl);
|
|
5618
|
+
}
|
|
5619
|
+
catch { /* noop */ }
|
|
5620
|
+
return;
|
|
5621
|
+
}
|
|
5590
5622
|
const isTimeout = (e?.name === 'TimeoutError') ||
|
|
5591
5623
|
(typeof e?.message === 'string' && /timeout/i.test(e.message)) ||
|
|
5592
5624
|
(httpStatus === 0 && typeof e?.message === 'string' && /timeout|aborted/i.test(e.message));
|
|
@@ -12660,6 +12692,24 @@ class TranslationManagerService {
|
|
|
12660
12692
|
backendRetryTimer;
|
|
12661
12693
|
firstRunStatusChecked = false;
|
|
12662
12694
|
firstRunStatusValue = false;
|
|
12695
|
+
/**
|
|
12696
|
+
* Circuit breaker BE-offline: dopo {@link MAX_BACKEND_RETRIES} fallimenti
|
|
12697
|
+
* consecutivi di `loadTranslations`, smettiamo di rischedulare il retry
|
|
12698
|
+
* automatico. Con il vecchio loop a 1s, un BE offline generava ~60 chiamate
|
|
12699
|
+
* fallite/min (vedi screenshot 2026-05-19: 318 errori console + ~190 XHR in
|
|
12700
|
+
* pochi secondi). Ora dopo 5 fallimenti il timer si ferma e l'utente vede
|
|
12701
|
+
* un banner globale "Backend offline" + bottone "Riprova" che chiama
|
|
12702
|
+
* `retryBackendNow()` per resettare il circuito.
|
|
12703
|
+
*
|
|
12704
|
+
* Reset condizioni:
|
|
12705
|
+
* - chiamata esplicita a `ensureTranslationsLoaded(true)` (forceReload);
|
|
12706
|
+
* - chiamata esplicita a `retryBackendNow()` (bottone UI);
|
|
12707
|
+
* - prima chiamata con successo (counter back to 0).
|
|
12708
|
+
*/
|
|
12709
|
+
static MAX_BACKEND_RETRIES = 5;
|
|
12710
|
+
consecutiveBackendFailures = 0;
|
|
12711
|
+
/** True quando MAX_BACKEND_RETRIES e' stato raggiunto → niente piu' retry automatici. */
|
|
12712
|
+
backendCircuitOpen$ = new BehaviorSubject(false);
|
|
12663
12713
|
/**
|
|
12664
12714
|
* Dedup set per i warning "Missing translation resource". Senza questo
|
|
12665
12715
|
* Angular ChangeDetection invoca `instant(key)` ad ogni ciclo per ogni
|
|
@@ -12753,6 +12803,14 @@ class TranslationManagerService {
|
|
|
12753
12803
|
clearTimeout(this.backendRetryTimer);
|
|
12754
12804
|
this.backendRetryTimer = undefined;
|
|
12755
12805
|
}
|
|
12806
|
+
// Reset circuit breaker BE-offline: forceReload e' un'azione utente
|
|
12807
|
+
// esplicita (cambio lingua, logout/login, retry manuale), quindi
|
|
12808
|
+
// l'eventuale stato di "BE irraggiungibile" della sessione precedente
|
|
12809
|
+
// va azzerato per dargli una nuova chance.
|
|
12810
|
+
this.consecutiveBackendFailures = 0;
|
|
12811
|
+
if (this.backendCircuitOpen$.value)
|
|
12812
|
+
this.backendCircuitOpen$.next(false);
|
|
12813
|
+
this.firstRunStatusChecked = false;
|
|
12756
12814
|
}
|
|
12757
12815
|
if (!this.loadPromise) {
|
|
12758
12816
|
const currentLoad = this.loadTranslations();
|
|
@@ -13071,14 +13129,28 @@ class TranslationManagerService {
|
|
|
13071
13129
|
}
|
|
13072
13130
|
}
|
|
13073
13131
|
this.translationsLoaded$.next(true);
|
|
13132
|
+
// Successo → reset circuit breaker (anche se non era aperto, resta zero).
|
|
13133
|
+
this.consecutiveBackendFailures = 0;
|
|
13134
|
+
if (this.backendCircuitOpen$.value)
|
|
13135
|
+
this.backendCircuitOpen$.next(false);
|
|
13074
13136
|
}
|
|
13075
13137
|
catch (err) {
|
|
13076
|
-
// Errore HTTP (network/5xx):
|
|
13077
|
-
//
|
|
13078
|
-
//
|
|
13079
|
-
//
|
|
13080
|
-
//
|
|
13138
|
+
// Errore HTTP (network/5xx): retry con limite. Senza il counter qui sotto
|
|
13139
|
+
// un BE offline genera ~60 chiamate fallite/min (1s loop × 2 endpoint:
|
|
13140
|
+
// FirstRunStatus + GetTranslation), e Chrome inonda la console di CORS
|
|
13141
|
+
// errors. Dopo MAX_BACKEND_RETRIES (5) il loop si ferma e l'utente
|
|
13142
|
+
// riprova tramite UI (banner / refresh / `retryBackendNow()`).
|
|
13081
13143
|
this.translationsLoaded$.next(false);
|
|
13144
|
+
this.consecutiveBackendFailures += 1;
|
|
13145
|
+
if (this.consecutiveBackendFailures >= TranslationManagerService.MAX_BACKEND_RETRIES) {
|
|
13146
|
+
// Circuito aperto: smette di rischedulare. Logga UNA volta per non spammare.
|
|
13147
|
+
if (!this.backendCircuitOpen$.value) {
|
|
13148
|
+
// eslint-disable-next-line no-console
|
|
13149
|
+
console.warn(`[translation-manager] Backend irraggiungibile dopo ${this.consecutiveBackendFailures} tentativi. Retry automatici sospesi. Chiama TranslationManagerService.retryBackendNow() o ricarica la pagina per riprovare.`);
|
|
13150
|
+
this.backendCircuitOpen$.next(true);
|
|
13151
|
+
}
|
|
13152
|
+
return;
|
|
13153
|
+
}
|
|
13082
13154
|
if (!this.backendRetryTimer) {
|
|
13083
13155
|
this.backendRetryTimer = setTimeout(() => {
|
|
13084
13156
|
this.backendRetryTimer = undefined;
|
|
@@ -13087,6 +13159,25 @@ class TranslationManagerService {
|
|
|
13087
13159
|
}
|
|
13088
13160
|
}
|
|
13089
13161
|
}
|
|
13162
|
+
/**
|
|
13163
|
+
* Reset esplicito del circuit breaker BE-offline + retry immediato.
|
|
13164
|
+
* Da chiamare quando l'utente clicca "Riprova" sul banner offline, o
|
|
13165
|
+
* quando un altro servizio rileva che il BE e' tornato online (es. ping
|
|
13166
|
+
* health check, network 'online' event, ecc.). NON usare in retry loops
|
|
13167
|
+
* automatici — il senso del breaker e' proprio fermarli.
|
|
13168
|
+
*/
|
|
13169
|
+
retryBackendNow() {
|
|
13170
|
+
this.consecutiveBackendFailures = 0;
|
|
13171
|
+
if (this.backendCircuitOpen$.value)
|
|
13172
|
+
this.backendCircuitOpen$.next(false);
|
|
13173
|
+
if (this.backendRetryTimer) {
|
|
13174
|
+
clearTimeout(this.backendRetryTimer);
|
|
13175
|
+
this.backendRetryTimer = undefined;
|
|
13176
|
+
}
|
|
13177
|
+
this.firstRunStatusChecked = false;
|
|
13178
|
+
this.loadPromise = undefined;
|
|
13179
|
+
void this.ensureTranslationsLoaded();
|
|
13180
|
+
}
|
|
13090
13181
|
/**
|
|
13091
13182
|
* Revalidate background: rifetcha la tabella traduzioni dal backend SENZA
|
|
13092
13183
|
* bloccare l'UI. Confronta size + contenuto (hash leggero su `id,resource,
|
|
@@ -13585,6 +13676,18 @@ class DataSourceComponent {
|
|
|
13585
13676
|
aRoute;
|
|
13586
13677
|
userInfo;
|
|
13587
13678
|
static liveInstances = new Set();
|
|
13679
|
+
/**
|
|
13680
|
+
* Riferimento al DOM host element. Iniettato via `inject()` (Angular 14+ functional
|
|
13681
|
+
* DI) invece che da costruttore per non rompere i call site manuali tipo
|
|
13682
|
+
* `new DataSourceComponent(metaSrv, dataSrv, ...)` in designer.component.ts
|
|
13683
|
+
* e metadata-editor.service.ts (che mantengono i 7 params posizionali storici).
|
|
13684
|
+
* `{ optional: true }` rende il field null fuori da un Angular DI context
|
|
13685
|
+
* (es. unit test che istanziano la classe a mano) — il consumo in ngOnInit
|
|
13686
|
+
* usa `?.nativeElement` per sopportare entrambi i path.
|
|
13687
|
+
* Scopo: esporre `this` su `host.__wuicCmp` per E2E introspection senza
|
|
13688
|
+
* dipendere da `window.ng.getComponent` (tree-shaken in prod build).
|
|
13689
|
+
*/
|
|
13690
|
+
elementRef = inject(ElementRef, { optional: true });
|
|
13588
13691
|
static getLiveInstances() {
|
|
13589
13692
|
return Array.from(DataSourceComponent.liveInstances);
|
|
13590
13693
|
}
|
|
@@ -14189,6 +14292,18 @@ class DataSourceComponent {
|
|
|
14189
14292
|
*/
|
|
14190
14293
|
ngOnInit() {
|
|
14191
14294
|
DataSourceComponent.liveInstances.add(this);
|
|
14295
|
+
// E2E introspection hook: expose component instance on the host element so
|
|
14296
|
+
// tests can find it via DOM (`host.__wuicCmp`) without depending on
|
|
14297
|
+
// `window.ng.getComponent`, which Angular tree-shakes in production builds
|
|
14298
|
+
// (verified empirically 2026-05-25: VM serves prod bundle, `window.ng` has
|
|
14299
|
+
// only `ɵcompilerFacade`, no `getComponent`). The smart-app contract test
|
|
14300
|
+
// (`smart-app--default.mjs`) and code-editor toggle-monaco test use this
|
|
14301
|
+
// path to assert public method surface (enableClientSideCrud, etc.).
|
|
14302
|
+
// Pattern mirror PrimeNG `__component` / Vuetify `__vueParentComponent`.
|
|
14303
|
+
try {
|
|
14304
|
+
(this.elementRef?.nativeElement).__wuicCmp = this;
|
|
14305
|
+
}
|
|
14306
|
+
catch { /* defensive */ }
|
|
14192
14307
|
this.lastAction = this.aRoute.snapshot.paramMap.get('action');
|
|
14193
14308
|
if (this.routeFromRouting) {
|
|
14194
14309
|
this.routerEventsSubscription?.unsubscribe();
|
|
@@ -14268,6 +14383,13 @@ class DataSourceComponent {
|
|
|
14268
14383
|
*/
|
|
14269
14384
|
ngOnDestroy() {
|
|
14270
14385
|
DataSourceComponent.liveInstances.delete(this);
|
|
14386
|
+
// Clear the E2E introspection hook set in ngOnInit. The host element may
|
|
14387
|
+
// outlive the component instance briefly during Angular's tear-down, so
|
|
14388
|
+
// dropping the ref prevents stale-component leaks for tests.
|
|
14389
|
+
try {
|
|
14390
|
+
delete (this.elementRef?.nativeElement).__wuicCmp;
|
|
14391
|
+
}
|
|
14392
|
+
catch { /* defensive */ }
|
|
14271
14393
|
if (this.interval) {
|
|
14272
14394
|
clearInterval(this.interval);
|
|
14273
14395
|
}
|
|
@@ -21074,7 +21196,7 @@ class LazySchedulerListComponent {
|
|
|
21074
21196
|
* Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
|
|
21075
21197
|
*/
|
|
21076
21198
|
async ngOnInit() {
|
|
21077
|
-
schedulerListComponentPromise ??= import('./wuic-framework-lib-scheduler-list.component-
|
|
21199
|
+
schedulerListComponentPromise ??= import('./wuic-framework-lib-scheduler-list.component-3E5m-9Qd.mjs').then((m) => m.SchedulerListComponent);
|
|
21078
21200
|
this.loadedComponent = await schedulerListComponentPromise;
|
|
21079
21201
|
this.cdr.markForCheck();
|
|
21080
21202
|
}
|
|
@@ -21282,7 +21404,7 @@ class LazySpreadsheetListSfComponent {
|
|
|
21282
21404
|
this.activatedRoute = activatedRoute;
|
|
21283
21405
|
}
|
|
21284
21406
|
async ngOnInit() {
|
|
21285
|
-
spreadsheetListSfComponentPromise ??= import('./wuic-framework-lib-spreadsheet-list-sf.component-
|
|
21407
|
+
spreadsheetListSfComponentPromise ??= import('./wuic-framework-lib-spreadsheet-list-sf.component-D9P9WbDl.mjs').then((m) => m.SpreadsheetListSfComponent);
|
|
21286
21408
|
this.loadedComponent = await spreadsheetListSfComponentPromise;
|
|
21287
21409
|
// Quando la promise e' gia' risolta dal cache module-scope (secondo mount
|
|
21288
21410
|
// post-refresh), il microtask che risolve `await` non scatena sempre CD
|
|
@@ -21560,7 +21682,7 @@ class LazyChartListComponent {
|
|
|
21560
21682
|
* Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
|
|
21561
21683
|
*/
|
|
21562
21684
|
async ngOnInit() {
|
|
21563
|
-
chartListComponentPromise ??= import('./wuic-framework-lib-chart-list.component-
|
|
21685
|
+
chartListComponentPromise ??= import('./wuic-framework-lib-chart-list.component-B1V8Q-Qq.mjs').then((m) => m.ChartListComponent);
|
|
21564
21686
|
this.loadedComponent = await chartListComponentPromise;
|
|
21565
21687
|
this.cdr.markForCheck();
|
|
21566
21688
|
}
|
|
@@ -41148,13 +41270,33 @@ class TreeListComponent {
|
|
|
41148
41270
|
const route = this.metaInfo?.tableMetadata?.md_route_name;
|
|
41149
41271
|
labelFunction = (record) => WtoolboxService.runUserCallbackSync('archetypes.tree.labelFunction', () => compiledLabelFn(record), [], { archetype: 'tree', route });
|
|
41150
41272
|
}
|
|
41273
|
+
// FIX 2026-05-22: in server-side ops mode, se leafField ritorna null/undefined
|
|
41274
|
+
// (es. colonna IsLeaf non popolata), PrimeNG cade nel fallback `!children.length`
|
|
41275
|
+
// e tratta il nodo come leaf → niente chevron di espansione → utente non puo'
|
|
41276
|
+
// aprire i child. Default `leaf: false` in lazy mode cosi' il chevron e' sempre
|
|
41277
|
+
// mostrato e il child viene caricato on-demand via onNodeExpand.
|
|
41278
|
+
const isServerSideMode = !!this.metaInfo?.tableMetadata?.md_server_side_operations;
|
|
41151
41279
|
if (data) {
|
|
41152
41280
|
data.forEach((record) => {
|
|
41153
41281
|
const recordKey = this.getRecordPrimaryKeyValue(record);
|
|
41154
41282
|
const recordLabel = labelFunction ? labelFunction(record) : this.getRecordFieldValue(record, this.treeOptions?.labelField);
|
|
41155
41283
|
const recordIcon = this.getRecordFieldValue(record, this.treeOptions?.iconField);
|
|
41156
|
-
const
|
|
41284
|
+
const recordLeafRaw = this.getRecordFieldValue(record, this.treeOptions?.leafField);
|
|
41157
41285
|
const parentKey = this.getRecordFieldValue(record, this.treeOptions?.parentField);
|
|
41286
|
+
// Normalizza leaf flag:
|
|
41287
|
+
// - valore esplicito boolean → usa quello
|
|
41288
|
+
// - null/undefined in server-side mode → leaf=false (chevron + lazy load)
|
|
41289
|
+
// - null/undefined in client-side mode → leaf=undefined (PrimeNG decide su children)
|
|
41290
|
+
let recordLeaf;
|
|
41291
|
+
if (recordLeafRaw === true || recordLeafRaw === 'true' || recordLeafRaw === 1 || recordLeafRaw === '1') {
|
|
41292
|
+
recordLeaf = true;
|
|
41293
|
+
}
|
|
41294
|
+
else if (recordLeafRaw === false || recordLeafRaw === 'false' || recordLeafRaw === 0 || recordLeafRaw === '0') {
|
|
41295
|
+
recordLeaf = false;
|
|
41296
|
+
}
|
|
41297
|
+
else {
|
|
41298
|
+
recordLeaf = isServerSideMode ? false : undefined;
|
|
41299
|
+
}
|
|
41158
41300
|
let item = {
|
|
41159
41301
|
key: recordKey,
|
|
41160
41302
|
label: recordLabel ?? '',
|
|
@@ -41221,11 +41363,24 @@ class TreeListComponent {
|
|
|
41221
41363
|
]);
|
|
41222
41364
|
const res = await this.dataSrv.select(this.datasource.value, true);
|
|
41223
41365
|
const records = Array.isArray(res?.dato) ? res.dato : [];
|
|
41366
|
+
// FIX 2026-05-22: stessa normalizzazione leaf di _parseDataInternal (sopra)
|
|
41367
|
+
// per i nodi lazy-loaded da onNodeExpand.
|
|
41368
|
+
const isServerSideMode = !!this.metaInfo?.tableMetadata?.md_server_side_operations;
|
|
41224
41369
|
const children = records.map((record) => {
|
|
41225
41370
|
const recordKey = this.getRecordPrimaryKeyValue(record);
|
|
41226
41371
|
const recordLabel = this.getRecordFieldValue(record, this.treeOptions?.labelField);
|
|
41227
41372
|
const recordIcon = this.getRecordFieldValue(record, this.treeOptions?.iconField);
|
|
41228
|
-
const
|
|
41373
|
+
const recordLeafRaw = this.getRecordFieldValue(record, this.treeOptions?.leafField);
|
|
41374
|
+
let recordLeaf;
|
|
41375
|
+
if (recordLeafRaw === true || recordLeafRaw === 'true' || recordLeafRaw === 1 || recordLeafRaw === '1') {
|
|
41376
|
+
recordLeaf = true;
|
|
41377
|
+
}
|
|
41378
|
+
else if (recordLeafRaw === false || recordLeafRaw === 'false' || recordLeafRaw === 0 || recordLeafRaw === '0') {
|
|
41379
|
+
recordLeaf = false;
|
|
41380
|
+
}
|
|
41381
|
+
else {
|
|
41382
|
+
recordLeaf = isServerSideMode ? false : undefined;
|
|
41383
|
+
}
|
|
41229
41384
|
return {
|
|
41230
41385
|
key: recordKey,
|
|
41231
41386
|
label: recordLabel ?? '',
|
|
@@ -43506,6 +43661,13 @@ class MetaMenuComponent {
|
|
|
43506
43661
|
* tradotti, che e' un'esperienza confusa.
|
|
43507
43662
|
*/
|
|
43508
43663
|
translationsLoaded$;
|
|
43664
|
+
/**
|
|
43665
|
+
* Stato circuit breaker BE-offline esposto dal TranslationManagerService.
|
|
43666
|
+
* Quando true → mostriamo il banner "Backend offline" + bottone "Riprova"
|
|
43667
|
+
* al posto dello spinner "Loading…" altrimenti infinito. Il click sul
|
|
43668
|
+
* bottone chiama `retryBackend()` che riarma il circuito e ritenta.
|
|
43669
|
+
*/
|
|
43670
|
+
backendCircuitOpen$;
|
|
43509
43671
|
/**
|
|
43510
43672
|
* Proprieta di stato del componente per auth return url, usata dalla logica interna e dal template.
|
|
43511
43673
|
*/
|
|
@@ -43595,6 +43757,17 @@ class MetaMenuComponent {
|
|
|
43595
43757
|
this.elementRef = elementRef;
|
|
43596
43758
|
this.authState$ = this.authSession.state$;
|
|
43597
43759
|
this.translationsLoaded$ = this.trslSrv.translationsLoaded$.asObservable();
|
|
43760
|
+
this.backendCircuitOpen$ = this.trslSrv.backendCircuitOpen$.asObservable();
|
|
43761
|
+
}
|
|
43762
|
+
/**
|
|
43763
|
+
* Handler del bottone "Riprova" del banner BE-offline. Resetta il circuit
|
|
43764
|
+
* breaker nel TranslationManagerService e tenta immediatamente una nuova
|
|
43765
|
+
* fetch di `MetaService.GetTranslation`. Se il BE e' di nuovo online il
|
|
43766
|
+
* banner sparisce e parte lo spinner standard; se il BE e' ancora offline,
|
|
43767
|
+
* dopo altri 5 fallimenti consecutivi il banner riappare.
|
|
43768
|
+
*/
|
|
43769
|
+
retryBackend() {
|
|
43770
|
+
this.trslSrv.retryBackendNow();
|
|
43598
43771
|
}
|
|
43599
43772
|
/**
|
|
43600
43773
|
* Completa inizializzazione dopo il rendering della view e collega riferimenti UI.
|
|
@@ -45068,11 +45241,11 @@ class MetaMenuComponent {
|
|
|
45068
45241
|
}
|
|
45069
45242
|
}
|
|
45070
45243
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MetaMenuComponent, deps: [{ token: MetadataProviderService }, { token: AuthSessionService }, { token: TranslationManagerService }, { token: UserInfoService }, { token: WorkflowRuntimeMenuService }, { token: i1$1.HttpClient }, { token: i0.NgZone }, { token: i1$2.Router }, { token: LicenseFeatureService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
45071
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MetaMenuComponent, isStandalone: true, selector: "wuic-meta-menu", host: { listeners: { "document:click": "onDocumentClick()" } }, viewQueries: [{ propertyName: "menu", first: true, predicate: ["menubar"], descendants: true }, { propertyName: "menuMetadataDs", first: true, predicate: ["menuMetadataDs"], descendants: true }], ngImport: i0, template: "@if (authState$ | async; as auth) {\n<nav class=\"wuic-meta-menu-landmark\" aria-label=\"Menu principale\">\n @if (auth.sessionExpiring) {\n <div class=\"wuic-session-warning\">\n <span class=\"pi pi-exclamation-triangle\"></span>\n {{ 'auth.session.expiring_in' | translate }} <strong>{{ auth.sessionExpiresInSeconds }}</strong> {{ 'seconds' |\n translate }}.\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"refreshAuthSession()\">{{ 'auth.session.extend' | translate\n }}</button>\n </div>\n }\n @if (auth.initialized && !requiresAuthentication(auth)) {\n <div style=\"display:none\">\n <wuic-data-source #menuMetadataDs [hardcodedRoute]=\"metaMenuRoute\" [autoload]=\"false\"></wuic-data-source>\n </div>\n <p-menubar #menubar [model]=\"items\" [autoHide]=\"false\">\n <ng-template #item let-item>\n @if (item.route) {\n <!-- [href] con path assoluto (NO `#/` hash) cosi' Lighthouse SEO\n `crawlable-anchors` considera il link crawlable: il path\n `/<route>` e' un URL valid + condivisibile + apribile in nuova\n tab via Ctrl+Click. Il click handler `onMenuItemClick` chiama\n `event.preventDefault()` quando il button click e' \"primary\"\n (no Ctrl/middle), cosi' la SPA navigation passa per\n `router.navigateByUrl` (che con `withHashLocation()` aggiunge\n comunque l'hash internamente all'URL) e preserva pending changes\n /query params. Per Ctrl+Click / middle-click il browser segue\n l'href naturalmente \u2192 apre nuova tab con path puro (poi il\n server fa SPA fallback a index.html, e Angular legge la route\n dalla path). -->\n <a class=\"p-menubar-item-link\" [href]=\"getMenuItemHref(item)\" (click)=\"onMenuItemClick(item, $event)\"\n (contextmenu)=\"onMenuContext($event, item, auth, menuCtx)\"\n [attr.draggable]=\"canDragMenu(auth, item) ? true : null\" (dragstart)=\"onMenuDragStart($event, item, auth)\"\n (dragover)=\"onMenuDragOver($event, item, auth)\" (drop)=\"onMenuDrop($event, item, auth)\"\n (dragend)=\"onMenuDragEnd()\">\n <span [class]=\"item.icon\"></span>\n <span class=\"ml-2\">{{ item.label | translate }}</span>\n </a>\n } @else {\n <!-- Parent items (folder con submenu, NO route propria): NON sono `<a>`\n ma `<div>` semantici. Lighthouse non flagga `<div>` come uncrawlable\n (l'audit `crawlable-anchors` controlla solo `<a>`). PrimeNG si\n occupa di toggle del submenu via il (click). -->\n <div class=\"p-menubar-item-link\" (click)=\"onMenuItemClick(item, $event); onFocus($event)\"\n (contextmenu)=\"onMenuContext($event, item, auth, menuCtx)\"\n [attr.draggable]=\"canDragMenu(auth, item) ? true : null\" (dragstart)=\"onMenuDragStart($event, item, auth)\"\n (dragover)=\"onMenuDragOver($event, item, auth)\" (drop)=\"onMenuDrop($event, item, auth)\"\n (dragend)=\"onMenuDragEnd()\">\n <span [class]=\"item.icon\"></span>\n <span class=\"ml-2\">{{ item.label | translate }}</span>\n <span class=\"pi pi-fw pi-angle-down ml-2\"></span>\n </div>\n }\n </ng-template>\n\n <ng-template #end>\n @if (auth.authenticated || auth.legacyAuthenticated) {\n <div class=\"wuic-menubar-extra\">\n <span class=\"wuic-license-badge\" [class.wuic-license-badge-pro]=\"getLicenseTier() === 'professional'\"\n [class.wuic-license-badge-dev]=\"getLicenseTier() === 'developer'\"\n [class.wuic-license-badge-trial]=\"getLicenseTier() === 'trial'\" [attr.title]=\"getLicenseTooltip()\"\n role=\"status\" [attr.aria-label]=\"getLicenseTooltip()\">\n <span [class]=\"getLicenseIconClass()\" aria-hidden=\"true\"></span>\n <span class=\"wuic-license-badge-label\">{{ getLicenseBadgeLabel() }}</span>\n </span>\n\n <div class=\"wuic-menubar-user-wrap\" (click)=\"toggleUserLanguageMenu($event)\">\n <img class=\"wuic-menubar-user-flag\" [src]=\"getCurrentUserLanguageFlagSrc()\" [alt]=\"getCurrentUserLanguageId()\"\n (error)=\"onLanguageFlagLoadError($event)\" />\n <div class=\"wuic-menubar-user\">\n @if (auth.authenticated) {\n <span [pTooltip]=\"auth.name || ('user.default' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-menubar-user-name\">{{ auth.name || ('user.default' | translate) }}</span>\n <span class=\"wuic-menubar-user-role\">\n <span [pTooltip]=\"auth.provider || ('auth.provider.google' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-role-badge\">{{ auth.provider || ('auth.provider.google' | translate) }}</span>\n </span>\n } @else {\n <span [pTooltip]=\"auth.legacyName || ('user.default' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-menubar-user-name\">{{ auth.legacyName || ('user.default' | translate) }}</span>\n <span class=\"wuic-menubar-user-role\">\n <span [pTooltip]=\"auth.legacyRole || ('auth.role.na' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-role-badge\" [class.wuic-role-badge-admin]=\"isAdminRole(auth)\">{{ auth.legacyRole ||\n ('auth.role.na' | translate) }}</span>\n </span>\n }\n </div>\n @if (userLanguageSwitchEnabled) {\n <span class=\"pi pi-angle-down wuic-menubar-user-caret\" aria-hidden=\"true\"></span>\n }\n @if (userLanguageSwitchEnabled && userLanguageMenuVisible) {\n <div class=\"wuic-language-menu\" (click)=\"$event.stopPropagation()\">\n @for (lang of userLanguages; track lang.id) {\n <button type=\"button\" class=\"wuic-language-item\" [class.is-active]=\"isCurrentUserLanguage(lang.id)\"\n (click)=\"onSelectUserLanguage(lang.id, $event)\">\n <img class=\"wuic-language-item-flag\" [src]=\"getLanguageFlagSrc(lang.id)\" [alt]=\"lang.id\"\n (error)=\"onLanguageFlagLoadError($event)\" />\n <span>{{ lang.lingua || lang.id }}</span>\n <small>{{ lang.id }}</small>\n </button>\n }\n </div>\n }\n </div>\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-menubar-logout\" (click)=\"logout()\" [disabled]=\"auth.loading\">\n {{ 'logout' | translate }}\n </button>\n </div>\n }\n </ng-template>\n </p-menubar>\n <p-contextMenu #menuCtx [model]=\"contextItems\" appendTo=\"body\" [autoZIndex]=\"true\"\n [baseZIndex]=\"13000\"></p-contextMenu>\n <p-dialog [(visible)]=\"moveDialogVisible\" [modal]=\"true\" [draggable]=\"false\" [resizable]=\"false\" [closable]=\"true\"\n [style]=\"{ width: '28rem' }\" [header]=\"'menu.move.title' | translate\" (onHide)=\"cancelPendingMove()\"\n [autoZIndex]=\"true\" [baseZIndex]=\"14000\">\n <p>{{ 'menu.move.drop_target' | translate }}: <strong>{{ pendingMove?.targetLabel || pendingMove?.targetId\n }}</strong></p>\n <p>{{ 'menu.move.choose_position' | translate }}</p>\n <div class=\"wuic-menu-move-actions\">\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"executePendingMove('before')\"\n [disabled]=\"!hasMenuAdminMethod('reorderMenu')\">{{ 'menu.move.before' | translate }}</button>\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"executePendingMove('after')\"\n [disabled]=\"!hasMenuAdminMethod('reorderMenu')\">{{ 'menu.move.after' | translate }}</button>\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"executePendingMove('inside')\"\n [disabled]=\"!hasMenuAdminMethod('nestMenu')\">{{ 'menu.move.inside' | translate }}</button>\n </div>\n </p-dialog>\n }\n @if (auth.initialized && showAuthBar(auth)) {\n <div class=\"wuic-auth-stage\" [class.wuic-auth-stage-login]=\"requiresAuthentication(auth)\">\n @if (!(translationsLoaded$ | async)) {\n <!-- Non mostrare il form login finche' le traduzioni non sono caricate: l'utente\n vedrebbe i placeholder grezzi `auth.username` / `auth.password` invece dei\n label tradotti. Meglio uno spinner finche' la tabella traduzioni arriva\n (localStorage o backend). Tipicamente <50ms se cache, ~200-800ms se\n cold-fetch dal backend. -->\n <div class=\"wuic-auth-bar wuic-auth-bar-loading\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-auth-loading\">\n <i class=\"pi pi-spinner pi-spin\"></i>\n <span>Loading\u2026</span>\n </div>\n </div>\n } @else {\n <div class=\"wuic-auth-bar\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-auth-status\">\n @if (auth.loading) {\n <span>{{ 'auth.status.loading' | translate }}</span>\n } @else if (auth.authenticated) {\n <span>{{ 'auth.status.active' | translate }}: <strong>{{ auth.name || ('user.default' | translate) }}</strong>\n ({{ auth.provider || ('auth.provider.google' | translate) }})</span>\n } @else if (auth.enabled) {\n <span>{{ 'auth.status.not_authenticated' | translate }} ({{ auth.provider || ('auth.provider.google' |\n translate)\n }})</span>\n } @else if (auth.legacyAuthenticated) {\n <span>{{ 'auth.status.active' | translate }}: <strong>{{ auth.legacyName || ('user.default' | translate)\n }}</strong> ({{ 'auth.provider.credentials' | translate }})</span>\n } @else {\n <span>{{ 'auth.status.login_required' | translate }} ({{ 'auth.provider.credentials' | translate }})</span>\n }\n </div>\n\n <div class=\"wuic-auth-form\" [class.wuic-auth-form-login]=\"requiresAuthentication(auth)\">\n @if (auth.enabled) {\n <label for=\"wuicAuthReturnUrl\">{{ 'auth.return_url' | translate }}</label>\n <input id=\"wuicAuthReturnUrl\" type=\"text\" [(ngModel)]=\"authReturnUrl\" (ngModelChange)=\"onAuthReturnUrlChanged()\"\n placeholder=\"/\" />\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"loginWithGoogle()\"\n [disabled]=\"auth.authenticated || auth.loading\">\n {{ 'auth.login_google' | translate }}\n </button>\n\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"logout()\" [disabled]=\"!auth.authenticated || auth.loading\">\n {{ 'logout' | translate }}\n </button>\n } @else if (!auth.legacyAuthenticated) {\n\n @if (authView === 'login') {\n <form (ngSubmit)=\"loginLegacy()\" novalidate>\n <label for=\"wuicAuthUser\">{{ 'auth.username' | translate }}</label>\n <input id=\"wuicAuthUser\" type=\"text\" [(ngModel)]=\"loginUsername\" [placeholder]=\"'auth.username' | translate\"\n autocomplete=\"username\" name=\"loginUsername\" />\n\n <label for=\"wuicAuthPwd\">{{ 'auth.password' | translate }}</label>\n <input id=\"wuicAuthPwd\" type=\"password\" [(ngModel)]=\"loginPassword\"\n [placeholder]=\"'auth.password' | translate\" autocomplete=\"current-password\" name=\"loginPassword\" />\n\n @if (captchaEnabled) {\n <div id=\"wuic-captcha-container\" class=\"wuic-captcha\"></div>\n }\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\"\n [disabled]=\"!loginUsername || !loginPassword || auth.loading || (captchaEnabled && !captchaToken)\">\n {{ 'auth.login' | translate }}\n </button>\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('forgotPassword')\">{{\n 'auth.link.forgot_password' | translate }}</button>\n @if (registrationEnabled) {\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('register')\">{{ 'auth.link.register' |\n translate }}</button>\n }\n </div>\n </form>\n } @else if (authView === 'register') {\n <form (ngSubmit)=\"submitRegistration()\" novalidate>\n <label for=\"wuic-auth-register-username\">{{ 'auth.username' | translate }}</label>\n <input id=\"wuic-auth-register-username\" type=\"text\" [(ngModel)]=\"registerUsername\"\n [placeholder]=\"'auth.username' | translate\" autocomplete=\"username\" name=\"registerUsername\" />\n\n <label for=\"wuic-auth-register-email\">{{ 'auth.email' | translate }}</label>\n <input id=\"wuic-auth-register-email\" type=\"email\" [(ngModel)]=\"registerEmail\"\n [placeholder]=\"'auth.email' | translate\" autocomplete=\"email\" name=\"registerEmail\" />\n\n <label for=\"wuic-auth-register-password\">{{ 'auth.password' | translate }}</label>\n <input id=\"wuic-auth-register-password\" type=\"password\" [(ngModel)]=\"registerPassword\"\n [placeholder]=\"'auth.password' | translate\" autocomplete=\"new-password\" name=\"registerPassword\" />\n\n @if (captchaEnabled) {\n <div id=\"wuic-captcha-container\" class=\"wuic-captcha\"></div>\n }\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\"\n [disabled]=\"!registerUsername || !registerEmail || !registerPassword || (captchaEnabled && !captchaToken)\">\n {{ 'auth.link.register' | translate }}\n </button>\n\n @if (registerMessage) {\n <div class=\"wuic-auth-success\">{{ registerMessage }}</div>\n }\n @if (registerError) {\n <div class=\"wuic-auth-error\">{{ registerError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login'\n | translate }}</button>\n </div>\n </form>\n } @else if (authView === 'forgotPassword') {\n <label for=\"wuic-auth-forgot-email\">{{ 'auth.email' | translate }}</label>\n <input id=\"wuic-auth-forgot-email\" type=\"email\" [(ngModel)]=\"forgotEmail\"\n [placeholder]=\"'auth.forgot.email_placeholder' | translate\" autocomplete=\"email\"\n (keyup.enter)=\"submitForgotPassword()\" />\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"submitForgotPassword()\"\n [disabled]=\"!forgotEmail\">\n {{ 'auth.forgot.send_reset_link' | translate }}\n </button>\n\n @if (forgotMessage) {\n <div class=\"wuic-auth-success\">{{ forgotMessage }}</div>\n }\n @if (forgotError) {\n <div class=\"wuic-auth-error\">{{ forgotError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login' |\n translate }}</button>\n </div>\n } @else if (authView === 'resetPassword') {\n <form (ngSubmit)=\"submitResetPassword()\" novalidate>\n <label for=\"wuic-auth-reset-new-password\">{{ 'auth.reset.new_password' | translate }}</label>\n <input id=\"wuic-auth-reset-new-password\" type=\"password\" [(ngModel)]=\"resetNewPassword\"\n [placeholder]=\"'auth.reset.new_password' | translate\" autocomplete=\"new-password\" name=\"resetNewPassword\" />\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\" [disabled]=\"!resetNewPassword\">\n {{ 'auth.reset.submit' | translate }}\n </button>\n\n @if (resetMessage) {\n <div class=\"wuic-auth-success\">{{ resetMessage }}</div>\n }\n @if (resetError) {\n <div class=\"wuic-auth-error\">{{ resetError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login'\n | translate }}</button>\n </div>\n </form>\n }\n\n }\n\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"refreshAuthSession()\" [disabled]=\"auth.loading\">\n {{ 'auth.refresh' | translate }}\n </button>\n </div>\n\n @if (auth.error) {\n <div class=\"wuic-auth-error\">{{ auth.error }}</div>\n }\n </div>\n }\n </div>\n }\n</nav>\n}\n\n<!-- <p-megaMenu *ngIf=\"menuType=='megamenu'\" [model]=\"megaItems\">\n</p-megaMenu> -->\n\n<!-- <p-megaMenu *ngIf=\"menuType=='megamenu'\" [model]=\"megaItems2\"></p-megaMenu>\n</p-megaMenu> -->", styles: [".wuic-session-warning{display:flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background:color-mix(in srgb,var(--p-yellow-100, var(--yellow-100, #fef9c3)) 50%,var(--p-surface-card, var(--surface-card, #fff)));border-bottom:2px solid var(--p-yellow-500, var(--yellow-500, #eab308));color:var(--p-yellow-800, var(--yellow-800, #854d0e));font-size:.85rem;font-weight:500;z-index:1000}.wuic-session-warning .pi{font-size:1rem}.wuic-session-warning .wuic-auth-btn{margin-left:auto;padding:.25rem .6rem;font-size:.8rem}.wuic-auth-stage{display:block}.wuic-auth-bar-loading{display:flex;align-items:center;justify-content:center;min-height:48px;padding:.75rem 1rem}.wuic-auth-loading{display:flex;align-items:center;gap:.5rem;color:var(--p-text-color-secondary, var(--text-color-secondary, #64748b));font-size:.9rem}.wuic-auth-loading .pi-spinner{font-size:1.1rem}:host ::ng-deep .p-menubar .p-menubar-item-link[draggable=true]{cursor:grab}:host ::ng-deep .p-menubar .p-menubar-item-link[draggable=true]:active{cursor:grabbing}:host ::ng-deep .p-menubar .p-menubar-item-link:not(.p-disabled):hover{background:var(--p-content-hover-background, var(--surface-hover, #f1f5f9));color:var(--p-primary-color, var(--p-text-color, inherit))}:host-context(.theme-dark) ::ng-deep .p-menubar .p-menubar-item-link:not(.p-disabled):hover{background:color-mix(in srgb,var(--p-content-hover-background, #1f2937) 80%,var(--p-primary-color, #3b82f6) 20%);color:var(--p-primary-color, var(--p-text-color, #f3f4f6))}.wuic-menubar-extra{display:flex;align-items:center;gap:.75rem;min-width:280px;justify-content:flex-end;padding-left:.75rem}.wuic-menubar-user-flag{width:2rem;height:2rem;border-radius:999px;display:block;border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));background:var(--p-content-background, var(--surface-section, #eef3f8));object-fit:cover;flex:0 0 auto}.wuic-menubar-user-wrap{position:relative;display:flex;align-items:center;gap:.55rem;cursor:pointer}.wuic-menubar-user-caret{font-size:.8rem;color:var(--p-text-muted-color, var(--text-color-secondary, #4f6479))}.wuic-menubar-user{display:grid;line-height:1.15;text-align:right;min-width:0}.wuic-language-menu{position:absolute;top:calc(100% + .45rem);right:0;min-width:170px;background:var(--p-surface-card, var(--surface-card, #fff));border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));border-radius:8px;box-shadow:0 10px 28px color-mix(in srgb,var(--p-text-color, #1f2f43) 16%,transparent);z-index:1100;padding:.3rem}.wuic-language-item{width:100%;border:0;background:transparent;display:flex;align-items:center;gap:.8rem;text-align:left;border-radius:6px;padding:.45rem .55rem;cursor:pointer;color:var(--p-text-color, var(--text-color, #1f2f43))}.wuic-language-item-flag{width:1.1rem;height:1.1rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));object-fit:cover;flex:0 0 auto}.wuic-language-item span{flex:1 1 auto}.wuic-language-item small{color:var(--p-text-muted-color, var(--text-color-secondary, #5f748a))}.wuic-language-item:hover{background:var(--p-content-hover-background, var(--surface-hover, #f5f8fb))}.wuic-language-item.is-active{background:color-mix(in srgb,var(--p-primary-color, #3b82f6) 14%,transparent);color:var(--p-primary-color, #315fdd)}:host-context(.theme-dark) .wuic-language-menu{background:var(--p-content-background, var(--surface-card, #111827));border-color:var(--p-content-border-color, var(--surface-border, rgba(255, 255, 255, .2)));box-shadow:0 10px 28px color-mix(in srgb,#000 55%,transparent),0 0 0 1px color-mix(in srgb,var(--p-content-border-color, rgba(255, 255, 255, .2)) 65%,transparent) inset}:host-context(.theme-dark) .wuic-language-item{color:var(--p-text-color, var(--text-color, #f3f4f6))}:host-context(.theme-dark) .wuic-language-item small{color:var(--p-text-muted-color, var(--text-color-secondary, #b7c3d0))}:host-context(.theme-dark) .wuic-language-item:hover{background:color-mix(in srgb,var(--p-content-hover-background, #1f2937) 85%,var(--p-primary-color, #3b82f6) 15%)}:host-context(.theme-dark) .wuic-language-item.is-active{background:color-mix(in srgb,var(--p-primary-color, #3b82f6) 30%,transparent);color:var(--p-primary-contrast-color, #e7f0ff)}.wuic-menubar-user-name{font-weight:600;color:var(--p-text-color, var(--text-color, #1f2f43));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.wuic-menubar-user-role{font-size:.75rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}.wuic-role-badge{display:inline-flex;align-items:center;max-width:100%;padding:.15rem .5rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d4deea));background:var(--p-content-background, var(--surface-section, #f3f7fb));color:var(--p-text-muted-color, var(--text-color-secondary, #4a6077));font-size:.72rem;font-weight:600}.wuic-role-badge-admin{border-color:color-mix(in srgb,var(--p-yellow-500, var(--yellow-500, #f59e0b)) 55%,var(--p-content-border-color, var(--surface-border, #d4deea)));background:color-mix(in srgb,var(--p-yellow-100, var(--yellow-100, #fff6df)) 30%,var(--p-surface-card, var(--surface-card, #fff)));color:color-mix(in srgb,var(--p-yellow-700, var(--yellow-700, #9a5a00)) 80%,var(--p-text-color, var(--text-color, #233242)))}.wuic-menubar-logout{white-space:nowrap;padding-inline:.8rem}.wuic-license-badge{display:inline-flex;align-items:center;gap:.35rem;padding:.25rem .6rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d4deea));background:var(--p-content-background, var(--surface-section, #f3f7fb));color:var(--p-text-muted-color, var(--text-color-secondary, #4a6077));font-size:.72rem;font-weight:700;letter-spacing:.02em;cursor:default;white-space:nowrap;-webkit-user-select:none;user-select:none}.wuic-license-badge .pi{font-size:.85rem}.wuic-license-badge-label{line-height:1}.wuic-license-badge-pro{border-color:color-mix(in srgb,var(--p-emerald-500, #10b981) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-emerald-100, #d1fae5) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-emerald-700, #047857) 80%,var(--p-text-color, #233242))}.wuic-license-badge-dev{border-color:color-mix(in srgb,var(--p-blue-500, #3b82f6) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-blue-100, #dbeafe) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-blue-700, #1d4ed8) 80%,var(--p-text-color, #233242))}.wuic-license-badge-trial{border-color:color-mix(in srgb,var(--p-orange-500, #f97316) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-orange-100, #ffedd5) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-orange-700, #c2410c) 80%,var(--p-text-color, #233242))}.wuic-auth-stage-login,.wuic-auth-stage-login *{color-scheme:inherit}.wuic-auth-stage-login{--wuic-surface-ground: var(--p-surface-ground, var(--surface-ground, var(--surface-b, #f7f8fa)));--wuic-surface-card: var(--p-surface-card, var(--surface-card, var(--surface-a, #ffffff)));--wuic-surface-section: var(--p-content-background, var(--surface-section, var(--surface-c, #ffffff)));--wuic-surface-hover: var(--p-content-hover-background, var(--surface-hover, var(--surface-hover-background, #f3f4f6)));--wuic-surface-border: var(--p-content-border-color, var(--surface-border, var(--surface-d, #d7dce3)));--wuic-text: var(--p-text-color, var(--text-color, #1f2937));--wuic-text-muted: var(--p-text-muted-color, var(--text-color-secondary, #6b7280));--wuic-primary: var(--p-primary-color, var(--primary-color, #3b82f6));--wuic-primary-text: var(--p-primary-contrast-color, var(--primary-color-text, #ffffff));--wuic-danger-100: var(--p-red-100, var(--red-100, #fee2e2));--wuic-danger-500: var(--p-red-500, var(--red-500, #ef4444));--wuic-danger-700: var(--p-red-700, var(--red-700, #b91c1c));min-height:calc(100vh - 2rem);display:grid;place-items:center;padding:1rem;color:var(--wuic-text);background-color:var(--wuic-surface-ground)!important;background:radial-gradient(circle at 15% 20%,color-mix(in srgb,var(--wuic-primary) 12%,transparent),transparent 45%),radial-gradient(circle at 85% 15%,color-mix(in srgb,var(--wuic-primary) 8%,transparent),transparent 40%),linear-gradient(180deg,var(--wuic-surface-ground) 0%,var(--wuic-surface-ground) 100%)!important}:host-context(.theme-dark) .wuic-auth-stage-login{--wuic-surface-ground: var(--p-surface-900, var(--p-content-background, var(--surface-b, #0f172a)));--wuic-surface-card: var(--p-content-background, var(--p-surface-800, var(--surface-a, #111827)));--wuic-surface-section: var(--p-content-background, var(--p-surface-800, var(--surface-c, #1f2937)));--wuic-surface-hover: var(--p-content-hover-background, var(--p-surface-700, var(--surface-hover-background, #374151)));--wuic-surface-border: var(--p-content-border-color, var(--surface-d, rgba(255, 255, 255, .28)));--wuic-text: var(--p-content-color, var(--p-text-color, var(--text-color, #f3f4f6)));--wuic-text-muted: var(--p-text-muted-color, var(--text-color-secondary, #d1d5db))}:host-context(.theme-dark) .wuic-auth-bar,:host-context(.theme-dark) .wuic-auth-bar-login{background:var(--wuic-surface-card)!important;color:var(--wuic-text)!important;border-color:var(--wuic-surface-border)!important}:host-context(.theme-dark) .wuic-auth-form label,:host-context(.theme-dark) .wuic-auth-status,:host-context(.theme-dark) .wuic-auth-bar span,:host-context(.theme-dark) .wuic-auth-bar strong{color:var(--wuic-text)!important}:host-context(.theme-dark) .wuic-auth-form input{background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-color:var(--wuic-surface-border)!important}:host-context(.theme-dark) .wuic-auth-form input::placeholder{color:var(--wuic-text-muted)!important}:host-context(.theme-dark) .wuic-auth-btn{background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-color:color-mix(in srgb,var(--wuic-surface-border) 75%,white 25%)!important}:host-context(.theme-dark) .wuic-auth-btn-primary{background:var(--wuic-primary)!important;border-color:var(--wuic-primary)!important;color:var(--wuic-primary-text)!important}.wuic-auth-bar{display:grid;gap:.5rem;padding:.6rem .75rem;border:1px solid var(--wuic-surface-border);border-top:0;background:var(--wuic-surface-card)!important;color:var(--wuic-text)!important}.wuic-auth-bar-login{width:min(420px,92vw);gap:1rem;padding:1.15rem 1.2rem;border-radius:14px;border:1px solid var(--wuic-surface-border)!important;background:var(--wuic-surface-card)!important;box-shadow:0 14px 40px color-mix(in srgb,var(--wuic-text) 12%,transparent),0 0 0 1px color-mix(in srgb,var(--wuic-surface-border) 65%,transparent) inset}.wuic-auth-status{font-size:.9rem;color:var(--wuic-text)!important;margin-bottom:.1rem;line-height:1.35}.wuic-auth-form{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.wuic-auth-form-login{flex-direction:column;align-items:stretch;gap:.75rem}.wuic-auth-form-login form{display:grid;gap:.5rem;margin:0}.wuic-auth-form label{font-size:.85rem;color:var(--wuic-text)!important}.wuic-auth-form-login label{font-weight:600;margin-top:0}.wuic-auth-form input{min-width:220px;flex:1 1 320px;border:1px solid var(--wuic-surface-border);border-radius:6px;padding:.45rem .6rem;background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;box-shadow:0 0 0 1px color-mix(in srgb,var(--wuic-surface-border) 35%,transparent) inset}.wuic-auth-form input::placeholder{color:var(--wuic-text-muted);opacity:1}.wuic-auth-form input:focus{outline:none;border-color:var(--wuic-primary);box-shadow:0 0 0 1px color-mix(in srgb,var(--wuic-primary) 55%,transparent) inset,0 0 0 .15rem color-mix(in srgb,var(--wuic-primary) 22%,transparent)}.wuic-auth-form-login input{min-width:0;width:100%;flex:initial}.wuic-auth-btn{border:1px solid var(--wuic-surface-border);background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-radius:6px;padding:.45rem .75rem;cursor:pointer;transition:background-color .12s ease,border-color .12s ease,color .12s ease,box-shadow .12s ease}.wuic-auth-form-login .wuic-auth-btn{width:100%;justify-content:center}.wuic-auth-form-login>.wuic-auth-btn:not(.wuic-auth-btn-primary){margin-top:.2rem}.wuic-auth-btn:disabled{opacity:.5;cursor:default}.wuic-auth-btn:not(:disabled):hover{background:var(--wuic-surface-hover)!important;border-color:color-mix(in srgb,var(--wuic-primary) 35%,var(--wuic-surface-border))}.wuic-auth-btn:not(:disabled):focus-visible{outline:none;box-shadow:0 0 0 .15rem color-mix(in srgb,var(--wuic-primary) 20%,transparent)}.wuic-auth-btn-primary{background:var(--wuic-primary)!important;border-color:var(--wuic-primary)!important;color:var(--wuic-primary-text)!important}.wuic-auth-btn-primary:not(:disabled):hover{background:color-mix(in srgb,var(--wuic-primary) 88%,black 12%)!important;border-color:color-mix(in srgb,var(--wuic-primary) 88%,black 12%)!important;color:var(--wuic-primary-text)!important}.wuic-captcha{margin:.25rem 0}.wuic-auth-error{color:var(--wuic-danger-700);font-size:.85rem;background:color-mix(in srgb,var(--wuic-danger-100) 22%,var(--wuic-surface-card));border:1px solid color-mix(in srgb,var(--wuic-danger-500) 35%,var(--wuic-surface-border));border-radius:8px;padding:.5rem .65rem}.wuic-auth-success{color:var(--p-green-700, var(--green-700, #15803d));font-size:.85rem;background:color-mix(in srgb,var(--p-green-100, var(--green-100, #dcfce7)) 22%,var(--wuic-surface-card));border:1px solid color-mix(in srgb,var(--p-green-500, var(--green-500, #22c55e)) 35%,var(--wuic-surface-border));border-radius:8px;padding:.5rem .65rem}.wuic-auth-links{display:flex;justify-content:center;gap:1.25rem;margin-top:.1rem}.wuic-auth-link{appearance:none;background:transparent;border:none;padding:0;margin:0;font:inherit;font-size:.82rem;color:color-mix(in srgb,var(--wuic-primary) 60%,#0f172a 40%);cursor:pointer;text-decoration:underline;text-underline-offset:2px}.wuic-auth-link:hover{color:color-mix(in srgb,var(--wuic-primary) 40%,#0f172a 60%)}@media(max-width:768px){.wuic-menubar-extra{min-width:0;gap:.5rem}.wuic-menubar-user-name,.wuic-menubar-user-role{max-width:130px}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list,:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu{overflow-x:hidden!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list{max-height:calc(100vh - 13rem);overflow-y:auto!important;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu{width:100%!important;margin-left:0!important;max-height:none;overflow-y:visible!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu>.p-menubar-item{width:100%!important;float:none!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-item-link{white-space:normal;word-break:break-word}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu{display:grid;grid-template-columns:minmax(0,1fr);gap:0}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu>.p-menubar-item>.p-menubar-item-link{padding-top:.5rem;padding-bottom:.5rem}}@media(max-width:768px)and (min-width:560px){:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:.25rem}}:host ::ng-deep .p-contextmenu{z-index:13000!important}:host ::ng-deep .p-menubar-item-link[draggable=true]{cursor:grab}:host ::ng-deep .p-menubar-item-link[draggable=true]:active{cursor:grabbing}.wuic-menu-move-actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.75rem}\n"], dependencies: [{ kind: "ngmodule", type: MenubarModule }, { kind: "component", type: i5$1.Menubar, selector: "p-menubar", inputs: ["model", "styleClass", "autoZIndex", "baseZIndex", "autoDisplay", "autoHide", "breakpoint", "autoHideDelay", "id", "ariaLabel", "ariaLabelledBy"], outputs: ["onFocus", "onBlur"] }, { kind: "ngmodule", type: MegaMenuModule }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i14.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: DataSourceComponent, selector: "wuic-data-source", inputs: ["route", "routeFromRouting", "hardcodedRoute", "autoload", "loading", "changeTracking", "parentRecord", "parentMetaInfo", "parentDatasource", "useComboEndpoint", "comboFormulaLookup", "comboMcId", "comboField", "comboExtraFields", "comboCurrentRecord", "componentRef"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$4.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }] });
|
|
45244
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MetaMenuComponent, isStandalone: true, selector: "wuic-meta-menu", host: { listeners: { "document:click": "onDocumentClick()" } }, viewQueries: [{ propertyName: "menu", first: true, predicate: ["menubar"], descendants: true }, { propertyName: "menuMetadataDs", first: true, predicate: ["menuMetadataDs"], descendants: true }], ngImport: i0, template: "@if (authState$ | async; as auth) {\n<nav class=\"wuic-meta-menu-landmark\" aria-label=\"Menu principale\">\n @if (auth.sessionExpiring) {\n <div class=\"wuic-session-warning\">\n <span class=\"pi pi-exclamation-triangle\"></span>\n {{ 'auth.session.expiring_in' | translate }} <strong>{{ auth.sessionExpiresInSeconds }}</strong> {{ 'seconds' |\n translate }}.\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"refreshAuthSession()\">{{ 'auth.session.extend' | translate\n }}</button>\n </div>\n }\n @if (auth.initialized && !requiresAuthentication(auth)) {\n <div style=\"display:none\">\n <wuic-data-source #menuMetadataDs [hardcodedRoute]=\"metaMenuRoute\" [autoload]=\"false\"></wuic-data-source>\n </div>\n <p-menubar #menubar [model]=\"items\" [autoHide]=\"false\">\n <ng-template #item let-item>\n @if (item.route) {\n <!-- [href] con path assoluto (NO `#/` hash) cosi' Lighthouse SEO\n `crawlable-anchors` considera il link crawlable: il path\n `/<route>` e' un URL valid + condivisibile + apribile in nuova\n tab via Ctrl+Click. Il click handler `onMenuItemClick` chiama\n `event.preventDefault()` quando il button click e' \"primary\"\n (no Ctrl/middle), cosi' la SPA navigation passa per\n `router.navigateByUrl` (che con `withHashLocation()` aggiunge\n comunque l'hash internamente all'URL) e preserva pending changes\n /query params. Per Ctrl+Click / middle-click il browser segue\n l'href naturalmente \u2192 apre nuova tab con path puro (poi il\n server fa SPA fallback a index.html, e Angular legge la route\n dalla path). -->\n <a class=\"p-menubar-item-link\" [href]=\"getMenuItemHref(item)\" (click)=\"onMenuItemClick(item, $event)\"\n (contextmenu)=\"onMenuContext($event, item, auth, menuCtx)\"\n [attr.draggable]=\"canDragMenu(auth, item) ? true : null\" (dragstart)=\"onMenuDragStart($event, item, auth)\"\n (dragover)=\"onMenuDragOver($event, item, auth)\" (drop)=\"onMenuDrop($event, item, auth)\"\n (dragend)=\"onMenuDragEnd()\">\n <span [class]=\"item.icon\"></span>\n <span class=\"ml-2\">{{ item.label | translate }}</span>\n </a>\n } @else {\n <!-- Parent items (folder con submenu, NO route propria): NON sono `<a>`\n ma `<div>` semantici. Lighthouse non flagga `<div>` come uncrawlable\n (l'audit `crawlable-anchors` controlla solo `<a>`). PrimeNG si\n occupa di toggle del submenu via il (click). -->\n <div class=\"p-menubar-item-link\" (click)=\"onMenuItemClick(item, $event); onFocus($event)\"\n (contextmenu)=\"onMenuContext($event, item, auth, menuCtx)\"\n [attr.draggable]=\"canDragMenu(auth, item) ? true : null\" (dragstart)=\"onMenuDragStart($event, item, auth)\"\n (dragover)=\"onMenuDragOver($event, item, auth)\" (drop)=\"onMenuDrop($event, item, auth)\"\n (dragend)=\"onMenuDragEnd()\">\n <span [class]=\"item.icon\"></span>\n <span class=\"ml-2\">{{ item.label | translate }}</span>\n <span class=\"pi pi-fw pi-angle-down ml-2\"></span>\n </div>\n }\n </ng-template>\n\n <ng-template #end>\n @if (auth.authenticated || auth.legacyAuthenticated) {\n <div class=\"wuic-menubar-extra\">\n <span class=\"wuic-license-badge\" [class.wuic-license-badge-pro]=\"getLicenseTier() === 'professional'\"\n [class.wuic-license-badge-dev]=\"getLicenseTier() === 'developer'\"\n [class.wuic-license-badge-trial]=\"getLicenseTier() === 'trial'\" [attr.title]=\"getLicenseTooltip()\"\n role=\"status\" [attr.aria-label]=\"getLicenseTooltip()\">\n <span [class]=\"getLicenseIconClass()\" aria-hidden=\"true\"></span>\n <span class=\"wuic-license-badge-label\">{{ getLicenseBadgeLabel() }}</span>\n </span>\n\n <div class=\"wuic-menubar-user-wrap\" (click)=\"toggleUserLanguageMenu($event)\">\n <img class=\"wuic-menubar-user-flag\" [src]=\"getCurrentUserLanguageFlagSrc()\" [alt]=\"getCurrentUserLanguageId()\"\n (error)=\"onLanguageFlagLoadError($event)\" />\n <div class=\"wuic-menubar-user\">\n @if (auth.authenticated) {\n <span [pTooltip]=\"auth.name || ('user.default' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-menubar-user-name\">{{ auth.name || ('user.default' | translate) }}</span>\n <span class=\"wuic-menubar-user-role\">\n <span [pTooltip]=\"auth.provider || ('auth.provider.google' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-role-badge\">{{ auth.provider || ('auth.provider.google' | translate) }}</span>\n </span>\n } @else {\n <span [pTooltip]=\"auth.legacyName || ('user.default' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-menubar-user-name\">{{ auth.legacyName || ('user.default' | translate) }}</span>\n <span class=\"wuic-menubar-user-role\">\n <span [pTooltip]=\"auth.legacyRole || ('auth.role.na' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-role-badge\" [class.wuic-role-badge-admin]=\"isAdminRole(auth)\">{{ auth.legacyRole ||\n ('auth.role.na' | translate) }}</span>\n </span>\n }\n </div>\n @if (userLanguageSwitchEnabled) {\n <span class=\"pi pi-angle-down wuic-menubar-user-caret\" aria-hidden=\"true\"></span>\n }\n @if (userLanguageSwitchEnabled && userLanguageMenuVisible) {\n <div class=\"wuic-language-menu\" (click)=\"$event.stopPropagation()\">\n @for (lang of userLanguages; track lang.id) {\n <button type=\"button\" class=\"wuic-language-item\" [class.is-active]=\"isCurrentUserLanguage(lang.id)\"\n (click)=\"onSelectUserLanguage(lang.id, $event)\">\n <img class=\"wuic-language-item-flag\" [src]=\"getLanguageFlagSrc(lang.id)\" [alt]=\"lang.id\"\n (error)=\"onLanguageFlagLoadError($event)\" />\n <span>{{ lang.lingua || lang.id }}</span>\n <small>{{ lang.id }}</small>\n </button>\n }\n </div>\n }\n </div>\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-menubar-logout\" (click)=\"logout()\" [disabled]=\"auth.loading\">\n {{ 'logout' | translate }}\n </button>\n </div>\n }\n </ng-template>\n </p-menubar>\n <p-contextMenu #menuCtx [model]=\"contextItems\" appendTo=\"body\" [autoZIndex]=\"true\"\n [baseZIndex]=\"13000\"></p-contextMenu>\n <p-dialog [(visible)]=\"moveDialogVisible\" [modal]=\"true\" [draggable]=\"false\" [resizable]=\"false\" [closable]=\"true\"\n [style]=\"{ width: '28rem' }\" [header]=\"'menu.move.title' | translate\" (onHide)=\"cancelPendingMove()\"\n [autoZIndex]=\"true\" [baseZIndex]=\"14000\">\n <p>{{ 'menu.move.drop_target' | translate }}: <strong>{{ pendingMove?.targetLabel || pendingMove?.targetId\n }}</strong></p>\n <p>{{ 'menu.move.choose_position' | translate }}</p>\n <div class=\"wuic-menu-move-actions\">\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"executePendingMove('before')\"\n [disabled]=\"!hasMenuAdminMethod('reorderMenu')\">{{ 'menu.move.before' | translate }}</button>\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"executePendingMove('after')\"\n [disabled]=\"!hasMenuAdminMethod('reorderMenu')\">{{ 'menu.move.after' | translate }}</button>\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"executePendingMove('inside')\"\n [disabled]=\"!hasMenuAdminMethod('nestMenu')\">{{ 'menu.move.inside' | translate }}</button>\n </div>\n </p-dialog>\n }\n @if (auth.initialized && showAuthBar(auth)) {\n <div class=\"wuic-auth-stage\" [class.wuic-auth-stage-login]=\"requiresAuthentication(auth)\">\n @if (!(translationsLoaded$ | async)) {\n <!-- Non mostrare il form login finche' le traduzioni non sono caricate: l'utente\n vedrebbe i placeholder grezzi `auth.username` / `auth.password` invece dei\n label tradotti. Meglio uno spinner finche' la tabella traduzioni arriva\n (localStorage o backend). Tipicamente <50ms se cache, ~200-800ms se\n cold-fetch dal backend.\n Eccezione: se il circuit breaker del TranslationManager si e' aperto\n (5 fallimenti consecutivi \u2192 BE offline persistente), lo spinner\n resterebbe infinito. Mostriamo invece un banner con bottone Riprova\n cosi' l'utente puo' riarmare manualmente quando il BE torna su. -->\n @if (backendCircuitOpen$ | async) {\n <div class=\"wuic-auth-bar wuic-auth-bar-loading wuic-be-offline-banner\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-be-offline-content\">\n <i class=\"pi pi-exclamation-triangle wuic-be-offline-icon\"></i>\n <div class=\"wuic-be-offline-text\">\n <strong>Backend non raggiungibile</strong>\n <span>Impossibile caricare le traduzioni dopo 5 tentativi. Verifica che il server WuicCore sia attivo.</span>\n </div>\n <button type=\"button\" class=\"wuic-be-offline-retry\" (click)=\"retryBackend()\" aria-label=\"Riprova connessione al backend\">\n <i class=\"pi pi-refresh\"></i>\n <span>Riprova</span>\n </button>\n </div>\n </div>\n } @else {\n <div class=\"wuic-auth-bar wuic-auth-bar-loading\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-auth-loading\">\n <i class=\"pi pi-spinner pi-spin\"></i>\n <span>Loading\u2026</span>\n </div>\n </div>\n }\n } @else {\n <div class=\"wuic-auth-bar\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-auth-status\">\n @if (auth.loading) {\n <span>{{ 'auth.status.loading' | translate }}</span>\n } @else if (auth.authenticated) {\n <span>{{ 'auth.status.active' | translate }}: <strong>{{ auth.name || ('user.default' | translate) }}</strong>\n ({{ auth.provider || ('auth.provider.google' | translate) }})</span>\n } @else if (auth.enabled) {\n <span>{{ 'auth.status.not_authenticated' | translate }} ({{ auth.provider || ('auth.provider.google' |\n translate)\n }})</span>\n } @else if (auth.legacyAuthenticated) {\n <span>{{ 'auth.status.active' | translate }}: <strong>{{ auth.legacyName || ('user.default' | translate)\n }}</strong> ({{ 'auth.provider.credentials' | translate }})</span>\n } @else {\n <span>{{ 'auth.status.login_required' | translate }} ({{ 'auth.provider.credentials' | translate }})</span>\n }\n </div>\n\n <div class=\"wuic-auth-form\" [class.wuic-auth-form-login]=\"requiresAuthentication(auth)\">\n @if (auth.enabled) {\n <label for=\"wuicAuthReturnUrl\">{{ 'auth.return_url' | translate }}</label>\n <input id=\"wuicAuthReturnUrl\" type=\"text\" [(ngModel)]=\"authReturnUrl\" (ngModelChange)=\"onAuthReturnUrlChanged()\"\n placeholder=\"/\" />\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"loginWithGoogle()\"\n [disabled]=\"auth.authenticated || auth.loading\">\n {{ 'auth.login_google' | translate }}\n </button>\n\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"logout()\" [disabled]=\"!auth.authenticated || auth.loading\">\n {{ 'logout' | translate }}\n </button>\n } @else if (!auth.legacyAuthenticated) {\n\n @if (authView === 'login') {\n <form (ngSubmit)=\"loginLegacy()\" novalidate>\n <label for=\"wuicAuthUser\">{{ 'auth.username' | translate }}</label>\n <input id=\"wuicAuthUser\" type=\"text\" [(ngModel)]=\"loginUsername\" [placeholder]=\"'auth.username' | translate\"\n autocomplete=\"username\" name=\"loginUsername\" />\n\n <label for=\"wuicAuthPwd\">{{ 'auth.password' | translate }}</label>\n <input id=\"wuicAuthPwd\" type=\"password\" [(ngModel)]=\"loginPassword\"\n [placeholder]=\"'auth.password' | translate\" autocomplete=\"current-password\" name=\"loginPassword\" />\n\n @if (captchaEnabled) {\n <div id=\"wuic-captcha-container\" class=\"wuic-captcha\"></div>\n }\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\"\n [disabled]=\"!loginUsername || !loginPassword || auth.loading || (captchaEnabled && !captchaToken)\">\n {{ 'auth.login' | translate }}\n </button>\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('forgotPassword')\">{{\n 'auth.link.forgot_password' | translate }}</button>\n @if (registrationEnabled) {\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('register')\">{{ 'auth.link.register' |\n translate }}</button>\n }\n </div>\n </form>\n } @else if (authView === 'register') {\n <form (ngSubmit)=\"submitRegistration()\" novalidate>\n <label for=\"wuic-auth-register-username\">{{ 'auth.username' | translate }}</label>\n <input id=\"wuic-auth-register-username\" type=\"text\" [(ngModel)]=\"registerUsername\"\n [placeholder]=\"'auth.username' | translate\" autocomplete=\"username\" name=\"registerUsername\" />\n\n <label for=\"wuic-auth-register-email\">{{ 'auth.email' | translate }}</label>\n <input id=\"wuic-auth-register-email\" type=\"email\" [(ngModel)]=\"registerEmail\"\n [placeholder]=\"'auth.email' | translate\" autocomplete=\"email\" name=\"registerEmail\" />\n\n <label for=\"wuic-auth-register-password\">{{ 'auth.password' | translate }}</label>\n <input id=\"wuic-auth-register-password\" type=\"password\" [(ngModel)]=\"registerPassword\"\n [placeholder]=\"'auth.password' | translate\" autocomplete=\"new-password\" name=\"registerPassword\" />\n\n @if (captchaEnabled) {\n <div id=\"wuic-captcha-container\" class=\"wuic-captcha\"></div>\n }\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\"\n [disabled]=\"!registerUsername || !registerEmail || !registerPassword || (captchaEnabled && !captchaToken)\">\n {{ 'auth.link.register' | translate }}\n </button>\n\n @if (registerMessage) {\n <div class=\"wuic-auth-success\">{{ registerMessage }}</div>\n }\n @if (registerError) {\n <div class=\"wuic-auth-error\">{{ registerError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login'\n | translate }}</button>\n </div>\n </form>\n } @else if (authView === 'forgotPassword') {\n <label for=\"wuic-auth-forgot-email\">{{ 'auth.email' | translate }}</label>\n <input id=\"wuic-auth-forgot-email\" type=\"email\" [(ngModel)]=\"forgotEmail\"\n [placeholder]=\"'auth.forgot.email_placeholder' | translate\" autocomplete=\"email\"\n (keyup.enter)=\"submitForgotPassword()\" />\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"submitForgotPassword()\"\n [disabled]=\"!forgotEmail\">\n {{ 'auth.forgot.send_reset_link' | translate }}\n </button>\n\n @if (forgotMessage) {\n <div class=\"wuic-auth-success\">{{ forgotMessage }}</div>\n }\n @if (forgotError) {\n <div class=\"wuic-auth-error\">{{ forgotError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login' |\n translate }}</button>\n </div>\n } @else if (authView === 'resetPassword') {\n <form (ngSubmit)=\"submitResetPassword()\" novalidate>\n <label for=\"wuic-auth-reset-new-password\">{{ 'auth.reset.new_password' | translate }}</label>\n <input id=\"wuic-auth-reset-new-password\" type=\"password\" [(ngModel)]=\"resetNewPassword\"\n [placeholder]=\"'auth.reset.new_password' | translate\" autocomplete=\"new-password\" name=\"resetNewPassword\" />\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\" [disabled]=\"!resetNewPassword\">\n {{ 'auth.reset.submit' | translate }}\n </button>\n\n @if (resetMessage) {\n <div class=\"wuic-auth-success\">{{ resetMessage }}</div>\n }\n @if (resetError) {\n <div class=\"wuic-auth-error\">{{ resetError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login'\n | translate }}</button>\n </div>\n </form>\n }\n\n }\n\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"refreshAuthSession()\" [disabled]=\"auth.loading\">\n {{ 'auth.refresh' | translate }}\n </button>\n </div>\n\n @if (auth.error) {\n <div class=\"wuic-auth-error\">{{ auth.error }}</div>\n }\n </div>\n }\n </div>\n }\n</nav>\n}\n\n<!-- <p-megaMenu *ngIf=\"menuType=='megamenu'\" [model]=\"megaItems\">\n</p-megaMenu> -->\n\n<!-- <p-megaMenu *ngIf=\"menuType=='megamenu'\" [model]=\"megaItems2\"></p-megaMenu>\n</p-megaMenu> -->", styles: [".wuic-session-warning{display:flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background:color-mix(in srgb,var(--p-yellow-100, var(--yellow-100, #fef9c3)) 50%,var(--p-surface-card, var(--surface-card, #fff)));border-bottom:2px solid var(--p-yellow-500, var(--yellow-500, #eab308));color:var(--p-yellow-800, var(--yellow-800, #854d0e));font-size:.85rem;font-weight:500;z-index:1000}.wuic-session-warning .pi{font-size:1rem}.wuic-session-warning .wuic-auth-btn{margin-left:auto;padding:.25rem .6rem;font-size:.8rem}.wuic-auth-stage{display:block}.wuic-auth-bar-loading{display:flex;align-items:center;justify-content:center;min-height:48px;padding:.75rem 1rem}.wuic-auth-loading{display:flex;align-items:center;gap:.5rem;color:var(--p-text-color-secondary, var(--text-color-secondary, #64748b));font-size:.9rem}.wuic-auth-loading .pi-spinner{font-size:1.1rem}:host ::ng-deep .p-menubar .p-menubar-item-link[draggable=true]{cursor:grab}:host ::ng-deep .p-menubar .p-menubar-item-link[draggable=true]:active{cursor:grabbing}:host ::ng-deep .p-menubar .p-menubar-item-link:not(.p-disabled):hover{background:var(--p-content-hover-background, var(--surface-hover, #f1f5f9));color:var(--p-primary-color, var(--p-text-color, inherit))}:host-context(.theme-dark) ::ng-deep .p-menubar .p-menubar-item-link:not(.p-disabled):hover{background:color-mix(in srgb,var(--p-content-hover-background, #1f2937) 80%,var(--p-primary-color, #3b82f6) 20%);color:var(--p-primary-color, var(--p-text-color, #f3f4f6))}.wuic-menubar-extra{display:flex;align-items:center;gap:.75rem;min-width:280px;justify-content:flex-end;padding-left:.75rem}.wuic-menubar-user-flag{width:2rem;height:2rem;border-radius:999px;display:block;border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));background:var(--p-content-background, var(--surface-section, #eef3f8));object-fit:cover;flex:0 0 auto}.wuic-menubar-user-wrap{position:relative;display:flex;align-items:center;gap:.55rem;cursor:pointer}.wuic-menubar-user-caret{font-size:.8rem;color:var(--p-text-muted-color, var(--text-color-secondary, #4f6479))}.wuic-menubar-user{display:grid;line-height:1.15;text-align:right;min-width:0}.wuic-language-menu{position:absolute;top:calc(100% + .45rem);right:0;min-width:170px;background:var(--p-surface-card, var(--surface-card, #fff));border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));border-radius:8px;box-shadow:0 10px 28px color-mix(in srgb,var(--p-text-color, #1f2f43) 16%,transparent);z-index:1100;padding:.3rem}.wuic-language-item{width:100%;border:0;background:transparent;display:flex;align-items:center;gap:.8rem;text-align:left;border-radius:6px;padding:.45rem .55rem;cursor:pointer;color:var(--p-text-color, var(--text-color, #1f2f43))}.wuic-language-item-flag{width:1.1rem;height:1.1rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));object-fit:cover;flex:0 0 auto}.wuic-language-item span{flex:1 1 auto}.wuic-language-item small{color:var(--p-text-muted-color, var(--text-color-secondary, #5f748a))}.wuic-language-item:hover{background:var(--p-content-hover-background, var(--surface-hover, #f5f8fb))}.wuic-language-item.is-active{background:color-mix(in srgb,var(--p-primary-color, #3b82f6) 14%,transparent);color:var(--p-primary-color, #315fdd)}:host-context(.theme-dark) .wuic-language-menu{background:var(--p-content-background, var(--surface-card, #111827));border-color:var(--p-content-border-color, var(--surface-border, rgba(255, 255, 255, .2)));box-shadow:0 10px 28px color-mix(in srgb,#000 55%,transparent),0 0 0 1px color-mix(in srgb,var(--p-content-border-color, rgba(255, 255, 255, .2)) 65%,transparent) inset}:host-context(.theme-dark) .wuic-language-item{color:var(--p-text-color, var(--text-color, #f3f4f6))}:host-context(.theme-dark) .wuic-language-item small{color:var(--p-text-muted-color, var(--text-color-secondary, #b7c3d0))}:host-context(.theme-dark) .wuic-language-item:hover{background:color-mix(in srgb,var(--p-content-hover-background, #1f2937) 85%,var(--p-primary-color, #3b82f6) 15%)}:host-context(.theme-dark) .wuic-language-item.is-active{background:color-mix(in srgb,var(--p-primary-color, #3b82f6) 30%,transparent);color:var(--p-primary-contrast-color, #e7f0ff)}.wuic-menubar-user-name{font-weight:600;color:var(--p-text-color, var(--text-color, #1f2f43));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.wuic-menubar-user-role{font-size:.75rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}.wuic-role-badge{display:inline-flex;align-items:center;max-width:100%;padding:.15rem .5rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d4deea));background:var(--p-content-background, var(--surface-section, #f3f7fb));color:var(--p-text-muted-color, var(--text-color-secondary, #4a6077));font-size:.72rem;font-weight:600}.wuic-role-badge-admin{border-color:color-mix(in srgb,var(--p-yellow-500, var(--yellow-500, #f59e0b)) 55%,var(--p-content-border-color, var(--surface-border, #d4deea)));background:color-mix(in srgb,var(--p-yellow-100, var(--yellow-100, #fff6df)) 30%,var(--p-surface-card, var(--surface-card, #fff)));color:color-mix(in srgb,var(--p-yellow-700, var(--yellow-700, #9a5a00)) 80%,var(--p-text-color, var(--text-color, #233242)))}.wuic-menubar-logout{white-space:nowrap;padding-inline:.8rem}.wuic-license-badge{display:inline-flex;align-items:center;gap:.35rem;padding:.25rem .6rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d4deea));background:var(--p-content-background, var(--surface-section, #f3f7fb));color:var(--p-text-muted-color, var(--text-color-secondary, #4a6077));font-size:.72rem;font-weight:700;letter-spacing:.02em;cursor:default;white-space:nowrap;-webkit-user-select:none;user-select:none}.wuic-license-badge .pi{font-size:.85rem}.wuic-license-badge-label{line-height:1}.wuic-license-badge-pro{border-color:color-mix(in srgb,var(--p-emerald-500, #10b981) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-emerald-100, #d1fae5) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-emerald-700, #047857) 80%,var(--p-text-color, #233242))}.wuic-license-badge-dev{border-color:color-mix(in srgb,var(--p-blue-500, #3b82f6) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-blue-100, #dbeafe) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-blue-700, #1d4ed8) 80%,var(--p-text-color, #233242))}.wuic-license-badge-trial{border-color:color-mix(in srgb,var(--p-orange-500, #f97316) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-orange-100, #ffedd5) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-orange-700, #c2410c) 80%,var(--p-text-color, #233242))}.wuic-auth-stage-login,.wuic-auth-stage-login *{color-scheme:inherit}.wuic-auth-stage-login{--wuic-surface-ground: var(--p-surface-ground, var(--surface-ground, var(--surface-b, #f7f8fa)));--wuic-surface-card: var(--p-surface-card, var(--surface-card, var(--surface-a, #ffffff)));--wuic-surface-section: var(--p-content-background, var(--surface-section, var(--surface-c, #ffffff)));--wuic-surface-hover: var(--p-content-hover-background, var(--surface-hover, var(--surface-hover-background, #f3f4f6)));--wuic-surface-border: var(--p-content-border-color, var(--surface-border, var(--surface-d, #d7dce3)));--wuic-text: var(--p-text-color, var(--text-color, #1f2937));--wuic-text-muted: var(--p-text-muted-color, var(--text-color-secondary, #6b7280));--wuic-primary: var(--p-primary-color, var(--primary-color, #3b82f6));--wuic-primary-text: var(--p-primary-contrast-color, var(--primary-color-text, #ffffff));--wuic-danger-100: var(--p-red-100, var(--red-100, #fee2e2));--wuic-danger-500: var(--p-red-500, var(--red-500, #ef4444));--wuic-danger-700: var(--p-red-700, var(--red-700, #b91c1c));min-height:calc(100vh - 2rem);display:grid;place-items:center;padding:1rem;color:var(--wuic-text);background-color:var(--wuic-surface-ground)!important;background:radial-gradient(circle at 15% 20%,color-mix(in srgb,var(--wuic-primary) 12%,transparent),transparent 45%),radial-gradient(circle at 85% 15%,color-mix(in srgb,var(--wuic-primary) 8%,transparent),transparent 40%),linear-gradient(180deg,var(--wuic-surface-ground) 0%,var(--wuic-surface-ground) 100%)!important}:host-context(.theme-dark) .wuic-auth-stage-login{--wuic-surface-ground: var(--p-surface-900, var(--p-content-background, var(--surface-b, #0f172a)));--wuic-surface-card: var(--p-content-background, var(--p-surface-800, var(--surface-a, #111827)));--wuic-surface-section: var(--p-content-background, var(--p-surface-800, var(--surface-c, #1f2937)));--wuic-surface-hover: var(--p-content-hover-background, var(--p-surface-700, var(--surface-hover-background, #374151)));--wuic-surface-border: var(--p-content-border-color, var(--surface-d, rgba(255, 255, 255, .28)));--wuic-text: var(--p-content-color, var(--p-text-color, var(--text-color, #f3f4f6)));--wuic-text-muted: var(--p-text-muted-color, var(--text-color-secondary, #d1d5db))}:host-context(.theme-dark) .wuic-auth-bar,:host-context(.theme-dark) .wuic-auth-bar-login{background:var(--wuic-surface-card)!important;color:var(--wuic-text)!important;border-color:var(--wuic-surface-border)!important}:host-context(.theme-dark) .wuic-auth-form label,:host-context(.theme-dark) .wuic-auth-status,:host-context(.theme-dark) .wuic-auth-bar span,:host-context(.theme-dark) .wuic-auth-bar strong{color:var(--wuic-text)!important}:host-context(.theme-dark) .wuic-auth-form input{background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-color:var(--wuic-surface-border)!important}:host-context(.theme-dark) .wuic-auth-form input::placeholder{color:var(--wuic-text-muted)!important}:host-context(.theme-dark) .wuic-auth-btn{background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-color:color-mix(in srgb,var(--wuic-surface-border) 75%,white 25%)!important}:host-context(.theme-dark) .wuic-auth-btn-primary{background:var(--wuic-primary)!important;border-color:var(--wuic-primary)!important;color:var(--wuic-primary-text)!important}.wuic-auth-bar{display:grid;gap:.5rem;padding:.6rem .75rem;border:1px solid var(--wuic-surface-border);border-top:0;background:var(--wuic-surface-card)!important;color:var(--wuic-text)!important}.wuic-auth-bar-login{width:min(420px,92vw);gap:1rem;padding:1.15rem 1.2rem;border-radius:14px;border:1px solid var(--wuic-surface-border)!important;background:var(--wuic-surface-card)!important;box-shadow:0 14px 40px color-mix(in srgb,var(--wuic-text) 12%,transparent),0 0 0 1px color-mix(in srgb,var(--wuic-surface-border) 65%,transparent) inset}.wuic-auth-status{font-size:.9rem;color:var(--wuic-text)!important;margin-bottom:.1rem;line-height:1.35}.wuic-auth-form{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.wuic-auth-form-login{flex-direction:column;align-items:stretch;gap:.75rem}.wuic-auth-form-login form{display:grid;gap:.5rem;margin:0}.wuic-auth-form label{font-size:.85rem;color:var(--wuic-text)!important}.wuic-auth-form-login label{font-weight:600;margin-top:0}.wuic-auth-form input{min-width:220px;flex:1 1 320px;border:1px solid var(--wuic-surface-border);border-radius:6px;padding:.45rem .6rem;background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;box-shadow:0 0 0 1px color-mix(in srgb,var(--wuic-surface-border) 35%,transparent) inset}.wuic-auth-form input::placeholder{color:var(--wuic-text-muted);opacity:1}.wuic-auth-form input:focus{outline:none;border-color:var(--wuic-primary);box-shadow:0 0 0 1px color-mix(in srgb,var(--wuic-primary) 55%,transparent) inset,0 0 0 .15rem color-mix(in srgb,var(--wuic-primary) 22%,transparent)}.wuic-auth-form-login input{min-width:0;width:100%;flex:initial}.wuic-auth-btn{border:1px solid var(--wuic-surface-border);background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-radius:6px;padding:.45rem .75rem;cursor:pointer;transition:background-color .12s ease,border-color .12s ease,color .12s ease,box-shadow .12s ease}.wuic-auth-form-login .wuic-auth-btn{width:100%;justify-content:center}.wuic-auth-form-login>.wuic-auth-btn:not(.wuic-auth-btn-primary){margin-top:.2rem}.wuic-auth-btn:disabled{opacity:.5;cursor:default}.wuic-auth-btn:not(:disabled):hover{background:var(--wuic-surface-hover)!important;border-color:color-mix(in srgb,var(--wuic-primary) 35%,var(--wuic-surface-border))}.wuic-auth-btn:not(:disabled):focus-visible{outline:none;box-shadow:0 0 0 .15rem color-mix(in srgb,var(--wuic-primary) 20%,transparent)}.wuic-auth-btn-primary{background:var(--wuic-primary)!important;border-color:var(--wuic-primary)!important;color:var(--wuic-primary-text)!important}.wuic-auth-btn-primary:not(:disabled):hover{background:color-mix(in srgb,var(--wuic-primary) 88%,black 12%)!important;border-color:color-mix(in srgb,var(--wuic-primary) 88%,black 12%)!important;color:var(--wuic-primary-text)!important}.wuic-captcha{margin:.25rem 0}.wuic-auth-error{color:var(--wuic-danger-700);font-size:.85rem;background:color-mix(in srgb,var(--wuic-danger-100) 22%,var(--wuic-surface-card));border:1px solid color-mix(in srgb,var(--wuic-danger-500) 35%,var(--wuic-surface-border));border-radius:8px;padding:.5rem .65rem}.wuic-auth-success{color:var(--p-green-700, var(--green-700, #15803d));font-size:.85rem;background:color-mix(in srgb,var(--p-green-100, var(--green-100, #dcfce7)) 22%,var(--wuic-surface-card));border:1px solid color-mix(in srgb,var(--p-green-500, var(--green-500, #22c55e)) 35%,var(--wuic-surface-border));border-radius:8px;padding:.5rem .65rem}.wuic-auth-links{display:flex;justify-content:center;gap:1.25rem;margin-top:.1rem}.wuic-auth-link{appearance:none;background:transparent;border:none;padding:0;margin:0;font:inherit;font-size:.82rem;color:color-mix(in srgb,var(--wuic-primary) 60%,#0f172a 40%);cursor:pointer;text-decoration:underline;text-underline-offset:2px}.wuic-auth-link:hover{color:color-mix(in srgb,var(--wuic-primary) 40%,#0f172a 60%)}@media(max-width:768px){.wuic-menubar-extra{min-width:0;gap:.5rem}.wuic-menubar-user-name,.wuic-menubar-user-role{max-width:130px}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list,:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu{overflow-x:hidden!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list{max-height:calc(100vh - 13rem);overflow-y:auto!important;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu{width:100%!important;margin-left:0!important;max-height:none;overflow-y:visible!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu>.p-menubar-item{width:100%!important;float:none!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-item-link{white-space:normal;word-break:break-word}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu{display:grid;grid-template-columns:minmax(0,1fr);gap:0}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu>.p-menubar-item>.p-menubar-item-link{padding-top:.5rem;padding-bottom:.5rem}}@media(max-width:768px)and (min-width:560px){:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:.25rem}}:host ::ng-deep .p-contextmenu{z-index:13000!important}:host ::ng-deep .p-menubar-item-link[draggable=true]{cursor:grab}:host ::ng-deep .p-menubar-item-link[draggable=true]:active{cursor:grabbing}.wuic-menu-move-actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.75rem}.wuic-be-offline-banner{background:#dc354514;border-bottom:2px solid rgba(220,53,69,.6)}.wuic-be-offline-content{display:flex;align-items:center;gap:.75rem;padding:.5rem 1rem;width:100%;max-width:720px;margin:0 auto}.wuic-be-offline-icon{color:#dc3545;font-size:1.5rem;flex-shrink:0}.wuic-be-offline-text{display:flex;flex-direction:column;flex:1 1 auto;min-width:0}.wuic-be-offline-text strong{color:#842029;font-size:.95rem}.wuic-be-offline-text span{color:#58151c;font-size:.8rem;opacity:.85}.wuic-be-offline-retry{display:inline-flex;align-items:center;gap:.4rem;padding:.45rem .9rem;background:#dc3545;color:#fff;border:1px solid #b02a37;border-radius:4px;font-weight:600;font-size:.85rem;cursor:pointer;flex-shrink:0;transition:background-color .12s ease}.wuic-be-offline-retry:hover{background:#bb2d3b}.wuic-be-offline-retry:active{background:#a52834}.wuic-be-offline-retry i{font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: MenubarModule }, { kind: "component", type: i5$1.Menubar, selector: "p-menubar", inputs: ["model", "styleClass", "autoZIndex", "baseZIndex", "autoDisplay", "autoHide", "breakpoint", "autoHideDelay", "id", "ariaLabel", "ariaLabelledBy"], outputs: ["onFocus", "onBlur"] }, { kind: "ngmodule", type: MegaMenuModule }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i14.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: DataSourceComponent, selector: "wuic-data-source", inputs: ["route", "routeFromRouting", "hardcodedRoute", "autoload", "loading", "changeTracking", "parentRecord", "parentMetaInfo", "parentDatasource", "useComboEndpoint", "comboFormulaLookup", "comboMcId", "comboField", "comboExtraFields", "comboCurrentRecord", "componentRef"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$4.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }] });
|
|
45072
45245
|
}
|
|
45073
45246
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MetaMenuComponent, decorators: [{
|
|
45074
45247
|
type: Component,
|
|
45075
|
-
args: [{ selector: 'wuic-meta-menu', imports: [MenubarModule, MegaMenuModule, ContextMenuModule, DialogModule, DataSourceComponent, RouterModule, FormsModule, AsyncPipe, TranslateModule, TooltipModule], template: "@if (authState$ | async; as auth) {\n<nav class=\"wuic-meta-menu-landmark\" aria-label=\"Menu principale\">\n @if (auth.sessionExpiring) {\n <div class=\"wuic-session-warning\">\n <span class=\"pi pi-exclamation-triangle\"></span>\n {{ 'auth.session.expiring_in' | translate }} <strong>{{ auth.sessionExpiresInSeconds }}</strong> {{ 'seconds' |\n translate }}.\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"refreshAuthSession()\">{{ 'auth.session.extend' | translate\n }}</button>\n </div>\n }\n @if (auth.initialized && !requiresAuthentication(auth)) {\n <div style=\"display:none\">\n <wuic-data-source #menuMetadataDs [hardcodedRoute]=\"metaMenuRoute\" [autoload]=\"false\"></wuic-data-source>\n </div>\n <p-menubar #menubar [model]=\"items\" [autoHide]=\"false\">\n <ng-template #item let-item>\n @if (item.route) {\n <!-- [href] con path assoluto (NO `#/` hash) cosi' Lighthouse SEO\n `crawlable-anchors` considera il link crawlable: il path\n `/<route>` e' un URL valid + condivisibile + apribile in nuova\n tab via Ctrl+Click. Il click handler `onMenuItemClick` chiama\n `event.preventDefault()` quando il button click e' \"primary\"\n (no Ctrl/middle), cosi' la SPA navigation passa per\n `router.navigateByUrl` (che con `withHashLocation()` aggiunge\n comunque l'hash internamente all'URL) e preserva pending changes\n /query params. Per Ctrl+Click / middle-click il browser segue\n l'href naturalmente \u2192 apre nuova tab con path puro (poi il\n server fa SPA fallback a index.html, e Angular legge la route\n dalla path). -->\n <a class=\"p-menubar-item-link\" [href]=\"getMenuItemHref(item)\" (click)=\"onMenuItemClick(item, $event)\"\n (contextmenu)=\"onMenuContext($event, item, auth, menuCtx)\"\n [attr.draggable]=\"canDragMenu(auth, item) ? true : null\" (dragstart)=\"onMenuDragStart($event, item, auth)\"\n (dragover)=\"onMenuDragOver($event, item, auth)\" (drop)=\"onMenuDrop($event, item, auth)\"\n (dragend)=\"onMenuDragEnd()\">\n <span [class]=\"item.icon\"></span>\n <span class=\"ml-2\">{{ item.label | translate }}</span>\n </a>\n } @else {\n <!-- Parent items (folder con submenu, NO route propria): NON sono `<a>`\n ma `<div>` semantici. Lighthouse non flagga `<div>` come uncrawlable\n (l'audit `crawlable-anchors` controlla solo `<a>`). PrimeNG si\n occupa di toggle del submenu via il (click). -->\n <div class=\"p-menubar-item-link\" (click)=\"onMenuItemClick(item, $event); onFocus($event)\"\n (contextmenu)=\"onMenuContext($event, item, auth, menuCtx)\"\n [attr.draggable]=\"canDragMenu(auth, item) ? true : null\" (dragstart)=\"onMenuDragStart($event, item, auth)\"\n (dragover)=\"onMenuDragOver($event, item, auth)\" (drop)=\"onMenuDrop($event, item, auth)\"\n (dragend)=\"onMenuDragEnd()\">\n <span [class]=\"item.icon\"></span>\n <span class=\"ml-2\">{{ item.label | translate }}</span>\n <span class=\"pi pi-fw pi-angle-down ml-2\"></span>\n </div>\n }\n </ng-template>\n\n <ng-template #end>\n @if (auth.authenticated || auth.legacyAuthenticated) {\n <div class=\"wuic-menubar-extra\">\n <span class=\"wuic-license-badge\" [class.wuic-license-badge-pro]=\"getLicenseTier() === 'professional'\"\n [class.wuic-license-badge-dev]=\"getLicenseTier() === 'developer'\"\n [class.wuic-license-badge-trial]=\"getLicenseTier() === 'trial'\" [attr.title]=\"getLicenseTooltip()\"\n role=\"status\" [attr.aria-label]=\"getLicenseTooltip()\">\n <span [class]=\"getLicenseIconClass()\" aria-hidden=\"true\"></span>\n <span class=\"wuic-license-badge-label\">{{ getLicenseBadgeLabel() }}</span>\n </span>\n\n <div class=\"wuic-menubar-user-wrap\" (click)=\"toggleUserLanguageMenu($event)\">\n <img class=\"wuic-menubar-user-flag\" [src]=\"getCurrentUserLanguageFlagSrc()\" [alt]=\"getCurrentUserLanguageId()\"\n (error)=\"onLanguageFlagLoadError($event)\" />\n <div class=\"wuic-menubar-user\">\n @if (auth.authenticated) {\n <span [pTooltip]=\"auth.name || ('user.default' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-menubar-user-name\">{{ auth.name || ('user.default' | translate) }}</span>\n <span class=\"wuic-menubar-user-role\">\n <span [pTooltip]=\"auth.provider || ('auth.provider.google' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-role-badge\">{{ auth.provider || ('auth.provider.google' | translate) }}</span>\n </span>\n } @else {\n <span [pTooltip]=\"auth.legacyName || ('user.default' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-menubar-user-name\">{{ auth.legacyName || ('user.default' | translate) }}</span>\n <span class=\"wuic-menubar-user-role\">\n <span [pTooltip]=\"auth.legacyRole || ('auth.role.na' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-role-badge\" [class.wuic-role-badge-admin]=\"isAdminRole(auth)\">{{ auth.legacyRole ||\n ('auth.role.na' | translate) }}</span>\n </span>\n }\n </div>\n @if (userLanguageSwitchEnabled) {\n <span class=\"pi pi-angle-down wuic-menubar-user-caret\" aria-hidden=\"true\"></span>\n }\n @if (userLanguageSwitchEnabled && userLanguageMenuVisible) {\n <div class=\"wuic-language-menu\" (click)=\"$event.stopPropagation()\">\n @for (lang of userLanguages; track lang.id) {\n <button type=\"button\" class=\"wuic-language-item\" [class.is-active]=\"isCurrentUserLanguage(lang.id)\"\n (click)=\"onSelectUserLanguage(lang.id, $event)\">\n <img class=\"wuic-language-item-flag\" [src]=\"getLanguageFlagSrc(lang.id)\" [alt]=\"lang.id\"\n (error)=\"onLanguageFlagLoadError($event)\" />\n <span>{{ lang.lingua || lang.id }}</span>\n <small>{{ lang.id }}</small>\n </button>\n }\n </div>\n }\n </div>\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-menubar-logout\" (click)=\"logout()\" [disabled]=\"auth.loading\">\n {{ 'logout' | translate }}\n </button>\n </div>\n }\n </ng-template>\n </p-menubar>\n <p-contextMenu #menuCtx [model]=\"contextItems\" appendTo=\"body\" [autoZIndex]=\"true\"\n [baseZIndex]=\"13000\"></p-contextMenu>\n <p-dialog [(visible)]=\"moveDialogVisible\" [modal]=\"true\" [draggable]=\"false\" [resizable]=\"false\" [closable]=\"true\"\n [style]=\"{ width: '28rem' }\" [header]=\"'menu.move.title' | translate\" (onHide)=\"cancelPendingMove()\"\n [autoZIndex]=\"true\" [baseZIndex]=\"14000\">\n <p>{{ 'menu.move.drop_target' | translate }}: <strong>{{ pendingMove?.targetLabel || pendingMove?.targetId\n }}</strong></p>\n <p>{{ 'menu.move.choose_position' | translate }}</p>\n <div class=\"wuic-menu-move-actions\">\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"executePendingMove('before')\"\n [disabled]=\"!hasMenuAdminMethod('reorderMenu')\">{{ 'menu.move.before' | translate }}</button>\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"executePendingMove('after')\"\n [disabled]=\"!hasMenuAdminMethod('reorderMenu')\">{{ 'menu.move.after' | translate }}</button>\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"executePendingMove('inside')\"\n [disabled]=\"!hasMenuAdminMethod('nestMenu')\">{{ 'menu.move.inside' | translate }}</button>\n </div>\n </p-dialog>\n }\n @if (auth.initialized && showAuthBar(auth)) {\n <div class=\"wuic-auth-stage\" [class.wuic-auth-stage-login]=\"requiresAuthentication(auth)\">\n @if (!(translationsLoaded$ | async)) {\n <!-- Non mostrare il form login finche' le traduzioni non sono caricate: l'utente\n vedrebbe i placeholder grezzi `auth.username` / `auth.password` invece dei\n label tradotti. Meglio uno spinner finche' la tabella traduzioni arriva\n (localStorage o backend). Tipicamente <50ms se cache, ~200-800ms se\n cold-fetch dal backend. -->\n <div class=\"wuic-auth-bar wuic-auth-bar-loading\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-auth-loading\">\n <i class=\"pi pi-spinner pi-spin\"></i>\n <span>Loading\u2026</span>\n </div>\n </div>\n } @else {\n <div class=\"wuic-auth-bar\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-auth-status\">\n @if (auth.loading) {\n <span>{{ 'auth.status.loading' | translate }}</span>\n } @else if (auth.authenticated) {\n <span>{{ 'auth.status.active' | translate }}: <strong>{{ auth.name || ('user.default' | translate) }}</strong>\n ({{ auth.provider || ('auth.provider.google' | translate) }})</span>\n } @else if (auth.enabled) {\n <span>{{ 'auth.status.not_authenticated' | translate }} ({{ auth.provider || ('auth.provider.google' |\n translate)\n }})</span>\n } @else if (auth.legacyAuthenticated) {\n <span>{{ 'auth.status.active' | translate }}: <strong>{{ auth.legacyName || ('user.default' | translate)\n }}</strong> ({{ 'auth.provider.credentials' | translate }})</span>\n } @else {\n <span>{{ 'auth.status.login_required' | translate }} ({{ 'auth.provider.credentials' | translate }})</span>\n }\n </div>\n\n <div class=\"wuic-auth-form\" [class.wuic-auth-form-login]=\"requiresAuthentication(auth)\">\n @if (auth.enabled) {\n <label for=\"wuicAuthReturnUrl\">{{ 'auth.return_url' | translate }}</label>\n <input id=\"wuicAuthReturnUrl\" type=\"text\" [(ngModel)]=\"authReturnUrl\" (ngModelChange)=\"onAuthReturnUrlChanged()\"\n placeholder=\"/\" />\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"loginWithGoogle()\"\n [disabled]=\"auth.authenticated || auth.loading\">\n {{ 'auth.login_google' | translate }}\n </button>\n\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"logout()\" [disabled]=\"!auth.authenticated || auth.loading\">\n {{ 'logout' | translate }}\n </button>\n } @else if (!auth.legacyAuthenticated) {\n\n @if (authView === 'login') {\n <form (ngSubmit)=\"loginLegacy()\" novalidate>\n <label for=\"wuicAuthUser\">{{ 'auth.username' | translate }}</label>\n <input id=\"wuicAuthUser\" type=\"text\" [(ngModel)]=\"loginUsername\" [placeholder]=\"'auth.username' | translate\"\n autocomplete=\"username\" name=\"loginUsername\" />\n\n <label for=\"wuicAuthPwd\">{{ 'auth.password' | translate }}</label>\n <input id=\"wuicAuthPwd\" type=\"password\" [(ngModel)]=\"loginPassword\"\n [placeholder]=\"'auth.password' | translate\" autocomplete=\"current-password\" name=\"loginPassword\" />\n\n @if (captchaEnabled) {\n <div id=\"wuic-captcha-container\" class=\"wuic-captcha\"></div>\n }\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\"\n [disabled]=\"!loginUsername || !loginPassword || auth.loading || (captchaEnabled && !captchaToken)\">\n {{ 'auth.login' | translate }}\n </button>\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('forgotPassword')\">{{\n 'auth.link.forgot_password' | translate }}</button>\n @if (registrationEnabled) {\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('register')\">{{ 'auth.link.register' |\n translate }}</button>\n }\n </div>\n </form>\n } @else if (authView === 'register') {\n <form (ngSubmit)=\"submitRegistration()\" novalidate>\n <label for=\"wuic-auth-register-username\">{{ 'auth.username' | translate }}</label>\n <input id=\"wuic-auth-register-username\" type=\"text\" [(ngModel)]=\"registerUsername\"\n [placeholder]=\"'auth.username' | translate\" autocomplete=\"username\" name=\"registerUsername\" />\n\n <label for=\"wuic-auth-register-email\">{{ 'auth.email' | translate }}</label>\n <input id=\"wuic-auth-register-email\" type=\"email\" [(ngModel)]=\"registerEmail\"\n [placeholder]=\"'auth.email' | translate\" autocomplete=\"email\" name=\"registerEmail\" />\n\n <label for=\"wuic-auth-register-password\">{{ 'auth.password' | translate }}</label>\n <input id=\"wuic-auth-register-password\" type=\"password\" [(ngModel)]=\"registerPassword\"\n [placeholder]=\"'auth.password' | translate\" autocomplete=\"new-password\" name=\"registerPassword\" />\n\n @if (captchaEnabled) {\n <div id=\"wuic-captcha-container\" class=\"wuic-captcha\"></div>\n }\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\"\n [disabled]=\"!registerUsername || !registerEmail || !registerPassword || (captchaEnabled && !captchaToken)\">\n {{ 'auth.link.register' | translate }}\n </button>\n\n @if (registerMessage) {\n <div class=\"wuic-auth-success\">{{ registerMessage }}</div>\n }\n @if (registerError) {\n <div class=\"wuic-auth-error\">{{ registerError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login'\n | translate }}</button>\n </div>\n </form>\n } @else if (authView === 'forgotPassword') {\n <label for=\"wuic-auth-forgot-email\">{{ 'auth.email' | translate }}</label>\n <input id=\"wuic-auth-forgot-email\" type=\"email\" [(ngModel)]=\"forgotEmail\"\n [placeholder]=\"'auth.forgot.email_placeholder' | translate\" autocomplete=\"email\"\n (keyup.enter)=\"submitForgotPassword()\" />\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"submitForgotPassword()\"\n [disabled]=\"!forgotEmail\">\n {{ 'auth.forgot.send_reset_link' | translate }}\n </button>\n\n @if (forgotMessage) {\n <div class=\"wuic-auth-success\">{{ forgotMessage }}</div>\n }\n @if (forgotError) {\n <div class=\"wuic-auth-error\">{{ forgotError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login' |\n translate }}</button>\n </div>\n } @else if (authView === 'resetPassword') {\n <form (ngSubmit)=\"submitResetPassword()\" novalidate>\n <label for=\"wuic-auth-reset-new-password\">{{ 'auth.reset.new_password' | translate }}</label>\n <input id=\"wuic-auth-reset-new-password\" type=\"password\" [(ngModel)]=\"resetNewPassword\"\n [placeholder]=\"'auth.reset.new_password' | translate\" autocomplete=\"new-password\" name=\"resetNewPassword\" />\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\" [disabled]=\"!resetNewPassword\">\n {{ 'auth.reset.submit' | translate }}\n </button>\n\n @if (resetMessage) {\n <div class=\"wuic-auth-success\">{{ resetMessage }}</div>\n }\n @if (resetError) {\n <div class=\"wuic-auth-error\">{{ resetError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login'\n | translate }}</button>\n </div>\n </form>\n }\n\n }\n\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"refreshAuthSession()\" [disabled]=\"auth.loading\">\n {{ 'auth.refresh' | translate }}\n </button>\n </div>\n\n @if (auth.error) {\n <div class=\"wuic-auth-error\">{{ auth.error }}</div>\n }\n </div>\n }\n </div>\n }\n</nav>\n}\n\n<!-- <p-megaMenu *ngIf=\"menuType=='megamenu'\" [model]=\"megaItems\">\n</p-megaMenu> -->\n\n<!-- <p-megaMenu *ngIf=\"menuType=='megamenu'\" [model]=\"megaItems2\"></p-megaMenu>\n</p-megaMenu> -->", styles: [".wuic-session-warning{display:flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background:color-mix(in srgb,var(--p-yellow-100, var(--yellow-100, #fef9c3)) 50%,var(--p-surface-card, var(--surface-card, #fff)));border-bottom:2px solid var(--p-yellow-500, var(--yellow-500, #eab308));color:var(--p-yellow-800, var(--yellow-800, #854d0e));font-size:.85rem;font-weight:500;z-index:1000}.wuic-session-warning .pi{font-size:1rem}.wuic-session-warning .wuic-auth-btn{margin-left:auto;padding:.25rem .6rem;font-size:.8rem}.wuic-auth-stage{display:block}.wuic-auth-bar-loading{display:flex;align-items:center;justify-content:center;min-height:48px;padding:.75rem 1rem}.wuic-auth-loading{display:flex;align-items:center;gap:.5rem;color:var(--p-text-color-secondary, var(--text-color-secondary, #64748b));font-size:.9rem}.wuic-auth-loading .pi-spinner{font-size:1.1rem}:host ::ng-deep .p-menubar .p-menubar-item-link[draggable=true]{cursor:grab}:host ::ng-deep .p-menubar .p-menubar-item-link[draggable=true]:active{cursor:grabbing}:host ::ng-deep .p-menubar .p-menubar-item-link:not(.p-disabled):hover{background:var(--p-content-hover-background, var(--surface-hover, #f1f5f9));color:var(--p-primary-color, var(--p-text-color, inherit))}:host-context(.theme-dark) ::ng-deep .p-menubar .p-menubar-item-link:not(.p-disabled):hover{background:color-mix(in srgb,var(--p-content-hover-background, #1f2937) 80%,var(--p-primary-color, #3b82f6) 20%);color:var(--p-primary-color, var(--p-text-color, #f3f4f6))}.wuic-menubar-extra{display:flex;align-items:center;gap:.75rem;min-width:280px;justify-content:flex-end;padding-left:.75rem}.wuic-menubar-user-flag{width:2rem;height:2rem;border-radius:999px;display:block;border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));background:var(--p-content-background, var(--surface-section, #eef3f8));object-fit:cover;flex:0 0 auto}.wuic-menubar-user-wrap{position:relative;display:flex;align-items:center;gap:.55rem;cursor:pointer}.wuic-menubar-user-caret{font-size:.8rem;color:var(--p-text-muted-color, var(--text-color-secondary, #4f6479))}.wuic-menubar-user{display:grid;line-height:1.15;text-align:right;min-width:0}.wuic-language-menu{position:absolute;top:calc(100% + .45rem);right:0;min-width:170px;background:var(--p-surface-card, var(--surface-card, #fff));border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));border-radius:8px;box-shadow:0 10px 28px color-mix(in srgb,var(--p-text-color, #1f2f43) 16%,transparent);z-index:1100;padding:.3rem}.wuic-language-item{width:100%;border:0;background:transparent;display:flex;align-items:center;gap:.8rem;text-align:left;border-radius:6px;padding:.45rem .55rem;cursor:pointer;color:var(--p-text-color, var(--text-color, #1f2f43))}.wuic-language-item-flag{width:1.1rem;height:1.1rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));object-fit:cover;flex:0 0 auto}.wuic-language-item span{flex:1 1 auto}.wuic-language-item small{color:var(--p-text-muted-color, var(--text-color-secondary, #5f748a))}.wuic-language-item:hover{background:var(--p-content-hover-background, var(--surface-hover, #f5f8fb))}.wuic-language-item.is-active{background:color-mix(in srgb,var(--p-primary-color, #3b82f6) 14%,transparent);color:var(--p-primary-color, #315fdd)}:host-context(.theme-dark) .wuic-language-menu{background:var(--p-content-background, var(--surface-card, #111827));border-color:var(--p-content-border-color, var(--surface-border, rgba(255, 255, 255, .2)));box-shadow:0 10px 28px color-mix(in srgb,#000 55%,transparent),0 0 0 1px color-mix(in srgb,var(--p-content-border-color, rgba(255, 255, 255, .2)) 65%,transparent) inset}:host-context(.theme-dark) .wuic-language-item{color:var(--p-text-color, var(--text-color, #f3f4f6))}:host-context(.theme-dark) .wuic-language-item small{color:var(--p-text-muted-color, var(--text-color-secondary, #b7c3d0))}:host-context(.theme-dark) .wuic-language-item:hover{background:color-mix(in srgb,var(--p-content-hover-background, #1f2937) 85%,var(--p-primary-color, #3b82f6) 15%)}:host-context(.theme-dark) .wuic-language-item.is-active{background:color-mix(in srgb,var(--p-primary-color, #3b82f6) 30%,transparent);color:var(--p-primary-contrast-color, #e7f0ff)}.wuic-menubar-user-name{font-weight:600;color:var(--p-text-color, var(--text-color, #1f2f43));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.wuic-menubar-user-role{font-size:.75rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}.wuic-role-badge{display:inline-flex;align-items:center;max-width:100%;padding:.15rem .5rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d4deea));background:var(--p-content-background, var(--surface-section, #f3f7fb));color:var(--p-text-muted-color, var(--text-color-secondary, #4a6077));font-size:.72rem;font-weight:600}.wuic-role-badge-admin{border-color:color-mix(in srgb,var(--p-yellow-500, var(--yellow-500, #f59e0b)) 55%,var(--p-content-border-color, var(--surface-border, #d4deea)));background:color-mix(in srgb,var(--p-yellow-100, var(--yellow-100, #fff6df)) 30%,var(--p-surface-card, var(--surface-card, #fff)));color:color-mix(in srgb,var(--p-yellow-700, var(--yellow-700, #9a5a00)) 80%,var(--p-text-color, var(--text-color, #233242)))}.wuic-menubar-logout{white-space:nowrap;padding-inline:.8rem}.wuic-license-badge{display:inline-flex;align-items:center;gap:.35rem;padding:.25rem .6rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d4deea));background:var(--p-content-background, var(--surface-section, #f3f7fb));color:var(--p-text-muted-color, var(--text-color-secondary, #4a6077));font-size:.72rem;font-weight:700;letter-spacing:.02em;cursor:default;white-space:nowrap;-webkit-user-select:none;user-select:none}.wuic-license-badge .pi{font-size:.85rem}.wuic-license-badge-label{line-height:1}.wuic-license-badge-pro{border-color:color-mix(in srgb,var(--p-emerald-500, #10b981) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-emerald-100, #d1fae5) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-emerald-700, #047857) 80%,var(--p-text-color, #233242))}.wuic-license-badge-dev{border-color:color-mix(in srgb,var(--p-blue-500, #3b82f6) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-blue-100, #dbeafe) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-blue-700, #1d4ed8) 80%,var(--p-text-color, #233242))}.wuic-license-badge-trial{border-color:color-mix(in srgb,var(--p-orange-500, #f97316) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-orange-100, #ffedd5) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-orange-700, #c2410c) 80%,var(--p-text-color, #233242))}.wuic-auth-stage-login,.wuic-auth-stage-login *{color-scheme:inherit}.wuic-auth-stage-login{--wuic-surface-ground: var(--p-surface-ground, var(--surface-ground, var(--surface-b, #f7f8fa)));--wuic-surface-card: var(--p-surface-card, var(--surface-card, var(--surface-a, #ffffff)));--wuic-surface-section: var(--p-content-background, var(--surface-section, var(--surface-c, #ffffff)));--wuic-surface-hover: var(--p-content-hover-background, var(--surface-hover, var(--surface-hover-background, #f3f4f6)));--wuic-surface-border: var(--p-content-border-color, var(--surface-border, var(--surface-d, #d7dce3)));--wuic-text: var(--p-text-color, var(--text-color, #1f2937));--wuic-text-muted: var(--p-text-muted-color, var(--text-color-secondary, #6b7280));--wuic-primary: var(--p-primary-color, var(--primary-color, #3b82f6));--wuic-primary-text: var(--p-primary-contrast-color, var(--primary-color-text, #ffffff));--wuic-danger-100: var(--p-red-100, var(--red-100, #fee2e2));--wuic-danger-500: var(--p-red-500, var(--red-500, #ef4444));--wuic-danger-700: var(--p-red-700, var(--red-700, #b91c1c));min-height:calc(100vh - 2rem);display:grid;place-items:center;padding:1rem;color:var(--wuic-text);background-color:var(--wuic-surface-ground)!important;background:radial-gradient(circle at 15% 20%,color-mix(in srgb,var(--wuic-primary) 12%,transparent),transparent 45%),radial-gradient(circle at 85% 15%,color-mix(in srgb,var(--wuic-primary) 8%,transparent),transparent 40%),linear-gradient(180deg,var(--wuic-surface-ground) 0%,var(--wuic-surface-ground) 100%)!important}:host-context(.theme-dark) .wuic-auth-stage-login{--wuic-surface-ground: var(--p-surface-900, var(--p-content-background, var(--surface-b, #0f172a)));--wuic-surface-card: var(--p-content-background, var(--p-surface-800, var(--surface-a, #111827)));--wuic-surface-section: var(--p-content-background, var(--p-surface-800, var(--surface-c, #1f2937)));--wuic-surface-hover: var(--p-content-hover-background, var(--p-surface-700, var(--surface-hover-background, #374151)));--wuic-surface-border: var(--p-content-border-color, var(--surface-d, rgba(255, 255, 255, .28)));--wuic-text: var(--p-content-color, var(--p-text-color, var(--text-color, #f3f4f6)));--wuic-text-muted: var(--p-text-muted-color, var(--text-color-secondary, #d1d5db))}:host-context(.theme-dark) .wuic-auth-bar,:host-context(.theme-dark) .wuic-auth-bar-login{background:var(--wuic-surface-card)!important;color:var(--wuic-text)!important;border-color:var(--wuic-surface-border)!important}:host-context(.theme-dark) .wuic-auth-form label,:host-context(.theme-dark) .wuic-auth-status,:host-context(.theme-dark) .wuic-auth-bar span,:host-context(.theme-dark) .wuic-auth-bar strong{color:var(--wuic-text)!important}:host-context(.theme-dark) .wuic-auth-form input{background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-color:var(--wuic-surface-border)!important}:host-context(.theme-dark) .wuic-auth-form input::placeholder{color:var(--wuic-text-muted)!important}:host-context(.theme-dark) .wuic-auth-btn{background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-color:color-mix(in srgb,var(--wuic-surface-border) 75%,white 25%)!important}:host-context(.theme-dark) .wuic-auth-btn-primary{background:var(--wuic-primary)!important;border-color:var(--wuic-primary)!important;color:var(--wuic-primary-text)!important}.wuic-auth-bar{display:grid;gap:.5rem;padding:.6rem .75rem;border:1px solid var(--wuic-surface-border);border-top:0;background:var(--wuic-surface-card)!important;color:var(--wuic-text)!important}.wuic-auth-bar-login{width:min(420px,92vw);gap:1rem;padding:1.15rem 1.2rem;border-radius:14px;border:1px solid var(--wuic-surface-border)!important;background:var(--wuic-surface-card)!important;box-shadow:0 14px 40px color-mix(in srgb,var(--wuic-text) 12%,transparent),0 0 0 1px color-mix(in srgb,var(--wuic-surface-border) 65%,transparent) inset}.wuic-auth-status{font-size:.9rem;color:var(--wuic-text)!important;margin-bottom:.1rem;line-height:1.35}.wuic-auth-form{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.wuic-auth-form-login{flex-direction:column;align-items:stretch;gap:.75rem}.wuic-auth-form-login form{display:grid;gap:.5rem;margin:0}.wuic-auth-form label{font-size:.85rem;color:var(--wuic-text)!important}.wuic-auth-form-login label{font-weight:600;margin-top:0}.wuic-auth-form input{min-width:220px;flex:1 1 320px;border:1px solid var(--wuic-surface-border);border-radius:6px;padding:.45rem .6rem;background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;box-shadow:0 0 0 1px color-mix(in srgb,var(--wuic-surface-border) 35%,transparent) inset}.wuic-auth-form input::placeholder{color:var(--wuic-text-muted);opacity:1}.wuic-auth-form input:focus{outline:none;border-color:var(--wuic-primary);box-shadow:0 0 0 1px color-mix(in srgb,var(--wuic-primary) 55%,transparent) inset,0 0 0 .15rem color-mix(in srgb,var(--wuic-primary) 22%,transparent)}.wuic-auth-form-login input{min-width:0;width:100%;flex:initial}.wuic-auth-btn{border:1px solid var(--wuic-surface-border);background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-radius:6px;padding:.45rem .75rem;cursor:pointer;transition:background-color .12s ease,border-color .12s ease,color .12s ease,box-shadow .12s ease}.wuic-auth-form-login .wuic-auth-btn{width:100%;justify-content:center}.wuic-auth-form-login>.wuic-auth-btn:not(.wuic-auth-btn-primary){margin-top:.2rem}.wuic-auth-btn:disabled{opacity:.5;cursor:default}.wuic-auth-btn:not(:disabled):hover{background:var(--wuic-surface-hover)!important;border-color:color-mix(in srgb,var(--wuic-primary) 35%,var(--wuic-surface-border))}.wuic-auth-btn:not(:disabled):focus-visible{outline:none;box-shadow:0 0 0 .15rem color-mix(in srgb,var(--wuic-primary) 20%,transparent)}.wuic-auth-btn-primary{background:var(--wuic-primary)!important;border-color:var(--wuic-primary)!important;color:var(--wuic-primary-text)!important}.wuic-auth-btn-primary:not(:disabled):hover{background:color-mix(in srgb,var(--wuic-primary) 88%,black 12%)!important;border-color:color-mix(in srgb,var(--wuic-primary) 88%,black 12%)!important;color:var(--wuic-primary-text)!important}.wuic-captcha{margin:.25rem 0}.wuic-auth-error{color:var(--wuic-danger-700);font-size:.85rem;background:color-mix(in srgb,var(--wuic-danger-100) 22%,var(--wuic-surface-card));border:1px solid color-mix(in srgb,var(--wuic-danger-500) 35%,var(--wuic-surface-border));border-radius:8px;padding:.5rem .65rem}.wuic-auth-success{color:var(--p-green-700, var(--green-700, #15803d));font-size:.85rem;background:color-mix(in srgb,var(--p-green-100, var(--green-100, #dcfce7)) 22%,var(--wuic-surface-card));border:1px solid color-mix(in srgb,var(--p-green-500, var(--green-500, #22c55e)) 35%,var(--wuic-surface-border));border-radius:8px;padding:.5rem .65rem}.wuic-auth-links{display:flex;justify-content:center;gap:1.25rem;margin-top:.1rem}.wuic-auth-link{appearance:none;background:transparent;border:none;padding:0;margin:0;font:inherit;font-size:.82rem;color:color-mix(in srgb,var(--wuic-primary) 60%,#0f172a 40%);cursor:pointer;text-decoration:underline;text-underline-offset:2px}.wuic-auth-link:hover{color:color-mix(in srgb,var(--wuic-primary) 40%,#0f172a 60%)}@media(max-width:768px){.wuic-menubar-extra{min-width:0;gap:.5rem}.wuic-menubar-user-name,.wuic-menubar-user-role{max-width:130px}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list,:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu{overflow-x:hidden!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list{max-height:calc(100vh - 13rem);overflow-y:auto!important;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu{width:100%!important;margin-left:0!important;max-height:none;overflow-y:visible!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu>.p-menubar-item{width:100%!important;float:none!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-item-link{white-space:normal;word-break:break-word}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu{display:grid;grid-template-columns:minmax(0,1fr);gap:0}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu>.p-menubar-item>.p-menubar-item-link{padding-top:.5rem;padding-bottom:.5rem}}@media(max-width:768px)and (min-width:560px){:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:.25rem}}:host ::ng-deep .p-contextmenu{z-index:13000!important}:host ::ng-deep .p-menubar-item-link[draggable=true]{cursor:grab}:host ::ng-deep .p-menubar-item-link[draggable=true]:active{cursor:grabbing}.wuic-menu-move-actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.75rem}\n"] }]
|
|
45248
|
+
args: [{ selector: 'wuic-meta-menu', imports: [MenubarModule, MegaMenuModule, ContextMenuModule, DialogModule, DataSourceComponent, RouterModule, FormsModule, AsyncPipe, TranslateModule, TooltipModule], template: "@if (authState$ | async; as auth) {\n<nav class=\"wuic-meta-menu-landmark\" aria-label=\"Menu principale\">\n @if (auth.sessionExpiring) {\n <div class=\"wuic-session-warning\">\n <span class=\"pi pi-exclamation-triangle\"></span>\n {{ 'auth.session.expiring_in' | translate }} <strong>{{ auth.sessionExpiresInSeconds }}</strong> {{ 'seconds' |\n translate }}.\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"refreshAuthSession()\">{{ 'auth.session.extend' | translate\n }}</button>\n </div>\n }\n @if (auth.initialized && !requiresAuthentication(auth)) {\n <div style=\"display:none\">\n <wuic-data-source #menuMetadataDs [hardcodedRoute]=\"metaMenuRoute\" [autoload]=\"false\"></wuic-data-source>\n </div>\n <p-menubar #menubar [model]=\"items\" [autoHide]=\"false\">\n <ng-template #item let-item>\n @if (item.route) {\n <!-- [href] con path assoluto (NO `#/` hash) cosi' Lighthouse SEO\n `crawlable-anchors` considera il link crawlable: il path\n `/<route>` e' un URL valid + condivisibile + apribile in nuova\n tab via Ctrl+Click. Il click handler `onMenuItemClick` chiama\n `event.preventDefault()` quando il button click e' \"primary\"\n (no Ctrl/middle), cosi' la SPA navigation passa per\n `router.navigateByUrl` (che con `withHashLocation()` aggiunge\n comunque l'hash internamente all'URL) e preserva pending changes\n /query params. Per Ctrl+Click / middle-click il browser segue\n l'href naturalmente \u2192 apre nuova tab con path puro (poi il\n server fa SPA fallback a index.html, e Angular legge la route\n dalla path). -->\n <a class=\"p-menubar-item-link\" [href]=\"getMenuItemHref(item)\" (click)=\"onMenuItemClick(item, $event)\"\n (contextmenu)=\"onMenuContext($event, item, auth, menuCtx)\"\n [attr.draggable]=\"canDragMenu(auth, item) ? true : null\" (dragstart)=\"onMenuDragStart($event, item, auth)\"\n (dragover)=\"onMenuDragOver($event, item, auth)\" (drop)=\"onMenuDrop($event, item, auth)\"\n (dragend)=\"onMenuDragEnd()\">\n <span [class]=\"item.icon\"></span>\n <span class=\"ml-2\">{{ item.label | translate }}</span>\n </a>\n } @else {\n <!-- Parent items (folder con submenu, NO route propria): NON sono `<a>`\n ma `<div>` semantici. Lighthouse non flagga `<div>` come uncrawlable\n (l'audit `crawlable-anchors` controlla solo `<a>`). PrimeNG si\n occupa di toggle del submenu via il (click). -->\n <div class=\"p-menubar-item-link\" (click)=\"onMenuItemClick(item, $event); onFocus($event)\"\n (contextmenu)=\"onMenuContext($event, item, auth, menuCtx)\"\n [attr.draggable]=\"canDragMenu(auth, item) ? true : null\" (dragstart)=\"onMenuDragStart($event, item, auth)\"\n (dragover)=\"onMenuDragOver($event, item, auth)\" (drop)=\"onMenuDrop($event, item, auth)\"\n (dragend)=\"onMenuDragEnd()\">\n <span [class]=\"item.icon\"></span>\n <span class=\"ml-2\">{{ item.label | translate }}</span>\n <span class=\"pi pi-fw pi-angle-down ml-2\"></span>\n </div>\n }\n </ng-template>\n\n <ng-template #end>\n @if (auth.authenticated || auth.legacyAuthenticated) {\n <div class=\"wuic-menubar-extra\">\n <span class=\"wuic-license-badge\" [class.wuic-license-badge-pro]=\"getLicenseTier() === 'professional'\"\n [class.wuic-license-badge-dev]=\"getLicenseTier() === 'developer'\"\n [class.wuic-license-badge-trial]=\"getLicenseTier() === 'trial'\" [attr.title]=\"getLicenseTooltip()\"\n role=\"status\" [attr.aria-label]=\"getLicenseTooltip()\">\n <span [class]=\"getLicenseIconClass()\" aria-hidden=\"true\"></span>\n <span class=\"wuic-license-badge-label\">{{ getLicenseBadgeLabel() }}</span>\n </span>\n\n <div class=\"wuic-menubar-user-wrap\" (click)=\"toggleUserLanguageMenu($event)\">\n <img class=\"wuic-menubar-user-flag\" [src]=\"getCurrentUserLanguageFlagSrc()\" [alt]=\"getCurrentUserLanguageId()\"\n (error)=\"onLanguageFlagLoadError($event)\" />\n <div class=\"wuic-menubar-user\">\n @if (auth.authenticated) {\n <span [pTooltip]=\"auth.name || ('user.default' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-menubar-user-name\">{{ auth.name || ('user.default' | translate) }}</span>\n <span class=\"wuic-menubar-user-role\">\n <span [pTooltip]=\"auth.provider || ('auth.provider.google' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-role-badge\">{{ auth.provider || ('auth.provider.google' | translate) }}</span>\n </span>\n } @else {\n <span [pTooltip]=\"auth.legacyName || ('user.default' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-menubar-user-name\">{{ auth.legacyName || ('user.default' | translate) }}</span>\n <span class=\"wuic-menubar-user-role\">\n <span [pTooltip]=\"auth.legacyRole || ('auth.role.na' | translate)\" tooltipPosition=\"bottom\"\n class=\"wuic-role-badge\" [class.wuic-role-badge-admin]=\"isAdminRole(auth)\">{{ auth.legacyRole ||\n ('auth.role.na' | translate) }}</span>\n </span>\n }\n </div>\n @if (userLanguageSwitchEnabled) {\n <span class=\"pi pi-angle-down wuic-menubar-user-caret\" aria-hidden=\"true\"></span>\n }\n @if (userLanguageSwitchEnabled && userLanguageMenuVisible) {\n <div class=\"wuic-language-menu\" (click)=\"$event.stopPropagation()\">\n @for (lang of userLanguages; track lang.id) {\n <button type=\"button\" class=\"wuic-language-item\" [class.is-active]=\"isCurrentUserLanguage(lang.id)\"\n (click)=\"onSelectUserLanguage(lang.id, $event)\">\n <img class=\"wuic-language-item-flag\" [src]=\"getLanguageFlagSrc(lang.id)\" [alt]=\"lang.id\"\n (error)=\"onLanguageFlagLoadError($event)\" />\n <span>{{ lang.lingua || lang.id }}</span>\n <small>{{ lang.id }}</small>\n </button>\n }\n </div>\n }\n </div>\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-menubar-logout\" (click)=\"logout()\" [disabled]=\"auth.loading\">\n {{ 'logout' | translate }}\n </button>\n </div>\n }\n </ng-template>\n </p-menubar>\n <p-contextMenu #menuCtx [model]=\"contextItems\" appendTo=\"body\" [autoZIndex]=\"true\"\n [baseZIndex]=\"13000\"></p-contextMenu>\n <p-dialog [(visible)]=\"moveDialogVisible\" [modal]=\"true\" [draggable]=\"false\" [resizable]=\"false\" [closable]=\"true\"\n [style]=\"{ width: '28rem' }\" [header]=\"'menu.move.title' | translate\" (onHide)=\"cancelPendingMove()\"\n [autoZIndex]=\"true\" [baseZIndex]=\"14000\">\n <p>{{ 'menu.move.drop_target' | translate }}: <strong>{{ pendingMove?.targetLabel || pendingMove?.targetId\n }}</strong></p>\n <p>{{ 'menu.move.choose_position' | translate }}</p>\n <div class=\"wuic-menu-move-actions\">\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"executePendingMove('before')\"\n [disabled]=\"!hasMenuAdminMethod('reorderMenu')\">{{ 'menu.move.before' | translate }}</button>\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"executePendingMove('after')\"\n [disabled]=\"!hasMenuAdminMethod('reorderMenu')\">{{ 'menu.move.after' | translate }}</button>\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"executePendingMove('inside')\"\n [disabled]=\"!hasMenuAdminMethod('nestMenu')\">{{ 'menu.move.inside' | translate }}</button>\n </div>\n </p-dialog>\n }\n @if (auth.initialized && showAuthBar(auth)) {\n <div class=\"wuic-auth-stage\" [class.wuic-auth-stage-login]=\"requiresAuthentication(auth)\">\n @if (!(translationsLoaded$ | async)) {\n <!-- Non mostrare il form login finche' le traduzioni non sono caricate: l'utente\n vedrebbe i placeholder grezzi `auth.username` / `auth.password` invece dei\n label tradotti. Meglio uno spinner finche' la tabella traduzioni arriva\n (localStorage o backend). Tipicamente <50ms se cache, ~200-800ms se\n cold-fetch dal backend.\n Eccezione: se il circuit breaker del TranslationManager si e' aperto\n (5 fallimenti consecutivi \u2192 BE offline persistente), lo spinner\n resterebbe infinito. Mostriamo invece un banner con bottone Riprova\n cosi' l'utente puo' riarmare manualmente quando il BE torna su. -->\n @if (backendCircuitOpen$ | async) {\n <div class=\"wuic-auth-bar wuic-auth-bar-loading wuic-be-offline-banner\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-be-offline-content\">\n <i class=\"pi pi-exclamation-triangle wuic-be-offline-icon\"></i>\n <div class=\"wuic-be-offline-text\">\n <strong>Backend non raggiungibile</strong>\n <span>Impossibile caricare le traduzioni dopo 5 tentativi. Verifica che il server WuicCore sia attivo.</span>\n </div>\n <button type=\"button\" class=\"wuic-be-offline-retry\" (click)=\"retryBackend()\" aria-label=\"Riprova connessione al backend\">\n <i class=\"pi pi-refresh\"></i>\n <span>Riprova</span>\n </button>\n </div>\n </div>\n } @else {\n <div class=\"wuic-auth-bar wuic-auth-bar-loading\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-auth-loading\">\n <i class=\"pi pi-spinner pi-spin\"></i>\n <span>Loading\u2026</span>\n </div>\n </div>\n }\n } @else {\n <div class=\"wuic-auth-bar\" [class.wuic-auth-bar-login]=\"requiresAuthentication(auth)\">\n <div class=\"wuic-auth-status\">\n @if (auth.loading) {\n <span>{{ 'auth.status.loading' | translate }}</span>\n } @else if (auth.authenticated) {\n <span>{{ 'auth.status.active' | translate }}: <strong>{{ auth.name || ('user.default' | translate) }}</strong>\n ({{ auth.provider || ('auth.provider.google' | translate) }})</span>\n } @else if (auth.enabled) {\n <span>{{ 'auth.status.not_authenticated' | translate }} ({{ auth.provider || ('auth.provider.google' |\n translate)\n }})</span>\n } @else if (auth.legacyAuthenticated) {\n <span>{{ 'auth.status.active' | translate }}: <strong>{{ auth.legacyName || ('user.default' | translate)\n }}</strong> ({{ 'auth.provider.credentials' | translate }})</span>\n } @else {\n <span>{{ 'auth.status.login_required' | translate }} ({{ 'auth.provider.credentials' | translate }})</span>\n }\n </div>\n\n <div class=\"wuic-auth-form\" [class.wuic-auth-form-login]=\"requiresAuthentication(auth)\">\n @if (auth.enabled) {\n <label for=\"wuicAuthReturnUrl\">{{ 'auth.return_url' | translate }}</label>\n <input id=\"wuicAuthReturnUrl\" type=\"text\" [(ngModel)]=\"authReturnUrl\" (ngModelChange)=\"onAuthReturnUrlChanged()\"\n placeholder=\"/\" />\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"loginWithGoogle()\"\n [disabled]=\"auth.authenticated || auth.loading\">\n {{ 'auth.login_google' | translate }}\n </button>\n\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"logout()\" [disabled]=\"!auth.authenticated || auth.loading\">\n {{ 'logout' | translate }}\n </button>\n } @else if (!auth.legacyAuthenticated) {\n\n @if (authView === 'login') {\n <form (ngSubmit)=\"loginLegacy()\" novalidate>\n <label for=\"wuicAuthUser\">{{ 'auth.username' | translate }}</label>\n <input id=\"wuicAuthUser\" type=\"text\" [(ngModel)]=\"loginUsername\" [placeholder]=\"'auth.username' | translate\"\n autocomplete=\"username\" name=\"loginUsername\" />\n\n <label for=\"wuicAuthPwd\">{{ 'auth.password' | translate }}</label>\n <input id=\"wuicAuthPwd\" type=\"password\" [(ngModel)]=\"loginPassword\"\n [placeholder]=\"'auth.password' | translate\" autocomplete=\"current-password\" name=\"loginPassword\" />\n\n @if (captchaEnabled) {\n <div id=\"wuic-captcha-container\" class=\"wuic-captcha\"></div>\n }\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\"\n [disabled]=\"!loginUsername || !loginPassword || auth.loading || (captchaEnabled && !captchaToken)\">\n {{ 'auth.login' | translate }}\n </button>\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('forgotPassword')\">{{\n 'auth.link.forgot_password' | translate }}</button>\n @if (registrationEnabled) {\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('register')\">{{ 'auth.link.register' |\n translate }}</button>\n }\n </div>\n </form>\n } @else if (authView === 'register') {\n <form (ngSubmit)=\"submitRegistration()\" novalidate>\n <label for=\"wuic-auth-register-username\">{{ 'auth.username' | translate }}</label>\n <input id=\"wuic-auth-register-username\" type=\"text\" [(ngModel)]=\"registerUsername\"\n [placeholder]=\"'auth.username' | translate\" autocomplete=\"username\" name=\"registerUsername\" />\n\n <label for=\"wuic-auth-register-email\">{{ 'auth.email' | translate }}</label>\n <input id=\"wuic-auth-register-email\" type=\"email\" [(ngModel)]=\"registerEmail\"\n [placeholder]=\"'auth.email' | translate\" autocomplete=\"email\" name=\"registerEmail\" />\n\n <label for=\"wuic-auth-register-password\">{{ 'auth.password' | translate }}</label>\n <input id=\"wuic-auth-register-password\" type=\"password\" [(ngModel)]=\"registerPassword\"\n [placeholder]=\"'auth.password' | translate\" autocomplete=\"new-password\" name=\"registerPassword\" />\n\n @if (captchaEnabled) {\n <div id=\"wuic-captcha-container\" class=\"wuic-captcha\"></div>\n }\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\"\n [disabled]=\"!registerUsername || !registerEmail || !registerPassword || (captchaEnabled && !captchaToken)\">\n {{ 'auth.link.register' | translate }}\n </button>\n\n @if (registerMessage) {\n <div class=\"wuic-auth-success\">{{ registerMessage }}</div>\n }\n @if (registerError) {\n <div class=\"wuic-auth-error\">{{ registerError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login'\n | translate }}</button>\n </div>\n </form>\n } @else if (authView === 'forgotPassword') {\n <label for=\"wuic-auth-forgot-email\">{{ 'auth.email' | translate }}</label>\n <input id=\"wuic-auth-forgot-email\" type=\"email\" [(ngModel)]=\"forgotEmail\"\n [placeholder]=\"'auth.forgot.email_placeholder' | translate\" autocomplete=\"email\"\n (keyup.enter)=\"submitForgotPassword()\" />\n\n <button type=\"button\" class=\"wuic-auth-btn wuic-auth-btn-primary\" (click)=\"submitForgotPassword()\"\n [disabled]=\"!forgotEmail\">\n {{ 'auth.forgot.send_reset_link' | translate }}\n </button>\n\n @if (forgotMessage) {\n <div class=\"wuic-auth-success\">{{ forgotMessage }}</div>\n }\n @if (forgotError) {\n <div class=\"wuic-auth-error\">{{ forgotError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login' |\n translate }}</button>\n </div>\n } @else if (authView === 'resetPassword') {\n <form (ngSubmit)=\"submitResetPassword()\" novalidate>\n <label for=\"wuic-auth-reset-new-password\">{{ 'auth.reset.new_password' | translate }}</label>\n <input id=\"wuic-auth-reset-new-password\" type=\"password\" [(ngModel)]=\"resetNewPassword\"\n [placeholder]=\"'auth.reset.new_password' | translate\" autocomplete=\"new-password\" name=\"resetNewPassword\" />\n\n <button type=\"submit\" class=\"wuic-auth-btn wuic-auth-btn-primary\" [disabled]=\"!resetNewPassword\">\n {{ 'auth.reset.submit' | translate }}\n </button>\n\n @if (resetMessage) {\n <div class=\"wuic-auth-success\">{{ resetMessage }}</div>\n }\n @if (resetError) {\n <div class=\"wuic-auth-error\">{{ resetError }}</div>\n }\n\n <div class=\"wuic-auth-links\">\n <button type=\"button\" class=\"wuic-auth-link\" (click)=\"switchAuthView('login')\">{{ 'auth.link.back_to_login'\n | translate }}</button>\n </div>\n </form>\n }\n\n }\n\n <button type=\"button\" class=\"wuic-auth-btn\" (click)=\"refreshAuthSession()\" [disabled]=\"auth.loading\">\n {{ 'auth.refresh' | translate }}\n </button>\n </div>\n\n @if (auth.error) {\n <div class=\"wuic-auth-error\">{{ auth.error }}</div>\n }\n </div>\n }\n </div>\n }\n</nav>\n}\n\n<!-- <p-megaMenu *ngIf=\"menuType=='megamenu'\" [model]=\"megaItems\">\n</p-megaMenu> -->\n\n<!-- <p-megaMenu *ngIf=\"menuType=='megamenu'\" [model]=\"megaItems2\"></p-megaMenu>\n</p-megaMenu> -->", styles: [".wuic-session-warning{display:flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background:color-mix(in srgb,var(--p-yellow-100, var(--yellow-100, #fef9c3)) 50%,var(--p-surface-card, var(--surface-card, #fff)));border-bottom:2px solid var(--p-yellow-500, var(--yellow-500, #eab308));color:var(--p-yellow-800, var(--yellow-800, #854d0e));font-size:.85rem;font-weight:500;z-index:1000}.wuic-session-warning .pi{font-size:1rem}.wuic-session-warning .wuic-auth-btn{margin-left:auto;padding:.25rem .6rem;font-size:.8rem}.wuic-auth-stage{display:block}.wuic-auth-bar-loading{display:flex;align-items:center;justify-content:center;min-height:48px;padding:.75rem 1rem}.wuic-auth-loading{display:flex;align-items:center;gap:.5rem;color:var(--p-text-color-secondary, var(--text-color-secondary, #64748b));font-size:.9rem}.wuic-auth-loading .pi-spinner{font-size:1.1rem}:host ::ng-deep .p-menubar .p-menubar-item-link[draggable=true]{cursor:grab}:host ::ng-deep .p-menubar .p-menubar-item-link[draggable=true]:active{cursor:grabbing}:host ::ng-deep .p-menubar .p-menubar-item-link:not(.p-disabled):hover{background:var(--p-content-hover-background, var(--surface-hover, #f1f5f9));color:var(--p-primary-color, var(--p-text-color, inherit))}:host-context(.theme-dark) ::ng-deep .p-menubar .p-menubar-item-link:not(.p-disabled):hover{background:color-mix(in srgb,var(--p-content-hover-background, #1f2937) 80%,var(--p-primary-color, #3b82f6) 20%);color:var(--p-primary-color, var(--p-text-color, #f3f4f6))}.wuic-menubar-extra{display:flex;align-items:center;gap:.75rem;min-width:280px;justify-content:flex-end;padding-left:.75rem}.wuic-menubar-user-flag{width:2rem;height:2rem;border-radius:999px;display:block;border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));background:var(--p-content-background, var(--surface-section, #eef3f8));object-fit:cover;flex:0 0 auto}.wuic-menubar-user-wrap{position:relative;display:flex;align-items:center;gap:.55rem;cursor:pointer}.wuic-menubar-user-caret{font-size:.8rem;color:var(--p-text-muted-color, var(--text-color-secondary, #4f6479))}.wuic-menubar-user{display:grid;line-height:1.15;text-align:right;min-width:0}.wuic-language-menu{position:absolute;top:calc(100% + .45rem);right:0;min-width:170px;background:var(--p-surface-card, var(--surface-card, #fff));border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));border-radius:8px;box-shadow:0 10px 28px color-mix(in srgb,var(--p-text-color, #1f2f43) 16%,transparent);z-index:1100;padding:.3rem}.wuic-language-item{width:100%;border:0;background:transparent;display:flex;align-items:center;gap:.8rem;text-align:left;border-radius:6px;padding:.45rem .55rem;cursor:pointer;color:var(--p-text-color, var(--text-color, #1f2f43))}.wuic-language-item-flag{width:1.1rem;height:1.1rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d9e2ec));object-fit:cover;flex:0 0 auto}.wuic-language-item span{flex:1 1 auto}.wuic-language-item small{color:var(--p-text-muted-color, var(--text-color-secondary, #5f748a))}.wuic-language-item:hover{background:var(--p-content-hover-background, var(--surface-hover, #f5f8fb))}.wuic-language-item.is-active{background:color-mix(in srgb,var(--p-primary-color, #3b82f6) 14%,transparent);color:var(--p-primary-color, #315fdd)}:host-context(.theme-dark) .wuic-language-menu{background:var(--p-content-background, var(--surface-card, #111827));border-color:var(--p-content-border-color, var(--surface-border, rgba(255, 255, 255, .2)));box-shadow:0 10px 28px color-mix(in srgb,#000 55%,transparent),0 0 0 1px color-mix(in srgb,var(--p-content-border-color, rgba(255, 255, 255, .2)) 65%,transparent) inset}:host-context(.theme-dark) .wuic-language-item{color:var(--p-text-color, var(--text-color, #f3f4f6))}:host-context(.theme-dark) .wuic-language-item small{color:var(--p-text-muted-color, var(--text-color-secondary, #b7c3d0))}:host-context(.theme-dark) .wuic-language-item:hover{background:color-mix(in srgb,var(--p-content-hover-background, #1f2937) 85%,var(--p-primary-color, #3b82f6) 15%)}:host-context(.theme-dark) .wuic-language-item.is-active{background:color-mix(in srgb,var(--p-primary-color, #3b82f6) 30%,transparent);color:var(--p-primary-contrast-color, #e7f0ff)}.wuic-menubar-user-name{font-weight:600;color:var(--p-text-color, var(--text-color, #1f2f43));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.wuic-menubar-user-role{font-size:.75rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}.wuic-role-badge{display:inline-flex;align-items:center;max-width:100%;padding:.15rem .5rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d4deea));background:var(--p-content-background, var(--surface-section, #f3f7fb));color:var(--p-text-muted-color, var(--text-color-secondary, #4a6077));font-size:.72rem;font-weight:600}.wuic-role-badge-admin{border-color:color-mix(in srgb,var(--p-yellow-500, var(--yellow-500, #f59e0b)) 55%,var(--p-content-border-color, var(--surface-border, #d4deea)));background:color-mix(in srgb,var(--p-yellow-100, var(--yellow-100, #fff6df)) 30%,var(--p-surface-card, var(--surface-card, #fff)));color:color-mix(in srgb,var(--p-yellow-700, var(--yellow-700, #9a5a00)) 80%,var(--p-text-color, var(--text-color, #233242)))}.wuic-menubar-logout{white-space:nowrap;padding-inline:.8rem}.wuic-license-badge{display:inline-flex;align-items:center;gap:.35rem;padding:.25rem .6rem;border-radius:999px;border:1px solid var(--p-content-border-color, var(--surface-border, #d4deea));background:var(--p-content-background, var(--surface-section, #f3f7fb));color:var(--p-text-muted-color, var(--text-color-secondary, #4a6077));font-size:.72rem;font-weight:700;letter-spacing:.02em;cursor:default;white-space:nowrap;-webkit-user-select:none;user-select:none}.wuic-license-badge .pi{font-size:.85rem}.wuic-license-badge-label{line-height:1}.wuic-license-badge-pro{border-color:color-mix(in srgb,var(--p-emerald-500, #10b981) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-emerald-100, #d1fae5) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-emerald-700, #047857) 80%,var(--p-text-color, #233242))}.wuic-license-badge-dev{border-color:color-mix(in srgb,var(--p-blue-500, #3b82f6) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-blue-100, #dbeafe) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-blue-700, #1d4ed8) 80%,var(--p-text-color, #233242))}.wuic-license-badge-trial{border-color:color-mix(in srgb,var(--p-orange-500, #f97316) 55%,var(--p-content-border-color, #d4deea));background:color-mix(in srgb,var(--p-orange-100, #ffedd5) 45%,var(--p-surface-card, #fff));color:color-mix(in srgb,var(--p-orange-700, #c2410c) 80%,var(--p-text-color, #233242))}.wuic-auth-stage-login,.wuic-auth-stage-login *{color-scheme:inherit}.wuic-auth-stage-login{--wuic-surface-ground: var(--p-surface-ground, var(--surface-ground, var(--surface-b, #f7f8fa)));--wuic-surface-card: var(--p-surface-card, var(--surface-card, var(--surface-a, #ffffff)));--wuic-surface-section: var(--p-content-background, var(--surface-section, var(--surface-c, #ffffff)));--wuic-surface-hover: var(--p-content-hover-background, var(--surface-hover, var(--surface-hover-background, #f3f4f6)));--wuic-surface-border: var(--p-content-border-color, var(--surface-border, var(--surface-d, #d7dce3)));--wuic-text: var(--p-text-color, var(--text-color, #1f2937));--wuic-text-muted: var(--p-text-muted-color, var(--text-color-secondary, #6b7280));--wuic-primary: var(--p-primary-color, var(--primary-color, #3b82f6));--wuic-primary-text: var(--p-primary-contrast-color, var(--primary-color-text, #ffffff));--wuic-danger-100: var(--p-red-100, var(--red-100, #fee2e2));--wuic-danger-500: var(--p-red-500, var(--red-500, #ef4444));--wuic-danger-700: var(--p-red-700, var(--red-700, #b91c1c));min-height:calc(100vh - 2rem);display:grid;place-items:center;padding:1rem;color:var(--wuic-text);background-color:var(--wuic-surface-ground)!important;background:radial-gradient(circle at 15% 20%,color-mix(in srgb,var(--wuic-primary) 12%,transparent),transparent 45%),radial-gradient(circle at 85% 15%,color-mix(in srgb,var(--wuic-primary) 8%,transparent),transparent 40%),linear-gradient(180deg,var(--wuic-surface-ground) 0%,var(--wuic-surface-ground) 100%)!important}:host-context(.theme-dark) .wuic-auth-stage-login{--wuic-surface-ground: var(--p-surface-900, var(--p-content-background, var(--surface-b, #0f172a)));--wuic-surface-card: var(--p-content-background, var(--p-surface-800, var(--surface-a, #111827)));--wuic-surface-section: var(--p-content-background, var(--p-surface-800, var(--surface-c, #1f2937)));--wuic-surface-hover: var(--p-content-hover-background, var(--p-surface-700, var(--surface-hover-background, #374151)));--wuic-surface-border: var(--p-content-border-color, var(--surface-d, rgba(255, 255, 255, .28)));--wuic-text: var(--p-content-color, var(--p-text-color, var(--text-color, #f3f4f6)));--wuic-text-muted: var(--p-text-muted-color, var(--text-color-secondary, #d1d5db))}:host-context(.theme-dark) .wuic-auth-bar,:host-context(.theme-dark) .wuic-auth-bar-login{background:var(--wuic-surface-card)!important;color:var(--wuic-text)!important;border-color:var(--wuic-surface-border)!important}:host-context(.theme-dark) .wuic-auth-form label,:host-context(.theme-dark) .wuic-auth-status,:host-context(.theme-dark) .wuic-auth-bar span,:host-context(.theme-dark) .wuic-auth-bar strong{color:var(--wuic-text)!important}:host-context(.theme-dark) .wuic-auth-form input{background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-color:var(--wuic-surface-border)!important}:host-context(.theme-dark) .wuic-auth-form input::placeholder{color:var(--wuic-text-muted)!important}:host-context(.theme-dark) .wuic-auth-btn{background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-color:color-mix(in srgb,var(--wuic-surface-border) 75%,white 25%)!important}:host-context(.theme-dark) .wuic-auth-btn-primary{background:var(--wuic-primary)!important;border-color:var(--wuic-primary)!important;color:var(--wuic-primary-text)!important}.wuic-auth-bar{display:grid;gap:.5rem;padding:.6rem .75rem;border:1px solid var(--wuic-surface-border);border-top:0;background:var(--wuic-surface-card)!important;color:var(--wuic-text)!important}.wuic-auth-bar-login{width:min(420px,92vw);gap:1rem;padding:1.15rem 1.2rem;border-radius:14px;border:1px solid var(--wuic-surface-border)!important;background:var(--wuic-surface-card)!important;box-shadow:0 14px 40px color-mix(in srgb,var(--wuic-text) 12%,transparent),0 0 0 1px color-mix(in srgb,var(--wuic-surface-border) 65%,transparent) inset}.wuic-auth-status{font-size:.9rem;color:var(--wuic-text)!important;margin-bottom:.1rem;line-height:1.35}.wuic-auth-form{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.wuic-auth-form-login{flex-direction:column;align-items:stretch;gap:.75rem}.wuic-auth-form-login form{display:grid;gap:.5rem;margin:0}.wuic-auth-form label{font-size:.85rem;color:var(--wuic-text)!important}.wuic-auth-form-login label{font-weight:600;margin-top:0}.wuic-auth-form input{min-width:220px;flex:1 1 320px;border:1px solid var(--wuic-surface-border);border-radius:6px;padding:.45rem .6rem;background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;box-shadow:0 0 0 1px color-mix(in srgb,var(--wuic-surface-border) 35%,transparent) inset}.wuic-auth-form input::placeholder{color:var(--wuic-text-muted);opacity:1}.wuic-auth-form input:focus{outline:none;border-color:var(--wuic-primary);box-shadow:0 0 0 1px color-mix(in srgb,var(--wuic-primary) 55%,transparent) inset,0 0 0 .15rem color-mix(in srgb,var(--wuic-primary) 22%,transparent)}.wuic-auth-form-login input{min-width:0;width:100%;flex:initial}.wuic-auth-btn{border:1px solid var(--wuic-surface-border);background:var(--wuic-surface-section)!important;color:var(--wuic-text)!important;border-radius:6px;padding:.45rem .75rem;cursor:pointer;transition:background-color .12s ease,border-color .12s ease,color .12s ease,box-shadow .12s ease}.wuic-auth-form-login .wuic-auth-btn{width:100%;justify-content:center}.wuic-auth-form-login>.wuic-auth-btn:not(.wuic-auth-btn-primary){margin-top:.2rem}.wuic-auth-btn:disabled{opacity:.5;cursor:default}.wuic-auth-btn:not(:disabled):hover{background:var(--wuic-surface-hover)!important;border-color:color-mix(in srgb,var(--wuic-primary) 35%,var(--wuic-surface-border))}.wuic-auth-btn:not(:disabled):focus-visible{outline:none;box-shadow:0 0 0 .15rem color-mix(in srgb,var(--wuic-primary) 20%,transparent)}.wuic-auth-btn-primary{background:var(--wuic-primary)!important;border-color:var(--wuic-primary)!important;color:var(--wuic-primary-text)!important}.wuic-auth-btn-primary:not(:disabled):hover{background:color-mix(in srgb,var(--wuic-primary) 88%,black 12%)!important;border-color:color-mix(in srgb,var(--wuic-primary) 88%,black 12%)!important;color:var(--wuic-primary-text)!important}.wuic-captcha{margin:.25rem 0}.wuic-auth-error{color:var(--wuic-danger-700);font-size:.85rem;background:color-mix(in srgb,var(--wuic-danger-100) 22%,var(--wuic-surface-card));border:1px solid color-mix(in srgb,var(--wuic-danger-500) 35%,var(--wuic-surface-border));border-radius:8px;padding:.5rem .65rem}.wuic-auth-success{color:var(--p-green-700, var(--green-700, #15803d));font-size:.85rem;background:color-mix(in srgb,var(--p-green-100, var(--green-100, #dcfce7)) 22%,var(--wuic-surface-card));border:1px solid color-mix(in srgb,var(--p-green-500, var(--green-500, #22c55e)) 35%,var(--wuic-surface-border));border-radius:8px;padding:.5rem .65rem}.wuic-auth-links{display:flex;justify-content:center;gap:1.25rem;margin-top:.1rem}.wuic-auth-link{appearance:none;background:transparent;border:none;padding:0;margin:0;font:inherit;font-size:.82rem;color:color-mix(in srgb,var(--wuic-primary) 60%,#0f172a 40%);cursor:pointer;text-decoration:underline;text-underline-offset:2px}.wuic-auth-link:hover{color:color-mix(in srgb,var(--wuic-primary) 40%,#0f172a 60%)}@media(max-width:768px){.wuic-menubar-extra{min-width:0;gap:.5rem}.wuic-menubar-user-name,.wuic-menubar-user-role{max-width:130px}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list,:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu{overflow-x:hidden!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list{max-height:calc(100vh - 13rem);overflow-y:auto!important;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu{width:100%!important;margin-left:0!important;max-height:none;overflow-y:visible!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-submenu>.p-menubar-item{width:100%!important;float:none!important}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-item-link{white-space:normal;word-break:break-word}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu{display:grid;grid-template-columns:minmax(0,1fr);gap:0}:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu>.p-menubar-item>.p-menubar-item-link{padding-top:.5rem;padding-bottom:.5rem}}@media(max-width:768px)and (min-width:560px){:host ::ng-deep .p-menubar.p-menubar-mobile-active .p-menubar-root-list>.p-menubar-item>.p-menubar-submenu{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:.25rem}}:host ::ng-deep .p-contextmenu{z-index:13000!important}:host ::ng-deep .p-menubar-item-link[draggable=true]{cursor:grab}:host ::ng-deep .p-menubar-item-link[draggable=true]:active{cursor:grabbing}.wuic-menu-move-actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.75rem}.wuic-be-offline-banner{background:#dc354514;border-bottom:2px solid rgba(220,53,69,.6)}.wuic-be-offline-content{display:flex;align-items:center;gap:.75rem;padding:.5rem 1rem;width:100%;max-width:720px;margin:0 auto}.wuic-be-offline-icon{color:#dc3545;font-size:1.5rem;flex-shrink:0}.wuic-be-offline-text{display:flex;flex-direction:column;flex:1 1 auto;min-width:0}.wuic-be-offline-text strong{color:#842029;font-size:.95rem}.wuic-be-offline-text span{color:#58151c;font-size:.8rem;opacity:.85}.wuic-be-offline-retry{display:inline-flex;align-items:center;gap:.4rem;padding:.45rem .9rem;background:#dc3545;color:#fff;border:1px solid #b02a37;border-radius:4px;font-weight:600;font-size:.85rem;cursor:pointer;flex-shrink:0;transition:background-color .12s ease}.wuic-be-offline-retry:hover{background:#bb2d3b}.wuic-be-offline-retry:active{background:#a52834}.wuic-be-offline-retry i{font-size:.9rem}\n"] }]
|
|
45076
45249
|
}], ctorParameters: () => [{ type: MetadataProviderService }, { type: AuthSessionService }, { type: TranslationManagerService }, { type: UserInfoService }, { type: WorkflowRuntimeMenuService }, { type: i1$1.HttpClient }, { type: i0.NgZone }, { type: i1$2.Router }, { type: LicenseFeatureService }, { type: i0.ElementRef }], propDecorators: { menu: [{
|
|
45077
45250
|
type: ViewChild,
|
|
45078
45251
|
args: ['menubar']
|
|
@@ -45177,7 +45350,7 @@ class LazyFirstRunWizardComponent {
|
|
|
45177
45350
|
this.cdr = cdr;
|
|
45178
45351
|
}
|
|
45179
45352
|
async ngOnInit() {
|
|
45180
|
-
firstRunWizardComponentPromise ??= import('./wuic-framework-lib-first-run-wizard.component-
|
|
45353
|
+
firstRunWizardComponentPromise ??= import('./wuic-framework-lib-first-run-wizard.component-CaGePYLi.mjs').then((m) => m.WuicFirstRunWizardComponent);
|
|
45181
45354
|
const componentClass = await firstRunWizardComponentPromise;
|
|
45182
45355
|
this.componentRef = this.vcr.createComponent(componentClass);
|
|
45183
45356
|
// Forward output del componente reale al wrapper. Type assertion necessaria
|
|
@@ -56821,7 +56994,7 @@ class LazyCodeEditorComponent {
|
|
|
56821
56994
|
this.cdr = cdr;
|
|
56822
56995
|
}
|
|
56823
56996
|
async ngOnInit() {
|
|
56824
|
-
codeEditorComponentPromise ??= import('./wuic-framework-lib-code-editor.component-
|
|
56997
|
+
codeEditorComponentPromise ??= import('./wuic-framework-lib-code-editor.component-4N95qt3D.mjs').then((m) => m.CodeEditorComponent);
|
|
56825
56998
|
this.loadedComponent = await codeEditorComponentPromise;
|
|
56826
56999
|
this.cdr.markForCheck();
|
|
56827
57000
|
}
|
|
@@ -58608,7 +58781,7 @@ class DesignerRouteComponent {
|
|
|
58608
58781
|
* Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
|
|
58609
58782
|
*/
|
|
58610
58783
|
async ngOnInit() {
|
|
58611
|
-
designerComponentPromise ??= import('./wuic-framework-lib-designer.component-
|
|
58784
|
+
designerComponentPromise ??= import('./wuic-framework-lib-designer.component-pW1YK-oY.mjs').then((m) => m.DesignerComponent);
|
|
58612
58785
|
this.loadedComponent = await designerComponentPromise;
|
|
58613
58786
|
}
|
|
58614
58787
|
/**
|
|
@@ -58685,7 +58858,7 @@ class LazyPivotBuilderComponent {
|
|
|
58685
58858
|
this.cdr = cdr;
|
|
58686
58859
|
}
|
|
58687
58860
|
async ngOnInit() {
|
|
58688
|
-
pivotBuilderComponentPromise ??= import('./wuic-framework-lib-pivot-builder.component-
|
|
58861
|
+
pivotBuilderComponentPromise ??= import('./wuic-framework-lib-pivot-builder.component-VIs0CIH_.mjs').then((m) => m.PivotBuilderComponent);
|
|
58689
58862
|
this.loadedComponent = await pivotBuilderComponentPromise;
|
|
58690
58863
|
this.cdr.markForCheck();
|
|
58691
58864
|
}
|
|
@@ -58724,7 +58897,7 @@ class WorkflowDesignerRouteComponent {
|
|
|
58724
58897
|
* Inizializza il componente preparando stato, sottoscrizioni e primi caricamenti richiesti.
|
|
58725
58898
|
*/
|
|
58726
58899
|
async ngOnInit() {
|
|
58727
|
-
workflowDesignerComponentPromise ??= import('./wuic-framework-lib-workflow-designer.component-
|
|
58900
|
+
workflowDesignerComponentPromise ??= import('./wuic-framework-lib-workflow-designer.component-4RC2EkGA.mjs').then((m) => m.WorkflowDesignerComponent);
|
|
58728
58901
|
this.loadedComponent = await workflowDesignerComponentPromise;
|
|
58729
58902
|
}
|
|
58730
58903
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: WorkflowDesignerRouteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -58781,7 +58954,7 @@ class LazyReportDesignerComponent {
|
|
|
58781
58954
|
this.cdr = cdr;
|
|
58782
58955
|
}
|
|
58783
58956
|
async ngOnInit() {
|
|
58784
|
-
reportDesignerComponentPromise ??= import('./wuic-framework-lib-report-designer.component-
|
|
58957
|
+
reportDesignerComponentPromise ??= import('./wuic-framework-lib-report-designer.component-FiAwNkPM.mjs').then((m) => m.ReportDesignerComponent);
|
|
58785
58958
|
this.loadedComponent = await reportDesignerComponentPromise;
|
|
58786
58959
|
this.cdr.markForCheck();
|
|
58787
58960
|
}
|
|
@@ -58836,7 +59009,7 @@ class LazyReportViewerComponent {
|
|
|
58836
59009
|
this.cdr = cdr;
|
|
58837
59010
|
}
|
|
58838
59011
|
async ngOnInit() {
|
|
58839
|
-
reportViewerComponentPromise ??= import('./wuic-framework-lib-report-viewer.component-
|
|
59012
|
+
reportViewerComponentPromise ??= import('./wuic-framework-lib-report-viewer.component-DY0dGMrt.mjs').then((m) => m.ReportViewerComponent);
|
|
58840
59013
|
this.loadedComponent = await reportViewerComponentPromise;
|
|
58841
59014
|
this.cdr.markForCheck();
|
|
58842
59015
|
}
|
|
@@ -58864,6 +59037,8 @@ class KanbanListComponent {
|
|
|
58864
59037
|
trslSrv;
|
|
58865
59038
|
dataProviderSrv;
|
|
58866
59039
|
userInfo;
|
|
59040
|
+
cdr;
|
|
59041
|
+
ngZone;
|
|
58867
59042
|
hardcodedRoute;
|
|
58868
59043
|
parentRecord;
|
|
58869
59044
|
parentMetaInfo;
|
|
@@ -58905,11 +59080,13 @@ class KanbanListComponent {
|
|
|
58905
59080
|
datasourceReadySubscription;
|
|
58906
59081
|
fetchInfoSubscription;
|
|
58907
59082
|
pendingChanges = new Map();
|
|
58908
|
-
constructor(router, trslSrv, dataProviderSrv, userInfo) {
|
|
59083
|
+
constructor(router, trslSrv, dataProviderSrv, userInfo, cdr, ngZone) {
|
|
58909
59084
|
this.router = router;
|
|
58910
59085
|
this.trslSrv = trslSrv;
|
|
58911
59086
|
this.dataProviderSrv = dataProviderSrv;
|
|
58912
59087
|
this.userInfo = userInfo;
|
|
59088
|
+
this.cdr = cdr;
|
|
59089
|
+
this.ngZone = ngZone;
|
|
58913
59090
|
}
|
|
58914
59091
|
t(key, fallback) {
|
|
58915
59092
|
const translated = this.trslSrv?.instant?.(key);
|
|
@@ -59126,16 +59303,43 @@ class KanbanListComponent {
|
|
|
59126
59303
|
// se lookup non pronta). POI aspetta async lookup + rebuildBoard di nuovo.
|
|
59127
59304
|
// setTimeout per re-enter Angular zone (ensureLookup completes in microtask
|
|
59128
59305
|
// outside zone in alcuni scenari Playwright headless → CD non scatta).
|
|
59129
|
-
|
|
59306
|
+
//
|
|
59307
|
+
// FIX 2026-05-22 (refresh): cdr.detectChanges() + ngZone.run() per forzare
|
|
59308
|
+
// CD quando la Promise risolve fuori NgZone (sintomo: tutte le card in
|
|
59309
|
+
// unassigned, altre colonne compaiono solo al primo evento utente).
|
|
59310
|
+
//
|
|
59311
|
+
// FIX 2026-05-22 (navigation): differenza chiave navigation vs refresh:
|
|
59312
|
+
// - refresh → datasource.value=null all'init → branch datasourceReady
|
|
59313
|
+
// waits async → subscribe FUORI da ngOnInit CD cycle → tutto OK.
|
|
59314
|
+
// - navigation → datasource.value gia' pronto → subscribe SINCRONO
|
|
59315
|
+
// dentro ngOnInit → fetchInfo$ BehaviorSubject emette sync nella
|
|
59316
|
+
// stessa stack frame di ngOnInit → siamo gia' dentro un CD cycle del
|
|
59317
|
+
// parent → cdr.detectChanges() sincrono qui o fallisce con
|
|
59318
|
+
// ExpressionChangedAfterCheckedError (dev) o e' silent-no-op.
|
|
59319
|
+
// Soluzione: differire l'intero handling al prossimo microtask via
|
|
59320
|
+
// `Promise.resolve().then(...)`. Cosi' ngOnInit completa, la CD cycle
|
|
59321
|
+
// termina, poi il nostro callback rebuilda con CD pulita.
|
|
59322
|
+
Promise.resolve().then(() => {
|
|
59323
|
+
this.ngZone.run(() => {
|
|
59324
|
+
this.rebuildBoard();
|
|
59325
|
+
this.cdr.detectChanges();
|
|
59326
|
+
this.onKanbanDataBound.emit({
|
|
59327
|
+
metaInfo: this.metaInfo,
|
|
59328
|
+
columns: this.columns,
|
|
59329
|
+
unassignedCards: this.unassignedCards
|
|
59330
|
+
});
|
|
59331
|
+
});
|
|
59332
|
+
});
|
|
59130
59333
|
this.ensureLookupStatusColumnsLoaded().then(() => {
|
|
59131
|
-
|
|
59334
|
+
this.ngZone.run(() => {
|
|
59132
59335
|
this.rebuildBoard();
|
|
59336
|
+
this.cdr.detectChanges();
|
|
59133
59337
|
this.onKanbanDataBound.emit({
|
|
59134
59338
|
metaInfo: this.metaInfo,
|
|
59135
59339
|
columns: this.columns,
|
|
59136
59340
|
unassignedCards: this.unassignedCards
|
|
59137
59341
|
});
|
|
59138
|
-
}
|
|
59342
|
+
});
|
|
59139
59343
|
});
|
|
59140
59344
|
this.onKanbanDataBound.emit({
|
|
59141
59345
|
metaInfo: this.metaInfo,
|
|
@@ -59720,7 +59924,15 @@ class KanbanListComponent {
|
|
|
59720
59924
|
// (Playwright headless con dispatcher applyPatch → invalidateMetadataRuntime
|
|
59721
59925
|
// → re-bind boundaryRepeater → kanban subscribe nuova chain in cui CD
|
|
59722
59926
|
// detection async non si attiva senza un macrotask boundary).
|
|
59723
|
-
|
|
59927
|
+
//
|
|
59928
|
+
// FIX 2026-05-22: setTimeout(0) NON e' sufficiente se il dataProviderSrv
|
|
59929
|
+
// ritorna fuori NgZone (sintomo: su navigazione SPA tutte le card finiscono
|
|
59930
|
+
// in unassigned, e solo dopo evento utente compaiono le altre colonne).
|
|
59931
|
+
// Wrap esplicito in ngZone.run() + cdr.detectChanges() force.
|
|
59932
|
+
this.ngZone.run(() => {
|
|
59933
|
+
this.rebuildBoard();
|
|
59934
|
+
this.cdr.detectChanges();
|
|
59935
|
+
});
|
|
59724
59936
|
}
|
|
59725
59937
|
catch (err) {
|
|
59726
59938
|
this.lookupDerivedStatusColumns = [];
|
|
@@ -59731,13 +59943,13 @@ class KanbanListComponent {
|
|
|
59731
59943
|
this.lookupColumnsLoading = false;
|
|
59732
59944
|
}
|
|
59733
59945
|
}
|
|
59734
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: KanbanListComponent, deps: [{ token: i1$2.Router }, { token: TranslationManagerService }, { token: DataProviderService }, { token: UserInfoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
59946
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: KanbanListComponent, deps: [{ token: i1$2.Router }, { token: TranslationManagerService }, { token: DataProviderService }, { token: UserInfoService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
59735
59947
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: KanbanListComponent, isStandalone: true, selector: "wuic-kanban-list", inputs: { hardcodedRoute: "hardcodedRoute", parentRecord: "parentRecord", parentMetaInfo: "parentMetaInfo", datasource: "datasource", hardcodedDatasource: "hardcodedDatasource", hideToolbar: "hideToolbar" }, outputs: { onKanbanDataBound: "onKanbanDataBound", onKanbanCardDrop: "onKanbanCardDrop", onKanbanCardClick: "onKanbanCardClick", onKanbanBatchSave: "onKanbanBatchSave", onKanbanBatchCancel: "onKanbanBatchCancel", onKanbanConfigApplied: "onKanbanConfigApplied" }, ngImport: i0, template: "<div class=\"kanban-root\">\n @if (!hideToolbar) {\n <div class=\"kanban-toolbar\">\n @if (isAdmin) {\n <p-button [label]=\"'kanban.configure' | translate\" icon=\"pi pi-cog\" (onClick)=\"openKanbanConfig()\"></p-button>\n }\n @if (canAddCard) {\n <p-button [label]=\"'add' | translate\" icon=\"pi pi-plus\" (onClick)=\"addRecord()\"></p-button>\n }\n @if (kanbanOptions?.persistMode === 'batch') {\n <p-button [label]=\"'kanban.save_changes' | translate\" icon=\"pi pi-save\" [disabled]=\"!hasPendingChanges || savingBatch\" (onClick)=\"saveBatchChanges()\"></p-button>\n <p-button [label]=\"'kanban.discard_changes' | translate\" icon=\"pi pi-undo\" severity=\"secondary\" [disabled]=\"!hasPendingChanges || savingBatch\" (onClick)=\"cancelBatchChanges()\"></p-button>\n }\n </div>\n }\n\n @if (warningMessage) {\n <div class=\"kanban-warning\">{{ warningMessage }}</div>\n }\n\n @if (canRenderBoard) {\n <div class=\"kanban-board\" cdkDropListGroup>\n <div class=\"kanban-column kanban-column-unassigned\">\n <div class=\"kanban-column-header\">\n <span class=\"kanban-column-title\">{{ 'kanban.unassigned' | translate }}</span>\n <span class=\"kanban-column-count\">{{ unassignedCards.length }}</span>\n </div>\n\n <div class=\"kanban-column-body\" cdkDropList [id]=\"unassignedDropListId\" [cdkDropListData]=\"unassignedCards\"\n [cdkDropListConnectedTo]=\"connectedDropListIds\" (cdkDropListDropped)=\"onDrop($event, null)\">\n @for (card of unassignedCards; track trackCard($index, card)) {\n <div class=\"kanban-card\" cdkDrag (click)=\"onCardClick(card, $event)\">\n <div class=\"kanban-card-actions\" (click)=\"$event.stopPropagation()\">\n <wuic-data-action-button-lazy [data]=\"card.record\" [metaInfo]=\"metaInfo\" [datasource]=\"datasource\">\n </wuic-data-action-button-lazy>\n </div>\n <div class=\"kanban-card-title\">{{ card.title || '-' }}</div>\n @if (card.subtitle) {\n <div class=\"kanban-card-subtitle\">{{ card.subtitle }}</div>\n }\n @if (card.description) {\n <div class=\"kanban-card-description\">{{ card.description }}</div>\n }\n @if (card.assignedUserLabel) {\n <div class=\"kanban-card-subtitle\">{{ 'kanban.assignee' | translate }}: {{ card.assignedUserLabel }}</div>\n }\n </div>\n }\n </div>\n </div>\n\n @for (column of columns; track trackColumn($index, column)) {\n <div class=\"kanban-column\" [ngStyle]=\"getColumnStyle(column)\">\n <div class=\"kanban-column-header\">\n <span class=\"kanban-column-title\">{{ column.label }}</span>\n <span class=\"kanban-column-count\">{{ column.cards.length }}</span>\n </div>\n\n <div class=\"kanban-column-body\" cdkDropList [id]=\"column.id\" [cdkDropListData]=\"column.cards\"\n [cdkDropListConnectedTo]=\"connectedDropListIds\" (cdkDropListDropped)=\"onDrop($event, column)\">\n @for (card of column.cards; track trackCard($index, card)) {\n <div class=\"kanban-card\" cdkDrag (click)=\"onCardClick(card, $event)\">\n <div class=\"kanban-card-actions\" (click)=\"$event.stopPropagation()\">\n <wuic-data-action-button-lazy [data]=\"card.record\" [metaInfo]=\"metaInfo\" [datasource]=\"datasource\">\n </wuic-data-action-button-lazy>\n </div>\n <div class=\"kanban-card-title\">{{ card.title || '-' }}</div>\n @if (card.subtitle) {\n <div class=\"kanban-card-subtitle\">{{ card.subtitle }}</div>\n }\n @if (card.description) {\n <div class=\"kanban-card-description\">{{ card.description }}</div>\n }\n @if (card.assignedUserLabel) {\n <div class=\"kanban-card-subtitle\">{{ 'kanban.assignee' | translate }}: {{ card.assignedUserLabel }}</div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n</div>\n\n<wuic-archetype-configurator [visible]=\"showConfigDialog\" (visibleChange)=\"showConfigDialog = $event\" [archetype]=\"'kanban'\"\n [metaInfo]=\"metaInfo\" [value]=\"kanbanOptions\" (applyConfig)=\"applyKanbanConfig($event)\">\n</wuic-archetype-configurator>\r\n", styles: [":host{display:block;width:100%;height:100%;min-height:0;--kanban-surface: var(--p-content-background, var(--p-surface-0, #ffffff));--kanban-surface-alt: var(--p-surface-100, #f8fafc);--kanban-card-surface: var(--p-surface-0, #ffffff);--kanban-border: var(--p-content-border-color, var(--p-divider-color, #dcdcdc));--kanban-text: var(--p-text-color, #111827);--kanban-text-muted: var(--p-text-muted-color, #6b7280);--kanban-accent: var(--p-primary-color, #3b82f6);--kanban-header-text: var(--p-primary-contrast-color, #ffffff)}.kanban-root{display:flex;flex-direction:column;gap:.75rem;height:100%;min-height:0}.kanban-toolbar{display:flex;gap:.5rem;align-items:center}.kanban-warning{border:1px solid color-mix(in srgb,var(--kanban-accent) 40%,var(--kanban-border) 60%);background:color-mix(in srgb,var(--kanban-accent) 14%,var(--kanban-surface) 86%);color:var(--kanban-text);border-radius:8px;padding:.6rem .75rem}.kanban-board{display:flex;gap:.75rem;align-items:stretch;flex:1 1 auto;min-height:0;width:100%;overflow-x:auto;overflow-y:hidden;padding-bottom:.35rem}.kanban-column{flex:1 1 0;min-width:0;width:auto;max-width:none;background:var(--kanban-surface-alt);border:1px solid var(--kanban-border);border-radius:10px;display:flex;flex-direction:column;height:100%;min-height:0}.kanban-column-unassigned{border-style:dashed;border-color:color-mix(in srgb,var(--kanban-accent) 35%,var(--kanban-border) 65%)}.kanban-column-header{display:flex;align-items:center;justify-content:space-between;padding:.6rem .65rem;border-bottom:1px solid var(--kanban-border);background:var(--kanban-column-color, color-mix(in srgb, var(--kanban-accent) 16%, var(--kanban-surface) 84%));color:var(--kanban-header-text);border-top-left-radius:10px;border-top-right-radius:10px}.kanban-column-title{font-weight:700}.kanban-column-count{font-size:.82rem;border-radius:999px;padding:.12rem .45rem;background:color-mix(in srgb,var(--kanban-header-text) 22%,transparent);color:inherit}.kanban-column-body{display:flex;flex-direction:column;gap:.55rem;flex:1 1 auto;min-height:0;padding:.6rem;overflow-y:auto;overflow-x:visible}.kanban-card{border:1px solid var(--kanban-border);border-radius:8px;padding:.55rem;background:var(--kanban-card-surface);color:var(--kanban-text);box-shadow:0 1px 2px #0000000f;cursor:pointer}.kanban-card-actions{display:flex;justify-content:flex-end;margin-bottom:.35rem}.kanban-card-title{font-weight:700;margin-bottom:.2rem}.kanban-card-subtitle{font-size:.85rem;color:var(--kanban-text-muted);margin-bottom:.25rem}.kanban-card-description{font-size:.9rem;color:var(--kanban-text)}:host-context(.theme-dark){--kanban-surface: var(--p-surface-900, #0f172a);--kanban-surface-alt: var(--p-surface-800, #1e293b);--kanban-card-surface: var(--p-surface-800, #1f2937);--kanban-border: var(--p-content-border-color, #334155);--kanban-text: var(--p-text-color, #e5e7eb);--kanban-text-muted: var(--p-text-muted-color, #cbd5e1)}:host-context(.theme-dark) .kanban-card{box-shadow:0 2px 8px #00000059}.cdk-drag-preview{box-sizing:border-box;border-radius:8px;box-shadow:0 5px 12px #0003}.cdk-drag-placeholder{opacity:.3}@media(max-width:768px){.kanban-column{flex:0 0 240px;min-width:240px}.kanban-column-body{overflow-y:auto;overflow-x:hidden}.kanban-card{min-width:0;overflow:hidden}.kanban-card,.kanban-card-title,.kanban-card-subtitle,.kanban-card-description{overflow-wrap:anywhere;word-break:break-word;white-space:normal}}\n"], dependencies: [{ kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5$4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i5$4.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i5$4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: LazyDataActionButtonComponent, selector: "wuic-data-action-button-lazy", inputs: ["data", "metaInfo", "datasource", "filter", "simplified", "parentField"] }, { kind: "component", type: ArchetypeConfiguratorComponent, selector: "wuic-archetype-configurator", inputs: ["visible", "archetype", "metaInfo", "value"], outputs: ["visibleChange", "applyConfig"] }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }] });
|
|
59736
59948
|
}
|
|
59737
59949
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: KanbanListComponent, decorators: [{
|
|
59738
59950
|
type: Component,
|
|
59739
59951
|
args: [{ selector: 'wuic-kanban-list', imports: [DragDropModule, ButtonModule, TranslateModule, NgStyle, LazyDataActionButtonComponent, ArchetypeConfiguratorComponent], template: "<div class=\"kanban-root\">\n @if (!hideToolbar) {\n <div class=\"kanban-toolbar\">\n @if (isAdmin) {\n <p-button [label]=\"'kanban.configure' | translate\" icon=\"pi pi-cog\" (onClick)=\"openKanbanConfig()\"></p-button>\n }\n @if (canAddCard) {\n <p-button [label]=\"'add' | translate\" icon=\"pi pi-plus\" (onClick)=\"addRecord()\"></p-button>\n }\n @if (kanbanOptions?.persistMode === 'batch') {\n <p-button [label]=\"'kanban.save_changes' | translate\" icon=\"pi pi-save\" [disabled]=\"!hasPendingChanges || savingBatch\" (onClick)=\"saveBatchChanges()\"></p-button>\n <p-button [label]=\"'kanban.discard_changes' | translate\" icon=\"pi pi-undo\" severity=\"secondary\" [disabled]=\"!hasPendingChanges || savingBatch\" (onClick)=\"cancelBatchChanges()\"></p-button>\n }\n </div>\n }\n\n @if (warningMessage) {\n <div class=\"kanban-warning\">{{ warningMessage }}</div>\n }\n\n @if (canRenderBoard) {\n <div class=\"kanban-board\" cdkDropListGroup>\n <div class=\"kanban-column kanban-column-unassigned\">\n <div class=\"kanban-column-header\">\n <span class=\"kanban-column-title\">{{ 'kanban.unassigned' | translate }}</span>\n <span class=\"kanban-column-count\">{{ unassignedCards.length }}</span>\n </div>\n\n <div class=\"kanban-column-body\" cdkDropList [id]=\"unassignedDropListId\" [cdkDropListData]=\"unassignedCards\"\n [cdkDropListConnectedTo]=\"connectedDropListIds\" (cdkDropListDropped)=\"onDrop($event, null)\">\n @for (card of unassignedCards; track trackCard($index, card)) {\n <div class=\"kanban-card\" cdkDrag (click)=\"onCardClick(card, $event)\">\n <div class=\"kanban-card-actions\" (click)=\"$event.stopPropagation()\">\n <wuic-data-action-button-lazy [data]=\"card.record\" [metaInfo]=\"metaInfo\" [datasource]=\"datasource\">\n </wuic-data-action-button-lazy>\n </div>\n <div class=\"kanban-card-title\">{{ card.title || '-' }}</div>\n @if (card.subtitle) {\n <div class=\"kanban-card-subtitle\">{{ card.subtitle }}</div>\n }\n @if (card.description) {\n <div class=\"kanban-card-description\">{{ card.description }}</div>\n }\n @if (card.assignedUserLabel) {\n <div class=\"kanban-card-subtitle\">{{ 'kanban.assignee' | translate }}: {{ card.assignedUserLabel }}</div>\n }\n </div>\n }\n </div>\n </div>\n\n @for (column of columns; track trackColumn($index, column)) {\n <div class=\"kanban-column\" [ngStyle]=\"getColumnStyle(column)\">\n <div class=\"kanban-column-header\">\n <span class=\"kanban-column-title\">{{ column.label }}</span>\n <span class=\"kanban-column-count\">{{ column.cards.length }}</span>\n </div>\n\n <div class=\"kanban-column-body\" cdkDropList [id]=\"column.id\" [cdkDropListData]=\"column.cards\"\n [cdkDropListConnectedTo]=\"connectedDropListIds\" (cdkDropListDropped)=\"onDrop($event, column)\">\n @for (card of column.cards; track trackCard($index, card)) {\n <div class=\"kanban-card\" cdkDrag (click)=\"onCardClick(card, $event)\">\n <div class=\"kanban-card-actions\" (click)=\"$event.stopPropagation()\">\n <wuic-data-action-button-lazy [data]=\"card.record\" [metaInfo]=\"metaInfo\" [datasource]=\"datasource\">\n </wuic-data-action-button-lazy>\n </div>\n <div class=\"kanban-card-title\">{{ card.title || '-' }}</div>\n @if (card.subtitle) {\n <div class=\"kanban-card-subtitle\">{{ card.subtitle }}</div>\n }\n @if (card.description) {\n <div class=\"kanban-card-description\">{{ card.description }}</div>\n }\n @if (card.assignedUserLabel) {\n <div class=\"kanban-card-subtitle\">{{ 'kanban.assignee' | translate }}: {{ card.assignedUserLabel }}</div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n</div>\n\n<wuic-archetype-configurator [visible]=\"showConfigDialog\" (visibleChange)=\"showConfigDialog = $event\" [archetype]=\"'kanban'\"\n [metaInfo]=\"metaInfo\" [value]=\"kanbanOptions\" (applyConfig)=\"applyKanbanConfig($event)\">\n</wuic-archetype-configurator>\r\n", styles: [":host{display:block;width:100%;height:100%;min-height:0;--kanban-surface: var(--p-content-background, var(--p-surface-0, #ffffff));--kanban-surface-alt: var(--p-surface-100, #f8fafc);--kanban-card-surface: var(--p-surface-0, #ffffff);--kanban-border: var(--p-content-border-color, var(--p-divider-color, #dcdcdc));--kanban-text: var(--p-text-color, #111827);--kanban-text-muted: var(--p-text-muted-color, #6b7280);--kanban-accent: var(--p-primary-color, #3b82f6);--kanban-header-text: var(--p-primary-contrast-color, #ffffff)}.kanban-root{display:flex;flex-direction:column;gap:.75rem;height:100%;min-height:0}.kanban-toolbar{display:flex;gap:.5rem;align-items:center}.kanban-warning{border:1px solid color-mix(in srgb,var(--kanban-accent) 40%,var(--kanban-border) 60%);background:color-mix(in srgb,var(--kanban-accent) 14%,var(--kanban-surface) 86%);color:var(--kanban-text);border-radius:8px;padding:.6rem .75rem}.kanban-board{display:flex;gap:.75rem;align-items:stretch;flex:1 1 auto;min-height:0;width:100%;overflow-x:auto;overflow-y:hidden;padding-bottom:.35rem}.kanban-column{flex:1 1 0;min-width:0;width:auto;max-width:none;background:var(--kanban-surface-alt);border:1px solid var(--kanban-border);border-radius:10px;display:flex;flex-direction:column;height:100%;min-height:0}.kanban-column-unassigned{border-style:dashed;border-color:color-mix(in srgb,var(--kanban-accent) 35%,var(--kanban-border) 65%)}.kanban-column-header{display:flex;align-items:center;justify-content:space-between;padding:.6rem .65rem;border-bottom:1px solid var(--kanban-border);background:var(--kanban-column-color, color-mix(in srgb, var(--kanban-accent) 16%, var(--kanban-surface) 84%));color:var(--kanban-header-text);border-top-left-radius:10px;border-top-right-radius:10px}.kanban-column-title{font-weight:700}.kanban-column-count{font-size:.82rem;border-radius:999px;padding:.12rem .45rem;background:color-mix(in srgb,var(--kanban-header-text) 22%,transparent);color:inherit}.kanban-column-body{display:flex;flex-direction:column;gap:.55rem;flex:1 1 auto;min-height:0;padding:.6rem;overflow-y:auto;overflow-x:visible}.kanban-card{border:1px solid var(--kanban-border);border-radius:8px;padding:.55rem;background:var(--kanban-card-surface);color:var(--kanban-text);box-shadow:0 1px 2px #0000000f;cursor:pointer}.kanban-card-actions{display:flex;justify-content:flex-end;margin-bottom:.35rem}.kanban-card-title{font-weight:700;margin-bottom:.2rem}.kanban-card-subtitle{font-size:.85rem;color:var(--kanban-text-muted);margin-bottom:.25rem}.kanban-card-description{font-size:.9rem;color:var(--kanban-text)}:host-context(.theme-dark){--kanban-surface: var(--p-surface-900, #0f172a);--kanban-surface-alt: var(--p-surface-800, #1e293b);--kanban-card-surface: var(--p-surface-800, #1f2937);--kanban-border: var(--p-content-border-color, #334155);--kanban-text: var(--p-text-color, #e5e7eb);--kanban-text-muted: var(--p-text-muted-color, #cbd5e1)}:host-context(.theme-dark) .kanban-card{box-shadow:0 2px 8px #00000059}.cdk-drag-preview{box-sizing:border-box;border-radius:8px;box-shadow:0 5px 12px #0003}.cdk-drag-placeholder{opacity:.3}@media(max-width:768px){.kanban-column{flex:0 0 240px;min-width:240px}.kanban-column-body{overflow-y:auto;overflow-x:hidden}.kanban-card{min-width:0;overflow:hidden}.kanban-card,.kanban-card-title,.kanban-card-subtitle,.kanban-card-description{overflow-wrap:anywhere;word-break:break-word;white-space:normal}}\n"] }]
|
|
59740
|
-
}], ctorParameters: () => [{ type: i1$2.Router }, { type: TranslationManagerService }, { type: DataProviderService }, { type: UserInfoService }], propDecorators: { hardcodedRoute: [{
|
|
59952
|
+
}], ctorParameters: () => [{ type: i1$2.Router }, { type: TranslationManagerService }, { type: DataProviderService }, { type: UserInfoService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }], propDecorators: { hardcodedRoute: [{
|
|
59741
59953
|
type: Input
|
|
59742
59954
|
}], parentRecord: [{
|
|
59743
59955
|
type: Input
|
|
@@ -61808,7 +62020,7 @@ const designerPendingChangesGuard = async (component) => {
|
|
|
61808
62020
|
const routes = [
|
|
61809
62021
|
{
|
|
61810
62022
|
path: 'framework-docs',
|
|
61811
|
-
loadComponent: () => import('./wuic-framework-lib-framework-docs.component-
|
|
62023
|
+
loadComponent: () => import('./wuic-framework-lib-framework-docs.component-m0IlS0Sl.mjs').then((m) => m.FrameworkDocsComponent),
|
|
61812
62024
|
canMatch: [menuRouteAccessCanMatchGuard],
|
|
61813
62025
|
canActivate: [menuRouteAccessCanActivateGuard],
|
|
61814
62026
|
data: {
|
|
@@ -61817,7 +62029,7 @@ const routes = [
|
|
|
61817
62029
|
},
|
|
61818
62030
|
{
|
|
61819
62031
|
path: 'framework-docs/:slug',
|
|
61820
|
-
loadComponent: () => import('./wuic-framework-lib-framework-docs.component-
|
|
62032
|
+
loadComponent: () => import('./wuic-framework-lib-framework-docs.component-m0IlS0Sl.mjs').then((m) => m.FrameworkDocsComponent),
|
|
61821
62033
|
canMatch: [menuRouteAccessCanMatchGuard],
|
|
61822
62034
|
canActivate: [menuRouteAccessCanActivateGuard],
|
|
61823
62035
|
data: {
|
|
@@ -61835,7 +62047,7 @@ const routes = [
|
|
|
61835
62047
|
},
|
|
61836
62048
|
{
|
|
61837
62049
|
path: ':route/report-designer',
|
|
61838
|
-
loadComponent: () => import('./wuic-framework-lib-report-designer.component-
|
|
62050
|
+
loadComponent: () => import('./wuic-framework-lib-report-designer.component-FiAwNkPM.mjs').then((m) => m.ReportDesignerComponent),
|
|
61839
62051
|
canMatch: [menuRouteAccessCanMatchGuard, featureRouteCanMatchGuard],
|
|
61840
62052
|
canActivate: [menuRouteAccessCanActivateGuard, featureRouteCanActivateGuard],
|
|
61841
62053
|
data: {
|
|
@@ -61845,7 +62057,7 @@ const routes = [
|
|
|
61845
62057
|
},
|
|
61846
62058
|
{
|
|
61847
62059
|
path: ':route/report-viewer',
|
|
61848
|
-
loadComponent: () => import('./wuic-framework-lib-report-viewer.component-
|
|
62060
|
+
loadComponent: () => import('./wuic-framework-lib-report-viewer.component-DY0dGMrt.mjs').then((m) => m.ReportViewerComponent),
|
|
61849
62061
|
canMatch: [menuRouteAccessCanMatchGuard],
|
|
61850
62062
|
canActivate: [menuRouteAccessCanActivateGuard],
|
|
61851
62063
|
data: {
|
|
@@ -61865,7 +62077,7 @@ const routes = [
|
|
|
61865
62077
|
},
|
|
61866
62078
|
{
|
|
61867
62079
|
path: ':route/pivot-builder',
|
|
61868
|
-
loadComponent: () => import('./wuic-framework-lib-pivot-builder.component-
|
|
62080
|
+
loadComponent: () => import('./wuic-framework-lib-pivot-builder.component-VIs0CIH_.mjs').then((m) => m.PivotBuilderComponent),
|
|
61869
62081
|
canMatch: [menuRouteAccessCanMatchGuard, featureRouteCanMatchGuard],
|
|
61870
62082
|
canActivate: [menuRouteAccessCanActivateGuard, featureRouteCanActivateGuard],
|
|
61871
62083
|
data: {
|
|
@@ -61875,7 +62087,7 @@ const routes = [
|
|
|
61875
62087
|
},
|
|
61876
62088
|
{
|
|
61877
62089
|
path: 'pivot-builder',
|
|
61878
|
-
loadComponent: () => import('./wuic-framework-lib-pivot-builder.component-
|
|
62090
|
+
loadComponent: () => import('./wuic-framework-lib-pivot-builder.component-VIs0CIH_.mjs').then((m) => m.PivotBuilderComponent),
|
|
61879
62091
|
canMatch: [menuRouteAccessCanMatchGuard, featureRouteCanMatchGuard],
|
|
61880
62092
|
canActivate: [menuRouteAccessCanActivateGuard, featureRouteCanActivateGuard],
|
|
61881
62093
|
data: {
|
|
@@ -62134,4 +62346,4 @@ function getThemePrimaryHex(value) {
|
|
|
62134
62346
|
*/
|
|
62135
62347
|
|
|
62136
62348
|
export { KanbanListComponent as $, ArchetypeConfiguratorComponent as A, BooleanEditorComponent as B, CallbackPipe as C, DynamicGenericTemplateComponent as D, CrashReporterService as E, FilterBarComponent as F, GlobalHandler as G, CustomAttributesService as H, ImportExportButtonComponent as I, CustomException as J, DataActionButtonComponent as K, LazyParametricDialogComponent as L, MetadataProviderService as M, DataProviderOdataService as N, DateEditorComponent as O, PagerComponent as P, DesignerRouteComponent as Q, DictionaryEditorComponent as R, DynamicRowTemplateComponent as S, TranslationManagerService as T, UserInfoService as U, FormatGridViewValuePipe as V, WtoolboxService as W, GetSrcUploadPreviewPipe as X, HtmlEditorComponent as Y, ImageWrapperComponent as Z, IsSelectedRowPipe as _, DynamicCompilerService as a, loadLookupEditorComponent as a$, KanbanOptions as a0, KanbanStatusColumnItem as a1, LazyChartListComponent as a2, LazyCodeEditorComponent as a3, LazyDataActionButtonComponent as a4, LazyDataSourceComponent as a5, LazyFieldEditorComponent as a6, LazyFirstRunWizardComponent as a7, LazyImageWrapperComponent as a8, LazyKanbanListComponent as a9, VisibleFieldListPipe as aA, WidgetDefinition as aB, WorkflowDesignerRouteComponent as aC, WorkflowRunnerComponent as aD, WuicAziendaSwitcherComponent as aE, WuicErrorDialogComponent as aF, WuicErrorInterceptor as aG, WuicFeatureDirective as aH, WuicFrozenColumnDirective as aI, WuicRagChatbotComponent as aJ, WuicRagChatbotFabComponent as aK, WuicRagService as aL, WuicRowTogglerDirective as aM, _PRIMENG_TABLE_DIRECTIVES_NAMES as aN, authExpiredInterceptor as aO, boundedRepeaterPendingChangesGuard as aP, featureRouteCanActivateGuard as aQ, featureRouteCanMatchGuard as aR, getThemePrimaryHex as aS, inferTemplateFieldFromBaseClass as aT, loadBooleanEditorComponent as aU, loadButtonEditorComponent as aV, loadCodeAreaEditorComponent as aW, loadColorEditorComponent as aX, loadDateEditorComponent as aY, loadDictionaryEditorComponent as aZ, loadHtmlEditorComponent as a_, LazyMetaMenuComponent as aa, LazyPivotBuilderComponent as ab, LazyReportDesignerComponent as ac, LazyReportViewerComponent as ad, LazySchedulerListComponent as ae, LazySpreadsheetListSfComponent as af, ListGridComponent as ag, LookupEditorComponent as ah, MapListComponent as ai, MetaMenuComponent as aj, MetadatiTabella as ak, NotificationBellComponent as al, NotificationRealtimeService as am, NumberEditorComponent as an, PRIMARY_PALETTES as ao, PropertyArrayEditorComponent as ap, PropertyObjectEditorComponent as aq, THEME_OPTIONS as ar, TextAreaEditorComponent as as, TextEditorComponent as at, TreeListComponent as au, TreeViewSelectorComponent as av, UploadDialogComponent as aw, UploadEditorComponent as ax, ValidationRule as ay, ValueChangedPayload as az, DataSourceComponent as b, loadNumberEditorComponent as b0, loadPropertyArrayEditorComponent as b1, loadPropertyObjectEditorComponent as b2, loadTextAreaEditorComponent as b3, loadTextEditorComponent as b4, loadTreeViewSelectorComponent as b5, loadUploadEditorComponent as b6, menuRouteAccessCanActivateGuard as b7, menuRouteAccessCanMatchGuard as b8, routes as b9, wuicErrorInterceptor as ba, DataRepeaterComponent as c, ParametricDialogComponent as d, MetadatiColonna as e, DataProviderService as f, MetadataEditorService as g, WorkflowRuntimeMetadataService as h, FieldEditorComponent as i, MetadataEditorComponent as j, WuicClientException as k, WuicErrorCodes as l, MetaInfo as m, AuthSessionService as n, FilterInfo as o, LicenseFeatureService as p, FilterItem as q, getThemeOptions as r, AUTH_REDIRECT_REASON_KEY as s, AppSettingsEditorComponent as t, BoundedRepeaterComponent as u, ButtonEditorComponent as v, CallbackPipe2 as w, CarouselListComponent as x, CodeAreaEditorComponent as y, ColorEditorComponent as z };
|
|
62137
|
-
//# sourceMappingURL=wuic-framework-lib-wuic-framework-lib-
|
|
62349
|
+
//# sourceMappingURL=wuic-framework-lib-wuic-framework-lib-BSyGhpM1.mjs.map
|