@memberjunction/ng-dashboards 5.44.0 → 5.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +5 -3
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +4 -2
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +13 -11
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.d.ts +3 -1
- package/dist/AI/components/prompts/prompt-version-control.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js +12 -10
- package/dist/AI/components/prompts/prompt-version-control.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +1 -0
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +10 -8
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts +2 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +1 -0
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +5 -3
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts +3 -1
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +11 -5
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.d.ts +3 -2
- package/dist/Credentials/components/credentials-list-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +23 -9
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.d.ts +3 -2
- package/dist/Credentials/components/credentials-types-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +10 -4
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/modify/database-modify.component.d.ts +2 -1
- package/dist/DatabaseDesigner/components/modify/database-modify.component.d.ts.map +1 -1
- package/dist/DatabaseDesigner/components/modify/database-modify.component.js +13 -6
- package/dist/DatabaseDesigner/components/modify/database-modify.component.js.map +1 -1
- package/dist/FormBuilder/form-builder-resource.component.d.ts +2 -1
- package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
- package/dist/FormBuilder/form-builder-resource.component.js +10 -8
- package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.d.ts +3 -1
- package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +32 -14
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts +4 -2
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +15 -13
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/UserRoutines/user-routines-agent-context.d.ts +44 -0
- package/dist/UserRoutines/user-routines-agent-context.d.ts.map +1 -0
- package/dist/UserRoutines/user-routines-agent-context.js +81 -0
- package/dist/UserRoutines/user-routines-agent-context.js.map +1 -0
- package/dist/UserRoutines/user-routines-resource.component.d.ts +60 -0
- package/dist/UserRoutines/user-routines-resource.component.d.ts.map +1 -0
- package/dist/UserRoutines/user-routines-resource.component.js +328 -0
- package/dist/UserRoutines/user-routines-resource.component.js.map +1 -0
- package/dist/module.d.ts +16 -15
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +7 -0
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/dist/routines-dashboards.module.d.ts +17 -0
- package/dist/routines-dashboards.module.d.ts.map +1 -0
- package/dist/routines-dashboards.module.js +65 -0
- package/dist/routines-dashboards.module.js.map +1 -0
- package/package.json +63 -58
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials-categories-resource.component.js","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-categories-resource.component.ts","../../../src/Credentials/components/credentials-categories-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy, ViewChild } from '@angular/core';\nimport { ResourceData, MJCredentialCategoryEntity, MJCredentialTypeEntity } from '@memberjunction/core-entities';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { RunView, Metadata } from '@memberjunction/core';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { CredentialCategoryEditPanelComponent } from '@memberjunction/ng-credentials';\ninterface CategoryNode {\n category: MJCredentialCategoryEntity;\n children: CategoryNode[];\n expanded: boolean;\n level: number;\n typeCount: number;\n}\n\n@RegisterClass(BaseResourceComponent, 'CredentialsCategoriesResource')\n@Component({\n standalone: false,\n selector: 'mj-credentials-categories-resource',\n templateUrl: './credentials-categories-resource.component.html',\n styleUrls: ['./credentials-categories-resource.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class CredentialsCategoriesResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public isLoading = true;\n public categories: MJCredentialCategoryEntity[] = [];\n public categoryTree: CategoryNode[] = [];\n public types: MJCredentialTypeEntity[] = [];\n public selectedNode: CategoryNode | null = null;\n public searchText = '';\n\n // Permissions\n private _metadata = this.ProviderToUse;\n private _permissionCache = new Map<string, boolean>();\n\n @ViewChild('categoryEditPanel') categoryEditPanel!: CredentialCategoryEditPanelComponent;\n\n constructor(\n private cdr: ChangeDetectorRef) {\n super();\n }\n\n ngOnInit(): void {\n super.ngOnInit();\n this.loadData();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n // Cleanup if needed\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Categories';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-folder-tree';\n }\n\n // === Permission Checks ===\n\n public get UserCanCreate(): boolean {\n return this.checkEntityPermission('MJ: Credential Categories', 'Create');\n }\n\n public get UserCanUpdate(): boolean {\n return this.checkEntityPermission('MJ: Credential Categories', 'Update');\n }\n\n public get UserCanDelete(): boolean {\n return this.checkEntityPermission('MJ: Credential Categories', 'Delete');\n }\n\n private checkEntityPermission(entityName: string, permissionType: 'Create' | 'Read' | 'Update' | 'Delete'): boolean {\n const cacheKey = `${entityName}_${permissionType}`;\n\n if (this._permissionCache.has(cacheKey)) {\n return this._permissionCache.get(cacheKey)!;\n }\n\n try {\n const entityInfo = this._metadata.Entities.find(e => e.Name === entityName);\n if (!entityInfo) {\n this._permissionCache.set(cacheKey, false);\n return false;\n }\n\n const userPermissions = entityInfo.GetUserPermisions(this._metadata.CurrentUser);\n let hasPermission = false;\n\n switch (permissionType) {\n case 'Create': hasPermission = userPermissions.CanCreate; break;\n case 'Read': hasPermission = userPermissions.CanRead; break;\n case 'Update': hasPermission = userPermissions.CanUpdate; break;\n case 'Delete': hasPermission = userPermissions.CanDelete; break;\n }\n\n this._permissionCache.set(cacheKey, hasPermission);\n return hasPermission;\n } catch (error) {\n this._permissionCache.set(cacheKey, false);\n return false;\n }\n }\n\n private async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.markForCheck();\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const [catResult, typeResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Credential Categories',\n OrderBy: 'Name',\n ResultType: 'entity_object'\n },\n {\n EntityName: 'MJ: Credential Types',\n ResultType: 'entity_object'\n }\n ]);\n\n if (catResult.Success) {\n this.categories = catResult.Results as MJCredentialCategoryEntity[];\n }\n\n if (typeResult.Success) {\n this.types = typeResult.Results as MJCredentialTypeEntity[];\n }\n\n this.buildTree();\n\n } catch (error) {\n console.error('Error loading credential categories:', error);\n MJNotificationService.Instance.CreateSimpleNotification('Error loading categories', 'error', 3000);\n } finally {\n this.isLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n private buildTree(): void {\n const categoryMap = new Map<string, CategoryNode>();\n\n // Create nodes for all categories with stats\n for (const category of this.categories) {\n const typesInCategory = this.types.filter(t => t.Category === category.Name);\n categoryMap.set(category.ID, {\n category,\n children: [],\n expanded: true,\n level: 0,\n typeCount: typesInCategory.length\n });\n }\n\n // Build tree structure\n const roots: CategoryNode[] = [];\n for (const category of this.categories) {\n const node = categoryMap.get(category.ID)!;\n if (category.ParentID) {\n const parent = categoryMap.get(category.ParentID);\n if (parent) {\n node.level = parent.level + 1;\n parent.children.push(node);\n } else {\n roots.push(node);\n }\n } else {\n roots.push(node);\n }\n }\n\n // Sort children recursively\n const sortNodes = (nodes: CategoryNode[]): void => {\n nodes.sort((a, b) => a.category.Name.localeCompare(b.category.Name));\n for (const node of nodes) {\n sortNodes(node.children);\n }\n };\n sortNodes(roots);\n\n this.categoryTree = roots;\n }\n\n // === CRUD Operations ===\n\n public createNewCategory(): void {\n if (this.categoryEditPanel) {\n this.categoryEditPanel.open(null);\n }\n }\n\n public createChildCategory(parentNode: CategoryNode, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n if (this.categoryEditPanel) {\n this.categoryEditPanel.open(null, parentNode.category.ID);\n }\n }\n\n public editCategory(node: CategoryNode, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n if (this.categoryEditPanel) {\n this.categoryEditPanel.open(node.category);\n }\n }\n\n public async deleteCategory(node: CategoryNode, event?: Event): Promise<void> {\n if (event) {\n event.stopPropagation();\n }\n\n if (!this.UserCanDelete) {\n MJNotificationService.Instance.CreateSimpleNotification('You do not have permission to delete categories', 'warning', 3000);\n return;\n }\n\n if (node.children.length > 0) {\n MJNotificationService.Instance.CreateSimpleNotification(\n `Cannot delete \"${node.category.Name}\" - it has ${node.children.length} subcategories`,\n 'warning',\n 4000\n );\n return;\n }\n\n if (node.typeCount > 0) {\n MJNotificationService.Instance.CreateSimpleNotification(\n `Cannot delete \"${node.category.Name}\" - it has ${node.typeCount} credential type(s) using it`,\n 'warning',\n 4000\n );\n return;\n }\n\n const confirmed = confirm(`Are you sure you want to delete \"${node.category.Name}\"? This action cannot be undone.`);\n if (!confirmed) return;\n\n try {\n const success = await node.category.Delete();\n if (success) {\n MJNotificationService.Instance.CreateSimpleNotification(`Category \"${node.category.Name}\" deleted successfully`, 'success', 3000);\n this.categories = this.categories.filter(c => !UUIDsEqual(c.ID, node.category.ID));\n if (UUIDsEqual(this.selectedNode?.category.ID, node.category.ID)) {\n this.selectedNode = null;\n }\n this.buildTree();\n this.cdr.markForCheck();\n } else {\n MJNotificationService.Instance.CreateSimpleNotification('Failed to delete category', 'error', 3000);\n }\n } catch (error) {\n console.error('Error deleting category:', error);\n MJNotificationService.Instance.CreateSimpleNotification('Error deleting category', 'error', 3000);\n }\n }\n\n // === Panel Event Handlers ===\n\n public onCategorySaved(category: MJCredentialCategoryEntity): void {\n const existingIndex = this.categories.findIndex(c => UUIDsEqual(c.ID, category.ID));\n\n if (existingIndex >= 0) {\n this.categories[existingIndex] = category;\n } else {\n this.categories.push(category);\n }\n\n this.buildTree();\n this.cdr.markForCheck();\n }\n\n public onCategoryDeleted(categoryId: string): void {\n this.categories = this.categories.filter(c => !UUIDsEqual(c.ID, categoryId));\n if (UUIDsEqual(this.selectedNode?.category.ID, categoryId)) {\n this.selectedNode = null;\n }\n this.buildTree();\n this.cdr.markForCheck();\n }\n\n // === Selection ===\n\n public selectNode(node: CategoryNode): void {\n this.selectedNode = UUIDsEqual(this.selectedNode?.category.ID, node.category.ID) ? null : node;\n this.cdr.markForCheck();\n }\n\n public toggleExpand(node: CategoryNode, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n node.expanded = !node.expanded;\n this.cdr.markForCheck();\n }\n\n // === Search ===\n\n public onSearchChange(value: string): void {\n this.searchText = value;\n if (value) {\n this.expandAll();\n }\n this.cdr.markForCheck();\n }\n\n public clearSearch(): void {\n this.searchText = '';\n this.cdr.markForCheck();\n }\n\n /** Empty-state CTA: clear search when narrowing, otherwise create. */\n public onEmptyStateAction(): void {\n if (this.searchText) {\n this.clearSearch();\n } else {\n this.createNewCategory();\n }\n }\n\n public expandAll(): void {\n const expand = (nodes: CategoryNode[]): void => {\n for (const node of nodes) {\n node.expanded = true;\n expand(node.children);\n }\n };\n expand(this.categoryTree);\n this.cdr.markForCheck();\n }\n\n public collapseAll(): void {\n const collapse = (nodes: CategoryNode[]): void => {\n for (const node of nodes) {\n node.expanded = false;\n collapse(node.children);\n }\n };\n collapse(this.categoryTree);\n this.cdr.markForCheck();\n }\n\n public getFlattenedNodes(): CategoryNode[] {\n const result: CategoryNode[] = [];\n const searchLower = this.searchText.toLowerCase().trim();\n\n const flatten = (nodes: CategoryNode[]): void => {\n for (const node of nodes) {\n if (searchLower) {\n const matches = this.nodeMatchesSearch(node, searchLower);\n if (matches) {\n result.push(node);\n }\n } else {\n result.push(node);\n }\n\n if (node.expanded && node.children.length > 0) {\n flatten(node.children);\n }\n }\n };\n\n flatten(this.categoryTree);\n return result;\n }\n\n private nodeMatchesSearch(node: CategoryNode, searchLower: string): boolean {\n const nameMatch = node.category.Name.toLowerCase().includes(searchLower);\n const descMatch = node.category.Description?.toLowerCase().includes(searchLower);\n return nameMatch || descMatch || false;\n }\n\n public getTotalTypeCount(): number {\n return this.types.length;\n }\n\n public getTypesForCategory(categoryName: string): MJCredentialTypeEntity[] {\n return this.types.filter(t => t.Category === categoryName);\n }\n\n public createCredentialWithCategory(categoryId: string, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n // Navigate to Credentials nav item with the category pre-selected and create panel open\n this.navigationService.OpenNavItemByName('Credentials', {\n categoryId: categoryId,\n openCreatePanel: true\n });\n }\n\n public viewTypesForCategory(categoryName: string, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n // Navigate to Types nav item filtered by this category\n this.navigationService.OpenNavItemByName('Types', {\n categoryFilter: categoryName\n });\n }\n\n /** Case-insensitive UUID check whether a tree node is the currently selected node. */\n public IsNodeSelected(node: CategoryNode): boolean {\n return UUIDsEqual(this.selectedNode?.category?.ID, node.category.ID);\n }\n\n public getCategoryColor(index: number): string {\n const colors = [\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-primary)',\n 'var(--mj-status-warning)',\n 'var(--mj-status-success)',\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-primary)'\n ];\n return colors[index % colors.length];\n }\n\n public refresh(): void {\n this.selectedNode = null;\n this.loadData();\n }\n}\n","<mj-page-layout>\n <mj-page-header\n Title=\"Categories\"\n Icon=\"fa-solid fa-folder-tree\">\n <!-- [meta] intentionally omitted — chrome slot discipline audit Task B.\n The categories count mirrored the visible tree; the cross-entity\n types count belongs on the Types page, not here. -->\n\n <div actions>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"expandAll()\" title=\"Expand all\">\n <i class=\"fa-solid fa-expand\"></i> <span class=\"action-btn-label\">Expand</span>\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"collapseAll()\" title=\"Collapse all\">\n <i class=\"fa-solid fa-compress\"></i> <span class=\"action-btn-label\">Collapse</span>\n </button>\n <mj-refresh-button [Loading]=\"isLoading\" (Clicked)=\"refresh()\"></mj-refresh-button>\n @if (UserCanCreate) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"createNewCategory()\">\n <i class=\"fa-solid fa-plus\"></i> <span class=\"action-btn-label\">New Category</span>\n </button>\n }\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search categories...\"\n [Value]=\"searchText\"\n (ValueChange)=\"onSearchChange($event)\">\n </mj-page-search>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n @if (isLoading) {\n <mj-loading text=\"Loading categories...\"></mj-loading>\n }\n\n @if (!isLoading) {\n <div class=\"categories-layout\">\n <!-- Tree Container -->\n <div class=\"tree-panel\">\n @if (categoryTree.length > 0) {\n <div class=\"tree-container\">\n @for (node of getFlattenedNodes(); track node; let i = $index) {\n <div\n class=\"tree-node\"\n [class.selected]=\"IsNodeSelected(node)\"\n [style.padding-left.px]=\"12 + (node.level * 20)\"\n (click)=\"selectNode(node)\"\n >\n <div class=\"node-content\">\n @if (node.children.length > 0) {\n <button\n class=\"expand-btn\"\n (click)=\"toggleExpand(node, $event)\"\n >\n <i [class]=\"node.expanded ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-right'\"></i>\n </button>\n }\n @if (node.children.length === 0) {\n <span class=\"expand-placeholder\"></span>\n }\n <div class=\"node-icon\" [style.backgroundColor]=\"getCategoryColor(i) + '15'\" [style.color]=\"getCategoryColor(i)\">\n <i [class]=\"node.category.IconClass || 'fa-solid fa-folder'\"></i>\n </div>\n <div class=\"node-info\">\n <div class=\"node-name\">{{node.category.Name}}</div>\n @if (node.category.Description) {\n <div class=\"node-description\">\n {{node.category.Description | slice:0:50}}{{node.category.Description.length > 50 ? '...' : ''}}\n </div>\n }\n </div>\n <div class=\"node-badges\">\n @if (node.typeCount > 0) {\n <span class=\"badge types\">\n <i class=\"fa-solid fa-shapes\"></i>\n {{node.typeCount}}\n </span>\n }\n @if (node.children.length > 0) {\n <span class=\"badge children\">\n <i class=\"fa-solid fa-folder\"></i>\n {{node.children.length}}\n </span>\n }\n </div>\n <div class=\"node-actions\">\n @if (UserCanUpdate) {\n <button mjButton variant=\"flat\" size=\"sm\"\n (click)=\"editCategory(node, $event)\"\n title=\"Edit\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n @if (UserCanDelete && node.children.length === 0 && node.typeCount === 0) {\n <button mjButton variant=\"danger\" size=\"sm\"\n (click)=\"deleteCategory(node, $event)\"\n title=\"Delete\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (categoryTree.length === 0) {\n <mj-empty-state\n [Variant]=\"searchText ? 'no-results' : 'empty'\"\n Icon=\"fa-solid fa-folder-open\"\n Title=\"No Categories\"\n [Message]=\"searchText ? 'No categories match your search.' : 'Get started by creating your first category.'\"\n [ActionText]=\"searchText ? 'Clear search' : (UserCanCreate ? 'Create Category' : '')\"\n [ActionIcon]=\"searchText ? 'fa-solid fa-rotate-left' : 'fa-solid fa-plus'\"\n (Action)=\"onEmptyStateAction()\" />\n }\n </div>\n <!-- Detail Panel -->\n @if (selectedNode) {\n <div class=\"detail-panel\">\n <div class=\"detail-header\">\n <div class=\"detail-icon\" [style.backgroundColor]=\"getCategoryColor(0) + '15'\" [style.color]=\"getCategoryColor(0)\">\n <i [class]=\"selectedNode.category.IconClass || 'fa-solid fa-folder'\"></i>\n </div>\n <div class=\"detail-title\">\n <h2>{{selectedNode.category.Name}}</h2>\n @if (selectedNode.level > 0) {\n <span class=\"level-badge\">\n Level {{selectedNode.level + 1}}\n </span>\n }\n </div>\n <div class=\"detail-actions\">\n @if (UserCanUpdate) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"editCategory(selectedNode)\" title=\"Edit\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n <button class=\"close-btn\" (click)=\"selectedNode = null\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"detail-body\">\n <!-- Stats -->\n <div class=\"detail-stats\">\n <div class=\"detail-stat\">\n <div class=\"stat-value\">{{selectedNode.typeCount}}</div>\n <div class=\"stat-label\">Credential Types</div>\n </div>\n <div class=\"detail-stat\">\n <div class=\"stat-value\">{{selectedNode.children.length}}</div>\n <div class=\"stat-label\">Subcategories</div>\n </div>\n </div>\n <!-- Description -->\n @if (selectedNode.category.Description) {\n <div class=\"description-section\">\n <h3>\n <i class=\"fa-solid fa-align-left\"></i>\n Description\n </h3>\n <p class=\"description\">{{selectedNode.category.Description}}</p>\n </div>\n }\n <!-- Types in Category -->\n @if (selectedNode.typeCount > 0) {\n <div class=\"types-section\">\n <h3>\n <i class=\"fa-solid fa-shapes\"></i>\n Credential Types\n </h3>\n <div class=\"type-list\">\n @for (type of getTypesForCategory(selectedNode.category.Name); track type) {\n <div class=\"type-item\">\n <div class=\"type-icon\">\n <i [class]=\"type.IconClass || 'fa-solid fa-key'\"></i>\n </div>\n <div class=\"type-info\">\n <div class=\"type-name\">{{type.Name}}</div>\n @if (type.Description) {\n <div class=\"type-desc\">{{type.Description | slice:0:60}}</div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Subcategories -->\n @if (selectedNode.children.length > 0) {\n <div class=\"subcategories-section\">\n <h3>\n <i class=\"fa-solid fa-folder-tree\"></i>\n Subcategories\n </h3>\n <div class=\"subcategory-list\">\n @for (child of selectedNode.children; track child) {\n <div class=\"subcategory-item\" (click)=\"selectNode(child)\">\n <i [class]=\"child.category.IconClass || 'fa-solid fa-folder'\"></i>\n <span>{{child.category.Name}}</span>\n @if (child.typeCount > 0) {\n <span class=\"sub-type-count\">{{child.typeCount}} types</span>\n }\n </div>\n }\n </div>\n </div>\n }\n <!-- Quick Actions -->\n <div class=\"detail-quick-actions\">\n @if (selectedNode.typeCount > 0) {\n <button\n class=\"btn-secondary\"\n (click)=\"viewTypesForCategory(selectedNode.category.Name)\"\n >\n <i class=\"fa-solid fa-shapes\"></i>\n View Types\n </button>\n }\n <button\n class=\"btn-primary\"\n (click)=\"createCredentialWithCategory(selectedNode.category.ID)\"\n >\n <i class=\"fa-solid fa-plus\"></i>\n Create Credential\n </button>\n </div>\n </div>\n </div>\n }\n <!-- No Selection -->\n @if (!selectedNode && categoryTree.length > 0) {\n <mj-empty-state Icon=\"fa-solid fa-hand-pointer\"\n Title=\"Select a Category\"\n Message=\"Click on a category to view its details and credential types\" />\n }\n </div>\n }\n </mj-page-body>\n\n <!-- Category Edit Panel -->\n <mj-credential-category-edit-panel\n #categoryEditPanel\n (saved)=\"onCategorySaved($any($event))\"\n (deleted)=\"onCategoryDeleted($any($event))\"\n ></mj-credential-category-edit-panel>\n</mj-page-layout>\n"]}
|
|
1
|
+
{"version":3,"file":"credentials-categories-resource.component.js","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-categories-resource.component.ts","../../../src/Credentials/components/credentials-categories-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy, ViewChild } from '@angular/core';\nimport { ResourceData, MJCredentialCategoryEntity, MJCredentialTypeEntity } from '@memberjunction/core-entities';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { RunView, Metadata } from '@memberjunction/core';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { MJConfirmService } from '@memberjunction/ng-ui-components';\nimport { CredentialCategoryEditPanelComponent } from '@memberjunction/ng-credentials';\ninterface CategoryNode {\n category: MJCredentialCategoryEntity;\n children: CategoryNode[];\n expanded: boolean;\n level: number;\n typeCount: number;\n}\n\n@RegisterClass(BaseResourceComponent, 'CredentialsCategoriesResource')\n@Component({\n standalone: false,\n selector: 'mj-credentials-categories-resource',\n templateUrl: './credentials-categories-resource.component.html',\n styleUrls: ['./credentials-categories-resource.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class CredentialsCategoriesResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public isLoading = true;\n public categories: MJCredentialCategoryEntity[] = [];\n public categoryTree: CategoryNode[] = [];\n public types: MJCredentialTypeEntity[] = [];\n public selectedNode: CategoryNode | null = null;\n public searchText = '';\n\n // Permissions\n private _metadata = this.ProviderToUse;\n private _permissionCache = new Map<string, boolean>();\n\n @ViewChild('categoryEditPanel') categoryEditPanel!: CredentialCategoryEditPanelComponent;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private confirm: MJConfirmService) {\n super();\n }\n\n ngOnInit(): void {\n super.ngOnInit();\n this.loadData();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n // Cleanup if needed\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Categories';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-folder-tree';\n }\n\n // === Permission Checks ===\n\n public get UserCanCreate(): boolean {\n return this.checkEntityPermission('MJ: Credential Categories', 'Create');\n }\n\n public get UserCanUpdate(): boolean {\n return this.checkEntityPermission('MJ: Credential Categories', 'Update');\n }\n\n public get UserCanDelete(): boolean {\n return this.checkEntityPermission('MJ: Credential Categories', 'Delete');\n }\n\n private checkEntityPermission(entityName: string, permissionType: 'Create' | 'Read' | 'Update' | 'Delete'): boolean {\n const cacheKey = `${entityName}_${permissionType}`;\n\n if (this._permissionCache.has(cacheKey)) {\n return this._permissionCache.get(cacheKey)!;\n }\n\n try {\n const entityInfo = this._metadata.Entities.find(e => e.Name === entityName);\n if (!entityInfo) {\n this._permissionCache.set(cacheKey, false);\n return false;\n }\n\n const userPermissions = entityInfo.GetUserPermisions(this._metadata.CurrentUser);\n let hasPermission = false;\n\n switch (permissionType) {\n case 'Create': hasPermission = userPermissions.CanCreate; break;\n case 'Read': hasPermission = userPermissions.CanRead; break;\n case 'Update': hasPermission = userPermissions.CanUpdate; break;\n case 'Delete': hasPermission = userPermissions.CanDelete; break;\n }\n\n this._permissionCache.set(cacheKey, hasPermission);\n return hasPermission;\n } catch (error) {\n this._permissionCache.set(cacheKey, false);\n return false;\n }\n }\n\n private async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.markForCheck();\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const [catResult, typeResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Credential Categories',\n OrderBy: 'Name',\n ResultType: 'entity_object'\n },\n {\n EntityName: 'MJ: Credential Types',\n ResultType: 'entity_object'\n }\n ]);\n\n if (catResult.Success) {\n this.categories = catResult.Results as MJCredentialCategoryEntity[];\n }\n\n if (typeResult.Success) {\n this.types = typeResult.Results as MJCredentialTypeEntity[];\n }\n\n this.buildTree();\n\n } catch (error) {\n console.error('Error loading credential categories:', error);\n MJNotificationService.Instance.CreateSimpleNotification('Error loading categories', 'error', 3000);\n } finally {\n this.isLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n private buildTree(): void {\n const categoryMap = new Map<string, CategoryNode>();\n\n // Create nodes for all categories with stats\n for (const category of this.categories) {\n const typesInCategory = this.types.filter(t => t.Category === category.Name);\n categoryMap.set(category.ID, {\n category,\n children: [],\n expanded: true,\n level: 0,\n typeCount: typesInCategory.length\n });\n }\n\n // Build tree structure\n const roots: CategoryNode[] = [];\n for (const category of this.categories) {\n const node = categoryMap.get(category.ID)!;\n if (category.ParentID) {\n const parent = categoryMap.get(category.ParentID);\n if (parent) {\n node.level = parent.level + 1;\n parent.children.push(node);\n } else {\n roots.push(node);\n }\n } else {\n roots.push(node);\n }\n }\n\n // Sort children recursively\n const sortNodes = (nodes: CategoryNode[]): void => {\n nodes.sort((a, b) => a.category.Name.localeCompare(b.category.Name));\n for (const node of nodes) {\n sortNodes(node.children);\n }\n };\n sortNodes(roots);\n\n this.categoryTree = roots;\n }\n\n // === CRUD Operations ===\n\n public createNewCategory(): void {\n if (this.categoryEditPanel) {\n this.categoryEditPanel.open(null);\n }\n }\n\n public createChildCategory(parentNode: CategoryNode, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n if (this.categoryEditPanel) {\n this.categoryEditPanel.open(null, parentNode.category.ID);\n }\n }\n\n public editCategory(node: CategoryNode, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n if (this.categoryEditPanel) {\n this.categoryEditPanel.open(node.category);\n }\n }\n\n public async deleteCategory(node: CategoryNode, event?: Event): Promise<void> {\n if (event) {\n event.stopPropagation();\n }\n\n if (!this.UserCanDelete) {\n MJNotificationService.Instance.CreateSimpleNotification('You do not have permission to delete categories', 'warning', 3000);\n return;\n }\n\n if (node.children.length > 0) {\n MJNotificationService.Instance.CreateSimpleNotification(\n `Cannot delete \"${node.category.Name}\" - it has ${node.children.length} subcategories`,\n 'warning',\n 4000\n );\n return;\n }\n\n if (node.typeCount > 0) {\n MJNotificationService.Instance.CreateSimpleNotification(\n `Cannot delete \"${node.category.Name}\" - it has ${node.typeCount} credential type(s) using it`,\n 'warning',\n 4000\n );\n return;\n }\n\n const confirmed = await this.confirm.ConfirmDelete({\n title: 'Delete category',\n message: `Delete \"${node.category.Name}\"?`,\n detail: 'This action cannot be undone.',\n });\n if (!confirmed) return;\n\n try {\n const success = await node.category.Delete();\n if (success) {\n MJNotificationService.Instance.CreateSimpleNotification(`Category \"${node.category.Name}\" deleted successfully`, 'success', 3000);\n this.categories = this.categories.filter(c => !UUIDsEqual(c.ID, node.category.ID));\n if (UUIDsEqual(this.selectedNode?.category.ID, node.category.ID)) {\n this.selectedNode = null;\n }\n this.buildTree();\n this.cdr.markForCheck();\n } else {\n MJNotificationService.Instance.CreateSimpleNotification('Failed to delete category', 'error', 3000);\n }\n } catch (error) {\n console.error('Error deleting category:', error);\n MJNotificationService.Instance.CreateSimpleNotification('Error deleting category', 'error', 3000);\n }\n }\n\n // === Panel Event Handlers ===\n\n public onCategorySaved(category: MJCredentialCategoryEntity): void {\n const existingIndex = this.categories.findIndex(c => UUIDsEqual(c.ID, category.ID));\n\n if (existingIndex >= 0) {\n this.categories[existingIndex] = category;\n } else {\n this.categories.push(category);\n }\n\n this.buildTree();\n this.cdr.markForCheck();\n }\n\n public onCategoryDeleted(categoryId: string): void {\n this.categories = this.categories.filter(c => !UUIDsEqual(c.ID, categoryId));\n if (UUIDsEqual(this.selectedNode?.category.ID, categoryId)) {\n this.selectedNode = null;\n }\n this.buildTree();\n this.cdr.markForCheck();\n }\n\n // === Selection ===\n\n public selectNode(node: CategoryNode): void {\n this.selectedNode = UUIDsEqual(this.selectedNode?.category.ID, node.category.ID) ? null : node;\n this.cdr.markForCheck();\n }\n\n public toggleExpand(node: CategoryNode, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n node.expanded = !node.expanded;\n this.cdr.markForCheck();\n }\n\n // === Search ===\n\n public onSearchChange(value: string): void {\n this.searchText = value;\n if (value) {\n this.expandAll();\n }\n this.cdr.markForCheck();\n }\n\n public clearSearch(): void {\n this.searchText = '';\n this.cdr.markForCheck();\n }\n\n /** Empty-state CTA: clear search when narrowing, otherwise create. */\n public onEmptyStateAction(): void {\n if (this.searchText) {\n this.clearSearch();\n } else {\n this.createNewCategory();\n }\n }\n\n public expandAll(): void {\n const expand = (nodes: CategoryNode[]): void => {\n for (const node of nodes) {\n node.expanded = true;\n expand(node.children);\n }\n };\n expand(this.categoryTree);\n this.cdr.markForCheck();\n }\n\n public collapseAll(): void {\n const collapse = (nodes: CategoryNode[]): void => {\n for (const node of nodes) {\n node.expanded = false;\n collapse(node.children);\n }\n };\n collapse(this.categoryTree);\n this.cdr.markForCheck();\n }\n\n public getFlattenedNodes(): CategoryNode[] {\n const result: CategoryNode[] = [];\n const searchLower = this.searchText.toLowerCase().trim();\n\n const flatten = (nodes: CategoryNode[]): void => {\n for (const node of nodes) {\n if (searchLower) {\n const matches = this.nodeMatchesSearch(node, searchLower);\n if (matches) {\n result.push(node);\n }\n } else {\n result.push(node);\n }\n\n if (node.expanded && node.children.length > 0) {\n flatten(node.children);\n }\n }\n };\n\n flatten(this.categoryTree);\n return result;\n }\n\n private nodeMatchesSearch(node: CategoryNode, searchLower: string): boolean {\n const nameMatch = node.category.Name.toLowerCase().includes(searchLower);\n const descMatch = node.category.Description?.toLowerCase().includes(searchLower);\n return nameMatch || descMatch || false;\n }\n\n public getTotalTypeCount(): number {\n return this.types.length;\n }\n\n public getTypesForCategory(categoryName: string): MJCredentialTypeEntity[] {\n return this.types.filter(t => t.Category === categoryName);\n }\n\n public createCredentialWithCategory(categoryId: string, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n // Navigate to Credentials nav item with the category pre-selected and create panel open\n this.navigationService.OpenNavItemByName('Credentials', {\n categoryId: categoryId,\n openCreatePanel: true\n });\n }\n\n public viewTypesForCategory(categoryName: string, event?: Event): void {\n if (event) {\n event.stopPropagation();\n }\n // Navigate to Types nav item filtered by this category\n this.navigationService.OpenNavItemByName('Types', {\n categoryFilter: categoryName\n });\n }\n\n /** Case-insensitive UUID check whether a tree node is the currently selected node. */\n public IsNodeSelected(node: CategoryNode): boolean {\n return UUIDsEqual(this.selectedNode?.category?.ID, node.category.ID);\n }\n\n public getCategoryColor(index: number): string {\n const colors = [\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-primary)',\n 'var(--mj-status-warning)',\n 'var(--mj-status-success)',\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-primary)'\n ];\n return colors[index % colors.length];\n }\n\n public refresh(): void {\n this.selectedNode = null;\n this.loadData();\n }\n}\n","<mj-page-layout>\n <mj-page-header\n Title=\"Categories\"\n Icon=\"fa-solid fa-folder-tree\">\n <!-- [meta] intentionally omitted — chrome slot discipline audit Task B.\n The categories count mirrored the visible tree; the cross-entity\n types count belongs on the Types page, not here. -->\n\n <div actions>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"expandAll()\" title=\"Expand all\">\n <i class=\"fa-solid fa-expand\"></i> <span class=\"action-btn-label\">Expand</span>\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"collapseAll()\" title=\"Collapse all\">\n <i class=\"fa-solid fa-compress\"></i> <span class=\"action-btn-label\">Collapse</span>\n </button>\n <mj-refresh-button [Loading]=\"isLoading\" (Clicked)=\"refresh()\"></mj-refresh-button>\n @if (UserCanCreate) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"createNewCategory()\">\n <i class=\"fa-solid fa-plus\"></i> <span class=\"action-btn-label\">New Category</span>\n </button>\n }\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search categories...\"\n [Value]=\"searchText\"\n (ValueChange)=\"onSearchChange($event)\">\n </mj-page-search>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n @if (isLoading) {\n <mj-loading text=\"Loading categories...\"></mj-loading>\n }\n\n @if (!isLoading) {\n <div class=\"categories-layout\">\n <!-- Tree Container -->\n <div class=\"tree-panel\">\n @if (categoryTree.length > 0) {\n <div class=\"tree-container\">\n @for (node of getFlattenedNodes(); track node; let i = $index) {\n <div\n class=\"tree-node\"\n [class.selected]=\"IsNodeSelected(node)\"\n [style.padding-left.px]=\"12 + (node.level * 20)\"\n (click)=\"selectNode(node)\"\n >\n <div class=\"node-content\">\n @if (node.children.length > 0) {\n <button\n class=\"expand-btn\"\n (click)=\"toggleExpand(node, $event)\"\n >\n <i [class]=\"node.expanded ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-right'\"></i>\n </button>\n }\n @if (node.children.length === 0) {\n <span class=\"expand-placeholder\"></span>\n }\n <div class=\"node-icon\" [style.backgroundColor]=\"getCategoryColor(i) + '15'\" [style.color]=\"getCategoryColor(i)\">\n <i [class]=\"node.category.IconClass || 'fa-solid fa-folder'\"></i>\n </div>\n <div class=\"node-info\">\n <div class=\"node-name\">{{node.category.Name}}</div>\n @if (node.category.Description) {\n <div class=\"node-description\">\n {{node.category.Description | slice:0:50}}{{node.category.Description.length > 50 ? '...' : ''}}\n </div>\n }\n </div>\n <div class=\"node-badges\">\n @if (node.typeCount > 0) {\n <span class=\"badge types\">\n <i class=\"fa-solid fa-shapes\"></i>\n {{node.typeCount}}\n </span>\n }\n @if (node.children.length > 0) {\n <span class=\"badge children\">\n <i class=\"fa-solid fa-folder\"></i>\n {{node.children.length}}\n </span>\n }\n </div>\n <div class=\"node-actions\">\n @if (UserCanUpdate) {\n <button mjButton variant=\"flat\" size=\"sm\"\n (click)=\"editCategory(node, $event)\"\n title=\"Edit\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n @if (UserCanDelete && node.children.length === 0 && node.typeCount === 0) {\n <button mjButton variant=\"danger\" size=\"sm\"\n (click)=\"deleteCategory(node, $event)\"\n title=\"Delete\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (categoryTree.length === 0) {\n <mj-empty-state\n [Variant]=\"searchText ? 'no-results' : 'empty'\"\n Icon=\"fa-solid fa-folder-open\"\n Title=\"No Categories\"\n [Message]=\"searchText ? 'No categories match your search.' : 'Get started by creating your first category.'\"\n [ActionText]=\"searchText ? 'Clear search' : (UserCanCreate ? 'Create Category' : '')\"\n [ActionIcon]=\"searchText ? 'fa-solid fa-rotate-left' : 'fa-solid fa-plus'\"\n (Action)=\"onEmptyStateAction()\" />\n }\n </div>\n <!-- Detail Panel -->\n @if (selectedNode) {\n <div class=\"detail-panel\">\n <div class=\"detail-header\">\n <div class=\"detail-icon\" [style.backgroundColor]=\"getCategoryColor(0) + '15'\" [style.color]=\"getCategoryColor(0)\">\n <i [class]=\"selectedNode.category.IconClass || 'fa-solid fa-folder'\"></i>\n </div>\n <div class=\"detail-title\">\n <h2>{{selectedNode.category.Name}}</h2>\n @if (selectedNode.level > 0) {\n <span class=\"level-badge\">\n Level {{selectedNode.level + 1}}\n </span>\n }\n </div>\n <div class=\"detail-actions\">\n @if (UserCanUpdate) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"editCategory(selectedNode)\" title=\"Edit\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n }\n <button class=\"close-btn\" (click)=\"selectedNode = null\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"detail-body\">\n <!-- Stats -->\n <div class=\"detail-stats\">\n <div class=\"detail-stat\">\n <div class=\"stat-value\">{{selectedNode.typeCount}}</div>\n <div class=\"stat-label\">Credential Types</div>\n </div>\n <div class=\"detail-stat\">\n <div class=\"stat-value\">{{selectedNode.children.length}}</div>\n <div class=\"stat-label\">Subcategories</div>\n </div>\n </div>\n <!-- Description -->\n @if (selectedNode.category.Description) {\n <div class=\"description-section\">\n <h3>\n <i class=\"fa-solid fa-align-left\"></i>\n Description\n </h3>\n <p class=\"description\">{{selectedNode.category.Description}}</p>\n </div>\n }\n <!-- Types in Category -->\n @if (selectedNode.typeCount > 0) {\n <div class=\"types-section\">\n <h3>\n <i class=\"fa-solid fa-shapes\"></i>\n Credential Types\n </h3>\n <div class=\"type-list\">\n @for (type of getTypesForCategory(selectedNode.category.Name); track type) {\n <div class=\"type-item\">\n <div class=\"type-icon\">\n <i [class]=\"type.IconClass || 'fa-solid fa-key'\"></i>\n </div>\n <div class=\"type-info\">\n <div class=\"type-name\">{{type.Name}}</div>\n @if (type.Description) {\n <div class=\"type-desc\">{{type.Description | slice:0:60}}</div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Subcategories -->\n @if (selectedNode.children.length > 0) {\n <div class=\"subcategories-section\">\n <h3>\n <i class=\"fa-solid fa-folder-tree\"></i>\n Subcategories\n </h3>\n <div class=\"subcategory-list\">\n @for (child of selectedNode.children; track child) {\n <div class=\"subcategory-item\" (click)=\"selectNode(child)\">\n <i [class]=\"child.category.IconClass || 'fa-solid fa-folder'\"></i>\n <span>{{child.category.Name}}</span>\n @if (child.typeCount > 0) {\n <span class=\"sub-type-count\">{{child.typeCount}} types</span>\n }\n </div>\n }\n </div>\n </div>\n }\n <!-- Quick Actions -->\n <div class=\"detail-quick-actions\">\n @if (selectedNode.typeCount > 0) {\n <button\n class=\"btn-secondary\"\n (click)=\"viewTypesForCategory(selectedNode.category.Name)\"\n >\n <i class=\"fa-solid fa-shapes\"></i>\n View Types\n </button>\n }\n <button\n class=\"btn-primary\"\n (click)=\"createCredentialWithCategory(selectedNode.category.ID)\"\n >\n <i class=\"fa-solid fa-plus\"></i>\n Create Credential\n </button>\n </div>\n </div>\n </div>\n }\n <!-- No Selection -->\n @if (!selectedNode && categoryTree.length > 0) {\n <mj-empty-state Icon=\"fa-solid fa-hand-pointer\"\n Title=\"Select a Category\"\n Message=\"Click on a category to view its details and credential types\" />\n }\n </div>\n }\n </mj-page-body>\n\n <!-- Category Edit Panel -->\n <mj-credential-category-edit-panel\n #categoryEditPanel\n (saved)=\"onCategorySaved($any($event))\"\n (deleted)=\"onCategoryDeleted($any($event))\"\n ></mj-credential-category-edit-panel>\n</mj-page-layout>\n"]}
|
|
@@ -3,12 +3,13 @@ import { Subject } from 'rxjs';
|
|
|
3
3
|
import { ResourceData, MJCredentialEntity, MJCredentialTypeEntity } from '@memberjunction/core-entities';
|
|
4
4
|
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
5
5
|
import { CredentialEditPanelComponent } from '@memberjunction/ng-credentials';
|
|
6
|
-
import { FilterFieldConfig, ViewToggleOption } from '@memberjunction/ng-ui-components';
|
|
6
|
+
import { FilterFieldConfig, ViewToggleOption, MJConfirmService } from '@memberjunction/ng-ui-components';
|
|
7
7
|
import * as i0 from "@angular/core";
|
|
8
8
|
type ViewMode = 'grid' | 'list';
|
|
9
9
|
type StatusFilter = '' | 'active' | 'inactive' | 'expired' | 'expiring';
|
|
10
10
|
export declare class CredentialsListResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {
|
|
11
11
|
private cdr;
|
|
12
|
+
private confirm;
|
|
12
13
|
isLoading: boolean;
|
|
13
14
|
credentials: MJCredentialEntity[];
|
|
14
15
|
filteredCredentials: MJCredentialEntity[];
|
|
@@ -30,7 +31,7 @@ export declare class CredentialsListResourceComponent extends BaseResourceCompon
|
|
|
30
31
|
get ActiveFilterCount(): number;
|
|
31
32
|
onFilterValuesChange(v: Record<string, unknown>): void;
|
|
32
33
|
resetFilters(): void;
|
|
33
|
-
constructor(cdr: ChangeDetectorRef);
|
|
34
|
+
constructor(cdr: ChangeDetectorRef, confirm: MJConfirmService);
|
|
34
35
|
ngOnInit(): void;
|
|
35
36
|
ngOnDestroy(): void;
|
|
36
37
|
GetResourceDisplayName(data: ResourceData): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials-list-resource.component.d.ts","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-list-resource.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAsC,MAAM,eAAe,CAAC;AACpH,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAEzG,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;;
|
|
1
|
+
{"version":3,"file":"credentials-list-resource.component.d.ts","sourceRoot":"","sources":["../../../src/Credentials/components/credentials-list-resource.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,8 +11,8 @@ import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
|
11
11
|
import { RunView } from '@memberjunction/core';
|
|
12
12
|
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
13
13
|
import * as i0 from "@angular/core";
|
|
14
|
-
import * as i1 from "@
|
|
15
|
-
import * as i2 from "@
|
|
14
|
+
import * as i1 from "@memberjunction/ng-ui-components";
|
|
15
|
+
import * as i2 from "@angular/common";
|
|
16
16
|
import * as i3 from "@memberjunction/ng-shared-generic";
|
|
17
17
|
import * as i4 from "@memberjunction/ng-credentials";
|
|
18
18
|
const _c0 = ["editPanel"];
|
|
@@ -469,6 +469,7 @@ function CredentialsListResourceComponent_Conditional_16_Template(rf, ctx) { if
|
|
|
469
469
|
} }
|
|
470
470
|
let CredentialsListResourceComponent = class CredentialsListResourceComponent extends BaseResourceComponent {
|
|
471
471
|
cdr;
|
|
472
|
+
confirm;
|
|
472
473
|
isLoading = true;
|
|
473
474
|
credentials = [];
|
|
474
475
|
filteredCredentials = [];
|
|
@@ -548,9 +549,10 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
548
549
|
if (this.selectedStatusFilter)
|
|
549
550
|
this.onStatusFilterChange('');
|
|
550
551
|
}
|
|
551
|
-
constructor(cdr) {
|
|
552
|
+
constructor(cdr, confirm) {
|
|
552
553
|
super();
|
|
553
554
|
this.cdr = cdr;
|
|
555
|
+
this.confirm = confirm;
|
|
554
556
|
}
|
|
555
557
|
ngOnInit() {
|
|
556
558
|
super.ngOnInit();
|
|
@@ -722,7 +724,11 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
722
724
|
MJNotificationService.Instance.CreateSimpleNotification('You do not have permission to delete credentials', 'warning', 3000);
|
|
723
725
|
return;
|
|
724
726
|
}
|
|
725
|
-
const confirmed = confirm(
|
|
727
|
+
const confirmed = await this.confirm.ConfirmDelete({
|
|
728
|
+
title: 'Delete credential',
|
|
729
|
+
message: `Delete "${credential.Name}"?`,
|
|
730
|
+
detail: 'This action cannot be undone.',
|
|
731
|
+
});
|
|
726
732
|
if (!confirmed)
|
|
727
733
|
return;
|
|
728
734
|
try {
|
|
@@ -814,7 +820,11 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
814
820
|
if (!this.UserCanDelete || this.selectedCredentials.size === 0)
|
|
815
821
|
return;
|
|
816
822
|
const count = this.selectedCredentials.size;
|
|
817
|
-
const confirmed = confirm(
|
|
823
|
+
const confirmed = await this.confirm.ConfirmDelete({
|
|
824
|
+
title: 'Delete credentials',
|
|
825
|
+
message: `Delete ${count} credential(s)?`,
|
|
826
|
+
detail: 'This action cannot be undone.',
|
|
827
|
+
});
|
|
818
828
|
if (!confirmed)
|
|
819
829
|
return;
|
|
820
830
|
const toDelete = Array.from(this.selectedCredentials)
|
|
@@ -1114,7 +1124,11 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
1114
1124
|
if (!this.UserCanDelete || this.selectedCredentials.size === 0)
|
|
1115
1125
|
return;
|
|
1116
1126
|
const count = this.selectedCredentials.size;
|
|
1117
|
-
const confirmed = confirm(
|
|
1127
|
+
const confirmed = await this.confirm.ConfirmDelete({
|
|
1128
|
+
title: 'Delete credentials',
|
|
1129
|
+
message: `Delete ${count} credential(s)?`,
|
|
1130
|
+
detail: 'This action cannot be undone.',
|
|
1131
|
+
});
|
|
1118
1132
|
if (!confirmed)
|
|
1119
1133
|
return;
|
|
1120
1134
|
const toDelete = Array.from(this.selectedCredentials)
|
|
@@ -1138,7 +1152,7 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
1138
1152
|
MJNotificationService.Instance.CreateSimpleNotification('Failed to delete credentials — all changes have been rolled back', 'error', 3000);
|
|
1139
1153
|
}
|
|
1140
1154
|
}
|
|
1141
|
-
static ɵfac = function CredentialsListResourceComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CredentialsListResourceComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
1155
|
+
static ɵfac = function CredentialsListResourceComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CredentialsListResourceComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.MJConfirmService)); };
|
|
1142
1156
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CredentialsListResourceComponent, selectors: [["mj-credentials-list-resource"]], viewQuery: function CredentialsListResourceComponent_Query(rf, ctx) { if (rf & 1) {
|
|
1143
1157
|
i0.ɵɵviewQuery(_c0, 5);
|
|
1144
1158
|
} if (rf & 2) {
|
|
@@ -1198,7 +1212,7 @@ let CredentialsListResourceComponent = class CredentialsListResourceComponent ex
|
|
|
1198
1212
|
i0.ɵɵconditional(!ctx.isLoading ? 16 : -1);
|
|
1199
1213
|
i0.ɵɵadvance();
|
|
1200
1214
|
i0.ɵɵproperty("credentialTypes", ctx.types);
|
|
1201
|
-
} }, dependencies: [i1.NgClass, i2.MJButtonDirective, i2.MJPageHeaderComponent, i2.MJPageLayoutComponent, i2.MJPageBodyComponent, i2.MJPageSearchComponent, i2.MJFilterPopoverComponent, i2.MJFilterPanelComponent, i2.MJViewToggleComponent, i2.MJStatBadgeComponent, i2.MJRefreshButtonComponent, i2.MJEmptyStateComponent, i3.LoadingComponent, i4.CredentialEditPanelComponent], styles: ["\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@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\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}"], changeDetection: 0 });
|
|
1215
|
+
} }, dependencies: [i2.NgClass, i1.MJButtonDirective, i1.MJPageHeaderComponent, i1.MJPageLayoutComponent, i1.MJPageBodyComponent, i1.MJPageSearchComponent, i1.MJFilterPopoverComponent, i1.MJFilterPanelComponent, i1.MJViewToggleComponent, i1.MJStatBadgeComponent, i1.MJRefreshButtonComponent, i1.MJEmptyStateComponent, i3.LoadingComponent, i4.CredentialEditPanelComponent], styles: ["\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@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\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}"], changeDetection: 0 });
|
|
1202
1216
|
};
|
|
1203
1217
|
CredentialsListResourceComponent = __decorate([
|
|
1204
1218
|
RegisterClass(BaseResourceComponent, 'CredentialsListResource')
|
|
@@ -1207,7 +1221,7 @@ export { CredentialsListResourceComponent };
|
|
|
1207
1221
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CredentialsListResourceComponent, [{
|
|
1208
1222
|
type: Component,
|
|
1209
1223
|
args: [{ standalone: false, selector: 'mj-credentials-list-resource', changeDetection: ChangeDetectionStrategy.OnPush, template: "<mj-page-layout>\n <mj-page-header\n Title=\"Credentials\"\n Icon=\"fa-solid fa-key\">\n <div meta>\n <mj-stat-badge\n [Count]=\"filteredCredentials.length\"\n [Total]=\"credentials.length\"\n Label=\"credentials\">\n </mj-stat-badge>\n @if (getExpiringSoonCount() > 0) {\n <mj-stat-badge\n Icon=\"fa-solid fa-clock\"\n [Count]=\"getExpiringSoonCount()\"\n Label=\"expiring\"\n Variant=\"warning\">\n </mj-stat-badge>\n }\n @if (getExpiredCount() > 0) {\n <mj-stat-badge\n Icon=\"fa-solid fa-exclamation-circle\"\n [Count]=\"getExpiredCount()\"\n Label=\"expired\"\n Variant=\"error\">\n </mj-stat-badge>\n }\n </div>\n <div actions>\n <mj-refresh-button [Loading]=\"isLoading\" (Clicked)=\"refresh()\"></mj-refresh-button>\n @if (UserCanCreate) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"createNewCredential()\">\n <i class=\"fa-solid fa-plus\"></i> <span class=\"action-btn-label\">New Credential</span>\n </button>\n }\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search credentials...\"\n [Value]=\"searchText\"\n (ValueChange)=\"onSearchChange($event)\">\n </mj-page-search>\n <mj-filter-popover\n [ActiveCount]=\"ActiveFilterCount\"\n [ShowClearAll]=\"ActiveFilterCount > 0\"\n (ClearAllRequested)=\"resetFilters()\">\n <mj-filter-panel\n [Fields]=\"FilterFields\"\n [Values]=\"FilterValues\"\n (ValuesChange)=\"onFilterValuesChange($event)\"\n (Reset)=\"resetFilters()\">\n </mj-filter-panel>\n </mj-filter-popover>\n <mj-view-toggle\n [Options]=\"viewOptions\"\n [ActiveKey]=\"viewMode\"\n (KeyChange)=\"setViewMode($any($event))\">\n </mj-view-toggle>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n @if (isLoading) {\n <mj-loading text=\"Loading credentials...\"></mj-loading>\n }\n\n @if (!isLoading) {\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 <mj-empty-state\n [Variant]=\"IsListNarrowed ? 'no-results' : 'empty'\"\n Icon=\"fa-solid fa-key\"\n Title=\"No Credentials Found\"\n [Message]=\"IsListNarrowed ? 'No credentials match your current filters.' : 'Get started by creating your first credential.'\"\n [ActionText]=\"IsListNarrowed ? 'Reset filters' : (UserCanCreate ? 'Create Credential' : '')\"\n [ActionIcon]=\"IsListNarrowed ? 'fa-solid fa-rotate-left' : 'fa-solid fa-plus'\"\n (Action)=\"onEmptyStateAction()\" />\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 </mj-page-body>\n</mj-page-layout>\n", styles: ["/* 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/* 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\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"] }]
|
|
1210
|
-
}], () => [{ type: i0.ChangeDetectorRef }], { editPanel: [{
|
|
1224
|
+
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.MJConfirmService }], { editPanel: [{
|
|
1211
1225
|
type: ViewChild,
|
|
1212
1226
|
args: ['editPanel']
|
|
1213
1227
|
}] }); })();
|