@memberjunction/ng-explorer-settings 6.1.4 → 6.2.0-edge.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/account-info/account-info.component.d.ts +1 -1
- package/dist/lib/account-info/account-info.component.js +2 -2
- package/dist/lib/account-info/account-info.component.js.map +1 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts +93 -10
- package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.js +232 -80
- package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
- package/dist/lib/application-management/application-management.component.d.ts +94 -11
- package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-management.component.js +231 -67
- package/dist/lib/application-management/application-management.component.js.map +1 -1
- package/dist/lib/application-settings/application-settings.component.d.ts +4 -4
- package/dist/lib/application-settings/application-settings.component.js +10 -10
- package/dist/lib/application-settings/application-settings.component.js.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts +88 -10
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.js +219 -63
- package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts +44 -6
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +117 -43
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
- package/dist/lib/notification-preferences/notification-preferences.component.d.ts +25 -3
- package/dist/lib/notification-preferences/notification-preferences.component.d.ts.map +1 -1
- package/dist/lib/notification-preferences/notification-preferences.component.js +62 -18
- package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -1
- package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts +32 -4
- package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-dialog/role-dialog.component.js +84 -30
- package/dist/lib/role-management/role-dialog/role-dialog.component.js.map +1 -1
- package/dist/lib/role-management/role-management-agent-context.d.ts +12 -4
- package/dist/lib/role-management/role-management-agent-context.d.ts.map +1 -1
- package/dist/lib/role-management/role-management-agent-context.js +26 -10
- package/dist/lib/role-management/role-management-agent-context.js.map +1 -1
- package/dist/lib/role-management/role-management.component.d.ts +95 -11
- package/dist/lib/role-management/role-management.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-management.component.js +259 -91
- package/dist/lib/role-management/role-management.component.js.map +1 -1
- package/dist/lib/settings/settings.component.d.ts +87 -11
- package/dist/lib/settings/settings.component.d.ts.map +1 -1
- package/dist/lib/settings/settings.component.js +211 -65
- package/dist/lib/settings/settings.component.js.map +1 -1
- package/dist/lib/shared/settings-card.component.d.ts +24 -4
- package/dist/lib/shared/settings-card.component.d.ts.map +1 -1
- package/dist/lib/shared/settings-card.component.js +46 -6
- package/dist/lib/shared/settings-card.component.js.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.d.ts +172 -18
- package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.js +320 -108
- package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
- package/dist/lib/user-app-config/user-app-config-content.component.js +3 -3
- package/dist/lib/user-app-config/user-app-config-content.component.js.map +1 -1
- package/dist/lib/user-app-config/user-app-config-reorder.d.ts +4 -0
- package/dist/lib/user-app-config/user-app-config-reorder.d.ts.map +1 -1
- package/dist/lib/user-app-config/user-app-config-reorder.js +11 -3
- package/dist/lib/user-app-config/user-app-config-reorder.js.map +1 -1
- package/dist/lib/user-management/transaction-group-refusals.d.ts +45 -0
- package/dist/lib/user-management/transaction-group-refusals.d.ts.map +1 -0
- package/dist/lib/user-management/transaction-group-refusals.js +49 -0
- package/dist/lib/user-management/transaction-group-refusals.js.map +1 -0
- package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts +44 -6
- package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-dialog/user-dialog.component.js +134 -45
- package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
- package/dist/lib/user-management/user-management-agent-context.d.ts +10 -0
- package/dist/lib/user-management/user-management-agent-context.d.ts.map +1 -1
- package/dist/lib/user-management/user-management-agent-context.js +26 -6
- package/dist/lib/user-management/user-management-agent-context.js.map +1 -1
- package/dist/lib/user-management/user-management.component.d.ts +174 -16
- package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-management.component.js +501 -177
- package/dist/lib/user-management/user-management.component.js.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts +97 -15
- package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.js +280 -116
- package/dist/lib/user-profile-settings/user-profile-settings.component.js.map +1 -1
- package/package.json +20 -20
|
@@ -265,19 +265,75 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
|
|
|
265
265
|
location;
|
|
266
266
|
cdr;
|
|
267
267
|
ngZone;
|
|
268
|
-
|
|
268
|
+
StateChange = new EventEmitter();
|
|
269
|
+
/**
|
|
270
|
+
* @deprecated Use {@link StateChange}.
|
|
271
|
+
*
|
|
272
|
+
* The same emitter under the old binding name, so a template still binding
|
|
273
|
+
* (stateChange) keeps working. Must stay AFTER StateChange: class fields
|
|
274
|
+
* initialise in order, and the other way round this captures undefined.
|
|
275
|
+
*/
|
|
276
|
+
stateChange = this.StateChange;
|
|
269
277
|
// State management
|
|
270
|
-
|
|
271
|
-
|
|
278
|
+
ActiveTab = 'general';
|
|
279
|
+
/** @deprecated Use {@link ActiveTab}. */
|
|
280
|
+
get activeTab() {
|
|
281
|
+
return this.ActiveTab;
|
|
282
|
+
}
|
|
283
|
+
/** @deprecated Use {@link ActiveTab}. */
|
|
284
|
+
set activeTab(value) {
|
|
285
|
+
this.ActiveTab = value;
|
|
286
|
+
}
|
|
287
|
+
SearchTerm$ = new BehaviorSubject('');
|
|
288
|
+
/** @deprecated Use {@link SearchTerm$}. */
|
|
289
|
+
get searchTerm$() {
|
|
290
|
+
return this.SearchTerm$;
|
|
291
|
+
}
|
|
292
|
+
/** @deprecated Use {@link SearchTerm$}. */
|
|
293
|
+
set searchTerm$(value) {
|
|
294
|
+
this.SearchTerm$ = value;
|
|
295
|
+
}
|
|
272
296
|
isLoading = false;
|
|
273
297
|
error = null;
|
|
274
298
|
// Search state
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
299
|
+
FilteredTabs = [];
|
|
300
|
+
/** @deprecated Use {@link FilteredTabs}. */
|
|
301
|
+
get filteredTabs() {
|
|
302
|
+
return this.FilteredTabs;
|
|
303
|
+
}
|
|
304
|
+
/** @deprecated Use {@link FilteredTabs}. */
|
|
305
|
+
set filteredTabs(value) {
|
|
306
|
+
this.FilteredTabs = value;
|
|
307
|
+
}
|
|
308
|
+
SearchResults = [];
|
|
309
|
+
/** @deprecated Use {@link SearchResults}. */
|
|
310
|
+
get searchResults() {
|
|
311
|
+
return this.SearchResults;
|
|
312
|
+
}
|
|
313
|
+
/** @deprecated Use {@link SearchResults}. */
|
|
314
|
+
set searchResults(value) {
|
|
315
|
+
this.SearchResults = value;
|
|
316
|
+
}
|
|
317
|
+
IsSearching = false;
|
|
318
|
+
/** @deprecated Use {@link IsSearching}. */
|
|
319
|
+
get isSearching() {
|
|
320
|
+
return this.IsSearching;
|
|
321
|
+
}
|
|
322
|
+
/** @deprecated Use {@link IsSearching}. */
|
|
323
|
+
set isSearching(value) {
|
|
324
|
+
this.IsSearching = value;
|
|
325
|
+
}
|
|
326
|
+
ShowSearchResults = false;
|
|
327
|
+
/** @deprecated Use {@link ShowSearchResults}. */
|
|
328
|
+
get showSearchResults() {
|
|
329
|
+
return this.ShowSearchResults;
|
|
330
|
+
}
|
|
331
|
+
/** @deprecated Use {@link ShowSearchResults}. */
|
|
332
|
+
set showSearchResults(value) {
|
|
333
|
+
this.ShowSearchResults = value;
|
|
334
|
+
}
|
|
279
335
|
// Tab configuration - User-focused tabs only
|
|
280
|
-
|
|
336
|
+
Tabs = [
|
|
281
337
|
{
|
|
282
338
|
id: 'general',
|
|
283
339
|
label: 'General',
|
|
@@ -304,6 +360,14 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
|
|
|
304
360
|
disabled: true
|
|
305
361
|
}
|
|
306
362
|
];
|
|
363
|
+
/** @deprecated Use {@link Tabs}. */
|
|
364
|
+
get tabs() {
|
|
365
|
+
return this.Tabs;
|
|
366
|
+
}
|
|
367
|
+
/** @deprecated Use {@link Tabs}. */
|
|
368
|
+
set tabs(value) {
|
|
369
|
+
this.Tabs = value;
|
|
370
|
+
}
|
|
307
371
|
// Searchable content registry - User settings only
|
|
308
372
|
searchableItems = [
|
|
309
373
|
// General tab
|
|
@@ -352,10 +416,34 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
|
|
|
352
416
|
}
|
|
353
417
|
];
|
|
354
418
|
// Section expansion state
|
|
355
|
-
|
|
419
|
+
ExpandedSections = ['profile', 'account'];
|
|
420
|
+
/** @deprecated Use {@link ExpandedSections}. */
|
|
421
|
+
get expandedSections() {
|
|
422
|
+
return this.ExpandedSections;
|
|
423
|
+
}
|
|
424
|
+
/** @deprecated Use {@link ExpandedSections}. */
|
|
425
|
+
set expandedSections(value) {
|
|
426
|
+
this.ExpandedSections = value;
|
|
427
|
+
}
|
|
356
428
|
// Mobile state
|
|
357
|
-
|
|
358
|
-
|
|
429
|
+
IsMobile = window.innerWidth < 768;
|
|
430
|
+
/** @deprecated Use {@link IsMobile}. */
|
|
431
|
+
get isMobile() {
|
|
432
|
+
return this.IsMobile;
|
|
433
|
+
}
|
|
434
|
+
/** @deprecated Use {@link IsMobile}. */
|
|
435
|
+
set isMobile(value) {
|
|
436
|
+
this.IsMobile = value;
|
|
437
|
+
}
|
|
438
|
+
IsMobileNavOpen = false;
|
|
439
|
+
/** @deprecated Use {@link IsMobileNavOpen}. */
|
|
440
|
+
get isMobileNavOpen() {
|
|
441
|
+
return this.IsMobileNavOpen;
|
|
442
|
+
}
|
|
443
|
+
/** @deprecated Use {@link IsMobileNavOpen}. */
|
|
444
|
+
set isMobileNavOpen(value) {
|
|
445
|
+
this.IsMobileNavOpen = value;
|
|
446
|
+
}
|
|
359
447
|
destroy$ = new Subject();
|
|
360
448
|
constructor(location, cdr, ngZone) {
|
|
361
449
|
super();
|
|
@@ -365,9 +453,9 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
|
|
|
365
453
|
window.addEventListener('resize', this.handleResize.bind(this));
|
|
366
454
|
}
|
|
367
455
|
ngOnInit() {
|
|
368
|
-
this.
|
|
456
|
+
this.FilteredTabs = [...this.Tabs];
|
|
369
457
|
this.setupSearchFilter();
|
|
370
|
-
this.
|
|
458
|
+
this.LoadInitialData();
|
|
371
459
|
}
|
|
372
460
|
ngOnDestroy() {
|
|
373
461
|
this.destroy$.next();
|
|
@@ -375,14 +463,14 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
|
|
|
375
463
|
window.removeEventListener('resize', this.handleResize.bind(this));
|
|
376
464
|
}
|
|
377
465
|
setupSearchFilter() {
|
|
378
|
-
this.
|
|
466
|
+
this.SearchTerm$
|
|
379
467
|
.pipe(debounceTime(200), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
380
468
|
.subscribe(term => {
|
|
381
469
|
this.filterContent(term);
|
|
382
470
|
this.emitStateChange();
|
|
383
471
|
});
|
|
384
472
|
}
|
|
385
|
-
async
|
|
473
|
+
async LoadInitialData() {
|
|
386
474
|
try {
|
|
387
475
|
this.isLoading = true;
|
|
388
476
|
await this.simulateDataLoad();
|
|
@@ -399,140 +487,188 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
|
|
|
399
487
|
});
|
|
400
488
|
}
|
|
401
489
|
}
|
|
490
|
+
/** @deprecated Use {@link LoadInitialData}. */
|
|
491
|
+
async loadInitialData() {
|
|
492
|
+
return this.LoadInitialData();
|
|
493
|
+
}
|
|
402
494
|
async simulateDataLoad() {
|
|
403
495
|
return new Promise(resolve => setTimeout(resolve, 300));
|
|
404
496
|
}
|
|
405
|
-
|
|
406
|
-
const tab = this.
|
|
497
|
+
OnTabChange(tabId) {
|
|
498
|
+
const tab = this.Tabs.find(t => t.id === tabId);
|
|
407
499
|
if (tab?.disabled) {
|
|
408
500
|
return; // Don't switch to disabled tabs
|
|
409
501
|
}
|
|
410
|
-
this.
|
|
502
|
+
this.ActiveTab = tabId;
|
|
411
503
|
this.emitStateChange();
|
|
412
504
|
}
|
|
413
|
-
|
|
505
|
+
/** @deprecated Use {@link OnTabChange}. */
|
|
506
|
+
onTabChange(tabId) {
|
|
507
|
+
return this.OnTabChange(tabId);
|
|
508
|
+
}
|
|
509
|
+
OnSearchChange(event) {
|
|
414
510
|
const term = event.target.value;
|
|
415
|
-
this.
|
|
511
|
+
this.SearchTerm$.next(term);
|
|
512
|
+
}
|
|
513
|
+
/** @deprecated Use {@link OnSearchChange}. */
|
|
514
|
+
onSearchChange(event) {
|
|
515
|
+
return this.OnSearchChange(event);
|
|
416
516
|
}
|
|
417
517
|
toggleSection(sectionId) {
|
|
418
|
-
const index = this.
|
|
518
|
+
const index = this.ExpandedSections.indexOf(sectionId);
|
|
419
519
|
if (index === -1) {
|
|
420
|
-
this.
|
|
520
|
+
this.ExpandedSections.push(sectionId);
|
|
421
521
|
}
|
|
422
522
|
else {
|
|
423
|
-
this.
|
|
523
|
+
this.ExpandedSections.splice(index, 1);
|
|
424
524
|
}
|
|
425
525
|
this.emitStateChange();
|
|
426
526
|
}
|
|
527
|
+
IsSectionExpanded(sectionId) {
|
|
528
|
+
return this.ExpandedSections.includes(sectionId);
|
|
529
|
+
}
|
|
530
|
+
/** @deprecated Use {@link IsSectionExpanded}. */
|
|
427
531
|
isSectionExpanded(sectionId) {
|
|
428
|
-
return this.
|
|
532
|
+
return this.IsSectionExpanded(sectionId);
|
|
429
533
|
}
|
|
430
534
|
/**
|
|
431
535
|
* Filters searchable content based on search term
|
|
432
536
|
*/
|
|
433
537
|
filterContent(term) {
|
|
434
538
|
if (!term || term.trim() === '') {
|
|
435
|
-
this.
|
|
436
|
-
this.
|
|
437
|
-
this.
|
|
539
|
+
this.ShowSearchResults = false;
|
|
540
|
+
this.SearchResults = [];
|
|
541
|
+
this.FilteredTabs = [...this.Tabs];
|
|
438
542
|
return;
|
|
439
543
|
}
|
|
440
544
|
const searchLower = term.toLowerCase().trim();
|
|
441
|
-
this.
|
|
545
|
+
this.IsSearching = true;
|
|
442
546
|
// Filter searchable items
|
|
443
|
-
this.
|
|
547
|
+
this.SearchResults = this.searchableItems.filter(item => {
|
|
444
548
|
const matchesLabel = item.label.toLowerCase().includes(searchLower);
|
|
445
549
|
const matchesKeywords = item.keywords.some(kw => kw.toLowerCase().includes(searchLower));
|
|
446
550
|
const matchesDescription = item.description?.toLowerCase().includes(searchLower) || false;
|
|
447
551
|
return matchesLabel || matchesKeywords || matchesDescription;
|
|
448
552
|
});
|
|
449
553
|
// Get unique tabs that have matching results
|
|
450
|
-
const matchingTabIds = new Set(this.
|
|
451
|
-
this.
|
|
452
|
-
this.
|
|
453
|
-
this.
|
|
554
|
+
const matchingTabIds = new Set(this.SearchResults.map(r => r.tabId));
|
|
555
|
+
this.FilteredTabs = this.Tabs.filter(tab => matchingTabIds.has(tab.id));
|
|
556
|
+
this.ShowSearchResults = true;
|
|
557
|
+
this.IsSearching = false;
|
|
454
558
|
}
|
|
455
559
|
/**
|
|
456
560
|
* Navigates to a search result
|
|
457
561
|
*/
|
|
458
|
-
|
|
459
|
-
const tab = this.
|
|
562
|
+
NavigateToSearchResult(result) {
|
|
563
|
+
const tab = this.Tabs.find(t => t.id === result.tabId);
|
|
460
564
|
if (tab?.disabled) {
|
|
461
565
|
return; // Don't navigate to disabled tabs
|
|
462
566
|
}
|
|
463
|
-
this.
|
|
567
|
+
this.ActiveTab = result.tabId;
|
|
464
568
|
// Expand the section if applicable
|
|
465
|
-
if (result.sectionId && !this.
|
|
466
|
-
this.
|
|
569
|
+
if (result.sectionId && !this.ExpandedSections.includes(result.sectionId)) {
|
|
570
|
+
this.ExpandedSections.push(result.sectionId);
|
|
467
571
|
}
|
|
468
|
-
this.
|
|
572
|
+
this.ClearSearch();
|
|
469
573
|
this.emitStateChange();
|
|
470
574
|
}
|
|
575
|
+
/** @deprecated Use {@link NavigateToSearchResult}. */
|
|
576
|
+
navigateToSearchResult(result) {
|
|
577
|
+
return this.NavigateToSearchResult(result);
|
|
578
|
+
}
|
|
471
579
|
/**
|
|
472
580
|
* Clears the search and resets the view
|
|
473
581
|
*/
|
|
582
|
+
ClearSearch() {
|
|
583
|
+
this.SearchTerm$.next('');
|
|
584
|
+
this.ShowSearchResults = false;
|
|
585
|
+
this.SearchResults = [];
|
|
586
|
+
this.FilteredTabs = [...this.Tabs];
|
|
587
|
+
}
|
|
588
|
+
/** @deprecated Use {@link ClearSearch}. */
|
|
474
589
|
clearSearch() {
|
|
475
|
-
this.
|
|
476
|
-
this.showSearchResults = false;
|
|
477
|
-
this.searchResults = [];
|
|
478
|
-
this.filteredTabs = [...this.tabs];
|
|
590
|
+
return this.ClearSearch();
|
|
479
591
|
}
|
|
480
592
|
/**
|
|
481
593
|
* Toggles the mobile navigation rail
|
|
482
594
|
*/
|
|
595
|
+
ToggleMobileNav() {
|
|
596
|
+
this.IsMobileNavOpen = !this.IsMobileNavOpen;
|
|
597
|
+
}
|
|
598
|
+
/** @deprecated Use {@link ToggleMobileNav}. */
|
|
483
599
|
toggleMobileNav() {
|
|
484
|
-
|
|
600
|
+
return this.ToggleMobileNav();
|
|
485
601
|
}
|
|
486
602
|
/**
|
|
487
603
|
* Closes the mobile navigation rail
|
|
488
604
|
*/
|
|
605
|
+
CloseMobileNav() {
|
|
606
|
+
this.IsMobileNavOpen = false;
|
|
607
|
+
}
|
|
608
|
+
/** @deprecated Use {@link CloseMobileNav}. */
|
|
489
609
|
closeMobileNav() {
|
|
490
|
-
this.
|
|
610
|
+
return this.CloseMobileNav();
|
|
491
611
|
}
|
|
492
612
|
/**
|
|
493
613
|
* Closes the settings page and navigates back
|
|
494
614
|
*/
|
|
495
|
-
|
|
615
|
+
CloseSettings() {
|
|
496
616
|
this.location.back();
|
|
497
617
|
}
|
|
618
|
+
/** @deprecated Use {@link CloseSettings}. */
|
|
619
|
+
closeSettings() {
|
|
620
|
+
return this.CloseSettings();
|
|
621
|
+
}
|
|
498
622
|
/**
|
|
499
623
|
* Handles tab change on mobile
|
|
500
624
|
*/
|
|
625
|
+
OnMobileTabChange(tabId) {
|
|
626
|
+
this.OnTabChange(tabId);
|
|
627
|
+
this.CloseMobileNav();
|
|
628
|
+
}
|
|
629
|
+
/** @deprecated Use {@link OnMobileTabChange}. */
|
|
501
630
|
onMobileTabChange(tabId) {
|
|
502
|
-
this.
|
|
503
|
-
this.closeMobileNav();
|
|
631
|
+
return this.OnMobileTabChange(tabId);
|
|
504
632
|
}
|
|
505
633
|
handleResize() {
|
|
506
|
-
this.
|
|
507
|
-
if (!this.
|
|
508
|
-
this.
|
|
634
|
+
this.IsMobile = window.innerWidth < 768;
|
|
635
|
+
if (!this.IsMobile) {
|
|
636
|
+
this.IsMobileNavOpen = false;
|
|
509
637
|
}
|
|
510
638
|
}
|
|
511
639
|
emitStateChange() {
|
|
512
640
|
const state = {
|
|
513
|
-
activeTab: this.
|
|
514
|
-
searchTerm: this.
|
|
515
|
-
expandedSections: [...this.
|
|
641
|
+
activeTab: this.ActiveTab,
|
|
642
|
+
searchTerm: this.SearchTerm$.value,
|
|
643
|
+
expandedSections: [...this.ExpandedSections]
|
|
516
644
|
};
|
|
517
|
-
this.
|
|
645
|
+
this.StateChange.emit(state);
|
|
518
646
|
}
|
|
519
|
-
|
|
647
|
+
LoadUserState(state) {
|
|
520
648
|
if (state.activeTab) {
|
|
521
|
-
this.
|
|
649
|
+
this.ActiveTab = state.activeTab;
|
|
522
650
|
}
|
|
523
651
|
if (state.searchTerm !== undefined) {
|
|
524
|
-
this.
|
|
652
|
+
this.SearchTerm$.next(state.searchTerm);
|
|
525
653
|
}
|
|
526
654
|
if (state.expandedSections) {
|
|
527
|
-
this.
|
|
655
|
+
this.ExpandedSections = [...state.expandedSections];
|
|
528
656
|
}
|
|
529
657
|
}
|
|
530
|
-
|
|
658
|
+
/** @deprecated Use {@link LoadUserState}. */
|
|
659
|
+
loadUserState(state) {
|
|
660
|
+
return this.LoadUserState(state);
|
|
661
|
+
}
|
|
662
|
+
GetTabIcon(tab) {
|
|
531
663
|
return tab.icon;
|
|
532
664
|
}
|
|
533
|
-
|
|
665
|
+
/** @deprecated Use {@link GetTabIcon}. */
|
|
666
|
+
getTabIcon(tab) {
|
|
667
|
+
return this.GetTabIcon(tab);
|
|
668
|
+
}
|
|
669
|
+
GetTabClass(tab) {
|
|
534
670
|
const classes = ['settings-tab'];
|
|
535
|
-
if (this.
|
|
671
|
+
if (this.ActiveTab === tab.id) {
|
|
536
672
|
classes.push('active');
|
|
537
673
|
}
|
|
538
674
|
if (tab.disabled) {
|
|
@@ -543,11 +679,19 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
|
|
|
543
679
|
}
|
|
544
680
|
return classes.join(' ');
|
|
545
681
|
}
|
|
546
|
-
|
|
682
|
+
/** @deprecated Use {@link GetTabClass}. */
|
|
683
|
+
getTabClass(tab) {
|
|
684
|
+
return this.GetTabClass(tab);
|
|
685
|
+
}
|
|
686
|
+
IsTabDisabled(tab) {
|
|
547
687
|
return tab.disabled || false;
|
|
548
688
|
}
|
|
689
|
+
/** @deprecated Use {@link IsTabDisabled}. */
|
|
690
|
+
isTabDisabled(tab) {
|
|
691
|
+
return this.IsTabDisabled(tab);
|
|
692
|
+
}
|
|
549
693
|
static ɵfac = function SettingsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SettingsComponent)(i0.ɵɵdirectiveInject(i1.Location), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.NgZone)); };
|
|
550
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsComponent, selectors: [["mj-settings"]], outputs: { stateChange: "stateChange" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [[1, "mj-page-container"], ["role", "status", "aria-live", "polite", 1, "loading-container"], ["role", "alert", 1, "error-container"], [1, "settings-content"], ["text", "Loading settings..."], [1, "error-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], [1, "retry-button", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-refresh"], [1, "desktop-layout", 2, "display", "flex"], [1, "mobile-layout"], ["role", "navigation", "aria-label", "Settings navigation", 1, "side-navigation"], [1, "nav-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-search", "nav-search-icon"], ["type", "text", "placeholder", "Search settings...", "aria-label", "Search settings", 1, "nav-search-input", 3, "input", "value"], ["aria-label", "Clear search", "tabindex", "0", 1, "nav-search-clear"], ["role", "tablist", "aria-orientation", "vertical", 1, "nav-list"], ["role", "tab", "tabindex", "0", 1, "nav-item", 3, "active", "disabled"], ["role", "tabpanel", 1, "content-area"], [1, "tab-content"], [1, "notifications-settings"], ["aria-label", "Clear search", "tabindex", "0", 1, "nav-search-clear", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["role", "tab", "tabindex", "0", 1, "nav-item", 3, "click", "keydown.enter"], ["aria-hidden", "true"], [1, "nav-label"], [1, "coming-soon-badge"], [1, "nav-badge", 3, "class"], [1, "nav-badge"], [1, "section-title"], [1, "section-description"], [1, "mobile-header"], ["aria-hidden", "true", 1, "mobile-nav-backdrop"], ["role", "navigation", "aria-label", "Settings navigation", 1, "mobile-nav-rail"], [1, "nav-rail-header"], [1, "nav-rail-title"], ["role", "tablist", 1, "nav-rail-items"], ["role", "tab", 1, "nav-rail-item", 3, "active", "disabled"], ["aria-label", "Close settings", 1, "nav-rail-item", "nav-rail-close-item", 3, "click"], [1, "nav-rail-label"], [1, "mobile-content"], ["aria-label", "Toggle navigation menu", 1, "mobile-header-icon", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-bars"], [1, "mobile-header-title"], [1, "mobile-header-spacer"], ["aria-hidden", "true", 1, "mobile-nav-backdrop", 3, "click"], ["role", "tab", 1, "nav-rail-item", 3, "click", "disabled"], [1, "rail-badge", 3, "class"], [1, "rail-badge"]], template: function SettingsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
694
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsComponent, selectors: [["mj-settings"]], outputs: { StateChange: "StateChange", stateChange: "stateChange" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [[1, "mj-page-container"], ["role", "status", "aria-live", "polite", 1, "loading-container"], ["role", "alert", 1, "error-container"], [1, "settings-content"], ["text", "Loading settings..."], [1, "error-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], [1, "retry-button", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-refresh"], [1, "desktop-layout", 2, "display", "flex"], [1, "mobile-layout"], ["role", "navigation", "aria-label", "Settings navigation", 1, "side-navigation"], [1, "nav-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-search", "nav-search-icon"], ["type", "text", "placeholder", "Search settings...", "aria-label", "Search settings", 1, "nav-search-input", 3, "input", "value"], ["aria-label", "Clear search", "tabindex", "0", 1, "nav-search-clear"], ["role", "tablist", "aria-orientation", "vertical", 1, "nav-list"], ["role", "tab", "tabindex", "0", 1, "nav-item", 3, "active", "disabled"], ["role", "tabpanel", 1, "content-area"], [1, "tab-content"], [1, "notifications-settings"], ["aria-label", "Clear search", "tabindex", "0", 1, "nav-search-clear", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["role", "tab", "tabindex", "0", 1, "nav-item", 3, "click", "keydown.enter"], ["aria-hidden", "true"], [1, "nav-label"], [1, "coming-soon-badge"], [1, "nav-badge", 3, "class"], [1, "nav-badge"], [1, "section-title"], [1, "section-description"], [1, "mobile-header"], ["aria-hidden", "true", 1, "mobile-nav-backdrop"], ["role", "navigation", "aria-label", "Settings navigation", 1, "mobile-nav-rail"], [1, "nav-rail-header"], [1, "nav-rail-title"], ["role", "tablist", 1, "nav-rail-items"], ["role", "tab", 1, "nav-rail-item", 3, "active", "disabled"], ["aria-label", "Close settings", 1, "nav-rail-item", "nav-rail-close-item", 3, "click"], [1, "nav-rail-label"], [1, "mobile-content"], ["aria-label", "Toggle navigation menu", 1, "mobile-header-icon", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-bars"], [1, "mobile-header-title"], [1, "mobile-header-spacer"], ["aria-hidden", "true", 1, "mobile-nav-backdrop", 3, "click"], ["role", "tab", 1, "nav-rail-item", 3, "click", "disabled"], [1, "rail-badge", 3, "class"], [1, "rail-badge"]], template: function SettingsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
551
695
|
i0.ɵɵelementStart(0, "div", 0);
|
|
552
696
|
i0.ɵɵconditionalCreate(1, SettingsComponent_Conditional_1_Template, 2, 0, "div", 1);
|
|
553
697
|
i0.ɵɵconditionalCreate(2, SettingsComponent_Conditional_2_Template, 8, 1, "div", 2);
|
|
@@ -569,7 +713,9 @@ export { SettingsComponent };
|
|
|
569
713
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SettingsComponent, [{
|
|
570
714
|
type: Component,
|
|
571
715
|
args: [{ standalone: false, selector: 'mj-settings', template: "<div class=\"mj-page-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\" role=\"status\" aria-live=\"polite\">\n <mj-loading text=\"Loading settings...\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-container\" role=\"alert\">\n <div class=\"error-content\">\n <i class=\"fa-solid fa-exclamation-triangle error-icon\" aria-hidden=\"true\"></i>\n <p class=\"error-message\">{{ error }}</p>\n <button class=\"retry-button\" (click)=\"loadInitialData()\">\n <i class=\"fa-solid fa-refresh\" aria-hidden=\"true\"></i>\n Try Again\n </button>\n </div>\n </div>\n }\n\n <!-- Main Content -->\n @if (!isLoading && !error) {\n <div class=\"settings-content\">\n <!-- Desktop Layout -->\n @if (!isMobile) {\n <div class=\"desktop-layout\" style=\"display: flex;\">\n <!-- Side Navigation -->\n <nav class=\"side-navigation\" role=\"navigation\" aria-label=\"Settings navigation\">\n <!-- Search Bar -->\n <div class=\"nav-search\">\n <i class=\"fa-solid fa-search nav-search-icon\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n class=\"nav-search-input\"\n placeholder=\"Search settings...\"\n (input)=\"onSearchChange($event)\"\n [value]=\"searchTerm$.value\"\n aria-label=\"Search settings\"\n />\n @if (searchTerm$.value) {\n <button\n class=\"nav-search-clear\"\n (click)=\"clearSearch()\"\n aria-label=\"Clear search\"\n tabindex=\"0\"\n >\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n\n <ul class=\"nav-list\" role=\"tablist\" aria-orientation=\"vertical\">\n @for (tab of filteredTabs; track tab.id) {\n <li\n class=\"nav-item\"\n [class.active]=\"activeTab === tab.id\"\n [class.disabled]=\"tab.disabled\"\n (click)=\"onTabChange(tab.id)\"\n (keydown.enter)=\"onTabChange(tab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.id\"\n [attr.aria-controls]=\"'panel-' + tab.id\"\n [attr.aria-disabled]=\"tab.disabled\"\n tabindex=\"0\"\n >\n <i [class]=\"tab.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ tab.label }}</span>\n @if (tab.disabled) {\n <span class=\"coming-soon-badge\">Soon</span>\n }\n @if (tab.badgeCount && tab.badgeCount > 0) {\n <span class=\"nav-badge\" [class]=\"'badge-' + (tab.badgeColor || 'primary')\">\n {{ tab.badgeCount }}\n </span>\n }\n </li>\n }\n </ul>\n </nav>\n\n <!-- Content Area -->\n <div class=\"content-area\" role=\"tabpanel\" [attr.id]=\"'panel-' + activeTab\">\n <div class=\"tab-content\">\n @switch (activeTab) {\n @case ('general') {\n <mj-general-settings></mj-general-settings>\n }\n\n @case ('notifications') {\n <div class=\"notifications-settings\">\n <h2 class=\"section-title\">Notifications</h2>\n <p class=\"section-description\">Configure how and when you receive notifications</p>\n <mj-notification-preferences></mj-notification-preferences>\n </div>\n }\n\n @case ('applications') {\n <mj-application-settings></mj-application-settings>\n }\n\n @case ('appearance') {\n <mj-appearance-settings></mj-appearance-settings>\n }\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Mobile Layout -->\n @if (isMobile) {\n <div class=\"mobile-layout\">\n <!-- Mobile Header -->\n @if (!isMobileNavOpen) {\n <header class=\"mobile-header\">\n <button\n class=\"mobile-header-icon\"\n (click)=\"toggleMobileNav()\"\n aria-label=\"Toggle navigation menu\"\n [attr.aria-expanded]=\"isMobileNavOpen\"\n >\n <i class=\"fa-solid fa-bars\" aria-hidden=\"true\"></i>\n </button>\n <h1 class=\"mobile-header-title\">Settings</h1>\n <div class=\"mobile-header-spacer\"></div>\n </header>\n }\n\n <!-- Backdrop Overlay -->\n @if (isMobileNavOpen) {\n <div\n class=\"mobile-nav-backdrop\"\n (click)=\"closeMobileNav()\"\n aria-hidden=\"true\"\n ></div>\n }\n\n <!-- Mobile Navigation Rail -->\n <nav\n class=\"mobile-nav-rail\"\n [class.open]=\"isMobileNavOpen\"\n role=\"navigation\"\n aria-label=\"Settings navigation\"\n >\n <div class=\"nav-rail-header\">\n <span class=\"nav-rail-title\">Settings</span>\n </div>\n\n <div class=\"nav-rail-items\" role=\"tablist\">\n @for (tab of filteredTabs; track tab.id) {\n <button\n class=\"nav-rail-item\"\n [class.active]=\"activeTab === tab.id\"\n [class.disabled]=\"tab.disabled\"\n [disabled]=\"tab.disabled\"\n (click)=\"onMobileTabChange(tab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.id\"\n [attr.aria-label]=\"tab.label\"\n >\n <i [class]=\"tab.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-rail-label\">{{ tab.label }}</span>\n @if (tab.disabled) {\n <span class=\"coming-soon-badge\">Soon</span>\n }\n @if (tab.badgeCount && tab.badgeCount > 0) {\n <span class=\"rail-badge\" [class]=\"'badge-' + (tab.badgeColor || 'primary')\">\n {{ tab.badgeCount }}\n </span>\n }\n </button>\n }\n\n <button\n class=\"nav-rail-item nav-rail-close-item\"\n (click)=\"closeSettings()\"\n aria-label=\"Close settings\"\n >\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n <span class=\"nav-rail-label\">Close</span>\n </button>\n </div>\n </nav>\n\n <!-- Mobile Content Area -->\n <div class=\"mobile-content\">\n <div class=\"tab-content\">\n @switch (activeTab) {\n @case ('general') {\n <mj-general-settings></mj-general-settings>\n }\n\n @case ('notifications') {\n <div class=\"notifications-settings\">\n <h2 class=\"section-title\">Notifications</h2>\n <p class=\"section-description\">Configure how and when you receive notifications</p>\n <mj-notification-preferences></mj-notification-preferences>\n </div>\n }\n\n @case ('applications') {\n <mj-application-settings></mj-application-settings>\n }\n\n @case ('appearance') {\n <mj-appearance-settings></mj-appearance-settings>\n }\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: ["/* ============================================\n Settings Component\n Using MJ Design Tokens\n ============================================ */\n\n/* ============================================\n Host & Page Container\n ============================================ */\n\n/* Host element must fill its container */\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n@media (max-width: 768px) {\n :host {\n height: auto;\n min-height: 100vh;\n overflow: visible;\n }\n}\n\n/* Page container needs proper height and scrolling */\n.mj-page-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n@media (max-width: 768px) {\n .mj-page-container {\n overflow-y: visible;\n overflow-x: hidden;\n height: auto;\n min-height: 100vh;\n }\n}\n\n/* ============================================\n Keyframe Animations\n ============================================ */\n\n@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n/* ============================================\n Settings Container & Main Layout\n ============================================ */\n\n.settings-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n background-color: var(--mj-bg-page);\n overflow-y: auto;\n position: relative;\n}\n\n/* ============================================\n Loading State\n ============================================ */\n.loading-container {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n}\n\n.loading-content {\n text-align: center;\n}\n\n.loading-text {\n color: var(--mj-text-muted);\n font-size: 1rem;\n}\n\n/* ============================================\n Error State\n ============================================ */\n.error-container {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n}\n\n.error-content {\n text-align: center;\n max-width: 400px;\n}\n\n.error-content .error-icon {\n font-size: 3rem;\n color: var(--mj-status-error);\n margin-bottom: 1rem;\n}\n\n.error-content .error-message {\n color: var(--mj-text-primary);\n margin-bottom: 1.5rem;\n font-size: 1rem;\n}\n\n.error-content .retry-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n border: none;\n border-radius: 20px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n background-color: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n}\n\n.error-content .retry-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.error-content .retry-button:hover:not(:disabled) {\n background-color: var(--mj-brand-primary);\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n}\n\n.error-content .retry-button i {\n font-size: 0.875rem;\n}\n\n/* ============================================\n Main Content Area & Tab Layout\n ============================================ */\n\n.settings-content {\n display: flex;\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n flex-direction: column;\n width: 100%;\n min-height: 0;\n}\n\n@media (max-width: 768px) {\n .settings-content {\n overflow-y: visible;\n overflow-x: hidden;\n height: auto;\n min-height: 0;\n flex: none;\n }\n}\n\n.desktop-layout {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n.settings-content .desktop-layout {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n/* ============================================\n Side Navigation (Desktop Only)\n ============================================ */\n\n.side-navigation {\n width: 280px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n overflow-y: auto;\n flex-shrink: 0;\n box-shadow: var(--mj-shadow-sm);\n}\n\n/* Navigation Search Bar */\n.nav-search {\n position: relative;\n padding: 1rem;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface);\n}\n\n.nav-search-icon {\n position: absolute;\n left: 1.75rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-muted);\n font-size: 1rem;\n pointer-events: none;\n z-index: 1;\n}\n\n.nav-search-input {\n width: 100%;\n padding: 0.75rem 2.75rem 0.75rem 2.5rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 9999px;\n font-size: 0.875rem;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n background-color: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.nav-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n background-color: var(--mj-bg-surface);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.nav-search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n.nav-search-clear {\n position: absolute;\n right: 1.25rem;\n top: 50%;\n transform: translateY(-50%);\n padding: 0.25rem;\n background: transparent;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n border-radius: 9999px;\n min-width: 32px;\n min-height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n z-index: 1;\n}\n\n.nav-search-clear:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.nav-search-clear:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.nav-list {\n list-style: none;\n margin: 0;\n padding: 1rem 0;\n}\n\n.nav-item {\n position: relative;\n display: flex;\n align-items: center;\n padding: 1rem 1.5rem;\n margin: 0.25rem 0.75rem;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n color: var(--mj-text-muted);\n font-size: 1rem;\n border: 2px solid transparent;\n}\n\n.nav-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n transform: translateX(4px);\n}\n\n.nav-item:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Color-coded navigation items */\n.nav-item[aria-controls=\"panel-general\"] {\n --item-color: var(--mj-brand-primary);\n --item-container: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-users\"] {\n --item-color: var(--mj-status-warning);\n --item-container: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-roles\"] {\n --item-color: var(--mj-status-success);\n --item-container: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-applications\"] {\n --item-color: var(--mj-brand-primary);\n --item-container: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-permissions\"] {\n --item-color: var(--mj-status-error);\n --item-container: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-advanced\"] {\n --item-color: var(--mj-status-warning);\n --item-container: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n}\n\n.nav-item.active {\n background-color: var(--item-container);\n color: var(--item-color);\n font-weight: 600;\n border-color: var(--item-color);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.nav-item:hover:not(.active) {\n border-color: var(--item-color);\n background-color: var(--mj-bg-surface-card);\n}\n\n.nav-item i {\n width: 20px;\n margin-right: 0.75rem;\n font-size: 1.1rem;\n}\n\n.nav-item .nav-label {\n flex: 1;\n}\n\n.nav-item .nav-badge {\n padding: 0.125rem 0.5rem;\n border-radius: 9999px;\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.nav-item .nav-badge.badge-primary {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.nav-item .nav-badge.badge-danger {\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.nav-item .nav-badge.badge-warning {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.nav-item .nav-badge.badge-success {\n background-color: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n/* Disabled Navigation Items */\n.nav-item.disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.nav-item.disabled:hover {\n background-color: transparent;\n transform: none;\n}\n\n/* Coming Soon Badge */\n.coming-soon-badge {\n display: inline-flex;\n align-items: center;\n padding: 0.125rem 0.5rem;\n border-radius: 9999px;\n font-size: 0.625rem;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid var(--mj-border-default);\n}\n\n/* Mobile Navigation Disabled Items */\n.nav-rail-item.disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.nav-rail-item.disabled:hover {\n background-color: transparent;\n}\n\n/* ============================================\n Content Area & Tab Panels\n ============================================ */\n\n.content-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 0;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0;\n background: var(--mj-bg-surface);\n}\n\n@media (max-width: 768px) {\n .content-area {\n padding: 1rem;\n }\n}\n\n.tab-content {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n max-width: 100%;\n min-height: 0;\n box-sizing: border-box;\n overflow-x: hidden;\n padding: 1.5rem 2rem;\n}\n\n@media (max-width: 768px) {\n .tab-content {\n height: auto;\n min-height: 0;\n overflow-y: visible;\n overflow-x: hidden;\n padding: 0.5rem;\n }\n}\n\n/* ============================================\n Section Titles\n ============================================ */\n.section-title {\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 1rem 0;\n padding-bottom: 0.75rem;\n border-bottom: 3px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.section-title::before {\n content: \"\";\n width: 4px;\n height: 2rem;\n background: var(--mj-brand-primary);\n border-radius: 2px;\n}\n\n.section-description {\n color: var(--mj-text-muted);\n margin: 0 0 1.5rem 0;\n font-size: 1rem;\n padding: 1rem 1.25rem;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n}\n\n/* ============================================\n Settings Grid\n ============================================ */\n.settings-grid,\n.mj-grid {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n margin-top: 1.5rem;\n}\n\n.mj-grid-responsive {\n /* Single column stacked layout */\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n@media (max-width: 768px) {\n .settings-grid,\n .mj-grid,\n .mj-grid-responsive {\n gap: 1rem;\n margin-top: 0.5rem;\n }\n}\n\n/* ============================================\n Section Title & Description Spacing\n ============================================ */\n.general-settings .section-title,\n.users-settings .section-title,\n.roles-settings .section-title {\n margin-bottom: 0.25rem;\n}\n\n.users-settings .section-description,\n.roles-settings .section-description {\n margin-bottom: 0.5rem;\n}\n\n/* ============================================\n Card Content\n ============================================ */\n.card-content {\n padding: 1rem;\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n}\n\n.card-content p {\n margin: 0 0 1rem 0;\n line-height: 1.6;\n}\n\n/* ============================================\n Beta Warning\n ============================================ */\n.beta-warning {\n display: inline-flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1.25rem;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border-radius: 12px;\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 1.5rem;\n max-width: 100%;\n box-sizing: border-box;\n border: 2px solid var(--mj-status-warning);\n box-shadow: 0 2px 8px rgba(255, 111, 0, 0.2);\n}\n\n.beta-warning i {\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n@media (max-width: 768px) {\n .beta-warning {\n font-size: 0.8125rem;\n padding: 0.5rem 0.75rem;\n margin-bottom: 0.75rem;\n }\n}\n\n/* ============================================\n Mobile Layout with Collapsible Navigation Rail\n ============================================ */\n\n.mobile-layout {\n position: relative;\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n width: 100%;\n max-width: 100vw;\n overflow: visible;\n box-sizing: border-box;\n}\n\n/* Mobile Header */\n.mobile-header {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 56px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0.5rem;\n background-color: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n z-index: 100;\n box-sizing: border-box;\n}\n\n.mobile-header-icon {\n width: 48px;\n height: 48px;\n min-width: 48px;\n border-radius: 9999px;\n background: transparent;\n color: var(--mj-text-primary);\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.mobile-header-icon:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.mobile-header-icon:active {\n transform: scale(0.95);\n}\n\n.mobile-header-icon i {\n font-size: 1.25rem;\n}\n\n.mobile-header-title {\n flex: 1;\n text-align: center;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n padding: 0 0.5rem;\n}\n\n.mobile-header-spacer {\n width: 48px;\n min-width: 48px;\n}\n\n/* Backdrop Overlay */\n.mobile-nav-backdrop {\n position: fixed;\n inset: 0;\n background-color: rgba(0, 0, 0, 0.5);\n z-index: 1000;\n animation: fadeIn 0.2s ease-out;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Collapsible Navigation Rail */\n.mobile-nav-rail {\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 80vw;\n background-color: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n z-index: 1001;\n transform: translateX(-100%);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--mj-shadow-lg);\n overflow: hidden;\n}\n\n.mobile-nav-rail.open {\n transform: translateX(0);\n}\n\n/* Navigation Rail Header */\n.nav-rail-header {\n display: flex;\n align-items: center;\n padding: 1rem 1.5rem;\n min-height: 64px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.nav-rail-title {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n/* Navigation Items Container */\n.nav-rail-items {\n display: flex;\n flex-direction: column;\n padding: 0.5rem;\n gap: 0.25rem;\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n}\n\n/* Close Navigation Item */\n.nav-rail-close-item {\n margin-top: auto;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 0.75rem !important;\n margin-top: 0.5rem;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)) !important;\n color: var(--mj-status-error) !important;\n}\n\n.nav-rail-close-item:hover {\n background-color: var(--mj-status-error) !important;\n color: var(--mj-bg-surface) !important;\n}\n\n.nav-rail-close-item i {\n font-size: 1.5rem;\n}\n\n/* Navigation Item */\n.nav-rail-item {\n position: relative;\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 1rem;\n width: 100%;\n padding: 0.875rem 1rem;\n background: transparent;\n border: none;\n border-radius: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n text-align: left;\n min-height: 56px;\n}\n\n.nav-rail-item i {\n font-size: 1.5rem;\n width: 24px;\n text-align: center;\n flex-shrink: 0;\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.nav-rail-label {\n font-size: 1rem;\n font-weight: 500;\n flex: 1;\n}\n\n.nav-rail-item:hover:not(.active) {\n background-color: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.nav-rail-item.active {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.nav-rail-item.active .nav-rail-label {\n font-weight: 600;\n}\n\n.nav-rail-item:active {\n transform: scale(0.98);\n}\n\n.nav-rail-item:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Badge indicator */\n.rail-badge {\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: 9999px;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.rail-badge.badge-primary {\n background-color: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n}\n\n.rail-badge.badge-danger {\n background-color: var(--mj-status-error);\n color: var(--mj-bg-surface);\n}\n\n.rail-badge.badge-warning {\n background-color: var(--mj-status-success);\n color: var(--mj-bg-surface);\n}\n\n.rail-badge.badge-success {\n background-color: var(--mj-status-warning);\n color: var(--mj-text-primary);\n}\n\n/* Mobile Content Area */\n.mobile-content {\n width: 100%;\n max-width: 100vw;\n overflow-y: visible;\n overflow-x: hidden;\n padding: 72px 0.75rem 2rem 0.75rem;\n min-width: 0;\n box-sizing: border-box;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n/* Responsive adjustments */\n@media (max-width: 374px) {\n .mobile-nav-rail {\n width: 260px;\n }\n\n .mobile-content {\n padding: 64px 0.5rem 1.5rem 0.5rem;\n }\n\n .mobile-header {\n height: 52px;\n padding: 0 0.25rem;\n }\n\n .mobile-header-icon {\n width: 44px;\n height: 44px;\n min-width: 44px;\n }\n\n .mobile-header-spacer {\n width: 44px;\n min-width: 44px;\n }\n\n .mobile-header-title {\n font-size: 1.125rem;\n }\n}\n\n/* ============================================\n Advanced Settings Sub-Tabs\n ============================================ */\n\n.advanced-tabs {\n display: flex;\n gap: 0.5rem;\n border-bottom: 2px solid var(--mj-border-default);\n margin-bottom: 1rem;\n margin-top: 1rem;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n -webkit-overflow-scrolling: touch;\n}\n\n.advanced-tabs .tab-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background: transparent;\n border: none;\n border-bottom: 3px solid transparent;\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n min-height: 44px;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Mobile-specific tab adjustments - Segmented Button Style */\n@media (max-width: 768px) {\n .advanced-tabs {\n gap: 0;\n margin-bottom: 1rem;\n margin-top: 1rem;\n border-bottom: none;\n border: 1px solid var(--mj-border-strong);\n border-radius: 9999px;\n padding: 0;\n background-color: var(--mj-bg-surface-sunken);\n overflow-x: hidden;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n }\n\n .advanced-tabs .tab-btn {\n flex: 1;\n padding: 0.625rem 0.5rem;\n font-size: 0.75rem;\n border-bottom: none;\n border-radius: 0;\n border-right: 1px solid var(--mj-border-strong);\n min-width: 0;\n justify-content: center;\n text-align: center;\n white-space: nowrap;\n overflow: hidden;\n }\n\n .advanced-tabs .tab-btn:last-child {\n border-right: none;\n }\n\n .advanced-tabs .tab-btn:first-child {\n border-radius: 9999px 0 0 9999px;\n }\n\n .advanced-tabs .tab-btn:last-child {\n border-radius: 0 9999px 9999px 0;\n }\n\n .advanced-tabs .tab-btn.active {\n background-color: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border-bottom: none;\n }\n\n .advanced-tabs .tab-btn i {\n font-size: 0.875rem;\n }\n}\n\n.advanced-tabs .tab-btn:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.advanced-tabs .tab-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: -2px;\n}\n\n.advanced-tabs .tab-btn.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.advanced-tabs .tab-btn.active i {\n color: var(--mj-brand-primary);\n}\n\n.advanced-tabs .tab-btn i {\n font-size: 1.125rem;\n}\n\n/* ============================================\n Advanced Tab Content Panels\n ============================================ */\n\n.advanced-tab-content {\n flex: 1;\n overflow-y: visible;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n background: var(--mj-bg-surface);\n border-radius: 16px;\n padding: 0;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n/* Ensure scrolling works on mobile */\n@media (max-width: 768px) {\n .advanced-tab-content {\n height: auto;\n min-height: 200px;\n overflow-y: visible;\n }\n}\n\n.performance-settings,\n.developer-settings {\n padding: 2rem;\n}\n\n.performance-settings h3,\n.developer-settings h3 {\n margin: 0 0 1rem 0;\n font-size: 1.25rem;\n color: var(--mj-text-primary);\n}\n\n.performance-settings p,\n.developer-settings p {\n color: var(--mj-text-muted);\n font-size: 1rem;\n}\n\n/* ============================================\n Settings Panel Containers with Fade-In Animation\n ============================================ */\n\n.general-settings,\n.users-settings,\n.roles-settings,\n.applications-settings,\n.permissions-settings,\n.advanced-settings {\n animation: fadeIn 0.3s ease-out;\n width: 100%;\n max-width: 100%;\n height: auto;\n min-height: 100%;\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n overflow-y: visible;\n overflow-x: hidden;\n box-sizing: border-box;\n}\n\n/* Mobile-specific adjustments */\n@media (max-width: 768px) {\n .general-settings,\n .users-settings,\n .roles-settings,\n .applications-settings,\n .permissions-settings,\n .advanced-settings {\n gap: 0.75rem;\n height: auto;\n min-height: auto;\n }\n\n .section-title {\n margin-bottom: 0.5rem;\n font-size: 1.375rem;\n }\n\n .section-description {\n margin-bottom: 0.75rem;\n }\n}\n\n/* Only apply flex: 1 to actual content components, not titles/descriptions */\n.general-settings > mj-settings-card,\n.general-settings > .mj-grid,\n.users-settings > mj-user-management,\n.roles-settings > mj-role-management,\n.applications-settings > mj-application-management,\n.permissions-settings > mj-entity-permissions,\n.advanced-settings > .advanced-tabs,\n.advanced-settings > .advanced-tab-content {\n flex-shrink: 0;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n/* Allow content to flow naturally on mobile */\n@media (max-width: 768px) {\n .users-settings > mj-user-management,\n .roles-settings > mj-role-management,\n .applications-settings > mj-application-management,\n .permissions-settings > mj-entity-permissions,\n .advanced-settings > .advanced-tab-content {\n flex: none;\n height: auto !important;\n min-height: 0;\n max-height: none !important;\n overflow-y: visible !important;\n overflow-x: hidden;\n }\n}\n\n/* Titles and descriptions should not flex or grow */\n.general-settings > .section-title,\n.users-settings > .section-title,\n.roles-settings > .section-title,\n.users-settings > .section-description,\n.roles-settings > .section-description {\n flex-shrink: 0;\n flex-grow: 0;\n}\n\n/* ============================================\n Accessibility: Reduced Motion Support\n ============================================ */\n\n@media (prefers-reduced-motion: reduce) {\n .general-settings,\n .users-settings,\n .roles-settings,\n .applications-settings,\n .permissions-settings,\n .advanced-settings {\n animation: none;\n }\n\n .nav-tab i,\n .nav-item,\n .tab-btn,\n .search-input,\n .retry-button,\n .search-result-item {\n transition: none;\n }\n}\n\n/* ============================================\n Responsive Breakpoints\n ============================================ */\n@media (max-width: 640px) {\n .side-navigation {\n width: 200px;\n }\n\n .nav-item {\n padding: 0.75rem 1rem;\n }\n}\n\n@media (max-width: 1024px) {\n .content-area {\n padding: 1.5rem;\n }\n}\n\n/* Mobile scroll fix - ensure all child components flow naturally */\n@media (max-width: 768px) {\n .mobile-layout mj-user-management,\n .mobile-layout mj-role-management,\n .mobile-layout mj-application-management,\n .mobile-layout mj-entity-permissions,\n .mobile-layout mj-sql-logging,\n .mobile-layout mj-settings-card,\n .mobile-layout mj-user-profile-settings {\n display: block;\n height: auto !important;\n max-height: none !important;\n overflow: visible !important;\n }\n\n /* Ensure all nested content areas flow naturally */\n .mobile-layout .general-settings,\n .mobile-layout .users-settings,\n .mobile-layout .roles-settings,\n .mobile-layout .applications-settings,\n .mobile-layout .permissions-settings,\n .mobile-layout .advanced-settings {\n height: auto !important;\n min-height: 0 !important;\n max-height: none !important;\n }\n\n /* Ensure mj-grid and card content can expand */\n .mobile-layout .mj-grid,\n .mobile-layout .mj-grid-responsive,\n .mobile-layout .card-content {\n height: auto !important;\n min-height: 0 !important;\n }\n}\n\n@media (min-width: 1440px) {\n .content-area {\n padding: 2.5rem 3rem;\n }\n\n .side-navigation {\n width: 280px;\n }\n}\n\n/* ============================================\n iOS Safari Mobile Scrolling Fix\n ============================================ */\n@media (max-width: 768px) {\n /* Prevent iOS from restricting body scrolling */\n body {\n position: relative;\n overflow-y: visible;\n -webkit-overflow-scrolling: touch;\n }\n\n /* Allow mobile layout and all parents to expand naturally */\n .mobile-layout,\n .mobile-layout > *,\n .mobile-content > *,\n .tab-content > * {\n -webkit-overflow-scrolling: touch;\n }\n\n /* Prevent fixed heights from blocking scroll */\n .mobile-layout * {\n box-sizing: border-box;\n }\n}\n"] }]
|
|
572
|
-
}], () => [{ type: i1.Location }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }], {
|
|
716
|
+
}], () => [{ type: i1.Location }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }], { StateChange: [{
|
|
717
|
+
type: Output
|
|
718
|
+
}], stateChange: [{
|
|
573
719
|
type: Output
|
|
574
720
|
}] }); })();
|
|
575
721
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SettingsComponent, { className: "SettingsComponent", filePath: "src/lib/settings/settings.component.ts", lineNumber: 41 }); })();
|