@memberjunction/ng-dashboards 5.11.0 → 5.13.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.
Files changed (229) hide show
  1. package/dist/AI/components/agents/agent-configuration.component.d.ts +34 -2
  2. package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
  3. package/dist/AI/components/agents/agent-configuration.component.js +586 -223
  4. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  5. package/dist/AI/components/agents/agent-editor.component.js +2 -2
  6. package/dist/AI/components/agents/agent-filter-panel.component.d.ts +8 -0
  7. package/dist/AI/components/agents/agent-filter-panel.component.d.ts.map +1 -1
  8. package/dist/AI/components/agents/agent-filter-panel.component.js +85 -52
  9. package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
  10. package/dist/AI/components/charts/performance-heatmap.component.d.ts +1 -0
  11. package/dist/AI/components/charts/performance-heatmap.component.d.ts.map +1 -1
  12. package/dist/AI/components/charts/performance-heatmap.component.js +27 -5
  13. package/dist/AI/components/charts/performance-heatmap.component.js.map +1 -1
  14. package/dist/AI/components/charts/time-series-chart.component.d.ts +5 -0
  15. package/dist/AI/components/charts/time-series-chart.component.d.ts.map +1 -1
  16. package/dist/AI/components/charts/time-series-chart.component.js +23 -8
  17. package/dist/AI/components/charts/time-series-chart.component.js.map +1 -1
  18. package/dist/AI/components/execution-monitoring.component.js +2 -2
  19. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  20. package/dist/AI/components/models/model-management.component.js +2 -2
  21. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +2 -2
  22. package/dist/AI/components/prompts/prompt-filter-panel.component.js +2 -2
  23. package/dist/AI/components/prompts/prompt-management.component.js +3 -3
  24. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  25. package/dist/AI/components/prompts/prompt-version-control.component.js +2 -2
  26. package/dist/AI/components/requests/agent-requests-resource.component.d.ts +83 -0
  27. package/dist/AI/components/requests/agent-requests-resource.component.d.ts.map +1 -0
  28. package/dist/AI/components/requests/agent-requests-resource.component.js +547 -0
  29. package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -0
  30. package/dist/AI/components/system/system-config-filter-panel.component.js +2 -2
  31. package/dist/AI/components/system/system-configuration.component.js +2 -2
  32. package/dist/AI/components/widgets/kpi-card.component.js +7 -7
  33. package/dist/AI/components/widgets/kpi-card.component.js.map +1 -1
  34. package/dist/AI/components/widgets/live-execution-widget.component.d.ts.map +1 -1
  35. package/dist/AI/components/widgets/live-execution-widget.component.js +6 -6
  36. package/dist/AI/components/widgets/live-execution-widget.component.js.map +1 -1
  37. package/dist/AI/index.d.ts +1 -0
  38. package/dist/AI/index.d.ts.map +1 -1
  39. package/dist/AI/index.js +2 -0
  40. package/dist/AI/index.js.map +1 -1
  41. package/dist/APIKeys/api-applications-panel.component.js +3 -3
  42. package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
  43. package/dist/APIKeys/api-key-create-dialog.component.js +3 -3
  44. package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
  45. package/dist/APIKeys/api-key-edit-panel.component.js +1 -1
  46. package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
  47. package/dist/APIKeys/api-key-list.component.js +3 -3
  48. package/dist/APIKeys/api-key-list.component.js.map +1 -1
  49. package/dist/APIKeys/api-keys-resource.component.js +1 -1
  50. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  51. package/dist/APIKeys/api-scopes-panel.component.js +2 -2
  52. package/dist/APIKeys/api-usage-panel.component.js +2 -2
  53. package/dist/Actions/components/actions-overview.component.js +2 -2
  54. package/dist/Actions/components/execution-monitoring.component.js +2 -2
  55. package/dist/Actions/components/explorer/action-breadcrumb.component.js +2 -2
  56. package/dist/Actions/components/explorer/action-card.component.js +2 -2
  57. package/dist/Actions/components/explorer/action-explorer.component.js +2 -2
  58. package/dist/Actions/components/explorer/action-list-item.component.js +2 -2
  59. package/dist/Actions/components/explorer/action-toolbar.component.js +2 -2
  60. package/dist/Actions/components/explorer/action-tree-panel.component.js +2 -2
  61. package/dist/Actions/components/explorer/new-action-panel.component.js +2 -2
  62. package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
  63. package/dist/Actions/components/explorer/new-category-panel.component.js +2 -2
  64. package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
  65. package/dist/Communication/communication-dashboard.component.js +2 -2
  66. package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
  67. package/dist/Communication/communication-logs-resource.component.js +3 -3
  68. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  69. package/dist/Communication/communication-monitor-resource.component.d.ts.map +1 -1
  70. package/dist/Communication/communication-monitor-resource.component.js +5 -5
  71. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  72. package/dist/Communication/communication-providers-resource.component.d.ts.map +1 -1
  73. package/dist/Communication/communication-providers-resource.component.js +3 -3
  74. package/dist/Communication/communication-providers-resource.component.js.map +1 -1
  75. package/dist/Communication/communication-runs-resource.component.d.ts.map +1 -1
  76. package/dist/Communication/communication-runs-resource.component.js +3 -3
  77. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  78. package/dist/Communication/communication-templates-resource.component.js +2 -2
  79. package/dist/Communication/communication-templates-resource.component.js.map +1 -1
  80. package/dist/ComponentStudio/component-studio-dashboard.component.js +2 -2
  81. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +2 -2
  82. package/dist/ComponentStudio/components/artifact-load-dialog.component.js +2 -2
  83. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -2
  84. package/dist/ComponentStudio/components/browser/component-browser.component.js +2 -2
  85. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +2 -2
  86. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
  87. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +2 -2
  88. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
  89. package/dist/ComponentStudio/components/editors/requirements-editor.component.js +2 -2
  90. package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
  91. package/dist/ComponentStudio/components/editors/spec-editor.component.js +2 -2
  92. package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
  93. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +2 -2
  94. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +2 -2
  95. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
  96. package/dist/ComponentStudio/components/text-import-dialog.component.js +2 -2
  97. package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
  98. package/dist/ComponentStudio/components/workspace/component-preview.component.js +2 -2
  99. package/dist/ComponentStudio/components/workspace/editor-tabs.component.js +2 -2
  100. package/dist/ComponentStudio/components/workspace/editor-tabs.component.js.map +1 -1
  101. package/dist/Credentials/components/credentials-audit-resource.component.js +9 -9
  102. package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
  103. package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
  104. package/dist/Credentials/components/credentials-categories-resource.component.js +11 -3
  105. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  106. package/dist/Credentials/components/credentials-list-resource.component.js +2 -2
  107. package/dist/Credentials/components/credentials-overview-resource.component.d.ts.map +1 -1
  108. package/dist/Credentials/components/credentials-overview-resource.component.js +12 -11
  109. package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
  110. package/dist/Credentials/components/credentials-types-resource.component.js +9 -9
  111. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  112. package/dist/Credentials/credentials-dashboard.component.js +2 -2
  113. package/dist/DashboardBrowser/dashboard-browser-resource.component.js +2 -2
  114. package/dist/DashboardBrowser/dashboard-share-dialog.component.js +2 -2
  115. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +2 -2
  116. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +2 -2
  117. package/dist/DataExplorer/components/view-selector/view-selector.component.js +2 -2
  118. package/dist/DataExplorer/data-explorer-dashboard.component.js +4 -4
  119. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  120. package/dist/Home/home-dashboard.component.js +2 -2
  121. package/dist/Integration/components/activity/activity.component.d.ts +1 -1
  122. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
  123. package/dist/Integration/components/activity/activity.component.js +5 -5
  124. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  125. package/dist/Integration/components/connections/connections.component.d.ts +31 -2
  126. package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
  127. package/dist/Integration/components/connections/connections.component.js +753 -412
  128. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  129. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +3 -3
  130. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
  131. package/dist/Integration/components/overview/overview.component.d.ts +0 -1
  132. package/dist/Integration/components/overview/overview.component.d.ts.map +1 -1
  133. package/dist/Integration/components/overview/overview.component.js +3 -6
  134. package/dist/Integration/components/overview/overview.component.js.map +1 -1
  135. package/dist/Integration/components/pipelines/pipelines.component.js +3 -3
  136. package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
  137. package/dist/Integration/components/schedules/schedules.component.d.ts +20 -0
  138. package/dist/Integration/components/schedules/schedules.component.d.ts.map +1 -1
  139. package/dist/Integration/components/schedules/schedules.component.js +97 -5
  140. package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
  141. package/dist/Integration/components/visual-editor/visual-editor.component.js +2 -2
  142. package/dist/Integration/components/widgets/integration-card.component.d.ts.map +1 -1
  143. package/dist/Integration/components/widgets/integration-card.component.js +5 -1
  144. package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
  145. package/dist/Integration/components/widgets/run-history-panel.component.js +2 -2
  146. package/dist/Integration/components/widgets/run-history-panel.component.js.map +1 -1
  147. package/dist/Integration/integration.module.d.ts +2 -1
  148. package/dist/Integration/integration.module.d.ts.map +1 -1
  149. package/dist/Integration/integration.module.js +7 -3
  150. package/dist/Integration/integration.module.js.map +1 -1
  151. package/dist/Integration/services/integration-data.service.d.ts +27 -2
  152. package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
  153. package/dist/Integration/services/integration-data.service.js +107 -4
  154. package/dist/Integration/services/integration-data.service.js.map +1 -1
  155. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  156. package/dist/Lists/components/lists-browse-resource.component.js +25 -24
  157. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  158. package/dist/Lists/components/lists-categories-resource.component.js +2 -2
  159. package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
  160. package/dist/Lists/components/lists-my-lists-resource.component.d.ts.map +1 -1
  161. package/dist/Lists/components/lists-my-lists-resource.component.js +26 -25
  162. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  163. package/dist/Lists/components/lists-operations-resource.component.js +2 -2
  164. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  165. package/dist/Lists/components/venn-diagram/venn-diagram.component.js +3 -3
  166. package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
  167. package/dist/MCP/components/mcp-connection-dialog.component.js +2 -2
  168. package/dist/MCP/components/mcp-log-detail-panel.component.js +2 -2
  169. package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
  170. package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
  171. package/dist/MCP/components/mcp-test-tool-dialog.component.js +2 -2
  172. package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
  173. package/dist/MCP/mcp-dashboard.component.js +2 -2
  174. package/dist/MCP/mcp-filter-panel.component.js +2 -2
  175. package/dist/QueryBrowser/query-browser-resource.component.js +7 -7
  176. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  177. package/dist/Scheduling/components/index.d.ts +0 -1
  178. package/dist/Scheduling/components/index.d.ts.map +1 -1
  179. package/dist/Scheduling/components/index.js +0 -1
  180. package/dist/Scheduling/components/index.js.map +1 -1
  181. package/dist/Scheduling/components/scheduling-activity.component.js +2 -2
  182. package/dist/Scheduling/components/scheduling-jobs.component.d.ts +6 -9
  183. package/dist/Scheduling/components/scheduling-jobs.component.d.ts.map +1 -1
  184. package/dist/Scheduling/components/scheduling-jobs.component.js +118 -110
  185. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  186. package/dist/Scheduling/components/scheduling-overview.component.js +3 -3
  187. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  188. package/dist/Scheduling/scheduling-dashboard.component.js +2 -2
  189. package/dist/SystemDiagnostics/system-diagnostics.component.js +4 -4
  190. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  191. package/dist/Testing/components/testing-analytics.component.js +2 -2
  192. package/dist/Testing/components/testing-analytics.component.js.map +1 -1
  193. package/dist/Testing/components/testing-dashboard-tab.component.js +4 -4
  194. package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
  195. package/dist/Testing/components/testing-explorer.component.js +2 -2
  196. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  197. package/dist/Testing/components/testing-review.component.d.ts.map +1 -1
  198. package/dist/Testing/components/testing-review.component.js +5 -5
  199. package/dist/Testing/components/testing-review.component.js.map +1 -1
  200. package/dist/Testing/components/testing-runs.component.js +2 -2
  201. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  202. package/dist/Testing/components/widgets/oracle-breakdown-table.component.js +2 -2
  203. package/dist/Testing/components/widgets/oracle-breakdown-table.component.js.map +1 -1
  204. package/dist/Testing/components/widgets/suite-tree.component.js +4 -4
  205. package/dist/Testing/components/widgets/suite-tree.component.js.map +1 -1
  206. package/dist/Testing/components/widgets/test-run-detail-panel.component.js +2 -2
  207. package/dist/Testing/components/widgets/test-run-detail-panel.component.js.map +1 -1
  208. package/dist/Testing/testing-dashboard.component.js +2 -2
  209. package/dist/VersionHistory/components/diff-resource.component.js +2 -2
  210. package/dist/VersionHistory/components/graph-resource.component.js +2 -2
  211. package/dist/VersionHistory/components/labels-resource.component.js +3 -3
  212. package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
  213. package/dist/VersionHistory/components/restore-resource.component.js +3 -3
  214. package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
  215. package/dist/__tests__/integration-data-service.test.js +1 -0
  216. package/dist/__tests__/integration-data-service.test.js.map +1 -1
  217. package/dist/module.d.ts +52 -49
  218. package/dist/module.d.ts.map +1 -1
  219. package/dist/module.js +25 -6
  220. package/dist/module.js.map +1 -1
  221. package/dist/public-api.d.ts +1 -1
  222. package/dist/public-api.d.ts.map +1 -1
  223. package/dist/public-api.js +1 -1
  224. package/dist/public-api.js.map +1 -1
  225. package/package.json +42 -40
  226. package/dist/Scheduling/components/job-slideout.component.d.ts +0 -45
  227. package/dist/Scheduling/components/job-slideout.component.d.ts.map +0 -1
  228. package/dist/Scheduling/components/job-slideout.component.js +0 -459
  229. package/dist/Scheduling/components/job-slideout.component.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"labels-resource.component.js","sourceRoot":"","sources":["../../../src/VersionHistory/components/labels-resource.component.ts","../../../src/VersionHistory/components/labels-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { RunView, Metadata } from '@memberjunction/core';\nimport { ResourceData, MJVersionLabelEntityType, MJVersionLabelItemEntityType, UserInfoEngine } from '@memberjunction/core-entities';\nimport { EntityLinkClickEvent } from '@memberjunction/ng-versions';\ninterface ScopeStat {\n Scope: string;\n Count: number;\n Icon: string;\n Color: string;\n}\n\ninterface StatusStat {\n Status: string;\n Count: number;\n Color: string;\n}\n\ninterface VersionLabelPreferences {\n ViewMode: 'card' | 'list';\n ActiveScopeFilter: string;\n ActiveStatusFilter: string;\n DefaultDetailTab: string;\n SortField: string;\n SortDirection: 'asc' | 'desc';\n}\n\ntype SortField = 'Name' | 'Scope' | 'Status' | 'Items' | 'Date';\n\n@RegisterClass(BaseResourceComponent, 'VersionHistoryLabelsResource')\n@Component({\n standalone: false,\n selector: 'mj-version-history-labels-resource',\n templateUrl: './labels-resource.component.html',\n styleUrls: ['./labels-resource.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class VersionHistoryLabelsResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n private static readonly PREFS_KEY = 'VersionHistory.Labels.UserPreferences';\n\n public IsLoading = true;\n\n // View mode\n public ViewMode: 'card' | 'list' = 'card';\n\n // Detail panel\n public SelectedLabel: MJVersionLabelEntityType | null = null;\n public ShowDetailPanel = false;\n\n // Stats\n public TotalLabels = 0;\n public ActiveLabels = 0;\n public ArchivedLabels = 0;\n public RestoredLabels = 0;\n\n // Grouped data\n public ScopeStats: ScopeStat[] = [];\n public StatusStats: StatusStat[] = [];\n public Labels: MJVersionLabelEntityType[] = [];\n public FilteredLabels: MJVersionLabelEntityType[] = [];\n public ItemCountMap = new Map<string, number>();\n\n // Filters\n public ScopeFilter = '';\n public StatusFilter = '';\n public SearchText = '';\n\n // Sorting\n public SortField: SortField = 'Date';\n public SortDirection: 'asc' | 'desc' = 'desc';\n\n // User preferences\n private preferencesLoaded = false;\n\n // Create Label Wizard\n public ShowCreateWizard = false;\n\n private metadata = new Metadata();\n private destroy$ = new Subject<void>();\n\n constructor(private cdr: ChangeDetectorRef, private navigationService: NavigationService) {\n super();\n }\n\n ngOnInit(): void {\n this.loadUserPreferences();\n this.LoadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Labels';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-tags';\n }\n\n // =======================================================================\n // Data loading\n // =======================================================================\n\n public async LoadData(): Promise<void> {\n try {\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n const rv = new RunView();\n\n const [labelsResult, itemsResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Version Labels',\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 500,\n ResultType: 'simple'\n },\n {\n EntityName: 'MJ: Version Label Items',\n Fields: ['VersionLabelID'],\n ResultType: 'simple'\n }\n ]);\n\n if (labelsResult.Success) {\n this.Labels = labelsResult.Results as MJVersionLabelEntityType[];\n const items = itemsResult.Success\n ? itemsResult.Results as MJVersionLabelItemEntityType[]\n : [];\n this.ItemCountMap = this.buildItemCountMap(items);\n this.computeStats();\n this.applyFilters();\n }\n } catch (error) {\n console.error('Error loading version labels:', error);\n } finally {\n this.IsLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n private buildItemCountMap(items: MJVersionLabelItemEntityType[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const item of items) {\n const labelId = item.VersionLabelID ?? '';\n counts.set(labelId, (counts.get(labelId) ?? 0) + 1);\n }\n return counts;\n }\n\n public GetItemCount(labelId: string | undefined): number {\n return this.ItemCountMap.get(labelId ?? '') ?? 0;\n }\n\n public ResolveEntityName(entityId: string | undefined): string {\n if (!entityId) return '';\n const entity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, entityId));\n return entity ? entity.Name : '';\n }\n\n // =======================================================================\n // Stats\n // =======================================================================\n\n private computeStats(): void {\n // Only count root-level labels (exclude children) for stats\n const rootLabels = this.Labels.filter(l => !l.ParentID);\n this.TotalLabels = rootLabels.length;\n this.ActiveLabels = rootLabels.filter(l => l.Status === 'Active').length;\n this.ArchivedLabels = rootLabels.filter(l => l.Status === 'Archived').length;\n this.RestoredLabels = rootLabels.filter(l => l.Status === 'Restored').length;\n\n this.ScopeStats = this.computeScopeStats();\n this.StatusStats = this.computeStatusStats();\n }\n\n private computeScopeStats(): ScopeStat[] {\n const scopeMap = new Map<string, number>();\n for (const label of this.Labels) {\n const scope = label.Scope ?? 'Record';\n scopeMap.set(scope, (scopeMap.get(scope) ?? 0) + 1);\n }\n\n const scopeConfig: Record<string, { Icon: string; Color: string }> = {\n 'System': { Icon: 'fa-solid fa-globe', Color: '#6366f1' },\n 'Entity': { Icon: 'fa-solid fa-table', Color: '#3b82f6' },\n 'Record': { Icon: 'fa-solid fa-file', Color: '#10b981' }\n };\n\n return Array.from(scopeMap.entries()).map(([scope, count]) => ({\n Scope: scope,\n Count: count,\n Icon: scopeConfig[scope]?.Icon ?? 'fa-solid fa-tag',\n Color: scopeConfig[scope]?.Color ?? '#64748b'\n }));\n }\n\n private computeStatusStats(): StatusStat[] {\n const statusMap = new Map<string, number>();\n for (const label of this.Labels) {\n const status = label.Status ?? 'Active';\n statusMap.set(status, (statusMap.get(status) ?? 0) + 1);\n }\n\n const statusColors: Record<string, string> = {\n 'Active': '#10b981',\n 'Archived': '#6b7280',\n 'Restored': '#f59e0b'\n };\n\n return Array.from(statusMap.entries()).map(([status, count]) => ({\n Status: status,\n Count: count,\n Color: statusColors[status] ?? '#64748b'\n }));\n }\n\n // =======================================================================\n // Filters\n // =======================================================================\n\n public applyFilters(): void {\n // First: exclude child labels (those with ParentID) from top-level list\n let result = this.Labels.filter(l => !l.ParentID);\n\n // Apply scope filter\n if (this.ScopeFilter) {\n result = result.filter(l => l.Scope === this.ScopeFilter);\n }\n\n // Apply status filter\n if (this.StatusFilter) {\n result = result.filter(l => l.Status === this.StatusFilter);\n }\n\n // Apply search\n if (this.SearchText) {\n const search = this.SearchText.toLowerCase();\n result = result.filter(l => {\n const name = (l.Name ?? '').toLowerCase();\n const desc = (l.Description ?? '').toLowerCase();\n const entityName = (l.Entity ?? this.ResolveEntityName(l.EntityID)).toLowerCase();\n return name.includes(search) || desc.includes(search) || entityName.includes(search);\n });\n }\n\n // Apply sorting\n result = this.sortLabels(result);\n\n this.FilteredLabels = result;\n this.cdr.markForCheck();\n }\n\n private sortLabels(labels: MJVersionLabelEntityType[]): MJVersionLabelEntityType[] {\n const dir = this.SortDirection === 'asc' ? 1 : -1;\n return [...labels].sort((a, b) => {\n switch (this.SortField) {\n case 'Name':\n return dir * (a.Name ?? '').localeCompare(b.Name ?? '');\n case 'Scope':\n return dir * (a.Scope ?? '').localeCompare(b.Scope ?? '');\n case 'Status':\n return dir * (a.Status ?? '').localeCompare(b.Status ?? '');\n case 'Items': {\n const aCount = this.GetItemCount(a.ID);\n const bCount = this.GetItemCount(b.ID);\n return dir * (aCount - bCount);\n }\n case 'Date':\n default: {\n const aDate = (a as Record<string, unknown>)['__mj_CreatedAt'] ?? '';\n const bDate = (b as Record<string, unknown>)['__mj_CreatedAt'] ?? '';\n return dir * String(aDate).localeCompare(String(bDate));\n }\n }\n });\n }\n\n public OnSortChange(field: SortField): void {\n if (this.SortField === field) {\n this.SortDirection = this.SortDirection === 'asc' ? 'desc' : 'asc';\n } else {\n this.SortField = field;\n this.SortDirection = field === 'Date' ? 'desc' : 'asc';\n }\n this.applyFilters();\n this.persistPreferences();\n }\n\n public GetSortIcon(field: SortField): string {\n if (this.SortField !== field) return 'fa-solid fa-sort';\n return this.SortDirection === 'asc' ? 'fa-solid fa-sort-up' : 'fa-solid fa-sort-down';\n }\n\n public OnScopeFilterChange(scope: string): void {\n this.ScopeFilter = this.ScopeFilter === scope ? '' : scope;\n this.applyFilters();\n this.persistPreferences();\n }\n\n public OnStatusFilterChange(status: string): void {\n this.StatusFilter = this.StatusFilter === status ? '' : status;\n this.applyFilters();\n this.persistPreferences();\n }\n\n public OnSearchChange(text: string): void {\n this.SearchText = text;\n this.applyFilters();\n }\n\n public Refresh(): void {\n this.LoadData();\n }\n\n // =======================================================================\n // View mode and detail panel\n // =======================================================================\n\n public ToggleViewMode(): void {\n this.ViewMode = this.ViewMode === 'card' ? 'list' : 'card';\n this.persistPreferences();\n this.cdr.markForCheck();\n }\n\n public SetViewMode(mode: 'card' | 'list'): void {\n if (this.ViewMode !== mode) {\n this.ViewMode = mode;\n this.persistPreferences();\n this.cdr.markForCheck();\n }\n }\n\n public OnLabelClick(label: MJVersionLabelEntityType): void {\n this.SelectedLabel = label;\n this.ShowDetailPanel = true;\n this.cdr.markForCheck();\n }\n\n public OnDetailPanelClose(): void {\n this.ShowDetailPanel = false;\n this.SelectedLabel = null;\n this.cdr.markForCheck();\n }\n\n public OnLabelUpdated(): void {\n this.LoadData();\n }\n\n public OnEntityLinkClick(event: EntityLinkClickEvent): void {\n this.navigationService.OpenEntityRecord(event.EntityName, event.CompositeKey);\n }\n\n // =======================================================================\n // User preferences\n // =======================================================================\n\n private loadUserPreferences(): void {\n try {\n const json = UserInfoEngine.Instance.GetSetting(VersionHistoryLabelsResourceComponent.PREFS_KEY);\n if (json) {\n const prefs = JSON.parse(json) as VersionLabelPreferences;\n this.ViewMode = prefs.ViewMode ?? 'card';\n this.ScopeFilter = prefs.ActiveScopeFilter ?? '';\n this.StatusFilter = prefs.ActiveStatusFilter ?? '';\n if (prefs.SortField) this.SortField = prefs.SortField as SortField;\n if (prefs.SortDirection) this.SortDirection = prefs.SortDirection;\n }\n } catch (e) {\n console.warn('[VersionLabels] Failed to load user preferences:', e);\n } finally {\n this.preferencesLoaded = true;\n }\n }\n\n private persistPreferences(): void {\n if (!this.preferencesLoaded) return;\n\n const prefs: VersionLabelPreferences = {\n ViewMode: this.ViewMode,\n ActiveScopeFilter: this.ScopeFilter,\n ActiveStatusFilter: this.StatusFilter,\n DefaultDetailTab: 'overview',\n SortField: this.SortField,\n SortDirection: this.SortDirection,\n };\n\n UserInfoEngine.Instance.SetSettingDebounced(\n VersionHistoryLabelsResourceComponent.PREFS_KEY,\n JSON.stringify(prefs)\n );\n }\n\n // =======================================================================\n // Create Label Wizard\n // =======================================================================\n\n public OpenCreateDialog(): void {\n this.ShowCreateWizard = true;\n this.cdr.markForCheck();\n }\n\n public OnLabelCreated(_event: { LabelCount: number; ItemCount: number }): void {\n this.ShowCreateWizard = false;\n this.cdr.markForCheck();\n this.LoadData();\n }\n\n public OnCreateWizardCancel(): void {\n this.ShowCreateWizard = false;\n this.cdr.markForCheck();\n }\n\n // =======================================================================\n // Display helpers\n // =======================================================================\n\n public GetScopeIcon(scope: string | undefined): string {\n const icons: Record<string, string> = {\n 'System': 'fa-solid fa-globe',\n 'Entity': 'fa-solid fa-table',\n 'Record': 'fa-solid fa-file'\n };\n return icons[scope ?? ''] ?? 'fa-solid fa-tag';\n }\n\n public GetStatusClass(status: string | undefined): string {\n const classes: Record<string, string> = {\n 'Active': 'status-active',\n 'Archived': 'status-archived',\n 'Restored': 'status-restored'\n };\n return classes[status ?? ''] ?? '';\n }\n\n public FormatDate(date: Date | string | undefined): string {\n if (!date) return '';\n const d = date instanceof Date ? date : new Date(date);\n const now = new Date();\n const diffMs = now.getTime() - d.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return 'Just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric'\n });\n }\n\n public FormatNumber(num: number): string {\n if (num >= 1000) return (num / 1000).toFixed(1) + 'k';\n return num.toString();\n }\n\n public FormatDuration(ms: number | undefined): string {\n if (!ms) return '';\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n }\n\n public IsGroupParent(label: MJVersionLabelEntityType): boolean {\n return !label.RecordID && !label.ParentID && !!label.EntityID;\n }\n\n public GetChildLabels(parentId: string | undefined): MJVersionLabelEntityType[] {\n if (!parentId) return [];\n return this.Labels.filter(l => UUIDsEqual(l.ParentID, parentId));\n }\n}\n","<div class=\"labels-container\">\n @if (IsLoading) {\n <mj-loading text=\"Loading version labels...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"page-header\">\n <div class=\"header-left\">\n <h2 class=\"page-title\">Version Labels</h2>\n <p class=\"page-subtitle\">Manage versioning snapshots across your system</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"view-toggle\">\n <button class=\"toggle-btn\" [class.active]=\"ViewMode === 'card'\" (click)=\"SetViewMode('card')\" title=\"Card view\">\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n <button class=\"toggle-btn\" [class.active]=\"ViewMode === 'list'\" (click)=\"SetViewMode('list')\" title=\"List view\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n </div>\n <button class=\"btn-primary\" (click)=\"OpenCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Create Label</span>\n </button>\n <button class=\"btn-icon\" (click)=\"Refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- KPI Cards -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(99, 102, 241, 0.1); color: #6366f1;\">\n <i class=\"fa-solid fa-tags\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FormatNumber(TotalLabels)}}</div>\n <div class=\"kpi-label\">Total Labels</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(16, 185, 129, 0.1); color: #10b981;\">\n <i class=\"fa-solid fa-circle-check\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FormatNumber(ActiveLabels)}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(107, 114, 128, 0.1); color: #6b7280;\">\n <i class=\"fa-solid fa-box-archive\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FormatNumber(ArchivedLabels)}}</div>\n <div class=\"kpi-label\">Archived</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(245, 158, 11, 0.1); color: #f59e0b;\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FormatNumber(RestoredLabels)}}</div>\n <div class=\"kpi-label\">Restored</div>\n </div>\n </div>\n </div>\n <!-- Scope breakdown -->\n <div class=\"scope-chips\">\n @for (stat of ScopeStats; track stat) {\n <button class=\"scope-chip\"\n [class.active]=\"ScopeFilter === stat.Scope\"\n (click)=\"OnScopeFilterChange(stat.Scope)\">\n <i [class]=\"stat.Icon\"></i>\n <span>{{stat.Scope}}</span>\n <span class=\"chip-count\">{{stat.Count}}</span>\n </button>\n }\n @for (stat of StatusStats; track stat) {\n <button class=\"scope-chip\"\n [class.active]=\"StatusFilter === stat.Status\"\n [ngClass]=\"GetStatusClass(stat.Status)\"\n (click)=\"OnStatusFilterChange(stat.Status)\">\n <span>{{stat.Status}}</span>\n <span class=\"chip-count\">{{stat.Count}}</span>\n </button>\n }\n </div>\n <!-- Search -->\n <div class=\"search-bar\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search labels by name, description, or entity...\"\n [ngModel]=\"SearchText\"\n (ngModelChange)=\"OnSearchChange($event)\" />\n @if (SearchText) {\n <button class=\"btn-clear\" (click)=\"OnSearchChange('')\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n }\n </div>\n <!-- Labels Card View -->\n @if (FilteredLabels.length > 0 && ViewMode === 'card') {\n <div class=\"labels-list\">\n @for (label of FilteredLabels; track label) {\n <div class=\"label-card clickable\"\n [class.group-parent]=\"IsGroupParent(label)\"\n (click)=\"OnLabelClick(label)\">\n <div class=\"label-header\">\n <div class=\"label-title-row\">\n <i [class]=\"GetScopeIcon(label.Scope)\" class=\"label-scope-icon\"></i>\n <h3 class=\"label-name\">{{label.Name}}</h3>\n @if (IsGroupParent(label)) {\n <span class=\"group-badge\">\n <i class=\"fa-solid fa-layer-group\"></i>\n {{GetChildLabels(label.ID).length}} records\n </span>\n }\n <span class=\"label-status\" [ngClass]=\"GetStatusClass(label.Status)\">\n {{label.Status}}\n </span>\n </div>\n <div class=\"label-meta\">\n <span class=\"meta-item\" title=\"Scope\">\n <i class=\"fa-solid fa-layer-group\"></i> {{label.Scope}}\n </span>\n @if (label.Entity || label.EntityID) {\n <span class=\"meta-item\" title=\"Entity\">\n <i class=\"fa-solid fa-table\"></i> {{label.Entity ?? ResolveEntityName(label.EntityID)}}\n </span>\n }\n @if (label.RecordID) {\n <span class=\"meta-item\" title=\"Record ID\">\n <i class=\"fa-solid fa-fingerprint\"></i> {{label.RecordID | slice:0:12}}...\n </span>\n }\n @if (label.ItemCount) {\n <span class=\"meta-item\" title=\"Items captured\">\n <i class=\"fa-solid fa-camera\"></i> {{label.ItemCount}} items\n </span>\n }\n @if (!label.ItemCount) {\n <span class=\"meta-item\" title=\"Items captured\">\n <i class=\"fa-solid fa-camera\"></i> {{GetItemCount(label.ID)}} items\n </span>\n }\n @if (label.CreationDurationMS) {\n <span class=\"meta-item\" title=\"Creation time\">\n <i class=\"fa-solid fa-stopwatch\"></i> {{FormatDuration(label.CreationDurationMS)}}\n </span>\n }\n @if (label.CreatedByUser) {\n <span class=\"meta-item\" title=\"Created by\">\n <i class=\"fa-solid fa-user\"></i> {{label.CreatedByUser}}\n </span>\n }\n <span class=\"meta-item\" title=\"Created\">\n <i class=\"fa-regular fa-clock\"></i> {{FormatDate(label.__mj_CreatedAt)}}\n </span>\n </div>\n </div>\n @if (label.Description) {\n <p class=\"label-description\">{{label.Description}}</p>\n }\n <!-- Child labels for group parents -->\n @if (IsGroupParent(label) && GetChildLabels(label.ID).length > 0) {\n <div class=\"child-labels\">\n @for (child of GetChildLabels(label.ID); track child) {\n <div class=\"child-label\">\n <i class=\"fa-solid fa-tag child-icon\"></i>\n <span class=\"child-name\">{{child.Name}}</span>\n @if (child.RecordID) {\n <span class=\"child-record\">{{child.RecordID | slice:0:12}}...</span>\n }\n @if (child.ItemCount) {\n <span class=\"child-items\">{{child.ItemCount}} items</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Labels List View -->\n @if (FilteredLabels.length > 0 && ViewMode === 'list') {\n <div class=\"labels-table\">\n <div class=\"list-header-row\">\n <span class=\"list-col-icon\"></span>\n <span class=\"list-col-name sortable-header\" (click)=\"OnSortChange('Name')\">\n Name <i [class]=\"GetSortIcon('Name')\" class=\"sort-icon\"></i>\n </span>\n <span class=\"list-col-entity\">Entity</span>\n <span class=\"list-col-status sortable-header\" (click)=\"OnSortChange('Status')\">\n Status <i [class]=\"GetSortIcon('Status')\" class=\"sort-icon\"></i>\n </span>\n <span class=\"list-col-items sortable-header\" (click)=\"OnSortChange('Items')\">\n Items <i [class]=\"GetSortIcon('Items')\" class=\"sort-icon\"></i>\n </span>\n <span class=\"list-col-date sortable-header\" (click)=\"OnSortChange('Date')\">\n Created <i [class]=\"GetSortIcon('Date')\" class=\"sort-icon\"></i>\n </span>\n <span class=\"list-col-arrow\"></span>\n </div>\n @for (label of FilteredLabels; track label) {\n <div class=\"list-row clickable\"\n (click)=\"OnLabelClick(label)\">\n <span class=\"list-col-icon\">\n <i [class]=\"GetScopeIcon(label.Scope)\" class=\"list-scope-icon\"></i>\n </span>\n <span class=\"list-col-name\">\n <span class=\"list-label-name\">{{label.Name}}</span>\n @if (IsGroupParent(label)) {\n <span class=\"list-group-badge\">\n <i class=\"fa-solid fa-layer-group\"></i> {{GetChildLabels(label.ID).length}}\n </span>\n }\n </span>\n <span class=\"list-col-entity\">{{label.Entity ?? ResolveEntityName(label.EntityID)}}</span>\n <span class=\"list-col-status\">\n <span class=\"label-status small\" [ngClass]=\"GetStatusClass(label.Status)\">{{label.Status}}</span>\n </span>\n <span class=\"list-col-items\">{{label.ItemCount || GetItemCount(label.ID)}}</span>\n <span class=\"list-col-date\">{{FormatDate(label.__mj_CreatedAt)}}</span>\n <span class=\"list-col-arrow\">\n <i class=\"fa-solid fa-chevron-right list-arrow\"></i>\n </span>\n </div>\n }\n </div>\n }\n <!-- Empty state -->\n @if (FilteredLabels.length === 0 && !IsLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-tags empty-icon\"></i>\n <h3>No labels found</h3>\n @if (SearchText || ScopeFilter || StatusFilter) {\n <p>\n Try adjusting your filters or search criteria.\n </p>\n }\n @if (!SearchText && !ScopeFilter && !StatusFilter) {\n <p>\n No version labels have been created yet.\n </p>\n }\n @if (!SearchText && !ScopeFilter && !StatusFilter) {\n <button class=\"btn-primary empty-cta\"\n (click)=\"OpenCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Create Your First Label</span>\n </button>\n }\n </div>\n }\n }\n\n <!-- Create Label Wizard -->\n @if (ShowCreateWizard) {\n <div class=\"create-wizard-overlay\" (click)=\"OnCreateWizardCancel()\">\n <div class=\"create-wizard-container\" (click)=\"$event.stopPropagation()\">\n <div class=\"create-wizard-header\">\n <h3 class=\"create-wizard-title\">\n <i class=\"fa-solid fa-tag\"></i>\n Create Version Label\n </h3>\n <button class=\"create-wizard-close\" (click)=\"OnCreateWizardCancel()\" title=\"Close\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"create-wizard-body\">\n <mj-label-create\n (Created)=\"OnLabelCreated($event)\"\n (Cancel)=\"OnCreateWizardCancel()\">\n </mj-label-create>\n </div>\n </div>\n </div>\n }\n\n <!-- Detail panel -->\n @if (ShowDetailPanel && SelectedLabel) {\n <mj-label-detail-panel\n [Label]=\"SelectedLabel\"\n [AllLabels]=\"Labels\"\n [ItemCountMap]=\"ItemCountMap\"\n (Close)=\"OnDetailPanelClose()\"\n (LabelUpdated)=\"OnLabelUpdated()\"\n (EntityLinkClick)=\"OnEntityLinkClick($event)\">\n </mj-label-detail-panel>\n }\n</div>\n"]}
