@flusys/ng-layout 1.1.0-beta → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -4
- package/fesm2022/flusys-ng-layout.mjs +306 -414
- package/fesm2022/flusys-ng-layout.mjs.map +1 -1
- package/package.json +11 -11
- package/types/flusys-ng-layout.d.ts +122 -135
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import * as i1 from '@angular/common';
|
|
2
|
-
import { isPlatformBrowser, CommonModule, DOCUMENT as DOCUMENT$1 } from '@angular/common';
|
|
3
1
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { inject, PLATFORM_ID, Injectable, DOCUMENT, signal, computed, effect, Component,
|
|
5
|
-
import
|
|
2
|
+
import { inject, PLATFORM_ID, Injectable, DOCUMENT, signal, computed, effect, ChangeDetectionStrategy, Component, afterNextRender, InjectionToken, DestroyRef, ElementRef, viewChild, input, Renderer2 } from '@angular/core';
|
|
3
|
+
import { isPlatformBrowser, NgClass, DOCUMENT as DOCUMENT$1 } from '@angular/common';
|
|
4
|
+
import { APP_CONFIG, DEFAULT_APP_NAME, DEFAULT_AUTHOR, isCompanyFeatureEnabled } from '@flusys/ng-core';
|
|
5
|
+
import * as i2$2 from '@flusys/ng-shared';
|
|
6
|
+
import { evaluateLogicNode, PermissionValidatorService, AngularModule, IconComponent } from '@flusys/ng-shared';
|
|
7
|
+
import { Subject, fromEvent, filter as filter$1 } from 'rxjs';
|
|
8
|
+
import * as i1 from '@angular/forms';
|
|
6
9
|
import { FormsModule } from '@angular/forms';
|
|
7
10
|
import * as i1$2 from '@angular/router';
|
|
8
11
|
import { Router, RouterModule, NavigationEnd } from '@angular/router';
|
|
@@ -10,13 +13,8 @@ import { updatePreset, updateSurfacePalette, $t, definePreset } from '@primeuix/
|
|
|
10
13
|
import Aura from '@primeuix/themes/aura';
|
|
11
14
|
import Lara from '@primeuix/themes/lara';
|
|
12
15
|
import Nora from '@primeuix/themes/nora';
|
|
13
|
-
import
|
|
14
|
-
import * as i3 from 'primeng/selectbutton';
|
|
16
|
+
import * as i2 from 'primeng/selectbutton';
|
|
15
17
|
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
16
|
-
import { APP_CONFIG, DEFAULT_APP_NAME, DEFAULT_AUTHOR, isCompanyFeatureEnabled } from '@flusys/ng-core';
|
|
17
|
-
import * as i2$2 from '@flusys/ng-shared';
|
|
18
|
-
import { evaluateLogicNode, PermissionValidatorService, PlatformService, AngularModule, IconComponent } from '@flusys/ng-shared';
|
|
19
|
-
import { Subject, fromEvent, filter as filter$1 } from 'rxjs';
|
|
20
18
|
import * as i1$1 from 'primeng/button';
|
|
21
19
|
import { ButtonModule } from 'primeng/button';
|
|
22
20
|
import * as i2$1 from 'primeng/styleclass';
|
|
@@ -194,104 +192,79 @@ class LayoutPersistenceService {
|
|
|
194
192
|
const { _version, ...cleanConfig } = config;
|
|
195
193
|
return cleanConfig;
|
|
196
194
|
}
|
|
197
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
198
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.
|
|
195
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LayoutPersistenceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
196
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LayoutPersistenceService, providedIn: 'root' });
|
|
199
197
|
}
|
|
200
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
198
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LayoutPersistenceService, decorators: [{
|
|
201
199
|
type: Injectable,
|
|
202
200
|
args: [{
|
|
203
201
|
providedIn: 'root',
|
|
204
202
|
}]
|
|
205
203
|
}] });
|
|
206
204
|
|
|
207
|
-
/**
|
|
208
|
-
* Service managing layout configuration and state.
|
|
209
|
-
* Provides signals for reactive layout updates.
|
|
210
|
-
*/
|
|
205
|
+
/** Layout configuration and state management service */
|
|
211
206
|
class LayoutService {
|
|
212
207
|
document = inject(DOCUMENT);
|
|
213
208
|
platformId = inject(PLATFORM_ID);
|
|
214
209
|
isBrowser = isPlatformBrowser(this.platformId);
|
|
215
210
|
persistence = inject(LayoutPersistenceService);
|
|
216
211
|
appConfig = inject(APP_CONFIG, { optional: true });
|
|
217
|
-
|
|
212
|
+
DEFAULT_CONFIG = {
|
|
218
213
|
preset: 'Aura',
|
|
219
214
|
primary: 'emerald',
|
|
220
215
|
surface: null,
|
|
221
216
|
darkTheme: false,
|
|
222
217
|
menuMode: 'static',
|
|
223
218
|
};
|
|
224
|
-
|
|
225
|
-
initialConfig = (() => {
|
|
226
|
-
const persisted = this.persistence.load();
|
|
227
|
-
return persisted
|
|
228
|
-
? { ...this.defaultConfig, ...persisted }
|
|
229
|
-
: this.defaultConfig;
|
|
230
|
-
})();
|
|
231
|
-
defaultState = {
|
|
219
|
+
DEFAULT_STATE = {
|
|
232
220
|
staticMenuDesktopInactive: false,
|
|
233
221
|
overlayMenuActive: false,
|
|
234
222
|
configSidebarVisible: false,
|
|
235
223
|
staticMenuMobileActive: false,
|
|
236
224
|
menuHoverActive: false,
|
|
237
225
|
};
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
// App Launcher Signals
|
|
250
|
-
_rawApps = signal([], ...(ngDevMode ? [{ debugName: "_rawApps" }] : []));
|
|
251
|
-
/**
|
|
252
|
-
* Filtered launcher apps based on user permissions.
|
|
253
|
-
* Automatically recomputes when raw apps or permissions change.
|
|
254
|
-
*/
|
|
255
|
-
apps = computed(() => {
|
|
256
|
-
const raw = this._rawApps();
|
|
257
|
-
const permission = this.permissionValidator.permissions();
|
|
258
|
-
return filterAppsByPermissions(raw, permission);
|
|
259
|
-
}, ...(ngDevMode ? [{ debugName: "apps" }] : []));
|
|
260
|
-
// Menu Signals
|
|
226
|
+
_layoutConfig = signal({
|
|
227
|
+
...this.DEFAULT_CONFIG,
|
|
228
|
+
...this.persistence.load(),
|
|
229
|
+
}, ...(ngDevMode ? [{ debugName: "_layoutConfig" }] : []));
|
|
230
|
+
_layoutState = signal(this.DEFAULT_STATE, ...(ngDevMode ? [{ debugName: "_layoutState" }] : []));
|
|
231
|
+
_transitionComplete = signal(false, ...(ngDevMode ? [{ debugName: "_transitionComplete" }] : []));
|
|
232
|
+
layoutConfig = this._layoutConfig.asReadonly();
|
|
233
|
+
layoutState = this._layoutState.asReadonly();
|
|
234
|
+
transitionComplete = this._transitionComplete.asReadonly();
|
|
235
|
+
_userProfile = signal(null, ...(ngDevMode ? [{ debugName: "_userProfile" }] : []));
|
|
236
|
+
_companyProfile = signal(null, ...(ngDevMode ? [{ debugName: "_companyProfile" }] : []));
|
|
261
237
|
_rawMenu = signal([], ...(ngDevMode ? [{ debugName: "_rawMenu" }] : []));
|
|
238
|
+
_rawApps = signal([], ...(ngDevMode ? [{ debugName: "_rawApps" }] : []));
|
|
262
239
|
permissionValidator = inject(PermissionValidatorService);
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
240
|
+
userProfile = this._userProfile.asReadonly();
|
|
241
|
+
companyProfile = this._companyProfile.asReadonly();
|
|
242
|
+
// Static app info from config
|
|
243
|
+
appName = this.appConfig?.appName ?? DEFAULT_APP_NAME;
|
|
244
|
+
authorName = this.appConfig?.author?.name ?? DEFAULT_AUTHOR.name;
|
|
245
|
+
authorUrl = this.appConfig?.author?.url ?? DEFAULT_AUTHOR.url;
|
|
246
|
+
// Permission-filtered menu and apps
|
|
247
|
+
menu = computed(() => filterMenuByPermissions(this._rawMenu(), this.permissionValidator.permissions()), ...(ngDevMode ? [{ debugName: "menu" }] : []));
|
|
248
|
+
apps = computed(() => filterAppsByPermissions(this._rawApps(), this.permissionValidator.permissions()), ...(ngDevMode ? [{ debugName: "apps" }] : []));
|
|
249
|
+
hasApps = computed(() => this.apps().length > 0, ...(ngDevMode ? [{ debugName: "hasApps" }] : []));
|
|
273
250
|
// Computed signals - Layout
|
|
274
|
-
isSidebarActive = computed(() => this.
|
|
275
|
-
this.
|
|
276
|
-
isDarkTheme = computed(() => this.
|
|
277
|
-
getPrimary = computed(() => this.
|
|
278
|
-
getSurface = computed(() => this.
|
|
279
|
-
isOverlay = computed(() => this.
|
|
280
|
-
//
|
|
281
|
-
userName = computed(() => this.
|
|
282
|
-
userEmail = computed(() => this.
|
|
283
|
-
userProfilePictureUrl = computed(() => this.
|
|
251
|
+
isSidebarActive = computed(() => this._layoutState().overlayMenuActive ||
|
|
252
|
+
this._layoutState().staticMenuMobileActive, ...(ngDevMode ? [{ debugName: "isSidebarActive" }] : []));
|
|
253
|
+
isDarkTheme = computed(() => this._layoutConfig().darkTheme, ...(ngDevMode ? [{ debugName: "isDarkTheme" }] : []));
|
|
254
|
+
getPrimary = computed(() => this._layoutConfig().primary, ...(ngDevMode ? [{ debugName: "getPrimary" }] : []));
|
|
255
|
+
getSurface = computed(() => this._layoutConfig().surface, ...(ngDevMode ? [{ debugName: "getSurface" }] : []));
|
|
256
|
+
isOverlay = computed(() => this._layoutConfig().menuMode === 'overlay', ...(ngDevMode ? [{ debugName: "isOverlay" }] : []));
|
|
257
|
+
// User profile computed signals
|
|
258
|
+
userName = computed(() => this._userProfile()?.name ?? 'User', ...(ngDevMode ? [{ debugName: "userName" }] : []));
|
|
259
|
+
userEmail = computed(() => this._userProfile()?.email ?? '', ...(ngDevMode ? [{ debugName: "userEmail" }] : []));
|
|
260
|
+
userProfilePictureUrl = computed(() => this._userProfile()?.profilePictureUrl ?? null, ...(ngDevMode ? [{ debugName: "userProfilePictureUrl" }] : []));
|
|
261
|
+
companyLogoUrl = computed(() => this._companyProfile()?.logoUrl ?? null, ...(ngDevMode ? [{ debugName: "companyLogoUrl" }] : []));
|
|
262
|
+
isAuthenticated = computed(() => !!this._userProfile(), ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : []));
|
|
284
263
|
companyName = computed(() => {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
return this.companyProfile()?.name ?? this.appName();
|
|
264
|
+
if (!this.appConfig || !isCompanyFeatureEnabled(this.appConfig))
|
|
265
|
+
return this.appName;
|
|
266
|
+
return this._companyProfile()?.name ?? this.appName;
|
|
290
267
|
}, ...(ngDevMode ? [{ debugName: "companyName" }] : []));
|
|
291
|
-
companyLogoUrl = computed(() => this.companyProfile()?.logoUrl ?? null, ...(ngDevMode ? [{ debugName: "companyLogoUrl" }] : []));
|
|
292
|
-
isAuthenticated = computed(() => !!this.userProfile(), ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : []));
|
|
293
|
-
// Computed signals - App Launcher
|
|
294
|
-
hasApps = computed(() => this.apps().length > 0, ...(ngDevMode ? [{ debugName: "hasApps" }] : []));
|
|
295
268
|
// RxJS Subjects for event communication
|
|
296
269
|
configUpdate = new Subject();
|
|
297
270
|
overlayOpen = new Subject();
|
|
@@ -304,79 +277,56 @@ class LayoutService {
|
|
|
304
277
|
initialized = false;
|
|
305
278
|
constructor() {
|
|
306
279
|
effect(() => {
|
|
307
|
-
const config = this.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
});
|
|
312
|
-
effect(() => {
|
|
313
|
-
const config = this.layoutConfig();
|
|
314
|
-
if (!this.initialized || !config) {
|
|
315
|
-
this.initialized = true;
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
this.handleDarkModeTransition(config);
|
|
319
|
-
});
|
|
320
|
-
// Auto-save configuration changes to localStorage
|
|
321
|
-
effect(() => {
|
|
322
|
-
const config = this.layoutConfig();
|
|
323
|
-
if (config && this.initialized) {
|
|
280
|
+
const config = this._layoutConfig();
|
|
281
|
+
this.configUpdate.next(config);
|
|
282
|
+
if (this.initialized) {
|
|
283
|
+
this.handleDarkModeTransition(config);
|
|
324
284
|
this.persistence.save(config);
|
|
325
285
|
}
|
|
286
|
+
this.initialized = true;
|
|
326
287
|
});
|
|
327
288
|
}
|
|
289
|
+
toggleDarkMode(config) {
|
|
290
|
+
const isDark = (config ?? this._layoutConfig()).darkTheme;
|
|
291
|
+
this.document.documentElement.classList.toggle('app-dark', isDark);
|
|
292
|
+
}
|
|
328
293
|
handleDarkModeTransition(config) {
|
|
329
|
-
|
|
330
|
-
|
|
294
|
+
const doc = this.document;
|
|
295
|
+
if ('startViewTransition' in doc && typeof doc.startViewTransition === 'function') {
|
|
296
|
+
doc
|
|
297
|
+
.startViewTransition(() => this.toggleDarkMode(config))
|
|
298
|
+
.ready.then(() => this.onTransitionEnd())
|
|
299
|
+
.catch(() => { });
|
|
331
300
|
}
|
|
332
301
|
else {
|
|
333
302
|
this.toggleDarkMode(config);
|
|
334
303
|
this.onTransitionEnd();
|
|
335
304
|
}
|
|
336
305
|
}
|
|
337
|
-
startViewTransition(config) {
|
|
338
|
-
const transition = this.document.startViewTransition(() => {
|
|
339
|
-
this.toggleDarkMode(config);
|
|
340
|
-
});
|
|
341
|
-
transition.ready.then(() => this.onTransitionEnd()).catch(() => { });
|
|
342
|
-
}
|
|
343
|
-
toggleDarkMode(config) {
|
|
344
|
-
const _config = config || this.layoutConfig();
|
|
345
|
-
if (_config.darkTheme) {
|
|
346
|
-
this.document.documentElement.classList.add('app-dark');
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
this.document.documentElement.classList.remove('app-dark');
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
306
|
onTransitionEnd() {
|
|
353
|
-
this.
|
|
354
|
-
setTimeout(() => this.
|
|
307
|
+
this._transitionComplete.set(true);
|
|
308
|
+
setTimeout(() => this._transitionComplete.set(false));
|
|
355
309
|
}
|
|
356
310
|
onMenuToggle() {
|
|
311
|
+
const state = this._layoutState();
|
|
357
312
|
if (this.isOverlay()) {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
}));
|
|
362
|
-
if (this.layoutState().overlayMenuActive) {
|
|
313
|
+
const newOverlayActive = !state.overlayMenuActive;
|
|
314
|
+
this._layoutState.update((prev) => ({ ...prev, overlayMenuActive: newOverlayActive }));
|
|
315
|
+
if (newOverlayActive)
|
|
363
316
|
this.overlayOpen.next();
|
|
364
|
-
|
|
317
|
+
return;
|
|
365
318
|
}
|
|
366
319
|
if (this.isDesktop()) {
|
|
367
|
-
this.
|
|
320
|
+
this._layoutState.update((prev) => ({
|
|
368
321
|
...prev,
|
|
369
|
-
staticMenuDesktopInactive: !
|
|
322
|
+
staticMenuDesktopInactive: !state.staticMenuDesktopInactive,
|
|
370
323
|
}));
|
|
371
324
|
}
|
|
372
325
|
else {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}));
|
|
377
|
-
if (this.layoutState().staticMenuMobileActive) {
|
|
326
|
+
const newMobileActive = !state.staticMenuMobileActive;
|
|
327
|
+
this._layoutState.update((prev) => ({ ...prev, staticMenuMobileActive: newMobileActive }));
|
|
328
|
+
if (newMobileActive)
|
|
378
329
|
this.overlayOpen.next();
|
|
379
|
-
}
|
|
380
330
|
}
|
|
381
331
|
}
|
|
382
332
|
isDesktop() {
|
|
@@ -385,77 +335,70 @@ class LayoutService {
|
|
|
385
335
|
isMobile() {
|
|
386
336
|
return !this.isDesktop();
|
|
387
337
|
}
|
|
388
|
-
onConfigUpdate() {
|
|
389
|
-
this.configUpdate.next(this.layoutConfig());
|
|
390
|
-
}
|
|
391
338
|
onMenuStateChange(event) {
|
|
392
339
|
this.menuSource.next(event);
|
|
393
340
|
}
|
|
394
341
|
reset() {
|
|
395
342
|
this.resetSource.next(true);
|
|
396
343
|
}
|
|
397
|
-
//
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
344
|
+
// Config & state updates
|
|
345
|
+
updateLayoutConfig(config) {
|
|
346
|
+
this._layoutConfig.update((prev) => ({ ...prev, ...config }));
|
|
347
|
+
}
|
|
348
|
+
updateLayoutState(state) {
|
|
349
|
+
this._layoutState.update((prev) => ({ ...prev, ...state }));
|
|
350
|
+
}
|
|
351
|
+
// Profile setters
|
|
404
352
|
setUserProfile(profile) {
|
|
405
|
-
this.
|
|
353
|
+
this._userProfile.set(profile);
|
|
406
354
|
}
|
|
407
|
-
/**
|
|
408
|
-
* Set the current company profile for display in layout.
|
|
409
|
-
* Called by auth integration to sync company data.
|
|
410
|
-
*/
|
|
411
355
|
setCompanyProfile(profile) {
|
|
412
|
-
this.
|
|
356
|
+
this._companyProfile.set(profile);
|
|
413
357
|
}
|
|
414
|
-
//
|
|
415
|
-
// Menu Methods
|
|
416
|
-
// ==========================================================================
|
|
417
|
-
/**
|
|
418
|
-
* Set the raw menu items (unfiltered).
|
|
419
|
-
* Menu will be automatically filtered based on permission checker.
|
|
420
|
-
* Called by app initialization to set menu from IAM or other source.
|
|
421
|
-
*/
|
|
358
|
+
// Menu & apps
|
|
422
359
|
setMenu(items) {
|
|
423
360
|
this._rawMenu.set(items);
|
|
424
361
|
}
|
|
425
|
-
/**
|
|
426
|
-
* Clear menu and permission/role checkers.
|
|
427
|
-
* Called on logout.
|
|
428
|
-
*/
|
|
429
362
|
clearMenu() {
|
|
430
363
|
this._rawMenu.set([]);
|
|
431
364
|
}
|
|
432
|
-
// ==========================================================================
|
|
433
|
-
// App Launcher Methods
|
|
434
|
-
// ==========================================================================
|
|
435
|
-
/**
|
|
436
|
-
* Set launcher apps for display in header.
|
|
437
|
-
* Apps will be automatically filtered based on user permissions.
|
|
438
|
-
* If empty after filtering, the app launcher button is hidden.
|
|
439
|
-
*/
|
|
440
365
|
setApps(apps) {
|
|
441
366
|
this._rawApps.set(apps);
|
|
442
367
|
}
|
|
443
|
-
/**
|
|
444
|
-
* Clear launcher apps.
|
|
445
|
-
* Called on logout.
|
|
446
|
-
*/
|
|
447
368
|
clearApps() {
|
|
448
369
|
this._rawApps.set([]);
|
|
449
370
|
}
|
|
450
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
451
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.
|
|
371
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LayoutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
372
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LayoutService, providedIn: 'root' });
|
|
452
373
|
}
|
|
453
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
374
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LayoutService, decorators: [{
|
|
454
375
|
type: Injectable,
|
|
376
|
+
args: [{ providedIn: 'root' }]
|
|
377
|
+
}], ctorParameters: () => [] });
|
|
378
|
+
|
|
379
|
+
class AppFooter {
|
|
380
|
+
layoutService = inject(LayoutService);
|
|
381
|
+
// Footer shows product branding (appName), not user's company
|
|
382
|
+
appName = this.layoutService.appName;
|
|
383
|
+
authorName = this.layoutService.authorName;
|
|
384
|
+
authorUrl = this.layoutService.authorUrl;
|
|
385
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
386
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: AppFooter, isStandalone: true, selector: "app-footer", ngImport: i0, template: `<div class="layout-footer">
|
|
387
|
+
{{ appName }} by
|
|
388
|
+
<a [href]="authorUrl" target="_blank" rel="noopener noreferrer" class="text-primary font-bold hover:underline">{{ authorName }}</a>
|
|
389
|
+
</div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
390
|
+
}
|
|
391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppFooter, decorators: [{
|
|
392
|
+
type: Component,
|
|
455
393
|
args: [{
|
|
456
|
-
|
|
394
|
+
selector: 'app-footer',
|
|
395
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
396
|
+
template: `<div class="layout-footer">
|
|
397
|
+
{{ appName }} by
|
|
398
|
+
<a [href]="authorUrl" target="_blank" rel="noopener noreferrer" class="text-primary font-bold hover:underline">{{ authorName }}</a>
|
|
399
|
+
</div>`,
|
|
457
400
|
}]
|
|
458
|
-
}]
|
|
401
|
+
}] });
|
|
459
402
|
|
|
460
403
|
const presets = {
|
|
461
404
|
Aura,
|
|
@@ -464,19 +407,19 @@ const presets = {
|
|
|
464
407
|
};
|
|
465
408
|
class AppConfigurator {
|
|
466
409
|
router = inject(Router);
|
|
467
|
-
primeng = inject(PrimeNG);
|
|
468
410
|
layoutService = inject(LayoutService);
|
|
469
|
-
platformService = inject(PlatformService);
|
|
470
411
|
presets = Object.keys(presets);
|
|
471
412
|
showMenuModeButton = signal(!this.router.url.includes('auth'), ...(ngDevMode ? [{ debugName: "showMenuModeButton" }] : []));
|
|
472
413
|
menuModeOptions = [
|
|
473
414
|
{ label: 'Static', value: 'static' },
|
|
474
415
|
{ label: 'Overlay', value: 'overlay' },
|
|
475
416
|
];
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
417
|
+
constructor() {
|
|
418
|
+
// Use afterNextRender for browser-only initialization (replaces isServer check)
|
|
419
|
+
afterNextRender(() => {
|
|
420
|
+
const preset = this.layoutService.layoutConfig().preset ?? 'Aura';
|
|
421
|
+
this.onPresetChange(preset);
|
|
422
|
+
});
|
|
480
423
|
}
|
|
481
424
|
surfaces = [
|
|
482
425
|
{
|
|
@@ -782,16 +725,10 @@ class AppConfigurator {
|
|
|
782
725
|
}
|
|
783
726
|
updateColors(event, type, color) {
|
|
784
727
|
if (type === 'primary') {
|
|
785
|
-
this.layoutService.
|
|
786
|
-
...state,
|
|
787
|
-
primary: color.name,
|
|
788
|
-
}));
|
|
728
|
+
this.layoutService.updateLayoutConfig({ primary: color.name });
|
|
789
729
|
}
|
|
790
730
|
else if (type === 'surface') {
|
|
791
|
-
this.layoutService.
|
|
792
|
-
...state,
|
|
793
|
-
surface: color.name,
|
|
794
|
-
}));
|
|
731
|
+
this.layoutService.updateLayoutConfig({ surface: color.name });
|
|
795
732
|
}
|
|
796
733
|
this.applyTheme(type, color);
|
|
797
734
|
event.stopPropagation();
|
|
@@ -805,12 +742,12 @@ class AppConfigurator {
|
|
|
805
742
|
}
|
|
806
743
|
}
|
|
807
744
|
onPresetChange(event) {
|
|
808
|
-
this.layoutService.
|
|
809
|
-
...state,
|
|
810
|
-
preset: event,
|
|
811
|
-
}));
|
|
745
|
+
this.layoutService.updateLayoutConfig({ preset: event });
|
|
812
746
|
const preset = presets[event];
|
|
813
|
-
|
|
747
|
+
// Use selected surface or default (slate for light, zinc for dark)
|
|
748
|
+
const selectedSurface = this.selectedSurfaceColor();
|
|
749
|
+
const defaultSurface = this.layoutService.layoutConfig().darkTheme ? 'zinc' : 'slate';
|
|
750
|
+
const surfacePalette = this.surfaces.find((s) => s.name === (selectedSurface || defaultSurface))?.palette;
|
|
814
751
|
$t()
|
|
815
752
|
.preset(preset)
|
|
816
753
|
.preset(this.getPresetExt())
|
|
@@ -818,13 +755,10 @@ class AppConfigurator {
|
|
|
818
755
|
.use({ useDefaultOptions: true });
|
|
819
756
|
}
|
|
820
757
|
onMenuModeChange(event) {
|
|
821
|
-
this.layoutService.
|
|
822
|
-
...prev,
|
|
823
|
-
menuMode: event,
|
|
824
|
-
}));
|
|
758
|
+
this.layoutService.updateLayoutConfig({ menuMode: event });
|
|
825
759
|
}
|
|
826
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
827
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
760
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppConfigurator, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
761
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AppConfigurator, isStandalone: true, selector: "app-configurator", host: { styleAttribute: "background-color: var(--surface-overlay)", classAttribute: "hidden absolute top-[3.25rem] right-0 w-[calc(100vw-2rem)] sm:w-72 max-w-72 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]" }, ngImport: i0, template: `
|
|
828
762
|
<div class="flex flex-col gap-4">
|
|
829
763
|
<div>
|
|
830
764
|
<span class="text-sm text-muted-color font-semibold">Primary</span>
|
|
@@ -891,14 +825,14 @@ class AppConfigurator {
|
|
|
891
825
|
</div>
|
|
892
826
|
}
|
|
893
827
|
</div>
|
|
894
|
-
`, isInline: true, dependencies: [{ kind: "
|
|
828
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i2.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
895
829
|
}
|
|
896
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
830
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppConfigurator, decorators: [{
|
|
897
831
|
type: Component,
|
|
898
832
|
args: [{
|
|
899
833
|
selector: 'app-configurator',
|
|
900
|
-
|
|
901
|
-
imports: [
|
|
834
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
835
|
+
imports: [NgClass, FormsModule, SelectButtonModule],
|
|
902
836
|
template: `
|
|
903
837
|
<div class="flex flex-col gap-4">
|
|
904
838
|
<div>
|
|
@@ -968,36 +902,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
968
902
|
</div>
|
|
969
903
|
`,
|
|
970
904
|
host: {
|
|
971
|
-
class: 'hidden absolute top-[3.25rem] right-0 w-72 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]',
|
|
905
|
+
class: 'hidden absolute top-[3.25rem] right-0 w-[calc(100vw-2rem)] sm:w-72 max-w-72 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]',
|
|
972
906
|
style: 'background-color: var(--surface-overlay)',
|
|
973
907
|
},
|
|
974
908
|
}]
|
|
975
|
-
}] });
|
|
909
|
+
}], ctorParameters: () => [] });
|
|
976
910
|
|
|
977
911
|
class AppFloatingConfigurator {
|
|
978
|
-
|
|
979
|
-
isDarkTheme = computed(() => this.
|
|
912
|
+
layoutService = inject(LayoutService);
|
|
913
|
+
isDarkTheme = computed(() => this.layoutService.layoutConfig().darkTheme, ...(ngDevMode ? [{ debugName: "isDarkTheme" }] : []));
|
|
980
914
|
toggleDarkMode() {
|
|
981
|
-
this.
|
|
915
|
+
const currentDarkTheme = this.layoutService.layoutConfig().darkTheme;
|
|
916
|
+
this.layoutService.updateLayoutConfig({ darkTheme: !currentDarkTheme });
|
|
982
917
|
}
|
|
983
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
984
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.
|
|
985
|
-
<div class="fixed flex flex-col md:flex-row gap-4 top-8 right-
|
|
918
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppFloatingConfigurator, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
919
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: AppFloatingConfigurator, isStandalone: true, selector: "app-floating-configurator", ngImport: i0, template: `
|
|
920
|
+
<div class="fixed flex flex-col md:flex-row gap-2 md:gap-4 top-4 md:top-8 right-2 md:right-8 z-50">
|
|
986
921
|
<p-button type="button" (onClick)="toggleDarkMode()" [rounded]="true" [icon]="isDarkTheme() ? 'pi pi-moon' : 'pi pi-sun'" severity="secondary" />
|
|
987
922
|
<div class="relative">
|
|
988
923
|
<p-button icon="pi pi-palette" pStyleClass="@next" enterFromClass="hidden" enterActiveClass="animate-scalein" leaveToClass="hidden" leaveActiveClass="animate-fadeout" [hideOnOutsideClick]="true" type="button" rounded />
|
|
989
924
|
<app-configurator />
|
|
990
925
|
</div>
|
|
991
926
|
</div>
|
|
992
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: StyleClassModule }, { kind: "directive", type: i2$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfigurator, selector: "app-configurator" }] });
|
|
927
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: StyleClassModule }, { kind: "directive", type: i2$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfigurator, selector: "app-configurator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
993
928
|
}
|
|
994
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
929
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppFloatingConfigurator, decorators: [{
|
|
995
930
|
type: Component,
|
|
996
931
|
args: [{
|
|
997
932
|
selector: 'app-floating-configurator',
|
|
933
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
998
934
|
imports: [ButtonModule, StyleClassModule, AppConfigurator],
|
|
999
935
|
template: `
|
|
1000
|
-
<div class="fixed flex flex-col md:flex-row gap-4 top-8 right-
|
|
936
|
+
<div class="fixed flex flex-col md:flex-row gap-2 md:gap-4 top-4 md:top-8 right-2 md:right-8 z-50">
|
|
1001
937
|
<p-button type="button" (onClick)="toggleDarkMode()" [rounded]="true" [icon]="isDarkTheme() ? 'pi pi-moon' : 'pi pi-sun'" severity="secondary" />
|
|
1002
938
|
<div class="relative">
|
|
1003
939
|
<p-button icon="pi pi-palette" pStyleClass="@next" enterFromClass="hidden" enterActiveClass="animate-scalein" leaveToClass="hidden" leaveActiveClass="animate-fadeout" [hideOnOutsideClick]="true" type="button" rounded />
|
|
@@ -1008,34 +944,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1008
944
|
}]
|
|
1009
945
|
}] });
|
|
1010
946
|
|
|
1011
|
-
class AppFooter {
|
|
1012
|
-
layoutService = inject(LayoutService);
|
|
1013
|
-
// Footer shows product branding (appName), not user's company
|
|
1014
|
-
appName = this.layoutService.appName;
|
|
1015
|
-
authorName = this.layoutService.authorName;
|
|
1016
|
-
authorUrl = this.layoutService.authorUrl;
|
|
1017
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1018
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AppFooter, isStandalone: true, selector: "app-footer", ngImport: i0, template: `<div class="layout-footer">
|
|
1019
|
-
{{ appName() }} by
|
|
1020
|
-
<a [href]="authorUrl()" target="_blank" rel="noopener noreferrer" class="text-primary font-bold hover:underline">{{ authorName() }}</a>
|
|
1021
|
-
</div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1022
|
-
}
|
|
1023
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppFooter, decorators: [{
|
|
1024
|
-
type: Component,
|
|
1025
|
-
args: [{
|
|
1026
|
-
standalone: true,
|
|
1027
|
-
selector: 'app-footer',
|
|
1028
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1029
|
-
template: `<div class="layout-footer">
|
|
1030
|
-
{{ appName() }} by
|
|
1031
|
-
<a [href]="authorUrl()" target="_blank" rel="noopener noreferrer" class="text-primary font-bold hover:underline">{{ authorName() }}</a>
|
|
1032
|
-
</div>`,
|
|
1033
|
-
}]
|
|
1034
|
-
}] });
|
|
1035
|
-
|
|
1036
947
|
const LAYOUT_AUTH_STATE = new InjectionToken('LAYOUT_AUTH_STATE');
|
|
1037
948
|
const LAYOUT_AUTH_API = new InjectionToken('LAYOUT_AUTH_API');
|
|
1038
949
|
|
|
950
|
+
/**
|
|
951
|
+
* View Transitions API type definitions
|
|
952
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API
|
|
953
|
+
*/
|
|
954
|
+
|
|
1039
955
|
/** Company/branch switcher displayed in top bar */
|
|
1040
956
|
class AppCompanyBranchSelector {
|
|
1041
957
|
destroyRef = inject(DestroyRef);
|
|
@@ -1044,26 +960,34 @@ class AppCompanyBranchSelector {
|
|
|
1044
960
|
messageService = inject(MessageService);
|
|
1045
961
|
document = inject(DOCUMENT$1);
|
|
1046
962
|
elementRef = inject(ElementRef);
|
|
1047
|
-
|
|
963
|
+
_isActive = signal(false, ...(ngDevMode ? [{ debugName: "_isActive" }] : []));
|
|
964
|
+
isActive = this._isActive.asReadonly();
|
|
1048
965
|
constructor() {
|
|
1049
966
|
fromEvent(this.document, 'click')
|
|
1050
967
|
.pipe(takeUntilDestroyed(this.destroyRef), filter(() => this.isActive()))
|
|
1051
968
|
.subscribe((event) => {
|
|
1052
969
|
const target = event.target;
|
|
1053
970
|
if (!this.elementRef.nativeElement.contains(target)) {
|
|
1054
|
-
this.
|
|
971
|
+
this._isActive.set(false);
|
|
1055
972
|
}
|
|
1056
973
|
});
|
|
1057
974
|
}
|
|
1058
975
|
currentCompanyName = computed(() => this.authState?.currentCompanyInfo()?.name ?? 'No Company', ...(ngDevMode ? [{ debugName: "currentCompanyName" }] : []));
|
|
1059
976
|
currentBranchName = computed(() => this.authState?.currentBranchInfo()?.name ?? null, ...(ngDevMode ? [{ debugName: "currentBranchName" }] : []));
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
977
|
+
_companies = signal([], ...(ngDevMode ? [{ debugName: "_companies" }] : []));
|
|
978
|
+
companies = this._companies.asReadonly();
|
|
979
|
+
_branches = signal([], ...(ngDevMode ? [{ debugName: "_branches" }] : []));
|
|
980
|
+
branches = this._branches.asReadonly();
|
|
981
|
+
_selectedCompanyId = signal(null, ...(ngDevMode ? [{ debugName: "_selectedCompanyId" }] : []));
|
|
982
|
+
selectedCompanyId = this._selectedCompanyId.asReadonly();
|
|
983
|
+
_selectedBranchId = signal(null, ...(ngDevMode ? [{ debugName: "_selectedBranchId" }] : []));
|
|
984
|
+
selectedBranchId = this._selectedBranchId.asReadonly();
|
|
985
|
+
_isLoadingCompanies = signal(false, ...(ngDevMode ? [{ debugName: "_isLoadingCompanies" }] : []));
|
|
986
|
+
isLoadingCompanies = this._isLoadingCompanies.asReadonly();
|
|
987
|
+
_isLoadingBranches = signal(false, ...(ngDevMode ? [{ debugName: "_isLoadingBranches" }] : []));
|
|
988
|
+
isLoadingBranches = this._isLoadingBranches.asReadonly();
|
|
989
|
+
_isSwitching = signal(false, ...(ngDevMode ? [{ debugName: "_isSwitching" }] : []));
|
|
990
|
+
isSwitching = this._isSwitching.asReadonly();
|
|
1067
991
|
canSwitch = computed(() => {
|
|
1068
992
|
const selectedCompany = this.selectedCompanyId();
|
|
1069
993
|
if (!selectedCompany)
|
|
@@ -1074,7 +998,7 @@ class AppCompanyBranchSelector {
|
|
|
1074
998
|
return selectedCompany !== currentCompanyId || selectedBranch !== currentBranchId;
|
|
1075
999
|
}, ...(ngDevMode ? [{ debugName: "canSwitch" }] : []));
|
|
1076
1000
|
onPanelToggle() {
|
|
1077
|
-
this.
|
|
1001
|
+
this._isActive.update((v) => !v);
|
|
1078
1002
|
if (this.isActive() && this.companies().length === 0) {
|
|
1079
1003
|
this.loadCompanies();
|
|
1080
1004
|
}
|
|
@@ -1082,61 +1006,53 @@ class AppCompanyBranchSelector {
|
|
|
1082
1006
|
loadCompanies() {
|
|
1083
1007
|
if (!this.authApi)
|
|
1084
1008
|
return;
|
|
1085
|
-
this.
|
|
1009
|
+
this._isLoadingCompanies.set(true);
|
|
1086
1010
|
this.authApi
|
|
1087
1011
|
.getUserCompanies()
|
|
1088
1012
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1089
1013
|
.subscribe({
|
|
1090
1014
|
next: (companies) => {
|
|
1091
|
-
this.
|
|
1092
|
-
this.
|
|
1015
|
+
this._companies.set(companies);
|
|
1016
|
+
this._isLoadingCompanies.set(false);
|
|
1093
1017
|
},
|
|
1094
|
-
error: (
|
|
1095
|
-
|
|
1096
|
-
this.
|
|
1097
|
-
severity: 'error',
|
|
1098
|
-
summary: 'Error',
|
|
1099
|
-
detail: err?.message || 'Failed to load companies',
|
|
1100
|
-
});
|
|
1018
|
+
error: () => {
|
|
1019
|
+
// Error toast handled by global interceptor
|
|
1020
|
+
this._isLoadingCompanies.set(false);
|
|
1101
1021
|
},
|
|
1102
1022
|
});
|
|
1103
1023
|
}
|
|
1104
1024
|
onCompanyChange(companyId) {
|
|
1105
|
-
this.
|
|
1025
|
+
this._selectedCompanyId.set(companyId);
|
|
1106
1026
|
if (!companyId) {
|
|
1107
|
-
this.
|
|
1108
|
-
this.
|
|
1027
|
+
this._branches.set([]);
|
|
1028
|
+
this._selectedBranchId.set(null);
|
|
1109
1029
|
return;
|
|
1110
1030
|
}
|
|
1111
1031
|
this.loadBranches(companyId);
|
|
1112
1032
|
}
|
|
1113
1033
|
onBranchChange(branchId) {
|
|
1114
|
-
this.
|
|
1034
|
+
this._selectedBranchId.set(branchId);
|
|
1115
1035
|
}
|
|
1116
1036
|
loadBranches(companyId) {
|
|
1117
1037
|
if (!this.authApi)
|
|
1118
1038
|
return;
|
|
1119
|
-
this.
|
|
1120
|
-
this.
|
|
1039
|
+
this._isLoadingBranches.set(true);
|
|
1040
|
+
this._selectedBranchId.set(null);
|
|
1121
1041
|
this.authApi
|
|
1122
1042
|
.getCompanyBranches(companyId)
|
|
1123
1043
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1124
1044
|
.subscribe({
|
|
1125
1045
|
next: (branches) => {
|
|
1126
|
-
this.
|
|
1127
|
-
this.
|
|
1046
|
+
this._branches.set(branches);
|
|
1047
|
+
this._isLoadingBranches.set(false);
|
|
1128
1048
|
// Auto-select if only one branch available
|
|
1129
1049
|
if (branches.length === 1) {
|
|
1130
|
-
this.
|
|
1050
|
+
this._selectedBranchId.set(branches[0].id);
|
|
1131
1051
|
}
|
|
1132
1052
|
},
|
|
1133
|
-
error: (
|
|
1134
|
-
|
|
1135
|
-
this.
|
|
1136
|
-
severity: 'error',
|
|
1137
|
-
summary: 'Error',
|
|
1138
|
-
detail: err?.message || 'Failed to load branches',
|
|
1139
|
-
});
|
|
1053
|
+
error: () => {
|
|
1054
|
+
// Error toast handled by global interceptor
|
|
1055
|
+
this._isLoadingBranches.set(false);
|
|
1140
1056
|
},
|
|
1141
1057
|
});
|
|
1142
1058
|
}
|
|
@@ -1153,24 +1069,20 @@ class AppCompanyBranchSelector {
|
|
|
1153
1069
|
});
|
|
1154
1070
|
return;
|
|
1155
1071
|
}
|
|
1156
|
-
this.
|
|
1072
|
+
this._isSwitching.set(true);
|
|
1157
1073
|
this.authApi
|
|
1158
1074
|
.switchCompany(selectedCompany, selectedBranch || '')
|
|
1159
1075
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1160
1076
|
.subscribe({
|
|
1161
1077
|
next: () => { },
|
|
1162
|
-
error: (
|
|
1163
|
-
|
|
1164
|
-
this.
|
|
1165
|
-
severity: 'error',
|
|
1166
|
-
summary: 'Error',
|
|
1167
|
-
detail: err?.message || 'Failed to switch company',
|
|
1168
|
-
});
|
|
1078
|
+
error: () => {
|
|
1079
|
+
// Error toast handled by global interceptor
|
|
1080
|
+
this._isSwitching.set(false);
|
|
1169
1081
|
},
|
|
1170
1082
|
});
|
|
1171
1083
|
}
|
|
1172
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1173
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
1084
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppCompanyBranchSelector, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1085
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AppCompanyBranchSelector, isStandalone: true, selector: "app-company-branch-selector", host: { classAttribute: "relative" }, ngImport: i0, template: `
|
|
1174
1086
|
<button
|
|
1175
1087
|
type="button"
|
|
1176
1088
|
class="layout-topbar-action"
|
|
@@ -1190,10 +1102,10 @@ class AppCompanyBranchSelector {
|
|
|
1190
1102
|
}
|
|
1191
1103
|
</button>
|
|
1192
1104
|
<div
|
|
1193
|
-
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]"
|
|
1105
|
+
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)] w-[calc(100vw-2rem)] sm:w-auto sm:min-w-[300px] max-w-[360px]"
|
|
1194
1106
|
style="background-color: var(--surface-overlay)"
|
|
1195
1107
|
>
|
|
1196
|
-
<div class="flex flex-col gap-4
|
|
1108
|
+
<div class="flex flex-col gap-4">
|
|
1197
1109
|
<span class="text-sm text-muted-color font-semibold"
|
|
1198
1110
|
>Switch Company & Branch</span
|
|
1199
1111
|
>
|
|
@@ -1243,13 +1155,13 @@ class AppCompanyBranchSelector {
|
|
|
1243
1155
|
</div>
|
|
1244
1156
|
</div>
|
|
1245
1157
|
</div>
|
|
1246
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type:
|
|
1158
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i2$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i4.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1247
1159
|
}
|
|
1248
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1160
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppCompanyBranchSelector, decorators: [{
|
|
1249
1161
|
type: Component,
|
|
1250
1162
|
args: [{
|
|
1251
1163
|
selector: 'app-company-branch-selector',
|
|
1252
|
-
|
|
1164
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1253
1165
|
imports: [AngularModule, StyleClassModule, ButtonModule, SelectModule],
|
|
1254
1166
|
host: { class: 'relative' },
|
|
1255
1167
|
template: `
|
|
@@ -1272,10 +1184,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1272
1184
|
}
|
|
1273
1185
|
</button>
|
|
1274
1186
|
<div
|
|
1275
|
-
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]"
|
|
1187
|
+
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)] w-[calc(100vw-2rem)] sm:w-auto sm:min-w-[300px] max-w-[360px]"
|
|
1276
1188
|
style="background-color: var(--surface-overlay)"
|
|
1277
1189
|
>
|
|
1278
|
-
<div class="flex flex-col gap-4
|
|
1190
|
+
<div class="flex flex-col gap-4">
|
|
1279
1191
|
<span class="text-sm text-muted-color font-semibold"
|
|
1280
1192
|
>Switch Company & Branch</span
|
|
1281
1193
|
>
|
|
@@ -1334,22 +1246,23 @@ class AppLauncher {
|
|
|
1334
1246
|
document = inject(DOCUMENT$1);
|
|
1335
1247
|
elementRef = inject(ElementRef);
|
|
1336
1248
|
layoutService = inject(LayoutService);
|
|
1337
|
-
|
|
1249
|
+
_isActive = signal(false, ...(ngDevMode ? [{ debugName: "_isActive" }] : []));
|
|
1250
|
+
isActive = this._isActive.asReadonly();
|
|
1338
1251
|
constructor() {
|
|
1339
1252
|
fromEvent(this.document, 'click')
|
|
1340
|
-
.pipe(takeUntilDestroyed(this.destroyRef), filter(() => this.
|
|
1253
|
+
.pipe(takeUntilDestroyed(this.destroyRef), filter(() => this._isActive()))
|
|
1341
1254
|
.subscribe((event) => {
|
|
1342
1255
|
const target = event.target;
|
|
1343
1256
|
if (!this.elementRef.nativeElement.contains(target)) {
|
|
1344
|
-
this.
|
|
1257
|
+
this._isActive.set(false);
|
|
1345
1258
|
}
|
|
1346
1259
|
});
|
|
1347
1260
|
}
|
|
1348
1261
|
togglePanel() {
|
|
1349
|
-
this.
|
|
1262
|
+
this._isActive.update((v) => !v);
|
|
1350
1263
|
}
|
|
1351
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1352
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
1264
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppLauncher, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1265
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AppLauncher, isStandalone: true, selector: "app-launcher", host: { classAttribute: "relative" }, ngImport: i0, template: `
|
|
1353
1266
|
<button
|
|
1354
1267
|
type="button"
|
|
1355
1268
|
class="layout-topbar-action"
|
|
@@ -1366,15 +1279,15 @@ class AppLauncher {
|
|
|
1366
1279
|
<span>Apps</span>
|
|
1367
1280
|
</button>
|
|
1368
1281
|
<div
|
|
1369
|
-
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]"
|
|
1282
|
+
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)] w-[calc(100vw-2rem)] sm:w-auto sm:min-w-[280px] max-w-[320px]"
|
|
1370
1283
|
style="background-color: var(--surface-overlay)"
|
|
1371
1284
|
>
|
|
1372
|
-
<div class="flex flex-col gap-2
|
|
1285
|
+
<div class="flex flex-col gap-2">
|
|
1373
1286
|
<span class="text-sm text-muted-color font-semibold">Applications</span>
|
|
1374
|
-
<div class="grid grid-cols-3 gap-2">
|
|
1287
|
+
<div class="grid grid-cols-2 sm:grid-cols-3 gap-2">
|
|
1375
1288
|
@for (app of layoutService.apps(); track app.id) {
|
|
1376
1289
|
<a
|
|
1377
|
-
class="group flex flex-col items-center
|
|
1290
|
+
class="group flex flex-col items-center p-2 rounded-border cursor-pointer no-underline transition-all duration-200 hover:bg-emphasis"
|
|
1378
1291
|
[href]="app.url"
|
|
1379
1292
|
target="_blank"
|
|
1380
1293
|
rel="noopener noreferrer"
|
|
@@ -1389,7 +1302,7 @@ class AppLauncher {
|
|
|
1389
1302
|
/>
|
|
1390
1303
|
</div>
|
|
1391
1304
|
<span
|
|
1392
|
-
class="text-xs mt-2 text-center text-muted-color group-hover:text-color transition-colors duration-200"
|
|
1305
|
+
class="text-xs mt-2 text-center text-muted-color group-hover:text-color transition-colors duration-200 truncate max-w-full"
|
|
1393
1306
|
>{{ app.name }}</span
|
|
1394
1307
|
>
|
|
1395
1308
|
</a>
|
|
@@ -1397,13 +1310,13 @@ class AppLauncher {
|
|
|
1397
1310
|
</div>
|
|
1398
1311
|
</div>
|
|
1399
1312
|
</div>
|
|
1400
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i2$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: IconComponent, selector: "lib-icon", inputs: ["icon", "iconType"] }] });
|
|
1313
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i2$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: IconComponent, selector: "lib-icon", inputs: ["icon", "iconType"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1401
1314
|
}
|
|
1402
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1315
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppLauncher, decorators: [{
|
|
1403
1316
|
type: Component,
|
|
1404
1317
|
args: [{
|
|
1405
1318
|
selector: 'app-launcher',
|
|
1406
|
-
|
|
1319
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1407
1320
|
imports: [StyleClassModule, IconComponent],
|
|
1408
1321
|
host: { class: 'relative' },
|
|
1409
1322
|
template: `
|
|
@@ -1423,15 +1336,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1423
1336
|
<span>Apps</span>
|
|
1424
1337
|
</button>
|
|
1425
1338
|
<div
|
|
1426
|
-
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]"
|
|
1339
|
+
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)] w-[calc(100vw-2rem)] sm:w-auto sm:min-w-[280px] max-w-[320px]"
|
|
1427
1340
|
style="background-color: var(--surface-overlay)"
|
|
1428
1341
|
>
|
|
1429
|
-
<div class="flex flex-col gap-2
|
|
1342
|
+
<div class="flex flex-col gap-2">
|
|
1430
1343
|
<span class="text-sm text-muted-color font-semibold">Applications</span>
|
|
1431
|
-
<div class="grid grid-cols-3 gap-2">
|
|
1344
|
+
<div class="grid grid-cols-2 sm:grid-cols-3 gap-2">
|
|
1432
1345
|
@for (app of layoutService.apps(); track app.id) {
|
|
1433
1346
|
<a
|
|
1434
|
-
class="group flex flex-col items-center
|
|
1347
|
+
class="group flex flex-col items-center p-2 rounded-border cursor-pointer no-underline transition-all duration-200 hover:bg-emphasis"
|
|
1435
1348
|
[href]="app.url"
|
|
1436
1349
|
target="_blank"
|
|
1437
1350
|
rel="noopener noreferrer"
|
|
@@ -1446,7 +1359,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1446
1359
|
/>
|
|
1447
1360
|
</div>
|
|
1448
1361
|
<span
|
|
1449
|
-
class="text-xs mt-2 text-center text-muted-color group-hover:text-color transition-colors duration-200"
|
|
1362
|
+
class="text-xs mt-2 text-center text-muted-color group-hover:text-color transition-colors duration-200 truncate max-w-full"
|
|
1450
1363
|
>{{ app.name }}</span
|
|
1451
1364
|
>
|
|
1452
1365
|
</a>
|
|
@@ -1466,23 +1379,23 @@ class AppProfile {
|
|
|
1466
1379
|
messageService = inject(MessageService);
|
|
1467
1380
|
document = inject(DOCUMENT$1);
|
|
1468
1381
|
elementRef = inject(ElementRef);
|
|
1469
|
-
|
|
1382
|
+
_isActive = signal(false, ...(ngDevMode ? [{ debugName: "_isActive" }] : []));
|
|
1383
|
+
isActive = this._isActive.asReadonly();
|
|
1470
1384
|
constructor() {
|
|
1471
1385
|
fromEvent(this.document, 'click')
|
|
1472
1386
|
.pipe(takeUntilDestroyed(this.destroyRef), filter(() => this.isActive()))
|
|
1473
1387
|
.subscribe((event) => {
|
|
1474
1388
|
const target = event.target;
|
|
1475
1389
|
if (!this.elementRef.nativeElement.contains(target)) {
|
|
1476
|
-
this.
|
|
1390
|
+
this._isActive.set(false);
|
|
1477
1391
|
}
|
|
1478
1392
|
});
|
|
1479
1393
|
}
|
|
1480
1394
|
togglePanel() {
|
|
1481
|
-
this.
|
|
1395
|
+
this._isActive.update((v) => !v);
|
|
1482
1396
|
}
|
|
1483
1397
|
userName = computed(() => this.authState?.loginUserData()?.name ?? 'Guest', ...(ngDevMode ? [{ debugName: "userName" }] : []));
|
|
1484
1398
|
userEmail = computed(() => this.authState?.loginUserData()?.email ?? '', ...(ngDevMode ? [{ debugName: "userEmail" }] : []));
|
|
1485
|
-
// Use LayoutService for profile picture URL (synced by AuthLayoutSyncService)
|
|
1486
1399
|
profilePicture = computed(() => this.layoutService.userProfilePictureUrl() ?? '', ...(ngDevMode ? [{ debugName: "profilePicture" }] : []));
|
|
1487
1400
|
logout() {
|
|
1488
1401
|
if (!this.authApi)
|
|
@@ -1499,12 +1412,8 @@ class AppProfile {
|
|
|
1499
1412
|
});
|
|
1500
1413
|
this.authApi?.navigateLogin(false);
|
|
1501
1414
|
},
|
|
1502
|
-
error: (
|
|
1503
|
-
|
|
1504
|
-
severity: 'error',
|
|
1505
|
-
summary: 'Error',
|
|
1506
|
-
detail: err?.message || 'Failed to logout',
|
|
1507
|
-
});
|
|
1415
|
+
error: () => {
|
|
1416
|
+
// Error toast handled by global interceptor
|
|
1508
1417
|
},
|
|
1509
1418
|
});
|
|
1510
1419
|
}
|
|
@@ -1528,8 +1437,8 @@ class AppProfile {
|
|
|
1528
1437
|
});
|
|
1529
1438
|
});
|
|
1530
1439
|
}
|
|
1531
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1532
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
1440
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppProfile, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1441
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AppProfile, isStandalone: true, selector: "app-profile", host: { classAttribute: "relative" }, ngImport: i0, template: `
|
|
1533
1442
|
<button
|
|
1534
1443
|
type="button"
|
|
1535
1444
|
class="layout-topbar-action"
|
|
@@ -1546,10 +1455,10 @@ class AppProfile {
|
|
|
1546
1455
|
<span>Profile</span>
|
|
1547
1456
|
</button>
|
|
1548
1457
|
<div
|
|
1549
|
-
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]"
|
|
1458
|
+
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)] w-[calc(100vw-2rem)] sm:w-auto sm:min-w-[280px] max-w-[320px]"
|
|
1550
1459
|
style="background-color: var(--surface-overlay)"
|
|
1551
1460
|
>
|
|
1552
|
-
<div class="flex flex-col gap-3
|
|
1461
|
+
<div class="flex flex-col gap-3">
|
|
1553
1462
|
<!-- User Info -->
|
|
1554
1463
|
<a
|
|
1555
1464
|
class="flex items-center gap-3 p-3 rounded-border cursor-pointer no-underline hover:bg-emphasis transition-all duration-200"
|
|
@@ -1568,9 +1477,9 @@ class AppProfile {
|
|
|
1568
1477
|
<i class="pi pi-user text-xl text-primary-contrast"></i>
|
|
1569
1478
|
</div>
|
|
1570
1479
|
}
|
|
1571
|
-
<div class="flex flex-col">
|
|
1572
|
-
<span class="font-semibold text-color">{{ userName() }}</span>
|
|
1573
|
-
<span class="text-sm text-muted-color">{{ userEmail() }}</span>
|
|
1480
|
+
<div class="flex flex-col min-w-0 flex-1">
|
|
1481
|
+
<span class="font-semibold text-color truncate">{{ userName() }}</span>
|
|
1482
|
+
<span class="text-sm text-muted-color truncate">{{ userEmail() }}</span>
|
|
1574
1483
|
</div>
|
|
1575
1484
|
</a>
|
|
1576
1485
|
|
|
@@ -1596,13 +1505,13 @@ class AppProfile {
|
|
|
1596
1505
|
</div>
|
|
1597
1506
|
</div>
|
|
1598
1507
|
</div>
|
|
1599
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2$2.IsEmptyImageDirective, selector: "img", inputs: ["src"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i2$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }] });
|
|
1508
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2$2.IsEmptyImageDirective, selector: "img", inputs: ["src"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i2$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1600
1509
|
}
|
|
1601
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1510
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppProfile, decorators: [{
|
|
1602
1511
|
type: Component,
|
|
1603
1512
|
args: [{
|
|
1604
1513
|
selector: 'app-profile',
|
|
1605
|
-
|
|
1514
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1606
1515
|
imports: [AngularModule, StyleClassModule],
|
|
1607
1516
|
host: { class: 'relative' },
|
|
1608
1517
|
template: `
|
|
@@ -1622,10 +1531,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1622
1531
|
<span>Profile</span>
|
|
1623
1532
|
</button>
|
|
1624
1533
|
<div
|
|
1625
|
-
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]"
|
|
1534
|
+
class="hidden absolute top-[3.25rem] right-0 z-50 p-4 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)] w-[calc(100vw-2rem)] sm:w-auto sm:min-w-[280px] max-w-[320px]"
|
|
1626
1535
|
style="background-color: var(--surface-overlay)"
|
|
1627
1536
|
>
|
|
1628
|
-
<div class="flex flex-col gap-3
|
|
1537
|
+
<div class="flex flex-col gap-3">
|
|
1629
1538
|
<!-- User Info -->
|
|
1630
1539
|
<a
|
|
1631
1540
|
class="flex items-center gap-3 p-3 rounded-border cursor-pointer no-underline hover:bg-emphasis transition-all duration-200"
|
|
@@ -1644,9 +1553,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1644
1553
|
<i class="pi pi-user text-xl text-primary-contrast"></i>
|
|
1645
1554
|
</div>
|
|
1646
1555
|
}
|
|
1647
|
-
<div class="flex flex-col">
|
|
1648
|
-
<span class="font-semibold text-color">{{ userName() }}</span>
|
|
1649
|
-
<span class="text-sm text-muted-color">{{ userEmail() }}</span>
|
|
1556
|
+
<div class="flex flex-col min-w-0 flex-1">
|
|
1557
|
+
<span class="font-semibold text-color truncate">{{ userName() }}</span>
|
|
1558
|
+
<span class="text-sm text-muted-color truncate">{{ userEmail() }}</span>
|
|
1650
1559
|
</div>
|
|
1651
1560
|
</a>
|
|
1652
1561
|
|
|
@@ -1690,16 +1599,13 @@ class AppTopbar {
|
|
|
1690
1599
|
this.handleOutsideClick(event);
|
|
1691
1600
|
});
|
|
1692
1601
|
}
|
|
1693
|
-
// Use layoutService.companyName which falls back to appName
|
|
1694
1602
|
companyName = this.layoutService.companyName;
|
|
1695
1603
|
enableCompanyFeature = computed(() => {
|
|
1696
1604
|
return isCompanyFeatureEnabled(this.appConfig);
|
|
1697
1605
|
}, ...(ngDevMode ? [{ debugName: "enableCompanyFeature" }] : []));
|
|
1698
1606
|
toggleDarkMode() {
|
|
1699
|
-
this.layoutService.layoutConfig
|
|
1700
|
-
|
|
1701
|
-
darkTheme: !state.darkTheme,
|
|
1702
|
-
}));
|
|
1607
|
+
const currentDarkTheme = this.layoutService.layoutConfig().darkTheme;
|
|
1608
|
+
this.layoutService.updateLayoutConfig({ darkTheme: !currentDarkTheme });
|
|
1703
1609
|
}
|
|
1704
1610
|
togglePanel(panel) {
|
|
1705
1611
|
this.activePanel.update((current) => (current === panel ? null : panel));
|
|
@@ -1711,8 +1617,8 @@ class AppTopbar {
|
|
|
1711
1617
|
this.activePanel.set(null);
|
|
1712
1618
|
}
|
|
1713
1619
|
}
|
|
1714
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1715
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
1620
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppTopbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1621
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AppTopbar, isStandalone: true, selector: "app-topbar", viewQueries: [{ propertyName: "configContainer", first: true, predicate: ["configContainer"], descendants: true, isSignal: true }], ngImport: i0, template: ` <div class="layout-topbar">
|
|
1716
1622
|
<div class="layout-topbar-logo-container">
|
|
1717
1623
|
<button
|
|
1718
1624
|
class="layout-menu-button layout-topbar-action"
|
|
@@ -1733,11 +1639,9 @@ class AppTopbar {
|
|
|
1733
1639
|
(click)="toggleDarkMode()"
|
|
1734
1640
|
>
|
|
1735
1641
|
<i
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
'pi-sun': !layoutService.isDarkTheme(),
|
|
1740
|
-
}"
|
|
1642
|
+
class="pi"
|
|
1643
|
+
[class.pi-moon]="layoutService.isDarkTheme()"
|
|
1644
|
+
[class.pi-sun]="!layoutService.isDarkTheme()"
|
|
1741
1645
|
></i>
|
|
1742
1646
|
</button>
|
|
1743
1647
|
<div class="relative" #configContainer>
|
|
@@ -1782,16 +1686,15 @@ class AppTopbar {
|
|
|
1782
1686
|
</div>
|
|
1783
1687
|
</div>
|
|
1784
1688
|
</div>
|
|
1785
|
-
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type:
|
|
1689
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i2$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfigurator, selector: "app-configurator" }, { kind: "component", type: AppProfile, selector: "app-profile" }, { kind: "component", type: AppCompanyBranchSelector, selector: "app-company-branch-selector" }, { kind: "component", type: AppLauncher, selector: "app-launcher" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1786
1690
|
}
|
|
1787
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1691
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppTopbar, decorators: [{
|
|
1788
1692
|
type: Component,
|
|
1789
1693
|
args: [{
|
|
1790
1694
|
selector: 'app-topbar',
|
|
1791
|
-
|
|
1695
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1792
1696
|
imports: [
|
|
1793
1697
|
RouterModule,
|
|
1794
|
-
CommonModule,
|
|
1795
1698
|
StyleClassModule,
|
|
1796
1699
|
AppConfigurator,
|
|
1797
1700
|
AppProfile,
|
|
@@ -1819,11 +1722,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1819
1722
|
(click)="toggleDarkMode()"
|
|
1820
1723
|
>
|
|
1821
1724
|
<i
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
'pi-sun': !layoutService.isDarkTheme(),
|
|
1826
|
-
}"
|
|
1725
|
+
class="pi"
|
|
1726
|
+
[class.pi-moon]="layoutService.isDarkTheme()"
|
|
1727
|
+
[class.pi-sun]="!layoutService.isDarkTheme()"
|
|
1827
1728
|
></i>
|
|
1828
1729
|
</button>
|
|
1829
1730
|
<div class="relative" #configContainer>
|
|
@@ -1880,10 +1781,10 @@ class AppMenuitem {
|
|
|
1880
1781
|
// Injected services
|
|
1881
1782
|
router = inject(Router);
|
|
1882
1783
|
layoutService = inject(LayoutService);
|
|
1883
|
-
authState = inject(LAYOUT_AUTH_STATE, { optional: true });
|
|
1884
1784
|
destroyRef = inject(DestroyRef);
|
|
1885
|
-
// State signals
|
|
1886
|
-
|
|
1785
|
+
// State signals - private writable + public readonly pattern
|
|
1786
|
+
_active = signal(false, ...(ngDevMode ? [{ debugName: "_active" }] : []));
|
|
1787
|
+
active = this._active.asReadonly();
|
|
1887
1788
|
// Computed signals
|
|
1888
1789
|
key = computed(() => {
|
|
1889
1790
|
const parent = this.parentKey();
|
|
@@ -1912,19 +1813,19 @@ class AppMenuitem {
|
|
|
1912
1813
|
Promise.resolve(null).then(() => {
|
|
1913
1814
|
const currentKey = this.key();
|
|
1914
1815
|
if (value.routeEvent) {
|
|
1915
|
-
this.
|
|
1816
|
+
this._active.set(value.key === currentKey ||
|
|
1916
1817
|
value.key?.startsWith(currentKey + '-'));
|
|
1917
1818
|
}
|
|
1918
1819
|
else if (value.key !== currentKey &&
|
|
1919
1820
|
!value.key?.startsWith(currentKey + '-')) {
|
|
1920
|
-
this.
|
|
1821
|
+
this._active.set(false);
|
|
1921
1822
|
}
|
|
1922
1823
|
});
|
|
1923
1824
|
});
|
|
1924
1825
|
// Subscribe to menu reset
|
|
1925
1826
|
this.layoutService.resetSource$
|
|
1926
1827
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1927
|
-
.subscribe(() => this.
|
|
1828
|
+
.subscribe(() => this._active.set(false));
|
|
1928
1829
|
// Subscribe to navigation events
|
|
1929
1830
|
this.router.events
|
|
1930
1831
|
.pipe(filter((event) => event instanceof NavigationEnd), takeUntilDestroyed(this.destroyRef))
|
|
@@ -1963,12 +1864,12 @@ class AppMenuitem {
|
|
|
1963
1864
|
}
|
|
1964
1865
|
itemClick() {
|
|
1965
1866
|
if (this.item().children) {
|
|
1966
|
-
this.
|
|
1867
|
+
this._active.update((prev) => !prev);
|
|
1967
1868
|
}
|
|
1968
1869
|
this.layoutService.onMenuStateChange({ key: this.key() });
|
|
1969
1870
|
}
|
|
1970
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1971
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
1871
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppMenuitem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1872
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AppMenuitem, isStandalone: true, selector: "[app-menuitem]", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: true, transformFunction: null }, parentKey: { classPropertyName: "parentKey", publicName: "parentKey", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.active-menuitem": "active()" } }, ngImport: i0, template: `
|
|
1972
1873
|
<ng-container>
|
|
1973
1874
|
@if (item().children?.length) {
|
|
1974
1875
|
<a (click)="itemClick()" tabindex="0" pRipple>
|
|
@@ -2024,11 +1925,11 @@ class AppMenuitem {
|
|
|
2024
1925
|
</ul>
|
|
2025
1926
|
}
|
|
2026
1927
|
</ng-container>
|
|
2027
|
-
`, isInline: true, styles: [":host ul{overflow:hidden;transition:max-height .4s cubic-bezier(.86,0,.07,1)}:host ul.submenu-collapsed{max-height:0}:host ul.submenu-expanded{max-height:1000px}\n"], dependencies: [{ kind: "component", type: AppMenuitem, selector: "[app-menuitem]", inputs: ["item", "index", "parentKey"] }, { kind: "component", type: IconComponent, selector: "lib-icon", inputs: ["icon", "iconType"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i2$3.Ripple, selector: "[pRipple]" }] });
|
|
1928
|
+
`, isInline: true, styles: [":host ul{overflow:hidden;transition:max-height .4s cubic-bezier(.86,0,.07,1)}:host ul.submenu-collapsed{max-height:0}:host ul.submenu-expanded{max-height:1000px}\n"], dependencies: [{ kind: "component", type: AppMenuitem, selector: "[app-menuitem]", inputs: ["item", "index", "parentKey"] }, { kind: "component", type: IconComponent, selector: "lib-icon", inputs: ["icon", "iconType"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i2$3.Ripple, selector: "[pRipple]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2028
1929
|
}
|
|
2029
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1930
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppMenuitem, decorators: [{
|
|
2030
1931
|
type: Component,
|
|
2031
|
-
args: [{ selector: '[app-menuitem]',
|
|
1932
|
+
args: [{ selector: '[app-menuitem]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [IconComponent, RouterModule, RippleModule], template: `
|
|
2032
1933
|
<ng-container>
|
|
2033
1934
|
@if (item().children?.length) {
|
|
2034
1935
|
<a (click)="itemClick()" tabindex="0" pRipple>
|
|
@@ -2103,8 +2004,8 @@ class AppMenu {
|
|
|
2103
2004
|
* - Permission state changes (user permissions updated)
|
|
2104
2005
|
*/
|
|
2105
2006
|
menuItems = this.layoutService.menu;
|
|
2106
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
2107
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
2007
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2008
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AppMenu, isStandalone: true, selector: "app-menu", ngImport: i0, template: `<div class="layout-menu">
|
|
2108
2009
|
<ul>
|
|
2109
2010
|
@for (
|
|
2110
2011
|
item of menuItems();
|
|
@@ -2114,13 +2015,13 @@ class AppMenu {
|
|
|
2114
2015
|
<li app-menuitem [item]="item" [index]="i"></li>
|
|
2115
2016
|
}
|
|
2116
2017
|
</ul>
|
|
2117
|
-
</div>`, isInline: true, dependencies: [{ kind: "component", type: AppMenuitem, selector: "[app-menuitem]", inputs: ["item", "index", "parentKey"] }, { kind: "ngmodule", type: RouterModule }] });
|
|
2018
|
+
</div>`, isInline: true, dependencies: [{ kind: "component", type: AppMenuitem, selector: "[app-menuitem]", inputs: ["item", "index", "parentKey"] }, { kind: "ngmodule", type: RouterModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2118
2019
|
}
|
|
2119
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
2020
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppMenu, decorators: [{
|
|
2120
2021
|
type: Component,
|
|
2121
2022
|
args: [{
|
|
2122
2023
|
selector: 'app-menu',
|
|
2123
|
-
|
|
2024
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2124
2025
|
imports: [AppMenuitem, RouterModule],
|
|
2125
2026
|
template: `<div class="layout-menu">
|
|
2126
2027
|
<ul>
|
|
@@ -2137,18 +2038,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2137
2038
|
}] });
|
|
2138
2039
|
|
|
2139
2040
|
class AppSidebar {
|
|
2140
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
2141
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.
|
|
2041
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2042
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: AppSidebar, isStandalone: true, selector: "app-sidebar", ngImport: i0, template: `
|
|
2142
2043
|
<div class="layout-sidebar">
|
|
2143
2044
|
<app-menu />
|
|
2144
2045
|
</div>
|
|
2145
|
-
`, isInline: true, dependencies: [{ kind: "component", type: AppMenu, selector: "app-menu" }] });
|
|
2046
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AppMenu, selector: "app-menu" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2146
2047
|
}
|
|
2147
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
2048
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppSidebar, decorators: [{
|
|
2148
2049
|
type: Component,
|
|
2149
2050
|
args: [{
|
|
2150
2051
|
selector: 'app-sidebar',
|
|
2151
|
-
|
|
2052
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2152
2053
|
imports: [AppMenu],
|
|
2153
2054
|
template: `
|
|
2154
2055
|
<div class="layout-sidebar">
|
|
@@ -2165,8 +2066,6 @@ class AppLayout {
|
|
|
2165
2066
|
renderer = inject(Renderer2);
|
|
2166
2067
|
router = inject(Router);
|
|
2167
2068
|
menuOutsideClickListener = null;
|
|
2168
|
-
appSidebar;
|
|
2169
|
-
appTopBar;
|
|
2170
2069
|
constructor() {
|
|
2171
2070
|
this.layoutService.overlayOpen$
|
|
2172
2071
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
@@ -2196,12 +2095,11 @@ class AppLayout {
|
|
|
2196
2095
|
topbarEl?.contains(eventTarget));
|
|
2197
2096
|
}
|
|
2198
2097
|
hideMenu() {
|
|
2199
|
-
this.layoutService.
|
|
2200
|
-
...prev,
|
|
2098
|
+
this.layoutService.updateLayoutState({
|
|
2201
2099
|
overlayMenuActive: false,
|
|
2202
2100
|
staticMenuMobileActive: false,
|
|
2203
2101
|
menuHoverActive: false,
|
|
2204
|
-
})
|
|
2102
|
+
});
|
|
2205
2103
|
if (this.menuOutsideClickListener) {
|
|
2206
2104
|
this.menuOutsideClickListener();
|
|
2207
2105
|
this.menuOutsideClickListener = null;
|
|
@@ -2214,7 +2112,7 @@ class AppLayout {
|
|
|
2214
2112
|
unblockBodyScroll() {
|
|
2215
2113
|
this.document.body.classList.remove('blocked-scroll');
|
|
2216
2114
|
}
|
|
2217
|
-
|
|
2115
|
+
containerClass = computed(() => {
|
|
2218
2116
|
const config = this.layoutService.layoutConfig();
|
|
2219
2117
|
const state = this.layoutService.layoutState();
|
|
2220
2118
|
return {
|
|
@@ -2224,10 +2122,10 @@ class AppLayout {
|
|
|
2224
2122
|
'layout-overlay-active': state.overlayMenuActive,
|
|
2225
2123
|
'layout-mobile-active': state.staticMenuMobileActive,
|
|
2226
2124
|
};
|
|
2227
|
-
}
|
|
2228
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
2229
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.
|
|
2230
|
-
<div class="layout-wrapper" [ngClass]="containerClass">
|
|
2125
|
+
}, ...(ngDevMode ? [{ debugName: "containerClass" }] : []));
|
|
2126
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppLayout, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2127
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: AppLayout, isStandalone: true, selector: "app-layout", ngImport: i0, template: `
|
|
2128
|
+
<div class="layout-wrapper" [ngClass]="containerClass()">
|
|
2231
2129
|
<app-topbar></app-topbar>
|
|
2232
2130
|
<app-sidebar></app-sidebar>
|
|
2233
2131
|
<div class="layout-main-container">
|
|
@@ -2238,16 +2136,16 @@ class AppLayout {
|
|
|
2238
2136
|
</div>
|
|
2239
2137
|
<div class="layout-mask animate-fadein"></div>
|
|
2240
2138
|
</div>
|
|
2241
|
-
`, isInline: true, dependencies: [{ kind: "
|
|
2139
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "app-topbar" }, { kind: "component", type: AppSidebar, selector: "app-sidebar" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$2.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AppFooter, selector: "app-footer" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2242
2140
|
}
|
|
2243
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
2141
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AppLayout, decorators: [{
|
|
2244
2142
|
type: Component,
|
|
2245
2143
|
args: [{
|
|
2246
2144
|
selector: 'app-layout',
|
|
2247
|
-
|
|
2248
|
-
imports: [
|
|
2145
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2146
|
+
imports: [NgClass, AppTopbar, AppSidebar, RouterModule, AppFooter],
|
|
2249
2147
|
template: `
|
|
2250
|
-
<div class="layout-wrapper" [ngClass]="containerClass">
|
|
2148
|
+
<div class="layout-wrapper" [ngClass]="containerClass()">
|
|
2251
2149
|
<app-topbar></app-topbar>
|
|
2252
2150
|
<app-sidebar></app-sidebar>
|
|
2253
2151
|
<div class="layout-main-container">
|
|
@@ -2260,50 +2158,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2260
2158
|
</div>
|
|
2261
2159
|
`,
|
|
2262
2160
|
}]
|
|
2263
|
-
}], ctorParameters: () => []
|
|
2264
|
-
type: ViewChild,
|
|
2265
|
-
args: [AppSidebar]
|
|
2266
|
-
}], appTopBar: [{
|
|
2267
|
-
type: ViewChild,
|
|
2268
|
-
args: [AppTopbar]
|
|
2269
|
-
}] } });
|
|
2161
|
+
}], ctorParameters: () => [] });
|
|
2270
2162
|
|
|
2271
|
-
const
|
|
2163
|
+
const NavyBlueTheme = definePreset(Material, {
|
|
2272
2164
|
semantic: {
|
|
2273
2165
|
colorScheme: {
|
|
2274
2166
|
light: {
|
|
2275
2167
|
primary: {
|
|
2276
|
-
color: '#
|
|
2277
|
-
inverseColor: '#
|
|
2278
|
-
hoverColor: '#
|
|
2279
|
-
activeColor: '#
|
|
2168
|
+
color: '#3535cd',
|
|
2169
|
+
inverseColor: '#0707a9',
|
|
2170
|
+
hoverColor: '#0707a9',
|
|
2171
|
+
activeColor: '#0707a9',
|
|
2280
2172
|
},
|
|
2281
2173
|
highlight: {
|
|
2282
2174
|
background: '#e2e8f0',
|
|
2283
2175
|
focusBackground: '#e2e8f0',
|
|
2284
|
-
color: '#
|
|
2285
|
-
focusColor: '#
|
|
2176
|
+
color: '#3535cd',
|
|
2177
|
+
focusColor: '#3535cd',
|
|
2286
2178
|
},
|
|
2287
2179
|
},
|
|
2288
2180
|
},
|
|
2289
2181
|
},
|
|
2290
2182
|
});
|
|
2291
2183
|
|
|
2292
|
-
const
|
|
2184
|
+
const GreenTheme = definePreset(Material, {
|
|
2293
2185
|
semantic: {
|
|
2294
2186
|
colorScheme: {
|
|
2295
2187
|
light: {
|
|
2296
2188
|
primary: {
|
|
2297
|
-
color: '#
|
|
2298
|
-
inverseColor: '#
|
|
2299
|
-
hoverColor: '#
|
|
2300
|
-
activeColor: '#
|
|
2189
|
+
color: '#01712c',
|
|
2190
|
+
inverseColor: '#119744',
|
|
2191
|
+
hoverColor: '#119744',
|
|
2192
|
+
activeColor: '#119744',
|
|
2301
2193
|
},
|
|
2302
2194
|
highlight: {
|
|
2303
2195
|
background: '#e2e8f0',
|
|
2304
2196
|
focusBackground: '#e2e8f0',
|
|
2305
|
-
color: '#
|
|
2306
|
-
focusColor: '#
|
|
2197
|
+
color: '#01712c',
|
|
2198
|
+
focusColor: '#01712c',
|
|
2307
2199
|
},
|
|
2308
2200
|
},
|
|
2309
2201
|
},
|