@memberjunction/ng-dashboards 5.38.0 → 5.40.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 (321) hide show
  1. package/README.md +14 -7
  2. package/dist/AI/components/agents/agent-configuration.component.js +199 -198
  3. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -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 +20 -17
  6. package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
  7. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
  8. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
  9. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
  10. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
  11. package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
  12. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
  13. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
  14. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
  15. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
  16. package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
  17. package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
  18. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
  19. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
  20. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
  21. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
  22. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
  23. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
  24. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
  25. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
  26. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +217 -860
  27. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  28. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1717 -7802
  29. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  30. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts +56 -0
  31. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts.map +1 -0
  32. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js +423 -0
  33. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js.map +1 -0
  34. package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts +70 -0
  35. package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts.map +1 -0
  36. package/dist/AI/components/autotagging/components/classify-item-grid.component.js +308 -0
  37. package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -0
  38. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts +29 -0
  39. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -0
  40. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +186 -0
  41. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -0
  42. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts +69 -0
  43. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts.map +1 -0
  44. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js +278 -0
  45. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js.map +1 -0
  46. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts +73 -0
  47. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts.map +1 -0
  48. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js +393 -0
  49. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js.map +1 -0
  50. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts +122 -0
  51. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts.map +1 -0
  52. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js +908 -0
  53. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js.map +1 -0
  54. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
  55. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
  56. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
  57. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
  58. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
  59. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
  60. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
  61. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
  62. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
  63. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
  64. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
  65. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
  66. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +333 -0
  67. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
  68. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +2125 -0
  69. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
  70. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
  71. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
  72. package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
  73. package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
  74. package/dist/AI/components/autotagging/shared/classify.format.d.ts +58 -0
  75. package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
  76. package/dist/AI/components/autotagging/shared/classify.format.js +260 -0
  77. package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
  78. package/dist/AI/components/autotagging/shared/classify.types.d.ts +319 -0
  79. package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
  80. package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
  81. package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
  82. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
  83. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
  84. package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
  85. package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
  86. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +77 -0
  87. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
  88. package/dist/AI/components/autotagging/tabs/history-tab.component.js +519 -0
  89. package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
  90. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
  91. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
  92. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
  93. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
  94. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +131 -0
  95. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
  96. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +813 -0
  97. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
  98. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +177 -0
  99. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
  100. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1465 -0
  101. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
  102. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +78 -0
  103. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
  104. package/dist/AI/components/autotagging/tabs/tags-tab.component.js +492 -0
  105. package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
  106. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
  107. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
  108. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
  109. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
  110. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +56 -0
  111. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
  112. package/dist/AI/components/autotagging/tabs/types-tab.component.js +271 -0
  113. package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
  114. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +3 -0
  115. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  116. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +306 -290
  117. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  118. package/dist/AI/components/execution-monitoring.component.js +1 -1
  119. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  120. package/dist/AI/components/models/model-management.component.js +209 -208
  121. package/dist/AI/components/models/model-management.component.js.map +1 -1
  122. package/dist/AI/components/prompts/prompt-management.component.js +130 -128
  123. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  124. package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
  125. package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
  126. package/dist/AI/components/system/system-configuration.component.js +17 -17
  127. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  128. package/dist/AI/components/tags/tags-resource.component.d.ts +1 -0
  129. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  130. package/dist/AI/components/tags/tags-resource.component.js +578 -538
  131. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  132. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +3 -0
  133. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  134. package/dist/AI/components/vectors/vector-management-resource.component.js +331 -303
  135. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  136. package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
  137. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  138. package/dist/AI/services/ai-instrumentation.service.js +14 -2
  139. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  140. package/dist/AI/services/cache-metrics.d.ts +50 -0
  141. package/dist/AI/services/cache-metrics.d.ts.map +1 -0
  142. package/dist/AI/services/cache-metrics.js +43 -0
  143. package/dist/AI/services/cache-metrics.js.map +1 -0
  144. package/dist/APIKeys/api-applications-panel.component.js +2 -2
  145. package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
  146. package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
  147. package/dist/APIKeys/api-keys-resource.component.js +132 -131
  148. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  149. package/dist/Actions/components/actions-overview.component.js +141 -141
  150. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  151. package/dist/Actions/components/execution-monitoring.component.js +15 -15
  152. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  153. package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
  154. package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
  155. package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
  156. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  157. package/dist/Admin/admin-data-schema.component.js +2 -2
  158. package/dist/Admin/admin-data-schema.component.js.map +1 -1
  159. package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
  160. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
  161. package/dist/Admin/admin-identity-access.component.js +2 -2
  162. package/dist/Admin/admin-identity-access.component.js.map +1 -1
  163. package/dist/Admin/admin-monitoring.component.js +2 -2
  164. package/dist/Admin/admin-monitoring.component.js.map +1 -1
  165. package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
  166. package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
  167. package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
  168. package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
  169. package/dist/Communication/communication-logs-resource.component.js +72 -50
  170. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  171. package/dist/Communication/communication-monitor-resource.component.js +103 -102
  172. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  173. package/dist/Communication/communication-providers-resource.component.js +52 -51
  174. package/dist/Communication/communication-providers-resource.component.js.map +1 -1
  175. package/dist/Communication/communication-runs-resource.component.js +39 -38
  176. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  177. package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
  178. package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
  179. package/dist/Communication/communication-templates-resource.component.js +92 -89
  180. package/dist/Communication/communication-templates-resource.component.js.map +1 -1
  181. package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
  182. package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
  183. package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
  184. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  185. package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
  186. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  187. package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
  188. package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
  189. package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
  190. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  191. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +31 -340
  192. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  193. package/dist/DataExplorer/data-explorer-dashboard.component.js +468 -1958
  194. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  195. package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
  196. package/dist/DataExplorer/data-explorer-resource.component.js +10 -0
  197. package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
  198. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
  199. package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
  200. package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
  201. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
  202. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
  203. package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
  204. package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
  205. package/dist/DevTools/app-state-inspector.component.js +18 -17
  206. package/dist/DevTools/app-state-inspector.component.js.map +1 -1
  207. package/dist/DevTools/class-registry.component.js +88 -85
  208. package/dist/DevTools/class-registry.component.js.map +1 -1
  209. package/dist/DevTools/event-monitor.component.js +155 -150
  210. package/dist/DevTools/event-monitor.component.js.map +1 -1
  211. package/dist/DevTools/graphql-console.component.js +245 -243
  212. package/dist/DevTools/graphql-console.component.js.map +1 -1
  213. package/dist/DevTools/layout-inspector.component.js +18 -17
  214. package/dist/DevTools/layout-inspector.component.js.map +1 -1
  215. package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
  216. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  217. package/dist/Home/home-dashboard.component.js +2 -2
  218. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
  219. package/dist/Integration/components/activity/activity.component.js +236 -229
  220. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  221. package/dist/Integration/components/connections/connections.component.js +390 -389
  222. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  223. package/dist/Integration/components/overview/overview.component.js +2 -2
  224. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
  225. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +14 -11
  226. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
  227. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +27 -2
  228. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
  229. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +244 -119
  230. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
  231. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
  232. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  233. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
  234. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
  235. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts +65 -0
  236. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts.map +1 -0
  237. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js +176 -0
  238. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js.map +1 -0
  239. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts +81 -0
  240. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts.map +1 -0
  241. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js +308 -0
  242. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js.map +1 -0
  243. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts +85 -0
  244. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts.map +1 -0
  245. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js +362 -0
  246. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js.map +1 -0
  247. package/dist/KnowledgeHub/index.d.ts +3 -0
  248. package/dist/KnowledgeHub/index.d.ts.map +1 -1
  249. package/dist/KnowledgeHub/index.js +3 -0
  250. package/dist/KnowledgeHub/index.js.map +1 -1
  251. package/dist/Lists/components/lists-browse-resource.component.d.ts +6 -2
  252. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  253. package/dist/Lists/components/lists-browse-resource.component.js +525 -566
  254. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  255. package/dist/Lists/components/lists-categories-resource.component.js +135 -134
  256. package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
  257. package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
  258. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  259. package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
  260. package/dist/MCP/mcp-dashboard.component.js +443 -438
  261. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  262. package/dist/QueryBrowser/query-browser-resource.component.js +1 -1
  263. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  264. package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
  265. package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
  266. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  267. package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
  268. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  269. package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
  270. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  271. package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
  272. package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
  273. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
  274. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
  275. package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
  276. package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
  277. package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
  278. package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
  279. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  280. package/dist/Testing/components/testing-explorer.component.js +436 -427
  281. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  282. package/dist/Testing/components/testing-runs-resource.component.js +1 -1
  283. package/dist/Testing/components/testing-runs.component.js +116 -115
  284. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  285. package/dist/Testing/testing-dashboard.component.js +6 -7
  286. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  287. package/dist/VersionHistory/components/labels-resource.component.js +173 -172
  288. package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
  289. package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
  290. package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
  291. package/dist/VersionHistory/components/restore-resource.component.js +116 -92
  292. package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
  293. package/dist/ai-dashboards.module.d.ts +57 -35
  294. package/dist/ai-dashboards.module.d.ts.map +1 -1
  295. package/dist/ai-dashboards.module.js +80 -1
  296. package/dist/ai-dashboards.module.js.map +1 -1
  297. package/dist/communication-dashboards.module.d.ts +1 -1
  298. package/dist/communication-dashboards.module.d.ts.map +1 -1
  299. package/dist/communication-dashboards.module.js +7 -1
  300. package/dist/communication-dashboards.module.js.map +1 -1
  301. package/dist/data-explorer-dashboards.module.d.ts +12 -14
  302. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  303. package/dist/data-explorer-dashboards.module.js +5 -14
  304. package/dist/data-explorer-dashboards.module.js.map +1 -1
  305. package/dist/public-api.d.ts +3 -0
  306. package/dist/public-api.d.ts.map +1 -1
  307. package/dist/public-api.js +3 -0
  308. package/dist/public-api.js.map +1 -1
  309. package/dist/testing-dashboards.module.d.ts +4 -5
  310. package/dist/testing-dashboards.module.d.ts.map +1 -1
  311. package/dist/testing-dashboards.module.js +7 -5
  312. package/dist/testing-dashboards.module.js.map +1 -1
  313. package/package.json +57 -54
  314. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +0 -79
  315. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +0 -1
  316. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +0 -195
  317. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +0 -1
  318. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +0 -226
  319. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +0 -1
  320. package/dist/DataExplorer/components/view-selector/view-selector.component.js +0 -861
  321. package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +0 -1
