@memberjunction/ng-dashboards 5.35.0 → 5.36.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 (159) hide show
  1. package/dist/AI/components/agents/agent-configuration.component.js +3 -3
  2. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  3. package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts +22 -1
  4. package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
  5. package/dist/AI/components/analytics/ai-analytics-resource.component.js +157 -137
  6. package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
  7. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +28 -0
  8. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  9. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +2075 -2068
  10. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  11. package/dist/AI/components/models/model-management.component.js +4 -4
  12. package/dist/AI/components/models/model-management.component.js.map +1 -1
  13. package/dist/AI/components/prompts/prompt-management.component.js +3 -3
  14. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  15. package/dist/AI/components/tags/tags-resource.component.d.ts +15 -0
  16. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  17. package/dist/AI/components/tags/tags-resource.component.js +1411 -1424
  18. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  19. package/dist/APIKeys/api-keys-resource.component.d.ts +12 -8
  20. package/dist/APIKeys/api-keys-resource.component.d.ts.map +1 -1
  21. package/dist/APIKeys/api-keys-resource.component.js +329 -371
  22. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  23. package/dist/Actions/components/actions-overview.component.js +137 -142
  24. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  25. package/dist/Actions/components/execution-monitoring.component.js +111 -116
  26. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  27. package/dist/Admin/admin-data-schema.component.js +13 -65
  28. package/dist/Admin/admin-data-schema.component.js.map +1 -1
  29. package/dist/Admin/admin-dev-tools-resource.component.js +13 -65
  30. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
  31. package/dist/Admin/admin-identity-access.component.js +13 -65
  32. package/dist/Admin/admin-identity-access.component.js.map +1 -1
  33. package/dist/Admin/admin-monitoring.component.js +13 -65
  34. package/dist/Admin/admin-monitoring.component.js.map +1 -1
  35. package/dist/Admin/base-admin-container.component.d.ts +9 -7
  36. package/dist/Admin/base-admin-container.component.d.ts.map +1 -1
  37. package/dist/Admin/base-admin-container.component.js +26 -17
  38. package/dist/Admin/base-admin-container.component.js.map +1 -1
  39. package/dist/ApplicationRoles/application-roles-resource.component.js +74 -67
  40. package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
  41. package/dist/Communication/communication-new-message-resource.component.d.ts +93 -0
  42. package/dist/Communication/communication-new-message-resource.component.d.ts.map +1 -0
  43. package/dist/Communication/communication-new-message-resource.component.js +661 -0
  44. package/dist/Communication/communication-new-message-resource.component.js.map +1 -0
  45. package/dist/Credentials/components/credentials-categories-resource.component.js +152 -159
  46. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  47. package/dist/Credentials/components/credentials-types-resource.component.js +151 -155
  48. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  49. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +20 -21
  50. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js.map +1 -1
  51. package/dist/DatabaseDesigner/components/entity-list.component.d.ts +2 -0
  52. package/dist/DatabaseDesigner/components/entity-list.component.d.ts.map +1 -1
  53. package/dist/DatabaseDesigner/components/entity-list.component.js +131 -125
  54. package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
  55. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +1 -1
  56. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
  57. package/dist/DatabaseDesigner/database-designer-dashboards.module.js +7 -1
  58. package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
  59. package/dist/DevTools/app-state-inspector.component.d.ts +5 -0
  60. package/dist/DevTools/app-state-inspector.component.d.ts.map +1 -1
  61. package/dist/DevTools/app-state-inspector.component.js +46 -72
  62. package/dist/DevTools/app-state-inspector.component.js.map +1 -1
  63. package/dist/DevTools/class-registry.component.js +88 -100
  64. package/dist/DevTools/class-registry.component.js.map +1 -1
  65. package/dist/DevTools/event-monitor.component.js +158 -168
  66. package/dist/DevTools/event-monitor.component.js.map +1 -1
  67. package/dist/DevTools/graphql-console.component.js +257 -264
  68. package/dist/DevTools/graphql-console.component.js.map +1 -1
  69. package/dist/DevTools/layout-inspector.component.d.ts +5 -0
  70. package/dist/DevTools/layout-inspector.component.d.ts.map +1 -1
  71. package/dist/DevTools/layout-inspector.component.js +46 -64
  72. package/dist/DevTools/layout-inspector.component.js.map +1 -1
  73. package/dist/DevTools/lazy-module-status.component.js +75 -84
  74. package/dist/DevTools/lazy-module-status.component.js.map +1 -1
  75. package/dist/DevTools/settings-explorer.component.js +76 -85
  76. package/dist/DevTools/settings-explorer.component.js.map +1 -1
  77. package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts +2 -0
  78. package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts.map +1 -1
  79. package/dist/EntityAdmin/entity-admin-dashboard.component.js +7 -3
  80. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  81. package/dist/Integration/components/activity/activity.component.js +97 -99
  82. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  83. package/dist/Integration/components/connections/connections.component.js +842 -855
  84. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  85. package/dist/Integration/components/pipelines/pipelines.component.js +502 -517
  86. package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
  87. package/dist/Integration/components/schedules/schedules.component.js +78 -89
  88. package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
  89. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts +5 -0
  90. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
  91. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +1120 -1128
  92. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
  93. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +11 -0
  94. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
  95. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +606 -661
  96. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  97. package/dist/Lists/components/lists-browse-resource.component.d.ts +102 -0
  98. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  99. package/dist/Lists/components/lists-browse-resource.component.js +1179 -504
  100. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  101. package/dist/Lists/components/lists-operations-resource.component.d.ts +133 -3
  102. package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
  103. package/dist/Lists/components/lists-operations-resource.component.js +1527 -327
  104. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  105. package/dist/Lists/components/lists-shared-with-me-resource.component.d.ts +29 -0
  106. package/dist/Lists/components/lists-shared-with-me-resource.component.d.ts.map +1 -0
  107. package/dist/Lists/components/lists-shared-with-me-resource.component.js +77 -0
  108. package/dist/Lists/components/lists-shared-with-me-resource.component.js.map +1 -0
  109. package/dist/Lists/components/venn-diagram/venn-diagram.component.d.ts +6 -0
  110. package/dist/Lists/components/venn-diagram/venn-diagram.component.d.ts.map +1 -1
  111. package/dist/Lists/components/venn-diagram/venn-diagram.component.js +35 -7
  112. package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
  113. package/dist/Lists/index.d.ts +1 -0
  114. package/dist/Lists/index.d.ts.map +1 -1
  115. package/dist/Lists/index.js +1 -0
  116. package/dist/Lists/index.js.map +1 -1
  117. package/dist/Lists/services/list-set-operations.service.d.ts +93 -2
  118. package/dist/Lists/services/list-set-operations.service.d.ts.map +1 -1
  119. package/dist/Lists/services/list-set-operations.service.js +236 -10
  120. package/dist/Lists/services/list-set-operations.service.js.map +1 -1
  121. package/dist/MCP/mcp-dashboard.component.js +19 -19
  122. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  123. package/dist/Scheduling/scheduling-dashboard.component.js +58 -60
  124. package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
  125. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts +13 -3
  126. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
  127. package/dist/SystemDiagnostics/system-diagnostics.component.js +1007 -1252
  128. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  129. package/dist/Testing/components/testing-explorer.component.d.ts +31 -6
  130. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  131. package/dist/Testing/components/testing-explorer.component.js +543 -629
  132. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  133. package/dist/Testing/testing-dashboard.component.js +50 -49
  134. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  135. package/dist/ai-dashboards.module.d.ts +1 -1
  136. package/dist/ai-dashboards.module.d.ts.map +1 -1
  137. package/dist/ai-dashboards.module.js +16 -1
  138. package/dist/ai-dashboards.module.js.map +1 -1
  139. package/dist/communication-dashboards.module.d.ts +9 -7
  140. package/dist/communication-dashboards.module.d.ts.map +1 -1
  141. package/dist/communication-dashboards.module.js +13 -4
  142. package/dist/communication-dashboards.module.js.map +1 -1
  143. package/dist/core-dashboards.module.d.ts +1 -1
  144. package/dist/core-dashboards.module.d.ts.map +1 -1
  145. package/dist/core-dashboards.module.js +16 -1
  146. package/dist/core-dashboards.module.js.map +1 -1
  147. package/dist/lists-dashboards.module.d.ts +10 -9
  148. package/dist/lists-dashboards.module.d.ts.map +1 -1
  149. package/dist/lists-dashboards.module.js +13 -2
  150. package/dist/lists-dashboards.module.js.map +1 -1
  151. package/dist/public-api.d.ts +1 -0
  152. package/dist/public-api.d.ts.map +1 -1
  153. package/dist/public-api.js +1 -0
  154. package/dist/public-api.js.map +1 -1
  155. package/dist/testing-dashboards.module.d.ts +1 -1
  156. package/dist/testing-dashboards.module.d.ts.map +1 -1
  157. package/dist/testing-dashboards.module.js +13 -1
  158. package/dist/testing-dashboards.module.js.map +1 -1
  159. package/package.json +53 -52
@@ -12,31 +12,33 @@ import { APIKeysEngineBase, parseAPIScopeUIConfig } from '@memberjunction/api-ke
12
12
  import { Subject } from 'rxjs';
13
13
  import * as i0 from "@angular/core";
14
14
  import * as i1 from "@angular/common";
15
- import * as i2 from "@memberjunction/ng-shared-generic";
16
- import * as i3 from "./api-key-create-dialog.component";
17
- import * as i4 from "./api-key-edit-panel.component";
18
- import * as i5 from "./api-key-list.component";
19
- import * as i6 from "./api-applications-panel.component";
20
- import * as i7 from "./api-scopes-panel.component";
21
- import * as i8 from "./api-usage-panel.component";
15
+ import * as i2 from "@memberjunction/ng-ui-components";
16
+ import * as i3 from "@memberjunction/ng-shared-generic";
17
+ import * as i4 from "./api-key-create-dialog.component";
18
+ import * as i5 from "./api-key-edit-panel.component";
19
+ import * as i6 from "./api-key-list.component";
20
+ import * as i7 from "./api-applications-panel.component";
21
+ import * as i8 from "./api-scopes-panel.component";
22
+ import * as i9 from "./api-usage-panel.component";
22
23
  const _c0 = ["keyList"];
23
- function APIKeysResourceComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
24
- i0.ɵɵelement(0, "mj-loading", 2);
24
+ function APIKeysResourceComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
25
+ const _r1 = i0.ɵɵgetCurrentView();
26
+ i0.ɵɵelementStart(0, "button", 10);
27
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
28
+ i0.ɵɵelement(1, "i", 11);
29
+ i0.ɵɵtext(2, " Generate New Key ");
30
+ i0.ɵɵelementEnd();
25
31
  } }
26
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_9_Template(rf, ctx) { if (rf & 1) {
27
- const _r4 = i0.ɵɵgetCurrentView();
28
- i0.ɵɵelementStart(0, "button", 76);
29
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
30
- i0.ɵɵelement(1, "i", 77);
31
- i0.ɵɵelementStart(2, "span");
32
- i0.ɵɵtext(3, "Generate New Key");
33
- i0.ɵɵelementEnd()();
32
+ function APIKeysResourceComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
33
+ i0.ɵɵelementStart(0, "div", 7);
34
+ i0.ɵɵelement(1, "mj-loading", 12);
35
+ i0.ɵɵelementEnd();
34
36
  } }
35
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_22_Template(rf, ctx) { if (rf & 1) {
36
- const _r5 = i0.ɵɵgetCurrentView();
37
- i0.ɵɵelementStart(0, "span", 78);
38
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_22_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expired")); });
39
- i0.ɵɵelement(1, "i", 79);
37
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template(rf, ctx) { if (rf & 1) {
38
+ const _r4 = i0.ɵɵgetCurrentView();
39
+ i0.ɵɵelementStart(0, "span", 62);
40
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expired")); });
41
+ i0.ɵɵelement(1, "i", 63);
40
42
  i0.ɵɵtext(2);
41
43
  i0.ɵɵelementEnd();
42
44
  } if (rf & 2) {
@@ -44,11 +46,11 @@ function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Con
44
46
  i0.ɵɵadvance(2);
45
47
  i0.ɵɵtextInterpolate1(" ", ctx_r1.ExpiredKeys, " expired ");
46
48
  } }
47
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_23_Template(rf, ctx) { if (rf & 1) {
48
- const _r6 = i0.ɵɵgetCurrentView();
49
- i0.ɵɵelementStart(0, "span", 80);
50
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_23_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
51
- i0.ɵɵelement(1, "i", 55);
49
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template(rf, ctx) { if (rf & 1) {
50
+ const _r5 = i0.ɵɵgetCurrentView();
51
+ i0.ɵɵelementStart(0, "span", 64);
52
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
53
+ i0.ɵɵelement(1, "i", 40);
52
54
  i0.ɵɵtext(2);
53
55
  i0.ɵɵelementEnd();
54
56
  } if (rf & 2) {
@@ -56,11 +58,11 @@ function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Con
56
58
  i0.ɵɵadvance(2);
57
59
  i0.ɵɵtextInterpolate1(" ", ctx_r1.ExpiringSoonCount, " expiring soon ");
58
60
  } }
59
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_24_Template(rf, ctx) { if (rf & 1) {
60
- const _r7 = i0.ɵɵgetCurrentView();
61
- i0.ɵɵelementStart(0, "span", 81);
62
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_24_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("never-used")); });
63
- i0.ɵɵelement(1, "i", 82);
61
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template(rf, ctx) { if (rf & 1) {
62
+ const _r6 = i0.ɵɵgetCurrentView();
63
+ i0.ɵɵelementStart(0, "span", 65);
64
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("never-used")); });
65
+ i0.ɵɵelement(1, "i", 66);
64
66
  i0.ɵɵtext(2);
65
67
  i0.ɵɵelementEnd();
66
68
  } if (rf & 2) {
@@ -68,129 +70,129 @@ function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Con
68
70
  i0.ɵɵadvance(2);
69
71
  i0.ɵɵtextInterpolate1(" ", ctx_r1.NeverUsedKeys, " never used ");
70
72
  } }
