@memberjunction/ng-dashboards 5.21.0 → 5.23.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 (262) hide show
  1. package/README.md +51 -0
  2. package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
  3. package/dist/AI/components/agents/agent-configuration.component.js +364 -362
  4. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  5. package/dist/AI/components/agents/agent-editor.component.js +2 -2
  6. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +313 -0
  7. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -0
  8. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +2792 -0
  9. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -0
  10. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +382 -0
  11. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -0
  12. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +2683 -0
  13. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -0
  14. package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
  15. package/dist/AI/components/execution-monitoring.component.js +191 -197
  16. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  17. package/dist/AI/components/models/model-management.component.js +9 -8
  18. package/dist/AI/components/models/model-management.component.js.map +1 -1
  19. package/dist/AI/components/prompts/prompt-management.component.js +305 -299
  20. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  21. package/dist/AI/components/system/system-configuration.component.js +319 -313
  22. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  23. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +240 -0
  24. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -0
  25. package/dist/AI/components/vectors/vector-management-resource.component.js +1767 -0
  26. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -0
  27. package/dist/AI/index.d.ts +3 -0
  28. package/dist/AI/index.d.ts.map +1 -1
  29. package/dist/AI/index.js +6 -0
  30. package/dist/AI/index.js.map +1 -1
  31. package/dist/AI/services/ai-instrumentation.service.d.ts +50 -7
  32. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  33. package/dist/AI/services/ai-instrumentation.service.js +161 -193
  34. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  35. package/dist/APIKeys/api-applications-panel.component.js +10 -12
  36. package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
  37. package/dist/APIKeys/api-key-create-dialog.component.js +13 -19
  38. package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
  39. package/dist/APIKeys/api-key-edit-panel.component.js +12 -14
  40. package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
  41. package/dist/APIKeys/api-scopes-panel.component.js +61 -68
  42. package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
  43. package/dist/APIKeys/api-usage-panel.component.js +10 -11
  44. package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
  45. package/dist/Actions/components/actions-list-view.component.js +82 -96
  46. package/dist/Actions/components/actions-list-view.component.js.map +1 -1
  47. package/dist/Actions/components/actions-overview.component.js +130 -134
  48. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  49. package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
  50. package/dist/Actions/components/categories-list-view.component.js +40 -46
  51. package/dist/Actions/components/categories-list-view.component.js.map +1 -1
  52. package/dist/Actions/components/code-management.component.js +2 -2
  53. package/dist/Actions/components/code-management.component.js.map +1 -1
  54. package/dist/Actions/components/entity-integration.component.js +2 -2
  55. package/dist/Actions/components/entity-integration.component.js.map +1 -1
  56. package/dist/Actions/components/execution-monitoring.component.js +127 -132
  57. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  58. package/dist/Actions/components/executions-list-view.component.js +2 -2
  59. package/dist/Actions/components/executions-list-view.component.js.map +1 -1
  60. package/dist/Actions/components/explorer/action-card.component.js +11 -17
  61. package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
  62. package/dist/Actions/components/explorer/action-explorer.component.js +5 -11
  63. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  64. package/dist/Actions/components/explorer/action-list-item.component.js +8 -10
  65. package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
  66. package/dist/Actions/components/explorer/action-toolbar.component.js +112 -133
  67. package/dist/Actions/components/explorer/action-toolbar.component.js.map +1 -1
  68. package/dist/Actions/components/explorer/action-tree-panel.component.js +63 -83
  69. package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
  70. package/dist/Actions/components/explorer/new-action-panel.component.js +17 -21
  71. package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
  72. package/dist/Actions/components/explorer/new-category-panel.component.js +17 -21
  73. package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
  74. package/dist/Actions/components/scheduled-actions.component.js +2 -2
  75. package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
  76. package/dist/Actions/components/security-permissions.component.js +2 -2
  77. package/dist/Actions/components/security-permissions.component.js.map +1 -1
  78. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts +13 -5
  79. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
  80. package/dist/ComponentStudio/component-studio-dashboard.component.js +168 -145
  81. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  82. package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +4 -5
  83. package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
  84. package/dist/ComponentStudio/components/artifact-load-dialog.component.js +197 -200
  85. package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
  86. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +5 -7
  87. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
  88. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +142 -148
  89. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  90. package/dist/ComponentStudio/components/browser/component-browser.component.js +153 -166
  91. package/dist/ComponentStudio/components/browser/component-browser.component.js.map +1 -1
  92. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +15 -20
  93. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
  94. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +16 -21
  95. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
  96. package/dist/ComponentStudio/components/editors/requirements-editor.component.js +18 -23
  97. package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
  98. package/dist/ComponentStudio/components/editors/spec-editor.component.js +25 -30
  99. package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
  100. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +10 -11
  101. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js.map +1 -1
  102. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.d.ts.map +1 -1
  103. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +24 -35
  104. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
  105. package/dist/ComponentStudio/components/text-import-dialog.component.js +15 -17
  106. package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
  107. package/dist/Credentials/components/credentials-categories-resource.component.js +7 -6
  108. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  109. package/dist/Credentials/components/credentials-list-resource.component.js +6 -5
  110. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  111. package/dist/Credentials/components/credentials-types-resource.component.js +7 -6
  112. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  113. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +11 -0
  114. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
  115. package/dist/DashboardBrowser/dashboard-browser-resource.component.js +57 -0
  116. package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
  117. package/dist/DashboardBrowser/dashboard-share-dialog.component.js +9 -9
  118. package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
  119. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +1 -1
  120. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +10 -2
  121. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  122. package/dist/DataExplorer/data-explorer-dashboard.component.js +35 -11
  123. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  124. package/dist/DataExplorer/data-explorer-resource.component.d.ts +1 -0
  125. package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
  126. package/dist/DataExplorer/data-explorer-resource.component.js +8 -4
  127. package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
  128. package/dist/Home/home-dashboard.component.d.ts +181 -1
  129. package/dist/Home/home-dashboard.component.d.ts.map +1 -1
  130. package/dist/Home/home-dashboard.component.js +1704 -182
  131. package/dist/Home/home-dashboard.component.js.map +1 -1
  132. package/dist/Integration/components/connections/connections.component.js +4 -4
  133. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  134. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +246 -259
  135. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
  136. package/dist/Integration/components/widgets/integration-card.component.js +7 -9
  137. package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
  138. package/dist/Integration/integration.module.d.ts +6 -10
  139. package/dist/Integration/integration.module.d.ts.map +1 -1
  140. package/dist/Integration/integration.module.js +12 -20
  141. package/dist/Integration/integration.module.js.map +1 -1
  142. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +106 -0
  143. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -0
  144. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +607 -0
  145. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -0
  146. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +126 -0
  147. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -0
  148. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +1086 -0
  149. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -0
  150. package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.d.ts +56 -0
  151. package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.d.ts.map +1 -0
  152. package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.js +291 -0
  153. package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.js.map +1 -0
  154. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts +85 -0
  155. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts.map +1 -0
  156. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js +461 -0
  157. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js.map +1 -0
  158. package/dist/KnowledgeHub/index.d.ts +5 -0
  159. package/dist/KnowledgeHub/index.d.ts.map +1 -0
  160. package/dist/KnowledgeHub/index.js +6 -0
  161. package/dist/KnowledgeHub/index.js.map +1 -0
  162. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  163. package/dist/Lists/components/lists-browse-resource.component.js +9 -7
  164. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  165. package/dist/Lists/components/lists-my-lists-resource.component.js +5 -4
  166. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  167. package/dist/Lists/components/lists-operations-resource.component.js +10 -9
  168. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  169. package/dist/MCP/components/mcp-connection-dialog.component.js +141 -132
  170. package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
  171. package/dist/MCP/components/mcp-log-detail-panel.component.js +4 -4
  172. package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
  173. package/dist/MCP/components/mcp-server-dialog.component.js +141 -128
  174. package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
  175. package/dist/MCP/components/mcp-test-tool-dialog.component.js +210 -218
  176. package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
  177. package/dist/MCP/mcp-dashboard.component.js +2 -2
  178. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  179. package/dist/MCP/mcp.module.d.ts +6 -9
  180. package/dist/MCP/mcp.module.d.ts.map +1 -1
  181. package/dist/MCP/mcp.module.js +20 -22
  182. package/dist/MCP/mcp.module.js.map +1 -1
  183. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  184. package/dist/QueryBrowser/query-browser-resource.component.js +5 -1
  185. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  186. package/dist/Scheduling/components/scheduling-activity.component.js +5 -4
  187. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  188. package/dist/Scheduling/components/scheduling-jobs.component.js +6 -5
  189. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  190. package/dist/Scheduling/components/scheduling-overview.component.js +93 -92
  191. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  192. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
  193. package/dist/SystemDiagnostics/system-diagnostics.component.js +1 -0
  194. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  195. package/dist/Testing/components/testing-dashboard-tab-resource.component.d.ts +7 -1
  196. package/dist/Testing/components/testing-dashboard-tab-resource.component.d.ts.map +1 -1
  197. package/dist/Testing/components/testing-dashboard-tab-resource.component.js +63 -8
  198. package/dist/Testing/components/testing-dashboard-tab-resource.component.js.map +1 -1
  199. package/dist/Testing/components/testing-dashboard-tab.component.d.ts +9 -1
  200. package/dist/Testing/components/testing-dashboard-tab.component.d.ts.map +1 -1
  201. package/dist/Testing/components/testing-dashboard-tab.component.js +109 -62
  202. package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
  203. package/dist/Testing/components/testing-explorer.component.d.ts +2 -1
  204. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  205. package/dist/Testing/components/testing-explorer.component.js +241 -200
  206. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  207. package/dist/Testing/components/testing-runs-resource.component.d.ts +7 -1
  208. package/dist/Testing/components/testing-runs-resource.component.d.ts.map +1 -1
  209. package/dist/Testing/components/testing-runs-resource.component.js +63 -8
  210. package/dist/Testing/components/testing-runs-resource.component.js.map +1 -1
  211. package/dist/Testing/components/testing-runs.component.d.ts.map +1 -1
  212. package/dist/Testing/components/testing-runs.component.js +7 -5
  213. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  214. package/dist/Testing/testing-dashboard.component.d.ts +9 -1
  215. package/dist/Testing/testing-dashboard.component.d.ts.map +1 -1
  216. package/dist/Testing/testing-dashboard.component.js +122 -54
  217. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  218. package/dist/actions-dashboards.module.d.ts +8 -13
  219. package/dist/actions-dashboards.module.d.ts.map +1 -1
  220. package/dist/actions-dashboards.module.js +6 -27
  221. package/dist/actions-dashboards.module.js.map +1 -1
  222. package/dist/ai-dashboards.module.d.ts +14 -11
  223. package/dist/ai-dashboards.module.d.ts.map +1 -1
  224. package/dist/ai-dashboards.module.js +58 -44
  225. package/dist/ai-dashboards.module.js.map +1 -1
  226. package/dist/communication-dashboards.module.d.ts +4 -8
  227. package/dist/communication-dashboards.module.d.ts.map +1 -1
  228. package/dist/communication-dashboards.module.js +0 -19
  229. package/dist/communication-dashboards.module.js.map +1 -1
  230. package/dist/component-studio-dashboards.module.d.ts +7 -11
  231. package/dist/component-studio-dashboards.module.d.ts.map +1 -1
  232. package/dist/component-studio-dashboards.module.js +22 -34
  233. package/dist/component-studio-dashboards.module.js.map +1 -1
  234. package/dist/core-dashboards.module.d.ts +13 -18
  235. package/dist/core-dashboards.module.d.ts.map +1 -1
  236. package/dist/core-dashboards.module.js +18 -31
  237. package/dist/core-dashboards.module.js.map +1 -1
  238. package/dist/credentials-dashboards.module.d.ts +5 -8
  239. package/dist/credentials-dashboards.module.d.ts.map +1 -1
  240. package/dist/credentials-dashboards.module.js +3 -19
  241. package/dist/credentials-dashboards.module.js.map +1 -1
  242. package/dist/data-explorer-dashboards.module.d.ts +7 -13
  243. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  244. package/dist/data-explorer-dashboards.module.js +0 -27
  245. package/dist/data-explorer-dashboards.module.js.map +1 -1
  246. package/dist/lists-dashboards.module.d.ts +5 -8
  247. package/dist/lists-dashboards.module.d.ts.map +1 -1
  248. package/dist/lists-dashboards.module.js +3 -19
  249. package/dist/lists-dashboards.module.js.map +1 -1
  250. package/dist/public-api.d.ts +5 -1
  251. package/dist/public-api.d.ts.map +1 -1
  252. package/dist/public-api.js +6 -1
  253. package/dist/public-api.js.map +1 -1
  254. package/dist/scheduling-dashboards.module.d.ts +6 -10
  255. package/dist/scheduling-dashboards.module.d.ts.map +1 -1
  256. package/dist/scheduling-dashboards.module.js +3 -23
  257. package/dist/scheduling-dashboards.module.js.map +1 -1
  258. package/dist/testing-dashboards.module.d.ts +7 -12
  259. package/dist/testing-dashboards.module.d.ts.map +1 -1
  260. package/dist/testing-dashboards.module.js +4 -27
  261. package/dist/testing-dashboards.module.js.map +1 -1
  262. package/package.json +47 -53
