@memberjunction/ng-dashboards 5.22.0 → 5.24.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.
- package/README.md +51 -0
- package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +364 -362
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +2 -2
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +947 -64
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +7645 -430
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +285 -6
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +2454 -277
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +191 -197
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +9 -8
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +305 -299
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +319 -313
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +20 -2
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +419 -232
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +10 -12
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.js +13 -19
- package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js +12 -14
- package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +61 -68
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
- package/dist/APIKeys/api-usage-panel.component.js +10 -11
- package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
- package/dist/Actions/components/actions-list-view.component.js +82 -96
- package/dist/Actions/components/actions-list-view.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +130 -134
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +40 -46
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/code-management.component.js +2 -2
- package/dist/Actions/components/code-management.component.js.map +1 -1
- package/dist/Actions/components/entity-integration.component.js +2 -2
- package/dist/Actions/components/entity-integration.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +127 -132
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/executions-list-view.component.js +2 -2
- package/dist/Actions/components/executions-list-view.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.js +11 -17
- package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +5 -11
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-list-item.component.js +8 -10
- package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-toolbar.component.js +112 -133
- package/dist/Actions/components/explorer/action-toolbar.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-tree-panel.component.js +63 -83
- package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js +17 -21
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +17 -21
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Actions/components/scheduled-actions.component.js +2 -2
- package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
- package/dist/Actions/components/security-permissions.component.js +2 -2
- package/dist/Actions/components/security-permissions.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts +13 -5
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +168 -145
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +4 -5
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +197 -200
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +5 -7
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +142 -148
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/browser/component-browser.component.js +153 -166
- package/dist/ComponentStudio/components/browser/component-browser.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +15 -20
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +16 -21
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js +18 -23
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/spec-editor.component.js +25 -30
- package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +10 -11
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +24 -35
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/text-import-dialog.component.js +15 -17
- package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +7 -6
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +6 -5
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +7 -6
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +9 -9
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +17 -17
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +4 -4
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +1 -0
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +5 -4
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.d.ts.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +247 -259
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.d.ts.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +1 -0
- package/dist/Integration/components/overview/overview.component.js.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.d.ts.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.js +1 -0
- package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.d.ts.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.js +1 -0
- package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
- package/dist/Integration/components/widgets/integration-card.component.js +7 -9
- package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
- package/dist/Integration/integration.module.d.ts +6 -10
- package/dist/Integration/integration.module.d.ts.map +1 -1
- package/dist/Integration/integration.module.js +12 -20
- package/dist/Integration/integration.module.js.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts +411 -0
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +4266 -0
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +140 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +780 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +8 -2
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +246 -195
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.d.ts +75 -0
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +601 -0
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts +93 -12
- package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js +637 -107
- package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/index.d.ts +3 -0
- package/dist/KnowledgeHub/index.d.ts.map +1 -1
- package/dist/KnowledgeHub/index.js +3 -0
- package/dist/KnowledgeHub/index.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +9 -7
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +5 -4
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +10 -9
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +141 -132
- package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-log-detail-panel.component.js +4 -4
- package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +141 -128
- package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +210 -218
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +2 -2
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/MCP/mcp.module.d.ts +6 -9
- package/dist/MCP/mcp.module.d.ts.map +1 -1
- package/dist/MCP/mcp.module.js +20 -22
- package/dist/MCP/mcp.module.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +5 -4
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +6 -5
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +93 -92
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +9 -10
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/__tests__/analytics-resource.test.d.ts +2 -0
- package/dist/__tests__/analytics-resource.test.d.ts.map +1 -0
- package/dist/__tests__/analytics-resource.test.js +181 -0
- package/dist/__tests__/analytics-resource.test.js.map +1 -0
- package/dist/__tests__/scheduling.test.d.ts +2 -0
- package/dist/__tests__/scheduling.test.d.ts.map +1 -0
- package/dist/__tests__/scheduling.test.js +205 -0
- package/dist/__tests__/scheduling.test.js.map +1 -0
- package/dist/actions-dashboards.module.d.ts +8 -13
- package/dist/actions-dashboards.module.d.ts.map +1 -1
- package/dist/actions-dashboards.module.js +6 -27
- package/dist/actions-dashboards.module.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +20 -20
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +43 -44
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +4 -8
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +0 -19
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/component-studio-dashboards.module.d.ts +7 -11
- package/dist/component-studio-dashboards.module.d.ts.map +1 -1
- package/dist/component-studio-dashboards.module.js +22 -34
- package/dist/component-studio-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +12 -18
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +15 -31
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/credentials-dashboards.module.d.ts +5 -8
- package/dist/credentials-dashboards.module.d.ts.map +1 -1
- package/dist/credentials-dashboards.module.js +3 -19
- package/dist/credentials-dashboards.module.js.map +1 -1
- package/dist/data-explorer-dashboards.module.d.ts +7 -13
- package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
- package/dist/data-explorer-dashboards.module.js +0 -27
- package/dist/data-explorer-dashboards.module.js.map +1 -1
- package/dist/lists-dashboards.module.d.ts +5 -8
- package/dist/lists-dashboards.module.d.ts.map +1 -1
- package/dist/lists-dashboards.module.js +3 -19
- package/dist/lists-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/dist/scheduling-dashboards.module.d.ts +6 -10
- package/dist/scheduling-dashboards.module.d.ts.map +1 -1
- package/dist/scheduling-dashboards.module.js +3 -23
- package/dist/scheduling-dashboards.module.js.map +1 -1
- package/dist/shared/entity-field-display.d.ts +44 -0
- package/dist/shared/entity-field-display.d.ts.map +1 -0
- package/dist/shared/entity-field-display.js +118 -0
- package/dist/shared/entity-field-display.js.map +1 -0
- package/dist/testing-dashboards.module.d.ts +7 -13
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +0 -27
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +48 -55
|
@@ -5,10 +5,8 @@ import { APIKeysEngineBase, parseAPIScopeUIConfig } from '@memberjunction/api-ke
|
|
|
5
5
|
import * as i0 from "@angular/core";
|
|
6
6
|
import * as i1 from "@angular/common";
|
|
7
7
|
import * as i2 from "@angular/forms";
|
|
8
|
-
import * as i3 from "@
|
|
9
|
-
import * as i4 from "@
|
|
10
|
-
import * as i5 from "@progress/kendo-angular-dateinputs";
|
|
11
|
-
import * as i6 from "@memberjunction/ng-shared-generic";
|
|
8
|
+
import * as i3 from "@memberjunction/ng-ui-components";
|
|
9
|
+
import * as i4 from "@memberjunction/ng-shared-generic";
|
|
12
10
|
function APIKeyEditPanelComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
13
11
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
14
12
|
i0.ɵɵelementStart(0, "div", 9);
|
|
@@ -86,7 +84,7 @@ function APIKeyEditPanelComponent_Conditional_12_Conditional_14_Conditional_48_T
|
|
|
86
84
|
} if (rf & 2) {
|
|
87
85
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
88
86
|
i0.ɵɵadvance();
|
|
89
|
-
i0.ɵɵproperty("
|
|
87
|
+
i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
|
|
90
88
|
i0.ɵɵadvance();
|
|
91
89
|
i0.ɵɵconditional(ctx_r1.IsSaving ? 2 : -1);
|
|
92
90
|
i0.ɵɵadvance();
|
|
@@ -235,12 +233,12 @@ function APIKeyEditPanelComponent_Conditional_12_Conditional_14_Template(rf, ctx
|
|
|
235
233
|
i0.ɵɵelementStart(42, "div", 37)(43, "label");
|
|
236
234
|
i0.ɵɵtext(44, "Expiration");
|
|
237
235
|
i0.ɵɵelementEnd();
|
|
238
|
-
i0.ɵɵelementStart(45, "div", 40)(46, "
|
|
239
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
236
|
+
i0.ɵɵelementStart(45, "div", 40)(46, "mj-datepicker", 41);
|
|
237
|
+
i0.ɵɵtwoWayListener("ngModelChange", function APIKeyEditPanelComponent_Conditional_12_Conditional_14_Template_mj_datepicker_ngModelChange_46_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.EditExpiresAt, $event) || (ctx_r1.EditExpiresAt = $event); return i0.ɵɵresetView($event); });
|
|
240
238
|
i0.ɵɵelementEnd();
|
|
241
239
|
i0.ɵɵconditionalCreate(47, APIKeyEditPanelComponent_Conditional_12_Conditional_14_Conditional_47_Template, 3, 0, "button", 42);
|
|
242
240
|
i0.ɵɵelementEnd()();
|
|
243
|
-
i0.ɵɵconditionalCreate(48, APIKeyEditPanelComponent_Conditional_12_Conditional_14_Conditional_48_Template, 4,
|
|
241
|
+
i0.ɵɵconditionalCreate(48, APIKeyEditPanelComponent_Conditional_12_Conditional_14_Conditional_48_Template, 4, 3, "div", 43);
|
|
244
242
|
i0.ɵɵelementEnd();
|
|
245
243
|
i0.ɵɵconditionalCreate(49, APIKeyEditPanelComponent_Conditional_12_Conditional_14_Conditional_49_Template, 5, 2, "div", 44);
|
|
246
244
|
i0.ɵɵconditionalCreate(50, APIKeyEditPanelComponent_Conditional_12_Conditional_14_Conditional_50_Template, 7, 0, "div", 45);
|
|
@@ -269,7 +267,7 @@ function APIKeyEditPanelComponent_Conditional_12_Conditional_14_Template(rf, ctx
|
|
|
269
267
|
i0.ɵɵproperty("disabled", !ctx_r1.IsEditing)("rows", 3);
|
|
270
268
|
i0.ɵɵadvance(5);
|
|
271
269
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditExpiresAt);
|
|
272
|
-
i0.ɵɵproperty("
|
|
270
|
+
i0.ɵɵproperty("Disabled", !ctx_r1.IsEditing)("Min", ctx_r1.getMinDate());
|
|
273
271
|
i0.ɵɵadvance();
|
|
274
272
|
i0.ɵɵconditional(ctx_r1.IsEditing && ctx_r1.EditExpiresAt ? 47 : -1);
|
|
275
273
|
i0.ɵɵadvance();
|
|
@@ -299,7 +297,7 @@ function APIKeyEditPanelComponent_Conditional_12_Conditional_15_Conditional_5_Te
|
|
|
299
297
|
i0.ɵɵelementEnd();
|
|
300
298
|
} if (rf & 2) {
|
|
301
299
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
302
|
-
i0.ɵɵproperty("
|
|
300
|
+
i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
|
|
303
301
|
i0.ɵɵadvance();
|
|
304
302
|
i0.ɵɵconditional(ctx_r1.IsSaving ? 1 : -1);
|
|
305
303
|
i0.ɵɵadvance();
|
|
@@ -421,7 +419,7 @@ function APIKeyEditPanelComponent_Conditional_12_Conditional_15_Template(rf, ctx
|
|
|
421
419
|
i0.ɵɵelementStart(0, "div", 20)(1, "div", 64)(2, "div", 65)(3, "span", 66);
|
|
422
420
|
i0.ɵɵtext(4);
|
|
423
421
|
i0.ɵɵelementEnd()();
|
|
424
|
-
i0.ɵɵconditionalCreate(5, APIKeyEditPanelComponent_Conditional_12_Conditional_15_Conditional_5_Template, 3,
|
|
422
|
+
i0.ɵɵconditionalCreate(5, APIKeyEditPanelComponent_Conditional_12_Conditional_15_Conditional_5_Template, 3, 3, "button", 67);
|
|
425
423
|
i0.ɵɵelementEnd();
|
|
426
424
|
i0.ɵɵconditionalCreate(6, APIKeyEditPanelComponent_Conditional_12_Conditional_15_Conditional_6_Template, 7, 0, "div", 68);
|
|
427
425
|
i0.ɵɵconditionalCreate(7, APIKeyEditPanelComponent_Conditional_12_Conditional_15_Conditional_7_Template, 1, 0, "mj-loading", 69);
|
|
@@ -1026,7 +1024,7 @@ export class APIKeyEditPanelComponent {
|
|
|
1026
1024
|
static ɵfac = function APIKeyEditPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || APIKeyEditPanelComponent)(); };
|
|
1027
1025
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: APIKeyEditPanelComponent, selectors: [["mj-api-key-edit-panel"]], hostBindings: function APIKeyEditPanelComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
1028
1026
|
i0.ɵɵlistener("keydown.escape", function APIKeyEditPanelComponent_keydown_escape_HostBindingHandler() { return ctx.onEscapeKey(); }, i0.ɵɵresolveDocument);
|
|
1029
|
-
} }, inputs: { Visible: "Visible", KeyId: "KeyId" }, outputs: { VisibleChange: "VisibleChange", Updated: "Updated", Revoked: "Revoked", Closed: "Closed" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 13, vars: 10, consts: [[1, "slideout-backdrop"], [1, "slideout-panel"], [1, "slideout-header"], [1, "slideout-title"], [1, "fa-solid", "fa-key"], [1, "key-status"], ["title", "Close (Esc)", 1, "slideout-close", 3, "click"], [1, "fa-solid", "fa-times"], ["text", "Loading key details..."], [1, "slideout-backdrop", 3, "click"], [1, "message", "success"], [1, "message", "error"], [1, "slideout-tabs"], [1, "slideout-tab", 3, "click"], [1, "fa-solid", "fa-info-circle"], [1, "fa-solid", "fa-shield-halved"], [1, "tab-badge", "unsaved"], [1, "fa-solid", "fa-chart-line"], [1, "slideout-content"], [1, "tab-panel"], [1, "tab-panel", "scopes-panel"], [1, "tab-panel", "usage-panel"], [1, "slideout-footer"], ["
|
|
1027
|
+
} }, inputs: { Visible: "Visible", KeyId: "KeyId" }, outputs: { VisibleChange: "VisibleChange", Updated: "Updated", Revoked: "Revoked", Closed: "Closed" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 13, vars: 10, consts: [[1, "slideout-backdrop"], [1, "slideout-panel"], [1, "slideout-header"], [1, "slideout-title"], [1, "fa-solid", "fa-key"], [1, "key-status"], ["title", "Close (Esc)", 1, "slideout-close", 3, "click"], [1, "fa-solid", "fa-times"], ["text", "Loading key details..."], [1, "slideout-backdrop", 3, "click"], [1, "message", "success"], [1, "message", "error"], [1, "slideout-tabs"], [1, "slideout-tab", 3, "click"], [1, "fa-solid", "fa-info-circle"], [1, "fa-solid", "fa-shield-halved"], [1, "tab-badge", "unsaved"], [1, "fa-solid", "fa-chart-line"], [1, "slideout-content"], [1, "tab-panel"], [1, "tab-panel", "scopes-panel"], [1, "tab-panel", "usage-panel"], [1, "slideout-footer"], ["mjButton", "", 3, "click"], [1, "fa-solid", "fa-check-circle"], [1, "fa-solid", "fa-circle-exclamation"], [1, "key-info-card"], [1, "info-header"], [1, "info-row"], [1, "info-label"], [1, "hash-value"], [1, "info-grid"], [1, "info-item"], [1, "info-value"], [1, "edit-section"], [1, "section-header"], [1, "edit-toggle"], [1, "form-field"], [1, "mj-input", "form-input", 3, "ngModelChange", "ngModel", "disabled"], [1, "mj-textarea", "form-textarea", 3, "ngModelChange", "ngModel", "disabled", "rows"], [1, "expiration-field"], ["Format", "MMM d, yyyy", "Placeholder", "Never expires", 3, "ngModelChange", "ngModel", "Disabled", "Min"], [1, "clear-btn"], [1, "edit-actions"], [1, "danger-zone"], [1, "revoked-notice"], [1, "edit-toggle", 3, "click"], [1, "fa-solid"], [1, "clear-btn", 3, "click"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], ["size", "small", 3, "showText"], [1, "fa-solid", "fa-save"], [1, "revoke-section"], [1, "revoke-confirm"], [1, "revoke-info"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "revoke-btn", 3, "click"], [1, "fa-solid", "fa-ban"], [1, "confirm-warning"], [1, "fa-solid", "fa-skull-crossbones"], [1, "confirm-input"], ["placeholder", "REVOKE", 1, "mj-input", 3, "ngModelChange", "ngModel"], [1, "confirm-actions"], [1, "confirm-revoke-btn", 3, "click", "disabled"], [1, "scopes-header"], [1, "scopes-info"], [1, "scope-count"], ["mjButton", "", "variant", "primary", 3, "disabled"], [1, "no-scopes-warning"], ["text", "Loading permissions..."], [1, "scope-categories"], [1, "scope-category"], [1, "category-header", 3, "click"], [1, "category-left"], [1, "category-name"], [1, "category-count"], [1, "category-right"], [1, "category-all-toggle"], [1, "fa-solid", "expand-icon"], [1, "category-scopes"], [1, "category-all-toggle", 3, "click"], ["type", "checkbox", 1, "mj-checkbox", 3, "change", "checked"], [1, "scope-item"], [1, "scope-label"], ["type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "change", "ngModel", "disabled"], [1, "scope-info"], [1, "scope-name"], [1, "scope-desc"], ["text", "Loading usage logs..."], [1, "usage-content"], [1, "usage-stats"], [1, "stat-card"], [1, "stat-value"], [1, "stat-label"], [1, "fa-solid", "fa-clock"], [1, "usage-logs"], [1, "empty-state"], [1, "log-header"], [1, "col-time"], [1, "col-endpoint"], [1, "col-status"], [1, "col-duration"], [1, "log-item"], [1, "method-badge"], [1, "col-status", 3, "ngClass"], [1, "fa-solid", "fa-chart-area"]], template: function APIKeyEditPanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1030
1028
|
i0.ɵɵconditionalCreate(0, APIKeyEditPanelComponent_Conditional_0_Template, 1, 0, "div", 0);
|
|
1031
1029
|
i0.ɵɵelementStart(1, "div", 1)(2, "div", 2)(3, "div", 3);
|
|
1032
1030
|
i0.ɵɵelement(4, "i", 4);
|
|
@@ -1055,11 +1053,11 @@ export class APIKeyEditPanelComponent {
|
|
|
1055
1053
|
i0.ɵɵconditional(ctx.IsLoading ? 11 : -1);
|
|
1056
1054
|
i0.ɵɵadvance();
|
|
1057
1055
|
i0.ɵɵconditional(!ctx.IsLoading && ctx.APIKey ? 12 : -1);
|
|
1058
|
-
} }, dependencies: [i1.NgClass, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.ButtonComponent, i4.TextBoxDirective, i4.TextAreaDirective, i4.CheckBoxDirective, i5.DatePickerComponent, i6.LoadingComponent], 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-brand-accent-subtle);\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.key-status[_ngcontent-%COMP%] {\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.key-status.active[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.key-status.revoked[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\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: var(--mj-bg-surface-hover);\n border: none;\n border-radius: 8px;\n color: var(--mj-text-secondary);\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-active);\n color: var(--mj-text-primary);\n}\n\n\n\n.slideout-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n padding: 12px 24px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.slideout-tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n}\n\n.slideout-tab[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.slideout-tab.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.slideout-tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 9px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.tab-badge.unsaved[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.slideout-tab[_ngcontent-%COMP%]:not(.active) .tab-badge[_ngcontent-%COMP%] {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n\n\n.slideout-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 0;\n}\n\n.tab-panel[_ngcontent-%COMP%] {\n padding: 20px 24px;\n}\n\n\n\n.slideout-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\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: 80px;\n padding: 8px 16px;\n font-weight: 500;\n border-radius: 6px;\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n margin: 12px 16px;\n border-radius: 8px;\n font-size: 14px;\n}\n\n.message.success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.message.error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n\n\n\n\n\n.key-info-card[_ngcontent-%COMP%] {\n background: var(--mj-brand-accent-subtle);\n border-radius: 10px;\n padding: 14px 16px;\n margin-bottom: 16px;\n}\n\n.info-header[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.info-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.hash-value[_ngcontent-%COMP%] {\n font-family: 'Fira Code', 'Consolas', monospace;\n font-size: 13px;\n color: var(--mj-text-primary);\n word-break: break-all;\n background: var(--mj-bg-surface);\n padding: 8px 12px;\n border-radius: 6px;\n}\n\n.info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 10px 16px;\n}\n\n.info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.info-value.never-used[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-style: italic;\n}\n\n\n\n.edit-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: 10px;\n padding: 16px;\n margin-bottom: 16px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 14px;\n}\n\n.section-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.edit-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\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.edit-toggle[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.form-field[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.form-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.form-input[_ngcontent-%COMP%], \n.form-textarea[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.expiration-field[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.clear-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: transparent;\n border: 1px dashed var(--mj-border-strong);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.clear-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.edit-actions[_ngcontent-%COMP%] {\n margin-top: 14px;\n padding-top: 14px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n\n\n.danger-zone[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n padding: 14px 16px;\n}\n\n.danger-zone[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.revoke-section[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n}\n\n.revoke-info[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n flex: 1;\n}\n\n.revoke-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-status-error);\n margin-top: 2px;\n}\n\n.revoke-info[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n color: var(--mj-status-error-text);\n margin-bottom: 4px;\n}\n\n.revoke-info[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.revoke-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-status-error);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-status-error);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.revoke-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n\n\n.revoke-confirm[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n border-radius: 8px;\n}\n\n.confirm-warning[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n margin-bottom: 20px;\n}\n\n.confirm-warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-status-error);\n}\n\n.confirm-warning[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n color: var(--mj-status-error-text);\n font-size: 16px;\n margin-bottom: 4px;\n}\n\n.confirm-warning[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.confirm-input[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.confirm-input[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-status-error-text);\n margin-bottom: 8px;\n}\n\n.confirm-input[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n.confirm-input[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.confirm-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.confirm-revoke-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-status-error);\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.confirm-revoke-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n}\n\n.confirm-revoke-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n.revoked-notice[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 20px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n}\n\n.revoked-notice[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-text-secondary);\n}\n\n.revoked-notice[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.revoked-notice[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.scopes-tab[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.scopes-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.scope-count[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\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-count[_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.category-all-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.category-all-toggle[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.category-all-toggle[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n.expand-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s ease;\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\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-primary);\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\n\n.usage-tab[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.usage-stats[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.stat-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background: var(--mj-brand-accent-subtle);\n border-radius: 12px;\n text-align: center;\n}\n\n.stat-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-brand-primary);\n margin-bottom: 12px;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-primary);\n margin-top: 4px;\n}\n\n\n\n.usage-logs[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.log-header[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 100px 1fr 80px 80px;\n gap: 12px;\n padding: 12px 16px;\n background: var(--mj-border-default);\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.log-item[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 100px 1fr 80px 80px;\n gap: 12px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 13px;\n align-items: center;\n}\n\n.log-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.col-time[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n.col-endpoint[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: monospace;\n color: var(--mj-text-primary);\n}\n\n.method-badge[_ngcontent-%COMP%] {\n padding: 2px 6px;\n background: var(--mj-status-info-bg);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-color-info-600);\n}\n\n.col-status[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.col-status.status-success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.col-status.status-warning[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.col-status.status-error[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.col-duration[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n text-align: right;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 8px 0 0 0;\n font-size: 13px;\n}\n\n\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}\n\n\n\n[_nghost-%COMP%] .edit-actions .k-button {\n min-width: 120px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n[_nghost-%COMP%] .edit-actions .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%] .edit-actions .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n\n\n[_nghost-%COMP%] .scopes-header .k-button {\n min-width: 120px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n[_nghost-%COMP%] .scopes-header .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%] .scopes-header .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\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: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n margin-bottom: 16px;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.no-scopes-warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-status-error);\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-text);\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}"] });
|
|
1056
|
+
} }, dependencies: [i1.NgClass, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.MJButtonDirective, i3.MJDatepickerComponent, i4.LoadingComponent], 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-brand-accent-subtle);\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.key-status[_ngcontent-%COMP%] {\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.key-status.active[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.key-status.revoked[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\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: var(--mj-bg-surface-hover);\n border: none;\n border-radius: 8px;\n color: var(--mj-text-secondary);\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-active);\n color: var(--mj-text-primary);\n}\n\n\n\n.slideout-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n padding: 12px 24px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.slideout-tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n}\n\n.slideout-tab[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.slideout-tab.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.slideout-tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 9px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.tab-badge.unsaved[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.slideout-tab[_ngcontent-%COMP%]:not(.active) .tab-badge[_ngcontent-%COMP%] {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n\n\n.slideout-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 0;\n}\n\n.tab-panel[_ngcontent-%COMP%] {\n padding: 20px 24px;\n}\n\n\n\n.slideout-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\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.slideout-footer[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n min-width: 80px;\n padding: 8px 16px;\n font-weight: 500;\n border-radius: 6px;\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n margin: 12px 16px;\n border-radius: 8px;\n font-size: 14px;\n}\n\n.message.success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.message.error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n\n\n\n\n\n.key-info-card[_ngcontent-%COMP%] {\n background: var(--mj-brand-accent-subtle);\n border-radius: 10px;\n padding: 14px 16px;\n margin-bottom: 16px;\n}\n\n.info-header[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.info-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.hash-value[_ngcontent-%COMP%] {\n font-family: 'Fira Code', 'Consolas', monospace;\n font-size: 13px;\n color: var(--mj-text-primary);\n word-break: break-all;\n background: var(--mj-bg-surface);\n padding: 8px 12px;\n border-radius: 6px;\n}\n\n.info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 10px 16px;\n}\n\n.info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.info-value.never-used[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-style: italic;\n}\n\n\n\n.edit-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: 10px;\n padding: 16px;\n margin-bottom: 16px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 14px;\n}\n\n.section-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.edit-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\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.edit-toggle[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.form-field[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.form-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.form-input[_ngcontent-%COMP%], \n.form-textarea[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.expiration-field[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.clear-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: transparent;\n border: 1px dashed var(--mj-border-strong);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.clear-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.edit-actions[_ngcontent-%COMP%] {\n margin-top: 14px;\n padding-top: 14px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n\n\n.danger-zone[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n padding: 14px 16px;\n}\n\n.danger-zone[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.revoke-section[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n}\n\n.revoke-info[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n flex: 1;\n}\n\n.revoke-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-status-error);\n margin-top: 2px;\n}\n\n.revoke-info[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n color: var(--mj-status-error-text);\n margin-bottom: 4px;\n}\n\n.revoke-info[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.revoke-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-status-error);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-status-error);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.revoke-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n\n\n.revoke-confirm[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n border-radius: 8px;\n}\n\n.confirm-warning[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n margin-bottom: 20px;\n}\n\n.confirm-warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-status-error);\n}\n\n.confirm-warning[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n color: var(--mj-status-error-text);\n font-size: 16px;\n margin-bottom: 4px;\n}\n\n.confirm-warning[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.confirm-input[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.confirm-input[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-status-error-text);\n margin-bottom: 8px;\n}\n\n.confirm-input[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n.confirm-input[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.confirm-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.confirm-revoke-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-status-error);\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.confirm-revoke-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n}\n\n.confirm-revoke-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n.revoked-notice[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 20px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n}\n\n.revoked-notice[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-text-secondary);\n}\n\n.revoked-notice[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n display: block;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.revoked-notice[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.scopes-tab[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.scopes-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.scope-count[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\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-count[_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.category-all-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.category-all-toggle[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.category-all-toggle[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n.expand-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s ease;\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\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-primary);\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\n\n.usage-tab[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.usage-stats[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.stat-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background: var(--mj-brand-accent-subtle);\n border-radius: 12px;\n text-align: center;\n}\n\n.stat-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-brand-primary);\n margin-bottom: 12px;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-primary);\n margin-top: 4px;\n}\n\n\n\n.usage-logs[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.log-header[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 100px 1fr 80px 80px;\n gap: 12px;\n padding: 12px 16px;\n background: var(--mj-border-default);\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.log-item[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 100px 1fr 80px 80px;\n gap: 12px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 13px;\n align-items: center;\n}\n\n.log-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.col-time[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n.col-endpoint[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: monospace;\n color: var(--mj-text-primary);\n}\n\n.method-badge[_ngcontent-%COMP%] {\n padding: 2px 6px;\n background: var(--mj-status-info-bg);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-color-info-600);\n}\n\n.col-status[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.col-status.status-success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.col-status.status-warning[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.col-status.status-error[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.col-duration[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n text-align: right;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 8px 0 0 0;\n font-size: 13px;\n}\n\n\n\n\n\n\n.form-input.mj-input[_ngcontent-%COMP%], \n.form-textarea.mj-textarea[_ngcontent-%COMP%], \n[_nghost-%COMP%] mj-datepicker .mj-input {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s ease;\n}\n\n.form-input.mj-input[_ngcontent-%COMP%]:focus, \n.form-textarea.mj-textarea[_ngcontent-%COMP%]:focus, \n[_nghost-%COMP%] mj-datepicker:focus-within {\n box-shadow: var(--mj-focus-ring);\n}\n\n\n\n.edit-actions[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n min-width: 120px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n.edit-actions[_ngcontent-%COMP%] .mj-btn--primary[_ngcontent-%COMP%] {\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n.edit-actions[_ngcontent-%COMP%] .mj-btn--primary[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n\n\n.scopes-header[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n min-width: 120px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n.scopes-header[_ngcontent-%COMP%] .mj-btn--primary[_ngcontent-%COMP%] {\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n.scopes-header[_ngcontent-%COMP%] .mj-btn--primary[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\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: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n margin-bottom: 16px;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.no-scopes-warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-status-error);\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-text);\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}"] });
|
|
1059
1057
|
}
|
|
1060
1058
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIKeyEditPanelComponent, [{
|
|
1061
1059
|
type: Component,
|
|
1062
|
-
args: [{ standalone: false, selector: 'mj-api-key-edit-panel', template: "<!-- Slide-out Backdrop -->\n@if (Visible) {\n <div class=\"slideout-backdrop\" (click)=\"close()\"></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>API Key Details</span>\n <span class=\"key-status\" [class.active]=\"APIKey?.Status === 'Active'\"\n [class.revoked]=\"APIKey?.Status === 'Revoked'\">\n {{APIKey?.Status}}\n </span>\n </div>\n <button class=\"slideout-close\" (click)=\"close()\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n @if (IsLoading) {\n <mj-loading text=\"Loading key details...\"></mj-loading>\n }\n\n @if (!IsLoading && APIKey) {\n <!-- Success/Error Messages -->\n @if (SuccessMessage) {\n <div class=\"message success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{SuccessMessage}}\n </div>\n }\n @if (ErrorMessage) {\n <div class=\"message error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ErrorMessage}}\n </div>\n }\n <!-- Tabs -->\n <div class=\"slideout-tabs\">\n <button class=\"slideout-tab\" [class.active]=\"ActiveTab === 'details'\"\n (click)=\"ActiveTab = 'details'\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Details\n </button>\n <button class=\"slideout-tab\" [class.active]=\"ActiveTab === 'scopes'\"\n (click)=\"ActiveTab = 'scopes'\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n Permissions\n @if (HasScopeChanges) {\n <span class=\"tab-badge unsaved\">!</span>\n }\n </button>\n <button class=\"slideout-tab\" [class.active]=\"ActiveTab === 'usage'\"\n (click)=\"ActiveTab = 'usage'\">\n <i class=\"fa-solid fa-chart-line\"></i>\n Usage\n </button>\n </div>\n <div class=\"slideout-content\">\n <!-- Details Tab -->\n @if (ActiveTab === 'details') {\n <div class=\"tab-panel\">\n <div class=\"key-info-card\">\n <div class=\"info-header\">\n <div class=\"info-row\">\n <span class=\"info-label\">Key Hash</span>\n <code class=\"hash-value\">{{APIKey.Hash}}</code>\n </div>\n </div>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Created</span>\n <span class=\"info-value\">{{formatDate(APIKey.__mj_CreatedAt)}}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Created By</span>\n <span class=\"info-value\">{{APIKey.CreatedByUser}}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Owner</span>\n <span class=\"info-value\">{{APIKey.User}}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Last Used</span>\n <span class=\"info-value\" [class.never-used]=\"!APIKey.LastUsedAt\">\n {{APIKey.LastUsedAt ? formatDate(APIKey.LastUsedAt) : 'Never'}}\n </span>\n </div>\n </div>\n </div>\n <!-- Editable Fields -->\n <div class=\"edit-section\">\n <div class=\"section-header\">\n <h4>Key Configuration</h4>\n @if (APIKey.Status === 'Active') {\n <button class=\"edit-toggle\"\n (click)=\"toggleEdit()\">\n <i class=\"fa-solid\" [class.fa-pencil]=\"!IsEditing\" [class.fa-times]=\"IsEditing\"></i>\n {{IsEditing ? 'Cancel' : 'Edit'}}\n </button>\n }\n </div>\n <div class=\"form-field\">\n <label>Label</label>\n <input kendoTextBox [(ngModel)]=\"EditLabel\"\n [disabled]=\"!IsEditing\"\n class=\"form-input\" />\n </div>\n <div class=\"form-field\">\n <label>Description</label>\n <textarea kendoTextArea [(ngModel)]=\"EditDescription\"\n [disabled]=\"!IsEditing\"\n [rows]=\"3\"\n class=\"form-textarea\"></textarea>\n </div>\n <div class=\"form-field\">\n <label>Expiration</label>\n <div class=\"expiration-field\">\n <kendo-datepicker [(ngModel)]=\"EditExpiresAt\"\n [disabled]=\"!IsEditing\"\n [min]=\"getMinDate()\"\n format=\"MMM d, yyyy\"\n placeholder=\"Never expires\">\n </kendo-datepicker>\n @if (IsEditing && EditExpiresAt) {\n <button class=\"clear-btn\"\n (click)=\"EditExpiresAt = null\">\n <i class=\"fa-solid fa-times\"></i>\n Never expires\n </button>\n }\n </div>\n </div>\n @if (IsEditing) {\n <div class=\"edit-actions\">\n <button kendoButton [themeColor]=\"'primary'\"\n [disabled]=\"IsSaving\"\n (click)=\"saveChanges()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n Save Changes\n </span>\n }\n </button>\n </div>\n }\n </div>\n <!-- Revoke Section -->\n @if (APIKey.Status === 'Active') {\n <div class=\"danger-zone\">\n <h4>Danger Zone</h4>\n @if (!ShowRevokeConfirm) {\n <div class=\"revoke-section\">\n <div class=\"revoke-info\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div>\n <strong>Revoke this API key</strong>\n <p>Once revoked, this key will immediately stop working. This action cannot be undone.</p>\n </div>\n </div>\n <button class=\"revoke-btn\" (click)=\"startRevoke()\">\n <i class=\"fa-solid fa-ban\"></i>\n Revoke Key\n </button>\n </div>\n }\n @if (ShowRevokeConfirm) {\n <div class=\"revoke-confirm\">\n <div class=\"confirm-warning\">\n <i class=\"fa-solid fa-skull-crossbones\"></i>\n <div>\n <strong>Are you absolutely sure?</strong>\n <p>This will permanently revoke the API key. Any applications using this key will immediately lose access.</p>\n </div>\n </div>\n <div class=\"confirm-input\">\n <label>Type <code>REVOKE</code> to confirm:</label>\n <input kendoTextBox [(ngModel)]=\"RevokeConfirmText\"\n placeholder=\"REVOKE\" />\n </div>\n <div class=\"confirm-actions\">\n <button kendoButton (click)=\"cancelRevoke()\">Cancel</button>\n <button class=\"confirm-revoke-btn\"\n [disabled]=\"RevokeConfirmText !== 'REVOKE' || IsRevoking\"\n (click)=\"confirmRevoke()\">\n @if (IsRevoking) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsRevoking) {\n <span>\n <i class=\"fa-solid fa-ban\"></i>\n Revoke Key\n </span>\n }\n </button>\n </div>\n </div>\n }\n </div>\n }\n <!-- Revoked Notice -->\n @if (APIKey.Status === 'Revoked') {\n <div class=\"revoked-notice\">\n <i class=\"fa-solid fa-ban\"></i>\n <div>\n <strong>This API key has been revoked</strong>\n <p>It can no longer be used for authentication. Consider deleting this record if no longer needed.</p>\n </div>\n </div>\n }\n </div>\n }\n <!-- Scopes Tab -->\n @if (ActiveTab === 'scopes') {\n <div class=\"tab-panel scopes-panel\">\n <div class=\"scopes-header\">\n <div class=\"scopes-info\">\n <span class=\"scope-count\">{{getAssignedScopeCount()}} permissions assigned</span>\n </div>\n @if (HasScopeChanges && APIKey.Status === 'Active') {\n <button kendoButton [themeColor]=\"'primary'\"\n [disabled]=\"IsSaving\"\n (click)=\"saveScopeChanges()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n Save Changes\n </span>\n }\n </button>\n }\n </div>\n <!-- No Scopes Warning -->\n @if (!IsLoadingScopes && getAssignedScopeCount() === 0 && APIKey.Status === 'Active') {\n <div class=\"no-scopes-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div>\n <strong>Warning: No permissions assigned</strong>\n <p>This API key has no assigned scopes and cannot perform any operations. All API requests using this key will be rejected until scopes are assigned.</p>\n </div>\n </div>\n }\n @if (IsLoadingScopes) {\n <mj-loading text=\"Loading permissions...\"></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-count\">\n {{getSelectedCount(category)}}/{{category.scopes.length}}\n </span>\n </div>\n <div class=\"category-right\">\n @if (APIKey.Status === 'Active') {\n <label class=\"category-all-toggle\"\n (click)=\"$event.stopPropagation()\"\n >\n <input type=\"checkbox\" kendoCheckBox\n [checked]=\"category.allSelected\"\n (change)=\"toggleCategoryAll(category)\" />\n <span>All</span>\n </label>\n }\n <i class=\"fa-solid expand-icon\" [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 [disabled]=\"APIKey.Status === 'Revoked'\"\n (change)=\"onScopeChange()\" />\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>\n }\n <!-- Usage Tab -->\n @if (ActiveTab === 'usage') {\n <div class=\"tab-panel usage-panel\">\n @if (IsLoadingLogs) {\n <mj-loading text=\"Loading usage logs...\"></mj-loading>\n }\n @if (!IsLoadingLogs) {\n <div class=\"usage-content\">\n <div class=\"usage-stats\">\n <div class=\"stat-card\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <div class=\"stat-value\">{{UsageLogs.length}}</div>\n <div class=\"stat-label\">Total Requests</div>\n </div>\n <div class=\"stat-card\">\n <i class=\"fa-solid fa-clock\"></i>\n <div class=\"stat-value\">\n {{UsageLogs.length > 0 ? formatRelativeTime(UsageLogs[0].timestamp) : 'Never'}}\n </div>\n <div class=\"stat-label\">Last Used</div>\n </div>\n </div>\n @if (UsageLogs.length > 0) {\n <div class=\"usage-logs\">\n <div class=\"log-header\">\n <span class=\"col-time\">Time</span>\n <span class=\"col-endpoint\">Endpoint</span>\n <span class=\"col-status\">Status</span>\n <span class=\"col-duration\">Duration</span>\n </div>\n @for (log of UsageLogs; track log) {\n <div class=\"log-item\">\n <span class=\"col-time\">{{formatRelativeTime(log.timestamp)}}</span>\n <span class=\"col-endpoint\">\n <span class=\"method-badge\">{{log.method}}</span>\n {{log.endpoint}}\n </span>\n <span class=\"col-status\" [ngClass]=\"getStatusClass(log.statusCode)\">\n {{log.statusCode}}\n </span>\n <span class=\"col-duration\">{{log.responseTime}}ms</span>\n </div>\n }\n </div>\n }\n @if (UsageLogs.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-chart-area\"></i>\n <span>No usage logs yet</span>\n <p>Usage will be recorded when this API key is used for authentication</p>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <!-- Footer -->\n <div class=\"slideout-footer\">\n <button kendoButton (click)=\"close()\">Close</button>\n </div>\n }\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-brand-accent-subtle);\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.key-status {\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.key-status.active {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.key-status.revoked {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.slideout-close {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-hover);\n border: none;\n border-radius: 8px;\n color: var(--mj-text-secondary);\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-active);\n color: var(--mj-text-primary);\n}\n\n/* Panel Tabs */\n.slideout-tabs {\n display: flex;\n gap: 4px;\n padding: 12px 24px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.slideout-tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n}\n\n.slideout-tab:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.slideout-tab.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.slideout-tab i {\n font-size: 14px;\n}\n\n.tab-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 9px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.tab-badge.unsaved {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.slideout-tab:not(.active) .tab-badge {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n/* Panel Content */\n.slideout-content {\n flex: 1;\n overflow-y: auto;\n padding: 0;\n}\n\n.tab-panel {\n padding: 20px 24px;\n}\n\n/* Panel Footer */\n.slideout-footer {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\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: 80px;\n padding: 8px 16px;\n font-weight: 500;\n border-radius: 6px;\n}\n\n/* Messages */\n.message {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n margin: 12px 16px;\n border-radius: 8px;\n font-size: 14px;\n}\n\n.message.success {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.message.error {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n/* Legacy tab styles removed - now using slideout-tabs */\n\n/* Key Info Card */\n.key-info-card {\n background: var(--mj-brand-accent-subtle);\n border-radius: 10px;\n padding: 14px 16px;\n margin-bottom: 16px;\n}\n\n.info-header {\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.info-row {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.hash-value {\n font-family: 'Fira Code', 'Consolas', monospace;\n font-size: 13px;\n color: var(--mj-text-primary);\n word-break: break-all;\n background: var(--mj-bg-surface);\n padding: 8px 12px;\n border-radius: 6px;\n}\n\n.info-grid {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 10px 16px;\n}\n\n.info-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.info-value {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.info-value.never-used {\n color: var(--mj-text-secondary);\n font-style: italic;\n}\n\n/* Edit Section */\n.edit-section {\n background: var(--mj-bg-page);\n border-radius: 10px;\n padding: 16px;\n margin-bottom: 16px;\n}\n\n.section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 14px;\n}\n\n.section-header h4 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.edit-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\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.edit-toggle:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.form-field {\n margin-bottom: 12px;\n}\n\n.form-field label {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.form-input,\n.form-textarea {\n width: 100%;\n}\n\n.expiration-field {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.clear-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: transparent;\n border: 1px dashed var(--mj-border-strong);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.clear-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.edit-actions {\n margin-top: 14px;\n padding-top: 14px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* Danger Zone */\n.danger-zone {\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n padding: 14px 16px;\n}\n\n.danger-zone h4 {\n margin: 0 0 12px 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.revoke-section {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n}\n\n.revoke-info {\n display: flex;\n gap: 12px;\n flex: 1;\n}\n\n.revoke-info i {\n font-size: 20px;\n color: var(--mj-status-error);\n margin-top: 2px;\n}\n\n.revoke-info strong {\n display: block;\n color: var(--mj-status-error-text);\n margin-bottom: 4px;\n}\n\n.revoke-info p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.revoke-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-status-error);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-status-error);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.revoke-btn:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* Revoke Confirm */\n.revoke-confirm {\n background: var(--mj-status-error-bg);\n border-radius: 8px;\n}\n\n.confirm-warning {\n display: flex;\n gap: 12px;\n margin-bottom: 20px;\n}\n\n.confirm-warning i {\n font-size: 24px;\n color: var(--mj-status-error);\n}\n\n.confirm-warning strong {\n display: block;\n color: var(--mj-status-error-text);\n font-size: 16px;\n margin-bottom: 4px;\n}\n\n.confirm-warning p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.confirm-input {\n margin-bottom: 16px;\n}\n\n.confirm-input label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-status-error-text);\n margin-bottom: 8px;\n}\n\n.confirm-input code {\n background: var(--mj-status-error-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n.confirm-input input {\n width: 100%;\n}\n\n.confirm-actions {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.confirm-revoke-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-status-error);\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.confirm-revoke-btn:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n}\n\n.confirm-revoke-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Revoked Notice */\n.revoked-notice {\n display: flex;\n gap: 12px;\n padding: 20px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n}\n\n.revoked-notice i {\n font-size: 24px;\n color: var(--mj-text-secondary);\n}\n\n.revoked-notice strong {\n display: block;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.revoked-notice p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n/* Scopes Tab */\n.scopes-tab {\n padding: 16px;\n}\n\n.scopes-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.scope-count {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\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-count {\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.category-all-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.category-all-toggle:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.category-all-toggle input {\n margin: 0;\n}\n\n.expand-icon {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s ease;\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); /* scope items separator */\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-primary);\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/* Usage Tab */\n.usage-tab {\n padding: 16px;\n}\n\n.usage-stats {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.stat-card {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background: var(--mj-brand-accent-subtle);\n border-radius: 12px;\n text-align: center;\n}\n\n.stat-card i {\n font-size: 24px;\n color: var(--mj-brand-primary);\n margin-bottom: 12px;\n}\n\n.stat-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.stat-label {\n font-size: 12px;\n color: var(--mj-text-primary);\n margin-top: 4px;\n}\n\n/* Usage Logs */\n.usage-logs {\n background: var(--mj-bg-page);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.log-header {\n display: grid;\n grid-template-columns: 100px 1fr 80px 80px;\n gap: 12px;\n padding: 12px 16px;\n background: var(--mj-border-default);\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.log-item {\n display: grid;\n grid-template-columns: 100px 1fr 80px 80px;\n gap: 12px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 13px;\n align-items: center;\n}\n\n.log-item:last-child {\n border-bottom: none;\n}\n\n.col-time {\n color: var(--mj-text-secondary);\n}\n\n.col-endpoint {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: monospace;\n color: var(--mj-text-primary);\n}\n\n.method-badge {\n padding: 2px 6px;\n background: var(--mj-status-info-bg);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-color-info-600);\n}\n\n.col-status {\n font-weight: 600;\n}\n\n.col-status.status-success {\n color: var(--mj-status-success);\n}\n\n.col-status.status-warning {\n color: var(--mj-brand-primary);\n}\n\n.col-status.status-error {\n color: var(--mj-status-error);\n}\n\n.col-duration {\n color: var(--mj-text-secondary);\n text-align: right;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state span {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.empty-state p {\n margin: 8px 0 0 0;\n font-size: 13px;\n}\n\n/* Legacy kendo-window styles removed - now using slideout-panel */\n\n/* Input and form field 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\n/* Button styling in edit actions */\n:host ::ng-deep .edit-actions .k-button {\n min-width: 120px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n:host ::ng-deep .edit-actions .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 .edit-actions .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n/* Scopes header button styling */\n:host ::ng-deep .scopes-header .k-button {\n min-width: 120px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n:host ::ng-deep .scopes-header .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 .scopes-header .k-button-solid-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\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: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n margin-bottom: 16px;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.no-scopes-warning i {\n font-size: 20px;\n color: var(--mj-status-error);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.no-scopes-warning strong {\n display: block;\n color: var(--mj-status-error-text);\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"] }]
|
|
1060
|
+
args: [{ standalone: false, selector: 'mj-api-key-edit-panel', template: "<!-- Slide-out Backdrop -->\n@if (Visible) {\n <div class=\"slideout-backdrop\" (click)=\"close()\"></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>API Key Details</span>\n <span class=\"key-status\" [class.active]=\"APIKey?.Status === 'Active'\"\n [class.revoked]=\"APIKey?.Status === 'Revoked'\">\n {{APIKey?.Status}}\n </span>\n </div>\n <button class=\"slideout-close\" (click)=\"close()\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n @if (IsLoading) {\n <mj-loading text=\"Loading key details...\"></mj-loading>\n }\n\n @if (!IsLoading && APIKey) {\n <!-- Success/Error Messages -->\n @if (SuccessMessage) {\n <div class=\"message success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{SuccessMessage}}\n </div>\n }\n @if (ErrorMessage) {\n <div class=\"message error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ErrorMessage}}\n </div>\n }\n <!-- Tabs -->\n <div class=\"slideout-tabs\">\n <button class=\"slideout-tab\" [class.active]=\"ActiveTab === 'details'\"\n (click)=\"ActiveTab = 'details'\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Details\n </button>\n <button class=\"slideout-tab\" [class.active]=\"ActiveTab === 'scopes'\"\n (click)=\"ActiveTab = 'scopes'\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n Permissions\n @if (HasScopeChanges) {\n <span class=\"tab-badge unsaved\">!</span>\n }\n </button>\n <button class=\"slideout-tab\" [class.active]=\"ActiveTab === 'usage'\"\n (click)=\"ActiveTab = 'usage'\">\n <i class=\"fa-solid fa-chart-line\"></i>\n Usage\n </button>\n </div>\n <div class=\"slideout-content\">\n <!-- Details Tab -->\n @if (ActiveTab === 'details') {\n <div class=\"tab-panel\">\n <div class=\"key-info-card\">\n <div class=\"info-header\">\n <div class=\"info-row\">\n <span class=\"info-label\">Key Hash</span>\n <code class=\"hash-value\">{{APIKey.Hash}}</code>\n </div>\n </div>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Created</span>\n <span class=\"info-value\">{{formatDate(APIKey.__mj_CreatedAt)}}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Created By</span>\n <span class=\"info-value\">{{APIKey.CreatedByUser}}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Owner</span>\n <span class=\"info-value\">{{APIKey.User}}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Last Used</span>\n <span class=\"info-value\" [class.never-used]=\"!APIKey.LastUsedAt\">\n {{APIKey.LastUsedAt ? formatDate(APIKey.LastUsedAt) : 'Never'}}\n </span>\n </div>\n </div>\n </div>\n <!-- Editable Fields -->\n <div class=\"edit-section\">\n <div class=\"section-header\">\n <h4>Key Configuration</h4>\n @if (APIKey.Status === 'Active') {\n <button class=\"edit-toggle\"\n (click)=\"toggleEdit()\">\n <i class=\"fa-solid\" [class.fa-pencil]=\"!IsEditing\" [class.fa-times]=\"IsEditing\"></i>\n {{IsEditing ? 'Cancel' : 'Edit'}}\n </button>\n }\n </div>\n <div class=\"form-field\">\n <label>Label</label>\n <input class=\"mj-input form-input\" [(ngModel)]=\"EditLabel\"\n [disabled]=\"!IsEditing\" />\n </div>\n <div class=\"form-field\">\n <label>Description</label>\n <textarea class=\"mj-textarea form-textarea\" [(ngModel)]=\"EditDescription\"\n [disabled]=\"!IsEditing\"\n [rows]=\"3\"></textarea>\n </div>\n <div class=\"form-field\">\n <label>Expiration</label>\n <div class=\"expiration-field\">\n <mj-datepicker [(ngModel)]=\"EditExpiresAt\"\n [Disabled]=\"!IsEditing\"\n [Min]=\"getMinDate()\"\n Format=\"MMM d, yyyy\"\n Placeholder=\"Never expires\">\n </mj-datepicker>\n @if (IsEditing && EditExpiresAt) {\n <button class=\"clear-btn\"\n (click)=\"EditExpiresAt = null\">\n <i class=\"fa-solid fa-times\"></i>\n Never expires\n </button>\n }\n </div>\n </div>\n @if (IsEditing) {\n <div class=\"edit-actions\">\n <button mjButton variant=\"primary\"\n [disabled]=\"IsSaving\"\n (click)=\"saveChanges()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n Save Changes\n </span>\n }\n </button>\n </div>\n }\n </div>\n <!-- Revoke Section -->\n @if (APIKey.Status === 'Active') {\n <div class=\"danger-zone\">\n <h4>Danger Zone</h4>\n @if (!ShowRevokeConfirm) {\n <div class=\"revoke-section\">\n <div class=\"revoke-info\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div>\n <strong>Revoke this API key</strong>\n <p>Once revoked, this key will immediately stop working. This action cannot be undone.</p>\n </div>\n </div>\n <button class=\"revoke-btn\" (click)=\"startRevoke()\">\n <i class=\"fa-solid fa-ban\"></i>\n Revoke Key\n </button>\n </div>\n }\n @if (ShowRevokeConfirm) {\n <div class=\"revoke-confirm\">\n <div class=\"confirm-warning\">\n <i class=\"fa-solid fa-skull-crossbones\"></i>\n <div>\n <strong>Are you absolutely sure?</strong>\n <p>This will permanently revoke the API key. Any applications using this key will immediately lose access.</p>\n </div>\n </div>\n <div class=\"confirm-input\">\n <label>Type <code>REVOKE</code> to confirm:</label>\n <input class=\"mj-input\" [(ngModel)]=\"RevokeConfirmText\"\n placeholder=\"REVOKE\" />\n </div>\n <div class=\"confirm-actions\">\n <button mjButton (click)=\"cancelRevoke()\">Cancel</button>\n <button class=\"confirm-revoke-btn\"\n [disabled]=\"RevokeConfirmText !== 'REVOKE' || IsRevoking\"\n (click)=\"confirmRevoke()\">\n @if (IsRevoking) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsRevoking) {\n <span>\n <i class=\"fa-solid fa-ban\"></i>\n Revoke Key\n </span>\n }\n </button>\n </div>\n </div>\n }\n </div>\n }\n <!-- Revoked Notice -->\n @if (APIKey.Status === 'Revoked') {\n <div class=\"revoked-notice\">\n <i class=\"fa-solid fa-ban\"></i>\n <div>\n <strong>This API key has been revoked</strong>\n <p>It can no longer be used for authentication. Consider deleting this record if no longer needed.</p>\n </div>\n </div>\n }\n </div>\n }\n <!-- Scopes Tab -->\n @if (ActiveTab === 'scopes') {\n <div class=\"tab-panel scopes-panel\">\n <div class=\"scopes-header\">\n <div class=\"scopes-info\">\n <span class=\"scope-count\">{{getAssignedScopeCount()}} permissions assigned</span>\n </div>\n @if (HasScopeChanges && APIKey.Status === 'Active') {\n <button mjButton variant=\"primary\"\n [disabled]=\"IsSaving\"\n (click)=\"saveScopeChanges()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n Save Changes\n </span>\n }\n </button>\n }\n </div>\n <!-- No Scopes Warning -->\n @if (!IsLoadingScopes && getAssignedScopeCount() === 0 && APIKey.Status === 'Active') {\n <div class=\"no-scopes-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div>\n <strong>Warning: No permissions assigned</strong>\n <p>This API key has no assigned scopes and cannot perform any operations. All API requests using this key will be rejected until scopes are assigned.</p>\n </div>\n </div>\n }\n @if (IsLoadingScopes) {\n <mj-loading text=\"Loading permissions...\"></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-count\">\n {{getSelectedCount(category)}}/{{category.scopes.length}}\n </span>\n </div>\n <div class=\"category-right\">\n @if (APIKey.Status === 'Active') {\n <label class=\"category-all-toggle\"\n (click)=\"$event.stopPropagation()\"\n >\n <input type=\"checkbox\" class=\"mj-checkbox\"\n [checked]=\"category.allSelected\"\n (change)=\"toggleCategoryAll(category)\" />\n <span>All</span>\n </label>\n }\n <i class=\"fa-solid expand-icon\" [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 [disabled]=\"APIKey.Status === 'Revoked'\"\n (change)=\"onScopeChange()\" />\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>\n }\n <!-- Usage Tab -->\n @if (ActiveTab === 'usage') {\n <div class=\"tab-panel usage-panel\">\n @if (IsLoadingLogs) {\n <mj-loading text=\"Loading usage logs...\"></mj-loading>\n }\n @if (!IsLoadingLogs) {\n <div class=\"usage-content\">\n <div class=\"usage-stats\">\n <div class=\"stat-card\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <div class=\"stat-value\">{{UsageLogs.length}}</div>\n <div class=\"stat-label\">Total Requests</div>\n </div>\n <div class=\"stat-card\">\n <i class=\"fa-solid fa-clock\"></i>\n <div class=\"stat-value\">\n {{UsageLogs.length > 0 ? formatRelativeTime(UsageLogs[0].timestamp) : 'Never'}}\n </div>\n <div class=\"stat-label\">Last Used</div>\n </div>\n </div>\n @if (UsageLogs.length > 0) {\n <div class=\"usage-logs\">\n <div class=\"log-header\">\n <span class=\"col-time\">Time</span>\n <span class=\"col-endpoint\">Endpoint</span>\n <span class=\"col-status\">Status</span>\n <span class=\"col-duration\">Duration</span>\n </div>\n @for (log of UsageLogs; track log) {\n <div class=\"log-item\">\n <span class=\"col-time\">{{formatRelativeTime(log.timestamp)}}</span>\n <span class=\"col-endpoint\">\n <span class=\"method-badge\">{{log.method}}</span>\n {{log.endpoint}}\n </span>\n <span class=\"col-status\" [ngClass]=\"getStatusClass(log.statusCode)\">\n {{log.statusCode}}\n </span>\n <span class=\"col-duration\">{{log.responseTime}}ms</span>\n </div>\n }\n </div>\n }\n @if (UsageLogs.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-chart-area\"></i>\n <span>No usage logs yet</span>\n <p>Usage will be recorded when this API key is used for authentication</p>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <!-- Footer -->\n <div class=\"slideout-footer\">\n <button mjButton (click)=\"close()\">Close</button>\n </div>\n }\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-brand-accent-subtle);\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.key-status {\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.key-status.active {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.key-status.revoked {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.slideout-close {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-hover);\n border: none;\n border-radius: 8px;\n color: var(--mj-text-secondary);\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-active);\n color: var(--mj-text-primary);\n}\n\n/* Panel Tabs */\n.slideout-tabs {\n display: flex;\n gap: 4px;\n padding: 12px 24px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.slideout-tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n}\n\n.slideout-tab:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.slideout-tab.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.slideout-tab i {\n font-size: 14px;\n}\n\n.tab-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 9px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.tab-badge.unsaved {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.slideout-tab:not(.active) .tab-badge {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n/* Panel Content */\n.slideout-content {\n flex: 1;\n overflow-y: auto;\n padding: 0;\n}\n\n.tab-panel {\n padding: 20px 24px;\n}\n\n/* Panel Footer */\n.slideout-footer {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\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.slideout-footer .mj-btn {\n min-width: 80px;\n padding: 8px 16px;\n font-weight: 500;\n border-radius: 6px;\n}\n\n/* Messages */\n.message {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n margin: 12px 16px;\n border-radius: 8px;\n font-size: 14px;\n}\n\n.message.success {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.message.error {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n/* Legacy tab styles removed - now using slideout-tabs */\n\n/* Key Info Card */\n.key-info-card {\n background: var(--mj-brand-accent-subtle);\n border-radius: 10px;\n padding: 14px 16px;\n margin-bottom: 16px;\n}\n\n.info-header {\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.info-row {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.hash-value {\n font-family: 'Fira Code', 'Consolas', monospace;\n font-size: 13px;\n color: var(--mj-text-primary);\n word-break: break-all;\n background: var(--mj-bg-surface);\n padding: 8px 12px;\n border-radius: 6px;\n}\n\n.info-grid {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 10px 16px;\n}\n\n.info-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.info-value {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.info-value.never-used {\n color: var(--mj-text-secondary);\n font-style: italic;\n}\n\n/* Edit Section */\n.edit-section {\n background: var(--mj-bg-page);\n border-radius: 10px;\n padding: 16px;\n margin-bottom: 16px;\n}\n\n.section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 14px;\n}\n\n.section-header h4 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.edit-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\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.edit-toggle:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.form-field {\n margin-bottom: 12px;\n}\n\n.form-field label {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.form-input,\n.form-textarea {\n width: 100%;\n}\n\n.expiration-field {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.clear-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: transparent;\n border: 1px dashed var(--mj-border-strong);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.clear-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.edit-actions {\n margin-top: 14px;\n padding-top: 14px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* Danger Zone */\n.danger-zone {\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n padding: 14px 16px;\n}\n\n.danger-zone h4 {\n margin: 0 0 12px 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.revoke-section {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n}\n\n.revoke-info {\n display: flex;\n gap: 12px;\n flex: 1;\n}\n\n.revoke-info i {\n font-size: 20px;\n color: var(--mj-status-error);\n margin-top: 2px;\n}\n\n.revoke-info strong {\n display: block;\n color: var(--mj-status-error-text);\n margin-bottom: 4px;\n}\n\n.revoke-info p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.revoke-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-status-error);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-status-error);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.revoke-btn:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* Revoke Confirm */\n.revoke-confirm {\n background: var(--mj-status-error-bg);\n border-radius: 8px;\n}\n\n.confirm-warning {\n display: flex;\n gap: 12px;\n margin-bottom: 20px;\n}\n\n.confirm-warning i {\n font-size: 24px;\n color: var(--mj-status-error);\n}\n\n.confirm-warning strong {\n display: block;\n color: var(--mj-status-error-text);\n font-size: 16px;\n margin-bottom: 4px;\n}\n\n.confirm-warning p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.confirm-input {\n margin-bottom: 16px;\n}\n\n.confirm-input label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-status-error-text);\n margin-bottom: 8px;\n}\n\n.confirm-input code {\n background: var(--mj-status-error-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n.confirm-input input {\n width: 100%;\n}\n\n.confirm-actions {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.confirm-revoke-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-status-error);\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.confirm-revoke-btn:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n}\n\n.confirm-revoke-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Revoked Notice */\n.revoked-notice {\n display: flex;\n gap: 12px;\n padding: 20px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n}\n\n.revoked-notice i {\n font-size: 24px;\n color: var(--mj-text-secondary);\n}\n\n.revoked-notice strong {\n display: block;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.revoked-notice p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n/* Scopes Tab */\n.scopes-tab {\n padding: 16px;\n}\n\n.scopes-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.scope-count {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\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-count {\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.category-all-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.category-all-toggle:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.category-all-toggle input {\n margin: 0;\n}\n\n.expand-icon {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s ease;\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); /* scope items separator */\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-primary);\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/* Usage Tab */\n.usage-tab {\n padding: 16px;\n}\n\n.usage-stats {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.stat-card {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background: var(--mj-brand-accent-subtle);\n border-radius: 12px;\n text-align: center;\n}\n\n.stat-card i {\n font-size: 24px;\n color: var(--mj-brand-primary);\n margin-bottom: 12px;\n}\n\n.stat-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.stat-label {\n font-size: 12px;\n color: var(--mj-text-primary);\n margin-top: 4px;\n}\n\n/* Usage Logs */\n.usage-logs {\n background: var(--mj-bg-page);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.log-header {\n display: grid;\n grid-template-columns: 100px 1fr 80px 80px;\n gap: 12px;\n padding: 12px 16px;\n background: var(--mj-border-default);\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.log-item {\n display: grid;\n grid-template-columns: 100px 1fr 80px 80px;\n gap: 12px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 13px;\n align-items: center;\n}\n\n.log-item:last-child {\n border-bottom: none;\n}\n\n.col-time {\n color: var(--mj-text-secondary);\n}\n\n.col-endpoint {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: monospace;\n color: var(--mj-text-primary);\n}\n\n.method-badge {\n padding: 2px 6px;\n background: var(--mj-status-info-bg);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-color-info-600);\n}\n\n.col-status {\n font-weight: 600;\n}\n\n.col-status.status-success {\n color: var(--mj-status-success);\n}\n\n.col-status.status-warning {\n color: var(--mj-brand-primary);\n}\n\n.col-status.status-error {\n color: var(--mj-status-error);\n}\n\n.col-duration {\n color: var(--mj-text-secondary);\n text-align: right;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state span {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.empty-state p {\n margin: 8px 0 0 0;\n font-size: 13px;\n}\n\n/* Legacy kendo-window styles removed - now using slideout-panel */\n\n/* Input and form field styling */\n.form-input.mj-input,\n.form-textarea.mj-textarea,\n:host ::ng-deep mj-datepicker .mj-input {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s ease;\n}\n\n.form-input.mj-input:focus,\n.form-textarea.mj-textarea:focus,\n:host ::ng-deep mj-datepicker:focus-within {\n box-shadow: var(--mj-focus-ring);\n}\n\n/* Button styling in edit actions */\n.edit-actions .mj-btn {\n min-width: 120px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n.edit-actions .mj-btn--primary {\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n.edit-actions .mj-btn--primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n/* Scopes header button styling */\n.scopes-header .mj-btn {\n min-width: 120px;\n padding: 10px 20px;\n font-weight: 600;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n.scopes-header .mj-btn--primary {\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n.scopes-header .mj-btn--primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\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: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 10px;\n margin-bottom: 16px;\n font-size: 13px;\n color: var(--mj-status-error-text);\n}\n\n.no-scopes-warning i {\n font-size: 20px;\n color: var(--mj-status-error);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.no-scopes-warning strong {\n display: block;\n color: var(--mj-status-error-text);\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"] }]
|
|
1063
1061
|
}], null, { Visible: [{
|
|
1064
1062
|
type: Input
|
|
1065
1063
|
}], KeyId: [{
|