@memberjunction/ng-dashboards 5.20.0 → 5.22.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 (99) hide show
  1. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +102 -0
  2. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -0
  3. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +583 -0
  4. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -0
  5. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +148 -0
  6. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -0
  7. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +773 -0
  8. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -0
  9. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +241 -0
  10. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -0
  11. package/dist/AI/components/vectors/vector-management-resource.component.js +1782 -0
  12. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -0
  13. package/dist/AI/index.d.ts +3 -0
  14. package/dist/AI/index.d.ts.map +1 -1
  15. package/dist/AI/index.js +6 -0
  16. package/dist/AI/index.js.map +1 -1
  17. package/dist/AI/services/ai-instrumentation.service.d.ts +50 -7
  18. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  19. package/dist/AI/services/ai-instrumentation.service.js +161 -193
  20. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  21. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +11 -0
  22. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
  23. package/dist/DashboardBrowser/dashboard-browser-resource.component.js +57 -0
  24. package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
  25. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +1 -1
  26. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +10 -2
  27. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  28. package/dist/DataExplorer/data-explorer-dashboard.component.js +35 -11
  29. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  30. package/dist/DataExplorer/data-explorer-resource.component.d.ts +1 -0
  31. package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
  32. package/dist/DataExplorer/data-explorer-resource.component.js +8 -4
  33. package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
  34. package/dist/Home/home-dashboard.component.d.ts +181 -1
  35. package/dist/Home/home-dashboard.component.d.ts.map +1 -1
  36. package/dist/Home/home-dashboard.component.js +1704 -182
  37. package/dist/Home/home-dashboard.component.js.map +1 -1
  38. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +121 -0
  39. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -0
  40. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +1058 -0
  41. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -0
  42. package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.d.ts +56 -0
  43. package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.d.ts.map +1 -0
  44. package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.js +291 -0
  45. package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.js.map +1 -0
  46. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts +85 -0
  47. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts.map +1 -0
  48. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js +461 -0
  49. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js.map +1 -0
  50. package/dist/KnowledgeHub/index.d.ts +4 -0
  51. package/dist/KnowledgeHub/index.d.ts.map +1 -0
  52. package/dist/KnowledgeHub/index.js +5 -0
  53. package/dist/KnowledgeHub/index.js.map +1 -0
  54. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  55. package/dist/QueryBrowser/query-browser-resource.component.js +5 -1
  56. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  57. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
  58. package/dist/SystemDiagnostics/system-diagnostics.component.js +1 -0
  59. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  60. package/dist/Testing/components/testing-dashboard-tab-resource.component.d.ts +7 -1
  61. package/dist/Testing/components/testing-dashboard-tab-resource.component.d.ts.map +1 -1
  62. package/dist/Testing/components/testing-dashboard-tab-resource.component.js +63 -8
  63. package/dist/Testing/components/testing-dashboard-tab-resource.component.js.map +1 -1
  64. package/dist/Testing/components/testing-dashboard-tab.component.d.ts +9 -1
  65. package/dist/Testing/components/testing-dashboard-tab.component.d.ts.map +1 -1
  66. package/dist/Testing/components/testing-dashboard-tab.component.js +109 -62
  67. package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
  68. package/dist/Testing/components/testing-explorer.component.d.ts +2 -1
  69. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  70. package/dist/Testing/components/testing-explorer.component.js +241 -200
  71. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  72. package/dist/Testing/components/testing-runs-resource.component.d.ts +7 -1
  73. package/dist/Testing/components/testing-runs-resource.component.d.ts.map +1 -1
  74. package/dist/Testing/components/testing-runs-resource.component.js +63 -8
  75. package/dist/Testing/components/testing-runs-resource.component.js.map +1 -1
  76. package/dist/Testing/components/testing-runs.component.d.ts.map +1 -1
  77. package/dist/Testing/components/testing-runs.component.js +7 -5
  78. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  79. package/dist/Testing/testing-dashboard.component.d.ts +9 -1
  80. package/dist/Testing/testing-dashboard.component.d.ts.map +1 -1
  81. package/dist/Testing/testing-dashboard.component.js +128 -59
  82. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  83. package/dist/ai-dashboards.module.d.ts +26 -19
  84. package/dist/ai-dashboards.module.d.ts.map +1 -1
  85. package/dist/ai-dashboards.module.js +40 -5
  86. package/dist/ai-dashboards.module.js.map +1 -1
  87. package/dist/core-dashboards.module.d.ts +1 -0
  88. package/dist/core-dashboards.module.d.ts.map +1 -1
  89. package/dist/core-dashboards.module.js +3 -0
  90. package/dist/core-dashboards.module.js.map +1 -1
  91. package/dist/public-api.d.ts +4 -1
  92. package/dist/public-api.d.ts.map +1 -1
  93. package/dist/public-api.js +5 -1
  94. package/dist/public-api.js.map +1 -1
  95. package/dist/testing-dashboards.module.d.ts +5 -4
  96. package/dist/testing-dashboards.module.d.ts.map +1 -1
  97. package/dist/testing-dashboards.module.js +4 -0
  98. package/dist/testing-dashboards.module.js.map +1 -1
  99. package/package.json +44 -42