@@ -4,11 +4,8 @@ import { UUIDsEqual } from '@memberjunction/global';
4
4
  import * as i0 from "@angular/core";
5
5
  import * as i1 from "@angular/common";
6
6
  import * as i2 from "@angular/forms";
7
- import * as i3 from "@progress/kendo-angular-buttons";
8
- import * as i4 from "@progress/kendo-angular-dropdowns";
9
- import * as i5 from "@progress/kendo-angular-inputs";
10
- import * as i6 from "@progress/kendo-angular-dialog";
11
- import * as i7 from "@memberjunction/ng-shared-generic";
7
+ import * as i3 from "@memberjunction/ng-ui-components";
8
+ import * as i4 from "@memberjunction/ng-shared-generic";
12
9
  const _c0 = a0 => ({ node: a0 });
13
10
  const _c1 = () => ({ FullPath: "(No Parent - Root Level)", ID: null });
14
11
  function APIScopesPanelComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
@@ -233,8 +230,8 @@ function APIScopesPanelComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
233
230
  i0.ɵɵadvance(2);
234
231
  i0.ɵɵconditional(ctx_r1.ScopeTree.length === 0 ? 28 : -1);
235
232
  } }
236
- function APIScopesPanelComponent_Conditional_3_Conditional_19_Template(rf, ctx) { if (rf & 1) {
237
- i0.ɵɵelementStart(0, "span", 56);
233
+ function APIScopesPanelComponent_Conditional_3_Conditional_17_Template(rf, ctx) { if (rf & 1) {
234
+ i0.ɵɵelementStart(0, "span", 54);
238
235
  i0.ɵɵtext(1, " Full path will be: ");
239
236
  i0.ɵɵelementStart(2, "code");
240
237
  i0.ɵɵtext(3);
@@ -244,14 +241,14 @@ function APIScopesPanelComponent_Conditional_3_Conditional_19_Template(rf, ctx)
244
241
  i0.ɵɵadvance(3);
245
242
  i0.ɵɵtextInterpolate2("", ctx_r1.SelectedParentScope.FullPath, ":", ctx_r1.EditName || "...");
246
243
  } }
247
- function APIScopesPanelComponent_Conditional_3_Conditional_43_Template(rf, ctx) { if (rf & 1) {
248
- i0.ɵɵelement(0, "mj-loading", 68);
244
+ function APIScopesPanelComponent_Conditional_3_Conditional_41_Template(rf, ctx) { if (rf & 1) {
245
+ i0.ɵɵelement(0, "mj-loading", 66);
249
246
  } if (rf & 2) {
250
247
  i0.ɵɵproperty("showText", false);
251
248
  } }
252
- function APIScopesPanelComponent_Conditional_3_Conditional_44_Template(rf, ctx) { if (rf & 1) {
249
+ function APIScopesPanelComponent_Conditional_3_Conditional_42_Template(rf, ctx) { if (rf & 1) {
253
250
  i0.ɵɵelementStart(0, "span");
254
- i0.ɵɵelement(1, "i", 70);
251
+ i0.ɵɵelement(1, "i", 68);
255
252
  i0.ɵɵtext(2);
256
253
  i0.ɵɵelementEnd();
257
254
  } if (rf & 2) {
@@ -261,99 +258,95 @@ function APIScopesPanelComponent_Conditional_3_Conditional_44_Template(rf, ctx)
261
258
  } }
262
259
  function APIScopesPanelComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
263
260
  const _r9 = i0.ɵɵgetCurrentView();
264
- i0.ɵɵelementStart(0, "kendo-window", 49);
265
- i0.ɵɵlistener("close", function APIScopesPanelComponent_Conditional_3_Template_kendo_window_close_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeDialogs()); });
266
- i0.ɵɵelementStart(1, "kendo-window-titlebar")(2, "div", 50);
261
+ i0.ɵɵelementStart(0, "mj-window", 49);
262
+ i0.ɵɵlistener("Close", function APIScopesPanelComponent_Conditional_3_Template_mj_window_Close_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeDialogs()); });
263
+ i0.ɵɵelementStart(1, "mj-window-titlebar")(2, "div", 50);
267
264
  i0.ɵɵelement(3, "i", 7);
268
265
  i0.ɵɵelementStart(4, "span");
269
266
  i0.ɵɵtext(5);
270
- i0.ɵɵelementEnd()();
271
- i0.ɵɵelementStart(6, "button", 51);
272
- i0.ɵɵlistener("click", function APIScopesPanelComponent_Conditional_3_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeDialogs()); });
273
- i0.ɵɵelement(7, "i", 52);
274
- i0.ɵɵelementEnd()();
275
- i0.ɵɵelementStart(8, "div", 53)(9, "div", 54)(10, "label");
276
- i0.ɵɵtext(11, "Scope Name *");
267
+ i0.ɵɵelementEnd()()();
268
+ i0.ɵɵelementStart(6, "div", 51)(7, "div", 52)(8, "label");
269
+ i0.ɵɵtext(9, "Scope Name *");
277
270
  i0.ɵɵelementEnd();
278
- i0.ɵɵelementStart(12, "input", 55);
279
- i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_input_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditName, $event) || (ctx_r1.EditName = $event); return i0.ɵɵresetView($event); });
271
+ i0.ɵɵelementStart(10, "input", 53);
272
+ i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditName, $event) || (ctx_r1.EditName = $event); return i0.ɵɵresetView($event); });
280
273
  i0.ɵɵelementEnd();
281
- i0.ɵɵelementStart(13, "span", 56);
282
- i0.ɵɵtext(14, "Use lowercase, single word. Will be combined with parent for full path.");
274
+ i0.ɵɵelementStart(11, "span", 54);
275
+ i0.ɵɵtext(12, "Use lowercase, single word. Will be combined with parent for full path.");
283
276
  i0.ɵɵelementEnd()();
284
- i0.ɵɵelementStart(15, "div", 54)(16, "label");
285
- i0.ɵɵtext(17, "Parent Scope");
277
+ i0.ɵɵelementStart(13, "div", 52)(14, "label");
278
+ i0.ɵɵtext(15, "Parent Scope");
286
279
  i0.ɵɵelementEnd();
287
- i0.ɵɵelementStart(18, "kendo-dropdownlist", 57);
288
- i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_kendo_dropdownlist_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditParentId, $event) || (ctx_r1.EditParentId = $event); return i0.ɵɵresetView($event); });
280
+ i0.ɵɵelementStart(16, "mj-dropdown", 55);
281
+ i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_mj_dropdown_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditParentId, $event) || (ctx_r1.EditParentId = $event); return i0.ɵɵresetView($event); });
289
282
  i0.ɵɵelementEnd();
290
- i0.ɵɵconditionalCreate(19, APIScopesPanelComponent_Conditional_3_Conditional_19_Template, 4, 2, "span", 56);
283
+ i0.ɵɵconditionalCreate(17, APIScopesPanelComponent_Conditional_3_Conditional_17_Template, 4, 2, "span", 54);
291
284
  i0.ɵɵelementEnd();
292
- i0.ɵɵelementStart(20, "div", 58)(21, "div", 59)(22, "label");
293
- i0.ɵɵtext(23, "Category");
285
+ i0.ɵɵelementStart(18, "div", 56)(19, "div", 57)(20, "label");
286
+ i0.ɵɵtext(21, "Category");
294
287
  i0.ɵɵelementEnd();
295
- i0.ɵɵelementStart(24, "kendo-dropdownlist", 60);
296
- i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_kendo_dropdownlist_ngModelChange_24_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditCategory, $event) || (ctx_r1.EditCategory = $event); return i0.ɵɵresetView($event); });
288
+ i0.ɵɵelementStart(22, "mj-dropdown", 58);
289
+ i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_mj_dropdown_ngModelChange_22_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditCategory, $event) || (ctx_r1.EditCategory = $event); return i0.ɵɵresetView($event); });
297
290
  i0.ɵɵelementEnd()();
298
- i0.ɵɵelementStart(25, "div", 59)(26, "label");
299
- i0.ɵɵtext(27, "Resource Type");
291
+ i0.ɵɵelementStart(23, "div", 57)(24, "label");
292
+ i0.ɵɵtext(25, "Resource Type");
300
293
  i0.ɵɵelementEnd();
301
- i0.ɵɵelementStart(28, "kendo-dropdownlist", 61);
302
- i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_kendo_dropdownlist_ngModelChange_28_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditResourceType, $event) || (ctx_r1.EditResourceType = $event); return i0.ɵɵresetView($event); });
294
+ i0.ɵɵelementStart(26, "mj-dropdown", 59);
295
+ i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_mj_dropdown_ngModelChange_26_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditResourceType, $event) || (ctx_r1.EditResourceType = $event); return i0.ɵɵresetView($event); });
303
296
  i0.ɵɵelementEnd()()();
304
- i0.ɵɵelementStart(29, "div", 54)(30, "label");
305
- i0.ɵɵtext(31, "Description");
297
+ i0.ɵɵelementStart(27, "div", 52)(28, "label");
298
+ i0.ɵɵtext(29, "Description");
306
299
  i0.ɵɵelementEnd();
307
- i0.ɵɵelementStart(32, "textarea", 62);
308
- i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_textarea_ngModelChange_32_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditDescription, $event) || (ctx_r1.EditDescription = $event); return i0.ɵɵresetView($event); });
300
+ i0.ɵɵelementStart(30, "textarea", 60);
301
+ i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_textarea_ngModelChange_30_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditDescription, $event) || (ctx_r1.EditDescription = $event); return i0.ɵɵresetView($event); });
309
302
  i0.ɵɵelementEnd()();
310
- i0.ɵɵelementStart(33, "div", 54)(34, "label", 63)(35, "input", 64);
311
- i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_input_ngModelChange_35_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditIsActive, $event) || (ctx_r1.EditIsActive = $event); return i0.ɵɵresetView($event); });
303
+ i0.ɵɵelementStart(31, "div", 52)(32, "label", 61)(33, "input", 62);
304
+ i0.ɵɵtwoWayListener("ngModelChange", function APIScopesPanelComponent_Conditional_3_Template_input_ngModelChange_33_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.EditIsActive, $event) || (ctx_r1.EditIsActive = $event); return i0.ɵɵresetView($event); });
312
305
  i0.ɵɵelementEnd();
313
- i0.ɵɵelementStart(36, "div")(37, "span");
314
- i0.ɵɵtext(38, "Active");
306
+ i0.ɵɵelementStart(34, "div")(35, "span");
307
+ i0.ɵɵtext(36, "Active");
315
308
  i0.ɵɵelementEnd();
316
- i0.ɵɵelementStart(39, "span", 65);
317
- i0.ɵɵtext(40, "Inactive scopes cannot be assigned to keys or applications");
309
+ i0.ɵɵelementStart(37, "span", 63);
310
+ i0.ɵɵtext(38, "Inactive scopes cannot be assigned to keys or applications");
318
311
  i0.ɵɵelementEnd()()()();
319
- i0.ɵɵelementStart(41, "div", 66)(42, "button", 67);
320
- i0.ɵɵlistener("click", function APIScopesPanelComponent_Conditional_3_Template_button_click_42_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.saveScope()); });
321
- i0.ɵɵconditionalCreate(43, APIScopesPanelComponent_Conditional_3_Conditional_43_Template, 1, 1, "mj-loading", 68);
322
- i0.ɵɵconditionalCreate(44, APIScopesPanelComponent_Conditional_3_Conditional_44_Template, 3, 1, "span");
312
+ i0.ɵɵelementStart(39, "div", 64)(40, "button", 65);
313
+ i0.ɵɵlistener("click", function APIScopesPanelComponent_Conditional_3_Template_button_click_40_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.saveScope()); });
314
+ i0.ɵɵconditionalCreate(41, APIScopesPanelComponent_Conditional_3_Conditional_41_Template, 1, 1, "mj-loading", 66);
315
+ i0.ɵɵconditionalCreate(42, APIScopesPanelComponent_Conditional_3_Conditional_42_Template, 3, 1, "span");
323
316
  i0.ɵɵelementEnd();