71
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_25_Template(rf, ctx) { if (rf & 1) {
72
- i0.ɵɵelementStart(0, "span", 42);
73
- i0.ɵɵelement(1, "i", 52);
73
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_15_Template(rf, ctx) { if (rf & 1) {
74
+ i0.ɵɵelementStart(0, "span", 26);
75
+ i0.ɵɵelement(1, "i", 37);
74
76
  i0.ɵɵtext(2, " All keys healthy ");
75
77
  i0.ɵɵelementEnd();
76
78
  } }
77
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_56_Template(rf, ctx) { if (rf & 1) {
78
- i0.ɵɵelementStart(0, "div", 56);
79
- i0.ɵɵelement(1, "i", 50);
79
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_46_Template(rf, ctx) { if (rf & 1) {
80
+ i0.ɵɵelementStart(0, "div", 41);
81
+ i0.ɵɵelement(1, "i", 35);
80
82
  i0.ɵɵelementEnd();
81
83
  } }
82
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_84_For_2_Template(rf, ctx) { if (rf & 1) {
83
- const _r8 = i0.ɵɵgetCurrentView();
84
- i0.ɵɵelementStart(0, "div", 84);
85
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_84_For_2_Template_div_click_0_listener() { const key_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.openEditPanel(key_r9)); });
86
- i0.ɵɵelementStart(1, "div", 85);
87
- i0.ɵɵelement(2, "i", 8);
84
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template(rf, ctx) { if (rf & 1) {
85
+ const _r7 = i0.ɵɵgetCurrentView();
86
+ i0.ɵɵelementStart(0, "div", 68);
87
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template_div_click_0_listener() { const key_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.openEditPanel(key_r8)); });
88
+ i0.ɵɵelementStart(1, "div", 69);
89
+ i0.ɵɵelement(2, "i", 30);
88
90
  i0.ɵɵelementEnd();
89
- i0.ɵɵelementStart(3, "div", 86)(4, "div", 87);
91
+ i0.ɵɵelementStart(3, "div", 70)(4, "div", 71);
90
92
  i0.ɵɵtext(5);
91
93
  i0.ɵɵelementEnd();
92
- i0.ɵɵelementStart(6, "div", 88)(7, "span", 89);
94
+ i0.ɵɵelementStart(6, "div", 72)(7, "span", 73);
93
95
  i0.ɵɵtext(8);
94
96
  i0.ɵɵelementEnd();
95
- i0.ɵɵelementStart(9, "span", 90);
97
+ i0.ɵɵelementStart(9, "span", 74);
96
98
  i0.ɵɵtext(10);
97
99
  i0.ɵɵelementEnd()()();
98
- i0.ɵɵelementStart(11, "div", 91)(12, "div", 92);
100
+ i0.ɵɵelementStart(11, "div", 75)(12, "div", 76);
99
101
  i0.ɵɵtext(13);
100
102
  i0.ɵɵelementEnd();
101
- i0.ɵɵelementStart(14, "div", 93);
103
+ i0.ɵɵelementStart(14, "div", 77);
102
104
  i0.ɵɵtext(15);
103
105
  i0.ɵɵelementEnd()()();
104
106
  } if (rf & 2) {
105
- const key_r9 = ctx.$implicit;
107
+ const key_r8 = ctx.$implicit;
106
108
  const ctx_r1 = i0.ɵɵnextContext(5);
107
109
  i0.ɵɵadvance();
108
- i0.ɵɵclassProp("active", key_r9.Status === "Active");
110
+ i0.ɵɵclassProp("active", key_r8.Status === "Active");
109
111
  i0.ɵɵadvance(4);
110
- i0.ɵɵtextInterpolate(key_r9.Label);
112
+ i0.ɵɵtextInterpolate(key_r8.Label);
111
113
  i0.ɵɵadvance(3);
112
- i0.ɵɵtextInterpolate(key_r9.User);
114
+ i0.ɵɵtextInterpolate(key_r8.User);
113
115
  i0.ɵɵadvance(2);
114
- i0.ɵɵtextInterpolate1("...", key_r9.Hash.slice(-8));
116
+ i0.ɵɵtextInterpolate1("...", key_r8.Hash.slice(-8));
115
117
  i0.ɵɵadvance(3);
116
- i0.ɵɵtextInterpolate(ctx_r1.formatDate(key_r9.LastUsedAt));
118
+ i0.ɵɵtextInterpolate(ctx_r1.formatDate(key_r8.LastUsedAt));
117
119
  i0.ɵɵadvance();
118
- i0.ɵɵproperty("ngClass", ctx_r1.getExpirationClass(key_r9));
120
+ i0.ɵɵproperty("ngClass", ctx_r1.getExpirationClass(key_r8));
119
121
  i0.ɵɵadvance();
120
- i0.ɵɵtextInterpolate1(" ", ctx_r1.formatExpiration(key_r9.ExpiresAt), " ");
122
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.formatExpiration(key_r8.ExpiresAt), " ");
121
123
  } }
122
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_84_Template(rf, ctx) { if (rf & 1) {
123
- i0.ɵɵelementStart(0, "div", 64);
124
- i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_84_For_2_Template, 16, 8, "div", 83, i0.ɵɵrepeaterTrackByIdentity);
124
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_Template(rf, ctx) { if (rf & 1) {
125
+ i0.ɵɵelementStart(0, "div", 50);
126
+ i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template, 16, 8, "div", 67, i0.ɵɵrepeaterTrackByIdentity);
125
127
  i0.ɵɵelementEnd();
126
128
  } if (rf & 2) {
127
129
  const ctx_r1 = i0.ɵɵnextContext(4);
128
130
  i0.ɵɵadvance();
129
131
  i0.ɵɵrepeater(ctx_r1.TopUsedKeys);
130
132
  } }
131
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_85_Template(rf, ctx) { if (rf & 1) {
132
- i0.ɵɵelementStart(0, "div", 65);
133
- i0.ɵɵelement(1, "i", 8);
133
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_75_Template(rf, ctx) { if (rf & 1) {
134
+ i0.ɵɵelementStart(0, "div", 51);
135
+ i0.ɵɵelement(1, "i", 30);
134
136
  i0.ɵɵelementStart(2, "span");
135
137
  i0.ɵɵtext(3, "No active keys with recent usage");
136
138
  i0.ɵɵelementEnd()();
137
139
  } }
138
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_95_For_5_Template(rf, ctx) { if (rf & 1) {
139
- const _r10 = i0.ɵɵgetCurrentView();
140
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_5_Template(rf, ctx) { if (rf & 1) {
141
+ const _r9 = i0.ɵɵgetCurrentView();
140
142
  i0.ɵɵnamespaceSVG();
141
143
  i0.ɵɵelementContainerStart(0);
142
- i0.ɵɵelementStart(1, "circle", 102);
143
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_95_For_5_Template_circle_click_1_listener() { const stat_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onScopeClick(stat_r11)); });
144
+ i0.ɵɵelementStart(1, "circle", 86);
145
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_5_Template_circle_click_1_listener() { const stat_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onScopeClick(stat_r10)); });
144
146
  i0.ɵɵelementEnd();
145
147
  i0.ɵɵelementContainerEnd();
146
148
  } if (rf & 2) {
147
- const stat_r11 = ctx.$implicit;
148
- const ɵ$index_303_r12 = ctx.$index;
149
+ const stat_r10 = ctx.$implicit;
150
+ const ɵ$index_243_r11 = ctx.$index;
149
151
  const ctx_r1 = i0.ɵɵnextContext(5);
150
152
  i0.ɵɵadvance();
151
- i0.ɵɵattribute("stroke", stat_r11.color)("stroke-dasharray", stat_r11.percentage * 2.51 + " " + (251 - stat_r11.percentage * 2.51))("stroke-dashoffset", ctx_r1.getDonutOffset(ɵ$index_303_r12));
153
+ i0.ɵɵattribute("stroke", stat_r10.color)("stroke-dasharray", stat_r10.percentage * 2.51 + " " + (251 - stat_r10.percentage * 2.51))("stroke-dashoffset", ctx_r1.getDonutOffset(ɵ$index_243_r11));
152
154
  } }
153
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_95_For_13_Template(rf, ctx) { if (rf & 1) {
154
- const _r13 = i0.ɵɵgetCurrentView();
155
- i0.ɵɵelementStart(0, "div", 103);
156
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_95_For_13_Template_div_click_0_listener() { const stat_r14 = i0.ɵɵrestoreView(_r13).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onScopeClick(stat_r14)); });
157
- i0.ɵɵelement(1, "div", 104);
158
- i0.ɵɵelementStart(2, "div", 105)(3, "div", 106);
155
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template(rf, ctx) { if (rf & 1) {
156
+ const _r12 = i0.ɵɵgetCurrentView();
157
+ i0.ɵɵelementStart(0, "div", 87);
158
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template_div_click_0_listener() { const stat_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onScopeClick(stat_r13)); });
159
+ i0.ɵɵelement(1, "div", 88);
160
+ i0.ɵɵelementStart(2, "div", 89)(3, "div", 90);
159
161
  i0.ɵɵelement(4, "i");
160
162
  i0.ɵɵtext(5);
161
163
  i0.ɵɵelementEnd();
162
- i0.ɵɵelementStart(6, "div", 107);
164
+ i0.ɵɵelementStart(6, "div", 91);
163
165
  i0.ɵɵtext(7);
164
166
  i0.ɵɵelementEnd()();
165
- i0.ɵɵelement(8, "i", 108);
167
+ i0.ɵɵelement(8, "i", 92);
166
168
  i0.ɵɵelementEnd();
167
169
  } if (rf & 2) {
168
- const stat_r14 = ctx.$implicit;
170
+ const stat_r13 = ctx.$implicit;
169
171
  i0.ɵɵadvance();
170
- i0.ɵɵstyleProp("background-color", stat_r14.color);
172
+ i0.ɵɵstyleProp("background-color", stat_r13.color);
171
173
  i0.ɵɵadvance(3);
172
- i0.ɵɵclassMap(stat_r14.iconClass);
174
+ i0.ɵɵclassMap(stat_r13.iconClass);
173
175
  i0.ɵɵadvance();
174
- i0.ɵɵtextInterpolate1(" ", stat_r14.category, " ");
176
+ i0.ɵɵtextInterpolate1(" ", stat_r13.category, " ");
175
177
  i0.ɵɵadvance(2);
176
- i0.ɵɵtextInterpolate1("", stat_r14.count, " scopes");
178
+ i0.ɵɵtextInterpolate1("", stat_r13.count, " scopes");
177
179
  } }
178
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_95_Template(rf, ctx) { if (rf & 1) {
179
- i0.ɵɵelementStart(0, "div", 68)(1, "div", 94);
180
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_Template(rf, ctx) { if (rf & 1) {
181
+ i0.ɵɵelementStart(0, "div", 54)(1, "div", 78);
180
182
  i0.ɵɵnamespaceSVG();
181
- i0.ɵɵelementStart(2, "svg", 95);
182
- i0.ɵɵelement(3, "circle", 96);
183
- i0.ɵɵrepeaterCreate(4, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_95_For_5_Template, 2, 3, ":svg:ng-container", null, i0.ɵɵrepeaterTrackByIdentity);
183
+ i0.ɵɵelementStart(2, "svg", 79);
184
+ i0.ɵɵelement(3, "circle", 80);
185
+ i0.ɵɵrepeaterCreate(4, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_5_Template, 2, 3, ":svg:ng-container", null, i0.ɵɵrepeaterTrackByIdentity);
184
186
  i0.ɵɵelementEnd();
185
187
  i0.ɵɵnamespaceHTML();
186
- i0.ɵɵelementStart(6, "div", 97)(7, "div", 98);
188
+ i0.ɵɵelementStart(6, "div", 81)(7, "div", 82);
187
189
  i0.ɵɵtext(8);
188
190
  i0.ɵɵelementEnd();
189
- i0.ɵɵelementStart(9, "div", 99);
191
+ i0.ɵɵelementStart(9, "div", 83);
190
192
  i0.ɵɵtext(10, "Categories");
191
193
  i0.ɵɵelementEnd()()();
192
- i0.ɵɵelementStart(11, "div", 100);
193
- i0.ɵɵrepeaterCreate(12, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_95_For_13_Template, 9, 6, "div", 101, i0.ɵɵrepeaterTrackByIdentity);
194
+ i0.ɵɵelementStart(11, "div", 84);
195
+ i0.ɵɵrepeaterCreate(12, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template, 9, 6, "div", 85, i0.ɵɵrepeaterTrackByIdentity);
194
196
  i0.ɵɵelementEnd()();
195
197
  } if (rf & 2) {
196
198
  const ctx_r1 = i0.ɵɵnextContext(4);
@@ -201,245 +203,230 @@ function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Con
201
203
  i0.ɵɵadvance(4);
202
204
  i0.ɵɵrepeater(ctx_r1.ScopeStats);
203
205
  } }
204
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_96_Template(rf, ctx) { if (rf & 1) {
205
- i0.ɵɵelementStart(0, "div", 65);
206
- i0.ɵɵelement(1, "i", 14);
206
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_86_Template(rf, ctx) { if (rf & 1) {
207
+ i0.ɵɵelementStart(0, "div", 51);
208
+ i0.ɵɵelement(1, "i", 43);
207
209
  i0.ɵɵelementStart(2, "span");
208
210
  i0.ɵɵtext(3, "No scopes configured");
209
211
  i0.ɵɵelementEnd()();
210
212
  } }
211
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_104_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
212
- i0.ɵɵelementStart(0, "span", 116);
213
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
214
+ i0.ɵɵelementStart(0, "span", 100);
213
215
  i0.ɵɵtext(1);
214
216
  i0.ɵɵelementEnd();
215
217
  } if (rf & 2) {
216
- const activity_r16 = i0.ɵɵnextContext().$implicit;
218
+ const activity_r15 = i0.ɵɵnextContext().$implicit;
217
219
  i0.ɵɵadvance();
218
- i0.ɵɵtextInterpolate1("by ", activity_r16.user);
220
+ i0.ɵɵtextInterpolate1("by ", activity_r15.user);
219
221
  } }
220
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_104_For_2_Template(rf, ctx) { if (rf & 1) {
221
- const _r15 = i0.ɵɵgetCurrentView();
222
- i0.ɵɵelementStart(0, "div", 110);
223
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_104_For_2_Template_div_click_0_listener() { const activity_r16 = i0.ɵɵrestoreView(_r15).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onActivityClick(activity_r16)); });
224
- i0.ɵɵelementStart(1, "div", 111);
222
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template(rf, ctx) { if (rf & 1) {
223
+ const _r14 = i0.ɵɵgetCurrentView();
224
+ i0.ɵɵelementStart(0, "div", 94);
225
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template_div_click_0_listener() { const activity_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onActivityClick(activity_r15)); });
226
+ i0.ɵɵelementStart(1, "div", 95);
225
227
  i0.ɵɵelement(2, "i");
226
228
  i0.ɵɵelementEnd();
227
- i0.ɵɵelementStart(3, "div", 112)(4, "div", 113);
229
+ i0.ɵɵelementStart(3, "div", 96)(4, "div", 97);
228
230
  i0.ɵɵtext(5);
229
231
  i0.ɵɵelementEnd();
230
- i0.ɵɵelementStart(6, "div", 114)(7, "span", 115);
232
+ i0.ɵɵelementStart(6, "div", 98)(7, "span", 99);
231
233
  i0.ɵɵtext(8);
232
234
  i0.ɵɵelementEnd();
233
- i0.ɵɵconditionalCreate(9, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_104_For_2_Conditional_9_Template, 2, 1, "span", 116);
235
+ i0.ɵɵconditionalCreate(9, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Conditional_9_Template, 2, 1, "span", 100);
234
236
  i0.ɵɵelementEnd()();
235
- i0.ɵɵelementStart(10, "div", 117);
237
+ i0.ɵɵelementStart(10, "div", 101);
236
238
  i0.ɵɵtext(11);
237
239
  i0.ɵɵelementEnd()();
238
240
  } if (rf & 2) {
239
- const activity_r16 = ctx.$implicit;
241
+ const activity_r15 = ctx.$implicit;
240
242
  const ctx_r1 = i0.ɵɵnextContext(5);
241
243
  i0.ɵɵadvance();
242
- i0.ɵɵproperty("ngClass", ctx_r1.getActionClass(activity_r16.action));
244
+ i0.ɵɵproperty("ngClass", ctx_r1.getActionClass(activity_r15.action));
243
245
  i0.ɵɵadvance();
244
- i0.ɵɵclassMap(ctx_r1.getActionIcon(activity_r16.action));
246
+ i0.ɵɵclassMap(ctx_r1.getActionIcon(activity_r15.action));
245
247
  i0.ɵɵadvance(3);
246
- i0.ɵɵtextInterpolate(activity_r16.keyLabel);
248
+ i0.ɵɵtextInterpolate(activity_r15.keyLabel);
247
249
  i0.ɵɵadvance(3);
248
- i0.ɵɵtextInterpolate(activity_r16.action);
250
+ i0.ɵɵtextInterpolate(activity_r15.action);
249
251
  i0.ɵɵadvance();
250
- i0.ɵɵconditional(activity_r16.user ? 9 : -1);
252
+ i0.ɵɵconditional(activity_r15.user ? 9 : -1);
251
253
  i0.ɵɵadvance(2);
252
- i0.ɵɵtextInterpolate1(" ", ctx_r1.formatDate(activity_r16.date), " ");
254
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.formatDate(activity_r15.date), " ");
253
255
  } }
