@memberjunction/ng-explorer-settings 2.49.0 → 2.51.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.
Files changed (66) hide show
  1. package/README.md +89 -1
  2. package/dist/lib/application-management/application-management.component.d.ts +59 -0
  3. package/dist/lib/application-management/application-management.component.d.ts.map +1 -0
  4. package/dist/lib/application-management/application-management.component.js +540 -0
  5. package/dist/lib/application-management/application-management.component.js.map +1 -0
  6. package/dist/lib/entity-permissions/entity-permissions.component.d.ts +71 -0
  7. package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -0
  8. package/dist/lib/entity-permissions/entity-permissions.component.js +667 -0
  9. package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -0
  10. package/dist/lib/module.d.ts +19 -23
  11. package/dist/lib/module.d.ts.map +1 -1
  12. package/dist/lib/module.js +13 -38
  13. package/dist/lib/module.js.map +1 -1
  14. package/dist/lib/role-management/role-management.component.d.ts +56 -0
  15. package/dist/lib/role-management/role-management.component.d.ts.map +1 -0
  16. package/dist/lib/role-management/role-management.component.js +464 -0
  17. package/dist/lib/role-management/role-management.component.js.map +1 -0
  18. package/dist/lib/settings/settings.component.d.ts +42 -51
  19. package/dist/lib/settings/settings.component.d.ts.map +1 -1
  20. package/dist/lib/settings/settings.component.js +432 -198
  21. package/dist/lib/settings/settings.component.js.map +1 -1
  22. package/dist/lib/shared/components/settings-card/settings-card.component.d.ts +27 -0
  23. package/dist/lib/shared/components/settings-card/settings-card.component.d.ts.map +1 -0
  24. package/dist/lib/shared/components/settings-card/settings-card.component.js +167 -0
  25. package/dist/lib/shared/components/settings-card/settings-card.component.js.map +1 -0
  26. package/dist/lib/shared/settings-card.component.d.ts +11 -0
  27. package/dist/lib/shared/settings-card.component.d.ts.map +1 -0
  28. package/dist/lib/shared/settings-card.component.js +73 -0
  29. package/dist/lib/shared/settings-card.component.js.map +1 -0
  30. package/dist/lib/shared/shared-settings.module.d.ts +9 -0
  31. package/dist/lib/shared/shared-settings.module.d.ts.map +1 -0
  32. package/dist/lib/shared/shared-settings.module.js +25 -0
  33. package/dist/lib/shared/shared-settings.module.js.map +1 -0
  34. package/dist/lib/sql-logging/sql-logging.component.d.ts +176 -0
  35. package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -0
  36. package/dist/lib/sql-logging/sql-logging.component.js +946 -0
  37. package/dist/lib/sql-logging/sql-logging.component.js.map +1 -0
  38. package/dist/lib/user-management/user-management.component.d.ts +65 -0
  39. package/dist/lib/user-management/user-management.component.d.ts.map +1 -0
  40. package/dist/lib/user-management/user-management.component.js +643 -0
  41. package/dist/lib/user-management/user-management.component.js.map +1 -0
  42. package/dist/public-api.d.ts +1 -5
  43. package/dist/public-api.d.ts.map +1 -1
  44. package/dist/public-api.js +1 -5
  45. package/dist/public-api.js.map +1 -1
  46. package/package.json +13 -13
  47. package/dist/lib/application-entities-grid/application-entities-grid.component.d.ts +0 -50
  48. package/dist/lib/application-entities-grid/application-entities-grid.component.d.ts.map +0 -1
  49. package/dist/lib/application-entities-grid/application-entities-grid.component.js +0 -342
  50. package/dist/lib/application-entities-grid/application-entities-grid.component.js.map +0 -1
  51. package/dist/lib/single-application/single-application.component.d.ts +0 -22
  52. package/dist/lib/single-application/single-application.component.d.ts.map +0 -1
  53. package/dist/lib/single-application/single-application.component.js +0 -130
  54. package/dist/lib/single-application/single-application.component.js.map +0 -1
  55. package/dist/lib/single-role/single-role.component.d.ts +0 -36
  56. package/dist/lib/single-role/single-role.component.d.ts.map +0 -1
  57. package/dist/lib/single-role/single-role.component.js +0 -188
  58. package/dist/lib/single-role/single-role.component.js.map +0 -1
  59. package/dist/lib/single-user/single-user.component.d.ts +0 -24
  60. package/dist/lib/single-user/single-user.component.d.ts.map +0 -1
  61. package/dist/lib/single-user/single-user.component.js +0 -176
  62. package/dist/lib/single-user/single-user.component.js.map +0 -1
  63. package/dist/lib/user-roles-grid/user-roles-grid.component.d.ts +0 -42
  64. package/dist/lib/user-roles-grid/user-roles-grid.component.d.ts.map +0 -1
  65. package/dist/lib/user-roles-grid/user-roles-grid.component.js +0 -326
  66. package/dist/lib/user-roles-grid/user-roles-grid.component.js.map +0 -1
@@ -4,257 +4,491 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component } from '@angular/core';
8
- import { NavigationEnd } from '@angular/router';
9
- import { Metadata } from '@memberjunction/core';
7
+ import { Component, EventEmitter, Output } from '@angular/core';
10
8
  import { RegisterClass } from '@memberjunction/global';
11
- import { MJNotificationService } from '@memberjunction/ng-notifications';
9
+ import { CommonModule } from '@angular/common';
10
+ import { Subject, BehaviorSubject } from 'rxjs';
11
+ import { takeUntil, debounceTime, distinctUntilChanged } from 'rxjs/operators';
12
+ import { SharedSettingsModule } from '../shared/shared-settings.module';
13
+ import { SqlLoggingComponent } from '../sql-logging/sql-logging.component';
14
+ import { UserManagementComponent } from '../user-management/user-management.component';
15
+ import { RoleManagementComponent } from '../role-management/role-management.component';
16
+ import { ApplicationManagementComponent } from '../application-management/application-management.component';
17
+ import { EntityPermissionsComponent } from '../entity-permissions/entity-permissions.component';
12
18
  import { BaseNavigationComponent } from '@memberjunction/ng-shared';
13
- import { filter } from 'rxjs/operators';
14
19
  import * as i0 from "@angular/core";
15
- import * as i1 from "@angular/router";
16
- import * as i2 from "@angular/common";
17
- import * as i3 from "@memberjunction/ng-container-directives";
18
- import * as i4 from "@memberjunction/ng-entity-permissions";
19
- import * as i5 from "@memberjunction/ng-simple-record-list";
20
- import * as i6 from "../single-role/single-role.component";
21
- import * as i7 from "../single-user/single-user.component";
22
- import * as i8 from "../single-application/single-application.component";
23
- const _c0 = () => ["Name", "Email", "IsActive", "Type"];
24
- const _c1 = () => ["Name", "Description"];
25
- function SettingsComponent_div_2_Template(rf, ctx) { if (rf & 1) {
20
+ import * as i1 from "../shared/settings-card.component";
21
+ const _forTrack0 = ($index, $item) => $item.id;
22
+ function SettingsComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
23
+ i0.ɵɵelementStart(0, "div", 8)(1, "div", 11)(2, "div", 12);
24
+ i0.ɵɵelement(3, "div", 13)(4, "div", 13)(5, "div", 13);
25
+ i0.ɵɵelementEnd();
26
+ i0.ɵɵelementStart(6, "div", 14);
27
+ i0.ɵɵtext(7, "Loading settings...");
28
+ i0.ɵɵelementEnd()()();
29
+ } }
30
+ function SettingsComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
26
31
  const _r1 = i0.ɵɵgetCurrentView();
27
- i0.ɵɵelementStart(0, "div", 10);
28
- i0.ɵɵlistener("click", function SettingsComponent_div_2_Template_div_click_0_listener() { const o_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectItem(o_r2.value)); });
32
+ i0.ɵɵelementStart(0, "div", 9)(1, "div", 15);
33
+ i0.ɵɵelement(2, "i", 16);
34
+ i0.ɵɵelementStart(3, "p", 17);
35
+ i0.ɵɵtext(4);
36
+ i0.ɵɵelementEnd();
37
+ i0.ɵɵelementStart(5, "button", 18);
38
+ i0.ɵɵlistener("click", function SettingsComponent_Conditional_11_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.loadInitialData()); });
39
+ i0.ɵɵelement(6, "i", 19);
40
+ i0.ɵɵtext(7, " Try Again ");
41
+ i0.ɵɵelementEnd()()();
42
+ } if (rf & 2) {
43
+ const ctx_r1 = i0.ɵɵnextContext();
44
+ i0.ɵɵadvance(4);
45
+ i0.ɵɵtextInterpolate(ctx_r1.error);
46
+ } }
47
+ function SettingsComponent_Conditional_12_Conditional_1_For_4_Conditional_4_Template(rf, ctx) { if (rf & 1) {
48
+ i0.ɵɵelementStart(0, "span", 36);
29
49
  i0.ɵɵtext(1);
30
50
  i0.ɵɵelementEnd();
31
51
  } if (rf & 2) {
32
- const o_r2 = ctx.$implicit;
33
- const ctx_r2 = i0.ɵɵnextContext();
34
- i0.ɵɵclassProp("selected", ctx_r2.leftNavItemSelected(o_r2));
52
+ const tab_r4 = i0.ɵɵnextContext().$implicit;
53
+ i0.ɵɵclassMap("badge-" + (tab_r4.badgeColor || "primary"));
35
54
  i0.ɵɵadvance();
36
- i0.ɵɵtextInterpolate(o_r2.label);
55
+ i0.ɵɵtextInterpolate1(" ", tab_r4.badgeCount, " ");
37
56
  } }
