@memberjunction/ng-dashboards 5.11.0 → 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.js +4 -4
- 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.js +7 -7
- 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
|
@@ -1247,7 +1247,7 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
1247
1247
|
i0.ɵɵconditional(!ctx.isLoading ? 2 : -1);
|
|
1248
1248
|
i0.ɵɵadvance();
|
|
1249
1249
|
i0.ɵɵproperty("credentialTypes", ctx.types);
|
|
1250
|
-
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i3.LoadingComponent, i4.CredentialEditPanelComponent], styles: [".list-container[_ngcontent-%COMP%] {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--page-background, #f8fafc);\n}\n\n\n\n.list-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 24px;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n.header-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.list-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n margin: 0;\n}\n\n.header-stats[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.stat-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n}\n\n.stat-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.stat-item.active[_ngcontent-%COMP%] {\n color: #10b981;\n}\n\n.stat-item.warning[_ngcontent-%COMP%] {\n color: #f59e0b;\n}\n\n.stat-item.danger[_ngcontent-%COMP%] {\n color: #ef4444;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);\n color: white;\n border: none;\n border-radius: 10px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 16px rgba(99, 102, 241, 0.4);\n}\n\n.btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n\n\n.toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n background: var(--card-background, #ffffff);\n padding: 16px;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n flex: 1;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.search-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n background: var(--input-background, #f9fafb);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n padding: 8px 12px;\n min-width: 280px;\n position: relative;\n}\n\n.search-container[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--text-secondary, #6b7280);\n margin-right: 8px;\n}\n\n.search-container[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n outline: none;\n flex: 1;\n font-size: 14px;\n color: var(--text-primary, #1f2937);\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 background: var(--border-color, #e5e7eb);\n border: none;\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, #6b7280);\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, #ffffff);\n font-size: 14px;\n color: var(--text-primary, #1f2937);\n cursor: pointer;\n min-width: 140px;\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 white-space: nowrap;\n}\n\n.view-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: var(--input-background, #f3f4f6);\n border-radius: 8px;\n padding: 4px;\n}\n\n.view-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.view-btn[_ngcontent-%COMP%]:hover {\n color: var(--accent-color, #6366f1);\n}\n\n.view-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: var(--accent-color, #6366f1);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n background: var(--button-background, #ffffff);\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(--button-hover, #f3f4f6);\n color: var(--accent-color, #6366f1);\n}\n\n\n\n.bulk-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);\n border-radius: 10px;\n margin-bottom: 16px;\n color: white;\n}\n\n.bulk-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.bulk-count[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n}\n\n.btn-link[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: rgba(255, 255, 255, 0.8);\n font-size: 13px;\n cursor: pointer;\n text-decoration: underline;\n padding: 0;\n}\n\n.btn-link[_ngcontent-%COMP%]:hover {\n color: white;\n}\n\n.bulk-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.btn-bulk[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: rgba(255, 255, 255, 0.2);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 6px;\n color: white;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-bulk[_ngcontent-%COMP%]:hover {\n background: rgba(255, 255, 255, 0.3);\n}\n\n.btn-bulk.danger[_ngcontent-%COMP%] {\n background: rgba(239, 68, 68, 0.3);\n border-color: rgba(239, 68, 68, 0.5);\n}\n\n.btn-bulk.danger[_ngcontent-%COMP%]:hover {\n background: rgba(239, 68, 68, 0.5);\n}\n\n\n\n.credentials-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));\n gap: 20px;\n}\n\n.credential-card[_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 transition: all 0.2s ease;\n position: relative;\n border: 2px solid transparent;\n}\n\n.credential-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);\n}\n\n.credential-card.selected[_ngcontent-%COMP%] {\n border-color: var(--accent-color, #6366f1);\n background: linear-gradient(to bottom, rgba(99, 102, 241, 0.03), white);\n}\n\n.credential-card.expired[_ngcontent-%COMP%] {\n border-color: rgba(239, 68, 68, 0.3);\n}\n\n.credential-card.expiring[_ngcontent-%COMP%] {\n border-color: rgba(245, 158, 11, 0.3);\n}\n\n.card-select[_ngcontent-%COMP%] {\n position: absolute;\n top: 12px;\n left: 12px;\n z-index: 10;\n}\n\n.card-select[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--accent-color, #6366f1);\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 16px;\n padding-left: 40px;\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.card-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.card-icon.active[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: white;\n}\n\n.card-icon.inactive[_ngcontent-%COMP%] {\n background: var(--icon-inactive, #e5e7eb);\n color: var(--text-secondary, #6b7280);\n}\n\n.card-icon.expired[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);\n color: white;\n}\n\n.card-icon.expiring[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n}\n\n.card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n}\n\n.card-title[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.credential-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 15px;\n color: var(--text-primary, #1f2937);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.credential-type[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n margin-top: 2px;\n}\n\n.card-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.credential-card[_ngcontent-%COMP%]:hover .card-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--input-background, #f3f4f6);\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover {\n background: var(--accent-color, #6366f1);\n color: white;\n}\n\n.action-btn.danger[_ngcontent-%COMP%]:hover {\n background: #ef4444;\n}\n\n.card-body[_ngcontent-%COMP%] {\n padding: 16px;\n padding-left: 40px;\n cursor: pointer;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n margin-bottom: 12px;\n}\n\n.status-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.status-badge.active[_ngcontent-%COMP%] {\n background: #d1fae5;\n color: #059669;\n}\n\n.status-badge.inactive[_ngcontent-%COMP%] {\n background: #f3f4f6;\n color: #6b7280;\n}\n\n.status-badge.expired[_ngcontent-%COMP%] {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.status-badge.expiring[_ngcontent-%COMP%] {\n background: #fef3c7;\n color: #d97706;\n}\n\n.credential-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n line-height: 1.5;\n margin: 0 0 12px 0;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.credential-meta[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.meta-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.meta-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--accent-color, #6366f1);\n}\n\n.meta-item.warning[_ngcontent-%COMP%] {\n color: #f59e0b;\n}\n\n.meta-item.warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #f59e0b;\n}\n\n.meta-item.danger[_ngcontent-%COMP%] {\n color: #ef4444;\n}\n\n.meta-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #ef4444;\n}\n\n.card-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n padding-left: 40px;\n background: var(--footer-background, #f9fafb);\n border-top: 1px solid var(--border-color, #f3f4f6);\n}\n\n.category-tag[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--tag-background, #e0e7ff);\n color: var(--accent-color, #6366f1);\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.category-tag[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.created-info[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--text-tertiary, #9ca3af);\n}\n\n\n\n.credentials-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.credentials-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.credentials-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n background: var(--header-background, #f9fafb);\n}\n\n.credentials-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n padding: 12px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--text-secondary, #6b7280);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n}\n\n.credentials-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px 16px;\n font-size: 14px;\n color: var(--text-primary, #1f2937);\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n transition: background 0.2s ease;\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background: var(--row-hover, #f9fafb);\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.selected[_ngcontent-%COMP%] {\n background: rgba(99, 102, 241, 0.05);\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.expired[_ngcontent-%COMP%] {\n background: rgba(239, 68, 68, 0.03);\n}\n\n.col-select[_ngcontent-%COMP%] {\n width: 40px;\n}\n\n.col-select[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n accent-color: var(--accent-color, #6366f1);\n}\n\n.col-name[_ngcontent-%COMP%] {\n min-width: 240px;\n cursor: pointer;\n}\n\n.name-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.name-cell[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.name-cell[_ngcontent-%COMP%] i.active[_ngcontent-%COMP%] {\n background: #d1fae5;\n color: #059669;\n}\n\n.name-cell[_ngcontent-%COMP%] i.inactive[_ngcontent-%COMP%] {\n background: #f3f4f6;\n color: #6b7280;\n}\n\n.name-cell[_ngcontent-%COMP%] i.expired[_ngcontent-%COMP%] {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.name-cell[_ngcontent-%COMP%] i.expiring[_ngcontent-%COMP%] {\n background: #fef3c7;\n color: #d97706;\n}\n\n.name-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n flex: 1;\n}\n\n.name-info[_ngcontent-%COMP%] .credential-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--text-primary, #1f2937);\n}\n\n.name-info[_ngcontent-%COMP%] .credential-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-secondary, #9ca3af);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.default-badge[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);\n color: white;\n font-size: 10px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.col-type[_ngcontent-%COMP%], \n.col-category[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n.category-pill[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 4px 10px;\n background: var(--tag-background, #e0e7ff);\n color: var(--accent-color, #6366f1);\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.col-status[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n.status-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-pill.active[_ngcontent-%COMP%] {\n background: #d1fae5;\n color: #059669;\n}\n\n.status-pill.inactive[_ngcontent-%COMP%] {\n background: #f3f4f6;\n color: #6b7280;\n}\n\n.status-pill.expired[_ngcontent-%COMP%] {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.status-pill.expiring[_ngcontent-%COMP%] {\n background: #fef3c7;\n color: #d97706;\n}\n\n.col-expires[_ngcontent-%COMP%], \n.col-used[_ngcontent-%COMP%] {\n white-space: nowrap;\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n}\n\n.col-expires.warning[_ngcontent-%COMP%] {\n color: #f59e0b;\n font-weight: 500;\n}\n\n.col-expires.danger[_ngcontent-%COMP%] {\n color: #ef4444;\n font-weight: 500;\n}\n\n.col-actions[_ngcontent-%COMP%] {\n width: 120px;\n}\n\n.table-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover .table-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.table-action-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--input-background, #f3f4f6);\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n font-size: 13px;\n}\n\n.table-action-btn[_ngcontent-%COMP%]:hover {\n background: var(--accent-color, #6366f1);\n color: white;\n}\n\n.table-action-btn.danger[_ngcontent-%COMP%]:hover {\n background: #ef4444;\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: 80px 24px;\n text-align: center;\n background: var(--card-background, #ffffff);\n border-radius: 16px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\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: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%);\n border-radius: 20px;\n margin-bottom: 24px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 36px;\n color: var(--accent-color, #6366f1);\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 700;\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 0 24px 0;\n max-width: 400px;\n line-height: 1.5;\n}\n\n.empty-state[_ngcontent-%COMP%] .btn-link[_ngcontent-%COMP%] {\n color: var(--accent-color, #6366f1);\n text-decoration: underline;\n cursor: pointer;\n background: none;\n border: none;\n font-size: 14px;\n padding: 0;\n}\n\n.empty-state[_ngcontent-%COMP%] .btn-link[_ngcontent-%COMP%]:hover {\n color: var(--accent-hover, #4f46e5);\n}\n\n.empty-state[_ngcontent-%COMP%] .btn-primary[_ngcontent-%COMP%] {\n margin-top: 0;\n}\n\n\n\n@media (max-width: 768px) {\n .list-container[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .list-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .list-title[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .header-stats[_ngcontent-%COMP%] {\n gap: 12px;\n }\n\n .stat-item[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .header-actions[_ngcontent-%COMP%] .btn-primary[_ngcontent-%COMP%] {\n flex: 1;\n justify-content: center;\n }\n\n .toolbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n\n .toolbar-left[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .search-container[_ngcontent-%COMP%] {\n min-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 .credentials-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n \n\n .card-actions[_ngcontent-%COMP%] {\n opacity: 1;\n }\n\n .card-header[_ngcontent-%COMP%] {\n padding: 14px;\n padding-left: 36px;\n }\n\n .card-body[_ngcontent-%COMP%] {\n padding: 14px;\n padding-left: 36px;\n }\n\n .card-footer[_ngcontent-%COMP%] {\n padding: 10px 14px;\n padding-left: 36px;\n }\n\n .card-icon[_ngcontent-%COMP%] {\n width: 38px;\n height: 38px;\n }\n\n .card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .bulk-actions[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 12px;\n text-align: center;\n }\n\n .bulk-info[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 8px;\n }\n\n .bulk-buttons[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n justify-content: center;\n }\n\n .credentials-table-container[_ngcontent-%COMP%] {\n overflow-x: auto;\n }\n\n .credentials-table[_ngcontent-%COMP%] {\n min-width: 800px;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 48px 20px;\n }\n\n .empty-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n }\n\n .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n}\n\n@media (max-width: 480px) {\n .list-container[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .list-title[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .header-stats[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n }\n\n .btn-primary[_ngcontent-%COMP%] {\n padding: 10px 16px;\n font-size: 13px;\n }\n\n .btn-primary[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: none;\n }\n\n .btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin: 0;\n }\n\n .toolbar[_ngcontent-%COMP%] {\n padding: 10px;\n }\n\n .view-toggle[_ngcontent-%COMP%] {\n display: none;\n }\n\n .results-info[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .credential-card[_ngcontent-%COMP%] {\n border-radius: 10px;\n }\n\n .card-select[_ngcontent-%COMP%] {\n top: 10px;\n left: 10px;\n }\n\n .card-header[_ngcontent-%COMP%] {\n padding: 12px;\n padding-left: 32px;\n }\n\n .card-body[_ngcontent-%COMP%] {\n padding: 12px;\n padding-left: 32px;\n }\n\n .card-footer[_ngcontent-%COMP%] {\n padding: 10px 12px;\n padding-left: 32px;\n }\n\n .card-icon[_ngcontent-%COMP%] {\n width: 34px;\n height: 34px;\n margin-right: 10px;\n }\n\n .credential-name[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .credential-type[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .action-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n }\n\n .status-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 3px 8px;\n }\n\n .credential-meta[_ngcontent-%COMP%] {\n gap: 8px;\n }\n\n .meta-item[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .category-tag[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 3px 8px;\n }\n\n .created-info[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 32px 16px;\n }\n\n .empty-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n margin-bottom: 16px;\n }\n\n .empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n }\n\n .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n}"], changeDetection: 0 });
|
|
1250
|
+
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i3.LoadingComponent, i4.CredentialEditPanelComponent], styles: [".list-container[_ngcontent-%COMP%] {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page);\n}\n\n\n\n.list-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 24px;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n.header-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.list-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.header-stats[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.stat-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.stat-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.stat-item.active[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.stat-item.warning[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.stat-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 10px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 16px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n\n\n.toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n background: var(--mj-bg-surface);\n padding: 16px;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n flex: 1;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.search-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 8px 12px;\n min-width: 280px;\n position: relative;\n}\n\n.search-container[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n margin-right: 8px;\n}\n\n.search-container[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n outline: none;\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\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 background: var(--mj-border-default);\n border: none;\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-secondary);\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);\n font-size: 14px;\n color: var(--mj-text-primary);\n cursor: pointer;\n min-width: 140px;\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 white-space: nowrap;\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.view-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n border-radius: 6px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.view-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n}\n\n.view-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.btn-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\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-sunken);\n color: var(--mj-brand-primary);\n}\n\n\n\n.bulk-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-bottom: 16px;\n color: var(--mj-text-inverse);\n}\n\n.bulk-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.bulk-count[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n}\n\n.btn-link[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: color-mix(in srgb, var(--mj-bg-surface) 80%, transparent);\n font-size: 13px;\n cursor: pointer;\n text-decoration: underline;\n padding: 0;\n}\n\n.btn-link[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-inverse);\n}\n\n.bulk-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.btn-bulk[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: color-mix(in srgb, var(--mj-bg-surface) 20%, transparent);\n border: 1px solid color-mix(in srgb, var(--mj-bg-surface) 30%, transparent);\n border-radius: 6px;\n color: var(--mj-text-inverse);\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-bulk[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-bg-surface) 30%, transparent);\n}\n\n.btn-bulk.danger[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n border-color: color-mix(in srgb, var(--mj-status-error) 50%, transparent);\n}\n\n.btn-bulk.danger[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 50%, transparent);\n}\n\n\n\n.credentials-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));\n gap: 20px;\n}\n\n.credential-card[_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 transition: all 0.2s ease;\n position: relative;\n border: 2px solid transparent;\n}\n\n.credential-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);\n}\n\n.credential-card.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, var(--mj-bg-surface));\n}\n\n.credential-card.expired[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n}\n\n.credential-card.expiring[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.card-select[_ngcontent-%COMP%] {\n position: absolute;\n top: 12px;\n left: 12px;\n z-index: 10;\n}\n\n.card-select[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 16px;\n padding-left: 40px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.card-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.card-icon.active[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.card-icon.inactive[_ngcontent-%COMP%] {\n background: var(--mj-border-default);\n color: var(--mj-text-secondary);\n}\n\n.card-icon.expired[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.card-icon.expiring[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n color: var(--mj-text-inverse);\n}\n\n.card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n}\n\n.card-title[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.credential-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 15px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.credential-type[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n.card-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.credential-card[_ngcontent-%COMP%]:hover .card-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.action-btn.danger[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n}\n\n.card-body[_ngcontent-%COMP%] {\n padding: 16px;\n padding-left: 40px;\n cursor: pointer;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n margin-bottom: 12px;\n}\n\n.status-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.status-badge.active[_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.inactive[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-badge.expired[_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.expiring[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.credential-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0 0 12px 0;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.credential-meta[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.meta-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.meta-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-brand-primary);\n}\n\n.meta-item.warning[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.meta-item.warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.meta-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.meta-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.card-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n padding-left: 40px;\n background: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.category-tag[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.category-tag[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.created-info[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-disabled);\n}\n\n\n\n.credentials-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.credentials-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.credentials-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n}\n\n.credentials-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n padding: 12px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.credentials-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px 16px;\n font-size: 14px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n transition: background 0.2s ease;\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.expired[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 3%, transparent);\n}\n\n.col-select[_ngcontent-%COMP%] {\n width: 40px;\n}\n\n.col-select[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n}\n\n.col-name[_ngcontent-%COMP%] {\n min-width: 240px;\n cursor: pointer;\n}\n\n.name-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.name-cell[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.name-cell[_ngcontent-%COMP%] i.active[_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.name-cell[_ngcontent-%COMP%] i.inactive[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.name-cell[_ngcontent-%COMP%] i.expired[_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.name-cell[_ngcontent-%COMP%] i.expiring[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.name-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n flex: 1;\n}\n\n.name-info[_ngcontent-%COMP%] .credential-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.name-info[_ngcontent-%COMP%] .credential-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-disabled);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.default-badge[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.col-type[_ngcontent-%COMP%], \n.col-category[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n.category-pill[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.col-status[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n.status-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-pill.active[_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-pill.inactive[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-pill.expired[_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-pill.expiring[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.col-expires[_ngcontent-%COMP%], \n.col-used[_ngcontent-%COMP%] {\n white-space: nowrap;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.col-expires.warning[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-weight: 500;\n}\n\n.col-expires.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.col-actions[_ngcontent-%COMP%] {\n width: 120px;\n}\n\n.table-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.credentials-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover .table-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.table-action-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n font-size: 13px;\n}\n\n.table-action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.table-action-btn.danger[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\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: 80px 24px;\n text-align: center;\n background: var(--mj-bg-surface);\n border-radius: 16px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 20px;\n margin-bottom: 24px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 36px;\n color: var(--mj-brand-primary);\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 700;\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 0 24px 0;\n max-width: 400px;\n line-height: 1.5;\n}\n\n.empty-state[_ngcontent-%COMP%] .btn-link[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n cursor: pointer;\n background: none;\n border: none;\n font-size: 14px;\n padding: 0;\n}\n\n.empty-state[_ngcontent-%COMP%] .btn-link[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary-hover);\n}\n\n.empty-state[_ngcontent-%COMP%] .btn-primary[_ngcontent-%COMP%] {\n margin-top: 0;\n}\n\n\n\n@media (max-width: 768px) {\n .list-container[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .list-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .list-title[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .header-stats[_ngcontent-%COMP%] {\n gap: 12px;\n }\n\n .stat-item[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .header-actions[_ngcontent-%COMP%] .btn-primary[_ngcontent-%COMP%] {\n flex: 1;\n justify-content: center;\n }\n\n .toolbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n\n .toolbar-left[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .search-container[_ngcontent-%COMP%] {\n min-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 .credentials-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n \n\n .card-actions[_ngcontent-%COMP%] {\n opacity: 1;\n }\n\n .card-header[_ngcontent-%COMP%] {\n padding: 14px;\n padding-left: 36px;\n }\n\n .card-body[_ngcontent-%COMP%] {\n padding: 14px;\n padding-left: 36px;\n }\n\n .card-footer[_ngcontent-%COMP%] {\n padding: 10px 14px;\n padding-left: 36px;\n }\n\n .card-icon[_ngcontent-%COMP%] {\n width: 38px;\n height: 38px;\n }\n\n .card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .bulk-actions[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 12px;\n text-align: center;\n }\n\n .bulk-info[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 8px;\n }\n\n .bulk-buttons[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n justify-content: center;\n }\n\n .credentials-table-container[_ngcontent-%COMP%] {\n overflow-x: auto;\n }\n\n .credentials-table[_ngcontent-%COMP%] {\n min-width: 800px;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 48px 20px;\n }\n\n .empty-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n }\n\n .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n}\n\n@media (max-width: 480px) {\n .list-container[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .list-title[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .header-stats[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n }\n\n .btn-primary[_ngcontent-%COMP%] {\n padding: 10px 16px;\n font-size: 13px;\n }\n\n .btn-primary[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: none;\n }\n\n .btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin: 0;\n }\n\n .toolbar[_ngcontent-%COMP%] {\n padding: 10px;\n }\n\n .view-toggle[_ngcontent-%COMP%] {\n display: none;\n }\n\n .results-info[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .credential-card[_ngcontent-%COMP%] {\n border-radius: 10px;\n }\n\n .card-select[_ngcontent-%COMP%] {\n top: 10px;\n left: 10px;\n }\n\n .card-header[_ngcontent-%COMP%] {\n padding: 12px;\n padding-left: 32px;\n }\n\n .card-body[_ngcontent-%COMP%] {\n padding: 12px;\n padding-left: 32px;\n }\n\n .card-footer[_ngcontent-%COMP%] {\n padding: 10px 12px;\n padding-left: 32px;\n }\n\n .card-icon[_ngcontent-%COMP%] {\n width: 34px;\n height: 34px;\n margin-right: 10px;\n }\n\n .credential-name[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .credential-type[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .action-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n }\n\n .status-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 3px 8px;\n }\n\n .credential-meta[_ngcontent-%COMP%] {\n gap: 8px;\n }\n\n .meta-item[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .category-tag[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 3px 8px;\n }\n\n .created-info[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 32px 16px;\n }\n\n .empty-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n margin-bottom: 16px;\n }\n\n .empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n }\n\n .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n}"], changeDetection: 0 });
|
|
1251
1251
|
};
|
|
1252
1252
|
CredentialsListResourceComponent = __decorate([
|
|
1253
1253
|
RegisterClass(BaseResourceComponent, 'CredentialsListResource')
|
|
@@ -1255,7 +1255,7 @@ CredentialsListResourceComponent = __decorate([
|
|
|
1255
1255
|
export { CredentialsListResourceComponent };
|
|
1256
1256
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CredentialsListResourceComponent, [{
|
|
1257
1257
|
type: Component,
|
|
1258
|
-
args: [{ standalone: false, selector: 'mj-credentials-list-resource', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"list-container\">\n @if (isLoading) {\n <mj-loading text=\"Loading credentials...\"></mj-loading>\n }\n\n @if (!isLoading) {\n <!-- Header with Stats -->\n <div class=\"list-header\">\n <div class=\"header-info\">\n <h2 class=\"list-title\">Credentials</h2>\n <div class=\"header-stats\">\n <span class=\"stat-item\">\n <i class=\"fa-solid fa-key\"></i>\n {{credentials.length}} total\n </span>\n <span class=\"stat-item active\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{getActiveCount()}} active\n </span>\n @if (getExpiringSoonCount() > 0) {\n <span class=\"stat-item warning\">\n <i class=\"fa-solid fa-clock\"></i>\n {{getExpiringSoonCount()}} expiring\n </span>\n }\n @if (getExpiredCount() > 0) {\n <span class=\"stat-item danger\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{getExpiredCount()}} expired\n </span>\n }\n </div>\n </div>\n <div class=\"header-actions\">\n @if (UserCanCreate) {\n <button class=\"btn-primary\" (click)=\"createNewCredential()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New Credential</span>\n </button>\n }\n </div>\n </div>\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 credentials...\"\n [value]=\"searchText\"\n (input)=\"onSearchChange($any($event.target).value)\"\n />\n @if (searchText) {\n <button class=\"search-clear\" (click)=\"onSearchChange('')\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <select\n class=\"filter-select\"\n [value]=\"selectedTypeFilter\"\n (change)=\"onTypeFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Types</option>\n @for (type of types; track type) {\n <option [value]=\"type.ID\">{{type.Name}}</option>\n }\n </select>\n <select\n class=\"filter-select\"\n [value]=\"selectedStatusFilter\"\n (change)=\"onStatusFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Statuses</option>\n <option value=\"active\">Active</option>\n <option value=\"inactive\">Inactive</option>\n <option value=\"expiring\">Expiring Soon</option>\n <option value=\"expired\">Expired</option>\n </select>\n </div>\n <div class=\"toolbar-right\">\n <div class=\"results-info\">\n {{filteredCredentials.length}} of {{credentials.length}}\n </div>\n <div class=\"view-toggle\">\n <button\n class=\"view-btn\"\n [class.active]=\"viewMode === 'grid'\"\n (click)=\"setViewMode('grid')\"\n title=\"Grid View\"\n >\n <i class=\"fa-solid fa-grid-2\"></i>\n </button>\n <button\n class=\"view-btn\"\n [class.active]=\"viewMode === 'list'\"\n (click)=\"setViewMode('list')\"\n title=\"List View\"\n >\n <i class=\"fa-solid fa-list\"></i>\n </button>\n </div>\n <button class=\"btn-icon\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- Bulk Actions Bar -->\n @if (selectedCredentials.size > 0) {\n <div class=\"bulk-actions\">\n <div class=\"bulk-info\">\n <span class=\"bulk-count\">{{selectedCredentials.size}} selected</span>\n <button class=\"btn-link\" (click)=\"clearSelection()\">Clear selection</button>\n </div>\n <div class=\"bulk-buttons\">\n @if (UserCanUpdate) {\n <button class=\"btn-bulk\" (click)=\"bulkToggleActive(true)\">\n <i class=\"fa-solid fa-toggle-on\"></i>\n Activate\n </button>\n }\n @if (UserCanUpdate) {\n <button class=\"btn-bulk\" (click)=\"bulkToggleActive(false)\">\n <i class=\"fa-solid fa-toggle-off\"></i>\n Deactivate\n </button>\n }\n @if (UserCanDelete) {\n <button class=\"btn-bulk danger\" (click)=\"bulkDelete()\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete\n </button>\n }\n </div>\n </div>\n }\n <!-- Grid View -->\n @if (viewMode === 'grid' && filteredCredentials.length > 0) {\n <div class=\"credentials-grid\">\n @for (credential of filteredCredentials; track credential) {\n <div\n class=\"credential-card\"\n [class.selected]=\"selectedCredentials.has(credential.ID)\"\n [class.expired]=\"isExpired(credential)\"\n [class.expiring]=\"isExpiringSoon(credential)\"\n >\n <!-- Selection Checkbox -->\n @if (UserCanUpdate || UserCanDelete) {\n <div class=\"card-select\">\n <input\n type=\"checkbox\"\n [checked]=\"selectedCredentials.has(credential.ID)\"\n (change)=\"toggleSelection(credential)\"\n />\n </div>\n }\n <div class=\"card-header\">\n <div class=\"card-icon\" [ngClass]=\"getStatusClass(credential)\">\n <i [class]=\"credential.IconClass || 'fa-solid fa-key'\"></i>\n </div>\n <div class=\"card-title\">\n <div class=\"credential-name\">{{credential.Name}}</div>\n <div class=\"credential-type\">{{credential.CredentialType || 'Unknown Type'}}</div>\n </div>\n <div class=\"card-actions\">\n @if (UserCanUpdate) {\n <button\n class=\"action-btn\"\n (click)=\"toggleCredentialActive(credential, $event)\"\n [title]=\"credential.IsActive ? 'Deactivate' : 'Activate'\"\n >\n <i [class]=\"credential.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\"></i>\n </button>\n }\n @if (UserCanUpdate) {\n <button\n class=\"action-btn\"\n (click)=\"editCredential(credential, $event)\"\n title=\"Edit\"\n >\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n @if (UserCanDelete) {\n <button\n class=\"action-btn danger\"\n (click)=\"deleteCredential(credential, $event)\"\n title=\"Delete\"\n >\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"card-body\" (click)=\"editCredential(credential)\">\n <div class=\"status-badge\" [ngClass]=\"getStatusClass(credential)\">\n <i [class]=\"getStatusIcon(credential)\"></i>\n {{getStatusLabel(credential)}}\n </div>\n @if (credential.Description) {\n <p class=\"credential-description\">\n {{credential.Description}}\n </p>\n }\n <div class=\"credential-meta\">\n @if (credential.IsDefault) {\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-star\"></i>\n <span>Default</span>\n </div>\n }\n @if (credential.ExpiresAt) {\n <div class=\"meta-item\" [class.warning]=\"isExpiringSoon(credential)\" [class.danger]=\"isExpired(credential)\">\n <i class=\"fa-solid fa-calendar\"></i>\n <span>{{isExpired(credential) ? 'Expired' : 'Expires'}}: {{formatDate(credential.ExpiresAt)}}</span>\n </div>\n }\n @if (credential.LastUsedAt) {\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Last used: {{formatDate(credential.LastUsedAt)}}</span>\n </div>\n }\n </div>\n </div>\n <div class=\"card-footer\">\n @if (credential.Category) {\n <div class=\"category-tag\">\n <i class=\"fa-solid fa-folder\"></i>\n {{credential.Category}}\n </div>\n }\n <div class=\"created-info\">\n Created {{formatDate(credential.__mj_CreatedAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n <!-- List View -->\n @if (viewMode === 'list' && filteredCredentials.length > 0) {\n <div class=\"credentials-table-container\">\n <table class=\"credentials-table\">\n <thead>\n <tr>\n @if (UserCanUpdate || UserCanDelete) {\n <th class=\"col-select\">\n <input\n type=\"checkbox\"\n [checked]=\"isAllSelected()\"\n (change)=\"toggleSelectAll()\"\n />\n </th>\n }\n <th class=\"col-name\">Name</th>\n <th class=\"col-type\">Type</th>\n <th class=\"col-category\">Category</th>\n <th class=\"col-status\">Status</th>\n <th class=\"col-expires\">Expires</th>\n <th class=\"col-used\">Last Used</th>\n <th class=\"col-actions\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (credential of filteredCredentials; track credential) {\n <tr\n [class.selected]=\"selectedCredentials.has(credential.ID)\"\n [class.expired]=\"isExpired(credential)\"\n >\n @if (UserCanUpdate || UserCanDelete) {\n <td class=\"col-select\">\n <input\n type=\"checkbox\"\n [checked]=\"selectedCredentials.has(credential.ID)\"\n (change)=\"toggleSelection(credential)\"\n />\n </td>\n }\n <td class=\"col-name\" (click)=\"editCredential(credential)\">\n <div class=\"name-cell\">\n <i [class]=\"credential.IconClass || 'fa-solid fa-key'\" [ngClass]=\"getStatusClass(credential)\"></i>\n <div class=\"name-info\">\n <span class=\"credential-name\">{{credential.Name}}</span>\n @if (credential.Description) {\n <span class=\"credential-desc\">{{credential.Description}}</span>\n }\n </div>\n @if (credential.IsDefault) {\n <span class=\"default-badge\">Default</span>\n }\n </div>\n </td>\n <td class=\"col-type\">{{credential.CredentialType || '-'}}</td>\n <td class=\"col-category\">\n @if (credential.Category) {\n <span class=\"category-pill\">{{credential.Category}}</span>\n }\n @if (!credential.Category) {\n <span>-</span>\n }\n </td>\n <td class=\"col-status\">\n <span class=\"status-pill\" [ngClass]=\"getStatusClass(credential)\">\n {{getStatusLabel(credential)}}\n </span>\n </td>\n <td class=\"col-expires\" [class.warning]=\"isExpiringSoon(credential)\" [class.danger]=\"isExpired(credential)\">\n {{credential.ExpiresAt ? formatDate(credential.ExpiresAt) : 'Never'}}\n </td>\n <td class=\"col-used\">\n {{credential.LastUsedAt ? formatDate(credential.LastUsedAt) : 'Never'}}\n </td>\n <td class=\"col-actions\">\n <div class=\"table-actions\">\n @if (UserCanUpdate) {\n <button\n class=\"table-action-btn\"\n (click)=\"toggleCredentialActive(credential, $event)\"\n [title]=\"credential.IsActive ? 'Deactivate' : 'Activate'\"\n >\n <i [class]=\"credential.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\"></i>\n </button>\n }\n @if (UserCanUpdate) {\n <button\n class=\"table-action-btn\"\n (click)=\"editCredential(credential, $event)\"\n title=\"Edit\"\n >\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n @if (UserCanDelete) {\n <button\n class=\"table-action-btn danger\"\n (click)=\"deleteCredential(credential, $event)\"\n title=\"Delete\"\n >\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n <!-- Empty State -->\n @if (filteredCredentials.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <h3>No Credentials Found</h3>\n @if (searchText || selectedTypeFilter || selectedStatusFilter) {\n <p>\n No credentials match your current filters.\n <button class=\"btn-link\" (click)=\"clearFilters()\">Clear filters</button>\n </p>\n }\n @if (!searchText && !selectedTypeFilter && !selectedStatusFilter) {\n <p>\n Get started by creating your first credential.\n </p>\n }\n @if (UserCanCreate && !searchText && !selectedTypeFilter && !selectedStatusFilter) {\n <button class=\"btn-primary\" (click)=\"createNewCredential()\">\n <i class=\"fa-solid fa-plus\"></i>\n Create Credential\n </button>\n }\n </div>\n }\n }\n\n <!-- Edit Panel -->\n <mj-credential-edit-panel\n #editPanel\n [credentialTypes]=\"types\"\n (saved)=\"onCredentialSaved($event)\"\n (deleted)=\"onCredentialDeleted($event)\"\n ></mj-credential-edit-panel>\n</div>\n", styles: [".list-container {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--page-background, #f8fafc);\n}\n\n/* Header */\n.list-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 24px;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n.header-info {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.list-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n margin: 0;\n}\n\n.header-stats {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.stat-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n}\n\n.stat-item i {\n font-size: 12px;\n}\n\n.stat-item.active {\n color: #10b981;\n}\n\n.stat-item.warning {\n color: #f59e0b;\n}\n\n.stat-item.danger {\n color: #ef4444;\n}\n\n.header-actions {\n display: flex;\n gap: 12px;\n}\n\n.btn-primary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);\n color: white;\n border: none;\n border-radius: 10px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);\n}\n\n.btn-primary:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 16px rgba(99, 102, 241, 0.4);\n}\n\n.btn-primary i {\n font-size: 13px;\n}\n\n/* Toolbar */\n.toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n background: var(--card-background, #ffffff);\n padding: 16px;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n\n.toolbar-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n flex: 1;\n}\n\n.toolbar-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.search-container {\n display: flex;\n align-items: center;\n background: var(--input-background, #f9fafb);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n padding: 8px 12px;\n min-width: 280px;\n position: relative;\n}\n\n.search-container i {\n color: var(--text-secondary, #6b7280);\n margin-right: 8px;\n}\n\n.search-container input {\n border: none;\n background: transparent;\n outline: none;\n flex: 1;\n font-size: 14px;\n color: var(--text-primary, #1f2937);\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 background: var(--border-color, #e5e7eb);\n border: none;\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, #6b7280);\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, #ffffff);\n font-size: 14px;\n color: var(--text-primary, #1f2937);\n cursor: pointer;\n min-width: 140px;\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 white-space: nowrap;\n}\n\n.view-toggle {\n display: flex;\n background: var(--input-background, #f3f4f6);\n border-radius: 8px;\n padding: 4px;\n}\n\n.view-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.view-btn:hover {\n color: var(--accent-color, #6366f1);\n}\n\n.view-btn.active {\n background: white;\n color: var(--accent-color, #6366f1);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.btn-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n background: var(--button-background, #ffffff);\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-icon:hover {\n background: var(--button-hover, #f3f4f6);\n color: var(--accent-color, #6366f1);\n}\n\n/* Bulk Actions Bar */\n.bulk-actions {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);\n border-radius: 10px;\n margin-bottom: 16px;\n color: white;\n}\n\n.bulk-info {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.bulk-count {\n font-weight: 600;\n font-size: 14px;\n}\n\n.btn-link {\n background: none;\n border: none;\n color: rgba(255, 255, 255, 0.8);\n font-size: 13px;\n cursor: pointer;\n text-decoration: underline;\n padding: 0;\n}\n\n.btn-link:hover {\n color: white;\n}\n\n.bulk-buttons {\n display: flex;\n gap: 8px;\n}\n\n.btn-bulk {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: rgba(255, 255, 255, 0.2);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 6px;\n color: white;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-bulk:hover {\n background: rgba(255, 255, 255, 0.3);\n}\n\n.btn-bulk.danger {\n background: rgba(239, 68, 68, 0.3);\n border-color: rgba(239, 68, 68, 0.5);\n}\n\n.btn-bulk.danger:hover {\n background: rgba(239, 68, 68, 0.5);\n}\n\n/* Credentials Grid */\n.credentials-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));\n gap: 20px;\n}\n\n.credential-card {\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 transition: all 0.2s ease;\n position: relative;\n border: 2px solid transparent;\n}\n\n.credential-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);\n}\n\n.credential-card.selected {\n border-color: var(--accent-color, #6366f1);\n background: linear-gradient(to bottom, rgba(99, 102, 241, 0.03), white);\n}\n\n.credential-card.expired {\n border-color: rgba(239, 68, 68, 0.3);\n}\n\n.credential-card.expiring {\n border-color: rgba(245, 158, 11, 0.3);\n}\n\n.card-select {\n position: absolute;\n top: 12px;\n left: 12px;\n z-index: 10;\n}\n\n.card-select input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--accent-color, #6366f1);\n}\n\n.card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n padding-left: 40px;\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.card-icon {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.card-icon.active {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: white;\n}\n\n.card-icon.inactive {\n background: var(--icon-inactive, #e5e7eb);\n color: var(--text-secondary, #6b7280);\n}\n\n.card-icon.expired {\n background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);\n color: white;\n}\n\n.card-icon.expiring {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n}\n\n.card-icon i {\n font-size: 18px;\n}\n\n.card-title {\n flex: 1;\n min-width: 0;\n}\n\n.credential-name {\n font-weight: 600;\n font-size: 15px;\n color: var(--text-primary, #1f2937);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.credential-type {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n margin-top: 2px;\n}\n\n.card-actions {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.credential-card:hover .card-actions {\n opacity: 1;\n}\n\n.action-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--input-background, #f3f4f6);\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.action-btn:hover {\n background: var(--accent-color, #6366f1);\n color: white;\n}\n\n.action-btn.danger:hover {\n background: #ef4444;\n}\n\n.card-body {\n padding: 16px;\n padding-left: 40px;\n cursor: pointer;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n margin-bottom: 12px;\n}\n\n.status-badge i {\n font-size: 10px;\n}\n\n.status-badge.active {\n background: #d1fae5;\n color: #059669;\n}\n\n.status-badge.inactive {\n background: #f3f4f6;\n color: #6b7280;\n}\n\n.status-badge.expired {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.status-badge.expiring {\n background: #fef3c7;\n color: #d97706;\n}\n\n.credential-description {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n line-height: 1.5;\n margin: 0 0 12px 0;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.credential-meta {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.meta-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.meta-item i {\n font-size: 11px;\n color: var(--accent-color, #6366f1);\n}\n\n.meta-item.warning {\n color: #f59e0b;\n}\n\n.meta-item.warning i {\n color: #f59e0b;\n}\n\n.meta-item.danger {\n color: #ef4444;\n}\n\n.meta-item.danger i {\n color: #ef4444;\n}\n\n.card-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n padding-left: 40px;\n background: var(--footer-background, #f9fafb);\n border-top: 1px solid var(--border-color, #f3f4f6);\n}\n\n.category-tag {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--tag-background, #e0e7ff);\n color: var(--accent-color, #6366f1);\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.category-tag i {\n font-size: 10px;\n}\n\n.created-info {\n font-size: 11px;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Table View */\n.credentials-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.credentials-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.credentials-table thead {\n background: var(--header-background, #f9fafb);\n}\n\n.credentials-table th {\n padding: 12px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--text-secondary, #6b7280);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n}\n\n.credentials-table td {\n padding: 12px 16px;\n font-size: 14px;\n color: var(--text-primary, #1f2937);\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.credentials-table tbody tr {\n transition: background 0.2s ease;\n}\n\n.credentials-table tbody tr:hover {\n background: var(--row-hover, #f9fafb);\n}\n\n.credentials-table tbody tr.selected {\n background: rgba(99, 102, 241, 0.05);\n}\n\n.credentials-table tbody tr.expired {\n background: rgba(239, 68, 68, 0.03);\n}\n\n.col-select {\n width: 40px;\n}\n\n.col-select input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n accent-color: var(--accent-color, #6366f1);\n}\n\n.col-name {\n min-width: 240px;\n cursor: pointer;\n}\n\n.name-cell {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.name-cell i {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.name-cell i.active {\n background: #d1fae5;\n color: #059669;\n}\n\n.name-cell i.inactive {\n background: #f3f4f6;\n color: #6b7280;\n}\n\n.name-cell i.expired {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.name-cell i.expiring {\n background: #fef3c7;\n color: #d97706;\n}\n\n.name-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n flex: 1;\n}\n\n.name-info .credential-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--text-primary, #1f2937);\n}\n\n.name-info .credential-desc {\n font-size: 12px;\n color: var(--text-secondary, #9ca3af);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.default-badge {\n background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);\n color: white;\n font-size: 10px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.col-type,\n.col-category {\n white-space: nowrap;\n}\n\n.category-pill {\n display: inline-block;\n padding: 4px 10px;\n background: var(--tag-background, #e0e7ff);\n color: var(--accent-color, #6366f1);\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.col-status {\n white-space: nowrap;\n}\n\n.status-pill {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-pill.active {\n background: #d1fae5;\n color: #059669;\n}\n\n.status-pill.inactive {\n background: #f3f4f6;\n color: #6b7280;\n}\n\n.status-pill.expired {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.status-pill.expiring {\n background: #fef3c7;\n color: #d97706;\n}\n\n.col-expires,\n.col-used {\n white-space: nowrap;\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n}\n\n.col-expires.warning {\n color: #f59e0b;\n font-weight: 500;\n}\n\n.col-expires.danger {\n color: #ef4444;\n font-weight: 500;\n}\n\n.col-actions {\n width: 120px;\n}\n\n.table-actions {\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.credentials-table tbody tr:hover .table-actions {\n opacity: 1;\n}\n\n.table-action-btn {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--input-background, #f3f4f6);\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n font-size: 13px;\n}\n\n.table-action-btn:hover {\n background: var(--accent-color, #6366f1);\n color: white;\n}\n\n.table-action-btn.danger:hover {\n background: #ef4444;\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: 80px 24px;\n text-align: center;\n background: var(--card-background, #ffffff);\n border-radius: 16px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%);\n border-radius: 20px;\n margin-bottom: 24px;\n}\n\n.empty-icon i {\n font-size: 36px;\n color: var(--accent-color, #6366f1);\n}\n\n.empty-state h3 {\n font-size: 20px;\n font-weight: 700;\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 0 24px 0;\n max-width: 400px;\n line-height: 1.5;\n}\n\n.empty-state .btn-link {\n color: var(--accent-color, #6366f1);\n text-decoration: underline;\n cursor: pointer;\n background: none;\n border: none;\n font-size: 14px;\n padding: 0;\n}\n\n.empty-state .btn-link:hover {\n color: var(--accent-hover, #4f46e5);\n}\n\n.empty-state .btn-primary {\n margin-top: 0;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .list-container {\n padding: 16px;\n }\n\n .list-header {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .list-title {\n font-size: 20px;\n }\n\n .header-stats {\n gap: 12px;\n }\n\n .stat-item {\n font-size: 12px;\n }\n\n .header-actions {\n width: 100%;\n }\n\n .header-actions .btn-primary {\n flex: 1;\n justify-content: center;\n }\n\n .toolbar {\n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n\n .toolbar-left {\n flex-direction: column;\n }\n\n .search-container {\n min-width: 100%;\n }\n\n .filter-select {\n width: 100%;\n }\n\n .toolbar-right {\n justify-content: space-between;\n }\n\n .credentials-grid {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n /* Make card actions always visible on mobile */\n .card-actions {\n opacity: 1;\n }\n\n .card-header {\n padding: 14px;\n padding-left: 36px;\n }\n\n .card-body {\n padding: 14px;\n padding-left: 36px;\n }\n\n .card-footer {\n padding: 10px 14px;\n padding-left: 36px;\n }\n\n .card-icon {\n width: 38px;\n height: 38px;\n }\n\n .card-icon i {\n font-size: 16px;\n }\n\n .bulk-actions {\n flex-direction: column;\n gap: 12px;\n text-align: center;\n }\n\n .bulk-info {\n flex-direction: column;\n gap: 8px;\n }\n\n .bulk-buttons {\n flex-wrap: wrap;\n justify-content: center;\n }\n\n .credentials-table-container {\n overflow-x: auto;\n }\n\n .credentials-table {\n min-width: 800px;\n }\n\n .empty-state {\n padding: 48px 20px;\n }\n\n .empty-icon {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon i {\n font-size: 28px;\n }\n\n .empty-state h3 {\n font-size: 18px;\n }\n}\n\n@media (max-width: 480px) {\n .list-container {\n padding: 12px;\n }\n\n .list-title {\n font-size: 18px;\n }\n\n .header-stats {\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n }\n\n .btn-primary {\n padding: 10px 16px;\n font-size: 13px;\n }\n\n .btn-primary span {\n display: none;\n }\n\n .btn-primary i {\n margin: 0;\n }\n\n .toolbar {\n padding: 10px;\n }\n\n .view-toggle {\n display: none;\n }\n\n .results-info {\n font-size: 12px;\n }\n\n .credential-card {\n border-radius: 10px;\n }\n\n .card-select {\n top: 10px;\n left: 10px;\n }\n\n .card-header {\n padding: 12px;\n padding-left: 32px;\n }\n\n .card-body {\n padding: 12px;\n padding-left: 32px;\n }\n\n .card-footer {\n padding: 10px 12px;\n padding-left: 32px;\n }\n\n .card-icon {\n width: 34px;\n height: 34px;\n margin-right: 10px;\n }\n\n .credential-name {\n font-size: 14px;\n }\n\n .credential-type {\n font-size: 11px;\n }\n\n .action-btn {\n width: 28px;\n height: 28px;\n }\n\n .status-badge {\n font-size: 10px;\n padding: 3px 8px;\n }\n\n .credential-meta {\n gap: 8px;\n }\n\n .meta-item {\n font-size: 11px;\n }\n\n .category-tag {\n font-size: 10px;\n padding: 3px 8px;\n }\n\n .created-info {\n font-size: 10px;\n }\n\n .empty-state {\n padding: 32px 16px;\n }\n\n .empty-icon {\n width: 56px;\n height: 56px;\n margin-bottom: 16px;\n }\n\n .empty-icon i {\n font-size: 24px;\n }\n\n .empty-state h3 {\n font-size: 16px;\n }\n\n .empty-state p {\n font-size: 13px;\n }\n}\n"] }]
|
|
1258
|
+
args: [{ standalone: false, selector: 'mj-credentials-list-resource', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"list-container\">\n @if (isLoading) {\n <mj-loading text=\"Loading credentials...\"></mj-loading>\n }\n\n @if (!isLoading) {\n <!-- Header with Stats -->\n <div class=\"list-header\">\n <div class=\"header-info\">\n <h2 class=\"list-title\">Credentials</h2>\n <div class=\"header-stats\">\n <span class=\"stat-item\">\n <i class=\"fa-solid fa-key\"></i>\n {{credentials.length}} total\n </span>\n <span class=\"stat-item active\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{getActiveCount()}} active\n </span>\n @if (getExpiringSoonCount() > 0) {\n <span class=\"stat-item warning\">\n <i class=\"fa-solid fa-clock\"></i>\n {{getExpiringSoonCount()}} expiring\n </span>\n }\n @if (getExpiredCount() > 0) {\n <span class=\"stat-item danger\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{getExpiredCount()}} expired\n </span>\n }\n </div>\n </div>\n <div class=\"header-actions\">\n @if (UserCanCreate) {\n <button class=\"btn-primary\" (click)=\"createNewCredential()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New Credential</span>\n </button>\n }\n </div>\n </div>\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 credentials...\"\n [value]=\"searchText\"\n (input)=\"onSearchChange($any($event.target).value)\"\n />\n @if (searchText) {\n <button class=\"search-clear\" (click)=\"onSearchChange('')\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <select\n class=\"filter-select\"\n [value]=\"selectedTypeFilter\"\n (change)=\"onTypeFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Types</option>\n @for (type of types; track type) {\n <option [value]=\"type.ID\">{{type.Name}}</option>\n }\n </select>\n <select\n class=\"filter-select\"\n [value]=\"selectedStatusFilter\"\n (change)=\"onStatusFilterChange($any($event.target).value)\"\n >\n <option value=\"\">All Statuses</option>\n <option value=\"active\">Active</option>\n <option value=\"inactive\">Inactive</option>\n <option value=\"expiring\">Expiring Soon</option>\n <option value=\"expired\">Expired</option>\n </select>\n </div>\n <div class=\"toolbar-right\">\n <div class=\"results-info\">\n {{filteredCredentials.length}} of {{credentials.length}}\n </div>\n <div class=\"view-toggle\">\n <button\n class=\"view-btn\"\n [class.active]=\"viewMode === 'grid'\"\n (click)=\"setViewMode('grid')\"\n title=\"Grid View\"\n >\n <i class=\"fa-solid fa-grid-2\"></i>\n </button>\n <button\n class=\"view-btn\"\n [class.active]=\"viewMode === 'list'\"\n (click)=\"setViewMode('list')\"\n title=\"List View\"\n >\n <i class=\"fa-solid fa-list\"></i>\n </button>\n </div>\n <button class=\"btn-icon\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- Bulk Actions Bar -->\n @if (selectedCredentials.size > 0) {\n <div class=\"bulk-actions\">\n <div class=\"bulk-info\">\n <span class=\"bulk-count\">{{selectedCredentials.size}} selected</span>\n <button class=\"btn-link\" (click)=\"clearSelection()\">Clear selection</button>\n </div>\n <div class=\"bulk-buttons\">\n @if (UserCanUpdate) {\n <button class=\"btn-bulk\" (click)=\"bulkToggleActive(true)\">\n <i class=\"fa-solid fa-toggle-on\"></i>\n Activate\n </button>\n }\n @if (UserCanUpdate) {\n <button class=\"btn-bulk\" (click)=\"bulkToggleActive(false)\">\n <i class=\"fa-solid fa-toggle-off\"></i>\n Deactivate\n </button>\n }\n @if (UserCanDelete) {\n <button class=\"btn-bulk danger\" (click)=\"bulkDelete()\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete\n </button>\n }\n </div>\n </div>\n }\n <!-- Grid View -->\n @if (viewMode === 'grid' && filteredCredentials.length > 0) {\n <div class=\"credentials-grid\">\n @for (credential of filteredCredentials; track credential) {\n <div\n class=\"credential-card\"\n [class.selected]=\"selectedCredentials.has(credential.ID)\"\n [class.expired]=\"isExpired(credential)\"\n [class.expiring]=\"isExpiringSoon(credential)\"\n >\n <!-- Selection Checkbox -->\n @if (UserCanUpdate || UserCanDelete) {\n <div class=\"card-select\">\n <input\n type=\"checkbox\"\n [checked]=\"selectedCredentials.has(credential.ID)\"\n (change)=\"toggleSelection(credential)\"\n />\n </div>\n }\n <div class=\"card-header\">\n <div class=\"card-icon\" [ngClass]=\"getStatusClass(credential)\">\n <i [class]=\"credential.IconClass || 'fa-solid fa-key'\"></i>\n </div>\n <div class=\"card-title\">\n <div class=\"credential-name\">{{credential.Name}}</div>\n <div class=\"credential-type\">{{credential.CredentialType || 'Unknown Type'}}</div>\n </div>\n <div class=\"card-actions\">\n @if (UserCanUpdate) {\n <button\n class=\"action-btn\"\n (click)=\"toggleCredentialActive(credential, $event)\"\n [title]=\"credential.IsActive ? 'Deactivate' : 'Activate'\"\n >\n <i [class]=\"credential.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\"></i>\n </button>\n }\n @if (UserCanUpdate) {\n <button\n class=\"action-btn\"\n (click)=\"editCredential(credential, $event)\"\n title=\"Edit\"\n >\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n @if (UserCanDelete) {\n <button\n class=\"action-btn danger\"\n (click)=\"deleteCredential(credential, $event)\"\n title=\"Delete\"\n >\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"card-body\" (click)=\"editCredential(credential)\">\n <div class=\"status-badge\" [ngClass]=\"getStatusClass(credential)\">\n <i [class]=\"getStatusIcon(credential)\"></i>\n {{getStatusLabel(credential)}}\n </div>\n @if (credential.Description) {\n <p class=\"credential-description\">\n {{credential.Description}}\n </p>\n }\n <div class=\"credential-meta\">\n @if (credential.IsDefault) {\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-star\"></i>\n <span>Default</span>\n </div>\n }\n @if (credential.ExpiresAt) {\n <div class=\"meta-item\" [class.warning]=\"isExpiringSoon(credential)\" [class.danger]=\"isExpired(credential)\">\n <i class=\"fa-solid fa-calendar\"></i>\n <span>{{isExpired(credential) ? 'Expired' : 'Expires'}}: {{formatDate(credential.ExpiresAt)}}</span>\n </div>\n }\n @if (credential.LastUsedAt) {\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Last used: {{formatDate(credential.LastUsedAt)}}</span>\n </div>\n }\n </div>\n </div>\n <div class=\"card-footer\">\n @if (credential.Category) {\n <div class=\"category-tag\">\n <i class=\"fa-solid fa-folder\"></i>\n {{credential.Category}}\n </div>\n }\n <div class=\"created-info\">\n Created {{formatDate(credential.__mj_CreatedAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n <!-- List View -->\n @if (viewMode === 'list' && filteredCredentials.length > 0) {\n <div class=\"credentials-table-container\">\n <table class=\"credentials-table\">\n <thead>\n <tr>\n @if (UserCanUpdate || UserCanDelete) {\n <th class=\"col-select\">\n <input\n type=\"checkbox\"\n [checked]=\"isAllSelected()\"\n (change)=\"toggleSelectAll()\"\n />\n </th>\n }\n <th class=\"col-name\">Name</th>\n <th class=\"col-type\">Type</th>\n <th class=\"col-category\">Category</th>\n <th class=\"col-status\">Status</th>\n <th class=\"col-expires\">Expires</th>\n <th class=\"col-used\">Last Used</th>\n <th class=\"col-actions\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (credential of filteredCredentials; track credential) {\n <tr\n [class.selected]=\"selectedCredentials.has(credential.ID)\"\n [class.expired]=\"isExpired(credential)\"\n >\n @if (UserCanUpdate || UserCanDelete) {\n <td class=\"col-select\">\n <input\n type=\"checkbox\"\n [checked]=\"selectedCredentials.has(credential.ID)\"\n (change)=\"toggleSelection(credential)\"\n />\n </td>\n }\n <td class=\"col-name\" (click)=\"editCredential(credential)\">\n <div class=\"name-cell\">\n <i [class]=\"credential.IconClass || 'fa-solid fa-key'\" [ngClass]=\"getStatusClass(credential)\"></i>\n <div class=\"name-info\">\n <span class=\"credential-name\">{{credential.Name}}</span>\n @if (credential.Description) {\n <span class=\"credential-desc\">{{credential.Description}}</span>\n }\n </div>\n @if (credential.IsDefault) {\n <span class=\"default-badge\">Default</span>\n }\n </div>\n </td>\n <td class=\"col-type\">{{credential.CredentialType || '-'}}</td>\n <td class=\"col-category\">\n @if (credential.Category) {\n <span class=\"category-pill\">{{credential.Category}}</span>\n }\n @if (!credential.Category) {\n <span>-</span>\n }\n </td>\n <td class=\"col-status\">\n <span class=\"status-pill\" [ngClass]=\"getStatusClass(credential)\">\n {{getStatusLabel(credential)}}\n </span>\n </td>\n <td class=\"col-expires\" [class.warning]=\"isExpiringSoon(credential)\" [class.danger]=\"isExpired(credential)\">\n {{credential.ExpiresAt ? formatDate(credential.ExpiresAt) : 'Never'}}\n </td>\n <td class=\"col-used\">\n {{credential.LastUsedAt ? formatDate(credential.LastUsedAt) : 'Never'}}\n </td>\n <td class=\"col-actions\">\n <div class=\"table-actions\">\n @if (UserCanUpdate) {\n <button\n class=\"table-action-btn\"\n (click)=\"toggleCredentialActive(credential, $event)\"\n [title]=\"credential.IsActive ? 'Deactivate' : 'Activate'\"\n >\n <i [class]=\"credential.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\"></i>\n </button>\n }\n @if (UserCanUpdate) {\n <button\n class=\"table-action-btn\"\n (click)=\"editCredential(credential, $event)\"\n title=\"Edit\"\n >\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n @if (UserCanDelete) {\n <button\n class=\"table-action-btn danger\"\n (click)=\"deleteCredential(credential, $event)\"\n title=\"Delete\"\n >\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n <!-- Empty State -->\n @if (filteredCredentials.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <h3>No Credentials Found</h3>\n @if (searchText || selectedTypeFilter || selectedStatusFilter) {\n <p>\n No credentials match your current filters.\n <button class=\"btn-link\" (click)=\"clearFilters()\">Clear filters</button>\n </p>\n }\n @if (!searchText && !selectedTypeFilter && !selectedStatusFilter) {\n <p>\n Get started by creating your first credential.\n </p>\n }\n @if (UserCanCreate && !searchText && !selectedTypeFilter && !selectedStatusFilter) {\n <button class=\"btn-primary\" (click)=\"createNewCredential()\">\n <i class=\"fa-solid fa-plus\"></i>\n Create Credential\n </button>\n }\n </div>\n }\n }\n\n <!-- Edit Panel -->\n <mj-credential-edit-panel\n #editPanel\n [credentialTypes]=\"types\"\n (saved)=\"onCredentialSaved($event)\"\n (deleted)=\"onCredentialDeleted($event)\"\n ></mj-credential-edit-panel>\n</div>\n", styles: [".list-container {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page);\n}\n\n/* Header */\n.list-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 24px;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n.header-info {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.list-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.header-stats {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.stat-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.stat-item i {\n font-size: 12px;\n}\n\n.stat-item.active {\n color: var(--mj-status-success);\n}\n\n.stat-item.warning {\n color: var(--mj-status-warning);\n}\n\n.stat-item.danger {\n color: var(--mj-status-error);\n}\n\n.header-actions {\n display: flex;\n gap: 12px;\n}\n\n.btn-primary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 10px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.btn-primary:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 16px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.btn-primary i {\n font-size: 13px;\n}\n\n/* Toolbar */\n.toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n background: var(--mj-bg-surface);\n padding: 16px;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n\n.toolbar-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n flex: 1;\n}\n\n.toolbar-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.search-container {\n display: flex;\n align-items: center;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 8px 12px;\n min-width: 280px;\n position: relative;\n}\n\n.search-container i {\n color: var(--mj-text-secondary);\n margin-right: 8px;\n}\n\n.search-container input {\n border: none;\n background: transparent;\n outline: none;\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\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 background: var(--mj-border-default);\n border: none;\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-secondary);\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);\n font-size: 14px;\n color: var(--mj-text-primary);\n cursor: pointer;\n min-width: 140px;\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 white-space: nowrap;\n}\n\n.view-toggle {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n padding: 4px;\n}\n\n.view-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n border-radius: 6px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.view-btn:hover {\n color: var(--mj-brand-primary);\n}\n\n.view-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.btn-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\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-sunken);\n color: var(--mj-brand-primary);\n}\n\n/* Bulk Actions Bar */\n.bulk-actions {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-bottom: 16px;\n color: var(--mj-text-inverse);\n}\n\n.bulk-info {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.bulk-count {\n font-weight: 600;\n font-size: 14px;\n}\n\n.btn-link {\n background: none;\n border: none;\n color: color-mix(in srgb, var(--mj-bg-surface) 80%, transparent);\n font-size: 13px;\n cursor: pointer;\n text-decoration: underline;\n padding: 0;\n}\n\n.btn-link:hover {\n color: var(--mj-text-inverse);\n}\n\n.bulk-buttons {\n display: flex;\n gap: 8px;\n}\n\n.btn-bulk {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: color-mix(in srgb, var(--mj-bg-surface) 20%, transparent);\n border: 1px solid color-mix(in srgb, var(--mj-bg-surface) 30%, transparent);\n border-radius: 6px;\n color: var(--mj-text-inverse);\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-bulk:hover {\n background: color-mix(in srgb, var(--mj-bg-surface) 30%, transparent);\n}\n\n.btn-bulk.danger {\n background: color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n border-color: color-mix(in srgb, var(--mj-status-error) 50%, transparent);\n}\n\n.btn-bulk.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 50%, transparent);\n}\n\n/* Credentials Grid */\n.credentials-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));\n gap: 20px;\n}\n\n.credential-card {\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 transition: all 0.2s ease;\n position: relative;\n border: 2px solid transparent;\n}\n\n.credential-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);\n}\n\n.credential-card.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, var(--mj-bg-surface));\n}\n\n.credential-card.expired {\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n}\n\n.credential-card.expiring {\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.card-select {\n position: absolute;\n top: 12px;\n left: 12px;\n z-index: 10;\n}\n\n.card-select input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n}\n\n.card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n padding-left: 40px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.card-icon {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.card-icon.active {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.card-icon.inactive {\n background: var(--mj-border-default);\n color: var(--mj-text-secondary);\n}\n\n.card-icon.expired {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.card-icon.expiring {\n background: var(--mj-status-warning);\n color: var(--mj-text-inverse);\n}\n\n.card-icon i {\n font-size: 18px;\n}\n\n.card-title {\n flex: 1;\n min-width: 0;\n}\n\n.credential-name {\n font-weight: 600;\n font-size: 15px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.credential-type {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n.card-actions {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.credential-card:hover .card-actions {\n opacity: 1;\n}\n\n.action-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.action-btn.danger:hover {\n background: var(--mj-status-error);\n}\n\n.card-body {\n padding: 16px;\n padding-left: 40px;\n cursor: pointer;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n margin-bottom: 12px;\n}\n\n.status-badge i {\n font-size: 10px;\n}\n\n.status-badge.active {\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.inactive {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-badge.expired {\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.expiring {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.credential-description {\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0 0 12px 0;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.credential-meta {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.meta-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.meta-item i {\n font-size: 11px;\n color: var(--mj-brand-primary);\n}\n\n.meta-item.warning {\n color: var(--mj-status-warning);\n}\n\n.meta-item.warning i {\n color: var(--mj-status-warning);\n}\n\n.meta-item.danger {\n color: var(--mj-status-error);\n}\n\n.meta-item.danger i {\n color: var(--mj-status-error);\n}\n\n.card-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n padding-left: 40px;\n background: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.category-tag {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.category-tag i {\n font-size: 10px;\n}\n\n.created-info {\n font-size: 11px;\n color: var(--mj-text-disabled);\n}\n\n/* Table View */\n.credentials-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.credentials-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.credentials-table thead {\n background: var(--mj-bg-surface-card);\n}\n\n.credentials-table th {\n padding: 12px 16px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.credentials-table td {\n padding: 12px 16px;\n font-size: 14px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.credentials-table tbody tr {\n transition: background 0.2s ease;\n}\n\n.credentials-table tbody tr:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.credentials-table tbody tr.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.credentials-table tbody tr.expired {\n background: color-mix(in srgb, var(--mj-status-error) 3%, transparent);\n}\n\n.col-select {\n width: 40px;\n}\n\n.col-select input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n}\n\n.col-name {\n min-width: 240px;\n cursor: pointer;\n}\n\n.name-cell {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.name-cell i {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.name-cell i.active {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.name-cell i.inactive {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.name-cell i.expired {\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.name-cell i.expiring {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.name-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n flex: 1;\n}\n\n.name-info .credential-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.name-info .credential-desc {\n font-size: 12px;\n color: var(--mj-text-disabled);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.default-badge {\n background: var(--mj-status-warning);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.col-type,\n.col-category {\n white-space: nowrap;\n}\n\n.category-pill {\n display: inline-block;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.col-status {\n white-space: nowrap;\n}\n\n.status-pill {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-pill.active {\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-pill.inactive {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-pill.expired {\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-pill.expiring {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.col-expires,\n.col-used {\n white-space: nowrap;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.col-expires.warning {\n color: var(--mj-status-warning);\n font-weight: 500;\n}\n\n.col-expires.danger {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.col-actions {\n width: 120px;\n}\n\n.table-actions {\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.credentials-table tbody tr:hover .table-actions {\n opacity: 1;\n}\n\n.table-action-btn {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n font-size: 13px;\n}\n\n.table-action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.table-action-btn.danger:hover {\n background: var(--mj-status-error);\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: 80px 24px;\n text-align: center;\n background: var(--mj-bg-surface);\n border-radius: 16px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 20px;\n margin-bottom: 24px;\n}\n\n.empty-icon i {\n font-size: 36px;\n color: var(--mj-brand-primary);\n}\n\n.empty-state h3 {\n font-size: 20px;\n font-weight: 700;\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 0 24px 0;\n max-width: 400px;\n line-height: 1.5;\n}\n\n.empty-state .btn-link {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n cursor: pointer;\n background: none;\n border: none;\n font-size: 14px;\n padding: 0;\n}\n\n.empty-state .btn-link:hover {\n color: var(--mj-brand-primary-hover);\n}\n\n.empty-state .btn-primary {\n margin-top: 0;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .list-container {\n padding: 16px;\n }\n\n .list-header {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .list-title {\n font-size: 20px;\n }\n\n .header-stats {\n gap: 12px;\n }\n\n .stat-item {\n font-size: 12px;\n }\n\n .header-actions {\n width: 100%;\n }\n\n .header-actions .btn-primary {\n flex: 1;\n justify-content: center;\n }\n\n .toolbar {\n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n\n .toolbar-left {\n flex-direction: column;\n }\n\n .search-container {\n min-width: 100%;\n }\n\n .filter-select {\n width: 100%;\n }\n\n .toolbar-right {\n justify-content: space-between;\n }\n\n .credentials-grid {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n /* Make card actions always visible on mobile */\n .card-actions {\n opacity: 1;\n }\n\n .card-header {\n padding: 14px;\n padding-left: 36px;\n }\n\n .card-body {\n padding: 14px;\n padding-left: 36px;\n }\n\n .card-footer {\n padding: 10px 14px;\n padding-left: 36px;\n }\n\n .card-icon {\n width: 38px;\n height: 38px;\n }\n\n .card-icon i {\n font-size: 16px;\n }\n\n .bulk-actions {\n flex-direction: column;\n gap: 12px;\n text-align: center;\n }\n\n .bulk-info {\n flex-direction: column;\n gap: 8px;\n }\n\n .bulk-buttons {\n flex-wrap: wrap;\n justify-content: center;\n }\n\n .credentials-table-container {\n overflow-x: auto;\n }\n\n .credentials-table {\n min-width: 800px;\n }\n\n .empty-state {\n padding: 48px 20px;\n }\n\n .empty-icon {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon i {\n font-size: 28px;\n }\n\n .empty-state h3 {\n font-size: 18px;\n }\n}\n\n@media (max-width: 480px) {\n .list-container {\n padding: 12px;\n }\n\n .list-title {\n font-size: 18px;\n }\n\n .header-stats {\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n }\n\n .btn-primary {\n padding: 10px 16px;\n font-size: 13px;\n }\n\n .btn-primary span {\n display: none;\n }\n\n .btn-primary i {\n margin: 0;\n }\n\n .toolbar {\n padding: 10px;\n }\n\n .view-toggle {\n display: none;\n }\n\n .results-info {\n font-size: 12px;\n }\n\n .credential-card {\n border-radius: 10px;\n }\n\n .card-select {\n top: 10px;\n left: 10px;\n }\n\n .card-header {\n padding: 12px;\n padding-left: 32px;\n }\n\n .card-body {\n padding: 12px;\n padding-left: 32px;\n }\n\n .card-footer {\n padding: 10px 12px;\n padding-left: 32px;\n }\n\n .card-icon {\n width: 34px;\n height: 34px;\n margin-right: 10px;\n }\n\n .credential-name {\n font-size: 14px;\n }\n\n .credential-type {\n font-size: 11px;\n }\n\n .action-btn {\n width: 28px;\n height: 28px;\n }\n\n .status-badge {\n font-size: 10px;\n padding: 3px 8px;\n }\n\n .credential-meta {\n gap: 8px;\n }\n\n .meta-item {\n font-size: 11px;\n }\n\n .category-tag {\n font-size: 10px;\n padding: 3px 8px;\n }\n\n .created-info {\n font-size: 10px;\n }\n\n .empty-state {\n padding: 32px 16px;\n }\n\n .empty-icon {\n width: 56px;\n height: 56px;\n margin-bottom: 16px;\n }\n\n .empty-icon i {\n font-size: 24px;\n }\n\n .empty-state h3 {\n font-size: 16px;\n }\n\n .empty-state p {\n font-size: 13px;\n }\n}\n"] }]
|
|
1259
1259
|
}], () => [{ type: i0.ChangeDetectorRef }], { editPanel: [{
|
|
1260
1260
|
type: ViewChild,
|
|
1261
1261
|
args: ['editPanel']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials-overview-resource.component.d.ts","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-overview-resource.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAA2B,MAAM,eAAe,CAAC;AAEzG,OAAO,EAAE,YAAY,EAA4F,MAAM,+BAA+B,CAAC;AAEvJ,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;;AAErF,UAAU,YAAY;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,QAAQ;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,YAAY;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IACvD,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,eAAe;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,qBAQa,oCAAqC,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;
|
|
1
|
+
{"version":3,"file":"credentials-overview-resource.component.d.ts","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-overview-resource.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAA2B,MAAM,eAAe,CAAC;AAEzG,OAAO,EAAE,YAAY,EAA4F,MAAM,+BAA+B,CAAC;AAEvJ,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;;AAErF,UAAU,YAAY;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,QAAQ;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,YAAY;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IACvD,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,eAAe;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,qBAQa,oCAAqC,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAyCpG,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,iBAAiB;IAzCtB,SAAS,UAAQ;IAGjB,gBAAgB,SAAK;IACrB,iBAAiB,SAAK;IACtB,kBAAkB,SAAK;IACvB,iBAAiB,SAAK;IACtB,eAAe,SAAK;IACpB,UAAU,SAAK;IAGf,aAAa,EAAE,YAAY,EAAE,CAAM;IACnC,SAAS,EAAE,QAAQ,EAAE,CAAM;IAC3B,cAAc,EAAE,YAAY,EAAE,CAAM;IACpC,UAAU,EAAE,eAAe,EAAE,CAAM;IAG1C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,SAAS,CAA0B;IAG3C,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,gBAAgB,CAA8B;IAItD,OAAO,CAAC,cAAc,CAOpB;IAEF,OAAO,CAAC,QAAQ,CAAuB;gBAG3B,GAAG,EAAE,iBAAiB,EACtB,iBAAiB,EAAE,iBAAiB;IAKhD,QAAQ,IAAI,IAAI;IAIhB,WAAW,IAAI,IAAI;IAKb,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3D,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAK/D,IAAW,wBAAwB,IAAI,OAAO,CAE7C;IAED,IAAW,wBAAwB,IAAI,OAAO,CAE7C;IAED,OAAO,CAAC,qBAAqB;YAgCf,QAAQ;IAuEtB,OAAO,CAAC,sBAAsB;IAoB9B,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,oBAAoB;IAiC5B,OAAO,CAAC,wBAAwB;IAkDhC,OAAO,CAAC,4BAA4B;IAgBpC,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,eAAe;IAchB,mBAAmB,IAAI,IAAI;IAO3B,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAK1C,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAO7C,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAOrC,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAM7C,kBAAkB,IAAI,IAAI;IAI1B,YAAY,IAAI,IAAI;IAIpB,YAAY,IAAI,IAAI;IAIpB,iBAAiB,IAAI,IAAI;IAIzB,uBAAuB,IAAI,IAAI;IAQ/B,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAoB9B,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAUrC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAUtC,OAAO,IAAI,IAAI;IAIf,cAAc,IAAI,MAAM;IAUxB,cAAc,IAAI,MAAM;IAOxB,cAAc,IAAI,MAAM;IAOxB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;yCA1dnC,oCAAoC;2CAApC,oCAAoC;CAsehD"}
|