@@ -26,19 +26,20 @@ function APIKeysResourceComponent_Conditional_5_Template(rf, ctx) { if (rf & 1)
26
26
  i0.ɵɵelementStart(0, "button", 10);
27
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
28
  i0.ɵɵelement(1, "i", 11);
29
- i0.ɵɵtext(2, " Generate New Key ");
30
- i0.ɵɵelementEnd();
29
+ i0.ɵɵelementStart(2, "span", 12);
30
+ i0.ɵɵtext(3, "Generate New Key");
31
+ i0.ɵɵelementEnd()();
31
32
  } }
32
33
  function APIKeysResourceComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
33
34
  i0.ɵɵelementStart(0, "div", 7);
34
- i0.ɵɵelement(1, "mj-loading", 12);
35
+ i0.ɵɵelement(1, "mj-loading", 13);
35
36
  i0.ɵɵelementEnd();
36
37
  } }
37
38
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template(rf, ctx) { if (rf & 1) {
38
39
  const _r4 = i0.ɵɵgetCurrentView();
39
- i0.ɵɵelementStart(0, "span", 62);
40
+ i0.ɵɵelementStart(0, "span", 63);
40
41
  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);
42
+ i0.ɵɵelement(1, "i", 64);
42
43
  i0.ɵɵtext(2);
43
44
  i0.ɵɵelementEnd();
44
45
  } if (rf & 2) {
@@ -48,9 +49,9 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
48
49
  } }