254
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_104_Template(rf, ctx) { if (rf & 1) {
255
- i0.ɵɵelementStart(0, "div", 71);
256
- i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_104_For_2_Template, 12, 7, "div", 109, i0.ɵɵrepeaterTrackByIdentity);
256
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_Template(rf, ctx) { if (rf & 1) {
257
+ i0.ɵɵelementStart(0, "div", 57);
258
+ i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template, 12, 7, "div", 93, i0.ɵɵrepeaterTrackByIdentity);
257
259
  i0.ɵɵelementEnd();
258
260
  } if (rf & 2) {
259
261
  const ctx_r1 = i0.ɵɵnextContext(4);
260
262
  i0.ɵɵadvance();
261
263
  i0.ɵɵrepeater(ctx_r1.RecentActivity);
262
264
  } }
263
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_105_Template(rf, ctx) { if (rf & 1) {
264
- i0.ɵɵelementStart(0, "div", 65);
265
- i0.ɵɵelement(1, "i", 118);
265
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_95_Template(rf, ctx) { if (rf & 1) {
266
+ i0.ɵɵelementStart(0, "div", 51);
267
+ i0.ɵɵelement(1, "i", 102);
266
268
  i0.ɵɵelementStart(2, "span");
267
269
  i0.ɵɵtext(3, "No recent activity");
268
270
  i0.ɵɵelementEnd()();
269
271
  } }
270
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_106_Template(rf, ctx) { if (rf & 1) {
271
- const _r17 = i0.ɵɵgetCurrentView();
272
- i0.ɵɵelementStart(0, "div", 72)(1, "div", 119);
272
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template(rf, ctx) { if (rf & 1) {
273
+ const _r16 = i0.ɵɵgetCurrentView();
274
+ i0.ɵɵelementStart(0, "div", 58)(1, "div", 103);
273
275
  i0.ɵɵtext(2, "Quick Actions");
274
276
  i0.ɵɵelementEnd();
275
- i0.ɵɵelementStart(3, "div", 120)(4, "button", 121);
276
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_106_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
277
- i0.ɵɵelement(5, "i", 77);
277
+ i0.ɵɵelementStart(3, "div", 104)(4, "button", 105);
278
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
279
+ i0.ɵɵelement(5, "i", 106);
278
280
  i0.ɵɵelementStart(6, "span");
279
281
  i0.ɵɵtext(7, "Generate Key");
280
282
  i0.ɵɵelementEnd()();
281
- i0.ɵɵelementStart(8, "button", 121);
282
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_106_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
283
- i0.ɵɵelement(9, "i", 122);
283
+ i0.ɵɵelementStart(8, "button", 105);
284
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
285
+ i0.ɵɵelement(9, "i", 107);
284
286
  i0.ɵɵelementStart(10, "span");
285
287
  i0.ɵɵtext(11, "View All Keys");
286
288
  i0.ɵɵelementEnd()();
287
- i0.ɵɵelementStart(12, "button", 121);
288
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_106_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
289
- i0.ɵɵelement(13, "i", 55);
289
+ i0.ɵɵelementStart(12, "button", 105);
290
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
291
+ i0.ɵɵelement(13, "i", 40);
290
292
  i0.ɵɵelementStart(14, "span");
291
293
  i0.ɵɵtext(15, "Expiring Keys");
292
294
  i0.ɵɵelementEnd()();
293
- i0.ɵɵelementStart(16, "button", 121);
294
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_106_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("never-used")); });
295
- i0.ɵɵelement(17, "i", 82);
295
+ i0.ɵɵelementStart(16, "button", 105);
296
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("never-used")); });
297
+ i0.ɵɵelement(17, "i", 66);
296
298
  i0.ɵɵelementStart(18, "span");
297
299
  i0.ɵɵtext(19, "Never Used");
298
300
  i0.ɵɵelementEnd()()()();
299
301
  } }
300
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template(rf, ctx) { if (rf & 1) {
302
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
301
303
  const _r3 = i0.ɵɵgetCurrentView();
302
- i0.ɵɵelementStart(0, "div", 21)(1, "div", 22)(2, "h2", 23);
303
- i0.ɵɵtext(3, "API Keys Management");
304
- i0.ɵɵelementEnd();
305
- i0.ɵɵelementStart(4, "p", 24);
306
- i0.ɵɵtext(5, "Manage API keys for external integrations and services");
307
- i0.ɵɵelementEnd()();
308
- i0.ɵɵelementStart(6, "div", 25)(7, "button", 26);
309
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.refresh()); });
310
- i0.ɵɵelement(8, "i", 27);
311
- i0.ɵɵelementEnd();
312
- i0.ɵɵconditionalCreate(9, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_9_Template, 4, 0, "button", 28);
313
- i0.ɵɵelementEnd()();
314
- i0.ɵɵelementStart(10, "div", 29)(11, "div", 30)(12, "div", 31);
304
+ i0.ɵɵelementStart(0, "div", 13)(1, "div", 14)(2, "div", 15);
315
305
  i0.ɵɵnamespaceSVG();
316
- i0.ɵɵelementStart(13, "svg", 32);
317
- i0.ɵɵelement(14, "path", 33)(15, "path", 34);
306
+ i0.ɵɵelementStart(3, "svg", 16);
307
+ i0.ɵɵelement(4, "path", 17)(5, "path", 18);
318
308
  i0.ɵɵelementEnd();
319
309
  i0.ɵɵnamespaceHTML();
320
- i0.ɵɵelementStart(16, "div", 35);
321
- i0.ɵɵtext(17);
310
+ i0.ɵɵelementStart(6, "div", 19);
311
+ i0.ɵɵtext(7);
322
312
  i0.ɵɵelementEnd()()();
323
- i0.ɵɵelementStart(18, "div", 36)(19, "div", 37);
324
- i0.ɵɵtext(20);
313
+ i0.ɵɵelementStart(8, "div", 20)(9, "div", 21);
314
+ i0.ɵɵtext(10);
325
315
  i0.ɵɵelementEnd();
326
- i0.ɵɵelementStart(21, "div", 38);
327
- i0.ɵɵconditionalCreate(22, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_22_Template, 3, 1, "span", 39);
328
- i0.ɵɵconditionalCreate(23, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_23_Template, 3, 1, "span", 40);
329
- i0.ɵɵconditionalCreate(24, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_24_Template, 3, 1, "span", 41);
330
- i0.ɵɵconditionalCreate(25, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_25_Template, 3, 0, "span", 42);
316
+ i0.ɵɵelementStart(11, "div", 22);
317
+ i0.ɵɵconditionalCreate(12, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template, 3, 1, "span", 23);
318
+ i0.ɵɵconditionalCreate(13, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template, 3, 1, "span", 24);
319
+ i0.ɵɵconditionalCreate(14, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template, 3, 1, "span", 25);
320
+ i0.ɵɵconditionalCreate(15, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_15_Template, 3, 0, "span", 26);
331
321
  i0.ɵɵelementEnd()()();
332
- i0.ɵɵelementStart(26, "div", 43)(27, "div", 44);
333
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template_div_click_27_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
334
- i0.ɵɵelementStart(28, "div", 45);
335
- i0.ɵɵelement(29, "i", 8);
322
+ i0.ɵɵelementStart(16, "div", 27)(17, "div", 28);
323
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_17_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
324
+ i0.ɵɵelementStart(18, "div", 29);
325
+ i0.ɵɵelement(19, "i", 30);
336
326
  i0.ɵɵelementEnd();
337
- i0.ɵɵelementStart(30, "div", 46)(31, "div", 47);
338
- i0.ɵɵtext(32);
327
+ i0.ɵɵelementStart(20, "div", 31)(21, "div", 32);
328
+ i0.ɵɵtext(22);
339
329
  i0.ɵɵelementEnd();
340
- i0.ɵɵelementStart(33, "div", 48);
341
- i0.ɵɵtext(34, "Total Keys");
330
+ i0.ɵɵelementStart(23, "div", 33);
331
+ i0.ɵɵtext(24, "Total Keys");
342
332
  i0.ɵɵelementEnd()();
343
- i0.ɵɵelementStart(35, "div", 49);
344
- i0.ɵɵelement(36, "i", 50);
333
+ i0.ɵɵelementStart(25, "div", 34);
334
+ i0.ɵɵelement(26, "i", 35);
345
335
  i0.ɵɵelementEnd()();
346
- i0.ɵɵelementStart(37, "div", 51);
347
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template_div_click_37_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("active")); });
348
- i0.ɵɵelementStart(38, "div", 45);
349
- i0.ɵɵelement(39, "i", 52);
336
+ i0.ɵɵelementStart(27, "div", 36);
337
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_27_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("active")); });
338
+ i0.ɵɵelementStart(28, "div", 29);
339
+ i0.ɵɵelement(29, "i", 37);
350
340
  i0.ɵɵelementEnd();
351
- i0.ɵɵelementStart(40, "div", 46)(41, "div", 47);
352
- i0.ɵɵtext(42);
341
+ i0.ɵɵelementStart(30, "div", 31)(31, "div", 32);
342
+ i0.ɵɵtext(32);
353
343
  i0.ɵɵelementEnd();
354
- i0.ɵɵelementStart(43, "div", 48);
355
- i0.ɵɵtext(44, "Active");
344
+ i0.ɵɵelementStart(33, "div", 33);
345
+ i0.ɵɵtext(34, "Active");
356
346
  i0.ɵɵelementEnd()();
357
- i0.ɵɵelementStart(45, "div", 53)(46, "span", 54);
358
- i0.ɵɵtext(47);
347
+ i0.ɵɵelementStart(35, "div", 38)(36, "span", 39);
348
+ i0.ɵɵtext(37);
359
349
  i0.ɵɵelementEnd()()();
360
- i0.ɵɵelementStart(48, "div", 44);
361
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template_div_click_48_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
362
- i0.ɵɵelementStart(49, "div", 45);
363
- i0.ɵɵelement(50, "i", 55);
350
+ i0.ɵɵelementStart(38, "div", 28);
351
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_38_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
352
+ i0.ɵɵelementStart(39, "div", 29);
353
+ i0.ɵɵelement(40, "i", 40);
364
354
  i0.ɵɵelementEnd();
365
- i0.ɵɵelementStart(51, "div", 46)(52, "div", 47);
366
- i0.ɵɵtext(53);
355
+ i0.ɵɵelementStart(41, "div", 31)(42, "div", 32);
356
+ i0.ɵɵtext(43);
367
357
  i0.ɵɵelementEnd();
368
- i0.ɵɵelementStart(54, "div", 48);
369
- i0.ɵɵtext(55, "Expiring Soon");
358
+ i0.ɵɵelementStart(44, "div", 33);
359
+ i0.ɵɵtext(45, "Expiring Soon");
370
360
  i0.ɵɵelementEnd()();
371
- i0.ɵɵconditionalCreate(56, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_56_Template, 2, 0, "div", 56);
361
+ i0.ɵɵconditionalCreate(46, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_46_Template, 2, 0, "div", 41);
372
362
  i0.ɵɵelementEnd();
373
- i0.ɵɵelementStart(57, "div", 44);
374
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template_div_click_57_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("revoked")); });
375
- i0.ɵɵelementStart(58, "div", 45);
376
- i0.ɵɵelement(59, "i", 57);
363
+ i0.ɵɵelementStart(47, "div", 28);
364
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_47_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("revoked")); });
365
+ i0.ɵɵelementStart(48, "div", 29);
366
+ i0.ɵɵelement(49, "i", 42);
377
367
  i0.ɵɵelementEnd();
378
- i0.ɵɵelementStart(60, "div", 46)(61, "div", 47);
379
- i0.ɵɵtext(62);
368
+ i0.ɵɵelementStart(50, "div", 31)(51, "div", 32);
369
+ i0.ɵɵtext(52);
380
370
  i0.ɵɵelementEnd();
381
- i0.ɵɵelementStart(63, "div", 48);
382
- i0.ɵɵtext(64, "Revoked");
371
+ i0.ɵɵelementStart(53, "div", 33);
372
+ i0.ɵɵtext(54, "Revoked");
383
373
  i0.ɵɵelementEnd()()();