1
+ {"version":3,"file":"labels-resource.component.js","sourceRoot":"","sources":["../../../src/VersionHistory/components/labels-resource.component.ts","../../../src/VersionHistory/components/labels-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { RunView, Metadata } from '@memberjunction/core';\nimport { ResourceData, MJVersionLabelEntityType, MJVersionLabelItemEntityType, UserInfoEngine } from '@memberjunction/core-entities';\nimport { EntityLinkClickEvent } from '@memberjunction/ng-versions';\ninterface ScopeStat {\n Scope: string;\n Count: number;\n Icon: string;\n Color: string;\n}\n\ninterface StatusStat {\n Status: string;\n Count: number;\n Color: string;\n}\n\ninterface VersionLabelPreferences {\n ViewMode: 'card' | 'list';\n ActiveScopeFilter: string;\n ActiveStatusFilter: string;\n DefaultDetailTab: string;\n SortField: string;\n SortDirection: 'asc' | 'desc';\n}\n\ntype SortField = 'Name' | 'Scope' | 'Status' | 'Items' | 'Date';\n\n@RegisterClass(BaseResourceComponent, 'VersionHistoryLabelsResource')\n@Component({\n standalone: false,\n selector: 'mj-version-history-labels-resource',\n templateUrl: './labels-resource.component.html',\n styleUrls: ['./labels-resource.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class VersionHistoryLabelsResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n private static readonly PREFS_KEY = 'VersionHistory.Labels.UserPreferences';\n\n public IsLoading = true;\n\n // View mode\n public ViewMode: 'card' | 'list' = 'card';\n\n // Detail panel\n public SelectedLabel: MJVersionLabelEntityType | null = null;\n public ShowDetailPanel = false;\n\n // Stats\n public TotalLabels = 0;\n public ActiveLabels = 0;\n public ArchivedLabels = 0;\n public RestoredLabels = 0;\n\n // Grouped data\n public ScopeStats: ScopeStat[] = [];\n public StatusStats: StatusStat[] = [];\n public Labels: MJVersionLabelEntityType[] = [];\n public FilteredLabels: MJVersionLabelEntityType[] = [];\n public ItemCountMap = new Map<string, number>();\n\n // Filters\n public ScopeFilter = '';\n public StatusFilter = '';\n public SearchText = '';\n\n // Sorting\n public SortField: SortField = 'Date';\n public SortDirection: 'asc' | 'desc' = 'desc';\n\n // User preferences\n private preferencesLoaded = false;\n\n // Create Label Wizard\n public ShowCreateWizard = false;\n\n private metadata = new Metadata();\n private destroy$ = new Subject<void>();\n\n constructor(private cdr: ChangeDetectorRef, private navigationService: NavigationService) {\n super();\n }\n\n ngOnInit(): void {\n this.loadUserPreferences();\n this.LoadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Labels';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-tags';\n }\n\n // =======================================================================\n // Data loading\n // =======================================================================\n\n public async LoadData(): Promise<void> {\n try {\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n const rv = new RunView();\n\n const [labelsResult, itemsResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Version Labels',\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 500,\n ResultType: 'simple'\n },\n {\n EntityName: 'MJ: Version Label Items',\n Fields: ['VersionLabelID'],\n ResultType: 'simple'\n }\n ]);\n\n if (labelsResult.Success) {\n this.Labels = labelsResult.Results as MJVersionLabelEntityType[];\n const items = itemsResult.Success\n ? itemsResult.Results as MJVersionLabelItemEntityType[]\n : [];\n this.ItemCountMap = this.buildItemCountMap(items);\n this.computeStats();\n this.applyFilters();\n }\n } catch (error) {\n console.error('Error loading version labels:', error);\n } finally {\n this.IsLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n private buildItemCountMap(items: MJVersionLabelItemEntityType[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const item of items) {\n const labelId = item.VersionLabelID ?? '';\n counts.set(labelId, (counts.get(labelId) ?? 0) + 1);\n }\n return counts;\n }\n\n public GetItemCount(labelId: string | undefined): number {\n return this.ItemCountMap.get(labelId ?? '') ?? 0;\n }\n\n public ResolveEntityName(entityId: string | undefined): string {\n if (!entityId) return '';\n const entity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, entityId));\n return entity ? entity.Name : '';\n }\n\n // =======================================================================\n // Stats\n // =======================================================================\n\n private computeStats(): void {\n // Only count root-level labels (exclude children) for stats\n const rootLabels = this.Labels.filter(l => !l.ParentID);\n this.TotalLabels = rootLabels.length;\n this.ActiveLabels = rootLabels.filter(l => l.Status === 'Active').length;\n this.ArchivedLabels = rootLabels.filter(l => l.Status === 'Archived').length;\n this.RestoredLabels = rootLabels.filter(l => l.Status === 'Restored').length;\n\n this.ScopeStats = this.computeScopeStats();\n this.StatusStats = this.computeStatusStats();\n }\n\n private computeScopeStats(): ScopeStat[] {\n const scopeMap = new Map<string, number>();\n for (const label of this.Labels) {\n const scope = label.Scope ?? 'Record';\n scopeMap.set(scope, (scopeMap.get(scope) ?? 0) + 1);\n }\n\n const scopeConfig: Record<string, { Icon: string; Color: string }> = {\n 'System': { Icon: 'fa-solid fa-globe', Color: '#6366f1' },\n 'Entity': { Icon: 'fa-solid fa-table', Color: '#3b82f6' },\n 'Record': { Icon: 'fa-solid fa-file', Color: '#10b981' }\n };\n\n return Array.from(scopeMap.entries()).map(([scope, count]) => ({\n Scope: scope,\n Count: count,\n Icon: scopeConfig[scope]?.Icon ?? 'fa-solid fa-tag',\n Color: scopeConfig[scope]?.Color ?? '#64748b'\n }));\n }\n\n private computeStatusStats(): StatusStat[] {\n const statusMap = new Map<string, number>();\n for (const label of this.Labels) {\n const status = label.Status ?? 'Active';\n statusMap.set(status, (statusMap.get(status) ?? 0) + 1);\n }\n\n const statusColors: Record<string, string> = {\n 'Active': '#10b981',\n 'Archived': '#6b7280',\n 'Restored': '#f59e0b'\n };\n\n return Array.from(statusMap.entries()).map(([status, count]) => ({\n Status: status,\n Count: count,\n Color: statusColors[status] ?? '#64748b'\n }));\n }\n\n // =======================================================================\n // Filters\n // =======================================================================\n\n public applyFilters(): void {\n // First: exclude child labels (those with ParentID) from top-level list\n let result = this.Labels.filter(l => !l.ParentID);\n\n // Apply scope filter\n if (this.ScopeFilter) {\n result = result.filter(l => l.Scope === this.ScopeFilter);\n }\n\n // Apply status filter\n if (this.StatusFilter) {\n result = result.filter(l => l.Status === this.StatusFilter);\n }\n\n // Apply search\n if (this.SearchText) {\n const search = this.SearchText.toLowerCase();\n result = result.filter(l => {\n const name = (l.Name ?? '').toLowerCase();\n const desc = (l.Description ?? '').toLowerCase();\n const entityName = (l.Entity ?? this.ResolveEntityName(l.EntityID)).toLowerCase();\n return name.includes(search) || desc.includes(search) || entityName.includes(search);\n });\n }\n\n // Apply sorting\n result = this.sortLabels(result);\n\n this.FilteredLabels = result;\n this.cdr.markForCheck();\n }\n\n private sortLabels(labels: MJVersionLabelEntityType[]): MJVersionLabelEntityType[] {\n const dir = this.SortDirection === 'asc' ? 1 : -1;\n return [...labels].sort((a, b) => {\n switch (this.SortField) {\n case 'Name':\n return dir * (a.Name ?? '').localeCompare(b.Name ?? '');\n case 'Scope':\n return dir * (a.Scope ?? '').localeCompare(b.Scope ?? '');\n case 'Status':\n return dir * (a.Status ?? '').localeCompare(b.Status ?? '');\n case 'Items': {\n const aCount = this.GetItemCount(a.ID);\n const bCount = this.GetItemCount(b.ID);\n return dir * (aCount - bCount);\n }\n case 'Date':\n default: {\n const aDate = (a as Record<string, unknown>)['__mj_CreatedAt'] ?? '';\n const bDate = (b as Record<string, unknown>)['__mj_CreatedAt'] ?? '';\n return dir * String(aDate).localeCompare(String(bDate));\n }\n }\n });\n }\n\n public OnSortChange(field: SortField): void {\n if (this.SortField === field) {\n this.SortDirection = this.SortDirection === 'asc' ? 'desc' : 'asc';\n } else {\n this.SortField = field;\n this.SortDirection = field === 'Date' ? 'desc' : 'asc';\n }\n this.applyFilters();\n this.persistPreferences();\n }\n\n public GetSortIcon(field: SortField): string {\n if (this.SortField !== field) return 'fa-solid fa-sort';\n return this.SortDirection === 'asc' ? 'fa-solid fa-sort-up' : 'fa-solid fa-sort-down';\n }\n\n public OnScopeFilterChange(scope: string): void {\n this.ScopeFilter = this.ScopeFilter === scope ? '' : scope;\n this.applyFilters();\n this.persistPreferences();\n }\n\n public OnStatusFilterChange(status: string): void {\n this.StatusFilter = this.StatusFilter === status ? '' : status;\n this.applyFilters();\n this.persistPreferences();\n }\n\n public OnSearchChange(text: string): void {\n this.SearchText = text;\n this.applyFilters();\n }\n\n public Refresh(): void {\n this.LoadData();\n }\n\n // =======================================================================\n // View mode and detail panel\n // =======================================================================\n\n public ToggleViewMode(): void {\n this.ViewMode = this.ViewMode === 'card' ? 'list' : 'card';\n this.persistPreferences();\n this.cdr.markForCheck();\n }\n\n public SetViewMode(mode: 'card' | 'list'): void {\n if (this.ViewMode !== mode) {\n this.ViewMode = mode;\n this.persistPreferences();\n this.cdr.markForCheck();\n }\n }\n\n public OnLabelClick(label: MJVersionLabelEntityType): void {\n this.SelectedLabel = label;\n this.ShowDetailPanel = true;\n this.cdr.markForCheck();\n }\n\n public OnDetailPanelClose(): void {\n this.ShowDetailPanel = false;\n this.SelectedLabel = null;\n this.cdr.markForCheck();\n }\n\n public OnLabelUpdated(): void {\n this.LoadData();\n }\n\n public OnEntityLinkClick(event: EntityLinkClickEvent): void {\n this.navigationService.OpenEntityRecord(event.EntityName, event.CompositeKey);\n }\n\n // =======================================================================\n // User preferences\n // =======================================================================\n\n private loadUserPreferences(): void {\n try {\n const json = UserInfoEngine.Instance.GetSetting(VersionHistoryLabelsResourceComponent.PREFS_KEY);\n if (json) {\n const prefs = JSON.parse(json) as VersionLabelPreferences;\n this.ViewMode = prefs.ViewMode ?? 'card';\n this.ScopeFilter = prefs.ActiveScopeFilter ?? '';\n this.StatusFilter = prefs.ActiveStatusFilter ?? '';\n if (prefs.SortField) this.SortField = prefs.SortField as SortField;\n if (prefs.SortDirection) this.SortDirection = prefs.SortDirection;\n }\n } catch (e) {\n console.warn('[VersionLabels] Failed to load user preferences:', e);\n } finally {\n this.preferencesLoaded = true;\n }\n }\n\n private persistPreferences(): void {\n if (!this.preferencesLoaded) return;\n\n const prefs: VersionLabelPreferences = {\n ViewMode: this.ViewMode,\n ActiveScopeFilter: this.ScopeFilter,\n ActiveStatusFilter: this.StatusFilter,\n DefaultDetailTab: 'overview',\n SortField: this.SortField,\n SortDirection: this.SortDirection,\n };\n\n UserInfoEngine.Instance.SetSettingDebounced(\n VersionHistoryLabelsResourceComponent.PREFS_KEY,\n JSON.stringify(prefs)\n );\n }\n\n // =======================================================================\n // Create Label Wizard\n // =======================================================================\n\n public OpenCreateDialog(): void {\n this.ShowCreateWizard = true;\n this.cdr.markForCheck();\n }\n\n public OnLabelCreated(_event: { LabelCount: number; ItemCount: number }): void {\n this.ShowCreateWizard = false;\n this.cdr.markForCheck();\n this.LoadData();\n }\n\n public OnCreateWizardCancel(): void {\n this.ShowCreateWizard = false;\n this.cdr.markForCheck();\n }\n\n // =======================================================================\n // Display helpers\n // =======================================================================\n\n public GetScopeIcon(scope: string | undefined): string {\n const icons: Record<string, string> = {\n 'System': 'fa-solid fa-globe',\n 'Entity': 'fa-solid fa-table',\n 'Record': 'fa-solid fa-file'\n };\n return icons[scope ?? ''] ?? 'fa-solid fa-tag';\n }\n\n public GetStatusClass(status: string | undefined): string {\n const classes: Record<string, string> = {\n 'Active': 'status-active',\n 'Archived': 'status-archived',\n 'Restored': 'status-restored'\n };\n return classes[status ?? ''] ?? '';\n }\n\n public FormatDate(date: Date | string | undefined): string {\n if (!date) return '';\n const d = date instanceof Date ? date : new Date(date);\n const now = new Date();\n const diffMs = now.getTime() - d.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return 'Just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric'\n });\n }\n\n public FormatNumber(num: number): string {\n if (num >= 1000) return (num / 1000).toFixed(1) + 'k';\n return num.toString();\n }\n\n public FormatDuration(ms: number | undefined): string {\n if (!ms) return '';\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n }\n\n public IsGroupParent(label: MJVersionLabelEntityType): boolean {\n return !label.RecordID && !label.ParentID && !!label.EntityID;\n }\n\n public GetChildLabels(parentId: string | undefined): MJVersionLabelEntityType[] {\n if (!parentId) return [];\n return this.Labels.filter(l => UUIDsEqual(l.ParentID, parentId));\n }\n}\n","<div class=\"labels-container\">\n @if (IsLoading) {\n <mj-loading text=\"Loading version labels...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"page-header\">\n <div class=\"header-left\">\n <h2 class=\"page-title\">Version Labels</h2>\n <p class=\"page-subtitle\">Manage versioning snapshots across your system</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"view-toggle\">\n <button class=\"toggle-btn\" [class.active]=\"ViewMode === 'card'\" (click)=\"SetViewMode('card')\" title=\"Card view\">\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n <button class=\"toggle-btn\" [class.active]=\"ViewMode === 'list'\" (click)=\"SetViewMode('list')\" title=\"List view\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n </div>\n <button class=\"btn-primary\" (click)=\"OpenCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Create Label</span>\n </button>\n <button class=\"btn-icon\" (click)=\"Refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- KPI Cards -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent); color: var(--mj-brand-primary);\">\n <i class=\"fa-solid fa-tags\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FormatNumber(TotalLabels)}}</div>\n <div class=\"kpi-label\">Total Labels</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-status-success) 10%, transparent); color: var(--mj-status-success);\">\n <i class=\"fa-solid fa-circle-check\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FormatNumber(ActiveLabels)}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-text-muted) 10%, transparent); color: var(--mj-text-muted);\">\n <i class=\"fa-solid fa-box-archive\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FormatNumber(ArchivedLabels)}}</div>\n <div class=\"kpi-label\">Archived</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-status-warning) 10%, transparent); color: var(--mj-status-warning);\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FormatNumber(RestoredLabels)}}</div>\n <div class=\"kpi-label\">Restored</div>\n </div>\n </div>\n </div>\n <!-- Scope breakdown -->\n <div class=\"scope-chips\">\n @for (stat of ScopeStats; track stat) {\n <button class=\"scope-chip\"\n [class.active]=\"ScopeFilter === stat.Scope\"\n (click)=\"OnScopeFilterChange(stat.Scope)\">\n <i [class]=\"stat.Icon\"></i>\n <span>{{stat.Scope}}</span>\n <span class=\"chip-count\">{{stat.Count}}</span>\n </button>\n }\n @for (stat of StatusStats; track stat) {\n <button class=\"scope-chip\"\n [class.active]=\"StatusFilter === stat.Status\"\n [ngClass]=\"GetStatusClass(stat.Status)\"\n (click)=\"OnStatusFilterChange(stat.Status)\">\n <span>{{stat.Status}}</span>\n <span class=\"chip-count\">{{stat.Count}}</span>\n </button>\n }\n </div>\n <!-- Search -->\n <div class=\"search-bar\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search labels by name, description, or entity...\"\n [ngModel]=\"SearchText\"\n (ngModelChange)=\"OnSearchChange($event)\" />\n @if (SearchText) {\n <button class=\"btn-clear\" (click)=\"OnSearchChange('')\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n }\n </div>\n <!-- Labels Card View -->\n @if (FilteredLabels.length > 0 && ViewMode === 'card') {\n <div class=\"labels-list\">\n @for (label of FilteredLabels; track label) {\n <div class=\"label-card clickable\"\n [class.group-parent]=\"IsGroupParent(label)\"\n (click)=\"OnLabelClick(label)\">\n <div class=\"label-header\">\n <div class=\"label-title-row\">\n <i [class]=\"GetScopeIcon(label.Scope)\" class=\"label-scope-icon\"></i>\n <h3 class=\"label-name\">{{label.Name}}</h3>\n @if (IsGroupParent(label)) {\n <span class=\"group-badge\">\n <i class=\"fa-solid fa-layer-group\"></i>\n {{GetChildLabels(label.ID).length}} records\n </span>\n }\n <span class=\"label-status\" [ngClass]=\"GetStatusClass(label.Status)\">\n {{label.Status}}\n </span>\n </div>\n <div class=\"label-meta\">\n <span class=\"meta-item\" title=\"Scope\">\n <i class=\"fa-solid fa-layer-group\"></i> {{label.Scope}}\n </span>\n @if (label.Entity || label.EntityID) {\n <span class=\"meta-item\" title=\"Entity\">\n <i class=\"fa-solid fa-table\"></i> {{label.Entity ?? ResolveEntityName(label.EntityID)}}\n </span>\n }\n @if (label.RecordID) {\n <span class=\"meta-item\" title=\"Record ID\">\n <i class=\"fa-solid fa-fingerprint\"></i> {{label.RecordID | slice:0:12}}...\n </span>\n }\n @if (label.ItemCount) {\n <span class=\"meta-item\" title=\"Items captured\">\n <i class=\"fa-solid fa-camera\"></i> {{label.ItemCount}} items\n </span>\n }\n @if (!label.ItemCount) {\n <span class=\"meta-item\" title=\"Items captured\">\n <i class=\"fa-solid fa-camera\"></i> {{GetItemCount(label.ID)}} items\n </span>\n }\n @if (label.CreationDurationMS) {\n <span class=\"meta-item\" title=\"Creation time\">\n <i class=\"fa-solid fa-stopwatch\"></i> {{FormatDuration(label.CreationDurationMS)}}\n </span>\n }\n @if (label.CreatedByUser) {\n <span class=\"meta-item\" title=\"Created by\">\n <i class=\"fa-solid fa-user\"></i> {{label.CreatedByUser}}\n </span>\n }\n <span class=\"meta-item\" title=\"Created\">\n <i class=\"fa-regular fa-clock\"></i> {{FormatDate(label.__mj_CreatedAt)}}\n </span>\n </div>\n </div>\n @if (label.Description) {\n <p class=\"label-description\">{{label.Description}}</p>\n }\n <!-- Child labels for group parents -->\n @if (IsGroupParent(label) && GetChildLabels(label.ID).length > 0) {\n <div class=\"child-labels\">\n @for (child of GetChildLabels(label.ID); track child) {\n <div class=\"child-label\">\n <i class=\"fa-solid fa-tag child-icon\"></i>\n <span class=\"child-name\">{{child.Name}}</span>\n @if (child.RecordID) {\n <span class=\"child-record\">{{child.RecordID | slice:0:12}}...</span>\n }\n @if (child.ItemCount) {\n <span class=\"child-items\">{{child.ItemCount}} items</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Labels List View -->\n @if (FilteredLabels.length > 0 && ViewMode === 'list') {\n <div class=\"labels-table\">\n <div class=\"list-header-row\">\n <span class=\"list-col-icon\"></span>\n <span class=\"list-col-name sortable-header\" (click)=\"OnSortChange('Name')\">\n Name <i [class]=\"GetSortIcon('Name')\" class=\"sort-icon\"></i>\n </span>\n <span class=\"list-col-entity\">Entity</span>\n <span class=\"list-col-status sortable-header\" (click)=\"OnSortChange('Status')\">\n Status <i [class]=\"GetSortIcon('Status')\" class=\"sort-icon\"></i>\n </span>\n <span class=\"list-col-items sortable-header\" (click)=\"OnSortChange('Items')\">\n Items <i [class]=\"GetSortIcon('Items')\" class=\"sort-icon\"></i>\n </span>\n <span class=\"list-col-date sortable-header\" (click)=\"OnSortChange('Date')\">\n Created <i [class]=\"GetSortIcon('Date')\" class=\"sort-icon\"></i>\n </span>\n <span class=\"list-col-arrow\"></span>\n </div>\n @for (label of FilteredLabels; track label) {\n <div class=\"list-row clickable\"\n (click)=\"OnLabelClick(label)\">\n <span class=\"list-col-icon\">\n <i [class]=\"GetScopeIcon(label.Scope)\" class=\"list-scope-icon\"></i>\n </span>\n <span class=\"list-col-name\">\n <span class=\"list-label-name\">{{label.Name}}</span>\n @if (IsGroupParent(label)) {\n <span class=\"list-group-badge\">\n <i class=\"fa-solid fa-layer-group\"></i> {{GetChildLabels(label.ID).length}}\n </span>\n }\n </span>\n <span class=\"list-col-entity\">{{label.Entity ?? ResolveEntityName(label.EntityID)}}</span>\n <span class=\"list-col-status\">\n <span class=\"label-status small\" [ngClass]=\"GetStatusClass(label.Status)\">{{label.Status}}</span>\n </span>\n <span class=\"list-col-items\">{{label.ItemCount || GetItemCount(label.ID)}}</span>\n <span class=\"list-col-date\">{{FormatDate(label.__mj_CreatedAt)}}</span>\n <span class=\"list-col-arrow\">\n <i class=\"fa-solid fa-chevron-right list-arrow\"></i>\n </span>\n </div>\n }\n </div>\n }\n <!-- Empty state -->\n @if (FilteredLabels.length === 0 && !IsLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-tags empty-icon\"></i>\n <h3>No labels found</h3>\n @if (SearchText || ScopeFilter || StatusFilter) {\n <p>\n Try adjusting your filters or search criteria.\n </p>\n }\n @if (!SearchText && !ScopeFilter && !StatusFilter) {\n <p>\n No version labels have been created yet.\n </p>\n }\n @if (!SearchText && !ScopeFilter && !StatusFilter) {\n <button class=\"btn-primary empty-cta\"\n (click)=\"OpenCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Create Your First Label</span>\n </button>\n }\n </div>\n }\n }\n\n <!-- Create Label Wizard -->\n @if (ShowCreateWizard) {\n <div class=\"create-wizard-overlay\" (click)=\"OnCreateWizardCancel()\">\n <div class=\"create-wizard-container\" (click)=\"$event.stopPropagation()\">\n <div class=\"create-wizard-header\">\n <h3 class=\"create-wizard-title\">\n <i class=\"fa-solid fa-tag\"></i>\n Create Version Label\n </h3>\n <button class=\"create-wizard-close\" (click)=\"OnCreateWizardCancel()\" title=\"Close\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"create-wizard-body\">\n <mj-label-create\n (Created)=\"OnLabelCreated($event)\"\n (Cancel)=\"OnCreateWizardCancel()\">\n </mj-label-create>\n </div>\n </div>\n </div>\n }\n\n <!-- Detail panel -->\n @if (ShowDetailPanel && SelectedLabel) {\n <mj-label-detail-panel\n [Label]=\"SelectedLabel\"\n [AllLabels]=\"Labels\"\n [ItemCountMap]=\"ItemCountMap\"\n (Close)=\"OnDetailPanelClose()\"\n (LabelUpdated)=\"OnLabelUpdated()\"\n (EntityLinkClick)=\"OnEntityLinkClick($event)\">\n </mj-label-detail-panel>\n }\n</div>\n"]}
@@ -448,7 +448,7 @@ let VersionHistoryRestoreResourceComponent = class VersionHistoryRestoreResource
448
448
  this.LoadData();