38
- function SettingsComponent_Case_4_Template(rf, ctx) { if (rf & 1) {
39
- i0.ɵɵelement(0, "mj-entity-permissions-selector-with-grid");
57
+ function SettingsComponent_Conditional_12_Conditional_1_For_4_Template(rf, ctx) { if (rf & 1) {
58
+ const _r3 = i0.ɵɵgetCurrentView();
59
+ i0.ɵɵelementStart(0, "li", 33);
60
+ i0.ɵɵlistener("click", function SettingsComponent_Conditional_12_Conditional_1_For_4_Template_li_click_0_listener() { const tab_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onTabChange(tab_r4.id)); });
61
+ i0.ɵɵelement(1, "i");
62
+ i0.ɵɵelementStart(2, "span", 34);
63
+ i0.ɵɵtext(3);
64
+ i0.ɵɵelementEnd();
65
+ i0.ɵɵtemplate(4, SettingsComponent_Conditional_12_Conditional_1_For_4_Conditional_4_Template, 2, 3, "span", 35);
66
+ i0.ɵɵelementEnd();
67
+ } if (rf & 2) {
68
+ const tab_r4 = ctx.$implicit;
69
+ const ctx_r1 = i0.ɵɵnextContext(3);
70
+ i0.ɵɵclassProp("active", ctx_r1.activeTab === tab_r4.id);
71
+ i0.ɵɵadvance();
72
+ i0.ɵɵclassMap(tab_r4.icon);
73
+ i0.ɵɵadvance(2);
74
+ i0.ɵɵtextInterpolate(tab_r4.label);
75
+ i0.ɵɵadvance();
76
+ i0.ɵɵconditional(tab_r4.badgeCount && tab_r4.badgeCount > 0 ? 4 : -1);
40
77
  } }
41
- function SettingsComponent_Case_5_Template(rf, ctx) { if (rf & 1) {
42
- const _r4 = i0.ɵɵgetCurrentView();
43
- i0.ɵɵelementStart(0, "mj-simple-record-list", 11);
44
- i0.ɵɵlistener("RecordSelected", function SettingsComponent_Case_5_Template_mj_simple_record_list_RecordSelected_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectUser($event)); })("CustomActionConfirmed", function SettingsComponent_Case_5_Template_mj_simple_record_list_CustomActionConfirmed_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleUserActivation($event)); });
78
+ function SettingsComponent_Conditional_12_Conditional_1_Case_7_Template(rf, ctx) { if (rf & 1) {
79
+ const _r5 = i0.ɵɵgetCurrentView();
80
+ i0.ɵɵelementStart(0, "div", 27)(1, "h2", 37);
81
+ i0.ɵɵtext(2, "General Settings");
45
82
  i0.ɵɵelementEnd();
83
+ i0.ɵɵelementStart(3, "div", 38)(4, "mj-settings-card", 39);
84
+ i0.ɵɵlistener("toggle", function SettingsComponent_Conditional_12_Conditional_1_Case_7_Template_mj_settings_card_toggle_4_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleSection("profile")); });
85
+ i0.ɵɵelementStart(5, "div", 40)(6, "p");
86
+ i0.ɵɵtext(7, "Manage your profile information and preferences.");
87
+ i0.ɵɵelementEnd()()();
88
+ i0.ɵɵelementStart(8, "mj-settings-card", 41);
89
+ i0.ɵɵlistener("toggle", function SettingsComponent_Conditional_12_Conditional_1_Case_7_Template_mj_settings_card_toggle_8_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleSection("preferences")); });
90
+ i0.ɵɵelementStart(9, "div", 40)(10, "p");
91
+ i0.ɵɵtext(11, "Customize your experience with display and behavior preferences.");
92
+ i0.ɵɵelementEnd()()();
93
+ i0.ɵɵelementStart(12, "mj-settings-card", 42);
94
+ i0.ɵɵlistener("toggle", function SettingsComponent_Conditional_12_Conditional_1_Case_7_Template_mj_settings_card_toggle_12_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleSection("notifications")); });
95
+ i0.ɵɵelementStart(13, "div", 40)(14, "p");
96
+ i0.ɵɵtext(15, "Configure how and when you receive notifications.");
97
+ i0.ɵɵelementEnd()()()()();
46
98
  } if (rf & 2) {
47
- const ctx_r2 = i0.ɵɵnextContext();
48
- i0.ɵɵproperty("Columns", i0.ɵɵpureFunction0(8, _c0))("AllowDelete", false)("AllowCustomAction", true)("CustomActionIconFunction", ctx_r2.getUserToggleIcon)("CustomActionTooltipFunction", ctx_r2.getUserToggleTooltip)("CustomActionDialogTitle", "Toggle User Activation")("CustomActionDialogMessage", "Are you sure you want to toggle activation for this user?")("CustomActionDialogInfo", "Active users can log in to the system. Inactive users cannot log in.");
99
+ const ctx_r1 = i0.ɵɵnextContext(3);
100
+ i0.ɵɵadvance(4);
101
+ i0.ɵɵproperty("expanded", ctx_r1.isSectionExpanded("profile"));
102
+ i0.ɵɵadvance(4);
103
+ i0.ɵɵproperty("expanded", ctx_r1.isSectionExpanded("preferences"));
104
+ i0.ɵɵadvance(4);
105
+ i0.ɵɵproperty("expanded", ctx_r1.isSectionExpanded("notifications"));
49
106
  } }
50
- function SettingsComponent_Case_6_Template(rf, ctx) { if (rf & 1) {
51
- i0.ɵɵelement(0, "mj-single-user", 5);
107
+ function SettingsComponent_Conditional_12_Conditional_1_Case_8_Template(rf, ctx) { if (rf & 1) {
108
+ i0.ɵɵelementStart(0, "div", 28)(1, "h2", 37);
109
+ i0.ɵɵtext(2, "User Management");
110
+ i0.ɵɵelementEnd();
111
+ i0.ɵɵelementStart(3, "p", 43);
112
+ i0.ɵɵtext(4, "Manage user accounts, roles, and permissions");
113
+ i0.ɵɵelementEnd();
114
+ i0.ɵɵelement(5, "mj-user-management");
115
+ i0.ɵɵelementEnd();
116
+ } }
117
+ function SettingsComponent_Conditional_12_Conditional_1_Case_9_Template(rf, ctx) { if (rf & 1) {
118
+ i0.ɵɵelementStart(0, "div", 29)(1, "h2", 37);
119
+ i0.ɵɵtext(2, "Role Management");
120
+ i0.ɵɵelementEnd();
121
+ i0.ɵɵelementStart(3, "p", 43);
122
+ i0.ɵɵtext(4, "Define and manage security roles.");
123
+ i0.ɵɵelementEnd();
124
+ i0.ɵɵelement(5, "mj-role-management");
125
+ i0.ɵɵelementEnd();
126
+ } }
127
+ function SettingsComponent_Conditional_12_Conditional_1_Case_10_Template(rf, ctx) { if (rf & 1) {
128
+ i0.ɵɵelementStart(0, "div", 30);
129
+ i0.ɵɵelement(1, "mj-application-management");
130
+ i0.ɵɵelementEnd();
131
+ } }
132
+ function SettingsComponent_Conditional_12_Conditional_1_Case_11_Template(rf, ctx) { if (rf & 1) {
133
+ i0.ɵɵelementStart(0, "div", 31);
134
+ i0.ɵɵelement(1, "mj-entity-permissions");
135
+ i0.ɵɵelementEnd();
136
+ } }
137
+ function SettingsComponent_Conditional_12_Conditional_1_Case_12_Case_18_Template(rf, ctx) { if (rf & 1) {
138
+ i0.ɵɵelement(0, "mj-sql-logging");
139
+ } }
140
+ function SettingsComponent_Conditional_12_Conditional_1_Case_12_Case_19_Template(rf, ctx) { if (rf & 1) {
141
+ i0.ɵɵelementStart(0, "div", 52)(1, "h3");
142
+ i0.ɵɵtext(2, "Performance Settings");
143
+ i0.ɵɵelementEnd();
144
+ i0.ɵɵelementStart(3, "p");
145
+ i0.ɵɵtext(4, "Performance monitoring and optimization tools coming soon.");
146
+ i0.ɵɵelementEnd()();
147
+ } }
148
+ function SettingsComponent_Conditional_12_Conditional_1_Case_12_Case_20_Template(rf, ctx) { if (rf & 1) {
149
+ i0.ɵɵelementStart(0, "div", 53)(1, "h3");
150
+ i0.ɵɵtext(2, "Developer Tools");
151
+ i0.ɵɵelementEnd();
152
+ i0.ɵɵelementStart(3, "p");
153
+ i0.ɵɵtext(4, "Advanced developer options coming soon.");
154
+ i0.ɵɵelementEnd()();
155
+ } }
156
+ function SettingsComponent_Conditional_12_Conditional_1_Case_12_Template(rf, ctx) { if (rf & 1) {
157
+ const _r6 = i0.ɵɵgetCurrentView();
158
+ i0.ɵɵelementStart(0, "div", 32)(1, "h2", 37);
159
+ i0.ɵɵtext(2, "Advanced Settings");
160
+ i0.ɵɵelementEnd();
161
+ i0.ɵɵelementStart(3, "div", 44);
162
+ i0.ɵɵelement(4, "i", 45);
163
+ i0.ɵɵelementStart(5, "span");
164
+ i0.ɵɵtext(6, "Beta features - Use with caution");
165
+ i0.ɵɵelementEnd()();
166
+ i0.ɵɵelementStart(7, "div", 46)(8, "button", 47);
167
+ i0.ɵɵlistener("click", function SettingsComponent_Conditional_12_Conditional_1_Case_12_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.setAdvancedTab("sql-logging")); });
168
+ i0.ɵɵelement(9, "i", 48);
169
+ i0.ɵɵtext(10, " SQL Logging ");
170
+ i0.ɵɵelementEnd();
171
+ i0.ɵɵelementStart(11, "button", 47);
172
+ i0.ɵɵlistener("click", function SettingsComponent_Conditional_12_Conditional_1_Case_12_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.setAdvancedTab("performance")); });
173
+ i0.ɵɵelement(12, "i", 49);
174
+ i0.ɵɵtext(13, " Performance ");
175
+ i0.ɵɵelementEnd();
176
+ i0.ɵɵelementStart(14, "button", 47);
177
+ i0.ɵɵlistener("click", function SettingsComponent_Conditional_12_Conditional_1_Case_12_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.setAdvancedTab("developer")); });
178
+ i0.ɵɵelement(15, "i", 50);
179
+ i0.ɵɵtext(16, " Developer Tools ");
180
+ i0.ɵɵelementEnd()();
181
+ i0.ɵɵelementStart(17, "div", 51);
182
+ i0.ɵɵtemplate(18, SettingsComponent_Conditional_12_Conditional_1_Case_12_Case_18_Template, 1, 0, "mj-sql-logging")(19, SettingsComponent_Conditional_12_Conditional_1_Case_12_Case_19_Template, 5, 0, "div", 52)(20, SettingsComponent_Conditional_12_Conditional_1_Case_12_Case_20_Template, 5, 0, "div", 53);
183
+ i0.ɵɵelementEnd()();
52
184
  } if (rf & 2) {
53
- const ctx_r2 = i0.ɵɵnextContext();
54
- i0.ɵɵproperty("UserID", ctx_r2.selectedUserID);
185
+ let tmp_6_0;
186
+ const ctx_r1 = i0.ɵɵnextContext(3);
187
+ i0.ɵɵadvance(8);
188
+ i0.ɵɵclassProp("active", ctx_r1.advancedActiveTab === "sql-logging");
189
+ i0.ɵɵadvance(3);
190
+ i0.ɵɵclassProp("active", ctx_r1.advancedActiveTab === "performance");
191
+ i0.ɵɵadvance(3);
192
+ i0.ɵɵclassProp("active", ctx_r1.advancedActiveTab === "developer");
193
+ i0.ɵɵadvance(4);
194
+ i0.ɵɵconditional((tmp_6_0 = ctx_r1.advancedActiveTab) === "sql-logging" ? 18 : tmp_6_0 === "performance" ? 19 : tmp_6_0 === "developer" ? 20 : -1);
55
195
  } }