384
- i0.ɵɵelementStart(65, "div", 44);
385
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template_div_click_65_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.switchTab("scopes")); });
386
- i0.ɵɵelementStart(66, "div", 45);
387
- i0.ɵɵelement(67, "i", 14);
374
+ i0.ɵɵelementStart(55, "div", 28);
375
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_55_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.switchTab("scopes")); });
376
+ i0.ɵɵelementStart(56, "div", 29);
377
+ i0.ɵɵelement(57, "i", 43);
388
378
  i0.ɵɵelementEnd();
389
- i0.ɵɵelementStart(68, "div", 46)(69, "div", 47);
390
- i0.ɵɵtext(70);
379
+ i0.ɵɵelementStart(58, "div", 31)(59, "div", 32);
380
+ i0.ɵɵtext(60);
391
381
  i0.ɵɵelementEnd();
392
- i0.ɵɵelementStart(71, "div", 48);
393
- i0.ɵɵtext(72, "Scope Categories");
382
+ i0.ɵɵelementStart(61, "div", 33);
383
+ i0.ɵɵtext(62, "Scope Categories");
394
384
  i0.ɵɵelementEnd()()()();
395
- i0.ɵɵelementStart(73, "div", 58)(74, "div", 59)(75, "div", 60)(76, "div", 61);
396
- i0.ɵɵelement(77, "i", 8);
397
- i0.ɵɵelementStart(78, "span");
398
- i0.ɵɵtext(79, "Recently Used Keys");
385
+ i0.ɵɵelementStart(63, "div", 44)(64, "div", 45)(65, "div", 46)(66, "div", 47);
386
+ i0.ɵɵelement(67, "i", 30);
387
+ i0.ɵɵelementStart(68, "span");
388
+ i0.ɵɵtext(69, "Recently Used Keys");
399
389
  i0.ɵɵelementEnd()();
400
- i0.ɵɵelementStart(80, "button", 62);
401
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template_button_click_80_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
402
- i0.ɵɵtext(81, " View All ");
403
- i0.ɵɵelement(82, "i", 50);
390
+ i0.ɵɵelementStart(70, "button", 48);
391
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_button_click_70_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
392
+ i0.ɵɵtext(71, " View All ");
393
+ i0.ɵɵelement(72, "i", 35);
404
394
  i0.ɵɵelementEnd()();
405
- i0.ɵɵelementStart(83, "div", 63);
406
- i0.ɵɵconditionalCreate(84, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_84_Template, 3, 0, "div", 64);
407
- i0.ɵɵconditionalCreate(85, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_85_Template, 4, 0, "div", 65);
395
+ i0.ɵɵelementStart(73, "div", 49);
396
+ i0.ɵɵconditionalCreate(74, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_Template, 3, 0, "div", 50);
397
+ i0.ɵɵconditionalCreate(75, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_75_Template, 4, 0, "div", 51);
408
398
  i0.ɵɵelementEnd()();
409
- i0.ɵɵelementStart(86, "div", 66)(87, "div", 60)(88, "div", 61);
410
- i0.ɵɵelement(89, "i", 14);
411
- i0.ɵɵelementStart(90, "span");
412
- i0.ɵɵtext(91, "Permission Scopes");
399
+ i0.ɵɵelementStart(76, "div", 52)(77, "div", 46)(78, "div", 47);
400
+ i0.ɵɵelement(79, "i", 43);
401
+ i0.ɵɵelementStart(80, "span");
402
+ i0.ɵɵtext(81, "Permission Scopes");
413
403
  i0.ɵɵelementEnd()();
414
- i0.ɵɵelementStart(92, "span", 67);
415
- i0.ɵɵtext(93, "Available scope categories");
404
+ i0.ɵɵelementStart(82, "span", 53);
405
+ i0.ɵɵtext(83, "Available scope categories");
416
406
  i0.ɵɵelementEnd()();
417
- i0.ɵɵelementStart(94, "div", 63);
418
- i0.ɵɵconditionalCreate(95, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_95_Template, 14, 1, "div", 68);
419
- i0.ɵɵconditionalCreate(96, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_96_Template, 4, 0, "div", 65);
407
+ i0.ɵɵelementStart(84, "div", 49);
408
+ i0.ɵɵconditionalCreate(85, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_Template, 14, 1, "div", 54);
409
+ i0.ɵɵconditionalCreate(86, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_86_Template, 4, 0, "div", 51);
420
410
  i0.ɵɵelementEnd()();
421
- i0.ɵɵelementStart(97, "div", 69)(98, "div", 60)(99, "div", 61);
422
- i0.ɵɵelement(100, "i", 70);
423
- i0.ɵɵelementStart(101, "span");
424
- i0.ɵɵtext(102, "Recent Activity");
411
+ i0.ɵɵelementStart(87, "div", 55)(88, "div", 46)(89, "div", 47);
412
+ i0.ɵɵelement(90, "i", 56);
413
+ i0.ɵɵelementStart(91, "span");
414
+ i0.ɵɵtext(92, "Recent Activity");
425
415
  i0.ɵɵelementEnd()()();
426
- i0.ɵɵelementStart(103, "div", 63);
427
- i0.ɵɵconditionalCreate(104, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_104_Template, 3, 0, "div", 71);
428
- i0.ɵɵconditionalCreate(105, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_105_Template, 4, 0, "div", 65);
416
+ i0.ɵɵelementStart(93, "div", 49);
417
+ i0.ɵɵconditionalCreate(94, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_Template, 3, 0, "div", 57);
418
+ i0.ɵɵconditionalCreate(95, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_95_Template, 4, 0, "div", 51);
429
419
  i0.ɵɵelementEnd()()();
430
- i0.ɵɵconditionalCreate(106, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Conditional_106_Template, 20, 0, "div", 72);
431
- i0.ɵɵelementStart(107, "div", 73);
432
- i0.ɵɵelement(108, "i", 74);
433
- i0.ɵɵelementStart(109, "div", 75)(110, "strong");
434
- i0.ɵɵtext(111, "Security Best Practices:");
420
+ i0.ɵɵconditionalCreate(96, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template, 20, 0, "div", 58);
421
+ i0.ɵɵelementStart(97, "div", 59);
422
+ i0.ɵɵelement(98, "i", 60);
423
+ i0.ɵɵelementStart(99, "div", 61)(100, "strong");
424
+ i0.ɵɵtext(101, "Security Best Practices:");
435
425
  i0.ɵɵelementEnd();
436
- i0.ɵɵtext(112, " API keys should be rotated regularly and revoked when no longer needed. Keys are hashed and stored securely - the raw key is only shown once at creation time. All API key usage is logged for audit purposes. ");
426
+ i0.ɵɵtext(102, " API keys should be rotated regularly and revoked when no longer needed. Keys are hashed and stored securely - the raw key is only shown once at creation time. All API key usage is logged for audit purposes. ");
437
427
  i0.ɵɵelementEnd()();
438
428
  } if (rf & 2) {
439
429
  const ctx_r1 = i0.ɵɵnextContext(3);
440
- i0.ɵɵadvance(9);
441
- i0.ɵɵconditional(ctx_r1.UserCanCreateKeys ? 9 : -1);
442
- i0.ɵɵadvance();
443
430
  i0.ɵɵproperty("ngClass", ctx_r1.getHealthClass());
444
431
  i0.ɵɵadvance(5);
445
432
  i0.ɵɵattribute("stroke-dasharray", ctx_r1.getHealthScore() + ", 100");
@@ -448,13 +435,13 @@ function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Tem
448
435
  i0.ɵɵadvance(3);
449
436
  i0.ɵɵtextInterpolate(ctx_r1.getHealthLabel());
450
437
  i0.ɵɵadvance(2);
451
- i0.ɵɵconditional(ctx_r1.ExpiredKeys > 0 ? 22 : -1);
438
+ i0.ɵɵconditional(ctx_r1.ExpiredKeys > 0 ? 12 : -1);
452
439
  i0.ɵɵadvance();
453
- i0.ɵɵconditional(ctx_r1.ExpiringSoonCount > 0 ? 23 : -1);
440
+ i0.ɵɵconditional(ctx_r1.ExpiringSoonCount > 0 ? 13 : -1);
454
441
  i0.ɵɵadvance();
455
- i0.ɵɵconditional(ctx_r1.NeverUsedKeys > 0 ? 24 : -1);
442
+ i0.ɵɵconditional(ctx_r1.NeverUsedKeys > 0 ? 14 : -1);
456
443
  i0.ɵɵadvance();
457
- i0.ɵɵconditional(ctx_r1.ExpiredKeys === 0 && ctx_r1.ExpiringSoonCount === 0 && ctx_r1.NeverUsedKeys === 0 ? 25 : -1);
444
+ i0.ɵɵconditional(ctx_r1.ExpiredKeys === 0 && ctx_r1.ExpiringSoonCount === 0 && ctx_r1.NeverUsedKeys === 0 ? 15 : -1);
458
445
  i0.ɵɵadvance(7);
459
446
  i0.ɵɵtextInterpolate(ctx_r1.TotalKeys);
460
447
  i0.ɵɵadvance(10);
@@ -466,7 +453,7 @@ function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Tem
466
453
  i0.ɵɵadvance(5);
467
454
  i0.ɵɵtextInterpolate(ctx_r1.ExpiringSoonCount);
468
455
  i0.ɵɵadvance(3);
469
- i0.ɵɵconditional(ctx_r1.ExpiringSoonCount > 0 ? 56 : -1);
456
+ i0.ɵɵconditional(ctx_r1.ExpiringSoonCount > 0 ? 46 : -1);
470
457
  i0.ɵɵadvance();
471
458
  i0.ɵɵclassProp("danger", ctx_r1.RevokedKeys > 0);
472
459
  i0.ɵɵadvance(5);
@@ -474,138 +461,76 @@ function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Tem
474
461
  i0.ɵɵadvance(8);
475
462
  i0.ɵɵtextInterpolate(ctx_r1.ScopeStats.length);
476
463
  i0.ɵɵadvance(14);
477
- i0.ɵɵconditional(ctx_r1.TopUsedKeys.length > 0 ? 84 : -1);
464
+ i0.ɵɵconditional(ctx_r1.TopUsedKeys.length > 0 ? 74 : -1);
478
465
  i0.ɵɵadvance();
479
- i0.ɵɵconditional(ctx_r1.TopUsedKeys.length === 0 ? 85 : -1);
466
+ i0.ɵɵconditional(ctx_r1.TopUsedKeys.length === 0 ? 75 : -1);
480
467
  i0.ɵɵadvance(10);
481
- i0.ɵɵconditional(ctx_r1.ScopeStats.length > 0 ? 95 : -1);
468
+ i0.ɵɵconditional(ctx_r1.ScopeStats.length > 0 ? 85 : -1);
482
469
  i0.ɵɵadvance();
483
- i0.ɵɵconditional(ctx_r1.ScopeStats.length === 0 ? 96 : -1);
470
+ i0.ɵɵconditional(ctx_r1.ScopeStats.length === 0 ? 86 : -1);
484
471
  i0.ɵɵadvance(8);
485
- i0.ɵɵconditional(ctx_r1.RecentActivity.length > 0 ? 104 : -1);
472
+ i0.ɵɵconditional(ctx_r1.RecentActivity.length > 0 ? 94 : -1);
486
473
  i0.ɵɵadvance();
487
- i0.ɵɵconditional(ctx_r1.RecentActivity.length === 0 ? 105 : -1);
474
+ i0.ɵɵconditional(ctx_r1.RecentActivity.length === 0 ? 95 : -1);
488
475
  i0.ɵɵadvance();
489
- i0.ɵɵconditional(ctx_r1.UserCanCreateKeys ? 106 : -1);
476
+ i0.ɵɵconditional(ctx_r1.UserCanCreateKeys ? 96 : -1);
490
477
  } }
491
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_1_Template(rf, ctx) { if (rf & 1) {
492
- const _r18 = i0.ɵɵgetCurrentView();
493
- i0.ɵɵelementStart(0, "div", 123)(1, "button", 124);
494
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showOverview()); });
495
- i0.ɵɵelement(2, "i", 125);
478
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
479
+ const _r17 = i0.ɵɵgetCurrentView();
480
+ i0.ɵɵelementStart(0, "div", 108)(1, "button", 109);
481
+ i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showOverview()); });
482
+ i0.ɵɵelement(2, "i", 110);
496
483
  i0.ɵɵtext(3, " Back to Overview ");
497
484
  i0.ɵɵelementEnd()();
498
- i0.ɵɵelementStart(4, "mj-api-key-list", 126, 0);
499
- i0.ɵɵlistener("KeySelected", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_1_Template_mj_api_key_list_KeySelected_4_listener($event) { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onKeySelected($event)); })("CreateRequested", function APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_1_Template_mj_api_key_list_CreateRequested_4_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
485
+ i0.ɵɵelementStart(4, "mj-api-key-list", 111, 0);
486
+ i0.ɵɵlistener("KeySelected", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template_mj_api_key_list_KeySelected_4_listener($event) { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onKeySelected($event)); })("CreateRequested", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template_mj_api_key_list_CreateRequested_4_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
500
487
  i0.ɵɵelementEnd();
501
488
  } if (rf & 2) {
502
489
  const ctx_r1 = i0.ɵɵnextContext(3);
503
490
  i0.ɵɵadvance(4);
504
491
  i0.ɵɵproperty("Filter", ctx_r1.ListFilter);
505
492
  } }
506
- function APIKeysResourceComponent_Conditional_2_Conditional_31_Template(rf, ctx) { if (rf & 1) {
507
- i0.ɵɵconditionalCreate(0, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_0_Template, 113, 27);
508
- i0.ɵɵconditionalCreate(1, APIKeysResourceComponent_Conditional_2_Conditional_31_Conditional_1_Template, 6, 1);
493
+ function APIKeysResourceComponent_Conditional_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
494
+ i0.ɵɵconditionalCreate(0, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template, 103, 26);
495
+ i0.ɵɵconditionalCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template, 6, 1);
509
496
  } if (rf & 2) {
510
497
  const ctx_r1 = i0.ɵɵnextContext(2);
511
498
  i0.ɵɵconditional(ctx_r1.CurrentView === "overview" ? 0 : -1);
512
499
  i0.ɵɵadvance();
513
500
  i0.ɵɵconditional(ctx_r1.CurrentView === "list" ? 1 : -1);
514
501
  } }
515
- function APIKeysResourceComponent_Conditional_2_Conditional_32_Template(rf, ctx) { if (rf & 1) {
516
- const _r19 = i0.ɵɵgetCurrentView();
517
- i0.ɵɵelementStart(0, "mj-api-applications-panel", 127);
518
- i0.ɵɵlistener("ApplicationUpdated", function APIKeysResourceComponent_Conditional_2_Conditional_32_Template_mj_api_applications_panel_ApplicationUpdated_0_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDataUpdated()); });
502
+ function APIKeysResourceComponent_Conditional_7_Conditional_2_Template(rf, ctx) { if (rf & 1) {
503
+ const _r18 = i0.ɵɵgetCurrentView();
504
+ i0.ɵɵelementStart(0, "mj-api-applications-panel", 112);
505
+ i0.ɵɵlistener("ApplicationUpdated", function APIKeysResourceComponent_Conditional_7_Conditional_2_Template_mj_api_applications_panel_ApplicationUpdated_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDataUpdated()); });
519
506
  i0.ɵɵelementEnd();