49
50
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template(rf, ctx) { if (rf & 1) {
50
51
  const _r5 = i0.ɵɵgetCurrentView();
51
- i0.ɵɵelementStart(0, "span", 64);
52
+ i0.ɵɵelementStart(0, "span", 65);
52
53
  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);
54
+ i0.ɵɵelement(1, "i", 41);
54
55
  i0.ɵɵtext(2);
55
56
  i0.ɵɵelementEnd();
56
57
  } if (rf & 2) {
@@ -60,9 +61,9 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
60
61
  } }
61
62
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template(rf, ctx) { if (rf & 1) {
62
63
  const _r6 = i0.ɵɵgetCurrentView();
63
- i0.ɵɵelementStart(0, "span", 65);
64
+ i0.ɵɵelementStart(0, "span", 66);
64
65
  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);
66
+ i0.ɵɵelement(1, "i", 67);
66
67
  i0.ɵɵtext(2);
67
68
  i0.ɵɵelementEnd();
68
69
  } if (rf & 2) {
@@ -71,36 +72,36 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
71
72
  i0.ɵɵtextInterpolate1(" ", ctx_r1.NeverUsedKeys, " never used ");
72
73
  } }
73
74
  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);
75
+ i0.ɵɵelementStart(0, "span", 27);
76
+ i0.ɵɵelement(1, "i", 38);
76
77
  i0.ɵɵtext(2, " All keys healthy ");
77
78
  i0.ɵɵelementEnd();
78
79
  } }
79
80
  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);
81
+ i0.ɵɵelementStart(0, "div", 42);
82
+ i0.ɵɵelement(1, "i", 36);
82
83
  i0.ɵɵelementEnd();
83
84
  } }
84
85
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template(rf, ctx) { if (rf & 1) {
85
86
  const _r7 = i0.ɵɵgetCurrentView();
86
- i0.ɵɵelementStart(0, "div", 68);
87
+ i0.ɵɵelementStart(0, "div", 69);
87
88
  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);
89
+ i0.ɵɵelementStart(1, "div", 70);
90
+ i0.ɵɵelement(2, "i", 31);
90
91
  i0.ɵɵelementEnd();
91
- i0.ɵɵelementStart(3, "div", 70)(4, "div", 71);
92
+ i0.ɵɵelementStart(3, "div", 71)(4, "div", 72);
92
93
  i0.ɵɵtext(5);
93
94
  i0.ɵɵelementEnd();
94
- i0.ɵɵelementStart(6, "div", 72)(7, "span", 73);
95
+ i0.ɵɵelementStart(6, "div", 73)(7, "span", 74);
95
96
  i0.ɵɵtext(8);
96
97
  i0.ɵɵelementEnd();
97
- i0.ɵɵelementStart(9, "span", 74);
98
+ i0.ɵɵelementStart(9, "span", 75);
98
99
  i0.ɵɵtext(10);
99
100
  i0.ɵɵelementEnd()()();
100
- i0.ɵɵelementStart(11, "div", 75)(12, "div", 76);
101
+ i0.ɵɵelementStart(11, "div", 76)(12, "div", 77);
101
102
  i0.ɵɵtext(13);
102
103
  i0.ɵɵelementEnd();
103
- i0.ɵɵelementStart(14, "div", 77);
104
+ i0.ɵɵelementStart(14, "div", 78);
104
105
  i0.ɵɵtext(15);
105
106
  i0.ɵɵelementEnd()()();
106
107
  } if (rf & 2) {
@@ -122,8 +123,8 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
122
123
  i0.ɵɵtextInterpolate1(" ", ctx_r1.formatExpiration(key_r8.ExpiresAt), " ");
123
124
  } }
