@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,1782 @@
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 Vector Management Resource Component
9
+ *
10
+ * Dashboard resource for managing vector databases and entity vectorization.
11
+ * Displays KPI cards (total vectors, entities synced, last sync, avg embedding time),
12
+ * an entity sync table, and sidebar panels for DB health, embedding model info,
13
+ * and storage usage.
14
+ */
15
+ import { Component, ChangeDetectorRef, Input, inject } from '@angular/core';
16
+ import { Subject } from 'rxjs';
17
+ import { takeUntil } from 'rxjs/operators';
18
+ import { Metadata, RunView } from '@memberjunction/core';
19
+ import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
20
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
21
+ import { GraphQLAIClient } from '@memberjunction/graphql-dataprovider';
22
+ import { AIEngineBase } from '@memberjunction/ai-engine-base';
23
+ import { MJNotificationService } from '@memberjunction/ng-notifications';
24
+ import * as i0 from "@angular/core";
25
+ import * as i1 from "@angular/forms";
26
+ import * as i2 from "@memberjunction/ng-code-editor";
27
+ import * as i3 from "@memberjunction/ng-shared-generic";
28
+ import * as i4 from "../widgets/kpi-card.component";
29
+ import * as i5 from "@angular/common";
30
+ const _forTrack0 = ($index, $item) => $item.title;
31
+ const _forTrack1 = ($index, $item) => $item.EntityDocumentID;
32
+ const _forTrack2 = ($index, $item) => $item.ID;
33
+ const _forTrack3 = ($index, $item) => $item.SchemaName;
34
+ const _forTrack4 = ($index, $item) => $item.name;
35
+ function VectorManagementResourceComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
36
+ i0.ɵɵelementStart(0, "div", 0);
37
+ i0.ɵɵelement(1, "mj-loading", 1);
38
+ i0.ɵɵelementEnd();
39
+ } }
40
+ function VectorManagementResourceComponent_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
41
+ const _r2 = i0.ɵɵgetCurrentView();
42
+ i0.ɵɵelementStart(0, "div", 3)(1, "button", 39);
43
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.ViewMode = "index"); });
44
+ i0.ɵɵelement(2, "i", 40);
45
+ i0.ɵɵtext(3, " Index View ");
46
+ i0.ɵɵelementEnd();
47
+ i0.ɵɵelementStart(4, "button", 39);
48
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_1_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.ViewMode = "operations"); });
49
+ i0.ɵɵelement(5, "i", 41);
50
+ i0.ɵɵtext(6, " Operations ");
51
+ i0.ɵɵelementEnd()();
52
+ } if (rf & 2) {
53
+ const ctx_r2 = i0.ɵɵnextContext(2);
54
+ i0.ɵɵadvance();
55
+ i0.ɵɵclassProp("view-mode-btn-active", ctx_r2.ViewMode === "index");
56
+ i0.ɵɵadvance(3);
57
+ i0.ɵɵclassProp("view-mode-btn-active", ctx_r2.ViewMode === "operations");
58
+ } }
59
+ function VectorManagementResourceComponent_Conditional_1_For_4_Template(rf, ctx) { if (rf & 1) {
60
+ i0.ɵɵelement(0, "app-kpi-card", 5);
61
+ } if (rf & 2) {
62
+ const card_r4 = ctx.$implicit;
63
+ i0.ɵɵproperty("data", card_r4);
64
+ } }
65
+ function VectorManagementResourceComponent_Conditional_1_Conditional_19_Template(rf, ctx) { if (rf & 1) {
66
+ i0.ɵɵelementStart(0, "div", 17);
67
+ i0.ɵɵelement(1, "i", 42);
68
+ i0.ɵɵelementStart(2, "p");
69
+ i0.ɵɵtext(3, "No entity documents configured for vectorization.");
70
+ i0.ɵɵelementEnd()();
71
+ } }
72
+ function VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Conditional_13_Template(rf, ctx) { if (rf & 1) {
73
+ i0.ɵɵtext(0);
74
+ } if (rf & 2) {
75
+ const row_r6 = i0.ɵɵnextContext().$implicit;
76
+ i0.ɵɵtextInterpolate1(" ", row_r6.PercentComplete, "% ");
77
+ } }
78
+ function VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Conditional_14_Template(rf, ctx) { if (rf & 1) {
79
+ i0.ɵɵtext(0);
80
+ } if (rf & 2) {
81
+ const row_r6 = i0.ɵɵnextContext().$implicit;
82
+ i0.ɵɵtextInterpolate1(" ", row_r6.Status, " ");
83
+ } }
84
+ function VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Conditional_17_Template(rf, ctx) { if (rf & 1) {
85
+ i0.ɵɵelement(0, "i", 55);
86
+ i0.ɵɵtext(1);
87
+ } if (rf & 2) {
88
+ const row_r6 = i0.ɵɵnextContext().$implicit;
89
+ i0.ɵɵadvance();
90
+ i0.ɵɵtextInterpolate1(" ", row_r6.PercentComplete > 0 ? row_r6.PercentComplete + "%" : "Sync", " ");
91
+ } }
92
+ function VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Conditional_18_Template(rf, ctx) { if (rf & 1) {
93
+ i0.ɵɵelement(0, "i", 56);
94
+ i0.ɵɵtext(1, " Sync ");
95
+ } }
96
+ function VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Template(rf, ctx) { if (rf & 1) {
97
+ const _r5 = i0.ɵɵgetCurrentView();
98
+ i0.ɵɵelementStart(0, "tr")(1, "td", 46);
99
+ i0.ɵɵtext(2);
100
+ i0.ɵɵelementEnd();
101
+ i0.ɵɵelementStart(3, "td", 47);
102
+ i0.ɵɵtext(4);
103
+ i0.ɵɵelementEnd();
104
+ i0.ɵɵelementStart(5, "td", 48);
105
+ i0.ɵɵtext(6);
106
+ i0.ɵɵpipe(7, "number");
107
+ i0.ɵɵelementEnd();
108
+ i0.ɵɵelementStart(8, "td", 49);
109
+ i0.ɵɵtext(9);
110
+ i0.ɵɵelementEnd();
111
+ i0.ɵɵelementStart(10, "td")(11, "span", 50);
112
+ i0.ɵɵelement(12, "i");
113
+ i0.ɵɵconditionalCreate(13, VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Conditional_13_Template, 1, 1)(14, VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Conditional_14_Template, 1, 1);
114
+ i0.ɵɵelementEnd()();
115
+ i0.ɵɵelementStart(15, "td", 51)(16, "button", 52);
116
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Template_button_click_16_listener() { const row_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SyncEntity(row_r6.EntityDocumentID)); });
117
+ i0.ɵɵconditionalCreate(17, VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Conditional_17_Template, 2, 1)(18, VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Conditional_18_Template, 2, 0);
118
+ i0.ɵɵelementEnd();
119
+ i0.ɵɵelementStart(19, "button", 53);
120
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Template_button_click_19_listener() { const row_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OpenEditPanel(row_r6.EntityDocumentID)); });
121
+ i0.ɵɵelement(20, "i", 54);
122
+ i0.ɵɵelementEnd()()();
123
+ } if (rf & 2) {
124
+ const row_r6 = ctx.$implicit;
125
+ const ctx_r2 = i0.ɵɵnextContext(3);
126
+ i0.ɵɵadvance(2);
127
+ i0.ɵɵtextInterpolate(row_r6.EntityName);
128
+ i0.ɵɵadvance(2);
129
+ i0.ɵɵtextInterpolate(row_r6.DocumentName);
130
+ i0.ɵɵadvance(2);
131
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(7, 11, row_r6.VectorCount));
132
+ i0.ɵɵadvance(3);
133
+ i0.ɵɵtextInterpolate(ctx_r2.FormatDate(row_r6.LastSynced));
134
+ i0.ɵɵadvance(2);
135
+ i0.ɵɵclassMap(ctx_r2.GetStatusClass(row_r6.Status));
136
+ i0.ɵɵadvance();
137
+ i0.ɵɵclassMap(ctx_r2.GetStatusIcon(row_r6.Status));
138
+ i0.ɵɵadvance();
139
+ i0.ɵɵconditional(row_r6.Status === "Syncing" && row_r6.PercentComplete > 0 ? 13 : 14);
140
+ i0.ɵɵadvance(3);
141
+ i0.ɵɵproperty("disabled", ctx_r2.SyncingIds.has(row_r6.EntityDocumentID));
142
+ i0.ɵɵadvance();
143
+ i0.ɵɵconditional(ctx_r2.SyncingIds.has(row_r6.EntityDocumentID) ? 17 : 18);
144
+ } }
145
+ function VectorManagementResourceComponent_Conditional_1_Conditional_20_Template(rf, ctx) { if (rf & 1) {
146
+ i0.ɵɵelementStart(0, "div", 18)(1, "table", 43)(2, "thead")(3, "tr")(4, "th");
147
+ i0.ɵɵtext(5, "Entity");
148
+ i0.ɵɵelementEnd();
149
+ i0.ɵɵelementStart(6, "th");
150
+ i0.ɵɵtext(7, "Document");
151
+ i0.ɵɵelementEnd();
152
+ i0.ɵɵelementStart(8, "th", 44);
153
+ i0.ɵɵtext(9, "Vectors");
154
+ i0.ɵɵelementEnd();
155
+ i0.ɵɵelementStart(10, "th");
156
+ i0.ɵɵtext(11, "Last Synced");
157
+ i0.ɵɵelementEnd();
158
+ i0.ɵɵelementStart(12, "th");
159
+ i0.ɵɵtext(13, "Status");
160
+ i0.ɵɵelementEnd();
161
+ i0.ɵɵelementStart(14, "th", 45);
162
+ i0.ɵɵtext(15, "Actions");
163
+ i0.ɵɵelementEnd()()();
164
+ i0.ɵɵelementStart(16, "tbody");
165
+ i0.ɵɵrepeaterCreate(17, VectorManagementResourceComponent_Conditional_1_Conditional_20_For_18_Template, 21, 13, "tr", null, _forTrack1);
166
+ i0.ɵɵelementEnd()()();
167
+ } if (rf & 2) {
168
+ const ctx_r2 = i0.ɵɵnextContext(2);
169
+ i0.ɵɵadvance(17);
170
+ i0.ɵɵrepeater(ctx_r2.SyncRows);
171
+ } }
172
+ function VectorManagementResourceComponent_Conditional_1_Conditional_42_Template(rf, ctx) { if (rf & 1) {
173
+ i0.ɵɵelementStart(0, "div", 29)(1, "span", 30);
174
+ i0.ɵɵtext(2, "Dimensions");
175
+ i0.ɵɵelementEnd();
176
+ i0.ɵɵelementStart(3, "span", 31);
177
+ i0.ɵɵtext(4);
178
+ i0.ɵɵpipe(5, "number");
179
+ i0.ɵɵelementEnd()();
180
+ } if (rf & 2) {
181
+ const ctx_r2 = i0.ɵɵnextContext(2);
182
+ i0.ɵɵadvance(4);
183
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(5, 1, ctx_r2.EmbeddingModel.Dimensions));
184
+ } }
185
+ function VectorManagementResourceComponent_Conditional_1_Conditional_55_For_24_Template(rf, ctx) { if (rf & 1) {
186
+ i0.ɵɵelementStart(0, "option", 70);
187
+ i0.ɵɵtext(1);
188
+ i0.ɵɵelementEnd();
189
+ } if (rf & 2) {
190
+ const model_r8 = ctx.$implicit;
191
+ i0.ɵɵproperty("value", model_r8.ID);
192
+ i0.ɵɵadvance();
193
+ i0.ɵɵtextInterpolate(model_r8.Name);
194
+ } }
195
+ function VectorManagementResourceComponent_Conditional_1_Conditional_55_For_30_Template(rf, ctx) { if (rf & 1) {
196
+ i0.ɵɵelementStart(0, "option", 70);
197
+ i0.ɵɵtext(1);
198
+ i0.ɵɵelementEnd();
199
+ } if (rf & 2) {
200
+ const db_r9 = ctx.$implicit;
201
+ i0.ɵɵproperty("value", db_r9.ID);
202
+ i0.ɵɵadvance();
203
+ i0.ɵɵtextInterpolate(db_r9.Name);
204
+ } }
205
+ function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_34_For_4_Template(rf, ctx) { if (rf & 1) {
206
+ i0.ɵɵelementStart(0, "option", 70);
207
+ i0.ɵɵtext(1);
208
+ i0.ɵɵelementEnd();
209
+ } if (rf & 2) {
210
+ const idx_r11 = ctx.$implicit;
211
+ i0.ɵɵproperty("value", idx_r11.ID);
212
+ i0.ɵɵadvance();
213
+ i0.ɵɵtextInterpolate(idx_r11.Name);
214
+ } }
215
+ function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_34_Template(rf, ctx) { if (rf & 1) {
216
+ const _r10 = i0.ɵɵgetCurrentView();
217
+ i0.ɵɵelementStart(0, "select", 69);
218
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_34_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r2.EditDocVectorIndexID, $event) || (ctx_r2.EditDocVectorIndexID = $event); return i0.ɵɵresetView($event); });
219
+ i0.ɵɵelementStart(1, "option", 77);
220
+ i0.ɵɵtext(2, "Auto (create/find matching index)");
221
+ i0.ɵɵelementEnd();
222
+ i0.ɵɵrepeaterCreate(3, VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_34_For_4_Template, 2, 2, "option", 70, _forTrack2);
223
+ i0.ɵɵelementEnd();
224
+ } if (rf & 2) {
225
+ const ctx_r2 = i0.ɵɵnextContext(3);
226
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.EditDocVectorIndexID);
227
+ i0.ɵɵadvance(3);
228
+ i0.ɵɵrepeater(ctx_r2.EditFilteredIndexes);
229
+ } }
230
+ function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_35_Template(rf, ctx) { if (rf & 1) {
231
+ i0.ɵɵelementStart(0, "span", 72);
232
+ i0.ɵɵtext(1, " No indexes for this database \u2014 one will be created automatically on sync ");
233
+ i0.ɵɵelementEnd();
234
+ } }
235
+ function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_45_Template(rf, ctx) { if (rf & 1) {
236
+ i0.ɵɵelement(0, "mj-loading", 76);
237
+ } }
238
+ function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_46_Template(rf, ctx) { if (rf & 1) {
239
+ const _r12 = i0.ɵɵgetCurrentView();
240
+ i0.ɵɵelementStart(0, "button", 78);
241
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_46_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SaveEditedDocument()); });
242
+ i0.ɵɵelement(1, "i", 79);
243
+ i0.ɵɵtext(2, " Save Changes ");
244
+ i0.ɵɵelementEnd();
245
+ i0.ɵɵelementStart(3, "button", 80);
246
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_46_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.DeleteEntityDocument()); });
247
+ i0.ɵɵelement(4, "i", 81);
248
+ i0.ɵɵtext(5, " Delete ");
249
+ i0.ɵɵelementEnd();
250
+ i0.ɵɵelementStart(6, "button", 82);
251
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_46_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.CloseEditPanel()); });
252
+ i0.ɵɵtext(7, " Cancel ");
253
+ i0.ɵɵelementEnd();
254
+ } }
255
+ function VectorManagementResourceComponent_Conditional_1_Conditional_55_Template(rf, ctx) { if (rf & 1) {
256
+ const _r7 = i0.ɵɵgetCurrentView();
257
+ i0.ɵɵelementStart(0, "div", 57);
258
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.CloseEditPanel()); });
259
+ i0.ɵɵelementStart(1, "div", 58);
260
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r7); return i0.ɵɵresetView($event.stopPropagation()); });
261
+ i0.ɵɵelementStart(2, "div", 59)(3, "h3", 60);
262
+ i0.ɵɵelement(4, "i", 54);
263
+ i0.ɵɵtext(5, " Edit Entity Document ");
264
+ i0.ɵɵelementEnd();
265
+ i0.ɵɵelementStart(6, "button", 61);
266
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.CloseEditPanel()); });
267
+ i0.ɵɵelement(7, "i", 62);
268
+ i0.ɵɵelementEnd()();
269
+ i0.ɵɵelementStart(8, "div", 63)(9, "div", 64)(10, "div", 65)(11, "label", 66);
270
+ i0.ɵɵtext(12, "Entity");
271
+ i0.ɵɵelementEnd();
272
+ i0.ɵɵelementStart(13, "span", 67);
273
+ i0.ɵɵtext(14);
274
+ i0.ɵɵelementEnd()();
275
+ i0.ɵɵelementStart(15, "div", 65)(16, "label", 66);
276
+ i0.ɵɵtext(17, "Document Name");
277
+ i0.ɵɵelementEnd();
278
+ i0.ɵɵelementStart(18, "input", 68);
279
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Template_input_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.EditDocName, $event) || (ctx_r2.EditDocName = $event); return i0.ɵɵresetView($event); });
280
+ i0.ɵɵelementEnd()();
281
+ i0.ɵɵelementStart(19, "div", 65)(20, "label", 66);
282
+ i0.ɵɵtext(21, "Embedding Model");
283
+ i0.ɵɵelementEnd();
284
+ i0.ɵɵelementStart(22, "select", 69);
285
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Template_select_ngModelChange_22_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.EditDocAIModelID, $event) || (ctx_r2.EditDocAIModelID = $event); return i0.ɵɵresetView($event); });
286
+ i0.ɵɵrepeaterCreate(23, VectorManagementResourceComponent_Conditional_1_Conditional_55_For_24_Template, 2, 2, "option", 70, _forTrack2);
287
+ i0.ɵɵelementEnd()();
288
+ i0.ɵɵelementStart(25, "div", 65)(26, "label", 66);
289
+ i0.ɵɵtext(27, "Vector Database");
290
+ i0.ɵɵelementEnd();
291
+ i0.ɵɵelementStart(28, "select", 69);
292
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Template_select_ngModelChange_28_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.EditDocVectorDBID, $event) || (ctx_r2.EditDocVectorDBID = $event); return i0.ɵɵresetView($event); });
293
+ i0.ɵɵrepeaterCreate(29, VectorManagementResourceComponent_Conditional_1_Conditional_55_For_30_Template, 2, 2, "option", 70, _forTrack2);
294
+ i0.ɵɵelementEnd()();
295
+ i0.ɵɵelementStart(31, "div", 65)(32, "label", 66);
296
+ i0.ɵɵtext(33, "Vector Index");
297
+ i0.ɵɵelementEnd();
298
+ i0.ɵɵconditionalCreate(34, VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_34_Template, 5, 1, "select", 71)(35, VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_35_Template, 2, 0, "span", 72);
299
+ i0.ɵɵelementEnd();
300
+ i0.ɵɵelementStart(36, "div", 65)(37, "label", 66);
301
+ i0.ɵɵtext(38, "Status");
302
+ i0.ɵɵelementEnd();
303
+ i0.ɵɵelementStart(39, "select", 69);
304
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_55_Template_select_ngModelChange_39_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.EditDocStatus, $event) || (ctx_r2.EditDocStatus = $event); return i0.ɵɵresetView($event); });
305
+ i0.ɵɵelementStart(40, "option", 73);
306
+ i0.ɵɵtext(41, "Active");
307
+ i0.ɵɵelementEnd();
308
+ i0.ɵɵelementStart(42, "option", 74);
309
+ i0.ɵɵtext(43, "Inactive");
310
+ i0.ɵɵelementEnd()()();
311
+ i0.ɵɵelementStart(44, "div", 75);
312
+ i0.ɵɵconditionalCreate(45, VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_45_Template, 1, 0, "mj-loading", 76)(46, VectorManagementResourceComponent_Conditional_1_Conditional_55_Conditional_46_Template, 8, 0);
313
+ i0.ɵɵelementEnd()()()()();
314
+ } if (rf & 2) {
315
+ const ctx_r2 = i0.ɵɵnextContext(2);
316
+ i0.ɵɵadvance(14);
317
+ i0.ɵɵtextInterpolate(ctx_r2.EditDocEntityName);
318
+ i0.ɵɵadvance(4);
319
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.EditDocName);
320
+ i0.ɵɵadvance(4);
321
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.EditDocAIModelID);
322
+ i0.ɵɵadvance();
323
+ i0.ɵɵrepeater(ctx_r2.AvailableEmbeddingModels);
324
+ i0.ɵɵadvance(5);
325
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.EditDocVectorDBID);
326
+ i0.ɵɵadvance();
327
+ i0.ɵɵrepeater(ctx_r2.vectorDatabases);
328
+ i0.ɵɵadvance(5);
329
+ i0.ɵɵconditional(ctx_r2.EditFilteredIndexes.length > 0 ? 34 : 35);
330
+ i0.ɵɵadvance(5);
331
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.EditDocStatus);
332
+ i0.ɵɵadvance(6);
333
+ i0.ɵɵconditional(ctx_r2.IsEditSaving || ctx_r2.IsEditDeleting ? 45 : 46);
334
+ } }
335
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_6_Template(rf, ctx) { if (rf & 1) {
336
+ i0.ɵɵelement(0, "i", 96);
337
+ i0.ɵɵelementStart(1, "span", 97);
338
+ i0.ɵɵtext(2);
339
+ i0.ɵɵelementEnd();
340
+ } if (rf & 2) {
341
+ const ctx_r2 = i0.ɵɵnextContext(4);
342
+ i0.ɵɵadvance(2);
343
+ i0.ɵɵtextInterpolate(ctx_r2.SuggestEntityName);
344
+ } }
345
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_7_Template(rf, ctx) { if (rf & 1) {
346
+ i0.ɵɵelement(0, "i", 98);
347
+ i0.ɵɵelementStart(1, "span", 99);
348
+ i0.ɵɵtext(2, "Search and select an entity...");
349
+ i0.ɵɵelementEnd();
350
+ } }
351
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_For_6_For_5_Template(rf, ctx) { if (rf & 1) {
352
+ const _r16 = i0.ɵɵgetCurrentView();
353
+ i0.ɵɵelementStart(0, "button", 108);
354
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_For_6_For_5_Template_button_click_0_listener() { const entity_r17 = i0.ɵɵrestoreView(_r16).$implicit; const ctx_r2 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r2.SelectEntity(entity_r17.Name)); });
355
+ i0.ɵɵelement(1, "i", 96);
356
+ i0.ɵɵtext(2);
357
+ i0.ɵɵelementEnd();
358
+ } if (rf & 2) {
359
+ const entity_r17 = ctx.$implicit;
360
+ const ctx_r2 = i0.ɵɵnextContext(6);
361
+ i0.ɵɵclassProp("entity-picker-item-selected", entity_r17.Name === ctx_r2.SuggestEntityName);
362
+ i0.ɵɵadvance(2);
363
+ i0.ɵɵtextInterpolate1(" ", entity_r17.Name, " ");
364
+ } }
365
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_For_6_Template(rf, ctx) { if (rf & 1) {
366
+ i0.ɵɵelementStart(0, "div", 103)(1, "div", 105);
367
+ i0.ɵɵelement(2, "i", 106);
368
+ i0.ɵɵtext(3);
369
+ i0.ɵɵelementEnd();
370
+ i0.ɵɵrepeaterCreate(4, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_For_6_For_5_Template, 3, 3, "button", 107, _forTrack2);
371
+ i0.ɵɵelementEnd();
372
+ } if (rf & 2) {
373
+ const group_r18 = ctx.$implicit;
374
+ i0.ɵɵadvance(3);
375
+ i0.ɵɵtextInterpolate1(" ", group_r18.SchemaName, " ");
376
+ i0.ɵɵadvance();
377
+ i0.ɵɵrepeater(group_r18.Entities);
378
+ } }
379
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_Conditional_7_Template(rf, ctx) { if (rf & 1) {
380
+ i0.ɵɵelementStart(0, "div", 104);
381
+ i0.ɵɵtext(1);
382
+ i0.ɵɵelementEnd();
383
+ } if (rf & 2) {
384
+ const ctx_r2 = i0.ɵɵnextContext(5);
385
+ i0.ɵɵadvance();
386
+ i0.ɵɵtextInterpolate1(" No entities matching \"", ctx_r2.EntitySearchText, "\" ");
387
+ } }
388
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_Template(rf, ctx) { if (rf & 1) {
389
+ const _r15 = i0.ɵɵgetCurrentView();
390
+ i0.ɵɵelementStart(0, "div", 88)(1, "div", 100);
391
+ i0.ɵɵelement(2, "i", 98);
392
+ i0.ɵɵelementStart(3, "input", 101);
393
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_Template_input_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r2.EntitySearchText, $event) || (ctx_r2.EntitySearchText = $event); return i0.ɵɵresetView($event); });
394
+ i0.ɵɵlistener("input", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_Template_input_input_3_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.FilterEntities()); });
395
+ i0.ɵɵelementEnd()();
396
+ i0.ɵɵelementStart(4, "div", 102);
397
+ i0.ɵɵrepeaterCreate(5, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_For_6_Template, 6, 1, "div", 103, _forTrack3);
398
+ i0.ɵɵconditionalCreate(7, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_Conditional_7_Template, 2, 1, "div", 104);
399
+ i0.ɵɵelementEnd()();
400
+ } if (rf & 2) {
401
+ const ctx_r2 = i0.ɵɵnextContext(4);
402
+ i0.ɵɵadvance(3);
403
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.EntitySearchText);
404
+ i0.ɵɵadvance(2);
405
+ i0.ɵɵrepeater(ctx_r2.FilteredEntityGroups);
406
+ i0.ɵɵadvance(2);
407
+ i0.ɵɵconditional(ctx_r2.FilteredEntityGroups.length === 0 ? 7 : -1);
408
+ } }
409
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_24_Template(rf, ctx) { if (rf & 1) {
410
+ i0.ɵɵelement(0, "i", 55);
411
+ i0.ɵɵtext(1, " Generating with AI... ");
412
+ } }
413
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_25_Template(rf, ctx) { if (rf & 1) {
414
+ i0.ɵɵelement(0, "i", 13);
415
+ i0.ɵɵtext(1, " Generate Template ");
416
+ } }
417
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_26_Template(rf, ctx) { if (rf & 1) {
418
+ i0.ɵɵelementStart(0, "div", 95);
419
+ i0.ɵɵelement(1, "i", 109);
420
+ i0.ɵɵtext(2);
421
+ i0.ɵɵelementEnd();
422
+ } if (rf & 2) {
423
+ const ctx_r2 = i0.ɵɵnextContext(4);
424
+ i0.ɵɵadvance(2);
425
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.SuggestionError, " ");
426
+ } }
427
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Template(rf, ctx) { if (rf & 1) {
428
+ const _r14 = i0.ɵɵgetCurrentView();
429
+ i0.ɵɵelementStart(0, "div", 64)(1, "div", 65)(2, "label", 66);
430
+ i0.ɵɵtext(3, "Entity");
431
+ i0.ɵɵelementEnd();
432
+ i0.ɵɵelementStart(4, "div", 85)(5, "button", 86);
433
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.ToggleEntityPicker()); });
434
+ i0.ɵɵconditionalCreate(6, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_6_Template, 3, 1)(7, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_7_Template, 3, 0);
435
+ i0.ɵɵelement(8, "i", 87);
436
+ i0.ɵɵelementEnd();
437
+ i0.ɵɵconditionalCreate(9, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_9_Template, 8, 2, "div", 88);
438
+ i0.ɵɵelementEnd()();
439
+ i0.ɵɵelementStart(10, "div", 65)(11, "label", 66);
440
+ i0.ɵɵtext(12, "Use Case");
441
+ i0.ɵɵelementEnd();
442
+ i0.ɵɵelementStart(13, "div", 89)(14, "button", 90);
443
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SuggestUseCase = "duplicate detection"); });
444
+ i0.ɵɵelement(15, "i", 91);
445
+ i0.ɵɵtext(16, " Duplicate Detection ");
446
+ i0.ɵɵelementEnd();
447
+ i0.ɵɵelementStart(17, "button", 90);
448
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SuggestUseCase = "search"); });
449
+ i0.ɵɵelement(18, "i", 92);
450
+ i0.ɵɵtext(19, " Search ");
451
+ i0.ɵɵelementEnd();
452
+ i0.ɵɵelementStart(20, "button", 90);
453
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SuggestUseCase = "classification"); });
454
+ i0.ɵɵelement(21, "i", 93);
455
+ i0.ɵɵtext(22, " Classification ");
456
+ i0.ɵɵelementEnd()()();
457
+ i0.ɵɵelementStart(23, "button", 94);
458
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.RunSuggestion()); });
459
+ i0.ɵɵconditionalCreate(24, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_24_Template, 2, 0)(25, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_25_Template, 2, 0);
460
+ i0.ɵɵelementEnd();
461
+ i0.ɵɵconditionalCreate(26, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Conditional_26_Template, 3, 1, "div", 95);
462
+ i0.ɵɵelementEnd();
463
+ } if (rf & 2) {
464
+ const ctx_r2 = i0.ɵɵnextContext(3);
465
+ i0.ɵɵadvance(6);
466
+ i0.ɵɵconditional(ctx_r2.SuggestEntityName ? 6 : 7);
467
+ i0.ɵɵadvance(3);
468
+ i0.ɵɵconditional(ctx_r2.ShowEntityPicker ? 9 : -1);
469
+ i0.ɵɵadvance(5);
470
+ i0.ɵɵclassProp("use-case-btn-active", ctx_r2.SuggestUseCase === "duplicate detection");
471
+ i0.ɵɵadvance(3);
472
+ i0.ɵɵclassProp("use-case-btn-active", ctx_r2.SuggestUseCase === "search");
473
+ i0.ɵɵadvance(3);
474
+ i0.ɵɵclassProp("use-case-btn-active", ctx_r2.SuggestUseCase === "classification");
475
+ i0.ɵɵadvance(3);
476
+ i0.ɵɵproperty("disabled", ctx_r2.IsSuggesting || !ctx_r2.SuggestEntityName);
477
+ i0.ɵɵadvance();
478
+ i0.ɵɵconditional(ctx_r2.IsSuggesting ? 24 : 25);
479
+ i0.ɵɵadvance(2);
480
+ i0.ɵɵconditional(ctx_r2.SuggestionError ? 26 : -1);
481
+ } }
482
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_For_11_Template(rf, ctx) { if (rf & 1) {
483
+ i0.ɵɵelementStart(0, "span", 115);
484
+ i0.ɵɵtext(1);
485
+ i0.ɵɵelementEnd();
486
+ } if (rf & 2) {
487
+ const field_r20 = ctx.$implicit;
488
+ i0.ɵɵadvance();
489
+ i0.ɵɵtextInterpolate(field_r20);
490
+ } }
491
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_12_For_4_Template(rf, ctx) { if (rf & 1) {
492
+ i0.ɵɵelementStart(0, "div", 124)(1, "span", 125);
493
+ i0.ɵɵtext(2);
494
+ i0.ɵɵelementEnd();
495
+ i0.ɵɵelementStart(3, "span", 126);
496
+ i0.ɵɵtext(4);
497
+ i0.ɵɵelementEnd()();
498
+ } if (rf & 2) {
499
+ const rel_r21 = ctx.$implicit;
500
+ i0.ɵɵadvance(2);
501
+ i0.ɵɵtextInterpolate(rel_r21.name);
502
+ i0.ɵɵadvance(2);
503
+ i0.ɵɵtextInterpolate(rel_r21.fields.join(", "));
504
+ } }
505
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_12_Template(rf, ctx) { if (rf & 1) {
506
+ i0.ɵɵelementStart(0, "div", 110)(1, "h4", 111);
507
+ i0.ɵɵtext(2, "Related Entities");
508
+ i0.ɵɵelementEnd();
509
+ i0.ɵɵrepeaterCreate(3, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_12_For_4_Template, 5, 2, "div", 124, _forTrack4);
510
+ i0.ɵɵelementEnd();
511
+ } if (rf & 2) {
512
+ const ctx_r2 = i0.ɵɵnextContext(4);
513
+ i0.ɵɵadvance(3);
514
+ i0.ɵɵrepeater(ctx_r2.SuggestionResult.selectedRelationships);
515
+ } }
516
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_For_39_Template(rf, ctx) { if (rf & 1) {
517
+ i0.ɵɵelementStart(0, "option", 70);
518
+ i0.ɵɵtext(1);
519
+ i0.ɵɵelementEnd();
520
+ } if (rf & 2) {
521
+ const model_r22 = ctx.$implicit;
522
+ i0.ɵɵproperty("value", model_r22.ID);
523
+ i0.ɵɵadvance();
524
+ i0.ɵɵtextInterpolate(model_r22.Name);
525
+ } }
526
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_For_45_Template(rf, ctx) { if (rf & 1) {
527
+ i0.ɵɵelementStart(0, "option", 70);
528
+ i0.ɵɵtext(1);
529
+ i0.ɵɵelementEnd();
530
+ } if (rf & 2) {
531
+ const db_r23 = ctx.$implicit;
532
+ i0.ɵɵproperty("value", db_r23.ID);
533
+ i0.ɵɵadvance();
534
+ i0.ɵɵtextInterpolate(db_r23.Name);
535
+ } }
536
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_49_For_4_Template(rf, ctx) { if (rf & 1) {
537
+ i0.ɵɵelementStart(0, "option", 70);
538
+ i0.ɵɵtext(1);
539
+ i0.ɵɵelementEnd();
540
+ } if (rf & 2) {
541
+ const idx_r25 = ctx.$implicit;
542
+ i0.ɵɵproperty("value", idx_r25.ID);
543
+ i0.ɵɵadvance();
544
+ i0.ɵɵtextInterpolate(idx_r25.Name);
545
+ } }
546
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_49_Template(rf, ctx) { if (rf & 1) {
547
+ const _r24 = i0.ɵɵgetCurrentView();
548
+ i0.ɵɵelementStart(0, "select", 69);
549
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_49_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r2 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r2.SelectedVectorIndexID, $event) || (ctx_r2.SelectedVectorIndexID = $event); return i0.ɵɵresetView($event); });
550
+ i0.ɵɵelementStart(1, "option", 77);
551
+ i0.ɵɵtext(2, "Auto (create/find matching index)");
552
+ i0.ɵɵelementEnd();
553
+ i0.ɵɵrepeaterCreate(3, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_49_For_4_Template, 2, 2, "option", 70, _forTrack2);
554
+ i0.ɵɵelementEnd();
555
+ } if (rf & 2) {
556
+ const ctx_r2 = i0.ɵɵnextContext(4);
557
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.SelectedVectorIndexID);
558
+ i0.ɵɵadvance(3);
559
+ i0.ɵɵrepeater(ctx_r2.FilteredIndexesForSelectedDB);
560
+ } }
561
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_50_Template(rf, ctx) { if (rf & 1) {
562
+ i0.ɵɵelementStart(0, "span", 72);
563
+ i0.ɵɵtext(1, " No indexes yet \u2014 create one in Configuration > Vector Database, or one will be created on sync ");
564
+ i0.ɵɵelementEnd();
565
+ } }
566
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_52_Template(rf, ctx) { if (rf & 1) {
567
+ i0.ɵɵelementStart(0, "div", 123);
568
+ i0.ɵɵelement(1, "mj-loading", 76);
569
+ i0.ɵɵelementEnd();
570
+ } }
571
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_53_Template(rf, ctx) { if (rf & 1) {
572
+ const _r26 = i0.ɵɵgetCurrentView();
573
+ i0.ɵɵelementStart(0, "button", 78);
574
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_53_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r26); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.SaveAsEntityDocument()); });
575
+ i0.ɵɵelement(1, "i", 127);
576
+ i0.ɵɵtext(2, " Save as Entity Document ");
577
+ i0.ɵɵelementEnd();
578
+ i0.ɵɵelementStart(3, "button", 128);
579
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_53_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r26); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.ClearSuggestion()); });
580
+ i0.ɵɵelement(4, "i", 129);
581
+ i0.ɵɵtext(5, " Try Again ");
582
+ i0.ɵɵelementEnd();
583
+ i0.ɵɵelementStart(6, "button", 82);
584
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_53_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r26); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.CloseSuggestDialog()); });
585
+ i0.ɵɵtext(7, " Close ");
586
+ i0.ɵɵelementEnd();
587
+ } }
588
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Template(rf, ctx) { if (rf & 1) {
589
+ const _r19 = i0.ɵɵgetCurrentView();
590
+ i0.ɵɵelementStart(0, "div", 84)(1, "div", 110)(2, "h4", 111);
591
+ i0.ɵɵtext(3, "Suggested Template");
592
+ i0.ɵɵelementEnd();
593
+ i0.ɵɵelementStart(4, "div", 112)(5, "mj-code-editor", 113);
594
+ i0.ɵɵlistener("change", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Template_mj_code_editor_change_5_listener($event) { i0.ɵɵrestoreView(_r19); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnTemplateChange($event)); });
595
+ i0.ɵɵelementEnd()()();
596
+ i0.ɵɵelementStart(6, "div", 110)(7, "h4", 111);
597
+ i0.ɵɵtext(8, "Selected Fields");
598
+ i0.ɵɵelementEnd();
599
+ i0.ɵɵelementStart(9, "div", 114);
600
+ i0.ɵɵrepeaterCreate(10, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_For_11_Template, 2, 1, "span", 115, i0.ɵɵrepeaterTrackByIdentity);
601
+ i0.ɵɵelementEnd()();
602
+ i0.ɵɵconditionalCreate(12, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_12_Template, 5, 0, "div", 110);
603
+ i0.ɵɵelementStart(13, "div", 116)(14, "div", 117)(15, "span", 118);
604
+ i0.ɵɵtext(16, "Potential Match");
605
+ i0.ɵɵelementEnd();
606
+ i0.ɵɵelementStart(17, "span", 119);
607
+ i0.ɵɵtext(18);
608
+ i0.ɵɵelementEnd()();
609
+ i0.ɵɵelementStart(19, "div", 117)(20, "span", 118);
610
+ i0.ɵɵtext(21, "Absolute Match");
611
+ i0.ɵɵelementEnd();
612
+ i0.ɵɵelementStart(22, "span", 119);
613
+ i0.ɵɵtext(23);
614
+ i0.ɵɵelementEnd()()();
615
+ i0.ɵɵelementStart(24, "div", 110)(25, "h4", 111);
616
+ i0.ɵɵtext(26, "Reasoning");
617
+ i0.ɵɵelementEnd();
618
+ i0.ɵɵelementStart(27, "p", 120);
619
+ i0.ɵɵtext(28);
620
+ i0.ɵɵelementEnd()();
621
+ i0.ɵɵelementStart(29, "div", 110)(30, "div", 65)(31, "label", 66);
622
+ i0.ɵɵtext(32, "Document Name");
623
+ i0.ɵɵelementEnd();
624
+ i0.ɵɵelementStart(33, "input", 68);
625
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Template_input_ngModelChange_33_listener($event) { i0.ɵɵrestoreView(_r19); const ctx_r2 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r2.SaveDocumentName, $event) || (ctx_r2.SaveDocumentName = $event); return i0.ɵɵresetView($event); });
626
+ i0.ɵɵelementEnd()();
627
+ i0.ɵɵelementStart(34, "div", 121)(35, "label", 66);
628
+ i0.ɵɵtext(36, "Embedding Model");
629
+ i0.ɵɵelementEnd();
630
+ i0.ɵɵelementStart(37, "select", 69);
631
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Template_select_ngModelChange_37_listener($event) { i0.ɵɵrestoreView(_r19); const ctx_r2 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r2.SelectedEmbeddingModelID, $event) || (ctx_r2.SelectedEmbeddingModelID = $event); return i0.ɵɵresetView($event); });
632
+ i0.ɵɵrepeaterCreate(38, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_For_39_Template, 2, 2, "option", 70, _forTrack2);
633
+ i0.ɵɵelementEnd()();
634
+ i0.ɵɵelementStart(40, "div", 121)(41, "label", 66);
635
+ i0.ɵɵtext(42, "Vector Database");
636
+ i0.ɵɵelementEnd();
637
+ i0.ɵɵelementStart(43, "select", 69);
638
+ i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Template_select_ngModelChange_43_listener($event) { i0.ɵɵrestoreView(_r19); const ctx_r2 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r2.SelectedVectorDBID, $event) || (ctx_r2.SelectedVectorDBID = $event); return i0.ɵɵresetView($event); });
639
+ i0.ɵɵrepeaterCreate(44, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_For_45_Template, 2, 2, "option", 70, _forTrack2);
640
+ i0.ɵɵelementEnd()();
641
+ i0.ɵɵelementStart(46, "div", 121)(47, "label", 66);
642
+ i0.ɵɵtext(48, "Vector Index");
643
+ i0.ɵɵelementEnd();
644
+ i0.ɵɵconditionalCreate(49, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_49_Template, 5, 1, "select", 71)(50, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_50_Template, 2, 0, "span", 72);
645
+ i0.ɵɵelementEnd()();
646
+ i0.ɵɵelementStart(51, "div", 122);
647
+ i0.ɵɵconditionalCreate(52, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_52_Template, 2, 0, "div", 123)(53, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Conditional_53_Template, 8, 0);
648
+ i0.ɵɵelementEnd()();
649
+ } if (rf & 2) {
650
+ const ctx_r2 = i0.ɵɵnextContext(3);
651
+ i0.ɵɵadvance(5);
652
+ i0.ɵɵproperty("value", ctx_r2.EditableTemplate)("readonly", false)("lineWrapping", true);
653
+ i0.ɵɵadvance(5);
654
+ i0.ɵɵrepeater(ctx_r2.SuggestionResult.selectedFields);
655
+ i0.ɵɵadvance(2);
656
+ i0.ɵɵconditional(ctx_r2.SuggestionResult.selectedRelationships.length > 0 ? 12 : -1);
657
+ i0.ɵɵadvance(6);
658
+ i0.ɵɵtextInterpolate1("", (ctx_r2.SuggestionResult.potentialMatchThreshold * 100).toFixed(0), "%");
659
+ i0.ɵɵadvance(5);
660
+ i0.ɵɵtextInterpolate1("", (ctx_r2.SuggestionResult.absoluteMatchThreshold * 100).toFixed(0), "%");
661
+ i0.ɵɵadvance(5);
662
+ i0.ɵɵtextInterpolate(ctx_r2.SuggestionResult.reasoning);
663
+ i0.ɵɵadvance(5);
664
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.SaveDocumentName);
665
+ i0.ɵɵadvance(4);
666
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.SelectedEmbeddingModelID);
667
+ i0.ɵɵadvance();
668
+ i0.ɵɵrepeater(ctx_r2.AvailableEmbeddingModels);
669
+ i0.ɵɵadvance(5);
670
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.SelectedVectorDBID);
671
+ i0.ɵɵadvance();
672
+ i0.ɵɵrepeater(ctx_r2.vectorDatabases);
673
+ i0.ɵɵadvance(5);
674
+ i0.ɵɵconditional(ctx_r2.FilteredIndexesForSelectedDB.length > 0 ? 49 : 50);
675
+ i0.ɵɵadvance(3);
676
+ i0.ɵɵconditional(ctx_r2.IsSavingDocument ? 52 : 53);
677
+ } }
678
+ function VectorManagementResourceComponent_Conditional_1_Conditional_56_Template(rf, ctx) { if (rf & 1) {
679
+ const _r13 = i0.ɵɵgetCurrentView();
680
+ i0.ɵɵelementStart(0, "div", 57);
681
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.CloseSuggestDialog()); });
682
+ i0.ɵɵelementStart(1, "div", 83);
683
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r13); return i0.ɵɵresetView($event.stopPropagation()); });
684
+ i0.ɵɵelementStart(2, "div", 59)(3, "h3", 60);
685
+ i0.ɵɵelement(4, "i", 13);
686
+ i0.ɵɵtext(5, " AI Document Suggestion ");
687
+ i0.ɵɵelementEnd();
688
+ i0.ɵɵelementStart(6, "button", 61);
689
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Conditional_56_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.CloseSuggestDialog()); });
690
+ i0.ɵɵelement(7, "i", 62);
691
+ i0.ɵɵelementEnd()();
692
+ i0.ɵɵelementStart(8, "div", 63);
693
+ i0.ɵɵconditionalCreate(9, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_9_Template, 27, 11, "div", 64)(10, VectorManagementResourceComponent_Conditional_1_Conditional_56_Conditional_10_Template, 54, 12, "div", 84);
694
+ i0.ɵɵelementEnd()()();
695
+ } if (rf & 2) {
696
+ const ctx_r2 = i0.ɵɵnextContext(2);
697
+ i0.ɵɵadvance();
698
+ i0.ɵɵclassProp("open", ctx_r2.ShowSuggestDialog);
699
+ i0.ɵɵadvance(8);
700
+ i0.ɵɵconditional(!ctx_r2.SuggestionResult ? 9 : 10);
701
+ } }
702
+ function VectorManagementResourceComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
703
+ const _r1 = i0.ɵɵgetCurrentView();
704
+ i0.ɵɵelementStart(0, "div", 2);
705
+ i0.ɵɵconditionalCreate(1, VectorManagementResourceComponent_Conditional_1_Conditional_1_Template, 7, 4, "div", 3);
706
+ i0.ɵɵelementStart(2, "div", 4);
707
+ i0.ɵɵrepeaterCreate(3, VectorManagementResourceComponent_Conditional_1_For_4_Template, 1, 1, "app-kpi-card", 5, _forTrack0);
708
+ i0.ɵɵelementEnd();
709
+ i0.ɵɵelementStart(5, "div", 6)(6, "div", 7)(7, "div", 8)(8, "h3", 9);
710
+ i0.ɵɵelement(9, "i", 10);
711
+ i0.ɵɵtext(10, " Entity Sync Status ");
712
+ i0.ɵɵelementEnd();
713
+ i0.ɵɵelementStart(11, "div", 11)(12, "button", 12);
714
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OpenSuggestDialog()); });
715
+ i0.ɵɵelement(13, "i", 13);
716
+ i0.ɵɵelementStart(14, "span", 14);
717
+ i0.ɵɵtext(15, "Suggest Document");
718
+ i0.ɵɵelementEnd()();
719
+ i0.ɵɵelementStart(16, "button", 15);
720
+ i0.ɵɵlistener("click", function VectorManagementResourceComponent_Conditional_1_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.LoadData()); });
721
+ i0.ɵɵelement(17, "i", 16);
722
+ i0.ɵɵtext(18, " Refresh ");
723
+ i0.ɵɵelementEnd()()();
724
+ i0.ɵɵconditionalCreate(19, VectorManagementResourceComponent_Conditional_1_Conditional_19_Template, 4, 0, "div", 17)(20, VectorManagementResourceComponent_Conditional_1_Conditional_20_Template, 19, 0, "div", 18);
725
+ i0.ɵɵelementEnd();
726
+ i0.ɵɵelementStart(21, "div", 19)(22, "div", 20)(23, "h4", 21);
727
+ i0.ɵɵelement(24, "i", 22);
728
+ i0.ɵɵtext(25, " Vector DB Health ");
729
+ i0.ɵɵelementEnd();
730
+ i0.ɵɵelementStart(26, "div", 23);
731
+ i0.ɵɵelement(27, "span", 24);
732
+ i0.ɵɵelementStart(28, "span", 25);
733
+ i0.ɵɵtext(29);
734
+ i0.ɵɵelementEnd()();
735
+ i0.ɵɵelementStart(30, "div", 26);
736
+ i0.ɵɵtext(31);
737
+ i0.ɵɵelementEnd()();
738
+ i0.ɵɵelementStart(32, "div", 20)(33, "h4", 21);
739
+ i0.ɵɵelement(34, "i", 27);
740
+ i0.ɵɵtext(35, " Embedding Model ");
741
+ i0.ɵɵelementEnd();
742
+ i0.ɵɵelementStart(36, "div", 28)(37, "div", 29)(38, "span", 30);
743
+ i0.ɵɵtext(39, "Model");
744
+ i0.ɵɵelementEnd();
745
+ i0.ɵɵelementStart(40, "span", 31);
746
+ i0.ɵɵtext(41);
747
+ i0.ɵɵelementEnd()();
748
+ i0.ɵɵconditionalCreate(42, VectorManagementResourceComponent_Conditional_1_Conditional_42_Template, 6, 3, "div", 29);
749
+ i0.ɵɵelementEnd()();
750
+ i0.ɵɵelementStart(43, "div", 20)(44, "h4", 21);
751
+ i0.ɵɵelement(45, "i", 32);
752
+ i0.ɵɵtext(46, " Vectorization Coverage ");
753
+ i0.ɵɵelementEnd();
754
+ i0.ɵɵelementStart(47, "div", 33)(48, "div", 34);
755
+ i0.ɵɵelement(49, "div", 35);
756
+ i0.ɵɵelementEnd();
757
+ i0.ɵɵelementStart(50, "div", 36);
758
+ i0.ɵɵtext(51);
759
+ i0.ɵɵelementEnd()();
760
+ i0.ɵɵelementStart(52, "div", 37);
761
+ i0.ɵɵtext(53);
762
+ i0.ɵɵpipe(54, "number");
763
+ i0.ɵɵelementEnd()()()()();
764
+ i0.ɵɵconditionalCreate(55, VectorManagementResourceComponent_Conditional_1_Conditional_55_Template, 47, 7, "div", 38);
765
+ i0.ɵɵconditionalCreate(56, VectorManagementResourceComponent_Conditional_1_Conditional_56_Template, 11, 3, "div", 38);
766
+ } if (rf & 2) {
767
+ const ctx_r2 = i0.ɵɵnextContext();
768
+ i0.ɵɵadvance();
769
+ i0.ɵɵconditional(!ctx_r2.EmbeddedMode ? 1 : -1);
770
+ i0.ɵɵadvance(2);
771
+ i0.ɵɵrepeater(ctx_r2.KPICards);
772
+ i0.ɵɵadvance(16);
773
+ i0.ɵɵconditional(ctx_r2.SyncRows.length === 0 ? 19 : 20);
774
+ i0.ɵɵadvance(8);
775
+ i0.ɵɵclassMap(ctx_r2.DBHealthClass);
776
+ i0.ɵɵadvance(2);
777
+ i0.ɵɵtextInterpolate(ctx_r2.VectorDBName);
778
+ i0.ɵɵadvance(2);
779
+ i0.ɵɵtextInterpolate(ctx_r2.VectorDBStatus);
780
+ i0.ɵɵadvance(10);
781
+ i0.ɵɵtextInterpolate(ctx_r2.EmbeddingModel.Name);
782
+ i0.ɵɵadvance();
783
+ i0.ɵɵconditional(ctx_r2.EmbeddingModel.Dimensions != null ? 42 : -1);
784
+ i0.ɵɵadvance(7);
785
+ i0.ɵɵstyleProp("width", ctx_r2.StorageUsagePercent, "%");
786
+ i0.ɵɵadvance(2);
787
+ i0.ɵɵtextInterpolate1("", ctx_r2.StorageLabel, " of records vectorized");
788
+ i0.ɵɵadvance(2);
789
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(54, 14, ctx_r2.TotalVectors), " vectors stored ");
790
+ i0.ɵɵadvance(2);
791
+ i0.ɵɵconditional(ctx_r2.ShowEditPanel ? 55 : -1);
792
+ i0.ɵɵadvance();
793
+ i0.ɵɵconditional(ctx_r2.ShowSuggestDialog ? 56 : -1);
794
+ } }
795
+ let VectorManagementResourceComponent = class VectorManagementResourceComponent extends BaseResourceComponent {
796
+ cdr = inject(ChangeDetectorRef);
797
+ destroy$ = new Subject();
798
+ /** View mode: 'index' = Option A (shared index as hero, entity docs as children),
799
+ * 'operations' = Option C (operations monitoring with real-time sync status) */
800
+ ViewMode = 'index';
801
+ /** Whether this component is embedded inside the Knowledge Hub shell */
802
+ EmbeddedMode = false;
803
+ /** Toggle between view modes */
804
+ ToggleViewMode() {
805
+ this.ViewMode = this.ViewMode === 'index' ? 'operations' : 'index';
806
+ this.cdr.detectChanges();
807
+ }
808
+ // --- Loading state ---
809
+ IsLoading = true;
810
+ // --- KPI card data ---
811
+ KPICards = [];
812
+ // --- Entity sync table ---
813
+ SyncRows = [];
814
+ SyncingIds = new Set();
815
+ // --- Sidebar data ---
816
+ VectorDBName = '';
817
+ VectorDBStatus = 'Healthy';
818
+ EmbeddingModel = { Name: '', Dimensions: null };
819
+ StorageUsagePercent = 0;
820
+ TotalVectors = 0;
821
+ // --- Edit Entity Document Panel ---
822
+ ShowEditPanel = false;
823
+ IsEditSaving = false;
824
+ IsEditDeleting = false;
825
+ EditDocID = '';
826
+ EditDocName = '';
827
+ EditDocEntityName = '';
828
+ EditDocVectorDBID = '';
829
+ EditDocAIModelID = '';
830
+ EditDocVectorIndexID = '';
831
+ EditDocStatus = '';
832
+ /** Open the edit panel for an entity document */
833
+ OpenEditPanel(entityDocumentId) {
834
+ const doc = this.entityDocuments.find(d => UUIDsEqual(d.ID, entityDocumentId));
835
+ if (!doc)
836
+ return;
837
+ this.EditDocID = doc.ID;
838
+ this.EditDocName = doc.Name;
839
+ this.EditDocEntityName = doc.Entity || '';
840
+ this.EditDocVectorDBID = doc.VectorDatabaseID;
841
+ this.EditDocAIModelID = doc.AIModelID;
842
+ this.EditDocVectorIndexID = doc.VectorIndexID || '';
843
+ this.EditDocStatus = doc.Status;
844
+ this.ShowEditPanel = true;
845
+ this.cdr.detectChanges();
846
+ }
847
+ CloseEditPanel() {
848
+ this.ShowEditPanel = false;
849
+ this.cdr.detectChanges();
850
+ }
851
+ async SaveEditedDocument() {
852
+ this.IsEditSaving = true;
853
+ this.cdr.detectChanges();
854
+ try {
855
+ const md = new Metadata();
856
+ const doc = await md.GetEntityObject('MJ: Entity Documents');
857
+ const loaded = await doc.Load(this.EditDocID);
858
+ if (!loaded)
859
+ throw new Error('Could not load entity document');
860
+ doc.Name = this.EditDocName;
861
+ doc.VectorDatabaseID = this.EditDocVectorDBID;
862
+ doc.AIModelID = this.EditDocAIModelID;
863
+ doc.VectorIndexID = this.EditDocVectorIndexID || null;
864
+ doc.Status = this.EditDocStatus;
865
+ const saved = await doc.Save();
866
+ if (saved) {
867
+ MJNotificationService.Instance.CreateSimpleNotification('Entity document updated', 'success', 2500);
868
+ this.ShowEditPanel = false;
869
+ await this.LoadData();
870
+ }
871
+ else {
872
+ const msg = doc.LatestResult?.CompleteMessage || 'Unknown error';
873
+ MJNotificationService.Instance.CreateSimpleNotification(`Save failed: ${msg}`, 'error', 5000);
874
+ }
875
+ }
876
+ catch (error) {
877
+ const msg = error instanceof Error ? error.message : String(error);
878
+ MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 5000);
879
+ }
880
+ finally {
881
+ this.IsEditSaving = false;
882
+ this.cdr.detectChanges();
883
+ }
884
+ }
885
+ async DeleteEntityDocument() {
886
+ this.IsEditDeleting = true;
887
+ this.cdr.detectChanges();
888
+ try {
889
+ const md = new Metadata();
890
+ const doc = await md.GetEntityObject('MJ: Entity Documents');
891
+ const loaded = await doc.Load(this.EditDocID);
892
+ if (!loaded)
893
+ throw new Error('Could not load entity document');
894
+ const deleted = await doc.Delete();
895
+ if (deleted) {
896
+ MJNotificationService.Instance.CreateSimpleNotification('Entity document deleted', 'success', 2500);
897
+ this.ShowEditPanel = false;
898
+ await this.LoadData();
899
+ }
900
+ else {
901
+ MJNotificationService.Instance.CreateSimpleNotification('Delete failed', 'error', 3000);
902
+ }
903
+ }
904
+ catch (error) {
905
+ const msg = error instanceof Error ? error.message : String(error);
906
+ MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 5000);
907
+ }
908
+ finally {
909
+ this.IsEditDeleting = false;
910
+ this.cdr.detectChanges();
911
+ }
912
+ }
913
+ // --- Suggest Document Dialog ---
914
+ ShowSuggestDialog = false;
915
+ IsSuggesting = false;
916
+ SuggestEntityName = '';
917
+ SuggestUseCase = 'duplicate detection';
918
+ SuggestionResult = null;
919
+ SaveDocumentName = '';
920
+ SuggestionError = '';
921
+ IsSavingDocument = false;
922
+ EditableTemplate = '';
923
+ /** Prerequisites check — are vector DB and embedding model configured? */
924
+ HasVectorDB = false;
925
+ HasEmbeddingModel = false;
926
+ get PrerequisitesMet() {
927
+ return this.HasVectorDB && this.HasEmbeddingModel;
928
+ }
929
+ /** Available embedding models for selection in save form */
930
+ AvailableEmbeddingModels = [];
931
+ /** Selected embedding model ID for the new entity document */
932
+ SelectedEmbeddingModelID = '';
933
+ /** Selected vector database ID for the new entity document */
934
+ SelectedVectorDBID = '';
935
+ /** Available vector indexes for selection */
936
+ AvailableVectorIndexes = [];
937
+ /** Selected vector index ID — if user picks an existing one */
938
+ SelectedVectorIndexID = '';
939
+ /** Indexes filtered by the currently selected vector DB (for create/edit forms) */
940
+ get FilteredIndexesForSelectedDB() {
941
+ const dbId = this.SelectedVectorDBID || this.EditDocVectorDBID;
942
+ if (!dbId)
943
+ return this.AvailableVectorIndexes;
944
+ return this.AvailableVectorIndexes.filter(i => i.VectorDatabaseID === dbId);
945
+ }
946
+ /** Indexes filtered by the edit panel's selected vector DB */
947
+ get EditFilteredIndexes() {
948
+ if (!this.EditDocVectorDBID)
949
+ return this.AvailableVectorIndexes;
950
+ return this.AvailableVectorIndexes.filter(i => i.VectorDatabaseID === this.EditDocVectorDBID);
951
+ }
952
+ /** Grouped entity list for the suggestion panel — schemas as groups, entities as items */
953
+ EntityGroups = [];
954
+ /** Filtered entity groups based on search input */
955
+ FilteredEntityGroups = [];
956
+ /** Search text for filtering entities */
957
+ EntitySearchText = '';
958
+ /** Whether the entity picker dropdown is open */
959
+ ShowEntityPicker = false;
960
+ // --- Raw entity data (private) ---
961
+ entityDocuments = [];
962
+ vectorDatabases = [];
963
+ vectorIndexes = [];
964
+ recordDocuments = [];
965
+ aiModels = [];
966
+ // ================================================================
967
+ // Lifecycle
968
+ // ================================================================
969
+ async ngAfterViewInit() {
970
+ await this.LoadData();
971
+ this.NotifyLoadComplete();
972
+ }
973
+ ngOnDestroy() {
974
+ this.destroy$.next();
975
+ this.destroy$.complete();
976
+ }
977
+ // ================================================================
978
+ // BaseResourceComponent overrides
979
+ // ================================================================
980
+ async GetResourceDisplayName(_data) {
981
+ return 'Vector Management';
982
+ }
983
+ async GetResourceIconClass(_data) {
984
+ return 'fa-solid fa-database';
985
+ }
986
+ // ================================================================
987
+ // Public Methods
988
+ // ================================================================
989
+ /** Reload all dashboard data */
990
+ async LoadData() {
991
+ this.IsLoading = true;
992
+ this.cdr.detectChanges();
993
+ try {
994
+ await this.fetchAllData();
995
+ this.buildSyncRows();
996
+ this.buildKPICards();
997
+ this.buildSidebarData();
998
+ this.checkPrerequisites();
999
+ }
1000
+ catch (error) {
1001
+ console.error('[VectorManagement] Error loading data:', error);
1002
+ }
1003
+ finally {
1004
+ this.IsLoading = false;
1005
+ this.cdr.detectChanges();
1006
+ }
1007
+ }
1008
+ /** Trigger vectorization for a specific entity document via GraphQL (fire-and-forget with progress subscription) */
1009
+ async SyncEntity(entityDocumentId) {
1010
+ if (this.SyncingIds.has(entityDocumentId)) {
1011
+ return;
1012
+ }
1013
+ const doc = this.entityDocuments.find(d => UUIDsEqual(d.ID, entityDocumentId));
1014
+ if (!doc)
1015
+ return;
1016
+ const provider = Metadata.Provider;
1017
+ if (!provider)
1018
+ return;
1019
+ this.addSyncingId(entityDocumentId);
1020
+ this.updateRowStatus(entityDocumentId, 'Syncing');
1021
+ this.updateRowProgress(entityDocumentId, 0);
1022
+ this.cdr.detectChanges();
1023
+ try {
1024
+ const aiClient = new GraphQLAIClient(provider);
1025
+ MJNotificationService.Instance.CreateSimpleNotification(`Starting vectorization for ${doc.Entity}...`, 'info', 3000);
1026
+ // Step 1: Start the mutation (fire-and-forget — returns PipelineRunID immediately)
1027
+ const result = await aiClient.VectorizeEntity({
1028
+ entityDocumentID: entityDocumentId,
1029
+ entityID: doc.EntityID,
1030
+ batchSize: 50
1031
+ });
1032
+ if (!result.Success || !result.PipelineRunID) {
1033
+ MJNotificationService.Instance.CreateSimpleNotification(`Vectorization failed: ${result.ErrorMessage || 'Unknown error'}`, 'error', 5000);
1034
+ this.removeSyncingId(entityDocumentId);
1035
+ this.updateRowStatus(entityDocumentId, 'Error');
1036
+ this.cdr.detectChanges();
1037
+ return;
1038
+ }
1039
+ // Store PipelineRunID on the row for tracking
1040
+ const row = this.SyncRows.find(r => r.EntityDocumentID === entityDocumentId);
1041
+ if (row) {
1042
+ row.PipelineRunID = result.PipelineRunID;
1043
+ }
1044
+ // Step 2: Subscribe to progress updates and also set a safety timeout
1045
+ // in case the subscription misses events (race condition, network issue, etc.)
1046
+ this.subscribeToPipelineProgress(entityDocumentId, result.PipelineRunID, doc.Entity);
1047
+ }
1048
+ catch (error) {
1049
+ const msg = error instanceof Error ? error.message : String(error);
1050
+ console.error(`[VectorManagement] Error starting sync for ${entityDocumentId}:`, msg);
1051
+ MJNotificationService.Instance.CreateSimpleNotification(`Sync error: ${msg}`, 'error', 5000);
1052
+ this.removeSyncingId(entityDocumentId);
1053
+ this.updateRowStatus(entityDocumentId, 'Error');
1054
+ this.cdr.detectChanges();
1055
+ }
1056
+ }
1057
+ /** Subscribe to PipelineProgress for a specific pipeline run */
1058
+ subscribeToPipelineProgress(entityDocumentId, pipelineRunID, entityName) {
1059
+ const provider = Metadata.Provider;
1060
+ const subscriptionQuery = `
1061
+ subscription PipelineProgress($pipelineRunID: String!) {
1062
+ PipelineProgress(pipelineRunID: $pipelineRunID) {
1063
+ PipelineRunID
1064
+ Stage
1065
+ TotalItems
1066
+ ProcessedItems
1067
+ PercentComplete
1068
+ ElapsedMs
1069
+ }
1070
+ }
1071
+ `;
1072
+ let idleTimer = null;
1073
+ const finishSync = (success) => {
1074
+ if (idleTimer)
1075
+ clearTimeout(idleTimer);
1076
+ rxSub?.unsubscribe();
1077
+ // Use Promise.resolve().then() to defer state changes to the next
1078
+ // microtask, avoiding ExpressionChangedAfterItHasBeenCheckedError
1079
+ Promise.resolve().then(async () => {
1080
+ this.removeSyncingId(entityDocumentId);
1081
+ if (success) {
1082
+ MJNotificationService.Instance.CreateSimpleNotification(`Vectorization complete for ${entityName}`, 'success', 3000);
1083
+ await this.refreshSyncRow(entityDocumentId);
1084
+ }
1085
+ else {
1086
+ this.updateRowStatus(entityDocumentId, 'Error');
1087
+ MJNotificationService.Instance.CreateSimpleNotification(`Vectorization failed for ${entityName}`, 'error', 5000);
1088
+ this.cdr.detectChanges();
1089
+ }
1090
+ });
1091
+ };
1092
+ // Reset idle timer on every event. When no events arrive for 5s,
1093
+ // assume the pipeline is done (handles missing 'complete' event).
1094
+ const resetIdleTimer = () => {
1095
+ if (idleTimer)
1096
+ clearTimeout(idleTimer);
1097
+ idleTimer = setTimeout(() => {
1098
+ if (this.SyncingIds.has(entityDocumentId)) {
1099
+ finishSync(true);
1100
+ }
1101
+ }, 5000);
1102
+ };
1103
+ // Start the idle timer immediately in case no events ever arrive
1104
+ resetIdleTimer();
1105
+ const sub = provider.subscribe(subscriptionQuery, { pipelineRunID });
1106
+ const rxSub = sub.pipe(takeUntil(this.destroy$)).subscribe({
1107
+ next: (data) => {
1108
+ const progress = data['PipelineProgress'];
1109
+ if (!progress)
1110
+ return;
1111
+ const stage = progress['Stage'];
1112
+ const pct = progress['PercentComplete'];
1113
+ this.updateRowProgress(entityDocumentId, pct);
1114
+ this.cdr.detectChanges();
1115
+ if (stage === 'complete') {
1116
+ finishSync(true);
1117
+ }
1118
+ else if (stage === 'error') {
1119
+ finishSync(false);
1120
+ }
1121
+ else {
1122
+ // Got a progress event — reset idle timer
1123
+ resetIdleTimer();
1124
+ }
1125
+ },
1126
+ error: (err) => {
1127
+ console.error(`[VectorManagement] Pipeline subscription error:`, err);
1128
+ finishSync(false);
1129
+ }
1130
+ });
1131
+ }
1132
+ /**
1133
+ * Add an ID to SyncingIds, creating a new Set reference so Angular
1134
+ * change detection picks up the mutation in template bindings.
1135
+ */
1136
+ addSyncingId(id) {
1137
+ this.SyncingIds = new Set([...this.SyncingIds, id]);
1138
+ }
1139
+ /**
1140
+ * Remove an ID from SyncingIds, creating a new Set reference so Angular
1141
+ * change detection picks up the mutation in template bindings.
1142
+ */
1143
+ removeSyncingId(id) {
1144
+ if (this.SyncingIds.has(id)) {
1145
+ const next = new Set(this.SyncingIds);
1146
+ next.delete(id);
1147
+ this.SyncingIds = next;
1148
+ }
1149
+ }
1150
+ /** Opens the AI suggestion dialog */
1151
+ OpenSuggestDialog() {
1152
+ this.SuggestionResult = null;
1153
+ this.SuggestEntityName = '';
1154
+ this.SuggestUseCase = 'duplicate detection';
1155
+ this.EditableTemplate = '';
1156
+ this.SuggestionError = '';
1157
+ this.EntitySearchText = '';
1158
+ this.ShowEntityPicker = false;
1159
+ this.loadEntityGroups();
1160
+ this.ShowSuggestDialog = true;
1161
+ this.cdr.detectChanges();
1162
+ }
1163
+ /** Select an entity from the grouped picker */
1164
+ SelectEntity(entityName) {
1165
+ this.SuggestEntityName = entityName;
1166
+ this.ShowEntityPicker = false;
1167
+ this.cdr.detectChanges();
1168
+ }
1169
+ /** Filter entities by search text */
1170
+ FilterEntities() {
1171
+ const query = this.EntitySearchText.toLowerCase().trim();
1172
+ if (!query) {
1173
+ this.FilteredEntityGroups = this.EntityGroups;
1174
+ }
1175
+ else {
1176
+ this.FilteredEntityGroups = this.EntityGroups
1177
+ .map(group => ({
1178
+ SchemaName: group.SchemaName,
1179
+ Entities: group.Entities.filter(e => e.Name.toLowerCase().includes(query))
1180
+ }))
1181
+ .filter(group => group.Entities.length > 0);
1182
+ }
1183
+ this.cdr.detectChanges();
1184
+ }
1185
+ /** Toggle entity picker visibility */
1186
+ ToggleEntityPicker() {
1187
+ this.ShowEntityPicker = !this.ShowEntityPicker;
1188
+ if (this.ShowEntityPicker) {
1189
+ this.FilteredEntityGroups = this.EntityGroups;
1190
+ this.EntitySearchText = '';
1191
+ }
1192
+ this.cdr.detectChanges();
1193
+ }
1194
+ /** Handle template edits from code editor */
1195
+ OnTemplateChange(newValue) {
1196
+ this.EditableTemplate = newValue;
1197
+ if (this.SuggestionResult) {
1198
+ this.SuggestionResult.template = newValue;
1199
+ }
1200
+ }
1201
+ /** Closes the suggestion dialog */
1202
+ CloseSuggestDialog() {
1203
+ this.ShowSuggestDialog = false;
1204
+ this.SuggestionResult = null;
1205
+ this.cdr.detectChanges();
1206
+ }
1207
+ /** Clears the current suggestion to try again */
1208
+ ClearSuggestion() {
1209
+ this.SuggestionResult = null;
1210
+ this.cdr.detectChanges();
1211
+ }
1212
+ /**
1213
+ * Runs the AI suggestion by calling the server-side "Entity Document Suggestion"
1214
+ * AI prompt via GraphQL. The LLM analyzes the entity schema and generates
1215
+ * natural language Nunjucks templates optimized for embedding quality.
1216
+ */
1217
+ async RunSuggestion() {
1218
+ if (!this.SuggestEntityName || this.IsSuggesting) {
1219
+ return;
1220
+ }
1221
+ this.IsSuggesting = true;
1222
+ this.SuggestionError = '';
1223
+ this.cdr.detectChanges();
1224
+ try {
1225
+ const result = await this.callSuggestionPrompt(this.SuggestEntityName, this.SuggestUseCase);
1226
+ if (result) {
1227
+ this.SuggestionResult = result;
1228
+ this.EditableTemplate = result.template;
1229
+ this.SaveDocumentName = `${this.SuggestEntityName} - ${this.SuggestUseCase}`;
1230
+ }
1231
+ }
1232
+ catch (error) {
1233
+ const msg = error instanceof Error ? error.message : String(error);
1234
+ console.error('[VectorManagement] Error generating suggestion:', msg);
1235
+ this.SuggestionError = `Failed to generate suggestion: ${msg}`;
1236
+ }
1237
+ finally {
1238
+ this.IsSuggesting = false;
1239
+ this.cdr.detectChanges();
1240
+ }
1241
+ }
1242
+ /** Saves the current suggestion as an Entity Document record */
1243
+ async SaveAsEntityDocument() {
1244
+ if (this.IsSavingDocument || !this.SuggestionResult) {
1245
+ return;
1246
+ }
1247
+ this.IsSavingDocument = true;
1248
+ this.cdr.detectChanges();
1249
+ try {
1250
+ const md = new Metadata();
1251
+ const entityDoc = await md.GetEntityObject('MJ: Entity Documents');
1252
+ entityDoc.NewRecord();
1253
+ entityDoc.Name = this.SaveDocumentName;
1254
+ const matchingEntity = md.Entities.find(e => e.Name === this.SuggestEntityName);
1255
+ if (matchingEntity) {
1256
+ entityDoc.EntityID = matchingEntity.ID;
1257
+ }
1258
+ entityDoc.Status = 'Active';
1259
+ // Populate required FK fields from existing data
1260
+ await this.populateEntityDocumentFKs(entityDoc);
1261
+ const saved = await entityDoc.Save();
1262
+ if (saved) {
1263
+ MJNotificationService.Instance.CreateSimpleNotification(`Entity Document "${this.SaveDocumentName}" created successfully`, 'success', 3000);
1264
+ await this.LoadData();
1265
+ setTimeout(() => {
1266
+ this.CloseSuggestDialog();
1267
+ this.cdr.detectChanges();
1268
+ }, 1500);
1269
+ }
1270
+ else {
1271
+ const errorMsg = entityDoc.LatestResult?.CompleteMessage || 'Unknown error saving entity document';
1272
+ console.error('[VectorManagement] Failed to save entity document:', errorMsg);
1273
+ MJNotificationService.Instance.CreateSimpleNotification(`Failed to save: ${errorMsg}`, 'error', 5000);
1274
+ }
1275
+ }
1276
+ catch (error) {
1277
+ const msg = error instanceof Error ? error.message : String(error);
1278
+ console.error('[VectorManagement] Error saving entity document:', msg);
1279
+ MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 5000);
1280
+ }
1281
+ finally {
1282
+ this.IsSavingDocument = false;
1283
+ this.cdr.detectChanges();
1284
+ }
1285
+ }
1286
+ /** Returns the CSS class for a given sync status badge */
1287
+ GetStatusClass(status) {
1288
+ switch (status) {
1289
+ case 'Synced': return 'status-synced';
1290
+ case 'Syncing': return 'status-syncing';
1291
+ case 'Error': return 'status-error';
1292
+ case 'Pending': return 'status-pending';
1293
+ default: return '';
1294
+ }
1295
+ }
1296
+ /** Returns the icon class for a given sync status */
1297
+ GetStatusIcon(status) {
1298
+ switch (status) {
1299
+ case 'Synced': return 'fa-solid fa-circle-check';
1300
+ case 'Syncing': return 'fa-solid fa-spinner fa-spin';
1301
+ case 'Error': return 'fa-solid fa-circle-exclamation';
1302
+ case 'Pending': return 'fa-solid fa-clock';
1303
+ default: return 'fa-solid fa-question';
1304
+ }
1305
+ }
1306
+ /** Format a Date value for display */
1307
+ FormatDate(date) {
1308
+ if (!date)
1309
+ return 'Never';
1310
+ const d = new Date(date);
1311
+ return d.toLocaleDateString(undefined, {
1312
+ month: 'short',
1313
+ day: 'numeric',
1314
+ year: 'numeric',
1315
+ hour: '2-digit',
1316
+ minute: '2-digit'
1317
+ });
1318
+ }
1319
+ /** Format the storage gauge label */
1320
+ get StorageLabel() {
1321
+ return `${this.StorageUsagePercent}%`;
1322
+ }
1323
+ /** CSS class for the DB health indicator dot */
1324
+ get DBHealthClass() {
1325
+ switch (this.VectorDBStatus) {
1326
+ case 'Healthy': return 'health-healthy';
1327
+ case 'Degraded': return 'health-degraded';
1328
+ case 'Offline': return 'health-offline';
1329
+ default: return '';
1330
+ }
1331
+ }
1332
+ // ================================================================
1333
+ // Private helpers
1334
+ // ================================================================
1335
+ async fetchAllData() {
1336
+ const rv = new RunView();
1337
+ const [docsResult, vdbResult, viResult, erdResult, modelsResult] = await rv.RunViews([
1338
+ {
1339
+ EntityName: 'MJ: Entity Documents',
1340
+ ExtraFilter: '',
1341
+ OrderBy: 'Name',
1342
+ ResultType: 'entity_object'
1343
+ },
1344
+ {
1345
+ EntityName: 'MJ: Vector Databases',
1346
+ ExtraFilter: '',
1347
+ ResultType: 'entity_object'
1348
+ },
1349
+ {
1350
+ EntityName: 'MJ: Vector Indexes',
1351
+ ExtraFilter: '',
1352
+ ResultType: 'entity_object'
1353
+ },
1354
+ {
1355
+ EntityName: 'MJ: Entity Record Documents',
1356
+ ExtraFilter: '',
1357
+ Fields: ['ID', 'EntityDocumentID', 'VectorID', 'EntityDocument', 'Entity', '__mj_UpdatedAt'],
1358
+ ResultType: 'simple'
1359
+ },
1360
+ {
1361
+ EntityName: 'MJ: AI Models',
1362
+ ExtraFilter: '',
1363
+ ResultType: 'entity_object'
1364
+ }
1365
+ ]);
1366
+ if (docsResult.Success) {
1367
+ this.entityDocuments = docsResult.Results;
1368
+ }
1369
+ if (vdbResult.Success) {
1370
+ this.vectorDatabases = vdbResult.Results;
1371
+ }
1372
+ if (viResult.Success) {
1373
+ this.vectorIndexes = viResult.Results;
1374
+ }
1375
+ if (erdResult.Success) {
1376
+ this.recordDocuments = erdResult.Results;
1377
+ }
1378
+ if (modelsResult.Success) {
1379
+ this.aiModels = modelsResult.Results;
1380
+ }
1381
+ }
1382
+ buildSyncRows() {
1383
+ this.SyncRows = this.entityDocuments.map(doc => {
1384
+ const docsForEntity = this.recordDocuments.filter(rd => UUIDsEqual(rd.EntityDocumentID, doc.ID));
1385
+ const vectorCount = docsForEntity.filter(rd => rd.VectorID != null).length;
1386
+ const lastSynced = this.computeLastSynced(docsForEntity);
1387
+ const status = this.computeSyncStatus(doc, vectorCount, docsForEntity.length);
1388
+ // Preserve progress info from any active sync
1389
+ const existingRow = this.SyncRows.find(r => UUIDsEqual(r.EntityDocumentID, doc.ID));
1390
+ return {
1391
+ EntityDocumentID: doc.ID,
1392
+ EntityName: doc.Entity || '',
1393
+ DocumentName: doc.Name,
1394
+ VectorCount: vectorCount,
1395
+ LastSynced: lastSynced,
1396
+ Status: status,
1397
+ PercentComplete: existingRow?.PercentComplete ?? 0,
1398
+ PipelineRunID: existingRow?.PipelineRunID,
1399
+ };
1400
+ });
1401
+ }
1402
+ computeLastSynced(records) {
1403
+ if (records.length === 0)
1404
+ return null;
1405
+ const dates = records
1406
+ .map(r => new Date(r.__mj_UpdatedAt))
1407
+ .filter(d => !isNaN(d.getTime()));
1408
+ if (dates.length === 0)
1409
+ return null;
1410
+ return new Date(Math.max(...dates.map(d => d.getTime())));
1411
+ }
1412
+ computeSyncStatus(doc, vectorCount, totalRecords) {
1413
+ if (this.SyncingIds.has(doc.ID)) {
1414
+ return 'Syncing';
1415
+ }
1416
+ if (doc.Status === 'Inactive') {
1417
+ return 'Pending';
1418
+ }
1419
+ if (totalRecords === 0) {
1420
+ return 'Pending';
1421
+ }
1422
+ // If there are any vectors, consider it synced — partial syncs
1423
+ // still represent a successful state since the pipeline ran
1424
+ if (vectorCount > 0) {
1425
+ return 'Synced';
1426
+ }
1427
+ return 'Synced';
1428
+ }
1429
+ buildKPICards() {
1430
+ this.TotalVectors = this.recordDocuments.filter(rd => rd.VectorID != null).length;
1431
+ const entitiesSynced = new Set(this.entityDocuments
1432
+ .filter(d => d.Status === 'Active')
1433
+ .map(d => d.EntityID)).size;
1434
+ const allDates = this.recordDocuments
1435
+ .map(r => new Date(r.__mj_UpdatedAt))
1436
+ .filter(d => !isNaN(d.getTime()));
1437
+ const lastSyncDate = allDates.length > 0
1438
+ ? new Date(Math.max(...allDates.map(d => d.getTime())))
1439
+ : null;
1440
+ this.KPICards = [
1441
+ {
1442
+ title: 'Total Vectors',
1443
+ value: this.TotalVectors,
1444
+ subtitle: `across ${this.entityDocuments.length} documents`,
1445
+ icon: 'fa-cubes',
1446
+ color: 'primary',
1447
+ loading: false
1448
+ },
1449
+ {
1450
+ title: 'Entities Synced',
1451
+ value: entitiesSynced,
1452
+ subtitle: `of ${this.entityDocuments.length} configured`,
1453
+ icon: 'fa-layer-group',
1454
+ color: 'success',
1455
+ loading: false
1456
+ },
1457
+ {
1458
+ title: 'Last Sync',
1459
+ value: lastSyncDate ? this.FormatDate(lastSyncDate) : 'Never',
1460
+ icon: 'fa-clock',
1461
+ color: 'info',
1462
+ loading: false
1463
+ },
1464
+ {
1465
+ title: 'Vector Indexes',
1466
+ value: this.vectorIndexes.length,
1467
+ subtitle: `in ${this.vectorDatabases.length} database(s)`,
1468
+ icon: 'fa-diagram-project',
1469
+ color: 'warning',
1470
+ loading: false
1471
+ }
1472
+ ];
1473
+ }
1474
+ buildSidebarData() {
1475
+ this.buildVectorDBHealth();
1476
+ this.buildEmbeddingModelInfo();
1477
+ this.buildStorageUsage();
1478
+ }
1479
+ buildVectorDBHealth() {
1480
+ if (this.vectorDatabases.length > 0) {
1481
+ const db = this.vectorDatabases[0];
1482
+ this.VectorDBName = db.Name;
1483
+ // Determine health based on whether we have records with vectors
1484
+ const hasVectors = this.recordDocuments.some(rd => rd.VectorID != null);
1485
+ this.VectorDBStatus = hasVectors ? 'Healthy' : 'Degraded';
1486
+ }
1487
+ else {
1488
+ this.VectorDBName = 'Not configured';
1489
+ this.VectorDBStatus = 'Offline';
1490
+ }
1491
+ }
1492
+ buildEmbeddingModelInfo() {
1493
+ if (this.vectorIndexes.length > 0) {
1494
+ const index = this.vectorIndexes[0];
1495
+ const model = this.aiModels.find(m => UUIDsEqual(m.ID, index.EmbeddingModelID));
1496
+ this.EmbeddingModel = {
1497
+ Name: model?.Name ?? index.EmbeddingModel ?? 'Unknown',
1498
+ Dimensions: null
1499
+ };
1500
+ }
1501
+ else {
1502
+ this.EmbeddingModel = { Name: 'Not configured', Dimensions: null };
1503
+ }
1504
+ }
1505
+ buildStorageUsage() {
1506
+ // Estimate storage as a ratio of vectorized records vs total record documents
1507
+ const total = this.recordDocuments.length;
1508
+ const vectorized = this.recordDocuments.filter(rd => rd.VectorID != null).length;
1509
+ this.StorageUsagePercent = total > 0 ? Math.round((vectorized / total) * 100) : 0;
1510
+ }
1511
+ /** Check if vector DB and embedding model are configured, populate selection lists */
1512
+ checkPrerequisites() {
1513
+ this.HasVectorDB = this.vectorDatabases.length > 0;
1514
+ const allEmbeddings = this.aiModels.filter(m => m.AIModelType?.toLowerCase().includes('embedding') || m.Name?.toLowerCase().includes('embedding'));
1515
+ this.HasEmbeddingModel = allEmbeddings.length > 0;
1516
+ this.AvailableEmbeddingModels = allEmbeddings.map(m => ({ ID: m.ID, Name: m.Name }));
1517
+ // Default selections — first available, no hardcoded preference
1518
+ if (this.HasVectorDB && !this.SelectedVectorDBID) {
1519
+ this.SelectedVectorDBID = this.vectorDatabases[0].ID;
1520
+ }
1521
+ if (this.HasEmbeddingModel && !this.SelectedEmbeddingModelID) {
1522
+ this.SelectedEmbeddingModelID = allEmbeddings[0].ID;
1523
+ }
1524
+ // Build vector index list
1525
+ this.AvailableVectorIndexes = this.vectorIndexes.map(vi => ({
1526
+ ID: vi.ID,
1527
+ Name: vi.Name,
1528
+ VectorDatabaseID: vi.VectorDatabaseID,
1529
+ EmbeddingModelID: vi.EmbeddingModelID
1530
+ }));
1531
+ // Pre-select first index if available
1532
+ if (this.AvailableVectorIndexes.length > 0 && !this.SelectedVectorIndexID) {
1533
+ this.SelectedVectorIndexID = this.AvailableVectorIndexes[0].ID;
1534
+ }
1535
+ }
1536
+ /** Find the best embedding model from loaded AI models */
1537
+ findEmbeddingModel() {
1538
+ return this.aiModels.find(m => m.AIModelType?.toLowerCase().includes('embedding') || m.Name?.toLowerCase().includes('embedding'));
1539
+ }
1540
+ /**
1541
+ * Populate required foreign key fields on an Entity Document before saving.
1542
+ * Throws if prerequisites are not met.
1543
+ */
1544
+ async populateEntityDocumentFKs(entityDoc) {
1545
+ if (!this.PrerequisitesMet) {
1546
+ const missing = [];
1547
+ if (!this.HasVectorDB)
1548
+ missing.push('Vector Database');
1549
+ if (!this.HasEmbeddingModel)
1550
+ missing.push('Embedding Model');
1551
+ throw new Error(`Prerequisites not configured: ${missing.join(', ')}. Go to the Configuration tab to set these up.`);
1552
+ }
1553
+ // TypeID — look up 'Record Duplicate' entity document type
1554
+ const rv = new RunView();
1555
+ const typeResult = await rv.RunView({
1556
+ EntityName: 'MJ: Entity Document Types',
1557
+ ExtraFilter: "Name = 'Record Duplicate'",
1558
+ ResultType: 'simple',
1559
+ Fields: ['ID']
1560
+ });
1561
+ if (typeResult.Success && typeResult.Results.length > 0) {
1562
+ entityDoc.TypeID = typeResult.Results[0].ID;
1563
+ }
1564
+ else {
1565
+ throw new Error('Entity Document Type "Record Duplicate" not found in database');
1566
+ }
1567
+ // If a vector index is selected, use its DB + model so the syncer finds it
1568
+ // instead of auto-creating a new one
1569
+ if (this.SelectedVectorIndexID) {
1570
+ const idx = this.AvailableVectorIndexes.find(i => UUIDsEqual(i.ID, this.SelectedVectorIndexID));
1571
+ if (idx) {
1572
+ entityDoc.VectorDatabaseID = idx.VectorDatabaseID;
1573
+ entityDoc.AIModelID = idx.EmbeddingModelID;
1574
+ entityDoc.VectorIndexID = idx.ID;
1575
+ }
1576
+ else {
1577
+ entityDoc.VectorDatabaseID = this.SelectedVectorDBID || this.vectorDatabases[0].ID;
1578
+ entityDoc.AIModelID = this.SelectedEmbeddingModelID || this.findEmbeddingModel().ID;
1579
+ }
1580
+ }
1581
+ else {
1582
+ entityDoc.VectorDatabaseID = this.SelectedVectorDBID || this.vectorDatabases[0].ID;
1583
+ entityDoc.AIModelID = this.SelectedEmbeddingModelID || this.findEmbeddingModel().ID;
1584
+ }
1585
+ // TemplateID — create a Template record with the generated template content
1586
+ await this.createTemplateForDocument(entityDoc);
1587
+ }
1588
+ /** Create a Template + TemplateContent record for the entity document */
1589
+ async createTemplateForDocument(entityDoc) {
1590
+ const md = new Metadata();
1591
+ const templateText = this.EditableTemplate || this.SuggestionResult?.template || '';
1592
+ if (!templateText) {
1593
+ throw new Error('No template content to save');
1594
+ }
1595
+ // Create Template record
1596
+ const template = await md.GetEntityObject('MJ: Templates');
1597
+ template.NewRecord();
1598
+ template.Name = `Template for ${this.SaveDocumentName}`;
1599
+ template.Description = `Auto-generated template for entity document: ${this.SaveDocumentName}`;
1600
+ template.UserID = md.CurrentUser.ID;
1601
+ template.IsActive = true;
1602
+ const templateSaved = await template.Save();
1603
+ if (!templateSaved) {
1604
+ throw new Error(`Failed to create template: ${template.LatestResult?.CompleteMessage || 'unknown error'}`);
1605
+ }
1606
+ entityDoc.TemplateID = template.ID;
1607
+ // Find 'Text' content type
1608
+ const contentTypeResult = await new RunView().RunView({
1609
+ EntityName: 'MJ: Template Content Types',
1610
+ ExtraFilter: "Name = 'Text'",
1611
+ ResultType: 'simple',
1612
+ Fields: ['ID']
1613
+ });
1614
+ if (!contentTypeResult.Success || contentTypeResult.Results.length === 0) {
1615
+ throw new Error('Template Content Type "Text" not found');
1616
+ }
1617
+ // Create TemplateContent record with the template text
1618
+ // Server-side MJTemplateContentEntityServer hook auto-creates Scalar params
1619
+ // for each {{FieldName}} — GetTemplateData() handles them via the flat convention.
1620
+ const content = await md.GetEntityObject('MJ: Template Contents');
1621
+ content.NewRecord();
1622
+ content.TemplateID = template.ID;
1623
+ content.TypeID = contentTypeResult.Results[0].ID;
1624
+ content.TemplateText = templateText;
1625
+ content.Priority = 1;
1626
+ content.IsActive = true;
1627
+ const contentSaved = await content.Save();
1628
+ if (!contentSaved) {
1629
+ throw new Error(`Failed to create template content: ${content.LatestResult?.CompleteMessage || 'unknown error'}`);
1630
+ }
1631
+ }
1632
+ /** Build grouped entity list from metadata, grouped by SchemaName */
1633
+ loadEntityGroups() {
1634
+ const md = new Metadata();
1635
+ const groupMap = new Map();
1636
+ for (const entity of md.Entities) {
1637
+ const schema = entity.SchemaName || '__default';
1638
+ const existing = groupMap.get(schema);
1639
+ if (existing) {
1640
+ existing.push({ Name: entity.Name, ID: entity.ID });
1641
+ }
1642
+ else {
1643
+ groupMap.set(schema, [{ Name: entity.Name, ID: entity.ID }]);
1644
+ }
1645
+ }
1646
+ this.EntityGroups = Array.from(groupMap.entries())
1647
+ .map(([schemaName, entities]) => ({
1648
+ SchemaName: schemaName,
1649
+ Entities: entities.sort((a, b) => a.Name.localeCompare(b.Name))
1650
+ }))
1651
+ .sort((a, b) => a.SchemaName.localeCompare(b.SchemaName));
1652
+ this.FilteredEntityGroups = this.EntityGroups;
1653
+ }
1654
+ updateRowStatus(entityDocumentId, status) {
1655
+ const row = this.SyncRows.find(r => r.EntityDocumentID === entityDocumentId);
1656
+ if (row) {
1657
+ row.Status = status;
1658
+ }
1659
+ }
1660
+ updateRowProgress(entityDocumentId, percentComplete) {
1661
+ const row = this.SyncRows.find(r => r.EntityDocumentID === entityDocumentId);
1662
+ if (row) {
1663
+ row.PercentComplete = percentComplete;
1664
+ }
1665
+ }
1666
+ /** Refresh a single sync row's vector count and status from the DB */
1667
+ async refreshSyncRow(entityDocumentId) {
1668
+ const row = this.SyncRows.find(r => r.EntityDocumentID === entityDocumentId);
1669
+ if (!row)
1670
+ return;
1671
+ const rv = new RunView();
1672
+ const result = await rv.RunView({
1673
+ EntityName: 'MJ: Entity Record Documents',
1674
+ ExtraFilter: `EntityDocumentID='${entityDocumentId}'`,
1675
+ ResultType: 'entity_object'
1676
+ });
1677
+ if (result.Success) {
1678
+ const docs = result.Results;
1679
+ row.VectorCount = docs.filter(d => d.VectorID != null).length;
1680
+ row.LastSynced = this.computeLastSynced(docs);
1681
+ row.Status = row.VectorCount > 0 ? 'Synced' : 'Pending';
1682
+ row.PercentComplete = 100;
1683
+ this.cdr.detectChanges();
1684
+ }
1685
+ }
1686
+ /**
1687
+ * Calls the "Entity Document Suggestion" AI prompt via GraphQL to generate
1688
+ * a natural language template optimized for vector embeddings.
1689
+ */
1690
+ async callSuggestionPrompt(entityName, useCase) {
1691
+ const md = new Metadata();
1692
+ const entity = md.Entities.find(e => e.Name === entityName);
1693
+ if (!entity) {
1694
+ throw new Error(`Entity "${entityName}" not found in metadata`);
1695
+ }
1696
+ const prompt = this.findSuggestionPrompt();
1697
+ const provider = Metadata.Provider;
1698
+ if (!provider) {
1699
+ throw new Error('GraphQL provider not available');
1700
+ }
1701
+ const aiClient = new GraphQLAIClient(provider);
1702
+ const data = this.buildPromptData(entity, useCase);
1703
+ const result = await aiClient.RunAIPrompt({
1704
+ promptId: prompt.ID,
1705
+ data,
1706
+ });
1707
+ if (!result.success) {
1708
+ throw new Error(result.error || 'AI prompt execution failed');
1709
+ }
1710
+ const parsed = result.parsedResult;
1711
+ if (!parsed?.template) {
1712
+ throw new Error('AI returned no template in response');
1713
+ }
1714
+ return parsed;
1715
+ }
1716
+ /** Find the Entity Document Suggestion prompt from AIEngineBase */
1717
+ findSuggestionPrompt() {
1718
+ const prompt = AIEngineBase.Instance.Prompts.find((p) => p.Name === 'Entity Document Suggestion');
1719
+ if (!prompt) {
1720
+ throw new Error('AI Prompt "Entity Document Suggestion" not found. ' +
1721
+ 'Run "npx mj sync push --dir=metadata --include=prompts" to install it.');
1722
+ }
1723
+ return prompt;
1724
+ }
1725
+ /** Build the data payload for the suggestion prompt */
1726
+ buildPromptData(entity, useCase) {
1727
+ const fields = entity.Fields.map(f => ({
1728
+ Name: f.Name,
1729
+ Type: f.Type,
1730
+ IsPrimaryKey: f.IsPrimaryKey,
1731
+ IsUnique: f.IsUnique,
1732
+ MaxLength: f.MaxLength,
1733
+ AllowsNull: f.AllowsNull,
1734
+ Description: f.Description || '',
1735
+ }));
1736
+ const md = new Metadata();
1737
+ const relationships = entity.RelatedEntities
1738
+ .filter(r => r.Type === 'One to Many' || r.Type === 'Many to One')
1739
+ .slice(0, 20)
1740
+ .map(r => {
1741
+ const relatedEntity = md.Entities.find(e => e.Name === r.RelatedEntity);
1742
+ const relFields = relatedEntity
1743
+ ? relatedEntity.Fields
1744
+ .filter(f => !f.IsPrimaryKey && f.Type !== 'datetimeoffset')
1745
+ .map(f => f.Name)
1746
+ : [];
1747
+ return {
1748
+ Name: r.RelatedEntityJoinField || r.RelatedEntity,
1749
+ RelatedEntity: r.RelatedEntity,
1750
+ Fields: relFields,
1751
+ ForeignKeyField: r.RelatedEntityJoinField || '',
1752
+ };
1753
+ });
1754
+ return {
1755
+ EntityName: entity.Name,
1756
+ FieldsJSON: JSON.stringify(fields, null, 2),
1757
+ RelationshipsJSON: JSON.stringify(relationships, null, 2),
1758
+ UseCase: useCase,
1759
+ };
1760
+ }
1761
+ static ɵfac = /*@__PURE__*/ (() => { let ɵVectorManagementResourceComponent_BaseFactory; return function VectorManagementResourceComponent_Factory(__ngFactoryType__) { return (ɵVectorManagementResourceComponent_BaseFactory || (ɵVectorManagementResourceComponent_BaseFactory = i0.ɵɵgetInheritedFactory(VectorManagementResourceComponent)))(__ngFactoryType__ || VectorManagementResourceComponent); }; })();
1762
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: VectorManagementResourceComponent, selectors: [["app-vector-management-resource"]], inputs: { EmbeddedMode: "EmbeddedMode" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "vector-loading"], ["text", "Loading vector management data..."], [1, "vector-dashboard"], [1, "view-mode-toggle"], [1, "kpi-row"], [3, "data"], [1, "content-area"], [1, "sync-table-panel"], [1, "panel-header"], [1, "panel-title"], [1, "fa-solid", "fa-table-list"], [1, "panel-actions"], ["title", "Use AI to suggest an Entity Document template", 1, "suggest-btn", 3, "click"], [1, "fa-solid", "fa-wand-magic-sparkles"], [1, "suggest-btn-text"], ["title", "Refresh data", 1, "refresh-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "empty-state"], [1, "table-wrapper"], [1, "sidebar"], [1, "sidebar-card"], [1, "sidebar-title"], [1, "fa-solid", "fa-heart-pulse"], [1, "health-row"], [1, "health-dot"], [1, "health-label"], [1, "health-status"], [1, "fa-solid", "fa-microchip"], [1, "model-info"], [1, "info-row"], [1, "info-label"], [1, "info-value"], [1, "fa-solid", "fa-hard-drive"], [1, "gauge-container"], [1, "gauge-bar"], [1, "gauge-fill"], [1, "gauge-label"], [1, "storage-detail"], [1, "slide-panel-overlay"], [1, "view-mode-btn", 3, "click"], [1, "fa-solid", "fa-cubes"], [1, "fa-solid", "fa-gauge-high"], [1, "fa-solid", "fa-folder-open"], [1, "sync-table"], [1, "text-right"], [1, "text-center"], [1, "entity-name"], [1, "document-name"], [1, "text-right", "vector-count"], [1, "last-synced"], [1, "status-badge"], [1, "text-center", "actions-cell"], ["title", "Sync now", 1, "sync-btn", 3, "click", "disabled"], ["title", "Edit entity document", 1, "edit-btn", 3, "click"], [1, "fa-solid", "fa-pen"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-play"], [1, "slide-panel-overlay", 3, "click"], [1, "slide-panel", "open", 3, "click"], [1, "suggest-dialog-header"], [1, "suggest-dialog-title"], [1, "suggest-close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "suggest-dialog-body"], [1, "suggest-form"], [1, "suggest-field"], [1, "suggest-label"], [1, "edit-readonly-value"], ["type", "text", 1, "suggest-input", 3, "ngModelChange", "ngModel"], [1, "suggest-select", 3, "ngModelChange", "ngModel"], [3, "value"], [1, "suggest-select", 3, "ngModel"], [1, "edit-readonly-value", 2, "font-size", "13px", "color", "var(--mj-text-muted)"], ["value", "Active"], ["value", "Inactive"], [1, "result-actions", 2, "margin-top", "1rem"], ["text", "Saving...", "size", "small"], ["value", ""], [1, "suggest-submit-btn", 3, "click"], [1, "fa-solid", "fa-save"], [1, "edit-delete-btn", 3, "click"], [1, "fa-solid", "fa-trash-can"], [1, "suggest-close-action", 3, "click"], [1, "slide-panel", 3, "click"], [1, "suggest-result"], [1, "entity-picker"], [1, "entity-picker-trigger", 3, "click"], [1, "fa-solid", "fa-chevron-down", "entity-picker-arrow"], [1, "entity-picker-dropdown"], [1, "use-case-options"], [1, "use-case-btn", 3, "click"], [1, "fa-solid", "fa-clone"], [1, "fa-solid", "fa-magnifying-glass"], [1, "fa-solid", "fa-tags"], [1, "suggest-submit-btn", 3, "click", "disabled"], [1, "suggestion-error"], [1, "fa-solid", "fa-table"], [1, "entity-picker-value"], [1, "fa-solid", "fa-search"], [1, "entity-picker-placeholder"], [1, "entity-picker-search"], ["type", "text", "placeholder", "Filter entities...", "autofocus", "", 1, "entity-picker-search-input", 3, "ngModelChange", "input", "ngModel"], [1, "entity-picker-list"], [1, "entity-picker-group"], [1, "entity-picker-empty"], [1, "entity-picker-group-header"], [1, "fa-solid", "fa-database"], [1, "entity-picker-item", 3, "entity-picker-item-selected"], [1, "entity-picker-item", 3, "click"], [1, "fa-solid", "fa-circle-exclamation"], [1, "result-section"], [1, "result-heading"], [1, "template-editor-wrapper"], ["language", "markdown", 3, "change", "value", "readonly", "lineWrapping"], [1, "result-tags"], [1, "result-tag"], [1, "result-section", "result-thresholds"], [1, "threshold-item"], [1, "threshold-label"], [1, "threshold-value"], [1, "result-reasoning"], [1, "suggest-field", 2, "margin-top", "0.75rem"], [1, "result-actions"], [1, "save-spinner"], [1, "result-relationship"], [1, "rel-name"], [1, "rel-fields"], [1, "fa-solid", "fa-floppy-disk"], [1, "suggest-submit-btn", "suggest-try-again-btn", 3, "click"], [1, "fa-solid", "fa-rotate"]], template: function VectorManagementResourceComponent_Template(rf, ctx) { if (rf & 1) {
1763
+ i0.ɵɵconditionalCreate(0, VectorManagementResourceComponent_Conditional_0_Template, 2, 0, "div", 0)(1, VectorManagementResourceComponent_Conditional_1_Template, 57, 16);
1764
+ } if (rf & 2) {
1765
+ i0.ɵɵconditional(ctx.IsLoading ? 0 : 1);
1766
+ } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.CodeEditorComponent, i3.LoadingComponent, i4.KPICardComponent, i5.DecimalPipe], styles: ["\n\n\n\n\n\n\n\n.vector-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 400px;\n}\n\n\n\n.view-mode-toggle[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.25rem;\n padding: 0 24px 0;\n margin-bottom: -12px;\n}\n\n.view-mode-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 0.85rem;\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 font-size: 0.82rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.view-mode-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.view-mode-btn-active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n\n\n.vector-dashboard[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 24px;\n background: var(--mj-bg-page);\n min-height: 100%;\n}\n\n\n\n.kpi-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n}\n\n@media (max-width: 1200px) {\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 600px) {\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n\n\n.content-area[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 300px;\n gap: 24px;\n align-items: start;\n}\n\n@media (max-width: 1024px) {\n .content-area[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n\n\n.sync-table-panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.panel-title[_ngcontent-%COMP%] {\n margin: 0;\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.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.refresh-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 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 font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.refresh-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\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: 48px 24px;\n color: var(--mj-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 36px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\n.table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.sync-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.sync-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n padding: 10px 16px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n text-align: left;\n white-space: nowrap;\n}\n\n.sync-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px 16px;\n font-size: 13px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: middle;\n}\n\n.sync-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.sync-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:last-child td[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n.text-right[_ngcontent-%COMP%] {\n text-align: right;\n}\n\n.text-center[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.entity-name[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.document-name[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n.vector-count[_ngcontent-%COMP%] {\n font-variant-numeric: tabular-nums;\n font-weight: 600;\n}\n\n.last-synced[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: 12px;\n white-space: nowrap;\n}\n\n\n\n\n.actions-cell[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n align-items: center;\n justify-content: center;\n}\n\n.edit-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.edit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n}\n\n.edit-delete-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-status-error-border);\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error-text);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.edit-delete-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-bg-surface));\n}\n\n.edit-readonly-value[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n padding: 8px 0;\n}\n\n\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 600;\n white-space: nowrap;\n}\n\n.status-synced[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success-text, var(--mj-status-success));\n}\n\n.status-syncing[_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.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n color: var(--mj-status-error-text, var(--mj-status-error));\n}\n\n.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n}\n\n\n\n.sync-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.sync-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.sync-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n\n\n.sidebar[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.sidebar-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 16px 20px;\n}\n\n.sidebar-title[_ngcontent-%COMP%] {\n margin: 0 0 14px 0;\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.sidebar-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 13px;\n}\n\n\n\n.health-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n}\n\n.health-dot[_ngcontent-%COMP%] {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.health-healthy[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n box-shadow: 0 0 6px color-mix(in srgb, var(--mj-status-success) 50%, transparent);\n}\n\n.health-degraded[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n box-shadow: 0 0 6px color-mix(in srgb, var(--mj-status-warning) 50%, transparent);\n}\n\n.health-offline[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n box-shadow: 0 0 6px color-mix(in srgb, var(--mj-status-error) 50%, transparent);\n}\n\n.health-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.health-status[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n padding-left: 18px;\n}\n\n\n\n.model-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.info-row[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n\n\n.gauge-container[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n}\n\n.gauge-bar[_ngcontent-%COMP%] {\n height: 8px;\n border-radius: 4px;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n margin-bottom: 6px;\n}\n\n.gauge-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: 4px;\n background: var(--mj-brand-primary);\n transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 2px;\n}\n\n.gauge-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.storage-detail[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n.panel-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n\n\n.suggest-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.suggest-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary-hover);\n}\n\n\n\n.slide-panel-overlay[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n}\n\n.slide-panel[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n height: 100vh;\n width: 480px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n box-shadow: -4px 0 24px color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n transform: translateX(100%);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n overflow-y: auto;\n}\n\n.slide-panel.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.suggest-dialog-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.suggest-dialog-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.suggest-dialog-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.suggest-close-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n color: var(--mj-text-muted);\n font-size: 16px;\n cursor: pointer;\n padding: 4px;\n}\n\n.suggest-close-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.suggest-dialog-body[_ngcontent-%COMP%] {\n padding: 24px;\n}\n\n\n\n.suggest-form[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.suggest-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.suggest-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.suggest-select[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n}\n\n.suggest-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n\n\n\n.use-case-options[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.use-case-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.use-case-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.use-case-btn-active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.use-case-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n\n.entity-picker[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.entity-picker-trigger[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 9px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n transition: border-color 0.15s;\n}\n\n.entity-picker-trigger[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.entity-picker-placeholder[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n flex: 1;\n}\n\n.entity-picker-value[_ngcontent-%COMP%] {\n flex: 1;\n font-weight: 500;\n}\n\n.entity-picker-arrow[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n transition: transform 0.2s;\n}\n\n.entity-picker-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: var(--mj-bg-surface-elevated, var(--mj-bg-surface));\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 8px 32px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n z-index: 100;\n max-height: 350px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.entity-picker-search[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.entity-picker-search[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.entity-picker-search-input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n background: transparent;\n color: var(--mj-text-primary);\n font-size: 13px;\n outline: none;\n}\n\n.entity-picker-search-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.entity-picker-list[_ngcontent-%COMP%] {\n overflow-y: auto;\n max-height: 300px;\n padding: 4px 0;\n}\n\n.entity-picker-group-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px 4px;\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n background: var(--mj-bg-surface-elevated, var(--mj-bg-surface));\n}\n\n.entity-picker-group-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.entity-picker-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 7px 14px 7px 28px;\n border: none;\n background: transparent;\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n transition: background 0.1s;\n}\n\n.entity-picker-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.entity-picker-item-selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.entity-picker-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.entity-picker-item-selected[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.entity-picker-empty[_ngcontent-%COMP%] {\n padding: 20px 14px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n}\n\n\n\n\n.template-editor-wrapper[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 120px;\n max-height: 300px;\n}\n\n.template-editor-wrapper[_ngcontent-%COMP%] .cm-editor {\n min-height: 120px;\n max-height: 300px;\n font-size: 13px;\n}\n\n.suggest-submit-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px 20px;\n border: none;\n border-radius: 6px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.suggest-submit-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.suggestion-error[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\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 font-size: 13px;\n line-height: 1.4;\n}\n\n.suggestion-error[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n.suggest-submit-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n.suggest-result[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.result-section[_ngcontent-%COMP%] {\n border-bottom: 1px solid var(--mj-border-subtle);\n padding-bottom: 12px;\n}\n\n.result-section[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.result-heading[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.result-template[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n padding: 12px;\n font-size: 12px;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-break: break-all;\n margin: 0;\n}\n\n.result-tags[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.result-tag[_ngcontent-%COMP%] {\n padding: 3px 10px;\n border-radius: 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 500;\n}\n\n.result-relationship[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n}\n\n.rel-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.rel-fields[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.result-thresholds[_ngcontent-%COMP%] {\n display: flex;\n gap: 24px;\n}\n\n.threshold-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.threshold-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.threshold-value[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.result-reasoning[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n.result-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n}\n\n.suggest-close-action[_ngcontent-%COMP%] {\n padding: 10px 20px;\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 font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.suggest-close-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.suggest-input[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.suggest-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n\n\n.suggest-try-again-btn[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.suggest-try-again-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n\n\n.save-spinner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px 0;\n}\n\n\n\n\n\n\n@media (max-width: 768px) {\n .panel-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 12px;\n }\n\n .panel-actions[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n}\n\n@media (max-width: 600px) {\n .slide-panel[_ngcontent-%COMP%] {\n width: 100vw;\n max-width: 100vw;\n }\n}\n\n@media (max-width: 480px) {\n .vector-dashboard[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .suggest-btn[_ngcontent-%COMP%] .suggest-btn-text[_ngcontent-%COMP%] {\n display: none;\n }\n}"] });
1767
+ };
1768
+ VectorManagementResourceComponent = __decorate([
1769
+ RegisterClass(BaseResourceComponent, 'VectorManagementResource')
1770
+ ], VectorManagementResourceComponent);
1771
+ export { VectorManagementResourceComponent };
1772
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(VectorManagementResourceComponent, [{
1773
+ type: Component,
1774
+ args: [{ standalone: false, selector: 'app-vector-management-resource', template: "@if (IsLoading) {\n <div class=\"vector-loading\">\n <mj-loading text=\"Loading vector management data...\"></mj-loading>\n </div>\n} @else {\n <div class=\"vector-dashboard\">\n <!-- View Mode Toggle -->\n @if (!EmbeddedMode) {\n <div class=\"view-mode-toggle\">\n <button class=\"view-mode-btn\" [class.view-mode-btn-active]=\"ViewMode === 'index'\" (click)=\"ViewMode = 'index'\">\n <i class=\"fa-solid fa-cubes\"></i> Index View\n </button>\n <button class=\"view-mode-btn\" [class.view-mode-btn-active]=\"ViewMode === 'operations'\" (click)=\"ViewMode = 'operations'\">\n <i class=\"fa-solid fa-gauge-high\"></i> Operations\n </button>\n </div>\n }\n\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n @for (card of KPICards; track card.title) {\n <app-kpi-card [data]=\"card\"></app-kpi-card>\n }\n </div>\n\n <!-- Main Content Area: Table + Sidebar -->\n <div class=\"content-area\">\n <!-- Entity Sync Table -->\n <div class=\"sync-table-panel\">\n <div class=\"panel-header\">\n <h3 class=\"panel-title\">\n <i class=\"fa-solid fa-table-list\"></i>\n Entity Sync Status\n </h3>\n <div class=\"panel-actions\">\n <button class=\"suggest-btn\" (click)=\"OpenSuggestDialog()\" title=\"Use AI to suggest an Entity Document template\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n <span class=\"suggest-btn-text\">Suggest Document</span>\n </button>\n <button class=\"refresh-btn\" (click)=\"LoadData()\" title=\"Refresh data\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n Refresh\n </button>\n </div>\n </div>\n\n @if (SyncRows.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-folder-open\"></i>\n <p>No entity documents configured for vectorization.</p>\n </div>\n } @else {\n <div class=\"table-wrapper\">\n <table class=\"sync-table\">\n <thead>\n <tr>\n <th>Entity</th>\n <th>Document</th>\n <th class=\"text-right\">Vectors</th>\n <th>Last Synced</th>\n <th>Status</th>\n <th class=\"text-center\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (row of SyncRows; track row.EntityDocumentID) {\n <tr>\n <td class=\"entity-name\">{{ row.EntityName }}</td>\n <td class=\"document-name\">{{ row.DocumentName }}</td>\n <td class=\"text-right vector-count\">{{ row.VectorCount | number }}</td>\n <td class=\"last-synced\">{{ FormatDate(row.LastSynced) }}</td>\n <td>\n <span class=\"status-badge\" [class]=\"GetStatusClass(row.Status)\">\n <i [class]=\"GetStatusIcon(row.Status)\"></i>\n @if (row.Status === 'Syncing' && row.PercentComplete > 0) {\n {{ row.PercentComplete }}%\n } @else {\n {{ row.Status }}\n }\n </span>\n </td>\n <td class=\"text-center actions-cell\">\n <button\n class=\"sync-btn\"\n [disabled]=\"SyncingIds.has(row.EntityDocumentID)\"\n (click)=\"SyncEntity(row.EntityDocumentID)\"\n title=\"Sync now\">\n @if (SyncingIds.has(row.EntityDocumentID)) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n {{ row.PercentComplete > 0 ? row.PercentComplete + '%' : 'Sync' }}\n } @else {\n <i class=\"fa-solid fa-play\"></i>\n Sync\n }\n </button>\n <button\n class=\"edit-btn\"\n (click)=\"OpenEditPanel(row.EntityDocumentID)\"\n title=\"Edit entity document\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n\n <!-- Sidebar Panels -->\n <div class=\"sidebar\">\n <!-- Vector DB Health -->\n <div class=\"sidebar-card\">\n <h4 class=\"sidebar-title\">\n <i class=\"fa-solid fa-heart-pulse\"></i>\n Vector DB Health\n </h4>\n <div class=\"health-row\">\n <span class=\"health-dot\" [class]=\"DBHealthClass\"></span>\n <span class=\"health-label\">{{ VectorDBName }}</span>\n </div>\n <div class=\"health-status\">{{ VectorDBStatus }}</div>\n </div>\n\n <!-- Embedding Model Info -->\n <div class=\"sidebar-card\">\n <h4 class=\"sidebar-title\">\n <i class=\"fa-solid fa-microchip\"></i>\n Embedding Model\n </h4>\n <div class=\"model-info\">\n <div class=\"info-row\">\n <span class=\"info-label\">Model</span>\n <span class=\"info-value\">{{ EmbeddingModel.Name }}</span>\n </div>\n @if (EmbeddingModel.Dimensions != null) {\n <div class=\"info-row\">\n <span class=\"info-label\">Dimensions</span>\n <span class=\"info-value\">{{ EmbeddingModel.Dimensions | number }}</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Storage Usage -->\n <div class=\"sidebar-card\">\n <h4 class=\"sidebar-title\">\n <i class=\"fa-solid fa-hard-drive\"></i>\n Vectorization Coverage\n </h4>\n <div class=\"gauge-container\">\n <div class=\"gauge-bar\">\n <div class=\"gauge-fill\" [style.width.%]=\"StorageUsagePercent\"></div>\n </div>\n <div class=\"gauge-label\">{{ StorageLabel }} of records vectorized</div>\n </div>\n <div class=\"storage-detail\">\n {{ TotalVectors | number }} vectors stored\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Edit Entity Document Slide-in Panel -->\n @if (ShowEditPanel) {\n <div class=\"slide-panel-overlay\" (click)=\"CloseEditPanel()\">\n <div class=\"slide-panel open\" (click)=\"$event.stopPropagation()\">\n <div class=\"suggest-dialog-header\">\n <h3 class=\"suggest-dialog-title\">\n <i class=\"fa-solid fa-pen\"></i>\n Edit Entity Document\n </h3>\n <button class=\"suggest-close-btn\" (click)=\"CloseEditPanel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"suggest-dialog-body\">\n <div class=\"suggest-form\">\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Entity</label>\n <span class=\"edit-readonly-value\">{{ EditDocEntityName }}</span>\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Document Name</label>\n <input class=\"suggest-input\" type=\"text\" [(ngModel)]=\"EditDocName\" />\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Embedding Model</label>\n <select class=\"suggest-select\" [(ngModel)]=\"EditDocAIModelID\">\n @for (model of AvailableEmbeddingModels; track model.ID) {\n <option [value]=\"model.ID\">{{ model.Name }}</option>\n }\n </select>\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Vector Database</label>\n <select class=\"suggest-select\" [(ngModel)]=\"EditDocVectorDBID\">\n @for (db of vectorDatabases; track db.ID) {\n <option [value]=\"db.ID\">{{ db.Name }}</option>\n }\n </select>\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Vector Index</label>\n @if (EditFilteredIndexes.length > 0) {\n <select class=\"suggest-select\" [(ngModel)]=\"EditDocVectorIndexID\">\n <option value=\"\">Auto (create/find matching index)</option>\n @for (idx of EditFilteredIndexes; track idx.ID) {\n <option [value]=\"idx.ID\">{{ idx.Name }}</option>\n }\n </select>\n } @else {\n <span class=\"edit-readonly-value\" style=\"font-size: 13px; color: var(--mj-text-muted);\">\n No indexes for this database \u2014 one will be created automatically on sync\n </span>\n }\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Status</label>\n <select class=\"suggest-select\" [(ngModel)]=\"EditDocStatus\">\n <option value=\"Active\">Active</option>\n <option value=\"Inactive\">Inactive</option>\n </select>\n </div>\n <div class=\"result-actions\" style=\"margin-top: 1rem\">\n @if (IsEditSaving || IsEditDeleting) {\n <mj-loading text=\"Saving...\" size=\"small\"></mj-loading>\n } @else {\n <button class=\"suggest-submit-btn\" (click)=\"SaveEditedDocument()\">\n <i class=\"fa-solid fa-save\"></i> Save Changes\n </button>\n <button class=\"edit-delete-btn\" (click)=\"DeleteEntityDocument()\">\n <i class=\"fa-solid fa-trash-can\"></i> Delete\n </button>\n <button class=\"suggest-close-action\" (click)=\"CloseEditPanel()\">\n Cancel\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Suggest Document Slide-in Panel -->\n @if (ShowSuggestDialog) {\n <div class=\"slide-panel-overlay\" (click)=\"CloseSuggestDialog()\">\n <div class=\"slide-panel\" [class.open]=\"ShowSuggestDialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"suggest-dialog-header\">\n <h3 class=\"suggest-dialog-title\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n AI Document Suggestion\n </h3>\n <button class=\"suggest-close-btn\" (click)=\"CloseSuggestDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"suggest-dialog-body\">\n @if (!SuggestionResult) {\n <div class=\"suggest-form\">\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Entity</label>\n <div class=\"entity-picker\">\n <button class=\"entity-picker-trigger\" (click)=\"ToggleEntityPicker()\">\n @if (SuggestEntityName) {\n <i class=\"fa-solid fa-table\"></i>\n <span class=\"entity-picker-value\">{{ SuggestEntityName }}</span>\n } @else {\n <i class=\"fa-solid fa-search\"></i>\n <span class=\"entity-picker-placeholder\">Search and select an entity...</span>\n }\n <i class=\"fa-solid fa-chevron-down entity-picker-arrow\"></i>\n </button>\n @if (ShowEntityPicker) {\n <div class=\"entity-picker-dropdown\">\n <div class=\"entity-picker-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n class=\"entity-picker-search-input\"\n placeholder=\"Filter entities...\"\n [(ngModel)]=\"EntitySearchText\"\n (input)=\"FilterEntities()\"\n autofocus />\n </div>\n <div class=\"entity-picker-list\">\n @for (group of FilteredEntityGroups; track group.SchemaName) {\n <div class=\"entity-picker-group\">\n <div class=\"entity-picker-group-header\">\n <i class=\"fa-solid fa-database\"></i>\n {{ group.SchemaName }}\n </div>\n @for (entity of group.Entities; track entity.ID) {\n <button class=\"entity-picker-item\"\n [class.entity-picker-item-selected]=\"entity.Name === SuggestEntityName\"\n (click)=\"SelectEntity(entity.Name)\">\n <i class=\"fa-solid fa-table\"></i>\n {{ entity.Name }}\n </button>\n }\n </div>\n }\n @if (FilteredEntityGroups.length === 0) {\n <div class=\"entity-picker-empty\">\n No entities matching \"{{ EntitySearchText }}\"\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Use Case</label>\n <div class=\"use-case-options\">\n <button class=\"use-case-btn\"\n [class.use-case-btn-active]=\"SuggestUseCase === 'duplicate detection'\"\n (click)=\"SuggestUseCase = 'duplicate detection'\">\n <i class=\"fa-solid fa-clone\"></i>\n Duplicate Detection\n </button>\n <button class=\"use-case-btn\"\n [class.use-case-btn-active]=\"SuggestUseCase === 'search'\"\n (click)=\"SuggestUseCase = 'search'\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n Search\n </button>\n <button class=\"use-case-btn\"\n [class.use-case-btn-active]=\"SuggestUseCase === 'classification'\"\n (click)=\"SuggestUseCase = 'classification'\">\n <i class=\"fa-solid fa-tags\"></i>\n Classification\n </button>\n </div>\n </div>\n <button class=\"suggest-submit-btn\"\n [disabled]=\"IsSuggesting || !SuggestEntityName\"\n (click)=\"RunSuggestion()\">\n @if (IsSuggesting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Generating with AI...\n } @else {\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i> Generate Template\n }\n </button>\n @if (SuggestionError) {\n <div class=\"suggestion-error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ SuggestionError }}\n </div>\n }\n </div>\n } @else {\n <div class=\"suggest-result\">\n <div class=\"result-section\">\n <h4 class=\"result-heading\">Suggested Template</h4>\n <div class=\"template-editor-wrapper\">\n <mj-code-editor\n [value]=\"EditableTemplate\"\n language=\"markdown\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"OnTemplateChange($event)\">\n </mj-code-editor>\n </div>\n </div>\n <div class=\"result-section\">\n <h4 class=\"result-heading\">Selected Fields</h4>\n <div class=\"result-tags\">\n @for (field of SuggestionResult.selectedFields; track field) {\n <span class=\"result-tag\">{{ field }}</span>\n }\n </div>\n </div>\n @if (SuggestionResult.selectedRelationships.length > 0) {\n <div class=\"result-section\">\n <h4 class=\"result-heading\">Related Entities</h4>\n @for (rel of SuggestionResult.selectedRelationships; track rel.name) {\n <div class=\"result-relationship\">\n <span class=\"rel-name\">{{ rel.name }}</span>\n <span class=\"rel-fields\">{{ rel.fields.join(', ') }}</span>\n </div>\n }\n </div>\n }\n <div class=\"result-section result-thresholds\">\n <div class=\"threshold-item\">\n <span class=\"threshold-label\">Potential Match</span>\n <span class=\"threshold-value\">{{ (SuggestionResult.potentialMatchThreshold * 100).toFixed(0) }}%</span>\n </div>\n <div class=\"threshold-item\">\n <span class=\"threshold-label\">Absolute Match</span>\n <span class=\"threshold-value\">{{ (SuggestionResult.absoluteMatchThreshold * 100).toFixed(0) }}%</span>\n </div>\n </div>\n <div class=\"result-section\">\n <h4 class=\"result-heading\">Reasoning</h4>\n <p class=\"result-reasoning\">{{ SuggestionResult.reasoning }}</p>\n </div>\n <div class=\"result-section\">\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Document Name</label>\n <input class=\"suggest-input\" type=\"text\" [(ngModel)]=\"SaveDocumentName\" />\n </div>\n <div class=\"suggest-field\" style=\"margin-top: 0.75rem\">\n <label class=\"suggest-label\">Embedding Model</label>\n <select class=\"suggest-select\" [(ngModel)]=\"SelectedEmbeddingModelID\">\n @for (model of AvailableEmbeddingModels; track model.ID) {\n <option [value]=\"model.ID\">{{ model.Name }}</option>\n }\n </select>\n </div>\n <div class=\"suggest-field\" style=\"margin-top: 0.75rem\">\n <label class=\"suggest-label\">Vector Database</label>\n <select class=\"suggest-select\" [(ngModel)]=\"SelectedVectorDBID\">\n @for (db of vectorDatabases; track db.ID) {\n <option [value]=\"db.ID\">{{ db.Name }}</option>\n }\n </select>\n </div>\n <div class=\"suggest-field\" style=\"margin-top: 0.75rem\">\n <label class=\"suggest-label\">Vector Index</label>\n @if (FilteredIndexesForSelectedDB.length > 0) {\n <select class=\"suggest-select\" [(ngModel)]=\"SelectedVectorIndexID\">\n <option value=\"\">Auto (create/find matching index)</option>\n @for (idx of FilteredIndexesForSelectedDB; track idx.ID) {\n <option [value]=\"idx.ID\">{{ idx.Name }}</option>\n }\n </select>\n } @else {\n <span class=\"edit-readonly-value\" style=\"font-size: 13px; color: var(--mj-text-muted);\">\n No indexes yet \u2014 create one in Configuration > Vector Database, or one will be created on sync\n </span>\n }\n </div>\n </div>\n <div class=\"result-actions\">\n @if (IsSavingDocument) {\n <div class=\"save-spinner\">\n <mj-loading text=\"Saving...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n <button class=\"suggest-submit-btn\" (click)=\"SaveAsEntityDocument()\">\n <i class=\"fa-solid fa-floppy-disk\"></i> Save as Entity Document\n </button>\n <button class=\"suggest-submit-btn suggest-try-again-btn\" (click)=\"ClearSuggestion()\">\n <i class=\"fa-solid fa-rotate\"></i> Try Again\n </button>\n <button class=\"suggest-close-action\" (click)=\"CloseSuggestDialog()\">\n Close\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n}\n", styles: ["/* ================================================================\n Vector Management Dashboard\n All colors use MJ design tokens from _tokens.scss\n ================================================================ */\n\n/* --- Loading state --- */\n.vector-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 400px;\n}\n\n/* --- View Mode Toggle --- */\n.view-mode-toggle {\n display: flex;\n gap: 0.25rem;\n padding: 0 24px 0;\n margin-bottom: -12px;\n}\n\n.view-mode-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 0.85rem;\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 font-size: 0.82rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.view-mode-btn:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.view-mode-btn-active {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n/* --- Dashboard container --- */\n.vector-dashboard {\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 24px;\n background: var(--mj-bg-page);\n min-height: 100%;\n}\n\n/* --- KPI cards row --- */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n}\n\n@media (max-width: 1200px) {\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 600px) {\n .kpi-row {\n grid-template-columns: 1fr;\n }\n}\n\n/* --- Main content: table + sidebar --- */\n.content-area {\n display: grid;\n grid-template-columns: 1fr 300px;\n gap: 24px;\n align-items: start;\n}\n\n@media (max-width: 1024px) {\n .content-area {\n grid-template-columns: 1fr;\n }\n}\n\n/* --- Sync table panel --- */\n.sync-table-panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.panel-title {\n margin: 0;\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.panel-title i {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.refresh-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 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 font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.refresh-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\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: 48px 24px;\n color: var(--mj-text-muted);\n}\n\n.empty-state i {\n font-size: 36px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 14px;\n}\n\n/* --- Table --- */\n.table-wrapper {\n overflow-x: auto;\n}\n\n.sync-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.sync-table th {\n padding: 10px 16px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n text-align: left;\n white-space: nowrap;\n}\n\n.sync-table td {\n padding: 12px 16px;\n font-size: 13px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: middle;\n}\n\n.sync-table tbody tr:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.sync-table tbody tr:last-child td {\n border-bottom: none;\n}\n\n.text-right {\n text-align: right;\n}\n\n.text-center {\n text-align: center;\n}\n\n.entity-name {\n font-weight: 600;\n}\n\n.document-name {\n color: var(--mj-text-secondary);\n}\n\n.vector-count {\n font-variant-numeric: tabular-nums;\n font-weight: 600;\n}\n\n.last-synced {\n color: var(--mj-text-secondary);\n font-size: 12px;\n white-space: nowrap;\n}\n\n/* --- Action buttons in table --- */\n\n.actions-cell {\n display: flex;\n gap: 6px;\n align-items: center;\n justify-content: center;\n}\n\n.edit-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.edit-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n}\n\n.edit-delete-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-status-error-border);\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error-text);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.edit-delete-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-bg-surface));\n}\n\n.edit-readonly-value {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n padding: 8px 0;\n}\n\n/* --- Status badges --- */\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 600;\n white-space: nowrap;\n}\n\n.status-synced {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success-text, var(--mj-status-success));\n}\n\n.status-syncing {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.status-error {\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n color: var(--mj-status-error-text, var(--mj-status-error));\n}\n\n.status-pending {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n}\n\n/* --- Sync button --- */\n.sync-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.sync-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.sync-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* ================================================================\n Sidebar\n ================================================================ */\n.sidebar {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.sidebar-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 16px 20px;\n}\n\n.sidebar-title {\n margin: 0 0 14px 0;\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.sidebar-title i {\n color: var(--mj-brand-primary);\n font-size: 13px;\n}\n\n/* --- Vector DB Health --- */\n.health-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n}\n\n.health-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.health-healthy {\n background: var(--mj-status-success);\n box-shadow: 0 0 6px color-mix(in srgb, var(--mj-status-success) 50%, transparent);\n}\n\n.health-degraded {\n background: var(--mj-status-warning);\n box-shadow: 0 0 6px color-mix(in srgb, var(--mj-status-warning) 50%, transparent);\n}\n\n.health-offline {\n background: var(--mj-status-error);\n box-shadow: 0 0 6px color-mix(in srgb, var(--mj-status-error) 50%, transparent);\n}\n\n.health-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.health-status {\n font-size: 12px;\n color: var(--mj-text-muted);\n padding-left: 18px;\n}\n\n/* --- Model Info --- */\n.model-info {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.info-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.info-label {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.info-value {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n/* --- Storage / Coverage Gauge --- */\n.gauge-container {\n margin-bottom: 8px;\n}\n\n.gauge-bar {\n height: 8px;\n border-radius: 4px;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n margin-bottom: 6px;\n}\n\n.gauge-fill {\n height: 100%;\n border-radius: 4px;\n background: var(--mj-brand-primary);\n transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 2px;\n}\n\n.gauge-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.storage-detail {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* --- Panel actions row --- */\n.panel-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* --- Suggest Document Button --- */\n.suggest-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.suggest-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary-hover);\n}\n\n/* --- Slide-in Panel Overlay --- */\n.slide-panel-overlay {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n}\n\n.slide-panel {\n position: fixed;\n top: 0;\n right: 0;\n height: 100vh;\n width: 480px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n box-shadow: -4px 0 24px color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n transform: translateX(100%);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n overflow-y: auto;\n}\n\n.slide-panel.open {\n transform: translateX(0);\n}\n\n.suggest-dialog-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.suggest-dialog-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.suggest-dialog-title i {\n color: var(--mj-brand-primary);\n}\n\n.suggest-close-btn {\n border: none;\n background: none;\n color: var(--mj-text-muted);\n font-size: 16px;\n cursor: pointer;\n padding: 4px;\n}\n\n.suggest-close-btn:hover {\n color: var(--mj-text-primary);\n}\n\n.suggest-dialog-body {\n padding: 24px;\n}\n\n/* --- Suggest Form --- */\n.suggest-form {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.suggest-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.suggest-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.suggest-select {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n}\n\n.suggest-select:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n/* ---- Use Case Button Group ---- */\n\n.use-case-options {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.use-case-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.use-case-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.use-case-btn-active {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.use-case-btn i {\n font-size: 12px;\n}\n\n/* ---- Entity Picker (grouped by schema) ---- */\n\n.entity-picker {\n position: relative;\n}\n\n.entity-picker-trigger {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 9px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n transition: border-color 0.15s;\n}\n\n.entity-picker-trigger:hover {\n border-color: var(--mj-border-strong);\n}\n\n.entity-picker-placeholder {\n color: var(--mj-text-muted);\n flex: 1;\n}\n\n.entity-picker-value {\n flex: 1;\n font-weight: 500;\n}\n\n.entity-picker-arrow {\n font-size: 10px;\n color: var(--mj-text-muted);\n transition: transform 0.2s;\n}\n\n.entity-picker-dropdown {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: var(--mj-bg-surface-elevated, var(--mj-bg-surface));\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 8px 32px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n z-index: 100;\n max-height: 350px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.entity-picker-search {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.entity-picker-search i {\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.entity-picker-search-input {\n flex: 1;\n border: none;\n background: transparent;\n color: var(--mj-text-primary);\n font-size: 13px;\n outline: none;\n}\n\n.entity-picker-search-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.entity-picker-list {\n overflow-y: auto;\n max-height: 300px;\n padding: 4px 0;\n}\n\n.entity-picker-group-header {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px 4px;\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n background: var(--mj-bg-surface-elevated, var(--mj-bg-surface));\n}\n\n.entity-picker-group-header i {\n font-size: 10px;\n}\n\n.entity-picker-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 7px 14px 7px 28px;\n border: none;\n background: transparent;\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n transition: background 0.1s;\n}\n\n.entity-picker-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.entity-picker-item-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.entity-picker-item i {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.entity-picker-item-selected i {\n color: var(--mj-brand-primary);\n}\n\n.entity-picker-empty {\n padding: 20px 14px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n}\n\n/* ---- Template Editor ---- */\n\n.template-editor-wrapper {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 120px;\n max-height: 300px;\n}\n\n.template-editor-wrapper ::ng-deep .cm-editor {\n min-height: 120px;\n max-height: 300px;\n font-size: 13px;\n}\n\n.suggest-submit-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px 20px;\n border: none;\n border-radius: 6px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.suggest-submit-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.suggestion-error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\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 font-size: 13px;\n line-height: 1.4;\n}\n\n.suggestion-error i {\n flex-shrink: 0;\n}\n\n.suggest-submit-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* --- Suggestion Result --- */\n.suggest-result {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.result-section {\n border-bottom: 1px solid var(--mj-border-subtle);\n padding-bottom: 12px;\n}\n\n.result-section:last-child {\n border-bottom: none;\n}\n\n.result-heading {\n margin: 0 0 8px 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.result-template {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n padding: 12px;\n font-size: 12px;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-break: break-all;\n margin: 0;\n}\n\n.result-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.result-tag {\n padding: 3px 10px;\n border-radius: 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 500;\n}\n\n.result-relationship {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n}\n\n.rel-name {\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.rel-fields {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.result-thresholds {\n display: flex;\n gap: 24px;\n}\n\n.threshold-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.threshold-label {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.threshold-value {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.result-reasoning {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n.result-actions {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n}\n\n.suggest-close-action {\n padding: 10px 20px;\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 font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.suggest-close-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* --- Suggest Input --- */\n.suggest-input {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.suggest-input:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n/* --- Try Again Button (secondary style) --- */\n.suggest-try-again-btn {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.suggest-try-again-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n/* --- Save Spinner --- */\n.save-spinner {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px 0;\n}\n\n/* ================================================================\n Responsive \u2014 Vector Management\n ================================================================ */\n\n@media (max-width: 768px) {\n .panel-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 12px;\n }\n\n .panel-actions {\n flex-wrap: wrap;\n }\n}\n\n@media (max-width: 600px) {\n .slide-panel {\n width: 100vw;\n max-width: 100vw;\n }\n}\n\n@media (max-width: 480px) {\n .vector-dashboard {\n padding: 12px;\n }\n\n .suggest-btn .suggest-btn-text {\n display: none;\n }\n}\n"] }]
1775
+ }], null, { EmbeddedMode: [{
1776
+ type: Input
1777
+ }] }); })();
1778
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(VectorManagementResourceComponent, { className: "VectorManagementResourceComponent", filePath: "src/AI/components/vectors/vector-management-resource.component.ts", lineNumber: 69 }); })();
1779
+ export function LoadVectorManagementResource() {
1780
+ // Prevents tree-shaking
1781
+ }
1782
+ //# sourceMappingURL=vector-management-resource.component.js.map