449
449
  }
450
450
  static ɵfac = function VersionHistoryRestoreResourceComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || VersionHistoryRestoreResourceComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
451
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: VersionHistoryRestoreResourceComponent, selectors: [["mj-version-history-restore-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 3, vars: 2, consts: [[1, "restore-container"], ["text", "Loading restore history..."], [1, "page-header"], [1, "header-left"], [1, "page-title"], [1, "page-subtitle"], [1, "header-actions"], ["title", "Refresh", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-refresh"], [1, "kpi-row"], [1, "kpi-card"], [1, "kpi-icon", 2, "background", "rgba(99, 102, 241, 0.1)", "color", "#6366f1"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-icon", 2, "background", "rgba(16, 185, 129, 0.1)", "color", "#10b981"], [1, "fa-solid", "fa-circle-check"], [1, "kpi-icon", 2, "background", "rgba(239, 68, 68, 0.1)", "color", "#ef4444"], [1, "fa-solid", "fa-circle-xmark"], [1, "kpi-icon", 2, "background", "rgba(245, 158, 11, 0.1)", "color", "#f59e0b"], [1, "fa-solid", "fa-circle-half-stroke"], [1, "filter-row"], [1, "filter-chip", 3, "click"], [1, "restore-list"], [1, "empty-state"], [1, "restore-card", 3, "ngClass"], [1, "restore-header", 3, "click"], [1, "restore-header-left"], [1, "status-icon", 3, "ngClass"], [1, "restore-info"], [1, "restore-label-name"], [1, "restore-date"], [1, "restore-header-right"], [1, "restore-progress-bar"], [1, "progress-fill", 3, "ngClass"], [1, "restore-count"], [1, "expand-icon", 3, "ngClass"], [1, "restore-details"], [1, "detail-grid"], [1, "detail-item"], [1, "detail-label"], [1, "detail-value", 3, "ngClass"], [1, "detail-value"], [1, "error-log"], [1, "detail-value", "detail-mono"], [1, "error-log-header"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "error-log-content"], [1, "fa-solid", "fa-clock-rotate-left", "empty-icon"]], template: function VersionHistoryRestoreResourceComponent_Template(rf, ctx) { if (rf & 1) {
451
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: VersionHistoryRestoreResourceComponent, selectors: [["mj-version-history-restore-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 3, vars: 2, consts: [[1, "restore-container"], ["text", "Loading restore history..."], [1, "page-header"], [1, "header-left"], [1, "page-title"], [1, "page-subtitle"], [1, "header-actions"], ["title", "Refresh", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-refresh"], [1, "kpi-row"], [1, "kpi-card"], [1, "kpi-icon", 2, "background", "color-mix(in srgb, var(--mj-brand-primary) 10%, transparent)", "color", "var(--mj-brand-primary)"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-icon", 2, "background", "color-mix(in srgb, var(--mj-status-success) 10%, transparent)", "color", "var(--mj-status-success)"], [1, "fa-solid", "fa-circle-check"], [1, "kpi-icon", 2, "background", "color-mix(in srgb, var(--mj-status-error) 10%, transparent)", "color", "var(--mj-status-error)"], [1, "fa-solid", "fa-circle-xmark"], [1, "kpi-icon", 2, "background", "color-mix(in srgb, var(--mj-status-warning) 10%, transparent)", "color", "var(--mj-status-warning)"], [1, "fa-solid", "fa-circle-half-stroke"], [1, "filter-row"], [1, "filter-chip", 3, "click"], [1, "restore-list"], [1, "empty-state"], [1, "restore-card", 3, "ngClass"], [1, "restore-header", 3, "click"], [1, "restore-header-left"], [1, "status-icon", 3, "ngClass"], [1, "restore-info"], [1, "restore-label-name"], [1, "restore-date"], [1, "restore-header-right"], [1, "restore-progress-bar"], [1, "progress-fill", 3, "ngClass"], [1, "restore-count"], [1, "expand-icon", 3, "ngClass"], [1, "restore-details"], [1, "detail-grid"], [1, "detail-item"], [1, "detail-label"], [1, "detail-value", 3, "ngClass"], [1, "detail-value"], [1, "error-log"], [1, "detail-value", "detail-mono"], [1, "error-log-header"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "error-log-content"], [1, "fa-solid", "fa-clock-rotate-left", "empty-icon"]], template: function VersionHistoryRestoreResourceComponent_Template(rf, ctx) { if (rf & 1) {
452
452
  i0.ɵɵelementStart(0, "div", 0);
453
453
  i0.ɵɵconditionalCreate(1, VersionHistoryRestoreResourceComponent_Conditional_1_Template, 1, 0, "mj-loading", 1);
454
454
  i0.ɵɵconditionalCreate(2, VersionHistoryRestoreResourceComponent_Conditional_2_Template, 54, 12);
@@ -458,7 +458,7 @@ let VersionHistoryRestoreResourceComponent = class VersionHistoryRestoreResource
458
458
  i0.ɵɵconditional(ctx.IsLoading ? 1 : -1);
459
459
  i0.ɵɵadvance();
460
460
  i0.ɵɵconditional(!ctx.IsLoading ? 2 : -1);
461
- } }, dependencies: [i1.NgClass, i2.LoadingComponent, i1.SlicePipe], styles: [".restore-container[_ngcontent-%COMP%] {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n}\n\n\n\n.page-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left[_ngcontent-%COMP%] { flex: 1; }\n\n.page-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n margin: 0 0 4px 0;\n}\n\n.page-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] { display: flex; gap: 12px; }\n\n.btn-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--text-secondary, #6b7280);\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--hover-background, #f3f4f6);\n color: var(--text-primary, #1f2937);\n}\n\n\n\n.kpi-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 12px;\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n border-radius: 12px;\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n line-height: 1;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n margin-top: 4px;\n}\n\n\n\n.filter-row[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n}\n\n.filter-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 20px;\n cursor: pointer;\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n transition: all 0.2s ease;\n}\n\n.filter-chip[_ngcontent-%COMP%]:hover {\n background: var(--hover-background, #f3f4f6);\n}\n\n.filter-chip.active[_ngcontent-%COMP%] {\n background: #6366f1;\n border-color: #6366f1;\n color: #ffffff;\n}\n\n\n\n.restore-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.restore-card[_ngcontent-%COMP%] {\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 12px;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.restore-card[_ngcontent-%COMP%]:hover {\n border-color: var(--border-hover, #d1d5db);\n}\n\n.restore-card.expanded[_ngcontent-%COMP%] {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n}\n\n.restore-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n cursor: pointer;\n}\n\n.restore-header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.status-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n}\n\n.status-success[_ngcontent-%COMP%] { color: #10b981; }\n.status-failed[_ngcontent-%COMP%] { color: #ef4444; }\n.status-progress[_ngcontent-%COMP%] { color: #6366f1; }\n.status-pending[_ngcontent-%COMP%] { color: #f59e0b; }\n\n.restore-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.restore-label-name[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.dry-run-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 700;\n padding: 2px 8px;\n background: rgba(245, 158, 11, 0.1);\n color: #d97706;\n border-radius: 8px;\n letter-spacing: 0.5px;\n}\n\n.restore-date[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n}\n\n.restore-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.restore-progress-bar[_ngcontent-%COMP%] {\n width: 80px;\n height: 6px;\n background: var(--hover-background, #f3f4f6);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.progress-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s ease;\n}\n\n.progress-fill.status-success[_ngcontent-%COMP%] { background: #10b981; }\n.progress-fill.status-failed[_ngcontent-%COMP%] { background: #ef4444; }\n.progress-fill.status-progress[_ngcontent-%COMP%] { background: #6366f1; }\n.progress-fill.status-pending[_ngcontent-%COMP%] { background: #f59e0b; }\n\n.restore-count[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n white-space: nowrap;\n}\n\n.expand-icon[_ngcontent-%COMP%] {\n color: var(--text-tertiary, #9ca3af);\n font-size: 12px;\n}\n\n\n\n.restore-details[_ngcontent-%COMP%] {\n padding: 0 20px 20px;\n border-top: 1px solid var(--border-color, #e5e7eb);\n}\n\n.detail-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n padding-top: 16px;\n}\n\n.detail-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--text-secondary, #6b7280);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 15px;\n color: var(--text-primary, #1f2937);\n font-weight: 500;\n}\n\n.detail-mono[_ngcontent-%COMP%] {\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 13px;\n}\n\n.text-error[_ngcontent-%COMP%] {\n color: #ef4444;\n}\n\n\n\n.error-log[_ngcontent-%COMP%] {\n margin-top: 16px;\n border: 1px solid rgba(239, 68, 68, 0.2);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.error-log-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: rgba(239, 68, 68, 0.06);\n color: #dc2626;\n font-size: 13px;\n font-weight: 600;\n}\n\n.error-log-content[_ngcontent-%COMP%] {\n margin: 0;\n padding: 12px 14px;\n font-size: 12px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n color: var(--text-primary, #1f2937);\n background: var(--card-background, #ffffff);\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n color: var(--text-tertiary, #9ca3af);\n margin-bottom: 16px;\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n margin: 0 0 8px 0;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n max-width: 400px;\n}\n\n@media (max-width: 768px) {\n .kpi-row[_ngcontent-%COMP%] { grid-template-columns: repeat(2, 1fr); }\n}"], changeDetection: 0 });
461
+ } }, dependencies: [i1.NgClass, i2.LoadingComponent, i1.SlicePipe], styles: [".restore-container[_ngcontent-%COMP%] {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n}\n\n\n\n.page-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left[_ngcontent-%COMP%] { flex: 1; }\n\n.page-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.page-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] { display: flex; gap: 12px; }\n\n.btn-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--mj-text-secondary);\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n\n\n.kpi-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n border-radius: 12px;\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n}\n\n\n\n.filter-row[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n}\n\n.filter-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.filter-chip[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-chip.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n\n\n.restore-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.restore-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.restore-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.restore-card.expanded[_ngcontent-%COMP%] {\n box-shadow: var(--mj-shadow-md);\n}\n\n.restore-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n cursor: pointer;\n}\n\n.restore-header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.status-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n}\n\n.status-success[_ngcontent-%COMP%] { color: var(--mj-status-success); }\n.status-failed[_ngcontent-%COMP%] { color: var(--mj-status-error); }\n.status-progress[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n.status-pending[_ngcontent-%COMP%] { color: var(--mj-status-warning); }\n\n.restore-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.restore-label-name[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.dry-run-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 700;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-warning) 10%, transparent);\n color: var(--mj-status-warning);\n border-radius: 8px;\n letter-spacing: 0.5px;\n}\n\n.restore-date[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.restore-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.restore-progress-bar[_ngcontent-%COMP%] {\n width: 80px;\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.progress-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s ease;\n}\n\n.progress-fill.status-success[_ngcontent-%COMP%] { background: var(--mj-status-success); }\n.progress-fill.status-failed[_ngcontent-%COMP%] { background: var(--mj-status-error); }\n.progress-fill.status-progress[_ngcontent-%COMP%] { background: var(--mj-brand-primary); }\n.progress-fill.status-pending[_ngcontent-%COMP%] { background: var(--mj-status-warning); }\n\n.restore-count[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n.expand-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n\n\n.restore-details[_ngcontent-%COMP%] {\n padding: 0 20px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.detail-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n padding-top: 16px;\n}\n\n.detail-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 15px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.detail-mono[_ngcontent-%COMP%] {\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 13px;\n}\n\n.text-error[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.error-log[_ngcontent-%COMP%] {\n margin-top: 16px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, transparent);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.error-log-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: color-mix(in srgb, var(--mj-status-error) 6%, transparent);\n color: var(--mj-status-error);\n font-size: 13px;\n font-weight: 600;\n}\n\n.error-log-content[_ngcontent-%COMP%] {\n margin: 0;\n padding: 12px 14px;\n font-size: 12px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-card);\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 8px 0;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n max-width: 400px;\n}\n\n@media (max-width: 768px) {\n .kpi-row[_ngcontent-%COMP%] { grid-template-columns: repeat(2, 1fr); }\n}"], changeDetection: 0 });
462
462
  };
