@flusys/ng-layout 1.0.0-rc → 1.0.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 +1 -1
- package/fesm2022/flusys-ng-layout.mjs +94 -210
- package/fesm2022/flusys-ng-layout.mjs.map +1 -1
- package/package.json +12 -12
- package/types/flusys-ng-layout.d.ts +47 -84
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { isPlatformBrowser, NgClass, DOCUMENT as DOCUMENT$1 } from '@angular/common';
|
|
2
1
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, PLATFORM_ID, Injectable, DOCUMENT, signal, computed, effect,
|
|
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';
|
|
4
8
|
import * as i1 from '@angular/forms';
|
|
5
9
|
import { FormsModule } from '@angular/forms';
|
|
6
10
|
import * as i1$2 from '@angular/router';
|
|
@@ -11,10 +15,6 @@ import Lara from '@primeuix/themes/lara';
|
|
|
11
15
|
import Nora from '@primeuix/themes/nora';
|
|
12
16
|
import * as i2 from 'primeng/selectbutton';
|
|
13
17
|
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
14
|
-
import { APP_CONFIG, DEFAULT_APP_NAME, DEFAULT_AUTHOR, isCompanyFeatureEnabled } from '@flusys/ng-core';
|
|
15
|
-
import * as i2$2 from '@flusys/ng-shared';
|
|
16
|
-
import { evaluateLogicNode, PermissionValidatorService, AngularModule, IconComponent } from '@flusys/ng-shared';
|
|
17
|
-
import { Subject, fromEvent, filter as filter$1 } from 'rxjs';
|
|
18
18
|
import * as i1$1 from 'primeng/button';
|
|
19
19
|
import { ButtonModule } from 'primeng/button';
|
|
20
20
|
import * as i2$1 from 'primeng/styleclass';
|
|
@@ -202,80 +202,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
202
202
|
}]
|
|
203
203
|
}] });
|
|
204
204
|
|
|
205
|
-
/**
|
|
206
|
-
* Service managing layout configuration and state.
|
|
207
|
-
* Provides signals for reactive layout updates.
|
|
208
|
-
*/
|
|
205
|
+
/** Layout configuration and state management service */
|
|
209
206
|
class LayoutService {
|
|
210
207
|
document = inject(DOCUMENT);
|
|
211
208
|
platformId = inject(PLATFORM_ID);
|
|
212
209
|
isBrowser = isPlatformBrowser(this.platformId);
|
|
213
210
|
persistence = inject(LayoutPersistenceService);
|
|
214
211
|
appConfig = inject(APP_CONFIG, { optional: true });
|
|
215
|
-
|
|
212
|
+
DEFAULT_CONFIG = {
|
|
216
213
|
preset: 'Aura',
|
|
217
214
|
primary: 'emerald',
|
|
218
215
|
surface: null,
|
|
219
216
|
darkTheme: false,
|
|
220
217
|
menuMode: 'static',
|
|
221
218
|
};
|
|
222
|
-
|
|
223
|
-
initialConfig = (() => {
|
|
224
|
-
const persisted = this.persistence.load();
|
|
225
|
-
return persisted
|
|
226
|
-
? { ...this.defaultConfig, ...persisted }
|
|
227
|
-
: this.defaultConfig;
|
|
228
|
-
})();
|
|
229
|
-
defaultState = {
|
|
219
|
+
DEFAULT_STATE = {
|
|
230
220
|
staticMenuDesktopInactive: false,
|
|
231
221
|
overlayMenuActive: false,
|
|
232
222
|
configSidebarVisible: false,
|
|
233
223
|
staticMenuMobileActive: false,
|
|
234
224
|
menuHoverActive: false,
|
|
235
225
|
};
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
226
|
+
_layoutConfig = signal({
|
|
227
|
+
...this.DEFAULT_CONFIG,
|
|
228
|
+
...this.persistence.load(),
|
|
229
|
+
}, ...(ngDevMode ? [{ debugName: "_layoutConfig" }] : []));
|
|
230
|
+
_layoutState = signal(this.DEFAULT_STATE, ...(ngDevMode ? [{ debugName: "_layoutState" }] : []));
|
|
239
231
|
_transitionComplete = signal(false, ...(ngDevMode ? [{ debugName: "_transitionComplete" }] : []));
|
|
240
232
|
layoutConfig = this._layoutConfig.asReadonly();
|
|
241
233
|
layoutState = this._layoutState.asReadonly();
|
|
242
234
|
transitionComplete = this._transitionComplete.asReadonly();
|
|
243
|
-
// User Profile Signals (private writable, public readonly)
|
|
244
235
|
_userProfile = signal(null, ...(ngDevMode ? [{ debugName: "_userProfile" }] : []));
|
|
245
236
|
_companyProfile = signal(null, ...(ngDevMode ? [{ debugName: "_companyProfile" }] : []));
|
|
246
|
-
_appName = signal(this.appConfig?.appName ?? DEFAULT_APP_NAME, ...(ngDevMode ? [{ debugName: "_appName" }] : []));
|
|
247
|
-
userProfile = this._userProfile.asReadonly();
|
|
248
|
-
companyProfile = this._companyProfile.asReadonly();
|
|
249
|
-
appName = this._appName.asReadonly();
|
|
250
|
-
// Author/Brand Signals (private writable, public readonly)
|
|
251
|
-
_authorName = signal(this.appConfig?.author?.name ?? DEFAULT_AUTHOR.name, ...(ngDevMode ? [{ debugName: "_authorName" }] : []));
|
|
252
|
-
_authorUrl = signal(this.appConfig?.author?.url ?? DEFAULT_AUTHOR.url, ...(ngDevMode ? [{ debugName: "_authorUrl" }] : []));
|
|
253
|
-
authorName = this._authorName.asReadonly();
|
|
254
|
-
authorUrl = this._authorUrl.asReadonly();
|
|
255
|
-
// App Launcher Signals
|
|
256
|
-
_rawApps = signal([], ...(ngDevMode ? [{ debugName: "_rawApps" }] : []));
|
|
257
|
-
/**
|
|
258
|
-
* Filtered launcher apps based on user permissions.
|
|
259
|
-
* Automatically recomputes when raw apps or permissions change.
|
|
260
|
-
*/
|
|
261
|
-
apps = computed(() => {
|
|
262
|
-
const raw = this._rawApps();
|
|
263
|
-
const permission = this.permissionValidator.permissions();
|
|
264
|
-
return filterAppsByPermissions(raw, permission);
|
|
265
|
-
}, ...(ngDevMode ? [{ debugName: "apps" }] : []));
|
|
266
|
-
// Menu Signals
|
|
267
237
|
_rawMenu = signal([], ...(ngDevMode ? [{ debugName: "_rawMenu" }] : []));
|
|
238
|
+
_rawApps = signal([], ...(ngDevMode ? [{ debugName: "_rawApps" }] : []));
|
|
268
239
|
permissionValidator = inject(PermissionValidatorService);
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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" }] : []));
|
|
279
250
|
// Computed signals - Layout
|
|
280
251
|
isSidebarActive = computed(() => this._layoutState().overlayMenuActive ||
|
|
281
252
|
this._layoutState().staticMenuMobileActive, ...(ngDevMode ? [{ debugName: "isSidebarActive" }] : []));
|
|
@@ -283,21 +254,17 @@ class LayoutService {
|
|
|
283
254
|
getPrimary = computed(() => this._layoutConfig().primary, ...(ngDevMode ? [{ debugName: "getPrimary" }] : []));
|
|
284
255
|
getSurface = computed(() => this._layoutConfig().surface, ...(ngDevMode ? [{ debugName: "getSurface" }] : []));
|
|
285
256
|
isOverlay = computed(() => this._layoutConfig().menuMode === 'overlay', ...(ngDevMode ? [{ debugName: "isOverlay" }] : []));
|
|
286
|
-
//
|
|
257
|
+
// User profile computed signals
|
|
287
258
|
userName = computed(() => this._userProfile()?.name ?? 'User', ...(ngDevMode ? [{ debugName: "userName" }] : []));
|
|
288
259
|
userEmail = computed(() => this._userProfile()?.email ?? '', ...(ngDevMode ? [{ debugName: "userEmail" }] : []));
|
|
289
260
|
userProfilePictureUrl = computed(() => this._userProfile()?.profilePictureUrl ?? null, ...(ngDevMode ? [{ debugName: "userProfilePictureUrl" }] : []));
|
|
290
|
-
companyName = computed(() => {
|
|
291
|
-
// If company feature is disabled, always show app name
|
|
292
|
-
if (!this.appConfig || !isCompanyFeatureEnabled(this.appConfig)) {
|
|
293
|
-
return this._appName();
|
|
294
|
-
}
|
|
295
|
-
return this._companyProfile()?.name ?? this._appName();
|
|
296
|
-
}, ...(ngDevMode ? [{ debugName: "companyName" }] : []));
|
|
297
261
|
companyLogoUrl = computed(() => this._companyProfile()?.logoUrl ?? null, ...(ngDevMode ? [{ debugName: "companyLogoUrl" }] : []));
|
|
298
262
|
isAuthenticated = computed(() => !!this._userProfile(), ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : []));
|
|
299
|
-
|
|
300
|
-
|
|
263
|
+
companyName = computed(() => {
|
|
264
|
+
if (!this.appConfig || !isCompanyFeatureEnabled(this.appConfig))
|
|
265
|
+
return this.appName;
|
|
266
|
+
return this._companyProfile()?.name ?? this.appName;
|
|
267
|
+
}, ...(ngDevMode ? [{ debugName: "companyName" }] : []));
|
|
301
268
|
// RxJS Subjects for event communication
|
|
302
269
|
configUpdate = new Subject();
|
|
303
270
|
overlayOpen = new Subject();
|
|
@@ -311,80 +278,55 @@ class LayoutService {
|
|
|
311
278
|
constructor() {
|
|
312
279
|
effect(() => {
|
|
313
280
|
const config = this._layoutConfig();
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
});
|
|
318
|
-
effect(() => {
|
|
319
|
-
const config = this._layoutConfig();
|
|
320
|
-
if (!this.initialized || !config) {
|
|
321
|
-
this.initialized = true;
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
this.handleDarkModeTransition(config);
|
|
325
|
-
});
|
|
326
|
-
// Auto-save configuration changes to localStorage
|
|
327
|
-
effect(() => {
|
|
328
|
-
const config = this._layoutConfig();
|
|
329
|
-
if (config && this.initialized) {
|
|
281
|
+
this.configUpdate.next(config);
|
|
282
|
+
if (this.initialized) {
|
|
283
|
+
this.handleDarkModeTransition(config);
|
|
330
284
|
this.persistence.save(config);
|
|
331
285
|
}
|
|
286
|
+
this.initialized = true;
|
|
332
287
|
});
|
|
333
288
|
}
|
|
289
|
+
toggleDarkMode(config) {
|
|
290
|
+
const isDark = (config ?? this._layoutConfig()).darkTheme;
|
|
291
|
+
this.document.documentElement.classList.toggle('app-dark', isDark);
|
|
292
|
+
}
|
|
334
293
|
handleDarkModeTransition(config) {
|
|
335
294
|
const doc = this.document;
|
|
336
|
-
// Check for View Transitions API support (not all browsers support it)
|
|
337
295
|
if ('startViewTransition' in doc && typeof doc.startViewTransition === 'function') {
|
|
338
|
-
|
|
296
|
+
doc
|
|
297
|
+
.startViewTransition(() => this.toggleDarkMode(config))
|
|
298
|
+
.ready.then(() => this.onTransitionEnd())
|
|
299
|
+
.catch(() => { });
|
|
339
300
|
}
|
|
340
301
|
else {
|
|
341
302
|
this.toggleDarkMode(config);
|
|
342
303
|
this.onTransitionEnd();
|
|
343
304
|
}
|
|
344
305
|
}
|
|
345
|
-
startViewTransition(config, doc) {
|
|
346
|
-
const transition = doc.startViewTransition(() => {
|
|
347
|
-
this.toggleDarkMode(config);
|
|
348
|
-
});
|
|
349
|
-
transition.ready.then(() => this.onTransitionEnd()).catch(() => { });
|
|
350
|
-
}
|
|
351
|
-
toggleDarkMode(config) {
|
|
352
|
-
const _config = config || this._layoutConfig();
|
|
353
|
-
if (_config.darkTheme) {
|
|
354
|
-
this.document.documentElement.classList.add('app-dark');
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
this.document.documentElement.classList.remove('app-dark');
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
306
|
onTransitionEnd() {
|
|
361
307
|
this._transitionComplete.set(true);
|
|
362
308
|
setTimeout(() => this._transitionComplete.set(false));
|
|
363
309
|
}
|
|
364
310
|
onMenuToggle() {
|
|
311
|
+
const state = this._layoutState();
|
|
365
312
|
if (this.isOverlay()) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}));
|
|
370
|
-
if (this._layoutState().overlayMenuActive) {
|
|
313
|
+
const newOverlayActive = !state.overlayMenuActive;
|
|
314
|
+
this._layoutState.update((prev) => ({ ...prev, overlayMenuActive: newOverlayActive }));
|
|
315
|
+
if (newOverlayActive)
|
|
371
316
|
this.overlayOpen.next();
|
|
372
|
-
|
|
317
|
+
return;
|
|
373
318
|
}
|
|
374
319
|
if (this.isDesktop()) {
|
|
375
320
|
this._layoutState.update((prev) => ({
|
|
376
321
|
...prev,
|
|
377
|
-
staticMenuDesktopInactive: !
|
|
322
|
+
staticMenuDesktopInactive: !state.staticMenuDesktopInactive,
|
|
378
323
|
}));
|
|
379
324
|
}
|
|
380
325
|
else {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}));
|
|
385
|
-
if (this._layoutState().staticMenuMobileActive) {
|
|
326
|
+
const newMobileActive = !state.staticMenuMobileActive;
|
|
327
|
+
this._layoutState.update((prev) => ({ ...prev, staticMenuMobileActive: newMobileActive }));
|
|
328
|
+
if (newMobileActive)
|
|
386
329
|
this.overlayOpen.next();
|
|
387
|
-
}
|
|
388
330
|
}
|
|
389
331
|
}
|
|
390
332
|
isDesktop() {
|
|
@@ -393,82 +335,36 @@ class LayoutService {
|
|
|
393
335
|
isMobile() {
|
|
394
336
|
return !this.isDesktop();
|
|
395
337
|
}
|
|
396
|
-
onConfigUpdate() {
|
|
397
|
-
this.configUpdate.next(this._layoutConfig());
|
|
398
|
-
}
|
|
399
338
|
onMenuStateChange(event) {
|
|
400
339
|
this.menuSource.next(event);
|
|
401
340
|
}
|
|
402
341
|
reset() {
|
|
403
342
|
this.resetSource.next(true);
|
|
404
343
|
}
|
|
405
|
-
//
|
|
406
|
-
// Layout Config Methods
|
|
407
|
-
// ==========================================================================
|
|
408
|
-
/**
|
|
409
|
-
* Update layout configuration.
|
|
410
|
-
* Called by configurator component.
|
|
411
|
-
*/
|
|
344
|
+
// Config & state updates
|
|
412
345
|
updateLayoutConfig(config) {
|
|
413
346
|
this._layoutConfig.update((prev) => ({ ...prev, ...config }));
|
|
414
347
|
}
|
|
415
|
-
/**
|
|
416
|
-
* Update layout state.
|
|
417
|
-
* Called internally and by layout components.
|
|
418
|
-
*/
|
|
419
348
|
updateLayoutState(state) {
|
|
420
349
|
this._layoutState.update((prev) => ({ ...prev, ...state }));
|
|
421
350
|
}
|
|
422
|
-
//
|
|
423
|
-
// User Profile Methods
|
|
424
|
-
// ==========================================================================
|
|
425
|
-
/**
|
|
426
|
-
* Set the current user profile for display in layout.
|
|
427
|
-
* Called by auth integration to sync user data.
|
|
428
|
-
*/
|
|
351
|
+
// Profile setters
|
|
429
352
|
setUserProfile(profile) {
|
|
430
353
|
this._userProfile.set(profile);
|
|
431
354
|
}
|
|
432
|
-
/**
|
|
433
|
-
* Set the current company profile for display in layout.
|
|
434
|
-
* Called by auth integration to sync company data.
|
|
435
|
-
*/
|
|
436
355
|
setCompanyProfile(profile) {
|
|
437
356
|
this._companyProfile.set(profile);
|
|
438
357
|
}
|
|
439
|
-
//
|
|
440
|
-
// Menu Methods
|
|
441
|
-
// ==========================================================================
|
|
442
|
-
/**
|
|
443
|
-
* Set the raw menu items (unfiltered).
|
|
444
|
-
* Menu will be automatically filtered based on permission checker.
|
|
445
|
-
* Called by app initialization to set menu from IAM or other source.
|
|
446
|
-
*/
|
|
358
|
+
// Menu & apps
|
|
447
359
|
setMenu(items) {
|
|
448
360
|
this._rawMenu.set(items);
|
|
449
361
|
}
|
|
450
|
-
/**
|
|
451
|
-
* Clear menu and permission/role checkers.
|
|
452
|
-
* Called on logout.
|
|
453
|
-
*/
|
|
454
362
|
clearMenu() {
|
|
455
363
|
this._rawMenu.set([]);
|
|
456
364
|
}
|
|
457
|
-
// ==========================================================================
|
|
458
|
-
// App Launcher Methods
|
|
459
|
-
// ==========================================================================
|
|
460
|
-
/**
|
|
461
|
-
* Set launcher apps for display in header.
|
|
462
|
-
* Apps will be automatically filtered based on user permissions.
|
|
463
|
-
* If empty after filtering, the app launcher button is hidden.
|
|
464
|
-
*/
|
|
465
365
|
setApps(apps) {
|
|
466
366
|
this._rawApps.set(apps);
|
|
467
367
|
}
|
|
468
|
-
/**
|
|
469
|
-
* Clear launcher apps.
|
|
470
|
-
* Called on logout.
|
|
471
|
-
*/
|
|
472
368
|
clearApps() {
|
|
473
369
|
this._rawApps.set([]);
|
|
474
370
|
}
|
|
@@ -477,10 +373,32 @@ class LayoutService {
|
|
|
477
373
|
}
|
|
478
374
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LayoutService, decorators: [{
|
|
479
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.3", ngImport: i0, type: AppFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
386
|
+
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">
|
|
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.3", ngImport: i0, type: AppFooter, decorators: [{
|
|
392
|
+
type: Component,
|
|
480
393
|
args: [{
|
|
481
|
-
|
|
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>`,
|
|
482
400
|
}]
|
|
483
|
-
}]
|
|
401
|
+
}] });
|
|
484
402
|
|
|
485
403
|
const presets = {
|
|
486
404
|
Aura,
|
|
@@ -913,7 +831,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
913
831
|
type: Component,
|
|
914
832
|
args: [{
|
|
915
833
|
selector: 'app-configurator',
|
|
916
|
-
standalone: true,
|
|
917
834
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
918
835
|
imports: [NgClass, FormsModule, SelectButtonModule],
|
|
919
836
|
template: `
|
|
@@ -1013,7 +930,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1013
930
|
type: Component,
|
|
1014
931
|
args: [{
|
|
1015
932
|
selector: 'app-floating-configurator',
|
|
1016
|
-
standalone: true,
|
|
1017
933
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1018
934
|
imports: [ButtonModule, StyleClassModule, AppConfigurator],
|
|
1019
935
|
template: `
|
|
@@ -1028,31 +944,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1028
944
|
}]
|
|
1029
945
|
}] });
|
|
1030
946
|
|
|
1031
|
-
class AppFooter {
|
|
1032
|
-
layoutService = inject(LayoutService);
|
|
1033
|
-
// Footer shows product branding (appName), not user's company
|
|
1034
|
-
appName = this.layoutService.appName;
|
|
1035
|
-
authorName = this.layoutService.authorName;
|
|
1036
|
-
authorUrl = this.layoutService.authorUrl;
|
|
1037
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1038
|
-
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">
|
|
1039
|
-
{{ appName() }} by
|
|
1040
|
-
<a [href]="authorUrl()" target="_blank" rel="noopener noreferrer" class="text-primary font-bold hover:underline">{{ authorName() }}</a>
|
|
1041
|
-
</div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1042
|
-
}
|
|
1043
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppFooter, decorators: [{
|
|
1044
|
-
type: Component,
|
|
1045
|
-
args: [{
|
|
1046
|
-
standalone: true,
|
|
1047
|
-
selector: 'app-footer',
|
|
1048
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1049
|
-
template: `<div class="layout-footer">
|
|
1050
|
-
{{ appName() }} by
|
|
1051
|
-
<a [href]="authorUrl()" target="_blank" rel="noopener noreferrer" class="text-primary font-bold hover:underline">{{ authorName() }}</a>
|
|
1052
|
-
</div>`,
|
|
1053
|
-
}]
|
|
1054
|
-
}] });
|
|
1055
|
-
|
|
1056
947
|
const LAYOUT_AUTH_STATE = new InjectionToken('LAYOUT_AUTH_STATE');
|
|
1057
948
|
const LAYOUT_AUTH_API = new InjectionToken('LAYOUT_AUTH_API');
|
|
1058
949
|
|
|
@@ -1270,7 +1161,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1270
1161
|
type: Component,
|
|
1271
1162
|
args: [{
|
|
1272
1163
|
selector: 'app-company-branch-selector',
|
|
1273
|
-
standalone: true,
|
|
1274
1164
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1275
1165
|
imports: [AngularModule, StyleClassModule, ButtonModule, SelectModule],
|
|
1276
1166
|
host: { class: 'relative' },
|
|
@@ -1426,7 +1316,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1426
1316
|
type: Component,
|
|
1427
1317
|
args: [{
|
|
1428
1318
|
selector: 'app-launcher',
|
|
1429
|
-
standalone: true,
|
|
1430
1319
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1431
1320
|
imports: [StyleClassModule, IconComponent],
|
|
1432
1321
|
host: { class: 'relative' },
|
|
@@ -1622,7 +1511,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1622
1511
|
type: Component,
|
|
1623
1512
|
args: [{
|
|
1624
1513
|
selector: 'app-profile',
|
|
1625
|
-
standalone: true,
|
|
1626
1514
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1627
1515
|
imports: [AngularModule, StyleClassModule],
|
|
1628
1516
|
host: { class: 'relative' },
|
|
@@ -1804,7 +1692,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1804
1692
|
type: Component,
|
|
1805
1693
|
args: [{
|
|
1806
1694
|
selector: 'app-topbar',
|
|
1807
|
-
standalone: true,
|
|
1808
1695
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1809
1696
|
imports: [
|
|
1810
1697
|
RouterModule,
|
|
@@ -2042,7 +1929,7 @@ class AppMenuitem {
|
|
|
2042
1929
|
}
|
|
2043
1930
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppMenuitem, decorators: [{
|
|
2044
1931
|
type: Component,
|
|
2045
|
-
args: [{ selector: '[app-menuitem]',
|
|
1932
|
+
args: [{ selector: '[app-menuitem]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [IconComponent, RouterModule, RippleModule], template: `
|
|
2046
1933
|
<ng-container>
|
|
2047
1934
|
@if (item().children?.length) {
|
|
2048
1935
|
<a (click)="itemClick()" tabindex="0" pRipple>
|
|
@@ -2134,7 +2021,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2134
2021
|
type: Component,
|
|
2135
2022
|
args: [{
|
|
2136
2023
|
selector: 'app-menu',
|
|
2137
|
-
standalone: true,
|
|
2138
2024
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2139
2025
|
imports: [AppMenuitem, RouterModule],
|
|
2140
2026
|
template: `<div class="layout-menu">
|
|
@@ -2163,7 +2049,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2163
2049
|
type: Component,
|
|
2164
2050
|
args: [{
|
|
2165
2051
|
selector: 'app-sidebar',
|
|
2166
|
-
standalone: true,
|
|
2167
2052
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2168
2053
|
imports: [AppMenu],
|
|
2169
2054
|
template: `
|
|
@@ -2257,7 +2142,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2257
2142
|
type: Component,
|
|
2258
2143
|
args: [{
|
|
2259
2144
|
selector: 'app-layout',
|
|
2260
|
-
standalone: true,
|
|
2261
2145
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2262
2146
|
imports: [NgClass, AppTopbar, AppSidebar, RouterModule, AppFooter],
|
|
2263
2147
|
template: `
|
|
@@ -2276,42 +2160,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2276
2160
|
}]
|
|
2277
2161
|
}], ctorParameters: () => [] });
|
|
2278
2162
|
|
|
2279
|
-
const
|
|
2163
|
+
const NavyBlueTheme = definePreset(Material, {
|
|
2280
2164
|
semantic: {
|
|
2281
2165
|
colorScheme: {
|
|
2282
2166
|
light: {
|
|
2283
2167
|
primary: {
|
|
2284
|
-
color: '#
|
|
2285
|
-
inverseColor: '#
|
|
2286
|
-
hoverColor: '#
|
|
2287
|
-
activeColor: '#
|
|
2168
|
+
color: '#3535cd',
|
|
2169
|
+
inverseColor: '#0707a9',
|
|
2170
|
+
hoverColor: '#0707a9',
|
|
2171
|
+
activeColor: '#0707a9',
|
|
2288
2172
|
},
|
|
2289
2173
|
highlight: {
|
|
2290
2174
|
background: '#e2e8f0',
|
|
2291
2175
|
focusBackground: '#e2e8f0',
|
|
2292
|
-
color: '#
|
|
2293
|
-
focusColor: '#
|
|
2176
|
+
color: '#3535cd',
|
|
2177
|
+
focusColor: '#3535cd',
|
|
2294
2178
|
},
|
|
2295
2179
|
},
|
|
2296
2180
|
},
|
|
2297
2181
|
},
|
|
2298
2182
|
});
|
|
2299
2183
|
|
|
2300
|
-
const
|
|
2184
|
+
const GreenTheme = definePreset(Material, {
|
|
2301
2185
|
semantic: {
|
|
2302
2186
|
colorScheme: {
|
|
2303
2187
|
light: {
|
|
2304
2188
|
primary: {
|
|
2305
|
-
color: '#
|
|
2306
|
-
inverseColor: '#
|
|
2307
|
-
hoverColor: '#
|
|
2308
|
-
activeColor: '#
|
|
2189
|
+
color: '#01712c',
|
|
2190
|
+
inverseColor: '#119744',
|
|
2191
|
+
hoverColor: '#119744',
|
|
2192
|
+
activeColor: '#119744',
|
|
2309
2193
|
},
|
|
2310
2194
|
highlight: {
|
|
2311
2195
|
background: '#e2e8f0',
|
|
2312
2196
|
focusBackground: '#e2e8f0',
|
|
2313
|
-
color: '#
|
|
2314
|
-
focusColor: '#
|
|
2197
|
+
color: '#01712c',
|
|
2198
|
+
focusColor: '#01712c',
|
|
2315
2199
|
},
|
|
2316
2200
|
},
|
|
2317
2201
|
},
|