@memberjunction/ng-dashboards 5.22.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 (204) 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 +275 -64
  7. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  8. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +2645 -436
  9. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  10. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +240 -6
  11. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  12. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +2166 -256
  13. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  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 +1 -2
  24. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  25. package/dist/AI/components/vectors/vector-management-resource.component.js +12 -27
  26. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  27. package/dist/APIKeys/api-applications-panel.component.js +10 -12
  28. package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
  29. package/dist/APIKeys/api-key-create-dialog.component.js +13 -19
  30. package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
  31. package/dist/APIKeys/api-key-edit-panel.component.js +12 -14
  32. package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
  33. package/dist/APIKeys/api-scopes-panel.component.js +61 -68
  34. package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
  35. package/dist/APIKeys/api-usage-panel.component.js +10 -11
  36. package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
  37. package/dist/Actions/components/actions-list-view.component.js +82 -96
  38. package/dist/Actions/components/actions-list-view.component.js.map +1 -1
  39. package/dist/Actions/components/actions-overview.component.js +130 -134
  40. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  41. package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
  42. package/dist/Actions/components/categories-list-view.component.js +40 -46
  43. package/dist/Actions/components/categories-list-view.component.js.map +1 -1
  44. package/dist/Actions/components/code-management.component.js +2 -2
  45. package/dist/Actions/components/code-management.component.js.map +1 -1
  46. package/dist/Actions/components/entity-integration.component.js +2 -2
  47. package/dist/Actions/components/entity-integration.component.js.map +1 -1
  48. package/dist/Actions/components/execution-monitoring.component.js +127 -132
  49. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  50. package/dist/Actions/components/executions-list-view.component.js +2 -2
  51. package/dist/Actions/components/executions-list-view.component.js.map +1 -1
  52. package/dist/Actions/components/explorer/action-card.component.js +11 -17
  53. package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
  54. package/dist/Actions/components/explorer/action-explorer.component.js +5 -11
  55. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  56. package/dist/Actions/components/explorer/action-list-item.component.js +8 -10
  57. package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
  58. package/dist/Actions/components/explorer/action-toolbar.component.js +112 -133
  59. package/dist/Actions/components/explorer/action-toolbar.component.js.map +1 -1
  60. package/dist/Actions/components/explorer/action-tree-panel.component.js +63 -83
  61. package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
  62. package/dist/Actions/components/explorer/new-action-panel.component.js +17 -21
  63. package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
  64. package/dist/Actions/components/explorer/new-category-panel.component.js +17 -21
  65. package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
  66. package/dist/Actions/components/scheduled-actions.component.js +2 -2
  67. package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
  68. package/dist/Actions/components/security-permissions.component.js +2 -2
  69. package/dist/Actions/components/security-permissions.component.js.map +1 -1
  70. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts +13 -5
  71. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
  72. package/dist/ComponentStudio/component-studio-dashboard.component.js +168 -145
  73. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  74. package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +4 -5
  75. package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
  76. package/dist/ComponentStudio/components/artifact-load-dialog.component.js +197 -200
  77. package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
  78. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +5 -7
  79. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
  80. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +142 -148
  81. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  82. package/dist/ComponentStudio/components/browser/component-browser.component.js +153 -166
  83. package/dist/ComponentStudio/components/browser/component-browser.component.js.map +1 -1
  84. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +15 -20
  85. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
  86. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +16 -21
  87. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
  88. package/dist/ComponentStudio/components/editors/requirements-editor.component.js +18 -23
  89. package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
  90. package/dist/ComponentStudio/components/editors/spec-editor.component.js +25 -30
  91. package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
  92. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +10 -11
  93. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js.map +1 -1
  94. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.d.ts.map +1 -1
  95. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +24 -35
  96. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
  97. package/dist/ComponentStudio/components/text-import-dialog.component.js +15 -17
  98. package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
  99. package/dist/Credentials/components/credentials-categories-resource.component.js +7 -6
  100. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  101. package/dist/Credentials/components/credentials-list-resource.component.js +6 -5
  102. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  103. package/dist/Credentials/components/credentials-types-resource.component.js +7 -6
  104. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  105. package/dist/DashboardBrowser/dashboard-share-dialog.component.js +9 -9
  106. package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
  107. package/dist/Home/home-dashboard.component.js +4 -4
  108. package/dist/Home/home-dashboard.component.js.map +1 -1
  109. package/dist/Integration/components/connections/connections.component.js +4 -4
  110. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  111. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +246 -259
  112. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
  113. package/dist/Integration/components/widgets/integration-card.component.js +7 -9
  114. package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
  115. package/dist/Integration/integration.module.d.ts +6 -10
  116. package/dist/Integration/integration.module.d.ts.map +1 -1
  117. package/dist/Integration/integration.module.js +12 -20
  118. package/dist/Integration/integration.module.js.map +1 -1
  119. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +106 -0
  120. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -0
  121. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +607 -0
  122. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -0
  123. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +7 -2
  124. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
  125. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +59 -31
  126. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  127. package/dist/KnowledgeHub/index.d.ts +1 -0
  128. package/dist/KnowledgeHub/index.d.ts.map +1 -1
  129. package/dist/KnowledgeHub/index.js +1 -0
  130. package/dist/KnowledgeHub/index.js.map +1 -1
  131. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  132. package/dist/Lists/components/lists-browse-resource.component.js +9 -7
  133. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  134. package/dist/Lists/components/lists-my-lists-resource.component.js +5 -4
  135. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  136. package/dist/Lists/components/lists-operations-resource.component.js +10 -9
  137. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  138. package/dist/MCP/components/mcp-connection-dialog.component.js +141 -132
  139. package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
  140. package/dist/MCP/components/mcp-log-detail-panel.component.js +4 -4
  141. package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
  142. package/dist/MCP/components/mcp-server-dialog.component.js +141 -128
  143. package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
  144. package/dist/MCP/components/mcp-test-tool-dialog.component.js +210 -218
  145. package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
  146. package/dist/MCP/mcp-dashboard.component.js +2 -2
  147. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  148. package/dist/MCP/mcp.module.d.ts +6 -9
  149. package/dist/MCP/mcp.module.d.ts.map +1 -1
  150. package/dist/MCP/mcp.module.js +20 -22
  151. package/dist/MCP/mcp.module.js.map +1 -1
  152. package/dist/Scheduling/components/scheduling-activity.component.js +5 -4
  153. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  154. package/dist/Scheduling/components/scheduling-jobs.component.js +6 -5
  155. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  156. package/dist/Scheduling/components/scheduling-overview.component.js +93 -92
  157. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  158. package/dist/Testing/testing-dashboard.component.js +9 -10
  159. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  160. package/dist/actions-dashboards.module.d.ts +8 -13
  161. package/dist/actions-dashboards.module.d.ts.map +1 -1
  162. package/dist/actions-dashboards.module.js +6 -27
  163. package/dist/actions-dashboards.module.js.map +1 -1
  164. package/dist/ai-dashboards.module.d.ts +16 -20
  165. package/dist/ai-dashboards.module.d.ts.map +1 -1
  166. package/dist/ai-dashboards.module.js +23 -44
  167. package/dist/ai-dashboards.module.js.map +1 -1
  168. package/dist/communication-dashboards.module.d.ts +4 -8
  169. package/dist/communication-dashboards.module.d.ts.map +1 -1
  170. package/dist/communication-dashboards.module.js +0 -19
  171. package/dist/communication-dashboards.module.js.map +1 -1
  172. package/dist/component-studio-dashboards.module.d.ts +7 -11
  173. package/dist/component-studio-dashboards.module.d.ts.map +1 -1
  174. package/dist/component-studio-dashboards.module.js +22 -34
  175. package/dist/component-studio-dashboards.module.js.map +1 -1
  176. package/dist/core-dashboards.module.d.ts +12 -18
  177. package/dist/core-dashboards.module.d.ts.map +1 -1
  178. package/dist/core-dashboards.module.js +15 -31
  179. package/dist/core-dashboards.module.js.map +1 -1
  180. package/dist/credentials-dashboards.module.d.ts +5 -8
  181. package/dist/credentials-dashboards.module.d.ts.map +1 -1
  182. package/dist/credentials-dashboards.module.js +3 -19
  183. package/dist/credentials-dashboards.module.js.map +1 -1
  184. package/dist/data-explorer-dashboards.module.d.ts +7 -13
  185. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  186. package/dist/data-explorer-dashboards.module.js +0 -27
  187. package/dist/data-explorer-dashboards.module.js.map +1 -1
  188. package/dist/lists-dashboards.module.d.ts +5 -8
  189. package/dist/lists-dashboards.module.d.ts.map +1 -1
  190. package/dist/lists-dashboards.module.js +3 -19
  191. package/dist/lists-dashboards.module.js.map +1 -1
  192. package/dist/public-api.d.ts +1 -0
  193. package/dist/public-api.d.ts.map +1 -1
  194. package/dist/public-api.js +1 -0
  195. package/dist/public-api.js.map +1 -1
  196. package/dist/scheduling-dashboards.module.d.ts +6 -10
  197. package/dist/scheduling-dashboards.module.d.ts.map +1 -1
  198. package/dist/scheduling-dashboards.module.js +3 -23
  199. package/dist/scheduling-dashboards.module.js.map +1 -1
  200. package/dist/testing-dashboards.module.d.ts +7 -13
  201. package/dist/testing-dashboards.module.d.ts.map +1 -1
  202. package/dist/testing-dashboards.module.js +0 -27
  203. package/dist/testing-dashboards.module.js.map +1 -1
  204. package/package.json +47 -55
@@ -4,11 +4,9 @@ import { GraphQLEncryptionClient } from '@memberjunction/graphql-dataprovider';
4
4
  import { APIKeysEngineBase, parseAPIScopeUIConfig } from '@memberjunction/api-keys-base';
5
5
  import * as i0 from "@angular/core";
6
6
  import * as i1 from "@angular/forms";
7
- import * as i2 from "@progress/kendo-angular-buttons";
8
- import * as i3 from "@progress/kendo-angular-inputs";
9
- import * as i4 from "@progress/kendo-angular-dateinputs";
10
- import * as i5 from "@memberjunction/ng-shared-generic";
11
- import * as i6 from "@angular/common";
7
+ import * as i2 from "@memberjunction/ng-ui-components";
8
+ import * as i3 from "@memberjunction/ng-shared-generic";
9
+ import * as i4 from "@angular/common";
12
10
  function APIKeyCreateDialogComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
13
11
  const _r1 = i0.ɵɵgetCurrentView();
14
12
  i0.ɵɵelementStart(0, "div", 13);
@@ -69,14 +67,14 @@ function APIKeyCreateDialogComponent_Conditional_10_Conditional_19_Template(rf,
69
67
  } }
70
68
  function APIKeyCreateDialogComponent_Conditional_10_Conditional_20_Template(rf, ctx) { if (rf & 1) {
71
69
  const _r7 = i0.ɵɵgetCurrentView();
72
- i0.ɵɵelementStart(0, "div", 30)(1, "kendo-datepicker", 35);
73
- i0.ɵɵtwoWayListener("ngModelChange", function APIKeyCreateDialogComponent_Conditional_10_Conditional_20_Template_kendo_datepicker_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.ExpiresAt, $event) || (ctx_r1.ExpiresAt = $event); return i0.ɵɵresetView($event); });
70
+ i0.ɵɵelementStart(0, "div", 30)(1, "mj-datepicker", 35);
71
+ i0.ɵɵtwoWayListener("ngModelChange", function APIKeyCreateDialogComponent_Conditional_10_Conditional_20_Template_mj_datepicker_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.ExpiresAt, $event) || (ctx_r1.ExpiresAt = $event); return i0.ɵɵresetView($event); });
74
72
  i0.ɵɵelementEnd()();
75
73
  } if (rf & 2) {
76
74
  const ctx_r1 = i0.ɵɵnextContext(2);
77
75
  i0.ɵɵadvance();
78
76
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.ExpiresAt);
79
- i0.ɵɵproperty("min", ctx_r1.getMinDate());
77
+ i0.ɵɵproperty("Min", ctx_r1.getMinDate());
80
78
  } }
81
79
  function APIKeyCreateDialogComponent_Conditional_10_Conditional_21_Template(rf, ctx) { if (rf & 1) {
82
80
  i0.ɵɵelementStart(0, "div", 31);
@@ -390,8 +388,6 @@ function APIKeyCreateDialogComponent_Conditional_14_Template(rf, ctx) { if (rf &
390
388
  i0.ɵɵlistener("click", function APIKeyCreateDialogComponent_Conditional_14_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.close()); });
391
389
  i0.ɵɵtext(4, "Cancel");
392
390
  i0.ɵɵelementEnd();
393
- } if (rf & 2) {
394
- i0.ɵɵproperty("themeColor", "primary");
395
391
  } }