124
125
  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);
126
+ i0.ɵɵelementStart(0, "div", 51);
127
+ i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template, 16, 8, "div", 68, i0.ɵɵrepeaterTrackByIdentity);
127
128
  i0.ɵɵelementEnd();
128
129
  } if (rf & 2) {
129
130
  const ctx_r1 = i0.ɵɵnextContext(4);
@@ -131,8 +132,8 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
131
132
  i0.ɵɵrepeater(ctx_r1.TopUsedKeys);
132
133
  } }
133
134
  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);
135
+ i0.ɵɵelementStart(0, "div", 52);
136
+ i0.ɵɵelement(1, "i", 31);
136
137
  i0.ɵɵelementStart(2, "span");
137
138
  i0.ɵɵtext(3, "No active keys with recent usage");
138
139
  i0.ɵɵelementEnd()();
@@ -141,30 +142,30 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
141
142
  const _r9 = i0.ɵɵgetCurrentView();
142
143
  i0.ɵɵnamespaceSVG();
143
144
  i0.ɵɵelementContainerStart(0);
144
- i0.ɵɵelementStart(1, "circle", 86);
145
+ i0.ɵɵelementStart(1, "circle", 87);
145
146
  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)); });
146
147
  i0.ɵɵelementEnd();
147
148
  i0.ɵɵelementContainerEnd();
148
149
  } if (rf & 2) {
149
150
  const stat_r10 = ctx.$implicit;
150
- const ɵ$index_243_r11 = ctx.$index;
151
+ const ɵ$index_245_r11 = ctx.$index;
151
152
  const ctx_r1 = i0.ɵɵnextContext(5);
152
153
  i0.ɵɵadvance();
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));
154
+ 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_245_r11));
154
155
  } }
155
156
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template(rf, ctx) { if (rf & 1) {
156
157
  const _r12 = i0.ɵɵgetCurrentView();
157
- i0.ɵɵelementStart(0, "div", 87);
158
+ i0.ɵɵelementStart(0, "div", 88);
158
159
  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);
160
+ i0.ɵɵelement(1, "div", 89);
161
+ i0.ɵɵelementStart(2, "div", 90)(3, "div", 91);
161
162
  i0.ɵɵelement(4, "i");
162
163
  i0.ɵɵtext(5);
163
164
  i0.ɵɵelementEnd();
164
- i0.ɵɵelementStart(6, "div", 91);
165
+ i0.ɵɵelementStart(6, "div", 92);
165
166
  i0.ɵɵtext(7);
166
167
  i0.ɵɵelementEnd()();
167
- i0.ɵɵelement(8, "i", 92);
168
+ i0.ɵɵelement(8, "i", 93);
168
169
  i0.ɵɵelementEnd();
169
170
  } if (rf & 2) {
170
171
  const stat_r13 = ctx.$implicit;
@@ -178,21 +179,21 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
178
179
  i0.ɵɵtextInterpolate1("", stat_r13.count, " scopes");
179
180
  } }
180
181
  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);
182
+ i0.ɵɵelementStart(0, "div", 55)(1, "div", 79);
182
183
  i0.ɵɵnamespaceSVG();
183
- i0.ɵɵelementStart(2, "svg", 79);
184
- i0.ɵɵelement(3, "circle", 80);
184
+ i0.ɵɵelementStart(2, "svg", 80);
185
+ i0.ɵɵelement(3, "circle", 81);
185
186
  i0.ɵɵrepeaterCreate(4, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_5_Template, 2, 3, ":svg:ng-container", null, i0.ɵɵrepeaterTrackByIdentity);
186
187
  i0.ɵɵelementEnd();
187
188
  i0.ɵɵnamespaceHTML();
188
- i0.ɵɵelementStart(6, "div", 81)(7, "div", 82);
189
+ i0.ɵɵelementStart(6, "div", 82)(7, "div", 83);
189
190
  i0.ɵɵtext(8);
190
191
  i0.ɵɵelementEnd();
191
- i0.ɵɵelementStart(9, "div", 83);
192
+ i0.ɵɵelementStart(9, "div", 84);
192
193
  i0.ɵɵtext(10, "Categories");
193
194
  i0.ɵɵelementEnd()()();
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);
195
+ i0.ɵɵelementStart(11, "div", 85);
196
+ i0.ɵɵrepeaterCreate(12, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template, 9, 6, "div", 86, i0.ɵɵrepeaterTrackByIdentity);
196
197
  i0.ɵɵelementEnd()();