520
507
  } }
521
- function APIKeysResourceComponent_Conditional_2_Conditional_33_Template(rf, ctx) { if (rf & 1) {
522
- const _r20 = i0.ɵɵgetCurrentView();
523
- i0.ɵɵelementStart(0, "mj-api-scopes-panel", 128);
524
- i0.ɵɵlistener("ScopeUpdated", function APIKeysResourceComponent_Conditional_2_Conditional_33_Template_mj_api_scopes_panel_ScopeUpdated_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDataUpdated()); });
508
+ function APIKeysResourceComponent_Conditional_7_Conditional_3_Template(rf, ctx) { if (rf & 1) {
509
+ const _r19 = i0.ɵɵgetCurrentView();
510
+ i0.ɵɵelementStart(0, "mj-api-scopes-panel", 113);
511
+ i0.ɵɵlistener("ScopeUpdated", function APIKeysResourceComponent_Conditional_7_Conditional_3_Template_mj_api_scopes_panel_ScopeUpdated_0_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDataUpdated()); });
525
512
  i0.ɵɵelementEnd();
526
513
  } }
527
- function APIKeysResourceComponent_Conditional_2_Conditional_34_Template(rf, ctx) { if (rf & 1) {
514
+ function APIKeysResourceComponent_Conditional_7_Conditional_4_Template(rf, ctx) { if (rf & 1) {
528
515
  i0.ɵɵelement(0, "mj-api-usage-panel");
529
516
  } }
530
- function APIKeysResourceComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
531
- const _r1 = i0.ɵɵgetCurrentView();
532
- i0.ɵɵelementStart(0, "div", 5)(1, "div", 6)(2, "div", 7);
533
- i0.ɵɵelement(3, "i", 8);
534
- i0.ɵɵelementStart(4, "span");
535
- i0.ɵɵtext(5, "API Keys");
536
- i0.ɵɵelementEnd()()();
537
- i0.ɵɵelementStart(6, "div", 9)(7, "button", 10);
538
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.switchTab("keys"); return i0.ɵɵresetView(ctx_r1.closeNav()); });
539
- i0.ɵɵelement(8, "i", 8);
540
- i0.ɵɵelementStart(9, "span", 11);
541
- i0.ɵɵtext(10, "API Keys");
542
- i0.ɵɵelementEnd();
543
- i0.ɵɵelementStart(11, "span", 12);
544
- i0.ɵɵtext(12);
545
- i0.ɵɵelementEnd()();
546
- i0.ɵɵelementStart(13, "button", 10);
547
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.switchTab("applications"); return i0.ɵɵresetView(ctx_r1.closeNav()); });
548
- i0.ɵɵelement(14, "i", 13);
549
- i0.ɵɵelementStart(15, "span", 11);
550
- i0.ɵɵtext(16, "Applications");
551
- i0.ɵɵelementEnd();
552
- i0.ɵɵelementStart(17, "span", 12);
553
- i0.ɵɵtext(18);
554
- i0.ɵɵelementEnd()();
555
- i0.ɵɵelementStart(19, "button", 10);
556
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.switchTab("scopes"); return i0.ɵɵresetView(ctx_r1.closeNav()); });
557
- i0.ɵɵelement(20, "i", 14);
558
- i0.ɵɵelementStart(21, "span", 11);
559
- i0.ɵɵtext(22, "Scopes");
560
- i0.ɵɵelementEnd();
561
- i0.ɵɵelementStart(23, "span", 12);
562
- i0.ɵɵtext(24);
563
- i0.ɵɵelementEnd()();
564
- i0.ɵɵelementStart(25, "button", 10);
565
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Template_button_click_25_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.switchTab("usage"); return i0.ɵɵresetView(ctx_r1.closeNav()); });
566
- i0.ɵɵelement(26, "i", 15);
567
- i0.ɵɵelementStart(27, "span", 11);
568
- i0.ɵɵtext(28, "Usage Analytics");
569
- i0.ɵɵelementEnd()()()();
570
- i0.ɵɵelementStart(29, "div", 16)(30, "div", 17);
571
- i0.ɵɵconditionalCreate(31, APIKeysResourceComponent_Conditional_2_Conditional_31_Template, 2, 2);
572
- i0.ɵɵconditionalCreate(32, APIKeysResourceComponent_Conditional_2_Conditional_32_Template, 1, 0, "mj-api-applications-panel");
573
- i0.ɵɵconditionalCreate(33, APIKeysResourceComponent_Conditional_2_Conditional_33_Template, 1, 0, "mj-api-scopes-panel");
574
- i0.ɵɵconditionalCreate(34, APIKeysResourceComponent_Conditional_2_Conditional_34_Template, 1, 0, "mj-api-usage-panel");
575
- i0.ɵɵelementEnd()();
576
- i0.ɵɵelementStart(35, "button", 18);
577
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Template_button_click_35_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleNav()); });
578
- i0.ɵɵelement(36, "i", 19);
579
- i0.ɵɵelementEnd();
580
- i0.ɵɵelementStart(37, "div", 20);
581
- i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_2_Template_div_click_37_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeNav()); });
517
+ function APIKeysResourceComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
518
+ i0.ɵɵelementStart(0, "mj-page-body-interior");
519
+ i0.ɵɵconditionalCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Template, 2, 2);
520
+ i0.ɵɵconditionalCreate(2, APIKeysResourceComponent_Conditional_7_Conditional_2_Template, 1, 0, "mj-api-applications-panel");
521
+ i0.ɵɵconditionalCreate(3, APIKeysResourceComponent_Conditional_7_Conditional_3_Template, 1, 0, "mj-api-scopes-panel");
522
+ i0.ɵɵconditionalCreate(4, APIKeysResourceComponent_Conditional_7_Conditional_4_Template, 1, 0, "mj-api-usage-panel");
582
523
  i0.ɵɵelementEnd();
583
524
  } if (rf & 2) {
584
525
  const ctx_r1 = i0.ɵɵnextContext();
585
- i0.ɵɵadvance(7);
586
- i0.ɵɵclassProp("active", ctx_r1.MainTab === "keys");
587
- i0.ɵɵadvance(5);
588
- i0.ɵɵtextInterpolate(ctx_r1.TotalKeys);
589
526
  i0.ɵɵadvance();
590
- i0.ɵɵclassProp("active", ctx_r1.MainTab === "applications");
591
- i0.ɵɵadvance(5);
592
- i0.ɵɵtextInterpolate(ctx_r1.ApplicationCount);
527
+ i0.ɵɵconditional(ctx_r1.MainTab === "keys" ? 1 : -1);
593
528
  i0.ɵɵadvance();
594
- i0.ɵɵclassProp("active", ctx_r1.MainTab === "scopes");
595
- i0.ɵɵadvance(5);
596
- i0.ɵɵtextInterpolate(ctx_r1.ScopeCount);
529
+ i0.ɵɵconditional(ctx_r1.MainTab === "applications" ? 2 : -1);
597
530
  i0.ɵɵadvance();
598
- i0.ɵɵclassProp("active", ctx_r1.MainTab === "usage");
599
- i0.ɵɵadvance(6);
600
- i0.ɵɵconditional(ctx_r1.MainTab === "keys" ? 31 : -1);
531
+ i0.ɵɵconditional(ctx_r1.MainTab === "scopes" ? 3 : -1);
601
532
  i0.ɵɵadvance();
602
- i0.ɵɵconditional(ctx_r1.MainTab === "applications" ? 32 : -1);
603
- i0.ɵɵadvance();
604
- i0.ɵɵconditional(ctx_r1.MainTab === "scopes" ? 33 : -1);
605
- i0.ɵɵadvance();
606
- i0.ɵɵconditional(ctx_r1.MainTab === "usage" ? 34 : -1);
607
- i0.ɵɵadvance(2);
608
- i0.ɵɵclassProp("fa-bars", !ctx_r1.NavOpen)("fa-times", ctx_r1.NavOpen);
533
+ i0.ɵɵconditional(ctx_r1.MainTab === "usage" ? 4 : -1);
609
534
  } }
610
535
  /**
611
536
  * API Keys Resource Component
@@ -624,7 +549,6 @@ let APIKeysResourceComponent = class APIKeysResourceComponent extends BaseResour
624
549
  CurrentView = 'overview';
625
550
  ListFilter = 'all';
626
551
  MainTab = 'keys';
627
- NavOpen = false;
628
552
  // Application and scope counts for tab badges
629
553
  ApplicationCount = 0;
630
554
  ScopeCount = 0;
@@ -1073,26 +997,50 @@ let APIKeysResourceComponent = class APIKeysResourceComponent extends BaseResour
1073
997
  this.MainTab = 'scopes';
1074
998
  }
1075
999
  /**
1076
- * Switch to a main tab
1000
+ * Switch to a main tab. Resets to the overview view when returning to the
1001
+ * Keys tab so the user always lands on the dashboard, not a stale list view.
1077
1002
  */
1078
1003
  switchTab(tab) {
1079
1004
  this.MainTab = tab;
1080
- // Reset to overview when switching back to keys
1081
1005
  if (tab === 'keys') {
1082
1006
  this.CurrentView = 'overview';
1083
1007
  }
1084
1008
  }
1085
1009
  /**
1086
- * Toggle mobile navigation
1010
+ * L2 tabs rendered as `<mj-tab-nav>` in the interior chrome's [toolbar] slot.
1011
+ * Badges reflect live counts; Usage Analytics has no badge by design.
1087
1012
  */