396
392
  function APIKeyCreateDialogComponent_Conditional_15_Conditional_1_Template(rf, ctx) { if (rf & 1) {
397
393
  i0.ɵɵelement(0, "mj-loading", 80);
@@ -418,7 +414,7 @@ function APIKeyCreateDialogComponent_Conditional_15_Template(rf, ctx) { if (rf &
418
414
  i0.ɵɵelementEnd();
419
415
  } if (rf & 2) {
420
416
  const ctx_r1 = i0.ɵɵnextContext();
421
- i0.ɵɵproperty("themeColor", "primary")("disabled", ctx_r1.IsCreating);
417
+ i0.ɵɵproperty("disabled", ctx_r1.IsCreating);
422
418
  i0.ɵɵadvance();
423
419
  i0.ɵɵconditional(ctx_r1.IsCreating ? 1 : -1);
424
420
  i0.ɵɵadvance();
@@ -431,8 +427,6 @@ function APIKeyCreateDialogComponent_Conditional_16_Template(rf, ctx) { if (rf &
431
427
  i0.ɵɵelement(1, "i", 82);
432
428
  i0.ɵɵtext(2, " Done ");
433
429
  i0.ɵɵelementEnd();
434
- } if (rf & 2) {
435
- i0.ɵɵproperty("themeColor", "primary");
436
430
  } }
437
431
  /**
438
432
  * Dialog for creating new API keys
@@ -702,7 +696,7 @@ export class APIKeyCreateDialogComponent {
702
696
  static ɵfac = function APIKeyCreateDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || APIKeyCreateDialogComponent)(); };
703
697
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: APIKeyCreateDialogComponent, selectors: [["mj-api-key-create-dialog"]], hostBindings: function APIKeyCreateDialogComponent_HostBindings(rf, ctx) { if (rf & 1) {
704
698
  i0.ɵɵlistener("keydown.escape", function APIKeyCreateDialogComponent_keydown_escape_HostBindingHandler() { return ctx.onEscapeKey(); }, i0.ɵɵresolveDocument);
705
- } }, inputs: { Visible: "Visible" }, outputs: { VisibleChange: "VisibleChange", Created: "Created", Closed: "Closed" }, standalone: false, decls: 17, vars: 11, consts: [[1, "slideout-backdrop"], [1, "slideout-panel"], [1, "slideout-header"], [1, "slideout-title"], [1, "fa-solid", "fa-key"], ["title", "Close (Esc)", 1, "slideout-close"], [1, "step-indicator"], [1, "slideout-content"], [1, "step-panel"], [1, "step-panel", "scopes-step"], [1, "step-panel", "success-step"], [1, "slideout-footer"], ["kendoButton", "", 3, "themeColor"], [1, "slideout-backdrop", 3, "click"], ["title", "Close (Esc)", 1, "slideout-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "step"], [1, "step-number"], [1, "step-label"], [1, "step-connector"], [1, "form-section"], [1, "form-label", "required"], ["kendoTextBox", "", "placeholder", "e.g., ElevenLabs Integration, CI/CD Pipeline", 1, "form-input", 3, "ngModelChange", "ngModel"], [1, "form-hint"], [1, "form-label"], ["kendoTextArea", "", "placeholder", "Optional notes about how this key will be used...", 1, "form-textarea", 3, "ngModelChange", "ngModel", "rows"], [1, "expiration-options"], [1, "checkbox-label"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModelChange", "change", "ngModel"], [1, "preset-buttons"], [1, "custom-date"], [1, "expiration-preview"], [1, "error-message"], [1, "preset-btn", 3, "active"], [1, "preset-btn", 3, "click"], ["format", "MMM d, yyyy", "placeholder", "Select expiration date", 3, "ngModelChange", "ngModel", "min"], [1, "fa-solid", "fa-calendar-check"], [1, "fa-solid", "fa-circle-exclamation"], [1, "scopes-header"], [1, "scopes-info"], [1, "scopes-count"], ["text", "Loading scopes..."], [1, "scope-categories"], [1, "scope-tip"], [1, "fa-solid", "fa-lightbulb"], [1, "no-scopes-warning"], [1, "count"], [1, "scope-category"], [1, "category-header", 3, "click"], [1, "category-left"], [1, "category-name"], [1, "category-badge"], [1, "category-right"], [1, "select-all-label", 3, "click"], ["type", "checkbox", "kendoCheckBox", "", 3, "change", "checked"], [1, "fa-solid"], [1, "category-scopes"], [1, "scope-item"], [1, "scope-label"], [1, "scope-info"], [1, "scope-name"], [1, "scope-desc"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "success-icon"], [1, "fa-solid", "fa-check-circle"], [1, "success-title"], [1, "key-display"], [1, "key-warning"], [1, "key-value"], [1, "copy-btn", 3, "click"], [1, "key-details"], [1, "detail-row"], [1, "detail-label"], [1, "detail-value"], [1, "security-note"], [1, "fa-solid", "fa-shield-check"], ["kendoButton", "", 3, "click", "themeColor"], [1, "fa-solid", "fa-arrow-right"], ["kendoButton", "", 3, "click"], ["kendoButton", "", 3, "click", "themeColor", "disabled"], ["size", "small", 3, "showText"], [1, "fa-solid", "fa-arrow-left"], [1, "fa-solid", "fa-check"]], template: function APIKeyCreateDialogComponent_Template(rf, ctx) { if (rf & 1) {
699
+ } }, inputs: { Visible: "Visible" }, outputs: { VisibleChange: "VisibleChange", Created: "Created", Closed: "Closed" }, standalone: false, decls: 17, vars: 11, consts: [[1, "slideout-backdrop"], [1, "slideout-panel"], [1, "slideout-header"], [1, "slideout-title"], [1, "fa-solid", "fa-key"], ["title", "Close (Esc)", 1, "slideout-close"], [1, "step-indicator"], [1, "slideout-content"], [1, "step-panel"], [1, "step-panel", "scopes-step"], [1, "step-panel", "success-step"], [1, "slideout-footer"], ["mjButton", "", "variant", "primary"], [1, "slideout-backdrop", 3, "click"], ["title", "Close (Esc)", 1, "slideout-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "step"], [1, "step-number"], [1, "step-label"], [1, "step-connector"], [1, "form-section"], [1, "form-label", "required"], ["placeholder", "e.g., ElevenLabs Integration, CI/CD Pipeline", 1, "mj-input", "form-input", 3, "ngModelChange", "ngModel"], [1, "form-hint"], [1, "form-label"], ["placeholder", "Optional notes about how this key will be used...", 1, "mj-textarea", "form-textarea", 3, "ngModelChange", "ngModel", "rows"], [1, "expiration-options"], [1, "checkbox-label"], ["type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "change", "ngModel"], [1, "preset-buttons"], [1, "custom-date"], [1, "expiration-preview"], [1, "error-message"], [1, "preset-btn", 3, "active"], [1, "preset-btn", 3, "click"], ["Format", "MMM d, yyyy", "Placeholder", "Select expiration date", 3, "ngModelChange", "ngModel", "Min"], [1, "fa-solid", "fa-calendar-check"], [1, "fa-solid", "fa-circle-exclamation"], [1, "scopes-header"], [1, "scopes-info"], [1, "scopes-count"], ["text", "Loading scopes..."], [1, "scope-categories"], [1, "scope-tip"], [1, "fa-solid", "fa-lightbulb"], [1, "no-scopes-warning"], [1, "count"], [1, "scope-category"], [1, "category-header", 3, "click"], [1, "category-left"], [1, "category-name"], [1, "category-badge"], [1, "category-right"], [1, "select-all-label", 3, "click"], ["type", "checkbox", 1, "mj-checkbox", 3, "change", "checked"], [1, "fa-solid"], [1, "category-scopes"], [1, "scope-item"], [1, "scope-label"], [1, "scope-info"], [1, "scope-name"], [1, "scope-desc"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "success-icon"], [1, "fa-solid", "fa-check-circle"], [1, "success-title"], [1, "key-display"], [1, "key-warning"], [1, "key-value"], [1, "copy-btn", 3, "click"], [1, "key-details"], [1, "detail-row"], [1, "detail-label"], [1, "detail-value"], [1, "security-note"], [1, "fa-solid", "fa-shield-check"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "fa-solid", "fa-arrow-right"], ["mjButton", "", 3, "click"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], ["size", "small", 3, "showText"], [1, "fa-solid", "fa-arrow-left"], [1, "fa-solid", "fa-check"]], template: function APIKeyCreateDialogComponent_Template(rf, ctx) { if (rf & 1) {
706
700
  i0.ɵɵconditionalCreate(0, APIKeyCreateDialogComponent_Conditional_0_Template, 1, 0, "div", 0);
707
701
  i0.ɵɵelementStart(1, "div", 1)(2, "div", 2)(3, "div", 3);
708
702
  i0.ɵɵelement(4, "i", 4);
@@ -718,9 +712,9 @@ export class APIKeyCreateDialogComponent {
718
712
  i0.ɵɵconditionalCreate(12, APIKeyCreateDialogComponent_Conditional_12_Template, 41, 15, "div", 10);
719
713
  i0.ɵɵelementEnd();
720
714
  i0.ɵɵelementStart(13, "div", 11);
721
- i0.ɵɵconditionalCreate(14, APIKeyCreateDialogComponent_Conditional_14_Template, 5, 1);
722
- i0.ɵɵconditionalCreate(15, APIKeyCreateDialogComponent_Conditional_15_Template, 6, 4);
723
- i0.ɵɵconditionalCreate(16, APIKeyCreateDialogComponent_Conditional_16_Template, 3, 1, "button", 12);
715
+ i0.ɵɵconditionalCreate(14, APIKeyCreateDialogComponent_Conditional_14_Template, 5, 0);
716
+ i0.ɵɵconditionalCreate(15, APIKeyCreateDialogComponent_Conditional_15_Template, 6, 3);
717
+ i0.ɵɵconditionalCreate(16, APIKeyCreateDialogComponent_Conditional_16_Template, 3, 0, "button", 12);
724
718
  i0.ɵɵelementEnd()();
725
719
  } if (rf & 2) {
726
720
  i0.ɵɵconditional(ctx.Visible ? 0 : -1);
@@ -742,11 +736,11 @@ export class APIKeyCreateDialogComponent {
742
736
  i0.ɵɵconditional(ctx.Step === "scopes" ? 15 : -1);
743
737
  i0.ɵɵadvance();
744
738
  i0.ɵɵconditional(ctx.Step === "success" ? 16 : -1);
745
- } }, dependencies: [i1.DefaultValueAccessor, i1.CheckboxControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.ButtonComponent, i3.TextBoxDirective, i3.TextAreaDirective, i3.CheckBoxDirective, i4.DatePickerComponent, i5.LoadingComponent, i6.DatePipe], styles: ["\n\n\n\n\n\n\n.slideout-backdrop[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 100;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.slideout-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n width: 520px;\n height: 100%;\n max-height: 100%;\n background: var(--mj-bg-surface);\n box-shadow: -8px 0 32px var(--mj-bg-overlay);\n z-index: 101;\n display: flex;\n flex-direction: column;\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateX(100%);\n overflow: hidden;\n}\n\n.slideout-panel.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n\n\n.slideout-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.slideout-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 flex: 1;\n min-width: 0;\n}\n\n.slideout-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.slideout-close[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 8px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.slideout-close[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n}\n\n\n\n.slideout-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n}\n\n.step-panel[_ngcontent-%COMP%] {\n padding: 24px;\n}\n\n\n\n.slideout-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n background: var(--mj-bg-page);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n[_nghost-%COMP%] .slideout-footer .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%] .slideout-footer .k-button-solid-primary {\n background: var(--mj-brand-primary);\n border: none;\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n[_nghost-%COMP%] .slideout-footer .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n[_nghost-%COMP%] .slideout-footer .k-button i {\n margin: 0 5px;\n}\n\n\n\n.step-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px 24px;\n background: linear-gradient(135deg, var(--mj-color-brand-100) 0%, var(--mj-color-brand-200) 100%);\n border-bottom: 1px solid var(--mj-color-accent-300);\n}\n\n.step[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n\n.step-number[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-color-neutral-300);\n border-radius: 50%;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.step.active[_ngcontent-%COMP%] .step-number[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.step.completed[_ngcontent-%COMP%] .step-number[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.step-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step.active[_ngcontent-%COMP%] .step-label[_ngcontent-%COMP%] {\n color: var(--mj-color-brand-800);\n font-weight: 600;\n}\n\n.step-connector[_ngcontent-%COMP%] {\n width: 80px;\n height: 2px;\n background: var(--mj-color-neutral-300);\n margin: 0 16px;\n margin-bottom: 20px;\n transition: background 0.2s ease;\n}\n\n.step-connector.active[_ngcontent-%COMP%] {\n background: linear-gradient(90deg, var(--mj-status-success), var(--mj-brand-primary));\n}\n\n\n\n.dialog-content[_ngcontent-%COMP%] {\n padding: 24px;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.scopes-content[_ngcontent-%COMP%] {\n max-height: 450px;\n}\n\n\n\n.form-section[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.form-label[_ngcontent-%COMP%] {\n display: block;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.form-label.required[_ngcontent-%COMP%]::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-input[_ngcontent-%COMP%], \n.form-textarea[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.form-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 6px;\n}\n\n\n\n.expiration-options[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.preset-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.preset-btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.preset-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n}\n\n.preset-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.custom-date[_ngcontent-%COMP%] {\n margin-top: 4px;\n}\n\n.expiration-preview[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: var(--mj-color-success-50);\n border-radius: 8px;\n font-size: 13px;\n color: var(--mj-color-success-600);\n}\n\n.expiration-preview[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n\n\n.error-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n background: var(--mj-color-error-50);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 8px;\n color: var(--mj-color-error-600);\n font-size: 14px;\n}\n\n\n\n.scopes-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n}\n\n.scopes-info[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.scopes-info[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.scopes-count[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: var(--mj-brand-primary);\n border-radius: 20px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n}\n\n.scopes-count[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n\n\n.scope-categories[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.scope-category[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.category-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 16px;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.category-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.category-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.category-left[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.category-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.category-badge[_ngcontent-%COMP%] {\n padding: 2px 8px;\n background: var(--mj-border-default);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.category-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.select-all-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.category-right[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.category-scopes[_ngcontent-%COMP%] {\n padding: 8px 16px 16px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n\n.scope-item[_ngcontent-%COMP%] {\n padding: 10px 0;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.scope-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.scope-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n cursor: pointer;\n}\n\n.scope-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.scope-name[_ngcontent-%COMP%] {\n display: block;\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-family: monospace;\n}\n\n.scope-desc[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n.scope-tip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: var(--mj-status-info-bg);\n border-radius: 8px;\n margin-top: 16px;\n font-size: 13px;\n color: var(--mj-status-info-text);\n}\n\n.scope-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n}\n\n.scope-tip[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-color-info-100);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n}\n\n\n\n.no-scopes-warning[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: linear-gradient(135deg, var(--mj-color-error-50) 0%, var(--mj-color-error-100) 100%);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n margin-top: 16px;\n font-size: 13px;\n color: var(--mj-status-error);\n}\n\n.no-scopes-warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-color-error-600);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.no-scopes-warning[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n color: var(--mj-status-error);\n font-size: 14px;\n margin-bottom: 4px;\n}\n\n.no-scopes-warning[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n line-height: 1.5;\n}\n\n\n\n.success-content[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.success-icon[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.success-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 64px;\n color: var(--mj-status-success);\n}\n\n.success-title[_ngcontent-%COMP%] {\n margin: 0 0 24px 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n\n\n.key-display[_ngcontent-%COMP%] {\n background: var(--mj-color-neutral-800);\n border-radius: 12px;\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.key-warning[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 8px;\n margin-bottom: 16px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-color-accent-300);\n}\n\n.key-value[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n}\n\n.key-value[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n flex: 1;\n font-family: 'Fira Code', 'Consolas', monospace;\n font-size: 14px;\n color: var(--mj-status-success);\n word-break: break-all;\n text-align: left;\n}\n\n.copy-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-color-neutral-600);\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.copy-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-text-secondary);\n}\n\n.copy-btn.copied[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n\n\n.key-details[_ngcontent-%COMP%] {\n text-align: left;\n background: var(--mj-bg-page);\n border-radius: 10px;\n padding: 16px 20px;\n margin-bottom: 20px;\n}\n\n.detail-row[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.detail-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n\n\n.security-note[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n text-align: left;\n padding: 16px;\n background: linear-gradient(135deg, var(--mj-color-success-50) 0%, var(--mj-color-success-100) 100%);\n border-radius: 10px;\n font-size: 13px;\n color: var(--mj-color-success-800);\n}\n\n.security-note[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-status-success);\n margin-top: 2px;\n}\n\n.security-note[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 4px;\n}\n\n\n\n[_nghost-%COMP%] .form-input .k-input, \n[_nghost-%COMP%] .form-textarea .k-input-inner, \n[_nghost-%COMP%] .k-datepicker .k-input {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border-color: var(--mj-border-default);\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%] .k-datepicker:focus-within {\n box-shadow: var(--mj-focus-ring);\n}"] });
739
+ } }, dependencies: [i1.DefaultValueAccessor, i1.CheckboxControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.MJButtonDirective, i2.MJDatepickerComponent, i3.LoadingComponent, i4.DatePipe], styles: ["\n\n\n\n\n\n\n.slideout-backdrop[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 100;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.slideout-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n width: 520px;\n height: 100%;\n max-height: 100%;\n background: var(--mj-bg-surface);\n box-shadow: -8px 0 32px var(--mj-bg-overlay);\n z-index: 101;\n display: flex;\n flex-direction: column;\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateX(100%);\n overflow: hidden;\n}\n\n.slideout-panel.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n\n\n.slideout-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.slideout-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 flex: 1;\n min-width: 0;\n}\n\n.slideout-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.slideout-close[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 8px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.slideout-close[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n}\n\n\n\n.slideout-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n}\n\n.step-panel[_ngcontent-%COMP%] {\n padding: 24px;\n}\n\n\n\n.slideout-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n background: var(--mj-bg-page);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n[_nghost-%COMP%] .slideout-footer .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%] .slideout-footer .k-button-solid-primary {\n background: var(--mj-brand-primary);\n border: none;\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n[_nghost-%COMP%] .slideout-footer .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n[_nghost-%COMP%] .slideout-footer .k-button i {\n margin: 0 5px;\n}\n\n\n\n.step-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px 24px;\n background: linear-gradient(135deg, var(--mj-color-brand-100) 0%, var(--mj-color-brand-200) 100%);\n border-bottom: 1px solid var(--mj-color-accent-300);\n}\n\n.step[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n\n.step-number[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-color-neutral-300);\n border-radius: 50%;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.step.active[_ngcontent-%COMP%] .step-number[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.step.completed[_ngcontent-%COMP%] .step-number[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.step-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step.active[_ngcontent-%COMP%] .step-label[_ngcontent-%COMP%] {\n color: var(--mj-color-brand-800);\n font-weight: 600;\n}\n\n.step-connector[_ngcontent-%COMP%] {\n width: 80px;\n height: 2px;\n background: var(--mj-color-neutral-300);\n margin: 0 16px;\n margin-bottom: 20px;\n transition: background 0.2s ease;\n}\n\n.step-connector.active[_ngcontent-%COMP%] {\n background: linear-gradient(90deg, var(--mj-status-success), var(--mj-brand-primary));\n}\n\n\n\n.dialog-content[_ngcontent-%COMP%] {\n padding: 24px;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.scopes-content[_ngcontent-%COMP%] {\n max-height: 450px;\n}\n\n\n\n.form-section[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.form-label[_ngcontent-%COMP%] {\n display: block;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.form-label.required[_ngcontent-%COMP%]::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-input[_ngcontent-%COMP%], \n.form-textarea[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.form-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 6px;\n}\n\n\n\n.expiration-options[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.preset-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.preset-btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.preset-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n}\n\n.preset-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.custom-date[_ngcontent-%COMP%] {\n margin-top: 4px;\n}\n\n.expiration-preview[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: var(--mj-color-success-50);\n border-radius: 8px;\n font-size: 13px;\n color: var(--mj-color-success-600);\n}\n\n.expiration-preview[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n\n\n.error-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n background: var(--mj-color-error-50);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 8px;\n color: var(--mj-color-error-600);\n font-size: 14px;\n}\n\n\n\n.scopes-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n}\n\n.scopes-info[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.scopes-info[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.scopes-count[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: var(--mj-brand-primary);\n border-radius: 20px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n}\n\n.scopes-count[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n\n\n.scope-categories[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.scope-category[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.category-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 16px;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.category-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.category-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.category-left[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.category-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.category-badge[_ngcontent-%COMP%] {\n padding: 2px 8px;\n background: var(--mj-border-default);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.category-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.select-all-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.category-right[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.category-scopes[_ngcontent-%COMP%] {\n padding: 8px 16px 16px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n\n.scope-item[_ngcontent-%COMP%] {\n padding: 10px 0;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.scope-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.scope-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n cursor: pointer;\n}\n\n.scope-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.scope-name[_ngcontent-%COMP%] {\n display: block;\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-family: monospace;\n}\n\n.scope-desc[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n.scope-tip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: var(--mj-status-info-bg);\n border-radius: 8px;\n margin-top: 16px;\n font-size: 13px;\n color: var(--mj-status-info-text);\n}\n\n.scope-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n}\n\n.scope-tip[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-color-info-100);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n}\n\n\n\n.no-scopes-warning[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: linear-gradient(135deg, var(--mj-color-error-50) 0%, var(--mj-color-error-100) 100%);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n margin-top: 16px;\n font-size: 13px;\n color: var(--mj-status-error);\n}\n\n.no-scopes-warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-color-error-600);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.no-scopes-warning[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n color: var(--mj-status-error);\n font-size: 14px;\n margin-bottom: 4px;\n}\n\n.no-scopes-warning[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n line-height: 1.5;\n}\n\n\n\n.success-content[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.success-icon[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.success-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 64px;\n color: var(--mj-status-success);\n}\n\n.success-title[_ngcontent-%COMP%] {\n margin: 0 0 24px 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n\n\n.key-display[_ngcontent-%COMP%] {\n background: var(--mj-color-neutral-800);\n border-radius: 12px;\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.key-warning[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 8px;\n margin-bottom: 16px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-color-accent-300);\n}\n\n.key-value[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n}\n\n.key-value[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n flex: 1;\n font-family: 'Fira Code', 'Consolas', monospace;\n font-size: 14px;\n color: var(--mj-status-success);\n word-break: break-all;\n text-align: left;\n}\n\n.copy-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-color-neutral-600);\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.copy-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-text-secondary);\n}\n\n.copy-btn.copied[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n\n\n.key-details[_ngcontent-%COMP%] {\n text-align: left;\n background: var(--mj-bg-page);\n border-radius: 10px;\n padding: 16px 20px;\n margin-bottom: 20px;\n}\n\n.detail-row[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.detail-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n\n\n.security-note[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n text-align: left;\n padding: 16px;\n background: linear-gradient(135deg, var(--mj-color-success-50) 0%, var(--mj-color-success-100) 100%);\n border-radius: 10px;\n font-size: 13px;\n color: var(--mj-color-success-800);\n}\n\n.security-note[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-status-success);\n margin-top: 2px;\n}\n\n.security-note[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 4px;\n}\n\n\n\n[_nghost-%COMP%] .form-input .k-input, \n[_nghost-%COMP%] .form-textarea .k-input-inner, \n[_nghost-%COMP%] .k-datepicker .k-input {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border-color: var(--mj-border-default);\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%] .k-datepicker:focus-within {\n box-shadow: var(--mj-focus-ring);\n}"] });
746
740
  }
747
741
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIKeyCreateDialogComponent, [{
748
742
  type: Component,
749
- args: [{ standalone: false, selector: 'mj-api-key-create-dialog', template: "<!-- Slide-out Backdrop -->\n@if (Visible) {\n <div class=\"slideout-backdrop\" (click)=\"Step !== 'success' ? close() : null\"></div>\n}\n\n<!-- Slide-out Panel -->\n<div class=\"slideout-panel\" [class.open]=\"Visible\">\n <!-- Header -->\n <div class=\"slideout-header\">\n <div class=\"slideout-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Generate New API Key</span>\n </div>\n @if (Step !== 'success') {\n <button class=\"slideout-close\" (click)=\"close()\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n\n <!-- Step Indicator -->\n @if (Step !== 'success') {\n <div class=\"step-indicator\">\n <div class=\"step\" [class.active]=\"Step === 'configure'\" [class.completed]=\"Step === 'scopes'\">\n <div class=\"step-number\">1</div>\n <div class=\"step-label\">Configure</div>\n </div>\n <div class=\"step-connector\" [class.active]=\"Step === 'scopes'\"></div>\n <div class=\"step\" [class.active]=\"Step === 'scopes'\">\n <div class=\"step-number\">2</div>\n <div class=\"step-label\">Permissions</div>\n </div>\n </div>\n }\n\n <div class=\"slideout-content\">\n <!-- Configure Step -->\n @if (Step === 'configure') {\n <div class=\"step-panel\">\n <div class=\"form-section\">\n <label class=\"form-label required\">Key Label</label>\n <input kendoTextBox [(ngModel)]=\"Label\"\n placeholder=\"e.g., ElevenLabs Integration, CI/CD Pipeline\"\n class=\"form-input\" />\n <div class=\"form-hint\">A memorable name to identify this key's purpose</div>\n </div>\n <div class=\"form-section\">\n <label class=\"form-label\">Description</label>\n <textarea kendoTextArea [(ngModel)]=\"Description\"\n placeholder=\"Optional notes about how this key will be used...\"\n [rows]=\"3\"\n class=\"form-textarea\"></textarea>\n </div>\n <div class=\"form-section\">\n <label class=\"form-label\">Expiration</label>\n <div class=\"expiration-options\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" kendoCheckBox\n [(ngModel)]=\"NeverExpires\"\n (change)=\"onNeverExpiresChange()\" />\n <span>Never expires</span>\n </label>\n @if (!NeverExpires) {\n <div class=\"preset-buttons\">\n @for (preset of ExpirationPresets; track preset) {\n <button\n class=\"preset-btn\"\n [class.active]=\"SelectedPreset === preset\"\n (click)=\"onPresetSelect(preset)\">\n {{preset.label}}\n </button>\n }\n </div>\n }\n @if (!NeverExpires && SelectedPreset?.days === -1) {\n <div class=\"custom-date\">\n <kendo-datepicker [(ngModel)]=\"ExpiresAt\"\n [min]=\"getMinDate()\"\n format=\"MMM d, yyyy\"\n placeholder=\"Select expiration date\">\n </kendo-datepicker>\n </div>\n }\n @if (!NeverExpires && ExpiresAt) {\n <div class=\"expiration-preview\">\n <i class=\"fa-solid fa-calendar-check\"></i>\n <span>Key will expire on {{ExpiresAt | date:'MMMM d, yyyy'}}</span>\n </div>\n }\n </div>\n </div>\n @if (Error) {\n <div class=\"error-message\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{Error}}\n </div>\n }\n </div>\n }\n\n <!-- Scopes Step -->\n @if (Step === 'scopes') {\n <div class=\"step-panel scopes-step\">\n <div class=\"scopes-header\">\n <div class=\"scopes-info\">\n <h4>Select Permission Scopes</h4>\n <p>Choose what this API key can access. You can always modify this later.</p>\n </div>\n @if (getSelectedScopeCount() > 0) {\n <div class=\"scopes-count\">\n <span class=\"count\">{{getSelectedScopeCount()}}</span> selected\n </div>\n }\n </div>\n @if (IsLoadingScopes) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n @if (!IsLoadingScopes) {\n <div class=\"scope-categories\">\n @for (category of ScopeCategories; track category) {\n <div class=\"scope-category\">\n <div class=\"category-header\" (click)=\"toggleCategory(category)\">\n <div class=\"category-left\">\n <i [class]=\"category.icon\" [style.color]=\"category.color\"></i>\n <span class=\"category-name\">{{category.name}}</span>\n <span class=\"category-badge\">{{category.scopes.length}}</span>\n </div>\n <div class=\"category-right\">\n <label class=\"select-all-label\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" kendoCheckBox\n [checked]=\"category.allSelected\"\n (change)=\"toggleCategoryAll(category)\" />\n <span>All</span>\n </label>\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!category.expanded\"\n [class.fa-chevron-up]=\"category.expanded\"></i>\n </div>\n </div>\n @if (category.expanded) {\n <div class=\"category-scopes\">\n @for (item of category.scopes; track item) {\n <div class=\"scope-item\">\n <label class=\"scope-label\">\n <input type=\"checkbox\" kendoCheckBox\n [(ngModel)]=\"item.selected\"\n (change)=\"updateCategoryState(category)\" />\n <div class=\"scope-info\">\n <span class=\"scope-name\">{{item.scope.Name}}</span>\n @if (item.scope.Description) {\n <span class=\"scope-desc\">\n {{item.scope.Description}}\n </span>\n }\n </div>\n </label>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <div class=\"scope-tip\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Tip: Use wildcards like <code>entities:*</code> for broad access within a category</span>\n </div>\n <!-- No Scopes Warning -->\n @if (!IsLoadingScopes && getSelectedScopeCount() === 0) {\n <div class=\"no-scopes-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div>\n <strong>Warning: No permissions selected</strong>\n <p>API keys without any assigned scopes will have <strong>no permissions</strong> and cannot perform any operations. This key will be rejected by all API endpoints until scopes are assigned.</p>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Success Step -->\n @if (Step === 'success') {\n <div class=\"step-panel success-step\">\n <div class=\"success-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <h3 class=\"success-title\">API Key Created Successfully!</h3>\n <div class=\"key-display\">\n <div class=\"key-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>Copy this key now. It won't be shown again!</span>\n </div>\n <div class=\"key-value\">\n <code>{{RawApiKey}}</code>\n <button class=\"copy-btn\" (click)=\"copyKey()\" [class.copied]=\"KeyCopied\">\n <i class=\"fa-solid\" [class.fa-copy]=\"!KeyCopied\" [class.fa-check]=\"KeyCopied\"></i>\n <span>{{KeyCopied ? 'Copied!' : 'Copy'}}</span>\n </button>\n </div>\n </div>\n <div class=\"key-details\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Label:</span>\n <span class=\"detail-value\">{{Label}}</span>\n </div>\n @if (Description) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Description:</span>\n <span class=\"detail-value\">{{Description}}</span>\n </div>\n }\n <div class=\"detail-row\">\n <span class=\"detail-label\">Expires:</span>\n <span class=\"detail-value\">\n {{NeverExpires ? 'Never' : (ExpiresAt | date:'MMMM d, yyyy')}}\n </span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Scopes:</span>\n <span class=\"detail-value\">{{getSelectedScopeCount()}} permissions</span>\n </div>\n </div>\n <div class=\"security-note\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div>\n <strong>Security Note:</strong>\n Store this key securely. We only store a hash - the original key cannot be recovered.\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"slideout-footer\">\n @if (Step === 'configure') {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"goToScopes()\">\n Next: Permissions\n <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n <button kendoButton (click)=\"close()\">Cancel</button>\n }\n\n @if (Step === 'scopes') {\n <button kendoButton [themeColor]=\"'primary'\"\n [disabled]=\"IsCreating\"\n (click)=\"createKey()\">\n @if (IsCreating) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsCreating) {\n <span>\n <i class=\"fa-solid fa-key\"></i>\n Generate Key\n </span>\n }\n </button>\n <button kendoButton (click)=\"goBack()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back\n </button>\n }\n\n @if (Step === 'success') {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"close()\">\n <i class=\"fa-solid fa-check\"></i>\n Done\n </button>\n }\n </div>\n</div>\n", styles: ["/* ========================================\n Slide-out Panel Styles\n ======================================== */\n\n/* Backdrop */\n.slideout-backdrop {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 100;\n animation: fadeIn 0.2s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Slide-out Panel */\n.slideout-panel {\n position: absolute;\n top: 0;\n right: 0;\n width: 520px;\n height: 100%;\n max-height: 100%;\n background: var(--mj-bg-surface);\n box-shadow: -8px 0 32px var(--mj-bg-overlay);\n z-index: 101;\n display: flex;\n flex-direction: column;\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateX(100%);\n overflow: hidden;\n}\n\n.slideout-panel.open {\n transform: translateX(0);\n}\n\n/* Panel Header */\n.slideout-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.slideout-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 flex: 1;\n min-width: 0;\n}\n\n.slideout-title i {\n color: var(--mj-brand-primary);\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.slideout-close {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 8px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.slideout-close:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n}\n\n/* Panel Content */\n.slideout-content {\n flex: 1;\n overflow-y: auto;\n}\n\n.step-panel {\n padding: 24px;\n}\n\n/* Panel Footer */\n.slideout-footer {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n background: var(--mj-bg-page);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n:host ::ng-deep .slideout-footer .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 .slideout-footer .k-button-solid-primary {\n background: var(--mj-brand-primary);\n border: none;\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n:host ::ng-deep .slideout-footer .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n:host ::ng-deep .slideout-footer .k-button i {\n margin: 0 5px;\n}\n\n/* Step Indicator */\n.step-indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px 24px;\n background: linear-gradient(135deg, var(--mj-color-brand-100) 0%, var(--mj-color-brand-200) 100%);\n border-bottom: 1px solid var(--mj-color-accent-300);\n}\n\n.step {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n\n.step-number {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-color-neutral-300);\n border-radius: 50%;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.step.active .step-number {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.step.completed .step-number {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.step-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step.active .step-label {\n color: var(--mj-color-brand-800);\n font-weight: 600;\n}\n\n.step-connector {\n width: 80px;\n height: 2px;\n background: var(--mj-color-neutral-300);\n margin: 0 16px;\n margin-bottom: 20px;\n transition: background 0.2s ease;\n}\n\n.step-connector.active {\n background: linear-gradient(90deg, var(--mj-status-success), var(--mj-brand-primary));\n}\n\n/* Dialog Content */\n.dialog-content {\n padding: 24px;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.scopes-content {\n max-height: 450px;\n}\n\n/* Form Sections */\n.form-section {\n margin-bottom: 24px;\n}\n\n.form-label {\n display: block;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.form-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-input,\n.form-textarea {\n width: 100%;\n}\n\n.form-hint {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 6px;\n}\n\n/* Expiration Options */\n.expiration-options {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.checkbox-label {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.preset-buttons {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.preset-btn {\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.preset-btn:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n}\n\n.preset-btn.active {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.custom-date {\n margin-top: 4px;\n}\n\n.expiration-preview {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: var(--mj-color-success-50);\n border-radius: 8px;\n font-size: 13px;\n color: var(--mj-color-success-600);\n}\n\n.expiration-preview i {\n color: var(--mj-status-success);\n}\n\n/* Error Message */\n.error-message {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n background: var(--mj-color-error-50);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 8px;\n color: var(--mj-color-error-600);\n font-size: 14px;\n}\n\n/* Scopes */\n.scopes-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n}\n\n.scopes-info h4 {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.scopes-info p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.scopes-count {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: var(--mj-brand-primary);\n border-radius: 20px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n}\n\n.scopes-count .count {\n font-weight: 700;\n}\n\n/* Scope Categories */\n.scope-categories {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.scope-category {\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.category-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 16px;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.category-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.category-left {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.category-left i {\n font-size: 16px;\n}\n\n.category-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.category-badge {\n padding: 2px 8px;\n background: var(--mj-border-default);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.category-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.select-all-label {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.category-right > i {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.category-scopes {\n padding: 8px 16px 16px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n\n.scope-item {\n padding: 10px 0;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.scope-item:last-child {\n border-bottom: none;\n}\n\n.scope-label {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n cursor: pointer;\n}\n\n.scope-info {\n flex: 1;\n}\n\n.scope-name {\n display: block;\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-family: monospace;\n}\n\n.scope-desc {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n.scope-tip {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: var(--mj-status-info-bg);\n border-radius: 8px;\n margin-top: 16px;\n font-size: 13px;\n color: var(--mj-status-info-text);\n}\n\n.scope-tip i {\n color: var(--mj-status-info);\n}\n\n.scope-tip code {\n background: var(--mj-color-info-100);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n}\n\n/* No Scopes Warning */\n.no-scopes-warning {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: linear-gradient(135deg, var(--mj-color-error-50) 0%, var(--mj-color-error-100) 100%);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n margin-top: 16px;\n font-size: 13px;\n color: var(--mj-status-error);\n}\n\n.no-scopes-warning i {\n font-size: 20px;\n color: var(--mj-color-error-600);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.no-scopes-warning strong {\n display: block;\n color: var(--mj-status-error);\n font-size: 14px;\n margin-bottom: 4px;\n}\n\n.no-scopes-warning p {\n margin: 0;\n line-height: 1.5;\n}\n\n/* Success Content */\n.success-content {\n text-align: center;\n}\n\n.success-icon {\n margin-bottom: 16px;\n}\n\n.success-icon i {\n font-size: 64px;\n color: var(--mj-status-success);\n}\n\n.success-title {\n margin: 0 0 24px 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n/* Key Display */\n.key-display {\n background: var(--mj-color-neutral-800);\n border-radius: 12px;\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.key-warning {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 8px;\n margin-bottom: 16px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-color-accent-300);\n}\n\n.key-value {\n display: flex;\n align-items: center;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n}\n\n.key-value code {\n flex: 1;\n font-family: 'Fira Code', 'Consolas', monospace;\n font-size: 14px;\n color: var(--mj-status-success);\n word-break: break-all;\n text-align: left;\n}\n\n.copy-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-color-neutral-600);\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.copy-btn:hover {\n background: var(--mj-text-secondary);\n}\n\n.copy-btn.copied {\n background: var(--mj-status-success);\n}\n\n/* Key Details */\n.key-details {\n text-align: left;\n background: var(--mj-bg-page);\n border-radius: 10px;\n padding: 16px 20px;\n margin-bottom: 20px;\n}\n\n.detail-row {\n display: flex;\n justify-content: space-between;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.detail-row:last-child {\n border-bottom: none;\n}\n\n.detail-label {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.detail-value {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n/* Security Note */\n.security-note {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n text-align: left;\n padding: 16px;\n background: linear-gradient(135deg, var(--mj-color-success-50) 0%, var(--mj-color-success-100) 100%);\n border-radius: 10px;\n font-size: 13px;\n color: var(--mj-color-success-800);\n}\n\n.security-note i {\n font-size: 20px;\n color: var(--mj-status-success);\n margin-top: 2px;\n}\n\n.security-note strong {\n display: block;\n margin-bottom: 4px;\n}\n\n/* Form input styling */\n:host ::ng-deep .form-input .k-input,\n:host ::ng-deep .form-textarea .k-input-inner,\n:host ::ng-deep .k-datepicker .k-input {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border-color: var(--mj-border-default);\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 .k-datepicker:focus-within {\n box-shadow: var(--mj-focus-ring);\n}\n"] }]
743
+ args: [{ standalone: false, selector: 'mj-api-key-create-dialog', template: "<!-- Slide-out Backdrop -->\n@if (Visible) {\n <div class=\"slideout-backdrop\" (click)=\"Step !== 'success' ? close() : null\"></div>\n}\n\n<!-- Slide-out Panel -->\n<div class=\"slideout-panel\" [class.open]=\"Visible\">\n <!-- Header -->\n <div class=\"slideout-header\">\n <div class=\"slideout-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Generate New API Key</span>\n </div>\n @if (Step !== 'success') {\n <button class=\"slideout-close\" (click)=\"close()\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n\n <!-- Step Indicator -->\n @if (Step !== 'success') {\n <div class=\"step-indicator\">\n <div class=\"step\" [class.active]=\"Step === 'configure'\" [class.completed]=\"Step === 'scopes'\">\n <div class=\"step-number\">1</div>\n <div class=\"step-label\">Configure</div>\n </div>\n <div class=\"step-connector\" [class.active]=\"Step === 'scopes'\"></div>\n <div class=\"step\" [class.active]=\"Step === 'scopes'\">\n <div class=\"step-number\">2</div>\n <div class=\"step-label\">Permissions</div>\n </div>\n </div>\n }\n\n <div class=\"slideout-content\">\n <!-- Configure Step -->\n @if (Step === 'configure') {\n <div class=\"step-panel\">\n <div class=\"form-section\">\n <label class=\"form-label required\">Key Label</label>\n <input class=\"mj-input form-input\" [(ngModel)]=\"Label\"\n placeholder=\"e.g., ElevenLabs Integration, CI/CD Pipeline\" />\n <div class=\"form-hint\">A memorable name to identify this key's purpose</div>\n </div>\n <div class=\"form-section\">\n <label class=\"form-label\">Description</label>\n <textarea class=\"mj-textarea form-textarea\" [(ngModel)]=\"Description\"\n placeholder=\"Optional notes about how this key will be used...\"\n [rows]=\"3\"></textarea>\n </div>\n <div class=\"form-section\">\n <label class=\"form-label\">Expiration</label>\n <div class=\"expiration-options\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" class=\"mj-checkbox\"\n [(ngModel)]=\"NeverExpires\"\n (change)=\"onNeverExpiresChange()\" />\n <span>Never expires</span>\n </label>\n @if (!NeverExpires) {\n <div class=\"preset-buttons\">\n @for (preset of ExpirationPresets; track preset) {\n <button\n class=\"preset-btn\"\n [class.active]=\"SelectedPreset === preset\"\n (click)=\"onPresetSelect(preset)\">\n {{preset.label}}\n </button>\n }\n </div>\n }\n @if (!NeverExpires && SelectedPreset?.days === -1) {\n <div class=\"custom-date\">\n <mj-datepicker [(ngModel)]=\"ExpiresAt\"\n [Min]=\"getMinDate()\"\n Format=\"MMM d, yyyy\"\n Placeholder=\"Select expiration date\">\n </mj-datepicker>\n </div>\n }\n @if (!NeverExpires && ExpiresAt) {\n <div class=\"expiration-preview\">\n <i class=\"fa-solid fa-calendar-check\"></i>\n <span>Key will expire on {{ExpiresAt | date:'MMMM d, yyyy'}}</span>\n </div>\n }\n </div>\n </div>\n @if (Error) {\n <div class=\"error-message\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{Error}}\n </div>\n }\n </div>\n }\n\n <!-- Scopes Step -->\n @if (Step === 'scopes') {\n <div class=\"step-panel scopes-step\">\n <div class=\"scopes-header\">\n <div class=\"scopes-info\">\n <h4>Select Permission Scopes</h4>\n <p>Choose what this API key can access. You can always modify this later.</p>\n </div>\n @if (getSelectedScopeCount() > 0) {\n <div class=\"scopes-count\">\n <span class=\"count\">{{getSelectedScopeCount()}}</span> selected\n </div>\n }\n </div>\n @if (IsLoadingScopes) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n @if (!IsLoadingScopes) {\n <div class=\"scope-categories\">\n @for (category of ScopeCategories; track category) {\n <div class=\"scope-category\">\n <div class=\"category-header\" (click)=\"toggleCategory(category)\">\n <div class=\"category-left\">\n <i [class]=\"category.icon\" [style.color]=\"category.color\"></i>\n <span class=\"category-name\">{{category.name}}</span>\n <span class=\"category-badge\">{{category.scopes.length}}</span>\n </div>\n <div class=\"category-right\">\n <label class=\"select-all-label\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" class=\"mj-checkbox\"\n [checked]=\"category.allSelected\"\n (change)=\"toggleCategoryAll(category)\" />\n <span>All</span>\n </label>\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!category.expanded\"\n [class.fa-chevron-up]=\"category.expanded\"></i>\n </div>\n </div>\n @if (category.expanded) {\n <div class=\"category-scopes\">\n @for (item of category.scopes; track item) {\n <div class=\"scope-item\">\n <label class=\"scope-label\">\n <input type=\"checkbox\" class=\"mj-checkbox\"\n [(ngModel)]=\"item.selected\"\n (change)=\"updateCategoryState(category)\" />\n <div class=\"scope-info\">\n <span class=\"scope-name\">{{item.scope.Name}}</span>\n @if (item.scope.Description) {\n <span class=\"scope-desc\">\n {{item.scope.Description}}\n </span>\n }\n </div>\n </label>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <div class=\"scope-tip\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Tip: Use wildcards like <code>entities:*</code> for broad access within a category</span>\n </div>\n <!-- No Scopes Warning -->\n @if (!IsLoadingScopes && getSelectedScopeCount() === 0) {\n <div class=\"no-scopes-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div>\n <strong>Warning: No permissions selected</strong>\n <p>API keys without any assigned scopes will have <strong>no permissions</strong> and cannot perform any operations. This key will be rejected by all API endpoints until scopes are assigned.</p>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Success Step -->\n @if (Step === 'success') {\n <div class=\"step-panel success-step\">\n <div class=\"success-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <h3 class=\"success-title\">API Key Created Successfully!</h3>\n <div class=\"key-display\">\n <div class=\"key-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>Copy this key now. It won't be shown again!</span>\n </div>\n <div class=\"key-value\">\n <code>{{RawApiKey}}</code>\n <button class=\"copy-btn\" (click)=\"copyKey()\" [class.copied]=\"KeyCopied\">\n <i class=\"fa-solid\" [class.fa-copy]=\"!KeyCopied\" [class.fa-check]=\"KeyCopied\"></i>\n <span>{{KeyCopied ? 'Copied!' : 'Copy'}}</span>\n </button>\n </div>\n </div>\n <div class=\"key-details\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Label:</span>\n <span class=\"detail-value\">{{Label}}</span>\n </div>\n @if (Description) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Description:</span>\n <span class=\"detail-value\">{{Description}}</span>\n </div>\n }\n <div class=\"detail-row\">\n <span class=\"detail-label\">Expires:</span>\n <span class=\"detail-value\">\n {{NeverExpires ? 'Never' : (ExpiresAt | date:'MMMM d, yyyy')}}\n </span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Scopes:</span>\n <span class=\"detail-value\">{{getSelectedScopeCount()}} permissions</span>\n </div>\n </div>\n <div class=\"security-note\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div>\n <strong>Security Note:</strong>\n Store this key securely. We only store a hash - the original key cannot be recovered.\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"slideout-footer\">\n @if (Step === 'configure') {\n <button mjButton variant=\"primary\" (click)=\"goToScopes()\">\n Next: Permissions\n <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n <button mjButton (click)=\"close()\">Cancel</button>\n }\n\n @if (Step === 'scopes') {\n <button mjButton variant=\"primary\"\n [disabled]=\"IsCreating\"\n (click)=\"createKey()\">\n @if (IsCreating) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsCreating) {\n <span>\n <i class=\"fa-solid fa-key\"></i>\n Generate Key\n </span>\n }\n </button>\n <button mjButton (click)=\"goBack()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back\n </button>\n }\n\n @if (Step === 'success') {\n <button mjButton variant=\"primary\" (click)=\"close()\">\n <i class=\"fa-solid fa-check\"></i>\n Done\n </button>\n }\n </div>\n</div>\n", styles: ["/* ========================================\n Slide-out Panel Styles\n ======================================== */\n\n/* Backdrop */\n.slideout-backdrop {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 100;\n animation: fadeIn 0.2s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Slide-out Panel */\n.slideout-panel {\n position: absolute;\n top: 0;\n right: 0;\n width: 520px;\n height: 100%;\n max-height: 100%;\n background: var(--mj-bg-surface);\n box-shadow: -8px 0 32px var(--mj-bg-overlay);\n z-index: 101;\n display: flex;\n flex-direction: column;\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateX(100%);\n overflow: hidden;\n}\n\n.slideout-panel.open {\n transform: translateX(0);\n}\n\n/* Panel Header */\n.slideout-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.slideout-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 flex: 1;\n min-width: 0;\n}\n\n.slideout-title i {\n color: var(--mj-brand-primary);\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.slideout-close {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 8px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.slideout-close:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n}\n\n/* Panel Content */\n.slideout-content {\n flex: 1;\n overflow-y: auto;\n}\n\n.step-panel {\n padding: 24px;\n}\n\n/* Panel Footer */\n.slideout-footer {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n background: var(--mj-bg-page);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n:host ::ng-deep .slideout-footer .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 .slideout-footer .k-button-solid-primary {\n background: var(--mj-brand-primary);\n border: none;\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n:host ::ng-deep .slideout-footer .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n:host ::ng-deep .slideout-footer .k-button i {\n margin: 0 5px;\n}\n\n/* Step Indicator */\n.step-indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px 24px;\n background: linear-gradient(135deg, var(--mj-color-brand-100) 0%, var(--mj-color-brand-200) 100%);\n border-bottom: 1px solid var(--mj-color-accent-300);\n}\n\n.step {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n\n.step-number {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-color-neutral-300);\n border-radius: 50%;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.step.active .step-number {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.step.completed .step-number {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.step-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step.active .step-label {\n color: var(--mj-color-brand-800);\n font-weight: 600;\n}\n\n.step-connector {\n width: 80px;\n height: 2px;\n background: var(--mj-color-neutral-300);\n margin: 0 16px;\n margin-bottom: 20px;\n transition: background 0.2s ease;\n}\n\n.step-connector.active {\n background: linear-gradient(90deg, var(--mj-status-success), var(--mj-brand-primary));\n}\n\n/* Dialog Content */\n.dialog-content {\n padding: 24px;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.scopes-content {\n max-height: 450px;\n}\n\n/* Form Sections */\n.form-section {\n margin-bottom: 24px;\n}\n\n.form-label {\n display: block;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.form-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-input,\n.form-textarea {\n width: 100%;\n}\n\n.form-hint {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 6px;\n}\n\n/* Expiration Options */\n.expiration-options {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.checkbox-label {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.preset-buttons {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.preset-btn {\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.preset-btn:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n}\n\n.preset-btn.active {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.custom-date {\n margin-top: 4px;\n}\n\n.expiration-preview {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: var(--mj-color-success-50);\n border-radius: 8px;\n font-size: 13px;\n color: var(--mj-color-success-600);\n}\n\n.expiration-preview i {\n color: var(--mj-status-success);\n}\n\n/* Error Message */\n.error-message {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n background: var(--mj-color-error-50);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 8px;\n color: var(--mj-color-error-600);\n font-size: 14px;\n}\n\n/* Scopes */\n.scopes-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n}\n\n.scopes-info h4 {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.scopes-info p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.scopes-count {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: var(--mj-brand-primary);\n border-radius: 20px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n}\n\n.scopes-count .count {\n font-weight: 700;\n}\n\n/* Scope Categories */\n.scope-categories {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.scope-category {\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.category-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 16px;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.category-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.category-left {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.category-left i {\n font-size: 16px;\n}\n\n.category-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.category-badge {\n padding: 2px 8px;\n background: var(--mj-border-default);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.category-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.select-all-label {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.category-right > i {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.category-scopes {\n padding: 8px 16px 16px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n\n.scope-item {\n padding: 10px 0;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.scope-item:last-child {\n border-bottom: none;\n}\n\n.scope-label {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n cursor: pointer;\n}\n\n.scope-info {\n flex: 1;\n}\n\n.scope-name {\n display: block;\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-family: monospace;\n}\n\n.scope-desc {\n display: block;\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n.scope-tip {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: var(--mj-status-info-bg);\n border-radius: 8px;\n margin-top: 16px;\n font-size: 13px;\n color: var(--mj-status-info-text);\n}\n\n.scope-tip i {\n color: var(--mj-status-info);\n}\n\n.scope-tip code {\n background: var(--mj-color-info-100);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n}\n\n/* No Scopes Warning */\n.no-scopes-warning {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: linear-gradient(135deg, var(--mj-color-error-50) 0%, var(--mj-color-error-100) 100%);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n margin-top: 16px;\n font-size: 13px;\n color: var(--mj-status-error);\n}\n\n.no-scopes-warning i {\n font-size: 20px;\n color: var(--mj-color-error-600);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.no-scopes-warning strong {\n display: block;\n color: var(--mj-status-error);\n font-size: 14px;\n margin-bottom: 4px;\n}\n\n.no-scopes-warning p {\n margin: 0;\n line-height: 1.5;\n}\n\n/* Success Content */\n.success-content {\n text-align: center;\n}\n\n.success-icon {\n margin-bottom: 16px;\n}\n\n.success-icon i {\n font-size: 64px;\n color: var(--mj-status-success);\n}\n\n.success-title {\n margin: 0 0 24px 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n/* Key Display */\n.key-display {\n background: var(--mj-color-neutral-800);\n border-radius: 12px;\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.key-warning {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 8px;\n margin-bottom: 16px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-color-accent-300);\n}\n\n.key-value {\n display: flex;\n align-items: center;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n}\n\n.key-value code {\n flex: 1;\n font-family: 'Fira Code', 'Consolas', monospace;\n font-size: 14px;\n color: var(--mj-status-success);\n word-break: break-all;\n text-align: left;\n}\n\n.copy-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-color-neutral-600);\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.copy-btn:hover {\n background: var(--mj-text-secondary);\n}\n\n.copy-btn.copied {\n background: var(--mj-status-success);\n}\n\n/* Key Details */\n.key-details {\n text-align: left;\n background: var(--mj-bg-page);\n border-radius: 10px;\n padding: 16px 20px;\n margin-bottom: 20px;\n}\n\n.detail-row {\n display: flex;\n justify-content: space-between;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.detail-row:last-child {\n border-bottom: none;\n}\n\n.detail-label {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.detail-value {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n/* Security Note */\n.security-note {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n text-align: left;\n padding: 16px;\n background: linear-gradient(135deg, var(--mj-color-success-50) 0%, var(--mj-color-success-100) 100%);\n border-radius: 10px;\n font-size: 13px;\n color: var(--mj-color-success-800);\n}\n\n.security-note i {\n font-size: 20px;\n color: var(--mj-status-success);\n margin-top: 2px;\n}\n\n.security-note strong {\n display: block;\n margin-bottom: 4px;\n}\n\n/* Form input styling */\n:host ::ng-deep .form-input .k-input,\n:host ::ng-deep .form-textarea .k-input-inner,\n:host ::ng-deep .k-datepicker .k-input {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border-color: var(--mj-border-default);\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 .k-datepicker:focus-within {\n box-shadow: var(--mj-focus-ring);\n}\n"] }]
750
744
  }], null, { Visible: [{
751
745
  type: Input
752
746
  }], VisibleChange: [{
@@ -1 +1 @@
1
- {"version":3,"file":"api-key-create-dialog.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-key-create-dialog.component.ts","../../src/APIKeys/api-key-create-dialog.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAU,MAAM,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAuB,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AACpG,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;;;;;;;;;;ICFvF,+BAA6E;IAA9C,4MAAkB,SAAS,GAAG,cAAO,GAAG,IAAI,KAAC;IAAC,iBAAM;;;;IAY/E,kCAAqE;IAAtC,+LAAS,cAAO,KAAC;IAC9C,wBAAiC;IACnC,iBAAS;;;IAQP,AADF,AADF,8BAA4B,cACoE,cACnE;IAAA,iBAAC;IAAA,iBAAM;IAChC,+BAAwB;IAAA,yBAAS;IACnC,AADmC,iBAAM,EACnC;IACN,0BAAqE;IAEnE,AADF,+BAAqD,cAC1B;IAAA,iBAAC;IAAA,iBAAM;IAChC,gCAAwB;IAAA,4BAAW;IAEvC,AADE,AADqC,iBAAM,EACrC,EACF;;;IATc,cAAqC;IAAC,AAAtC,qDAAqC,uCAAsC;IAIjE,eAAkC;IAAlC,kDAAkC;IAC5C,cAAkC;IAAlC,kDAAkC;;;;IAqCxC,kCAGmC;IAAjC,kPAAS,gCAAsB,KAAC;IAChC,YACF;IAAA,iBAAS;;;;IAHP,6DAA0C;IAE1C,cACF;IADE,gDACF;;;IAPJ,+BAA4B;IAC1B,kJAOC;IACH,iBAAM;;;IARJ,cAOC;IAPD,uCAOC;;;;IAKD,AADF,+BAAyB,2BAIgB;IAHrB,iVAAuB;IAK3C,AADE,iBAAmB,EACf;;;IALc,cAAuB;IAAvB,gDAAuB;IACvC,yCAAoB;;;IAOxB,+BAAgC;IAC9B,wBAA0C;IAC1C,4BAAM;IAAA,YAAsD;;IAC9D,AAD8D,iBAAO,EAC/D;;;IADE,eAAsD;IAAtD,oGAAsD;;;IAMlE,+BAA2B;IACzB,wBAA8C;IAC9C,YACF;IAAA,iBAAM;;;IADJ,eACF;IADE,6CACF;;;;IAvDA,AADF,AADF,8BAAwB,cACI,gBACW;IAAA,yBAAS;IAAA,iBAAQ;IACpD,iCAEuB;IAFH,8SAAmB;IAAvC,iBAEuB;IACvB,+BAAuB;IAAA,+DAA+C;IACxE,AADwE,iBAAM,EACxE;IAEJ,AADF,+BAA0B,gBACE;IAAA,2BAAW;IAAA,iBAAQ;IAC7C,qCAGsB;IAHE,8TAAyB;IAInD,AADwB,iBAAW,EAC7B;IAEJ,AADF,gCAA0B,iBACE;IAAA,2BAAU;IAAA,iBAAQ;IAGxC,AADF,AADF,gCAAgC,iBACA,iBAGU;IADpC,6TAA0B;IAC1B,kMAAU,6BAAsB,KAAC;IAFnC,iBAEsC;IACtC,6BAAM;IAAA,8BAAa;IACrB,AADqB,iBAAO,EACpB;IACR,+GAAqB;IAYrB,+GAAoD;IASpD,+GAAkC;IAOtC,AADE,iBAAM,EACF;IACN,+GAAa;IAMf,iBAAM;;;IAxDkB,eAAmB;IAAnB,4CAAmB;IAOf,eAAyB;IAAzB,kDAAyB;IAE/C,wBAAU;IAQN,eAA0B;IAA1B,mDAA0B;IAI9B,eAWC;IAXD,gDAWC;IACD,cAQC;IARD,8HAQC;IACD,cAKC;IALD,oEAKC;IAGL,cAKC;IALD,wCAKC;;;IAcK,AADF,+BAA0B,eACJ;IAAA,YAA2B;IAAA,iBAAO;IAAC,0BACzD;IAAA,iBAAM;;;IADgB,eAA2B;IAA3B,oDAA2B;;;IAKnD,iCAAkD;;;IAkC9B,gCAAyB;IACvB,YACF;IAAA,iBAAO;;;IADL,cACF;IADE,2DACF;;;;IARJ,AADF,AADF,+BAAwB,gBACK,gBAGoB;IAD3C,0VAA2B;IAC3B,+RAAU,uCAA6B,KAAC;IAF1C,iBAE6C;IAE3C,AADF,+BAAwB,eACG;IAAA,YAAmB;IAAA,iBAAO;IACnD,uJAA8B;IAOpC,AADE,AADE,iBAAM,EACA,EACJ;;;IAXA,eAA2B;IAA3B,iDAA2B;IAGF,eAAmB;IAAnB,yCAAmB;IAC5C,cAIC;IAJD,qDAIC;;;IAbX,+BAA6B;IAC3B,mKAgBC;IACH,iBAAM;;;IAjBJ,cAgBC;IAhBD,iCAgBC;;;;IAnCL,AADF,+BAA4B,cACsC;IAAnC,gPAAS,kCAAwB,KAAC;IAC7D,+BAA2B;IACzB,oBAA8D;IAC9D,gCAA4B;IAAA,YAAiB;IAAA,iBAAO;IACpD,gCAA6B;IAAA,YAA0B;IACzD,AADyD,iBAAO,EAC1D;IAEJ,AADF,+BAA4B,gBACyC;IAAnC,sLAAS,wBAAwB,KAAC;IAChE,kCAE2C;IAAzC,qPAAU,qCAA2B,KAAC;IAFxC,iBAE2C;IAC3C,6BAAM;IAAA,oBAAG;IACX,AADW,iBAAO,EACV;IACR,yBAC8C;IAElD,AADE,iBAAM,EACF;IACN,mIAAyB;IAqB3B,iBAAM;;;IApCG,eAAuB;IAAvB,+BAAuB;IAAC,0CAA8B;IAC7B,eAAiB;IAAjB,sCAAiB;IAChB,eAA0B;IAA1B,+CAA0B;IAKnD,eAAgC;IAAhC,iDAAgC;IAIhB,eAA4C;IAChE,AADoB,wDAA4C,uCACvB;IAG7C,cAoBC;IApBD,gDAoBC;;;IAxCP,+BAA8B;IAC5B,gJAyCC;IACH,iBAAM;;;IA1CJ,cAyCC;IAzCD,qCAyCC;;;IASH,+BAA+B;IAC7B,wBAAgD;IAE9C,AADF,2BAAK,aACK;IAAA,gDAAgC;IAAA,iBAAS;IACjD,yBAAG;IAAA,+DAA+C;IAAA,8BAAQ;IAAA,8BAAc;IAAA,iBAAS;IAAC,6HAA4G;IAElM,AADE,AADgM,iBAAI,EAC9L,EACF;;;IAtEJ,AADF,AADF,AADF,8BAAoC,cACP,cACA,SACnB;IAAA,wCAAwB;IAAA,iBAAK;IACjC,yBAAG;IAAA,sFAAsE;IAC3E,AAD2E,iBAAI,EACzE;IACN,6GAAmC;IAKrC,iBAAM;IACN,oHAAuB;IAGvB,6GAAwB;IA8CxB,gCAAuB;IACrB,yBAAqC;IACrC,6BAAM;IAAA,yCAAwB;IAAA,6BAAM;IAAA,2BAAU;IAAA,iBAAO;IAAC,oDAAkC;IAC1F,AAD0F,iBAAO,EAC3F;IAEN,gHAAyD;IAS3D,iBAAM;;;IArEF,eAIC;IAJD,6DAIC;IAEH,cAEC;IAFD,iDAEC;IACD,cA6CC;IA7CD,kDA6CC;IAMD,eAQC;IARD,2FAQC;;;IA+BK,AADF,+BAAwB,eACK;IAAA,4BAAY;IAAA,iBAAO;IAC9C,gCAA2B;IAAA,YAAe;IAC5C,AAD4C,iBAAO,EAC7C;;;IADuB,eAAe;IAAf,wCAAe;;;;IAzBhD,AADF,+BAAqC,cACT;IACxB,wBAAwC;IAC1C,iBAAM;IACN,8BAA0B;IAAA,6CAA6B;IAAA,iBAAK;IAE1D,AADF,+BAAyB,cACE;IACvB,wBAAgD;IAChD,4BAAM;IAAA,2DAA2C;IACnD,AADmD,iBAAO,EACpD;IAEJ,AADF,gCAAuB,YACf;IAAA,aAAa;IAAA,iBAAO;IAC1B,mCAAwE;IAA/C,kMAAS,gBAAS,KAAC;IAC1C,yBAAkF;IAClF,6BAAM;IAAA,aAAkC;IAG9C,AADE,AADE,AAD0C,iBAAO,EACxC,EACL,EACF;IAGF,AADF,AADF,gCAAyB,eACC,gBACK;IAAA,uBAAM;IAAA,iBAAO;IACxC,iCAA2B;IAAA,aAAS;IACtC,AADsC,iBAAO,EACvC;IACN,+GAAmB;IAOjB,AADF,gCAAwB,gBACK;IAAA,yBAAQ;IAAA,iBAAO;IAC1C,iCAA2B;IACzB,aACF;;IACF,AADE,iBAAO,EACH;IAEJ,AADF,gCAAwB,gBACK;IAAA,wBAAO;IAAA,iBAAO;IACzC,iCAA2B;IAAA,aAAuC;IAEtE,AADE,AADoE,iBAAO,EACrE,EACF;IACN,gCAA2B;IACzB,yBAAwC;IAEtC,AADF,4BAAK,cACK;IAAA,+BAAc;IAAA,iBAAS;IAC/B,wGACF;IAEJ,AADE,AADE,iBAAM,EACF,EACF;;;IApCM,gBAAa;IAAb,sCAAa;IAC0B,cAA0B;IAA1B,0CAA0B;IACjD,cAA4B;IAAC,AAA7B,4CAA4B,8BAA6B;IACvE,eAAkC;IAAlC,2DAAkC;IAOf,eAAS;IAAT,kCAAS;IAEtC,cAKC;IALD,8CAKC;IAIG,eACF;IADE,yHACF;IAI2B,eAAuC;IAAvC,yEAAuC;;;;IAiBxE,kCAAoE;IAAvB,iMAAS,mBAAY,KAAC;IACjE,mCACA;IAAA,wBAAuC;IACzC,iBAAS;IACT,kCAAsC;IAAlB,iMAAS,cAAO,KAAC;IAAC,sBAAM;IAAA,iBAAS;;IAJjC,sCAAwB;;;IAYxC,iCAAyD;;IAA7C,gCAAkB;;;IAG9B,4BAAM;IACJ,uBAA+B;IAC/B,8BACF;IAAA,iBAAO;;;;IAVX,kCAEwB;IAAtB,iMAAS,kBAAW,KAAC;IACrB,oHAAkB;IAGlB,0GAAmB;IAMrB,iBAAS;IACT,kCAAuC;IAAnB,iMAAS,eAAQ,KAAC;IACpC,wBAAsC;IACtC,sBACF;IAAA,iBAAS;;;IAfP,AADkB,sCAAwB,+BACnB;IAEvB,cAEC;IAFD,4CAEC;IACD,cAKC;IALD,6CAKC;;;;IASH,kCAA+D;IAAlB,iMAAS,cAAO,KAAC;IAC5D,wBAAiC;IACjC,sBACF;IAAA,iBAAS;;IAHW,sCAAwB;;AD3OlD;;;GAGG;AAOH,MAAM,OAAO,2BAA2B;IAC3B,OAAO,GAAG,KAAK,CAAC;IACf,aAAa,GAAG,IAAI,YAAY,EAAW,CAAC;IAC5C,OAAO,GAAG,IAAI,YAAY,EAAsB,CAAC;IACjD,MAAM,GAAG,IAAI,YAAY,EAAQ,CAAC;IAE5C,cAAc;IACP,KAAK,GAAG,EAAE,CAAC;IACX,WAAW,GAAG,EAAE,CAAC;IACjB,SAAS,GAAgB,IAAI,CAAC;IAC9B,YAAY,GAAG,IAAI,CAAC;IAE3B,qBAAqB;IACd,iBAAiB,GAAG;QACvB,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE;QAC9B,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE;QAC9B,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE;QAC9B,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;KAChC,CAAC;IACK,cAAc,GAA2C,IAAI,CAAC;IAErE,SAAS;IACF,eAAe,GAAoB,EAAE,CAAC;IACtC,eAAe,GAAG,IAAI,CAAC;IAE9B,QAAQ;IACD,UAAU,GAAG,KAAK,CAAC;IACnB,IAAI,GAAuC,WAAW,CAAC;IACvD,SAAS,GAAG,EAAE,CAAC;IACf,SAAS,GAAG,KAAK,CAAC;IAClB,KAAK,GAAG,EAAE,CAAC;IAElB,kEAAkE;IACjD,eAAe,GAAG;QAC/B,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,sBAAsB;KAChC,CAAC;IAEF,QAAQ;QACJ,IAAI,CAAC,UAAU,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IAEI,WAAW;QACd,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,UAAU;QACd,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC;YACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAE3B,iDAAiD;YACjD,6EAA6E;YAC7E,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAA2C,CAAC;YAC7E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACzB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;oBAClB,2DAA2D;oBAC3D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;oBAC9C,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE;wBAClC,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI;wBAChD,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK;qBACtD,CAAC,CAAC;gBACP,CAAC;YACL,CAAC;YAED,2BAA2B;YAC3B,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;YACnD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC;gBAC3C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC7B,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAClC,CAAC;gBACD,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC;oBAC5B,KAAK;oBACL,QAAQ,EAAE,KAAK;iBAClB,CAAC,CAAC;YACP,CAAC;YAED,mDAAmD;YACnD,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;iBACnD,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;iBACtC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE;gBACxB,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC;gBACnE,OAAO;oBACH,IAAI;oBACJ,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC3E,QAAQ,EAAE,KAAK;oBACf,WAAW,EAAE,KAAK;iBACrB,CAAC;YACN,CAAC,CAAC,CAAC;QACX,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QACjC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,MAAuC;QACzD,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAE1B,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAC1B,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAC1B,CAAC;IACL,CAAC;IAED;;OAEG;IACI,oBAAoB;QACvB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC/B,CAAC;IACL,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,QAAuB;QACzC,QAAQ,CAAC,QAAQ,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC3C,CAAC;IAED;;OAEG;IACI,iBAAiB,CAAC,QAAuB;QAC5C,QAAQ,CAAC,WAAW,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC7C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC;QACzC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,mBAAmB,CAAC,QAAuB;QAC9C,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACI,qBAAqB;QACxB,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAC5C,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACI,UAAU;QACb,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,GAAG,sCAAsC,CAAC;YACpD,OAAO;QACX,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,MAAM;QACT,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,SAAS;QAClB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC;YACD,yBAAyB;YACzB,MAAM,gBAAgB,GAAG,IAAI,CAAC,eAAe;iBACxC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;iBAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;iBACvB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAE1B,4DAA4D;YAC5D,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAA+B,CAAC;YAC1D,MAAM,gBAAgB,GAAG,IAAI,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YAE/D,mEAAmE;YACnE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,YAAY,CAAC;gBAC/C,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;gBACxB,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,SAAS;gBACjD,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC;gBACxE,QAAQ,EAAE,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;aACvE,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC/B,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;gBAEtB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;oBACd,OAAO,EAAE,IAAI;oBACb,MAAM,EAAE,MAAM,CAAC,MAAM;iBACxB,CAAC,CAAC;YACP,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,6CAA6C,CAAC;YAC/E,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,IAAI,CAAC,KAAK,GAAG,+CAA+C,CAAC;QACjE,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC5B,CAAC;IACL,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO;QAChB,IAAI,CAAC;YACD,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACpD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC;IACL,CAAC;IAED;;OAEG;IACI,KAAK;QACR,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACK,KAAK;QACT,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAEhB,yBAAyB;QACzB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1C,QAAQ,CAAC,QAAQ,GAAG,KAAK,CAAC;YAC1B,QAAQ,CAAC,WAAW,GAAG,KAAK,CAAC;YAC7B,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAClC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;YAC3B,CAAC;QACL,CAAC;IACL,CAAC;IAED;;OAEG;IACI,UAAU;QACb,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC;QAC5B,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACzC,OAAO,QAAQ,CAAC;IACpB,CAAC;qHA9RQ,2BAA2B;6DAA3B,2BAA2B;YAA3B,kHAAA,iBAAa,0BAAc;;YCtCxC,6FAAe;YAQX,AADF,AAFF,8BAAmD,aAEpB,aACC;YAC1B,uBAA+B;YAC/B,4BAAM;YAAA,oCAAoB;YAC5B,AAD4B,iBAAO,EAC7B;YACN,gGAA0B;YAK5B,iBAAM;YAGN,8FAA0B;YAc1B,8BAA8B;YAE5B,gGAA4B;YAgE5B,gGAAyB;YAgFzB,kGAA0B;YAkD5B,iBAAM;YAGN,gCAA6B;YAC3B,qFAA4B;YAQ5B,qFAAyB;YAoBzB,mGAA0B;YAO9B,AADE,iBAAM,EACF;;YA7QN,sCAEC;YAG2B,cAAsB;YAAtB,mCAAsB;YAO9C,eAIC;YAJD,iDAIC;YAIH,cAYC;YAZD,iDAYC;YAIC,eA6DC;YA7DD,oDA6DC;YAGD,cA6EC;YA7ED,iDA6EC;YAGD,cAiDC;YAjDD,kDAiDC;YAKD,eAMC;YAND,oDAMC;YAED,cAkBC;YAlBD,iDAkBC;YAED,cAKC;YALD,kDAKC;;;iFDrOQ,2BAA2B;cANvC,SAAS;6BACI,KAAK,YACL,0BAA0B;;kBAKnC,KAAK;;kBACL,MAAM;;kBACN,MAAM;;kBACN,MAAM;;kBAyCN,YAAY;mBAAC,yBAAyB;;kFA7C9B,2BAA2B","sourcesContent":["import { Component, EventEmitter, HostListener, Input, OnInit, Output } from '@angular/core';\nimport { Metadata } from '@memberjunction/core';\nimport { MJAPIScopeEntity } from '@memberjunction/core-entities';\nimport { GraphQLDataProvider, GraphQLEncryptionClient } from '@memberjunction/graphql-dataprovider';\nimport { APIKeysEngineBase, parseAPIScopeUIConfig } from '@memberjunction/api-keys-base';\n\n/** Scope selection item */\ninterface ScopeItem {\n scope: MJAPIScopeEntity;\n selected: boolean;\n}\n\n/** Grouped scopes by category */\ninterface ScopeCategory {\n name: string;\n icon: string;\n color: string;\n scopes: ScopeItem[];\n expanded: boolean;\n allSelected: boolean;\n}\n\n/** Result of key creation */\nexport interface APIKeyCreateResult {\n success: boolean;\n apiKeyId?: string;\n rawKey?: string;\n error?: string;\n}\n/**\n * Dialog for creating new API keys\n * Shows the raw key only once - it cannot be recovered after closing\n */\n@Component({\n standalone: false,\n selector: 'mj-api-key-create-dialog',\n templateUrl: './api-key-create-dialog.component.html',\n styleUrls: ['./api-key-create-dialog.component.css']\n})\nexport class APIKeyCreateDialogComponent implements OnInit {\n @Input() Visible = false;\n @Output() VisibleChange = new EventEmitter<boolean>();\n @Output() Created = new EventEmitter<APIKeyCreateResult>();\n @Output() Closed = new EventEmitter<void>();\n\n // Form fields\n public Label = '';\n public Description = '';\n public ExpiresAt: Date | null = null;\n public NeverExpires = true;\n\n // Expiration presets\n public ExpirationPresets = [\n { label: '30 days', days: 30 },\n { label: '90 days', days: 90 },\n { label: '1 year', days: 365 },\n { label: 'Custom', days: -1 }\n ];\n public SelectedPreset: { label: string; days: number } | null = null;\n\n // Scopes\n public ScopeCategories: ScopeCategory[] = [];\n public IsLoadingScopes = true;\n\n // State\n public IsCreating = false;\n public Step: 'configure' | 'scopes' | 'success' = 'configure';\n public RawApiKey = '';\n public KeyCopied = false;\n public Error = '';\n\n // Default UI config for categories without explicit configuration\n private readonly defaultUIConfig = {\n icon: 'fa-solid fa-ellipsis',\n color: 'var(--mj-text-muted)'\n };\n\n ngOnInit(): void {\n this.loadScopes();\n }\n\n /**\n * Handle escape key to close dialog\n */\n @HostListener('document:keydown.escape')\n public onEscapeKey(): void {\n if (this.Visible && !this.IsCreating) {\n this.close();\n }\n }\n\n /**\n * Load available scopes from cached data.\n * Uses UIConfig from root scopes for category icons/colors.\n */\n private loadScopes(): void {\n this.IsLoadingScopes = true;\n try {\n const base = APIKeysEngineBase.Instance;\n const scopes = base.Scopes;\n\n // Build a map of category -> root scope UIConfig\n // Root scopes (ParentID is null) define the UI appearance for their category\n const categoryUIConfigs = new Map<string, { icon: string; color: string }>();\n for (const scope of scopes) {\n if (!scope.ParentID) {\n // This is a root scope - use its UIConfig for the category\n const uiConfig = parseAPIScopeUIConfig(scope);\n categoryUIConfigs.set(scope.Category, {\n icon: uiConfig.icon || this.defaultUIConfig.icon,\n color: uiConfig.color || this.defaultUIConfig.color\n });\n }\n }\n\n // Group scopes by category\n const categoryMap = new Map<string, ScopeItem[]>();\n for (const scope of scopes) {\n const category = scope.Category || 'Other';\n if (!categoryMap.has(category)) {\n categoryMap.set(category, []);\n }\n categoryMap.get(category)!.push({\n scope,\n selected: false\n });\n }\n\n // Build categories with UI config from root scopes\n this.ScopeCategories = Array.from(categoryMap.entries())\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([name, scopeItems]) => {\n const config = categoryUIConfigs.get(name) || this.defaultUIConfig;\n return {\n name,\n icon: config.icon,\n color: config.color,\n scopes: scopeItems.sort((a, b) => a.scope.Name.localeCompare(b.scope.Name)),\n expanded: false,\n allSelected: false\n };\n });\n } catch (error) {\n console.error('Error loading scopes:', error);\n } finally {\n this.IsLoadingScopes = false;\n }\n }\n\n /**\n * Handle expiration preset selection\n */\n public onPresetSelect(preset: { label: string; days: number }): void {\n this.SelectedPreset = preset;\n this.NeverExpires = false;\n\n if (preset.days > 0) {\n const date = new Date();\n date.setDate(date.getDate() + preset.days);\n this.ExpiresAt = date;\n } else {\n this.ExpiresAt = null;\n }\n }\n\n /**\n * Handle never expires toggle\n */\n public onNeverExpiresChange(): void {\n if (this.NeverExpires) {\n this.ExpiresAt = null;\n this.SelectedPreset = null;\n }\n }\n\n /**\n * Toggle category expansion\n */\n public toggleCategory(category: ScopeCategory): void {\n category.expanded = !category.expanded;\n }\n\n /**\n * Toggle all scopes in a category\n */\n public toggleCategoryAll(category: ScopeCategory): void {\n category.allSelected = !category.allSelected;\n for (const item of category.scopes) {\n item.selected = category.allSelected;\n }\n }\n\n /**\n * Update category allSelected state\n */\n public updateCategoryState(category: ScopeCategory): void {\n category.allSelected = category.scopes.every(s => s.selected);\n }\n\n /**\n * Get selected scope count\n */\n public getSelectedScopeCount(): number {\n return this.ScopeCategories.reduce((sum, cat) =>\n sum + cat.scopes.filter(s => s.selected).length, 0);\n }\n\n /**\n * Proceed to scopes step\n */\n public goToScopes(): void {\n if (!this.Label.trim()) {\n this.Error = 'Please enter a label for the API key';\n return;\n }\n this.Error = '';\n this.Step = 'scopes';\n }\n\n /**\n * Go back to configure step\n */\n public goBack(): void {\n this.Step = 'configure';\n }\n\n /**\n * Create the API key using server-side cryptographic hashing\n */\n public async createKey(): Promise<void> {\n this.IsCreating = true;\n this.Error = '';\n\n try {\n // Get selected scope IDs\n const selectedScopeIds = this.ScopeCategories\n .flatMap(cat => cat.scopes)\n .filter(s => s.selected)\n .map(s => s.scope.ID);\n\n // Get the GraphQL provider and create the encryption client\n const provider = Metadata.Provider as GraphQLDataProvider;\n const encryptionClient = new GraphQLEncryptionClient(provider);\n\n // Call the server to create the API key with proper crypto hashing\n const result = await encryptionClient.CreateAPIKey({\n Label: this.Label.trim(),\n Description: this.Description.trim() || undefined,\n ExpiresAt: this.NeverExpires ? undefined : (this.ExpiresAt || undefined),\n ScopeIDs: selectedScopeIds.length > 0 ? selectedScopeIds : undefined\n });\n\n if (result.Success && result.RawKey) {\n this.RawApiKey = result.RawKey;\n this.Step = 'success';\n\n this.Created.emit({\n success: true,\n rawKey: result.RawKey\n });\n } else {\n this.Error = result.Error || 'Failed to create API key. Please try again.';\n }\n } catch (error) {\n console.error('Error creating API key:', error);\n this.Error = 'An error occurred while creating the API key.';\n } finally {\n this.IsCreating = false;\n }\n }\n\n /**\n * Copy the API key to clipboard\n */\n public async copyKey(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.RawApiKey);\n this.KeyCopied = true;\n setTimeout(() => this.KeyCopied = false, 3000);\n } catch (error) {\n console.error('Failed to copy key:', error);\n }\n }\n\n /**\n * Close the dialog\n */\n public close(): void {\n this.reset();\n this.Visible = false;\n this.VisibleChange.emit(false);\n this.Closed.emit();\n }\n\n /**\n * Reset form state\n */\n private reset(): void {\n this.Label = '';\n this.Description = '';\n this.ExpiresAt = null;\n this.NeverExpires = true;\n this.SelectedPreset = null;\n this.Step = 'configure';\n this.RawApiKey = '';\n this.KeyCopied = false;\n this.Error = '';\n\n // Reset scope selections\n for (const category of this.ScopeCategories) {\n category.expanded = false;\n category.allSelected = false;\n for (const scope of category.scopes) {\n scope.selected = false;\n }\n }\n }\n\n /**\n * Get minimum date for expiration (tomorrow)\n */\n public getMinDate(): Date {\n const tomorrow = new Date();\n tomorrow.setDate(tomorrow.getDate() + 1);\n return tomorrow;\n }\n}\n","<!-- Slide-out Backdrop -->\n@if (Visible) {\n <div class=\"slideout-backdrop\" (click)=\"Step !== 'success' ? close() : null\"></div>\n}\n\n<!-- Slide-out Panel -->\n<div class=\"slideout-panel\" [class.open]=\"Visible\">\n <!-- Header -->\n <div class=\"slideout-header\">\n <div class=\"slideout-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Generate New API Key</span>\n </div>\n @if (Step !== 'success') {\n <button class=\"slideout-close\" (click)=\"close()\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n\n <!-- Step Indicator -->\n @if (Step !== 'success') {\n <div class=\"step-indicator\">\n <div class=\"step\" [class.active]=\"Step === 'configure'\" [class.completed]=\"Step === 'scopes'\">\n <div class=\"step-number\">1</div>\n <div class=\"step-label\">Configure</div>\n </div>\n <div class=\"step-connector\" [class.active]=\"Step === 'scopes'\"></div>\n <div class=\"step\" [class.active]=\"Step === 'scopes'\">\n <div class=\"step-number\">2</div>\n <div class=\"step-label\">Permissions</div>\n </div>\n </div>\n }\n\n <div class=\"slideout-content\">\n <!-- Configure Step -->\n @if (Step === 'configure') {\n <div class=\"step-panel\">\n <div class=\"form-section\">\n <label class=\"form-label required\">Key Label</label>\n <input kendoTextBox [(ngModel)]=\"Label\"\n placeholder=\"e.g., ElevenLabs Integration, CI/CD Pipeline\"\n class=\"form-input\" />\n <div class=\"form-hint\">A memorable name to identify this key's purpose</div>\n </div>\n <div class=\"form-section\">\n <label class=\"form-label\">Description</label>\n <textarea kendoTextArea [(ngModel)]=\"Description\"\n placeholder=\"Optional notes about how this key will be used...\"\n [rows]=\"3\"\n class=\"form-textarea\"></textarea>\n </div>\n <div class=\"form-section\">\n <label class=\"form-label\">Expiration</label>\n <div class=\"expiration-options\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" kendoCheckBox\n [(ngModel)]=\"NeverExpires\"\n (change)=\"onNeverExpiresChange()\" />\n <span>Never expires</span>\n </label>\n @if (!NeverExpires) {\n <div class=\"preset-buttons\">\n @for (preset of ExpirationPresets; track preset) {\n <button\n class=\"preset-btn\"\n [class.active]=\"SelectedPreset === preset\"\n (click)=\"onPresetSelect(preset)\">\n {{preset.label}}\n </button>\n }\n </div>\n }\n @if (!NeverExpires && SelectedPreset?.days === -1) {\n <div class=\"custom-date\">\n <kendo-datepicker [(ngModel)]=\"ExpiresAt\"\n [min]=\"getMinDate()\"\n format=\"MMM d, yyyy\"\n placeholder=\"Select expiration date\">\n </kendo-datepicker>\n </div>\n }\n @if (!NeverExpires && ExpiresAt) {\n <div class=\"expiration-preview\">\n <i class=\"fa-solid fa-calendar-check\"></i>\n <span>Key will expire on {{ExpiresAt | date:'MMMM d, yyyy'}}</span>\n </div>\n }\n </div>\n </div>\n @if (Error) {\n <div class=\"error-message\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{Error}}\n </div>\n }\n </div>\n }\n\n <!-- Scopes Step -->\n @if (Step === 'scopes') {\n <div class=\"step-panel scopes-step\">\n <div class=\"scopes-header\">\n <div class=\"scopes-info\">\n <h4>Select Permission Scopes</h4>\n <p>Choose what this API key can access. You can always modify this later.</p>\n </div>\n @if (getSelectedScopeCount() > 0) {\n <div class=\"scopes-count\">\n <span class=\"count\">{{getSelectedScopeCount()}}</span> selected\n </div>\n }\n </div>\n @if (IsLoadingScopes) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n @if (!IsLoadingScopes) {\n <div class=\"scope-categories\">\n @for (category of ScopeCategories; track category) {\n <div class=\"scope-category\">\n <div class=\"category-header\" (click)=\"toggleCategory(category)\">\n <div class=\"category-left\">\n <i [class]=\"category.icon\" [style.color]=\"category.color\"></i>\n <span class=\"category-name\">{{category.name}}</span>\n <span class=\"category-badge\">{{category.scopes.length}}</span>\n </div>\n <div class=\"category-right\">\n <label class=\"select-all-label\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" kendoCheckBox\n [checked]=\"category.allSelected\"\n (change)=\"toggleCategoryAll(category)\" />\n <span>All</span>\n </label>\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!category.expanded\"\n [class.fa-chevron-up]=\"category.expanded\"></i>\n </div>\n </div>\n @if (category.expanded) {\n <div class=\"category-scopes\">\n @for (item of category.scopes; track item) {\n <div class=\"scope-item\">\n <label class=\"scope-label\">\n <input type=\"checkbox\" kendoCheckBox\n [(ngModel)]=\"item.selected\"\n (change)=\"updateCategoryState(category)\" />\n <div class=\"scope-info\">\n <span class=\"scope-name\">{{item.scope.Name}}</span>\n @if (item.scope.Description) {\n <span class=\"scope-desc\">\n {{item.scope.Description}}\n </span>\n }\n </div>\n </label>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <div class=\"scope-tip\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Tip: Use wildcards like <code>entities:*</code> for broad access within a category</span>\n </div>\n <!-- No Scopes Warning -->\n @if (!IsLoadingScopes && getSelectedScopeCount() === 0) {\n <div class=\"no-scopes-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div>\n <strong>Warning: No permissions selected</strong>\n <p>API keys without any assigned scopes will have <strong>no permissions</strong> and cannot perform any operations. This key will be rejected by all API endpoints until scopes are assigned.</p>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Success Step -->\n @if (Step === 'success') {\n <div class=\"step-panel success-step\">\n <div class=\"success-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <h3 class=\"success-title\">API Key Created Successfully!</h3>\n <div class=\"key-display\">\n <div class=\"key-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>Copy this key now. It won't be shown again!</span>\n </div>\n <div class=\"key-value\">\n <code>{{RawApiKey}}</code>\n <button class=\"copy-btn\" (click)=\"copyKey()\" [class.copied]=\"KeyCopied\">\n <i class=\"fa-solid\" [class.fa-copy]=\"!KeyCopied\" [class.fa-check]=\"KeyCopied\"></i>\n <span>{{KeyCopied ? 'Copied!' : 'Copy'}}</span>\n </button>\n </div>\n </div>\n <div class=\"key-details\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Label:</span>\n <span class=\"detail-value\">{{Label}}</span>\n </div>\n @if (Description) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Description:</span>\n <span class=\"detail-value\">{{Description}}</span>\n </div>\n }\n <div class=\"detail-row\">\n <span class=\"detail-label\">Expires:</span>\n <span class=\"detail-value\">\n {{NeverExpires ? 'Never' : (ExpiresAt | date:'MMMM d, yyyy')}}\n </span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Scopes:</span>\n <span class=\"detail-value\">{{getSelectedScopeCount()}} permissions</span>\n </div>\n </div>\n <div class=\"security-note\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div>\n <strong>Security Note:</strong>\n Store this key securely. We only store a hash - the original key cannot be recovered.\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"slideout-footer\">\n @if (Step === 'configure') {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"goToScopes()\">\n Next: Permissions\n <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n <button kendoButton (click)=\"close()\">Cancel</button>\n }\n\n @if (Step === 'scopes') {\n <button kendoButton [themeColor]=\"'primary'\"\n [disabled]=\"IsCreating\"\n (click)=\"createKey()\">\n @if (IsCreating) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsCreating) {\n <span>\n <i class=\"fa-solid fa-key\"></i>\n Generate Key\n </span>\n }\n </button>\n <button kendoButton (click)=\"goBack()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back\n </button>\n }\n\n @if (Step === 'success') {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"close()\">\n <i class=\"fa-solid fa-check\"></i>\n Done\n </button>\n }\n </div>\n</div>\n"]}
1
+ {"version":3,"file":"api-key-create-dialog.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-key-create-dialog.component.ts","../../src/APIKeys/api-key-create-dialog.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, HostListener, Input, OnInit, Output } from '@angular/core';\nimport { Metadata } from '@memberjunction/core';\nimport { MJAPIScopeEntity } from '@memberjunction/core-entities';\nimport { GraphQLDataProvider, GraphQLEncryptionClient } from '@memberjunction/graphql-dataprovider';\nimport { APIKeysEngineBase, parseAPIScopeUIConfig } from '@memberjunction/api-keys-base';\n\n/** Scope selection item */\ninterface ScopeItem {\n scope: MJAPIScopeEntity;\n selected: boolean;\n}\n\n/** Grouped scopes by category */\ninterface ScopeCategory {\n name: string;\n icon: string;\n color: string;\n scopes: ScopeItem[];\n expanded: boolean;\n allSelected: boolean;\n}\n\n/** Result of key creation */\nexport interface APIKeyCreateResult {\n success: boolean;\n apiKeyId?: string;\n rawKey?: string;\n error?: string;\n}\n/**\n * Dialog for creating new API keys\n * Shows the raw key only once - it cannot be recovered after closing\n */\n@Component({\n standalone: false,\n selector: 'mj-api-key-create-dialog',\n templateUrl: './api-key-create-dialog.component.html',\n styleUrls: ['./api-key-create-dialog.component.css']\n})\nexport class APIKeyCreateDialogComponent implements OnInit {\n @Input() Visible = false;\n @Output() VisibleChange = new EventEmitter<boolean>();\n @Output() Created = new EventEmitter<APIKeyCreateResult>();\n @Output() Closed = new EventEmitter<void>();\n\n // Form fields\n public Label = '';\n public Description = '';\n public ExpiresAt: Date | null = null;\n public NeverExpires = true;\n\n // Expiration presets\n public ExpirationPresets = [\n { label: '30 days', days: 30 },\n { label: '90 days', days: 90 },\n { label: '1 year', days: 365 },\n { label: 'Custom', days: -1 }\n ];\n public SelectedPreset: { label: string; days: number } | null = null;\n\n // Scopes\n public ScopeCategories: ScopeCategory[] = [];\n public IsLoadingScopes = true;\n\n // State\n public IsCreating = false;\n public Step: 'configure' | 'scopes' | 'success' = 'configure';\n public RawApiKey = '';\n public KeyCopied = false;\n public Error = '';\n\n // Default UI config for categories without explicit configuration\n private readonly defaultUIConfig = {\n icon: 'fa-solid fa-ellipsis',\n color: 'var(--mj-text-muted)'\n };\n\n ngOnInit(): void {\n this.loadScopes();\n }\n\n /**\n * Handle escape key to close dialog\n */\n @HostListener('document:keydown.escape')\n public onEscapeKey(): void {\n if (this.Visible && !this.IsCreating) {\n this.close();\n }\n }\n\n /**\n * Load available scopes from cached data.\n * Uses UIConfig from root scopes for category icons/colors.\n */\n private loadScopes(): void {\n this.IsLoadingScopes = true;\n try {\n const base = APIKeysEngineBase.Instance;\n const scopes = base.Scopes;\n\n // Build a map of category -> root scope UIConfig\n // Root scopes (ParentID is null) define the UI appearance for their category\n const categoryUIConfigs = new Map<string, { icon: string; color: string }>();\n for (const scope of scopes) {\n if (!scope.ParentID) {\n // This is a root scope - use its UIConfig for the category\n const uiConfig = parseAPIScopeUIConfig(scope);\n categoryUIConfigs.set(scope.Category, {\n icon: uiConfig.icon || this.defaultUIConfig.icon,\n color: uiConfig.color || this.defaultUIConfig.color\n });\n }\n }\n\n // Group scopes by category\n const categoryMap = new Map<string, ScopeItem[]>();\n for (const scope of scopes) {\n const category = scope.Category || 'Other';\n if (!categoryMap.has(category)) {\n categoryMap.set(category, []);\n }\n categoryMap.get(category)!.push({\n scope,\n selected: false\n });\n }\n\n // Build categories with UI config from root scopes\n this.ScopeCategories = Array.from(categoryMap.entries())\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([name, scopeItems]) => {\n const config = categoryUIConfigs.get(name) || this.defaultUIConfig;\n return {\n name,\n icon: config.icon,\n color: config.color,\n scopes: scopeItems.sort((a, b) => a.scope.Name.localeCompare(b.scope.Name)),\n expanded: false,\n allSelected: false\n };\n });\n } catch (error) {\n console.error('Error loading scopes:', error);\n } finally {\n this.IsLoadingScopes = false;\n }\n }\n\n /**\n * Handle expiration preset selection\n */\n public onPresetSelect(preset: { label: string; days: number }): void {\n this.SelectedPreset = preset;\n this.NeverExpires = false;\n\n if (preset.days > 0) {\n const date = new Date();\n date.setDate(date.getDate() + preset.days);\n this.ExpiresAt = date;\n } else {\n this.ExpiresAt = null;\n }\n }\n\n /**\n * Handle never expires toggle\n */\n public onNeverExpiresChange(): void {\n if (this.NeverExpires) {\n this.ExpiresAt = null;\n this.SelectedPreset = null;\n }\n }\n\n /**\n * Toggle category expansion\n */\n public toggleCategory(category: ScopeCategory): void {\n category.expanded = !category.expanded;\n }\n\n /**\n * Toggle all scopes in a category\n */\n public toggleCategoryAll(category: ScopeCategory): void {\n category.allSelected = !category.allSelected;\n for (const item of category.scopes) {\n item.selected = category.allSelected;\n }\n }\n\n /**\n * Update category allSelected state\n */\n public updateCategoryState(category: ScopeCategory): void {\n category.allSelected = category.scopes.every(s => s.selected);\n }\n\n /**\n * Get selected scope count\n */\n public getSelectedScopeCount(): number {\n return this.ScopeCategories.reduce((sum, cat) =>\n sum + cat.scopes.filter(s => s.selected).length, 0);\n }\n\n /**\n * Proceed to scopes step\n */\n public goToScopes(): void {\n if (!this.Label.trim()) {\n this.Error = 'Please enter a label for the API key';\n return;\n }\n this.Error = '';\n this.Step = 'scopes';\n }\n\n /**\n * Go back to configure step\n */\n public goBack(): void {\n this.Step = 'configure';\n }\n\n /**\n * Create the API key using server-side cryptographic hashing\n */\n public async createKey(): Promise<void> {\n this.IsCreating = true;\n this.Error = '';\n\n try {\n // Get selected scope IDs\n const selectedScopeIds = this.ScopeCategories\n .flatMap(cat => cat.scopes)\n .filter(s => s.selected)\n .map(s => s.scope.ID);\n\n // Get the GraphQL provider and create the encryption client\n const provider = Metadata.Provider as GraphQLDataProvider;\n const encryptionClient = new GraphQLEncryptionClient(provider);\n\n // Call the server to create the API key with proper crypto hashing\n const result = await encryptionClient.CreateAPIKey({\n Label: this.Label.trim(),\n Description: this.Description.trim() || undefined,\n ExpiresAt: this.NeverExpires ? undefined : (this.ExpiresAt || undefined),\n ScopeIDs: selectedScopeIds.length > 0 ? selectedScopeIds : undefined\n });\n\n if (result.Success && result.RawKey) {\n this.RawApiKey = result.RawKey;\n this.Step = 'success';\n\n this.Created.emit({\n success: true,\n rawKey: result.RawKey\n });\n } else {\n this.Error = result.Error || 'Failed to create API key. Please try again.';\n }\n } catch (error) {\n console.error('Error creating API key:', error);\n this.Error = 'An error occurred while creating the API key.';\n } finally {\n this.IsCreating = false;\n }\n }\n\n /**\n * Copy the API key to clipboard\n */\n public async copyKey(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.RawApiKey);\n this.KeyCopied = true;\n setTimeout(() => this.KeyCopied = false, 3000);\n } catch (error) {\n console.error('Failed to copy key:', error);\n }\n }\n\n /**\n * Close the dialog\n */\n public close(): void {\n this.reset();\n this.Visible = false;\n this.VisibleChange.emit(false);\n this.Closed.emit();\n }\n\n /**\n * Reset form state\n */\n private reset(): void {\n this.Label = '';\n this.Description = '';\n this.ExpiresAt = null;\n this.NeverExpires = true;\n this.SelectedPreset = null;\n this.Step = 'configure';\n this.RawApiKey = '';\n this.KeyCopied = false;\n this.Error = '';\n\n // Reset scope selections\n for (const category of this.ScopeCategories) {\n category.expanded = false;\n category.allSelected = false;\n for (const scope of category.scopes) {\n scope.selected = false;\n }\n }\n }\n\n /**\n * Get minimum date for expiration (tomorrow)\n */\n public getMinDate(): Date {\n const tomorrow = new Date();\n tomorrow.setDate(tomorrow.getDate() + 1);\n return tomorrow;\n }\n}\n","<!-- Slide-out Backdrop -->\n@if (Visible) {\n <div class=\"slideout-backdrop\" (click)=\"Step !== 'success' ? close() : null\"></div>\n}\n\n<!-- Slide-out Panel -->\n<div class=\"slideout-panel\" [class.open]=\"Visible\">\n <!-- Header -->\n <div class=\"slideout-header\">\n <div class=\"slideout-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Generate New API Key</span>\n </div>\n @if (Step !== 'success') {\n <button class=\"slideout-close\" (click)=\"close()\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n\n <!-- Step Indicator -->\n @if (Step !== 'success') {\n <div class=\"step-indicator\">\n <div class=\"step\" [class.active]=\"Step === 'configure'\" [class.completed]=\"Step === 'scopes'\">\n <div class=\"step-number\">1</div>\n <div class=\"step-label\">Configure</div>\n </div>\n <div class=\"step-connector\" [class.active]=\"Step === 'scopes'\"></div>\n <div class=\"step\" [class.active]=\"Step === 'scopes'\">\n <div class=\"step-number\">2</div>\n <div class=\"step-label\">Permissions</div>\n </div>\n </div>\n }\n\n <div class=\"slideout-content\">\n <!-- Configure Step -->\n @if (Step === 'configure') {\n <div class=\"step-panel\">\n <div class=\"form-section\">\n <label class=\"form-label required\">Key Label</label>\n <input class=\"mj-input form-input\" [(ngModel)]=\"Label\"\n placeholder=\"e.g., ElevenLabs Integration, CI/CD Pipeline\" />\n <div class=\"form-hint\">A memorable name to identify this key's purpose</div>\n </div>\n <div class=\"form-section\">\n <label class=\"form-label\">Description</label>\n <textarea class=\"mj-textarea form-textarea\" [(ngModel)]=\"Description\"\n placeholder=\"Optional notes about how this key will be used...\"\n [rows]=\"3\"></textarea>\n </div>\n <div class=\"form-section\">\n <label class=\"form-label\">Expiration</label>\n <div class=\"expiration-options\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" class=\"mj-checkbox\"\n [(ngModel)]=\"NeverExpires\"\n (change)=\"onNeverExpiresChange()\" />\n <span>Never expires</span>\n </label>\n @if (!NeverExpires) {\n <div class=\"preset-buttons\">\n @for (preset of ExpirationPresets; track preset) {\n <button\n class=\"preset-btn\"\n [class.active]=\"SelectedPreset === preset\"\n (click)=\"onPresetSelect(preset)\">\n {{preset.label}}\n </button>\n }\n </div>\n }\n @if (!NeverExpires && SelectedPreset?.days === -1) {\n <div class=\"custom-date\">\n <mj-datepicker [(ngModel)]=\"ExpiresAt\"\n [Min]=\"getMinDate()\"\n Format=\"MMM d, yyyy\"\n Placeholder=\"Select expiration date\">\n </mj-datepicker>\n </div>\n }\n @if (!NeverExpires && ExpiresAt) {\n <div class=\"expiration-preview\">\n <i class=\"fa-solid fa-calendar-check\"></i>\n <span>Key will expire on {{ExpiresAt | date:'MMMM d, yyyy'}}</span>\n </div>\n }\n </div>\n </div>\n @if (Error) {\n <div class=\"error-message\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{Error}}\n </div>\n }\n </div>\n }\n\n <!-- Scopes Step -->\n @if (Step === 'scopes') {\n <div class=\"step-panel scopes-step\">\n <div class=\"scopes-header\">\n <div class=\"scopes-info\">\n <h4>Select Permission Scopes</h4>\n <p>Choose what this API key can access. You can always modify this later.</p>\n </div>\n @if (getSelectedScopeCount() > 0) {\n <div class=\"scopes-count\">\n <span class=\"count\">{{getSelectedScopeCount()}}</span> selected\n </div>\n }\n </div>\n @if (IsLoadingScopes) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n @if (!IsLoadingScopes) {\n <div class=\"scope-categories\">\n @for (category of ScopeCategories; track category) {\n <div class=\"scope-category\">\n <div class=\"category-header\" (click)=\"toggleCategory(category)\">\n <div class=\"category-left\">\n <i [class]=\"category.icon\" [style.color]=\"category.color\"></i>\n <span class=\"category-name\">{{category.name}}</span>\n <span class=\"category-badge\">{{category.scopes.length}}</span>\n </div>\n <div class=\"category-right\">\n <label class=\"select-all-label\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" class=\"mj-checkbox\"\n [checked]=\"category.allSelected\"\n (change)=\"toggleCategoryAll(category)\" />\n <span>All</span>\n </label>\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!category.expanded\"\n [class.fa-chevron-up]=\"category.expanded\"></i>\n </div>\n </div>\n @if (category.expanded) {\n <div class=\"category-scopes\">\n @for (item of category.scopes; track item) {\n <div class=\"scope-item\">\n <label class=\"scope-label\">\n <input type=\"checkbox\" class=\"mj-checkbox\"\n [(ngModel)]=\"item.selected\"\n (change)=\"updateCategoryState(category)\" />\n <div class=\"scope-info\">\n <span class=\"scope-name\">{{item.scope.Name}}</span>\n @if (item.scope.Description) {\n <span class=\"scope-desc\">\n {{item.scope.Description}}\n </span>\n }\n </div>\n </label>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <div class=\"scope-tip\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Tip: Use wildcards like <code>entities:*</code> for broad access within a category</span>\n </div>\n <!-- No Scopes Warning -->\n @if (!IsLoadingScopes && getSelectedScopeCount() === 0) {\n <div class=\"no-scopes-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div>\n <strong>Warning: No permissions selected</strong>\n <p>API keys without any assigned scopes will have <strong>no permissions</strong> and cannot perform any operations. This key will be rejected by all API endpoints until scopes are assigned.</p>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Success Step -->\n @if (Step === 'success') {\n <div class=\"step-panel success-step\">\n <div class=\"success-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <h3 class=\"success-title\">API Key Created Successfully!</h3>\n <div class=\"key-display\">\n <div class=\"key-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>Copy this key now. It won't be shown again!</span>\n </div>\n <div class=\"key-value\">\n <code>{{RawApiKey}}</code>\n <button class=\"copy-btn\" (click)=\"copyKey()\" [class.copied]=\"KeyCopied\">\n <i class=\"fa-solid\" [class.fa-copy]=\"!KeyCopied\" [class.fa-check]=\"KeyCopied\"></i>\n <span>{{KeyCopied ? 'Copied!' : 'Copy'}}</span>\n </button>\n </div>\n </div>\n <div class=\"key-details\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Label:</span>\n <span class=\"detail-value\">{{Label}}</span>\n </div>\n @if (Description) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Description:</span>\n <span class=\"detail-value\">{{Description}}</span>\n </div>\n }\n <div class=\"detail-row\">\n <span class=\"detail-label\">Expires:</span>\n <span class=\"detail-value\">\n {{NeverExpires ? 'Never' : (ExpiresAt | date:'MMMM d, yyyy')}}\n </span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Scopes:</span>\n <span class=\"detail-value\">{{getSelectedScopeCount()}} permissions</span>\n </div>\n </div>\n <div class=\"security-note\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div>\n <strong>Security Note:</strong>\n Store this key securely. We only store a hash - the original key cannot be recovered.\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"slideout-footer\">\n @if (Step === 'configure') {\n <button mjButton variant=\"primary\" (click)=\"goToScopes()\">\n Next: Permissions\n <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n <button mjButton (click)=\"close()\">Cancel</button>\n }\n\n @if (Step === 'scopes') {\n <button mjButton variant=\"primary\"\n [disabled]=\"IsCreating\"\n (click)=\"createKey()\">\n @if (IsCreating) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsCreating) {\n <span>\n <i class=\"fa-solid fa-key\"></i>\n Generate Key\n </span>\n }\n </button>\n <button mjButton (click)=\"goBack()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back\n </button>\n }\n\n @if (Step === 'success') {\n <button mjButton variant=\"primary\" (click)=\"close()\">\n <i class=\"fa-solid fa-check\"></i>\n Done\n </button>\n }\n </div>\n</div>\n"]}