197
198
  } if (rf & 2) {
198
199
  const ctx_r1 = i0.ɵɵnextContext(4);
@@ -204,14 +205,14 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
204
205
  i0.ɵɵrepeater(ctx_r1.ScopeStats);
205
206
  } }
206
207
  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);
208
+ i0.ɵɵelementStart(0, "div", 52);
209
+ i0.ɵɵelement(1, "i", 44);
209
210
  i0.ɵɵelementStart(2, "span");
210
211
  i0.ɵɵtext(3, "No scopes configured");
211
212
  i0.ɵɵelementEnd()();
212
213
  } }
213
214
  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);
215
+ i0.ɵɵelementStart(0, "span", 101);
215
216
  i0.ɵɵtext(1);
216
217
  i0.ɵɵelementEnd();
217
218
  } if (rf & 2) {
@@ -221,20 +222,20 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
221
222
  } }
222
223
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template(rf, ctx) { if (rf & 1) {
223
224
  const _r14 = i0.ɵɵgetCurrentView();
224
- i0.ɵɵelementStart(0, "div", 94);
225
+ i0.ɵɵelementStart(0, "div", 95);
225
226
  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);
227
+ i0.ɵɵelementStart(1, "div", 96);
227
228
  i0.ɵɵelement(2, "i");
228
229
  i0.ɵɵelementEnd();
229
- i0.ɵɵelementStart(3, "div", 96)(4, "div", 97);
230
+ i0.ɵɵelementStart(3, "div", 97)(4, "div", 98);
230
231
  i0.ɵɵtext(5);
231
232
  i0.ɵɵelementEnd();
232
- i0.ɵɵelementStart(6, "div", 98)(7, "span", 99);
233
+ i0.ɵɵelementStart(6, "div", 99)(7, "span", 100);
233
234
  i0.ɵɵtext(8);
234
235
  i0.ɵɵelementEnd();
235
- i0.ɵɵconditionalCreate(9, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Conditional_9_Template, 2, 1, "span", 100);
236
+ i0.ɵɵconditionalCreate(9, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Conditional_9_Template, 2, 1, "span", 101);
236
237
  i0.ɵɵelementEnd()();
237
- i0.ɵɵelementStart(10, "div", 101);
238
+ i0.ɵɵelementStart(10, "div", 102);
238
239
  i0.ɵɵtext(11);
239
240
  i0.ɵɵelementEnd()();
240
241
  } if (rf & 2) {
@@ -254,8 +255,8 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
254
255
  i0.ɵɵtextInterpolate1(" ", ctx_r1.formatDate(activity_r15.date), " ");
255
256
  } }
256
257
  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);
258
+ i0.ɵɵelementStart(0, "div", 58);
259
+ i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template, 12, 7, "div", 94, i0.ɵɵrepeaterTrackByIdentity);
259
260
  i0.ɵɵelementEnd();
260
261
  } if (rf & 2) {
261
262
  const ctx_r1 = i0.ɵɵnextContext(4);
@@ -263,164 +264,164 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
263
264
  i0.ɵɵrepeater(ctx_r1.RecentActivity);
264
265
  } }
265
266
  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);
267
+ i0.ɵɵelementStart(0, "div", 52);
268
+ i0.ɵɵelement(1, "i", 103);
268
269
  i0.ɵɵelementStart(2, "span");
269
270
  i0.ɵɵtext(3, "No recent activity");
270
271
  i0.ɵɵelementEnd()();
271
272
  } }
272
273
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template(rf, ctx) { if (rf & 1) {
273
274
  const _r16 = i0.ɵɵgetCurrentView();
274
- i0.ɵɵelementStart(0, "div", 58)(1, "div", 103);
275
+ i0.ɵɵelementStart(0, "div", 59)(1, "div", 104);
275
276
  i0.ɵɵtext(2, "Quick Actions");
276
277
  i0.ɵɵelementEnd();
277
- i0.ɵɵelementStart(3, "div", 104)(4, "button", 105);
278
+ i0.ɵɵelementStart(3, "div", 105)(4, "button", 106);
278
279
  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);
280
+ i0.ɵɵelement(5, "i", 107);
280
281
  i0.ɵɵelementStart(6, "span");
281
282
  i0.ɵɵtext(7, "Generate Key");
282
283
  i0.ɵɵelementEnd()();
283
- i0.ɵɵelementStart(8, "button", 105);
284
+ i0.ɵɵelementStart(8, "button", 106);
284
285
  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);
286
+ i0.ɵɵelement(9, "i", 108);
286
287
  i0.ɵɵelementStart(10, "span");
287
288
  i0.ɵɵtext(11, "View All Keys");
288
289
  i0.ɵɵelementEnd()();
289
- i0.ɵɵelementStart(12, "button", 105);
290
+ i0.ɵɵelementStart(12, "button", 106);
290
291
  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);
292
+ i0.ɵɵelement(13, "i", 41);
292
293
  i0.ɵɵelementStart(14, "span");
293
294
  i0.ɵɵtext(15, "Expiring Keys");