56
- function SettingsComponent_Case_7_Template(rf, ctx) { if (rf & 1) {
57
- const _r5 = i0.ɵɵgetCurrentView();
58
- i0.ɵɵelementStart(0, "mj-simple-record-list", 12);
59
- i0.ɵɵlistener("RecordSelected", function SettingsComponent_Case_7_Template_mj_simple_record_list_RecordSelected_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectRole($event)); });
196
+ function SettingsComponent_Conditional_12_Conditional_1_Template(rf, ctx) { if (rf & 1) {
197
+ i0.ɵɵelementStart(0, "div", 20)(1, "nav", 22)(2, "ul", 23);
198
+ i0.ɵɵrepeaterCreate(3, SettingsComponent_Conditional_12_Conditional_1_For_4_Template, 5, 6, "li", 24, _forTrack0);
199
+ i0.ɵɵelementEnd()();
200
+ i0.ɵɵelementStart(5, "div", 25)(6, "div", 26);
201
+ i0.ɵɵtemplate(7, SettingsComponent_Conditional_12_Conditional_1_Case_7_Template, 16, 3, "div", 27)(8, SettingsComponent_Conditional_12_Conditional_1_Case_8_Template, 6, 0, "div", 28)(9, SettingsComponent_Conditional_12_Conditional_1_Case_9_Template, 6, 0, "div", 29)(10, SettingsComponent_Conditional_12_Conditional_1_Case_10_Template, 2, 0, "div", 30)(11, SettingsComponent_Conditional_12_Conditional_1_Case_11_Template, 2, 0, "div", 31)(12, SettingsComponent_Conditional_12_Conditional_1_Case_12_Template, 21, 7, "div", 32);
202
+ i0.ɵɵelementEnd()()();
203
+ } if (rf & 2) {
204
+ let tmp_3_0;
205
+ const ctx_r1 = i0.ɵɵnextContext(2);
206
+ i0.ɵɵadvance(3);
207
+ i0.ɵɵrepeater(ctx_r1.tabs);
208
+ i0.ɵɵadvance(4);
209
+ i0.ɵɵconditional((tmp_3_0 = ctx_r1.activeTab) === "general" ? 7 : tmp_3_0 === "users" ? 8 : tmp_3_0 === "roles" ? 9 : tmp_3_0 === "applications" ? 10 : tmp_3_0 === "permissions" ? 11 : tmp_3_0 === "advanced" ? 12 : -1);
210
+ } }
211
+ function SettingsComponent_Conditional_12_Conditional_2_Case_2_Template(rf, ctx) { if (rf & 1) {
212
+ i0.ɵɵelementStart(0, "div", 27)(1, "h2", 37);
213
+ i0.ɵɵtext(2, "General Settings");
214
+ i0.ɵɵelementEnd()();
215
+ } }
216
+ function SettingsComponent_Conditional_12_Conditional_2_Case_3_Template(rf, ctx) { if (rf & 1) {
217
+ i0.ɵɵelementStart(0, "div", 28)(1, "h2", 37);
218
+ i0.ɵɵtext(2, "User Management");
219
+ i0.ɵɵelementEnd();
220
+ i0.ɵɵelementStart(3, "p", 43);
221
+ i0.ɵɵtext(4, "Manage user accounts, roles, and permissions");
222
+ i0.ɵɵelementEnd();
223
+ i0.ɵɵelement(5, "mj-user-management");
224
+ i0.ɵɵelementEnd();
225
+ } }
226
+ function SettingsComponent_Conditional_12_Conditional_2_For_7_Conditional_2_Template(rf, ctx) { if (rf & 1) {
227
+ i0.ɵɵelementStart(0, "span", 62);
228
+ i0.ɵɵtext(1);
60
229
  i0.ɵɵelementEnd();
61
230
  } if (rf & 2) {
62
- i0.ɵɵproperty("Columns", i0.ɵɵpureFunction0(1, _c1));
231
+ const tab_r8 = i0.ɵɵnextContext().$implicit;
232
+ i0.ɵɵclassMap("badge-" + (tab_r8.badgeColor || "primary"));
233
+ i0.ɵɵadvance();
234
+ i0.ɵɵtextInterpolate1(" ", tab_r8.badgeCount, " ");
63
235
  } }
64
- function SettingsComponent_Case_8_Template(rf, ctx) { if (rf & 1) {
65
- i0.ɵɵelement(0, "mj-single-role", 7);
236
+ function SettingsComponent_Conditional_12_Conditional_2_For_7_Template(rf, ctx) { if (rf & 1) {
237
+ const _r7 = i0.ɵɵgetCurrentView();
238
+ i0.ɵɵelementStart(0, "button", 59);
239
+ i0.ɵɵlistener("click", function SettingsComponent_Conditional_12_Conditional_2_For_7_Template_button_click_0_listener() { const tab_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onTabChange(tab_r8.id)); });
240
+ i0.ɵɵelement(1, "i");
241
+ i0.ɵɵtemplate(2, SettingsComponent_Conditional_12_Conditional_2_For_7_Conditional_2_Template, 2, 3, "span", 60);
242
+ i0.ɵɵelementStart(3, "span", 61);
243
+ i0.ɵɵtext(4);
244
+ i0.ɵɵelementEnd()();
66
245
  } if (rf & 2) {
67
- const ctx_r2 = i0.ɵɵnextContext();
68
- i0.ɵɵproperty("RoleID", ctx_r2.selectedRoleID);
246
+ const tab_r8 = ctx.$implicit;
247
+ const ctx_r1 = i0.ɵɵnextContext(3);
248
+ i0.ɵɵclassProp("active", ctx_r1.activeTab === tab_r8.id);
249
+ i0.ɵɵadvance();
250
+ i0.ɵɵclassMap(tab_r8.icon);
251
+ i0.ɵɵadvance();
252
+ i0.ɵɵconditional(tab_r8.badgeCount && tab_r8.badgeCount > 0 ? 2 : -1);
253
+ i0.ɵɵadvance(2);
254
+ i0.ɵɵtextInterpolate(tab_r8.label);
69
255
  } }
70
- function SettingsComponent_Case_9_Template(rf, ctx) { if (rf & 1) {
71
- const _r6 = i0.ɵɵgetCurrentView();
72
- i0.ɵɵelementStart(0, "mj-simple-record-list", 13);
73
- i0.ɵɵlistener("RecordSelected", function SettingsComponent_Case_9_Template_mj_simple_record_list_RecordSelected_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectApplication($event)); });
256
+ function SettingsComponent_Conditional_12_Conditional_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
257
+ i0.ɵɵelementStart(0, "button", 58);
258
+ i0.ɵɵelement(1, "i", 63);
259
+ i0.ɵɵelementStart(2, "span", 61);
260
+ i0.ɵɵtext(3, "More");
261
+ i0.ɵɵelementEnd()();
262
+ } }
263
+ function SettingsComponent_Conditional_12_Conditional_2_Template(rf, ctx) { if (rf & 1) {
264
+ i0.ɵɵelementStart(0, "div", 21)(1, "div", 54);
265
+ i0.ɵɵtemplate(2, SettingsComponent_Conditional_12_Conditional_2_Case_2_Template, 3, 0, "div", 27)(3, SettingsComponent_Conditional_12_Conditional_2_Case_3_Template, 6, 0, "div", 28);
74
266
  i0.ɵɵelementEnd();
267
+ i0.ɵɵelementStart(4, "nav", 55)(5, "div", 56);
268
+ i0.ɵɵrepeaterCreate(6, SettingsComponent_Conditional_12_Conditional_2_For_7_Template, 5, 6, "button", 57, _forTrack0);
269
+ i0.ɵɵtemplate(8, SettingsComponent_Conditional_12_Conditional_2_Conditional_8_Template, 4, 0, "button", 58);
270
+ i0.ɵɵelementEnd()()();
75
271
  } if (rf & 2) {
76
- i0.ɵɵproperty("Columns", i0.ɵɵpureFunction0(1, _c1));
272
+ let tmp_2_0;
273
+ const ctx_r1 = i0.ɵɵnextContext(2);
274
+ i0.ɵɵadvance(2);
275
+ i0.ɵɵconditional((tmp_2_0 = ctx_r1.activeTab) === "general" ? 2 : tmp_2_0 === "users" ? 3 : -1);
276
+ i0.ɵɵadvance(4);
277
+ i0.ɵɵrepeater(ctx_r1.tabs.slice(0, 5));
278
+ i0.ɵɵadvance(2);
279
+ i0.ɵɵconditional(ctx_r1.tabs.length > 5 ? 8 : -1);
77
280
  } }