463
463
  VersionHistoryRestoreResourceComponent = VersionHistoryRestoreResourceComponent_1 = __decorate([
464
464
  RegisterClass(BaseResourceComponent, 'VersionHistoryRestoreResource')
@@ -466,7 +466,7 @@ VersionHistoryRestoreResourceComponent = VersionHistoryRestoreResourceComponent_
466
466
  export { VersionHistoryRestoreResourceComponent };
467
467
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(VersionHistoryRestoreResourceComponent, [{
468
468
  type: Component,
469
- args: [{ standalone: false, selector: 'mj-version-history-restore-resource', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"restore-container\">\n @if (IsLoading) {\n <mj-loading text=\"Loading restore history...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"page-header\">\n <div class=\"header-left\">\n <h2 class=\"page-title\">Restore History</h2>\n <p class=\"page-subtitle\">Track all restore operations and their outcomes</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-icon\" (click)=\"Refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- KPI Cards -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(99, 102, 241, 0.1); color: #6366f1;\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalRestores}}</div>\n <div class=\"kpi-label\">Total Restores</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(16, 185, 129, 0.1); color: #10b981;\">\n <i class=\"fa-solid fa-circle-check\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{SuccessfulRestores}}</div>\n <div class=\"kpi-label\">Successful</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(239, 68, 68, 0.1); color: #ef4444;\">\n <i class=\"fa-solid fa-circle-xmark\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FailedRestores}}</div>\n <div class=\"kpi-label\">Failed</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(245, 158, 11, 0.1); color: #f59e0b;\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{PartialRestores}}</div>\n <div class=\"kpi-label\">Partial</div>\n </div>\n </div>\n </div>\n <!-- Filters -->\n <div class=\"filter-row\">\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Complete'\"\n (click)=\"OnStatusFilterChange('Complete')\">\n <i class=\"fa-solid fa-circle-check\"></i> Complete\n </button>\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Error'\"\n (click)=\"OnStatusFilterChange('Error')\">\n <i class=\"fa-solid fa-circle-xmark\"></i> Error\n </button>\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Partial'\"\n (click)=\"OnStatusFilterChange('Partial')\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i> Partial\n </button>\n </div>\n <!-- Restore List -->\n @if (FilteredRestores.length > 0) {\n <div class=\"restore-list\">\n @for (restore of FilteredRestores; track restore) {\n <div class=\"restore-card\"\n [ngClass]=\"{'expanded': IsExpanded(restore.ID)}\">\n <div class=\"restore-header\" (click)=\"ToggleExpand(restore.ID)\">\n <div class=\"restore-header-left\">\n <i [class]=\"GetStatusIcon(restore.Status)\"\n [ngClass]=\"GetStatusClass(restore.Status)\"\n class=\"status-icon\"></i>\n <div class=\"restore-info\">\n <div class=\"restore-label-name\">\n {{restore.VersionLabel}}\n </div>\n @if (restore.StartedAt) {\n <div class=\"restore-date\">{{FormatDate(restore.StartedAt)}}</div>\n }\n </div>\n </div>\n <div class=\"restore-header-right\">\n <div class=\"restore-progress-bar\">\n <div class=\"progress-fill\"\n [ngClass]=\"GetStatusClass(restore.Status)\"\n [style.width.%]=\"GetProgressPercent(restore)\">\n </div>\n </div>\n <span class=\"restore-count\">\n {{restore.CompletedItems ?? 0}} / {{restore.TotalItems ?? 0}} items\n </span>\n <i class=\"fa-solid\"\n [ngClass]=\"IsExpanded(restore.ID) ? 'fa-chevron-up' : 'fa-chevron-down'\"\n class=\"expand-icon\">\n </i>\n </div>\n </div>\n <!-- Expanded Details -->\n @if (IsExpanded(restore.ID)) {\n <div class=\"restore-details\">\n <div class=\"detail-grid\">\n <div class=\"detail-item\">\n <span class=\"detail-label\">Status</span>\n <span class=\"detail-value\" [ngClass]=\"GetStatusClass(restore.Status)\">\n {{restore.Status}}\n </span>\n </div>\n <div class=\"detail-item\">\n <span class=\"detail-label\">Items Completed</span>\n <span class=\"detail-value\">{{restore.CompletedItems ?? 0}}</span>\n </div>\n <div class=\"detail-item\">\n <span class=\"detail-label\">Items Failed</span>\n <span class=\"detail-value\" [class.text-error]=\"(restore.FailedItems ?? 0) > 0\">\n {{restore.FailedItems ?? 0}}\n </span>\n </div>\n @if (restore.User) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Restored By</span>\n <span class=\"detail-value\">{{restore.User}}</span>\n </div>\n }\n @if (restore.PreRestoreLabelID) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Pre-Restore Label</span>\n @if (restore.PreRestoreLabel) {\n <span class=\"detail-value detail-mono\">\n {{restore.PreRestoreLabel}}\n </span>\n }\n @if (!restore.PreRestoreLabel) {\n <span class=\"detail-value detail-mono\">\n {{restore.PreRestoreLabelID | slice:0:20}}...\n </span>\n }\n </div>\n }\n </div>\n @if (restore.ErrorLog) {\n <div class=\"error-log\">\n <div class=\"error-log-header\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n Error Log\n </div>\n <pre class=\"error-log-content\">{{restore.ErrorLog}}</pre>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (FilteredRestores.length === 0 && !IsLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-clock-rotate-left empty-icon\"></i>\n <h3>No restore operations found</h3>\n @if (StatusFilter) {\n <p>\n Try adjusting your filters.\n </p>\n }\n @if (!StatusFilter) {\n <p>\n No restores have been performed yet. Use the VersionHistoryEngine to restore records to a labeled state.\n </p>\n }\n </div>\n }\n }\n</div>\n", styles: [".restore-container {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n}\n\n/* Header */\n.page-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left { flex: 1; }\n\n.page-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n margin: 0 0 4px 0;\n}\n\n.page-subtitle {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n.header-actions { display: flex; gap: 12px; }\n\n.btn-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--text-secondary, #6b7280);\n}\n\n.btn-icon:hover {\n background: var(--hover-background, #f3f4f6);\n color: var(--text-primary, #1f2937);\n}\n\n/* KPI Row */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 12px;\n}\n\n.kpi-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n border-radius: 12px;\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.kpi-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n line-height: 1;\n}\n\n.kpi-label {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n margin-top: 4px;\n}\n\n/* Filter Row */\n.filter-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n}\n\n.filter-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 20px;\n cursor: pointer;\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n transition: all 0.2s ease;\n}\n\n.filter-chip:hover {\n background: var(--hover-background, #f3f4f6);\n}\n\n.filter-chip.active {\n background: #6366f1;\n border-color: #6366f1;\n color: #ffffff;\n}\n\n/* Restore List */\n.restore-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.restore-card {\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 12px;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.restore-card:hover {\n border-color: var(--border-hover, #d1d5db);\n}\n\n.restore-card.expanded {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n}\n\n.restore-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n cursor: pointer;\n}\n\n.restore-header-left {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.status-icon {\n font-size: 20px;\n}\n\n.status-success { color: #10b981; }\n.status-failed { color: #ef4444; }\n.status-progress { color: #6366f1; }\n.status-pending { color: #f59e0b; }\n\n.restore-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.restore-label-name {\n font-size: 15px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.dry-run-badge {\n font-size: 10px;\n font-weight: 700;\n padding: 2px 8px;\n background: rgba(245, 158, 11, 0.1);\n color: #d97706;\n border-radius: 8px;\n letter-spacing: 0.5px;\n}\n\n.restore-date {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n}\n\n.restore-header-right {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.restore-progress-bar {\n width: 80px;\n height: 6px;\n background: var(--hover-background, #f3f4f6);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.progress-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s ease;\n}\n\n.progress-fill.status-success { background: #10b981; }\n.progress-fill.status-failed { background: #ef4444; }\n.progress-fill.status-progress { background: #6366f1; }\n.progress-fill.status-pending { background: #f59e0b; }\n\n.restore-count {\n font-size: 13px;\n color: var(--text-secondary, #6b7280);\n white-space: nowrap;\n}\n\n.expand-icon {\n color: var(--text-tertiary, #9ca3af);\n font-size: 12px;\n}\n\n/* Expanded Details */\n.restore-details {\n padding: 0 20px 20px;\n border-top: 1px solid var(--border-color, #e5e7eb);\n}\n\n.detail-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n padding-top: 16px;\n}\n\n.detail-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-label {\n font-size: 12px;\n font-weight: 600;\n color: var(--text-secondary, #6b7280);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.detail-value {\n font-size: 15px;\n color: var(--text-primary, #1f2937);\n font-weight: 500;\n}\n\n.detail-mono {\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 13px;\n}\n\n.text-error {\n color: #ef4444;\n}\n\n/* Error Log */\n.error-log {\n margin-top: 16px;\n border: 1px solid rgba(239, 68, 68, 0.2);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.error-log-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: rgba(239, 68, 68, 0.06);\n color: #dc2626;\n font-size: 13px;\n font-weight: 600;\n}\n\n.error-log-content {\n margin: 0;\n padding: 12px 14px;\n font-size: 12px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n color: var(--text-primary, #1f2937);\n background: var(--card-background, #ffffff);\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n}\n\n.empty-icon {\n font-size: 48px;\n color: var(--text-tertiary, #9ca3af);\n margin-bottom: 16px;\n}\n\n.empty-state h3 {\n font-size: 18px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n margin: 0 0 8px 0;\n}\n\n.empty-state p {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n max-width: 400px;\n}\n\n@media (max-width: 768px) {\n .kpi-row { grid-template-columns: repeat(2, 1fr); }\n}\n"] }]
469
+ args: [{ standalone: false, selector: 'mj-version-history-restore-resource', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"restore-container\">\n @if (IsLoading) {\n <mj-loading text=\"Loading restore history...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"page-header\">\n <div class=\"header-left\">\n <h2 class=\"page-title\">Restore History</h2>\n <p class=\"page-subtitle\">Track all restore operations and their outcomes</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-icon\" (click)=\"Refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- KPI Cards -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent); color: var(--mj-brand-primary);\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalRestores}}</div>\n <div class=\"kpi-label\">Total Restores</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-status-success) 10%, transparent); color: var(--mj-status-success);\">\n <i class=\"fa-solid fa-circle-check\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{SuccessfulRestores}}</div>\n <div class=\"kpi-label\">Successful</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-status-error) 10%, transparent); color: var(--mj-status-error);\">\n <i class=\"fa-solid fa-circle-xmark\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FailedRestores}}</div>\n <div class=\"kpi-label\">Failed</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-status-warning) 10%, transparent); color: var(--mj-status-warning);\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{PartialRestores}}</div>\n <div class=\"kpi-label\">Partial</div>\n </div>\n </div>\n </div>\n <!-- Filters -->\n <div class=\"filter-row\">\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Complete'\"\n (click)=\"OnStatusFilterChange('Complete')\">\n <i class=\"fa-solid fa-circle-check\"></i> Complete\n </button>\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Error'\"\n (click)=\"OnStatusFilterChange('Error')\">\n <i class=\"fa-solid fa-circle-xmark\"></i> Error\n </button>\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Partial'\"\n (click)=\"OnStatusFilterChange('Partial')\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i> Partial\n </button>\n </div>\n <!-- Restore List -->\n @if (FilteredRestores.length > 0) {\n <div class=\"restore-list\">\n @for (restore of FilteredRestores; track restore) {\n <div class=\"restore-card\"\n [ngClass]=\"{'expanded': IsExpanded(restore.ID)}\">\n <div class=\"restore-header\" (click)=\"ToggleExpand(restore.ID)\">\n <div class=\"restore-header-left\">\n <i [class]=\"GetStatusIcon(restore.Status)\"\n [ngClass]=\"GetStatusClass(restore.Status)\"\n class=\"status-icon\"></i>\n <div class=\"restore-info\">\n <div class=\"restore-label-name\">\n {{restore.VersionLabel}}\n </div>\n @if (restore.StartedAt) {\n <div class=\"restore-date\">{{FormatDate(restore.StartedAt)}}</div>\n }\n </div>\n </div>\n <div class=\"restore-header-right\">\n <div class=\"restore-progress-bar\">\n <div class=\"progress-fill\"\n [ngClass]=\"GetStatusClass(restore.Status)\"\n [style.width.%]=\"GetProgressPercent(restore)\">\n </div>\n </div>\n <span class=\"restore-count\">\n {{restore.CompletedItems ?? 0}} / {{restore.TotalItems ?? 0}} items\n </span>\n <i class=\"fa-solid\"\n [ngClass]=\"IsExpanded(restore.ID) ? 'fa-chevron-up' : 'fa-chevron-down'\"\n class=\"expand-icon\">\n </i>\n </div>\n </div>\n <!-- Expanded Details -->\n @if (IsExpanded(restore.ID)) {\n <div class=\"restore-details\">\n <div class=\"detail-grid\">\n <div class=\"detail-item\">\n <span class=\"detail-label\">Status</span>\n <span class=\"detail-value\" [ngClass]=\"GetStatusClass(restore.Status)\">\n {{restore.Status}}\n </span>\n </div>\n <div class=\"detail-item\">\n <span class=\"detail-label\">Items Completed</span>\n <span class=\"detail-value\">{{restore.CompletedItems ?? 0}}</span>\n </div>\n <div class=\"detail-item\">\n <span class=\"detail-label\">Items Failed</span>\n <span class=\"detail-value\" [class.text-error]=\"(restore.FailedItems ?? 0) > 0\">\n {{restore.FailedItems ?? 0}}\n </span>\n </div>\n @if (restore.User) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Restored By</span>\n <span class=\"detail-value\">{{restore.User}}</span>\n </div>\n }\n @if (restore.PreRestoreLabelID) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Pre-Restore Label</span>\n @if (restore.PreRestoreLabel) {\n <span class=\"detail-value detail-mono\">\n {{restore.PreRestoreLabel}}\n </span>\n }\n @if (!restore.PreRestoreLabel) {\n <span class=\"detail-value detail-mono\">\n {{restore.PreRestoreLabelID | slice:0:20}}...\n </span>\n }\n </div>\n }\n </div>\n @if (restore.ErrorLog) {\n <div class=\"error-log\">\n <div class=\"error-log-header\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n Error Log\n </div>\n <pre class=\"error-log-content\">{{restore.ErrorLog}}</pre>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (FilteredRestores.length === 0 && !IsLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-clock-rotate-left empty-icon\"></i>\n <h3>No restore operations found</h3>\n @if (StatusFilter) {\n <p>\n Try adjusting your filters.\n </p>\n }\n @if (!StatusFilter) {\n <p>\n No restores have been performed yet. Use the VersionHistoryEngine to restore records to a labeled state.\n </p>\n }\n </div>\n }\n }\n</div>\n", styles: [".restore-container {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n}\n\n/* Header */\n.page-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left { flex: 1; }\n\n.page-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.page-subtitle {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions { display: flex; gap: 12px; }\n\n.btn-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--mj-text-secondary);\n}\n\n.btn-icon:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n/* KPI Row */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n}\n\n.kpi-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n border-radius: 12px;\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.kpi-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1;\n}\n\n.kpi-label {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n}\n\n/* Filter Row */\n.filter-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n}\n\n.filter-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.filter-chip:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-chip.active {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n/* Restore List */\n.restore-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.restore-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.restore-card:hover {\n border-color: var(--mj-border-strong);\n}\n\n.restore-card.expanded {\n box-shadow: var(--mj-shadow-md);\n}\n\n.restore-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n cursor: pointer;\n}\n\n.restore-header-left {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.status-icon {\n font-size: 20px;\n}\n\n.status-success { color: var(--mj-status-success); }\n.status-failed { color: var(--mj-status-error); }\n.status-progress { color: var(--mj-brand-primary); }\n.status-pending { color: var(--mj-status-warning); }\n\n.restore-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.restore-label-name {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.dry-run-badge {\n font-size: 10px;\n font-weight: 700;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-warning) 10%, transparent);\n color: var(--mj-status-warning);\n border-radius: 8px;\n letter-spacing: 0.5px;\n}\n\n.restore-date {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.restore-header-right {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.restore-progress-bar {\n width: 80px;\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.progress-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s ease;\n}\n\n.progress-fill.status-success { background: var(--mj-status-success); }\n.progress-fill.status-failed { background: var(--mj-status-error); }\n.progress-fill.status-progress { background: var(--mj-brand-primary); }\n.progress-fill.status-pending { background: var(--mj-status-warning); }\n\n.restore-count {\n font-size: 13px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n.expand-icon {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n/* Expanded Details */\n.restore-details {\n padding: 0 20px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.detail-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n padding-top: 16px;\n}\n\n.detail-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-label {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.detail-value {\n font-size: 15px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.detail-mono {\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 13px;\n}\n\n.text-error {\n color: var(--mj-status-error);\n}\n\n/* Error Log */\n.error-log {\n margin-top: 16px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, transparent);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.error-log-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: color-mix(in srgb, var(--mj-status-error) 6%, transparent);\n color: var(--mj-status-error);\n font-size: 13px;\n font-weight: 600;\n}\n\n.error-log-content {\n margin: 0;\n padding: 12px 14px;\n font-size: 12px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-card);\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n}\n\n.empty-icon {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n}\n\n.empty-state h3 {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 8px 0;\n}\n\n.empty-state p {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n max-width: 400px;\n}\n\n@media (max-width: 768px) {\n .kpi-row { grid-template-columns: repeat(2, 1fr); }\n}\n"] }]
470
470
  }], () => [{ type: i0.ChangeDetectorRef }], null); })();