294
295
  i0.ɵɵelementEnd()();
295
- i0.ɵɵelementStart(16, "button", 105);
296
+ i0.ɵɵelementStart(16, "button", 106);
296
297
  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);
298
+ i0.ɵɵelement(17, "i", 67);
298
299
  i0.ɵɵelementStart(18, "span");
299
300
  i0.ɵɵtext(19, "Never Used");
300
301
  i0.ɵɵelementEnd()()()();
301
302
  } }
302
303
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
303
304
  const _r3 = i0.ɵɵgetCurrentView();
304
- i0.ɵɵelementStart(0, "div", 13)(1, "div", 14)(2, "div", 15);
305
+ i0.ɵɵelementStart(0, "div", 14)(1, "div", 15)(2, "div", 16);
305
306
  i0.ɵɵnamespaceSVG();
306
- i0.ɵɵelementStart(3, "svg", 16);
307
- i0.ɵɵelement(4, "path", 17)(5, "path", 18);
307
+ i0.ɵɵelementStart(3, "svg", 17);
308
+ i0.ɵɵelement(4, "path", 18)(5, "path", 19);
308
309
  i0.ɵɵelementEnd();
309
310
  i0.ɵɵnamespaceHTML();
310
- i0.ɵɵelementStart(6, "div", 19);
311
+ i0.ɵɵelementStart(6, "div", 20);
311
312
  i0.ɵɵtext(7);
312
313
  i0.ɵɵelementEnd()()();
313
- i0.ɵɵelementStart(8, "div", 20)(9, "div", 21);
314
+ i0.ɵɵelementStart(8, "div", 21)(9, "div", 22);
314
315
  i0.ɵɵtext(10);
315
316
  i0.ɵɵelementEnd();
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);
317
+ i0.ɵɵelementStart(11, "div", 23);
318
+ i0.ɵɵconditionalCreate(12, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template, 3, 1, "span", 24);
319
+ i0.ɵɵconditionalCreate(13, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template, 3, 1, "span", 25);
320
+ i0.ɵɵconditionalCreate(14, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template, 3, 1, "span", 26);
321
+ i0.ɵɵconditionalCreate(15, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_15_Template, 3, 0, "span", 27);
321
322
  i0.ɵɵelementEnd()()();
322
- i0.ɵɵelementStart(16, "div", 27)(17, "div", 28);
323
+ i0.ɵɵelementStart(16, "div", 28)(17, "div", 29);
323
324
  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);
325
+ i0.ɵɵelementStart(18, "div", 30);
326
+ i0.ɵɵelement(19, "i", 31);
326
327
  i0.ɵɵelementEnd();
327
- i0.ɵɵelementStart(20, "div", 31)(21, "div", 32);
328
+ i0.ɵɵelementStart(20, "div", 32)(21, "div", 33);
328
329
  i0.ɵɵtext(22);
329
330
  i0.ɵɵelementEnd();
330
- i0.ɵɵelementStart(23, "div", 33);
331
+ i0.ɵɵelementStart(23, "div", 34);
331
332
  i0.ɵɵtext(24, "Total Keys");
332
333
  i0.ɵɵelementEnd()();
333
- i0.ɵɵelementStart(25, "div", 34);
334
- i0.ɵɵelement(26, "i", 35);
334
+ i0.ɵɵelementStart(25, "div", 35);
335
+ i0.ɵɵelement(26, "i", 36);
335
336
  i0.ɵɵelementEnd()();
336
- i0.ɵɵelementStart(27, "div", 36);
337
+ i0.ɵɵelementStart(27, "div", 37);
337
338
  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);
339
+ i0.ɵɵelementStart(28, "div", 30);
340
+ i0.ɵɵelement(29, "i", 38);
340
341
  i0.ɵɵelementEnd();
341
- i0.ɵɵelementStart(30, "div", 31)(31, "div", 32);
342
+ i0.ɵɵelementStart(30, "div", 32)(31, "div", 33);
342
343
  i0.ɵɵtext(32);
343
344
  i0.ɵɵelementEnd();
344
- i0.ɵɵelementStart(33, "div", 33);
345
+ i0.ɵɵelementStart(33, "div", 34);
345
346
  i0.ɵɵtext(34, "Active");
346
347
  i0.ɵɵelementEnd()();
347
- i0.ɵɵelementStart(35, "div", 38)(36, "span", 39);
348
+ i0.ɵɵelementStart(35, "div", 39)(36, "span", 40);
348
349
  i0.ɵɵtext(37);
349
350
  i0.ɵɵelementEnd()()();
350
- i0.ɵɵelementStart(38, "div", 28);
351
+ i0.ɵɵelementStart(38, "div", 29);
351
352
  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);
353
+ i0.ɵɵelementStart(39, "div", 30);
354
+ i0.ɵɵelement(40, "i", 41);
354
355
  i0.ɵɵelementEnd();
355
- i0.ɵɵelementStart(41, "div", 31)(42, "div", 32);
356
+ i0.ɵɵelementStart(41, "div", 32)(42, "div", 33);
356
357
  i0.ɵɵtext(43);
