@memberjunction/ng-dashboards 5.10.1 → 5.12.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/dist/AI/components/agents/agent-configuration.component.d.ts +34 -2
- package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +586 -223
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +2 -2
- package/dist/AI/components/agents/agent-filter-panel.component.d.ts +8 -0
- package/dist/AI/components/agents/agent-filter-panel.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-filter-panel.component.js +85 -52
- package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
- package/dist/AI/components/charts/performance-heatmap.component.d.ts +1 -0
- package/dist/AI/components/charts/performance-heatmap.component.d.ts.map +1 -1
- package/dist/AI/components/charts/performance-heatmap.component.js +27 -5
- package/dist/AI/components/charts/performance-heatmap.component.js.map +1 -1
- package/dist/AI/components/charts/time-series-chart.component.d.ts +5 -0
- package/dist/AI/components/charts/time-series-chart.component.d.ts.map +1 -1
- package/dist/AI/components/charts/time-series-chart.component.js +23 -8
- package/dist/AI/components/charts/time-series-chart.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +2 -2
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +2 -2
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +2 -2
- package/dist/AI/components/prompts/prompt-filter-panel.component.js +2 -2
- package/dist/AI/components/prompts/prompt-management.component.js +3 -3
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js +2 -2
- package/dist/AI/components/requests/agent-requests-resource.component.d.ts +83 -0
- package/dist/AI/components/requests/agent-requests-resource.component.d.ts.map +1 -0
- package/dist/AI/components/requests/agent-requests-resource.component.js +547 -0
- package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -0
- package/dist/AI/components/system/system-config-filter-panel.component.js +2 -2
- package/dist/AI/components/system/system-configuration.component.js +2 -2
- package/dist/AI/components/widgets/kpi-card.component.js +7 -7
- package/dist/AI/components/widgets/kpi-card.component.js.map +1 -1
- package/dist/AI/components/widgets/live-execution-widget.component.d.ts.map +1 -1
- package/dist/AI/components/widgets/live-execution-widget.component.js +6 -6
- package/dist/AI/components/widgets/live-execution-widget.component.js.map +1 -1
- package/dist/AI/index.d.ts +1 -0
- package/dist/AI/index.d.ts.map +1 -1
- package/dist/AI/index.js +2 -0
- package/dist/AI/index.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +3 -3
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.js +3 -3
- package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-list.component.js +3 -3
- package/dist/APIKeys/api-key-list.component.js.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +1 -1
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +2 -2
- package/dist/APIKeys/api-usage-panel.component.js +2 -2
- package/dist/Actions/components/actions-overview.component.js +2 -2
- package/dist/Actions/components/execution-monitoring.component.js +2 -2
- package/dist/Actions/components/explorer/action-breadcrumb.component.js +2 -2
- package/dist/Actions/components/explorer/action-card.component.js +2 -2
- package/dist/Actions/components/explorer/action-explorer.component.js +2 -2
- package/dist/Actions/components/explorer/action-list-item.component.js +2 -2
- package/dist/Actions/components/explorer/action-toolbar.component.js +2 -2
- package/dist/Actions/components/explorer/action-tree-panel.component.js +2 -2
- package/dist/Actions/components/explorer/new-action-panel.component.js +2 -2
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +2 -2
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Communication/communication-dashboard.component.js +2 -2
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +3 -3
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +5 -5
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +3 -3
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +3 -3
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +2 -2
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +2 -2
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +2 -2
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/browser/component-browser.component.js +2 -2
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +2 -2
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +2 -2
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js +2 -2
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/spec-editor.component.js +2 -2
- package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/text-import-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/workspace/component-preview.component.js +2 -2
- package/dist/ComponentStudio/components/workspace/editor-tabs.component.js +2 -2
- package/dist/ComponentStudio/components/workspace/editor-tabs.component.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +9 -9
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +11 -3
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +2 -2
- package/dist/Credentials/components/credentials-overview-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +12 -11
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +9 -9
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/Credentials/credentials-dashboard.component.js +2 -2
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +2 -2
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +2 -2
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +2 -2
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +2 -2
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +2 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +6 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +26 -8
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +2 -2
- package/dist/Integration/components/activity/activity.component.d.ts +1 -1
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +5 -5
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.d.ts +31 -2
- package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +753 -412
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +3 -3
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.d.ts +0 -1
- package/dist/Integration/components/overview/overview.component.d.ts.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +3 -6
- package/dist/Integration/components/overview/overview.component.js.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.js +3 -3
- package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.d.ts +20 -0
- package/dist/Integration/components/schedules/schedules.component.d.ts.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.js +97 -5
- package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
- package/dist/Integration/components/visual-editor/visual-editor.component.js +2 -2
- package/dist/Integration/components/widgets/integration-card.component.d.ts.map +1 -1
- package/dist/Integration/components/widgets/integration-card.component.js +5 -1
- package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
- package/dist/Integration/components/widgets/run-history-panel.component.js +2 -2
- package/dist/Integration/components/widgets/run-history-panel.component.js.map +1 -1
- package/dist/Integration/integration.module.d.ts +2 -1
- package/dist/Integration/integration.module.d.ts.map +1 -1
- package/dist/Integration/integration.module.js +7 -3
- package/dist/Integration/integration.module.js.map +1 -1
- package/dist/Integration/services/integration-data.service.d.ts +27 -2
- package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
- package/dist/Integration/services/integration-data.service.js +107 -4
- package/dist/Integration/services/integration-data.service.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +2 -2
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +2 -2
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +2 -2
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +2 -2
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/Lists/components/venn-diagram/venn-diagram.component.js +3 -3
- package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +2 -2
- package/dist/MCP/components/mcp-log-detail-panel.component.js +2 -2
- package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +2 -2
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +2 -2
- package/dist/MCP/mcp-filter-panel.component.js +2 -2
- package/dist/QueryBrowser/query-browser-resource.component.d.ts +55 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +664 -199
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/components/index.d.ts +0 -1
- package/dist/Scheduling/components/index.d.ts.map +1 -1
- package/dist/Scheduling/components/index.js +0 -1
- package/dist/Scheduling/components/index.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +2 -2
- package/dist/Scheduling/components/scheduling-jobs.component.d.ts +6 -9
- package/dist/Scheduling/components/scheduling-jobs.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +118 -110
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +3 -3
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +2 -2
- package/dist/SystemDiagnostics/system-diagnostics.component.js +4 -4
- package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
- package/dist/Testing/components/testing-analytics.component.js +2 -2
- package/dist/Testing/components/testing-analytics.component.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab.component.js +4 -4
- package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +2 -2
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-review.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-review.component.js +5 -5
- package/dist/Testing/components/testing-review.component.js.map +1 -1
- package/dist/Testing/components/testing-runs.component.js +2 -2
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/components/widgets/oracle-breakdown-table.component.js +2 -2
- package/dist/Testing/components/widgets/oracle-breakdown-table.component.js.map +1 -1
- package/dist/Testing/components/widgets/suite-tree.component.js +4 -4
- package/dist/Testing/components/widgets/suite-tree.component.js.map +1 -1
- package/dist/Testing/components/widgets/test-run-detail-panel.component.js +2 -2
- package/dist/Testing/components/widgets/test-run-detail-panel.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +2 -2
- package/dist/VersionHistory/components/diff-resource.component.js +2 -2
- package/dist/VersionHistory/components/graph-resource.component.js +2 -2
- package/dist/VersionHistory/components/labels-resource.component.js +3 -3
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +3 -3
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/__tests__/integration-data-service.test.js +1 -0
- package/dist/__tests__/integration-data-service.test.js.map +1 -1
- package/dist/module.d.ts +52 -49
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +25 -6
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +1 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +42 -40
- package/dist/Scheduling/components/job-slideout.component.d.ts +0 -45
- package/dist/Scheduling/components/job-slideout.component.d.ts.map +0 -1
- package/dist/Scheduling/components/job-slideout.component.js +0 -459
- package/dist/Scheduling/components/job-slideout.component.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor-tabs.component.js","sourceRoot":"","sources":["../../../../src/ComponentStudio/components/workspace/editor-tabs.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAwC,MAAM,eAAe,CAAC;;;;;;;;IA+BpE,iCAAiC;;;IAGjC,uCAA6C;;;IAG7C,6CAAwH;;IAA7D,AAAnC,gDAAkC,oCAAoC;;;IAG9F,6CAA0G;;IAAtD,AAA5B,yCAA2B,6BAA6B;;;IAGhF,8CAA2D;;AAiFvE,MAAM,OAAO,mBAAmB;IAKrB;IACC;IAJF,eAAe,GAAwB,IAAI,CAAC;IAEpD,YACS,KAAkC,EACjC,GAAsB;QADvB,UAAK,GAAL,KAAK,CAA6B;QACjC,QAAG,GAAH,GAAG,CAAmB;IAC7B,CAAC;IAEJ,QAAQ;QACN,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,EAAE;YAC5D,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC;YACnC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;6GAzBU,mBAAmB;6DAAnB,mBAAmB;YAlHxB,AADF,AADF,8BAAmC,aACZ,gBACoE;YAAvB,gGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,uBAAqC;YAAC,sBACxC;YAAA,iBAAS;YACT,iCAAuF;YAAvB,gGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,uBAAgC;YAAC,sBACnC;YAAA,iBAAS;YACT,iCAAuF;YAAvB,gGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,uBAA0C;YAAC,+BAC7C;YAAA,iBAAS;YACT,kCAAuF;YAAvB,iGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,wBAA4C;YAAC,yBAC/C;YAAA,iBAAS;YACT,kCAAuF;YAAvB,iGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,wBAAoC;YAAC,uBACvC;YAAA,iBAAS;YACT,2BAAgC;YAClC,iBAAM;YAEN,+BAAyB;YAcrB,AAHA,AAHA,AAHA,AAHA,wFAAW,wEAGA,8EAGA,8EAGA,+EAGA;YAKjB,AADE,iBAAM,EACF;;;YArCuB,eAAsC;YAAtC,mDAAsC;YAGtC,eAAsC;YAAtC,mDAAsC;YAGtC,eAAsC;YAAtC,mDAAsC;YAGtC,eAAsC;YAAtC,mDAAsC;YAGtC,eAAsC;YAAtC,mDAAsC;YAO/D,eAgBC;YAhBD,qDAAA,CAAC,oBAAD,CAAC,oBAAD,CAAC,oBAAD,CAAC,oBAAD,CAAC,WAgBA;;;iFA+EI,mBAAmB;cAxH/B,SAAS;6BACI,KAAK,YACP,gBAAgB,YAChB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCT;;kFA4EU,mBAAmB","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { ComponentStudioStateService } from '../../services/component-studio-state.service';\n\n@Component({\n standalone: false,\n selector: 'mj-editor-tabs',\n template: `\n <div class=\"editor-tabs-container\">\n <div class=\"tab-bar\">\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 0\" (click)=\"SelectTab(0)\">\n <i class=\"fa-solid fa-file-code\"></i> Spec\n </button>\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 1\" (click)=\"SelectTab(1)\">\n <i class=\"fa-solid fa-code\"></i> Code\n </button>\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 2\" (click)=\"SelectTab(2)\">\n <i class=\"fa-solid fa-clipboard-list\"></i> Requirements\n </button>\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 3\" (click)=\"SelectTab(3)\">\n <i class=\"fa-solid fa-drafting-compass\"></i> Design\n </button>\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 4\" (click)=\"SelectTab(4)\">\n <i class=\"fa-solid fa-database\"></i> Data\n </button>\n <span class=\"tab-spacer\"></span>\n </div>\n\n <div class=\"tab-content\">\n @switch (state.ActiveTab) {\n @case (0) {\n <mj-spec-editor></mj-spec-editor>\n }\n @case (1) {\n <mj-code-editor-panel></mj-code-editor-panel>\n }\n @case (2) {\n <mj-requirements-editor [Field]=\"'functionalRequirements'\" [Title]=\"'Functional Requirements'\"></mj-requirements-editor>\n }\n @case (3) {\n <mj-requirements-editor [Field]=\"'technicalDesign'\" [Title]=\"'Technical Design'\"></mj-requirements-editor>\n }\n @case (4) {\n <mj-data-requirements-editor></mj-data-requirements-editor>\n }\n }\n </div>\n </div>\n `,\n styles: [`\n :host {\n display: flex;\n flex: 1;\n overflow: hidden;\n }\n\n .editor-tabs-container {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n }\n\n .tab-bar {\n display: flex;\n align-items: center;\n padding: 0 8px;\n height: 38px;\n background: var(--
|
|
1
|
+
{"version":3,"file":"editor-tabs.component.js","sourceRoot":"","sources":["../../../../src/ComponentStudio/components/workspace/editor-tabs.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAwC,MAAM,eAAe,CAAC;;;;;;;;IA+BpE,iCAAiC;;;IAGjC,uCAA6C;;;IAG7C,6CAAwH;;IAA7D,AAAnC,gDAAkC,oCAAoC;;;IAG9F,6CAA0G;;IAAtD,AAA5B,yCAA2B,6BAA6B;;;IAGhF,8CAA2D;;AAiFvE,MAAM,OAAO,mBAAmB;IAKrB;IACC;IAJF,eAAe,GAAwB,IAAI,CAAC;IAEpD,YACS,KAAkC,EACjC,GAAsB;QADvB,UAAK,GAAL,KAAK,CAA6B;QACjC,QAAG,GAAH,GAAG,CAAmB;IAC7B,CAAC;IAEJ,QAAQ;QACN,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,EAAE;YAC5D,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC;YACnC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;6GAzBU,mBAAmB;6DAAnB,mBAAmB;YAlHxB,AADF,AADF,8BAAmC,aACZ,gBACoE;YAAvB,gGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,uBAAqC;YAAC,sBACxC;YAAA,iBAAS;YACT,iCAAuF;YAAvB,gGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,uBAAgC;YAAC,sBACnC;YAAA,iBAAS;YACT,iCAAuF;YAAvB,gGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,uBAA0C;YAAC,+BAC7C;YAAA,iBAAS;YACT,kCAAuF;YAAvB,iGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,wBAA4C;YAAC,yBAC/C;YAAA,iBAAS;YACT,kCAAuF;YAAvB,iGAAS,cAAU,CAAC,CAAC,IAAC;YACpF,wBAAoC;YAAC,uBACvC;YAAA,iBAAS;YACT,2BAAgC;YAClC,iBAAM;YAEN,+BAAyB;YAcrB,AAHA,AAHA,AAHA,AAHA,wFAAW,wEAGA,8EAGA,8EAGA,+EAGA;YAKjB,AADE,iBAAM,EACF;;;YArCuB,eAAsC;YAAtC,mDAAsC;YAGtC,eAAsC;YAAtC,mDAAsC;YAGtC,eAAsC;YAAtC,mDAAsC;YAGtC,eAAsC;YAAtC,mDAAsC;YAGtC,eAAsC;YAAtC,mDAAsC;YAO/D,eAgBC;YAhBD,qDAAA,CAAC,oBAAD,CAAC,oBAAD,CAAC,oBAAD,CAAC,oBAAD,CAAC,WAgBA;;;iFA+EI,mBAAmB;cAxH/B,SAAS;6BACI,KAAK,YACP,gBAAgB,YAChB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCT;;kFA4EU,mBAAmB","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { ComponentStudioStateService } from '../../services/component-studio-state.service';\n\n@Component({\n standalone: false,\n selector: 'mj-editor-tabs',\n template: `\n <div class=\"editor-tabs-container\">\n <div class=\"tab-bar\">\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 0\" (click)=\"SelectTab(0)\">\n <i class=\"fa-solid fa-file-code\"></i> Spec\n </button>\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 1\" (click)=\"SelectTab(1)\">\n <i class=\"fa-solid fa-code\"></i> Code\n </button>\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 2\" (click)=\"SelectTab(2)\">\n <i class=\"fa-solid fa-clipboard-list\"></i> Requirements\n </button>\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 3\" (click)=\"SelectTab(3)\">\n <i class=\"fa-solid fa-drafting-compass\"></i> Design\n </button>\n <button class=\"tab-pill\" [class.active]=\"state.ActiveTab === 4\" (click)=\"SelectTab(4)\">\n <i class=\"fa-solid fa-database\"></i> Data\n </button>\n <span class=\"tab-spacer\"></span>\n </div>\n\n <div class=\"tab-content\">\n @switch (state.ActiveTab) {\n @case (0) {\n <mj-spec-editor></mj-spec-editor>\n }\n @case (1) {\n <mj-code-editor-panel></mj-code-editor-panel>\n }\n @case (2) {\n <mj-requirements-editor [Field]=\"'functionalRequirements'\" [Title]=\"'Functional Requirements'\"></mj-requirements-editor>\n }\n @case (3) {\n <mj-requirements-editor [Field]=\"'technicalDesign'\" [Title]=\"'Technical Design'\"></mj-requirements-editor>\n }\n @case (4) {\n <mj-data-requirements-editor></mj-data-requirements-editor>\n }\n }\n </div>\n </div>\n `,\n styles: [`\n :host {\n display: flex;\n flex: 1;\n overflow: hidden;\n }\n\n .editor-tabs-container {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n }\n\n .tab-bar {\n display: flex;\n align-items: center;\n padding: 0 8px;\n height: 38px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 2px;\n }\n\n .tab-pill {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n font-family: inherit;\n }\n\n .tab-pill:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .tab-pill.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n font-weight: 600;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n }\n\n .tab-pill i {\n font-size: 11px;\n }\n\n .tab-spacer {\n flex: 1;\n }\n\n .tab-content {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .tab-content > * {\n flex: 1;\n overflow: hidden;\n }\n `]\n})\nexport class EditorTabsComponent implements OnInit, OnDestroy {\n\n private stateChangedSub: Subscription | null = null;\n\n constructor(\n public state: ComponentStudioStateService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.stateChangedSub = this.state.StateChanged.subscribe(() => {\n this.cdr.detectChanges();\n });\n }\n\n ngOnDestroy(): void {\n if (this.stateChangedSub) {\n this.stateChangedSub.unsubscribe();\n this.stateChangedSub = null;\n }\n }\n\n SelectTab(index: number): void {\n this.state.ActiveTab = index;\n this.cdr.detectChanges();\n }\n\n}\n"]}
|
|
@@ -765,13 +765,13 @@ let CredentialsAuditResourceComponent = class CredentialsAuditResourceComponent
|
|
|
765
765
|
}
|
|
766
766
|
getOperationColor(operation) {
|
|
767
767
|
switch (operation.toLowerCase()) {
|
|
768
|
-
case 'access': return '
|
|
769
|
-
case 'create': return '
|
|
770
|
-
case 'update': return '
|
|
771
|
-
case 'delete': return '
|
|
772
|
-
case 'rotate': return '
|
|
773
|
-
case 'validate': return '
|
|
774
|
-
default: return '
|
|
768
|
+
case 'access': return 'var(--mj-brand-primary)';
|
|
769
|
+
case 'create': return 'var(--mj-status-success)';
|
|
770
|
+
case 'update': return 'var(--mj-status-warning)';
|
|
771
|
+
case 'delete': return 'var(--mj-status-error)';
|
|
772
|
+
case 'rotate': return 'var(--mj-brand-primary)';
|
|
773
|
+
case 'validate': return 'var(--mj-brand-primary)';
|
|
774
|
+
default: return 'var(--mj-text-secondary)';
|
|
775
775
|
}
|
|
776
776
|
}
|
|
777
777
|
formatDate(date) {
|
|
@@ -854,7 +854,7 @@ let CredentialsAuditResourceComponent = class CredentialsAuditResourceComponent
|
|
|
854
854
|
i0.ɵɵconditional(ctx.isLoading ? 1 : -1);
|
|
855
855
|
i0.ɵɵadvance();
|
|
856
856
|
i0.ɵɵconditional(!ctx.isLoading ? 2 : -1);
|
|
857
|
-
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i3.LoadingComponent], styles: [".audit-container[_ngcontent-%COMP%] {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--background-secondary, #f8fafc);\n}\n\n\n\n.audit-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 24px;\n}\n\n.header-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.audit-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n margin: 0;\n}\n\n.audit-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--text-primary, #374151);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover {\n background: var(--hover-background, #f9fafb);\n border-color: var(--accent-color, #6366f1);\n color: var(--accent-color, #6366f1);\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--hover-background, #f9fafb);\n color: var(--accent-color, #6366f1);\n}\n\n\n\n.stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.stat-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n position: relative;\n}\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 12px;\n flex-shrink: 0;\n}\n\n.stat-icon.total[_ngcontent-%COMP%] {\n background: rgba(99, 102, 241, 0.1);\n color: #6366f1;\n}\n\n.stat-icon.success[_ngcontent-%COMP%] {\n background: rgba(16, 185, 129, 0.1);\n color: #10b981;\n}\n\n.stat-icon.failed[_ngcontent-%COMP%] {\n background: rgba(239, 68, 68, 0.1);\n color: #ef4444;\n}\n\n.stat-icon.users[_ngcontent-%COMP%] {\n background: rgba(139, 92, 246, 0.1);\n color: #8b5cf6;\n}\n\n.stat-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n}\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n line-height: 1;\n}\n\n.stat-value.success[_ngcontent-%COMP%] {\n color: #10b981;\n}\n\n.stat-value.failed[_ngcontent-%COMP%] {\n color: #ef4444;\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n margin-top: 4px;\n}\n\n.stat-rate[_ngcontent-%COMP%] {\n position: absolute;\n top: 12px;\n right: 16px;\n font-size: 12px;\n font-weight: 600;\n color: #10b981;\n background: rgba(16, 185, 129, 0.1);\n padding: 4px 8px;\n border-radius: 8px;\n}\n\n\n\n.activity-chart[_ngcontent-%COMP%] {\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n padding: 20px;\n margin-bottom: 20px;\n}\n\n.chart-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n margin: 0;\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--accent-color, #6366f1);\n}\n\n.chart-container[_ngcontent-%COMP%] {\n height: 120px;\n padding: 0 4px;\n}\n\n.chart-bars[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-end;\n height: 100%;\n gap: 2px;\n}\n\n.chart-bar-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n height: 100%;\n}\n\n.chart-bar[_ngcontent-%COMP%] {\n flex: 1;\n width: 100%;\n max-width: 24px;\n display: flex;\n flex-direction: column-reverse;\n border-radius: 4px 4px 0 0;\n overflow: hidden;\n background: var(--bar-background, #f3f4f6);\n}\n\n.bar-segment[_ngcontent-%COMP%] {\n width: 100%;\n transition: height 0.3s ease;\n}\n\n.bar-segment.success[_ngcontent-%COMP%] {\n background: linear-gradient(180deg, #10b981 0%, #059669 100%);\n}\n\n.bar-segment.failed[_ngcontent-%COMP%] {\n background: linear-gradient(180deg, #ef4444 0%, #dc2626 100%);\n}\n\n.chart-label[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--text-secondary, #9ca3af);\n margin-top: 4px;\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n gap: 24px;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--border-color, #f3f4f6);\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n}\n\n.legend-color.success[_ngcontent-%COMP%] {\n background: #10b981;\n}\n\n.legend-color.failed[_ngcontent-%COMP%] {\n background: #ef4444;\n}\n\n\n\n.toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n margin-bottom: 20px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n\n\n.search-container[_ngcontent-%COMP%] {\n position: relative;\n min-width: 200px;\n}\n\n.search-container[_ngcontent-%COMP%] i.fa-search[_ngcontent-%COMP%] {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--text-secondary, #9ca3af);\n font-size: 13px;\n}\n\n.search-container[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 8px 36px;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n font-size: 13px;\n background: var(--input-background, #f9fafb);\n transition: all 0.2s ease;\n}\n\n.search-container[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--accent-color, #6366f1);\n background: white;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.search-clear[_ngcontent-%COMP%] {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--button-hover, #e5e7eb);\n border-radius: 50%;\n cursor: pointer;\n color: var(--text-secondary, #6b7280);\n font-size: 10px;\n}\n\n.search-clear[_ngcontent-%COMP%]:hover {\n background: var(--text-secondary, #9ca3af);\n color: white;\n}\n\n.filter-select[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n background: var(--input-background, #f9fafb);\n font-size: 13px;\n color: var(--text-primary, #1f2937);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.filter-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--accent-color, #6366f1);\n}\n\n.results-info[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n}\n\n\n\n.view-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: var(--toggle-background, #f3f4f6);\n border-radius: 8px;\n padding: 4px;\n}\n\n.toggle-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.toggle-btn[_ngcontent-%COMP%]:hover {\n color: var(--text-primary, #1f2937);\n}\n\n.toggle-btn.active[_ngcontent-%COMP%] {\n background: var(--card-background, #ffffff);\n color: var(--accent-color, #6366f1);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n.timeline-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.timeline-group[_ngcontent-%COMP%] {\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n overflow: hidden;\n}\n\n.timeline-date[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--header-background, #f9fafb);\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.date-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n}\n\n.date-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n background: var(--badge-background, #e5e7eb);\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.timeline-items[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.timeline-item[_ngcontent-%COMP%] {\n display: flex;\n padding: 12px 20px;\n transition: background 0.2s ease;\n}\n\n.timeline-item[_ngcontent-%COMP%]:hover {\n background: var(--hover-background, #f9fafb);\n}\n\n.timeline-item.failed[_ngcontent-%COMP%] {\n background: rgba(239, 68, 68, 0.02);\n}\n\n.timeline-item.failed[_ngcontent-%COMP%]:hover {\n background: rgba(239, 68, 68, 0.05);\n}\n\n.timeline-line[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 24px;\n margin-right: 16px;\n flex-shrink: 0;\n}\n\n.timeline-dot[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.timeline-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n cursor: pointer;\n position: relative;\n}\n\n.timeline-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n}\n\n.timeline-operation[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.timeline-operation[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.operation-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n}\n\n.timeline-time[_ngcontent-%COMP%] {\n font-size: 12px;\n font-family: monospace;\n color: var(--text-secondary, #6b7280);\n}\n\n.timeline-body[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n}\n\n.timeline-user[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n margin-bottom: 4px;\n}\n\n.timeline-user[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.timeline-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-primary, #374151);\n margin-bottom: 8px;\n}\n\n.timeline-badges[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.success[_ngcontent-%COMP%] {\n background: #d1fae5;\n color: #059669;\n}\n\n.status-badge.failed[_ngcontent-%COMP%] {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.status-badge.unknown[_ngcontent-%COMP%] {\n background: #f3f4f6;\n color: #6b7280;\n}\n\n.status-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.subsystem-badge[_ngcontent-%COMP%], \n.type-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--badge-background, #f3f4f6);\n border-radius: 12px;\n font-size: 11px;\n color: var(--text-secondary, #6b7280);\n}\n\n.type-badge[_ngcontent-%COMP%] {\n background: rgba(99, 102, 241, 0.1);\n color: var(--accent-color, #6366f1);\n}\n\n.type-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.timeline-details[_ngcontent-%COMP%] {\n margin-top: 12px;\n padding: 16px;\n background: var(--detail-background, #f9fafb);\n border-radius: 8px;\n border: 1px solid var(--border-color, #e5e7eb);\n}\n\n.detail-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 12px;\n}\n\n.detail-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-item.full-width[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--text-secondary, #6b7280);\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-primary, #1f2937);\n}\n\n.detail-value.mono[_ngcontent-%COMP%] {\n font-family: monospace;\n font-size: 12px;\n}\n\n.detail-value.small[_ngcontent-%COMP%] {\n font-size: 11px;\n word-break: break-all;\n}\n\n.detail-value.error[_ngcontent-%COMP%] {\n color: #dc2626;\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: var(--accent-color, #6366f1);\n}\n\n.expand-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.audit-table-container[_ngcontent-%COMP%] {\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n overflow: hidden;\n}\n\n.audit-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.audit-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n padding: 14px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--text-secondary, #6b7280);\n background: var(--header-background, #f9fafb);\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n}\n\n.audit-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n font-size: 13px;\n color: var(--text-primary, #1f2937);\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.audit-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:last-child td[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n.audit-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover td[_ngcontent-%COMP%] {\n background: var(--hover-background, #f9fafb);\n}\n\n.audit-table[_ngcontent-%COMP%] tr.failed-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n background: rgba(239, 68, 68, 0.02);\n}\n\n.audit-table[_ngcontent-%COMP%] tr.failed-row[_ngcontent-%COMP%]:hover td[_ngcontent-%COMP%] {\n background: rgba(239, 68, 68, 0.05);\n}\n\n.timestamp[_ngcontent-%COMP%] {\n font-family: monospace;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n white-space: nowrap;\n}\n\n.user[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.operation-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.operation-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.description[_ngcontent-%COMP%] {\n max-width: 300px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.subsystem[_ngcontent-%COMP%] {\n color: var(--text-secondary, #6b7280);\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 24px;\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n text-align: center;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, #f3f4f6);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: var(--text-secondary, #d1d5db);\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n margin: 0 0 8px 0;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n.btn-link[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: var(--accent-color, #6366f1);\n cursor: pointer;\n font-size: inherit;\n padding: 0;\n text-decoration: underline;\n}\n\n.btn-link[_ngcontent-%COMP%]:hover {\n color: var(--accent-hover, #4f46e5);\n}\n\n\n\n@media (max-width: 1200px) {\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .audit-container[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .audit-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 16px;\n }\n\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .toolbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n\n .toolbar-left[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .search-container[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .filter-select[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .toolbar-right[_ngcontent-%COMP%] {\n justify-content: space-between;\n }\n\n .detail-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .chart-label[_ngcontent-%COMP%] {\n display: none;\n }\n\n .chart-label[_ngcontent-%COMP%]:nth-child(4n+1) {\n display: block;\n }\n}"], changeDetection: 0 });
|
|
857
|
+
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i3.LoadingComponent], styles: [".audit-container[_ngcontent-%COMP%] {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page);\n}\n\n\n\n.audit-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 24px;\n}\n\n.header-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.audit-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.audit-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-brand-primary);\n}\n\n\n\n.stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.stat-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n position: relative;\n}\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 12px;\n flex-shrink: 0;\n}\n\n.stat-icon.total[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n color: var(--mj-status-success);\n}\n\n.stat-icon.failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n color: var(--mj-status-error);\n}\n\n.stat-icon.users[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n}\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1;\n}\n\n.stat-value.success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.stat-value.failed[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n}\n\n.stat-rate[_ngcontent-%COMP%] {\n position: absolute;\n top: 12px;\n right: 16px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n padding: 4px 8px;\n border-radius: 8px;\n}\n\n\n\n.activity-chart[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n padding: 20px;\n margin-bottom: 20px;\n}\n\n.chart-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.chart-container[_ngcontent-%COMP%] {\n height: 120px;\n padding: 0 4px;\n}\n\n.chart-bars[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-end;\n height: 100%;\n gap: 2px;\n}\n\n.chart-bar-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n height: 100%;\n}\n\n.chart-bar[_ngcontent-%COMP%] {\n flex: 1;\n width: 100%;\n max-width: 24px;\n display: flex;\n flex-direction: column-reverse;\n border-radius: 4px 4px 0 0;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n}\n\n.bar-segment[_ngcontent-%COMP%] {\n width: 100%;\n transition: height 0.3s ease;\n}\n\n.bar-segment.success[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.bar-segment.failed[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n}\n\n.chart-label[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n margin-top: 4px;\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n gap: 24px;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n}\n\n.legend-color.success[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.legend-color.failed[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n}\n\n\n\n.toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n margin-bottom: 20px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n\n\n.search-container[_ngcontent-%COMP%] {\n position: relative;\n min-width: 200px;\n}\n\n.search-container[_ngcontent-%COMP%] i.fa-search[_ngcontent-%COMP%] {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-disabled);\n font-size: 13px;\n}\n\n.search-container[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 8px 36px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface-card);\n transition: all 0.2s ease;\n}\n\n.search-container[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-clear[_ngcontent-%COMP%] {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--mj-border-default);\n border-radius: 50%;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 10px;\n}\n\n.search-clear[_ngcontent-%COMP%]:hover {\n background: var(--mj-text-disabled);\n color: var(--mj-text-inverse);\n}\n\n.filter-select[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.filter-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.results-info[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.view-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n padding: 4px;\n}\n\n.toggle-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 6px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.toggle-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.toggle-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n.timeline-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.timeline-group[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n overflow: hidden;\n}\n\n.timeline-date[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.date-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.date-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n background: var(--mj-border-default);\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.timeline-items[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.timeline-item[_ngcontent-%COMP%] {\n display: flex;\n padding: 12px 20px;\n transition: background 0.2s ease;\n}\n\n.timeline-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.timeline-item.failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 2%, transparent);\n}\n\n.timeline-item.failed[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.timeline-line[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 24px;\n margin-right: 16px;\n flex-shrink: 0;\n}\n\n.timeline-dot[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.timeline-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n cursor: pointer;\n position: relative;\n}\n\n.timeline-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n}\n\n.timeline-operation[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.timeline-operation[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.operation-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.timeline-time[_ngcontent-%COMP%] {\n font-size: 12px;\n font-family: monospace;\n color: var(--mj-text-secondary);\n}\n\n.timeline-body[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n}\n\n.timeline-user[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-bottom: 4px;\n}\n\n.timeline-user[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.timeline-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n}\n\n.timeline-badges[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.status-badge.failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.status-badge.unknown[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.subsystem-badge[_ngcontent-%COMP%], \n.type-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.type-badge[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.type-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.timeline-details[_ngcontent-%COMP%] {\n margin-top: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n}\n\n.detail-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 12px;\n}\n\n.detail-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-item.full-width[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-secondary);\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.detail-value.mono[_ngcontent-%COMP%] {\n font-family: monospace;\n font-size: 12px;\n}\n\n.detail-value.small[_ngcontent-%COMP%] {\n font-size: 11px;\n word-break: break-all;\n}\n\n.detail-value.error[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n color: var(--mj-text-disabled);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n}\n\n.expand-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.audit-table-container[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n overflow: hidden;\n}\n\n.audit-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.audit-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n padding: 14px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.audit-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n font-size: 13px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.audit-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:last-child td[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n.audit-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover td[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n}\n\n.audit-table[_ngcontent-%COMP%] tr.failed-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 2%, transparent);\n}\n\n.audit-table[_ngcontent-%COMP%] tr.failed-row[_ngcontent-%COMP%]:hover td[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.timestamp[_ngcontent-%COMP%] {\n font-family: monospace;\n font-size: 12px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n.user[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.operation-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.operation-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.description[_ngcontent-%COMP%] {\n max-width: 300px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.subsystem[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 24px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n text-align: center;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-sunken);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: var(--mj-border-strong);\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 8px 0;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.btn-link[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: inherit;\n padding: 0;\n text-decoration: underline;\n}\n\n.btn-link[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary-hover);\n}\n\n\n\n@media (max-width: 1200px) {\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .audit-container[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .audit-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 16px;\n }\n\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .toolbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n\n .toolbar-left[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .search-container[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .filter-select[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .toolbar-right[_ngcontent-%COMP%] {\n justify-content: space-between;\n }\n\n .detail-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .chart-label[_ngcontent-%COMP%] {\n display: none;\n }\n\n .chart-label[_ngcontent-%COMP%]:nth-child(4n+1) {\n display: block;\n }\n}"], changeDetection: 0 });
|
|
858
858
|
};
|
|
859
859
|
CredentialsAuditResourceComponent = __decorate([
|
|
860
860
|
RegisterClass(BaseResourceComponent, 'CredentialsAuditResource')
|
|
@@ -862,7 +862,7 @@ CredentialsAuditResourceComponent = __decorate([
|
|
|
862
862
|
export { CredentialsAuditResourceComponent };
|
|
863
863
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CredentialsAuditResourceComponent, [{
|
|
864
864
|
type: Component,
|
|
865
|
-
args: [{ standalone: false, selector: 'mj-credentials-audit-resource', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"audit-container\">\n @if (isLoading) {\n <mj-loading text=\"Loading audit logs...\"></mj-loading>\n }\n\n @if (!isLoading) {\n <!-- Header -->\n <div class=\"audit-header\">\n <div class=\"header-info\">\n <h2 class=\"audit-title\">Audit Trail</h2>\n <p class=\"audit-subtitle\">Credential access and modification history</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-secondary\" (click)=\"exportToCSV()\" title=\"Export to CSV\">\n <i class=\"fa-solid fa-download\"></i>\n <span>Export</span>\n </button>\n <button class=\"btn-icon\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- Stats Cards -->\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon total\">\n <i class=\"fa-solid fa-clipboard-list\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{auditLogs.length}}</div>\n <div class=\"stat-label\">Total Events</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value success\">{{getSuccessCount()}}</div>\n <div class=\"stat-label\">Successful</div>\n </div>\n <div class=\"stat-rate\">{{getSuccessRate()}}%</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon failed\">\n <i class=\"fa-solid fa-times-circle\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value failed\">{{getFailedCount()}}</div>\n <div class=\"stat-label\">Failed</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon users\">\n <i class=\"fa-solid fa-users\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{getUniqueUserCount()}}</div>\n <div class=\"stat-label\">Unique Users</div>\n </div>\n </div>\n </div>\n <!-- Activity Chart -->\n @if (hourlyData.length > 0) {\n <div class=\"activity-chart\">\n <div class=\"chart-header\">\n <h3>\n <i class=\"fa-solid fa-chart-bar\"></i>\n Today's Activity\n </h3>\n </div>\n <div class=\"chart-container\">\n <div class=\"chart-bars\">\n @for (data of hourlyData; track data) {\n <div\n class=\"chart-bar-wrapper\"\n [title]=\"data.hour + ': ' + (data.success + data.failed) + ' events'\"\n >\n <div class=\"chart-bar\">\n <div\n class=\"bar-segment success\"\n [style.height.%]=\"(data.success / getMaxHourlyCount()) * 100\"\n ></div>\n <div\n class=\"bar-segment failed\"\n [style.height.%]=\"(data.failed / getMaxHourlyCount()) * 100\"\n ></div>\n </div>\n <span class=\"chart-label\">{{data.hour.split(':')[0]}}</span>\n </div>\n }\n </div>\n </div>\n <div class=\"chart-legend\">\n <span class=\"legend-item\">\n <span class=\"legend-color success\"></span>\n Success\n </span>\n <span class=\"legend-item\">\n <span class=\"legend-color failed\"></span>\n Failed\n </span>\n </div>\n </div>\n }\n <!-- Toolbar -->\n <div class=\"toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search logs...\"\n [value]=\"searchText\"\n (input)=\"onSearchChange($any($event.target).value)\"\n />\n @if (searchText) {\n <button class=\"search-clear\" (click)=\"clearSearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <select\n class=\"filter-select\"\n [value]=\"selectedStatus\"\n (change)=\"onStatusFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Statuses</option>\n <option value=\"Success\">Success</option>\n <option value=\"Failed\">Failed</option>\n </select>\n <select\n class=\"filter-select\"\n [value]=\"selectedOperation\"\n (change)=\"onOperationFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Operations</option>\n @for (op of getOperationList(); track op) {\n <option [value]=\"op\">{{op}}</option>\n }\n </select>\n <select\n class=\"filter-select\"\n [value]=\"dateRange\"\n (change)=\"onDateRangeChange($any($event.target).value)\"\n >\n <option value=\"1\">Last 24 hours</option>\n <option value=\"7\">Last 7 days</option>\n <option value=\"30\">Last 30 days</option>\n <option value=\"90\">Last 90 days</option>\n </select>\n </div>\n <div class=\"toolbar-right\">\n <div class=\"results-info\">\n {{filteredLogs.length}} of {{auditLogs.length}} events\n </div>\n <div class=\"view-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'timeline'\"\n (click)=\"setViewMode('timeline')\"\n title=\"Timeline View\"\n >\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'table'\"\n (click)=\"setViewMode('table')\"\n title=\"Table View\"\n >\n <i class=\"fa-solid fa-table\"></i>\n </button>\n </div>\n </div>\n </div>\n <!-- Timeline View -->\n @if (viewMode === 'timeline' && timelineGroups.length > 0) {\n <div class=\"timeline-container\">\n @for (group of timelineGroups; track group) {\n <div class=\"timeline-group\">\n <div class=\"timeline-date\">\n <span class=\"date-label\">{{group.displayDate}}</span>\n <span class=\"date-count\">{{group.logs.length}} events</span>\n </div>\n <div class=\"timeline-items\">\n @for (log of group.logs; track log) {\n <div\n class=\"timeline-item\"\n [class.expanded]=\"expandedLogId === log.ID\"\n [class.failed]=\"log.Status === 'Failed'\"\n >\n <div class=\"timeline-line\">\n <div\n class=\"timeline-dot\"\n [style.backgroundColor]=\"getOperationColor(getOperationType(log))\"\n ></div>\n </div>\n <div class=\"timeline-content\" (click)=\"toggleLogExpand(log.ID)\">\n <div class=\"timeline-header\">\n <div class=\"timeline-operation\">\n <i [class]=\"getOperationIcon(getOperationType(log))\" [style.color]=\"getOperationColor(getOperationType(log))\"></i>\n <span class=\"operation-name\">{{getOperationType(log)}}</span>\n </div>\n <div class=\"timeline-time\">{{formatTime(log.__mj_CreatedAt)}}</div>\n </div>\n <div class=\"timeline-body\">\n <div class=\"timeline-user\">\n <i class=\"fa-solid fa-user\"></i>\n {{log.User || 'Unknown'}}\n </div>\n @if (log.Description) {\n <div class=\"timeline-description\">\n {{log.Description}}\n </div>\n }\n <div class=\"timeline-badges\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass(log.Status)\">\n <i [class]=\"log.Status === 'Success' ? 'fa-solid fa-check' : 'fa-solid fa-times'\"></i>\n {{log.Status}}\n </span>\n @if (getSubsystem(log)) {\n <span class=\"subsystem-badge\">\n {{getSubsystem(log)}}\n </span>\n }\n @if (log.parsedDetails?.credentialType) {\n <span class=\"type-badge\">\n <i class=\"fa-solid fa-key\"></i>\n {{log.parsedDetails?.credentialType}}\n </span>\n }\n </div>\n </div>\n @if (expandedLogId === log.ID) {\n <div class=\"timeline-details\">\n <div class=\"detail-grid\">\n @if (log.parsedDetails?.ipAddress) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">IP Address</span>\n <span class=\"detail-value\">{{log.parsedDetails?.ipAddress}}</span>\n </div>\n }\n @if (log.parsedDetails?.duration) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Duration</span>\n <span class=\"detail-value\">{{formatDuration(log.parsedDetails?.duration)}}</span>\n </div>\n }\n @if (log.parsedDetails?.credentialId) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Credential ID</span>\n <span class=\"detail-value mono\">{{log.parsedDetails?.credentialId}}</span>\n </div>\n }\n @if (log.parsedDetails?.errorMessage) {\n <div class=\"detail-item full-width\">\n <span class=\"detail-label\">Error Message</span>\n <span class=\"detail-value error\">{{log.parsedDetails?.errorMessage}}</span>\n </div>\n }\n @if (log.parsedDetails?.userAgent) {\n <div class=\"detail-item full-width\">\n <span class=\"detail-label\">User Agent</span>\n <span class=\"detail-value mono small\">{{log.parsedDetails?.userAgent}}</span>\n </div>\n }\n </div>\n </div>\n }\n <button class=\"expand-btn\">\n <i [class]=\"expandedLogId === log.ID ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- Table View -->\n @if (viewMode === 'table' && filteredLogs.length > 0) {\n <div class=\"audit-table-container\">\n <table class=\"audit-table\">\n <thead>\n <tr>\n <th>Timestamp</th>\n <th>User</th>\n <th>Operation</th>\n <th>Description</th>\n <th>Subsystem</th>\n <th>Status</th>\n </tr>\n </thead>\n <tbody>\n @for (log of filteredLogs; track log) {\n <tr [class.failed-row]=\"log.Status === 'Failed'\">\n <td class=\"timestamp\">{{formatDate(log.__mj_CreatedAt)}}</td>\n <td class=\"user\">{{log.User || 'Unknown'}}</td>\n <td class=\"operation\">\n <span class=\"operation-badge\" [style.backgroundColor]=\"getOperationColor(getOperationType(log)) + '20'\" [style.color]=\"getOperationColor(getOperationType(log))\">\n <i [class]=\"getOperationIcon(getOperationType(log))\"></i>\n {{getOperationType(log)}}\n </span>\n </td>\n <td class=\"description\">{{log.Description || '-'}}</td>\n <td class=\"subsystem\">{{getSubsystem(log) || '-'}}</td>\n <td class=\"status\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass(log.Status)\">\n <i [class]=\"log.Status === 'Success' ? 'fa-solid fa-check' : 'fa-solid fa-times'\"></i>\n {{log.Status}}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n <!-- Empty State -->\n @if (filteredLogs.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-clipboard-list\"></i>\n </div>\n <h3>No Audit Logs</h3>\n @if (searchText || selectedStatus || selectedOperation) {\n <p>\n No events match your current filters.\n <button class=\"btn-link\" (click)=\"searchText = ''; selectedStatus = ''; selectedOperation = ''; applyFilters()\">Clear filters</button>\n </p>\n }\n @if (!searchText && !selectedStatus && !selectedOperation) {\n <p>\n No credential access events in the selected time range.\n </p>\n }\n </div>\n }\n }\n</div>\n", styles: [".audit-container {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--background-secondary, #f8fafc);\n}\n\n/* Header */\n.audit-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 24px;\n}\n\n.header-info {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.audit-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n margin: 0;\n}\n\n.audit-subtitle {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n}\n\n.btn-secondary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--text-primary, #374151);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-secondary:hover {\n background: var(--hover-background, #f9fafb);\n border-color: var(--accent-color, #6366f1);\n color: var(--accent-color, #6366f1);\n}\n\n.btn-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon:hover {\n background: var(--hover-background, #f9fafb);\n color: var(--accent-color, #6366f1);\n}\n\n/* Stats Grid */\n.stats-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.stat-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n position: relative;\n}\n\n.stat-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 12px;\n flex-shrink: 0;\n}\n\n.stat-icon.total {\n background: rgba(99, 102, 241, 0.1);\n color: #6366f1;\n}\n\n.stat-icon.success {\n background: rgba(16, 185, 129, 0.1);\n color: #10b981;\n}\n\n.stat-icon.failed {\n background: rgba(239, 68, 68, 0.1);\n color: #ef4444;\n}\n\n.stat-icon.users {\n background: rgba(139, 92, 246, 0.1);\n color: #8b5cf6;\n}\n\n.stat-icon i {\n font-size: 20px;\n}\n\n.stat-content {\n flex: 1;\n}\n\n.stat-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n line-height: 1;\n}\n\n.stat-value.success {\n color: #10b981;\n}\n\n.stat-value.failed {\n color: #ef4444;\n}\n\n.stat-label {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n margin-top: 4px;\n}\n\n.stat-rate {\n position: absolute;\n top: 12px;\n right: 16px;\n font-size: 12px;\n font-weight: 600;\n color: #10b981;\n background: rgba(16, 185, 129, 0.1);\n padding: 4px 8px;\n border-radius: 8px;\n}\n\n/* Activity Chart */\n.activity-chart {\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n padding: 20px;\n margin-bottom: 20px;\n}\n\n.chart-header {\n margin-bottom: 16px;\n}\n\n.chart-header h3 {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n margin: 0;\n}\n\n.chart-header h3 i {\n color: var(--accent-color, #6366f1);\n}\n\n.chart-container {\n height: 120px;\n padding: 0 4px;\n}\n\n.chart-bars {\n display: flex;\n align-items: flex-end;\n height: 100%;\n gap: 2px;\n}\n\n.chart-bar-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n height: 100%;\n}\n\n.chart-bar {\n flex: 1;\n width: 100%;\n max-width: 24px;\n display: flex;\n flex-direction: column-reverse;\n border-radius: 4px 4px 0 0;\n overflow: hidden;\n background: var(--bar-background, #f3f4f6);\n}\n\n.bar-segment {\n width: 100%;\n transition: height 0.3s ease;\n}\n\n.bar-segment.success {\n background: linear-gradient(180deg, #10b981 0%, #059669 100%);\n}\n\n.bar-segment.failed {\n background: linear-gradient(180deg, #ef4444 0%, #dc2626 100%);\n}\n\n.chart-label {\n font-size: 10px;\n color: var(--text-secondary, #9ca3af);\n margin-top: 4px;\n}\n\n.chart-legend {\n display: flex;\n justify-content: center;\n gap: 24px;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--border-color, #f3f4f6);\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n}\n\n.legend-color.success {\n background: #10b981;\n}\n\n.legend-color.failed {\n background: #ef4444;\n}\n\n/* Toolbar */\n.toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n margin-bottom: 20px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.toolbar-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.toolbar-right {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n/* Search */\n.search-container {\n position: relative;\n min-width: 200px;\n}\n\n.search-container i.fa-search {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--text-secondary, #9ca3af);\n font-size: 13px;\n}\n\n.search-container input {\n width: 100%;\n padding: 8px 36px;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n font-size: 13px;\n background: var(--input-background, #f9fafb);\n transition: all 0.2s ease;\n}\n\n.search-container input:focus {\n outline: none;\n border-color: var(--accent-color, #6366f1);\n background: white;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.search-clear {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--button-hover, #e5e7eb);\n border-radius: 50%;\n cursor: pointer;\n color: var(--text-secondary, #6b7280);\n font-size: 10px;\n}\n\n.search-clear:hover {\n background: var(--text-secondary, #9ca3af);\n color: white;\n}\n\n.filter-select {\n padding: 8px 12px;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n background: var(--input-background, #f9fafb);\n font-size: 13px;\n color: var(--text-primary, #1f2937);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.filter-select:focus {\n outline: none;\n border-color: var(--accent-color, #6366f1);\n}\n\n.results-info {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n}\n\n/* View Toggle */\n.view-toggle {\n display: flex;\n background: var(--toggle-background, #f3f4f6);\n border-radius: 8px;\n padding: 4px;\n}\n\n.toggle-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.toggle-btn:hover {\n color: var(--text-primary, #1f2937);\n}\n\n.toggle-btn.active {\n background: var(--card-background, #ffffff);\n color: var(--accent-color, #6366f1);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Timeline View */\n.timeline-container {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.timeline-group {\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n overflow: hidden;\n}\n\n.timeline-date {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--header-background, #f9fafb);\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.date-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n}\n\n.date-count {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n background: var(--badge-background, #e5e7eb);\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.timeline-items {\n padding: 8px 0;\n}\n\n.timeline-item {\n display: flex;\n padding: 12px 20px;\n transition: background 0.2s ease;\n}\n\n.timeline-item:hover {\n background: var(--hover-background, #f9fafb);\n}\n\n.timeline-item.failed {\n background: rgba(239, 68, 68, 0.02);\n}\n\n.timeline-item.failed:hover {\n background: rgba(239, 68, 68, 0.05);\n}\n\n.timeline-line {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 24px;\n margin-right: 16px;\n flex-shrink: 0;\n}\n\n.timeline-dot {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.timeline-content {\n flex: 1;\n min-width: 0;\n cursor: pointer;\n position: relative;\n}\n\n.timeline-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n}\n\n.timeline-operation {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.timeline-operation i {\n font-size: 14px;\n}\n\n.operation-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n}\n\n.timeline-time {\n font-size: 12px;\n font-family: monospace;\n color: var(--text-secondary, #6b7280);\n}\n\n.timeline-body {\n margin-bottom: 8px;\n}\n\n.timeline-user {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n margin-bottom: 4px;\n}\n\n.timeline-user i {\n font-size: 11px;\n}\n\n.timeline-description {\n font-size: 13px;\n color: var(--text-primary, #374151);\n margin-bottom: 8px;\n}\n\n.timeline-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.success {\n background: #d1fae5;\n color: #059669;\n}\n\n.status-badge.failed {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.status-badge.unknown {\n background: #f3f4f6;\n color: #6b7280;\n}\n\n.status-badge i {\n font-size: 10px;\n}\n\n.subsystem-badge,\n.type-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--badge-background, #f3f4f6);\n border-radius: 12px;\n font-size: 11px;\n color: var(--text-secondary, #6b7280);\n}\n\n.type-badge {\n background: rgba(99, 102, 241, 0.1);\n color: var(--accent-color, #6366f1);\n}\n\n.type-badge i {\n font-size: 10px;\n}\n\n/* Timeline Details */\n.timeline-details {\n margin-top: 12px;\n padding: 16px;\n background: var(--detail-background, #f9fafb);\n border-radius: 8px;\n border: 1px solid var(--border-color, #e5e7eb);\n}\n\n.detail-grid {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 12px;\n}\n\n.detail-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-item.full-width {\n grid-column: 1 / -1;\n}\n\n.detail-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--text-secondary, #6b7280);\n}\n\n.detail-value {\n font-size: 13px;\n color: var(--text-primary, #1f2937);\n}\n\n.detail-value.mono {\n font-family: monospace;\n font-size: 12px;\n}\n\n.detail-value.small {\n font-size: 11px;\n word-break: break-all;\n}\n\n.detail-value.error {\n color: #dc2626;\n}\n\n.expand-btn {\n position: absolute;\n top: 0;\n right: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.expand-btn:hover {\n color: var(--accent-color, #6366f1);\n}\n\n.expand-btn i {\n font-size: 10px;\n}\n\n/* Table View */\n.audit-table-container {\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n overflow: hidden;\n}\n\n.audit-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.audit-table th {\n padding: 14px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--text-secondary, #6b7280);\n background: var(--header-background, #f9fafb);\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n}\n\n.audit-table td {\n padding: 14px 16px;\n font-size: 13px;\n color: var(--text-primary, #1f2937);\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.audit-table tr:last-child td {\n border-bottom: none;\n}\n\n.audit-table tr:hover td {\n background: var(--hover-background, #f9fafb);\n}\n\n.audit-table tr.failed-row td {\n background: rgba(239, 68, 68, 0.02);\n}\n\n.audit-table tr.failed-row:hover td {\n background: rgba(239, 68, 68, 0.05);\n}\n\n.timestamp {\n font-family: monospace;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n white-space: nowrap;\n}\n\n.user {\n font-weight: 500;\n}\n\n.operation-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.operation-badge i {\n font-size: 10px;\n}\n\n.description {\n max-width: 300px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.subsystem {\n color: var(--text-secondary, #6b7280);\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: 64px 24px;\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n text-align: center;\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, #f3f4f6);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon i {\n font-size: 32px;\n color: var(--text-secondary, #d1d5db);\n}\n\n.empty-state h3 {\n font-size: 18px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n margin: 0 0 8px 0;\n}\n\n.empty-state p {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n.btn-link {\n background: none;\n border: none;\n color: var(--accent-color, #6366f1);\n cursor: pointer;\n font-size: inherit;\n padding: 0;\n text-decoration: underline;\n}\n\n.btn-link:hover {\n color: var(--accent-hover, #4f46e5);\n}\n\n/* Responsive */\n@media (max-width: 1200px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .audit-container {\n padding: 16px;\n }\n\n .audit-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 16px;\n }\n\n .stats-grid {\n grid-template-columns: 1fr;\n }\n\n .toolbar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .toolbar-left {\n flex-direction: column;\n }\n\n .search-container {\n width: 100%;\n }\n\n .filter-select {\n width: 100%;\n }\n\n .toolbar-right {\n justify-content: space-between;\n }\n\n .detail-grid {\n grid-template-columns: 1fr;\n }\n\n .chart-label {\n display: none;\n }\n\n .chart-label:nth-child(4n+1) {\n display: block;\n }\n}\n"] }]
|
|
865
|
+
args: [{ standalone: false, selector: 'mj-credentials-audit-resource', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"audit-container\">\n @if (isLoading) {\n <mj-loading text=\"Loading audit logs...\"></mj-loading>\n }\n\n @if (!isLoading) {\n <!-- Header -->\n <div class=\"audit-header\">\n <div class=\"header-info\">\n <h2 class=\"audit-title\">Audit Trail</h2>\n <p class=\"audit-subtitle\">Credential access and modification history</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-secondary\" (click)=\"exportToCSV()\" title=\"Export to CSV\">\n <i class=\"fa-solid fa-download\"></i>\n <span>Export</span>\n </button>\n <button class=\"btn-icon\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- Stats Cards -->\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon total\">\n <i class=\"fa-solid fa-clipboard-list\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{auditLogs.length}}</div>\n <div class=\"stat-label\">Total Events</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value success\">{{getSuccessCount()}}</div>\n <div class=\"stat-label\">Successful</div>\n </div>\n <div class=\"stat-rate\">{{getSuccessRate()}}%</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon failed\">\n <i class=\"fa-solid fa-times-circle\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value failed\">{{getFailedCount()}}</div>\n <div class=\"stat-label\">Failed</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon users\">\n <i class=\"fa-solid fa-users\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{getUniqueUserCount()}}</div>\n <div class=\"stat-label\">Unique Users</div>\n </div>\n </div>\n </div>\n <!-- Activity Chart -->\n @if (hourlyData.length > 0) {\n <div class=\"activity-chart\">\n <div class=\"chart-header\">\n <h3>\n <i class=\"fa-solid fa-chart-bar\"></i>\n Today's Activity\n </h3>\n </div>\n <div class=\"chart-container\">\n <div class=\"chart-bars\">\n @for (data of hourlyData; track data) {\n <div\n class=\"chart-bar-wrapper\"\n [title]=\"data.hour + ': ' + (data.success + data.failed) + ' events'\"\n >\n <div class=\"chart-bar\">\n <div\n class=\"bar-segment success\"\n [style.height.%]=\"(data.success / getMaxHourlyCount()) * 100\"\n ></div>\n <div\n class=\"bar-segment failed\"\n [style.height.%]=\"(data.failed / getMaxHourlyCount()) * 100\"\n ></div>\n </div>\n <span class=\"chart-label\">{{data.hour.split(':')[0]}}</span>\n </div>\n }\n </div>\n </div>\n <div class=\"chart-legend\">\n <span class=\"legend-item\">\n <span class=\"legend-color success\"></span>\n Success\n </span>\n <span class=\"legend-item\">\n <span class=\"legend-color failed\"></span>\n Failed\n </span>\n </div>\n </div>\n }\n <!-- Toolbar -->\n <div class=\"toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search logs...\"\n [value]=\"searchText\"\n (input)=\"onSearchChange($any($event.target).value)\"\n />\n @if (searchText) {\n <button class=\"search-clear\" (click)=\"clearSearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <select\n class=\"filter-select\"\n [value]=\"selectedStatus\"\n (change)=\"onStatusFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Statuses</option>\n <option value=\"Success\">Success</option>\n <option value=\"Failed\">Failed</option>\n </select>\n <select\n class=\"filter-select\"\n [value]=\"selectedOperation\"\n (change)=\"onOperationFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Operations</option>\n @for (op of getOperationList(); track op) {\n <option [value]=\"op\">{{op}}</option>\n }\n </select>\n <select\n class=\"filter-select\"\n [value]=\"dateRange\"\n (change)=\"onDateRangeChange($any($event.target).value)\"\n >\n <option value=\"1\">Last 24 hours</option>\n <option value=\"7\">Last 7 days</option>\n <option value=\"30\">Last 30 days</option>\n <option value=\"90\">Last 90 days</option>\n </select>\n </div>\n <div class=\"toolbar-right\">\n <div class=\"results-info\">\n {{filteredLogs.length}} of {{auditLogs.length}} events\n </div>\n <div class=\"view-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'timeline'\"\n (click)=\"setViewMode('timeline')\"\n title=\"Timeline View\"\n >\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'table'\"\n (click)=\"setViewMode('table')\"\n title=\"Table View\"\n >\n <i class=\"fa-solid fa-table\"></i>\n </button>\n </div>\n </div>\n </div>\n <!-- Timeline View -->\n @if (viewMode === 'timeline' && timelineGroups.length > 0) {\n <div class=\"timeline-container\">\n @for (group of timelineGroups; track group) {\n <div class=\"timeline-group\">\n <div class=\"timeline-date\">\n <span class=\"date-label\">{{group.displayDate}}</span>\n <span class=\"date-count\">{{group.logs.length}} events</span>\n </div>\n <div class=\"timeline-items\">\n @for (log of group.logs; track log) {\n <div\n class=\"timeline-item\"\n [class.expanded]=\"expandedLogId === log.ID\"\n [class.failed]=\"log.Status === 'Failed'\"\n >\n <div class=\"timeline-line\">\n <div\n class=\"timeline-dot\"\n [style.backgroundColor]=\"getOperationColor(getOperationType(log))\"\n ></div>\n </div>\n <div class=\"timeline-content\" (click)=\"toggleLogExpand(log.ID)\">\n <div class=\"timeline-header\">\n <div class=\"timeline-operation\">\n <i [class]=\"getOperationIcon(getOperationType(log))\" [style.color]=\"getOperationColor(getOperationType(log))\"></i>\n <span class=\"operation-name\">{{getOperationType(log)}}</span>\n </div>\n <div class=\"timeline-time\">{{formatTime(log.__mj_CreatedAt)}}</div>\n </div>\n <div class=\"timeline-body\">\n <div class=\"timeline-user\">\n <i class=\"fa-solid fa-user\"></i>\n {{log.User || 'Unknown'}}\n </div>\n @if (log.Description) {\n <div class=\"timeline-description\">\n {{log.Description}}\n </div>\n }\n <div class=\"timeline-badges\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass(log.Status)\">\n <i [class]=\"log.Status === 'Success' ? 'fa-solid fa-check' : 'fa-solid fa-times'\"></i>\n {{log.Status}}\n </span>\n @if (getSubsystem(log)) {\n <span class=\"subsystem-badge\">\n {{getSubsystem(log)}}\n </span>\n }\n @if (log.parsedDetails?.credentialType) {\n <span class=\"type-badge\">\n <i class=\"fa-solid fa-key\"></i>\n {{log.parsedDetails?.credentialType}}\n </span>\n }\n </div>\n </div>\n @if (expandedLogId === log.ID) {\n <div class=\"timeline-details\">\n <div class=\"detail-grid\">\n @if (log.parsedDetails?.ipAddress) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">IP Address</span>\n <span class=\"detail-value\">{{log.parsedDetails?.ipAddress}}</span>\n </div>\n }\n @if (log.parsedDetails?.duration) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Duration</span>\n <span class=\"detail-value\">{{formatDuration(log.parsedDetails?.duration)}}</span>\n </div>\n }\n @if (log.parsedDetails?.credentialId) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Credential ID</span>\n <span class=\"detail-value mono\">{{log.parsedDetails?.credentialId}}</span>\n </div>\n }\n @if (log.parsedDetails?.errorMessage) {\n <div class=\"detail-item full-width\">\n <span class=\"detail-label\">Error Message</span>\n <span class=\"detail-value error\">{{log.parsedDetails?.errorMessage}}</span>\n </div>\n }\n @if (log.parsedDetails?.userAgent) {\n <div class=\"detail-item full-width\">\n <span class=\"detail-label\">User Agent</span>\n <span class=\"detail-value mono small\">{{log.parsedDetails?.userAgent}}</span>\n </div>\n }\n </div>\n </div>\n }\n <button class=\"expand-btn\">\n <i [class]=\"expandedLogId === log.ID ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- Table View -->\n @if (viewMode === 'table' && filteredLogs.length > 0) {\n <div class=\"audit-table-container\">\n <table class=\"audit-table\">\n <thead>\n <tr>\n <th>Timestamp</th>\n <th>User</th>\n <th>Operation</th>\n <th>Description</th>\n <th>Subsystem</th>\n <th>Status</th>\n </tr>\n </thead>\n <tbody>\n @for (log of filteredLogs; track log) {\n <tr [class.failed-row]=\"log.Status === 'Failed'\">\n <td class=\"timestamp\">{{formatDate(log.__mj_CreatedAt)}}</td>\n <td class=\"user\">{{log.User || 'Unknown'}}</td>\n <td class=\"operation\">\n <span class=\"operation-badge\" [style.backgroundColor]=\"getOperationColor(getOperationType(log)) + '20'\" [style.color]=\"getOperationColor(getOperationType(log))\">\n <i [class]=\"getOperationIcon(getOperationType(log))\"></i>\n {{getOperationType(log)}}\n </span>\n </td>\n <td class=\"description\">{{log.Description || '-'}}</td>\n <td class=\"subsystem\">{{getSubsystem(log) || '-'}}</td>\n <td class=\"status\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass(log.Status)\">\n <i [class]=\"log.Status === 'Success' ? 'fa-solid fa-check' : 'fa-solid fa-times'\"></i>\n {{log.Status}}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n <!-- Empty State -->\n @if (filteredLogs.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-clipboard-list\"></i>\n </div>\n <h3>No Audit Logs</h3>\n @if (searchText || selectedStatus || selectedOperation) {\n <p>\n No events match your current filters.\n <button class=\"btn-link\" (click)=\"searchText = ''; selectedStatus = ''; selectedOperation = ''; applyFilters()\">Clear filters</button>\n </p>\n }\n @if (!searchText && !selectedStatus && !selectedOperation) {\n <p>\n No credential access events in the selected time range.\n </p>\n }\n </div>\n }\n }\n</div>\n", styles: [".audit-container {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page);\n}\n\n/* Header */\n.audit-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 24px;\n}\n\n.header-info {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.audit-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.audit-subtitle {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n}\n\n.btn-secondary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-secondary:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.btn-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-brand-primary);\n}\n\n/* Stats Grid */\n.stats-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.stat-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n position: relative;\n}\n\n.stat-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 12px;\n flex-shrink: 0;\n}\n\n.stat-icon.total {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon.success {\n background: color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n color: var(--mj-status-success);\n}\n\n.stat-icon.failed {\n background: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n color: var(--mj-status-error);\n}\n\n.stat-icon.users {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon i {\n font-size: 20px;\n}\n\n.stat-content {\n flex: 1;\n}\n\n.stat-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1;\n}\n\n.stat-value.success {\n color: var(--mj-status-success);\n}\n\n.stat-value.failed {\n color: var(--mj-status-error);\n}\n\n.stat-label {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n}\n\n.stat-rate {\n position: absolute;\n top: 12px;\n right: 16px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n padding: 4px 8px;\n border-radius: 8px;\n}\n\n/* Activity Chart */\n.activity-chart {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n padding: 20px;\n margin-bottom: 20px;\n}\n\n.chart-header {\n margin-bottom: 16px;\n}\n\n.chart-header h3 {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.chart-header h3 i {\n color: var(--mj-brand-primary);\n}\n\n.chart-container {\n height: 120px;\n padding: 0 4px;\n}\n\n.chart-bars {\n display: flex;\n align-items: flex-end;\n height: 100%;\n gap: 2px;\n}\n\n.chart-bar-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n height: 100%;\n}\n\n.chart-bar {\n flex: 1;\n width: 100%;\n max-width: 24px;\n display: flex;\n flex-direction: column-reverse;\n border-radius: 4px 4px 0 0;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n}\n\n.bar-segment {\n width: 100%;\n transition: height 0.3s ease;\n}\n\n.bar-segment.success {\n background: var(--mj-status-success);\n}\n\n.bar-segment.failed {\n background: var(--mj-status-error);\n}\n\n.chart-label {\n font-size: 10px;\n color: var(--mj-text-disabled);\n margin-top: 4px;\n}\n\n.chart-legend {\n display: flex;\n justify-content: center;\n gap: 24px;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n}\n\n.legend-color.success {\n background: var(--mj-status-success);\n}\n\n.legend-color.failed {\n background: var(--mj-status-error);\n}\n\n/* Toolbar */\n.toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n margin-bottom: 20px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.toolbar-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.toolbar-right {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n/* Search */\n.search-container {\n position: relative;\n min-width: 200px;\n}\n\n.search-container i.fa-search {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-disabled);\n font-size: 13px;\n}\n\n.search-container input {\n width: 100%;\n padding: 8px 36px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface-card);\n transition: all 0.2s ease;\n}\n\n.search-container input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-clear {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--mj-border-default);\n border-radius: 50%;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 10px;\n}\n\n.search-clear:hover {\n background: var(--mj-text-disabled);\n color: var(--mj-text-inverse);\n}\n\n.filter-select {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.filter-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.results-info {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n/* View Toggle */\n.view-toggle {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n padding: 4px;\n}\n\n.toggle-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 6px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.toggle-btn:hover {\n color: var(--mj-text-primary);\n}\n\n.toggle-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Timeline View */\n.timeline-container {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.timeline-group {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n overflow: hidden;\n}\n\n.timeline-date {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.date-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.date-count {\n font-size: 12px;\n color: var(--mj-text-secondary);\n background: var(--mj-border-default);\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.timeline-items {\n padding: 8px 0;\n}\n\n.timeline-item {\n display: flex;\n padding: 12px 20px;\n transition: background 0.2s ease;\n}\n\n.timeline-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.timeline-item.failed {\n background: color-mix(in srgb, var(--mj-status-error) 2%, transparent);\n}\n\n.timeline-item.failed:hover {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.timeline-line {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 24px;\n margin-right: 16px;\n flex-shrink: 0;\n}\n\n.timeline-dot {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.timeline-content {\n flex: 1;\n min-width: 0;\n cursor: pointer;\n position: relative;\n}\n\n.timeline-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n}\n\n.timeline-operation {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.timeline-operation i {\n font-size: 14px;\n}\n\n.operation-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.timeline-time {\n font-size: 12px;\n font-family: monospace;\n color: var(--mj-text-secondary);\n}\n\n.timeline-body {\n margin-bottom: 8px;\n}\n\n.timeline-user {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-bottom: 4px;\n}\n\n.timeline-user i {\n font-size: 11px;\n}\n\n.timeline-description {\n font-size: 13px;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n}\n\n.timeline-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.status-badge.failed {\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.status-badge.unknown {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-badge i {\n font-size: 10px;\n}\n\n.subsystem-badge,\n.type-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.type-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.type-badge i {\n font-size: 10px;\n}\n\n/* Timeline Details */\n.timeline-details {\n margin-top: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n}\n\n.detail-grid {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 12px;\n}\n\n.detail-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-item.full-width {\n grid-column: 1 / -1;\n}\n\n.detail-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-secondary);\n}\n\n.detail-value {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.detail-value.mono {\n font-family: monospace;\n font-size: 12px;\n}\n\n.detail-value.small {\n font-size: 11px;\n word-break: break-all;\n}\n\n.detail-value.error {\n color: var(--mj-status-error);\n}\n\n.expand-btn {\n position: absolute;\n top: 0;\n right: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n color: var(--mj-text-disabled);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.expand-btn:hover {\n color: var(--mj-brand-primary);\n}\n\n.expand-btn i {\n font-size: 10px;\n}\n\n/* Table View */\n.audit-table-container {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n overflow: hidden;\n}\n\n.audit-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.audit-table th {\n padding: 14px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.audit-table td {\n padding: 14px 16px;\n font-size: 13px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.audit-table tr:last-child td {\n border-bottom: none;\n}\n\n.audit-table tr:hover td {\n background: var(--mj-bg-surface-card);\n}\n\n.audit-table tr.failed-row td {\n background: color-mix(in srgb, var(--mj-status-error) 2%, transparent);\n}\n\n.audit-table tr.failed-row:hover td {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.timestamp {\n font-family: monospace;\n font-size: 12px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n.user {\n font-weight: 500;\n}\n\n.operation-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.operation-badge i {\n font-size: 10px;\n}\n\n.description {\n max-width: 300px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.subsystem {\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: 64px 24px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n text-align: center;\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-sunken);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon i {\n font-size: 32px;\n color: var(--mj-border-strong);\n}\n\n.empty-state h3 {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 8px 0;\n}\n\n.empty-state p {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.btn-link {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: inherit;\n padding: 0;\n text-decoration: underline;\n}\n\n.btn-link:hover {\n color: var(--mj-brand-primary-hover);\n}\n\n/* Responsive */\n@media (max-width: 1200px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .audit-container {\n padding: 16px;\n }\n\n .audit-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 16px;\n }\n\n .stats-grid {\n grid-template-columns: 1fr;\n }\n\n .toolbar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .toolbar-left {\n flex-direction: column;\n }\n\n .search-container {\n width: 100%;\n }\n\n .filter-select {\n width: 100%;\n }\n\n .toolbar-right {\n justify-content: space-between;\n }\n\n .detail-grid {\n grid-template-columns: 1fr;\n }\n\n .chart-label {\n display: none;\n }\n\n .chart-label:nth-child(4n+1) {\n display: block;\n }\n}\n"] }]
|
|
866
866
|
}], () => [{ type: i0.ChangeDetectorRef }], null); })();
|
|
867
867
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CredentialsAuditResourceComponent, { className: "CredentialsAuditResourceComponent", filePath: "src/Credentials/components/credentials-audit-resource.component.ts", lineNumber: 38 }); })();
|
|
868
868
|
//# sourceMappingURL=credentials-audit-resource.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials-audit-resource.component.js","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-audit-resource.component.ts","../../../src/Credentials/components/credentials-audit-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';\nimport { ResourceData, MJAuditLogEntity } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RunView } from '@memberjunction/core';\n// The Credential Access AuditLogType ID from metadata\nconst CREDENTIAL_ACCESS_AUDIT_LOG_TYPE_ID = 'E8D4D100-E785-42D3-997F-ECFF3B0BCFC0';\n\ninterface AuditLogWithDetails extends MJAuditLogEntity {\n parsedDetails?: ParsedDetails;\n}\n\ninterface ParsedDetails {\n operation?: string;\n subsystem?: string;\n credentialType?: string;\n credentialId?: string;\n ipAddress?: string;\n userAgent?: string;\n duration?: number;\n errorMessage?: string;\n}\n\ninterface TimelineGroup {\n date: string;\n displayDate: string;\n logs: AuditLogWithDetails[];\n}\n\n@RegisterClass(BaseResourceComponent, 'CredentialsAuditResource')\n@Component({\n standalone: false,\n selector: 'mj-credentials-audit-resource',\n templateUrl: './credentials-audit-resource.component.html',\n styleUrls: ['./credentials-audit-resource.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class CredentialsAuditResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public isLoading = true;\n public auditLogs: AuditLogWithDetails[] = [];\n public filteredLogs: AuditLogWithDetails[] = [];\n public timelineGroups: TimelineGroup[] = [];\n\n public selectedStatus = '';\n public selectedOperation = '';\n public dateRange = '7'; // days\n public searchText = '';\n public viewMode: 'table' | 'timeline' = 'timeline';\n public expandedLogId: string | null = null;\n\n // Chart data\n public hourlyData: { hour: string; success: number; failed: number }[] = [];\n public operationCounts: Map<string, number> = new Map();\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n ngOnInit(): void {\n this.loadData();\n }\n\n ngOnDestroy(): void {\n // Cleanup if needed\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Audit Trail';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-clipboard-list';\n }\n\n private async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.markForCheck();\n\n const rv = new RunView();\n\n // Calculate date filter\n const startDate = new Date();\n startDate.setDate(startDate.getDate() - parseInt(this.dateRange, 10));\n const dateFilter = `AuditLogTypeID = '${CREDENTIAL_ACCESS_AUDIT_LOG_TYPE_ID}' AND __mj_CreatedAt >= '${startDate.toISOString()}'`;\n\n const result = await rv.RunView<AuditLogWithDetails>({\n EntityName: 'MJ: Audit Logs',\n ExtraFilter: dateFilter,\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 500,\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.auditLogs = result.Results;\n this.parseAllDetails();\n this.applyFilters();\n this.buildChartData();\n }\n\n } catch (error) {\n console.error('Error loading audit logs:', error);\n } finally {\n this.isLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n private parseAllDetails(): void {\n for (const log of this.auditLogs) {\n log.parsedDetails = this.parseDetails(log);\n }\n }\n\n private parseDetails(log: MJAuditLogEntity): ParsedDetails {\n try {\n if (log.Details) {\n return JSON.parse(log.Details);\n }\n } catch (e) {\n // Ignore parse errors\n }\n return {};\n }\n\n public onStatusFilterChange(status: string): void {\n this.selectedStatus = status;\n this.applyFilters();\n }\n\n public onOperationFilterChange(operation: string): void {\n this.selectedOperation = operation;\n this.applyFilters();\n }\n\n public onDateRangeChange(days: string): void {\n this.dateRange = days;\n this.loadData();\n }\n\n public onSearchChange(value: string): void {\n this.searchText = value;\n this.applyFilters();\n }\n\n public clearSearch(): void {\n this.searchText = '';\n this.applyFilters();\n }\n\n public setViewMode(mode: 'table' | 'timeline'): void {\n this.viewMode = mode;\n this.cdr.markForCheck();\n }\n\n public toggleLogExpand(logId: string): void {\n this.expandedLogId = this.expandedLogId === logId ? null : logId;\n this.cdr.markForCheck();\n }\n\n public applyFilters(): void {\n let filtered = [...this.auditLogs];\n\n if (this.selectedStatus) {\n filtered = filtered.filter(log => log.Status === this.selectedStatus);\n }\n\n if (this.selectedOperation) {\n filtered = filtered.filter(log => {\n const op = log.parsedDetails?.operation || 'Access';\n return op === this.selectedOperation;\n });\n }\n\n if (this.searchText) {\n const searchLower = this.searchText.toLowerCase();\n filtered = filtered.filter(log => {\n const user = (log.User || '').toLowerCase();\n const desc = (log.Description || '').toLowerCase();\n const subsystem = (log.parsedDetails?.subsystem || '').toLowerCase();\n const credType = (log.parsedDetails?.credentialType || '').toLowerCase();\n return user.includes(searchLower) ||\n desc.includes(searchLower) ||\n subsystem.includes(searchLower) ||\n credType.includes(searchLower);\n });\n }\n\n this.filteredLogs = filtered;\n this.buildTimelineGroups();\n this.cdr.markForCheck();\n }\n\n private buildTimelineGroups(): void {\n const groups = new Map<string, AuditLogWithDetails[]>();\n\n for (const log of this.filteredLogs) {\n const date = new Date(log.__mj_CreatedAt);\n const dateKey = date.toISOString().split('T')[0];\n\n if (!groups.has(dateKey)) {\n groups.set(dateKey, []);\n }\n groups.get(dateKey)!.push(log);\n }\n\n this.timelineGroups = Array.from(groups.entries())\n .sort((a, b) => b[0].localeCompare(a[0]))\n .map(([date, logs]) => ({\n date,\n displayDate: this.formatGroupDate(date),\n logs\n }));\n }\n\n private formatGroupDate(dateString: string): string {\n const date = new Date(dateString);\n const today = new Date();\n const yesterday = new Date(today);\n yesterday.setDate(yesterday.getDate() - 1);\n\n if (date.toDateString() === today.toDateString()) {\n return 'Today';\n } else if (date.toDateString() === yesterday.toDateString()) {\n return 'Yesterday';\n } else {\n return date.toLocaleDateString('en-US', {\n weekday: 'long',\n month: 'long',\n day: 'numeric',\n year: date.getFullYear() !== today.getFullYear() ? 'numeric' : undefined\n });\n }\n }\n\n private buildChartData(): void {\n // Build hourly distribution for today\n const hourCounts: { [key: string]: { success: number; failed: number } } = {};\n const today = new Date().toDateString();\n\n for (let i = 0; i < 24; i++) {\n const hour = i.toString().padStart(2, '0') + ':00';\n hourCounts[hour] = { success: 0, failed: 0 };\n }\n\n for (const log of this.auditLogs) {\n const date = new Date(log.__mj_CreatedAt);\n if (date.toDateString() === today) {\n const hour = date.getHours().toString().padStart(2, '0') + ':00';\n if (log.Status === 'Success') {\n hourCounts[hour].success++;\n } else {\n hourCounts[hour].failed++;\n }\n }\n }\n\n this.hourlyData = Object.entries(hourCounts).map(([hour, counts]) => ({\n hour,\n ...counts\n }));\n\n // Build operation counts\n this.operationCounts.clear();\n for (const log of this.auditLogs) {\n const op = log.parsedDetails?.operation || 'Access';\n this.operationCounts.set(op, (this.operationCounts.get(op) || 0) + 1);\n }\n }\n\n public getMaxHourlyCount(): number {\n return Math.max(...this.hourlyData.map(d => d.success + d.failed), 1);\n }\n\n public getOperationList(): string[] {\n return Array.from(this.operationCounts.keys());\n }\n\n public getStatusClass(status: string): string {\n switch (status) {\n case 'Success': return 'success';\n case 'Failed': return 'failed';\n default: return 'unknown';\n }\n }\n\n public getOperationType(log: AuditLogWithDetails): string {\n return log.parsedDetails?.operation || 'Access';\n }\n\n public getSubsystem(log: AuditLogWithDetails): string {\n return log.parsedDetails?.subsystem || '';\n }\n\n public getOperationIcon(operation: string): string {\n switch (operation.toLowerCase()) {\n case 'access': return 'fa-solid fa-eye';\n case 'create': return 'fa-solid fa-plus';\n case 'update': return 'fa-solid fa-pen';\n case 'delete': return 'fa-solid fa-trash';\n case 'rotate': return 'fa-solid fa-rotate';\n case 'validate': return 'fa-solid fa-check-circle';\n default: return 'fa-solid fa-circle';\n }\n }\n\n public getOperationColor(operation: string): string {\n switch (operation.toLowerCase()) {\n case 'access': return '#6366f1';\n case 'create': return '#10b981';\n case 'update': return '#f59e0b';\n case 'delete': return '#ef4444';\n case 'rotate': return '#8b5cf6';\n case 'validate': return '#06b6d4';\n default: return '#6b7280';\n }\n }\n\n public formatDate(date: Date | string | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit'\n });\n }\n\n public formatTime(date: Date | string | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit'\n });\n }\n\n public formatDuration(ms: number | undefined): string {\n if (!ms) return '-';\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n }\n\n public refresh(): void {\n this.loadData();\n }\n\n public getSuccessCount(): number {\n return this.auditLogs.filter(log => log.Status === 'Success').length;\n }\n\n public getFailedCount(): number {\n return this.auditLogs.filter(log => log.Status === 'Failed').length;\n }\n\n public getSuccessRate(): number {\n if (this.auditLogs.length === 0) return 0;\n return Math.round((this.getSuccessCount() / this.auditLogs.length) * 100);\n }\n\n public getUniqueUserCount(): number {\n const users = new Set(this.auditLogs.map(log => log.User).filter(Boolean));\n return users.size;\n }\n\n public exportToCSV(): void {\n const headers = ['Timestamp', 'User', 'Operation', 'Status', 'Description', 'Subsystem', 'Credential Type'];\n const rows = this.filteredLogs.map(log => [\n this.formatDate(log.__mj_CreatedAt),\n log.User || '',\n this.getOperationType(log),\n log.Status || '',\n log.Description || '',\n this.getSubsystem(log),\n log.parsedDetails?.credentialType || ''\n ]);\n\n const csvContent = [\n headers.join(','),\n ...rows.map(row => row.map(cell => `\"${cell.replace(/\"/g, '\"\"')}\"`).join(','))\n ].join('\\n');\n\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n const link = document.createElement('a');\n link.href = URL.createObjectURL(blob);\n link.download = `credential-audit-log-${new Date().toISOString().split('T')[0]}.csv`;\n link.click();\n }\n}\n","<div class=\"audit-container\">\n @if (isLoading) {\n <mj-loading text=\"Loading audit logs...\"></mj-loading>\n }\n\n @if (!isLoading) {\n <!-- Header -->\n <div class=\"audit-header\">\n <div class=\"header-info\">\n <h2 class=\"audit-title\">Audit Trail</h2>\n <p class=\"audit-subtitle\">Credential access and modification history</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-secondary\" (click)=\"exportToCSV()\" title=\"Export to CSV\">\n <i class=\"fa-solid fa-download\"></i>\n <span>Export</span>\n </button>\n <button class=\"btn-icon\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- Stats Cards -->\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon total\">\n <i class=\"fa-solid fa-clipboard-list\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{auditLogs.length}}</div>\n <div class=\"stat-label\">Total Events</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value success\">{{getSuccessCount()}}</div>\n <div class=\"stat-label\">Successful</div>\n </div>\n <div class=\"stat-rate\">{{getSuccessRate()}}%</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon failed\">\n <i class=\"fa-solid fa-times-circle\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value failed\">{{getFailedCount()}}</div>\n <div class=\"stat-label\">Failed</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon users\">\n <i class=\"fa-solid fa-users\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{getUniqueUserCount()}}</div>\n <div class=\"stat-label\">Unique Users</div>\n </div>\n </div>\n </div>\n <!-- Activity Chart -->\n @if (hourlyData.length > 0) {\n <div class=\"activity-chart\">\n <div class=\"chart-header\">\n <h3>\n <i class=\"fa-solid fa-chart-bar\"></i>\n Today's Activity\n </h3>\n </div>\n <div class=\"chart-container\">\n <div class=\"chart-bars\">\n @for (data of hourlyData; track data) {\n <div\n class=\"chart-bar-wrapper\"\n [title]=\"data.hour + ': ' + (data.success + data.failed) + ' events'\"\n >\n <div class=\"chart-bar\">\n <div\n class=\"bar-segment success\"\n [style.height.%]=\"(data.success / getMaxHourlyCount()) * 100\"\n ></div>\n <div\n class=\"bar-segment failed\"\n [style.height.%]=\"(data.failed / getMaxHourlyCount()) * 100\"\n ></div>\n </div>\n <span class=\"chart-label\">{{data.hour.split(':')[0]}}</span>\n </div>\n }\n </div>\n </div>\n <div class=\"chart-legend\">\n <span class=\"legend-item\">\n <span class=\"legend-color success\"></span>\n Success\n </span>\n <span class=\"legend-item\">\n <span class=\"legend-color failed\"></span>\n Failed\n </span>\n </div>\n </div>\n }\n <!-- Toolbar -->\n <div class=\"toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search logs...\"\n [value]=\"searchText\"\n (input)=\"onSearchChange($any($event.target).value)\"\n />\n @if (searchText) {\n <button class=\"search-clear\" (click)=\"clearSearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <select\n class=\"filter-select\"\n [value]=\"selectedStatus\"\n (change)=\"onStatusFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Statuses</option>\n <option value=\"Success\">Success</option>\n <option value=\"Failed\">Failed</option>\n </select>\n <select\n class=\"filter-select\"\n [value]=\"selectedOperation\"\n (change)=\"onOperationFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Operations</option>\n @for (op of getOperationList(); track op) {\n <option [value]=\"op\">{{op}}</option>\n }\n </select>\n <select\n class=\"filter-select\"\n [value]=\"dateRange\"\n (change)=\"onDateRangeChange($any($event.target).value)\"\n >\n <option value=\"1\">Last 24 hours</option>\n <option value=\"7\">Last 7 days</option>\n <option value=\"30\">Last 30 days</option>\n <option value=\"90\">Last 90 days</option>\n </select>\n </div>\n <div class=\"toolbar-right\">\n <div class=\"results-info\">\n {{filteredLogs.length}} of {{auditLogs.length}} events\n </div>\n <div class=\"view-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'timeline'\"\n (click)=\"setViewMode('timeline')\"\n title=\"Timeline View\"\n >\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'table'\"\n (click)=\"setViewMode('table')\"\n title=\"Table View\"\n >\n <i class=\"fa-solid fa-table\"></i>\n </button>\n </div>\n </div>\n </div>\n <!-- Timeline View -->\n @if (viewMode === 'timeline' && timelineGroups.length > 0) {\n <div class=\"timeline-container\">\n @for (group of timelineGroups; track group) {\n <div class=\"timeline-group\">\n <div class=\"timeline-date\">\n <span class=\"date-label\">{{group.displayDate}}</span>\n <span class=\"date-count\">{{group.logs.length}} events</span>\n </div>\n <div class=\"timeline-items\">\n @for (log of group.logs; track log) {\n <div\n class=\"timeline-item\"\n [class.expanded]=\"expandedLogId === log.ID\"\n [class.failed]=\"log.Status === 'Failed'\"\n >\n <div class=\"timeline-line\">\n <div\n class=\"timeline-dot\"\n [style.backgroundColor]=\"getOperationColor(getOperationType(log))\"\n ></div>\n </div>\n <div class=\"timeline-content\" (click)=\"toggleLogExpand(log.ID)\">\n <div class=\"timeline-header\">\n <div class=\"timeline-operation\">\n <i [class]=\"getOperationIcon(getOperationType(log))\" [style.color]=\"getOperationColor(getOperationType(log))\"></i>\n <span class=\"operation-name\">{{getOperationType(log)}}</span>\n </div>\n <div class=\"timeline-time\">{{formatTime(log.__mj_CreatedAt)}}</div>\n </div>\n <div class=\"timeline-body\">\n <div class=\"timeline-user\">\n <i class=\"fa-solid fa-user\"></i>\n {{log.User || 'Unknown'}}\n </div>\n @if (log.Description) {\n <div class=\"timeline-description\">\n {{log.Description}}\n </div>\n }\n <div class=\"timeline-badges\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass(log.Status)\">\n <i [class]=\"log.Status === 'Success' ? 'fa-solid fa-check' : 'fa-solid fa-times'\"></i>\n {{log.Status}}\n </span>\n @if (getSubsystem(log)) {\n <span class=\"subsystem-badge\">\n {{getSubsystem(log)}}\n </span>\n }\n @if (log.parsedDetails?.credentialType) {\n <span class=\"type-badge\">\n <i class=\"fa-solid fa-key\"></i>\n {{log.parsedDetails?.credentialType}}\n </span>\n }\n </div>\n </div>\n @if (expandedLogId === log.ID) {\n <div class=\"timeline-details\">\n <div class=\"detail-grid\">\n @if (log.parsedDetails?.ipAddress) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">IP Address</span>\n <span class=\"detail-value\">{{log.parsedDetails?.ipAddress}}</span>\n </div>\n }\n @if (log.parsedDetails?.duration) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Duration</span>\n <span class=\"detail-value\">{{formatDuration(log.parsedDetails?.duration)}}</span>\n </div>\n }\n @if (log.parsedDetails?.credentialId) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Credential ID</span>\n <span class=\"detail-value mono\">{{log.parsedDetails?.credentialId}}</span>\n </div>\n }\n @if (log.parsedDetails?.errorMessage) {\n <div class=\"detail-item full-width\">\n <span class=\"detail-label\">Error Message</span>\n <span class=\"detail-value error\">{{log.parsedDetails?.errorMessage}}</span>\n </div>\n }\n @if (log.parsedDetails?.userAgent) {\n <div class=\"detail-item full-width\">\n <span class=\"detail-label\">User Agent</span>\n <span class=\"detail-value mono small\">{{log.parsedDetails?.userAgent}}</span>\n </div>\n }\n </div>\n </div>\n }\n <button class=\"expand-btn\">\n <i [class]=\"expandedLogId === log.ID ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- Table View -->\n @if (viewMode === 'table' && filteredLogs.length > 0) {\n <div class=\"audit-table-container\">\n <table class=\"audit-table\">\n <thead>\n <tr>\n <th>Timestamp</th>\n <th>User</th>\n <th>Operation</th>\n <th>Description</th>\n <th>Subsystem</th>\n <th>Status</th>\n </tr>\n </thead>\n <tbody>\n @for (log of filteredLogs; track log) {\n <tr [class.failed-row]=\"log.Status === 'Failed'\">\n <td class=\"timestamp\">{{formatDate(log.__mj_CreatedAt)}}</td>\n <td class=\"user\">{{log.User || 'Unknown'}}</td>\n <td class=\"operation\">\n <span class=\"operation-badge\" [style.backgroundColor]=\"getOperationColor(getOperationType(log)) + '20'\" [style.color]=\"getOperationColor(getOperationType(log))\">\n <i [class]=\"getOperationIcon(getOperationType(log))\"></i>\n {{getOperationType(log)}}\n </span>\n </td>\n <td class=\"description\">{{log.Description || '-'}}</td>\n <td class=\"subsystem\">{{getSubsystem(log) || '-'}}</td>\n <td class=\"status\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass(log.Status)\">\n <i [class]=\"log.Status === 'Success' ? 'fa-solid fa-check' : 'fa-solid fa-times'\"></i>\n {{log.Status}}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n <!-- Empty State -->\n @if (filteredLogs.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-clipboard-list\"></i>\n </div>\n <h3>No Audit Logs</h3>\n @if (searchText || selectedStatus || selectedOperation) {\n <p>\n No events match your current filters.\n <button class=\"btn-link\" (click)=\"searchText = ''; selectedStatus = ''; selectedOperation = ''; applyFilters()\">Clear filters</button>\n </p>\n }\n @if (!searchText && !selectedStatus && !selectedOperation) {\n <p>\n No credential access events in the selected time range.\n </p>\n }\n </div>\n }\n }\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"credentials-audit-resource.component.js","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-audit-resource.component.ts","../../../src/Credentials/components/credentials-audit-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';\nimport { ResourceData, MJAuditLogEntity } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RunView } from '@memberjunction/core';\n// The Credential Access AuditLogType ID from metadata\nconst CREDENTIAL_ACCESS_AUDIT_LOG_TYPE_ID = 'E8D4D100-E785-42D3-997F-ECFF3B0BCFC0';\n\ninterface AuditLogWithDetails extends MJAuditLogEntity {\n parsedDetails?: ParsedDetails;\n}\n\ninterface ParsedDetails {\n operation?: string;\n subsystem?: string;\n credentialType?: string;\n credentialId?: string;\n ipAddress?: string;\n userAgent?: string;\n duration?: number;\n errorMessage?: string;\n}\n\ninterface TimelineGroup {\n date: string;\n displayDate: string;\n logs: AuditLogWithDetails[];\n}\n\n@RegisterClass(BaseResourceComponent, 'CredentialsAuditResource')\n@Component({\n standalone: false,\n selector: 'mj-credentials-audit-resource',\n templateUrl: './credentials-audit-resource.component.html',\n styleUrls: ['./credentials-audit-resource.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class CredentialsAuditResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public isLoading = true;\n public auditLogs: AuditLogWithDetails[] = [];\n public filteredLogs: AuditLogWithDetails[] = [];\n public timelineGroups: TimelineGroup[] = [];\n\n public selectedStatus = '';\n public selectedOperation = '';\n public dateRange = '7'; // days\n public searchText = '';\n public viewMode: 'table' | 'timeline' = 'timeline';\n public expandedLogId: string | null = null;\n\n // Chart data\n public hourlyData: { hour: string; success: number; failed: number }[] = [];\n public operationCounts: Map<string, number> = new Map();\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n ngOnInit(): void {\n this.loadData();\n }\n\n ngOnDestroy(): void {\n // Cleanup if needed\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Audit Trail';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-clipboard-list';\n }\n\n private async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.markForCheck();\n\n const rv = new RunView();\n\n // Calculate date filter\n const startDate = new Date();\n startDate.setDate(startDate.getDate() - parseInt(this.dateRange, 10));\n const dateFilter = `AuditLogTypeID = '${CREDENTIAL_ACCESS_AUDIT_LOG_TYPE_ID}' AND __mj_CreatedAt >= '${startDate.toISOString()}'`;\n\n const result = await rv.RunView<AuditLogWithDetails>({\n EntityName: 'MJ: Audit Logs',\n ExtraFilter: dateFilter,\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 500,\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.auditLogs = result.Results;\n this.parseAllDetails();\n this.applyFilters();\n this.buildChartData();\n }\n\n } catch (error) {\n console.error('Error loading audit logs:', error);\n } finally {\n this.isLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n private parseAllDetails(): void {\n for (const log of this.auditLogs) {\n log.parsedDetails = this.parseDetails(log);\n }\n }\n\n private parseDetails(log: MJAuditLogEntity): ParsedDetails {\n try {\n if (log.Details) {\n return JSON.parse(log.Details);\n }\n } catch (e) {\n // Ignore parse errors\n }\n return {};\n }\n\n public onStatusFilterChange(status: string): void {\n this.selectedStatus = status;\n this.applyFilters();\n }\n\n public onOperationFilterChange(operation: string): void {\n this.selectedOperation = operation;\n this.applyFilters();\n }\n\n public onDateRangeChange(days: string): void {\n this.dateRange = days;\n this.loadData();\n }\n\n public onSearchChange(value: string): void {\n this.searchText = value;\n this.applyFilters();\n }\n\n public clearSearch(): void {\n this.searchText = '';\n this.applyFilters();\n }\n\n public setViewMode(mode: 'table' | 'timeline'): void {\n this.viewMode = mode;\n this.cdr.markForCheck();\n }\n\n public toggleLogExpand(logId: string): void {\n this.expandedLogId = this.expandedLogId === logId ? null : logId;\n this.cdr.markForCheck();\n }\n\n public applyFilters(): void {\n let filtered = [...this.auditLogs];\n\n if (this.selectedStatus) {\n filtered = filtered.filter(log => log.Status === this.selectedStatus);\n }\n\n if (this.selectedOperation) {\n filtered = filtered.filter(log => {\n const op = log.parsedDetails?.operation || 'Access';\n return op === this.selectedOperation;\n });\n }\n\n if (this.searchText) {\n const searchLower = this.searchText.toLowerCase();\n filtered = filtered.filter(log => {\n const user = (log.User || '').toLowerCase();\n const desc = (log.Description || '').toLowerCase();\n const subsystem = (log.parsedDetails?.subsystem || '').toLowerCase();\n const credType = (log.parsedDetails?.credentialType || '').toLowerCase();\n return user.includes(searchLower) ||\n desc.includes(searchLower) ||\n subsystem.includes(searchLower) ||\n credType.includes(searchLower);\n });\n }\n\n this.filteredLogs = filtered;\n this.buildTimelineGroups();\n this.cdr.markForCheck();\n }\n\n private buildTimelineGroups(): void {\n const groups = new Map<string, AuditLogWithDetails[]>();\n\n for (const log of this.filteredLogs) {\n const date = new Date(log.__mj_CreatedAt);\n const dateKey = date.toISOString().split('T')[0];\n\n if (!groups.has(dateKey)) {\n groups.set(dateKey, []);\n }\n groups.get(dateKey)!.push(log);\n }\n\n this.timelineGroups = Array.from(groups.entries())\n .sort((a, b) => b[0].localeCompare(a[0]))\n .map(([date, logs]) => ({\n date,\n displayDate: this.formatGroupDate(date),\n logs\n }));\n }\n\n private formatGroupDate(dateString: string): string {\n const date = new Date(dateString);\n const today = new Date();\n const yesterday = new Date(today);\n yesterday.setDate(yesterday.getDate() - 1);\n\n if (date.toDateString() === today.toDateString()) {\n return 'Today';\n } else if (date.toDateString() === yesterday.toDateString()) {\n return 'Yesterday';\n } else {\n return date.toLocaleDateString('en-US', {\n weekday: 'long',\n month: 'long',\n day: 'numeric',\n year: date.getFullYear() !== today.getFullYear() ? 'numeric' : undefined\n });\n }\n }\n\n private buildChartData(): void {\n // Build hourly distribution for today\n const hourCounts: { [key: string]: { success: number; failed: number } } = {};\n const today = new Date().toDateString();\n\n for (let i = 0; i < 24; i++) {\n const hour = i.toString().padStart(2, '0') + ':00';\n hourCounts[hour] = { success: 0, failed: 0 };\n }\n\n for (const log of this.auditLogs) {\n const date = new Date(log.__mj_CreatedAt);\n if (date.toDateString() === today) {\n const hour = date.getHours().toString().padStart(2, '0') + ':00';\n if (log.Status === 'Success') {\n hourCounts[hour].success++;\n } else {\n hourCounts[hour].failed++;\n }\n }\n }\n\n this.hourlyData = Object.entries(hourCounts).map(([hour, counts]) => ({\n hour,\n ...counts\n }));\n\n // Build operation counts\n this.operationCounts.clear();\n for (const log of this.auditLogs) {\n const op = log.parsedDetails?.operation || 'Access';\n this.operationCounts.set(op, (this.operationCounts.get(op) || 0) + 1);\n }\n }\n\n public getMaxHourlyCount(): number {\n return Math.max(...this.hourlyData.map(d => d.success + d.failed), 1);\n }\n\n public getOperationList(): string[] {\n return Array.from(this.operationCounts.keys());\n }\n\n public getStatusClass(status: string): string {\n switch (status) {\n case 'Success': return 'success';\n case 'Failed': return 'failed';\n default: return 'unknown';\n }\n }\n\n public getOperationType(log: AuditLogWithDetails): string {\n return log.parsedDetails?.operation || 'Access';\n }\n\n public getSubsystem(log: AuditLogWithDetails): string {\n return log.parsedDetails?.subsystem || '';\n }\n\n public getOperationIcon(operation: string): string {\n switch (operation.toLowerCase()) {\n case 'access': return 'fa-solid fa-eye';\n case 'create': return 'fa-solid fa-plus';\n case 'update': return 'fa-solid fa-pen';\n case 'delete': return 'fa-solid fa-trash';\n case 'rotate': return 'fa-solid fa-rotate';\n case 'validate': return 'fa-solid fa-check-circle';\n default: return 'fa-solid fa-circle';\n }\n }\n\n public getOperationColor(operation: string): string {\n switch (operation.toLowerCase()) {\n case 'access': return 'var(--mj-brand-primary)';\n case 'create': return 'var(--mj-status-success)';\n case 'update': return 'var(--mj-status-warning)';\n case 'delete': return 'var(--mj-status-error)';\n case 'rotate': return 'var(--mj-brand-primary)';\n case 'validate': return 'var(--mj-brand-primary)';\n default: return 'var(--mj-text-secondary)';\n }\n }\n\n public formatDate(date: Date | string | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit'\n });\n }\n\n public formatTime(date: Date | string | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit'\n });\n }\n\n public formatDuration(ms: number | undefined): string {\n if (!ms) return '-';\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n }\n\n public refresh(): void {\n this.loadData();\n }\n\n public getSuccessCount(): number {\n return this.auditLogs.filter(log => log.Status === 'Success').length;\n }\n\n public getFailedCount(): number {\n return this.auditLogs.filter(log => log.Status === 'Failed').length;\n }\n\n public getSuccessRate(): number {\n if (this.auditLogs.length === 0) return 0;\n return Math.round((this.getSuccessCount() / this.auditLogs.length) * 100);\n }\n\n public getUniqueUserCount(): number {\n const users = new Set(this.auditLogs.map(log => log.User).filter(Boolean));\n return users.size;\n }\n\n public exportToCSV(): void {\n const headers = ['Timestamp', 'User', 'Operation', 'Status', 'Description', 'Subsystem', 'Credential Type'];\n const rows = this.filteredLogs.map(log => [\n this.formatDate(log.__mj_CreatedAt),\n log.User || '',\n this.getOperationType(log),\n log.Status || '',\n log.Description || '',\n this.getSubsystem(log),\n log.parsedDetails?.credentialType || ''\n ]);\n\n const csvContent = [\n headers.join(','),\n ...rows.map(row => row.map(cell => `\"${cell.replace(/\"/g, '\"\"')}\"`).join(','))\n ].join('\\n');\n\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n const link = document.createElement('a');\n link.href = URL.createObjectURL(blob);\n link.download = `credential-audit-log-${new Date().toISOString().split('T')[0]}.csv`;\n link.click();\n }\n}\n","<div class=\"audit-container\">\n @if (isLoading) {\n <mj-loading text=\"Loading audit logs...\"></mj-loading>\n }\n\n @if (!isLoading) {\n <!-- Header -->\n <div class=\"audit-header\">\n <div class=\"header-info\">\n <h2 class=\"audit-title\">Audit Trail</h2>\n <p class=\"audit-subtitle\">Credential access and modification history</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-secondary\" (click)=\"exportToCSV()\" title=\"Export to CSV\">\n <i class=\"fa-solid fa-download\"></i>\n <span>Export</span>\n </button>\n <button class=\"btn-icon\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- Stats Cards -->\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon total\">\n <i class=\"fa-solid fa-clipboard-list\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{auditLogs.length}}</div>\n <div class=\"stat-label\">Total Events</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value success\">{{getSuccessCount()}}</div>\n <div class=\"stat-label\">Successful</div>\n </div>\n <div class=\"stat-rate\">{{getSuccessRate()}}%</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon failed\">\n <i class=\"fa-solid fa-times-circle\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value failed\">{{getFailedCount()}}</div>\n <div class=\"stat-label\">Failed</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon users\">\n <i class=\"fa-solid fa-users\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{getUniqueUserCount()}}</div>\n <div class=\"stat-label\">Unique Users</div>\n </div>\n </div>\n </div>\n <!-- Activity Chart -->\n @if (hourlyData.length > 0) {\n <div class=\"activity-chart\">\n <div class=\"chart-header\">\n <h3>\n <i class=\"fa-solid fa-chart-bar\"></i>\n Today's Activity\n </h3>\n </div>\n <div class=\"chart-container\">\n <div class=\"chart-bars\">\n @for (data of hourlyData; track data) {\n <div\n class=\"chart-bar-wrapper\"\n [title]=\"data.hour + ': ' + (data.success + data.failed) + ' events'\"\n >\n <div class=\"chart-bar\">\n <div\n class=\"bar-segment success\"\n [style.height.%]=\"(data.success / getMaxHourlyCount()) * 100\"\n ></div>\n <div\n class=\"bar-segment failed\"\n [style.height.%]=\"(data.failed / getMaxHourlyCount()) * 100\"\n ></div>\n </div>\n <span class=\"chart-label\">{{data.hour.split(':')[0]}}</span>\n </div>\n }\n </div>\n </div>\n <div class=\"chart-legend\">\n <span class=\"legend-item\">\n <span class=\"legend-color success\"></span>\n Success\n </span>\n <span class=\"legend-item\">\n <span class=\"legend-color failed\"></span>\n Failed\n </span>\n </div>\n </div>\n }\n <!-- Toolbar -->\n <div class=\"toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search logs...\"\n [value]=\"searchText\"\n (input)=\"onSearchChange($any($event.target).value)\"\n />\n @if (searchText) {\n <button class=\"search-clear\" (click)=\"clearSearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <select\n class=\"filter-select\"\n [value]=\"selectedStatus\"\n (change)=\"onStatusFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Statuses</option>\n <option value=\"Success\">Success</option>\n <option value=\"Failed\">Failed</option>\n </select>\n <select\n class=\"filter-select\"\n [value]=\"selectedOperation\"\n (change)=\"onOperationFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Operations</option>\n @for (op of getOperationList(); track op) {\n <option [value]=\"op\">{{op}}</option>\n }\n </select>\n <select\n class=\"filter-select\"\n [value]=\"dateRange\"\n (change)=\"onDateRangeChange($any($event.target).value)\"\n >\n <option value=\"1\">Last 24 hours</option>\n <option value=\"7\">Last 7 days</option>\n <option value=\"30\">Last 30 days</option>\n <option value=\"90\">Last 90 days</option>\n </select>\n </div>\n <div class=\"toolbar-right\">\n <div class=\"results-info\">\n {{filteredLogs.length}} of {{auditLogs.length}} events\n </div>\n <div class=\"view-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'timeline'\"\n (click)=\"setViewMode('timeline')\"\n title=\"Timeline View\"\n >\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'table'\"\n (click)=\"setViewMode('table')\"\n title=\"Table View\"\n >\n <i class=\"fa-solid fa-table\"></i>\n </button>\n </div>\n </div>\n </div>\n <!-- Timeline View -->\n @if (viewMode === 'timeline' && timelineGroups.length > 0) {\n <div class=\"timeline-container\">\n @for (group of timelineGroups; track group) {\n <div class=\"timeline-group\">\n <div class=\"timeline-date\">\n <span class=\"date-label\">{{group.displayDate}}</span>\n <span class=\"date-count\">{{group.logs.length}} events</span>\n </div>\n <div class=\"timeline-items\">\n @for (log of group.logs; track log) {\n <div\n class=\"timeline-item\"\n [class.expanded]=\"expandedLogId === log.ID\"\n [class.failed]=\"log.Status === 'Failed'\"\n >\n <div class=\"timeline-line\">\n <div\n class=\"timeline-dot\"\n [style.backgroundColor]=\"getOperationColor(getOperationType(log))\"\n ></div>\n </div>\n <div class=\"timeline-content\" (click)=\"toggleLogExpand(log.ID)\">\n <div class=\"timeline-header\">\n <div class=\"timeline-operation\">\n <i [class]=\"getOperationIcon(getOperationType(log))\" [style.color]=\"getOperationColor(getOperationType(log))\"></i>\n <span class=\"operation-name\">{{getOperationType(log)}}</span>\n </div>\n <div class=\"timeline-time\">{{formatTime(log.__mj_CreatedAt)}}</div>\n </div>\n <div class=\"timeline-body\">\n <div class=\"timeline-user\">\n <i class=\"fa-solid fa-user\"></i>\n {{log.User || 'Unknown'}}\n </div>\n @if (log.Description) {\n <div class=\"timeline-description\">\n {{log.Description}}\n </div>\n }\n <div class=\"timeline-badges\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass(log.Status)\">\n <i [class]=\"log.Status === 'Success' ? 'fa-solid fa-check' : 'fa-solid fa-times'\"></i>\n {{log.Status}}\n </span>\n @if (getSubsystem(log)) {\n <span class=\"subsystem-badge\">\n {{getSubsystem(log)}}\n </span>\n }\n @if (log.parsedDetails?.credentialType) {\n <span class=\"type-badge\">\n <i class=\"fa-solid fa-key\"></i>\n {{log.parsedDetails?.credentialType}}\n </span>\n }\n </div>\n </div>\n @if (expandedLogId === log.ID) {\n <div class=\"timeline-details\">\n <div class=\"detail-grid\">\n @if (log.parsedDetails?.ipAddress) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">IP Address</span>\n <span class=\"detail-value\">{{log.parsedDetails?.ipAddress}}</span>\n </div>\n }\n @if (log.parsedDetails?.duration) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Duration</span>\n <span class=\"detail-value\">{{formatDuration(log.parsedDetails?.duration)}}</span>\n </div>\n }\n @if (log.parsedDetails?.credentialId) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Credential ID</span>\n <span class=\"detail-value mono\">{{log.parsedDetails?.credentialId}}</span>\n </div>\n }\n @if (log.parsedDetails?.errorMessage) {\n <div class=\"detail-item full-width\">\n <span class=\"detail-label\">Error Message</span>\n <span class=\"detail-value error\">{{log.parsedDetails?.errorMessage}}</span>\n </div>\n }\n @if (log.parsedDetails?.userAgent) {\n <div class=\"detail-item full-width\">\n <span class=\"detail-label\">User Agent</span>\n <span class=\"detail-value mono small\">{{log.parsedDetails?.userAgent}}</span>\n </div>\n }\n </div>\n </div>\n }\n <button class=\"expand-btn\">\n <i [class]=\"expandedLogId === log.ID ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- Table View -->\n @if (viewMode === 'table' && filteredLogs.length > 0) {\n <div class=\"audit-table-container\">\n <table class=\"audit-table\">\n <thead>\n <tr>\n <th>Timestamp</th>\n <th>User</th>\n <th>Operation</th>\n <th>Description</th>\n <th>Subsystem</th>\n <th>Status</th>\n </tr>\n </thead>\n <tbody>\n @for (log of filteredLogs; track log) {\n <tr [class.failed-row]=\"log.Status === 'Failed'\">\n <td class=\"timestamp\">{{formatDate(log.__mj_CreatedAt)}}</td>\n <td class=\"user\">{{log.User || 'Unknown'}}</td>\n <td class=\"operation\">\n <span class=\"operation-badge\" [style.backgroundColor]=\"getOperationColor(getOperationType(log)) + '20'\" [style.color]=\"getOperationColor(getOperationType(log))\">\n <i [class]=\"getOperationIcon(getOperationType(log))\"></i>\n {{getOperationType(log)}}\n </span>\n </td>\n <td class=\"description\">{{log.Description || '-'}}</td>\n <td class=\"subsystem\">{{getSubsystem(log) || '-'}}</td>\n <td class=\"status\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass(log.Status)\">\n <i [class]=\"log.Status === 'Success' ? 'fa-solid fa-check' : 'fa-solid fa-times'\"></i>\n {{log.Status}}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n <!-- Empty State -->\n @if (filteredLogs.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-clipboard-list\"></i>\n </div>\n <h3>No Audit Logs</h3>\n @if (searchText || selectedStatus || selectedOperation) {\n <p>\n No events match your current filters.\n <button class=\"btn-link\" (click)=\"searchText = ''; selectedStatus = ''; selectedOperation = ''; applyFilters()\">Clear filters</button>\n </p>\n }\n @if (!searchText && !selectedStatus && !selectedOperation) {\n <p>\n No credential access events in the selected time range.\n </p>\n }\n </div>\n }\n }\n</div>\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials-categories-resource.component.d.ts","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-categories-resource.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAsC,MAAM,eAAe,CAAC;AACpH,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAEjH,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGrF,OAAO,EAAE,oCAAoC,EAAE,MAAM,gCAAgC,CAAC;;AACtF,UAAU,YAAY;IAClB,QAAQ,EAAE,0BAA0B,CAAC;IACrC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,qBAQa,sCAAuC,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAetG,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,iBAAiB;IAftB,SAAS,UAAQ;IACjB,UAAU,EAAE,0BAA0B,EAAE,CAAM;IAC9C,YAAY,EAAE,YAAY,EAAE,CAAM;IAClC,KAAK,EAAE,sBAAsB,EAAE,CAAM;IACrC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IACzC,UAAU,SAAM;IAGvB,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,gBAAgB,CAA8B;IAEtB,iBAAiB,EAAG,oCAAoC,CAAC;gBAG7E,GAAG,EAAE,iBAAiB,EACtB,iBAAiB,EAAE,iBAAiB;IAKhD,QAAQ,IAAI,IAAI;IAIhB,WAAW,IAAI,IAAI;IAIb,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3D,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAM/D,IAAW,aAAa,IAAI,OAAO,CAElC;IAED,IAAW,aAAa,IAAI,OAAO,CAElC;IAED,IAAW,aAAa,IAAI,OAAO,CAElC;IAED,OAAO,CAAC,qBAAqB;YAgCf,QAAQ;IAsCtB,OAAO,CAAC,SAAS;IA8CV,iBAAiB,IAAI,IAAI;IAMzB,mBAAmB,CAAC,UAAU,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IASlE,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAS/C,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAoDtE,eAAe,CAAC,QAAQ,EAAE,0BAA0B,GAAG,IAAI;IAa3D,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAW3C,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAKpC,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAUrD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQnC,WAAW,IAAI,IAAI;IAKnB,SAAS,IAAI,IAAI;IAWjB,WAAW,IAAI,IAAI;IAWnB,iBAAiB,IAAI,YAAY,EAAE;IAyB1C,OAAO,CAAC,iBAAiB;IAMlB,iBAAiB,IAAI,MAAM;IAI3B,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,sBAAsB,EAAE;IAInE,4BAA4B,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAWrE,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAUtE,sFAAsF;IAC/E,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;IAI3C,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"credentials-categories-resource.component.d.ts","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-categories-resource.component.ts"],"names":[],"mappings":"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"}
|