1088
- toggleNav() {
1089
- this.NavOpen = !this.NavOpen;
1013
+ get tabsConfig() {
1014
+ return [
1015
+ { key: 'keys', icon: 'fa-solid fa-key', label: 'API Keys', badge: this.TotalKeys },
1016
+ { key: 'applications', icon: 'fa-solid fa-cube', label: 'Applications', badge: this.ApplicationCount },
1017
+ { key: 'scopes', icon: 'fa-solid fa-shield-halved', label: 'Scopes', badge: this.ScopeCount },
1018
+ { key: 'usage', icon: 'fa-solid fa-chart-line', label: 'Usage Analytics' }
1019
+ ];
1090
1020
  }
1091
- /**
1092
- * Close mobile navigation
1093
- */
1094
- closeNav() {
1095
- this.NavOpen = false;
1021
+ /** Adapter for `<mj-tab-nav>`'s string-typed `(TabChange)` output. */
1022
+ onTabChange(key) {
1023
+ if (key === 'keys' || key === 'applications' || key === 'scopes' || key === 'usage') {
1024
+ this.switchTab(key);
1025
+ }
1026
+ }
1027
+ /** Title rendered in the interior chrome — varies per tab. */
1028
+ get currentTabTitle() {
1029
+ switch (this.MainTab) {
1030
+ case 'keys': return 'API Keys';
1031
+ case 'applications': return 'API Applications';
1032
+ case 'scopes': return 'API Scopes';
1033
+ case 'usage': return 'Usage Analytics';
1034
+ }
1035
+ }
1036
+ /** Subtitle rendered in the interior chrome — varies per tab to give context. */
1037
+ get currentTabSubtitle() {
1038
+ switch (this.MainTab) {
1039
+ case 'keys': return 'Manage API keys for external integrations and services';
1040
+ case 'applications': return 'Register and manage API applications';
1041
+ case 'scopes': return 'Permission scopes that can be granted to API keys';
1042
+ case 'usage': return 'Track usage patterns and analytics across all API keys';
1043
+ }
1096
1044
  }
1097
1045
  /**
1098
1046
  * Handle updates from child panels
@@ -1107,27 +1055,37 @@ let APIKeysResourceComponent = class APIKeysResourceComponent extends BaseResour
1107
1055
  } if (rf & 2) {
1108
1056
  let _t;
1109
1057
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.keyListComponent = _t.first);
1110
- } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 9, consts: [["keyList", ""], [1, "api-keys-dashboard"], ["text", "Loading API Keys..."], [3, "Created", "Closed", "Visible"], [3, "Updated", "Revoked", "Closed", "Visible", "KeyId"], [1, "dashboard-nav"], [1, "nav-header"], [1, "nav-title"], [1, "fa-solid", "fa-key"], [1, "nav-items"], [1, "nav-item", 3, "click"], [1, "nav-label"], [1, "nav-badge"], [1, "fa-solid", "fa-cube"], [1, "fa-solid", "fa-shield-halved"], [1, "fa-solid", "fa-chart-line"], [1, "dashboard-content"], [1, "content-wrapper"], [1, "mobile-nav-toggle", 3, "click"], [1, "fa-solid"], [1, "mobile-nav-overlay", 3, "click"], [1, "overview-header"], [1, "header-left"], [1, "overview-title"], [1, "overview-subtitle"], [1, "header-actions"], ["title", "Refresh", 1, "btn-refresh", 3, "click"], [1, "fa-solid", "fa-refresh"], [1, "btn-primary"], [1, "health-banner", 3, "ngClass"], [1, "health-score-container"], [1, "health-score-ring"], ["viewBox", "0 0 36 36", 1, "circular-chart"], ["d", "M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831", 1, "circle-bg"], ["d", "M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831", 1, "circle"], [1, "health-score-value"], [1, "health-info"], [1, "health-label"], [1, "health-details"], [1, "health-alert"], [1, "health-warning-text"], [1, "health-info-text"], [1, "health-ok"], [1, "kpi-row"], [1, "kpi-card", "clickable", 3, "click"], [1, "kpi-icon"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-trend"], [1, "fa-solid", "fa-arrow-right"], [1, "kpi-card", "active", "clickable", 3, "click"], [1, "fa-solid", "fa-check-circle"], [1, "kpi-trend", "success"], [1, "percentage"], [1, "fa-solid", "fa-clock"], [1, "kpi-trend", "warning"], [1, "fa-solid", "fa-ban"], [1, "content-grid"], [1, "panel", "keys-panel"], [1, "panel-header"], [1, "panel-title"], [1, "panel-action", 3, "click"], [1, "panel-body"], [1, "key-list"], [1, "empty-state"], [1, "panel", "scope-panel"], [1, "panel-subtitle"], [1, "scope-chart"], [1, "panel", "activity-panel"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "activity-list"], [1, "quick-actions"], [1, "security-notice"], [1, "fa-solid", "fa-shield-check"], [1, "notice-content"], [1, "btn-primary", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "health-alert", 3, "click"], [1, "fa-solid", "fa-circle-exclamation"], [1, "health-warning-text", 3, "click"], [1, "health-info-text", 3, "click"], [1, "fa-solid", "fa-question-circle"], [1, "key-item"], [1, "key-item", 3, "click"], [1, "key-icon"], [1, "key-info"], [1, "key-label"], [1, "key-meta"], [1, "key-user"], [1, "key-hash"], [1, "key-status"], [1, "last-used"], [1, "expiration", 3, "ngClass"], [1, "donut-chart-container"], ["viewBox", "0 0 100 100", 1, "donut-chart"], ["cx", "50", "cy", "50", "r", "40", "fill", "none", "stroke", "#e5e7eb", "stroke-width", "12"], [1, "donut-center"], [1, "donut-total"], [1, "donut-label"], [1, "scope-legend"], [1, "legend-item"], ["cx", "50", "cy", "50", "r", "40", "fill", "none", "stroke-width", "12", 1, "donut-segment", 3, "click"], [1, "legend-item", 3, "click"], [1, "legend-color"], [1, "legend-info"], [1, "legend-name"], [1, "legend-value"], [1, "fa-solid", "fa-chevron-right", "legend-arrow"], [1, "activity-item"], [1, "activity-item", 3, "click"], [1, "activity-icon", 3, "ngClass"], [1, "activity-info"], [1, "activity-name"], [1, "activity-meta"], [1, "activity-action"], [1, "activity-user"], [1, "activity-time"], [1, "fa-solid", "fa-inbox"], [1, "quick-actions-title"], [1, "quick-actions-grid"], [1, "quick-action", 3, "click"], [1, "fa-solid", "fa-list"], [1, "list-view-header"], [1, "back-btn", 3, "click"], [1, "fa-solid", "fa-arrow-left"], [3, "KeySelected", "CreateRequested", "Filter"], [3, "ApplicationUpdated"], [3, "ScopeUpdated"]], template: function APIKeysResourceComponent_Template(rf, ctx) { if (rf & 1) {
1111
- i0.ɵɵelementStart(0, "div", 1);
1112
- i0.ɵɵconditionalCreate(1, APIKeysResourceComponent_Conditional_1_Template, 1, 0, "mj-loading", 2);
1113
- i0.ɵɵconditionalCreate(2, APIKeysResourceComponent_Conditional_2_Template, 38, 19);
1114
- i0.ɵɵelementStart(3, "mj-api-key-create-dialog", 3);
1115
- i0.ɵɵlistener("Created", function APIKeysResourceComponent_Template_mj_api_key_create_dialog_Created_3_listener($event) { return ctx.onKeyCreated($event); })("Closed", function APIKeysResourceComponent_Template_mj_api_key_create_dialog_Closed_3_listener() { return ctx.onCreateDialogClosed(); });
1058
+ } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 10, vars: 10, consts: [["keyList", ""], ["Role", "region", "AriaLabel", "API Keys", 3, "Title", "Subtitle"], ["toolbar", ""], [3, "TabChange", "Tabs", "ActiveKey"], ["actions", ""], [3, "Clicked", "Loading"], ["mjButton", "", "variant", "primary", "size", "sm", "aria-label", "Generate a new API key"], [1, "api-keys-loading"], [3, "Created", "Closed", "Visible"], [3, "Updated", "Revoked", "Closed", "Visible", "KeyId"], ["mjButton", "", "variant", "primary", "size", "sm", "aria-label", "Generate a new API key", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], ["text", "Loading API Keys..."], [1, "health-banner", 3, "ngClass"], [1, "health-score-container"], [1, "health-score-ring"], ["viewBox", "0 0 36 36", 1, "circular-chart"], ["d", "M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831", 1, "circle-bg"], ["d", "M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831", 1, "circle"], [1, "health-score-value"], [1, "health-info"], [1, "health-label"], [1, "health-details"], [1, "health-alert"], [1, "health-warning-text"], [1, "health-info-text"], [1, "health-ok"], [1, "kpi-row"], [1, "kpi-card", "clickable", 3, "click"], [1, "kpi-icon"], [1, "fa-solid", "fa-key"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-trend"], [1, "fa-solid", "fa-arrow-right"], [1, "kpi-card", "active", "clickable", 3, "click"], [1, "fa-solid", "fa-check-circle"], [1, "kpi-trend", "success"], [1, "percentage"], [1, "fa-solid", "fa-clock"], [1, "kpi-trend", "warning"], [1, "fa-solid", "fa-ban"], [1, "fa-solid", "fa-shield-halved"], [1, "content-grid"], [1, "panel", "keys-panel"], [1, "panel-header"], [1, "panel-title"], [1, "panel-action", 3, "click"], [1, "panel-body"], [1, "key-list"], [1, "empty-state"], [1, "panel", "scope-panel"], [1, "panel-subtitle"], [1, "scope-chart"], [1, "panel", "activity-panel"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "activity-list"], [1, "quick-actions"], [1, "security-notice"], [1, "fa-solid", "fa-shield-check"], [1, "notice-content"], [1, "health-alert", 3, "click"], [1, "fa-solid", "fa-circle-exclamation"], [1, "health-warning-text", 3, "click"], [1, "health-info-text", 3, "click"], [1, "fa-solid", "fa-question-circle"], [1, "key-item"], [1, "key-item", 3, "click"], [1, "key-icon"], [1, "key-info"], [1, "key-label"], [1, "key-meta"], [1, "key-user"], [1, "key-hash"], [1, "key-status"], [1, "last-used"], [1, "expiration", 3, "ngClass"], [1, "donut-chart-container"], ["viewBox", "0 0 100 100", 1, "donut-chart"], ["cx", "50", "cy", "50", "r", "40", "fill", "none", "stroke", "#e5e7eb", "stroke-width", "12"], [1, "donut-center"], [1, "donut-total"], [1, "donut-label"], [1, "scope-legend"], [1, "legend-item"], ["cx", "50", "cy", "50", "r", "40", "fill", "none", "stroke-width", "12", 1, "donut-segment", 3, "click"], [1, "legend-item", 3, "click"], [1, "legend-color"], [1, "legend-info"], [1, "legend-name"], [1, "legend-value"], [1, "fa-solid", "fa-chevron-right", "legend-arrow"], [1, "activity-item"], [1, "activity-item", 3, "click"], [1, "activity-icon", 3, "ngClass"], [1, "activity-info"], [1, "activity-name"], [1, "activity-meta"], [1, "activity-action"], [1, "activity-user"], [1, "activity-time"], [1, "fa-solid", "fa-inbox"], [1, "quick-actions-title"], [1, "quick-actions-grid"], [1, "quick-action", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fa-solid", "fa-list"], [1, "list-view-header"], [1, "back-btn", 3, "click"], [1, "fa-solid", "fa-arrow-left"], [3, "KeySelected", "CreateRequested", "Filter"], [3, "ApplicationUpdated"], [3, "ScopeUpdated"]], template: function APIKeysResourceComponent_Template(rf, ctx) { if (rf & 1) {
1059
+ i0.ɵɵelementStart(0, "mj-page-header-interior", 1)(1, "div", 2)(2, "mj-tab-nav", 3);
1060
+ i0.ɵɵlistener("TabChange", function APIKeysResourceComponent_Template_mj_tab_nav_TabChange_2_listener($event) { return ctx.onTabChange($event); });
1061
+ i0.ɵɵelementEnd()();
1062
+ i0.ɵɵelementStart(3, "div", 4)(4, "mj-refresh-button", 5);
1063
+ i0.ɵɵlistener("Clicked", function APIKeysResourceComponent_Template_mj_refresh_button_Clicked_4_listener() { return ctx.refresh(); });
1116
1064
  i0.ɵɵelementEnd();
1117
- i0.ɵɵelementStart(4, "mj-api-key-edit-panel", 4);
1118
- i0.ɵɵlistener("Updated", function APIKeysResourceComponent_Template_mj_api_key_edit_panel_Updated_4_listener() { return ctx.onKeyUpdated(); })("Revoked", function APIKeysResourceComponent_Template_mj_api_key_edit_panel_Revoked_4_listener() { return ctx.onKeyRevoked(); })("Closed", function APIKeysResourceComponent_Template_mj_api_key_edit_panel_Closed_4_listener() { return ctx.onEditPanelClosed(); });
1065
+ i0.ɵɵconditionalCreate(5, APIKeysResourceComponent_Conditional_5_Template, 3, 0, "button", 6);
1119
1066
  i0.ɵɵelementEnd()();
1067
+ i0.ɵɵconditionalCreate(6, APIKeysResourceComponent_Conditional_6_Template, 2, 0, "div", 7)(7, APIKeysResourceComponent_Conditional_7_Template, 5, 4, "mj-page-body-interior");
1068
+ i0.ɵɵelementStart(8, "mj-api-key-create-dialog", 8);
1069
+ i0.ɵɵlistener("Created", function APIKeysResourceComponent_Template_mj_api_key_create_dialog_Created_8_listener($event) { return ctx.onKeyCreated($event); })("Closed", function APIKeysResourceComponent_Template_mj_api_key_create_dialog_Closed_8_listener() { return ctx.onCreateDialogClosed(); });
1070
+ i0.ɵɵelementEnd();
1071
+ i0.ɵɵelementStart(9, "mj-api-key-edit-panel", 9);
1072
+ i0.ɵɵlistener("Updated", function APIKeysResourceComponent_Template_mj_api_key_edit_panel_Updated_9_listener() { return ctx.onKeyUpdated(); })("Revoked", function APIKeysResourceComponent_Template_mj_api_key_edit_panel_Revoked_9_listener() { return ctx.onKeyRevoked(); })("Closed", function APIKeysResourceComponent_Template_mj_api_key_edit_panel_Closed_9_listener() { return ctx.onEditPanelClosed(); });
1073
+ i0.ɵɵelementEnd();
1120
1074
  } if (rf & 2) {
1121
- i0.ɵɵclassProp("panel-open", ctx.ShowCreateDialog || ctx.ShowEditPanel)("nav-open", ctx.NavOpen);
1122
- i0.ɵɵadvance();
1123
- i0.ɵɵconditional(ctx.IsLoading ? 1 : -1);
1075
+ i0.ɵɵproperty("Title", ctx.currentTabTitle)("Subtitle", ctx.currentTabSubtitle);
1076
+ i0.ɵɵadvance(2);
1077
+ i0.ɵɵproperty("Tabs", ctx.tabsConfig)("ActiveKey", ctx.MainTab);
1078
+ i0.ɵɵadvance(2);
1079
+ i0.ɵɵproperty("Loading", ctx.IsLoading);
1124
1080
  i0.ɵɵadvance();
1125
- i0.ɵɵconditional(!ctx.IsLoading ? 2 : -1);
1081
+ i0.ɵɵconditional(ctx.MainTab === "keys" && ctx.CurrentView === "overview" && ctx.UserCanCreateKeys ? 5 : -1);
1126
1082
  i0.ɵɵadvance();
1083
+ i0.ɵɵconditional(ctx.IsLoading ? 6 : 7);
1084
+ i0.ɵɵadvance(2);
1127
1085
  i0.ɵɵproperty("Visible", ctx.ShowCreateDialog);
1128
1086
  i0.ɵɵadvance();
1129
1087
  i0.ɵɵproperty("Visible", ctx.ShowEditPanel)("KeyId", ctx.SelectedKeyId);
1130
- } }, dependencies: [i1.NgClass, i2.LoadingComponent, i3.APIKeyCreateDialogComponent, i4.APIKeyEditPanelComponent, i5.APIKeyListComponent, i6.APIApplicationsPanelComponent, i7.APIScopesPanelComponent, i8.APIUsagePanelComponent], styles: ["\n\n.api-keys-dashboard[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.api-keys-dashboard.panel-open[_ngcontent-%COMP%] .dashboard-content[_ngcontent-%COMP%] {\n overflow: hidden;\n}\n\n\n\n.dashboard-nav[_ngcontent-%COMP%] {\n width: 220px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n}\n\n.nav-header[_ngcontent-%COMP%] {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.nav-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 700;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n\n.nav-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 18px;\n}\n\n.nav-items[_ngcontent-%COMP%] {\n flex: 1;\n padding: 12px;\n overflow-y: auto;\n}\n\n.nav-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 4px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n width: 100%;\n text-align: left;\n}\n\n.nav-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.nav-item.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n.nav-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n.nav-item[_ngcontent-%COMP%] .nav-label[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.nav-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 20px;\n padding: 0 6px;\n background: var(--mj-bg-surface-active);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.nav-item.active[_ngcontent-%COMP%] .nav-badge[_ngcontent-%COMP%] {\n background: rgba(255, 255, 255, 0.25);\n}\n\n\n\n.dashboard-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n min-width: 0;\n}\n\n.content-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n\n\n.list-view-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.back-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n\n.overview-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.overview-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.overview-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n}\n\n.btn-refresh[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-refresh[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.btn-refresh[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n\n\n.health-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-color-accent-300);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error-border);\n}\n\n.health-score-container[_ngcontent-%COMP%] {\n margin-right: 24px;\n}\n\n.health-score-ring[_ngcontent-%COMP%] {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart[_ngcontent-%COMP%] {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg[_ngcontent-%COMP%] {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 3.8;\n}\n\n.circle[_ngcontent-%COMP%] {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: var(--mj-status-success);\n animation: _ngcontent-%COMP%_progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] .circle[_ngcontent-%COMP%] {\n stroke: var(--mj-color-warning-500);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] .circle[_ngcontent-%COMP%] {\n stroke: var(--mj-status-error);\n}\n\n@keyframes _ngcontent-%COMP%_progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.health-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.health-label[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-color-success-600);\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] .health-label[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] .health-label[_ngcontent-%COMP%] {\n color: var(--mj-color-error-600);\n}\n\n.health-details[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-error-600);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-warning-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary-hover);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-info-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-ok[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-success-600);\n font-weight: 500;\n font-size: 14px;\n}\n\n\n\n.kpi-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.kpi-card.clickable[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.kpi-card.active[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n}\n\n.kpi-card.warning[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-color-warning-500) 0%, var(--mj-brand-primary-hover) 100%);\n}\n\n.kpi-card.danger[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-status-error) 0%, var(--mj-color-error-600) 100%);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-text-inverse);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--mj-text-muted);\n}\n\n.kpi-trend.success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.kpi-trend.warning[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n}\n\n.kpi-trend[_ngcontent-%COMP%] .percentage[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n}\n\n\n\n.content-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel[_ngcontent-%COMP%] {\n grid-row: span 1;\n}\n\n.scope-panel[_ngcontent-%COMP%] {\n grid-row: span 1;\n}\n\n.activity-panel[_ngcontent-%COMP%] {\n grid-column: span 2;\n}\n\n.panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.panel-subtitle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.panel-body[_ngcontent-%COMP%] {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n\n\n.key-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.key-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--mj-color-neutral-500) 0%, var(--mj-color-neutral-600) 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.key-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-text-inverse);\n}\n\n.key-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.key-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.key-hash[_ngcontent-%COMP%] {\n font-family: monospace;\n background: var(--mj-bg-surface-active);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.expiration[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.expiration.expiring-soon[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n font-weight: 500;\n}\n\n.expiration.expiring-critical[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.expiration.expired[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n\n\n.scope-chart[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container[_ngcontent-%COMP%] {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment[_ngcontent-%COMP%]:hover {\n opacity: 0.8;\n}\n\n.donut-center[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.donut-label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.scope-legend[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.legend-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-value[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-arrow[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n\n\n.activity-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.activity-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, var(--mj-color-brand-100));\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.activity-icon.action-created[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n}\n\n.activity-icon.action-created[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-success-600);\n}\n\n.activity-icon.action-updated[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-100);\n}\n\n.activity-icon.action-updated[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-indigo-500);\n}\n\n.activity-icon.action-revoked[_ngcontent-%COMP%] {\n background: var(--mj-color-error-100);\n}\n\n.activity-icon.action-revoked[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-error-600);\n}\n\n.activity-icon.action-used[_ngcontent-%COMP%] {\n background: var(--mj-color-brand-100);\n}\n\n.activity-icon.action-used[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n}\n\n.activity-icon.action-extended[_ngcontent-%COMP%] {\n background: var(--mj-color-info-100);\n}\n\n.activity-icon.action-extended[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n}\n\n.activity-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name[_ngcontent-%COMP%] {\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.activity-action[_ngcontent-%COMP%] {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n\n\n.quick-actions[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.quick-actions-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n transform: translateY(-2px);\n}\n\n.quick-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.quick-action[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n\n\n.security-notice[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, var(--mj-color-brand-50) 0%, var(--mj-color-brand-100) 100%);\n border-radius: 12px;\n border: 1px solid var(--mj-color-accent-300);\n}\n\n.security-notice[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-brand-primary);\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-color-brand-800);\n line-height: 1.5;\n}\n\n.notice-content[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n\n\n.mobile-nav-toggle[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 50%;\n color: var(--mj-text-inverse);\n font-size: 24px;\n box-shadow: var(--mj-shadow-brand-md);\n cursor: pointer;\n z-index: 50;\n transition: transform 0.2s ease;\n}\n\n.mobile-nav-toggle[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.mobile-nav-overlay[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 90;\n}\n\n\n\n\n\n\n\n\n@media (max-width: 1024px) {\n .content-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .activity-panel[_ngcontent-%COMP%] {\n grid-column: span 1;\n }\n\n .scope-chart[_ngcontent-%COMP%] {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container[_ngcontent-%COMP%] {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .dashboard-nav[_ngcontent-%COMP%] {\n width: 200px;\n }\n}\n\n\n\n@media (max-width: 768px) {\n .api-keys-dashboard[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .dashboard-nav[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: -280px;\n width: 280px;\n height: 100%;\n z-index: 100;\n transition: left 0.3s ease;\n box-shadow: var(--mj-shadow-xl);\n }\n\n .api-keys-dashboard.nav-open[_ngcontent-%COMP%] .dashboard-nav[_ngcontent-%COMP%] {\n left: 0;\n }\n\n .mobile-nav-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.3s ease;\n }\n\n .api-keys-dashboard.nav-open[_ngcontent-%COMP%] .mobile-nav-overlay[_ngcontent-%COMP%] {\n opacity: 1;\n pointer-events: auto;\n }\n\n .dashboard-content[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .content-wrapper[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .overview-header[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: flex-end;\n }\n\n .health-banner[_ngcontent-%COMP%] {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container[_ngcontent-%COMP%] {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .quick-actions-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .key-item[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .key-status[_ngcontent-%COMP%] {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n\n\n@media (max-width: 480px) {\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .kpi-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .overview-title[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .btn-primary[_ngcontent-%COMP%] {\n padding: 8px 16px;\n font-size: 13px;\n }\n}"] });
1088
+ } }, dependencies: [i1.NgClass, i2.MJButtonDirective, i2.MJPageHeaderInteriorComponent, i2.MJPageBodyInteriorComponent, i2.MJRefreshButtonComponent, i2.MJTabNavComponent, i3.LoadingComponent, i4.APIKeyCreateDialogComponent, i5.APIKeyEditPanelComponent, i6.APIKeyListComponent, i7.APIApplicationsPanelComponent, i8.APIScopesPanelComponent, i9.APIUsagePanelComponent], styles: ["\n\n\n\n\n\n\n[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n.api-keys-loading[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n\n\n.list-view-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.back-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n\n.health-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-color-accent-300);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error-border);\n}\n\n.health-score-container[_ngcontent-%COMP%] {\n margin-right: 24px;\n}\n\n.health-score-ring[_ngcontent-%COMP%] {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart[_ngcontent-%COMP%] {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg[_ngcontent-%COMP%] {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 3.8;\n}\n\n.circle[_ngcontent-%COMP%] {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: var(--mj-status-success);\n animation: _ngcontent-%COMP%_progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] .circle[_ngcontent-%COMP%] {\n stroke: var(--mj-color-warning-500);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] .circle[_ngcontent-%COMP%] {\n stroke: var(--mj-status-error);\n}\n\n@keyframes _ngcontent-%COMP%_progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.health-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.health-label[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-color-success-600);\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] .health-label[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] .health-label[_ngcontent-%COMP%] {\n color: var(--mj-color-error-600);\n}\n\n.health-details[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-error-600);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-warning-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary-hover);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-info-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-ok[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-success-600);\n font-weight: 500;\n font-size: 14px;\n}\n\n\n\n.kpi-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.kpi-card.clickable[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.kpi-card.active[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n}\n\n.kpi-card.warning[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-color-warning-500) 0%, var(--mj-brand-primary-hover) 100%);\n}\n\n.kpi-card.danger[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-status-error) 0%, var(--mj-color-error-600) 100%);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-text-inverse);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--mj-text-muted);\n}\n\n.kpi-trend.success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.kpi-trend.warning[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n}\n\n.kpi-trend[_ngcontent-%COMP%] .percentage[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n}\n\n\n\n.content-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel[_ngcontent-%COMP%] {\n grid-row: span 1;\n}\n\n.scope-panel[_ngcontent-%COMP%] {\n grid-row: span 1;\n}\n\n.activity-panel[_ngcontent-%COMP%] {\n grid-column: span 2;\n}\n\n.panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.panel-subtitle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.panel-body[_ngcontent-%COMP%] {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n\n\n.key-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.key-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--mj-color-neutral-500) 0%, var(--mj-color-neutral-600) 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.key-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-text-inverse);\n}\n\n.key-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.key-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.key-hash[_ngcontent-%COMP%] {\n font-family: monospace;\n background: var(--mj-bg-surface-active);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.expiration[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.expiration.expiring-soon[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n font-weight: 500;\n}\n\n.expiration.expiring-critical[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.expiration.expired[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n\n\n.scope-chart[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container[_ngcontent-%COMP%] {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment[_ngcontent-%COMP%]:hover {\n opacity: 0.8;\n}\n\n.donut-center[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.donut-label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.scope-legend[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.legend-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-value[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-arrow[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n\n\n.activity-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.activity-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, var(--mj-color-brand-100));\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.activity-icon.action-created[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n}\n\n.activity-icon.action-created[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-success-600);\n}\n\n.activity-icon.action-updated[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-100);\n}\n\n.activity-icon.action-updated[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-indigo-500);\n}\n\n.activity-icon.action-revoked[_ngcontent-%COMP%] {\n background: var(--mj-color-error-100);\n}\n\n.activity-icon.action-revoked[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-error-600);\n}\n\n.activity-icon.action-used[_ngcontent-%COMP%] {\n background: var(--mj-color-brand-100);\n}\n\n.activity-icon.action-used[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n}\n\n.activity-icon.action-extended[_ngcontent-%COMP%] {\n background: var(--mj-color-info-100);\n}\n\n.activity-icon.action-extended[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n}\n\n.activity-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name[_ngcontent-%COMP%] {\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.activity-action[_ngcontent-%COMP%] {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n\n\n.quick-actions[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.quick-actions-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n transform: translateY(-2px);\n}\n\n.quick-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.quick-action[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n\n\n.security-notice[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, var(--mj-color-brand-50) 0%, var(--mj-color-brand-100) 100%);\n border-radius: 12px;\n border: 1px solid var(--mj-color-accent-300);\n}\n\n.security-notice[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-brand-primary);\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-color-brand-800);\n line-height: 1.5;\n}\n\n.notice-content[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n\n\n\n\n\n\n\n\n@media (max-width: 1024px) {\n .content-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .activity-panel[_ngcontent-%COMP%] {\n grid-column: span 1;\n }\n\n .scope-chart[_ngcontent-%COMP%] {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container[_ngcontent-%COMP%] {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend[_ngcontent-%COMP%] {\n flex: 1;\n }\n}\n\n\n\n@media (max-width: 768px) {\n .content-wrapper[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .health-banner[_ngcontent-%COMP%] {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container[_ngcontent-%COMP%] {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .quick-actions-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .key-item[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .key-status[_ngcontent-%COMP%] {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n\n\n@media (max-width: 480px) {\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .kpi-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n}"] });
1131
1089
  };
1132
1090
  APIKeysResourceComponent = __decorate([
1133
1091
  RegisterClass(BaseResourceComponent, 'APIKeysResource')
@@ -1135,10 +1093,10 @@ APIKeysResourceComponent = __decorate([
1135
1093
  export { APIKeysResourceComponent };
1136
1094
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIKeysResourceComponent, [{
1137
1095
  type: Component,
1138
- args: [{ standalone: false, selector: 'mj-api-keys-resource', template: "<div class=\"api-keys-dashboard\" [class.panel-open]=\"ShowCreateDialog || ShowEditPanel\" [class.nav-open]=\"NavOpen\">\n @if (IsLoading) {\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Left Navigation Sidebar -->\n <div class=\"dashboard-nav\">\n <div class=\"nav-header\">\n <div class=\"nav-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>API Keys</span>\n </div>\n </div>\n <div class=\"nav-items\">\n <button class=\"nav-item\" [class.active]=\"MainTab === 'keys'\" (click)=\"switchTab('keys'); closeNav()\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"nav-label\">API Keys</span>\n <span class=\"nav-badge\">{{TotalKeys}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'applications'\" (click)=\"switchTab('applications'); closeNav()\">\n <i class=\"fa-solid fa-cube\"></i>\n <span class=\"nav-label\">Applications</span>\n <span class=\"nav-badge\">{{ApplicationCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'scopes'\" (click)=\"switchTab('scopes'); closeNav()\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"nav-label\">Scopes</span>\n <span class=\"nav-badge\">{{ScopeCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'usage'\" (click)=\"switchTab('usage'); closeNav()\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <span class=\"nav-label\">Usage Analytics</span>\n </button>\n </div>\n </div>\n <!-- Main Content Area -->\n <div class=\"dashboard-content\">\n <div class=\"content-wrapper\">\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View -->\n @if (CurrentView === 'overview') {\n <!-- Header with Actions -->\n <div class=\"overview-header\">\n <div class=\"header-left\">\n <h2 class=\"overview-title\">API Keys Management</h2>\n <p class=\"overview-subtitle\">Manage API keys for external integrations and services</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-refresh\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n @if (UserCanCreateKeys) {\n <button class=\"btn-primary\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate New Key</span>\n </button>\n }\n </div>\n </div>\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </div><!-- /.content-wrapper -->\n </div><!-- /.dashboard-content -->\n <!-- Mobile Navigation Toggle -->\n <button class=\"mobile-nav-toggle\" (click)=\"toggleNav()\">\n <i class=\"fa-solid\" [class.fa-bars]=\"!NavOpen\" [class.fa-times]=\"NavOpen\"></i>\n </button>\n <!-- Mobile Navigation Overlay -->\n <div class=\"mobile-nav-overlay\" (click)=\"closeNav()\"></div>\n }\n\n <!-- Create Dialog -->\n <mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n </mj-api-key-create-dialog>\n\n <!-- Edit Panel -->\n <mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n </mj-api-key-edit-panel>\n</div>\n", styles: ["/* Main Dashboard Container */\n.api-keys-dashboard {\n display: flex;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.api-keys-dashboard.panel-open .dashboard-content {\n overflow: hidden;\n}\n\n/* Left Navigation Sidebar */\n.dashboard-nav {\n width: 220px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n}\n\n.nav-header {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.nav-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 700;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n\n.nav-title i {\n color: var(--mj-brand-primary);\n font-size: 18px;\n}\n\n.nav-items {\n flex: 1;\n padding: 12px;\n overflow-y: auto;\n}\n\n.nav-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 4px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n width: 100%;\n text-align: left;\n}\n\n.nav-item:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.nav-item.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n.nav-item i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n.nav-item .nav-label {\n flex: 1;\n}\n\n.nav-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 20px;\n padding: 0 6px;\n background: var(--mj-bg-surface-active);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.nav-item.active .nav-badge {\n background: rgba(255, 255, 255, 0.25);\n}\n\n/* Dashboard Content Area */\n.dashboard-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n min-width: 0;\n}\n\n.content-wrapper {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n/* List View Header */\n.list-view-header {\n margin-bottom: 16px;\n}\n\n.back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Header */\n.overview-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left {\n flex: 1;\n}\n\n.overview-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.overview-subtitle {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions {\n display: flex;\n gap: 12px;\n}\n\n.btn-refresh {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-refresh:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.btn-refresh i {\n color: var(--mj-text-secondary);\n}\n\n.btn-primary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n/* Health Banner */\n.health-banner {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-color-accent-300);\n}\n\n.health-banner.health-critical {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error-border);\n}\n\n.health-score-container {\n margin-right: 24px;\n}\n\n.health-score-ring {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 3.8;\n}\n\n.circle {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: var(--mj-status-success);\n animation: progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning .circle {\n stroke: var(--mj-color-warning-500);\n}\n\n.health-banner.health-critical .circle {\n stroke: var(--mj-status-error);\n}\n\n@keyframes progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.health-info {\n flex: 1;\n}\n\n.health-label {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-color-success-600);\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning .health-label {\n color: var(--mj-brand-primary-hover);\n}\n\n.health-banner.health-critical .health-label {\n color: var(--mj-color-error-600);\n}\n\n.health-details {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-error-600);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert:hover {\n text-decoration: underline;\n}\n\n.health-warning-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary-hover);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text:hover {\n text-decoration: underline;\n}\n\n.health-info-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text:hover {\n text-decoration: underline;\n}\n\n.health-ok {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-success-600);\n font-weight: 500;\n font-size: 14px;\n}\n\n/* KPI Cards */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable {\n cursor: pointer;\n}\n\n.kpi-card.clickable:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.kpi-card.active .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n}\n\n.kpi-card.warning .kpi-icon {\n background: linear-gradient(135deg, var(--mj-color-warning-500) 0%, var(--mj-brand-primary-hover) 100%);\n}\n\n.kpi-card.danger .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-error) 0%, var(--mj-color-error-600) 100%);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon i {\n font-size: 20px;\n color: var(--mj-text-inverse);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--mj-text-muted);\n}\n\n.kpi-trend.success {\n color: var(--mj-status-success);\n}\n\n.kpi-trend.warning {\n color: var(--mj-color-warning-500);\n}\n\n.kpi-trend .percentage {\n font-size: 12px;\n font-weight: 600;\n}\n\n/* Content Grid */\n.content-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel {\n grid-row: span 1;\n}\n\n.scope-panel {\n grid-row: span 1;\n}\n\n.activity-panel {\n grid-column: span 2;\n}\n\n.panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.panel-title i {\n color: var(--mj-brand-primary);\n}\n\n.panel-subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-action {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.panel-body {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Key List */\n.key-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.key-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--mj-color-neutral-500) 0%, var(--mj-color-neutral-600) 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active {\n background: var(--mj-brand-primary);\n}\n\n.key-icon i {\n font-size: 16px;\n color: var(--mj-text-inverse);\n}\n\n.key-info {\n flex: 1;\n min-width: 0;\n}\n\n.key-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.key-hash {\n font-family: monospace;\n background: var(--mj-bg-surface-active);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.expiration {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.expiration.expiring-soon {\n color: var(--mj-color-warning-500);\n font-weight: 500;\n}\n\n.expiration.expiring-critical {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.expiration.expired {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n/* Scope Chart */\n.scope-chart {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment:hover {\n opacity: 0.8;\n}\n\n.donut-center {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.donut-label {\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n/* Scope Legend */\n.scope-legend {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info {\n flex: 1;\n}\n\n.legend-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name i {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-value {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n/* Activity List */\n.activity-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.activity-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, var(--mj-color-brand-100));\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.activity-icon.action-created {\n background: var(--mj-color-success-100);\n}\n\n.activity-icon.action-created i {\n color: var(--mj-color-success-600);\n}\n\n.activity-icon.action-updated {\n background: var(--mj-color-indigo-100);\n}\n\n.activity-icon.action-updated i {\n color: var(--mj-color-indigo-500);\n}\n\n.activity-icon.action-revoked {\n background: var(--mj-color-error-100);\n}\n\n.activity-icon.action-revoked i {\n color: var(--mj-color-error-600);\n}\n\n.activity-icon.action-used {\n background: var(--mj-color-brand-100);\n}\n\n.activity-icon.action-used i {\n color: var(--mj-brand-primary-hover);\n}\n\n.activity-icon.action-extended {\n background: var(--mj-color-info-100);\n}\n\n.activity-icon.action-extended i {\n color: var(--mj-status-info);\n}\n\n.activity-info {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name {\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.activity-action {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n/* Quick Actions */\n.quick-actions {\n margin-bottom: 24px;\n}\n\n.quick-actions-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n transform: translateY(-2px);\n}\n\n.quick-action i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.quick-action span {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n/* Security Notice */\n.security-notice {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, var(--mj-color-brand-50) 0%, var(--mj-color-brand-100) 100%);\n border-radius: 12px;\n border: 1px solid var(--mj-color-accent-300);\n}\n\n.security-notice i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content {\n font-size: 13px;\n color: var(--mj-color-brand-800);\n line-height: 1.5;\n}\n\n.notice-content strong {\n font-weight: 600;\n}\n\n/* Mobile Navigation Toggle */\n.mobile-nav-toggle {\n display: none;\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 50%;\n color: var(--mj-text-inverse);\n font-size: 24px;\n box-shadow: var(--mj-shadow-brand-md);\n cursor: pointer;\n z-index: 50;\n transition: transform 0.2s ease;\n}\n\n.mobile-nav-toggle:hover {\n transform: scale(1.05);\n}\n\n/* Mobile Nav Overlay */\n.mobile-nav-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 90;\n}\n\n/* ========================================\n Responsive Styles\n ======================================== */\n\n/* Tablet */\n@media (max-width: 1024px) {\n .content-grid {\n grid-template-columns: 1fr;\n }\n\n .activity-panel {\n grid-column: span 1;\n }\n\n .scope-chart {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend {\n flex: 1;\n }\n\n .dashboard-nav {\n width: 200px;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .api-keys-dashboard {\n flex-direction: column;\n }\n\n .dashboard-nav {\n position: fixed;\n top: 0;\n left: -280px;\n width: 280px;\n height: 100%;\n z-index: 100;\n transition: left 0.3s ease;\n box-shadow: var(--mj-shadow-xl);\n }\n\n .api-keys-dashboard.nav-open .dashboard-nav {\n left: 0;\n }\n\n .mobile-nav-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .mobile-nav-overlay {\n display: block;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.3s ease;\n }\n\n .api-keys-dashboard.nav-open .mobile-nav-overlay {\n opacity: 1;\n pointer-events: auto;\n }\n\n .dashboard-content {\n width: 100%;\n }\n\n .content-wrapper {\n padding: 16px;\n }\n\n .overview-header {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: flex-end;\n }\n\n .health-banner {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart {\n flex-direction: column;\n }\n\n .quick-actions-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list {\n grid-template-columns: 1fr;\n }\n\n .key-item {\n flex-wrap: wrap;\n }\n\n .key-status {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n/* Small Mobile */\n@media (max-width: 480px) {\n .kpi-row {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 12px 16px;\n }\n\n .kpi-icon {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n\n .overview-title {\n font-size: 20px;\n }\n\n .btn-primary {\n padding: 8px 16px;\n font-size: 13px;\n }\n}\n"] }]
1096
+ args: [{ standalone: false, selector: 'mj-api-keys-resource', template: "<!--\n APIKeysResource is only ever loaded inside Admin \u2192 Identity & Access's\n left-nav shell. Per Section 9b/10 of plans/explorer-chrome-conventions.md,\n shell sub-pages must NOT render a page-level <mj-page-layout>+<mj-page-header>\n (that produces a doubled-header). Instead the body opens with an\n <mj-page-header-interior> card carrying the L2 tab nav and action chrome.\n-->\n<mj-page-header-interior\n Role=\"region\"\n AriaLabel=\"API Keys\"\n [Title]=\"currentTabTitle\"\n [Subtitle]=\"currentTabSubtitle\">\n <div toolbar>\n <mj-tab-nav\n [Tabs]=\"tabsConfig\"\n [ActiveKey]=\"MainTab\"\n (TabChange)=\"onTabChange($event)\">\n </mj-tab-nav>\n </div>\n <div actions>\n <mj-refresh-button [Loading]=\"IsLoading\" (Clicked)=\"refresh()\"></mj-refresh-button>\n @if (MainTab === 'keys' && CurrentView === 'overview' && UserCanCreateKeys) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"openCreateDialog()\" aria-label=\"Generate a new API key\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n Generate New Key\n </button>\n }\n </div>\n</mj-page-header-interior>\n\n@if (IsLoading) {\n <div class=\"api-keys-loading\">\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n </div>\n} @else {\n <mj-page-body-interior>\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View \u2014 title + Refresh + Generate New Key now live in the page chrome above. -->\n @if (CurrentView === 'overview') {\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </mj-page-body-interior>\n}\n\n<!-- Create Dialog -->\n<mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n</mj-api-key-create-dialog>\n\n<!-- Edit Panel -->\n<mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n</mj-api-key-edit-panel>\n", styles: ["/*\n APIKeysResource renders as a sub-page inside Admin \u2192 Identity & Access's\n left-nav shell. Host is a flex column so <mj-page-header-interior> pins at\n the top and <mj-page-body-interior> fills the rest. See Section 10 of\n plans/explorer-chrome-conventions.md.\n*/\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n.api-keys-loading {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* List View Header */\n.list-view-header {\n margin-bottom: 16px;\n}\n\n.back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Health Banner */\n.health-banner {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-color-accent-300);\n}\n\n.health-banner.health-critical {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error-border);\n}\n\n.health-score-container {\n margin-right: 24px;\n}\n\n.health-score-ring {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 3.8;\n}\n\n.circle {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: var(--mj-status-success);\n animation: progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning .circle {\n stroke: var(--mj-color-warning-500);\n}\n\n.health-banner.health-critical .circle {\n stroke: var(--mj-status-error);\n}\n\n@keyframes progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.health-info {\n flex: 1;\n}\n\n.health-label {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-color-success-600);\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning .health-label {\n color: var(--mj-brand-primary-hover);\n}\n\n.health-banner.health-critical .health-label {\n color: var(--mj-color-error-600);\n}\n\n.health-details {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-error-600);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert:hover {\n text-decoration: underline;\n}\n\n.health-warning-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary-hover);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text:hover {\n text-decoration: underline;\n}\n\n.health-info-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text:hover {\n text-decoration: underline;\n}\n\n.health-ok {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-success-600);\n font-weight: 500;\n font-size: 14px;\n}\n\n/* KPI Cards */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable {\n cursor: pointer;\n}\n\n.kpi-card.clickable:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.kpi-card.active .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n}\n\n.kpi-card.warning .kpi-icon {\n background: linear-gradient(135deg, var(--mj-color-warning-500) 0%, var(--mj-brand-primary-hover) 100%);\n}\n\n.kpi-card.danger .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-error) 0%, var(--mj-color-error-600) 100%);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon i {\n font-size: 20px;\n color: var(--mj-text-inverse);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--mj-text-muted);\n}\n\n.kpi-trend.success {\n color: var(--mj-status-success);\n}\n\n.kpi-trend.warning {\n color: var(--mj-color-warning-500);\n}\n\n.kpi-trend .percentage {\n font-size: 12px;\n font-weight: 600;\n}\n\n/* Content Grid */\n.content-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel {\n grid-row: span 1;\n}\n\n.scope-panel {\n grid-row: span 1;\n}\n\n.activity-panel {\n grid-column: span 2;\n}\n\n.panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.panel-title i {\n color: var(--mj-brand-primary);\n}\n\n.panel-subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-action {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.panel-body {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Key List */\n.key-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.key-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--mj-color-neutral-500) 0%, var(--mj-color-neutral-600) 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active {\n background: var(--mj-brand-primary);\n}\n\n.key-icon i {\n font-size: 16px;\n color: var(--mj-text-inverse);\n}\n\n.key-info {\n flex: 1;\n min-width: 0;\n}\n\n.key-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.key-hash {\n font-family: monospace;\n background: var(--mj-bg-surface-active);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.expiration {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.expiration.expiring-soon {\n color: var(--mj-color-warning-500);\n font-weight: 500;\n}\n\n.expiration.expiring-critical {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.expiration.expired {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n/* Scope Chart */\n.scope-chart {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment:hover {\n opacity: 0.8;\n}\n\n.donut-center {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.donut-label {\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n/* Scope Legend */\n.scope-legend {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info {\n flex: 1;\n}\n\n.legend-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name i {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-value {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n/* Activity List */\n.activity-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.activity-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, var(--mj-color-brand-100));\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.activity-icon.action-created {\n background: var(--mj-color-success-100);\n}\n\n.activity-icon.action-created i {\n color: var(--mj-color-success-600);\n}\n\n.activity-icon.action-updated {\n background: var(--mj-color-indigo-100);\n}\n\n.activity-icon.action-updated i {\n color: var(--mj-color-indigo-500);\n}\n\n.activity-icon.action-revoked {\n background: var(--mj-color-error-100);\n}\n\n.activity-icon.action-revoked i {\n color: var(--mj-color-error-600);\n}\n\n.activity-icon.action-used {\n background: var(--mj-color-brand-100);\n}\n\n.activity-icon.action-used i {\n color: var(--mj-brand-primary-hover);\n}\n\n.activity-icon.action-extended {\n background: var(--mj-color-info-100);\n}\n\n.activity-icon.action-extended i {\n color: var(--mj-status-info);\n}\n\n.activity-info {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name {\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.activity-action {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n/* Quick Actions */\n.quick-actions {\n margin-bottom: 24px;\n}\n\n.quick-actions-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n transform: translateY(-2px);\n}\n\n.quick-action i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.quick-action span {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n/* Security Notice */\n.security-notice {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, var(--mj-color-brand-50) 0%, var(--mj-color-brand-100) 100%);\n border-radius: 12px;\n border: 1px solid var(--mj-color-accent-300);\n}\n\n.security-notice i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content {\n font-size: 13px;\n color: var(--mj-color-brand-800);\n line-height: 1.5;\n}\n\n.notice-content strong {\n font-weight: 600;\n}\n\n/* ========================================\n Responsive Styles \u2014 chrome / nav responsiveness now owned by\n <mj-page-layout> + <mj-left-nav>; only inner content needs tuning here.\n ======================================== */\n\n/* Tablet */\n@media (max-width: 1024px) {\n .content-grid {\n grid-template-columns: 1fr;\n }\n\n .activity-panel {\n grid-column: span 1;\n }\n\n .scope-chart {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend {\n flex: 1;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .content-wrapper {\n padding: 16px;\n }\n\n .health-banner {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart {\n flex-direction: column;\n }\n\n .quick-actions-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list {\n grid-template-columns: 1fr;\n }\n\n .key-item {\n flex-wrap: wrap;\n }\n\n .key-status {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n/* Small Mobile */\n@media (max-width: 480px) {\n .kpi-row {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 12px 16px;\n }\n\n .kpi-icon {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n}\n"] }]
1139
1097
  }], () => [{ type: i0.ChangeDetectorRef }], { keyListComponent: [{
1140
1098
  type: ViewChild,
1141
1099
  args: ['keyList']
1142
1100
  }] }); })();
1143
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(APIKeysResourceComponent, { className: "APIKeysResourceComponent", filePath: "src/APIKeys/api-keys-resource.component.ts", lineNumber: 52 }); })();
1101
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(APIKeysResourceComponent, { className: "APIKeysResourceComponent", filePath: "src/APIKeys/api-keys-resource.component.ts", lineNumber: 53 }); })();
1144
1102
  //# sourceMappingURL=api-keys-resource.component.js.map