357
358
  i0.ɵɵelementEnd();
358
- i0.ɵɵelementStart(44, "div", 33);
359
+ i0.ɵɵelementStart(44, "div", 34);
359
360
  i0.ɵɵtext(45, "Expiring Soon");
360
361
  i0.ɵɵelementEnd()();
361
- i0.ɵɵconditionalCreate(46, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_46_Template, 2, 0, "div", 41);
362
+ i0.ɵɵconditionalCreate(46, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_46_Template, 2, 0, "div", 42);
362
363
  i0.ɵɵelementEnd();
363
- i0.ɵɵelementStart(47, "div", 28);
364
+ i0.ɵɵelementStart(47, "div", 29);
364
365
  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);
366
+ i0.ɵɵelementStart(48, "div", 30);
367
+ i0.ɵɵelement(49, "i", 43);
367
368
  i0.ɵɵelementEnd();
368
- i0.ɵɵelementStart(50, "div", 31)(51, "div", 32);
369
+ i0.ɵɵelementStart(50, "div", 32)(51, "div", 33);
369
370
  i0.ɵɵtext(52);
370
371
  i0.ɵɵelementEnd();
371
- i0.ɵɵelementStart(53, "div", 33);
372
+ i0.ɵɵelementStart(53, "div", 34);
372
373
  i0.ɵɵtext(54, "Revoked");
373
374
  i0.ɵɵelementEnd()()();
374
- i0.ɵɵelementStart(55, "div", 28);
375
+ i0.ɵɵelementStart(55, "div", 29);
375
376
  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);
377
+ i0.ɵɵelementStart(56, "div", 30);
378
+ i0.ɵɵelement(57, "i", 44);
378
379
  i0.ɵɵelementEnd();
379
- i0.ɵɵelementStart(58, "div", 31)(59, "div", 32);
380
+ i0.ɵɵelementStart(58, "div", 32)(59, "div", 33);
380
381
  i0.ɵɵtext(60);
381
382
  i0.ɵɵelementEnd();
382
- i0.ɵɵelementStart(61, "div", 33);
383
+ i0.ɵɵelementStart(61, "div", 34);
383
384
  i0.ɵɵtext(62, "Scope Categories");
384
385
  i0.ɵɵelementEnd()()()();
385
- i0.ɵɵelementStart(63, "div", 44)(64, "div", 45)(65, "div", 46)(66, "div", 47);
386
- i0.ɵɵelement(67, "i", 30);
386
+ i0.ɵɵelementStart(63, "div", 45)(64, "div", 46)(65, "div", 47)(66, "div", 48);
387
+ i0.ɵɵelement(67, "i", 31);
387
388
  i0.ɵɵelementStart(68, "span");
388
389
  i0.ɵɵtext(69, "Recently Used Keys");
389
390
  i0.ɵɵelementEnd()();
390
- i0.ɵɵelementStart(70, "button", 48);
391
+ i0.ɵɵelementStart(70, "button", 49);
391
392
  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
393
  i0.ɵɵtext(71, " View All ");
393
- i0.ɵɵelement(72, "i", 35);
394
+ i0.ɵɵelement(72, "i", 36);
394
395
  i0.ɵɵelementEnd()();
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);
396
+ i0.ɵɵelementStart(73, "div", 50);
397
+ i0.ɵɵconditionalCreate(74, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_Template, 3, 0, "div", 51);
398
+ i0.ɵɵconditionalCreate(75, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_75_Template, 4, 0, "div", 52);
398
399
  i0.ɵɵelementEnd()();
399
- i0.ɵɵelementStart(76, "div", 52)(77, "div", 46)(78, "div", 47);
400
- i0.ɵɵelement(79, "i", 43);
400
+ i0.ɵɵelementStart(76, "div", 53)(77, "div", 47)(78, "div", 48);
401
+ i0.ɵɵelement(79, "i", 44);
401
402
  i0.ɵɵelementStart(80, "span");
402
403
  i0.ɵɵtext(81, "Permission Scopes");
403
404
  i0.ɵɵelementEnd()();
404
- i0.ɵɵelementStart(82, "span", 53);
405
+ i0.ɵɵelementStart(82, "span", 54);
405
406
  i0.ɵɵtext(83, "Available scope categories");
406
407
  i0.ɵɵelementEnd()();
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);
408
+ i0.ɵɵelementStart(84, "div", 50);
409
+ i0.ɵɵconditionalCreate(85, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_Template, 14, 1, "div", 55);
410
+ i0.ɵɵconditionalCreate(86, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_86_Template, 4, 0, "div", 52);
410
411
  i0.ɵɵelementEnd()();
411
- i0.ɵɵelementStart(87, "div", 55)(88, "div", 46)(89, "div", 47);
412
- i0.ɵɵelement(90, "i", 56);
412
+ i0.ɵɵelementStart(87, "div", 56)(88, "div", 47)(89, "div", 48);
413
+ i0.ɵɵelement(90, "i", 57);
413
414
  i0.ɵɵelementStart(91, "span");
