@memberjunction/ng-dashboards 5.38.0 → 5.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -7
- package/dist/AI/components/agents/agent-configuration.component.js +199 -198
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.js +20 -17
- package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
- package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +217 -860
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1717 -7802
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts +56 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js +423 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts +70 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js +308 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts +29 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +186 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts +69 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js +278 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts +73 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js +393 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts +122 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js +908 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +333 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +2125 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts +58 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.format.js +260 -0
- package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts +319 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
- package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +77 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.js +519 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +131 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +813 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +177 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1465 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +78 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js +492 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +56 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.js +271 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +3 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +306 -290
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +1 -1
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +209 -208
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +130 -128
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
- package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +17 -17
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +1 -0
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +578 -538
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +3 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +331 -303
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js +14 -2
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/AI/services/cache-metrics.d.ts +50 -0
- package/dist/AI/services/cache-metrics.d.ts.map +1 -0
- package/dist/AI/services/cache-metrics.js +43 -0
- package/dist/AI/services/cache-metrics.js.map +1 -0
- package/dist/APIKeys/api-applications-panel.component.js +2 -2
- package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
- package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
- package/dist/APIKeys/api-keys-resource.component.js +132 -131
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +141 -141
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +15 -15
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
- package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Admin/admin-data-schema.component.js +2 -2
- package/dist/Admin/admin-data-schema.component.js.map +1 -1
- package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
- package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
- package/dist/Admin/admin-identity-access.component.js +2 -2
- package/dist/Admin/admin-identity-access.component.js.map +1 -1
- package/dist/Admin/admin-monitoring.component.js +2 -2
- package/dist/Admin/admin-monitoring.component.js.map +1 -1
- package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
- package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
- package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +72 -50
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +103 -102
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +52 -51
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +39 -38
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
- package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +92 -89
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +31 -340
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +468 -1958
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js +10 -0
- package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
- package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
- package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
- package/dist/DevTools/app-state-inspector.component.js +18 -17
- package/dist/DevTools/app-state-inspector.component.js.map +1 -1
- package/dist/DevTools/class-registry.component.js +88 -85
- package/dist/DevTools/class-registry.component.js.map +1 -1
- package/dist/DevTools/event-monitor.component.js +155 -150
- package/dist/DevTools/event-monitor.component.js.map +1 -1
- package/dist/DevTools/graphql-console.component.js +245 -243
- package/dist/DevTools/graphql-console.component.js.map +1 -1
- package/dist/DevTools/layout-inspector.component.js +18 -17
- package/dist/DevTools/layout-inspector.component.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +2 -2
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +236 -229
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +390 -389
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +2 -2
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +14 -11
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +27 -2
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +244 -119
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts +65 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js +176 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js.map +1 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts +81 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js +308 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js.map +1 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts +85 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js +362 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js.map +1 -0
- 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 +6 -2
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +525 -566
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +135 -134
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
- package/dist/MCP/mcp-dashboard.component.js +443 -438
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
- package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +436 -427
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.js +1 -1
- package/dist/Testing/components/testing-runs.component.js +116 -115
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +6 -7
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +173 -172
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
- package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +116 -92
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +57 -35
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +80 -1
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +1 -1
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +7 -1
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/data-explorer-dashboards.module.d.ts +12 -14
- package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
- package/dist/data-explorer-dashboards.module.js +5 -14
- package/dist/data-explorer-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +3 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +4 -5
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +7 -5
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +57 -54
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +0 -79
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +0 -1
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +0 -195
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +0 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +0 -226
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +0 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +0 -861
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +0 -1
|
@@ -1066,11 +1066,11 @@ export class APIKeyEditPanelComponent extends BaseAngularComponent {
|
|
|
1066
1066
|
i0.ɵɵconditional(ctx.IsLoading ? 11 : -1);
|
|
1067
1067
|
i0.ɵɵadvance();
|
|
1068
1068
|
i0.ɵɵconditional(!ctx.IsLoading && ctx.APIKey ? 12 : -1);
|
|
1069
|
-
} }, 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}"] });
|
|
1069
|
+
} }, 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\n\n\n.slideout-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n min-width: 80px;\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\n.edit-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%], \n.scopes-header[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n min-width: 120px;\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}"] });
|
|
1070
1070
|
}
|
|
1071
1071
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIKeyEditPanelComponent, [{
|
|
1072
1072
|
type: Component,
|
|
1073
|
-
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"] }]
|
|
1073
|
+
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/* Button shape/size is owned by the mjButton directive (variant/size inputs).\n Only the layout min-width is set here, scoped to the element (not .mj-btn). */\n.slideout-footer button {\n min-width: 80px;\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 shape/size is owned by the mjButton directive (variant/size inputs).\n Only the layout min-width is set here, scoped to the element (not .mj-btn). */\n.edit-actions button,\n.scopes-header button {\n min-width: 120px;\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"] }]
|
|
1074
1074
|
}], null, { Visible: [{
|
|
1075
1075
|
type: Input
|
|
1076
1076
|
}], KeyId: [{
|