@@ -0,0 +1,583 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * @fileoverview Content Autotagging Pipeline Monitor
9
+ *
10
+ * Operations dashboard for monitoring the content autotagging pipeline.
11
+ * Displays KPI metrics, pipeline stage visualization, recent processing feed,
12
+ * and source configuration status.
13
+ */
14
+ import { Component, ChangeDetectorRef, inject } from '@angular/core';
15
+ import { Subject } from 'rxjs';
16
+ import { RunView } from '@memberjunction/core';
17
+ import { RegisterClass } from '@memberjunction/global';
18
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
19
+ import * as i0 from "@angular/core";
20
+ import * as i1 from "@memberjunction/ng-shared-generic";
21
+ import * as i2 from "@angular/common";
22
+ const _forTrack0 = ($index, $item) => $item.Label;
23
+ const _forTrack1 = ($index, $item) => $item.Name;
24
+ const _forTrack2 = ($index, $item) => $item.ID;
25
+ function AutotaggingPipelineResourceComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
26
+ i0.ɵɵelementStart(0, "div", 1);
27
+ i0.ɵɵelement(1, "mj-loading", 3);
28
+ i0.ɵɵelementEnd();
29
+ } }
30
+ function AutotaggingPipelineResourceComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
31
+ const _r1 = i0.ɵɵgetCurrentView();
32
+ i0.ɵɵelementStart(0, "div", 2);
33
+ i0.ɵɵelement(1, "i", 4);
34
+ i0.ɵɵelementStart(2, "span");
35
+ i0.ɵɵtext(3);
36
+ i0.ɵɵelementEnd();
37
+ i0.ɵɵelementStart(4, "button", 5);
38
+ i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_2_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.RefreshData()); });
39
+ i0.ɵɵelement(5, "i", 6);
40
+ i0.ɵɵtext(6, " Retry ");
41
+ i0.ɵɵelementEnd()();
42
+ } if (rf & 2) {
43
+ const ctx_r1 = i0.ɵɵnextContext();
44
+ i0.ɵɵadvance(3);
45
+ i0.ɵɵtextInterpolate(ctx_r1.ErrorMessage);
46
+ } }
47
+ function AutotaggingPipelineResourceComponent_Conditional_3_For_10_Template(rf, ctx) { if (rf & 1) {
48
+ i0.ɵɵelementStart(0, "div", 26)(1, "div", 27);
49
+ i0.ɵɵelement(2, "i");
50
+ i0.ɵɵelementEnd();
51
+ i0.ɵɵelementStart(3, "div", 28)(4, "span", 29);
52
+ i0.ɵɵtext(5);
53
+ i0.ɵɵpipe(6, "number");
54
+ i0.ɵɵelementEnd();
55
+ i0.ɵɵelementStart(7, "span", 30);
56
+ i0.ɵɵtext(8);
57
+ i0.ɵɵelementEnd()()();
58
+ } if (rf & 2) {
59
+ const metric_r4 = ctx.$implicit;
60
+ i0.ɵɵclassMap(metric_r4.ColorClass);
61
+ i0.ɵɵadvance(2);
62
+ i0.ɵɵclassMap(metric_r4.Icon);
63
+ i0.ɵɵadvance(3);
64
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(6, 6, metric_r4.Value));
65
+ i0.ɵɵadvance(3);
66
+ i0.ɵɵtextInterpolate(metric_r4.Label);
67
+ } }
68
+ function AutotaggingPipelineResourceComponent_Conditional_3_For_17_Conditional_6_Template(rf, ctx) { if (rf & 1) {
69
+ i0.ɵɵtext(0);
70
+ } if (rf & 2) {
71
+ const stage_r5 = i0.ɵɵnextContext().$implicit;
72
+ i0.ɵɵtextInterpolate1(" ", stage_r5.ActiveCount, " active ");
73
+ } }
74
+ function AutotaggingPipelineResourceComponent_Conditional_3_For_17_Conditional_7_Template(rf, ctx) { if (rf & 1) {
75
+ i0.ɵɵtext(0, " Idle ");
76
+ } }
77
+ function AutotaggingPipelineResourceComponent_Conditional_3_For_17_Conditional_9_Template(rf, ctx) { if (rf & 1) {
78
+ i0.ɵɵelementStart(0, "div", 36);
79
+ i0.ɵɵelement(1, "i", 37);
80
+ i0.ɵɵelementEnd();
81
+ } }
82
+ function AutotaggingPipelineResourceComponent_Conditional_3_For_17_Template(rf, ctx) { if (rf & 1) {
83
+ i0.ɵɵelementStart(0, "div", 31)(1, "div", 32);
84
+ i0.ɵɵelement(2, "i");
85
+ i0.ɵɵelementEnd();
86
+ i0.ɵɵelementStart(3, "span", 33);
87
+ i0.ɵɵtext(4);
88
+ i0.ɵɵelementEnd();
89
+ i0.ɵɵelementStart(5, "span", 34);
90
+ i0.ɵɵconditionalCreate(6, AutotaggingPipelineResourceComponent_Conditional_3_For_17_Conditional_6_Template, 1, 1)(7, AutotaggingPipelineResourceComponent_Conditional_3_For_17_Conditional_7_Template, 1, 0);
91
+ i0.ɵɵelementEnd();
92
+ i0.ɵɵelement(8, "div", 35);
93
+ i0.ɵɵelementEnd();
94
+ i0.ɵɵconditionalCreate(9, AutotaggingPipelineResourceComponent_Conditional_3_For_17_Conditional_9_Template, 2, 0, "div", 36);
95
+ } if (rf & 2) {
96
+ const stage_r5 = ctx.$implicit;
97
+ const ɵ$index_63_r6 = ctx.$index;
98
+ const ɵ$count_63_r7 = ctx.$count;
99
+ i0.ɵɵclassMap("stage-" + stage_r5.Status);
100
+ i0.ɵɵadvance(2);
101
+ i0.ɵɵclassMap(stage_r5.Icon);
102
+ i0.ɵɵadvance(2);
103
+ i0.ɵɵtextInterpolate(stage_r5.Name);
104
+ i0.ɵɵadvance(2);
105
+ i0.ɵɵconditional(stage_r5.ActiveCount > 0 ? 6 : 7);
106
+ i0.ɵɵadvance(3);
107
+ i0.ɵɵconditional(!(ɵ$index_63_r6 === ɵ$count_63_r7 - 1) ? 9 : -1);
108
+ } }
109
+ function AutotaggingPipelineResourceComponent_Conditional_3_Conditional_24_Template(rf, ctx) { if (rf & 1) {
110
+ i0.ɵɵelementStart(0, "div", 20);
111
+ i0.ɵɵelement(1, "i", 38);
112
+ i0.ɵɵelementStart(2, "p");
113
+ i0.ɵɵtext(3, "No processed items yet.");
114
+ i0.ɵɵelementEnd()();
115
+ } }
116
+ function AutotaggingPipelineResourceComponent_Conditional_3_For_26_Template(rf, ctx) { if (rf & 1) {
117
+ i0.ɵɵelementStart(0, "div", 21)(1, "div", 39)(2, "span", 40);
118
+ i0.ɵɵtext(3);
119
+ i0.ɵɵelementEnd();
120
+ i0.ɵɵelementStart(4, "span", 41);
121
+ i0.ɵɵtext(5);
122
+ i0.ɵɵelementEnd()();
123
+ i0.ɵɵelementStart(6, "div", 42)(7, "span", 43);
124
+ i0.ɵɵelement(8, "i", 44);
125
+ i0.ɵɵtext(9);
126
+ i0.ɵɵelementEnd();
127
+ i0.ɵɵelementStart(10, "span", 43);
128
+ i0.ɵɵelement(11, "i", 45);
129
+ i0.ɵɵtext(12);
130
+ i0.ɵɵelementEnd();
131
+ i0.ɵɵelementStart(13, "span", 43);
132
+ i0.ɵɵelement(14, "i", 46);
133
+ i0.ɵɵtext(15);
134
+ i0.ɵɵelementEnd();
135
+ i0.ɵɵelementStart(16, "span", 47);
136
+ i0.ɵɵtext(17);
137
+ i0.ɵɵelementEnd()()();
138
+ } if (rf & 2) {
139
+ const item_r8 = ctx.$implicit;
140
+ const ctx_r1 = i0.ɵɵnextContext(2);
141
+ i0.ɵɵadvance(2);
142
+ i0.ɵɵproperty("title", item_r8.Name);
143
+ i0.ɵɵadvance();
144
+ i0.ɵɵtextInterpolate(item_r8.Name);
145
+ i0.ɵɵadvance();
146
+ i0.ɵɵclassMap(ctx_r1.GetStatusClass(item_r8.Status));
147
+ i0.ɵɵadvance();
148
+ i0.ɵɵtextInterpolate1(" ", item_r8.Status, " ");
149
+ i0.ɵɵadvance(4);
150
+ i0.ɵɵtextInterpolate1(" ", item_r8.SourceName, " ");
151
+ i0.ɵɵadvance(3);
152
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.FormatDuration(item_r8.ProcessingTimeMs), " ");
153
+ i0.ɵɵadvance(3);
154
+ i0.ɵɵtextInterpolate1(" ", item_r8.TagCount, " tags ");
155
+ i0.ɵɵadvance(2);
156
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.FormatRelativeTime(item_r8.ProcessedAt), " ");
157
+ } }
158
+ function AutotaggingPipelineResourceComponent_Conditional_3_Conditional_32_Template(rf, ctx) { if (rf & 1) {
159
+ i0.ɵɵelementStart(0, "div", 20);
160
+ i0.ɵɵelement(1, "i", 48);
161
+ i0.ɵɵelementStart(2, "p");
162
+ i0.ɵɵtext(3, "No sources configured.");
163
+ i0.ɵɵelementEnd()();
164
+ } }
165
+ function AutotaggingPipelineResourceComponent_Conditional_3_For_34_Template(rf, ctx) { if (rf & 1) {
166
+ i0.ɵɵelementStart(0, "div", 25)(1, "div", 49)(2, "div", 50);
167
+ i0.ɵɵelement(3, "i");
168
+ i0.ɵɵelementEnd();
169
+ i0.ɵɵelementStart(4, "div", 51)(5, "span", 52);
170
+ i0.ɵɵtext(6);
171
+ i0.ɵɵelementEnd();
172
+ i0.ɵɵelementStart(7, "span", 53);
173
+ i0.ɵɵtext(8);
174
+ i0.ɵɵelementEnd()();
175
+ i0.ɵɵelementStart(9, "span", 54);
176
+ i0.ɵɵtext(10);
177
+ i0.ɵɵelementEnd()();
178
+ i0.ɵɵelementStart(11, "div", 55)(12, "span", 56);
179
+ i0.ɵɵelement(13, "i", 57);
180
+ i0.ɵɵtext(14);
181
+ i0.ɵɵelementEnd();
182
+ i0.ɵɵelementStart(15, "span", 56);
183
+ i0.ɵɵelement(16, "i", 58);
184
+ i0.ɵɵtext(17);
185
+ i0.ɵɵpipe(18, "number");
186
+ i0.ɵɵelementEnd()()();
187
+ } if (rf & 2) {
188
+ const source_r9 = ctx.$implicit;
189
+ const ctx_r1 = i0.ɵɵnextContext(2);
190
+ i0.ɵɵadvance(3);
191
+ i0.ɵɵclassMap(source_r9.TypeIcon);
192
+ i0.ɵɵadvance(3);
193
+ i0.ɵɵtextInterpolate(source_r9.Name);
194
+ i0.ɵɵadvance(2);
195
+ i0.ɵɵtextInterpolate(source_r9.TypeName);
196
+ i0.ɵɵadvance();
197
+ i0.ɵɵclassMap(ctx_r1.GetStatusClass(source_r9.Status));
198
+ i0.ɵɵadvance();
199
+ i0.ɵɵtextInterpolate1(" ", source_r9.Status, " ");
200
+ i0.ɵɵadvance(4);
201
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.FormatRelativeTime(source_r9.LastRunAt), " ");
202
+ i0.ɵɵadvance(3);
203
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(18, 9, source_r9.ItemCount), " items ");
204
+ } }
205
+ function AutotaggingPipelineResourceComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
206
+ const _r3 = i0.ɵɵgetCurrentView();
207
+ i0.ɵɵelementStart(0, "div", 7)(1, "div", 8);
208
+ i0.ɵɵelement(2, "i", 9);
209
+ i0.ɵɵelementStart(3, "h2");
210
+ i0.ɵɵtext(4, "Content Autotagging Pipeline");
211
+ i0.ɵɵelementEnd()();
212
+ i0.ɵɵelementStart(5, "button", 5);
213
+ i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_3_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.RefreshData()); });
214
+ i0.ɵɵelement(6, "i", 6);
215
+ i0.ɵɵtext(7, " Refresh ");
216
+ i0.ɵɵelementEnd()();
217
+ i0.ɵɵelementStart(8, "div", 10);
218
+ i0.ɵɵrepeaterCreate(9, AutotaggingPipelineResourceComponent_Conditional_3_For_10_Template, 9, 8, "div", 11, _forTrack0);
219
+ i0.ɵɵelementEnd();
220
+ i0.ɵɵelementStart(11, "div", 12)(12, "h3", 13);
221
+ i0.ɵɵelement(13, "i", 14);
222
+ i0.ɵɵtext(14, " Pipeline Stages ");
223
+ i0.ɵɵelementEnd();
224
+ i0.ɵɵelementStart(15, "div", 15);
225
+ i0.ɵɵrepeaterCreate(16, AutotaggingPipelineResourceComponent_Conditional_3_For_17_Template, 10, 7, null, null, _forTrack1);
226
+ i0.ɵɵelementEnd()();
227
+ i0.ɵɵelementStart(18, "div", 16)(19, "div", 17)(20, "h3", 13);
228
+ i0.ɵɵelement(21, "i", 18);
229
+ i0.ɵɵtext(22, " Recent Processing ");
230
+ i0.ɵɵelementEnd();
231
+ i0.ɵɵelementStart(23, "div", 19);
232
+ i0.ɵɵconditionalCreate(24, AutotaggingPipelineResourceComponent_Conditional_3_Conditional_24_Template, 4, 0, "div", 20);
233
+ i0.ɵɵrepeaterCreate(25, AutotaggingPipelineResourceComponent_Conditional_3_For_26_Template, 18, 9, "div", 21, i0.ɵɵrepeaterTrackByIndex);
234
+ i0.ɵɵelementEnd()();
235
+ i0.ɵɵelementStart(27, "div", 22)(28, "h3", 13);
236
+ i0.ɵɵelement(29, "i", 23);
237
+ i0.ɵɵtext(30, " Content Sources ");
238
+ i0.ɵɵelementEnd();
239
+ i0.ɵɵelementStart(31, "div", 24);
240
+ i0.ɵɵconditionalCreate(32, AutotaggingPipelineResourceComponent_Conditional_3_Conditional_32_Template, 4, 0, "div", 20);
241
+ i0.ɵɵrepeaterCreate(33, AutotaggingPipelineResourceComponent_Conditional_3_For_34_Template, 19, 11, "div", 25, _forTrack2);
242
+ i0.ɵɵelementEnd()()();
243
+ } if (rf & 2) {
244
+ const ctx_r1 = i0.ɵɵnextContext();
245
+ i0.ɵɵadvance(9);
246
+ i0.ɵɵrepeater(ctx_r1.KPIMetrics);
247
+ i0.ɵɵadvance(7);
248
+ i0.ɵɵrepeater(ctx_r1.PipelineStages);
249
+ i0.ɵɵadvance(8);
250
+ i0.ɵɵconditional(ctx_r1.ProcessedItems.length === 0 ? 24 : -1);
251
+ i0.ɵɵadvance();
252
+ i0.ɵɵrepeater(ctx_r1.ProcessedItems);
253
+ i0.ɵɵadvance(7);
254
+ i0.ɵɵconditional(ctx_r1.ContentSources.length === 0 ? 32 : -1);
255
+ i0.ɵɵadvance();
256
+ i0.ɵɵrepeater(ctx_r1.ContentSources);
257
+ } }
258
+ let AutotaggingPipelineResourceComponent = class AutotaggingPipelineResourceComponent extends BaseResourceComponent {
259
+ destroy$ = new Subject();
260
+ IsLoading = false;
261
+ ErrorMessage = '';
262
+ // KPI data
263
+ KPIMetrics = [];
264
+ // Pipeline stages
265
+ PipelineStages = [];
266
+ // Recent processing feed
267
+ ProcessedItems = [];
268
+ // Source configuration
269
+ ContentSources = [];
270
+ // Raw data holders for aggregation
271
+ contentItems = [];
272
+ contentRuns = [];
273
+ contentTags = [];
274
+ contentSourceTypes = [];
275
+ contentSourcesRaw = [];
276
+ cdr = inject(ChangeDetectorRef);
277
+ async ngAfterViewInit() {
278
+ await this.LoadData();
279
+ this.NotifyLoadComplete();
280
+ }
281
+ ngOnDestroy() {
282
+ this.destroy$.next();
283
+ this.destroy$.complete();
284
+ }
285
+ async GetResourceDisplayName(_data) {
286
+ return 'Content Autotagging';
287
+ }
288
+ async GetResourceIconClass(_data) {
289
+ return 'fa-solid fa-tags';
290
+ }
291
+ /** Load all pipeline data from MJ entities */
292
+ async LoadData() {
293
+ this.IsLoading = true;
294
+ this.ErrorMessage = '';
295
+ this.cdr.detectChanges();
296
+ try {
297
+ const rv = new RunView();
298
+ const [sourcesResult, itemsResult, runsResult, tagsResult, typesResult] = await rv.RunViews([
299
+ {
300
+ EntityName: 'MJ: Content Sources',
301
+ OrderBy: 'Name',
302
+ ResultType: 'simple'
303
+ },
304
+ {
305
+ EntityName: 'MJ: Content Items',
306
+ OrderBy: '__mj_CreatedAt DESC',
307
+ MaxRows: 200,
308
+ ResultType: 'simple'
309
+ },
310
+ {
311
+ EntityName: 'MJ: Content Process Runs',
312
+ OrderBy: '__mj_CreatedAt DESC',
313
+ MaxRows: 100,
314
+ ResultType: 'simple'
315
+ },
316
+ {
317
+ EntityName: 'MJ: Content Item Tags',
318
+ ResultType: 'simple'
319
+ },
320
+ {
321
+ EntityName: 'MJ: Content Source Types',
322
+ ResultType: 'simple'
323
+ }
324
+ ]);
325
+ this.contentSourcesRaw = sourcesResult.Success ? sourcesResult.Results : [];
326
+ this.contentItems = itemsResult.Success ? itemsResult.Results : [];
327
+ this.contentRuns = runsResult.Success ? runsResult.Results : [];
328
+ this.contentTags = tagsResult.Success ? tagsResult.Results : [];
329
+ this.contentSourceTypes = typesResult.Success ? typesResult.Results : [];
330
+ this.buildKPIMetrics();
331
+ this.buildPipelineStages();
332
+ this.buildProcessedItems();
333
+ this.buildContentSources();
334
+ }
335
+ catch (error) {
336
+ console.error('Error loading autotagging pipeline data:', error);
337
+ this.ErrorMessage = 'Failed to load pipeline data. Please try again.';
338
+ }
339
+ finally {
340
+ this.IsLoading = false;
341
+ this.cdr.detectChanges();
342
+ }
343
+ }
344
+ /** Refresh pipeline status data */
345
+ async RefreshData() {
346
+ await this.LoadData();
347
+ }
348
+ /** Format milliseconds into a human-readable duration */
349
+ FormatDuration(ms) {
350
+ if (ms < 1000)
351
+ return `${ms}ms`;
352
+ if (ms < 60000)
353
+ return `${(ms / 1000).toFixed(1)}s`;
354
+ return `${(ms / 60000).toFixed(1)}m`;
355
+ }
356
+ /** Format a date as a relative time string */
357
+ FormatRelativeTime(date) {
358
+ if (!date)
359
+ return 'Never';
360
+ const now = new Date();
361
+ const diffMs = now.getTime() - new Date(date).getTime();
362
+ const diffMins = Math.floor(diffMs / 60000);
363
+ if (diffMins < 1)
364
+ return 'Just now';
365
+ if (diffMins < 60)
366
+ return `${diffMins}m ago`;
367
+ const diffHours = Math.floor(diffMins / 60);
368
+ if (diffHours < 24)
369
+ return `${diffHours}h ago`;
370
+ const diffDays = Math.floor(diffHours / 24);
371
+ return `${diffDays}d ago`;
372
+ }
373
+ /** Get CSS class for a processing status */
374
+ GetStatusClass(status) {
375
+ switch (status) {
376
+ case 'Complete':
377
+ case 'Active':
378
+ return 'status-success';
379
+ case 'Processing':
380
+ return 'status-processing';
381
+ case 'Error':
382
+ return 'status-error';
383
+ case 'Paused':
384
+ return 'status-warning';
385
+ default:
386
+ return 'status-default';
387
+ }
388
+ }
389
+ /** Get icon for a source type */
390
+ GetSourceTypeIcon(typeName) {
391
+ const iconMap = {
392
+ 'Web': 'fa-solid fa-globe',
393
+ 'API': 'fa-solid fa-plug',
394
+ 'Database': 'fa-solid fa-database',
395
+ 'File': 'fa-solid fa-file-alt',
396
+ 'Email': 'fa-solid fa-envelope',
397
+ 'RSS': 'fa-solid fa-rss',
398
+ 'CMS': 'fa-solid fa-newspaper'
399
+ };
400
+ return iconMap[typeName] ?? 'fa-solid fa-folder';
401
+ }
402
+ // ---- Private Methods ----
403
+ /** Build KPI metrics from loaded data */
404
+ buildKPIMetrics() {
405
+ const activeSources = this.contentSourcesRaw.filter((s) => s['Status'] === 'Active').length;
406
+ const totalItems = this.contentItems.length;
407
+ const totalTags = this.contentTags.length;
408
+ const errorCount = this.contentRuns.filter((r) => r['Status'] === 'Error').length;
409
+ this.KPIMetrics = [
410
+ {
411
+ Label: 'Active Sources',
412
+ Value: activeSources,
413
+ Icon: 'fa-solid fa-satellite-dish',
414
+ ColorClass: 'kpi-brand'
415
+ },
416
+ {
417
+ Label: 'Items Processed',
418
+ Value: totalItems,
419
+ Icon: 'fa-solid fa-file-lines',
420
+ ColorClass: 'kpi-info'
421
+ },
422
+ {
423
+ Label: 'Tags Generated',
424
+ Value: totalTags,
425
+ Icon: 'fa-solid fa-tags',
426
+ ColorClass: 'kpi-success'
427
+ },
428
+ {
429
+ Label: 'Errors',
430
+ Value: errorCount,
431
+ Icon: 'fa-solid fa-circle-exclamation',
432
+ ColorClass: errorCount > 0 ? 'kpi-error' : 'kpi-success'
433
+ }
434
+ ];
435
+ }
436
+ /** Build pipeline stage visualization data */
437
+ buildPipelineStages() {
438
+ const runsByStage = this.groupRunsByStage();
439
+ this.PipelineStages = [
440
+ this.createStage('Ingest', 'fa-solid fa-download', runsByStage),
441
+ this.createStage('Extract', 'fa-solid fa-file-export', runsByStage),
442
+ this.createStage('Chunk', 'fa-solid fa-puzzle-piece', runsByStage),
443
+ this.createStage('Tag', 'fa-solid fa-tag', runsByStage),
444
+ this.createStage('Vectorize', 'fa-solid fa-vector-square', runsByStage)
445
+ ];
446
+ }
447
+ /** Group content runs by their processing stage */
448
+ groupRunsByStage() {
449
+ const groups = new Map();
450
+ for (const run of this.contentRuns) {
451
+ const stage = run['Stage'] ?? 'Unknown';
452
+ const existing = groups.get(stage) ?? [];
453
+ existing.push(run);
454
+ groups.set(stage, existing);
455
+ }
456
+ return groups;
457
+ }
458
+ /** Create a pipeline stage object from run data */
459
+ createStage(name, icon, runsByStage) {
460
+ const stageRuns = runsByStage.get(name) ?? [];
461
+ const activeRuns = stageRuns.filter((r) => r['Status'] === 'Processing' || r['Status'] === 'Running');
462
+ const errorRuns = stageRuns.filter((r) => r['Status'] === 'Error');
463
+ let status = 'idle';
464
+ if (errorRuns.length > 0)
465
+ status = 'error';
466
+ else if (activeRuns.length > 0)
467
+ status = 'active';
468
+ return { Name: name, Icon: icon, ActiveCount: activeRuns.length, Status: status };
469
+ }
470
+ /** Build the recent processing feed from content items and tags */
471
+ buildProcessedItems() {
472
+ const tagCountByItem = this.countTagsByItem();
473
+ this.ProcessedItems = this.contentItems.slice(0, 50).map((item) => {
474
+ const itemId = item['ID'];
475
+ return {
476
+ Name: item['Name'] ?? 'Unnamed Item',
477
+ SourceName: item['ContentSource'] ?? item['ContentSourceID'] ?? 'Unknown',
478
+ ProcessingTimeMs: item['ProcessingTimeMs'] ?? 0,
479
+ Status: this.mapItemStatus(item['Status']),
480
+ TagCount: tagCountByItem.get(itemId) ?? 0,
481
+ ProcessedAt: item['__mj_CreatedAt'] ? new Date(item['__mj_CreatedAt']) : new Date()
482
+ };
483
+ });
484
+ }
485
+ /** Count tags per content item */
486
+ countTagsByItem() {
487
+ const counts = new Map();
488
+ for (const tag of this.contentTags) {
489
+ const itemId = tag['ContentItemID'];
490
+ if (itemId) {
491
+ counts.set(itemId, (counts.get(itemId) ?? 0) + 1);
492
+ }
493
+ }
494
+ return counts;
495
+ }
496
+ /** Map raw status values to display status */
497
+ mapItemStatus(status) {
498
+ if (!status)
499
+ return 'Processing';
500
+ const normalized = status.toLowerCase();
501
+ if (normalized === 'complete' || normalized === 'completed' || normalized === 'done')
502
+ return 'Complete';
503
+ if (normalized === 'error' || normalized === 'failed')
504
+ return 'Error';
505
+ return 'Processing';
506
+ }
507
+ /** Build content source summaries from raw data */
508
+ buildContentSources() {
509
+ const typeMap = this.buildTypeMap();
510
+ const itemCountBySource = this.countItemsBySource();
511
+ this.ContentSources = this.contentSourcesRaw.map((source) => {
512
+ const typeId = source['ContentSourceTypeID'];
513
+ const typeName = typeMap.get(typeId) ?? 'Unknown';
514
+ return {
515
+ ID: source['ID'],
516
+ Name: source['Name'] ?? 'Unnamed Source',
517
+ TypeName: typeName,
518
+ TypeIcon: this.GetSourceTypeIcon(typeName),
519
+ Status: this.mapSourceStatus(source['Status']),
520
+ LastRunAt: source['LastRunAt'] ? new Date(source['LastRunAt']) : null,
521
+ ItemCount: itemCountBySource.get(source['ID']) ?? 0
522
+ };
523
+ });
524
+ }
525
+ /** Build a map of source type IDs to names */
526
+ buildTypeMap() {
527
+ const map = new Map();
528
+ for (const type of this.contentSourceTypes) {
529
+ map.set(type['ID'], type['Name'] ?? 'Unknown');
530
+ }
531
+ return map;
532
+ }
533
+ /** Count content items per source */
534
+ countItemsBySource() {
535
+ const counts = new Map();
536
+ for (const item of this.contentItems) {
537
+ const sourceId = item['ContentSourceID'];
538
+ if (sourceId) {
539
+ counts.set(sourceId, (counts.get(sourceId) ?? 0) + 1);
540
+ }
541
+ }
542
+ return counts;
543
+ }
544
+ /** Map raw source status to display status */
545
+ mapSourceStatus(status) {
546
+ if (!status)
547
+ return 'Paused';
548
+ const normalized = status.toLowerCase();
549
+ if (normalized === 'active' || normalized === 'running')
550
+ return 'Active';
551
+ if (normalized === 'error' || normalized === 'failed')
552
+ return 'Error';
553
+ return 'Paused';
554
+ }
555
+ static ɵfac = /*@__PURE__*/ (() => { let ɵAutotaggingPipelineResourceComponent_BaseFactory; return function AutotaggingPipelineResourceComponent_Factory(__ngFactoryType__) { return (ɵAutotaggingPipelineResourceComponent_BaseFactory || (ɵAutotaggingPipelineResourceComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AutotaggingPipelineResourceComponent)))(__ngFactoryType__ || AutotaggingPipelineResourceComponent); }; })();
556
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AutotaggingPipelineResourceComponent, selectors: [["app-autotagging-pipeline-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [[1, "autotagging-container"], [1, "loading-overlay"], [1, "error-banner"], ["text", "Loading pipeline data..."], [1, "fa-solid", "fa-triangle-exclamation"], [1, "refresh-btn", 3, "click"], [1, "fa-solid", "fa-rotate-right"], [1, "header-row"], [1, "header-title"], [1, "fa-solid", "fa-tags", "header-icon"], [1, "kpi-strip"], [1, "kpi-card", 3, "class"], [1, "pipeline-section"], [1, "section-title"], [1, "fa-solid", "fa-diagram-project"], [1, "pipeline-flow"], [1, "main-content"], [1, "feed-section"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "feed-list"], [1, "empty-state"], [1, "feed-item"], [1, "sources-panel"], [1, "fa-solid", "fa-gear"], [1, "sources-list"], [1, "source-card"], [1, "kpi-card"], [1, "kpi-icon"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "pipeline-stage"], [1, "stage-icon"], [1, "stage-name"], [1, "stage-count"], [1, "stage-indicator"], [1, "stage-connector"], [1, "fa-solid", "fa-chevron-right"], [1, "fa-solid", "fa-inbox"], [1, "feed-item-header"], [1, "feed-item-name", 3, "title"], [1, "feed-item-status"], [1, "feed-item-details"], [1, "feed-detail"], [1, "fa-solid", "fa-database"], [1, "fa-solid", "fa-stopwatch"], [1, "fa-solid", "fa-tags"], [1, "feed-detail", "feed-time"], [1, "fa-solid", "fa-plug-circle-xmark"], [1, "source-header"], [1, "source-icon"], [1, "source-info"], [1, "source-name"], [1, "source-type"], [1, "source-status"], [1, "source-meta"], [1, "source-meta-item"], [1, "fa-solid", "fa-clock"], [1, "fa-solid", "fa-file-lines"]], template: function AutotaggingPipelineResourceComponent_Template(rf, ctx) { if (rf & 1) {
557
+ i0.ɵɵelementStart(0, "div", 0);
558
+ i0.ɵɵconditionalCreate(1, AutotaggingPipelineResourceComponent_Conditional_1_Template, 2, 0, "div", 1);
559
+ i0.ɵɵconditionalCreate(2, AutotaggingPipelineResourceComponent_Conditional_2_Template, 7, 1, "div", 2);
560
+ i0.ɵɵconditionalCreate(3, AutotaggingPipelineResourceComponent_Conditional_3_Template, 35, 2);
561
+ i0.ɵɵelementEnd();
562
+ } if (rf & 2) {
563
+ i0.ɵɵadvance();
564
+ i0.ɵɵconditional(ctx.IsLoading ? 1 : -1);
565
+ i0.ɵɵadvance();
566
+ i0.ɵɵconditional(ctx.ErrorMessage ? 2 : -1);
567
+ i0.ɵɵadvance();
568
+ i0.ɵɵconditional(!ctx.IsLoading ? 3 : -1);
569
+ } }, dependencies: [i1.LoadingComponent, i2.DecimalPipe], styles: ["\n\n\n\n\n\n[_nghost-%COMP%] {\n display: block;\n height: 100%;\n overflow: hidden;\n}\n\n\n\n\n.autotagging-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px;\n gap: 20px;\n overflow-y: auto;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n}\n\n\n\n\n.loading-overlay[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n}\n\n.error-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n border-radius: 6px;\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.error-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.error-banner[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n\n\n\n.header-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.header-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.header-title[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.refresh-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 13px;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.refresh-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n}\n\n\n\n\n.kpi-strip[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n border-radius: 8px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n transition: box-shadow 0.15s;\n}\n\n.kpi-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 10px;\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.kpi-brand[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-info[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-info) 12%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.kpi-success[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.kpi-error[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 22px;\n font-weight: 700;\n line-height: 1.2;\n color: var(--mj-text-primary);\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n\n\n\n.pipeline-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 18px 20px;\n}\n\n.section-title[_ngcontent-%COMP%] {\n margin: 0 0 14px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.pipeline-flow[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.pipeline-stage[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n padding: 14px 20px;\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n min-width: 100px;\n position: relative;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.stage-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-text-muted);\n}\n\n.stage-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.stage-count[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.stage-indicator[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 0;\n left: 10%;\n right: 10%;\n height: 3px;\n border-radius: 3px 3px 0 0;\n background: var(--mj-border-subtle);\n transition: background 0.2s;\n}\n\n\n\n\n.stage-active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 1px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.stage-active[_ngcontent-%COMP%] .stage-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.stage-active[_ngcontent-%COMP%] .stage-count[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.stage-active[_ngcontent-%COMP%] .stage-indicator[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.stage-error[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n.stage-error[_ngcontent-%COMP%] .stage-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.stage-error[_ngcontent-%COMP%] .stage-indicator[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n}\n\n.stage-connector[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n\n\n\n.main-content[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 320px;\n gap: 20px;\n flex: 1;\n min-height: 0;\n}\n\n\n\n\n.feed-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 18px 20px;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.feed-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.feed-item[_ngcontent-%COMP%] {\n padding: 10px 12px;\n border-radius: 6px;\n transition: background 0.1s;\n}\n\n.feed-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.feed-item-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n}\n\n.feed-item-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 70%;\n}\n\n.feed-item-status[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.feed-item-details[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n flex-wrap: wrap;\n}\n\n.feed-detail[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.feed-detail[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.feed-time[_ngcontent-%COMP%] {\n margin-left: auto;\n}\n\n\n\n\n.sources-panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 18px 20px;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.sources-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.source-card[_ngcontent-%COMP%] {\n padding: 12px;\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n transition: border-color 0.15s;\n}\n\n.source-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-default);\n}\n\n.source-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 8px;\n}\n\n.source-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.source-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n}\n\n.source-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.source-type[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.source-status[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n flex-shrink: 0;\n}\n\n.source-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.source-meta-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.source-meta-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n\n.status-success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.status-processing[_ngcontent-%COMP%] {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n\n.status-error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.status-warning[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n\n.status-default[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n border: 1px solid var(--mj-border-subtle);\n}\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 gap: 8px;\n padding: 32px 16px;\n color: var(--mj-text-disabled);\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n}\n\n\n\n\n@media (max-width: 1100px) {\n .main-content[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n@media (max-width: 768px) {\n .kpi-strip[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .pipeline-flow[_ngcontent-%COMP%] {\n gap: 6px;\n }\n\n .pipeline-stage[_ngcontent-%COMP%] {\n min-width: 80px;\n padding: 10px 12px;\n }\n}\n\n@media (max-width: 480px) {\n .kpi-strip[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .pipeline-stage[_ngcontent-%COMP%] {\n min-width: 70px;\n }\n\n .header-row[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 10px;\n }\n}"] });
570
+ };
571
+ AutotaggingPipelineResourceComponent = __decorate([
572
+ RegisterClass(BaseResourceComponent, 'AutotaggingPipelineResource')
573
+ ], AutotaggingPipelineResourceComponent);
574
+ export { AutotaggingPipelineResourceComponent };
575
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AutotaggingPipelineResourceComponent, [{
576
+ type: Component,
577
+ args: [{ standalone: false, selector: 'app-autotagging-pipeline-resource', template: "<!-- Content Autotagging Pipeline Monitor -->\n<div class=\"autotagging-container\">\n @if (IsLoading) {\n <div class=\"loading-overlay\">\n <mj-loading text=\"Loading pipeline data...\"></mj-loading>\n </div>\n }\n\n @if (ErrorMessage) {\n <div class=\"error-banner\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>{{ ErrorMessage }}</span>\n <button class=\"refresh-btn\" (click)=\"RefreshData()\">\n <i class=\"fa-solid fa-rotate-right\"></i> Retry\n </button>\n </div>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"header-row\">\n <div class=\"header-title\">\n <i class=\"fa-solid fa-tags header-icon\"></i>\n <h2>Content Autotagging Pipeline</h2>\n </div>\n <button class=\"refresh-btn\" (click)=\"RefreshData()\">\n <i class=\"fa-solid fa-rotate-right\"></i> Refresh\n </button>\n </div>\n\n <!-- KPI Strip -->\n <div class=\"kpi-strip\">\n @for (metric of KPIMetrics; track metric.Label) {\n <div class=\"kpi-card\" [class]=\"metric.ColorClass\">\n <div class=\"kpi-icon\">\n <i [class]=\"metric.Icon\"></i>\n </div>\n <div class=\"kpi-content\">\n <span class=\"kpi-value\">{{ metric.Value | number }}</span>\n <span class=\"kpi-label\">{{ metric.Label }}</span>\n </div>\n </div>\n }\n </div>\n\n <!-- Pipeline Stages Visualization -->\n <div class=\"pipeline-section\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-diagram-project\"></i> Pipeline Stages\n </h3>\n <div class=\"pipeline-flow\">\n @for (stage of PipelineStages; track stage.Name; let last = $last) {\n <div class=\"pipeline-stage\" [class]=\"'stage-' + stage.Status\">\n <div class=\"stage-icon\">\n <i [class]=\"stage.Icon\"></i>\n </div>\n <span class=\"stage-name\">{{ stage.Name }}</span>\n <span class=\"stage-count\">\n @if (stage.ActiveCount > 0) {\n {{ stage.ActiveCount }} active\n } @else {\n Idle\n }\n </span>\n <div class=\"stage-indicator\"></div>\n </div>\n @if (!last) {\n <div class=\"stage-connector\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </div>\n }\n }\n </div>\n </div>\n\n <!-- Main content area: Feed + Sources sidebar -->\n <div class=\"main-content\">\n <!-- Recent Processing Feed -->\n <div class=\"feed-section\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i> Recent Processing\n </h3>\n <div class=\"feed-list\">\n @if (ProcessedItems.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>No processed items yet.</p>\n </div>\n }\n @for (item of ProcessedItems; track $index) {\n <div class=\"feed-item\">\n <div class=\"feed-item-header\">\n <span class=\"feed-item-name\" [title]=\"item.Name\">{{ item.Name }}</span>\n <span class=\"feed-item-status\" [class]=\"GetStatusClass(item.Status)\">\n {{ item.Status }}\n </span>\n </div>\n <div class=\"feed-item-details\">\n <span class=\"feed-detail\">\n <i class=\"fa-solid fa-database\"></i> {{ item.SourceName }}\n </span>\n <span class=\"feed-detail\">\n <i class=\"fa-solid fa-stopwatch\"></i> {{ FormatDuration(item.ProcessingTimeMs) }}\n </span>\n <span class=\"feed-detail\">\n <i class=\"fa-solid fa-tags\"></i> {{ item.TagCount }} tags\n </span>\n <span class=\"feed-detail feed-time\">\n {{ FormatRelativeTime(item.ProcessedAt) }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Source Configuration Panel (right sidebar) -->\n <div class=\"sources-panel\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-gear\"></i> Content Sources\n </h3>\n <div class=\"sources-list\">\n @if (ContentSources.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-plug-circle-xmark\"></i>\n <p>No sources configured.</p>\n </div>\n }\n @for (source of ContentSources; track source.ID) {\n <div class=\"source-card\">\n <div class=\"source-header\">\n <div class=\"source-icon\">\n <i [class]=\"source.TypeIcon\"></i>\n </div>\n <div class=\"source-info\">\n <span class=\"source-name\">{{ source.Name }}</span>\n <span class=\"source-type\">{{ source.TypeName }}</span>\n </div>\n <span class=\"source-status\" [class]=\"GetStatusClass(source.Status)\">\n {{ source.Status }}\n </span>\n </div>\n <div class=\"source-meta\">\n <span class=\"source-meta-item\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ FormatRelativeTime(source.LastRunAt) }}\n </span>\n <span class=\"source-meta-item\">\n <i class=\"fa-solid fa-file-lines\"></i>\n {{ source.ItemCount | number }} items\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n</div>\n", styles: ["/* ============================================================\n Content Autotagging Pipeline Monitor\n All colors use MJ design tokens \u2014 no hardcoded hex values.\n ============================================================ */\n\n:host {\n display: block;\n height: 100%;\n overflow: hidden;\n}\n\n/* ---- Container ---- */\n\n.autotagging-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px;\n gap: 20px;\n overflow-y: auto;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n}\n\n/* ---- Loading & Error ---- */\n\n.loading-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n}\n\n.error-banner {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n border-radius: 6px;\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.error-banner i {\n font-size: 16px;\n}\n\n.error-banner span {\n flex: 1;\n}\n\n/* ---- Header ---- */\n\n.header-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.header-title {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.header-icon {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.header-title h2 {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.refresh-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 13px;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.refresh-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n}\n\n/* ---- KPI Strip ---- */\n\n.kpi-strip {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n border-radius: 8px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n transition: box-shadow 0.15s;\n}\n\n.kpi-card:hover {\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.kpi-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 10px;\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.kpi-brand .kpi-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-info .kpi-icon {\n background: color-mix(in srgb, var(--mj-status-info) 12%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.kpi-success .kpi-icon {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.kpi-error .kpi-icon {\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.kpi-content {\n display: flex;\n flex-direction: column;\n}\n\n.kpi-value {\n font-size: 22px;\n font-weight: 700;\n line-height: 1.2;\n color: var(--mj-text-primary);\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n/* ---- Pipeline Stages ---- */\n\n.pipeline-section {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 18px 20px;\n}\n\n.section-title {\n margin: 0 0 14px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.section-title i {\n color: var(--mj-text-muted);\n}\n\n.pipeline-flow {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.pipeline-stage {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n padding: 14px 20px;\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n min-width: 100px;\n position: relative;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.stage-icon {\n font-size: 20px;\n color: var(--mj-text-muted);\n}\n\n.stage-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.stage-count {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.stage-indicator {\n position: absolute;\n bottom: 0;\n left: 10%;\n right: 10%;\n height: 3px;\n border-radius: 3px 3px 0 0;\n background: var(--mj-border-subtle);\n transition: background 0.2s;\n}\n\n/* Stage status variants */\n\n.stage-active {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 1px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.stage-active .stage-icon {\n color: var(--mj-brand-primary);\n}\n\n.stage-active .stage-count {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.stage-active .stage-indicator {\n background: var(--mj-brand-primary);\n}\n\n.stage-error {\n border-color: var(--mj-status-error);\n}\n\n.stage-error .stage-icon {\n color: var(--mj-status-error);\n}\n\n.stage-error .stage-indicator {\n background: var(--mj-status-error);\n}\n\n.stage-connector {\n display: flex;\n align-items: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n/* ---- Main Content Area (Feed + Sources) ---- */\n\n.main-content {\n display: grid;\n grid-template-columns: 1fr 320px;\n gap: 20px;\n flex: 1;\n min-height: 0;\n}\n\n/* ---- Recent Processing Feed ---- */\n\n.feed-section {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 18px 20px;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.feed-list {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.feed-item {\n padding: 10px 12px;\n border-radius: 6px;\n transition: background 0.1s;\n}\n\n.feed-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.feed-item-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n}\n\n.feed-item-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 70%;\n}\n\n.feed-item-status {\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.feed-item-details {\n display: flex;\n align-items: center;\n gap: 14px;\n flex-wrap: wrap;\n}\n\n.feed-detail {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.feed-detail i {\n font-size: 10px;\n}\n\n.feed-time {\n margin-left: auto;\n}\n\n/* ---- Source Configuration Panel ---- */\n\n.sources-panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 18px 20px;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.sources-list {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.source-card {\n padding: 12px;\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n transition: border-color 0.15s;\n}\n\n.source-card:hover {\n border-color: var(--mj-border-default);\n}\n\n.source-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 8px;\n}\n\n.source-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.source-info {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n}\n\n.source-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.source-type {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.source-status {\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n flex-shrink: 0;\n}\n\n.source-meta {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n\n.source-meta-item {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.source-meta-item i {\n font-size: 10px;\n}\n\n/* ---- Status Color Variants ---- */\n\n.status-success {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.status-processing {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n\n.status-error {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.status-warning {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n\n.status-default {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n border: 1px solid var(--mj-border-subtle);\n}\n\n/* ---- Empty State ---- */\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 32px 16px;\n color: var(--mj-text-disabled);\n}\n\n.empty-state i {\n font-size: 28px;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 13px;\n}\n\n/* ---- Responsive ---- */\n\n@media (max-width: 1100px) {\n .main-content {\n grid-template-columns: 1fr;\n }\n}\n\n@media (max-width: 768px) {\n .kpi-strip {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .pipeline-flow {\n gap: 6px;\n }\n\n .pipeline-stage {\n min-width: 80px;\n padding: 10px 12px;\n }\n}\n\n@media (max-width: 480px) {\n .kpi-strip {\n grid-template-columns: 1fr;\n }\n\n .pipeline-stage {\n min-width: 70px;\n }\n\n .header-row {\n flex-direction: column;\n align-items: flex-start;\n gap: 10px;\n }\n}\n"] }]
578
+ }], null, null); })();
579
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AutotaggingPipelineResourceComponent, { className: "AutotaggingPipelineResourceComponent", filePath: "src/AI/components/autotagging/autotagging-pipeline-resource.component.ts", lineNumber: 60 }); })();
580
+ export function LoadAutotaggingPipelineResource() {
581
+ // Prevents tree-shaking
582
+ }
583
+ //# sourceMappingURL=autotagging-pipeline-resource.component.js.map