414
415
  i0.ɵɵtext(92, "Recent Activity");
415
416
  i0.ɵɵelementEnd()()();
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);
417
+ i0.ɵɵelementStart(93, "div", 50);
418
+ i0.ɵɵconditionalCreate(94, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_Template, 3, 0, "div", 58);
419
+ i0.ɵɵconditionalCreate(95, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_95_Template, 4, 0, "div", 52);
419
420
  i0.ɵɵelementEnd()()();
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");
421
+ i0.ɵɵconditionalCreate(96, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template, 20, 0, "div", 59);
422
+ i0.ɵɵelementStart(97, "div", 60);
423
+ i0.ɵɵelement(98, "i", 61);
424
+ i0.ɵɵelementStart(99, "div", 62)(100, "strong");
424
425
  i0.ɵɵtext(101, "Security Best Practices:");
425
426
  i0.ɵɵelementEnd();
426
427
  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. ");
@@ -477,12 +478,12 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Temp
477
478
  } }
478
479
  function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
479
480
  const _r17 = i0.ɵɵgetCurrentView();
480
- i0.ɵɵelementStart(0, "div", 108)(1, "button", 109);
481
+ i0.ɵɵelementStart(0, "div", 109)(1, "button", 110);
481
482
  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);
483
+ i0.ɵɵelement(2, "i", 111);
483
484
  i0.ɵɵtext(3, " Back to Overview ");
484
485
  i0.ɵɵelementEnd()();
485
- i0.ɵɵelementStart(4, "mj-api-key-list", 111, 0);
486
+ i0.ɵɵelementStart(4, "mj-api-key-list", 112, 0);
486
487
  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()); });
487
488
  i0.ɵɵelementEnd();
488
489
  } if (rf & 2) {
@@ -501,13 +502,13 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Template(rf, ctx)
501
502
  } }
502
503
  function APIKeysResourceComponent_Conditional_7_Conditional_2_Template(rf, ctx) { if (rf & 1) {
503
504
  const _r18 = i0.ɵɵgetCurrentView();
504
- i0.ɵɵelementStart(0, "mj-api-applications-panel", 112);
505
+ i0.ɵɵelementStart(0, "mj-api-applications-panel", 113);
505
506
  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()); });
506
507
  i0.ɵɵelementEnd();
507
508
  } }
508
509
  function APIKeysResourceComponent_Conditional_7_Conditional_3_Template(rf, ctx) { if (rf & 1) {
509
510
  const _r19 = i0.ɵɵgetCurrentView();
510
- i0.ɵɵelementStart(0, "mj-api-scopes-panel", 113);
511
+ i0.ɵɵelementStart(0, "mj-api-scopes-panel", 114);
511
512
  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()); });
512
513
  i0.ɵɵelementEnd();
513
514
  } }
@@ -1055,14 +1056,14 @@ let APIKeysResourceComponent = class APIKeysResourceComponent extends BaseResour
1055
1056
  } if (rf & 2) {
1056
1057
  let _t;
1057
1058
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.keyListComponent = _t.first);
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
+ } }, 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"], [1, "mj-action-label"], ["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
1060
  i0.ɵɵelementStart(0, "mj-page-header-interior", 1)(1, "div", 2)(2, "mj-tab-nav", 3);
1060
1061
  i0.ɵɵlistener("TabChange", function APIKeysResourceComponent_Template_mj_tab_nav_TabChange_2_listener($event) { return ctx.onTabChange($event); });
1061
1062
  i0.ɵɵelementEnd()();
1062
1063
  i0.ɵɵelementStart(3, "div", 4)(4, "mj-refresh-button", 5);
1063
1064
  i0.ɵɵlistener("Clicked", function APIKeysResourceComponent_Template_mj_refresh_button_Clicked_4_listener() { return ctx.refresh(); });
1064
1065
  i0.ɵɵelementEnd();
1065
- i0.ɵɵconditionalCreate(5, APIKeysResourceComponent_Conditional_5_Template, 3, 0, "button", 6);
1066
+ i0.ɵɵconditionalCreate(5, APIKeysResourceComponent_Conditional_5_Template, 4, 0, "button", 6);
1066
1067
  i0.ɵɵelementEnd()();
1067
1068
  i0.ɵɵconditionalCreate(6, APIKeysResourceComponent_Conditional_6_Template, 2, 0, "div", 7)(7, APIKeysResourceComponent_Conditional_7_Template, 5, 4, "mj-page-body-interior");
1068
1069
  i0.ɵɵelementStart(8, "mj-api-key-create-dialog", 8);
@@ -1093,7 +1094,7 @@ APIKeysResourceComponent = __decorate([
1093
1094
  export { APIKeysResourceComponent };
1094
1095
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIKeysResourceComponent, [{
1095
1096
  type: Component,
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"] }]
1097
+ 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 <span class=\"mj-action-label\">Generate New Key</span>\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"] }]
1097
1098
  }], () => [{ type: i0.ChangeDetectorRef }], { keyListComponent: [{
1098
1099
  type: ViewChild,
1099
1100
  args: ['keyList']