324
- i0.ɵɵelementStart(45, "button", 69);
325
- i0.ɵɵlistener("click", function APIScopesPanelComponent_Conditional_3_Template_button_click_45_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeDialogs()); });
326
- i0.ɵɵtext(46, "Cancel");
317
+ i0.ɵɵelementStart(43, "button", 67);
318
+ i0.ɵɵlistener("click", function APIScopesPanelComponent_Conditional_3_Template_button_click_43_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeDialogs()); });
319
+ i0.ɵɵtext(44, "Cancel");
327
320
  i0.ɵɵelementEnd()()()();
328
321
  } if (rf & 2) {
329
322
  const ctx_r1 = i0.ɵɵnextContext();
330
- i0.ɵɵproperty("width", 560)("minWidth", 420)("minHeight", 480)("resizable", true)("draggable", true)("top", 80);
323
+ i0.ɵɵproperty("Width", 560)("MinWidth", 420)("MinHeight", 480)("Resizable", true)("Draggable", true)("Visible", true)("Top", 80);
331
324
  i0.ɵɵadvance(5);
332
325
  i0.ɵɵtextInterpolate(ctx_r1.EditingScope ? "Edit Scope" : "New Scope");
333
- i0.ɵɵadvance(7);
326
+ i0.ɵɵadvance(5);
334
327
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditName);
335
328
  i0.ɵɵadvance(6);
336
329
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditParentId);
337
- i0.ɵɵproperty("data", ctx_r1.getParentOptions())("textField", "FullPath")("valueField", "ID")("valuePrimitive", true)("defaultItem", i0.ɵɵpureFunction0(29, _c1));
330
+ i0.ɵɵproperty("Data", ctx_r1.getParentOptions())("ValuePrimitive", true)("DefaultItem", i0.ɵɵpureFunction0(27, _c1));
338
331
  i0.ɵɵadvance();
339
- i0.ɵɵconditional(ctx_r1.SelectedParentScope ? 19 : -1);
332
+ i0.ɵɵconditional(ctx_r1.SelectedParentScope ? 17 : -1);
340
333
  i0.ɵɵadvance(5);
341
334
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditCategory);
342
- i0.ɵɵproperty("data", ctx_r1.Categories)("valuePrimitive", true);
335
+ i0.ɵɵproperty("Data", ctx_r1.Categories)("ValuePrimitive", true);
343
336
  i0.ɵɵadvance(4);
344
337
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditResourceType);
345
- i0.ɵɵproperty("data", ctx_r1.ResourceTypes)("valuePrimitive", true)("defaultItem", "");
338
+ i0.ɵɵproperty("Data", ctx_r1.ResourceTypes)("ValuePrimitive", true)("DefaultItem", "");
346
339
  i0.ɵɵadvance(4);
347
340
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditDescription);
348
341
  i0.ɵɵproperty("rows", 3);
349
342
  i0.ɵɵadvance(3);
350
343
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditIsActive);
351
344
  i0.ɵɵadvance(7);
352
- i0.ɵɵproperty("themeColor", "primary")("disabled", !ctx_r1.EditName.trim() || ctx_r1.IsSaving);
345
+ i0.ɵɵproperty("disabled", !ctx_r1.EditName.trim() || ctx_r1.IsSaving);
353
346
  i0.ɵɵadvance();
354
- i0.ɵɵconditional(ctx_r1.IsSaving ? 43 : -1);
347
+ i0.ɵɵconditional(ctx_r1.IsSaving ? 41 : -1);
355
348
  i0.ɵɵadvance();
356
- i0.ɵɵconditional(!ctx_r1.IsSaving ? 44 : -1);
349
+ i0.ɵɵconditional(!ctx_r1.IsSaving ? 42 : -1);
357
350
  } }
