@memberjunction/ng-dashboards 5.22.0 → 5.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -0
- package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +364 -362
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +2 -2
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +275 -64
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +2645 -436
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +240 -6
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +2166 -256
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +191 -197
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +9 -8
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +305 -299
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +319 -313
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +1 -2
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +12 -27
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +10 -12
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.js +13 -19
- package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js +12 -14
- package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +61 -68
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
- package/dist/APIKeys/api-usage-panel.component.js +10 -11
- package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
- package/dist/Actions/components/actions-list-view.component.js +82 -96
- package/dist/Actions/components/actions-list-view.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +130 -134
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +40 -46
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/code-management.component.js +2 -2
- package/dist/Actions/components/code-management.component.js.map +1 -1
- package/dist/Actions/components/entity-integration.component.js +2 -2
- package/dist/Actions/components/entity-integration.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +127 -132
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/executions-list-view.component.js +2 -2
- package/dist/Actions/components/executions-list-view.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.js +11 -17
- package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +5 -11
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-list-item.component.js +8 -10
- package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-toolbar.component.js +112 -133
- package/dist/Actions/components/explorer/action-toolbar.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-tree-panel.component.js +63 -83
- package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js +17 -21
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +17 -21
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Actions/components/scheduled-actions.component.js +2 -2
- package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
- package/dist/Actions/components/security-permissions.component.js +2 -2
- package/dist/Actions/components/security-permissions.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts +13 -5
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +168 -145
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +4 -5
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +197 -200
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +5 -7
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +142 -148
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/browser/component-browser.component.js +153 -166
- package/dist/ComponentStudio/components/browser/component-browser.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +15 -20
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +16 -21
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js +18 -23
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/spec-editor.component.js +25 -30
- package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +10 -11
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +24 -35
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/text-import-dialog.component.js +15 -17
- package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +7 -6
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +6 -5
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +7 -6
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +9 -9
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +4 -4
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +4 -4
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +246 -259
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
- package/dist/Integration/components/widgets/integration-card.component.js +7 -9
- package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
- package/dist/Integration/integration.module.d.ts +6 -10
- package/dist/Integration/integration.module.d.ts.map +1 -1
- package/dist/Integration/integration.module.js +12 -20
- package/dist/Integration/integration.module.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +106 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +607 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +7 -2
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +59 -31
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/index.d.ts +1 -0
- package/dist/KnowledgeHub/index.d.ts.map +1 -1
- package/dist/KnowledgeHub/index.js +1 -0
- package/dist/KnowledgeHub/index.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +9 -7
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +5 -4
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +10 -9
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +141 -132
- package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-log-detail-panel.component.js +4 -4
- package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +141 -128
- package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +210 -218
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +2 -2
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/MCP/mcp.module.d.ts +6 -9
- package/dist/MCP/mcp.module.d.ts.map +1 -1
- package/dist/MCP/mcp.module.js +20 -22
- package/dist/MCP/mcp.module.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +5 -4
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +6 -5
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +93 -92
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +9 -10
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/actions-dashboards.module.d.ts +8 -13
- package/dist/actions-dashboards.module.d.ts.map +1 -1
- package/dist/actions-dashboards.module.js +6 -27
- package/dist/actions-dashboards.module.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +16 -20
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +23 -44
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +4 -8
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +0 -19
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/component-studio-dashboards.module.d.ts +7 -11
- package/dist/component-studio-dashboards.module.d.ts.map +1 -1
- package/dist/component-studio-dashboards.module.js +22 -34
- package/dist/component-studio-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +12 -18
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +15 -31
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/credentials-dashboards.module.d.ts +5 -8
- package/dist/credentials-dashboards.module.d.ts.map +1 -1
- package/dist/credentials-dashboards.module.js +3 -19
- package/dist/credentials-dashboards.module.js.map +1 -1
- package/dist/data-explorer-dashboards.module.d.ts +7 -13
- package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
- package/dist/data-explorer-dashboards.module.js +0 -27
- package/dist/data-explorer-dashboards.module.js.map +1 -1
- package/dist/lists-dashboards.module.d.ts +5 -8
- package/dist/lists-dashboards.module.d.ts.map +1 -1
- package/dist/lists-dashboards.module.js +3 -19
- package/dist/lists-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/dist/scheduling-dashboards.module.d.ts +6 -10
- package/dist/scheduling-dashboards.module.d.ts.map +1 -1
- package/dist/scheduling-dashboards.module.js +3 -23
- package/dist/scheduling-dashboards.module.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +7 -13
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +0 -27
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +47 -55
|
@@ -13,8 +13,9 @@ import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
|
13
13
|
import * as i0 from "@angular/core";
|
|
14
14
|
import * as i1 from "@angular/common";
|
|
15
15
|
import * as i2 from "@angular/forms";
|
|
16
|
-
import * as i3 from "@memberjunction/ng-
|
|
17
|
-
import * as i4 from "@memberjunction/ng-
|
|
16
|
+
import * as i3 from "@memberjunction/ng-ui-components";
|
|
17
|
+
import * as i4 from "@memberjunction/ng-shared-generic";
|
|
18
|
+
import * as i5 from "@memberjunction/ng-credentials";
|
|
18
19
|
const _c0 = ["editPanel"];
|
|
19
20
|
function CredentialsListResourceComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
20
21
|
i0.ɵɵelement(0, "mj-loading", 2);
|
|
@@ -1232,7 +1233,7 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
1232
1233
|
} if (rf & 2) {
|
|
1233
1234
|
let _t;
|
|
1234
1235
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.editPanel = _t.first);
|
|
1235
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 3, consts: [["editPanel", ""], [1, "list-container"], ["text", "Loading credentials..."], [3, "saved", "deleted", "credentialTypes"], [1, "list-header"], [1, "header-info"], [1, "list-title"], [1, "header-stats"], [1, "stat-item"], [1, "fa-solid", "fa-key"], [1, "stat-item", "active"], [1, "fa-solid", "fa-check-circle"], [1, "stat-item", "warning"], [1, "stat-item", "danger"], [1, "header-actions"], [1, "btn-primary"], [1, "toolbar"], [1, "toolbar-left"], [1, "search-container"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search credentials...", 3, "input", "value"], [1, "search-clear"], [1, "filter-select", 3, "change", "value"], ["value", ""], [3, "value"], ["value", "active"], ["value", "inactive"], ["value", "expiring"], ["value", "expired"], [1, "toolbar-right"], [1, "results-info"], [1, "view-toggle"], ["title", "Grid View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-grid-2"], ["title", "List View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["title", "Refresh", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-refresh"], [1, "bulk-actions"], [1, "credentials-grid"], [1, "credentials-table-container"], [1, "empty-state"], [1, "fa-solid", "fa-clock"], [1, "fa-solid", "fa-exclamation-circle"], [1, "btn-primary", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "search-clear", 3, "click"], [1, "fa-solid", "fa-times"], [1, "bulk-info"], [1, "bulk-count"], [1, "btn-link", 3, "click"], [1, "bulk-buttons"], [1, "btn-bulk"], [1, "btn-bulk", "danger"], [1, "btn-bulk", 3, "click"], [1, "fa-solid", "fa-toggle-on"], [1, "fa-solid", "fa-toggle-off"], [1, "btn-bulk", "danger", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "credential-card", 3, "selected", "expired", "expiring"], [1, "credential-card"], [1, "card-select"], [1, "card-header"], [1, "card-icon", 3, "ngClass"], [1, "card-title"], [1, "credential-name"], [1, "credential-type"], [1, "card-actions"], [
|
|
1236
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 3, consts: [["editPanel", ""], [1, "list-container"], ["text", "Loading credentials..."], [3, "saved", "deleted", "credentialTypes"], [1, "list-header"], [1, "header-info"], [1, "list-title"], [1, "header-stats"], [1, "stat-item"], [1, "fa-solid", "fa-key"], [1, "stat-item", "active"], [1, "fa-solid", "fa-check-circle"], [1, "stat-item", "warning"], [1, "stat-item", "danger"], [1, "header-actions"], [1, "btn-primary"], [1, "toolbar"], [1, "toolbar-left"], [1, "search-container"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search credentials...", 3, "input", "value"], [1, "search-clear"], [1, "filter-select", 3, "change", "value"], ["value", ""], [3, "value"], ["value", "active"], ["value", "inactive"], ["value", "expiring"], ["value", "expired"], [1, "toolbar-right"], [1, "results-info"], [1, "view-toggle"], ["title", "Grid View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-grid-2"], ["title", "List View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["title", "Refresh", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-refresh"], [1, "bulk-actions"], [1, "credentials-grid"], [1, "credentials-table-container"], [1, "empty-state"], [1, "fa-solid", "fa-clock"], [1, "fa-solid", "fa-exclamation-circle"], [1, "btn-primary", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "search-clear", 3, "click"], [1, "fa-solid", "fa-times"], [1, "bulk-info"], [1, "bulk-count"], [1, "btn-link", 3, "click"], [1, "bulk-buttons"], [1, "btn-bulk"], [1, "btn-bulk", "danger"], [1, "btn-bulk", 3, "click"], [1, "fa-solid", "fa-toggle-on"], [1, "fa-solid", "fa-toggle-off"], [1, "btn-bulk", "danger", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "credential-card", 3, "selected", "expired", "expiring"], [1, "credential-card"], [1, "card-select"], [1, "card-header"], [1, "card-icon", 3, "ngClass"], [1, "card-title"], [1, "credential-name"], [1, "credential-type"], [1, "card-actions"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "title"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Edit"], ["mjButton", "", "variant", "danger", "size", "sm", "title", "Delete"], [1, "card-body", 3, "click"], [1, "status-badge", 3, "ngClass"], [1, "credential-description"], [1, "credential-meta"], [1, "meta-item"], [1, "meta-item", 3, "warning", "danger"], [1, "card-footer"], [1, "category-tag"], [1, "created-info"], ["type", "checkbox", 3, "change", "checked"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click", "title"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Edit", 3, "click"], [1, "fa-solid", "fa-pen"], ["mjButton", "", "variant", "danger", "size", "sm", "title", "Delete", 3, "click"], [1, "fa-solid", "fa-star"], [1, "fa-solid", "fa-calendar"], [1, "fa-solid", "fa-folder"], [1, "credentials-table"], [1, "col-select"], [1, "col-name"], [1, "col-type"], [1, "col-category"], [1, "col-status"], [1, "col-expires"], [1, "col-used"], [1, "col-actions"], [3, "selected", "expired"], [1, "col-name", 3, "click"], [1, "name-cell"], [3, "ngClass"], [1, "name-info"], [1, "credential-desc"], [1, "default-badge"], [1, "category-pill"], [1, "status-pill", 3, "ngClass"], [1, "table-actions"], [1, "table-action-btn", 3, "title"], ["title", "Edit", 1, "table-action-btn"], ["title", "Delete", 1, "table-action-btn", "danger"], [1, "table-action-btn", 3, "click", "title"], ["title", "Edit", 1, "table-action-btn", 3, "click"], ["title", "Delete", 1, "table-action-btn", "danger", 3, "click"], [1, "empty-icon"]], template: function CredentialsListResourceComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1236
1237
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
1237
1238
|
i0.ɵɵelementStart(0, "div", 1);
|
|
1238
1239
|
i0.ɵɵconditionalCreate(1, CredentialsListResourceComponent_Conditional_1_Template, 1, 0, "mj-loading", 2);
|
|
@@ -1247,7 +1248,7 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
1247
1248
|
i0.ɵɵconditional(!ctx.isLoading ? 2 : -1);
|
|
1248
1249
|
i0.ɵɵadvance();
|
|
1249
1250
|
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(--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
|
+
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i3.MJButtonDirective, i4.LoadingComponent, i5.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
1252
|
};
|
|
1252
1253
|
CredentialsListResourceComponent = __decorate([
|
|
1253
1254
|
RegisterClass(BaseResourceComponent, 'CredentialsListResource')
|
|
@@ -1255,7 +1256,7 @@ CredentialsListResourceComponent = __decorate([
|
|
|
1255
1256
|
export { CredentialsListResourceComponent };
|
|
1256
1257
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CredentialsListResourceComponent, [{
|
|
1257
1258
|
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(--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
|
+
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 mjButton variant=\"flat\" size=\"sm\"\n (click)=\"toggleCredentialActive(credential, $event)\"\n [title]=\"credential.IsActive ? 'Deactivate' : 'Activate'\">\n <i [class]=\"credential.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\"></i>\n </button>\n }\n @if (UserCanUpdate) {\n <button mjButton variant=\"flat\" size=\"sm\"\n (click)=\"editCredential(credential, $event)\"\n title=\"Edit\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n @if (UserCanDelete) {\n <button mjButton variant=\"danger\" size=\"sm\"\n (click)=\"deleteCredential(credential, $event)\"\n title=\"Delete\">\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
1260
|
}], () => [{ type: i0.ChangeDetectorRef }], { editPanel: [{
|
|
1260
1261
|
type: ViewChild,
|
|
1261
1262
|
args: ['editPanel']
|