78
- function SettingsComponent_Case_10_Template(rf, ctx) { if (rf & 1) {
79
- i0.ɵɵelement(0, "mj-single-application", 9);
281
+ function SettingsComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
282
+ i0.ɵɵelementStart(0, "div", 10);
283
+ i0.ɵɵtemplate(1, SettingsComponent_Conditional_12_Conditional_1_Template, 13, 1, "div", 20)(2, SettingsComponent_Conditional_12_Conditional_2_Template, 9, 2, "div", 21);
284
+ i0.ɵɵelementEnd();
80
285
  } if (rf & 2) {
81
- const ctx_r2 = i0.ɵɵnextContext();
82
- i0.ɵɵproperty("ApplicationID", ctx_r2.selectedApplicationID);
286
+ const ctx_r1 = i0.ɵɵnextContext();
287
+ i0.ɵɵadvance();
288
+ i0.ɵɵconditional(!ctx_r1.isMobile ? 1 : -1);
289
+ i0.ɵɵadvance();
290
+ i0.ɵɵconditional(ctx_r1.isMobile ? 2 : -1);
83
291
  } }
84
- export var SettingsItem;
85
- (function (SettingsItem) {
86
- SettingsItem["EntityPermissions"] = "EntityPermissions";
87
- SettingsItem["Users"] = "Users";
88
- SettingsItem["User"] = "User";
89
- SettingsItem["Roles"] = "Roles";
90
- SettingsItem["Role"] = "Role";
91
- SettingsItem["Applications"] = "Applications";
92
- SettingsItem["Application"] = "Application";
93
- })(SettingsItem || (SettingsItem = {}));
94
292
  let SettingsComponent = class SettingsComponent extends BaseNavigationComponent {
95
- router;
96
- activatedRoute;
97
- currentItem = SettingsItem.Users;
98
- baseRoute = '/settings';
99
- selectedRoleID = '';
100
- selectedUserID = "";
101
- selectedApplicationName = '';
102
- selectedApplicationID = '';
103
- options = [
104
- { label: 'Users', value: SettingsItem.Users },
105
- { label: 'Roles', value: SettingsItem.Roles },
106
- { label: 'Applications', value: SettingsItem.Applications },
107
- { label: 'Entity Permissions', value: SettingsItem.EntityPermissions }
293
+ stateChange = new EventEmitter();
294
+ // State management
295
+ activeTab = 'general';
296
+ advancedActiveTab = 'sql-logging';
297
+ searchTerm$ = new BehaviorSubject('');
298
+ isLoading = false;
299
+ error = null;
300
+ // Tab configuration
301
+ tabs = [
302
+ {
303
+ id: 'general',
304
+ label: 'General',
305
+ icon: 'fa-solid fa-cog',
306
+ badgeCount: 0
307
+ },
308
+ {
309
+ id: 'users',
310
+ label: 'Users',
311
+ icon: 'fa-solid fa-users',
312
+ badgeCount: 0
313
+ },
314
+ {
315
+ id: 'roles',
316
+ label: 'Roles',
317
+ icon: 'fa-solid fa-shield-halved',
318
+ badgeCount: 0
319
+ },
320
+ {
321
+ id: 'applications',
322
+ label: 'Applications',
323
+ icon: 'fa-solid fa-grid-2',
324
+ badgeCount: 0
325
+ },
326
+ {
327
+ id: 'permissions',
328
+ label: 'Permissions',
329
+ icon: 'fa-solid fa-lock',
330
+ badgeCount: 0
331
+ },
332
+ {
333
+ id: 'advanced',
334
+ label: 'Advanced',
335
+ icon: 'fa-solid fa-flask',
336
+ badgeCount: 1,
337
+ badgeColor: 'warning'
338
+ }
108
339
  ];
109
- selectItem(item, changeRoute = true) {
110
- if (typeof item === 'string')
111
- this.currentItem = SettingsItem[item];
112
- else
113
- this.currentItem = item;
114
- if (changeRoute)
115
- this.changeRoute(item.toLowerCase());
116
- }
117
- changeRoute(subPath) {
118
- // Constructs a navigation path relative to the /settings base route
119
- this.router.navigate([this.baseRoute, subPath]);
120
- }
121
- constructor(router, activatedRoute) {
340
+ // Section expansion state
341
+ expandedSections = ['profile', 'preferences'];
342
+ // Mobile state
343
+ isMobile = window.innerWidth < 768;
344
+ destroy$ = new Subject();
345
+ constructor() {
346
+ // Listen for window resize
122
347
  super();
123
- this.router = router;
124
- this.activatedRoute = activatedRoute;
348
+ window.addEventListener('resize', this.handleResize.bind(this));
125
349
  }
126
350
  ngOnInit() {
127
- // manually update the first time
128
- this.updateComponentStateBasedOnPath();
129
- // Listen to changes in the route
130
- this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
131
- this.updateComponentStateBasedOnPath();
351
+ this.setupSearchFilter();
352
+ this.loadInitialData();
353
+ }
354
+ ngOnDestroy() {
355
+ this.destroy$.next();
356
+ this.destroy$.complete();
357
+ window.removeEventListener('resize', this.handleResize.bind(this));
358
+ }
359
+ setupSearchFilter() {
360
+ this.searchTerm$
361
+ .pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.destroy$))
362
+ .subscribe(term => {
363
+ this.filterContent(term);
364
+ this.emitStateChange();
132
365
  });
133
366
  }
134
- updateComponentStateBasedOnPath() {
135
- // On each navigation end, access the current URL from window.location
136
- const fullPath = window.location.pathname + window.location.search;
137
- // Split the fullPath into segments and query string as needed
138
- const [path, queryString] = fullPath.split('?');
139
- const segments = path.split('/').filter(segment => segment.length > 0);
140
- const firstSegment = segments.length > 1 ? segments[1] : '';
141
- switch (firstSegment.trim().toLowerCase()) {
142
- case 'entitypermissions':
143
- this.selectItem(SettingsItem.EntityPermissions, false);
144
- break;
145
- case 'applications':
146
- this.selectItem(SettingsItem.Applications, false);
147
- break;
148
- case 'application':
149
- this.selectedApplicationName = segments.length > 2 ? segments[2] : '';
150
- const md = new Metadata();
151
- this.selectedApplicationID = md.Applications.find(a => a.Name === this.selectedApplicationName)?.ID ?? '';
152
- this.selectItem(SettingsItem.Application, false);
153
- break;
154
- case 'users':
155
- this.selectItem(SettingsItem.Users, false);
156
- break;
157
- case 'user':
158
- this.selectedUserID = segments.length > 2 ? segments[2] : "";
159
- this.selectItem(SettingsItem.User, false);
160
- break;
161
- case 'roles':
162
- this.selectItem(SettingsItem.Roles, false);
163
- break;
164
- case 'role':
165
- this.selectedRoleID = segments.length > 2 ? segments[2] : '';
166
- this.selectItem(SettingsItem.Role, false);
167
- break;
168
- default:
169
- break;
367
+ async loadInitialData() {
368
+ try {
369
+ this.isLoading = true;
370
+ // TODO: Load user settings, roles, applications data
371
+ await this.simulateDataLoad();
372
+ this.isLoading = false;
373
+ }
374
+ catch (error) {
375
+ this.error = 'Failed to load settings data';
376
+ this.isLoading = false;
170
377
  }
171
378
  }
172
- selectApplication(a) {
173
- this.selectRoute('/settings/application', a.Name);
379
+ async simulateDataLoad() {
380
+ return new Promise(resolve => setTimeout(resolve, 500));
174
381
  }
175
- selectRole(r) {
176
- this.selectRoute('/settings/role', r.ID);
382
+ onTabChange(tabId) {
383
+ this.activeTab = tabId;
384
+ this.emitStateChange();
177
385
  }
178
- selectUser(u) {
179
- this.selectRoute('/settings/user', u.ID);
386
+ onSearchChange(event) {
387
+ const term = event.target.value;
388
+ this.searchTerm$.next(term);
180
389
  }
181
- /**
182
- * Function that returns the appropriate Font Awesome icon for the user toggle button
183
- * based on the user's IsActive status
184
- */
185
- getUserToggleIcon(record) {
186
- const user = record;
187
- return user.IsActive ? 'fa-user-lock' : 'fa-user-check';
390
+ toggleSection(sectionId) {
391
+ const index = this.expandedSections.indexOf(sectionId);
392
+ if (index === -1) {
393
+ this.expandedSections.push(sectionId);
394
+ }
395
+ else {
396
+ this.expandedSections.splice(index, 1);
397
+ }
398
+ this.emitStateChange();
188
399
  }
189
- /**
190
- * Function that returns the appropriate tooltip text for the user toggle button
191
- * based on the user's IsActive status
192
- */
193
- getUserToggleTooltip(record) {
194
- const user = record;
195
- return user.IsActive ? 'Deactivate user' : 'Activate user';
400
+ isSectionExpanded(sectionId) {
401
+ return this.expandedSections.includes(sectionId);
196
402
  }
197
- /**
198
- * Handles toggling a user's activation status when the custom action is confirmed
199
- */
200
- async toggleUserActivation(record) {
201
- try {
202
- const user = record;
203
- // Get current status
204
- const currentlyActive = user.IsActive;
205
- const userName = user.Name;
206
- // Toggle the IsActive flag
207
- user.IsActive = !currentlyActive;
208
- if (await user.Save()) {
209
- MJNotificationService.Instance.CreateSimpleNotification(`User ${userName} has been ${currentlyActive ? 'deactivated' : 'activated'} successfully.`, 'success', 3000);
210
- // Refresh the user list
211
- this.selectItem(SettingsItem.Users);
212
- }
213
- else {
214
- MJNotificationService.Instance.CreateSimpleNotification(`Error ${currentlyActive ? 'deactivating' : 'activating'} user ${userName}`, 'error', 5000);
215
- }
403
+ setAdvancedTab(tabId) {
404
+ this.advancedActiveTab = tabId;
405
+ }
406
+ filterContent(term) {
407
+ // TODO: Implement content filtering based on search term
408
+ console.log('Filtering content with term:', term);
409
+ }
410
+ handleResize() {
411
+ this.isMobile = window.innerWidth < 768;
412
+ }
413
+ emitStateChange() {
414
+ const state = {
415
+ activeTab: this.activeTab,
416
+ searchTerm: this.searchTerm$.value,
417
+ expandedSections: [...this.expandedSections]
418
+ };
419
+ this.stateChange.emit(state);
420
+ }
421
+ loadUserState(state) {
422
+ if (state.activeTab) {
423
+ this.activeTab = state.activeTab;
216
424
  }
217
- catch (error) {
218
- console.error('Error toggling user activation:', error);
219
- MJNotificationService.Instance.CreateSimpleNotification('An error occurred while toggling user activation.', 'error', 5000);
425
+ if (state.searchTerm !== undefined) {
426
+ this.searchTerm$.next(state.searchTerm);
427
+ }
428
+ if (state.expandedSections) {
429
+ this.expandedSections = [...state.expandedSections];
220
430
  }
221
431
  }
222
- selectRoute(route, value) {
223
- this.router.navigate([route, value]);
432
+ getTabIcon(tab) {
433
+ return tab.icon;
224
434
  }
225
- leftNavItemSelected(option) {
226
- // if the currentItem matches it directly or if adding an S to the current item matches it, then return true
227
- // for example for Application/Applications we want to match so the left nav item is highlighted
228
- return option.value === this.currentItem || option.value === this.currentItem + 's';
435
+ getTabClass(tab) {
436
+ const classes = ['settings-tab'];
437
+ if (this.activeTab === tab.id) {
438
+ classes.push('active');
439
+ }
440
+ if (tab.badgeCount && tab.badgeCount > 0) {
441
+ classes.push('has-badge');
442
+ }
443
+ return classes.join(' ');
229
444
  }
230
- static ɵfac = function SettingsComponent_Factory(t) { return new (t || SettingsComponent)(i0.ɵɵdirectiveInject(i1.Router), i0.ɵɵdirectiveInject(i1.ActivatedRoute)); };
231
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsComponent, selectors: [["mj-settings"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 11, vars: 6, consts: [["mjFillContainer", "", 1, "container", 3, "bottomMargin", "rightMargin"], ["mjFillContainer", "", 1, "options-container", 3, "fillWidth"], ["class", "option-item", 3, "selected", "click", 4, "ngFor", "ngForOf"], ["mjFillContainer", "", 1, "display-container", 3, "fillWidth"], ["EntityName", "Users", "SortBy", "Name", 3, "Columns", "AllowDelete", "AllowCustomAction", "CustomActionIconFunction", "CustomActionTooltipFunction", "CustomActionDialogTitle", "CustomActionDialogMessage", "CustomActionDialogInfo"], [3, "UserID"], ["EntityName", "Roles", "SortBy", "Name", 3, "Columns"], ["mjFillContainer", "", 3, "RoleID"], ["EntityName", "Applications", "SortBy", "Name", 3, "Columns"], [3, "ApplicationID"], [1, "option-item", 3, "click"], ["EntityName", "Users", "SortBy", "Name", 3, "RecordSelected", "CustomActionConfirmed", "Columns", "AllowDelete", "AllowCustomAction", "CustomActionIconFunction", "CustomActionTooltipFunction", "CustomActionDialogTitle", "CustomActionDialogMessage", "CustomActionDialogInfo"], ["EntityName", "Roles", "SortBy", "Name", 3, "RecordSelected", "Columns"], ["EntityName", "Applications", "SortBy", "Name", 3, "RecordSelected", "Columns"]], template: function SettingsComponent_Template(rf, ctx) { if (rf & 1) {
232
- i0.ɵɵelementStart(0, "div", 0)(1, "div", 1);
233
- i0.ɵɵtemplate(2, SettingsComponent_div_2_Template, 2, 3, "div", 2);
234
- i0.ɵɵelementEnd();
235
- i0.ɵɵelementStart(3, "div", 3);
236
- i0.ɵɵtemplate(4, SettingsComponent_Case_4_Template, 1, 0, "mj-entity-permissions-selector-with-grid")(5, SettingsComponent_Case_5_Template, 1, 9, "mj-simple-record-list", 4)(6, SettingsComponent_Case_6_Template, 1, 1, "mj-single-user", 5)(7, SettingsComponent_Case_7_Template, 1, 2, "mj-simple-record-list", 6)(8, SettingsComponent_Case_8_Template, 1, 1, "mj-single-role", 7)(9, SettingsComponent_Case_9_Template, 1, 2, "mj-simple-record-list", 8)(10, SettingsComponent_Case_10_Template, 1, 1, "mj-single-application", 9);
445
+ static ɵfac = function SettingsComponent_Factory(t) { return new (t || SettingsComponent)(); };
446
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsComponent, selectors: [["mj-settings"]], outputs: { stateChange: "stateChange" }, standalone: true, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵStandaloneFeature], decls: 13, vars: 4, consts: [[1, "settings-container"], [1, "settings-header"], [1, "header-content"], [1, "header-title"], [1, "fa-solid", "fa-cog", "header-icon"], [1, "header-search"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", "placeholder", "Search settings...", 1, "search-input", 3, "input", "value"], [1, "loading-container"], [1, "error-container"], [1, "settings-content"], [1, "loading-content"], [1, "loading-spinner"], [1, "spinner-ring"], [1, "loading-text"], [1, "error-content"], [1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], [1, "retry-button", 3, "click"], [1, "fa-solid", "fa-refresh"], [1, "desktop-layout", 2, "display", "flex"], [1, "mobile-layout"], [1, "side-navigation"], [1, "nav-list"], [1, "nav-item", 3, "active"], [1, "content-area"], [1, "tab-content"], [1, "general-settings"], [1, "users-settings"], [1, "roles-settings"], [1, "applications-settings"], [1, "permissions-settings"], [1, "advanced-settings"], [1, "nav-item", 3, "click"], [1, "nav-label"], [1, "nav-badge", 3, "class"], [1, "nav-badge"], [1, "section-title"], [1, "settings-grid"], ["title", "Profile Information", "icon", "fa-solid fa-user", 3, "toggle", "expanded"], [1, "card-content"], ["title", "Preferences", "icon", "fa-solid fa-sliders", 3, "toggle", "expanded"], ["title", "Notifications", "icon", "fa-solid fa-bell", 3, "toggle", "expanded"], [1, "section-description"], [1, "beta-warning"], [1, "fa-solid", "fa-flask"], [1, "advanced-tabs"], [1, "tab-btn", 3, "click"], [1, "fa-solid", "fa-database"], [1, "fa-solid", "fa-gauge-high"], [1, "fa-solid", "fa-code"], [1, "advanced-tab-content"], [1, "performance-settings"], [1, "developer-settings"], [1, "mobile-content"], [1, "mobile-navigation"], [1, "nav-tabs"], [1, "nav-tab", 3, "active"], [1, "nav-tab", "more-tab"], [1, "nav-tab", 3, "click"], [1, "tab-badge", 3, "class"], [1, "tab-label"], [1, "tab-badge"], [1, "fa-solid", "fa-ellipsis"]], template: function SettingsComponent_Template(rf, ctx) { if (rf & 1) {
447
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3);
448
+ i0.ɵɵelement(4, "i", 4);
449
+ i0.ɵɵelementStart(5, "h1");
450
+ i0.ɵɵtext(6, "Settings");
237
451
  i0.ɵɵelementEnd()();
452
+ i0.ɵɵelementStart(7, "div", 5);
453
+ i0.ɵɵelement(8, "i", 6);
454
+ i0.ɵɵelementStart(9, "input", 7);
455
+ i0.ɵɵlistener("input", function SettingsComponent_Template_input_input_9_listener($event) { return ctx.onSearchChange($event); });
456
+ i0.ɵɵelementEnd()()()();
457
+ i0.ɵɵtemplate(10, SettingsComponent_Conditional_10_Template, 8, 0, "div", 8)(11, SettingsComponent_Conditional_11_Template, 8, 1, "div", 9)(12, SettingsComponent_Conditional_12_Template, 3, 2, "div", 10);
458
+ i0.ɵɵelementEnd();
238
459
  } if (rf & 2) {
239
- let tmp_5_0;
240
- i0.ɵɵproperty("bottomMargin", 5)("rightMargin", 0);
241
- i0.ɵɵadvance();
242
- i0.ɵɵproperty("fillWidth", false);
460
+ i0.ɵɵadvance(9);
461
+ i0.ɵɵproperty("value", ctx.searchTerm$.value);
243
462
  i0.ɵɵadvance();
244
- i0.ɵɵproperty("ngForOf", ctx.options);
463
+ i0.ɵɵconditional(ctx.isLoading ? 10 : -1);
245
464
  i0.ɵɵadvance();
246
- i0.ɵɵproperty("fillWidth", false);
465
+ i0.ɵɵconditional(ctx.error && !ctx.isLoading ? 11 : -1);
247
466
  i0.ɵɵadvance();
248
- i0.ɵɵconditional((tmp_5_0 = ctx.currentItem) === "EntityPermissions" ? 4 : tmp_5_0 === "Users" ? 5 : tmp_5_0 === "User" ? 6 : tmp_5_0 === "Roles" ? 7 : tmp_5_0 === "Role" ? 8 : tmp_5_0 === "Applications" ? 9 : tmp_5_0 === "Application" ? 10 : -1);
249
- } }, dependencies: [i2.NgForOf, i3.FillContainer, i4.EntityPermissionsSelectorWithGridComponent, i5.SimpleRecordListComponent, i6.SingleRoleComponent, i7.SingleUserComponent, i8.SingleApplicationComponent], styles: [".container[_ngcontent-%COMP%] {\n display: block;\n width: 100%;\n overflow: hidden; \n}\n\n.options-container[_ngcontent-%COMP%] {\n float: left; \n\n width: 150px; \n\n flex: 0 0 150px;\n padding: 10px;\n border-right: solid 1px lightgray;\n box-sizing: border-box; \n\n}\n\n.option-item[_ngcontent-%COMP%] {\n cursor: pointer;\n margin-bottom: 10px; \n\n padding: 5px 10px; \n\n border-radius: 4px; \n\n}\n\n.display-container[_ngcontent-%COMP%] {\n display: block; \n\n margin-left: 160px; \n\n padding: 10px;\n box-sizing: border-box; \n\n}\n\n.selected[_ngcontent-%COMP%] {\n background-color: #007bff; \n\n color: white; \n\n padding: 5px 10px; \n\n border-radius: 4px; \n\n}"] });
467
+ i0.ɵɵconditional(!ctx.isLoading && !ctx.error ? 12 : -1);
468
+ } }, dependencies: [CommonModule,
469
+ SharedSettingsModule, i1.SettingsCardComponent, SqlLoggingComponent,
470
+ UserManagementComponent,
471
+ RoleManagementComponent,
472
+ ApplicationManagementComponent,
473
+ EntityPermissionsComponent], styles: ["@import '../shared/styles/variables';\n@import '../shared/styles/mixins';\n\n.settings-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n background-color: #f5f7fa;\n overflow: hidden;\n position: relative;\n}\n\n//[_ngcontent-%COMP%] Header[_ngcontent-%COMP%] Section\n.settings-header[_ngcontent-%COMP%] {\n background-color: #ffffff;\n border-bottom: 1px solid #e5e7eb;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n z-index: 10;\n}\n\n.header-content[_ngcontent-%COMP%] {\n padding: 1.5rem 2rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 2rem;\n\n @media (max-width: 768px) {\n padding: 1rem;\n flex-direction: column;\n gap: 1rem;\n }\n}\n\n.header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n\n .header-icon {\n font-size: 1.75rem;\n color: #2196f3;\n }\n\n h1 {\n margin: 0;\n font-size: 1.75rem;\n font-weight: 600;\n color: #1f2937;\n }\n}\n\n.header-search[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n max-width: 400px;\n\n .search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: #6b7280;\n font-size: 1rem;\n }\n\n .search-input {\n width: 100%;\n padding: 0.75rem 1rem 0.75rem 2.75rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n transition: all 0.2s;\n background-color: #f9fafb;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n background-color: #ffffff;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n\n &::placeholder {\n color: #9ca3af;\n }\n }\n}\n\n//[_ngcontent-%COMP%] Loading[_ngcontent-%COMP%] State\n.loading-container[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n}\n\n.loading-content[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n position: relative;\n width: 60px;\n height: 60px;\n margin: 0 auto 1rem;\n\n .spinner-ring {\n position: absolute;\n width: 100%;\n height: 100%;\n border: 3px solid transparent;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_spin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n\n &:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n }\n\n &:nth-child(2) {\n border-color: transparent #4caf50 transparent transparent;\n animation-delay: -0.3s;\n }\n\n &:nth-child(3) {\n border-color: transparent transparent #ff9800 transparent;\n animation-delay: -0.15s;\n }\n }\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n.loading-text[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n//[_ngcontent-%COMP%] Error[_ngcontent-%COMP%] State\n.error-container[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n}\n\n.error-content[_ngcontent-%COMP%] {\n text-align: center;\n max-width: 400px;\n\n .error-icon {\n font-size: 3rem;\n color: #f44336;\n margin-bottom: 1rem;\n }\n\n .error-message {\n color: #374151;\n margin-bottom: 1.5rem;\n font-size: 1rem;\n }\n\n .retry-button {\n @include button-base;\n background-color: #2196f3;\n color: white;\n padding: 0.75rem 1.5rem;\n font-size: 0.95rem;\n border-radius: 8px;\n transition: all 0.2s;\n\n &:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n }\n\n i {\n margin-right: 0.5rem;\n }\n }\n}\n\n//[_ngcontent-%COMP%] Main[_ngcontent-%COMP%] Content\n.settings-content[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n overflow: hidden;\n flex-direction: column;\n width: 100%;\n}\n\n//[_ngcontent-%COMP%] Desktop[_ngcontent-%COMP%] Layout\n.desktop-layout[_ngcontent-%COMP%] {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n//[_ngcontent-%COMP%] More[_ngcontent-%COMP%] specific[_ngcontent-%COMP%] selector[_ngcontent-%COMP%] to[_ngcontent-%COMP%] ensure[_ngcontent-%COMP%] it[_ngcontent-%COMP%] applies\n.settings-content[_ngcontent-%COMP%] .desktop-layout[_ngcontent-%COMP%] {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n// Deep selector for Angular ViewEncapsulation\n[_nghost-%COMP%] .desktop-layout {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n.side-navigation[_ngcontent-%COMP%] {\n width: 260px;\n background-color: #ffffff;\n border-right: 1px solid #e5e7eb;\n overflow-y: auto;\n flex-shrink: 0;\n}\n\n.nav-list[_ngcontent-%COMP%] {\n list-style: none;\n margin: 0;\n padding: 1rem 0;\n}\n\n.nav-item[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n padding: 0.875rem 1.5rem;\n cursor: pointer;\n transition: all 0.2s;\n color: #4b5563;\n font-size: 0.95rem;\n\n &:hover {\n background-color: #f3f4f6;\n color: #1f2937;\n }\n\n &.active {\n background-color: #eff6ff;\n color: #2196f3;\n font-weight: 500;\n\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background-color: #2196f3;\n }\n }\n\n i {\n width: 20px;\n margin-right: 0.75rem;\n font-size: 1.1rem;\n }\n\n .nav-label {\n flex: 1;\n }\n\n .nav-badge {\n padding: 0.125rem 0.5rem;\n border-radius: 12px;\n font-size: 0.75rem;\n font-weight: 600;\n \n &.badge-primary {\n background-color: #dbeafe;\n color: #1e40af;\n }\n\n &.badge-danger {\n background-color: #fee2e2;\n color: #991b1b;\n }\n\n &.badge-warning {\n background-color: #fef3c7;\n color: #92400e;\n }\n\n &.badge-success {\n background-color: #d1fae5;\n color: #065f46;\n }\n }\n}\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 2rem;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0; // Important for proper flex sizing\n\n @media (max-width: 768px) {\n padding: 1rem;\n }\n}\n\n.tab-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n min-height: 0; // Important for proper flex sizing\n}\n\n//[_ngcontent-%COMP%] Section[_ngcontent-%COMP%] Styles\n.section-title[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.5rem 0;\n}\n\n.section-description[_ngcontent-%COMP%] {\n color: #6b7280;\n margin: 0 0 2rem 0;\n font-size: 0.95rem;\n}\n\n.settings-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));\n gap: 1.5rem;\n margin-top: 1.5rem;\n\n @media (max-width: 768px) {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n}\n\n.card-content[_ngcontent-%COMP%] {\n padding: 1rem;\n color: #4b5563;\n font-size: 0.95rem;\n\n p {\n margin: 0 0 1rem 0;\n line-height: 1.6;\n }\n}\n\n//[_ngcontent-%COMP%] Beta[_ngcontent-%COMP%] Warning\n.beta-warning[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n background-color: #fef3c7;\n color: #92400e;\n border-radius: 6px;\n font-size: 0.875rem;\n margin-bottom: 1.5rem;\n\n i {\n font-size: 1rem;\n }\n}\n\n//[_ngcontent-%COMP%] Mobile[_ngcontent-%COMP%] Layout\n.mobile-layout[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.mobile-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 1rem;\n padding-bottom: 80px; // Space for bottom nav\n}\n\n.mobile-navigation[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n background-color: #ffffff;\n border-top: 1px solid #e5e7eb;\n box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);\n z-index: 100;\n}\n\n.nav-tabs[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-around;\n align-items: center;\n padding: 0.5rem 0;\n}\n\n.nav-tab[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.25rem;\n padding: 0.5rem;\n background: none;\n border: none;\n color: #9ca3af;\n cursor: pointer;\n transition: all 0.2s;\n font-size: 0.75rem;\n min-width: 60px;\n\n &.active {\n color: #2196f3;\n\n i {\n transform: scale(1.1);\n }\n }\n\n &:active {\n transform: scale(0.95);\n }\n\n i {\n font-size: 1.25rem;\n transition: transform 0.2s;\n }\n\n .tab-badge {\n position: absolute;\n top: 0.25rem;\n right: 0.25rem;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n font-size: 0.625rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n \n &.badge-primary {\n background-color: #2196f3;\n color: white;\n }\n\n &.badge-warning {\n background-color: #ff9800;\n color: white;\n }\n }\n\n .tab-label {\n margin-top: 0.125rem;\n }\n}\n\n.more-tab[_ngcontent-%COMP%] {\n color: #6b7280;\n}\n\n//[_ngcontent-%COMP%] Advanced[_ngcontent-%COMP%] Settings[_ngcontent-%COMP%] Tabs\n.advanced-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n border-bottom: 2px solid #e5e7eb;\n margin-bottom: 2rem;\n margin-top: 1.5rem;\n\n .tab-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n background: transparent;\n border: none;\n border-bottom: 3px solid transparent;\n color: #6b7280;\n font-size: 0.95rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n position: relative;\n\n &:hover {\n color: #374151;\n background: #f9fafb;\n }\n\n &.active {\n color: #2196f3;\n border-bottom-color: #2196f3;\n background: #eff6ff;\n\n i {\n color: #2196f3;\n }\n }\n\n i {\n font-size: 1.125rem;\n }\n }\n}\n\n.advanced-tab-content[_ngcontent-%COMP%] {\n @include scrollable-content;\n background: white;\n border-radius: 12px;\n padding: 0;\n min-height: 500px;\n max-height: calc(100vh - 350px);\n}\n\n.performance-settings[_ngcontent-%COMP%], \n.developer-settings[_ngcontent-%COMP%] {\n padding: 2rem;\n \n h3 {\n margin: 0 0 1rem 0;\n color: #1f2937;\n font-size: 1.25rem;\n }\n \n p {\n color: #6b7280;\n font-size: 0.95rem;\n }\n}\n\n//[_ngcontent-%COMP%] Animations\n@keyframes[_ngcontent-%COMP%] fadeIn[_ngcontent-%COMP%] {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.general-settings[_ngcontent-%COMP%], \n.users-settings[_ngcontent-%COMP%], \n.roles-settings[_ngcontent-%COMP%], \n.applications-settings[_ngcontent-%COMP%], \n.permissions-settings[_ngcontent-%COMP%], \n.advanced-settings[_ngcontent-%COMP%] {\n animation: fadeIn 0.3s ease-out;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n min-height: 0; // Important for proper flex sizing\n overflow: hidden;\n \n // Direct child components should handle their own scrolling\n > * {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n}"] });
250
474
  };
251
475
  SettingsComponent = __decorate([
252
- RegisterClass(BaseNavigationComponent, 'Settings')
476
+ RegisterClass(BaseNavigationComponent, "Settings")
253
477
  ], SettingsComponent);
254
478
  export { SettingsComponent };
255
479
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SettingsComponent, [{
256
480
  type: Component,
257
- args: [{ selector: 'mj-settings', template: "<div class=\"container\" mjFillContainer [bottomMargin]=\"5\" [rightMargin]=\"0\">\n <!-- Options container -->\n <div class=\"options-container\" mjFillContainer [fillWidth]=\"false\">\n <div *ngFor=\"let o of options\"\n class=\"option-item\"\n [class.selected]=\"leftNavItemSelected(o)\"\n (click)=\"selectItem(o.value)\"\n >{{o.label}}</div>\n </div>\n\n <!-- Display container -->\n <div class=\"display-container\" mjFillContainer [fillWidth]=\"false\">\n <!-- <mj-join-grid\n RowsEntityName=\"Entities\"\n RowsEntityDisplayField=\"Name\"\n RowsEntityDataSource=\"FullEntity\"\n RowsExtraFilter=\"SchemaName <> '__mj' AND (Name like 'a%' or Name like 'p%')\"\n RowsOrderBy=\"Name\"\n ColumnsEntityName=\"Actions\"\n ColumnsEntityDisplayField=\"Name\"\n ColumnsEntityDataSource= \"FullEntity\"\n ColumnsMode=\"Entity\"\n ColumnsExtraFilter=\"Name like 'v%' or Name like 'd%' or Name like 'test%'\"\n ColumnsOrderBy=\"Name\"\n JoinEntityName=\"Entity Actions\"\n JoinEntityRowForeignKey=\"EntityID\"\n JoinEntityColumnForeignKey=\"ActionID\"\n CheckBoxValueMode=\"RecordExists\"\n \n style=\"height: 750px; width: 800px;\"\n >\n\n </mj-join-grid> -->\n @switch (currentItem) {\n @case ('EntityPermissions') {\n <mj-entity-permissions-selector-with-grid></mj-entity-permissions-selector-with-grid>\n }\n @case ('Users') {\n <mj-simple-record-list\n EntityName=\"Users\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Email', 'IsActive', 'Type']\" \n [AllowDelete]=\"false\"\n [AllowCustomAction]=\"true\"\n [CustomActionIconFunction]=\"getUserToggleIcon\"\n [CustomActionTooltipFunction]=\"getUserToggleTooltip\"\n [CustomActionDialogTitle]=\"'Toggle User Activation'\"\n [CustomActionDialogMessage]=\"'Are you sure you want to toggle activation for this user?'\"\n [CustomActionDialogInfo]=\"'Active users can log in to the system. Inactive users cannot log in.'\"\n (RecordSelected)=\"selectUser($event)\"\n (CustomActionConfirmed)=\"toggleUserActivation($event)\"\n ></mj-simple-record-list>\n }\n @case ('User') {\n <mj-single-user [UserID]=\"selectedUserID\"></mj-single-user>\n }\n @case ('Roles') {\n <mj-simple-record-list\n EntityName=\"Roles\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Description']\"\n (RecordSelected)=\"selectRole($event)\"\n ></mj-simple-record-list>\n }\n @case ('Role') {\n <mj-single-role [RoleID]=\"selectedRoleID\" mjFillContainer></mj-single-role>\n }\n @case ('Applications') {\n <mj-simple-record-list\n EntityName=\"Applications\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Description']\"\n (RecordSelected)=\"selectApplication($event)\"\n ></mj-simple-record-list>\n }\n @case ('Application') {\n <mj-single-application [ApplicationID]=\"selectedApplicationID\"></mj-single-application>\n }\n }\n </div>\n</div>", styles: [".container {\n display: block;\n width: 100%;\n overflow: hidden; \n}\n\n.options-container {\n float: left; /* Float to the left */\n width: 150px; /* Fixed width as specified */\n flex: 0 0 150px;\n padding: 10px;\n border-right: solid 1px lightgray;\n box-sizing: border-box; /* Ensures padding is included in the width */\n}\n\n.option-item {\n cursor: pointer;\n margin-bottom: 10px; /* Adds space between the options for better readability */\n padding: 5px 10px; /* Optional: Adds some padding for a better visual appearance */\n border-radius: 4px; /* Optional: Adds rounded corners for a more polished look */\n}\n\n.display-container {\n display: block; /* Ensures it's treated as a block-level element */\n margin-left: 160px; /* Width of the options-container plus its padding */\n padding: 10px;\n box-sizing: border-box; /* Ensures padding doesn't add to the width */\n}\n\n.selected {\n background-color: #007bff; /* A blue background for selected item */\n color: white; /* White text color for better contrast */\n padding: 5px 10px; /* Optional: Adds some padding for a better visual appearance */\n border-radius: 4px; /* Optional: Adds rounded corners for a more polished look */\n}\n"] }]
258
- }], () => [{ type: i1.Router }, { type: i1.ActivatedRoute }], null); })();
259
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SettingsComponent, { className: "SettingsComponent", filePath: "src/lib/settings/settings.component.ts", lineNumber: 26 }); })();
481
+ args: [{ selector: 'mj-settings', standalone: true, imports: [
482
+ CommonModule,
483
+ SharedSettingsModule,
484
+ SqlLoggingComponent,
485
+ UserManagementComponent,
486
+ RoleManagementComponent,
487
+ ApplicationManagementComponent,
488
+ EntityPermissionsComponent
489
+ ], template: "<div class=\"settings-container\">\n <!-- Header Section -->\n <div class=\"settings-header\">\n <div class=\"header-content\">\n <div class=\"header-title\">\n <i class=\"fa-solid fa-cog header-icon\"></i>\n <h1>Settings</h1>\n </div>\n \n <div class=\"header-search\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input \n type=\"text\" \n class=\"search-input\" \n placeholder=\"Search settings...\"\n (input)=\"onSearchChange($event)\"\n [value]=\"searchTerm$.value\"\n />\n </div>\n </div>\n </div>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <div class=\"loading-content\">\n <div class=\"loading-spinner\">\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n </div>\n <div class=\"loading-text\">Loading settings...</div>\n </div>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-container\">\n <div class=\"error-content\">\n <i class=\"fa-solid fa-exclamation-triangle error-icon\"></i>\n <p class=\"error-message\">{{ error }}</p>\n <button class=\"retry-button\" (click)=\"loadInitialData()\">\n <i class=\"fa-solid fa-refresh\"></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\">\n <ul class=\"nav-list\">\n @for (tab of tabs; track tab.id) {\n <li \n class=\"nav-item\"\n [class.active]=\"activeTab === tab.id\"\n (click)=\"onTabChange(tab.id)\"\n >\n <i [class]=\"tab.icon\"></i>\n <span class=\"nav-label\">{{ tab.label }}</span>\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\">\n <div class=\"tab-content\">\n @switch (activeTab) {\n @case ('general') {\n <div class=\"general-settings\">\n <h2 class=\"section-title\">General Settings</h2>\n <div class=\"settings-grid\">\n <mj-settings-card \n title=\"Profile Information\"\n icon=\"fa-solid fa-user\"\n [expanded]=\"isSectionExpanded('profile')\"\n (toggle)=\"toggleSection('profile')\"\n >\n <div class=\"card-content\">\n <p>Manage your profile information and preferences.</p>\n <!-- Profile settings content will go here -->\n </div>\n </mj-settings-card>\n\n <mj-settings-card \n title=\"Preferences\"\n icon=\"fa-solid fa-sliders\"\n [expanded]=\"isSectionExpanded('preferences')\"\n (toggle)=\"toggleSection('preferences')\"\n >\n <div class=\"card-content\">\n <p>Customize your experience with display and behavior preferences.</p>\n <!-- Preferences content will go here -->\n </div>\n </mj-settings-card>\n\n <mj-settings-card \n title=\"Notifications\"\n icon=\"fa-solid fa-bell\"\n [expanded]=\"isSectionExpanded('notifications')\"\n (toggle)=\"toggleSection('notifications')\"\n >\n <div class=\"card-content\">\n <p>Configure how and when you receive notifications.</p>\n <!-- Notification settings will go here -->\n </div>\n </mj-settings-card>\n </div>\n </div>\n }\n \n @case ('users') {\n <div class=\"users-settings\">\n <h2 class=\"section-title\">User Management</h2>\n <p class=\"section-description\">Manage user accounts, roles, and permissions</p>\n <mj-user-management></mj-user-management>\n </div>\n }\n \n @case ('roles') {\n <div class=\"roles-settings\">\n <h2 class=\"section-title\">Role Management</h2>\n <p class=\"section-description\">Define and manage security roles.</p>\n <mj-role-management></mj-role-management>\n </div>\n }\n \n @case ('applications') {\n <div class=\"applications-settings\">\n <mj-application-management></mj-application-management>\n </div>\n }\n \n @case ('permissions') {\n <div class=\"permissions-settings\">\n <mj-entity-permissions></mj-entity-permissions>\n </div>\n }\n \n @case ('advanced') {\n <div class=\"advanced-settings\">\n <h2 class=\"section-title\">Advanced Settings</h2>\n <div class=\"beta-warning\">\n <i class=\"fa-solid fa-flask\"></i>\n <span>Beta features - Use with caution</span>\n </div>\n \n <!-- Tab Navigation -->\n <div class=\"advanced-tabs\">\n <button \n class=\"tab-btn\"\n [class.active]=\"advancedActiveTab === 'sql-logging'\"\n (click)=\"setAdvancedTab('sql-logging')\"\n >\n <i class=\"fa-solid fa-database\"></i>\n SQL Logging\n </button>\n <button \n class=\"tab-btn\"\n [class.active]=\"advancedActiveTab === 'performance'\"\n (click)=\"setAdvancedTab('performance')\"\n >\n <i class=\"fa-solid fa-gauge-high\"></i>\n Performance\n </button>\n <button \n class=\"tab-btn\"\n [class.active]=\"advancedActiveTab === 'developer'\"\n (click)=\"setAdvancedTab('developer')\"\n >\n <i class=\"fa-solid fa-code\"></i>\n Developer Tools\n </button>\n </div>\n \n <!-- Tab Content -->\n <div class=\"advanced-tab-content\">\n @switch (advancedActiveTab) {\n @case ('sql-logging') {\n <mj-sql-logging></mj-sql-logging>\n }\n @case ('performance') {\n <div class=\"performance-settings\">\n <h3>Performance Settings</h3>\n <p>Performance monitoring and optimization tools coming soon.</p>\n </div>\n }\n @case ('developer') {\n <div class=\"developer-settings\">\n <h3>Developer Tools</h3>\n <p>Advanced developer options coming soon.</p>\n </div>\n }\n }\n </div>\n </div>\n }\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Mobile Layout -->\n @if (isMobile) {\n <div class=\"mobile-layout\">\n <!-- Mobile Content -->\n <div class=\"mobile-content\">\n @switch (activeTab) {\n @case ('general') {\n <div class=\"general-settings\">\n <h2 class=\"section-title\">General Settings</h2>\n <!-- Same content as desktop but responsive -->\n </div>\n }\n @case ('users') {\n <div class=\"users-settings\">\n <h2 class=\"section-title\">User Management</h2>\n <p class=\"section-description\">Manage user accounts, roles, and permissions</p>\n <mj-user-management></mj-user-management>\n </div>\n }\n <!-- Other cases similar to desktop -->\n }\n </div>\n\n <!-- Mobile Bottom Navigation -->\n <nav class=\"mobile-navigation\">\n <div class=\"nav-tabs\">\n @for (tab of tabs.slice(0, 5); track tab.id) {\n <button \n class=\"nav-tab\"\n [class.active]=\"activeTab === tab.id\"\n (click)=\"onTabChange(tab.id)\"\n >\n <i [class]=\"tab.icon\"></i>\n @if (tab.badgeCount && tab.badgeCount > 0) {\n <span class=\"tab-badge\" [class]=\"'badge-' + (tab.badgeColor || 'primary')\">\n {{ tab.badgeCount }}\n </span>\n }\n <span class=\"tab-label\">{{ tab.label }}</span>\n </button>\n }\n @if (tabs.length > 5) {\n <button class=\"nav-tab more-tab\">\n <i class=\"fa-solid fa-ellipsis\"></i>\n <span class=\"tab-label\">More</span>\n </button>\n }\n </div>\n </nav>\n </div>\n }\n </div>\n }\n</div>", styles: ["@import '../shared/styles/variables';\n@import '../shared/styles/mixins';\n\n.settings-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n background-color: #f5f7fa;\n overflow: hidden;\n position: relative;\n}\n\n// Header Section\n.settings-header {\n background-color: #ffffff;\n border-bottom: 1px solid #e5e7eb;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n z-index: 10;\n}\n\n.header-content {\n padding: 1.5rem 2rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 2rem;\n\n @media (max-width: 768px) {\n padding: 1rem;\n flex-direction: column;\n gap: 1rem;\n }\n}\n\n.header-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n\n .header-icon {\n font-size: 1.75rem;\n color: #2196f3;\n }\n\n h1 {\n margin: 0;\n font-size: 1.75rem;\n font-weight: 600;\n color: #1f2937;\n }\n}\n\n.header-search {\n position: relative;\n width: 100%;\n max-width: 400px;\n\n .search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: #6b7280;\n font-size: 1rem;\n }\n\n .search-input {\n width: 100%;\n padding: 0.75rem 1rem 0.75rem 2.75rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n transition: all 0.2s;\n background-color: #f9fafb;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n background-color: #ffffff;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n\n &::placeholder {\n color: #9ca3af;\n }\n }\n}\n\n// Loading State\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-spinner {\n position: relative;\n width: 60px;\n height: 60px;\n margin: 0 auto 1rem;\n\n .spinner-ring {\n position: absolute;\n width: 100%;\n height: 100%;\n border: 3px solid transparent;\n border-radius: 50%;\n animation: spin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n\n &:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n }\n\n &:nth-child(2) {\n border-color: transparent #4caf50 transparent transparent;\n animation-delay: -0.3s;\n }\n\n &:nth-child(3) {\n border-color: transparent transparent #ff9800 transparent;\n animation-delay: -0.15s;\n }\n }\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n.loading-text {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n// Error State\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 .error-icon {\n font-size: 3rem;\n color: #f44336;\n margin-bottom: 1rem;\n }\n\n .error-message {\n color: #374151;\n margin-bottom: 1.5rem;\n font-size: 1rem;\n }\n\n .retry-button {\n @include button-base;\n background-color: #2196f3;\n color: white;\n padding: 0.75rem 1.5rem;\n font-size: 0.95rem;\n border-radius: 8px;\n transition: all 0.2s;\n\n &:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n }\n\n i {\n margin-right: 0.5rem;\n }\n }\n}\n\n// Main Content\n.settings-content {\n display: flex;\n flex: 1;\n overflow: hidden;\n flex-direction: column;\n width: 100%;\n}\n\n// Desktop Layout\n.desktop-layout {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n// More specific selector to ensure it applies\n.settings-content .desktop-layout {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n// Deep selector for Angular ViewEncapsulation\n:host ::ng-deep .desktop-layout {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n.side-navigation {\n width: 260px;\n background-color: #ffffff;\n border-right: 1px solid #e5e7eb;\n overflow-y: auto;\n flex-shrink: 0;\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: 0.875rem 1.5rem;\n cursor: pointer;\n transition: all 0.2s;\n color: #4b5563;\n font-size: 0.95rem;\n\n &:hover {\n background-color: #f3f4f6;\n color: #1f2937;\n }\n\n &.active {\n background-color: #eff6ff;\n color: #2196f3;\n font-weight: 500;\n\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background-color: #2196f3;\n }\n }\n\n i {\n width: 20px;\n margin-right: 0.75rem;\n font-size: 1.1rem;\n }\n\n .nav-label {\n flex: 1;\n }\n\n .nav-badge {\n padding: 0.125rem 0.5rem;\n border-radius: 12px;\n font-size: 0.75rem;\n font-weight: 600;\n \n &.badge-primary {\n background-color: #dbeafe;\n color: #1e40af;\n }\n\n &.badge-danger {\n background-color: #fee2e2;\n color: #991b1b;\n }\n\n &.badge-warning {\n background-color: #fef3c7;\n color: #92400e;\n }\n\n &.badge-success {\n background-color: #d1fae5;\n color: #065f46;\n }\n }\n}\n\n.content-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 2rem;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0; // Important for proper flex sizing\n\n @media (max-width: 768px) {\n padding: 1rem;\n }\n}\n\n.tab-content {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n min-height: 0; // Important for proper flex sizing\n}\n\n// Section Styles\n.section-title {\n font-size: 1.5rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.5rem 0;\n}\n\n.section-description {\n color: #6b7280;\n margin: 0 0 2rem 0;\n font-size: 0.95rem;\n}\n\n.settings-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));\n gap: 1.5rem;\n margin-top: 1.5rem;\n\n @media (max-width: 768px) {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n}\n\n.card-content {\n padding: 1rem;\n color: #4b5563;\n font-size: 0.95rem;\n\n p {\n margin: 0 0 1rem 0;\n line-height: 1.6;\n }\n}\n\n// Beta Warning\n.beta-warning {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n background-color: #fef3c7;\n color: #92400e;\n border-radius: 6px;\n font-size: 0.875rem;\n margin-bottom: 1.5rem;\n\n i {\n font-size: 1rem;\n }\n}\n\n// Mobile Layout\n.mobile-layout {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.mobile-content {\n flex: 1;\n overflow-y: auto;\n padding: 1rem;\n padding-bottom: 80px; // Space for bottom nav\n}\n\n.mobile-navigation {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n background-color: #ffffff;\n border-top: 1px solid #e5e7eb;\n box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);\n z-index: 100;\n}\n\n.nav-tabs {\n display: flex;\n justify-content: space-around;\n align-items: center;\n padding: 0.5rem 0;\n}\n\n.nav-tab {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.25rem;\n padding: 0.5rem;\n background: none;\n border: none;\n color: #9ca3af;\n cursor: pointer;\n transition: all 0.2s;\n font-size: 0.75rem;\n min-width: 60px;\n\n &.active {\n color: #2196f3;\n\n i {\n transform: scale(1.1);\n }\n }\n\n &:active {\n transform: scale(0.95);\n }\n\n i {\n font-size: 1.25rem;\n transition: transform 0.2s;\n }\n\n .tab-badge {\n position: absolute;\n top: 0.25rem;\n right: 0.25rem;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n font-size: 0.625rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n \n &.badge-primary {\n background-color: #2196f3;\n color: white;\n }\n\n &.badge-warning {\n background-color: #ff9800;\n color: white;\n }\n }\n\n .tab-label {\n margin-top: 0.125rem;\n }\n}\n\n.more-tab {\n color: #6b7280;\n}\n\n// Advanced Settings Tabs\n.advanced-tabs {\n display: flex;\n gap: 0.5rem;\n border-bottom: 2px solid #e5e7eb;\n margin-bottom: 2rem;\n margin-top: 1.5rem;\n\n .tab-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n background: transparent;\n border: none;\n border-bottom: 3px solid transparent;\n color: #6b7280;\n font-size: 0.95rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n position: relative;\n\n &:hover {\n color: #374151;\n background: #f9fafb;\n }\n\n &.active {\n color: #2196f3;\n border-bottom-color: #2196f3;\n background: #eff6ff;\n\n i {\n color: #2196f3;\n }\n }\n\n i {\n font-size: 1.125rem;\n }\n }\n}\n\n.advanced-tab-content {\n @include scrollable-content;\n background: white;\n border-radius: 12px;\n padding: 0;\n min-height: 500px;\n max-height: calc(100vh - 350px);\n}\n\n.performance-settings,\n.developer-settings {\n padding: 2rem;\n \n h3 {\n margin: 0 0 1rem 0;\n color: #1f2937;\n font-size: 1.25rem;\n }\n \n p {\n color: #6b7280;\n font-size: 0.95rem;\n }\n}\n\n// Animations\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.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 height: 100%;\n display: flex;\n flex-direction: column;\n min-height: 0; // Important for proper flex sizing\n overflow: hidden;\n \n // Direct child components should handle their own scrolling\n > * {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n}"] }]
490
+ }], () => [], { stateChange: [{
491
+ type: Output
492
+ }] }); })();
493
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SettingsComponent, { className: "SettingsComponent", filePath: "src/lib/settings/settings.component.ts", lineNumber: 45 }); })();
260
494
  //# sourceMappingURL=settings.component.js.map