sgh-navbar 0.1.3 → 0.2.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 +12 -201
- package/fesm2022/sgh-navbar.mjs +36 -189
- package/fesm2022/sgh-navbar.mjs.map +1 -1
- package/lib/sidenav/sublevel-menu.component.d.ts +0 -5
- package/lib/toolbar/sub-client-dialog/sub-client-dialog.component.d.ts +5 -29
- package/lib/toolbar/toolbar.component.d.ts +1 -20
- package/package.json +8 -39
package/fesm2022/sgh-navbar.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, Input, HostBinding, ViewEncapsulation, Component, EventEmitter, Output, Inject, Pipe,
|
|
2
|
+
import { Injectable, Input, HostBinding, ViewEncapsulation, Component, EventEmitter, Output, Inject, Pipe, HostListener, ViewChild, NgModule } from '@angular/core';
|
|
3
3
|
import { BehaviorSubject, Subject } from 'rxjs';
|
|
4
4
|
import * as i2 from '@angular/common';
|
|
5
5
|
import { CommonModule } from '@angular/common';
|
|
@@ -11,12 +11,11 @@ import * as i1$1 from '@angular/material/dialog';
|
|
|
11
11
|
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
12
12
|
import * as i4 from '@angular/material/radio';
|
|
13
13
|
import { MatRadioModule } from '@angular/material/radio';
|
|
14
|
-
import * as
|
|
15
|
-
import * as i5 from '@angular/forms';
|
|
14
|
+
import * as i4$1 from '@angular/forms';
|
|
16
15
|
import { FormsModule } from '@angular/forms';
|
|
17
|
-
import * as
|
|
16
|
+
import * as i5 from '@angular/material/menu';
|
|
18
17
|
import { MatMenuModule } from '@angular/material/menu';
|
|
19
|
-
import * as
|
|
18
|
+
import * as i6 from '@angular/material/core';
|
|
20
19
|
import { MatRippleModule } from '@angular/material/core';
|
|
21
20
|
|
|
22
21
|
class SghNavbarService {
|
|
@@ -170,10 +169,7 @@ class MenuListItemComponent {
|
|
|
170
169
|
if (!item.items || !item.items.length) {
|
|
171
170
|
if (item.routeLink) {
|
|
172
171
|
this.router.navigate([item.routeLink]).catch(error => {
|
|
173
|
-
|
|
174
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
175
|
-
console.error('Navigation error:', error);
|
|
176
|
-
}
|
|
172
|
+
console.error('Navigation error:', error);
|
|
177
173
|
});
|
|
178
174
|
}
|
|
179
175
|
}
|
|
@@ -224,10 +220,7 @@ class SidenavComponent {
|
|
|
224
220
|
this.client = client;
|
|
225
221
|
},
|
|
226
222
|
error: (error) => {
|
|
227
|
-
|
|
228
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
229
|
-
console.error('Error getting client:', error);
|
|
230
|
-
}
|
|
223
|
+
console.error('Error getting client:', error);
|
|
231
224
|
}
|
|
232
225
|
});
|
|
233
226
|
this.sidebarService.getSubclient()
|
|
@@ -237,10 +230,7 @@ class SidenavComponent {
|
|
|
237
230
|
this.subclient = subclient;
|
|
238
231
|
},
|
|
239
232
|
error: (error) => {
|
|
240
|
-
|
|
241
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
242
|
-
console.error('Error getting subclient:', error);
|
|
243
|
-
}
|
|
233
|
+
console.error('Error getting subclient:', error);
|
|
244
234
|
}
|
|
245
235
|
});
|
|
246
236
|
}
|
|
@@ -254,10 +244,7 @@ class SidenavComponent {
|
|
|
254
244
|
if (!item.items || !item.items.length) {
|
|
255
245
|
if (item.routeLink) {
|
|
256
246
|
this.router.navigate([item.routeLink]).catch(error => {
|
|
257
|
-
|
|
258
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
259
|
-
console.error('Navigation error:', error);
|
|
260
|
-
}
|
|
247
|
+
console.error('Navigation error:', error);
|
|
261
248
|
});
|
|
262
249
|
}
|
|
263
250
|
}
|
|
@@ -357,73 +344,27 @@ class SubClientDialogComponent {
|
|
|
357
344
|
this.data = data;
|
|
358
345
|
this.dialogRef = dialogRef;
|
|
359
346
|
this.sghNavbarService = sghNavbarService;
|
|
360
|
-
this.client = null;
|
|
361
|
-
this.subClientList = [];
|
|
362
347
|
this.subClient = new EventEmitter();
|
|
363
|
-
this.
|
|
364
|
-
this.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
*/
|
|
369
|
-
initializeData() {
|
|
370
|
-
// Validate that data and client exist
|
|
371
|
-
if (!this.data?.client) {
|
|
372
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
373
|
-
console.error('SubClientDialogComponent: Invalid dialog data - client is required');
|
|
374
|
-
}
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
this.client = this.data.client;
|
|
378
|
-
// Validate that subClientList exists and is an array
|
|
379
|
-
if (!Array.isArray(this.data.client.subClientList) || this.data.client.subClientList.length === 0) {
|
|
380
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
381
|
-
console.error('SubClientDialogComponent: Invalid dialog data - subClientList is required');
|
|
382
|
-
}
|
|
383
|
-
this.subClientList = [];
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
this.subClientList = this.data.client.subClientList;
|
|
387
|
-
// Find the selected sub client using strict equality
|
|
388
|
-
const selectedSubClientIndex = this.subClientList.findIndex((subClient) => subClient.checked === true);
|
|
389
|
-
// Validate index bounds before accessing array
|
|
390
|
-
if (selectedSubClientIndex >= 0 && selectedSubClientIndex < this.subClientList.length) {
|
|
391
|
-
this.selectedSubClient = this.subClientList[selectedSubClientIndex];
|
|
392
|
-
}
|
|
393
|
-
else {
|
|
394
|
-
// Default to first item if no selection found
|
|
395
|
-
this.selectedSubClient = this.subClientList[0] ?? null;
|
|
396
|
-
}
|
|
348
|
+
this.client = data.client;
|
|
349
|
+
this.subClientList = data.client.subClientList;
|
|
350
|
+
// find the selected sub client
|
|
351
|
+
let selectedSubClientIndex = this.subClientList.findIndex((subClient) => subClient.checked == true);
|
|
352
|
+
this.selectedSubClient = this.subClientList[selectedSubClientIndex];
|
|
397
353
|
}
|
|
398
|
-
/**
|
|
399
|
-
* Handles sub-client selection with proper validation
|
|
400
|
-
*/
|
|
401
354
|
onSubClientSelect(item) {
|
|
402
|
-
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
// Update the sub client list with newly selected values using strict equality
|
|
355
|
+
// update the sub client list with newly selected values
|
|
406
356
|
this.subClientList.forEach((subClient) => {
|
|
407
|
-
|
|
408
|
-
|
|
357
|
+
if (subClient == item) {
|
|
358
|
+
subClient.checked = true;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
subClient.checked = false;
|
|
362
|
+
}
|
|
409
363
|
});
|
|
410
364
|
this.selectedSubClient = item;
|
|
411
365
|
}
|
|
412
|
-
/**
|
|
413
|
-
* Closes the dialog and returns the selected sub-client
|
|
414
|
-
*/
|
|
415
366
|
onSelectBtnClick() {
|
|
416
|
-
|
|
417
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
418
|
-
console.warn('SubClientDialogComponent: No sub-client selected');
|
|
419
|
-
}
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
this.dialogRef.close({
|
|
423
|
-
data: {
|
|
424
|
-
selectedSubClient: this.selectedSubClient
|
|
425
|
-
}
|
|
426
|
-
});
|
|
367
|
+
this.dialogRef.close({ data: { selectedSubClient: this.selectedSubClient } });
|
|
427
368
|
}
|
|
428
369
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SubClientDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1$1.MatDialogRef }, { token: SghNavbarService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
429
370
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SubClientDialogComponent, isStandalone: false, selector: "lib-subclient-dialog", outputs: { subClient: "subClient" }, ngImport: i0, template: "<div class=\"subclientlist-wrapper dialog-wrapper\">\r\n <h4 class=\"subclientlist-header\">Select Sub Client</h4>\r\n <div class=\"subclientlist-body\">\r\n <div>\r\n <mat-radio-group class=\"subclientlist-radiogrp\" aria-label=\"Select an option\">\r\n <mat-radio-button [value]=\"item.value\" *ngFor=\"let item of subClientList;index as i\" (click)=\"onSubClientSelect(item)\" [checked]=\"item.checked\">{{item.text}}</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n </div>\r\n <div class=\"subclientlist-btns\">\r\n <button class=\"sgh-btn-primary\" (click)=\"onSelectBtnClick()\">Select</button>\r\n </div>\r\n</div>\r\n\r\n", styles: [".subclientlist-wrapper .subclientlist-header{font-weight:500;line-height:48px;display:flex;justify-content:center;align-items:center;padding-bottom:0;margin:0}.subclientlist-wrapper .subclientlist-body{font-weight:400;text-align:center;color:#000;padding:0 15px 15px}.subclientlist-wrapper .subclientlist-body .subclientlist-radiogrp{display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start}.subclientlist-wrapper .subclientlist-btns{padding:0;min-height:48px}.subclientlist-wrapper button{width:100%;margin-bottom:0}.subclientlist-wrapper .mat-mdc-dialog-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:0}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i4.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }] }); }
|
|
@@ -500,11 +441,11 @@ class NotificationListComponent {
|
|
|
500
441
|
ngOnInit() {
|
|
501
442
|
}
|
|
502
443
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NotificationListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
503
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: NotificationListComponent, isStandalone: false, selector: "sgh-notification-list", ngImport: i0, template: "<div class=\"notifications-list-wrapper\">\r\n <div class=\"notifications-list\">\r\n <div class=\"notifications-title\">\r\n <span class=\"title mat-h3\">Notifications</span>\r\n </div>\r\n <div class=\"notifications-list-item\">\r\n <span class=\"item-title mat-h4\">David James</span>\r\n <span class=\"item-description mat-h5\">A notification box show message</span>\r\n </div>\r\n <div class=\"notifications-list-item\">\r\n <span class=\"item-title mat-h4\">David James</span>\r\n <span class=\"item-description mat-h5\">A notification box show message</span>\r\n </div>\r\n <div class=\"notifications-title\">\r\n <span class=\"see-all mat-h4\">See all</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".notifications-list-wrapper{position:absolute;
|
|
444
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: NotificationListComponent, isStandalone: false, selector: "sgh-notification-list", ngImport: i0, template: "<div class=\"notifications-list-wrapper\">\r\n <div class=\"notifications-list\">\r\n <div class=\"notifications-title\">\r\n <span class=\"title mat-h3\">Notifications</span>\r\n </div>\r\n <div class=\"notifications-list-item\">\r\n <span class=\"item-title mat-h4\">David James</span>\r\n <span class=\"item-description mat-h5\">A notification box show message</span>\r\n </div>\r\n <div class=\"notifications-list-item\">\r\n <span class=\"item-title mat-h4\">David James</span>\r\n <span class=\"item-description mat-h5\">A notification box show message</span>\r\n </div>\r\n <div class=\"notifications-title\">\r\n <span class=\"see-all mat-h4\">See all</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".notifications-list-wrapper{padding:10px;position:absolute;right:10px;top:45px;z-index:2;color:#000000de;width:400px}.notifications-list-wrapper .notifications-list{box-shadow:0 2px 10px #00000026;position:relative}.notifications-list-wrapper .notifications-list .notifications-title{background-color:#fff;text-align:center;padding:20px 10px;border-bottom:1px solid #f1f1f3}.notifications-list-wrapper .notifications-list .notifications-list-item{padding:10px 10px 10px 30px;background-color:#e0eced;border-bottom:1px solid #f1f1f3}.notifications-list-wrapper .notifications-list .notifications-list-item .item-title{margin:0 5px 0 0;white-space:normal}.notifications-list-wrapper .notifications-list .notifications-list-item .item-description{margin:0;color:#000000de;opacity:.5;white-space:normal}.notifications-list-wrapper .notifications-list .see-all{background-color:#fff;color:#006068;font-weight:500}@media screen and (max-width: 599px){.notifications-list-wrapper{width:auto}}.notifications-list-wrapper{-webkit-animation:cardAnim 1s cubic-bezier(.33,1,.68,1) 0s 1 normal none;animation:cardAnim 1s cubic-bezier(.33,1,.68,1) 0s 1 normal none}@keyframes cardAnim{0%{opacity:0;transform:rotateX(-100deg);transform-origin:top}to{opacity:1;transform:rotateX(0);transform-origin:top}}\n"] }); }
|
|
504
445
|
}
|
|
505
446
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NotificationListComponent, decorators: [{
|
|
506
447
|
type: Component,
|
|
507
|
-
args: [{ selector: 'sgh-notification-list', standalone: false, template: "<div class=\"notifications-list-wrapper\">\r\n <div class=\"notifications-list\">\r\n <div class=\"notifications-title\">\r\n <span class=\"title mat-h3\">Notifications</span>\r\n </div>\r\n <div class=\"notifications-list-item\">\r\n <span class=\"item-title mat-h4\">David James</span>\r\n <span class=\"item-description mat-h5\">A notification box show message</span>\r\n </div>\r\n <div class=\"notifications-list-item\">\r\n <span class=\"item-title mat-h4\">David James</span>\r\n <span class=\"item-description mat-h5\">A notification box show message</span>\r\n </div>\r\n <div class=\"notifications-title\">\r\n <span class=\"see-all mat-h4\">See all</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".notifications-list-wrapper{position:absolute;
|
|
448
|
+
args: [{ selector: 'sgh-notification-list', standalone: false, template: "<div class=\"notifications-list-wrapper\">\r\n <div class=\"notifications-list\">\r\n <div class=\"notifications-title\">\r\n <span class=\"title mat-h3\">Notifications</span>\r\n </div>\r\n <div class=\"notifications-list-item\">\r\n <span class=\"item-title mat-h4\">David James</span>\r\n <span class=\"item-description mat-h5\">A notification box show message</span>\r\n </div>\r\n <div class=\"notifications-list-item\">\r\n <span class=\"item-title mat-h4\">David James</span>\r\n <span class=\"item-description mat-h5\">A notification box show message</span>\r\n </div>\r\n <div class=\"notifications-title\">\r\n <span class=\"see-all mat-h4\">See all</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".notifications-list-wrapper{padding:10px;position:absolute;right:10px;top:45px;z-index:2;color:#000000de;width:400px}.notifications-list-wrapper .notifications-list{box-shadow:0 2px 10px #00000026;position:relative}.notifications-list-wrapper .notifications-list .notifications-title{background-color:#fff;text-align:center;padding:20px 10px;border-bottom:1px solid #f1f1f3}.notifications-list-wrapper .notifications-list .notifications-list-item{padding:10px 10px 10px 30px;background-color:#e0eced;border-bottom:1px solid #f1f1f3}.notifications-list-wrapper .notifications-list .notifications-list-item .item-title{margin:0 5px 0 0;white-space:normal}.notifications-list-wrapper .notifications-list .notifications-list-item .item-description{margin:0;color:#000000de;opacity:.5;white-space:normal}.notifications-list-wrapper .notifications-list .see-all{background-color:#fff;color:#006068;font-weight:500}@media screen and (max-width: 599px){.notifications-list-wrapper{width:auto}}.notifications-list-wrapper{-webkit-animation:cardAnim 1s cubic-bezier(.33,1,.68,1) 0s 1 normal none;animation:cardAnim 1s cubic-bezier(.33,1,.68,1) 0s 1 normal none}@keyframes cardAnim{0%{opacity:0;transform:rotateX(-100deg);transform-origin:top}to{opacity:1;transform:rotateX(0);transform-origin:top}}\n"] }]
|
|
508
449
|
}], ctorParameters: () => [] });
|
|
509
450
|
|
|
510
451
|
class SearchPipe {
|
|
@@ -539,10 +480,9 @@ class ToolbarComponent {
|
|
|
539
480
|
}
|
|
540
481
|
this.wasInside = false;
|
|
541
482
|
}
|
|
542
|
-
constructor(dialog, sghNavbarSvc
|
|
483
|
+
constructor(dialog, sghNavbarSvc) {
|
|
543
484
|
this.dialog = dialog;
|
|
544
485
|
this.sghNavbarSvc = sghNavbarSvc;
|
|
545
|
-
this.sanitizer = sanitizer;
|
|
546
486
|
this.expanded = false;
|
|
547
487
|
this.toggleSidebarEvent = new EventEmitter();
|
|
548
488
|
this.toolbarData = DEFAULT_TOOLBAR_CONFIG;
|
|
@@ -554,67 +494,8 @@ class ToolbarComponent {
|
|
|
554
494
|
this.selected = 'sgh-default-theme';
|
|
555
495
|
this.wasInside = false;
|
|
556
496
|
this.selectedClient = null;
|
|
557
|
-
// Sanitized profile content to prevent XSS attacks
|
|
558
|
-
this.sanitizedProfileContent = null;
|
|
559
|
-
// Whitelist of allowed theme classes to prevent CSS injection
|
|
560
|
-
this.allowedThemes = [
|
|
561
|
-
'sgh-default-theme',
|
|
562
|
-
'sgh-blue-theme',
|
|
563
|
-
'sgh-light-theme',
|
|
564
|
-
'sgh-dark-theme',
|
|
565
|
-
'natera-theme'
|
|
566
|
-
];
|
|
567
|
-
// Whitelist of allowed image URL protocols
|
|
568
|
-
this.allowedImageProtocols = ['https:', 'data:'];
|
|
569
497
|
this.searchText = '';
|
|
570
498
|
}
|
|
571
|
-
/**
|
|
572
|
-
* Sanitizes HTML content to prevent XSS attacks.
|
|
573
|
-
* Uses Angular's built-in sanitization which removes dangerous content.
|
|
574
|
-
*/
|
|
575
|
-
sanitizeProfileContent(content) {
|
|
576
|
-
if (!content) {
|
|
577
|
-
return null;
|
|
578
|
-
}
|
|
579
|
-
// Use SecurityContext.HTML to sanitize - this removes dangerous elements like <script>
|
|
580
|
-
const sanitized = this.sanitizer.sanitize(SecurityContext.HTML, content);
|
|
581
|
-
return sanitized ? this.sanitizer.bypassSecurityTrustHtml(sanitized) : null;
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Validates and returns a safe image URL.
|
|
585
|
-
* Only allows https: and data: protocols to prevent javascript: injection.
|
|
586
|
-
*/
|
|
587
|
-
getSafeImageUrl() {
|
|
588
|
-
const defaultImage = 'assets/images/default-logo.png';
|
|
589
|
-
if (!this.toolbarData?.img) {
|
|
590
|
-
return defaultImage;
|
|
591
|
-
}
|
|
592
|
-
try {
|
|
593
|
-
const url = new URL(this.toolbarData.img, window.location.origin);
|
|
594
|
-
// Allow relative URLs (same origin) and whitelisted protocols
|
|
595
|
-
if (url.origin === window.location.origin ||
|
|
596
|
-
this.allowedImageProtocols.includes(url.protocol)) {
|
|
597
|
-
return this.toolbarData.img;
|
|
598
|
-
}
|
|
599
|
-
// Only log in development mode
|
|
600
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
601
|
-
console.warn('Blocked potentially unsafe image URL:', this.toolbarData.img);
|
|
602
|
-
}
|
|
603
|
-
return defaultImage;
|
|
604
|
-
}
|
|
605
|
-
catch {
|
|
606
|
-
// If URL parsing fails, check if it's a relative path (starts with / or doesn't contain ://)
|
|
607
|
-
if (this.toolbarData.img.startsWith('/') ||
|
|
608
|
-
!this.toolbarData.img.includes('://')) {
|
|
609
|
-
return this.toolbarData.img;
|
|
610
|
-
}
|
|
611
|
-
// Only log in development mode
|
|
612
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
613
|
-
console.warn('Invalid image URL format:', this.toolbarData.img);
|
|
614
|
-
}
|
|
615
|
-
return defaultImage;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
499
|
toggleSidebar() {
|
|
619
500
|
// Toggle the expanded state and emit the new value
|
|
620
501
|
const newExpandedState = !this.expanded;
|
|
@@ -631,9 +512,7 @@ class ToolbarComponent {
|
|
|
631
512
|
this.searchInputEvent.emit(this.searchInput);
|
|
632
513
|
}
|
|
633
514
|
ngAfterViewInit() {
|
|
634
|
-
//
|
|
635
|
-
this.sanitizedProfileContent = this.sanitizeProfileContent(this.toolbarData?.profileContent);
|
|
636
|
-
// Initially set client and subclients
|
|
515
|
+
// initially set client and subclients
|
|
637
516
|
// Use Promise-based timeout for better error handling
|
|
638
517
|
Promise.resolve().then(() => {
|
|
639
518
|
try {
|
|
@@ -651,31 +530,14 @@ class ToolbarComponent {
|
|
|
651
530
|
});
|
|
652
531
|
}
|
|
653
532
|
catch (error) {
|
|
654
|
-
|
|
655
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
656
|
-
console.error('Error initializing clients:', error);
|
|
657
|
-
}
|
|
533
|
+
console.error('Error initializing clients:', error);
|
|
658
534
|
}
|
|
659
535
|
});
|
|
660
536
|
}
|
|
661
|
-
/**
|
|
662
|
-
* Sets the theme class on the document body.
|
|
663
|
-
* Validates against a whitelist to prevent CSS injection attacks.
|
|
664
|
-
*/
|
|
665
537
|
setClass(selected) {
|
|
666
|
-
// Validate against whitelist to prevent CSS injection
|
|
667
|
-
if (!selected || !this.allowedThemes.includes(selected)) {
|
|
668
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
669
|
-
console.warn('Attempted to set invalid theme class:', selected);
|
|
670
|
-
}
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
538
|
this.selected = selected;
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
document.body.classList.remove(this.prev);
|
|
677
|
-
}
|
|
678
|
-
document.body.classList.add(selected);
|
|
539
|
+
window.document.body.classList.remove(this.prev);
|
|
540
|
+
window.document.body.classList.add(selected);
|
|
679
541
|
this.prev = selected;
|
|
680
542
|
}
|
|
681
543
|
onRadioClick(themeValue) {
|
|
@@ -713,10 +575,7 @@ class ToolbarComponent {
|
|
|
713
575
|
}
|
|
714
576
|
},
|
|
715
577
|
error: (error) => {
|
|
716
|
-
|
|
717
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
718
|
-
console.error('Error in subclient dialog:', error);
|
|
719
|
-
}
|
|
578
|
+
console.error('Error in subclient dialog:', error);
|
|
720
579
|
}
|
|
721
580
|
});
|
|
722
581
|
}
|
|
@@ -750,8 +609,8 @@ class ToolbarComponent {
|
|
|
750
609
|
}
|
|
751
610
|
});
|
|
752
611
|
}
|
|
753
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ToolbarComponent, deps: [{ token: i1$1.MatDialog }, { token: SghNavbarService }
|
|
754
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ToolbarComponent, isStandalone: false, selector: "sgh-toolbar", inputs: { expanded: "expanded", toolbarData: "toolbarData" }, outputs: { toggleSidebarEvent: "toggleSidebarEvent", searchInputEvent: "searchInputEvent", client: "client", subClient: "subClient" }, host: { listeners: { "click": "clickInside()", "document:click": "clickOut()" } }, viewQueries: [{ propertyName: "clientMenuTrigger", first: true, predicate: ["clientMenuTrigger"], descendants: true }], ngImport: i0, template: "<header class=\"sgh-toolbar\" [style.background-color]=\"toolbarData.bgColor\" id=\"toolBarWrapper\" role=\"banner\">\r\n <nav class=\"toolbar-main-wrapper\">\r\n <!-- Left Section -->\r\n <div class=\"toolbar-left-section\">\r\n <!-- Logo -->\r\n <div class=\"toolbar-logo\">\r\n <img class=\"logo-image\" [src]=\"getSafeImageUrl()\" alt=\"Application Logo\"/>\r\n </div>\r\n\r\n <!-- Menu Toggle -->\r\n <button class=\"toolbar-menu-toggle\"\r\n (click)=\"toggleSidebar()\"\r\n aria-label=\"Toggle navigation menu\"\r\n title=\"Toggle Menu\">\r\n <i class=\"fa fa-bars\"></i>\r\n </button>\r\n\r\n <!-- Search Bar -->\r\n <div class=\"toolbar-search\" *ngIf=\"toolbarData.searchEnable\">\r\n <form class=\"search-form\" (submit)=\"$event.preventDefault()\">\r\n <div class=\"search-input-wrapper\">\r\n <i class=\"fa fa-search search-icon\"></i>\r\n <input type=\"search\"\r\n class=\"search-input\"\r\n placeholder=\"Search...\"\r\n autocomplete=\"off\"\r\n aria-label=\"Search\"/>\r\n <button type=\"submit\" class=\"search-submit\" aria-label=\"Submit search\">\r\n <i class=\"fa fa-arrow-right\"></i>\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Section -->\r\n <div class=\"toolbar-right-section\">\r\n <!-- Notification Button -->\r\n <button *ngIf=\"toolbarData.notificationEnable\"\r\n class=\"toolbar-action-btn notification-btn\"\r\n (click)=\"toggleNotificationList()\"\r\n aria-label=\"View notifications\"\r\n title=\"Notifications\">\r\n <i class=\"fa fa-bell\"></i>\r\n <span class=\"notification-badge\" *ngIf=\"true\">3</span>\r\n </button>\r\n\r\n <!-- Settings Button -->\r\n <button *ngIf=\"toolbarData.settingsEnable\"\r\n class=\"toolbar-action-btn settings-btn\"\r\n [matMenuTriggerFor]=\"settingsMenu\"\r\n aria-label=\"Open settings\"\r\n title=\"Settings\">\r\n <i class=\"fa fa-cog\"></i>\r\n </button>\r\n\r\n <!-- User Profile Button -->\r\n <button *ngIf=\"toolbarData.profileEnable\"\r\n class=\"toolbar-action-btn profile-btn\"\r\n (click)=\"clickProfile()\"\r\n aria-label=\"View profile\"\r\n title=\"Profile\">\r\n <i class=\"fa fa-user-circle\"></i>\r\n </button>\r\n </div>\r\n </nav>\r\n</header>\r\n\r\n<!-- Profile Dropdown -->\r\n<div *ngIf=\"toolbarData.profileView\" class=\"toolbar-dropdown profile-dropdown\" @fadeInOut>\r\n <div class=\"dropdown-card\">\r\n <div class=\"dropdown-content\">\r\n <!-- Using sanitized content to prevent XSS attacks -->\r\n <div *ngIf=\"sanitizedProfileContent\" [innerHTML]=\"sanitizedProfileContent\"></div>\r\n <div *ngIf=\"!sanitizedProfileContent && toolbarData.profileContent\">\r\n <!-- Fallback: Display as plain text if sanitization fails -->\r\n <p>{{toolbarData.profileContent}}</p>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Settings Menu -->\r\n<mat-menu #settingsMenu=\"matMenu\" xPosition=\"before\" class=\"sgh-settings-menu\">\r\n <button mat-menu-item\r\n [matMenuTriggerFor]=\"appConfig\"\r\n *ngIf=\"toolbarData.applicationConfigurationEnable\"\r\n class=\"menu-item-with-icon\">\r\n <i class=\"fa fa-paint-brush menu-icon\"></i>\r\n <span>Application Settings</span>\r\n </button>\r\n <button mat-menu-item\r\n [matMenuTriggerFor]=\"clientConfig\"\r\n *ngIf=\"toolbarData.clientConfigurationEnable\"\r\n #clientMenuTrigger\r\n class=\"menu-item-with-icon\">\r\n <i class=\"fa fa-building menu-icon\"></i>\r\n <span>Client Settings</span>\r\n </button>\r\n</mat-menu>\r\n\r\n<!-- Application Configuration Menu -->\r\n<mat-menu #appConfig=\"matMenu\" xPosition=\"after\" class=\"sgh-app-config-menu\">\r\n <div class=\"theme-menu-header\">\r\n <i class=\"fa fa-palette\"></i>\r\n <span>Choose Theme</span>\r\n </div>\r\n <div *ngFor=\"let themeoption of toolbarData.themeOptions\" class=\"theme-option-wrapper\">\r\n <button mat-menu-item class=\"theme-radio-option\" (click)=\"onRadioClick(themeoption.value)\">\r\n <div class=\"radio-button\">\r\n <input value=\"{{themeoption.value}}\"\r\n name=\"radio\"\r\n type=\"radio\"\r\n [checked]=\"selected === themeoption.value\"\r\n [ngModel]=\"selected\"\r\n (ngModelChange)=\"setClass($event)\">\r\n <span class=\"radio-label\">{{themeoption.name}}</span>\r\n </div>\r\n </button>\r\n </div>\r\n</mat-menu>\r\n\r\n<!-- Client Configuration Menu -->\r\n<mat-menu #clientConfig=\"matMenu\" xPosition=\"after\" class=\"sgh-client-config-menu\">\r\n <div class=\"client-menu-container\">\r\n <div class=\"client-menu-header\">\r\n <i class=\"fa fa-building\"></i>\r\n <span>Select Client</span>\r\n </div>\r\n <div class=\"client-search-wrapper\" (click)=\"$event.stopPropagation();\">\r\n <i class=\"fa fa-search search-icon\"></i>\r\n <input type=\"text\"\r\n class=\"client-search-input\"\r\n placeholder=\"Search clients...\"\r\n [(ngModel)]=\"searchText\"\r\n autocomplete=\"off\"/>\r\n </div>\r\n <div class=\"client-list-container\">\r\n <div class=\"client-list-item\"\r\n *ngFor=\"let item of toolbarData.clientList | search : searchText; let i = index\"\r\n [class.selected]=\"item.selected\"\r\n (click)=\"toggleSelect($event, item);\"\r\n mat-ripple>\r\n <i class=\"fa fa-check-circle check-icon\" *ngIf=\"item.selected\"></i>\r\n <span class=\"client-name\">{{item.text}}</span>\r\n </div>\r\n <div class=\"no-results\" *ngIf=\"(toolbarData.clientList | search : searchText)?.length === 0\">\r\n <i class=\"fa fa-search\"></i>\r\n <span>No clients found</span>\r\n </div>\r\n </div>\r\n </div>\r\n</mat-menu>\r\n\r\n<sgh-notification-list *ngIf=\"toolbarData.isNotifNavCollapsed\"></sgh-notification-list>\r\n", styles: [".sgh-toolbar{position:sticky;top:0;z-index:1000;box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f;background:var(--sgh-toolbar-bg, rgba(255, 255, 255, .95));border-bottom:1px solid var(--sgh-border-color, #e2e8f0)}@supports (backdrop-filter: blur(10px)){.sgh-toolbar{background:var(--sgh-toolbar-bg, rgba(255, 255, 255, .85));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}}.toolbar-main-wrapper{display:flex;align-items:center;justify-content:space-between;height:64px;padding:0 1.5rem;max-width:100%;margin:0 auto;transition:all .3s cubic-bezier(.4,0,.2,1)}@media (max-width: 768px){.toolbar-main-wrapper{height:56px;padding:0 1rem}}.toolbar-left-section{display:flex;align-items:center;gap:5rem;flex:1;min-width:0}.toolbar-logo{display:flex;align-items:center;flex-shrink:0}.toolbar-logo .logo-image{height:42px;width:auto;max-width:200px;object-fit:contain;cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);filter:drop-shadow(0 1px 2px rgba(0,0,0,.05))}.toolbar-logo .logo-image:hover{transform:scale(1.02);filter:drop-shadow(0 2px 4px rgba(0,0,0,.1))}.toolbar-logo .logo-image:active{transform:scale(.98)}.toolbar-menu-toggle{display:flex;align-items:center;justify-content:center;width:42px;height:42px;padding:0;border:none;border-radius:12px;background:transparent;color:var(--sgh-text-secondary, #64748b);cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);flex-shrink:0}.toolbar-menu-toggle i{font-size:1.25rem;transition:all .15s cubic-bezier(.4,0,.2,1)}.toolbar-menu-toggle:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08));color:var(--sgh-primary-color, #3b82f6);transform:translateY(-1px)}.toolbar-menu-toggle:hover i{transform:scale(1.1)}.toolbar-menu-toggle:active{transform:translateY(0) scale(.95)}.toolbar-menu-toggle:focus-visible{outline:2px solid var(--sgh-primary-color, #3b82f6);outline-offset:2px}.toolbar-search{flex:1;max-width:600px;margin:0 1rem}@media (max-width: 1024px){.toolbar-search{max-width:400px}}.search-form{width:100%}.search-input-wrapper{position:relative;display:flex;align-items:center;height:42px;background:var(--sgh-search-bg, #f8fafc);border:1.5px solid transparent;border-radius:12px;transition:all .15s cubic-bezier(.4,0,.2,1);overflow:hidden}.search-input-wrapper:hover{background:var(--sgh-surface-color, #ffffff);border-color:#3b82f633;box-shadow:0 0 0 3px #3b82f60d}.search-input-wrapper:focus-within{background:var(--sgh-surface-color, #ffffff);border-color:var(--sgh-primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.search-input-wrapper .search-icon{position:absolute;left:14px;color:var(--sgh-text-muted, #94a3b8);font-size:1rem;transition:all .15s cubic-bezier(.4,0,.2,1);pointer-events:none}.search-input-wrapper .search-input{flex:1;height:100%;padding:0 12px 0 42px;border:none;background:transparent;color:var(--sgh-text-primary, #1e293b);font-size:.9375rem;font-weight:400;outline:none}.search-input-wrapper .search-input::placeholder{color:var(--sgh-text-muted, #94a3b8);font-weight:400}.search-input-wrapper .search-input:focus::placeholder{opacity:.6}.search-input-wrapper .search-input:focus~.search-icon{color:var(--sgh-primary-color, #3b82f6)}.search-input-wrapper .search-submit{display:flex;align-items:center;justify-content:center;width:36px;height:36px;margin-right:3px;padding:0;border:none;border-radius:8px;background:transparent;color:var(--sgh-text-muted, #94a3b8);cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1)}.search-input-wrapper .search-submit i{font-size:.875rem;transition:all .15s cubic-bezier(.4,0,.2,1)}.search-input-wrapper .search-submit:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08));color:var(--sgh-primary-color, #3b82f6)}.search-input-wrapper .search-submit:hover i{transform:translate(2px)}.search-input-wrapper .search-submit:active{transform:scale(.95)}.toolbar-right-section{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.toolbar-action-btn{position:relative;display:flex;align-items:center;justify-content:center;width:42px;height:42px;padding:0;border:none;border-radius:12px;background:transparent;color:var(--sgh-text-secondary, #64748b);cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);flex-shrink:0}.toolbar-action-btn i{font-size:1.125rem;transition:all .15s cubic-bezier(.4,0,.2,1)}.toolbar-action-btn:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08));color:var(--sgh-primary-color, #3b82f6);transform:translateY(-1px);box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f}.toolbar-action-btn:hover i{transform:scale(1.1)}.toolbar-action-btn:active{transform:translateY(0) scale(.95);box-shadow:none}.toolbar-action-btn:focus-visible{outline:2px solid var(--sgh-primary-color, #3b82f6);outline-offset:2px}.toolbar-action-btn .notification-badge{position:absolute;top:6px;right:6px;display:flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;background:linear-gradient(135deg,#ef4444,#dc2626);border:2px solid var(--sgh-surface-color, #ffffff);border-radius:10px;color:#fff;font-size:.625rem;font-weight:700;line-height:1;box-shadow:0 2px 4px #00000026;animation:pulse 2s infinite}.toolbar-action-btn.notification-btn:hover .notification-badge{animation:none;transform:scale(1.1)}.toolbar-action-btn.profile-btn i{font-size:1.3rem}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.9;transform:scale(1.05)}}.toolbar-dropdown{position:absolute;top:72px;right:1.5rem;z-index:1001;min-width:320px;max-width:400px;animation:dropdownSlideIn .25s cubic-bezier(.4,0,.2,1)}@media (max-width: 768px){.toolbar-dropdown{top:64px;right:1rem;left:1rem;max-width:none}}.dropdown-card{background:var(--sgh-surface-color, #ffffff);border-radius:16px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;border:1px solid var(--sgh-border-color, #e2e8f0);overflow:hidden}@supports (backdrop-filter: blur(10px)){.dropdown-card{background:var(--sgh-surface-color, rgba(255, 255, 255, .95));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}}.dropdown-content{padding:1rem}@keyframes dropdownSlideIn{0%{opacity:0;transform:translateY(-10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}::ng-deep .sgh-settings-menu .mat-mdc-menu-panel,::ng-deep .sgh-app-config-menu .mat-mdc-menu-panel,::ng-deep .sgh-client-config-menu .mat-mdc-menu-panel{min-width:240px;border-radius:12px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;border:1px solid var(--sgh-border-color, #e2e8f0);overflow:hidden}::ng-deep .sgh-settings-menu .mat-mdc-menu-content,::ng-deep .sgh-app-config-menu .mat-mdc-menu-content,::ng-deep .sgh-client-config-menu .mat-mdc-menu-content{padding:.5rem}::ng-deep .sgh-settings-menu .mat-mdc-menu-item,::ng-deep .sgh-app-config-menu .mat-mdc-menu-item,::ng-deep .sgh-client-config-menu .mat-mdc-menu-item{border-radius:8px;margin-bottom:2px;min-height:42px;padding:0 12px;transition:all .15s cubic-bezier(.4,0,.2,1)}::ng-deep .sgh-settings-menu .mat-mdc-menu-item:hover,::ng-deep .sgh-app-config-menu .mat-mdc-menu-item:hover,::ng-deep .sgh-client-config-menu .mat-mdc-menu-item:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08))}::ng-deep .sgh-settings-menu .mat-mdc-menu-item.menu-item-with-icon,::ng-deep .sgh-app-config-menu .mat-mdc-menu-item.menu-item-with-icon,::ng-deep .sgh-client-config-menu .mat-mdc-menu-item.menu-item-with-icon{display:flex;align-items:center;gap:12px}::ng-deep .sgh-settings-menu .mat-mdc-menu-item.menu-item-with-icon .menu-icon,::ng-deep .sgh-app-config-menu .mat-mdc-menu-item.menu-item-with-icon .menu-icon,::ng-deep .sgh-client-config-menu .mat-mdc-menu-item.menu-item-with-icon .menu-icon{color:var(--sgh-text-secondary, #64748b);font-size:1rem;width:20px;text-align:center}.theme-menu-header{display:flex;align-items:center;gap:8px;padding:12px 16px 8px;color:var(--sgh-text-primary, #1e293b);font-weight:600;font-size:.9375rem;border-bottom:1px solid var(--sgh-border-color, #e2e8f0);margin-bottom:8px}.theme-menu-header i{color:var(--sgh-primary-color, #3b82f6);font-size:1rem}.theme-option-wrapper{padding:0 8px}.theme-radio-option{width:100%;border-radius:8px;padding:8px 12px!important}.theme-radio-option .radio-button{display:flex;align-items:center;gap:12px;width:100%}.theme-radio-option .radio-button input[type=radio]{appearance:none;width:18px;height:18px;border:2px solid var(--sgh-border-color, #e2e8f0);border-radius:50%;cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);position:relative;flex-shrink:0}.theme-radio-option .radio-button input[type=radio]:checked{border-color:var(--sgh-primary-color, #3b82f6)}.theme-radio-option .radio-button input[type=radio]:checked:before{content:\"\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:10px;height:10px;background:var(--sgh-primary-color, #3b82f6);border-radius:50%}.theme-radio-option .radio-button input[type=radio]:hover{border-color:var(--sgh-primary-color, #3b82f6)}.theme-radio-option .radio-button .radio-label{flex:1;color:var(--sgh-text-primary, #1e293b);font-size:.9375rem;-webkit-user-select:none;user-select:none}.client-menu-container{width:320px;max-width:calc(100vw - 2rem)}.client-menu-header{display:flex;align-items:center;gap:8px;padding:12px 16px;color:var(--sgh-text-primary, #1e293b);font-weight:600;font-size:.9375rem;border-bottom:1px solid var(--sgh-border-color, #e2e8f0);background:var(--sgh-surface-color, #f8fafc)}.client-menu-header i{color:var(--sgh-primary-color, #3b82f6);font-size:1rem}.client-search-wrapper{position:relative;padding:12px 16px;border-bottom:1px solid var(--sgh-border-color, #e2e8f0)}.client-search-wrapper .search-icon{position:absolute;left:28px;top:50%;transform:translateY(-50%);color:var(--sgh-text-muted, #94a3b8);font-size:.875rem;pointer-events:none}.client-search-wrapper .client-search-input{width:100%;height:36px;padding:0 12px 0 32px;border:1.5px solid var(--sgh-border-color, #e2e8f0);border-radius:8px;background:var(--sgh-surface-color, #ffffff);color:var(--sgh-text-primary, #1e293b);font-size:.875rem;outline:none;transition:all .15s cubic-bezier(.4,0,.2,1)}.client-search-wrapper .client-search-input::placeholder{color:var(--sgh-text-muted, #94a3b8)}.client-search-wrapper .client-search-input:focus{border-color:var(--sgh-primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.client-list-container{max-height:320px;overflow-y:auto;padding:8px}.client-list-container::-webkit-scrollbar{width:6px}.client-list-container::-webkit-scrollbar-track{background:transparent}.client-list-container::-webkit-scrollbar-thumb{background:#0000001a;border-radius:3px}.client-list-container::-webkit-scrollbar-thumb:hover{background:#0003}.client-list-item{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:8px;cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);position:relative}.client-list-item .check-icon{color:var(--sgh-primary-color, #3b82f6);font-size:1rem;flex-shrink:0}.client-list-item .client-name{flex:1;color:var(--sgh-text-primary, #1e293b);font-size:.9375rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.client-list-item:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08))}.client-list-item.selected{background:#3b82f61a}.client-list-item.selected .client-name{color:var(--sgh-primary-color, #3b82f6);font-weight:500}.no-results{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:2rem 1rem;color:var(--sgh-text-muted, #94a3b8);text-align:center}.no-results i{font-size:2rem;margin-bottom:.5rem;opacity:.5}.no-results span{font-size:.875rem}@media (max-width: 1024px){.toolbar-search{max-width:300px}}@media (max-width: 768px){.toolbar-search{display:none}.toolbar-left-section{gap:.5rem}.toolbar-logo .logo-image{height:36px;max-width:140px}.toolbar-menu-toggle,.toolbar-action-btn{width:40px;height:40px}.toolbar-menu-toggle i,.toolbar-action-btn i{font-size:1.125rem}.toolbar-action-btn .notification-badge{top:4px;right:4px}.toolbar-right-section{gap:.25rem}}@media (min-width: 1440px){.toolbar-main-wrapper{max-width:1400px}}@media (min-width: 1920px){.toolbar-main-wrapper{max-width:100%}.toolbar-logo .logo-image{height:48px;max-width:240px}.toolbar-search{max-width:700px}}@media (prefers-color-scheme: dark){.sgh-toolbar{--sgh-toolbar-bg: rgba(15, 23, 42, .95);--sgh-surface-color: #1e293b;--sgh-text-primary: #f1f5f9;--sgh-text-secondary: #94a3b8;--sgh-text-muted: #64748b;--sgh-border-color: #334155;--sgh-search-bg: #0f172a;--sgh-hover-bg: rgba(59, 130, 246, .15)}}@media print{.sgh-toolbar{display:none}}@media (prefers-reduced-motion: reduce){*{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@media (prefers-contrast: high){.toolbar-action-btn,.toolbar-menu-toggle{border:1px solid currentColor}}:focus-visible{outline:2px solid var(--sgh-primary-color, #3b82f6);outline-offset:2px}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i6.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i7.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "component", type: NotificationListComponent, selector: "sgh-notification-list" }, { kind: "pipe", type: SearchPipe, name: "search" }], animations: [
|
|
612
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ToolbarComponent, deps: [{ token: i1$1.MatDialog }, { token: SghNavbarService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
613
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ToolbarComponent, isStandalone: false, selector: "sgh-toolbar", inputs: { expanded: "expanded", toolbarData: "toolbarData" }, outputs: { toggleSidebarEvent: "toggleSidebarEvent", searchInputEvent: "searchInputEvent", client: "client", subClient: "subClient" }, host: { listeners: { "click": "clickInside()", "document:click": "clickOut()" } }, viewQueries: [{ propertyName: "clientMenuTrigger", first: true, predicate: ["clientMenuTrigger"], descendants: true }], ngImport: i0, template: "<nav class=\"toolbar-main-wrapper\" [style.background-color]=\"toolbarData.bgColor\" id=\"toolBarWrapper\">\r\n <div class=\"logo-wrapper\">\r\n <img class=\"logo\" [src]=\"toolbarData.img\"/>\r\n </div>\r\n <div>\r\n <button class=\"toggle-button\" (click)=\"toggleSidebar()\">\r\n <i class=\"fa fa-bars fa-fade\"></i>\r\n </button>\r\n </div>\r\n <div class=\"search\">\r\n <div class=\"form\" *ngIf=\"toolbarData.searchEnable\">\r\n <input type=\"text\" name=\"text\" autocomplete=\"off\" required/>\r\n <label class=\"label-name\">\r\n <span class=\"content-name\">\r\n Search\r\n </span>\r\n </label>\r\n <button class=\"search-wrapper\">\r\n <i class=\"fa fa-search\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"toolbarData.notificationEnable\" class=\"icon\" id=\"bell\" (click)=\"toggleNotificationList()\">\r\n <i class=\"fa fa-bell\"></i>\r\n </div>\r\n <div *ngIf=\"toolbarData.profileEnable\" class=\"icon\" id=\"bell3\" (click)=\"clickProfile()\">\r\n <i class=\"fa fa-user\"></i>\r\n </div>\r\n <div *ngIf=\"toolbarData.settingsEnable\" class=\"icon\" id=\"bell2\" [matMenuTriggerFor]=\"settingsMenu\">\r\n <i class=\"fa fa-gear\"></i>\r\n </div>\r\n</nav>\r\n\r\n<div *ngIf=\"toolbarData.profileView\" class=\"notifications\">\r\n <div class=\"notifications-list-wrapper profile-list-wrapper\">\r\n <div class=\"notifications-list\">\r\n <div class=\"notifications-list-item\">\r\n <div [innerHTML]=\"toolbarData.profileContent\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!--Settings related menus start-->\r\n<mat-menu #settingsMenu=\"matMenu\" xPosition=\"before\">\r\n <button mat-menu-item [matMenuTriggerFor]=\"appConfig\" *ngIf=\"toolbarData.applicationConfigurationEnable\">Application Settings</button>\r\n <button mat-menu-item [matMenuTriggerFor]=\"clientConfig\" *ngIf=\"toolbarData.clientConfigurationEnable\" #clientMenuTrigger>Client Settings</button>\r\n</mat-menu>\r\n<mat-menu #appConfig=\"matMenu\" xPosition=\"after\">\r\n <div *ngFor=\"let themeoption of toolbarData.themeOptions\">\r\n <button mat-menu-item class=\"radio\" (click)=\"onRadioClick(themeoption.value)\">\r\n <input value=\"{{themeoption.value}}\" name=\"radio\" type=\"radio\" checked [ngModel]=\"selected\"\r\n (ngModelChange)=\"setClass($event)\">\r\n <span>{{themeoption.name}}</span>\r\n </button>\r\n </div>\r\n</mat-menu>\r\n<mat-menu #clientConfig=\"matMenu\" xPosition=\"after\">\r\n <div style=\"width: 250px\" class=\"client-menu-wrapper\">\r\n <div class=\"container-fluid\">\r\n <div class=\"row\">\r\n <div class=\"col-sm-12\" (click)=\"$event.stopPropagation();\">\r\n <input type=\"text\" class=\"search-input\" placeholder=\"Search Client\" [(ngModel)]=\"searchText\"/>\r\n </div>\r\n <div class=\"col-sm-12\">\r\n <div class=\"mt-2 list-item-container\">\r\n <div class=\"list-item text-truncate\" *ngFor=\"let item of toolbarData.clientList | search : searchText;let i = index\"\r\n [ngClass]=\"{'client-selected': item.selected}\"\r\n (click)=\"toggleSelect($event, item);\" mat-ripple>{{item.text}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</mat-menu>\r\n\r\n<!--Settings related menus end-->\r\n\r\n<sgh-notification-list *ngIf=\"toolbarData.isNotifNavCollapsed\"></sgh-notification-list>\r\n", styles: [".toolbar-main-wrapper{position:relative;box-shadow:var(--sgh-shadow, 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06));z-index:1000;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid var(--sgh-border-color, rgba(255, 255, 255, .1))}nav{display:flex;align-items:center;background:var(--sgh-toolbar-bg, rgba(255, 255, 255, .95));height:64px;position:relative;padding:0 1.5rem;transition:all .3s cubic-bezier(.4,0,.2,1)}@supports (backdrop-filter: blur(10px)){nav{background:var(--sgh-toolbar-bg, rgba(255, 255, 255, .8));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}}.logo-wrapper{display:flex;align-items:center;flex-shrink:0;margin-right:2rem}.logo{height:32px;width:auto;object-fit:contain;transition:transform .2s ease}.logo:hover{transform:scale(1.05)}.icon{cursor:pointer;margin-left:.75rem;width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative;background:transparent;border:none}.icon i{color:var(--sgh-text-secondary, #64748b);font-size:1.125rem;transition:color .2s ease}.icon:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .1));transform:translateY(-1px);box-shadow:var(--sgh-shadow, 0 4px 12px rgba(0, 0, 0, .15))}.icon:hover i{color:var(--sgh-primary-color, #3b82f6)}.icon:active{transform:translateY(0);box-shadow:var(--sgh-shadow, 0 2px 4px rgba(0, 0, 0, .1))}.icon span{background:var(--sgh-error-color, #ef4444);padding:2px 6px;border-radius:10px;color:#fff;font-size:.75rem;font-weight:500;position:absolute;top:-2px;right:-2px;min-width:16px;height:16px;display:flex;align-items:center;justify-content:center;border:2px solid var(--sgh-surface-color, white)}.icon img{width:20px;height:20px;border-radius:50%}.search{flex:1;max-width:400px;margin:0 2rem}.notifications h2{font-size:14px;padding:10px;border-bottom:1px solid #eee;color:#999}.notifications h2 span{color:red}.notifications-item{display:flex;border-bottom:1px solid #eee;padding:6px 9px;margin-bottom:0;cursor:pointer}.notifications-item:hover{background-color:#eee}.notifications-item img{display:block;width:50px;height:50px;margin-right:9px;border-radius:50%;margin-top:2px}.notifications-item .text h4{color:#777;font-size:16px;margin-top:3px}.notifications-item .text p{color:#aaa;font-size:12px}.box{width:280px;height:auto;background-color:#fff;border-radius:0;display:flex;align-items:center;padding:0;border-bottom:2px solid #005860}.box>i{font-size:20px;color:#777}.box>input{flex:1;height:35px;border:none;outline:none;font-size:14px;padding-left:10px}.box>button{background:transparent;border:none;cursor:pointer}.toggle-button{background:transparent;border:none;cursor:pointer;width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);margin-right:1rem}.toggle-button i{color:var(--sgh-text-secondary, #64748b);font-size:1.125rem;transition:color .2s ease}.toggle-button:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .1));transform:translateY(-1px)}.toggle-button:hover i{color:var(--sgh-primary-color, #3b82f6)}.toggle-button:active{transform:translateY(0)}.search-wrapper{border-radius:20px;padding:13px;border:none;background:transparent;cursor:pointer}.search-wrapper i{color:#005860!important}.search-wrapper:hover{background:#0000000a!important}.logo{width:49%!important;padding:0 19px}.theme-list-wrapper,.profile-list-wrapper{width:300px!important}.notifications-list-wrapper{padding:10px;position:absolute;right:10px;top:45px;z-index:2;color:#000000de;width:450px}.notifications-list-wrapper .notifications-list{box-shadow:0 2px 10px #00000026;position:relative}.notifications-list-wrapper .notifications-list .notifications-title{background-color:#fff;text-align:center;padding:20px 10px;border-bottom:1px solid #f1f1f3}.notifications-list-wrapper .notifications-list .notifications-list-item{padding:10px;background-color:#fff;border-bottom:1px solid #f1f1f3;font-size:14px}.notifications-list-wrapper .notifications-list .notifications-list-item .item-title{margin:0;white-space:normal}.notifications-list-wrapper .notifications-list .notifications-list-item .item-description{margin:0;color:#000000de;opacity:.5;white-space:normal}.notifications-list-wrapper .notifications-list .see-all{background-color:#fff;color:#006068;font-weight:500}@media screen and (max-width: 599px){.notifications-list-wrapper{width:auto}}.notifications-list-wrapper{-webkit-animation:cardAnim 1s cubic-bezier(.33,1,.68,1) 0s 1 normal none;animation:cardAnim 1s cubic-bezier(.33,1,.68,1) 0s 1 normal none}@keyframes cardAnim{0%{opacity:0;transform:rotateX(-100deg);transform-origin:top}to{opacity:1;transform:rotateX(0);transform-origin:top}}select{padding:10px 20px;border-radius:5px;width:100%;margin:3% 10%;border:1px solid #005860}select:focus{outline:none}.form{width:100%;position:relative;height:40px;display:flex;align-items:center;background:var(--sgh-search-bg, rgba(248, 250, 252, .8));border:1px solid var(--sgh-border-color, #e2e8f0);border-radius:12px;transition:all .3s cubic-bezier(.4,0,.2,1);overflow:hidden}.form:hover{border-color:var(--sgh-primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.form:focus-within{border-color:var(--sgh-primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a;background:var(--sgh-surface-color, white)}.form input{width:100%;height:100%;color:var(--sgh-text-primary, #1e293b);padding:0 12px;border:none;background:transparent;font-size:.875rem;outline:none}.form input::placeholder{color:var(--sgh-text-muted, #94a3b8);transition:opacity .3s ease}.form input:focus::placeholder{opacity:.7}.form label{position:absolute;top:50%;left:12px;transform:translateY(-50%);pointer-events:none;transition:all .3s cubic-bezier(.4,0,.2,1);color:var(--sgh-text-muted, #94a3b8);font-size:.875rem;background:transparent;padding:0 4px}.content-name{transition:all .3s cubic-bezier(.4,0,.2,1)}.form input:focus+.label-name .content-name,.form input:valid+.label-name .content-name{transform:translateY(-120%);font-size:.75rem;color:var(--sgh-primary-color, #3b82f6);background:var(--sgh-surface-color, white);padding:0 4px}.search-wrapper{background:transparent;border:none;cursor:pointer;padding:8px 12px;display:flex;align-items:center;justify-content:center;transition:all .2s ease;border-radius:8px;margin-right:4px}.search-wrapper i{color:var(--sgh-text-muted, #94a3b8);font-size:1rem;transition:color .2s ease}.search-wrapper:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .1))}.search-wrapper:hover i{color:var(--sgh-primary-color, #3b82f6)}.radio{display:block;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:left}.radio+.radio{margin-top:12px}.radio input{display:none}.radio input+span{display:inline-block;position:relative;padding-left:30px}.radio input+span:before{content:\"\";display:block;position:absolute;top:0;left:0;border-radius:50%;margin-right:5px;width:16px;height:16px;border:1px solid #ccc;background:#fff}.radio input+span:after{content:\"\";display:block;width:11px;height:11px;background:#005860;position:absolute;border-radius:50%;top:3px;left:3px;opacity:0;transform:scale(0);transition:all .2s cubic-bezier(.64,.57,.67,1.53)}.radio input:checked+span:after{opacity:1;transform:scale(1)}.client-menu-wrapper .container-fluid{padding-right:15px;padding-left:15px;margin:10px}.client-menu-wrapper .container-fluid .row{display:flex;flex-wrap:wrap;margin-right:-15px;margin-left:-15px;flex-direction:column}.client-menu-wrapper .container-fluid .row .search-input{width:100%;box-sizing:border-box;display:block;padding:.375rem .75rem;font-size:12px;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.client-menu-wrapper .container-fluid .row .search-input:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem #007bff40}.client-menu-wrapper .container-fluid .row .list-item-container{border:.5px rgba(0,0,0,.12) solid;margin-top:5px;border-radius:5px;overflow:hidden}.client-menu-wrapper .container-fluid .row .list-item-container .mat-ripple{padding:8px;font-size:12px}.client-menu-wrapper .container-fluid .row .list-item-container .mat-ripple:hover{background:#76767642;cursor:pointer;transition:all .3s ease 0s}.client-menu-wrapper .container-fluid .row .list-item-container .client-selected{color:#fff;background-color:#005860}@media screen and (max-width: 600px){.search{display:none}.logo-wrapper{width:30%}.logo-wrapper .logo{width:78%!important;padding:9px}.sgh-sidebar{z-index:1!important;position:absolute!important;background:#fff!important}.icon{cursor:pointer;margin-right:0;margin-left:34px}.toggle-button{order:-1}.logo-wrapper,.icon{order:1}#toolBarWrapper{padding:0 15px;justify-content:space-between}}@media screen and (min-width: 1900px){.logo{width:29%!important;padding:0 35px}}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4$1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i6.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "component", type: NotificationListComponent, selector: "sgh-notification-list" }, { kind: "pipe", type: SearchPipe, name: "search" }], animations: [
|
|
755
614
|
fadeInOut
|
|
756
615
|
] }); }
|
|
757
616
|
}
|
|
@@ -759,8 +618,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
759
618
|
type: Component,
|
|
760
619
|
args: [{ selector: 'sgh-toolbar', animations: [
|
|
761
620
|
fadeInOut
|
|
762
|
-
], standalone: false, template: "<header class=\"sgh-toolbar\" [style.background-color]=\"toolbarData.bgColor\" id=\"toolBarWrapper\" role=\"banner\">\r\n <nav class=\"toolbar-main-wrapper\">\r\n <!-- Left Section -->\r\n <div class=\"toolbar-left-section\">\r\n <!-- Logo -->\r\n <div class=\"toolbar-logo\">\r\n <img class=\"logo-image\" [src]=\"getSafeImageUrl()\" alt=\"Application Logo\"/>\r\n </div>\r\n\r\n <!-- Menu Toggle -->\r\n <button class=\"toolbar-menu-toggle\"\r\n (click)=\"toggleSidebar()\"\r\n aria-label=\"Toggle navigation menu\"\r\n title=\"Toggle Menu\">\r\n <i class=\"fa fa-bars\"></i>\r\n </button>\r\n\r\n <!-- Search Bar -->\r\n <div class=\"toolbar-search\" *ngIf=\"toolbarData.searchEnable\">\r\n <form class=\"search-form\" (submit)=\"$event.preventDefault()\">\r\n <div class=\"search-input-wrapper\">\r\n <i class=\"fa fa-search search-icon\"></i>\r\n <input type=\"search\"\r\n class=\"search-input\"\r\n placeholder=\"Search...\"\r\n autocomplete=\"off\"\r\n aria-label=\"Search\"/>\r\n <button type=\"submit\" class=\"search-submit\" aria-label=\"Submit search\">\r\n <i class=\"fa fa-arrow-right\"></i>\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Section -->\r\n <div class=\"toolbar-right-section\">\r\n <!-- Notification Button -->\r\n <button *ngIf=\"toolbarData.notificationEnable\"\r\n class=\"toolbar-action-btn notification-btn\"\r\n (click)=\"toggleNotificationList()\"\r\n aria-label=\"View notifications\"\r\n title=\"Notifications\">\r\n <i class=\"fa fa-bell\"></i>\r\n <span class=\"notification-badge\" *ngIf=\"true\">3</span>\r\n </button>\r\n\r\n <!-- Settings Button -->\r\n <button *ngIf=\"toolbarData.settingsEnable\"\r\n class=\"toolbar-action-btn settings-btn\"\r\n [matMenuTriggerFor]=\"settingsMenu\"\r\n aria-label=\"Open settings\"\r\n title=\"Settings\">\r\n <i class=\"fa fa-cog\"></i>\r\n </button>\r\n\r\n <!-- User Profile Button -->\r\n <button *ngIf=\"toolbarData.profileEnable\"\r\n class=\"toolbar-action-btn profile-btn\"\r\n (click)=\"clickProfile()\"\r\n aria-label=\"View profile\"\r\n title=\"Profile\">\r\n <i class=\"fa fa-user-circle\"></i>\r\n </button>\r\n </div>\r\n </nav>\r\n</header>\r\n\r\n<!-- Profile Dropdown -->\r\n<div *ngIf=\"toolbarData.profileView\" class=\"toolbar-dropdown profile-dropdown\" @fadeInOut>\r\n <div class=\"dropdown-card\">\r\n <div class=\"dropdown-content\">\r\n <!-- Using sanitized content to prevent XSS attacks -->\r\n <div *ngIf=\"sanitizedProfileContent\" [innerHTML]=\"sanitizedProfileContent\"></div>\r\n <div *ngIf=\"!sanitizedProfileContent && toolbarData.profileContent\">\r\n <!-- Fallback: Display as plain text if sanitization fails -->\r\n <p>{{toolbarData.profileContent}}</p>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Settings Menu -->\r\n<mat-menu #settingsMenu=\"matMenu\" xPosition=\"before\" class=\"sgh-settings-menu\">\r\n <button mat-menu-item\r\n [matMenuTriggerFor]=\"appConfig\"\r\n *ngIf=\"toolbarData.applicationConfigurationEnable\"\r\n class=\"menu-item-with-icon\">\r\n <i class=\"fa fa-paint-brush menu-icon\"></i>\r\n <span>Application Settings</span>\r\n </button>\r\n <button mat-menu-item\r\n [matMenuTriggerFor]=\"clientConfig\"\r\n *ngIf=\"toolbarData.clientConfigurationEnable\"\r\n #clientMenuTrigger\r\n class=\"menu-item-with-icon\">\r\n <i class=\"fa fa-building menu-icon\"></i>\r\n <span>Client Settings</span>\r\n </button>\r\n</mat-menu>\r\n\r\n<!-- Application Configuration Menu -->\r\n<mat-menu #appConfig=\"matMenu\" xPosition=\"after\" class=\"sgh-app-config-menu\">\r\n <div class=\"theme-menu-header\">\r\n <i class=\"fa fa-palette\"></i>\r\n <span>Choose Theme</span>\r\n </div>\r\n <div *ngFor=\"let themeoption of toolbarData.themeOptions\" class=\"theme-option-wrapper\">\r\n <button mat-menu-item class=\"theme-radio-option\" (click)=\"onRadioClick(themeoption.value)\">\r\n <div class=\"radio-button\">\r\n <input value=\"{{themeoption.value}}\"\r\n name=\"radio\"\r\n type=\"radio\"\r\n [checked]=\"selected === themeoption.value\"\r\n [ngModel]=\"selected\"\r\n (ngModelChange)=\"setClass($event)\">\r\n <span class=\"radio-label\">{{themeoption.name}}</span>\r\n </div>\r\n </button>\r\n </div>\r\n</mat-menu>\r\n\r\n<!-- Client Configuration Menu -->\r\n<mat-menu #clientConfig=\"matMenu\" xPosition=\"after\" class=\"sgh-client-config-menu\">\r\n <div class=\"client-menu-container\">\r\n <div class=\"client-menu-header\">\r\n <i class=\"fa fa-building\"></i>\r\n <span>Select Client</span>\r\n </div>\r\n <div class=\"client-search-wrapper\" (click)=\"$event.stopPropagation();\">\r\n <i class=\"fa fa-search search-icon\"></i>\r\n <input type=\"text\"\r\n class=\"client-search-input\"\r\n placeholder=\"Search clients...\"\r\n [(ngModel)]=\"searchText\"\r\n autocomplete=\"off\"/>\r\n </div>\r\n <div class=\"client-list-container\">\r\n <div class=\"client-list-item\"\r\n *ngFor=\"let item of toolbarData.clientList | search : searchText; let i = index\"\r\n [class.selected]=\"item.selected\"\r\n (click)=\"toggleSelect($event, item);\"\r\n mat-ripple>\r\n <i class=\"fa fa-check-circle check-icon\" *ngIf=\"item.selected\"></i>\r\n <span class=\"client-name\">{{item.text}}</span>\r\n </div>\r\n <div class=\"no-results\" *ngIf=\"(toolbarData.clientList | search : searchText)?.length === 0\">\r\n <i class=\"fa fa-search\"></i>\r\n <span>No clients found</span>\r\n </div>\r\n </div>\r\n </div>\r\n</mat-menu>\r\n\r\n<sgh-notification-list *ngIf=\"toolbarData.isNotifNavCollapsed\"></sgh-notification-list>\r\n", styles: [".sgh-toolbar{position:sticky;top:0;z-index:1000;box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f;background:var(--sgh-toolbar-bg, rgba(255, 255, 255, .95));border-bottom:1px solid var(--sgh-border-color, #e2e8f0)}@supports (backdrop-filter: blur(10px)){.sgh-toolbar{background:var(--sgh-toolbar-bg, rgba(255, 255, 255, .85));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}}.toolbar-main-wrapper{display:flex;align-items:center;justify-content:space-between;height:64px;padding:0 1.5rem;max-width:100%;margin:0 auto;transition:all .3s cubic-bezier(.4,0,.2,1)}@media (max-width: 768px){.toolbar-main-wrapper{height:56px;padding:0 1rem}}.toolbar-left-section{display:flex;align-items:center;gap:5rem;flex:1;min-width:0}.toolbar-logo{display:flex;align-items:center;flex-shrink:0}.toolbar-logo .logo-image{height:42px;width:auto;max-width:200px;object-fit:contain;cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);filter:drop-shadow(0 1px 2px rgba(0,0,0,.05))}.toolbar-logo .logo-image:hover{transform:scale(1.02);filter:drop-shadow(0 2px 4px rgba(0,0,0,.1))}.toolbar-logo .logo-image:active{transform:scale(.98)}.toolbar-menu-toggle{display:flex;align-items:center;justify-content:center;width:42px;height:42px;padding:0;border:none;border-radius:12px;background:transparent;color:var(--sgh-text-secondary, #64748b);cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);flex-shrink:0}.toolbar-menu-toggle i{font-size:1.25rem;transition:all .15s cubic-bezier(.4,0,.2,1)}.toolbar-menu-toggle:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08));color:var(--sgh-primary-color, #3b82f6);transform:translateY(-1px)}.toolbar-menu-toggle:hover i{transform:scale(1.1)}.toolbar-menu-toggle:active{transform:translateY(0) scale(.95)}.toolbar-menu-toggle:focus-visible{outline:2px solid var(--sgh-primary-color, #3b82f6);outline-offset:2px}.toolbar-search{flex:1;max-width:600px;margin:0 1rem}@media (max-width: 1024px){.toolbar-search{max-width:400px}}.search-form{width:100%}.search-input-wrapper{position:relative;display:flex;align-items:center;height:42px;background:var(--sgh-search-bg, #f8fafc);border:1.5px solid transparent;border-radius:12px;transition:all .15s cubic-bezier(.4,0,.2,1);overflow:hidden}.search-input-wrapper:hover{background:var(--sgh-surface-color, #ffffff);border-color:#3b82f633;box-shadow:0 0 0 3px #3b82f60d}.search-input-wrapper:focus-within{background:var(--sgh-surface-color, #ffffff);border-color:var(--sgh-primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.search-input-wrapper .search-icon{position:absolute;left:14px;color:var(--sgh-text-muted, #94a3b8);font-size:1rem;transition:all .15s cubic-bezier(.4,0,.2,1);pointer-events:none}.search-input-wrapper .search-input{flex:1;height:100%;padding:0 12px 0 42px;border:none;background:transparent;color:var(--sgh-text-primary, #1e293b);font-size:.9375rem;font-weight:400;outline:none}.search-input-wrapper .search-input::placeholder{color:var(--sgh-text-muted, #94a3b8);font-weight:400}.search-input-wrapper .search-input:focus::placeholder{opacity:.6}.search-input-wrapper .search-input:focus~.search-icon{color:var(--sgh-primary-color, #3b82f6)}.search-input-wrapper .search-submit{display:flex;align-items:center;justify-content:center;width:36px;height:36px;margin-right:3px;padding:0;border:none;border-radius:8px;background:transparent;color:var(--sgh-text-muted, #94a3b8);cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1)}.search-input-wrapper .search-submit i{font-size:.875rem;transition:all .15s cubic-bezier(.4,0,.2,1)}.search-input-wrapper .search-submit:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08));color:var(--sgh-primary-color, #3b82f6)}.search-input-wrapper .search-submit:hover i{transform:translate(2px)}.search-input-wrapper .search-submit:active{transform:scale(.95)}.toolbar-right-section{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.toolbar-action-btn{position:relative;display:flex;align-items:center;justify-content:center;width:42px;height:42px;padding:0;border:none;border-radius:12px;background:transparent;color:var(--sgh-text-secondary, #64748b);cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);flex-shrink:0}.toolbar-action-btn i{font-size:1.125rem;transition:all .15s cubic-bezier(.4,0,.2,1)}.toolbar-action-btn:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08));color:var(--sgh-primary-color, #3b82f6);transform:translateY(-1px);box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f}.toolbar-action-btn:hover i{transform:scale(1.1)}.toolbar-action-btn:active{transform:translateY(0) scale(.95);box-shadow:none}.toolbar-action-btn:focus-visible{outline:2px solid var(--sgh-primary-color, #3b82f6);outline-offset:2px}.toolbar-action-btn .notification-badge{position:absolute;top:6px;right:6px;display:flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;background:linear-gradient(135deg,#ef4444,#dc2626);border:2px solid var(--sgh-surface-color, #ffffff);border-radius:10px;color:#fff;font-size:.625rem;font-weight:700;line-height:1;box-shadow:0 2px 4px #00000026;animation:pulse 2s infinite}.toolbar-action-btn.notification-btn:hover .notification-badge{animation:none;transform:scale(1.1)}.toolbar-action-btn.profile-btn i{font-size:1.3rem}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.9;transform:scale(1.05)}}.toolbar-dropdown{position:absolute;top:72px;right:1.5rem;z-index:1001;min-width:320px;max-width:400px;animation:dropdownSlideIn .25s cubic-bezier(.4,0,.2,1)}@media (max-width: 768px){.toolbar-dropdown{top:64px;right:1rem;left:1rem;max-width:none}}.dropdown-card{background:var(--sgh-surface-color, #ffffff);border-radius:16px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;border:1px solid var(--sgh-border-color, #e2e8f0);overflow:hidden}@supports (backdrop-filter: blur(10px)){.dropdown-card{background:var(--sgh-surface-color, rgba(255, 255, 255, .95));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}}.dropdown-content{padding:1rem}@keyframes dropdownSlideIn{0%{opacity:0;transform:translateY(-10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}::ng-deep .sgh-settings-menu .mat-mdc-menu-panel,::ng-deep .sgh-app-config-menu .mat-mdc-menu-panel,::ng-deep .sgh-client-config-menu .mat-mdc-menu-panel{min-width:240px;border-radius:12px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;border:1px solid var(--sgh-border-color, #e2e8f0);overflow:hidden}::ng-deep .sgh-settings-menu .mat-mdc-menu-content,::ng-deep .sgh-app-config-menu .mat-mdc-menu-content,::ng-deep .sgh-client-config-menu .mat-mdc-menu-content{padding:.5rem}::ng-deep .sgh-settings-menu .mat-mdc-menu-item,::ng-deep .sgh-app-config-menu .mat-mdc-menu-item,::ng-deep .sgh-client-config-menu .mat-mdc-menu-item{border-radius:8px;margin-bottom:2px;min-height:42px;padding:0 12px;transition:all .15s cubic-bezier(.4,0,.2,1)}::ng-deep .sgh-settings-menu .mat-mdc-menu-item:hover,::ng-deep .sgh-app-config-menu .mat-mdc-menu-item:hover,::ng-deep .sgh-client-config-menu .mat-mdc-menu-item:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08))}::ng-deep .sgh-settings-menu .mat-mdc-menu-item.menu-item-with-icon,::ng-deep .sgh-app-config-menu .mat-mdc-menu-item.menu-item-with-icon,::ng-deep .sgh-client-config-menu .mat-mdc-menu-item.menu-item-with-icon{display:flex;align-items:center;gap:12px}::ng-deep .sgh-settings-menu .mat-mdc-menu-item.menu-item-with-icon .menu-icon,::ng-deep .sgh-app-config-menu .mat-mdc-menu-item.menu-item-with-icon .menu-icon,::ng-deep .sgh-client-config-menu .mat-mdc-menu-item.menu-item-with-icon .menu-icon{color:var(--sgh-text-secondary, #64748b);font-size:1rem;width:20px;text-align:center}.theme-menu-header{display:flex;align-items:center;gap:8px;padding:12px 16px 8px;color:var(--sgh-text-primary, #1e293b);font-weight:600;font-size:.9375rem;border-bottom:1px solid var(--sgh-border-color, #e2e8f0);margin-bottom:8px}.theme-menu-header i{color:var(--sgh-primary-color, #3b82f6);font-size:1rem}.theme-option-wrapper{padding:0 8px}.theme-radio-option{width:100%;border-radius:8px;padding:8px 12px!important}.theme-radio-option .radio-button{display:flex;align-items:center;gap:12px;width:100%}.theme-radio-option .radio-button input[type=radio]{appearance:none;width:18px;height:18px;border:2px solid var(--sgh-border-color, #e2e8f0);border-radius:50%;cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);position:relative;flex-shrink:0}.theme-radio-option .radio-button input[type=radio]:checked{border-color:var(--sgh-primary-color, #3b82f6)}.theme-radio-option .radio-button input[type=radio]:checked:before{content:\"\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:10px;height:10px;background:var(--sgh-primary-color, #3b82f6);border-radius:50%}.theme-radio-option .radio-button input[type=radio]:hover{border-color:var(--sgh-primary-color, #3b82f6)}.theme-radio-option .radio-button .radio-label{flex:1;color:var(--sgh-text-primary, #1e293b);font-size:.9375rem;-webkit-user-select:none;user-select:none}.client-menu-container{width:320px;max-width:calc(100vw - 2rem)}.client-menu-header{display:flex;align-items:center;gap:8px;padding:12px 16px;color:var(--sgh-text-primary, #1e293b);font-weight:600;font-size:.9375rem;border-bottom:1px solid var(--sgh-border-color, #e2e8f0);background:var(--sgh-surface-color, #f8fafc)}.client-menu-header i{color:var(--sgh-primary-color, #3b82f6);font-size:1rem}.client-search-wrapper{position:relative;padding:12px 16px;border-bottom:1px solid var(--sgh-border-color, #e2e8f0)}.client-search-wrapper .search-icon{position:absolute;left:28px;top:50%;transform:translateY(-50%);color:var(--sgh-text-muted, #94a3b8);font-size:.875rem;pointer-events:none}.client-search-wrapper .client-search-input{width:100%;height:36px;padding:0 12px 0 32px;border:1.5px solid var(--sgh-border-color, #e2e8f0);border-radius:8px;background:var(--sgh-surface-color, #ffffff);color:var(--sgh-text-primary, #1e293b);font-size:.875rem;outline:none;transition:all .15s cubic-bezier(.4,0,.2,1)}.client-search-wrapper .client-search-input::placeholder{color:var(--sgh-text-muted, #94a3b8)}.client-search-wrapper .client-search-input:focus{border-color:var(--sgh-primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.client-list-container{max-height:320px;overflow-y:auto;padding:8px}.client-list-container::-webkit-scrollbar{width:6px}.client-list-container::-webkit-scrollbar-track{background:transparent}.client-list-container::-webkit-scrollbar-thumb{background:#0000001a;border-radius:3px}.client-list-container::-webkit-scrollbar-thumb:hover{background:#0003}.client-list-item{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:8px;cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1);position:relative}.client-list-item .check-icon{color:var(--sgh-primary-color, #3b82f6);font-size:1rem;flex-shrink:0}.client-list-item .client-name{flex:1;color:var(--sgh-text-primary, #1e293b);font-size:.9375rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.client-list-item:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .08))}.client-list-item.selected{background:#3b82f61a}.client-list-item.selected .client-name{color:var(--sgh-primary-color, #3b82f6);font-weight:500}.no-results{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:2rem 1rem;color:var(--sgh-text-muted, #94a3b8);text-align:center}.no-results i{font-size:2rem;margin-bottom:.5rem;opacity:.5}.no-results span{font-size:.875rem}@media (max-width: 1024px){.toolbar-search{max-width:300px}}@media (max-width: 768px){.toolbar-search{display:none}.toolbar-left-section{gap:.5rem}.toolbar-logo .logo-image{height:36px;max-width:140px}.toolbar-menu-toggle,.toolbar-action-btn{width:40px;height:40px}.toolbar-menu-toggle i,.toolbar-action-btn i{font-size:1.125rem}.toolbar-action-btn .notification-badge{top:4px;right:4px}.toolbar-right-section{gap:.25rem}}@media (min-width: 1440px){.toolbar-main-wrapper{max-width:1400px}}@media (min-width: 1920px){.toolbar-main-wrapper{max-width:100%}.toolbar-logo .logo-image{height:48px;max-width:240px}.toolbar-search{max-width:700px}}@media (prefers-color-scheme: dark){.sgh-toolbar{--sgh-toolbar-bg: rgba(15, 23, 42, .95);--sgh-surface-color: #1e293b;--sgh-text-primary: #f1f5f9;--sgh-text-secondary: #94a3b8;--sgh-text-muted: #64748b;--sgh-border-color: #334155;--sgh-search-bg: #0f172a;--sgh-hover-bg: rgba(59, 130, 246, .15)}}@media print{.sgh-toolbar{display:none}}@media (prefers-reduced-motion: reduce){*{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@media (prefers-contrast: high){.toolbar-action-btn,.toolbar-menu-toggle{border:1px solid currentColor}}:focus-visible{outline:2px solid var(--sgh-primary-color, #3b82f6);outline-offset:2px}\n"] }]
|
|
763
|
-
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: SghNavbarService }
|
|
621
|
+
], standalone: false, template: "<nav class=\"toolbar-main-wrapper\" [style.background-color]=\"toolbarData.bgColor\" id=\"toolBarWrapper\">\r\n <div class=\"logo-wrapper\">\r\n <img class=\"logo\" [src]=\"toolbarData.img\"/>\r\n </div>\r\n <div>\r\n <button class=\"toggle-button\" (click)=\"toggleSidebar()\">\r\n <i class=\"fa fa-bars fa-fade\"></i>\r\n </button>\r\n </div>\r\n <div class=\"search\">\r\n <div class=\"form\" *ngIf=\"toolbarData.searchEnable\">\r\n <input type=\"text\" name=\"text\" autocomplete=\"off\" required/>\r\n <label class=\"label-name\">\r\n <span class=\"content-name\">\r\n Search\r\n </span>\r\n </label>\r\n <button class=\"search-wrapper\">\r\n <i class=\"fa fa-search\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"toolbarData.notificationEnable\" class=\"icon\" id=\"bell\" (click)=\"toggleNotificationList()\">\r\n <i class=\"fa fa-bell\"></i>\r\n </div>\r\n <div *ngIf=\"toolbarData.profileEnable\" class=\"icon\" id=\"bell3\" (click)=\"clickProfile()\">\r\n <i class=\"fa fa-user\"></i>\r\n </div>\r\n <div *ngIf=\"toolbarData.settingsEnable\" class=\"icon\" id=\"bell2\" [matMenuTriggerFor]=\"settingsMenu\">\r\n <i class=\"fa fa-gear\"></i>\r\n </div>\r\n</nav>\r\n\r\n<div *ngIf=\"toolbarData.profileView\" class=\"notifications\">\r\n <div class=\"notifications-list-wrapper profile-list-wrapper\">\r\n <div class=\"notifications-list\">\r\n <div class=\"notifications-list-item\">\r\n <div [innerHTML]=\"toolbarData.profileContent\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!--Settings related menus start-->\r\n<mat-menu #settingsMenu=\"matMenu\" xPosition=\"before\">\r\n <button mat-menu-item [matMenuTriggerFor]=\"appConfig\" *ngIf=\"toolbarData.applicationConfigurationEnable\">Application Settings</button>\r\n <button mat-menu-item [matMenuTriggerFor]=\"clientConfig\" *ngIf=\"toolbarData.clientConfigurationEnable\" #clientMenuTrigger>Client Settings</button>\r\n</mat-menu>\r\n<mat-menu #appConfig=\"matMenu\" xPosition=\"after\">\r\n <div *ngFor=\"let themeoption of toolbarData.themeOptions\">\r\n <button mat-menu-item class=\"radio\" (click)=\"onRadioClick(themeoption.value)\">\r\n <input value=\"{{themeoption.value}}\" name=\"radio\" type=\"radio\" checked [ngModel]=\"selected\"\r\n (ngModelChange)=\"setClass($event)\">\r\n <span>{{themeoption.name}}</span>\r\n </button>\r\n </div>\r\n</mat-menu>\r\n<mat-menu #clientConfig=\"matMenu\" xPosition=\"after\">\r\n <div style=\"width: 250px\" class=\"client-menu-wrapper\">\r\n <div class=\"container-fluid\">\r\n <div class=\"row\">\r\n <div class=\"col-sm-12\" (click)=\"$event.stopPropagation();\">\r\n <input type=\"text\" class=\"search-input\" placeholder=\"Search Client\" [(ngModel)]=\"searchText\"/>\r\n </div>\r\n <div class=\"col-sm-12\">\r\n <div class=\"mt-2 list-item-container\">\r\n <div class=\"list-item text-truncate\" *ngFor=\"let item of toolbarData.clientList | search : searchText;let i = index\"\r\n [ngClass]=\"{'client-selected': item.selected}\"\r\n (click)=\"toggleSelect($event, item);\" mat-ripple>{{item.text}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</mat-menu>\r\n\r\n<!--Settings related menus end-->\r\n\r\n<sgh-notification-list *ngIf=\"toolbarData.isNotifNavCollapsed\"></sgh-notification-list>\r\n", styles: [".toolbar-main-wrapper{position:relative;box-shadow:var(--sgh-shadow, 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06));z-index:1000;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid var(--sgh-border-color, rgba(255, 255, 255, .1))}nav{display:flex;align-items:center;background:var(--sgh-toolbar-bg, rgba(255, 255, 255, .95));height:64px;position:relative;padding:0 1.5rem;transition:all .3s cubic-bezier(.4,0,.2,1)}@supports (backdrop-filter: blur(10px)){nav{background:var(--sgh-toolbar-bg, rgba(255, 255, 255, .8));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}}.logo-wrapper{display:flex;align-items:center;flex-shrink:0;margin-right:2rem}.logo{height:32px;width:auto;object-fit:contain;transition:transform .2s ease}.logo:hover{transform:scale(1.05)}.icon{cursor:pointer;margin-left:.75rem;width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative;background:transparent;border:none}.icon i{color:var(--sgh-text-secondary, #64748b);font-size:1.125rem;transition:color .2s ease}.icon:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .1));transform:translateY(-1px);box-shadow:var(--sgh-shadow, 0 4px 12px rgba(0, 0, 0, .15))}.icon:hover i{color:var(--sgh-primary-color, #3b82f6)}.icon:active{transform:translateY(0);box-shadow:var(--sgh-shadow, 0 2px 4px rgba(0, 0, 0, .1))}.icon span{background:var(--sgh-error-color, #ef4444);padding:2px 6px;border-radius:10px;color:#fff;font-size:.75rem;font-weight:500;position:absolute;top:-2px;right:-2px;min-width:16px;height:16px;display:flex;align-items:center;justify-content:center;border:2px solid var(--sgh-surface-color, white)}.icon img{width:20px;height:20px;border-radius:50%}.search{flex:1;max-width:400px;margin:0 2rem}.notifications h2{font-size:14px;padding:10px;border-bottom:1px solid #eee;color:#999}.notifications h2 span{color:red}.notifications-item{display:flex;border-bottom:1px solid #eee;padding:6px 9px;margin-bottom:0;cursor:pointer}.notifications-item:hover{background-color:#eee}.notifications-item img{display:block;width:50px;height:50px;margin-right:9px;border-radius:50%;margin-top:2px}.notifications-item .text h4{color:#777;font-size:16px;margin-top:3px}.notifications-item .text p{color:#aaa;font-size:12px}.box{width:280px;height:auto;background-color:#fff;border-radius:0;display:flex;align-items:center;padding:0;border-bottom:2px solid #005860}.box>i{font-size:20px;color:#777}.box>input{flex:1;height:35px;border:none;outline:none;font-size:14px;padding-left:10px}.box>button{background:transparent;border:none;cursor:pointer}.toggle-button{background:transparent;border:none;cursor:pointer;width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);margin-right:1rem}.toggle-button i{color:var(--sgh-text-secondary, #64748b);font-size:1.125rem;transition:color .2s ease}.toggle-button:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .1));transform:translateY(-1px)}.toggle-button:hover i{color:var(--sgh-primary-color, #3b82f6)}.toggle-button:active{transform:translateY(0)}.search-wrapper{border-radius:20px;padding:13px;border:none;background:transparent;cursor:pointer}.search-wrapper i{color:#005860!important}.search-wrapper:hover{background:#0000000a!important}.logo{width:49%!important;padding:0 19px}.theme-list-wrapper,.profile-list-wrapper{width:300px!important}.notifications-list-wrapper{padding:10px;position:absolute;right:10px;top:45px;z-index:2;color:#000000de;width:450px}.notifications-list-wrapper .notifications-list{box-shadow:0 2px 10px #00000026;position:relative}.notifications-list-wrapper .notifications-list .notifications-title{background-color:#fff;text-align:center;padding:20px 10px;border-bottom:1px solid #f1f1f3}.notifications-list-wrapper .notifications-list .notifications-list-item{padding:10px;background-color:#fff;border-bottom:1px solid #f1f1f3;font-size:14px}.notifications-list-wrapper .notifications-list .notifications-list-item .item-title{margin:0;white-space:normal}.notifications-list-wrapper .notifications-list .notifications-list-item .item-description{margin:0;color:#000000de;opacity:.5;white-space:normal}.notifications-list-wrapper .notifications-list .see-all{background-color:#fff;color:#006068;font-weight:500}@media screen and (max-width: 599px){.notifications-list-wrapper{width:auto}}.notifications-list-wrapper{-webkit-animation:cardAnim 1s cubic-bezier(.33,1,.68,1) 0s 1 normal none;animation:cardAnim 1s cubic-bezier(.33,1,.68,1) 0s 1 normal none}@keyframes cardAnim{0%{opacity:0;transform:rotateX(-100deg);transform-origin:top}to{opacity:1;transform:rotateX(0);transform-origin:top}}select{padding:10px 20px;border-radius:5px;width:100%;margin:3% 10%;border:1px solid #005860}select:focus{outline:none}.form{width:100%;position:relative;height:40px;display:flex;align-items:center;background:var(--sgh-search-bg, rgba(248, 250, 252, .8));border:1px solid var(--sgh-border-color, #e2e8f0);border-radius:12px;transition:all .3s cubic-bezier(.4,0,.2,1);overflow:hidden}.form:hover{border-color:var(--sgh-primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.form:focus-within{border-color:var(--sgh-primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a;background:var(--sgh-surface-color, white)}.form input{width:100%;height:100%;color:var(--sgh-text-primary, #1e293b);padding:0 12px;border:none;background:transparent;font-size:.875rem;outline:none}.form input::placeholder{color:var(--sgh-text-muted, #94a3b8);transition:opacity .3s ease}.form input:focus::placeholder{opacity:.7}.form label{position:absolute;top:50%;left:12px;transform:translateY(-50%);pointer-events:none;transition:all .3s cubic-bezier(.4,0,.2,1);color:var(--sgh-text-muted, #94a3b8);font-size:.875rem;background:transparent;padding:0 4px}.content-name{transition:all .3s cubic-bezier(.4,0,.2,1)}.form input:focus+.label-name .content-name,.form input:valid+.label-name .content-name{transform:translateY(-120%);font-size:.75rem;color:var(--sgh-primary-color, #3b82f6);background:var(--sgh-surface-color, white);padding:0 4px}.search-wrapper{background:transparent;border:none;cursor:pointer;padding:8px 12px;display:flex;align-items:center;justify-content:center;transition:all .2s ease;border-radius:8px;margin-right:4px}.search-wrapper i{color:var(--sgh-text-muted, #94a3b8);font-size:1rem;transition:color .2s ease}.search-wrapper:hover{background:var(--sgh-hover-bg, rgba(59, 130, 246, .1))}.search-wrapper:hover i{color:var(--sgh-primary-color, #3b82f6)}.radio{display:block;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:left}.radio+.radio{margin-top:12px}.radio input{display:none}.radio input+span{display:inline-block;position:relative;padding-left:30px}.radio input+span:before{content:\"\";display:block;position:absolute;top:0;left:0;border-radius:50%;margin-right:5px;width:16px;height:16px;border:1px solid #ccc;background:#fff}.radio input+span:after{content:\"\";display:block;width:11px;height:11px;background:#005860;position:absolute;border-radius:50%;top:3px;left:3px;opacity:0;transform:scale(0);transition:all .2s cubic-bezier(.64,.57,.67,1.53)}.radio input:checked+span:after{opacity:1;transform:scale(1)}.client-menu-wrapper .container-fluid{padding-right:15px;padding-left:15px;margin:10px}.client-menu-wrapper .container-fluid .row{display:flex;flex-wrap:wrap;margin-right:-15px;margin-left:-15px;flex-direction:column}.client-menu-wrapper .container-fluid .row .search-input{width:100%;box-sizing:border-box;display:block;padding:.375rem .75rem;font-size:12px;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.client-menu-wrapper .container-fluid .row .search-input:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem #007bff40}.client-menu-wrapper .container-fluid .row .list-item-container{border:.5px rgba(0,0,0,.12) solid;margin-top:5px;border-radius:5px;overflow:hidden}.client-menu-wrapper .container-fluid .row .list-item-container .mat-ripple{padding:8px;font-size:12px}.client-menu-wrapper .container-fluid .row .list-item-container .mat-ripple:hover{background:#76767642;cursor:pointer;transition:all .3s ease 0s}.client-menu-wrapper .container-fluid .row .list-item-container .client-selected{color:#fff;background-color:#005860}@media screen and (max-width: 600px){.search{display:none}.logo-wrapper{width:30%}.logo-wrapper .logo{width:78%!important;padding:9px}.sgh-sidebar{z-index:1!important;position:absolute!important;background:#fff!important}.icon{cursor:pointer;margin-right:0;margin-left:34px}.toggle-button{order:-1}.logo-wrapper,.icon{order:1}#toolBarWrapper{padding:0 15px;justify-content:space-between}}@media screen and (min-width: 1900px){.logo{width:29%!important;padding:0 35px}}\n"] }]
|
|
622
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: SghNavbarService }], propDecorators: { expanded: [{
|
|
764
623
|
type: Input
|
|
765
624
|
}], toggleSidebarEvent: [{
|
|
766
625
|
type: Output
|
|
@@ -941,22 +800,10 @@ class SublevelMenuComponent {
|
|
|
941
800
|
}
|
|
942
801
|
item.expanded = !item.expanded;
|
|
943
802
|
}
|
|
944
|
-
/**
|
|
945
|
-
* Determines if a menu item should have the active class.
|
|
946
|
-
* Uses proper URL path matching instead of simple string includes
|
|
947
|
-
* to prevent false positives (e.g., "/dashboard" matching "/admin-dashboard").
|
|
948
|
-
*/
|
|
949
803
|
getActiveClass(item) {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
// Use proper URL path matching
|
|
954
|
-
const currentUrl = this.router.url.split('?')[0]; // Remove query params
|
|
955
|
-
const routeLink = item.routeLink.startsWith('/') ? item.routeLink : '/' + item.routeLink;
|
|
956
|
-
// Check if current URL matches exactly or is a child route
|
|
957
|
-
const isExactMatch = currentUrl === routeLink;
|
|
958
|
-
const isChildRoute = currentUrl.startsWith(routeLink + '/');
|
|
959
|
-
return (isExactMatch || isChildRoute) ? 'active-sublevel' : '';
|
|
804
|
+
return item.expanded && this.router.url.includes(item.routeLink)
|
|
805
|
+
? 'active-sublevel'
|
|
806
|
+
: '';
|
|
960
807
|
}
|
|
961
808
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SublevelMenuComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
962
809
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SublevelMenuComponent, isStandalone: false, selector: "sgh-sublevel-menu", inputs: { data: "data", collapsed: "collapsed", animating: "animating", expanded: "expanded", multiple: "multiple" }, ngImport: i0, template: `
|