471
471
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(VersionHistoryRestoreResourceComponent, { className: "VersionHistoryRestoreResourceComponent", filePath: "src/VersionHistory/components/restore-resource.component.ts", lineNumber: 19 }); })();
472
472
  //# sourceMappingURL=restore-resource.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"restore-resource.component.js","sourceRoot":"","sources":["../../../src/VersionHistory/components/restore-resource.component.ts","../../../src/VersionHistory/components/restore-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RunView } from '@memberjunction/core';\nimport { ResourceData, UserInfoEngine, MJVersionLabelRestoreEntityType } from '@memberjunction/core-entities';\n\ninterface VersionRestorePreferences {\n StatusFilter: string;\n}\n@RegisterClass(BaseResourceComponent, 'VersionHistoryRestoreResource')\n@Component({\n standalone: false,\n selector: 'mj-version-history-restore-resource',\n templateUrl: './restore-resource.component.html',\n styleUrls: ['./restore-resource.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class VersionHistoryRestoreResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public IsLoading = true;\n\n // Stats\n public TotalRestores = 0;\n public SuccessfulRestores = 0;\n public FailedRestores = 0;\n public PartialRestores = 0;\n\n // Data\n public Restores: MJVersionLabelRestoreEntityType[] = [];\n public FilteredRestores: MJVersionLabelRestoreEntityType[] = [];\n\n // Filters\n public StatusFilter = '';\n\n // Expanded detail\n public ExpandedRestoreId = '';\n\n private static readonly PREFS_KEY = 'VersionHistory.Restore.UserPreferences';\n private preferencesLoaded = false;\n private destroy$ = new Subject<void>();\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n ngOnInit(): void {\n this.loadUserPreferences();\n this.LoadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Restore History';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-clock-rotate-left';\n }\n\n public async LoadData(): Promise<void> {\n try {\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n const rv = new RunView();\n const result = await rv.RunView<MJVersionLabelRestoreEntityType>({\n EntityName: 'MJ: Version Label Restores',\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 200,\n ResultType: 'simple'\n });\n\n if (result.Success) {\n this.Restores = result.Results;\n this.computeStats();\n this.applyFilters();\n }\n } catch (error) {\n console.error('Error loading restore history:', error);\n } finally {\n this.IsLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n private computeStats(): void {\n this.TotalRestores = this.Restores.length;\n this.SuccessfulRestores = this.Restores.filter(r => r.Status === 'Complete').length;\n this.FailedRestores = this.Restores.filter(r => r.Status === 'Error').length;\n this.PartialRestores = this.Restores.filter(r => r.Status === 'Partial').length;\n }\n\n public applyFilters(): void {\n this.FilteredRestores = this.Restores.filter(r => {\n if (this.StatusFilter && r.Status !== this.StatusFilter) return false;\n return true;\n });\n this.cdr.markForCheck();\n }\n\n public OnStatusFilterChange(status: string): void {\n this.StatusFilter = this.StatusFilter === status ? '' : status;\n this.applyFilters();\n this.persistPreferences();\n }\n\n private loadUserPreferences(): void {\n try {\n const raw = UserInfoEngine.Instance.GetSetting(VersionHistoryRestoreResourceComponent.PREFS_KEY);\n if (raw) {\n const prefs: VersionRestorePreferences = JSON.parse(raw);\n if (prefs.StatusFilter != null) {\n this.StatusFilter = prefs.StatusFilter;\n }\n }\n } catch (error) {\n console.error('Error loading restore preferences:', error);\n this.StatusFilter = '';\n }\n this.preferencesLoaded = true;\n }\n\n private persistPreferences(): void {\n if (!this.preferencesLoaded) return;\n const prefs: VersionRestorePreferences = {\n StatusFilter: this.StatusFilter\n };\n UserInfoEngine.Instance.SetSettingDebounced(VersionHistoryRestoreResourceComponent.PREFS_KEY, JSON.stringify(prefs));\n }\n\n public ToggleExpand(restoreId: string | undefined): void {\n const id = restoreId ?? '';\n this.ExpandedRestoreId = this.ExpandedRestoreId === id ? '' : id;\n this.cdr.markForCheck();\n }\n\n public IsExpanded(restoreId: string | undefined): boolean {\n return this.ExpandedRestoreId === (restoreId ?? '');\n }\n\n public GetStatusClass(status: string | undefined): string {\n const classes: Record<string, string> = {\n 'Complete': 'status-success',\n 'Error': 'status-failed',\n 'In Progress': 'status-progress',\n 'Pending': 'status-pending',\n 'Partial': 'status-partial'\n };\n return classes[status ?? ''] ?? '';\n }\n\n public GetStatusIcon(status: string | undefined): string {\n const icons: Record<string, string> = {\n 'Complete': 'fa-solid fa-circle-check',\n 'Error': 'fa-solid fa-circle-xmark',\n 'In Progress': 'fa-solid fa-spinner fa-spin',\n 'Pending': 'fa-solid fa-clock',\n 'Partial': 'fa-solid fa-circle-half-stroke'\n };\n return icons[status ?? ''] ?? 'fa-solid fa-circle';\n }\n\n public GetProgressPercent(restore: MJVersionLabelRestoreEntityType): number {\n if (!restore.TotalItems) return 0;\n return Math.round(((restore.CompletedItems ?? 0) / restore.TotalItems) * 100);\n }\n\n public FormatDate(date: Date | string | undefined): string {\n if (!date) return '';\n const d = date instanceof Date ? date : new Date(date);\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n }\n\n public Refresh(): void {\n this.LoadData();\n }\n}\n","<div class=\"restore-container\">\n @if (IsLoading) {\n <mj-loading text=\"Loading restore history...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"page-header\">\n <div class=\"header-left\">\n <h2 class=\"page-title\">Restore History</h2>\n <p class=\"page-subtitle\">Track all restore operations and their outcomes</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-icon\" (click)=\"Refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- KPI Cards -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(99, 102, 241, 0.1); color: #6366f1;\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalRestores}}</div>\n <div class=\"kpi-label\">Total Restores</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(16, 185, 129, 0.1); color: #10b981;\">\n <i class=\"fa-solid fa-circle-check\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{SuccessfulRestores}}</div>\n <div class=\"kpi-label\">Successful</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(239, 68, 68, 0.1); color: #ef4444;\">\n <i class=\"fa-solid fa-circle-xmark\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FailedRestores}}</div>\n <div class=\"kpi-label\">Failed</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: rgba(245, 158, 11, 0.1); color: #f59e0b;\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{PartialRestores}}</div>\n <div class=\"kpi-label\">Partial</div>\n </div>\n </div>\n </div>\n <!-- Filters -->\n <div class=\"filter-row\">\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Complete'\"\n (click)=\"OnStatusFilterChange('Complete')\">\n <i class=\"fa-solid fa-circle-check\"></i> Complete\n </button>\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Error'\"\n (click)=\"OnStatusFilterChange('Error')\">\n <i class=\"fa-solid fa-circle-xmark\"></i> Error\n </button>\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Partial'\"\n (click)=\"OnStatusFilterChange('Partial')\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i> Partial\n </button>\n </div>\n <!-- Restore List -->\n @if (FilteredRestores.length > 0) {\n <div class=\"restore-list\">\n @for (restore of FilteredRestores; track restore) {\n <div class=\"restore-card\"\n [ngClass]=\"{'expanded': IsExpanded(restore.ID)}\">\n <div class=\"restore-header\" (click)=\"ToggleExpand(restore.ID)\">\n <div class=\"restore-header-left\">\n <i [class]=\"GetStatusIcon(restore.Status)\"\n [ngClass]=\"GetStatusClass(restore.Status)\"\n class=\"status-icon\"></i>\n <div class=\"restore-info\">\n <div class=\"restore-label-name\">\n {{restore.VersionLabel}}\n </div>\n @if (restore.StartedAt) {\n <div class=\"restore-date\">{{FormatDate(restore.StartedAt)}}</div>\n }\n </div>\n </div>\n <div class=\"restore-header-right\">\n <div class=\"restore-progress-bar\">\n <div class=\"progress-fill\"\n [ngClass]=\"GetStatusClass(restore.Status)\"\n [style.width.%]=\"GetProgressPercent(restore)\">\n </div>\n </div>\n <span class=\"restore-count\">\n {{restore.CompletedItems ?? 0}} / {{restore.TotalItems ?? 0}} items\n </span>\n <i class=\"fa-solid\"\n [ngClass]=\"IsExpanded(restore.ID) ? 'fa-chevron-up' : 'fa-chevron-down'\"\n class=\"expand-icon\">\n </i>\n </div>\n </div>\n <!-- Expanded Details -->\n @if (IsExpanded(restore.ID)) {\n <div class=\"restore-details\">\n <div class=\"detail-grid\">\n <div class=\"detail-item\">\n <span class=\"detail-label\">Status</span>\n <span class=\"detail-value\" [ngClass]=\"GetStatusClass(restore.Status)\">\n {{restore.Status}}\n </span>\n </div>\n <div class=\"detail-item\">\n <span class=\"detail-label\">Items Completed</span>\n <span class=\"detail-value\">{{restore.CompletedItems ?? 0}}</span>\n </div>\n <div class=\"detail-item\">\n <span class=\"detail-label\">Items Failed</span>\n <span class=\"detail-value\" [class.text-error]=\"(restore.FailedItems ?? 0) > 0\">\n {{restore.FailedItems ?? 0}}\n </span>\n </div>\n @if (restore.User) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Restored By</span>\n <span class=\"detail-value\">{{restore.User}}</span>\n </div>\n }\n @if (restore.PreRestoreLabelID) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Pre-Restore Label</span>\n @if (restore.PreRestoreLabel) {\n <span class=\"detail-value detail-mono\">\n {{restore.PreRestoreLabel}}\n </span>\n }\n @if (!restore.PreRestoreLabel) {\n <span class=\"detail-value detail-mono\">\n {{restore.PreRestoreLabelID | slice:0:20}}...\n </span>\n }\n </div>\n }\n </div>\n @if (restore.ErrorLog) {\n <div class=\"error-log\">\n <div class=\"error-log-header\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n Error Log\n </div>\n <pre class=\"error-log-content\">{{restore.ErrorLog}}</pre>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (FilteredRestores.length === 0 && !IsLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-clock-rotate-left empty-icon\"></i>\n <h3>No restore operations found</h3>\n @if (StatusFilter) {\n <p>\n Try adjusting your filters.\n </p>\n }\n @if (!StatusFilter) {\n <p>\n No restores have been performed yet. Use the VersionHistoryEngine to restore records to a labeled state.\n </p>\n }\n </div>\n }\n }\n</div>\n"]}
