@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
|
@@ -26,19 +26,20 @@ function APIKeysResourceComponent_Conditional_5_Template(rf, ctx) { if (rf & 1)
|
|
|
26
26
|
i0.ɵɵelementStart(0, "button", 10);
|
|
27
27
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
|
|
28
28
|
i0.ɵɵelement(1, "i", 11);
|
|
29
|
-
i0.ɵɵ
|
|
30
|
-
i0.ɵɵ
|
|
29
|
+
i0.ɵɵelementStart(2, "span", 12);
|
|
30
|
+
i0.ɵɵtext(3, "Generate New Key");
|
|
31
|
+
i0.ɵɵelementEnd()();
|
|
31
32
|
} }
|
|
32
33
|
function APIKeysResourceComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
33
34
|
i0.ɵɵelementStart(0, "div", 7);
|
|
34
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
35
|
+
i0.ɵɵelement(1, "mj-loading", 13);
|
|
35
36
|
i0.ɵɵelementEnd();
|
|
36
37
|
} }
|
|
37
38
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
38
39
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
39
|
-
i0.ɵɵelementStart(0, "span",
|
|
40
|
+
i0.ɵɵelementStart(0, "span", 63);
|
|
40
41
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expired")); });
|
|
41
|
-
i0.ɵɵelement(1, "i",
|
|
42
|
+
i0.ɵɵelement(1, "i", 64);
|
|
42
43
|
i0.ɵɵtext(2);
|
|
43
44
|
i0.ɵɵelementEnd();
|
|
44
45
|
} if (rf & 2) {
|
|
@@ -48,9 +49,9 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
48
49
|
} }
|
|
49
50
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
50
51
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
51
|
-
i0.ɵɵelementStart(0, "span",
|
|
52
|
+
i0.ɵɵelementStart(0, "span", 65);
|
|
52
53
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
|
|
53
|
-
i0.ɵɵelement(1, "i",
|
|
54
|
+
i0.ɵɵelement(1, "i", 41);
|
|
54
55
|
i0.ɵɵtext(2);
|
|
55
56
|
i0.ɵɵelementEnd();
|
|
56
57
|
} if (rf & 2) {
|
|
@@ -60,9 +61,9 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
60
61
|
} }
|
|
61
62
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
62
63
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
63
|
-
i0.ɵɵelementStart(0, "span",
|
|
64
|
+
i0.ɵɵelementStart(0, "span", 66);
|
|
64
65
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("never-used")); });
|
|
65
|
-
i0.ɵɵelement(1, "i",
|
|
66
|
+
i0.ɵɵelement(1, "i", 67);
|
|
66
67
|
i0.ɵɵtext(2);
|
|
67
68
|
i0.ɵɵelementEnd();
|
|
68
69
|
} if (rf & 2) {
|
|
@@ -71,36 +72,36 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
71
72
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.NeverUsedKeys, " never used ");
|
|
72
73
|
} }
|
|
73
74
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
74
|
-
i0.ɵɵelementStart(0, "span",
|
|
75
|
-
i0.ɵɵelement(1, "i",
|
|
75
|
+
i0.ɵɵelementStart(0, "span", 27);
|
|
76
|
+
i0.ɵɵelement(1, "i", 38);
|
|
76
77
|
i0.ɵɵtext(2, " All keys healthy ");
|
|
77
78
|
i0.ɵɵelementEnd();
|
|
78
79
|
} }
|
|
79
80
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_46_Template(rf, ctx) { if (rf & 1) {
|
|
80
|
-
i0.ɵɵelementStart(0, "div",
|
|
81
|
-
i0.ɵɵelement(1, "i",
|
|
81
|
+
i0.ɵɵelementStart(0, "div", 42);
|
|
82
|
+
i0.ɵɵelement(1, "i", 36);
|
|
82
83
|
i0.ɵɵelementEnd();
|
|
83
84
|
} }
|
|
84
85
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
85
86
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
86
|
-
i0.ɵɵelementStart(0, "div",
|
|
87
|
+
i0.ɵɵelementStart(0, "div", 69);
|
|
87
88
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template_div_click_0_listener() { const key_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.openEditPanel(key_r8)); });
|
|
88
|
-
i0.ɵɵelementStart(1, "div",
|
|
89
|
-
i0.ɵɵelement(2, "i",
|
|
89
|
+
i0.ɵɵelementStart(1, "div", 70);
|
|
90
|
+
i0.ɵɵelement(2, "i", 31);
|
|
90
91
|
i0.ɵɵelementEnd();
|
|
91
|
-
i0.ɵɵelementStart(3, "div",
|
|
92
|
+
i0.ɵɵelementStart(3, "div", 71)(4, "div", 72);
|
|
92
93
|
i0.ɵɵtext(5);
|
|
93
94
|
i0.ɵɵelementEnd();
|
|
94
|
-
i0.ɵɵelementStart(6, "div",
|
|
95
|
+
i0.ɵɵelementStart(6, "div", 73)(7, "span", 74);
|
|
95
96
|
i0.ɵɵtext(8);
|
|
96
97
|
i0.ɵɵelementEnd();
|
|
97
|
-
i0.ɵɵelementStart(9, "span",
|
|
98
|
+
i0.ɵɵelementStart(9, "span", 75);
|
|
98
99
|
i0.ɵɵtext(10);
|
|
99
100
|
i0.ɵɵelementEnd()()();
|
|
100
|
-
i0.ɵɵelementStart(11, "div",
|
|
101
|
+
i0.ɵɵelementStart(11, "div", 76)(12, "div", 77);
|
|
101
102
|
i0.ɵɵtext(13);
|
|
102
103
|
i0.ɵɵelementEnd();
|
|
103
|
-
i0.ɵɵelementStart(14, "div",
|
|
104
|
+
i0.ɵɵelementStart(14, "div", 78);
|
|
104
105
|
i0.ɵɵtext(15);
|
|
105
106
|
i0.ɵɵelementEnd()()();
|
|
106
107
|
} if (rf & 2) {
|
|
@@ -122,8 +123,8 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
122
123
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.formatExpiration(key_r8.ExpiresAt), " ");
|
|
123
124
|
} }
|
|
124
125
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_Template(rf, ctx) { if (rf & 1) {
|
|
125
|
-
i0.ɵɵelementStart(0, "div",
|
|
126
|
-
i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template, 16, 8, "div",
|
|
126
|
+
i0.ɵɵelementStart(0, "div", 51);
|
|
127
|
+
i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_For_2_Template, 16, 8, "div", 68, i0.ɵɵrepeaterTrackByIdentity);
|
|
127
128
|
i0.ɵɵelementEnd();
|
|
128
129
|
} if (rf & 2) {
|
|
129
130
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
@@ -131,8 +132,8 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
131
132
|
i0.ɵɵrepeater(ctx_r1.TopUsedKeys);
|
|
132
133
|
} }
|
|
133
134
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_75_Template(rf, ctx) { if (rf & 1) {
|
|
134
|
-
i0.ɵɵelementStart(0, "div",
|
|
135
|
-
i0.ɵɵelement(1, "i",
|
|
135
|
+
i0.ɵɵelementStart(0, "div", 52);
|
|
136
|
+
i0.ɵɵelement(1, "i", 31);
|
|
136
137
|
i0.ɵɵelementStart(2, "span");
|
|
137
138
|
i0.ɵɵtext(3, "No active keys with recent usage");
|
|
138
139
|
i0.ɵɵelementEnd()();
|
|
@@ -141,30 +142,30 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
141
142
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
142
143
|
i0.ɵɵnamespaceSVG();
|
|
143
144
|
i0.ɵɵelementContainerStart(0);
|
|
144
|
-
i0.ɵɵelementStart(1, "circle",
|
|
145
|
+
i0.ɵɵelementStart(1, "circle", 87);
|
|
145
146
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_5_Template_circle_click_1_listener() { const stat_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onScopeClick(stat_r10)); });
|
|
146
147
|
i0.ɵɵelementEnd();
|
|
147
148
|
i0.ɵɵelementContainerEnd();
|
|
148
149
|
} if (rf & 2) {
|
|
149
150
|
const stat_r10 = ctx.$implicit;
|
|
150
|
-
const ɵ$
|
|
151
|
+
const ɵ$index_245_r11 = ctx.$index;
|
|
151
152
|
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
152
153
|
i0.ɵɵadvance();
|
|
153
|
-
i0.ɵɵattribute("stroke", stat_r10.color)("stroke-dasharray", stat_r10.percentage * 2.51 + " " + (251 - stat_r10.percentage * 2.51))("stroke-dashoffset", ctx_r1.getDonutOffset(ɵ$
|
|
154
|
+
i0.ɵɵattribute("stroke", stat_r10.color)("stroke-dasharray", stat_r10.percentage * 2.51 + " " + (251 - stat_r10.percentage * 2.51))("stroke-dashoffset", ctx_r1.getDonutOffset(ɵ$index_245_r11));
|
|
154
155
|
} }
|
|
155
156
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template(rf, ctx) { if (rf & 1) {
|
|
156
157
|
const _r12 = i0.ɵɵgetCurrentView();
|
|
157
|
-
i0.ɵɵelementStart(0, "div",
|
|
158
|
+
i0.ɵɵelementStart(0, "div", 88);
|
|
158
159
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template_div_click_0_listener() { const stat_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onScopeClick(stat_r13)); });
|
|
159
|
-
i0.ɵɵelement(1, "div",
|
|
160
|
-
i0.ɵɵelementStart(2, "div",
|
|
160
|
+
i0.ɵɵelement(1, "div", 89);
|
|
161
|
+
i0.ɵɵelementStart(2, "div", 90)(3, "div", 91);
|
|
161
162
|
i0.ɵɵelement(4, "i");
|
|
162
163
|
i0.ɵɵtext(5);
|
|
163
164
|
i0.ɵɵelementEnd();
|
|
164
|
-
i0.ɵɵelementStart(6, "div",
|
|
165
|
+
i0.ɵɵelementStart(6, "div", 92);
|
|
165
166
|
i0.ɵɵtext(7);
|
|
166
167
|
i0.ɵɵelementEnd()();
|
|
167
|
-
i0.ɵɵelement(8, "i",
|
|
168
|
+
i0.ɵɵelement(8, "i", 93);
|
|
168
169
|
i0.ɵɵelementEnd();
|
|
169
170
|
} if (rf & 2) {
|
|
170
171
|
const stat_r13 = ctx.$implicit;
|
|
@@ -178,21 +179,21 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
178
179
|
i0.ɵɵtextInterpolate1("", stat_r13.count, " scopes");
|
|
179
180
|
} }
|
|
180
181
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_Template(rf, ctx) { if (rf & 1) {
|
|
181
|
-
i0.ɵɵelementStart(0, "div",
|
|
182
|
+
i0.ɵɵelementStart(0, "div", 55)(1, "div", 79);
|
|
182
183
|
i0.ɵɵnamespaceSVG();
|
|
183
|
-
i0.ɵɵelementStart(2, "svg",
|
|
184
|
-
i0.ɵɵelement(3, "circle",
|
|
184
|
+
i0.ɵɵelementStart(2, "svg", 80);
|
|
185
|
+
i0.ɵɵelement(3, "circle", 81);
|
|
185
186
|
i0.ɵɵrepeaterCreate(4, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_5_Template, 2, 3, ":svg:ng-container", null, i0.ɵɵrepeaterTrackByIdentity);
|
|
186
187
|
i0.ɵɵelementEnd();
|
|
187
188
|
i0.ɵɵnamespaceHTML();
|
|
188
|
-
i0.ɵɵelementStart(6, "div",
|
|
189
|
+
i0.ɵɵelementStart(6, "div", 82)(7, "div", 83);
|
|
189
190
|
i0.ɵɵtext(8);
|
|
190
191
|
i0.ɵɵelementEnd();
|
|
191
|
-
i0.ɵɵelementStart(9, "div",
|
|
192
|
+
i0.ɵɵelementStart(9, "div", 84);
|
|
192
193
|
i0.ɵɵtext(10, "Categories");
|
|
193
194
|
i0.ɵɵelementEnd()()();
|
|
194
|
-
i0.ɵɵelementStart(11, "div",
|
|
195
|
-
i0.ɵɵrepeaterCreate(12, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template, 9, 6, "div",
|
|
195
|
+
i0.ɵɵelementStart(11, "div", 85);
|
|
196
|
+
i0.ɵɵrepeaterCreate(12, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_For_13_Template, 9, 6, "div", 86, i0.ɵɵrepeaterTrackByIdentity);
|
|
196
197
|
i0.ɵɵelementEnd()();
|
|
197
198
|
} if (rf & 2) {
|
|
198
199
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
@@ -204,14 +205,14 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
204
205
|
i0.ɵɵrepeater(ctx_r1.ScopeStats);
|
|
205
206
|
} }
|
|
206
207
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_86_Template(rf, ctx) { if (rf & 1) {
|
|
207
|
-
i0.ɵɵelementStart(0, "div",
|
|
208
|
-
i0.ɵɵelement(1, "i",
|
|
208
|
+
i0.ɵɵelementStart(0, "div", 52);
|
|
209
|
+
i0.ɵɵelement(1, "i", 44);
|
|
209
210
|
i0.ɵɵelementStart(2, "span");
|
|
210
211
|
i0.ɵɵtext(3, "No scopes configured");
|
|
211
212
|
i0.ɵɵelementEnd()();
|
|
212
213
|
} }
|
|
213
214
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
214
|
-
i0.ɵɵelementStart(0, "span",
|
|
215
|
+
i0.ɵɵelementStart(0, "span", 101);
|
|
215
216
|
i0.ɵɵtext(1);
|
|
216
217
|
i0.ɵɵelementEnd();
|
|
217
218
|
} if (rf & 2) {
|
|
@@ -221,20 +222,20 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
221
222
|
} }
|
|
222
223
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
223
224
|
const _r14 = i0.ɵɵgetCurrentView();
|
|
224
|
-
i0.ɵɵelementStart(0, "div",
|
|
225
|
+
i0.ɵɵelementStart(0, "div", 95);
|
|
225
226
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template_div_click_0_listener() { const activity_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onActivityClick(activity_r15)); });
|
|
226
|
-
i0.ɵɵelementStart(1, "div",
|
|
227
|
+
i0.ɵɵelementStart(1, "div", 96);
|
|
227
228
|
i0.ɵɵelement(2, "i");
|
|
228
229
|
i0.ɵɵelementEnd();
|
|
229
|
-
i0.ɵɵelementStart(3, "div",
|
|
230
|
+
i0.ɵɵelementStart(3, "div", 97)(4, "div", 98);
|
|
230
231
|
i0.ɵɵtext(5);
|
|
231
232
|
i0.ɵɵelementEnd();
|
|
232
|
-
i0.ɵɵelementStart(6, "div",
|
|
233
|
+
i0.ɵɵelementStart(6, "div", 99)(7, "span", 100);
|
|
233
234
|
i0.ɵɵtext(8);
|
|
234
235
|
i0.ɵɵelementEnd();
|
|
235
|
-
i0.ɵɵconditionalCreate(9, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Conditional_9_Template, 2, 1, "span",
|
|
236
|
+
i0.ɵɵconditionalCreate(9, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Conditional_9_Template, 2, 1, "span", 101);
|
|
236
237
|
i0.ɵɵelementEnd()();
|
|
237
|
-
i0.ɵɵelementStart(10, "div",
|
|
238
|
+
i0.ɵɵelementStart(10, "div", 102);
|
|
238
239
|
i0.ɵɵtext(11);
|
|
239
240
|
i0.ɵɵelementEnd()();
|
|
240
241
|
} if (rf & 2) {
|
|
@@ -254,8 +255,8 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
254
255
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.formatDate(activity_r15.date), " ");
|
|
255
256
|
} }
|
|
256
257
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_Template(rf, ctx) { if (rf & 1) {
|
|
257
|
-
i0.ɵɵelementStart(0, "div",
|
|
258
|
-
i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template, 12, 7, "div",
|
|
258
|
+
i0.ɵɵelementStart(0, "div", 58);
|
|
259
|
+
i0.ɵɵrepeaterCreate(1, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_For_2_Template, 12, 7, "div", 94, i0.ɵɵrepeaterTrackByIdentity);
|
|
259
260
|
i0.ɵɵelementEnd();
|
|
260
261
|
} if (rf & 2) {
|
|
261
262
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
@@ -263,164 +264,164 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Cond
|
|
|
263
264
|
i0.ɵɵrepeater(ctx_r1.RecentActivity);
|
|
264
265
|
} }
|
|
265
266
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_95_Template(rf, ctx) { if (rf & 1) {
|
|
266
|
-
i0.ɵɵelementStart(0, "div",
|
|
267
|
-
i0.ɵɵelement(1, "i",
|
|
267
|
+
i0.ɵɵelementStart(0, "div", 52);
|
|
268
|
+
i0.ɵɵelement(1, "i", 103);
|
|
268
269
|
i0.ɵɵelementStart(2, "span");
|
|
269
270
|
i0.ɵɵtext(3, "No recent activity");
|
|
270
271
|
i0.ɵɵelementEnd()();
|
|
271
272
|
} }
|
|
272
273
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template(rf, ctx) { if (rf & 1) {
|
|
273
274
|
const _r16 = i0.ɵɵgetCurrentView();
|
|
274
|
-
i0.ɵɵelementStart(0, "div",
|
|
275
|
+
i0.ɵɵelementStart(0, "div", 59)(1, "div", 104);
|
|
275
276
|
i0.ɵɵtext(2, "Quick Actions");
|
|
276
277
|
i0.ɵɵelementEnd();
|
|
277
|
-
i0.ɵɵelementStart(3, "div",
|
|
278
|
+
i0.ɵɵelementStart(3, "div", 105)(4, "button", 106);
|
|
278
279
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
|
|
279
|
-
i0.ɵɵelement(5, "i",
|
|
280
|
+
i0.ɵɵelement(5, "i", 107);
|
|
280
281
|
i0.ɵɵelementStart(6, "span");
|
|
281
282
|
i0.ɵɵtext(7, "Generate Key");
|
|
282
283
|
i0.ɵɵelementEnd()();
|
|
283
|
-
i0.ɵɵelementStart(8, "button",
|
|
284
|
+
i0.ɵɵelementStart(8, "button", 106);
|
|
284
285
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
|
|
285
|
-
i0.ɵɵelement(9, "i",
|
|
286
|
+
i0.ɵɵelement(9, "i", 108);
|
|
286
287
|
i0.ɵɵelementStart(10, "span");
|
|
287
288
|
i0.ɵɵtext(11, "View All Keys");
|
|
288
289
|
i0.ɵɵelementEnd()();
|
|
289
|
-
i0.ɵɵelementStart(12, "button",
|
|
290
|
+
i0.ɵɵelementStart(12, "button", 106);
|
|
290
291
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
|
|
291
|
-
i0.ɵɵelement(13, "i",
|
|
292
|
+
i0.ɵɵelement(13, "i", 41);
|
|
292
293
|
i0.ɵɵelementStart(14, "span");
|
|
293
294
|
i0.ɵɵtext(15, "Expiring Keys");
|
|
294
295
|
i0.ɵɵelementEnd()();
|
|
295
|
-
i0.ɵɵelementStart(16, "button",
|
|
296
|
+
i0.ɵɵelementStart(16, "button", 106);
|
|
296
297
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.showListView("never-used")); });
|
|
297
|
-
i0.ɵɵelement(17, "i",
|
|
298
|
+
i0.ɵɵelement(17, "i", 67);
|
|
298
299
|
i0.ɵɵelementStart(18, "span");
|
|
299
300
|
i0.ɵɵtext(19, "Never Used");
|
|
300
301
|
i0.ɵɵelementEnd()()()();
|
|
301
302
|
} }
|
|
302
303
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
303
304
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
304
|
-
i0.ɵɵelementStart(0, "div",
|
|
305
|
+
i0.ɵɵelementStart(0, "div", 14)(1, "div", 15)(2, "div", 16);
|
|
305
306
|
i0.ɵɵnamespaceSVG();
|
|
306
|
-
i0.ɵɵelementStart(3, "svg",
|
|
307
|
-
i0.ɵɵelement(4, "path",
|
|
307
|
+
i0.ɵɵelementStart(3, "svg", 17);
|
|
308
|
+
i0.ɵɵelement(4, "path", 18)(5, "path", 19);
|
|
308
309
|
i0.ɵɵelementEnd();
|
|
309
310
|
i0.ɵɵnamespaceHTML();
|
|
310
|
-
i0.ɵɵelementStart(6, "div",
|
|
311
|
+
i0.ɵɵelementStart(6, "div", 20);
|
|
311
312
|
i0.ɵɵtext(7);
|
|
312
313
|
i0.ɵɵelementEnd()()();
|
|
313
|
-
i0.ɵɵelementStart(8, "div",
|
|
314
|
+
i0.ɵɵelementStart(8, "div", 21)(9, "div", 22);
|
|
314
315
|
i0.ɵɵtext(10);
|
|
315
316
|
i0.ɵɵelementEnd();
|
|
316
|
-
i0.ɵɵelementStart(11, "div",
|
|
317
|
-
i0.ɵɵconditionalCreate(12, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template, 3, 1, "span",
|
|
318
|
-
i0.ɵɵconditionalCreate(13, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template, 3, 1, "span",
|
|
319
|
-
i0.ɵɵconditionalCreate(14, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template, 3, 1, "span",
|
|
320
|
-
i0.ɵɵconditionalCreate(15, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_15_Template, 3, 0, "span",
|
|
317
|
+
i0.ɵɵelementStart(11, "div", 23);
|
|
318
|
+
i0.ɵɵconditionalCreate(12, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_12_Template, 3, 1, "span", 24);
|
|
319
|
+
i0.ɵɵconditionalCreate(13, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_13_Template, 3, 1, "span", 25);
|
|
320
|
+
i0.ɵɵconditionalCreate(14, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_14_Template, 3, 1, "span", 26);
|
|
321
|
+
i0.ɵɵconditionalCreate(15, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_15_Template, 3, 0, "span", 27);
|
|
321
322
|
i0.ɵɵelementEnd()()();
|
|
322
|
-
i0.ɵɵelementStart(16, "div",
|
|
323
|
+
i0.ɵɵelementStart(16, "div", 28)(17, "div", 29);
|
|
323
324
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_17_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
|
|
324
|
-
i0.ɵɵelementStart(18, "div",
|
|
325
|
-
i0.ɵɵelement(19, "i",
|
|
325
|
+
i0.ɵɵelementStart(18, "div", 30);
|
|
326
|
+
i0.ɵɵelement(19, "i", 31);
|
|
326
327
|
i0.ɵɵelementEnd();
|
|
327
|
-
i0.ɵɵelementStart(20, "div",
|
|
328
|
+
i0.ɵɵelementStart(20, "div", 32)(21, "div", 33);
|
|
328
329
|
i0.ɵɵtext(22);
|
|
329
330
|
i0.ɵɵelementEnd();
|
|
330
|
-
i0.ɵɵelementStart(23, "div",
|
|
331
|
+
i0.ɵɵelementStart(23, "div", 34);
|
|
331
332
|
i0.ɵɵtext(24, "Total Keys");
|
|
332
333
|
i0.ɵɵelementEnd()();
|
|
333
|
-
i0.ɵɵelementStart(25, "div",
|
|
334
|
-
i0.ɵɵelement(26, "i",
|
|
334
|
+
i0.ɵɵelementStart(25, "div", 35);
|
|
335
|
+
i0.ɵɵelement(26, "i", 36);
|
|
335
336
|
i0.ɵɵelementEnd()();
|
|
336
|
-
i0.ɵɵelementStart(27, "div",
|
|
337
|
+
i0.ɵɵelementStart(27, "div", 37);
|
|
337
338
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_27_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("active")); });
|
|
338
|
-
i0.ɵɵelementStart(28, "div",
|
|
339
|
-
i0.ɵɵelement(29, "i",
|
|
339
|
+
i0.ɵɵelementStart(28, "div", 30);
|
|
340
|
+
i0.ɵɵelement(29, "i", 38);
|
|
340
341
|
i0.ɵɵelementEnd();
|
|
341
|
-
i0.ɵɵelementStart(30, "div",
|
|
342
|
+
i0.ɵɵelementStart(30, "div", 32)(31, "div", 33);
|
|
342
343
|
i0.ɵɵtext(32);
|
|
343
344
|
i0.ɵɵelementEnd();
|
|
344
|
-
i0.ɵɵelementStart(33, "div",
|
|
345
|
+
i0.ɵɵelementStart(33, "div", 34);
|
|
345
346
|
i0.ɵɵtext(34, "Active");
|
|
346
347
|
i0.ɵɵelementEnd()();
|
|
347
|
-
i0.ɵɵelementStart(35, "div",
|
|
348
|
+
i0.ɵɵelementStart(35, "div", 39)(36, "span", 40);
|
|
348
349
|
i0.ɵɵtext(37);
|
|
349
350
|
i0.ɵɵelementEnd()()();
|
|
350
|
-
i0.ɵɵelementStart(38, "div",
|
|
351
|
+
i0.ɵɵelementStart(38, "div", 29);
|
|
351
352
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_38_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("expiring")); });
|
|
352
|
-
i0.ɵɵelementStart(39, "div",
|
|
353
|
-
i0.ɵɵelement(40, "i",
|
|
353
|
+
i0.ɵɵelementStart(39, "div", 30);
|
|
354
|
+
i0.ɵɵelement(40, "i", 41);
|
|
354
355
|
i0.ɵɵelementEnd();
|
|
355
|
-
i0.ɵɵelementStart(41, "div",
|
|
356
|
+
i0.ɵɵelementStart(41, "div", 32)(42, "div", 33);
|
|
356
357
|
i0.ɵɵtext(43);
|
|
357
358
|
i0.ɵɵelementEnd();
|
|
358
|
-
i0.ɵɵelementStart(44, "div",
|
|
359
|
+
i0.ɵɵelementStart(44, "div", 34);
|
|
359
360
|
i0.ɵɵtext(45, "Expiring Soon");
|
|
360
361
|
i0.ɵɵelementEnd()();
|
|
361
|
-
i0.ɵɵconditionalCreate(46, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_46_Template, 2, 0, "div",
|
|
362
|
+
i0.ɵɵconditionalCreate(46, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_46_Template, 2, 0, "div", 42);
|
|
362
363
|
i0.ɵɵelementEnd();
|
|
363
|
-
i0.ɵɵelementStart(47, "div",
|
|
364
|
+
i0.ɵɵelementStart(47, "div", 29);
|
|
364
365
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_47_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("revoked")); });
|
|
365
|
-
i0.ɵɵelementStart(48, "div",
|
|
366
|
-
i0.ɵɵelement(49, "i",
|
|
366
|
+
i0.ɵɵelementStart(48, "div", 30);
|
|
367
|
+
i0.ɵɵelement(49, "i", 43);
|
|
367
368
|
i0.ɵɵelementEnd();
|
|
368
|
-
i0.ɵɵelementStart(50, "div",
|
|
369
|
+
i0.ɵɵelementStart(50, "div", 32)(51, "div", 33);
|
|
369
370
|
i0.ɵɵtext(52);
|
|
370
371
|
i0.ɵɵelementEnd();
|
|
371
|
-
i0.ɵɵelementStart(53, "div",
|
|
372
|
+
i0.ɵɵelementStart(53, "div", 34);
|
|
372
373
|
i0.ɵɵtext(54, "Revoked");
|
|
373
374
|
i0.ɵɵelementEnd()()();
|
|
374
|
-
i0.ɵɵelementStart(55, "div",
|
|
375
|
+
i0.ɵɵelementStart(55, "div", 29);
|
|
375
376
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_div_click_55_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.switchTab("scopes")); });
|
|
376
|
-
i0.ɵɵelementStart(56, "div",
|
|
377
|
-
i0.ɵɵelement(57, "i",
|
|
377
|
+
i0.ɵɵelementStart(56, "div", 30);
|
|
378
|
+
i0.ɵɵelement(57, "i", 44);
|
|
378
379
|
i0.ɵɵelementEnd();
|
|
379
|
-
i0.ɵɵelementStart(58, "div",
|
|
380
|
+
i0.ɵɵelementStart(58, "div", 32)(59, "div", 33);
|
|
380
381
|
i0.ɵɵtext(60);
|
|
381
382
|
i0.ɵɵelementEnd();
|
|
382
|
-
i0.ɵɵelementStart(61, "div",
|
|
383
|
+
i0.ɵɵelementStart(61, "div", 34);
|
|
383
384
|
i0.ɵɵtext(62, "Scope Categories");
|
|
384
385
|
i0.ɵɵelementEnd()()()();
|
|
385
|
-
i0.ɵɵelementStart(63, "div",
|
|
386
|
-
i0.ɵɵelement(67, "i",
|
|
386
|
+
i0.ɵɵelementStart(63, "div", 45)(64, "div", 46)(65, "div", 47)(66, "div", 48);
|
|
387
|
+
i0.ɵɵelement(67, "i", 31);
|
|
387
388
|
i0.ɵɵelementStart(68, "span");
|
|
388
389
|
i0.ɵɵtext(69, "Recently Used Keys");
|
|
389
390
|
i0.ɵɵelementEnd()();
|
|
390
|
-
i0.ɵɵelementStart(70, "button",
|
|
391
|
+
i0.ɵɵelementStart(70, "button", 49);
|
|
391
392
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Template_button_click_70_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showListView("all")); });
|
|
392
393
|
i0.ɵɵtext(71, " View All ");
|
|
393
|
-
i0.ɵɵelement(72, "i",
|
|
394
|
+
i0.ɵɵelement(72, "i", 36);
|
|
394
395
|
i0.ɵɵelementEnd()();
|
|
395
|
-
i0.ɵɵelementStart(73, "div",
|
|
396
|
-
i0.ɵɵconditionalCreate(74, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_Template, 3, 0, "div",
|
|
397
|
-
i0.ɵɵconditionalCreate(75, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_75_Template, 4, 0, "div",
|
|
396
|
+
i0.ɵɵelementStart(73, "div", 50);
|
|
397
|
+
i0.ɵɵconditionalCreate(74, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_74_Template, 3, 0, "div", 51);
|
|
398
|
+
i0.ɵɵconditionalCreate(75, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_75_Template, 4, 0, "div", 52);
|
|
398
399
|
i0.ɵɵelementEnd()();
|
|
399
|
-
i0.ɵɵelementStart(76, "div",
|
|
400
|
-
i0.ɵɵelement(79, "i",
|
|
400
|
+
i0.ɵɵelementStart(76, "div", 53)(77, "div", 47)(78, "div", 48);
|
|
401
|
+
i0.ɵɵelement(79, "i", 44);
|
|
401
402
|
i0.ɵɵelementStart(80, "span");
|
|
402
403
|
i0.ɵɵtext(81, "Permission Scopes");
|
|
403
404
|
i0.ɵɵelementEnd()();
|
|
404
|
-
i0.ɵɵelementStart(82, "span",
|
|
405
|
+
i0.ɵɵelementStart(82, "span", 54);
|
|
405
406
|
i0.ɵɵtext(83, "Available scope categories");
|
|
406
407
|
i0.ɵɵelementEnd()();
|
|
407
|
-
i0.ɵɵelementStart(84, "div",
|
|
408
|
-
i0.ɵɵconditionalCreate(85, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_Template, 14, 1, "div",
|
|
409
|
-
i0.ɵɵconditionalCreate(86, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_86_Template, 4, 0, "div",
|
|
408
|
+
i0.ɵɵelementStart(84, "div", 50);
|
|
409
|
+
i0.ɵɵconditionalCreate(85, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_85_Template, 14, 1, "div", 55);
|
|
410
|
+
i0.ɵɵconditionalCreate(86, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_86_Template, 4, 0, "div", 52);
|
|
410
411
|
i0.ɵɵelementEnd()();
|
|
411
|
-
i0.ɵɵelementStart(87, "div",
|
|
412
|
-
i0.ɵɵelement(90, "i",
|
|
412
|
+
i0.ɵɵelementStart(87, "div", 56)(88, "div", 47)(89, "div", 48);
|
|
413
|
+
i0.ɵɵelement(90, "i", 57);
|
|
413
414
|
i0.ɵɵelementStart(91, "span");
|
|
414
415
|
i0.ɵɵtext(92, "Recent Activity");
|
|
415
416
|
i0.ɵɵelementEnd()()();
|
|
416
|
-
i0.ɵɵelementStart(93, "div",
|
|
417
|
-
i0.ɵɵconditionalCreate(94, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_Template, 3, 0, "div",
|
|
418
|
-
i0.ɵɵconditionalCreate(95, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_95_Template, 4, 0, "div",
|
|
417
|
+
i0.ɵɵelementStart(93, "div", 50);
|
|
418
|
+
i0.ɵɵconditionalCreate(94, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_94_Template, 3, 0, "div", 58);
|
|
419
|
+
i0.ɵɵconditionalCreate(95, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_95_Template, 4, 0, "div", 52);
|
|
419
420
|
i0.ɵɵelementEnd()()();
|
|
420
|
-
i0.ɵɵconditionalCreate(96, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template, 20, 0, "div",
|
|
421
|
-
i0.ɵɵelementStart(97, "div",
|
|
422
|
-
i0.ɵɵelement(98, "i",
|
|
423
|
-
i0.ɵɵelementStart(99, "div",
|
|
421
|
+
i0.ɵɵconditionalCreate(96, APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Conditional_96_Template, 20, 0, "div", 59);
|
|
422
|
+
i0.ɵɵelementStart(97, "div", 60);
|
|
423
|
+
i0.ɵɵelement(98, "i", 61);
|
|
424
|
+
i0.ɵɵelementStart(99, "div", 62)(100, "strong");
|
|
424
425
|
i0.ɵɵtext(101, "Security Best Practices:");
|
|
425
426
|
i0.ɵɵelementEnd();
|
|
426
427
|
i0.ɵɵtext(102, " API keys should be rotated regularly and revoked when no longer needed. Keys are hashed and stored securely - the raw key is only shown once at creation time. All API key usage is logged for audit purposes. ");
|
|
@@ -477,12 +478,12 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_0_Temp
|
|
|
477
478
|
} }
|
|
478
479
|
function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
479
480
|
const _r17 = i0.ɵɵgetCurrentView();
|
|
480
|
-
i0.ɵɵelementStart(0, "div",
|
|
481
|
+
i0.ɵɵelementStart(0, "div", 109)(1, "button", 110);
|
|
481
482
|
i0.ɵɵlistener("click", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showOverview()); });
|
|
482
|
-
i0.ɵɵelement(2, "i",
|
|
483
|
+
i0.ɵɵelement(2, "i", 111);
|
|
483
484
|
i0.ɵɵtext(3, " Back to Overview ");
|
|
484
485
|
i0.ɵɵelementEnd()();
|
|
485
|
-
i0.ɵɵelementStart(4, "mj-api-key-list",
|
|
486
|
+
i0.ɵɵelementStart(4, "mj-api-key-list", 112, 0);
|
|
486
487
|
i0.ɵɵlistener("KeySelected", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template_mj_api_key_list_KeySelected_4_listener($event) { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onKeySelected($event)); })("CreateRequested", function APIKeysResourceComponent_Conditional_7_Conditional_1_Conditional_1_Template_mj_api_key_list_CreateRequested_4_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openCreateDialog()); });
|
|
487
488
|
i0.ɵɵelementEnd();
|
|
488
489
|
} if (rf & 2) {
|
|
@@ -501,13 +502,13 @@ function APIKeysResourceComponent_Conditional_7_Conditional_1_Template(rf, ctx)
|
|
|
501
502
|
} }
|
|
502
503
|
function APIKeysResourceComponent_Conditional_7_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
503
504
|
const _r18 = i0.ɵɵgetCurrentView();
|
|
504
|
-
i0.ɵɵelementStart(0, "mj-api-applications-panel",
|
|
505
|
+
i0.ɵɵelementStart(0, "mj-api-applications-panel", 113);
|
|
505
506
|
i0.ɵɵlistener("ApplicationUpdated", function APIKeysResourceComponent_Conditional_7_Conditional_2_Template_mj_api_applications_panel_ApplicationUpdated_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDataUpdated()); });
|
|
506
507
|
i0.ɵɵelementEnd();
|
|
507
508
|
} }
|
|
508
509
|
function APIKeysResourceComponent_Conditional_7_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
509
510
|
const _r19 = i0.ɵɵgetCurrentView();
|
|
510
|
-
i0.ɵɵelementStart(0, "mj-api-scopes-panel",
|
|
511
|
+
i0.ɵɵelementStart(0, "mj-api-scopes-panel", 114);
|
|
511
512
|
i0.ɵɵlistener("ScopeUpdated", function APIKeysResourceComponent_Conditional_7_Conditional_3_Template_mj_api_scopes_panel_ScopeUpdated_0_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDataUpdated()); });
|
|
512
513
|
i0.ɵɵelementEnd();
|
|
513
514
|
} }
|
|
@@ -1055,14 +1056,14 @@ let APIKeysResourceComponent = class APIKeysResourceComponent extends BaseResour
|
|
|
1055
1056
|
} if (rf & 2) {
|
|
1056
1057
|
let _t;
|
|
1057
1058
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.keyListComponent = _t.first);
|
|
1058
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 10, vars: 10, consts: [["keyList", ""], ["Role", "region", "AriaLabel", "API Keys", 3, "Title", "Subtitle"], ["toolbar", ""], [3, "TabChange", "Tabs", "ActiveKey"], ["actions", ""], [3, "Clicked", "Loading"], ["mjButton", "", "variant", "primary", "size", "sm", "aria-label", "Generate a new API key"], [1, "api-keys-loading"], [3, "Created", "Closed", "Visible"], [3, "Updated", "Revoked", "Closed", "Visible", "KeyId"], ["mjButton", "", "variant", "primary", "size", "sm", "aria-label", "Generate a new API key", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], ["text", "Loading API Keys..."], [1, "health-banner", 3, "ngClass"], [1, "health-score-container"], [1, "health-score-ring"], ["viewBox", "0 0 36 36", 1, "circular-chart"], ["d", "M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831", 1, "circle-bg"], ["d", "M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831", 1, "circle"], [1, "health-score-value"], [1, "health-info"], [1, "health-label"], [1, "health-details"], [1, "health-alert"], [1, "health-warning-text"], [1, "health-info-text"], [1, "health-ok"], [1, "kpi-row"], [1, "kpi-card", "clickable", 3, "click"], [1, "kpi-icon"], [1, "fa-solid", "fa-key"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-trend"], [1, "fa-solid", "fa-arrow-right"], [1, "kpi-card", "active", "clickable", 3, "click"], [1, "fa-solid", "fa-check-circle"], [1, "kpi-trend", "success"], [1, "percentage"], [1, "fa-solid", "fa-clock"], [1, "kpi-trend", "warning"], [1, "fa-solid", "fa-ban"], [1, "fa-solid", "fa-shield-halved"], [1, "content-grid"], [1, "panel", "keys-panel"], [1, "panel-header"], [1, "panel-title"], [1, "panel-action", 3, "click"], [1, "panel-body"], [1, "key-list"], [1, "empty-state"], [1, "panel", "scope-panel"], [1, "panel-subtitle"], [1, "scope-chart"], [1, "panel", "activity-panel"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "activity-list"], [1, "quick-actions"], [1, "security-notice"], [1, "fa-solid", "fa-shield-check"], [1, "notice-content"], [1, "health-alert", 3, "click"], [1, "fa-solid", "fa-circle-exclamation"], [1, "health-warning-text", 3, "click"], [1, "health-info-text", 3, "click"], [1, "fa-solid", "fa-question-circle"], [1, "key-item"], [1, "key-item", 3, "click"], [1, "key-icon"], [1, "key-info"], [1, "key-label"], [1, "key-meta"], [1, "key-user"], [1, "key-hash"], [1, "key-status"], [1, "last-used"], [1, "expiration", 3, "ngClass"], [1, "donut-chart-container"], ["viewBox", "0 0 100 100", 1, "donut-chart"], ["cx", "50", "cy", "50", "r", "40", "fill", "none", "stroke", "#e5e7eb", "stroke-width", "12"], [1, "donut-center"], [1, "donut-total"], [1, "donut-label"], [1, "scope-legend"], [1, "legend-item"], ["cx", "50", "cy", "50", "r", "40", "fill", "none", "stroke-width", "12", 1, "donut-segment", 3, "click"], [1, "legend-item", 3, "click"], [1, "legend-color"], [1, "legend-info"], [1, "legend-name"], [1, "legend-value"], [1, "fa-solid", "fa-chevron-right", "legend-arrow"], [1, "activity-item"], [1, "activity-item", 3, "click"], [1, "activity-icon", 3, "ngClass"], [1, "activity-info"], [1, "activity-name"], [1, "activity-meta"], [1, "activity-action"], [1, "activity-user"], [1, "activity-time"], [1, "fa-solid", "fa-inbox"], [1, "quick-actions-title"], [1, "quick-actions-grid"], [1, "quick-action", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fa-solid", "fa-list"], [1, "list-view-header"], [1, "back-btn", 3, "click"], [1, "fa-solid", "fa-arrow-left"], [3, "KeySelected", "CreateRequested", "Filter"], [3, "ApplicationUpdated"], [3, "ScopeUpdated"]], template: function APIKeysResourceComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1059
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 10, vars: 10, consts: [["keyList", ""], ["Role", "region", "AriaLabel", "API Keys", 3, "Title", "Subtitle"], ["toolbar", ""], [3, "TabChange", "Tabs", "ActiveKey"], ["actions", ""], [3, "Clicked", "Loading"], ["mjButton", "", "variant", "primary", "size", "sm", "aria-label", "Generate a new API key"], [1, "api-keys-loading"], [3, "Created", "Closed", "Visible"], [3, "Updated", "Revoked", "Closed", "Visible", "KeyId"], ["mjButton", "", "variant", "primary", "size", "sm", "aria-label", "Generate a new API key", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], [1, "mj-action-label"], ["text", "Loading API Keys..."], [1, "health-banner", 3, "ngClass"], [1, "health-score-container"], [1, "health-score-ring"], ["viewBox", "0 0 36 36", 1, "circular-chart"], ["d", "M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831", 1, "circle-bg"], ["d", "M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831", 1, "circle"], [1, "health-score-value"], [1, "health-info"], [1, "health-label"], [1, "health-details"], [1, "health-alert"], [1, "health-warning-text"], [1, "health-info-text"], [1, "health-ok"], [1, "kpi-row"], [1, "kpi-card", "clickable", 3, "click"], [1, "kpi-icon"], [1, "fa-solid", "fa-key"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-trend"], [1, "fa-solid", "fa-arrow-right"], [1, "kpi-card", "active", "clickable", 3, "click"], [1, "fa-solid", "fa-check-circle"], [1, "kpi-trend", "success"], [1, "percentage"], [1, "fa-solid", "fa-clock"], [1, "kpi-trend", "warning"], [1, "fa-solid", "fa-ban"], [1, "fa-solid", "fa-shield-halved"], [1, "content-grid"], [1, "panel", "keys-panel"], [1, "panel-header"], [1, "panel-title"], [1, "panel-action", 3, "click"], [1, "panel-body"], [1, "key-list"], [1, "empty-state"], [1, "panel", "scope-panel"], [1, "panel-subtitle"], [1, "scope-chart"], [1, "panel", "activity-panel"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "activity-list"], [1, "quick-actions"], [1, "security-notice"], [1, "fa-solid", "fa-shield-check"], [1, "notice-content"], [1, "health-alert", 3, "click"], [1, "fa-solid", "fa-circle-exclamation"], [1, "health-warning-text", 3, "click"], [1, "health-info-text", 3, "click"], [1, "fa-solid", "fa-question-circle"], [1, "key-item"], [1, "key-item", 3, "click"], [1, "key-icon"], [1, "key-info"], [1, "key-label"], [1, "key-meta"], [1, "key-user"], [1, "key-hash"], [1, "key-status"], [1, "last-used"], [1, "expiration", 3, "ngClass"], [1, "donut-chart-container"], ["viewBox", "0 0 100 100", 1, "donut-chart"], ["cx", "50", "cy", "50", "r", "40", "fill", "none", "stroke", "#e5e7eb", "stroke-width", "12"], [1, "donut-center"], [1, "donut-total"], [1, "donut-label"], [1, "scope-legend"], [1, "legend-item"], ["cx", "50", "cy", "50", "r", "40", "fill", "none", "stroke-width", "12", 1, "donut-segment", 3, "click"], [1, "legend-item", 3, "click"], [1, "legend-color"], [1, "legend-info"], [1, "legend-name"], [1, "legend-value"], [1, "fa-solid", "fa-chevron-right", "legend-arrow"], [1, "activity-item"], [1, "activity-item", 3, "click"], [1, "activity-icon", 3, "ngClass"], [1, "activity-info"], [1, "activity-name"], [1, "activity-meta"], [1, "activity-action"], [1, "activity-user"], [1, "activity-time"], [1, "fa-solid", "fa-inbox"], [1, "quick-actions-title"], [1, "quick-actions-grid"], [1, "quick-action", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fa-solid", "fa-list"], [1, "list-view-header"], [1, "back-btn", 3, "click"], [1, "fa-solid", "fa-arrow-left"], [3, "KeySelected", "CreateRequested", "Filter"], [3, "ApplicationUpdated"], [3, "ScopeUpdated"]], template: function APIKeysResourceComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1059
1060
|
i0.ɵɵelementStart(0, "mj-page-header-interior", 1)(1, "div", 2)(2, "mj-tab-nav", 3);
|
|
1060
1061
|
i0.ɵɵlistener("TabChange", function APIKeysResourceComponent_Template_mj_tab_nav_TabChange_2_listener($event) { return ctx.onTabChange($event); });
|
|
1061
1062
|
i0.ɵɵelementEnd()();
|
|
1062
1063
|
i0.ɵɵelementStart(3, "div", 4)(4, "mj-refresh-button", 5);
|
|
1063
1064
|
i0.ɵɵlistener("Clicked", function APIKeysResourceComponent_Template_mj_refresh_button_Clicked_4_listener() { return ctx.refresh(); });
|
|
1064
1065
|
i0.ɵɵelementEnd();
|
|
1065
|
-
i0.ɵɵconditionalCreate(5, APIKeysResourceComponent_Conditional_5_Template,
|
|
1066
|
+
i0.ɵɵconditionalCreate(5, APIKeysResourceComponent_Conditional_5_Template, 4, 0, "button", 6);
|
|
1066
1067
|
i0.ɵɵelementEnd()();
|
|
1067
1068
|
i0.ɵɵconditionalCreate(6, APIKeysResourceComponent_Conditional_6_Template, 2, 0, "div", 7)(7, APIKeysResourceComponent_Conditional_7_Template, 5, 4, "mj-page-body-interior");
|
|
1068
1069
|
i0.ɵɵelementStart(8, "mj-api-key-create-dialog", 8);
|
|
@@ -1093,7 +1094,7 @@ APIKeysResourceComponent = __decorate([
|
|
|
1093
1094
|
export { APIKeysResourceComponent };
|
|
1094
1095
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIKeysResourceComponent, [{
|
|
1095
1096
|
type: Component,
|
|
1096
|
-
args: [{ standalone: false, selector: 'mj-api-keys-resource', template: "<!--\n APIKeysResource is only ever loaded inside Admin \u2192 Identity & Access's\n left-nav shell. Per Section 9b/10 of plans/explorer-chrome-conventions.md,\n shell sub-pages must NOT render a page-level <mj-page-layout>+<mj-page-header>\n (that produces a doubled-header). Instead the body opens with an\n <mj-page-header-interior> card carrying the L2 tab nav and action chrome.\n-->\n<mj-page-header-interior\n Role=\"region\"\n AriaLabel=\"API Keys\"\n [Title]=\"currentTabTitle\"\n [Subtitle]=\"currentTabSubtitle\">\n <div toolbar>\n <mj-tab-nav\n [Tabs]=\"tabsConfig\"\n [ActiveKey]=\"MainTab\"\n (TabChange)=\"onTabChange($event)\">\n </mj-tab-nav>\n </div>\n <div actions>\n <mj-refresh-button [Loading]=\"IsLoading\" (Clicked)=\"refresh()\"></mj-refresh-button>\n @if (MainTab === 'keys' && CurrentView === 'overview' && UserCanCreateKeys) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"openCreateDialog()\" aria-label=\"Generate a new API key\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n Generate New Key\n </button>\n }\n </div>\n</mj-page-header-interior>\n\n@if (IsLoading) {\n <div class=\"api-keys-loading\">\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n </div>\n} @else {\n <mj-page-body-interior>\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View \u2014 title + Refresh + Generate New Key now live in the page chrome above. -->\n @if (CurrentView === 'overview') {\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </mj-page-body-interior>\n}\n\n<!-- Create Dialog -->\n<mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n</mj-api-key-create-dialog>\n\n<!-- Edit Panel -->\n<mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n</mj-api-key-edit-panel>\n", styles: ["/*\n APIKeysResource renders as a sub-page inside Admin \u2192 Identity & Access's\n left-nav shell. Host is a flex column so <mj-page-header-interior> pins at\n the top and <mj-page-body-interior> fills the rest. See Section 10 of\n plans/explorer-chrome-conventions.md.\n*/\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n.api-keys-loading {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* List View Header */\n.list-view-header {\n margin-bottom: 16px;\n}\n\n.back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Health Banner */\n.health-banner {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-color-accent-300);\n}\n\n.health-banner.health-critical {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error-border);\n}\n\n.health-score-container {\n margin-right: 24px;\n}\n\n.health-score-ring {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 3.8;\n}\n\n.circle {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: var(--mj-status-success);\n animation: progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning .circle {\n stroke: var(--mj-color-warning-500);\n}\n\n.health-banner.health-critical .circle {\n stroke: var(--mj-status-error);\n}\n\n@keyframes progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.health-info {\n flex: 1;\n}\n\n.health-label {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-color-success-600);\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning .health-label {\n color: var(--mj-brand-primary-hover);\n}\n\n.health-banner.health-critical .health-label {\n color: var(--mj-color-error-600);\n}\n\n.health-details {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-error-600);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert:hover {\n text-decoration: underline;\n}\n\n.health-warning-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary-hover);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text:hover {\n text-decoration: underline;\n}\n\n.health-info-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text:hover {\n text-decoration: underline;\n}\n\n.health-ok {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-success-600);\n font-weight: 500;\n font-size: 14px;\n}\n\n/* KPI Cards */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable {\n cursor: pointer;\n}\n\n.kpi-card.clickable:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.kpi-card.active .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n}\n\n.kpi-card.warning .kpi-icon {\n background: linear-gradient(135deg, var(--mj-color-warning-500) 0%, var(--mj-brand-primary-hover) 100%);\n}\n\n.kpi-card.danger .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-error) 0%, var(--mj-color-error-600) 100%);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon i {\n font-size: 20px;\n color: var(--mj-text-inverse);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--mj-text-muted);\n}\n\n.kpi-trend.success {\n color: var(--mj-status-success);\n}\n\n.kpi-trend.warning {\n color: var(--mj-color-warning-500);\n}\n\n.kpi-trend .percentage {\n font-size: 12px;\n font-weight: 600;\n}\n\n/* Content Grid */\n.content-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel {\n grid-row: span 1;\n}\n\n.scope-panel {\n grid-row: span 1;\n}\n\n.activity-panel {\n grid-column: span 2;\n}\n\n.panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.panel-title i {\n color: var(--mj-brand-primary);\n}\n\n.panel-subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-action {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.panel-body {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Key List */\n.key-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.key-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--mj-color-neutral-500) 0%, var(--mj-color-neutral-600) 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active {\n background: var(--mj-brand-primary);\n}\n\n.key-icon i {\n font-size: 16px;\n color: var(--mj-text-inverse);\n}\n\n.key-info {\n flex: 1;\n min-width: 0;\n}\n\n.key-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.key-hash {\n font-family: monospace;\n background: var(--mj-bg-surface-active);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.expiration {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.expiration.expiring-soon {\n color: var(--mj-color-warning-500);\n font-weight: 500;\n}\n\n.expiration.expiring-critical {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.expiration.expired {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n/* Scope Chart */\n.scope-chart {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment:hover {\n opacity: 0.8;\n}\n\n.donut-center {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.donut-label {\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n/* Scope Legend */\n.scope-legend {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info {\n flex: 1;\n}\n\n.legend-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name i {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-value {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n/* Activity List */\n.activity-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.activity-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, var(--mj-color-brand-100));\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.activity-icon.action-created {\n background: var(--mj-color-success-100);\n}\n\n.activity-icon.action-created i {\n color: var(--mj-color-success-600);\n}\n\n.activity-icon.action-updated {\n background: var(--mj-color-indigo-100);\n}\n\n.activity-icon.action-updated i {\n color: var(--mj-color-indigo-500);\n}\n\n.activity-icon.action-revoked {\n background: var(--mj-color-error-100);\n}\n\n.activity-icon.action-revoked i {\n color: var(--mj-color-error-600);\n}\n\n.activity-icon.action-used {\n background: var(--mj-color-brand-100);\n}\n\n.activity-icon.action-used i {\n color: var(--mj-brand-primary-hover);\n}\n\n.activity-icon.action-extended {\n background: var(--mj-color-info-100);\n}\n\n.activity-icon.action-extended i {\n color: var(--mj-status-info);\n}\n\n.activity-info {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name {\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.activity-action {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n/* Quick Actions */\n.quick-actions {\n margin-bottom: 24px;\n}\n\n.quick-actions-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n transform: translateY(-2px);\n}\n\n.quick-action i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.quick-action span {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n/* Security Notice */\n.security-notice {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, var(--mj-color-brand-50) 0%, var(--mj-color-brand-100) 100%);\n border-radius: 12px;\n border: 1px solid var(--mj-color-accent-300);\n}\n\n.security-notice i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content {\n font-size: 13px;\n color: var(--mj-color-brand-800);\n line-height: 1.5;\n}\n\n.notice-content strong {\n font-weight: 600;\n}\n\n/* ========================================\n Responsive Styles \u2014 chrome / nav responsiveness now owned by\n <mj-page-layout> + <mj-left-nav>; only inner content needs tuning here.\n ======================================== */\n\n/* Tablet */\n@media (max-width: 1024px) {\n .content-grid {\n grid-template-columns: 1fr;\n }\n\n .activity-panel {\n grid-column: span 1;\n }\n\n .scope-chart {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend {\n flex: 1;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .content-wrapper {\n padding: 16px;\n }\n\n .health-banner {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart {\n flex-direction: column;\n }\n\n .quick-actions-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list {\n grid-template-columns: 1fr;\n }\n\n .key-item {\n flex-wrap: wrap;\n }\n\n .key-status {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n/* Small Mobile */\n@media (max-width: 480px) {\n .kpi-row {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 12px 16px;\n }\n\n .kpi-icon {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n}\n"] }]
|
|
1097
|
+
args: [{ standalone: false, selector: 'mj-api-keys-resource', template: "<!--\n APIKeysResource is only ever loaded inside Admin \u2192 Identity & Access's\n left-nav shell. Per Section 9b/10 of plans/explorer-chrome-conventions.md,\n shell sub-pages must NOT render a page-level <mj-page-layout>+<mj-page-header>\n (that produces a doubled-header). Instead the body opens with an\n <mj-page-header-interior> card carrying the L2 tab nav and action chrome.\n-->\n<mj-page-header-interior\n Role=\"region\"\n AriaLabel=\"API Keys\"\n [Title]=\"currentTabTitle\"\n [Subtitle]=\"currentTabSubtitle\">\n <div toolbar>\n <mj-tab-nav\n [Tabs]=\"tabsConfig\"\n [ActiveKey]=\"MainTab\"\n (TabChange)=\"onTabChange($event)\">\n </mj-tab-nav>\n </div>\n <div actions>\n <mj-refresh-button [Loading]=\"IsLoading\" (Clicked)=\"refresh()\"></mj-refresh-button>\n @if (MainTab === 'keys' && CurrentView === 'overview' && UserCanCreateKeys) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"openCreateDialog()\" aria-label=\"Generate a new API key\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span class=\"mj-action-label\">Generate New Key</span>\n </button>\n }\n </div>\n</mj-page-header-interior>\n\n@if (IsLoading) {\n <div class=\"api-keys-loading\">\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n </div>\n} @else {\n <mj-page-body-interior>\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View \u2014 title + Refresh + Generate New Key now live in the page chrome above. -->\n @if (CurrentView === 'overview') {\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </mj-page-body-interior>\n}\n\n<!-- Create Dialog -->\n<mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n</mj-api-key-create-dialog>\n\n<!-- Edit Panel -->\n<mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n</mj-api-key-edit-panel>\n", styles: ["/*\n APIKeysResource renders as a sub-page inside Admin \u2192 Identity & Access's\n left-nav shell. Host is a flex column so <mj-page-header-interior> pins at\n the top and <mj-page-body-interior> fills the rest. See Section 10 of\n plans/explorer-chrome-conventions.md.\n*/\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n.api-keys-loading {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* List View Header */\n.list-view-header {\n margin-bottom: 16px;\n}\n\n.back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Health Banner */\n.health-banner {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-color-accent-300);\n}\n\n.health-banner.health-critical {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error-border);\n}\n\n.health-score-container {\n margin-right: 24px;\n}\n\n.health-score-ring {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 3.8;\n}\n\n.circle {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: var(--mj-status-success);\n animation: progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning .circle {\n stroke: var(--mj-color-warning-500);\n}\n\n.health-banner.health-critical .circle {\n stroke: var(--mj-status-error);\n}\n\n@keyframes progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.health-info {\n flex: 1;\n}\n\n.health-label {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-color-success-600);\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning .health-label {\n color: var(--mj-brand-primary-hover);\n}\n\n.health-banner.health-critical .health-label {\n color: var(--mj-color-error-600);\n}\n\n.health-details {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-error-600);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert:hover {\n text-decoration: underline;\n}\n\n.health-warning-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary-hover);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text:hover {\n text-decoration: underline;\n}\n\n.health-info-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text:hover {\n text-decoration: underline;\n}\n\n.health-ok {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-success-600);\n font-weight: 500;\n font-size: 14px;\n}\n\n/* KPI Cards */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable {\n cursor: pointer;\n}\n\n.kpi-card.clickable:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.kpi-card.active .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n}\n\n.kpi-card.warning .kpi-icon {\n background: linear-gradient(135deg, var(--mj-color-warning-500) 0%, var(--mj-brand-primary-hover) 100%);\n}\n\n.kpi-card.danger .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-error) 0%, var(--mj-color-error-600) 100%);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon i {\n font-size: 20px;\n color: var(--mj-text-inverse);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--mj-text-muted);\n}\n\n.kpi-trend.success {\n color: var(--mj-status-success);\n}\n\n.kpi-trend.warning {\n color: var(--mj-color-warning-500);\n}\n\n.kpi-trend .percentage {\n font-size: 12px;\n font-weight: 600;\n}\n\n/* Content Grid */\n.content-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel {\n grid-row: span 1;\n}\n\n.scope-panel {\n grid-row: span 1;\n}\n\n.activity-panel {\n grid-column: span 2;\n}\n\n.panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.panel-title i {\n color: var(--mj-brand-primary);\n}\n\n.panel-subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-action {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.panel-body {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Key List */\n.key-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.key-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--mj-color-neutral-500) 0%, var(--mj-color-neutral-600) 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active {\n background: var(--mj-brand-primary);\n}\n\n.key-icon i {\n font-size: 16px;\n color: var(--mj-text-inverse);\n}\n\n.key-info {\n flex: 1;\n min-width: 0;\n}\n\n.key-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.key-hash {\n font-family: monospace;\n background: var(--mj-bg-surface-active);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.expiration {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.expiration.expiring-soon {\n color: var(--mj-color-warning-500);\n font-weight: 500;\n}\n\n.expiration.expiring-critical {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.expiration.expired {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n/* Scope Chart */\n.scope-chart {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment:hover {\n opacity: 0.8;\n}\n\n.donut-center {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.donut-label {\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n/* Scope Legend */\n.scope-legend {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info {\n flex: 1;\n}\n\n.legend-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name i {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-value {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n/* Activity List */\n.activity-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.activity-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, var(--mj-color-brand-100));\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.activity-icon.action-created {\n background: var(--mj-color-success-100);\n}\n\n.activity-icon.action-created i {\n color: var(--mj-color-success-600);\n}\n\n.activity-icon.action-updated {\n background: var(--mj-color-indigo-100);\n}\n\n.activity-icon.action-updated i {\n color: var(--mj-color-indigo-500);\n}\n\n.activity-icon.action-revoked {\n background: var(--mj-color-error-100);\n}\n\n.activity-icon.action-revoked i {\n color: var(--mj-color-error-600);\n}\n\n.activity-icon.action-used {\n background: var(--mj-color-brand-100);\n}\n\n.activity-icon.action-used i {\n color: var(--mj-brand-primary-hover);\n}\n\n.activity-icon.action-extended {\n background: var(--mj-color-info-100);\n}\n\n.activity-icon.action-extended i {\n color: var(--mj-status-info);\n}\n\n.activity-info {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name {\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.activity-action {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n/* Quick Actions */\n.quick-actions {\n margin-bottom: 24px;\n}\n\n.quick-actions-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n transform: translateY(-2px);\n}\n\n.quick-action i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.quick-action span {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n/* Security Notice */\n.security-notice {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, var(--mj-color-brand-50) 0%, var(--mj-color-brand-100) 100%);\n border-radius: 12px;\n border: 1px solid var(--mj-color-accent-300);\n}\n\n.security-notice i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content {\n font-size: 13px;\n color: var(--mj-color-brand-800);\n line-height: 1.5;\n}\n\n.notice-content strong {\n font-weight: 600;\n}\n\n/* ========================================\n Responsive Styles \u2014 chrome / nav responsiveness now owned by\n <mj-page-layout> + <mj-left-nav>; only inner content needs tuning here.\n ======================================== */\n\n/* Tablet */\n@media (max-width: 1024px) {\n .content-grid {\n grid-template-columns: 1fr;\n }\n\n .activity-panel {\n grid-column: span 1;\n }\n\n .scope-chart {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend {\n flex: 1;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .content-wrapper {\n padding: 16px;\n }\n\n .health-banner {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart {\n flex-direction: column;\n }\n\n .quick-actions-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list {\n grid-template-columns: 1fr;\n }\n\n .key-item {\n flex-wrap: wrap;\n }\n\n .key-status {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n/* Small Mobile */\n@media (max-width: 480px) {\n .kpi-row {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 12px 16px;\n }\n\n .kpi-icon {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n}\n"] }]
|
|
1097
1098
|
}], () => [{ type: i0.ChangeDetectorRef }], { keyListComponent: [{
|
|
1098
1099
|
type: ViewChild,
|
|
1099
1100
|
args: ['keyList']
|