@memberjunction/ng-dashboards 6.2.0-edge.4 → 6.2.0-edge.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +15 -7
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +7 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +209 -57
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts +12 -11
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.js +15 -15
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +28 -16
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +1 -0
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +30 -6
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +15 -7
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/sensitive-fields.d.ts +58 -0
- package/dist/AI/components/vectors/sensitive-fields.d.ts.map +1 -0
- package/dist/AI/components/vectors/sensitive-fields.js +251 -0
- package/dist/AI/components/vectors/sensitive-fields.js.map +1 -0
- package/dist/AI/components/vectors/vector-document-rules.d.ts +139 -0
- package/dist/AI/components/vectors/vector-document-rules.d.ts.map +1 -0
- package/dist/AI/components/vectors/vector-document-rules.js +182 -0
- package/dist/AI/components/vectors/vector-document-rules.js.map +1 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +83 -14
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +546 -271
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-store-selection.d.ts +32 -0
- package/dist/AI/components/vectors/vector-store-selection.d.ts.map +1 -0
- package/dist/AI/components/vectors/vector-store-selection.js +57 -0
- package/dist/AI/components/vectors/vector-store-selection.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts +236 -0
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.js +374 -0
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts +195 -0
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js +2910 -0
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js.map +1 -0
- package/dist/ChiefOfStaff/index.d.ts +3 -0
- package/dist/ChiefOfStaff/index.d.ts.map +1 -0
- package/dist/ChiefOfStaff/index.js +3 -0
- package/dist/ChiefOfStaff/index.js.map +1 -0
- package/dist/Communication/communication-agent-context.d.ts +11 -1
- package/dist/Communication/communication-agent-context.d.ts.map +1 -1
- package/dist/Communication/communication-agent-context.js +15 -0
- package/dist/Communication/communication-agent-context.js.map +1 -1
- package/dist/Communication/communication-dashboard.component.d.ts.map +1 -1
- package/dist/Communication/communication-dashboard.component.js +5 -0
- package/dist/Communication/communication-dashboard.component.js.map +1 -1
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +2 -1
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +23 -18
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.d.ts +27 -1
- package/dist/Communication/communication-providers-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +722 -78
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +11 -10
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/DashboardEditor/dashboard-editor.component.d.ts +17 -2
- package/dist/DashboardEditor/dashboard-editor.component.d.ts.map +1 -1
- package/dist/DashboardEditor/dashboard-editor.component.js +94 -43
- package/dist/DashboardEditor/dashboard-editor.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +49 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +220 -55
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.d.ts +2 -0
- package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
- package/dist/DevTools/app-state-inspector.component.d.ts.map +1 -1
- package/dist/DevTools/app-state-inspector.component.js +1 -0
- package/dist/DevTools/app-state-inspector.component.js.map +1 -1
- package/dist/DevTools/class-registry.component.d.ts.map +1 -1
- package/dist/DevTools/class-registry.component.js +1 -0
- package/dist/DevTools/class-registry.component.js.map +1 -1
- package/dist/DevTools/event-monitor.component.d.ts.map +1 -1
- package/dist/DevTools/event-monitor.component.js +2 -0
- package/dist/DevTools/event-monitor.component.js.map +1 -1
- package/dist/DevTools/graphql-console.component.d.ts.map +1 -1
- package/dist/DevTools/graphql-console.component.js.map +1 -1
- package/dist/DevTools/grid-width-lab.component.d.ts.map +1 -1
- package/dist/DevTools/grid-width-lab.component.js +1 -0
- package/dist/DevTools/grid-width-lab.component.js.map +1 -1
- package/dist/DevTools/layout-inspector.component.d.ts.map +1 -1
- package/dist/DevTools/layout-inspector.component.js +1 -0
- package/dist/DevTools/layout-inspector.component.js.map +1 -1
- package/dist/DevTools/lazy-module-status.component.d.ts.map +1 -1
- package/dist/DevTools/lazy-module-status.component.js +1 -0
- package/dist/DevTools/lazy-module-status.component.js.map +1 -1
- package/dist/DevTools/settings-explorer.component.d.ts.map +1 -1
- package/dist/DevTools/settings-explorer.component.js +1 -0
- package/dist/DevTools/settings-explorer.component.js.map +1 -1
- package/dist/DevTools/tab-strip-lab.component.d.ts.map +1 -1
- package/dist/DevTools/tab-strip-lab.component.js +1 -0
- package/dist/DevTools/tab-strip-lab.component.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts +5 -0
- package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +8 -5
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +2 -2
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +2 -2
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipeline.engine.d.ts +11 -1
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipeline.engine.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipeline.engine.js +24 -2
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipeline.engine.js.map +1 -1
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.d.ts +16 -2
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.js +87 -33
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.js.map +1 -1
- package/dist/LoginStudio/login-studio-inspector.component.d.ts +130 -0
- package/dist/LoginStudio/login-studio-inspector.component.d.ts.map +1 -0
- package/dist/LoginStudio/login-studio-inspector.component.js +781 -0
- package/dist/LoginStudio/login-studio-inspector.component.js.map +1 -0
- package/dist/LoginStudio/login-studio-resource.component.d.ts +161 -0
- package/dist/LoginStudio/login-studio-resource.component.d.ts.map +1 -0
- package/dist/LoginStudio/login-studio-resource.component.js +890 -0
- package/dist/LoginStudio/login-studio-resource.component.js.map +1 -0
- package/dist/MCP/mcp-dashboard.component.d.ts +24 -4
- package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +118 -65
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/PredictiveStudio/business-predictions.view-models.d.ts +1 -1
- package/dist/PredictiveStudio/business-predictions.view-models.d.ts.map +1 -1
- package/dist/PredictiveStudio/business-predictions.view-models.js +3 -3
- package/dist/PredictiveStudio/business-predictions.view-models.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.d.ts +6 -63
- package/dist/PredictiveStudio/components/ps-experiments.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.js +256 -521
- package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.d.ts +0 -18
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js +122 -249
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts +5 -9
- package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.js +98 -130
- package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts +53 -4
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.js +335 -326
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-row-drivers.component.d.ts +19 -0
- package/dist/PredictiveStudio/components/ps-row-drivers.component.d.ts.map +1 -0
- package/dist/PredictiveStudio/components/ps-row-drivers.component.js +85 -0
- package/dist/PredictiveStudio/components/ps-row-drivers.component.js.map +1 -0
- package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts +19 -1
- package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts.map +1 -1
- package/dist/PredictiveStudio/engine/predictive-studio.engine.js +51 -2
- package/dist/PredictiveStudio/engine/predictive-studio.engine.js.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts +3 -1
- package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-agent-context.js +3 -0
- package/dist/PredictiveStudio/predictive-studio-agent-context.js.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-score-history.service.d.ts +27 -4
- package/dist/PredictiveStudio/predictive-studio-score-history.service.d.ts.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-score-history.service.js +94 -61
- package/dist/PredictiveStudio/predictive-studio-score-history.service.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts +29 -5
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +185 -103
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.js +1 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.js.map +1 -1
- package/dist/Workflows/components/workflow-runs-resource.component.js +4 -4
- package/dist/Workflows/components/workflow-runs-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +22 -21
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +8 -2
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +2 -1
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +11 -3
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +3 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +4 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +72 -69
- package/dist/PredictiveStudio/at-risk.view-models.d.ts +0 -120
- package/dist/PredictiveStudio/at-risk.view-models.d.ts.map +0 -1
- package/dist/PredictiveStudio/at-risk.view-models.js +0 -261
- package/dist/PredictiveStudio/at-risk.view-models.js.map +0 -1
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.d.ts +0 -109
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.d.ts.map +0 -1
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.js +0 -323
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.js.map +0 -1
- package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.d.ts +0 -137
- package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.d.ts.map +0 -1
- package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.js +0 -826
- package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.js.map +0 -1
|
@@ -4,6 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
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
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
+
var VectorManagementResourceComponent_1;
|
|
7
8
|
/**
|
|
8
9
|
* @fileoverview Vector Management Resource Component
|
|
9
10
|
*
|
|
@@ -17,7 +18,7 @@ import { Subject } from 'rxjs';
|
|
|
17
18
|
import { takeUntil } from 'rxjs/operators';
|
|
18
19
|
import { RunView } from '@memberjunction/core';
|
|
19
20
|
import { KnowledgeHubMetadataEngine } from '@memberjunction/core-entities';
|
|
20
|
-
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
|
|
21
|
+
import { RegisterClass, UUIDsEqual, EscapeSQLString } from '@memberjunction/global';
|
|
21
22
|
import { BaseResourceComponent, NavigationService, ActivityService } from '@memberjunction/ng-shared';
|
|
22
23
|
import { GraphQLAIClient } from '@memberjunction/graphql-dataprovider';
|
|
23
24
|
import { AIEngineBase } from '@memberjunction/ai-engine-base';
|
|
@@ -25,8 +26,11 @@ import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
|
25
26
|
import { BuildSingleStaticParamConfiguration, ResolveActionJobTypeID } from '../../../shared/action-scheduled-job';
|
|
26
27
|
import { CronToHumanReadable } from '../autotagging/shared/classify.format';
|
|
27
28
|
import { BuildAutoVectorIndexName, FindMatchingVectorIndex } from './vector-index-auto';
|
|
29
|
+
import { ChosenIndexForSave, IndexesForSelection, SelectDatabase, SelectEmbeddingModel, SelectIndex, } from './vector-store-selection';
|
|
28
30
|
import { BuildVectorAgentContext, ResolveSyncRow, } from './vector-management-agent-context';
|
|
29
31
|
import { ValidateStringParam } from '../../../shared/agent-tool-validation';
|
|
32
|
+
import { WithoutSensitiveFields, SensitiveFieldsInTemplate } from './sensitive-fields';
|
|
33
|
+
import { ENTITY_DOCUMENT_TYPE_BY_USE_CASE, MAX_TEMPLATE_FIELDS, CapSelectedFields, EntityDocumentTypeForUseCase, SuggestionUseCaseForDocumentType, IsVectorizableEntity, SuggestedMatchThresholds, TemplateFieldCapRefusal, } from './vector-document-rules';
|
|
30
34
|
import * as i0 from "@angular/core";
|
|
31
35
|
import * as i1 from "@angular/common";
|
|
32
36
|
import * as i2 from "@angular/forms";
|
|
@@ -85,31 +89,31 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_For_3_Tem
|
|
|
85
89
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
86
90
|
i0.ɵɵelement(0, "mj-empty-state", 23);
|
|
87
91
|
} }
|
|
88
|
-
function
|
|
92
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
89
93
|
i0.ɵɵtext(0);
|
|
90
94
|
} if (rf & 2) {
|
|
91
95
|
const row_r7 = i0.ɵɵnextContext().$implicit;
|
|
92
96
|
i0.ɵɵtextInterpolate1(" ", row_r7.PercentComplete, "% ");
|
|
93
97
|
} }
|
|
94
|
-
function
|
|
98
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
95
99
|
i0.ɵɵtext(0);
|
|
96
100
|
} if (rf & 2) {
|
|
97
101
|
const row_r7 = i0.ɵɵnextContext().$implicit;
|
|
98
102
|
i0.ɵɵtextInterpolate1(" ", row_r7.Status, " ");
|
|
99
103
|
} }
|
|
100
|
-
function
|
|
101
|
-
i0.ɵɵelement(0, "i",
|
|
104
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
105
|
+
i0.ɵɵelement(0, "i", 61);
|
|
102
106
|
i0.ɵɵtext(1);
|
|
103
107
|
} if (rf & 2) {
|
|
104
108
|
const row_r7 = i0.ɵɵnextContext().$implicit;
|
|
105
109
|
i0.ɵɵadvance();
|
|
106
110
|
i0.ɵɵtextInterpolate1(" ", row_r7.PercentComplete > 0 ? row_r7.PercentComplete + "%" : "Sync", " ");
|
|
107
111
|
} }
|
|
108
|
-
function
|
|
109
|
-
i0.ɵɵelement(0, "i",
|
|
112
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
113
|
+
i0.ɵɵelement(0, "i", 62);
|
|
110
114
|
i0.ɵɵtext(1, " Sync ");
|
|
111
115
|
} }
|
|
112
|
-
function
|
|
116
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Template(rf, ctx) { if (rf & 1) {
|
|
113
117
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
114
118
|
i0.ɵɵelementStart(0, "tr")(1, "td", 49);
|
|
115
119
|
i0.ɵɵtext(2);
|
|
@@ -119,26 +123,29 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
119
123
|
i0.ɵɵelementEnd();
|
|
120
124
|
i0.ɵɵelementStart(5, "td", 51);
|
|
121
125
|
i0.ɵɵtext(6);
|
|
122
|
-
i0.ɵɵpipe(7, "number");
|
|
123
126
|
i0.ɵɵelementEnd();
|
|
124
|
-
i0.ɵɵelementStart(
|
|
125
|
-
i0.ɵɵtext(
|
|
127
|
+
i0.ɵɵelementStart(7, "td", 52);
|
|
128
|
+
i0.ɵɵtext(8);
|
|
129
|
+
i0.ɵɵpipe(9, "number");
|
|
130
|
+
i0.ɵɵelementEnd();
|
|
131
|
+
i0.ɵɵelementStart(10, "td", 53);
|
|
132
|
+
i0.ɵɵtext(11);
|
|
126
133
|
i0.ɵɵelementEnd();
|
|
127
|
-
i0.ɵɵelementStart(
|
|
128
|
-
i0.ɵɵelement(
|
|
129
|
-
i0.ɵɵconditionalCreate(
|
|
134
|
+
i0.ɵɵelementStart(12, "td")(13, "span", 54);
|
|
135
|
+
i0.ɵɵelement(14, "i");
|
|
136
|
+
i0.ɵɵconditionalCreate(15, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Conditional_15_Template, 1, 1)(16, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Conditional_16_Template, 1, 1);
|
|
130
137
|
i0.ɵɵelementEnd()();
|
|
131
|
-
i0.ɵɵelementStart(
|
|
132
|
-
i0.ɵɵlistener("click", function
|
|
133
|
-
i0.ɵɵconditionalCreate(
|
|
138
|
+
i0.ɵɵelementStart(17, "td", 55)(18, "button", 56);
|
|
139
|
+
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Template_button_click_18_listener() { const row_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SyncEntity(row_r7.EntityDocumentID)); });
|
|
140
|
+
i0.ɵɵconditionalCreate(19, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Conditional_19_Template, 2, 1)(20, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Conditional_20_Template, 2, 0);
|
|
134
141
|
i0.ɵɵelementEnd();
|
|
135
|
-
i0.ɵɵelementStart(
|
|
136
|
-
i0.ɵɵlistener("click", function
|
|
137
|
-
i0.ɵɵelement(
|
|
142
|
+
i0.ɵɵelementStart(21, "button", 57);
|
|
143
|
+
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Template_button_click_21_listener() { const row_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OpenScheduleSyncDialog(row_r7.EntityDocumentID)); });
|
|
144
|
+
i0.ɵɵelement(22, "i", 58);
|
|
138
145
|
i0.ɵɵelementEnd();
|
|
139
|
-
i0.ɵɵelementStart(
|
|
140
|
-
i0.ɵɵlistener("click", function
|
|
141
|
-
i0.ɵɵelement(
|
|
146
|
+
i0.ɵɵelementStart(23, "button", 59);
|
|
147
|
+
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Template_button_click_23_listener() { const row_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OpenEditPanel(row_r7.EntityDocumentID)); });
|
|
148
|
+
i0.ɵɵelement(24, "i", 60);
|
|
142
149
|
i0.ɵɵelementEnd()()();
|
|
143
150
|
} if (rf & 2) {
|
|
144
151
|
const row_r7 = ctx.$implicit;
|
|
@@ -148,7 +155,9 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
148
155
|
i0.ɵɵadvance(2);
|
|
149
156
|
i0.ɵɵtextInterpolate(row_r7.DocumentName);
|
|
150
157
|
i0.ɵɵadvance(2);
|
|
151
|
-
i0.ɵɵtextInterpolate(
|
|
158
|
+
i0.ɵɵtextInterpolate(row_r7.DocumentType);
|
|
159
|
+
i0.ɵɵadvance(2);
|
|
160
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(9, 12, row_r7.VectorCount));
|
|
152
161
|
i0.ɵɵadvance(3);
|
|
153
162
|
i0.ɵɵtextInterpolate(ctx_r1.FormatDate(row_r7.LastSynced));
|
|
154
163
|
i0.ɵɵadvance(2);
|
|
@@ -156,11 +165,11 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
156
165
|
i0.ɵɵadvance();
|
|
157
166
|
i0.ɵɵclassMap(ctx_r1.GetStatusIcon(row_r7.Status));
|
|
158
167
|
i0.ɵɵadvance();
|
|
159
|
-
i0.ɵɵconditional(row_r7.Status === "Syncing" && row_r7.PercentComplete > 0 ?
|
|
168
|
+
i0.ɵɵconditional(row_r7.Status === "Syncing" && row_r7.PercentComplete > 0 ? 15 : 16);
|
|
160
169
|
i0.ɵɵadvance(3);
|
|
161
170
|
i0.ɵɵproperty("disabled", ctx_r1.IsSyncing(row_r7.EntityDocumentID));
|
|
162
171
|
i0.ɵɵadvance();
|
|
163
|
-
i0.ɵɵconditional(ctx_r1.IsSyncing(row_r7.EntityDocumentID) ?
|
|
172
|
+
i0.ɵɵconditional(ctx_r1.IsSyncing(row_r7.EntityDocumentID) ? 19 : 20);
|
|
164
173
|
} }
|
|
165
174
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
166
175
|
i0.ɵɵelementStart(0, "div", 24)(1, "table", 46)(2, "thead")(3, "tr")(4, "th");
|
|
@@ -169,24 +178,27 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
169
178
|
i0.ɵɵelementStart(6, "th");
|
|
170
179
|
i0.ɵɵtext(7, "Document");
|
|
171
180
|
i0.ɵɵelementEnd();
|
|
172
|
-
i0.ɵɵelementStart(8, "th"
|
|
173
|
-
i0.ɵɵtext(9, "
|
|
181
|
+
i0.ɵɵelementStart(8, "th");
|
|
182
|
+
i0.ɵɵtext(9, "Type");
|
|
174
183
|
i0.ɵɵelementEnd();
|
|
175
|
-
i0.ɵɵelementStart(10, "th");
|
|
176
|
-
i0.ɵɵtext(11, "
|
|
184
|
+
i0.ɵɵelementStart(10, "th", 47);
|
|
185
|
+
i0.ɵɵtext(11, "Vectors");
|
|
177
186
|
i0.ɵɵelementEnd();
|
|
178
187
|
i0.ɵɵelementStart(12, "th");
|
|
179
|
-
i0.ɵɵtext(13, "
|
|
188
|
+
i0.ɵɵtext(13, "Last Synced");
|
|
189
|
+
i0.ɵɵelementEnd();
|
|
190
|
+
i0.ɵɵelementStart(14, "th");
|
|
191
|
+
i0.ɵɵtext(15, "Status");
|
|
180
192
|
i0.ɵɵelementEnd();
|
|
181
|
-
i0.ɵɵelementStart(
|
|
182
|
-
i0.ɵɵtext(
|
|
193
|
+
i0.ɵɵelementStart(16, "th", 48);
|
|
194
|
+
i0.ɵɵtext(17, "Actions");
|
|
183
195
|
i0.ɵɵelementEnd()()();
|
|
184
|
-
i0.ɵɵelementStart(
|
|
185
|
-
i0.ɵɵrepeaterCreate(
|
|
196
|
+
i0.ɵɵelementStart(18, "tbody");
|
|
197
|
+
i0.ɵɵrepeaterCreate(19, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_For_20_Template, 25, 14, "tr", null, _forTrack1);
|
|
186
198
|
i0.ɵɵelementEnd()()();
|
|
187
199
|
} if (rf & 2) {
|
|
188
200
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
189
|
-
i0.ɵɵadvance(
|
|
201
|
+
i0.ɵɵadvance(19);
|
|
190
202
|
i0.ɵɵrepeater(ctx_r1.SyncRows);
|
|
191
203
|
} }
|
|
192
204
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_31_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -202,7 +214,7 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
202
214
|
i0.ɵɵelementStart(0, "div", 36)(1, "span", 37);
|
|
203
215
|
i0.ɵɵtext(2, "Dimensions");
|
|
204
216
|
i0.ɵɵelementEnd();
|
|
205
|
-
i0.ɵɵelementStart(3, "span",
|
|
217
|
+
i0.ɵɵelementStart(3, "span", 63);
|
|
206
218
|
i0.ɵɵtext(4);
|
|
207
219
|
i0.ɵɵpipe(5, "number");
|
|
208
220
|
i0.ɵɵelementEnd()();
|
|
@@ -211,16 +223,16 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
211
223
|
i0.ɵɵadvance(4);
|
|
212
224
|
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(5, 1, ctx_r1.EmbeddingModel.Dimensions));
|
|
213
225
|
} }
|
|
214
|
-
function
|
|
215
|
-
i0.ɵɵelement(0, "i",
|
|
226
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
227
|
+
i0.ɵɵelement(0, "i", 61);
|
|
216
228
|
i0.ɵɵtext(1, " Regenerating... ");
|
|
217
229
|
} }
|
|
218
|
-
function
|
|
230
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
219
231
|
i0.ɵɵelement(0, "i", 19);
|
|
220
232
|
i0.ɵɵtext(1, " Regenerate with AI ");
|
|
221
233
|
} }
|
|
222
|
-
function
|
|
223
|
-
i0.ɵɵelementStart(0, "span",
|
|
234
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_29_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
235
|
+
i0.ɵɵelementStart(0, "span", 89);
|
|
224
236
|
i0.ɵɵtext(1);
|
|
225
237
|
i0.ɵɵelementEnd();
|
|
226
238
|
} if (rf & 2) {
|
|
@@ -228,20 +240,20 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
228
240
|
i0.ɵɵadvance();
|
|
229
241
|
i0.ɵɵtextInterpolate(field_r9);
|
|
230
242
|
} }
|
|
231
|
-
function
|
|
232
|
-
i0.ɵɵelementStart(0, "div",
|
|
243
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
244
|
+
i0.ɵɵelementStart(0, "div", 72)(1, "label", 73);
|
|
233
245
|
i0.ɵɵtext(2, "Selected Fields");
|
|
234
246
|
i0.ɵɵelementEnd();
|
|
235
|
-
i0.ɵɵelementStart(3, "div",
|
|
236
|
-
i0.ɵɵrepeaterCreate(4,
|
|
247
|
+
i0.ɵɵelementStart(3, "div", 88);
|
|
248
|
+
i0.ɵɵrepeaterCreate(4, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_29_For_5_Template, 2, 1, "span", 89, i0.ɵɵrepeaterTrackByIdentity);
|
|
237
249
|
i0.ɵɵelementEnd()();
|
|
238
250
|
} if (rf & 2) {
|
|
239
251
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
240
252
|
i0.ɵɵadvance(4);
|
|
241
253
|
i0.ɵɵrepeater(ctx_r1.EditDocSelectedFields);
|
|
242
254
|
} }
|
|
243
|
-
function
|
|
244
|
-
i0.ɵɵelementStart(0, "option",
|
|
255
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_For_39_Template(rf, ctx) { if (rf & 1) {
|
|
256
|
+
i0.ɵɵelementStart(0, "option", 81);
|
|
245
257
|
i0.ɵɵtext(1);
|
|
246
258
|
i0.ɵɵelementEnd();
|
|
247
259
|
} if (rf & 2) {
|
|
@@ -250,8 +262,8 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
250
262
|
i0.ɵɵadvance();
|
|
251
263
|
i0.ɵɵtextInterpolate(model_r10.Name);
|
|
252
264
|
} }
|
|
253
|
-
function
|
|
254
|
-
i0.ɵɵelementStart(0, "option",
|
|
265
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_For_45_Template(rf, ctx) { if (rf & 1) {
|
|
266
|
+
i0.ɵɵelementStart(0, "option", 81);
|
|
255
267
|
i0.ɵɵtext(1);
|
|
256
268
|
i0.ɵɵelementEnd();
|
|
257
269
|
} if (rf & 2) {
|
|
@@ -260,8 +272,8 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
260
272
|
i0.ɵɵadvance();
|
|
261
273
|
i0.ɵɵtextInterpolate(db_r11.Name);
|
|
262
274
|
} }
|
|
263
|
-
function
|
|
264
|
-
i0.ɵɵelementStart(0, "option",
|
|
275
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_49_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
276
|
+
i0.ɵɵelementStart(0, "option", 81);
|
|
265
277
|
i0.ɵɵtext(1);
|
|
266
278
|
i0.ɵɵelementEnd();
|
|
267
279
|
} if (rf & 2) {
|
|
@@ -270,204 +282,212 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
270
282
|
i0.ɵɵadvance();
|
|
271
283
|
i0.ɵɵtextInterpolate(idx_r13.Name);
|
|
272
284
|
} }
|
|
273
|
-
function
|
|
285
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_49_Template(rf, ctx) { if (rf & 1) {
|
|
274
286
|
const _r12 = i0.ɵɵgetCurrentView();
|
|
275
|
-
i0.ɵɵelementStart(0, "select",
|
|
276
|
-
i0.ɵɵ
|
|
277
|
-
i0.ɵɵelementStart(1, "option",
|
|
287
|
+
i0.ɵɵelementStart(0, "select", 80);
|
|
288
|
+
i0.ɵɵlistener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_49_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnEditVectorIndexChange($event)); });
|
|
289
|
+
i0.ɵɵelementStart(1, "option", 90);
|
|
278
290
|
i0.ɵɵtext(2, "Auto (create/find matching index)");
|
|
279
291
|
i0.ɵɵelementEnd();
|
|
280
|
-
i0.ɵɵrepeaterCreate(3,
|
|
292
|
+
i0.ɵɵrepeaterCreate(3, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_49_For_4_Template, 2, 2, "option", 81, _forTrack2);
|
|
281
293
|
i0.ɵɵelementEnd();
|
|
282
294
|
} if (rf & 2) {
|
|
283
295
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
284
|
-
i0.ɵɵ
|
|
296
|
+
i0.ɵɵproperty("ngModel", ctx_r1.EditDocVectorIndexID);
|
|
285
297
|
i0.ɵɵadvance(3);
|
|
286
298
|
i0.ɵɵrepeater(ctx_r1.EditFilteredIndexes);
|
|
287
299
|
} }
|
|
288
|
-
function
|
|
289
|
-
i0.ɵɵelementStart(0, "span",
|
|
300
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_50_Template(rf, ctx) { if (rf & 1) {
|
|
301
|
+
i0.ɵɵelementStart(0, "span", 83);
|
|
290
302
|
i0.ɵɵtext(1, " No indexes for this database \u2014 one will be created automatically on sync ");
|
|
291
303
|
i0.ɵɵelementEnd();
|
|
292
304
|
} }
|
|
293
|
-
function
|
|
294
|
-
i0.ɵɵelement(0, "mj-loading",
|
|
305
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_60_Template(rf, ctx) { if (rf & 1) {
|
|
306
|
+
i0.ɵɵelement(0, "mj-loading", 87);
|
|
295
307
|
} }
|
|
296
|
-
function
|
|
308
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_61_Template(rf, ctx) { if (rf & 1) {
|
|
297
309
|
const _r14 = i0.ɵɵgetCurrentView();
|
|
298
|
-
i0.ɵɵelementStart(0, "button",
|
|
299
|
-
i0.ɵɵlistener("click", function
|
|
300
|
-
i0.ɵɵelement(1, "i",
|
|
310
|
+
i0.ɵɵelementStart(0, "button", 91);
|
|
311
|
+
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_61_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SaveEditedDocument()); });
|
|
312
|
+
i0.ɵɵelement(1, "i", 92);
|
|
301
313
|
i0.ɵɵtext(2, " Save Changes ");
|
|
302
314
|
i0.ɵɵelementEnd();
|
|
303
|
-
i0.ɵɵelementStart(3, "button",
|
|
304
|
-
i0.ɵɵlistener("click", function
|
|
305
|
-
i0.ɵɵelement(4, "i",
|
|
315
|
+
i0.ɵɵelementStart(3, "button", 93);
|
|
316
|
+
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_61_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.DeleteEntityDocument()); });
|
|
317
|
+
i0.ɵɵelement(4, "i", 94);
|
|
306
318
|
i0.ɵɵtext(5, " Delete ");
|
|
307
319
|
i0.ɵɵelementEnd();
|
|
308
|
-
i0.ɵɵelementStart(6, "button",
|
|
309
|
-
i0.ɵɵlistener("click", function
|
|
320
|
+
i0.ɵɵelementStart(6, "button", 95);
|
|
321
|
+
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_61_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.CloseEditPanel()); });
|
|
310
322
|
i0.ɵɵtext(7, " Cancel ");
|
|
311
323
|
i0.ɵɵelementEnd();
|
|
312
324
|
} }
|
|
313
325
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template(rf, ctx) { if (rf & 1) {
|
|
314
326
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
315
|
-
i0.ɵɵelementStart(0, "div",
|
|
327
|
+
i0.ɵɵelementStart(0, "div", 64);
|
|
316
328
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CloseEditPanel()); });
|
|
317
|
-
i0.ɵɵelementStart(1, "div",
|
|
329
|
+
i0.ɵɵelementStart(1, "div", 65);
|
|
318
330
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
|
|
319
|
-
i0.ɵɵelementStart(2, "div",
|
|
320
|
-
i0.ɵɵelement(4, "i",
|
|
331
|
+
i0.ɵɵelementStart(2, "div", 66)(3, "h3", 67);
|
|
332
|
+
i0.ɵɵelement(4, "i", 60);
|
|
321
333
|
i0.ɵɵtext(5, " Edit Entity Document ");
|
|
322
334
|
i0.ɵɵelementEnd();
|
|
323
|
-
i0.ɵɵelementStart(6, "button",
|
|
335
|
+
i0.ɵɵelementStart(6, "button", 68);
|
|
324
336
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CloseEditPanel()); });
|
|
325
|
-
i0.ɵɵelement(7, "i",
|
|
337
|
+
i0.ɵɵelement(7, "i", 69);
|
|
326
338
|
i0.ɵɵelementEnd()();
|
|
327
|
-
i0.ɵɵelementStart(8, "div",
|
|
339
|
+
i0.ɵɵelementStart(8, "div", 70)(9, "div", 71)(10, "div", 72)(11, "label", 73);
|
|
328
340
|
i0.ɵɵtext(12, "Entity");
|
|
329
341
|
i0.ɵɵelementEnd();
|
|
330
|
-
i0.ɵɵelementStart(13, "span",
|
|
342
|
+
i0.ɵɵelementStart(13, "span", 74);
|
|
331
343
|
i0.ɵɵtext(14);
|
|
332
344
|
i0.ɵɵelementEnd()();
|
|
333
|
-
i0.ɵɵelementStart(15, "div",
|
|
334
|
-
i0.ɵɵtext(
|
|
345
|
+
i0.ɵɵelementStart(15, "div", 72)(16, "label", 73);
|
|
346
|
+
i0.ɵɵtext(17, "Type");
|
|
335
347
|
i0.ɵɵelementEnd();
|
|
336
|
-
i0.ɵɵelementStart(
|
|
337
|
-
i0.ɵɵ
|
|
338
|
-
i0.ɵɵconditionalCreate(20, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_20_Template, 2, 0)(21, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_21_Template, 2, 0);
|
|
348
|
+
i0.ɵɵelementStart(18, "span", 74);
|
|
349
|
+
i0.ɵɵtext(19);
|
|
339
350
|
i0.ɵɵelementEnd()();
|
|
340
|
-
i0.ɵɵelementStart(
|
|
341
|
-
i0.ɵɵ
|
|
351
|
+
i0.ɵɵelementStart(20, "div", 72)(21, "div", 75)(22, "label", 73);
|
|
352
|
+
i0.ɵɵtext(23, "Template");
|
|
353
|
+
i0.ɵɵelementEnd();
|
|
354
|
+
i0.ɵɵelementStart(24, "button", 76);
|
|
355
|
+
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_button_click_24_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.RegenerateTemplate()); });
|
|
356
|
+
i0.ɵɵconditionalCreate(25, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_25_Template, 2, 0)(26, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_26_Template, 2, 0);
|
|
357
|
+
i0.ɵɵelementEnd()();
|
|
358
|
+
i0.ɵɵelementStart(27, "div", 77)(28, "mj-code-editor", 78);
|
|
359
|
+
i0.ɵɵlistener("change", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_mj_code_editor_change_28_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnEditTemplateChange($event)); });
|
|
342
360
|
i0.ɵɵelementEnd()()();
|
|
343
|
-
i0.ɵɵconditionalCreate(
|
|
344
|
-
i0.ɵɵelementStart(
|
|
345
|
-
i0.ɵɵtext(
|
|
361
|
+
i0.ɵɵconditionalCreate(29, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_29_Template, 6, 0, "div", 72);
|
|
362
|
+
i0.ɵɵelementStart(30, "div", 72)(31, "label", 73);
|
|
363
|
+
i0.ɵɵtext(32, "Document Name");
|
|
346
364
|
i0.ɵɵelementEnd();
|
|
347
|
-
i0.ɵɵelementStart(
|
|
348
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
365
|
+
i0.ɵɵelementStart(33, "input", 79);
|
|
366
|
+
i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_input_ngModelChange_33_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.EditDocName, $event) || (ctx_r1.EditDocName = $event); return i0.ɵɵresetView($event); });
|
|
349
367
|
i0.ɵɵelementEnd()();
|
|
350
|
-
i0.ɵɵelementStart(
|
|
351
|
-
i0.ɵɵtext(
|
|
368
|
+
i0.ɵɵelementStart(34, "div", 72)(35, "label", 73);
|
|
369
|
+
i0.ɵɵtext(36, "Embedding Model");
|
|
352
370
|
i0.ɵɵelementEnd();
|
|
353
|
-
i0.ɵɵelementStart(
|
|
354
|
-
i0.ɵɵ
|
|
355
|
-
i0.ɵɵrepeaterCreate(
|
|
371
|
+
i0.ɵɵelementStart(37, "select", 80);
|
|
372
|
+
i0.ɵɵlistener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_select_ngModelChange_37_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnEditEmbeddingModelChange($event)); });
|
|
373
|
+
i0.ɵɵrepeaterCreate(38, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_For_39_Template, 2, 2, "option", 81, _forTrack2);
|
|
356
374
|
i0.ɵɵelementEnd()();
|
|
357
|
-
i0.ɵɵelementStart(
|
|
358
|
-
i0.ɵɵtext(
|
|
375
|
+
i0.ɵɵelementStart(40, "div", 72)(41, "label", 73);
|
|
376
|
+
i0.ɵɵtext(42, "Vector Database");
|
|
359
377
|
i0.ɵɵelementEnd();
|
|
360
|
-
i0.ɵɵelementStart(
|
|
361
|
-
i0.ɵɵ
|
|
362
|
-
i0.ɵɵrepeaterCreate(
|
|
378
|
+
i0.ɵɵelementStart(43, "select", 80);
|
|
379
|
+
i0.ɵɵlistener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_select_ngModelChange_43_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnEditVectorDBChange($event)); });
|
|
380
|
+
i0.ɵɵrepeaterCreate(44, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_For_45_Template, 2, 2, "option", 81, _forTrack2);
|
|
363
381
|
i0.ɵɵelementEnd()();
|
|
364
|
-
i0.ɵɵelementStart(
|
|
365
|
-
i0.ɵɵtext(
|
|
382
|
+
i0.ɵɵelementStart(46, "div", 72)(47, "label", 73);
|
|
383
|
+
i0.ɵɵtext(48, "Vector Index");
|
|
366
384
|
i0.ɵɵelementEnd();
|
|
367
|
-
i0.ɵɵconditionalCreate(
|
|
385
|
+
i0.ɵɵconditionalCreate(49, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_49_Template, 5, 1, "select", 82)(50, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_50_Template, 2, 0, "span", 83);
|
|
368
386
|
i0.ɵɵelementEnd();
|
|
369
|
-
i0.ɵɵelementStart(
|
|
370
|
-
i0.ɵɵtext(
|
|
387
|
+
i0.ɵɵelementStart(51, "div", 72)(52, "label", 73);
|
|
388
|
+
i0.ɵɵtext(53, "Status");
|
|
371
389
|
i0.ɵɵelementEnd();
|
|
372
|
-
i0.ɵɵelementStart(
|
|
373
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
374
|
-
i0.ɵɵelementStart(
|
|
375
|
-
i0.ɵɵtext(
|
|
390
|
+
i0.ɵɵelementStart(54, "select", 80);
|
|
391
|
+
i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template_select_ngModelChange_54_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.EditDocStatus, $event) || (ctx_r1.EditDocStatus = $event); return i0.ɵɵresetView($event); });
|
|
392
|
+
i0.ɵɵelementStart(55, "option", 84);
|
|
393
|
+
i0.ɵɵtext(56, "Active");
|
|
376
394
|
i0.ɵɵelementEnd();
|
|
377
|
-
i0.ɵɵelementStart(
|
|
378
|
-
i0.ɵɵtext(
|
|
395
|
+
i0.ɵɵelementStart(57, "option", 85);
|
|
396
|
+
i0.ɵɵtext(58, "Inactive");
|
|
379
397
|
i0.ɵɵelementEnd()()();
|
|
380
|
-
i0.ɵɵelementStart(
|
|
381
|
-
i0.ɵɵconditionalCreate(
|
|
398
|
+
i0.ɵɵelementStart(59, "div", 86);
|
|
399
|
+
i0.ɵɵconditionalCreate(60, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_60_Template, 1, 0, "mj-loading", 87)(61, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Conditional_61_Template, 8, 0);
|
|
382
400
|
i0.ɵɵelementEnd()()()()();
|
|
383
401
|
} if (rf & 2) {
|
|
384
402
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
385
403
|
i0.ɵɵadvance(14);
|
|
386
404
|
i0.ɵɵtextInterpolate(ctx_r1.EditDocEntityName);
|
|
387
405
|
i0.ɵɵadvance(5);
|
|
406
|
+
i0.ɵɵtextInterpolate(ctx_r1.EditDocType);
|
|
407
|
+
i0.ɵɵadvance(5);
|
|
388
408
|
i0.ɵɵproperty("disabled", ctx_r1.IsEditRegenerating);
|
|
389
409
|
i0.ɵɵadvance();
|
|
390
|
-
i0.ɵɵconditional(ctx_r1.IsEditRegenerating ?
|
|
410
|
+
i0.ɵɵconditional(ctx_r1.IsEditRegenerating ? 25 : 26);
|
|
391
411
|
i0.ɵɵadvance(3);
|
|
392
412
|
i0.ɵɵproperty("value", ctx_r1.EditDocTemplate)("readonly", false)("lineWrapping", true);
|
|
393
413
|
i0.ɵɵadvance();
|
|
394
|
-
i0.ɵɵconditional(ctx_r1.EditDocSelectedFields.length > 0 ?
|
|
414
|
+
i0.ɵɵconditional(ctx_r1.EditDocSelectedFields.length > 0 ? 29 : -1);
|
|
395
415
|
i0.ɵɵadvance(4);
|
|
396
416
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditDocName);
|
|
397
417
|
i0.ɵɵadvance(4);
|
|
398
|
-
i0.ɵɵ
|
|
418
|
+
i0.ɵɵproperty("ngModel", ctx_r1.EditDocAIModelID);
|
|
399
419
|
i0.ɵɵadvance();
|
|
400
420
|
i0.ɵɵrepeater(ctx_r1.AvailableEmbeddingModels);
|
|
401
421
|
i0.ɵɵadvance(5);
|
|
402
|
-
i0.ɵɵ
|
|
422
|
+
i0.ɵɵproperty("ngModel", ctx_r1.EditDocVectorDBID);
|
|
403
423
|
i0.ɵɵadvance();
|
|
404
424
|
i0.ɵɵrepeater(ctx_r1.vectorDatabases);
|
|
405
425
|
i0.ɵɵadvance(5);
|
|
406
|
-
i0.ɵɵconditional(ctx_r1.EditFilteredIndexes.length > 0 ?
|
|
426
|
+
i0.ɵɵconditional(ctx_r1.EditFilteredIndexes.length > 0 ? 49 : 50);
|
|
407
427
|
i0.ɵɵadvance(5);
|
|
408
428
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EditDocStatus);
|
|
409
429
|
i0.ɵɵadvance(6);
|
|
410
|
-
i0.ɵɵconditional(ctx_r1.IsEditSaving || ctx_r1.IsEditDeleting ?
|
|
430
|
+
i0.ɵɵconditional(ctx_r1.IsEditSaving || ctx_r1.IsEditDeleting ? 60 : 61);
|
|
411
431
|
} }
|
|
412
432
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Conditional_32_Template(rf, ctx) { if (rf & 1) {
|
|
413
|
-
i0.ɵɵelement(0, "mj-loading",
|
|
433
|
+
i0.ɵɵelement(0, "mj-loading", 87);
|
|
414
434
|
} }
|
|
415
435
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Conditional_33_Template(rf, ctx) { if (rf & 1) {
|
|
416
436
|
const _r16 = i0.ɵɵgetCurrentView();
|
|
417
|
-
i0.ɵɵelementStart(0, "button",
|
|
437
|
+
i0.ɵɵelementStart(0, "button", 91);
|
|
418
438
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Conditional_33_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SaveScheduleSync()); });
|
|
419
|
-
i0.ɵɵelement(1, "i",
|
|
439
|
+
i0.ɵɵelement(1, "i", 102);
|
|
420
440
|
i0.ɵɵtext(2, " Create Schedule ");
|
|
421
441
|
i0.ɵɵelementEnd();
|
|
422
|
-
i0.ɵɵelementStart(3, "button",
|
|
442
|
+
i0.ɵɵelementStart(3, "button", 95);
|
|
423
443
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Conditional_33_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.CloseScheduleSyncDialog()); });
|
|
424
444
|
i0.ɵɵtext(4, " Cancel ");
|
|
425
445
|
i0.ɵɵelementEnd();
|
|
426
446
|
} }
|
|
427
447
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Template(rf, ctx) { if (rf & 1) {
|
|
428
448
|
const _r15 = i0.ɵɵgetCurrentView();
|
|
429
|
-
i0.ɵɵelementStart(0, "div",
|
|
449
|
+
i0.ɵɵelementStart(0, "div", 64);
|
|
430
450
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CloseScheduleSyncDialog()); });
|
|
431
|
-
i0.ɵɵelementStart(1, "div",
|
|
451
|
+
i0.ɵɵelementStart(1, "div", 96);
|
|
432
452
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
|
|
433
|
-
i0.ɵɵelementStart(2, "div",
|
|
434
|
-
i0.ɵɵelement(4, "i",
|
|
453
|
+
i0.ɵɵelementStart(2, "div", 66)(3, "h3", 67);
|
|
454
|
+
i0.ɵɵelement(4, "i", 58);
|
|
435
455
|
i0.ɵɵtext(5, " Schedule Vector Sync ");
|
|
436
456
|
i0.ɵɵelementEnd();
|
|
437
|
-
i0.ɵɵelementStart(6, "button",
|
|
457
|
+
i0.ɵɵelementStart(6, "button", 68);
|
|
438
458
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CloseScheduleSyncDialog()); });
|
|
439
|
-
i0.ɵɵelement(7, "i",
|
|
459
|
+
i0.ɵɵelement(7, "i", 69);
|
|
440
460
|
i0.ɵɵelementEnd()();
|
|
441
|
-
i0.ɵɵelementStart(8, "div",
|
|
461
|
+
i0.ɵɵelementStart(8, "div", 70)(9, "div", 71)(10, "div", 72)(11, "label", 73);
|
|
442
462
|
i0.ɵɵtext(12, "Entity Document");
|
|
443
463
|
i0.ɵɵelementEnd();
|
|
444
|
-
i0.ɵɵelementStart(13, "span",
|
|
464
|
+
i0.ɵɵelementStart(13, "span", 74);
|
|
445
465
|
i0.ɵɵtext(14);
|
|
446
466
|
i0.ɵɵelementEnd()();
|
|
447
|
-
i0.ɵɵelementStart(15, "div",
|
|
467
|
+
i0.ɵɵelementStart(15, "div", 72)(16, "label", 73);
|
|
448
468
|
i0.ɵɵtext(17, "Action");
|
|
449
469
|
i0.ɵɵelementEnd();
|
|
450
|
-
i0.ɵɵelementStart(18, "span",
|
|
470
|
+
i0.ɵɵelementStart(18, "span", 74);
|
|
451
471
|
i0.ɵɵtext(19, "__VectorizeEntity");
|
|
452
472
|
i0.ɵɵelementEnd()();
|
|
453
|
-
i0.ɵɵelementStart(20, "div",
|
|
473
|
+
i0.ɵɵelementStart(20, "div", 72)(21, "label", 73);
|
|
454
474
|
i0.ɵɵtext(22, "Cron Expression");
|
|
455
475
|
i0.ɵɵelementEnd();
|
|
456
|
-
i0.ɵɵelementStart(23, "input",
|
|
476
|
+
i0.ɵɵelementStart(23, "input", 97);
|
|
457
477
|
i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Template_input_ngModelChange_23_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.ScheduleSyncCron, $event) || (ctx_r1.ScheduleSyncCron = $event); return i0.ɵɵresetView($event); });
|
|
458
478
|
i0.ɵɵelementEnd();
|
|
459
|
-
i0.ɵɵelementStart(24, "div",
|
|
460
|
-
i0.ɵɵelement(25, "i",
|
|
479
|
+
i0.ɵɵelementStart(24, "div", 98);
|
|
480
|
+
i0.ɵɵelement(25, "i", 99);
|
|
461
481
|
i0.ɵɵtext(26);
|
|
462
482
|
i0.ɵɵelementEnd()();
|
|
463
|
-
i0.ɵɵelementStart(27, "div",
|
|
483
|
+
i0.ɵɵelementStart(27, "div", 100)(28, "label", 73);
|
|
464
484
|
i0.ɵɵtext(29, "Enabled");
|
|
465
485
|
i0.ɵɵelementEnd();
|
|
466
|
-
i0.ɵɵelementStart(30, "input",
|
|
486
|
+
i0.ɵɵelementStart(30, "input", 101);
|
|
467
487
|
i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Template_input_ngModelChange_30_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.ScheduleSyncEnabled, $event) || (ctx_r1.ScheduleSyncEnabled = $event); return i0.ɵɵresetView($event); });
|
|
468
488
|
i0.ɵɵelementEnd()();
|
|
469
|
-
i0.ɵɵelementStart(31, "div",
|
|
470
|
-
i0.ɵɵconditionalCreate(32, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Conditional_32_Template, 1, 0, "mj-loading",
|
|
489
|
+
i0.ɵɵelementStart(31, "div", 86);
|
|
490
|
+
i0.ɵɵconditionalCreate(32, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Conditional_32_Template, 1, 0, "mj-loading", 87)(33, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Conditional_33_Template, 5, 0);
|
|
471
491
|
i0.ɵɵelementEnd()()()()();
|
|
472
492
|
} if (rf & 2) {
|
|
473
493
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
@@ -484,25 +504,25 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
484
504
|
} }
|
|
485
505
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_57_Template(rf, ctx) { if (rf & 1) {
|
|
486
506
|
const _r17 = i0.ɵɵgetCurrentView();
|
|
487
|
-
i0.ɵɵelementStart(0, "div",
|
|
507
|
+
i0.ɵɵelementStart(0, "div", 64);
|
|
488
508
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_57_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CloseNoIndexWarning()); });
|
|
489
|
-
i0.ɵɵelementStart(1, "div",
|
|
509
|
+
i0.ɵɵelementStart(1, "div", 103);
|
|
490
510
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_57_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
|
|
491
|
-
i0.ɵɵelementStart(2, "div",
|
|
492
|
-
i0.ɵɵelement(3, "i",
|
|
511
|
+
i0.ɵɵelementStart(2, "div", 104);
|
|
512
|
+
i0.ɵɵelement(3, "i", 105);
|
|
493
513
|
i0.ɵɵelementEnd();
|
|
494
|
-
i0.ɵɵelementStart(4, "h3",
|
|
514
|
+
i0.ɵɵelementStart(4, "h3", 106);
|
|
495
515
|
i0.ɵɵtext(5, "Vector Index Required");
|
|
496
516
|
i0.ɵɵelementEnd();
|
|
497
|
-
i0.ɵɵelementStart(6, "p",
|
|
517
|
+
i0.ɵɵelementStart(6, "p", 107);
|
|
498
518
|
i0.ɵɵtext(7, " You need to create at least one vector database and index before creating entity documents. Go to the Configuration section to set up a vector database and create an index. ");
|
|
499
519
|
i0.ɵɵelementEnd();
|
|
500
|
-
i0.ɵɵelementStart(8, "div",
|
|
520
|
+
i0.ɵɵelementStart(8, "div", 108)(9, "button", 91);
|
|
501
521
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_57_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.GoToConfiguration()); });
|
|
502
|
-
i0.ɵɵelement(10, "i",
|
|
522
|
+
i0.ɵɵelement(10, "i", 109);
|
|
503
523
|
i0.ɵɵtext(11, " Go to Configuration ");
|
|
504
524
|
i0.ɵɵelementEnd();
|
|
505
|
-
i0.ɵɵelementStart(12, "button",
|
|
525
|
+
i0.ɵɵelementStart(12, "button", 95);
|
|
506
526
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_57_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CloseNoIndexWarning()); });
|
|
507
527
|
i0.ɵɵtext(13, " Close ");
|
|
508
528
|
i0.ɵɵelementEnd()()()();
|
|
@@ -583,15 +603,15 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
583
603
|
i0.ɵɵadvance(2);
|
|
584
604
|
i0.ɵɵconditional(ctx_r1.FilteredEntityGroups.length === 0 ? 8 : -1);
|
|
585
605
|
} }
|
|
586
|
-
function
|
|
587
|
-
i0.ɵɵelement(0, "i",
|
|
606
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
607
|
+
i0.ɵɵelement(0, "i", 61);
|
|
588
608
|
i0.ɵɵtext(1, " Generating with AI... ");
|
|
589
609
|
} }
|
|
590
|
-
function
|
|
610
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
591
611
|
i0.ɵɵelement(0, "i", 19);
|
|
592
612
|
i0.ɵɵtext(1, " Generate Template ");
|
|
593
613
|
} }
|
|
594
|
-
function
|
|
614
|
+
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
595
615
|
i0.ɵɵelementStart(0, "mj-alert", 121);
|
|
596
616
|
i0.ɵɵtext(1);
|
|
597
617
|
i0.ɵɵelementEnd();
|
|
@@ -602,39 +622,34 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
602
622
|
} }
|
|
603
623
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
604
624
|
const _r19 = i0.ɵɵgetCurrentView();
|
|
605
|
-
i0.ɵɵelementStart(0, "div",
|
|
625
|
+
i0.ɵɵelementStart(0, "div", 71)(1, "div", 72)(2, "label", 73);
|
|
606
626
|
i0.ɵɵtext(3, "Entity");
|
|
607
627
|
i0.ɵɵelementEnd();
|
|
608
|
-
i0.ɵɵelementStart(4, "div",
|
|
628
|
+
i0.ɵɵelementStart(4, "div", 112)(5, "button", 113);
|
|
609
629
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.ToggleEntityPicker()); });
|
|
610
630
|
i0.ɵɵconditionalCreate(6, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_6_Template, 3, 1)(7, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_7_Template, 3, 0);
|
|
611
|
-
i0.ɵɵelement(8, "i",
|
|
631
|
+
i0.ɵɵelement(8, "i", 114);
|
|
612
632
|
i0.ɵɵelementEnd();
|
|
613
|
-
i0.ɵɵconditionalCreate(9, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_9_Template, 9, 2, "div",
|
|
633
|
+
i0.ɵɵconditionalCreate(9, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_9_Template, 9, 2, "div", 115);
|
|
614
634
|
i0.ɵɵelementEnd()();
|
|
615
|
-
i0.ɵɵelementStart(10, "div",
|
|
635
|
+
i0.ɵɵelementStart(10, "div", 72)(11, "label", 73);
|
|
616
636
|
i0.ɵɵtext(12, "Use Case");
|
|
617
637
|
i0.ɵɵelementEnd();
|
|
618
|
-
i0.ɵɵelementStart(13, "div",
|
|
638
|
+
i0.ɵɵelementStart(13, "div", 116)(14, "button", 117);
|
|
619
639
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SuggestUseCase = "duplicate detection"); });
|
|
620
|
-
i0.ɵɵelement(15, "i",
|
|
640
|
+
i0.ɵɵelement(15, "i", 118);
|
|
621
641
|
i0.ɵɵtext(16, " Duplicate Detection ");
|
|
622
642
|
i0.ɵɵelementEnd();
|
|
623
|
-
i0.ɵɵelementStart(17, "button",
|
|
643
|
+
i0.ɵɵelementStart(17, "button", 117);
|
|
624
644
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SuggestUseCase = "search"); });
|
|
625
|
-
i0.ɵɵelement(18, "i",
|
|
645
|
+
i0.ɵɵelement(18, "i", 119);
|
|
626
646
|
i0.ɵɵtext(19, " Search ");
|
|
627
|
-
i0.ɵɵelementEnd();
|
|
628
|
-
i0.ɵɵelementStart(20, "button", 116);
|
|
629
|
-
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SuggestUseCase = "classification"); });
|
|
630
|
-
i0.ɵɵelement(21, "i", 119);
|
|
631
|
-
i0.ɵɵtext(22, " Classification ");
|
|
632
647
|
i0.ɵɵelementEnd()()();
|
|
633
|
-
i0.ɵɵelementStart(
|
|
634
|
-
i0.ɵɵlistener("click", function
|
|
635
|
-
i0.ɵɵconditionalCreate(
|
|
648
|
+
i0.ɵɵelementStart(20, "button", 120);
|
|
649
|
+
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.RunSuggestion()); });
|
|
650
|
+
i0.ɵɵconditionalCreate(21, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_21_Template, 2, 0)(22, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_22_Template, 2, 0);
|
|
636
651
|
i0.ɵɵelementEnd();
|
|
637
|
-
i0.ɵɵconditionalCreate(
|
|
652
|
+
i0.ɵɵconditionalCreate(23, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Conditional_23_Template, 2, 1, "mj-alert", 121);
|
|
638
653
|
i0.ɵɵelementEnd();
|
|
639
654
|
} if (rf & 2) {
|
|
640
655
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
@@ -647,16 +662,14 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
647
662
|
i0.ɵɵadvance(3);
|
|
648
663
|
i0.ɵɵclassProp("use-case-btn-active", ctx_r1.SuggestUseCase === "search");
|
|
649
664
|
i0.ɵɵadvance(3);
|
|
650
|
-
i0.ɵɵclassProp("use-case-btn-active", ctx_r1.SuggestUseCase === "classification");
|
|
651
|
-
i0.ɵɵadvance(3);
|
|
652
665
|
i0.ɵɵproperty("disabled", ctx_r1.IsSuggesting || !ctx_r1.SuggestEntityName);
|
|
653
666
|
i0.ɵɵadvance();
|
|
654
|
-
i0.ɵɵconditional(ctx_r1.IsSuggesting ?
|
|
667
|
+
i0.ɵɵconditional(ctx_r1.IsSuggesting ? 21 : 22);
|
|
655
668
|
i0.ɵɵadvance(2);
|
|
656
|
-
i0.ɵɵconditional(ctx_r1.SuggestionError ?
|
|
669
|
+
i0.ɵɵconditional(ctx_r1.SuggestionError ? 23 : -1);
|
|
657
670
|
} }
|
|
658
671
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_11_Template(rf, ctx) { if (rf & 1) {
|
|
659
|
-
i0.ɵɵelementStart(0, "span",
|
|
672
|
+
i0.ɵɵelementStart(0, "span", 89);
|
|
660
673
|
i0.ɵɵtext(1);
|
|
661
674
|
i0.ɵɵelementEnd();
|
|
662
675
|
} if (rf & 2) {
|
|
@@ -690,7 +703,7 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
690
703
|
i0.ɵɵrepeater(ctx_r1.SuggestionResult.selectedRelationships);
|
|
691
704
|
} }
|
|
692
705
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_39_Template(rf, ctx) { if (rf & 1) {
|
|
693
|
-
i0.ɵɵelementStart(0, "option",
|
|
706
|
+
i0.ɵɵelementStart(0, "option", 81);
|
|
694
707
|
i0.ɵɵtext(1);
|
|
695
708
|
i0.ɵɵelementEnd();
|
|
696
709
|
} if (rf & 2) {
|
|
@@ -700,7 +713,7 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
700
713
|
i0.ɵɵtextInterpolate(model_r27.Name);
|
|
701
714
|
} }
|
|
702
715
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_45_Template(rf, ctx) { if (rf & 1) {
|
|
703
|
-
i0.ɵɵelementStart(0, "option",
|
|
716
|
+
i0.ɵɵelementStart(0, "option", 81);
|
|
704
717
|
i0.ɵɵtext(1);
|
|
705
718
|
i0.ɵɵelementEnd();
|
|
706
719
|
} if (rf & 2) {
|
|
@@ -710,7 +723,7 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
710
723
|
i0.ɵɵtextInterpolate(db_r28.Name);
|
|
711
724
|
} }
|
|
712
725
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_49_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
713
|
-
i0.ɵɵelementStart(0, "option",
|
|
726
|
+
i0.ɵɵelementStart(0, "option", 81);
|
|
714
727
|
i0.ɵɵtext(1);
|
|
715
728
|
i0.ɵɵelementEnd();
|
|
716
729
|
} if (rf & 2) {
|
|
@@ -721,32 +734,32 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
721
734
|
} }
|
|
722
735
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_49_Template(rf, ctx) { if (rf & 1) {
|
|
723
736
|
const _r29 = i0.ɵɵgetCurrentView();
|
|
724
|
-
i0.ɵɵelementStart(0, "select",
|
|
725
|
-
i0.ɵɵ
|
|
726
|
-
i0.ɵɵelementStart(1, "option",
|
|
737
|
+
i0.ɵɵelementStart(0, "select", 80);
|
|
738
|
+
i0.ɵɵlistener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_49_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r29); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.OnSuggestVectorIndexChange($event)); });
|
|
739
|
+
i0.ɵɵelementStart(1, "option", 90);
|
|
727
740
|
i0.ɵɵtext(2, "Auto (create/find matching index)");
|
|
728
741
|
i0.ɵɵelementEnd();
|
|
729
|
-
i0.ɵɵrepeaterCreate(3, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_49_For_4_Template, 2, 2, "option",
|
|
742
|
+
i0.ɵɵrepeaterCreate(3, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_49_For_4_Template, 2, 2, "option", 81, _forTrack2);
|
|
730
743
|
i0.ɵɵelementEnd();
|
|
731
744
|
} if (rf & 2) {
|
|
732
745
|
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
733
|
-
i0.ɵɵ
|
|
746
|
+
i0.ɵɵproperty("ngModel", ctx_r1.SelectedVectorIndexID);
|
|
734
747
|
i0.ɵɵadvance(3);
|
|
735
748
|
i0.ɵɵrepeater(ctx_r1.FilteredIndexesForSelectedDB);
|
|
736
749
|
} }
|
|
737
750
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_50_Template(rf, ctx) { if (rf & 1) {
|
|
738
|
-
i0.ɵɵelementStart(0, "span",
|
|
751
|
+
i0.ɵɵelementStart(0, "span", 83);
|
|
739
752
|
i0.ɵɵtext(1, " No indexes yet \u2014 create one in Configuration > Vector Database, or one will be created on sync ");
|
|
740
753
|
i0.ɵɵelementEnd();
|
|
741
754
|
} }
|
|
742
755
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_52_Template(rf, ctx) { if (rf & 1) {
|
|
743
756
|
i0.ɵɵelementStart(0, "div", 145);
|
|
744
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
757
|
+
i0.ɵɵelement(1, "mj-loading", 87);
|
|
745
758
|
i0.ɵɵelementEnd();
|
|
746
759
|
} }
|
|
747
760
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_53_Template(rf, ctx) { if (rf & 1) {
|
|
748
761
|
const _r31 = i0.ɵɵgetCurrentView();
|
|
749
|
-
i0.ɵɵelementStart(0, "button",
|
|
762
|
+
i0.ɵɵelementStart(0, "button", 91);
|
|
750
763
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_53_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.SaveAsEntityDocument()); });
|
|
751
764
|
i0.ɵɵelement(1, "i", 149);
|
|
752
765
|
i0.ɵɵtext(2, " Save as Entity Document ");
|
|
@@ -756,24 +769,24 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
756
769
|
i0.ɵɵelement(4, "i", 151);
|
|
757
770
|
i0.ɵɵtext(5, " Try Again ");
|
|
758
771
|
i0.ɵɵelementEnd();
|
|
759
|
-
i0.ɵɵelementStart(6, "button",
|
|
772
|
+
i0.ɵɵelementStart(6, "button", 95);
|
|
760
773
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_53_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.CloseSuggestDialog()); });
|
|
761
774
|
i0.ɵɵtext(7, " Close ");
|
|
762
775
|
i0.ɵɵelementEnd();
|
|
763
776
|
} }
|
|
764
777
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
765
778
|
const _r24 = i0.ɵɵgetCurrentView();
|
|
766
|
-
i0.ɵɵelementStart(0, "div",
|
|
779
|
+
i0.ɵɵelementStart(0, "div", 111)(1, "div", 136)(2, "h4", 137);
|
|
767
780
|
i0.ɵɵtext(3, "Suggested Template");
|
|
768
781
|
i0.ɵɵelementEnd();
|
|
769
|
-
i0.ɵɵelementStart(4, "div",
|
|
782
|
+
i0.ɵɵelementStart(4, "div", 77)(5, "mj-code-editor", 78);
|
|
770
783
|
i0.ɵɵlistener("change", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Template_mj_code_editor_change_5_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnTemplateChange($event)); });
|
|
771
784
|
i0.ɵɵelementEnd()()();
|
|
772
785
|
i0.ɵɵelementStart(6, "div", 136)(7, "h4", 137);
|
|
773
786
|
i0.ɵɵtext(8, "Selected Fields");
|
|
774
787
|
i0.ɵɵelementEnd();
|
|
775
|
-
i0.ɵɵelementStart(9, "div",
|
|
776
|
-
i0.ɵɵrepeaterCreate(10, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_11_Template, 2, 1, "span",
|
|
788
|
+
i0.ɵɵelementStart(9, "div", 88);
|
|
789
|
+
i0.ɵɵrepeaterCreate(10, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_11_Template, 2, 1, "span", 89, i0.ɵɵrepeaterTrackByIdentity);
|
|
777
790
|
i0.ɵɵelementEnd()();
|
|
778
791
|
i0.ɵɵconditionalCreate(12, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_12_Template, 5, 0, "div", 136);
|
|
779
792
|
i0.ɵɵelementStart(13, "div", 138)(14, "div", 139)(15, "span", 140);
|
|
@@ -794,30 +807,30 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
794
807
|
i0.ɵɵelementStart(27, "p", 142);
|
|
795
808
|
i0.ɵɵtext(28);
|
|
796
809
|
i0.ɵɵelementEnd()();
|
|
797
|
-
i0.ɵɵelementStart(29, "div", 136)(30, "div",
|
|
810
|
+
i0.ɵɵelementStart(29, "div", 136)(30, "div", 72)(31, "label", 73);
|
|
798
811
|
i0.ɵɵtext(32, "Document Name");
|
|
799
812
|
i0.ɵɵelementEnd();
|
|
800
|
-
i0.ɵɵelementStart(33, "input",
|
|
813
|
+
i0.ɵɵelementStart(33, "input", 79);
|
|
801
814
|
i0.ɵɵtwoWayListener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Template_input_ngModelChange_33_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.SaveDocumentName, $event) || (ctx_r1.SaveDocumentName = $event); return i0.ɵɵresetView($event); });
|
|
802
815
|
i0.ɵɵelementEnd()();
|
|
803
|
-
i0.ɵɵelementStart(34, "div", 143)(35, "label",
|
|
816
|
+
i0.ɵɵelementStart(34, "div", 143)(35, "label", 73);
|
|
804
817
|
i0.ɵɵtext(36, "Embedding Model");
|
|
805
818
|
i0.ɵɵelementEnd();
|
|
806
|
-
i0.ɵɵelementStart(37, "select",
|
|
807
|
-
i0.ɵɵ
|
|
808
|
-
i0.ɵɵrepeaterCreate(38, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_39_Template, 2, 2, "option",
|
|
819
|
+
i0.ɵɵelementStart(37, "select", 80);
|
|
820
|
+
i0.ɵɵlistener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Template_select_ngModelChange_37_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnSuggestEmbeddingModelChange($event)); });
|
|
821
|
+
i0.ɵɵrepeaterCreate(38, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_39_Template, 2, 2, "option", 81, _forTrack2);
|
|
809
822
|
i0.ɵɵelementEnd()();
|
|
810
|
-
i0.ɵɵelementStart(40, "div", 143)(41, "label",
|
|
823
|
+
i0.ɵɵelementStart(40, "div", 143)(41, "label", 73);
|
|
811
824
|
i0.ɵɵtext(42, "Vector Database");
|
|
812
825
|
i0.ɵɵelementEnd();
|
|
813
|
-
i0.ɵɵelementStart(43, "select",
|
|
814
|
-
i0.ɵɵ
|
|
815
|
-
i0.ɵɵrepeaterCreate(44, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_45_Template, 2, 2, "option",
|
|
826
|
+
i0.ɵɵelementStart(43, "select", 80);
|
|
827
|
+
i0.ɵɵlistener("ngModelChange", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Template_select_ngModelChange_43_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnSuggestVectorDBChange($event)); });
|
|
828
|
+
i0.ɵɵrepeaterCreate(44, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_For_45_Template, 2, 2, "option", 81, _forTrack2);
|
|
816
829
|
i0.ɵɵelementEnd()();
|
|
817
|
-
i0.ɵɵelementStart(46, "div", 143)(47, "label",
|
|
830
|
+
i0.ɵɵelementStart(46, "div", 143)(47, "label", 73);
|
|
818
831
|
i0.ɵɵtext(48, "Vector Index");
|
|
819
832
|
i0.ɵɵelementEnd();
|
|
820
|
-
i0.ɵɵconditionalCreate(49, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_49_Template, 5, 1, "select",
|
|
833
|
+
i0.ɵɵconditionalCreate(49, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_49_Template, 5, 1, "select", 82)(50, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_50_Template, 2, 0, "span", 83);
|
|
821
834
|
i0.ɵɵelementEnd()();
|
|
822
835
|
i0.ɵɵelementStart(51, "div", 144);
|
|
823
836
|
i0.ɵɵconditionalCreate(52, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_52_Template, 2, 0, "div", 145)(53, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Conditional_53_Template, 8, 0);
|
|
@@ -839,11 +852,11 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
839
852
|
i0.ɵɵadvance(5);
|
|
840
853
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.SaveDocumentName);
|
|
841
854
|
i0.ɵɵadvance(4);
|
|
842
|
-
i0.ɵɵ
|
|
855
|
+
i0.ɵɵproperty("ngModel", ctx_r1.SelectedEmbeddingModelID);
|
|
843
856
|
i0.ɵɵadvance();
|
|
844
857
|
i0.ɵɵrepeater(ctx_r1.AvailableEmbeddingModels);
|
|
845
858
|
i0.ɵɵadvance(5);
|
|
846
|
-
i0.ɵɵ
|
|
859
|
+
i0.ɵɵproperty("ngModel", ctx_r1.SelectedVectorDBID);
|
|
847
860
|
i0.ɵɵadvance();
|
|
848
861
|
i0.ɵɵrepeater(ctx_r1.vectorDatabases);
|
|
849
862
|
i0.ɵɵadvance(5);
|
|
@@ -853,20 +866,20 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Condition
|
|
|
853
866
|
} }
|
|
854
867
|
function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Template(rf, ctx) { if (rf & 1) {
|
|
855
868
|
const _r18 = i0.ɵɵgetCurrentView();
|
|
856
|
-
i0.ɵɵelementStart(0, "div",
|
|
869
|
+
i0.ɵɵelementStart(0, "div", 64);
|
|
857
870
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CloseSuggestDialog()); });
|
|
858
|
-
i0.ɵɵelementStart(1, "div",
|
|
871
|
+
i0.ɵɵelementStart(1, "div", 110);
|
|
859
872
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
|
|
860
|
-
i0.ɵɵelementStart(2, "div",
|
|
873
|
+
i0.ɵɵelementStart(2, "div", 66)(3, "h3", 67);
|
|
861
874
|
i0.ɵɵelement(4, "i", 19);
|
|
862
875
|
i0.ɵɵtext(5, " AI Document Suggestion ");
|
|
863
876
|
i0.ɵɵelementEnd();
|
|
864
|
-
i0.ɵɵelementStart(6, "button",
|
|
877
|
+
i0.ɵɵelementStart(6, "button", 68);
|
|
865
878
|
i0.ɵɵlistener("click", function VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CloseSuggestDialog()); });
|
|
866
|
-
i0.ɵɵelement(7, "i",
|
|
879
|
+
i0.ɵɵelement(7, "i", 69);
|
|
867
880
|
i0.ɵɵelementEnd()();
|
|
868
|
-
i0.ɵɵelementStart(8, "div",
|
|
869
|
-
i0.ɵɵconditionalCreate(9, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Template,
|
|
881
|
+
i0.ɵɵelementStart(8, "div", 70);
|
|
882
|
+
i0.ɵɵconditionalCreate(9, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_9_Template, 24, 9, "div", 71)(10, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Conditional_10_Template, 54, 12, "div", 111);
|
|
870
883
|
i0.ɵɵelementEnd()()();
|
|
871
884
|
} if (rf & 2) {
|
|
872
885
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
@@ -895,7 +908,7 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Template(
|
|
|
895
908
|
i0.ɵɵelement(16, "i", 22);
|
|
896
909
|
i0.ɵɵtext(17, " Refresh ");
|
|
897
910
|
i0.ɵɵelementEnd()()();
|
|
898
|
-
i0.ɵɵconditionalCreate(18, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_18_Template, 1, 0, "mj-empty-state", 23)(19, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_Template,
|
|
911
|
+
i0.ɵɵconditionalCreate(18, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_18_Template, 1, 0, "mj-empty-state", 23)(19, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_19_Template, 21, 0, "div", 24);
|
|
899
912
|
i0.ɵɵelementEnd();
|
|
900
913
|
i0.ɵɵelementStart(20, "div", 25)(21, "div", 26)(22, "h4", 27);
|
|
901
914
|
i0.ɵɵelement(23, "i", 28);
|
|
@@ -937,7 +950,7 @@ function VectorManagementResourceComponent_ng_template_2_Conditional_1_Template(
|
|
|
937
950
|
i0.ɵɵtext(53);
|
|
938
951
|
i0.ɵɵpipe(54, "number");
|
|
939
952
|
i0.ɵɵelementEnd()()()()();
|
|
940
|
-
i0.ɵɵconditionalCreate(55, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template,
|
|
953
|
+
i0.ɵɵconditionalCreate(55, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_55_Template, 62, 14, "div", 45);
|
|
941
954
|
i0.ɵɵconditionalCreate(56, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_56_Template, 34, 5, "div", 45);
|
|
942
955
|
i0.ɵɵconditionalCreate(57, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_57_Template, 14, 0, "div", 45);
|
|
943
956
|
i0.ɵɵconditionalCreate(58, VectorManagementResourceComponent_ng_template_2_Conditional_1_Conditional_58_Template, 11, 3, "div", 45);
|
|
@@ -985,10 +998,16 @@ function VectorManagementResourceComponent_ng_template_2_Template(rf, ctx) { if
|
|
|
985
998
|
i0.ɵɵconditional(ctx_r1.IsLoading ? 0 : 1);
|
|
986
999
|
} }
|
|
987
1000
|
let VectorManagementResourceComponent = class VectorManagementResourceComponent extends BaseResourceComponent {
|
|
1001
|
+
static { VectorManagementResourceComponent_1 = this; }
|
|
988
1002
|
cdr = inject(ChangeDetectorRef);
|
|
989
1003
|
activityService = inject(ActivityService);
|
|
990
1004
|
navigationService = inject(NavigationService);
|
|
991
1005
|
destroy$ = new Subject();
|
|
1006
|
+
/**
|
|
1007
|
+
* How long a sync may go without a progress event before the tab stops waiting. Reaching it does
|
|
1008
|
+
* not mean the sync finished (see subscribeToPipelineProgress).
|
|
1009
|
+
*/
|
|
1010
|
+
static SYNC_SILENCE_LIMIT_MS = 2 * 60 * 1000;
|
|
992
1011
|
/** View mode: 'index' = Option A (shared index as hero, entity docs as children),
|
|
993
1012
|
* 'operations' = Option C (operations monitoring with real-time sync status) */
|
|
994
1013
|
ViewMode = 'index';
|
|
@@ -1033,6 +1052,8 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1033
1052
|
EditDocVectorIndexID = '';
|
|
1034
1053
|
EditDocStatus = '';
|
|
1035
1054
|
EditDocTemplate = '';
|
|
1055
|
+
/** Entity Document Type of the document being edited. Fixed at creation, shown read-only. */
|
|
1056
|
+
EditDocType = '';
|
|
1036
1057
|
IsEditRegenerating = false;
|
|
1037
1058
|
/** Parse {{ FieldName }} patterns from the edit panel's template */
|
|
1038
1059
|
get EditDocSelectedFields() {
|
|
@@ -1057,6 +1078,7 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1057
1078
|
this.EditDocAIModelID = doc.AIModelID ?? '';
|
|
1058
1079
|
this.EditDocVectorIndexID = doc.VectorIndexID || '';
|
|
1059
1080
|
this.EditDocStatus = doc.Status;
|
|
1081
|
+
this.EditDocType = doc.Type || '';
|
|
1060
1082
|
this.EditDocTemplate = '';
|
|
1061
1083
|
this.IsEditRegenerating = false;
|
|
1062
1084
|
this.ShowEditPanel = true;
|
|
@@ -1107,8 +1129,10 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1107
1129
|
doc.AIModelID = aiModelID;
|
|
1108
1130
|
// "Auto (create/find matching index)" resolves to a real index for this DB + model, so the
|
|
1109
1131
|
// syncer always has one to write into; without both parts there is nothing to match.
|
|
1110
|
-
|
|
1111
|
-
|
|
1132
|
+
// A chosen index counts only when it matches the database and model shown.
|
|
1133
|
+
const chosenIndex = ChosenIndexForSave(this.editSelection, this.AvailableVectorIndexes);
|
|
1134
|
+
doc.VectorIndexID = chosenIndex
|
|
1135
|
+
? chosenIndex.ID
|
|
1112
1136
|
: (vectorDatabaseID && aiModelID
|
|
1113
1137
|
? await this.resolveOrCreateVectorIndex(vectorDatabaseID, aiModelID, this.EditDocEntityName)
|
|
1114
1138
|
: null);
|
|
@@ -1162,10 +1186,17 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1162
1186
|
async RegenerateTemplate() {
|
|
1163
1187
|
if (!this.EditDocEntityName || this.IsEditRegenerating)
|
|
1164
1188
|
return;
|
|
1189
|
+
// Ask for the use case this document's type stands for, so the regenerated template
|
|
1190
|
+
// still matches the type. Refuse rather than fall back to another use case.
|
|
1191
|
+
const useCase = SuggestionUseCaseForDocumentType(this.EditDocType);
|
|
1192
|
+
if (!useCase) {
|
|
1193
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Can't regenerate: documents of type "${this.EditDocType || 'unknown'}" have no AI template use case.`, 'error', 5000);
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1165
1196
|
this.IsEditRegenerating = true;
|
|
1166
1197
|
this.cdr.detectChanges();
|
|
1167
1198
|
try {
|
|
1168
|
-
const result = await this.callSuggestionPrompt(this.EditDocEntityName,
|
|
1199
|
+
const result = await this.callSuggestionPrompt(this.EditDocEntityName, useCase);
|
|
1169
1200
|
if (result) {
|
|
1170
1201
|
this.EditDocTemplate = result.template;
|
|
1171
1202
|
MJNotificationService.Instance.CreateSimpleNotification('Template regenerated with AI. Review and save to apply.', 'info', 3000);
|
|
@@ -1329,18 +1360,56 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1329
1360
|
AvailableVectorIndexes = [];
|
|
1330
1361
|
/** Selected vector index ID — if user picks an existing one */
|
|
1331
1362
|
SelectedVectorIndexID = '';
|
|
1332
|
-
/**
|
|
1363
|
+
/**
|
|
1364
|
+
* The indexes the suggestion panel offers: those in the selected database built with the selected
|
|
1365
|
+
* embedding model, so a chosen index can never store a different model than the one shown.
|
|
1366
|
+
*/
|
|
1333
1367
|
get FilteredIndexesForSelectedDB() {
|
|
1334
|
-
|
|
1335
|
-
if (!dbId)
|
|
1336
|
-
return this.AvailableVectorIndexes;
|
|
1337
|
-
return this.AvailableVectorIndexes.filter(i => i.VectorDatabaseID === dbId);
|
|
1368
|
+
return IndexesForSelection(this.AvailableVectorIndexes, this.SelectedVectorDBID, this.SelectedEmbeddingModelID);
|
|
1338
1369
|
}
|
|
1339
|
-
/**
|
|
1370
|
+
/** The indexes the edit panel offers, matched to its database and embedding model the same way. */
|
|
1340
1371
|
get EditFilteredIndexes() {
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1372
|
+
return IndexesForSelection(this.AvailableVectorIndexes, this.EditDocVectorDBID, this.EditDocAIModelID);
|
|
1373
|
+
}
|
|
1374
|
+
/** Suggestion panel: picking an index moves the model and database dropdowns to its values. */
|
|
1375
|
+
OnSuggestVectorIndexChange(indexID) {
|
|
1376
|
+
this.applySuggestSelection(SelectIndex(this.suggestSelection, this.AvailableVectorIndexes, indexID));
|
|
1377
|
+
}
|
|
1378
|
+
/** Suggestion panel: a chosen index from another database goes back to Auto. */
|
|
1379
|
+
OnSuggestVectorDBChange(databaseID) {
|
|
1380
|
+
this.applySuggestSelection(SelectDatabase(this.suggestSelection, this.AvailableVectorIndexes, databaseID));
|
|
1381
|
+
}
|
|
1382
|
+
/** Suggestion panel: a chosen index built with another model goes back to Auto. */
|
|
1383
|
+
OnSuggestEmbeddingModelChange(embeddingModelID) {
|
|
1384
|
+
this.applySuggestSelection(SelectEmbeddingModel(this.suggestSelection, this.AvailableVectorIndexes, embeddingModelID));
|
|
1385
|
+
}
|
|
1386
|
+
/** Edit panel: picking an index moves the model and database dropdowns to its values. */
|
|
1387
|
+
OnEditVectorIndexChange(indexID) {
|
|
1388
|
+
this.applyEditSelection(SelectIndex(this.editSelection, this.AvailableVectorIndexes, indexID));
|
|
1389
|
+
}
|
|
1390
|
+
/** Edit panel: a chosen index from another database goes back to Auto. */
|
|
1391
|
+
OnEditVectorDBChange(databaseID) {
|
|
1392
|
+
this.applyEditSelection(SelectDatabase(this.editSelection, this.AvailableVectorIndexes, databaseID));
|
|
1393
|
+
}
|
|
1394
|
+
/** Edit panel: a chosen index built with another model goes back to Auto. */
|
|
1395
|
+
OnEditEmbeddingModelChange(embeddingModelID) {
|
|
1396
|
+
this.applyEditSelection(SelectEmbeddingModel(this.editSelection, this.AvailableVectorIndexes, embeddingModelID));
|
|
1397
|
+
}
|
|
1398
|
+
get suggestSelection() {
|
|
1399
|
+
return { EmbeddingModelID: this.SelectedEmbeddingModelID, VectorDatabaseID: this.SelectedVectorDBID, VectorIndexID: this.SelectedVectorIndexID };
|
|
1400
|
+
}
|
|
1401
|
+
applySuggestSelection(selection) {
|
|
1402
|
+
this.SelectedEmbeddingModelID = selection.EmbeddingModelID;
|
|
1403
|
+
this.SelectedVectorDBID = selection.VectorDatabaseID;
|
|
1404
|
+
this.SelectedVectorIndexID = selection.VectorIndexID;
|
|
1405
|
+
}
|
|
1406
|
+
get editSelection() {
|
|
1407
|
+
return { EmbeddingModelID: this.EditDocAIModelID, VectorDatabaseID: this.EditDocVectorDBID, VectorIndexID: this.EditDocVectorIndexID };
|
|
1408
|
+
}
|
|
1409
|
+
applyEditSelection(selection) {
|
|
1410
|
+
this.EditDocAIModelID = selection.EmbeddingModelID;
|
|
1411
|
+
this.EditDocVectorDBID = selection.VectorDatabaseID;
|
|
1412
|
+
this.EditDocVectorIndexID = selection.VectorIndexID;
|
|
1344
1413
|
}
|
|
1345
1414
|
/** Grouped entity list for the suggestion panel — schemas as groups, entities as items */
|
|
1346
1415
|
EntityGroups = [];
|
|
@@ -1627,11 +1696,19 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1627
1696
|
`;
|
|
1628
1697
|
let idleTimer = null;
|
|
1629
1698
|
const activityID = this.activityService.Start('Vector sync', { icon: 'fa-solid fa-cubes', detail: entityName, progress: 0 });
|
|
1630
|
-
|
|
1699
|
+
/**
|
|
1700
|
+
* 'success' and 'error' come only from the server's own complete / error events.
|
|
1701
|
+
* 'unconfirmed' is a long silence (a dropped connection, say): the row is refreshed from the
|
|
1702
|
+
* database, but nothing claims the run finished, because the server may still be working.
|
|
1703
|
+
*/
|
|
1704
|
+
const finishSync = (outcome) => {
|
|
1631
1705
|
if (idleTimer)
|
|
1632
1706
|
clearTimeout(idleTimer);
|
|
1633
1707
|
rxSub?.unsubscribe();
|
|
1634
|
-
|
|
1708
|
+
const success = outcome !== 'error';
|
|
1709
|
+
this.activityService.Complete(activityID, success ? 'success' : 'error', outcome === 'success' ? `${entityName} vectorized`
|
|
1710
|
+
: outcome === 'error' ? `Failed for ${entityName}`
|
|
1711
|
+
: `${entityName}: no progress received`);
|
|
1635
1712
|
// Use setTimeout to defer state changes to the next macrotask,
|
|
1636
1713
|
// avoiding ExpressionChangedAfterItHasBeenCheckedError.
|
|
1637
1714
|
// (Promise.resolve microtasks run between Angular's check passes
|
|
@@ -1639,10 +1716,15 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1639
1716
|
setTimeout(async () => {
|
|
1640
1717
|
try {
|
|
1641
1718
|
this.removeSyncingId(entityDocumentId);
|
|
1642
|
-
if (success) {
|
|
1719
|
+
if (outcome === 'success') {
|
|
1643
1720
|
MJNotificationService.Instance.CreateSimpleNotification(`Vectorization complete for ${entityName}`, 'success', 3000);
|
|
1644
1721
|
await this.refreshSyncRow(entityDocumentId);
|
|
1645
1722
|
}
|
|
1723
|
+
else if (outcome === 'unconfirmed') {
|
|
1724
|
+
MJNotificationService.Instance.CreateSimpleNotification(`No progress received for ${entityName} in ${VectorManagementResourceComponent_1.SYNC_SILENCE_LIMIT_MS / 60000} minutes, ` +
|
|
1725
|
+
`so the result can't be confirmed. The vector count shown is what is stored now; refresh later to check.`, 'warning', 8000);
|
|
1726
|
+
await this.refreshSyncRow(entityDocumentId);
|
|
1727
|
+
}
|
|
1646
1728
|
else {
|
|
1647
1729
|
this.updateRowStatus(entityDocumentId, 'Error');
|
|
1648
1730
|
MJNotificationService.Instance.CreateSimpleNotification(`Vectorization failed for ${entityName}`, 'error', 5000);
|
|
@@ -1658,16 +1740,17 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1658
1740
|
}
|
|
1659
1741
|
});
|
|
1660
1742
|
};
|
|
1661
|
-
// Reset
|
|
1662
|
-
//
|
|
1743
|
+
// Reset on every event. Silence is not success: the server reports progress in 5% steps,
|
|
1744
|
+
// and with a remote embedding model one step can take far longer than a few seconds, so a
|
|
1745
|
+
// short silence routinely reported "Synced" while most records were still being embedded.
|
|
1663
1746
|
const resetIdleTimer = () => {
|
|
1664
1747
|
if (idleTimer)
|
|
1665
1748
|
clearTimeout(idleTimer);
|
|
1666
1749
|
idleTimer = setTimeout(() => {
|
|
1667
1750
|
if (this.IsSyncing(entityDocumentId)) {
|
|
1668
|
-
finishSync(
|
|
1751
|
+
finishSync('unconfirmed');
|
|
1669
1752
|
}
|
|
1670
|
-
},
|
|
1753
|
+
}, VectorManagementResourceComponent_1.SYNC_SILENCE_LIMIT_MS);
|
|
1671
1754
|
};
|
|
1672
1755
|
// Start the idle timer immediately in case no events ever arrive
|
|
1673
1756
|
resetIdleTimer();
|
|
@@ -1682,10 +1765,10 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1682
1765
|
this.updateRowProgress(entityDocumentId, pct);
|
|
1683
1766
|
this.cdr.detectChanges();
|
|
1684
1767
|
if (stage === 'complete') {
|
|
1685
|
-
finishSync(
|
|
1768
|
+
finishSync('success');
|
|
1686
1769
|
}
|
|
1687
1770
|
else if (stage === 'error') {
|
|
1688
|
-
finishSync(
|
|
1771
|
+
finishSync('error');
|
|
1689
1772
|
}
|
|
1690
1773
|
else {
|
|
1691
1774
|
// Got a progress event — reset idle timer
|
|
@@ -1694,7 +1777,7 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1694
1777
|
},
|
|
1695
1778
|
error: (err) => {
|
|
1696
1779
|
console.error(`[VectorManagement] Pipeline subscription error:`, err);
|
|
1697
|
-
finishSync(
|
|
1780
|
+
finishSync('error');
|
|
1698
1781
|
}
|
|
1699
1782
|
});
|
|
1700
1783
|
}
|
|
@@ -1896,6 +1979,15 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1896
1979
|
try {
|
|
1897
1980
|
const result = await this.callSuggestionPrompt(this.SuggestEntityName, this.SuggestUseCase);
|
|
1898
1981
|
if (result) {
|
|
1982
|
+
// The field list is whatever the model returned — no cap, no filter. Bound it
|
|
1983
|
+
// here so an over-wide suggestion is visible immediately rather than at save.
|
|
1984
|
+
const capped = CapSelectedFields(result.selectedFields);
|
|
1985
|
+
if (capped.dropped > 0) {
|
|
1986
|
+
MJNotificationService.Instance.CreateSimpleNotification(`The suggestion selected ${capped.fields.length + capped.dropped} fields. ` +
|
|
1987
|
+
`Keeping the first ${MAX_TEMPLATE_FIELDS} and dropping ${capped.dropped} — a list ` +
|
|
1988
|
+
`this long usually means the whole table was pulled in. Check the template.`, 'warning', 6000);
|
|
1989
|
+
}
|
|
1990
|
+
result.selectedFields = capped.fields;
|
|
1899
1991
|
this.SuggestionResult = result;
|
|
1900
1992
|
this.EditableTemplate = result.template;
|
|
1901
1993
|
this.SaveDocumentName = `${this.SuggestEntityName} - ${this.SuggestUseCase}`;
|
|
@@ -1920,8 +2012,7 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1920
2012
|
this.cdr.detectChanges();
|
|
1921
2013
|
try {
|
|
1922
2014
|
const md = this.ProviderToUse;
|
|
1923
|
-
const entityDoc = await
|
|
1924
|
-
entityDoc.NewRecord();
|
|
2015
|
+
const entityDoc = await this.findOrCreateEntityDocument();
|
|
1925
2016
|
entityDoc.Name = this.SaveDocumentName;
|
|
1926
2017
|
const matchingEntity = md.Entities.find(e => e.Name === this.SuggestEntityName);
|
|
1927
2018
|
if (matchingEntity) {
|
|
@@ -1930,6 +2021,12 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
1930
2021
|
entityDoc.Status = 'Active';
|
|
1931
2022
|
// Populate required FK fields from existing data
|
|
1932
2023
|
await this.populateEntityDocumentFKs(entityDoc);
|
|
2024
|
+
// The panel shows the model's match thresholds; store them rather than leaving the defaults.
|
|
2025
|
+
const thresholds = SuggestedMatchThresholds(this.SuggestionResult.potentialMatchThreshold, this.SuggestionResult.absoluteMatchThreshold);
|
|
2026
|
+
if (thresholds) {
|
|
2027
|
+
entityDoc.PotentialMatchThreshold = thresholds.Potential;
|
|
2028
|
+
entityDoc.AbsoluteMatchThreshold = thresholds.Absolute;
|
|
2029
|
+
}
|
|
1933
2030
|
const saved = await entityDoc.Save();
|
|
1934
2031
|
if (saved) {
|
|
1935
2032
|
MJNotificationService.Instance.CreateSimpleNotification(`Entity Document "${this.SaveDocumentName}" created successfully`, 'success', 3000);
|
|
@@ -2020,8 +2117,10 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2020
2117
|
// hands out its own cached array, which this component must not mutate.
|
|
2021
2118
|
this.vectorIndexes = [...AIEngineBase.Instance.VectorIndexes];
|
|
2022
2119
|
// Build per-EntityDocument aggregate stats (vector count + last synced).
|
|
2023
|
-
// Each query fetches
|
|
2024
|
-
//
|
|
2120
|
+
// Each query fetches the two most recent rows and uses TotalRowCount for the
|
|
2121
|
+
// vector count, which avoids loading all rows. MaxRows is 2, not 1: a full
|
|
2122
|
+
// `MaxRows: 1` read skips the total count (#4450), so TotalRowCount would be 1.
|
|
2123
|
+
// With 2, a full page triggers the count, and a short page is itself the total.
|
|
2025
2124
|
// AI Models come from a different domain — fetched in the same batch.
|
|
2026
2125
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2027
2126
|
const erdQueries = this.entityDocuments.map(doc => ({
|
|
@@ -2030,7 +2129,7 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2030
2129
|
ResultType: 'simple',
|
|
2031
2130
|
Fields: ['__mj_UpdatedAt'],
|
|
2032
2131
|
OrderBy: '__mj_UpdatedAt DESC',
|
|
2033
|
-
MaxRows:
|
|
2132
|
+
MaxRows: 2,
|
|
2034
2133
|
BypassCache: forceRefresh,
|
|
2035
2134
|
}));
|
|
2036
2135
|
const allQueries = [
|
|
@@ -2069,6 +2168,7 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2069
2168
|
EntityDocumentID: doc.ID,
|
|
2070
2169
|
EntityName: doc.Entity || '',
|
|
2071
2170
|
DocumentName: doc.Name,
|
|
2171
|
+
DocumentType: doc.Type || '',
|
|
2072
2172
|
VectorCount: vectorCount,
|
|
2073
2173
|
LastSynced: lastSynced,
|
|
2074
2174
|
Status: status,
|
|
@@ -2199,10 +2299,9 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2199
2299
|
VectorDatabaseID: vi.VectorDatabaseID,
|
|
2200
2300
|
EmbeddingModelID: vi.EmbeddingModelID
|
|
2201
2301
|
}));
|
|
2202
|
-
//
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
}
|
|
2302
|
+
// No index is pre-selected: the first index is whatever happens to sort first (here, another
|
|
2303
|
+
// feature's shared index), and a chosen index decides the database and model Save stores.
|
|
2304
|
+
// Auto finds or creates the index for the database and model shown.
|
|
2206
2305
|
}
|
|
2207
2306
|
/** Find the best embedding model from loaded AI models */
|
|
2208
2307
|
findEmbeddingModel() {
|
|
@@ -2221,26 +2320,46 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2221
2320
|
missing.push('Embedding Model');
|
|
2222
2321
|
throw new Error(`Prerequisites not configured: ${missing.join(', ')}. Go to the Configuration tab to set these up.`);
|
|
2223
2322
|
}
|
|
2224
|
-
// TypeID —
|
|
2323
|
+
// TypeID — from the use case the user actually chose. This used to be hardcoded to
|
|
2324
|
+
// 'Record Duplicate', so picking "search" in the dialog silently produced a
|
|
2325
|
+
// duplicate-detection document: the selection was discarded and the document was the
|
|
2326
|
+
// wrong type. A vector pool is typed — Provider.SearchEntity and the Search Entity
|
|
2327
|
+
// action read Search-typed documents — so the mislabelled document is also invisible
|
|
2328
|
+
// to the feature that asked for it.
|
|
2329
|
+
const wantedTypeName = EntityDocumentTypeForUseCase(this.SuggestUseCase);
|
|
2330
|
+
if (!wantedTypeName) {
|
|
2331
|
+
throw new Error(`No Entity Document Type is defined for the "${this.SuggestUseCase}" use case. ` +
|
|
2332
|
+
`Known use cases: ${Object.keys(ENTITY_DOCUMENT_TYPE_BY_USE_CASE).join(', ')}.`);
|
|
2333
|
+
}
|
|
2225
2334
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2226
2335
|
const typeResult = await rv.RunView({
|
|
2227
2336
|
EntityName: 'MJ: Entity Document Types',
|
|
2228
|
-
ExtraFilter: "Name = 'Record Duplicate'",
|
|
2229
2337
|
ResultType: 'simple',
|
|
2230
|
-
Fields: ['ID']
|
|
2338
|
+
Fields: ['ID', 'Name']
|
|
2231
2339
|
});
|
|
2232
|
-
|
|
2233
|
-
|
|
2340
|
+
const availableTypes = typeResult.Success ? typeResult.Results : [];
|
|
2341
|
+
// Trimmed, case-insensitive comparison — the same match EntityDocumentCache
|
|
2342
|
+
// .GetDocumentTypeByName makes server-side, so the dialog and the syncer agree.
|
|
2343
|
+
const wanted = wantedTypeName.trim().toLowerCase();
|
|
2344
|
+
const matchedType = availableTypes.find(t => t.Name?.trim().toLowerCase() === wanted);
|
|
2345
|
+
if (matchedType) {
|
|
2346
|
+
entityDoc.TypeID = matchedType.ID;
|
|
2234
2347
|
}
|
|
2235
2348
|
else {
|
|
2236
|
-
|
|
2349
|
+
// Never substitute a type that happens to exist: that is the defect above.
|
|
2350
|
+
const names = availableTypes.map(t => t.Name).sort();
|
|
2351
|
+
throw new Error(`Entity Document Type "${wantedTypeName}" not found in database. It is the type the ` +
|
|
2352
|
+
`"${this.SuggestUseCase}" use case needs, and no other type will be used in its place. ` +
|
|
2353
|
+
(names.length > 0
|
|
2354
|
+
? `Types that do exist: ${names.join(', ')}. Add "${wantedTypeName}" to MJ: Entity Document Types.`
|
|
2355
|
+
: 'No Entity Document Types exist at all.'));
|
|
2237
2356
|
}
|
|
2238
2357
|
// An explicitly chosen index fixes the DB + model. "Auto (create/find matching index)" resolves
|
|
2239
2358
|
// (or creates) the index for the chosen DB + model, so the syncer always has a VectorIndexID:
|
|
2240
2359
|
// it refuses to run without one, which made the Auto choice a dead end before.
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2360
|
+
// Only an index that matches the database and model shown counts as chosen, so the stored
|
|
2361
|
+
// database and model are always the ones the dropdowns displayed.
|
|
2362
|
+
const chosen = ChosenIndexForSave(this.suggestSelection, this.AvailableVectorIndexes);
|
|
2244
2363
|
if (chosen) {
|
|
2245
2364
|
entityDoc.VectorDatabaseID = chosen.VectorDatabaseID;
|
|
2246
2365
|
entityDoc.AIModelID = chosen.EmbeddingModelID;
|
|
@@ -2297,12 +2416,33 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2297
2416
|
if (!templateText) {
|
|
2298
2417
|
throw new Error('No template content to save');
|
|
2299
2418
|
}
|
|
2300
|
-
//
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2419
|
+
// LAYER 2: the template is hand-editable after the model returns, so a user can type
|
|
2420
|
+
// a field the picker never offered. Refuse before anything is written — once values
|
|
2421
|
+
// reach the vector index they are retrievable by similarity search, outside the
|
|
2422
|
+
// entity permissions that guard the source column, and not fully reversible.
|
|
2423
|
+
const sensitive = SensitiveFieldsInTemplate(templateText, this.vectorFieldPurpose(this.SuggestUseCase));
|
|
2424
|
+
if (sensitive.length > 0) {
|
|
2425
|
+
throw new Error(`This template references ${sensitive.length === 1 ? 'a field' : 'fields'} that must not be ` +
|
|
2426
|
+
`vectorized: ${sensitive.join(', ')}. Embedding copies the values into the vector index, ` +
|
|
2427
|
+
`where they are retrievable by similarity search rather than by an authorized query. ` +
|
|
2428
|
+
`Remove ${sensitive.length === 1 ? 'it' : 'them'} from the template and save again.`);
|
|
2429
|
+
}
|
|
2430
|
+
// The field list is unbounded and comes straight from a prompt, and the template stays
|
|
2431
|
+
// hand-editable after the model returns — so the authoritative bound is here, on what
|
|
2432
|
+
// actually gets embedded, not on the model's own description of what it picked.
|
|
2433
|
+
const capRefusal = TemplateFieldCapRefusal(templateText);
|
|
2434
|
+
if (capRefusal) {
|
|
2435
|
+
throw new Error(capRefusal);
|
|
2436
|
+
}
|
|
2437
|
+
// Find-or-create, so a retry after a mid-flow failure converges on one set of rows.
|
|
2438
|
+
const templateName = this.templateNameForDocument();
|
|
2439
|
+
const template = await this.findOrCreateTemplate(templateName, entityDoc.TemplateID);
|
|
2440
|
+
template.Name = templateName;
|
|
2304
2441
|
template.Description = `Auto-generated template for entity document: ${this.SaveDocumentName}`;
|
|
2305
|
-
template
|
|
2442
|
+
// An adopted template keeps its owner; only a new one is the current user's.
|
|
2443
|
+
if (!template.UserID) {
|
|
2444
|
+
template.UserID = md.CurrentUser.ID;
|
|
2445
|
+
}
|
|
2306
2446
|
template.IsActive = true;
|
|
2307
2447
|
const templateSaved = await template.Save();
|
|
2308
2448
|
if (!templateSaved) {
|
|
@@ -2322,8 +2462,7 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2322
2462
|
// Create TemplateContent record with the template text
|
|
2323
2463
|
// Server-side MJTemplateContentEntityServer hook auto-creates Scalar params
|
|
2324
2464
|
// for each {{FieldName}} — GetTemplateData() handles them via the flat convention.
|
|
2325
|
-
const content = await
|
|
2326
|
-
content.NewRecord();
|
|
2465
|
+
const content = await this.findOrCreateTemplateContent(template.ID);
|
|
2327
2466
|
content.TemplateID = template.ID;
|
|
2328
2467
|
content.TypeID = contentTypeResult.Results[0].ID;
|
|
2329
2468
|
content.TemplateText = templateText;
|
|
@@ -2334,11 +2473,136 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2334
2473
|
throw new Error(`Failed to create template content: ${content.LatestResult?.CompleteMessage || 'unknown error'}`);
|
|
2335
2474
|
}
|
|
2336
2475
|
}
|
|
2476
|
+
/** The Template name this dialog deterministically gives the current document. */
|
|
2477
|
+
templateNameForDocument() {
|
|
2478
|
+
return `Template for ${this.SaveDocumentName}`;
|
|
2479
|
+
}
|
|
2480
|
+
/**
|
|
2481
|
+
* The Entity Document for the current dialog, reusing the row an earlier attempt created
|
|
2482
|
+
* rather than adding a second one.
|
|
2483
|
+
*
|
|
2484
|
+
* This flow writes three rows — Template, Template Content, Entity Document — in that
|
|
2485
|
+
* order, and only the last is protected by a unique index (`UQ_EntityDocument_Name` on
|
|
2486
|
+
* `EntityDocument.Name`). So a duplicate was not a rare partial-failure case: that index
|
|
2487
|
+
* guarantees a second attempt with the same name fails at the final step, *after* the
|
|
2488
|
+
* Template and Template Content rows have been written again. Orphans accumulated one
|
|
2489
|
+
* pair per retry.
|
|
2490
|
+
*
|
|
2491
|
+
* Matched on Name, because that is the identity the database itself enforces.
|
|
2492
|
+
*
|
|
2493
|
+
* An existing document is adopted only when this dialog created it — its TemplateID points
|
|
2494
|
+
* at the template named `Template for <document name>` — and only for the same entity, so a
|
|
2495
|
+
* retry never moves another entity's document. A collision with a document
|
|
2496
|
+
* authored anywhere else is refused, because silently overwriting somebody's configured
|
|
2497
|
+
* document is worse than asking for a different name.
|
|
2498
|
+
*/
|
|
2499
|
+
async findOrCreateEntityDocument() {
|
|
2500
|
+
const md = this.ProviderToUse;
|
|
2501
|
+
const rv = RunView.FromMetadataProvider(md);
|
|
2502
|
+
const existing = await rv.RunView({
|
|
2503
|
+
EntityName: 'MJ: Entity Documents',
|
|
2504
|
+
ExtraFilter: `Name='${EscapeSQLString(this.SaveDocumentName)}'`,
|
|
2505
|
+
ResultType: 'entity_object',
|
|
2506
|
+
MaxRows: 1,
|
|
2507
|
+
});
|
|
2508
|
+
if (existing.Success && existing.Results.length > 0) {
|
|
2509
|
+
const priorDoc = existing.Results[0];
|
|
2510
|
+
const ownTemplate = priorDoc.TemplateID
|
|
2511
|
+
? await this.templateHasName(priorDoc.TemplateID, this.templateNameForDocument())
|
|
2512
|
+
: false;
|
|
2513
|
+
if (!ownTemplate) {
|
|
2514
|
+
throw new Error(`An Entity Document named "${this.SaveDocumentName}" already exists and was not ` +
|
|
2515
|
+
`created here, so it will not be overwritten. Choose a different name.`);
|
|
2516
|
+
}
|
|
2517
|
+
// Adopting a document for another entity would move it to this one.
|
|
2518
|
+
const entity = md.Entities.find(e => e.Name === this.SuggestEntityName);
|
|
2519
|
+
if (entity && priorDoc.EntityID && !UUIDsEqual(priorDoc.EntityID, entity.ID)) {
|
|
2520
|
+
throw new Error(`An Entity Document named "${this.SaveDocumentName}" already exists for ` +
|
|
2521
|
+
`${priorDoc.Entity || 'another entity'}, so it will not be reused. Choose a different name.`);
|
|
2522
|
+
}
|
|
2523
|
+
return priorDoc;
|
|
2524
|
+
}
|
|
2525
|
+
const entityDoc = await md.GetEntityObject('MJ: Entity Documents');
|
|
2526
|
+
entityDoc.NewRecord();
|
|
2527
|
+
return entityDoc;
|
|
2528
|
+
}
|
|
2529
|
+
/**
|
|
2530
|
+
* The Template for the current document, reusing an earlier attempt's row.
|
|
2531
|
+
*
|
|
2532
|
+
* An adopted Entity Document already points at its template (findOrCreateEntityDocument
|
|
2533
|
+
* checked its name), so that row is reused by ID. Matching it on Name + UserID instead
|
|
2534
|
+
* misses it when another user created it, writes a second template, re-points the document
|
|
2535
|
+
* and orphans the first Template and Template Content.
|
|
2536
|
+
*
|
|
2537
|
+
* For a new document, matched on Name + UserID: `Template` carries no unique index, and that
|
|
2538
|
+
* pair is exactly what this flow writes, so it identifies our own prior row without claiming
|
|
2539
|
+
* anyone else's.
|
|
2540
|
+
*/
|
|
2541
|
+
async findOrCreateTemplate(templateName, adoptedTemplateId) {
|
|
2542
|
+
const md = this.ProviderToUse;
|
|
2543
|
+
const rv = RunView.FromMetadataProvider(md);
|
|
2544
|
+
const existing = await rv.RunView({
|
|
2545
|
+
EntityName: 'MJ: Templates',
|
|
2546
|
+
ExtraFilter: adoptedTemplateId
|
|
2547
|
+
? `ID='${EscapeSQLString(adoptedTemplateId)}'`
|
|
2548
|
+
: `Name='${EscapeSQLString(templateName)}' AND UserID='${md.CurrentUser.ID}'`,
|
|
2549
|
+
ResultType: 'entity_object',
|
|
2550
|
+
MaxRows: 1,
|
|
2551
|
+
});
|
|
2552
|
+
if (existing.Success && existing.Results.length > 0) {
|
|
2553
|
+
return existing.Results[0];
|
|
2554
|
+
}
|
|
2555
|
+
const template = await md.GetEntityObject('MJ: Templates');
|
|
2556
|
+
template.NewRecord();
|
|
2557
|
+
return template;
|
|
2558
|
+
}
|
|
2559
|
+
/**
|
|
2560
|
+
* The Template Content row for a template, reusing the one it already has.
|
|
2561
|
+
*
|
|
2562
|
+
* `Priority ASC`, first row, is how loadEditDocTemplate and saveEditDocTemplate already
|
|
2563
|
+
* identify "the" content of a template — this follows that convention rather than adding
|
|
2564
|
+
* a second one.
|
|
2565
|
+
*/
|
|
2566
|
+
async findOrCreateTemplateContent(templateId) {
|
|
2567
|
+
const md = this.ProviderToUse;
|
|
2568
|
+
const rv = RunView.FromMetadataProvider(md);
|
|
2569
|
+
const existing = await rv.RunView({
|
|
2570
|
+
EntityName: 'MJ: Template Contents',
|
|
2571
|
+
ExtraFilter: `TemplateID='${templateId}'`,
|
|
2572
|
+
ResultType: 'entity_object',
|
|
2573
|
+
OrderBy: 'Priority ASC',
|
|
2574
|
+
MaxRows: 1,
|
|
2575
|
+
});
|
|
2576
|
+
if (existing.Success && existing.Results.length > 0) {
|
|
2577
|
+
return existing.Results[0];
|
|
2578
|
+
}
|
|
2579
|
+
const content = await md.GetEntityObject('MJ: Template Contents');
|
|
2580
|
+
content.NewRecord();
|
|
2581
|
+
return content;
|
|
2582
|
+
}
|
|
2583
|
+
/** True when the template with this ID carries the given name. */
|
|
2584
|
+
async templateHasName(templateId, name) {
|
|
2585
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2586
|
+
const result = await rv.RunView({
|
|
2587
|
+
EntityName: 'MJ: Templates',
|
|
2588
|
+
ExtraFilter: `ID='${templateId}'`,
|
|
2589
|
+
Fields: ['Name'],
|
|
2590
|
+
ResultType: 'simple',
|
|
2591
|
+
MaxRows: 1,
|
|
2592
|
+
});
|
|
2593
|
+
return result.Success && result.Results.length > 0 && result.Results[0].Name === name;
|
|
2594
|
+
}
|
|
2337
2595
|
/** Build grouped entity list from metadata, grouped by SchemaName */
|
|
2338
2596
|
loadEntityGroups() {
|
|
2339
2597
|
const md = this.ProviderToUse;
|
|
2340
2598
|
const groupMap = new Map();
|
|
2341
2599
|
for (const entity of md.Entities) {
|
|
2600
|
+
// The picker used to list every entity in metadata, so MJ's own internal entities
|
|
2601
|
+
// were offered as vectorization targets. See vector-document-rules.ts for the rule
|
|
2602
|
+
// and the precedent it follows.
|
|
2603
|
+
if (!IsVectorizableEntity(entity)) {
|
|
2604
|
+
continue;
|
|
2605
|
+
}
|
|
2342
2606
|
const schema = entity.SchemaName || '__default';
|
|
2343
2607
|
const existing = groupMap.get(schema);
|
|
2344
2608
|
if (existing) {
|
|
@@ -2451,9 +2715,19 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2451
2715
|
}
|
|
2452
2716
|
return prompt;
|
|
2453
2717
|
}
|
|
2718
|
+
/**
|
|
2719
|
+
* What a document for this use case embeds its fields for. Only a duplicate-detection document
|
|
2720
|
+
* may embed a date of birth (see sensitive-fields.ts).
|
|
2721
|
+
*/
|
|
2722
|
+
vectorFieldPurpose(useCase) {
|
|
2723
|
+
return EntityDocumentTypeForUseCase(useCase) === 'Record Duplicate' ? 'duplicate-detection' : 'other';
|
|
2724
|
+
}
|
|
2454
2725
|
/** Build the data payload for the suggestion prompt */
|
|
2455
2726
|
buildPromptData(entity, useCase) {
|
|
2456
|
-
|
|
2727
|
+
// LAYER 1 of the sensitive-field refusal: the model never sees these columns, so it
|
|
2728
|
+
// cannot suggest them. See sensitive-fields.ts for why this cannot live in the prompt.
|
|
2729
|
+
const purpose = this.vectorFieldPurpose(useCase);
|
|
2730
|
+
const fields = WithoutSensitiveFields(entity.Fields, purpose).map(f => ({
|
|
2457
2731
|
Name: f.Name,
|
|
2458
2732
|
Type: f.Type,
|
|
2459
2733
|
IsPrimaryKey: f.IsPrimaryKey,
|
|
@@ -2468,8 +2742,9 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2468
2742
|
.slice(0, 20)
|
|
2469
2743
|
.map(r => {
|
|
2470
2744
|
const relatedEntity = md.Entities.find(e => e.Name === r.RelatedEntity);
|
|
2745
|
+
// Layer 1 covers related entities too: their fields reach the model here.
|
|
2471
2746
|
const relFields = relatedEntity
|
|
2472
|
-
? relatedEntity.Fields
|
|
2747
|
+
? WithoutSensitiveFields(relatedEntity.Fields, purpose)
|
|
2473
2748
|
.filter(f => !f.IsPrimaryKey && f.Type !== 'datetimeoffset')
|
|
2474
2749
|
.map(f => f.Name)
|
|
2475
2750
|
: [];
|
|
@@ -2493,7 +2768,7 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2493
2768
|
} if (rf & 2) {
|
|
2494
2769
|
let _t;
|
|
2495
2770
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.EntitySearchInput = _t.first);
|
|
2496
|
-
} }, inputs: { HideToolbar: "HideToolbar" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [["vectorBody", ""], ["entitySearchInput", ""], ["Title", "Vector Management", "Icon", "fa-solid fa-cubes", "Subtitle", "Vector index health, embeddings, and entity sync status"], ["actions", ""], [3, "KeyChange", "Options", "ActiveKey"], [3, "Flex"], [4, "ngTemplateOutlet"], [1, "vector-loading"], ["text", "Loading vector management data..."], [1, "vector-dashboard"], [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"], ["Icon", "fa-solid fa-folder-open", "Title", "No entity documents configured for vectorization."], [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", 3, "title"], [1, "health-reason"], [1, "fa-solid", "fa-microchip"], [1, "model-info"], [1, "info-row"], [1, "info-label"], [1, "info-value", 3, "title"], [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, "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", "Schedule recurring sync", 1, "schedule-btn", 3, "click"], [1, "fa-regular", "fa-clock"], ["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, "info-value"], [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"], [1, "edit-template-header"], ["title", "Regenerate template using AI", 1, "edit-regenerate-btn", 3, "click", "disabled"], [1, "template-editor-wrapper"], ["language", "markdown", 3, "change", "value", "readonly", "lineWrapping"], ["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"], [1, "result-tags"], [1, "result-tag"], ["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, "schedule-dialog", 3, "click"], ["type", "text", "placeholder", "0 2 * * *", 1, "suggest-input", 3, "ngModelChange", "ngModel"], [1, "schedule-cron-preview"], [1, "fa-solid", "fa-info-circle"], [1, "suggest-field", "schedule-toggle-row"], ["type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-check"], [1, "no-index-warning-dialog", 3, "click"], [1, "no-index-warning-icon"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "no-index-warning-title"], [1, "no-index-warning-message"], [1, "no-index-warning-actions"], [1, "fa-solid", "fa-gear"], [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, "
|
|
2771
|
+
} }, inputs: { HideToolbar: "HideToolbar" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [["vectorBody", ""], ["entitySearchInput", ""], ["Title", "Vector Management", "Icon", "fa-solid fa-cubes", "Subtitle", "Vector index health, embeddings, and entity sync status"], ["actions", ""], [3, "KeyChange", "Options", "ActiveKey"], [3, "Flex"], [4, "ngTemplateOutlet"], [1, "vector-loading"], ["text", "Loading vector management data..."], [1, "vector-dashboard"], [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"], ["Icon", "fa-solid fa-folder-open", "Title", "No entity documents configured for vectorization."], [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", 3, "title"], [1, "health-reason"], [1, "fa-solid", "fa-microchip"], [1, "model-info"], [1, "info-row"], [1, "info-label"], [1, "info-value", 3, "title"], [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, "sync-table"], [1, "text-right"], [1, "text-center"], [1, "entity-name"], [1, "document-name"], [1, "document-type"], [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", "Schedule recurring sync", 1, "schedule-btn", 3, "click"], [1, "fa-regular", "fa-clock"], ["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, "info-value"], [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"], [1, "edit-template-header"], ["title", "Regenerate template using AI", 1, "edit-regenerate-btn", 3, "click", "disabled"], [1, "template-editor-wrapper"], ["language", "markdown", 3, "change", "value", "readonly", "lineWrapping"], ["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"], [1, "result-tags"], [1, "result-tag"], ["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, "schedule-dialog", 3, "click"], ["type", "text", "placeholder", "0 2 * * *", 1, "suggest-input", 3, "ngModelChange", "ngModel"], [1, "schedule-cron-preview"], [1, "fa-solid", "fa-info-circle"], [1, "suggest-field", "schedule-toggle-row"], ["type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-check"], [1, "no-index-warning-dialog", 3, "click"], [1, "no-index-warning-icon"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "no-index-warning-title"], [1, "no-index-warning-message"], [1, "no-index-warning-actions"], [1, "fa-solid", "fa-gear"], [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, "suggest-submit-btn", 3, "click", "disabled"], ["Variant", "error", "Size", "sm"], [1, "fa-solid", "fa-table"], [1, "entity-picker-value"], [1, "fa-solid", "fa-search"], [1, "entity-picker-placeholder"], [1, "entity-picker-dropdown", 3, "mousedown"], [1, "entity-picker-search"], ["type", "text", "placeholder", "Filter entities...", 1, "entity-picker-search-input", 3, "ngModelChange", "input", "keydown", "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", "entity-picker-item-focused"], [1, "entity-picker-item", 3, "click"], [1, "result-section"], [1, "result-heading"], [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) {
|
|
2497
2772
|
i0.ɵɵconditionalCreate(0, VectorManagementResourceComponent_Conditional_0_Template, 6, 4, "mj-page-layout");
|
|
2498
2773
|
i0.ɵɵconditionalCreate(1, VectorManagementResourceComponent_Conditional_1_Template, 1, 1, "ng-container");
|
|
2499
2774
|
i0.ɵɵtemplate(2, VectorManagementResourceComponent_ng_template_2_Template, 2, 1, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
|
|
@@ -2501,22 +2776,22 @@ let VectorManagementResourceComponent = class VectorManagementResourceComponent
|
|
|
2501
2776
|
i0.ɵɵconditional(!ctx.HideToolbar ? 0 : -1);
|
|
2502
2777
|
i0.ɵɵadvance();
|
|
2503
2778
|
i0.ɵɵconditional(ctx.HideToolbar ? 1 : -1);
|
|
2504
|
-
} }, dependencies: [i1.NgTemplateOutlet, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.LoadingComponent, i5.KPICardComponent, i6.MJPageHeaderComponent, i6.MJPageLayoutComponent, i6.MJPageBodyComponent, i6.MJViewToggleComponent, i6.MJEmptyStateComponent, i6.MJAlertComponent, i1.DecimalPipe], styles: ["\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.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.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.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.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.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.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.actions-cell[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n align-items: center;\n justify-content: center;\n}\n\n.schedule-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.schedule-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\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\n.schedule-dialog[_ngcontent-%COMP%] {\n width: 440px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);\n overflow: hidden;\n}\n\n.schedule-cron-preview[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 0 0;\n font-size: 0.82rem;\n color: var(--mj-text-muted);\n}\n\n.schedule-toggle-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\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.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.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.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.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.health-reason[_ngcontent-%COMP%] {\n font-size: 11px;\n line-height: 1.4;\n color: var(--mj-text-muted);\n padding-left: 18px;\n margin-top: 4px;\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.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.panel-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\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.slide-panel-overlay[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 100000;\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.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.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.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-item-focused[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: -2px;\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.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\n.suggest-submit-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\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.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.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.save-spinner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px 0;\n}\n\n\n.edit-template-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.edit-regenerate-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.edit-regenerate-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.edit-regenerate-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n.no-index-warning-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 440px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 20px 60px color-mix(in srgb, var(--mj-text-primary) 20%, transparent);\n padding: 32px;\n text-align: center;\n}\n\n.no-index-warning-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 56px;\n height: 56px;\n margin: 0 auto 16px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n}\n\n.no-index-warning-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-status-warning);\n}\n\n.no-index-warning-title[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.no-index-warning-message[_ngcontent-%COMP%] {\n margin: 0 0 24px 0;\n font-size: 14px;\n line-height: 1.5;\n color: var(--mj-text-secondary);\n}\n\n.no-index-warning-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n justify-content: center;\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}"] });
|
|
2779
|
+
} }, dependencies: [i1.NgTemplateOutlet, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.LoadingComponent, i5.KPICardComponent, i6.MJPageHeaderComponent, i6.MJPageLayoutComponent, i6.MJPageBodyComponent, i6.MJViewToggleComponent, i6.MJEmptyStateComponent, i6.MJAlertComponent, i1.DecimalPipe], styles: ["\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.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.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.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.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.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.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.document-type[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n white-space: nowrap;\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.actions-cell[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n align-items: center;\n justify-content: center;\n}\n\n.schedule-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.schedule-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\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\n.schedule-dialog[_ngcontent-%COMP%] {\n width: 440px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);\n overflow: hidden;\n}\n\n.schedule-cron-preview[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 0 0;\n font-size: 0.82rem;\n color: var(--mj-text-muted);\n}\n\n.schedule-toggle-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\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.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.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.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.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.health-reason[_ngcontent-%COMP%] {\n font-size: 11px;\n line-height: 1.4;\n color: var(--mj-text-muted);\n padding-left: 18px;\n margin-top: 4px;\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.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.panel-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\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.slide-panel-overlay[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 100000;\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.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.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.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-item-focused[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: -2px;\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.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\n.suggest-submit-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\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.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.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.save-spinner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px 0;\n}\n\n\n.edit-template-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.edit-regenerate-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.edit-regenerate-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.edit-regenerate-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n.no-index-warning-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 440px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 20px 60px color-mix(in srgb, var(--mj-text-primary) 20%, transparent);\n padding: 32px;\n text-align: center;\n}\n\n.no-index-warning-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 56px;\n height: 56px;\n margin: 0 auto 16px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n}\n\n.no-index-warning-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-status-warning);\n}\n\n.no-index-warning-title[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.no-index-warning-message[_ngcontent-%COMP%] {\n margin: 0 0 24px 0;\n font-size: 14px;\n line-height: 1.5;\n color: var(--mj-text-secondary);\n}\n\n.no-index-warning-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n justify-content: center;\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}"] });
|
|
2505
2780
|
};
|
|
2506
|
-
VectorManagementResourceComponent = __decorate([
|
|
2781
|
+
VectorManagementResourceComponent = VectorManagementResourceComponent_1 = __decorate([
|
|
2507
2782
|
RegisterClass(BaseResourceComponent, 'VectorManagementResource')
|
|
2508
2783
|
], VectorManagementResourceComponent);
|
|
2509
2784
|
export { VectorManagementResourceComponent };
|
|
2510
2785
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(VectorManagementResourceComponent, [{
|
|
2511
2786
|
type: Component,
|
|
2512
|
-
args: [{ standalone: false, selector: 'app-vector-management-resource', template: "@if (!HideToolbar) {\n <mj-page-layout>\n <mj-page-header\n Title=\"Vector Management\"\n Icon=\"fa-solid fa-cubes\"\n Subtitle=\"Vector index health, embeddings, and entity sync status\">\n <div actions>\n <mj-view-toggle\n [Options]=\"VectorViewOptions\"\n [ActiveKey]=\"ViewMode\"\n (KeyChange)=\"ViewMode = $any($event)\">\n </mj-view-toggle>\n </div>\n </mj-page-header>\n <mj-page-body [Flex]=\"true\">\n <ng-container *ngTemplateOutlet=\"vectorBody\"></ng-container>\n </mj-page-body>\n </mj-page-layout>\n}\n@if (HideToolbar) {\n <ng-container *ngTemplateOutlet=\"vectorBody\"></ng-container>\n}\n\n<ng-template #vectorBody>\n@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\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(true)\" 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 <mj-empty-state Icon=\"fa-solid fa-folder-open\"\n Title=\"No entity documents configured for vectorization.\" />\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]=\"IsSyncing(row.EntityDocumentID)\"\n (click)=\"SyncEntity(row.EntityDocumentID)\"\n title=\"Sync now\">\n @if (IsSyncing(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=\"schedule-btn\"\n (click)=\"OpenScheduleSyncDialog(row.EntityDocumentID)\"\n title=\"Schedule recurring sync\">\n <i class=\"fa-regular fa-clock\"></i>\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\" [title]=\"VectorDBStatusReason\">{{ VectorDBStatus }}</div>\n @if (VectorDBStatusReason) {\n <div class=\"health-reason\">{{ VectorDBStatusReason }}</div>\n }\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\" [title]=\"'Embeddings are generated by this model; the index above stores the resulting vectors.'\">{{ 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\n <!-- Template Section -->\n <div class=\"suggest-field\">\n <div class=\"edit-template-header\">\n <label class=\"suggest-label\">Template</label>\n <button class=\"edit-regenerate-btn\"\n [disabled]=\"IsEditRegenerating\"\n (click)=\"RegenerateTemplate()\"\n title=\"Regenerate template using AI\">\n @if (IsEditRegenerating) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Regenerating...\n } @else {\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i> Regenerate with AI\n }\n </button>\n </div>\n <div class=\"template-editor-wrapper\">\n <mj-code-editor\n [value]=\"EditDocTemplate\"\n language=\"markdown\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"OnEditTemplateChange($event)\">\n </mj-code-editor>\n </div>\n </div>\n\n <!-- Selected Fields (parsed from template) -->\n @if (EditDocSelectedFields.length > 0) {\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Selected Fields</label>\n <div class=\"result-tags\">\n @for (field of EditDocSelectedFields; track field) {\n <span class=\"result-tag\">{{ field }}</span>\n }\n </div>\n </div>\n }\n\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 <!-- Schedule Sync Dialog -->\n @if (ShowScheduleSyncDialog) {\n <div class=\"slide-panel-overlay\" (click)=\"CloseScheduleSyncDialog()\">\n <div class=\"schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"suggest-dialog-header\">\n <h3 class=\"suggest-dialog-title\">\n <i class=\"fa-regular fa-clock\"></i>\n Schedule Vector Sync\n </h3>\n <button class=\"suggest-close-btn\" (click)=\"CloseScheduleSyncDialog()\">\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 Document</label>\n <span class=\"edit-readonly-value\">{{ ScheduleSyncDocName }}</span>\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Action</label>\n <span class=\"edit-readonly-value\">__VectorizeEntity</span>\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Cron Expression</label>\n <input class=\"suggest-input\" type=\"text\" [(ngModel)]=\"ScheduleSyncCron\" placeholder=\"0 2 * * *\" />\n <div class=\"schedule-cron-preview\">\n <i class=\"fa-solid fa-info-circle\"></i>\n {{ GetScheduleCronPreview(ScheduleSyncCron) }}\n </div>\n </div>\n <div class=\"suggest-field schedule-toggle-row\">\n <label class=\"suggest-label\">Enabled</label>\n <input type=\"checkbox\" class=\"mj-checkbox\" [(ngModel)]=\"ScheduleSyncEnabled\" />\n </div>\n <div class=\"result-actions\" style=\"margin-top: 1rem\">\n @if (ScheduleSyncSaving) {\n <mj-loading text=\"Saving...\" size=\"small\"></mj-loading>\n } @else {\n <button class=\"suggest-submit-btn\" (click)=\"SaveScheduleSync()\">\n <i class=\"fa-solid fa-check\"></i> Create Schedule\n </button>\n <button class=\"suggest-close-action\" (click)=\"CloseScheduleSyncDialog()\">\n Cancel\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- No Vector Index Warning Dialog -->\n @if (ShowNoIndexWarning) {\n <div class=\"slide-panel-overlay\" (click)=\"CloseNoIndexWarning()\">\n <div class=\"no-index-warning-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"no-index-warning-icon\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n </div>\n <h3 class=\"no-index-warning-title\">Vector Index Required</h3>\n <p class=\"no-index-warning-message\">\n You need to create at least one vector database and index before creating entity documents.\n Go to the Configuration section to set up a vector database and create an index.\n </p>\n <div class=\"no-index-warning-actions\">\n <button class=\"suggest-submit-btn\" (click)=\"GoToConfiguration()\">\n <i class=\"fa-solid fa-gear\"></i> Go to Configuration\n </button>\n <button class=\"suggest-close-action\" (click)=\"CloseNoIndexWarning()\">\n Close\n </button>\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\" (mousedown)=\"$event.stopPropagation()\">\n <div class=\"entity-picker-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input #entitySearchInput\n type=\"text\"\n class=\"entity-picker-search-input\"\n placeholder=\"Filter entities...\"\n [(ngModel)]=\"EntitySearchText\"\n (input)=\"FilterEntities()\"\n (keydown)=\"OnEntityPickerKeyDown($event)\" />\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 [class.entity-picker-item-focused]=\"FlatFilteredEntities[SelectedEntityIndex]?.ID === entity.ID\"\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 <mj-alert Variant=\"error\" Size=\"sm\">{{ SuggestionError }}</mj-alert>\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) > 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</ng-template>\n", styles: ["/* ================================================================\n Vector Management Dashboard\n All colors use MJ design tokens from _tokens.scss\n ================================================================ */\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/* --- 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.schedule-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.schedule-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\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/* --- Schedule Dialog --- */\n.schedule-dialog {\n width: 440px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);\n overflow: hidden;\n}\n\n.schedule-cron-preview {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 0 0;\n font-size: 0.82rem;\n color: var(--mj-text-muted);\n}\n\n.schedule-toggle-row {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\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.health-reason {\n font-size: 11px;\n line-height: 1.4;\n color: var(--mj-text-muted);\n padding-left: 18px;\n margin-top: 4px;\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: 100000;\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-item-focused {\n background: var(--mj-bg-surface-hover);\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: -2px;\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\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/* --- Edit Panel Template Header --- */\n.edit-template-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.edit-regenerate-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.edit-regenerate-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.edit-regenerate-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* --- No Vector Index Warning Dialog --- */\n.no-index-warning-dialog {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 440px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 20px 60px color-mix(in srgb, var(--mj-text-primary) 20%, transparent);\n padding: 32px;\n text-align: center;\n}\n\n.no-index-warning-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 56px;\n height: 56px;\n margin: 0 auto 16px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n}\n\n.no-index-warning-icon i {\n font-size: 24px;\n color: var(--mj-status-warning);\n}\n\n.no-index-warning-title {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.no-index-warning-message {\n margin: 0 0 24px 0;\n font-size: 14px;\n line-height: 1.5;\n color: var(--mj-text-secondary);\n}\n\n.no-index-warning-actions {\n display: flex;\n gap: 8px;\n justify-content: center;\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"] }]
|
|
2787
|
+
args: [{ standalone: false, selector: 'app-vector-management-resource', template: "@if (!HideToolbar) {\n <mj-page-layout>\n <mj-page-header\n Title=\"Vector Management\"\n Icon=\"fa-solid fa-cubes\"\n Subtitle=\"Vector index health, embeddings, and entity sync status\">\n <div actions>\n <mj-view-toggle\n [Options]=\"VectorViewOptions\"\n [ActiveKey]=\"ViewMode\"\n (KeyChange)=\"ViewMode = $any($event)\">\n </mj-view-toggle>\n </div>\n </mj-page-header>\n <mj-page-body [Flex]=\"true\">\n <ng-container *ngTemplateOutlet=\"vectorBody\"></ng-container>\n </mj-page-body>\n </mj-page-layout>\n}\n@if (HideToolbar) {\n <ng-container *ngTemplateOutlet=\"vectorBody\"></ng-container>\n}\n\n<ng-template #vectorBody>\n@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\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(true)\" 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 <mj-empty-state Icon=\"fa-solid fa-folder-open\"\n Title=\"No entity documents configured for vectorization.\" />\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>Type</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=\"document-type\">{{ row.DocumentType }}</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]=\"IsSyncing(row.EntityDocumentID)\"\n (click)=\"SyncEntity(row.EntityDocumentID)\"\n title=\"Sync now\">\n @if (IsSyncing(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=\"schedule-btn\"\n (click)=\"OpenScheduleSyncDialog(row.EntityDocumentID)\"\n title=\"Schedule recurring sync\">\n <i class=\"fa-regular fa-clock\"></i>\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\" [title]=\"VectorDBStatusReason\">{{ VectorDBStatus }}</div>\n @if (VectorDBStatusReason) {\n <div class=\"health-reason\">{{ VectorDBStatusReason }}</div>\n }\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\" [title]=\"'Embeddings are generated by this model; the index above stores the resulting vectors.'\">{{ 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\">Type</label>\n <span class=\"edit-readonly-value\">{{ EditDocType }}</span>\n </div>\n\n <!-- Template Section -->\n <div class=\"suggest-field\">\n <div class=\"edit-template-header\">\n <label class=\"suggest-label\">Template</label>\n <button class=\"edit-regenerate-btn\"\n [disabled]=\"IsEditRegenerating\"\n (click)=\"RegenerateTemplate()\"\n title=\"Regenerate template using AI\">\n @if (IsEditRegenerating) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Regenerating...\n } @else {\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i> Regenerate with AI\n }\n </button>\n </div>\n <div class=\"template-editor-wrapper\">\n <mj-code-editor\n [value]=\"EditDocTemplate\"\n language=\"markdown\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"OnEditTemplateChange($event)\">\n </mj-code-editor>\n </div>\n </div>\n\n <!-- Selected Fields (parsed from template) -->\n @if (EditDocSelectedFields.length > 0) {\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Selected Fields</label>\n <div class=\"result-tags\">\n @for (field of EditDocSelectedFields; track field) {\n <span class=\"result-tag\">{{ field }}</span>\n }\n </div>\n </div>\n }\n\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\" (ngModelChange)=\"OnEditEmbeddingModelChange($event)\">\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\" (ngModelChange)=\"OnEditVectorDBChange($event)\">\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\" (ngModelChange)=\"OnEditVectorIndexChange($event)\">\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 <!-- Schedule Sync Dialog -->\n @if (ShowScheduleSyncDialog) {\n <div class=\"slide-panel-overlay\" (click)=\"CloseScheduleSyncDialog()\">\n <div class=\"schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"suggest-dialog-header\">\n <h3 class=\"suggest-dialog-title\">\n <i class=\"fa-regular fa-clock\"></i>\n Schedule Vector Sync\n </h3>\n <button class=\"suggest-close-btn\" (click)=\"CloseScheduleSyncDialog()\">\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 Document</label>\n <span class=\"edit-readonly-value\">{{ ScheduleSyncDocName }}</span>\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Action</label>\n <span class=\"edit-readonly-value\">__VectorizeEntity</span>\n </div>\n <div class=\"suggest-field\">\n <label class=\"suggest-label\">Cron Expression</label>\n <input class=\"suggest-input\" type=\"text\" [(ngModel)]=\"ScheduleSyncCron\" placeholder=\"0 2 * * *\" />\n <div class=\"schedule-cron-preview\">\n <i class=\"fa-solid fa-info-circle\"></i>\n {{ GetScheduleCronPreview(ScheduleSyncCron) }}\n </div>\n </div>\n <div class=\"suggest-field schedule-toggle-row\">\n <label class=\"suggest-label\">Enabled</label>\n <input type=\"checkbox\" class=\"mj-checkbox\" [(ngModel)]=\"ScheduleSyncEnabled\" />\n </div>\n <div class=\"result-actions\" style=\"margin-top: 1rem\">\n @if (ScheduleSyncSaving) {\n <mj-loading text=\"Saving...\" size=\"small\"></mj-loading>\n } @else {\n <button class=\"suggest-submit-btn\" (click)=\"SaveScheduleSync()\">\n <i class=\"fa-solid fa-check\"></i> Create Schedule\n </button>\n <button class=\"suggest-close-action\" (click)=\"CloseScheduleSyncDialog()\">\n Cancel\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- No Vector Index Warning Dialog -->\n @if (ShowNoIndexWarning) {\n <div class=\"slide-panel-overlay\" (click)=\"CloseNoIndexWarning()\">\n <div class=\"no-index-warning-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"no-index-warning-icon\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n </div>\n <h3 class=\"no-index-warning-title\">Vector Index Required</h3>\n <p class=\"no-index-warning-message\">\n You need to create at least one vector database and index before creating entity documents.\n Go to the Configuration section to set up a vector database and create an index.\n </p>\n <div class=\"no-index-warning-actions\">\n <button class=\"suggest-submit-btn\" (click)=\"GoToConfiguration()\">\n <i class=\"fa-solid fa-gear\"></i> Go to Configuration\n </button>\n <button class=\"suggest-close-action\" (click)=\"CloseNoIndexWarning()\">\n Close\n </button>\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\" (mousedown)=\"$event.stopPropagation()\">\n <div class=\"entity-picker-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input #entitySearchInput\n type=\"text\"\n class=\"entity-picker-search-input\"\n placeholder=\"Filter entities...\"\n [(ngModel)]=\"EntitySearchText\"\n (input)=\"FilterEntities()\"\n (keydown)=\"OnEntityPickerKeyDown($event)\" />\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 [class.entity-picker-item-focused]=\"FlatFilteredEntities[SelectedEntityIndex]?.ID === entity.ID\"\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 </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 <mj-alert Variant=\"error\" Size=\"sm\">{{ SuggestionError }}</mj-alert>\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) > 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\" (ngModelChange)=\"OnSuggestEmbeddingModelChange($event)\">\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\" (ngModelChange)=\"OnSuggestVectorDBChange($event)\">\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\" (ngModelChange)=\"OnSuggestVectorIndexChange($event)\">\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</ng-template>\n", styles: ["/* ================================================================\n Vector Management Dashboard\n All colors use MJ design tokens from _tokens.scss\n ================================================================ */\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/* --- 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.document-type {\n color: var(--mj-text-secondary);\n white-space: nowrap;\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.schedule-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.schedule-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\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/* --- Schedule Dialog --- */\n.schedule-dialog {\n width: 440px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);\n overflow: hidden;\n}\n\n.schedule-cron-preview {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 0 0;\n font-size: 0.82rem;\n color: var(--mj-text-muted);\n}\n\n.schedule-toggle-row {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\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.health-reason {\n font-size: 11px;\n line-height: 1.4;\n color: var(--mj-text-muted);\n padding-left: 18px;\n margin-top: 4px;\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: 100000;\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-item-focused {\n background: var(--mj-bg-surface-hover);\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: -2px;\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\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/* --- Edit Panel Template Header --- */\n.edit-template-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.edit-regenerate-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.edit-regenerate-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.edit-regenerate-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* --- No Vector Index Warning Dialog --- */\n.no-index-warning-dialog {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 440px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: 0 20px 60px color-mix(in srgb, var(--mj-text-primary) 20%, transparent);\n padding: 32px;\n text-align: center;\n}\n\n.no-index-warning-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 56px;\n height: 56px;\n margin: 0 auto 16px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n}\n\n.no-index-warning-icon i {\n font-size: 24px;\n color: var(--mj-status-warning);\n}\n\n.no-index-warning-title {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.no-index-warning-message {\n margin: 0 0 24px 0;\n font-size: 14px;\n line-height: 1.5;\n color: var(--mj-text-secondary);\n}\n\n.no-index-warning-actions {\n display: flex;\n gap: 8px;\n justify-content: center;\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"] }]
|
|
2513
2788
|
}], null, { HideToolbar: [{
|
|
2514
2789
|
type: Input
|
|
2515
2790
|
}], EntitySearchInput: [{
|
|
2516
2791
|
type: ViewChild,
|
|
2517
2792
|
args: ['entitySearchInput']
|
|
2518
2793
|
}] }); })();
|
|
2519
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(VectorManagementResourceComponent, { className: "VectorManagementResourceComponent", filePath: "src/AI/components/vectors/vector-management-resource.component.ts", lineNumber:
|
|
2794
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(VectorManagementResourceComponent, { className: "VectorManagementResourceComponent", filePath: "src/AI/components/vectors/vector-management-resource.component.ts", lineNumber: 102 }); })();
|
|
2520
2795
|
export function LoadVectorManagementResource() {
|
|
2521
2796
|
// Prevents tree-shaking
|
|
2522
2797
|
}
|