1
+ {"version":3,"file":"restore-resource.component.js","sourceRoot":"","sources":["../../../src/VersionHistory/components/restore-resource.component.ts","../../../src/VersionHistory/components/restore-resource.component.html"],"names":[],"mappings":";;;;;;;AAAA,OAAO,EAAE,SAAS,EAAwC,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAgB,cAAc,EAAmC,MAAM,+BAA+B,CAAC;;;;;;ICH1G,gCAA2D;;;IAyF3C,+BAA0B;IAAA,YAAiC;IAAA,iBAAM;;;;IAAvC,cAAiC;IAAjC,6DAAiC;;;IA0CzD,AADF,+BAAyB,eACI;IAAA,2BAAW;IAAA,iBAAO;IAC7C,gCAA2B;IAAA,YAAgB;IAC7C,AAD6C,iBAAO,EAC9C;;;IADuB,eAAgB;IAAhB,qCAAgB;;;IAOzC,gCAAuC;IACrC,YACF;IAAA,iBAAO;;;IADL,cACF;IADE,2DACF;;;IAGA,gCAAuC;IACrC,YACF;;IAAA,iBAAO;;;IADL,cACF;IADE,6FACF;;;IATF,AADF,+BAAyB,eACI;IAAA,iCAAiB;IAAA,iBAAO;IACnD,2KAA+B;IAK/B,2KAAgC;IAKlC,iBAAM;;;IAVJ,eAIC;IAJD,qDAIC;IACD,cAIC;IAJD,sDAIC;;;IAMH,AADF,+BAAuB,cACS;IAC5B,wBAAgD;IAChD,2BACF;IAAA,iBAAM;IACN,+BAA+B;IAAA,YAAoB;IACrD,AADqD,iBAAM,EACrD;;;IAD2B,eAAoB;IAApB,yCAAoB;;;IA3CnD,AADF,AADF,AADF,+BAA6B,cACF,cACE,eACI;IAAA,sBAAM;IAAA,iBAAO;IACxC,gCAAsE;IACpE,YACF;IACF,AADE,iBAAO,EACH;IAEJ,AADF,+BAAyB,eACI;IAAA,+BAAe;IAAA,iBAAO;IACjD,iCAA2B;IAAA,aAA+B;IAC5D,AAD4D,iBAAO,EAC7D;IAEJ,AADF,gCAAyB,gBACI;IAAA,6BAAY;IAAA,iBAAO;IAC9C,iCAA+E;IAC7E,aACF;IACF,AADE,iBAAO,EACH;IACN,6JAAoB;IAMpB,6JAAiC;IAenC,iBAAM;IACN,6JAAwB;IAS1B,iBAAM;;;;IA7C2B,eAA0C;IAA1C,kEAA0C;IACnE,cACF;IADE,kDACF;IAI2B,eAA+B;IAA/B,oDAA+B;IAI/B,eAAmD;IAAnD,+DAAmD;IAC5E,cACF;IADE,4DACF;IAEF,cAKC;IALD,2CAKC;IACD,cAcC;IAdD,wDAcC;IAEH,cAQC;IARD,+CAQC;;;;IAhFL,AAFF,+BACmD,cACc;IAAnC,0PAAS,kCAAwB,KAAC;IAC5D,+BAAiC;IAC/B,wBAEwB;IAEtB,AADF,+BAA0B,cACQ;IAC9B,YACF;IAAA,iBAAM;IACN,4IAAyB;IAI7B,AADE,iBAAM,EACF;IAEJ,AADF,+BAAkC,cACE;IAChC,2BAGM;IACR,iBAAM;IACN,iCAA4B;IAC1B,aACF;IAAA,iBAAO;IACP,yBAGI;IAER,AADE,iBAAM,EACF;IAEN,+IAA8B;IAoDhC,iBAAM;;;;IApFJ,uFAAgD;IAGzC,eAAuC;IAAvC,sDAAuC;IACxC,kEAA0C;IAIxC,eACF;IADE,wDACF;IACA,cAEC;IAFD,+CAEC;IAOC,eAA6C;IAA7C,mEAA6C;IAD7C,kEAA0C;IAK5C,eACF;IADE,wGACF;IAEE,cAAwE;IAAxE,gGAAwE;IAM9E,cAmDC;IAnDD,4DAmDC;;;IAtFP,+BAA0B;IACxB,2JAuFC;IACH,iBAAM;;;IAxFJ,cAuFC;IAvFD,sCAuFC;;;IASC,yBAAG;IACD,6CACF;IAAA,iBAAI;;;IAGJ,yBAAG;IACD,0HACF;IAAA,iBAAI;;;IAXR,+BAAyB;IACvB,wBAAwD;IACxD,0BAAI;IAAA,2CAA2B;IAAA,iBAAK;IACpC,gIAAoB;IAKpB,gIAAqB;IAKvB,iBAAM;;;IAVJ,eAIC;IAJD,8CAIC;IACD,cAIC;IAJD,+CAIC;;;;IA7KD,AADF,AADF,8BAAyB,aACE,YACA;IAAA,+BAAe;IAAA,iBAAK;IAC3C,4BAAyB;IAAA,+DAA+C;IAC1E,AAD0E,iBAAI,EACxE;IAEJ,AADF,8BAA4B,gBACmC;IAApC,0MAAS,gBAAS,KAAC;IAC1C,uBAAmC;IAGzC,AADE,AADE,iBAAS,EACL,EACF;IAIF,AADF,AADF,8BAAqB,eACG,eACoH;IACtI,yBAA6C;IAC/C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAiB;IAAA,iBAAM;IAC9C,gCAAuB;IAAA,+BAAc;IAEzC,AADE,AADuC,iBAAM,EACvC,EACF;IAEJ,AADF,gCAAsB,eACsH;IACxI,yBAAwC;IAC1C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAsB;IAAA,iBAAM;IACnD,gCAAuB;IAAA,2BAAU;IAErC,AADE,AADmC,iBAAM,EACnC,EACF;IAEJ,AADF,gCAAsB,eACkH;IACpI,yBAAwC;IAC1C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAkB;IAAA,iBAAM;IAC/C,gCAAuB;IAAA,uBAAM;IAEjC,AADE,AAD+B,iBAAM,EAC/B,EACF;IAEJ,AADF,gCAAsB,eACsH;IACxI,yBAA8C;IAChD,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAmB;IAAA,iBAAM;IAChD,gCAAuB;IAAA,wBAAO;IAGpC,AADE,AADE,AADgC,iBAAM,EAChC,EACF,EACF;IAGJ,AADF,gCAAwB,kBAGuB;IAA3C,2MAAS,4BAAqB,UAAU,CAAC,KAAC;IAC1C,yBAAwC;IAAC,2BAC3C;IAAA,iBAAS;IACT,mCAE0C;IAAxC,2MAAS,4BAAqB,OAAO,CAAC,KAAC;IACvC,yBAAwC;IAAC,wBAC3C;IAAA,iBAAS;IACT,mCAE4C;IAA1C,2MAAS,4BAAqB,SAAS,CAAC,KAAC;IACzC,yBAA8C;IAAC,0BACjD;IACF,AADE,iBAAS,EACL;IAEN,yHAAmC;IA6FnC,yHAAmD;;;IAhJtB,gBAAiB;IAAjB,0CAAiB;IASjB,eAAsB;IAAtB,+CAAsB;IAStB,eAAkB;IAAlB,2CAAkB;IASlB,eAAmB;IAAnB,4CAAmB;IAQ5C,eAA4C;IAA5C,4DAA4C;IAK5C,eAAyC;IAAzC,yDAAyC;IAKzC,eAA2C;IAA3C,2DAA2C;IAM/C,eA2FC;IA3FD,8DA2FC;IAED,cAeC;IAfD,qFAeC;;ADtKE,IAAM,sCAAsC,GAA5C,MAAM,sCAAuC,SAAQ,qBAAqB;;IAuBzD;IAtBb,SAAS,GAAG,IAAI,CAAC;IAExB,QAAQ;IACD,aAAa,GAAG,CAAC,CAAC;IAClB,kBAAkB,GAAG,CAAC,CAAC;IACvB,cAAc,GAAG,CAAC,CAAC;IACnB,eAAe,GAAG,CAAC,CAAC;IAE3B,OAAO;IACA,QAAQ,GAAsC,EAAE,CAAC;IACjD,gBAAgB,GAAsC,EAAE,CAAC;IAEhE,UAAU;IACH,YAAY,GAAG,EAAE,CAAC;IAEzB,kBAAkB;IACX,iBAAiB,GAAG,EAAE,CAAC;IAEtB,MAAM,CAAU,SAAS,GAAG,wCAAwC,CAAC;IACrE,iBAAiB,GAAG,KAAK,CAAC;IAC1B,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAEvC,YAAoB,GAAsB;QACtC,KAAK,EAAE,CAAC;QADQ,QAAG,GAAH,GAAG,CAAmB;IAE1C,CAAC;IAED,QAAQ;QACJ,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,QAAQ,EAAE,CAAC;IACpB,CAAC;IAED,WAAW;QACP,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,IAAkB;QAC3C,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,IAAkB;QACzC,OAAO,+BAA+B,CAAC;IAC3C,CAAC;IAEM,KAAK,CAAC,QAAQ;QACjB,IAAI,CAAC;YACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAExB,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAkC;gBAC7D,UAAU,EAAE,4BAA4B;gBACxC,OAAO,EAAE,qBAAqB;gBAC9B,OAAO,EAAE,GAAG;gBACZ,UAAU,EAAE,QAAQ;aACvB,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;gBAC/B,IAAI,CAAC,YAAY,EAAE,CAAC;gBACpB,IAAI,CAAC,YAAY,EAAE,CAAC;YACxB,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;QAC3D,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;IACL,CAAC;IAEO,YAAY;QAChB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC1C,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;QACpF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;QAC7E,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IACpF,CAAC;IAEM,YAAY;QACf,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAC7C,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,YAAY;gBAAE,OAAO,KAAK,CAAC;YACtE,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEM,oBAAoB,CAAC,MAAc;QACtC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/D,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC9B,CAAC;IAEO,mBAAmB;QACvB,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,wCAAsC,CAAC,SAAS,CAAC,CAAC;YACjG,IAAI,GAAG,EAAE,CAAC;gBACN,MAAM,KAAK,GAA8B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACzD,IAAI,KAAK,CAAC,YAAY,IAAI,IAAI,EAAE,CAAC;oBAC7B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;gBAC3C,CAAC;YACL,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;YAC3D,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAClC,CAAC;IAEO,kBAAkB;QACtB,IAAI,CAAC,IAAI,CAAC,iBAAiB;YAAE,OAAO;QACpC,MAAM,KAAK,GAA8B;YACrC,YAAY,EAAE,IAAI,CAAC,YAAY;SAClC,CAAC;QACF,cAAc,CAAC,QAAQ,CAAC,mBAAmB,CAAC,wCAAsC,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACzH,CAAC;IAEM,YAAY,CAAC,SAA6B;QAC7C,MAAM,EAAE,GAAG,SAAS,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEM,UAAU,CAAC,SAA6B;QAC3C,OAAO,IAAI,CAAC,iBAAiB,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAEM,cAAc,CAAC,MAA0B;QAC5C,MAAM,OAAO,GAA2B;YACpC,UAAU,EAAE,gBAAgB;YAC5B,OAAO,EAAE,eAAe;YACxB,aAAa,EAAE,iBAAiB;YAChC,SAAS,EAAE,gBAAgB;YAC3B,SAAS,EAAE,gBAAgB;SAC9B,CAAC;QACF,OAAO,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IACvC,CAAC;IAEM,aAAa,CAAC,MAA0B;QAC3C,MAAM,KAAK,GAA2B;YAClC,UAAU,EAAE,0BAA0B;YACtC,OAAO,EAAE,0BAA0B;YACnC,aAAa,EAAE,6BAA6B;YAC5C,SAAS,EAAE,mBAAmB;YAC9B,SAAS,EAAE,gCAAgC;SAC9C,CAAC;QACF,OAAO,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,oBAAoB,CAAC;IACvD,CAAC;IAEM,kBAAkB,CAAC,OAAwC;QAC9D,IAAI,CAAC,OAAO,CAAC,UAAU;YAAE,OAAO,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC;IAClF,CAAC;IAEM,UAAU,CAAC,IAA+B;QAC7C,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;YACjC,KAAK,EAAE,OAAO;YACd,GAAG,EAAE,SAAS;YACd,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,SAAS;SACpB,CAAC,CAAC;IACP,CAAC;IAEM,OAAO;QACV,IAAI,CAAC,QAAQ,EAAE,CAAC;IACpB,CAAC;gIAxKQ,sCAAsC;6DAAtC,sCAAsC;YClBnD,8BAA+B;YAC7B,+GAAiB;YAIjB,gGAAkB;YAqLpB,iBAAM;;YAzLJ,cAEC;YAFD,wCAEC;YAED,cAoLC;YApLD,yCAoLC;;;ADvKU,sCAAsC;IARlD,aAAa,CAAC,qBAAqB,EAAE,+BAA+B,CAAC;GAQzD,sCAAsC,CAyKlD;;iFAzKY,sCAAsC;cAPlD,SAAS;6BACI,KAAK,YACL,qCAAqC,mBAG9B,uBAAuB,CAAC,MAAM;;kFAEtC,sCAAsC","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RunView } from '@memberjunction/core';\nimport { ResourceData, UserInfoEngine, MJVersionLabelRestoreEntityType } from '@memberjunction/core-entities';\n\ninterface VersionRestorePreferences {\n StatusFilter: string;\n}\n@RegisterClass(BaseResourceComponent, 'VersionHistoryRestoreResource')\n@Component({\n standalone: false,\n selector: 'mj-version-history-restore-resource',\n templateUrl: './restore-resource.component.html',\n styleUrls: ['./restore-resource.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class VersionHistoryRestoreResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public IsLoading = true;\n\n // Stats\n public TotalRestores = 0;\n public SuccessfulRestores = 0;\n public FailedRestores = 0;\n public PartialRestores = 0;\n\n // Data\n public Restores: MJVersionLabelRestoreEntityType[] = [];\n public FilteredRestores: MJVersionLabelRestoreEntityType[] = [];\n\n // Filters\n public StatusFilter = '';\n\n // Expanded detail\n public ExpandedRestoreId = '';\n\n private static readonly PREFS_KEY = 'VersionHistory.Restore.UserPreferences';\n private preferencesLoaded = false;\n private destroy$ = new Subject<void>();\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n ngOnInit(): void {\n this.loadUserPreferences();\n this.LoadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Restore History';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-clock-rotate-left';\n }\n\n public async LoadData(): Promise<void> {\n try {\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n const rv = new RunView();\n const result = await rv.RunView<MJVersionLabelRestoreEntityType>({\n EntityName: 'MJ: Version Label Restores',\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 200,\n ResultType: 'simple'\n });\n\n if (result.Success) {\n this.Restores = result.Results;\n this.computeStats();\n this.applyFilters();\n }\n } catch (error) {\n console.error('Error loading restore history:', error);\n } finally {\n this.IsLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n private computeStats(): void {\n this.TotalRestores = this.Restores.length;\n this.SuccessfulRestores = this.Restores.filter(r => r.Status === 'Complete').length;\n this.FailedRestores = this.Restores.filter(r => r.Status === 'Error').length;\n this.PartialRestores = this.Restores.filter(r => r.Status === 'Partial').length;\n }\n\n public applyFilters(): void {\n this.FilteredRestores = this.Restores.filter(r => {\n if (this.StatusFilter && r.Status !== this.StatusFilter) return false;\n return true;\n });\n this.cdr.markForCheck();\n }\n\n public OnStatusFilterChange(status: string): void {\n this.StatusFilter = this.StatusFilter === status ? '' : status;\n this.applyFilters();\n this.persistPreferences();\n }\n\n private loadUserPreferences(): void {\n try {\n const raw = UserInfoEngine.Instance.GetSetting(VersionHistoryRestoreResourceComponent.PREFS_KEY);\n if (raw) {\n const prefs: VersionRestorePreferences = JSON.parse(raw);\n if (prefs.StatusFilter != null) {\n this.StatusFilter = prefs.StatusFilter;\n }\n }\n } catch (error) {\n console.error('Error loading restore preferences:', error);\n this.StatusFilter = '';\n }\n this.preferencesLoaded = true;\n }\n\n private persistPreferences(): void {\n if (!this.preferencesLoaded) return;\n const prefs: VersionRestorePreferences = {\n StatusFilter: this.StatusFilter\n };\n UserInfoEngine.Instance.SetSettingDebounced(VersionHistoryRestoreResourceComponent.PREFS_KEY, JSON.stringify(prefs));\n }\n\n public ToggleExpand(restoreId: string | undefined): void {\n const id = restoreId ?? '';\n this.ExpandedRestoreId = this.ExpandedRestoreId === id ? '' : id;\n this.cdr.markForCheck();\n }\n\n public IsExpanded(restoreId: string | undefined): boolean {\n return this.ExpandedRestoreId === (restoreId ?? '');\n }\n\n public GetStatusClass(status: string | undefined): string {\n const classes: Record<string, string> = {\n 'Complete': 'status-success',\n 'Error': 'status-failed',\n 'In Progress': 'status-progress',\n 'Pending': 'status-pending',\n 'Partial': 'status-partial'\n };\n return classes[status ?? ''] ?? '';\n }\n\n public GetStatusIcon(status: string | undefined): string {\n const icons: Record<string, string> = {\n 'Complete': 'fa-solid fa-circle-check',\n 'Error': 'fa-solid fa-circle-xmark',\n 'In Progress': 'fa-solid fa-spinner fa-spin',\n 'Pending': 'fa-solid fa-clock',\n 'Partial': 'fa-solid fa-circle-half-stroke'\n };\n return icons[status ?? ''] ?? 'fa-solid fa-circle';\n }\n\n public GetProgressPercent(restore: MJVersionLabelRestoreEntityType): number {\n if (!restore.TotalItems) return 0;\n return Math.round(((restore.CompletedItems ?? 0) / restore.TotalItems) * 100);\n }\n\n public FormatDate(date: Date | string | undefined): string {\n if (!date) return '';\n const d = date instanceof Date ? date : new Date(date);\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n }\n\n public Refresh(): void {\n this.LoadData();\n }\n}\n","<div class=\"restore-container\">\n @if (IsLoading) {\n <mj-loading text=\"Loading restore history...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"page-header\">\n <div class=\"header-left\">\n <h2 class=\"page-title\">Restore History</h2>\n <p class=\"page-subtitle\">Track all restore operations and their outcomes</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-icon\" (click)=\"Refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n <!-- KPI Cards -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent); color: var(--mj-brand-primary);\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalRestores}}</div>\n <div class=\"kpi-label\">Total Restores</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-status-success) 10%, transparent); color: var(--mj-status-success);\">\n <i class=\"fa-solid fa-circle-check\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{SuccessfulRestores}}</div>\n <div class=\"kpi-label\">Successful</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-status-error) 10%, transparent); color: var(--mj-status-error);\">\n <i class=\"fa-solid fa-circle-xmark\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{FailedRestores}}</div>\n <div class=\"kpi-label\">Failed</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\" style=\"background: color-mix(in srgb, var(--mj-status-warning) 10%, transparent); color: var(--mj-status-warning);\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{PartialRestores}}</div>\n <div class=\"kpi-label\">Partial</div>\n </div>\n </div>\n </div>\n <!-- Filters -->\n <div class=\"filter-row\">\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Complete'\"\n (click)=\"OnStatusFilterChange('Complete')\">\n <i class=\"fa-solid fa-circle-check\"></i> Complete\n </button>\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Error'\"\n (click)=\"OnStatusFilterChange('Error')\">\n <i class=\"fa-solid fa-circle-xmark\"></i> Error\n </button>\n <button class=\"filter-chip\"\n [class.active]=\"StatusFilter === 'Partial'\"\n (click)=\"OnStatusFilterChange('Partial')\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i> Partial\n </button>\n </div>\n <!-- Restore List -->\n @if (FilteredRestores.length > 0) {\n <div class=\"restore-list\">\n @for (restore of FilteredRestores; track restore) {\n <div class=\"restore-card\"\n [ngClass]=\"{'expanded': IsExpanded(restore.ID)}\">\n <div class=\"restore-header\" (click)=\"ToggleExpand(restore.ID)\">\n <div class=\"restore-header-left\">\n <i [class]=\"GetStatusIcon(restore.Status)\"\n [ngClass]=\"GetStatusClass(restore.Status)\"\n class=\"status-icon\"></i>\n <div class=\"restore-info\">\n <div class=\"restore-label-name\">\n {{restore.VersionLabel}}\n </div>\n @if (restore.StartedAt) {\n <div class=\"restore-date\">{{FormatDate(restore.StartedAt)}}</div>\n }\n </div>\n </div>\n <div class=\"restore-header-right\">\n <div class=\"restore-progress-bar\">\n <div class=\"progress-fill\"\n [ngClass]=\"GetStatusClass(restore.Status)\"\n [style.width.%]=\"GetProgressPercent(restore)\">\n </div>\n </div>\n <span class=\"restore-count\">\n {{restore.CompletedItems ?? 0}} / {{restore.TotalItems ?? 0}} items\n </span>\n <i class=\"fa-solid\"\n [ngClass]=\"IsExpanded(restore.ID) ? 'fa-chevron-up' : 'fa-chevron-down'\"\n class=\"expand-icon\">\n </i>\n </div>\n </div>\n <!-- Expanded Details -->\n @if (IsExpanded(restore.ID)) {\n <div class=\"restore-details\">\n <div class=\"detail-grid\">\n <div class=\"detail-item\">\n <span class=\"detail-label\">Status</span>\n <span class=\"detail-value\" [ngClass]=\"GetStatusClass(restore.Status)\">\n {{restore.Status}}\n </span>\n </div>\n <div class=\"detail-item\">\n <span class=\"detail-label\">Items Completed</span>\n <span class=\"detail-value\">{{restore.CompletedItems ?? 0}}</span>\n </div>\n <div class=\"detail-item\">\n <span class=\"detail-label\">Items Failed</span>\n <span class=\"detail-value\" [class.text-error]=\"(restore.FailedItems ?? 0) > 0\">\n {{restore.FailedItems ?? 0}}\n </span>\n </div>\n @if (restore.User) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Restored By</span>\n <span class=\"detail-value\">{{restore.User}}</span>\n </div>\n }\n @if (restore.PreRestoreLabelID) {\n <div class=\"detail-item\">\n <span class=\"detail-label\">Pre-Restore Label</span>\n @if (restore.PreRestoreLabel) {\n <span class=\"detail-value detail-mono\">\n {{restore.PreRestoreLabel}}\n </span>\n }\n @if (!restore.PreRestoreLabel) {\n <span class=\"detail-value detail-mono\">\n {{restore.PreRestoreLabelID | slice:0:20}}...\n </span>\n }\n </div>\n }\n </div>\n @if (restore.ErrorLog) {\n <div class=\"error-log\">\n <div class=\"error-log-header\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n Error Log\n </div>\n <pre class=\"error-log-content\">{{restore.ErrorLog}}</pre>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (FilteredRestores.length === 0 && !IsLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-clock-rotate-left empty-icon\"></i>\n <h3>No restore operations found</h3>\n @if (StatusFilter) {\n <p>\n Try adjusting your filters.\n </p>\n }\n @if (!StatusFilter) {\n <p>\n No restores have been performed yet. Use the VersionHistoryEngine to restore records to a labeled state.\n </p>\n }\n </div>\n }\n }\n</div>\n"]}
@@ -22,6 +22,7 @@ function createSummary(overrides = {}) {
22
22
  TotalRecordsSyncedToday: 0,
23
23
  TotalErrors: 0,
24
24
  DurationMs: null,
25
+ Icon: null,
25
26
  ...overrides
26
27
  };
27
28
  }