358
351
  /**
359
352
  * API Scopes Panel Component
@@ -624,11 +617,11 @@ export class APIScopesPanelComponent {
624
617
  return this.FlatScopes.filter(s => s.IsActive).length;
625
618
  }
626
619
  static ɵfac = function APIScopesPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || APIScopesPanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
627
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: APIScopesPanelComponent, selectors: [["mj-api-scopes-panel"]], outputs: { ScopeUpdated: "ScopeUpdated" }, standalone: false, decls: 4, vars: 3, consts: [["scopeNode", ""], [1, "scopes-panel"], ["text", "Loading scopes..."], [3, "width", "minWidth", "minHeight", "resizable", "draggable", "top"], [1, "panel-header"], [1, "header-left"], [1, "panel-title"], [1, "fa-solid", "fa-shield-halved"], [1, "panel-subtitle"], [1, "header-actions"], [1, "scope-stats"], [1, "stat"], [1, "fa-solid", "fa-shield"], [1, "stat", "active"], [1, "fa-solid", "fa-check-circle"], [1, "tree-controls"], ["title", "Expand All", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-plus-square"], ["title", "Collapse All", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-minus-square"], [1, "btn-create", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "message", "success"], [1, "message", "error"], [1, "scope-tree"], [1, "empty-state"], [1, "fa-solid", "fa-circle-exclamation"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"], [1, "scope-node"], [1, "node-content"], [1, "expand-btn"], [1, "expand-placeholder"], [1, "scope-info", 3, "click"], [1, "scope-icon"], [1, "scope-details"], [1, "scope-name"], [1, "full-path"], [1, "status-badge"], [1, "scope-meta"], [1, "category"], [1, "resource-type"], [1, "description"], [1, "node-actions"], ["title", "Add Child Scope", 1, "btn-node-action", 3, "click"], ["title", "Edit Scope", 1, "btn-node-action", 3, "click"], [1, "fa-solid", "fa-pencil"], [1, "children"], [1, "expand-btn", 3, "click"], [1, "fa-solid"], [3, "close", "width", "minWidth", "minHeight", "resizable", "draggable", "top"], [1, "dialog-title"], ["kendoButton", "", "fillMode", "flat", "title", "Close (Esc)", 1, "window-close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "dialog-content"], [1, "form-field"], ["kendoTextBox", "", "placeholder", "e.g., runview, create, execute", 1, "form-input", 3, "ngModelChange", "ngModel"], [1, "field-hint"], [3, "ngModelChange", "ngModel", "data", "textField", "valueField", "valuePrimitive", "defaultItem"], [1, "form-row"], [1, "form-field", "half"], [3, "ngModelChange", "ngModel", "data", "valuePrimitive"], [3, "ngModelChange", "ngModel", "data", "valuePrimitive", "defaultItem"], ["kendoTextArea", "", "placeholder", "Describe what this scope allows...", 1, "form-textarea", 3, "ngModelChange", "ngModel", "rows"], [1, "checkbox-label"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModelChange", "ngModel"], [1, "checkbox-hint"], [1, "dialog-actions"], ["kendoButton", "", 3, "click", "themeColor", "disabled"], ["size", "small", 3, "showText"], ["kendoButton", "", 3, "click"], [1, "fa-solid", "fa-save"]], template: function APIScopesPanelComponent_Template(rf, ctx) { if (rf & 1) {
620
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: APIScopesPanelComponent, selectors: [["mj-api-scopes-panel"]], outputs: { ScopeUpdated: "ScopeUpdated" }, standalone: false, decls: 4, vars: 3, consts: [["scopeNode", ""], [1, "scopes-panel"], ["text", "Loading scopes..."], [3, "Width", "MinWidth", "MinHeight", "Resizable", "Draggable", "Visible", "Top"], [1, "panel-header"], [1, "header-left"], [1, "panel-title"], [1, "fa-solid", "fa-shield-halved"], [1, "panel-subtitle"], [1, "header-actions"], [1, "scope-stats"], [1, "stat"], [1, "fa-solid", "fa-shield"], [1, "stat", "active"], [1, "fa-solid", "fa-check-circle"], [1, "tree-controls"], ["title", "Expand All", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-plus-square"], ["title", "Collapse All", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-minus-square"], [1, "btn-create", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "message", "success"], [1, "message", "error"], [1, "scope-tree"], [1, "empty-state"], [1, "fa-solid", "fa-circle-exclamation"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"], [1, "scope-node"], [1, "node-content"], [1, "expand-btn"], [1, "expand-placeholder"], [1, "scope-info", 3, "click"], [1, "scope-icon"], [1, "scope-details"], [1, "scope-name"], [1, "full-path"], [1, "status-badge"], [1, "scope-meta"], [1, "category"], [1, "resource-type"], [1, "description"], [1, "node-actions"], ["title", "Add Child Scope", 1, "btn-node-action", 3, "click"], ["title", "Edit Scope", 1, "btn-node-action", 3, "click"], [1, "fa-solid", "fa-pencil"], [1, "children"], [1, "expand-btn", 3, "click"], [1, "fa-solid"], [3, "Close", "Width", "MinWidth", "MinHeight", "Resizable", "Draggable", "Visible", "Top"], [1, "dialog-title"], [1, "dialog-content"], [1, "form-field"], ["placeholder", "e.g., runview, create, execute", 1, "mj-input", "form-input", 3, "ngModelChange", "ngModel"], [1, "field-hint"], ["TextField", "FullPath", "ValueField", "ID", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive", "DefaultItem"], [1, "form-row"], [1, "form-field", "half"], [3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], [3, "ngModelChange", "ngModel", "Data", "ValuePrimitive", "DefaultItem"], ["placeholder", "Describe what this scope allows...", 1, "mj-textarea", "form-textarea", 3, "ngModelChange", "ngModel", "rows"], [1, "checkbox-label"], ["type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "checkbox-hint"], [1, "dialog-actions"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], ["size", "small", 3, "showText"], ["mjButton", "", 3, "click"], [1, "fa-solid", "fa-save"]], template: function APIScopesPanelComponent_Template(rf, ctx) { if (rf & 1) {
628
621
  i0.ɵɵelementStart(0, "div", 1);
629
622
  i0.ɵɵconditionalCreate(1, APIScopesPanelComponent_Conditional_1_Template, 1, 0, "mj-loading", 2);
630
623
  i0.ɵɵconditionalCreate(2, APIScopesPanelComponent_Conditional_2_Template, 31, 5);
631
- i0.ɵɵconditionalCreate(3, APIScopesPanelComponent_Conditional_3_Template, 47, 30, "kendo-window", 3);
624
+ i0.ɵɵconditionalCreate(3, APIScopesPanelComponent_Conditional_3_Template, 45, 28, "mj-window", 3);
632
625
  i0.ɵɵelementEnd();
633
626
  } if (rf & 2) {
634
627
  i0.ɵɵadvance();
@@ -637,11 +630,11 @@ export class APIScopesPanelComponent {
637
630
  i0.ɵɵconditional(!ctx.IsLoading ? 2 : -1);
638
631
  i0.ɵɵadvance();
639
632
  i0.ɵɵconditional(ctx.ShowCreateDialog || ctx.ShowEditDialog ? 3 : -1);
640
- } }, dependencies: [i1.NgTemplateOutlet, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.ButtonComponent, i4.DropDownListComponent, i5.TextBoxDirective, i5.TextAreaDirective, i5.CheckBoxDirective, i6.WindowComponent, i6.WindowTitleBarComponent, i7.LoadingComponent], styles: [".scopes-panel[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 200px;\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.panel-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.scope-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n}\n\n.stat[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.stat.active[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.stat[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.tree-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.btn-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.btn-create[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-create[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 16px;\n font-size: 14px;\n}\n\n.message.success[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.message.error[_ngcontent-%COMP%] {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n border: 1px solid var(--mj-status-error-border);\n}\n\n\n\n.scope-tree[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n}\n\n.scope-node[_ngcontent-%COMP%] {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.scope-node[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.node-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n transition: background 0.2s ease;\n}\n\n.node-content[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.node-content.inactive[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: transform 0.2s ease;\n flex-shrink: 0;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.expand-placeholder[_ngcontent-%COMP%] {\n width: 24px;\n flex-shrink: 0;\n}\n\n.scope-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n cursor: pointer;\n}\n\n.scope-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.scope-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-inverse);\n}\n\n.scope-details[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.scope-name[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n flex-wrap: wrap;\n}\n\n.full-path[_ngcontent-%COMP%] {\n font-family: monospace;\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 500;\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.scope-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-top: 4px;\n font-size: 12px;\n flex-wrap: wrap;\n}\n\n.category[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.resource-type[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.description[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 300px;\n}\n\n.node-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-left: 12px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.node-content[_ngcontent-%COMP%]:hover .node-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.btn-node-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-node-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.btn-node-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.children[_ngcontent-%COMP%] {\n margin-left: 0;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 500;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n margin-top: 8px;\n}\n\n\n\n\n\n\n\n\n[_nghost-%COMP%] kendo-window {\n border-radius: 16px !important;\n overflow: hidden;\n box-shadow: var(--mj-shadow-2xl) !important;\n background: var(--mj-bg-surface) !important;\n}\n\n[_nghost-%COMP%] kendo-window .k-window-content {\n padding: 0 !important;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--mj-bg-surface) !important;\n}\n\n[_nghost-%COMP%] kendo-window-titlebar {\n display: flex !important;\n align-items: center;\n justify-content: space-between;\n padding: 18px 24px !important;\n background: var(--mj-bg-page) !important;\n border-bottom: 1px solid var(--mj-border-default) !important;\n}\n\n.dialog-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n font-weight: 600;\n font-size: 17px;\n color: var(--mj-text-primary);\n}\n\n.dialog-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n font-size: 18px;\n}\n\n.window-close-btn[_ngcontent-%COMP%] {\n margin-left: auto;\n color: var(--mj-text-muted);\n transition: all 0.2s ease;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n}\n\n.window-close-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.window-close-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n\n\n.dialog-content[_ngcontent-%COMP%] {\n padding: 24px;\n flex: 1;\n overflow-y: auto;\n}\n\n\n\n.form-field[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.form-field[_ngcontent-%COMP%]:last-of-type {\n margin-bottom: 0;\n}\n\n.form-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n letter-spacing: 0.01em;\n}\n\n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.form-textarea[_ngcontent-%COMP%] {\n width: 100%;\n resize: vertical;\n min-height: 80px;\n}\n\n[_nghost-%COMP%] .form-input .k-input, \n[_nghost-%COMP%] .form-textarea .k-input-inner, \n[_nghost-%COMP%] .form-field .k-dropdownlist {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border-color: var(--mj-border-default);\n background: var(--mj-bg-surface) !important;\n color: var(--mj-text-primary) !important;\n transition: all 0.2s ease;\n}\n\n[_nghost-%COMP%] .form-input:focus-within, \n[_nghost-%COMP%] .form-textarea:focus-within, \n[_nghost-%COMP%] .form-field .k-dropdownlist.k-focus {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n}\n\n.field-hint[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 6px;\n line-height: 1.4;\n}\n\n.form-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n}\n\n.form-field.half[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n padding: 12px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s ease;\n}\n\n.checkbox-label[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.checkbox-label[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.checkbox-label[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:first-of-type {\n font-weight: 600;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.checkbox-hint[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n line-height: 1.4;\n}\n\n\n\n.dialog-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 20px 24px;\n background: var(--mj-bg-page);\n border-top: 1px solid var(--mj-border-default);\n margin: 0 -24px -24px -24px;\n}\n\n[_nghost-%COMP%] .dialog-actions .k-button {\n min-width: 100px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n[_nghost-%COMP%] .dialog-actions .k-button-solid-primary {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n border: none;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n[_nghost-%COMP%] .dialog-actions .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}"] });
633
+ } }, dependencies: [i1.NgTemplateOutlet, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.MJButtonDirective, i3.MJWindowComponent, i3.MJWindowTitlebarComponent, i3.MJDropdownComponent, i4.LoadingComponent], styles: [".scopes-panel[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 200px;\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.panel-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.scope-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n}\n\n.stat[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.stat.active[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.stat[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.tree-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.btn-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.btn-create[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-create[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 16px;\n font-size: 14px;\n}\n\n.message.success[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.message.error[_ngcontent-%COMP%] {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n border: 1px solid var(--mj-status-error-border);\n}\n\n\n\n.scope-tree[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n}\n\n.scope-node[_ngcontent-%COMP%] {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.scope-node[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.node-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n transition: background 0.2s ease;\n}\n\n.node-content[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.node-content.inactive[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: transform 0.2s ease;\n flex-shrink: 0;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.expand-placeholder[_ngcontent-%COMP%] {\n width: 24px;\n flex-shrink: 0;\n}\n\n.scope-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n cursor: pointer;\n}\n\n.scope-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.scope-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-inverse);\n}\n\n.scope-details[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.scope-name[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n flex-wrap: wrap;\n}\n\n.full-path[_ngcontent-%COMP%] {\n font-family: monospace;\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 500;\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.scope-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-top: 4px;\n font-size: 12px;\n flex-wrap: wrap;\n}\n\n.category[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.resource-type[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.description[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 300px;\n}\n\n.node-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-left: 12px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.node-content[_ngcontent-%COMP%]:hover .node-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.btn-node-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-node-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.btn-node-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.children[_ngcontent-%COMP%] {\n margin-left: 0;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 500;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n margin-top: 8px;\n}\n\n\n\n\n\n\n\n\n[_nghost-%COMP%] .mj-window {\n border-radius: 16px !important;\n overflow: hidden;\n box-shadow: var(--mj-shadow-2xl) !important;\n background: var(--mj-bg-surface) !important;\n}\n\n[_nghost-%COMP%] .mj-window-body {\n padding: 0 !important;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--mj-bg-surface) !important;\n}\n\n[_nghost-%COMP%] .mj-window-titlebar {\n display: flex !important;\n align-items: center;\n justify-content: space-between;\n padding: 18px 24px !important;\n background: var(--mj-bg-page) !important;\n border-bottom: 1px solid var(--mj-border-default) !important;\n}\n\n.dialog-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n font-weight: 600;\n font-size: 17px;\n color: var(--mj-text-primary);\n}\n\n.dialog-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n font-size: 18px;\n}\n\n.window-close-btn[_ngcontent-%COMP%] {\n margin-left: auto;\n color: var(--mj-text-muted);\n transition: all 0.2s ease;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n}\n\n.window-close-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.window-close-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n\n\n.dialog-content[_ngcontent-%COMP%] {\n padding: 24px;\n flex: 1;\n overflow-y: auto;\n}\n\n\n\n.form-field[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.form-field[_ngcontent-%COMP%]:last-of-type {\n margin-bottom: 0;\n}\n\n.form-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n letter-spacing: 0.01em;\n}\n\n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.form-textarea[_ngcontent-%COMP%] {\n width: 100%;\n resize: vertical;\n min-height: 80px;\n}\n\n[_nghost-%COMP%] .form-input.mj-input, \n[_nghost-%COMP%] .form-textarea.mj-textarea, \n[_nghost-%COMP%] .form-field .mj-dropdown {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border-color: var(--mj-border-default);\n background: var(--mj-bg-surface) !important;\n color: var(--mj-text-primary) !important;\n transition: all 0.2s ease;\n}\n\n[_nghost-%COMP%] .form-input.mj-input:focus-within, \n[_nghost-%COMP%] .form-textarea.mj-textarea:focus-within, \n[_nghost-%COMP%] .form-field .mj-dropdown:focus-within {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n}\n\n.field-hint[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 6px;\n line-height: 1.4;\n}\n\n.form-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n}\n\n.form-field.half[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n padding: 12px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s ease;\n}\n\n.checkbox-label[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.checkbox-label[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.checkbox-label[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:first-of-type {\n font-weight: 600;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.checkbox-hint[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n line-height: 1.4;\n}\n\n\n\n.dialog-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 20px 24px;\n background: var(--mj-bg-page);\n border-top: 1px solid var(--mj-border-default);\n margin: 0 -24px -24px -24px;\n}\n\n[_nghost-%COMP%] .dialog-actions .mj-button {\n min-width: 100px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n[_nghost-%COMP%] .dialog-actions .mj-button-primary {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n border: none;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n[_nghost-%COMP%] .dialog-actions .mj-button-primary:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}"] });
641
634
  }
642
635
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIScopesPanelComponent, [{
643
636
  type: Component,
644
- args: [{ standalone: false, selector: 'mj-api-scopes-panel', template: "<div class=\"scopes-panel\">\n @if (IsLoading) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <h3 class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n API Scopes\n </h3>\n <p class=\"panel-subtitle\">Manage hierarchical permission scopes for API access</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"scope-stats\">\n <span class=\"stat\">\n <i class=\"fa-solid fa-shield\"></i>\n {{getTotalCount()}} total\n </span>\n <span class=\"stat active\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{getActiveCount()}} active\n </span>\n </div>\n <div class=\"tree-controls\">\n <button class=\"btn-icon\" (click)=\"expandAll()\" title=\"Expand All\">\n <i class=\"fa-solid fa-plus-square\"></i>\n </button>\n <button class=\"btn-icon\" (click)=\"collapseAll()\" title=\"Collapse All\">\n <i class=\"fa-solid fa-minus-square\"></i>\n </button>\n </div>\n <button class=\"btn-create\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Scope\n </button>\n </div>\n </div>\n <!-- Messages -->\n @if (SuccessMessage) {\n <div class=\"message success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{SuccessMessage}}\n </div>\n }\n @if (ErrorMessage) {\n <div class=\"message error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ErrorMessage}}\n </div>\n }\n <!-- Scope Tree -->\n <div class=\"scope-tree\">\n @for (node of ScopeTree; track node) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: node }\"></ng-container>\n }\n <!-- Empty State -->\n @if (ScopeTree.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n <p>Create scopes to define API access permissions</p>\n </div>\n }\n </div>\n <!-- Recursive Node Template -->\n <ng-template #scopeNode let-node=\"node\">\n <div class=\"scope-node\" [style.padding-left.px]=\"node.level * 24\">\n <div class=\"node-content\" [class.inactive]=\"!node.scope.IsActive\">\n @if (node.children.length > 0) {\n <button class=\"expand-btn\"\n (click)=\"toggleExpanded(node)\">\n <i class=\"fa-solid\"\n [class.fa-chevron-right]=\"!node.expanded\"\n [class.fa-chevron-down]=\"node.expanded\"></i>\n </button>\n }\n @if (node.children.length === 0) {\n <span class=\"expand-placeholder\"></span>\n }\n <div class=\"scope-info\" (click)=\"openEditDialog(node.scope)\">\n <div class=\"scope-icon\" [style.backgroundColor]=\"getCategoryColor(node.scope.Category)\">\n <i class=\"fa-solid fa-shield\"></i>\n </div>\n <div class=\"scope-details\">\n <div class=\"scope-name\">\n {{node.scope.Name}}\n @if (node.scope.FullPath && node.scope.FullPath !== node.scope.Name) {\n <span class=\"full-path\">\n {{node.scope.FullPath}}\n </span>\n }\n @if (!node.scope.IsActive) {\n <span class=\"status-badge\">Inactive</span>\n }\n </div>\n <div class=\"scope-meta\">\n <span class=\"category\" [style.color]=\"getCategoryColor(node.scope.Category)\">\n {{node.scope.Category}}\n </span>\n @if (node.scope.ResourceType) {\n <span class=\"resource-type\">\n {{node.scope.ResourceType}}\n </span>\n }\n @if (node.scope.Description) {\n <span class=\"description\">\n {{node.scope.Description}}\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"node-actions\">\n <button class=\"btn-node-action\" (click)=\"openCreateDialog(node.scope)\" title=\"Add Child Scope\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"btn-node-action\" (click)=\"openEditDialog(node.scope)\" title=\"Edit Scope\">\n <i class=\"fa-solid fa-pencil\"></i>\n </button>\n </div>\n </div>\n @if (node.expanded && node.children.length > 0) {\n <div class=\"children\">\n @for (child of node.children; track child) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: child }\"></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n }\n\n <!-- Create/Edit Dialog -->\n @if (ShowCreateDialog || ShowEditDialog) {\n <kendo-window\n [width]=\"560\"\n [minWidth]=\"420\"\n [minHeight]=\"480\"\n [resizable]=\"true\"\n [draggable]=\"true\"\n [top]=\"80\"\n (close)=\"closeDialogs()\">\n <kendo-window-titlebar>\n <div class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{EditingScope ? 'Edit Scope' : 'New Scope'}}</span>\n </div>\n <button kendoButton fillMode=\"flat\" (click)=\"closeDialogs()\" class=\"window-close-btn\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </kendo-window-titlebar>\n <div class=\"dialog-content\">\n <div class=\"form-field\">\n <label>Scope Name *</label>\n <input kendoTextBox [(ngModel)]=\"EditName\"\n placeholder=\"e.g., runview, create, execute\"\n class=\"form-input\" />\n <span class=\"field-hint\">Use lowercase, single word. Will be combined with parent for full path.</span>\n </div>\n <div class=\"form-field\">\n <label>Parent Scope</label>\n <kendo-dropdownlist [(ngModel)]=\"EditParentId\"\n [data]=\"getParentOptions()\"\n [textField]=\"'FullPath'\"\n [valueField]=\"'ID'\"\n [valuePrimitive]=\"true\"\n [defaultItem]=\"{ FullPath: '(No Parent - Root Level)', ID: null }\">\n </kendo-dropdownlist>\n @if (SelectedParentScope) {\n <span class=\"field-hint\">\n Full path will be: <code>{{SelectedParentScope.FullPath}}:{{EditName || '...'}}</code>\n </span>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field half\">\n <label>Category</label>\n <kendo-dropdownlist [(ngModel)]=\"EditCategory\"\n [data]=\"Categories\"\n [valuePrimitive]=\"true\">\n </kendo-dropdownlist>\n </div>\n <div class=\"form-field half\">\n <label>Resource Type</label>\n <kendo-dropdownlist [(ngModel)]=\"EditResourceType\"\n [data]=\"ResourceTypes\"\n [valuePrimitive]=\"true\"\n [defaultItem]=\"''\">\n </kendo-dropdownlist>\n </div>\n </div>\n <div class=\"form-field\">\n <label>Description</label>\n <textarea kendoTextArea [(ngModel)]=\"EditDescription\"\n placeholder=\"Describe what this scope allows...\"\n [rows]=\"3\"\n class=\"form-textarea\"></textarea>\n </div>\n <div class=\"form-field\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" kendoCheckBox [(ngModel)]=\"EditIsActive\" />\n <div>\n <span>Active</span>\n <span class=\"checkbox-hint\">Inactive scopes cannot be assigned to keys or applications</span>\n </div>\n </label>\n </div>\n <div class=\"dialog-actions\">\n <button kendoButton [themeColor]=\"'primary'\"\n [disabled]=\"!EditName.trim() || IsSaving\"\n (click)=\"saveScope()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n {{EditingScope ? 'Update' : 'Create'}}\n </span>\n }\n </button>\n <button kendoButton (click)=\"closeDialogs()\">Cancel</button>\n </div>\n </div>\n </kendo-window>\n }\n</div>\n", styles: [".scopes-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n/* Panel Header */\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n.header-left {\n flex: 1;\n min-width: 200px;\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.panel-title i {\n color: var(--mj-status-success);\n}\n\n.panel-subtitle {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.scope-stats {\n display: flex;\n gap: 16px;\n}\n\n.stat {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.stat.active {\n color: var(--mj-status-success);\n}\n\n.stat i {\n font-size: 14px;\n}\n\n.tree-controls {\n display: flex;\n gap: 4px;\n}\n\n.btn-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.btn-icon i {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.btn-create {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-create:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n\n/* Messages */\n.message {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 16px;\n font-size: 14px;\n}\n\n.message.success {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.message.error {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n border: 1px solid var(--mj-status-error-border);\n}\n\n/* Scope Tree */\n.scope-tree {\n flex: 1;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n}\n\n.scope-node {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.scope-node:last-child {\n border-bottom: none;\n}\n\n.node-content {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n transition: background 0.2s ease;\n}\n\n.node-content:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.node-content.inactive {\n opacity: 0.6;\n}\n\n.expand-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: transform 0.2s ease;\n flex-shrink: 0;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.expand-placeholder {\n width: 24px;\n flex-shrink: 0;\n}\n\n.scope-info {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n cursor: pointer;\n}\n\n.scope-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.scope-icon i {\n font-size: 14px;\n color: var(--mj-text-inverse);\n}\n\n.scope-details {\n flex: 1;\n min-width: 0;\n}\n\n.scope-name {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n flex-wrap: wrap;\n}\n\n.full-path {\n font-family: monospace;\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.status-badge {\n font-size: 10px;\n font-weight: 500;\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.scope-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-top: 4px;\n font-size: 12px;\n flex-wrap: wrap;\n}\n\n.category {\n font-weight: 500;\n}\n\n.resource-type {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.description {\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 300px;\n}\n\n.node-actions {\n display: flex;\n gap: 4px;\n margin-left: 12px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.node-content:hover .node-actions {\n opacity: 1;\n}\n\n.btn-node-action {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-node-action:hover {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.btn-node-action i {\n font-size: 12px;\n}\n\n.children {\n margin-left: 0;\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: 48px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state span {\n font-size: 16px;\n font-weight: 500;\n}\n\n.empty-state p {\n font-size: 14px;\n margin-top: 8px;\n}\n\n/* ========================================\n Dialog Styles - Polished & Professional\n ======================================== */\n\n/* Window styling */\n:host ::ng-deep kendo-window {\n border-radius: 16px !important;\n overflow: hidden;\n box-shadow: var(--mj-shadow-2xl) !important;\n background: var(--mj-bg-surface) !important;\n}\n\n:host ::ng-deep kendo-window .k-window-content {\n padding: 0 !important;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--mj-bg-surface) !important;\n}\n\n:host ::ng-deep kendo-window-titlebar {\n display: flex !important;\n align-items: center;\n justify-content: space-between;\n padding: 18px 24px !important;\n background: var(--mj-bg-page) !important;\n border-bottom: 1px solid var(--mj-border-default) !important;\n}\n\n.dialog-title {\n display: flex;\n align-items: center;\n gap: 12px;\n font-weight: 600;\n font-size: 17px;\n color: var(--mj-text-primary);\n}\n\n.dialog-title i {\n color: var(--mj-status-success);\n font-size: 18px;\n}\n\n.window-close-btn {\n margin-left: auto;\n color: var(--mj-text-muted);\n transition: all 0.2s ease;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n}\n\n.window-close-btn:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.window-close-btn i {\n font-size: 16px;\n}\n\n/* Dialog Content */\n.dialog-content {\n padding: 24px;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Form Fields */\n.form-field {\n margin-bottom: 20px;\n}\n\n.form-field:last-of-type {\n margin-bottom: 0;\n}\n\n.form-field label {\n display: block;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n letter-spacing: 0.01em;\n}\n\n.form-input {\n width: 100%;\n}\n\n.form-textarea {\n width: 100%;\n resize: vertical;\n min-height: 80px;\n}\n\n:host ::ng-deep .form-input .k-input,\n:host ::ng-deep .form-textarea .k-input-inner,\n:host ::ng-deep .form-field .k-dropdownlist {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border-color: var(--mj-border-default);\n background: var(--mj-bg-surface) !important;\n color: var(--mj-text-primary) !important;\n transition: all 0.2s ease;\n}\n\n:host ::ng-deep .form-input:focus-within,\n:host ::ng-deep .form-textarea:focus-within,\n:host ::ng-deep .form-field .k-dropdownlist.k-focus {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n}\n\n.field-hint {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 6px;\n line-height: 1.4;\n}\n\n.form-row {\n display: flex;\n gap: 16px;\n}\n\n.form-field.half {\n flex: 1;\n}\n\n.checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n padding: 12px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s ease;\n}\n\n.checkbox-label:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.checkbox-label input {\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.checkbox-label span:first-of-type {\n font-weight: 600;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.checkbox-hint {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n line-height: 1.4;\n}\n\n/* Dialog Actions */\n.dialog-actions {\n display: flex;\n gap: 12px;\n padding: 20px 24px;\n background: var(--mj-bg-page);\n border-top: 1px solid var(--mj-border-default);\n margin: 0 -24px -24px -24px;\n}\n\n:host ::ng-deep .dialog-actions .k-button {\n min-width: 100px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n:host ::ng-deep .dialog-actions .k-button-solid-primary {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n border: none;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n:host ::ng-deep .dialog-actions .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n"] }]
637
+ args: [{ standalone: false, selector: 'mj-api-scopes-panel', template: "<div class=\"scopes-panel\">\n @if (IsLoading) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <h3 class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n API Scopes\n </h3>\n <p class=\"panel-subtitle\">Manage hierarchical permission scopes for API access</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"scope-stats\">\n <span class=\"stat\">\n <i class=\"fa-solid fa-shield\"></i>\n {{getTotalCount()}} total\n </span>\n <span class=\"stat active\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{getActiveCount()}} active\n </span>\n </div>\n <div class=\"tree-controls\">\n <button class=\"btn-icon\" (click)=\"expandAll()\" title=\"Expand All\">\n <i class=\"fa-solid fa-plus-square\"></i>\n </button>\n <button class=\"btn-icon\" (click)=\"collapseAll()\" title=\"Collapse All\">\n <i class=\"fa-solid fa-minus-square\"></i>\n </button>\n </div>\n <button class=\"btn-create\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Scope\n </button>\n </div>\n </div>\n <!-- Messages -->\n @if (SuccessMessage) {\n <div class=\"message success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{SuccessMessage}}\n </div>\n }\n @if (ErrorMessage) {\n <div class=\"message error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ErrorMessage}}\n </div>\n }\n <!-- Scope Tree -->\n <div class=\"scope-tree\">\n @for (node of ScopeTree; track node) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: node }\"></ng-container>\n }\n <!-- Empty State -->\n @if (ScopeTree.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n <p>Create scopes to define API access permissions</p>\n </div>\n }\n </div>\n <!-- Recursive Node Template -->\n <ng-template #scopeNode let-node=\"node\">\n <div class=\"scope-node\" [style.padding-left.px]=\"node.level * 24\">\n <div class=\"node-content\" [class.inactive]=\"!node.scope.IsActive\">\n @if (node.children.length > 0) {\n <button class=\"expand-btn\"\n (click)=\"toggleExpanded(node)\">\n <i class=\"fa-solid\"\n [class.fa-chevron-right]=\"!node.expanded\"\n [class.fa-chevron-down]=\"node.expanded\"></i>\n </button>\n }\n @if (node.children.length === 0) {\n <span class=\"expand-placeholder\"></span>\n }\n <div class=\"scope-info\" (click)=\"openEditDialog(node.scope)\">\n <div class=\"scope-icon\" [style.backgroundColor]=\"getCategoryColor(node.scope.Category)\">\n <i class=\"fa-solid fa-shield\"></i>\n </div>\n <div class=\"scope-details\">\n <div class=\"scope-name\">\n {{node.scope.Name}}\n @if (node.scope.FullPath && node.scope.FullPath !== node.scope.Name) {\n <span class=\"full-path\">\n {{node.scope.FullPath}}\n </span>\n }\n @if (!node.scope.IsActive) {\n <span class=\"status-badge\">Inactive</span>\n }\n </div>\n <div class=\"scope-meta\">\n <span class=\"category\" [style.color]=\"getCategoryColor(node.scope.Category)\">\n {{node.scope.Category}}\n </span>\n @if (node.scope.ResourceType) {\n <span class=\"resource-type\">\n {{node.scope.ResourceType}}\n </span>\n }\n @if (node.scope.Description) {\n <span class=\"description\">\n {{node.scope.Description}}\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"node-actions\">\n <button class=\"btn-node-action\" (click)=\"openCreateDialog(node.scope)\" title=\"Add Child Scope\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"btn-node-action\" (click)=\"openEditDialog(node.scope)\" title=\"Edit Scope\">\n <i class=\"fa-solid fa-pencil\"></i>\n </button>\n </div>\n </div>\n @if (node.expanded && node.children.length > 0) {\n <div class=\"children\">\n @for (child of node.children; track child) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: child }\"></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n }\n\n <!-- Create/Edit Dialog -->\n @if (ShowCreateDialog || ShowEditDialog) {\n <mj-window\n [Width]=\"560\"\n [MinWidth]=\"420\"\n [MinHeight]=\"480\"\n [Resizable]=\"true\"\n [Draggable]=\"true\"\n [Visible]=\"true\"\n [Top]=\"80\"\n (Close)=\"closeDialogs()\">\n <mj-window-titlebar>\n <div class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{EditingScope ? 'Edit Scope' : 'New Scope'}}</span>\n </div>\n </mj-window-titlebar>\n <div class=\"dialog-content\">\n <div class=\"form-field\">\n <label>Scope Name *</label>\n <input class=\"mj-input form-input\" [(ngModel)]=\"EditName\"\n placeholder=\"e.g., runview, create, execute\" />\n <span class=\"field-hint\">Use lowercase, single word. Will be combined with parent for full path.</span>\n </div>\n <div class=\"form-field\">\n <label>Parent Scope</label>\n <mj-dropdown [(ngModel)]=\"EditParentId\"\n [Data]=\"getParentOptions()\"\n TextField=\"FullPath\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [DefaultItem]=\"{ FullPath: '(No Parent - Root Level)', ID: null }\">\n </mj-dropdown>\n @if (SelectedParentScope) {\n <span class=\"field-hint\">\n Full path will be: <code>{{SelectedParentScope.FullPath}}:{{EditName || '...'}}</code>\n </span>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field half\">\n <label>Category</label>\n <mj-dropdown [(ngModel)]=\"EditCategory\"\n [Data]=\"Categories\"\n [ValuePrimitive]=\"true\">\n </mj-dropdown>\n </div>\n <div class=\"form-field half\">\n <label>Resource Type</label>\n <mj-dropdown [(ngModel)]=\"EditResourceType\"\n [Data]=\"ResourceTypes\"\n [ValuePrimitive]=\"true\"\n [DefaultItem]=\"''\">\n </mj-dropdown>\n </div>\n </div>\n <div class=\"form-field\">\n <label>Description</label>\n <textarea class=\"mj-textarea form-textarea\" [(ngModel)]=\"EditDescription\"\n placeholder=\"Describe what this scope allows...\"\n [rows]=\"3\"></textarea>\n </div>\n <div class=\"form-field\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" class=\"mj-checkbox\" [(ngModel)]=\"EditIsActive\" />\n <div>\n <span>Active</span>\n <span class=\"checkbox-hint\">Inactive scopes cannot be assigned to keys or applications</span>\n </div>\n </label>\n </div>\n <div class=\"dialog-actions\">\n <button mjButton variant=\"primary\"\n [disabled]=\"!EditName.trim() || IsSaving\"\n (click)=\"saveScope()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n {{EditingScope ? 'Update' : 'Create'}}\n </span>\n }\n </button>\n <button mjButton (click)=\"closeDialogs()\">Cancel</button>\n </div>\n </div>\n </mj-window>\n }\n</div>\n", styles: [".scopes-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n/* Panel Header */\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n.header-left {\n flex: 1;\n min-width: 200px;\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.panel-title i {\n color: var(--mj-status-success);\n}\n\n.panel-subtitle {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.scope-stats {\n display: flex;\n gap: 16px;\n}\n\n.stat {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.stat.active {\n color: var(--mj-status-success);\n}\n\n.stat i {\n font-size: 14px;\n}\n\n.tree-controls {\n display: flex;\n gap: 4px;\n}\n\n.btn-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.btn-icon i {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.btn-create {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-create:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n\n/* Messages */\n.message {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 16px;\n font-size: 14px;\n}\n\n.message.success {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.message.error {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n border: 1px solid var(--mj-status-error-border);\n}\n\n/* Scope Tree */\n.scope-tree {\n flex: 1;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n}\n\n.scope-node {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.scope-node:last-child {\n border-bottom: none;\n}\n\n.node-content {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n transition: background 0.2s ease;\n}\n\n.node-content:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.node-content.inactive {\n opacity: 0.6;\n}\n\n.expand-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: transform 0.2s ease;\n flex-shrink: 0;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.expand-placeholder {\n width: 24px;\n flex-shrink: 0;\n}\n\n.scope-info {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n cursor: pointer;\n}\n\n.scope-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.scope-icon i {\n font-size: 14px;\n color: var(--mj-text-inverse);\n}\n\n.scope-details {\n flex: 1;\n min-width: 0;\n}\n\n.scope-name {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n flex-wrap: wrap;\n}\n\n.full-path {\n font-family: monospace;\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.status-badge {\n font-size: 10px;\n font-weight: 500;\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.scope-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-top: 4px;\n font-size: 12px;\n flex-wrap: wrap;\n}\n\n.category {\n font-weight: 500;\n}\n\n.resource-type {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.description {\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 300px;\n}\n\n.node-actions {\n display: flex;\n gap: 4px;\n margin-left: 12px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.node-content:hover .node-actions {\n opacity: 1;\n}\n\n.btn-node-action {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-node-action:hover {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.btn-node-action i {\n font-size: 12px;\n}\n\n.children {\n margin-left: 0;\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: 48px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state span {\n font-size: 16px;\n font-weight: 500;\n}\n\n.empty-state p {\n font-size: 14px;\n margin-top: 8px;\n}\n\n/* ========================================\n Dialog Styles - Polished & Professional\n ======================================== */\n\n/* Window styling */\n:host ::ng-deep .mj-window {\n border-radius: 16px !important;\n overflow: hidden;\n box-shadow: var(--mj-shadow-2xl) !important;\n background: var(--mj-bg-surface) !important;\n}\n\n:host ::ng-deep .mj-window-body {\n padding: 0 !important;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--mj-bg-surface) !important;\n}\n\n:host ::ng-deep .mj-window-titlebar {\n display: flex !important;\n align-items: center;\n justify-content: space-between;\n padding: 18px 24px !important;\n background: var(--mj-bg-page) !important;\n border-bottom: 1px solid var(--mj-border-default) !important;\n}\n\n.dialog-title {\n display: flex;\n align-items: center;\n gap: 12px;\n font-weight: 600;\n font-size: 17px;\n color: var(--mj-text-primary);\n}\n\n.dialog-title i {\n color: var(--mj-status-success);\n font-size: 18px;\n}\n\n.window-close-btn {\n margin-left: auto;\n color: var(--mj-text-muted);\n transition: all 0.2s ease;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n}\n\n.window-close-btn:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.window-close-btn i {\n font-size: 16px;\n}\n\n/* Dialog Content */\n.dialog-content {\n padding: 24px;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Form Fields */\n.form-field {\n margin-bottom: 20px;\n}\n\n.form-field:last-of-type {\n margin-bottom: 0;\n}\n\n.form-field label {\n display: block;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n letter-spacing: 0.01em;\n}\n\n.form-input {\n width: 100%;\n}\n\n.form-textarea {\n width: 100%;\n resize: vertical;\n min-height: 80px;\n}\n\n:host ::ng-deep .form-input.mj-input,\n:host ::ng-deep .form-textarea.mj-textarea,\n:host ::ng-deep .form-field .mj-dropdown {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border-color: var(--mj-border-default);\n background: var(--mj-bg-surface) !important;\n color: var(--mj-text-primary) !important;\n transition: all 0.2s ease;\n}\n\n:host ::ng-deep .form-input.mj-input:focus-within,\n:host ::ng-deep .form-textarea.mj-textarea:focus-within,\n:host ::ng-deep .form-field .mj-dropdown:focus-within {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n}\n\n.field-hint {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 6px;\n line-height: 1.4;\n}\n\n.form-row {\n display: flex;\n gap: 16px;\n}\n\n.form-field.half {\n flex: 1;\n}\n\n.checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n padding: 12px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s ease;\n}\n\n.checkbox-label:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.checkbox-label input {\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.checkbox-label span:first-of-type {\n font-weight: 600;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.checkbox-hint {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n line-height: 1.4;\n}\n\n/* Dialog Actions */\n.dialog-actions {\n display: flex;\n gap: 12px;\n padding: 20px 24px;\n background: var(--mj-bg-page);\n border-top: 1px solid var(--mj-border-default);\n margin: 0 -24px -24px -24px;\n}\n\n:host ::ng-deep .dialog-actions .mj-button {\n min-width: 100px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n:host ::ng-deep .dialog-actions .mj-button-primary {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n border: none;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n:host ::ng-deep .dialog-actions .mj-button-primary:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n"] }]
645
638
  }], () => [{ type: i0.ChangeDetectorRef }], { ScopeUpdated: [{
646
639
  type: Output
647
640
  }] }); })();
@@ -1 +1 @@
1
- {"version":3,"file":"api-scopes-panel.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-scopes-panel.component.ts","../../src/APIKeys/api-scopes-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, EventEmitter, Output, ChangeDetectorRef } from '@angular/core';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJAPIScopeEntity } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n/** Scope tree node structure */\ninterface ScopeTreeNode {\n scope: MJAPIScopeEntity;\n children: ScopeTreeNode[];\n expanded: boolean;\n level: number;\n}\n\n/**\n * API Scopes Panel Component\n * Manages API Scopes in a hierarchical tree structure\n */\n@Component({\n standalone: false,\n selector: 'mj-api-scopes-panel',\n templateUrl: './api-scopes-panel.component.html',\n styleUrls: ['./api-scopes-panel.component.css']\n})\nexport class APIScopesPanelComponent implements OnInit {\n @Output() ScopeUpdated = new EventEmitter<void>();\n\n private md = new Metadata();\n private cdr: ChangeDetectorRef;\n\n // Loading states\n public IsLoading = true;\n public IsSaving = false;\n\n // Data\n public ScopeTree: ScopeTreeNode[] = [];\n public FlatScopes: MJAPIScopeEntity[] = [];\n\n // Edit state\n public EditingScope: MJAPIScopeEntity | null = null;\n public EditName = '';\n public EditDescription = '';\n public EditCategory = '';\n public EditResourceType = '';\n public EditParentId: string | null = null;\n public EditIsActive = true;\n\n // Dialog states\n public ShowCreateDialog = false;\n public ShowEditDialog = false;\n public SelectedParentScope: MJAPIScopeEntity | null = null;\n\n // Messages\n public SuccessMessage = '';\n public ErrorMessage = '';\n\n // Category colors\n public readonly CategoryColors: Record<string, string> = {\n 'Entities': '#6366f1',\n 'Agents': '#10b981',\n 'Admin': '#f59e0b',\n 'Actions': '#8b5cf6',\n 'Queries': '#3b82f6',\n 'Reports': '#ef4444',\n 'Communication': '#ec4899',\n 'Other': '#6b7280'\n };\n\n // Resource type options\n public readonly ResourceTypes = ['Entity', 'Agent', 'Query', 'Mutation', 'Action', 'Report', 'Admin', 'Other'];\n public readonly Categories = ['Entities', 'Agents', 'Admin', 'Actions', 'Queries', 'Reports', 'Communication', 'Other'];\n\n constructor(cdr: ChangeDetectorRef) {\n this.cdr = cdr;\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n /**\n * Load all scopes\n */\n public async loadData(): Promise<void> {\n this.IsLoading = true;\n try {\n const rv = new RunView();\n const result = await rv.RunView<MJAPIScopeEntity>({\n EntityName: 'MJ: API Scopes',\n OrderBy: 'FullPath',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.FlatScopes = result.Results;\n this.buildTree();\n }\n } catch (error) {\n console.error('Error loading scopes:', error);\n this.ErrorMessage = 'Failed to load scopes';\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Build tree structure from flat scopes\n */\n private buildTree(): void {\n const scopeMap = new Map<string, ScopeTreeNode>();\n const rootNodes: ScopeTreeNode[] = [];\n\n // Create nodes\n for (const scope of this.FlatScopes) {\n scopeMap.set(scope.ID, {\n scope,\n children: [],\n expanded: true,\n level: 0\n });\n }\n\n // Build hierarchy\n for (const scope of this.FlatScopes) {\n const node = scopeMap.get(scope.ID)!;\n if (scope.ParentID) {\n const parent = scopeMap.get(scope.ParentID);\n if (parent) {\n parent.children.push(node);\n node.level = parent.level + 1;\n } else {\n rootNodes.push(node);\n }\n } else {\n rootNodes.push(node);\n }\n }\n\n // Calculate levels recursively\n const calculateLevels = (nodes: ScopeTreeNode[], level: number) => {\n for (const node of nodes) {\n node.level = level;\n calculateLevels(node.children, level + 1);\n }\n };\n calculateLevels(rootNodes, 0);\n\n this.ScopeTree = rootNodes;\n }\n\n /**\n * Open create dialog for new scope\n */\n public openCreateDialog(parentScope: MJAPIScopeEntity | null = null): void {\n this.EditName = '';\n this.EditDescription = '';\n this.EditCategory = parentScope?.Category || 'Entities';\n this.EditResourceType = '';\n this.EditParentId = parentScope?.ID || null;\n this.EditIsActive = true;\n this.EditingScope = null;\n this.SelectedParentScope = parentScope;\n this.ShowCreateDialog = true;\n }\n\n /**\n * Open edit dialog for existing scope\n */\n public openEditDialog(scope: MJAPIScopeEntity): void {\n this.EditingScope = scope;\n this.EditName = scope.Name;\n this.EditDescription = scope.Description || '';\n this.EditCategory = scope.Category || 'Entities';\n this.EditResourceType = scope.ResourceType || '';\n this.EditParentId = scope.ParentID;\n this.EditIsActive = scope.IsActive;\n this.SelectedParentScope = scope.ParentID\n ? this.FlatScopes.find(s => UUIDsEqual(s.ID, scope.ParentID)) || null\n : null;\n this.ShowEditDialog = true;\n }\n\n /**\n * Save scope (create or update)\n */\n public async saveScope(): Promise<void> {\n this.IsSaving = true;\n this.ErrorMessage = '';\n\n try {\n let scope: MJAPIScopeEntity;\n\n if (this.EditingScope) {\n scope = this.EditingScope;\n } else {\n scope = await this.md.GetEntityObject<MJAPIScopeEntity>('MJ: API Scopes');\n scope.NewRecord();\n }\n\n scope.Name = this.EditName.trim();\n scope.Description = this.EditDescription.trim() || null;\n scope.Category = this.EditCategory;\n scope.ResourceType = this.EditResourceType || null;\n scope.ParentID = this.EditParentId;\n scope.IsActive = this.EditIsActive;\n // FullPath is auto-computed by the trigger\n\n const result = await scope.Save();\n if (result) {\n this.SuccessMessage = this.EditingScope\n ? 'Scope updated successfully'\n : 'Scope created successfully';\n this.closeDialogs();\n await this.loadData();\n this.ScopeUpdated.emit();\n setTimeout(() => this.SuccessMessage = '', 3000);\n } else {\n this.ErrorMessage = 'Failed to save scope';\n }\n } catch (error) {\n console.error('Error saving scope:', error);\n this.ErrorMessage = 'An error occurred while saving';\n } finally {\n this.IsSaving = false;\n }\n }\n\n /**\n * Toggle node expansion\n */\n public toggleExpanded(node: ScopeTreeNode): void {\n node.expanded = !node.expanded;\n }\n\n /**\n * Expand all nodes\n */\n public expandAll(): void {\n const expand = (nodes: ScopeTreeNode[]) => {\n for (const node of nodes) {\n node.expanded = true;\n expand(node.children);\n }\n };\n expand(this.ScopeTree);\n }\n\n /**\n * Collapse all nodes\n */\n public collapseAll(): void {\n const collapse = (nodes: ScopeTreeNode[]) => {\n for (const node of nodes) {\n node.expanded = false;\n collapse(node.children);\n }\n };\n collapse(this.ScopeTree);\n }\n\n /**\n * Close all dialogs\n */\n public closeDialogs(): void {\n this.ShowCreateDialog = false;\n this.ShowEditDialog = false;\n this.EditingScope = null;\n this.SelectedParentScope = null;\n }\n\n /**\n * Get parent scopes for dropdown (exclude self and descendants)\n */\n public getParentOptions(): MJAPIScopeEntity[] {\n if (!this.EditingScope) {\n return this.FlatScopes;\n }\n\n // Exclude self and all descendants\n const excludeIds = new Set<string>([this.EditingScope.ID]);\n const addDescendants = (parentId: string) => {\n for (const scope of this.FlatScopes) {\n if (UUIDsEqual(scope.ParentID, parentId) && !excludeIds.has(scope.ID)) {\n excludeIds.add(scope.ID);\n addDescendants(scope.ID);\n }\n }\n };\n addDescendants(this.EditingScope.ID);\n\n return this.FlatScopes.filter(s => !excludeIds.has(s.ID));\n }\n\n /**\n * Get category color\n */\n public getCategoryColor(category: string | null): string {\n return this.CategoryColors[category || 'Other'] || this.CategoryColors['Other'];\n }\n\n /**\n * Get count of total scopes\n */\n public getTotalCount(): number {\n return this.FlatScopes.length;\n }\n\n /**\n * Get count of active scopes\n */\n public getActiveCount(): number {\n return this.FlatScopes.filter(s => s.IsActive).length;\n }\n}\n","<div class=\"scopes-panel\">\n @if (IsLoading) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <h3 class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n API Scopes\n </h3>\n <p class=\"panel-subtitle\">Manage hierarchical permission scopes for API access</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"scope-stats\">\n <span class=\"stat\">\n <i class=\"fa-solid fa-shield\"></i>\n {{getTotalCount()}} total\n </span>\n <span class=\"stat active\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{getActiveCount()}} active\n </span>\n </div>\n <div class=\"tree-controls\">\n <button class=\"btn-icon\" (click)=\"expandAll()\" title=\"Expand All\">\n <i class=\"fa-solid fa-plus-square\"></i>\n </button>\n <button class=\"btn-icon\" (click)=\"collapseAll()\" title=\"Collapse All\">\n <i class=\"fa-solid fa-minus-square\"></i>\n </button>\n </div>\n <button class=\"btn-create\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Scope\n </button>\n </div>\n </div>\n <!-- Messages -->\n @if (SuccessMessage) {\n <div class=\"message success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{SuccessMessage}}\n </div>\n }\n @if (ErrorMessage) {\n <div class=\"message error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ErrorMessage}}\n </div>\n }\n <!-- Scope Tree -->\n <div class=\"scope-tree\">\n @for (node of ScopeTree; track node) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: node }\"></ng-container>\n }\n <!-- Empty State -->\n @if (ScopeTree.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n <p>Create scopes to define API access permissions</p>\n </div>\n }\n </div>\n <!-- Recursive Node Template -->\n <ng-template #scopeNode let-node=\"node\">\n <div class=\"scope-node\" [style.padding-left.px]=\"node.level * 24\">\n <div class=\"node-content\" [class.inactive]=\"!node.scope.IsActive\">\n @if (node.children.length > 0) {\n <button class=\"expand-btn\"\n (click)=\"toggleExpanded(node)\">\n <i class=\"fa-solid\"\n [class.fa-chevron-right]=\"!node.expanded\"\n [class.fa-chevron-down]=\"node.expanded\"></i>\n </button>\n }\n @if (node.children.length === 0) {\n <span class=\"expand-placeholder\"></span>\n }\n <div class=\"scope-info\" (click)=\"openEditDialog(node.scope)\">\n <div class=\"scope-icon\" [style.backgroundColor]=\"getCategoryColor(node.scope.Category)\">\n <i class=\"fa-solid fa-shield\"></i>\n </div>\n <div class=\"scope-details\">\n <div class=\"scope-name\">\n {{node.scope.Name}}\n @if (node.scope.FullPath && node.scope.FullPath !== node.scope.Name) {\n <span class=\"full-path\">\n {{node.scope.FullPath}}\n </span>\n }\n @if (!node.scope.IsActive) {\n <span class=\"status-badge\">Inactive</span>\n }\n </div>\n <div class=\"scope-meta\">\n <span class=\"category\" [style.color]=\"getCategoryColor(node.scope.Category)\">\n {{node.scope.Category}}\n </span>\n @if (node.scope.ResourceType) {\n <span class=\"resource-type\">\n {{node.scope.ResourceType}}\n </span>\n }\n @if (node.scope.Description) {\n <span class=\"description\">\n {{node.scope.Description}}\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"node-actions\">\n <button class=\"btn-node-action\" (click)=\"openCreateDialog(node.scope)\" title=\"Add Child Scope\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"btn-node-action\" (click)=\"openEditDialog(node.scope)\" title=\"Edit Scope\">\n <i class=\"fa-solid fa-pencil\"></i>\n </button>\n </div>\n </div>\n @if (node.expanded && node.children.length > 0) {\n <div class=\"children\">\n @for (child of node.children; track child) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: child }\"></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n }\n\n <!-- Create/Edit Dialog -->\n @if (ShowCreateDialog || ShowEditDialog) {\n <kendo-window\n [width]=\"560\"\n [minWidth]=\"420\"\n [minHeight]=\"480\"\n [resizable]=\"true\"\n [draggable]=\"true\"\n [top]=\"80\"\n (close)=\"closeDialogs()\">\n <kendo-window-titlebar>\n <div class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{EditingScope ? 'Edit Scope' : 'New Scope'}}</span>\n </div>\n <button kendoButton fillMode=\"flat\" (click)=\"closeDialogs()\" class=\"window-close-btn\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </kendo-window-titlebar>\n <div class=\"dialog-content\">\n <div class=\"form-field\">\n <label>Scope Name *</label>\n <input kendoTextBox [(ngModel)]=\"EditName\"\n placeholder=\"e.g., runview, create, execute\"\n class=\"form-input\" />\n <span class=\"field-hint\">Use lowercase, single word. Will be combined with parent for full path.</span>\n </div>\n <div class=\"form-field\">\n <label>Parent Scope</label>\n <kendo-dropdownlist [(ngModel)]=\"EditParentId\"\n [data]=\"getParentOptions()\"\n [textField]=\"'FullPath'\"\n [valueField]=\"'ID'\"\n [valuePrimitive]=\"true\"\n [defaultItem]=\"{ FullPath: '(No Parent - Root Level)', ID: null }\">\n </kendo-dropdownlist>\n @if (SelectedParentScope) {\n <span class=\"field-hint\">\n Full path will be: <code>{{SelectedParentScope.FullPath}}:{{EditName || '...'}}</code>\n </span>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field half\">\n <label>Category</label>\n <kendo-dropdownlist [(ngModel)]=\"EditCategory\"\n [data]=\"Categories\"\n [valuePrimitive]=\"true\">\n </kendo-dropdownlist>\n </div>\n <div class=\"form-field half\">\n <label>Resource Type</label>\n <kendo-dropdownlist [(ngModel)]=\"EditResourceType\"\n [data]=\"ResourceTypes\"\n [valuePrimitive]=\"true\"\n [defaultItem]=\"''\">\n </kendo-dropdownlist>\n </div>\n </div>\n <div class=\"form-field\">\n <label>Description</label>\n <textarea kendoTextArea [(ngModel)]=\"EditDescription\"\n placeholder=\"Describe what this scope allows...\"\n [rows]=\"3\"\n class=\"form-textarea\"></textarea>\n </div>\n <div class=\"form-field\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" kendoCheckBox [(ngModel)]=\"EditIsActive\" />\n <div>\n <span>Active</span>\n <span class=\"checkbox-hint\">Inactive scopes cannot be assigned to keys or applications</span>\n </div>\n </label>\n </div>\n <div class=\"dialog-actions\">\n <button kendoButton [themeColor]=\"'primary'\"\n [disabled]=\"!EditName.trim() || IsSaving\"\n (click)=\"saveScope()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n {{EditingScope ? 'Update' : 'Create'}}\n </span>\n }\n </button>\n <button kendoButton (click)=\"closeDialogs()\">Cancel</button>\n </div>\n </div>\n </kendo-window>\n }\n</div>\n"]}
1
+ {"version":3,"file":"api-scopes-panel.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-scopes-panel.component.ts","../../src/APIKeys/api-scopes-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, EventEmitter, Output, ChangeDetectorRef } from '@angular/core';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJAPIScopeEntity } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n/** Scope tree node structure */\ninterface ScopeTreeNode {\n scope: MJAPIScopeEntity;\n children: ScopeTreeNode[];\n expanded: boolean;\n level: number;\n}\n\n/**\n * API Scopes Panel Component\n * Manages API Scopes in a hierarchical tree structure\n */\n@Component({\n standalone: false,\n selector: 'mj-api-scopes-panel',\n templateUrl: './api-scopes-panel.component.html',\n styleUrls: ['./api-scopes-panel.component.css']\n})\nexport class APIScopesPanelComponent implements OnInit {\n @Output() ScopeUpdated = new EventEmitter<void>();\n\n private md = new Metadata();\n private cdr: ChangeDetectorRef;\n\n // Loading states\n public IsLoading = true;\n public IsSaving = false;\n\n // Data\n public ScopeTree: ScopeTreeNode[] = [];\n public FlatScopes: MJAPIScopeEntity[] = [];\n\n // Edit state\n public EditingScope: MJAPIScopeEntity | null = null;\n public EditName = '';\n public EditDescription = '';\n public EditCategory = '';\n public EditResourceType = '';\n public EditParentId: string | null = null;\n public EditIsActive = true;\n\n // Dialog states\n public ShowCreateDialog = false;\n public ShowEditDialog = false;\n public SelectedParentScope: MJAPIScopeEntity | null = null;\n\n // Messages\n public SuccessMessage = '';\n public ErrorMessage = '';\n\n // Category colors\n public readonly CategoryColors: Record<string, string> = {\n 'Entities': '#6366f1',\n 'Agents': '#10b981',\n 'Admin': '#f59e0b',\n 'Actions': '#8b5cf6',\n 'Queries': '#3b82f6',\n 'Reports': '#ef4444',\n 'Communication': '#ec4899',\n 'Other': '#6b7280'\n };\n\n // Resource type options\n public readonly ResourceTypes = ['Entity', 'Agent', 'Query', 'Mutation', 'Action', 'Report', 'Admin', 'Other'];\n public readonly Categories = ['Entities', 'Agents', 'Admin', 'Actions', 'Queries', 'Reports', 'Communication', 'Other'];\n\n constructor(cdr: ChangeDetectorRef) {\n this.cdr = cdr;\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n /**\n * Load all scopes\n */\n public async loadData(): Promise<void> {\n this.IsLoading = true;\n try {\n const rv = new RunView();\n const result = await rv.RunView<MJAPIScopeEntity>({\n EntityName: 'MJ: API Scopes',\n OrderBy: 'FullPath',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.FlatScopes = result.Results;\n this.buildTree();\n }\n } catch (error) {\n console.error('Error loading scopes:', error);\n this.ErrorMessage = 'Failed to load scopes';\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Build tree structure from flat scopes\n */\n private buildTree(): void {\n const scopeMap = new Map<string, ScopeTreeNode>();\n const rootNodes: ScopeTreeNode[] = [];\n\n // Create nodes\n for (const scope of this.FlatScopes) {\n scopeMap.set(scope.ID, {\n scope,\n children: [],\n expanded: true,\n level: 0\n });\n }\n\n // Build hierarchy\n for (const scope of this.FlatScopes) {\n const node = scopeMap.get(scope.ID)!;\n if (scope.ParentID) {\n const parent = scopeMap.get(scope.ParentID);\n if (parent) {\n parent.children.push(node);\n node.level = parent.level + 1;\n } else {\n rootNodes.push(node);\n }\n } else {\n rootNodes.push(node);\n }\n }\n\n // Calculate levels recursively\n const calculateLevels = (nodes: ScopeTreeNode[], level: number) => {\n for (const node of nodes) {\n node.level = level;\n calculateLevels(node.children, level + 1);\n }\n };\n calculateLevels(rootNodes, 0);\n\n this.ScopeTree = rootNodes;\n }\n\n /**\n * Open create dialog for new scope\n */\n public openCreateDialog(parentScope: MJAPIScopeEntity | null = null): void {\n this.EditName = '';\n this.EditDescription = '';\n this.EditCategory = parentScope?.Category || 'Entities';\n this.EditResourceType = '';\n this.EditParentId = parentScope?.ID || null;\n this.EditIsActive = true;\n this.EditingScope = null;\n this.SelectedParentScope = parentScope;\n this.ShowCreateDialog = true;\n }\n\n /**\n * Open edit dialog for existing scope\n */\n public openEditDialog(scope: MJAPIScopeEntity): void {\n this.EditingScope = scope;\n this.EditName = scope.Name;\n this.EditDescription = scope.Description || '';\n this.EditCategory = scope.Category || 'Entities';\n this.EditResourceType = scope.ResourceType || '';\n this.EditParentId = scope.ParentID;\n this.EditIsActive = scope.IsActive;\n this.SelectedParentScope = scope.ParentID\n ? this.FlatScopes.find(s => UUIDsEqual(s.ID, scope.ParentID)) || null\n : null;\n this.ShowEditDialog = true;\n }\n\n /**\n * Save scope (create or update)\n */\n public async saveScope(): Promise<void> {\n this.IsSaving = true;\n this.ErrorMessage = '';\n\n try {\n let scope: MJAPIScopeEntity;\n\n if (this.EditingScope) {\n scope = this.EditingScope;\n } else {\n scope = await this.md.GetEntityObject<MJAPIScopeEntity>('MJ: API Scopes');\n scope.NewRecord();\n }\n\n scope.Name = this.EditName.trim();\n scope.Description = this.EditDescription.trim() || null;\n scope.Category = this.EditCategory;\n scope.ResourceType = this.EditResourceType || null;\n scope.ParentID = this.EditParentId;\n scope.IsActive = this.EditIsActive;\n // FullPath is auto-computed by the trigger\n\n const result = await scope.Save();\n if (result) {\n this.SuccessMessage = this.EditingScope\n ? 'Scope updated successfully'\n : 'Scope created successfully';\n this.closeDialogs();\n await this.loadData();\n this.ScopeUpdated.emit();\n setTimeout(() => this.SuccessMessage = '', 3000);\n } else {\n this.ErrorMessage = 'Failed to save scope';\n }\n } catch (error) {\n console.error('Error saving scope:', error);\n this.ErrorMessage = 'An error occurred while saving';\n } finally {\n this.IsSaving = false;\n }\n }\n\n /**\n * Toggle node expansion\n */\n public toggleExpanded(node: ScopeTreeNode): void {\n node.expanded = !node.expanded;\n }\n\n /**\n * Expand all nodes\n */\n public expandAll(): void {\n const expand = (nodes: ScopeTreeNode[]) => {\n for (const node of nodes) {\n node.expanded = true;\n expand(node.children);\n }\n };\n expand(this.ScopeTree);\n }\n\n /**\n * Collapse all nodes\n */\n public collapseAll(): void {\n const collapse = (nodes: ScopeTreeNode[]) => {\n for (const node of nodes) {\n node.expanded = false;\n collapse(node.children);\n }\n };\n collapse(this.ScopeTree);\n }\n\n /**\n * Close all dialogs\n */\n public closeDialogs(): void {\n this.ShowCreateDialog = false;\n this.ShowEditDialog = false;\n this.EditingScope = null;\n this.SelectedParentScope = null;\n }\n\n /**\n * Get parent scopes for dropdown (exclude self and descendants)\n */\n public getParentOptions(): MJAPIScopeEntity[] {\n if (!this.EditingScope) {\n return this.FlatScopes;\n }\n\n // Exclude self and all descendants\n const excludeIds = new Set<string>([this.EditingScope.ID]);\n const addDescendants = (parentId: string) => {\n for (const scope of this.FlatScopes) {\n if (UUIDsEqual(scope.ParentID, parentId) && !excludeIds.has(scope.ID)) {\n excludeIds.add(scope.ID);\n addDescendants(scope.ID);\n }\n }\n };\n addDescendants(this.EditingScope.ID);\n\n return this.FlatScopes.filter(s => !excludeIds.has(s.ID));\n }\n\n /**\n * Get category color\n */\n public getCategoryColor(category: string | null): string {\n return this.CategoryColors[category || 'Other'] || this.CategoryColors['Other'];\n }\n\n /**\n * Get count of total scopes\n */\n public getTotalCount(): number {\n return this.FlatScopes.length;\n }\n\n /**\n * Get count of active scopes\n */\n public getActiveCount(): number {\n return this.FlatScopes.filter(s => s.IsActive).length;\n }\n}\n","<div class=\"scopes-panel\">\n @if (IsLoading) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <h3 class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n API Scopes\n </h3>\n <p class=\"panel-subtitle\">Manage hierarchical permission scopes for API access</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"scope-stats\">\n <span class=\"stat\">\n <i class=\"fa-solid fa-shield\"></i>\n {{getTotalCount()}} total\n </span>\n <span class=\"stat active\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{getActiveCount()}} active\n </span>\n </div>\n <div class=\"tree-controls\">\n <button class=\"btn-icon\" (click)=\"expandAll()\" title=\"Expand All\">\n <i class=\"fa-solid fa-plus-square\"></i>\n </button>\n <button class=\"btn-icon\" (click)=\"collapseAll()\" title=\"Collapse All\">\n <i class=\"fa-solid fa-minus-square\"></i>\n </button>\n </div>\n <button class=\"btn-create\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Scope\n </button>\n </div>\n </div>\n <!-- Messages -->\n @if (SuccessMessage) {\n <div class=\"message success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{SuccessMessage}}\n </div>\n }\n @if (ErrorMessage) {\n <div class=\"message error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ErrorMessage}}\n </div>\n }\n <!-- Scope Tree -->\n <div class=\"scope-tree\">\n @for (node of ScopeTree; track node) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: node }\"></ng-container>\n }\n <!-- Empty State -->\n @if (ScopeTree.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n <p>Create scopes to define API access permissions</p>\n </div>\n }\n </div>\n <!-- Recursive Node Template -->\n <ng-template #scopeNode let-node=\"node\">\n <div class=\"scope-node\" [style.padding-left.px]=\"node.level * 24\">\n <div class=\"node-content\" [class.inactive]=\"!node.scope.IsActive\">\n @if (node.children.length > 0) {\n <button class=\"expand-btn\"\n (click)=\"toggleExpanded(node)\">\n <i class=\"fa-solid\"\n [class.fa-chevron-right]=\"!node.expanded\"\n [class.fa-chevron-down]=\"node.expanded\"></i>\n </button>\n }\n @if (node.children.length === 0) {\n <span class=\"expand-placeholder\"></span>\n }\n <div class=\"scope-info\" (click)=\"openEditDialog(node.scope)\">\n <div class=\"scope-icon\" [style.backgroundColor]=\"getCategoryColor(node.scope.Category)\">\n <i class=\"fa-solid fa-shield\"></i>\n </div>\n <div class=\"scope-details\">\n <div class=\"scope-name\">\n {{node.scope.Name}}\n @if (node.scope.FullPath && node.scope.FullPath !== node.scope.Name) {\n <span class=\"full-path\">\n {{node.scope.FullPath}}\n </span>\n }\n @if (!node.scope.IsActive) {\n <span class=\"status-badge\">Inactive</span>\n }\n </div>\n <div class=\"scope-meta\">\n <span class=\"category\" [style.color]=\"getCategoryColor(node.scope.Category)\">\n {{node.scope.Category}}\n </span>\n @if (node.scope.ResourceType) {\n <span class=\"resource-type\">\n {{node.scope.ResourceType}}\n </span>\n }\n @if (node.scope.Description) {\n <span class=\"description\">\n {{node.scope.Description}}\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"node-actions\">\n <button class=\"btn-node-action\" (click)=\"openCreateDialog(node.scope)\" title=\"Add Child Scope\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"btn-node-action\" (click)=\"openEditDialog(node.scope)\" title=\"Edit Scope\">\n <i class=\"fa-solid fa-pencil\"></i>\n </button>\n </div>\n </div>\n @if (node.expanded && node.children.length > 0) {\n <div class=\"children\">\n @for (child of node.children; track child) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: child }\"></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n }\n\n <!-- Create/Edit Dialog -->\n @if (ShowCreateDialog || ShowEditDialog) {\n <mj-window\n [Width]=\"560\"\n [MinWidth]=\"420\"\n [MinHeight]=\"480\"\n [Resizable]=\"true\"\n [Draggable]=\"true\"\n [Visible]=\"true\"\n [Top]=\"80\"\n (Close)=\"closeDialogs()\">\n <mj-window-titlebar>\n <div class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{EditingScope ? 'Edit Scope' : 'New Scope'}}</span>\n </div>\n </mj-window-titlebar>\n <div class=\"dialog-content\">\n <div class=\"form-field\">\n <label>Scope Name *</label>\n <input class=\"mj-input form-input\" [(ngModel)]=\"EditName\"\n placeholder=\"e.g., runview, create, execute\" />\n <span class=\"field-hint\">Use lowercase, single word. Will be combined with parent for full path.</span>\n </div>\n <div class=\"form-field\">\n <label>Parent Scope</label>\n <mj-dropdown [(ngModel)]=\"EditParentId\"\n [Data]=\"getParentOptions()\"\n TextField=\"FullPath\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [DefaultItem]=\"{ FullPath: '(No Parent - Root Level)', ID: null }\">\n </mj-dropdown>\n @if (SelectedParentScope) {\n <span class=\"field-hint\">\n Full path will be: <code>{{SelectedParentScope.FullPath}}:{{EditName || '...'}}</code>\n </span>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field half\">\n <label>Category</label>\n <mj-dropdown [(ngModel)]=\"EditCategory\"\n [Data]=\"Categories\"\n [ValuePrimitive]=\"true\">\n </mj-dropdown>\n </div>\n <div class=\"form-field half\">\n <label>Resource Type</label>\n <mj-dropdown [(ngModel)]=\"EditResourceType\"\n [Data]=\"ResourceTypes\"\n [ValuePrimitive]=\"true\"\n [DefaultItem]=\"''\">\n </mj-dropdown>\n </div>\n </div>\n <div class=\"form-field\">\n <label>Description</label>\n <textarea class=\"mj-textarea form-textarea\" [(ngModel)]=\"EditDescription\"\n placeholder=\"Describe what this scope allows...\"\n [rows]=\"3\"></textarea>\n </div>\n <div class=\"form-field\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" class=\"mj-checkbox\" [(ngModel)]=\"EditIsActive\" />\n <div>\n <span>Active</span>\n <span class=\"checkbox-hint\">Inactive scopes cannot be assigned to keys or applications</span>\n </div>\n </label>\n </div>\n <div class=\"dialog-actions\">\n <button mjButton variant=\"primary\"\n [disabled]=\"!EditName.trim() || IsSaving\"\n (click)=\"saveScope()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n {{EditingScope ? 'Update' : 'Create'}}\n </span>\n }\n </button>\n <button mjButton (click)=\"closeDialogs()\">Cancel</button>\n </div>\n </div>\n </mj-window>\n }\n</div>\n"]}