@memberjunction/ng-dashboards 5.38.0 → 5.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -7
- package/dist/AI/components/agents/agent-configuration.component.js +199 -198
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.js +20 -17
- package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
- package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +89 -856
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1353 -7841
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +235 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +1735 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts +43 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.format.js +209 -0
- package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts +276 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
- package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +40 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.js +402 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +122 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +752 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +166 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1384 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +70 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js +448 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +47 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.js +220 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +293 -289
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +209 -208
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +130 -128
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
- package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +17 -17
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +550 -532
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js +14 -2
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/AI/services/cache-metrics.d.ts +50 -0
- package/dist/AI/services/cache-metrics.d.ts.map +1 -0
- package/dist/AI/services/cache-metrics.js +43 -0
- package/dist/AI/services/cache-metrics.js.map +1 -0
- package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
- package/dist/APIKeys/api-keys-resource.component.js +132 -131
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +141 -141
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +15 -15
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
- package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Admin/admin-data-schema.component.js +2 -2
- package/dist/Admin/admin-data-schema.component.js.map +1 -1
- package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
- package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
- package/dist/Admin/admin-identity-access.component.js +2 -2
- package/dist/Admin/admin-identity-access.component.js.map +1 -1
- package/dist/Admin/admin-monitoring.component.js +2 -2
- package/dist/Admin/admin-monitoring.component.js.map +1 -1
- package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
- package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
- package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +72 -50
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +103 -102
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +52 -51
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +39 -38
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
- package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +92 -89
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +2 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
- package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
- package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
- package/dist/DevTools/app-state-inspector.component.js +18 -17
- package/dist/DevTools/app-state-inspector.component.js.map +1 -1
- package/dist/DevTools/class-registry.component.js +88 -85
- package/dist/DevTools/class-registry.component.js.map +1 -1
- package/dist/DevTools/event-monitor.component.js +155 -150
- package/dist/DevTools/event-monitor.component.js.map +1 -1
- package/dist/DevTools/graphql-console.component.js +245 -243
- package/dist/DevTools/graphql-console.component.js.map +1 -1
- package/dist/DevTools/layout-inspector.component.js +18 -17
- package/dist/DevTools/layout-inspector.component.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +2 -2
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +236 -229
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +390 -389
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +2 -2
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +2 -2
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +45 -44
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts +6 -2
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +525 -566
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +135 -134
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +443 -438
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
- package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +436 -427
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.js +1 -1
- package/dist/Testing/components/testing-runs.component.js +116 -115
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +6 -7
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +173 -172
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
- package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +116 -92
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +47 -35
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +40 -1
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +1 -1
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +7 -1
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +4 -5
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +7 -5
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +55 -54
|
@@ -0,0 +1,3490 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Classify · Taxonomy Governance tab.
|
|
3
|
+
*
|
|
4
|
+
* Self-contained sub-page: owns its header-interior (sub-tab nav + Refresh),
|
|
5
|
+
* the five governance sub-tabs (Tree, Duplicates, Orphans, Treemap, Audit), and
|
|
6
|
+
* the five governance dialogs (Split, Move, Merge-Into, Create-Tag, Confirm).
|
|
7
|
+
*
|
|
8
|
+
* Loads its own taxonomy data (Tags, Tagged Items, Tag Audit Logs, and per-tag
|
|
9
|
+
* SQL aggregates) via `RunView.FromMetadataProvider(this.ProviderToUse)` /
|
|
10
|
+
* `RunQuery`, exactly as the host did. Receives the already-loaded shared
|
|
11
|
+
* `MJ: Content Item Tags` rows from the host via `[ContentTags]` (used for
|
|
12
|
+
* per-tag counts + recent-item previews). After a governance mutation it
|
|
13
|
+
* reloads its own data and emits `(DataChanged)` so the host can react if needed.
|
|
14
|
+
*/
|
|
15
|
+
import { Component, ChangeDetectorRef, EventEmitter, Input, Output, inject } from '@angular/core';
|
|
16
|
+
import { CompositeKey, RunQuery, RunView } from '@memberjunction/core';
|
|
17
|
+
import { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';
|
|
18
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
19
|
+
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
20
|
+
import { formatShortDate, formatDate } from '../shared/classify.format';
|
|
21
|
+
import * as i0 from "@angular/core";
|
|
22
|
+
import * as i1 from "@angular/forms";
|
|
23
|
+
import * as i2 from "@memberjunction/ng-shared-generic";
|
|
24
|
+
import * as i3 from "@memberjunction/ng-ui-components";
|
|
25
|
+
const _forTrack0 = ($index, $item) => $item.ID;
|
|
26
|
+
const _forTrack1 = ($index, $item) => $item.Label;
|
|
27
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
28
|
+
i0.ɵɵelementStart(0, "div", 20);
|
|
29
|
+
i0.ɵɵelement(1, "i", 39);
|
|
30
|
+
i0.ɵɵelementStart(2, "p");
|
|
31
|
+
i0.ɵɵtext(3, "No tags found");
|
|
32
|
+
i0.ɵɵelementEnd()();
|
|
33
|
+
} }
|
|
34
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
35
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
36
|
+
i0.ɵɵelementStart(0, "input", 47);
|
|
37
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Conditional_1_Template_input_click_0_listener($event) { i0.ɵɵrestoreView(_r5); const node_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleNodeSelection(node_r4, $event)); });
|
|
38
|
+
i0.ɵɵelementEnd();
|
|
39
|
+
} if (rf & 2) {
|
|
40
|
+
const node_r4 = i0.ɵɵnextContext().$implicit;
|
|
41
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
42
|
+
i0.ɵɵproperty("checked", ctx_r1.IsNodeMultiSelected(node_r4.ID));
|
|
43
|
+
} }
|
|
44
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template(rf, ctx) { if (rf & 1) {
|
|
45
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
46
|
+
i0.ɵɵelementStart(0, "div", 40);
|
|
47
|
+
i0.ɵɵlistener("dragstart", function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template_div_dragstart_0_listener($event) { const node_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTreeNodeDragStart($event, node_r4)); })("dragover", function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template_div_dragover_0_listener($event) { const node_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTreeNodeDragOver($event, node_r4)); })("dragleave", function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template_div_dragleave_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTreeNodeDragLeave()); })("drop", function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template_div_drop_0_listener($event) { const node_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); ctx_r1.OnTreeNodeDrop($event, node_r4); return i0.ɵɵresetView($event.stopPropagation()); })("click", function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template_div_click_0_listener() { const node_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SelectTaxNode(node_r4)); });
|
|
48
|
+
i0.ɵɵconditionalCreate(1, ClassifyTaxonomyTabComponent_Conditional_11_For_11_Conditional_1_Template, 1, 1, "input", 41);
|
|
49
|
+
i0.ɵɵelementStart(2, "span", 42);
|
|
50
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template_span_click_2_listener($event) { const node_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); ctx_r1.ToggleTaxNode(node_r4); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
51
|
+
i0.ɵɵelementEnd();
|
|
52
|
+
i0.ɵɵelement(3, "span", 43);
|
|
53
|
+
i0.ɵɵelementStart(4, "span", 44);
|
|
54
|
+
i0.ɵɵtext(5);
|
|
55
|
+
i0.ɵɵelementEnd();
|
|
56
|
+
i0.ɵɵelementStart(6, "span", 45);
|
|
57
|
+
i0.ɵɵtext(7);
|
|
58
|
+
i0.ɵɵelementEnd();
|
|
59
|
+
i0.ɵɵelementStart(8, "span", 46);
|
|
60
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template_span_click_8_listener($event) { const node_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); ctx_r1.OpenCreateChildTagFor(node_r4); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
61
|
+
i0.ɵɵelement(9, "i", 16);
|
|
62
|
+
i0.ɵɵelementEnd()();
|
|
63
|
+
} if (rf & 2) {
|
|
64
|
+
const node_r4 = ctx.$implicit;
|
|
65
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
66
|
+
i0.ɵɵstyleProp("padding-left", 16 + node_r4.Depth * 20, "px");
|
|
67
|
+
i0.ɵɵclassProp("at-tax-node-selected", node_r4.IsSelected)("at-tax-node-drag-over", ctx_r1.TaxDragOverNodeID === node_r4.ID)("at-tax-node-multi-selected", ctx_r1.IsNodeMultiSelected(node_r4.ID));
|
|
68
|
+
i0.ɵɵattribute("draggable", true);
|
|
69
|
+
i0.ɵɵadvance();
|
|
70
|
+
i0.ɵɵconditional(ctx_r1.TaxMultiSelectMode ? 1 : -1);
|
|
71
|
+
i0.ɵɵadvance();
|
|
72
|
+
i0.ɵɵclassProp("at-tax-arrow-expanded", node_r4.IsExpanded && node_r4.Children.length > 0)("at-tax-arrow-collapsed", !node_r4.IsExpanded && node_r4.Children.length > 0)("at-tax-arrow-leaf", node_r4.Children.length === 0);
|
|
73
|
+
i0.ɵɵadvance();
|
|
74
|
+
i0.ɵɵclassMap(node_r4.HealthColor);
|
|
75
|
+
i0.ɵɵadvance();
|
|
76
|
+
i0.ɵɵclassProp("at-tax-tree-label-selected", node_r4.IsSelected);
|
|
77
|
+
i0.ɵɵadvance();
|
|
78
|
+
i0.ɵɵtextInterpolate(node_r4.Name);
|
|
79
|
+
i0.ɵɵadvance(2);
|
|
80
|
+
i0.ɵɵtextInterpolate1("(", node_r4.ItemCount, ")");
|
|
81
|
+
} }
|
|
82
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
83
|
+
i0.ɵɵelementStart(0, "div", 22);
|
|
84
|
+
i0.ɵɵelement(1, "mj-loading", 48);
|
|
85
|
+
i0.ɵɵelementEnd();
|
|
86
|
+
} }
|
|
87
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
88
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
89
|
+
i0.ɵɵelementStart(0, "span", 61);
|
|
90
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_For_3_Template_span_click_0_listener() { const bc_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.NavigateToBreadcrumb(bc_r8.ID)); });
|
|
91
|
+
i0.ɵɵtext(1);
|
|
92
|
+
i0.ɵɵelementEnd();
|
|
93
|
+
i0.ɵɵelementStart(2, "span", 62);
|
|
94
|
+
i0.ɵɵtext(3, "\u203A");
|
|
95
|
+
i0.ɵɵelementEnd();
|
|
96
|
+
} if (rf & 2) {
|
|
97
|
+
const bc_r8 = ctx.$implicit;
|
|
98
|
+
i0.ɵɵadvance();
|
|
99
|
+
i0.ɵɵtextInterpolate(bc_r8.Name);
|
|
100
|
+
} }
|
|
101
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_6_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
102
|
+
i0.ɵɵelementStart(0, "div", 66);
|
|
103
|
+
i0.ɵɵtext(1);
|
|
104
|
+
i0.ɵɵelementEnd();
|
|
105
|
+
} if (rf & 2) {
|
|
106
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
107
|
+
i0.ɵɵadvance();
|
|
108
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxSelectedNode.Description);
|
|
109
|
+
} }
|
|
110
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
111
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
112
|
+
i0.ɵɵelementStart(0, "div", 63);
|
|
113
|
+
i0.ɵɵtext(1);
|
|
114
|
+
i0.ɵɵelementStart(2, "span", 64);
|
|
115
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_6_Template_span_click_2_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.StartEditTag()); });
|
|
116
|
+
i0.ɵɵelement(3, "i", 65);
|
|
117
|
+
i0.ɵɵelementEnd()();
|
|
118
|
+
i0.ɵɵconditionalCreate(4, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_6_Conditional_4_Template, 2, 1, "div", 66);
|
|
119
|
+
} if (rf & 2) {
|
|
120
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
121
|
+
i0.ɵɵadvance();
|
|
122
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.TaxSelectedNode.DisplayName, " ");
|
|
123
|
+
i0.ɵɵadvance(3);
|
|
124
|
+
i0.ɵɵconditional(ctx_r1.TaxSelectedNode.Description ? 4 : -1);
|
|
125
|
+
} }
|
|
126
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
127
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
128
|
+
i0.ɵɵelementStart(0, "div", 52)(1, "div", 67)(2, "label", 68);
|
|
129
|
+
i0.ɵɵtext(3, "Name");
|
|
130
|
+
i0.ɵɵelementEnd();
|
|
131
|
+
i0.ɵɵelementStart(4, "input", 69);
|
|
132
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_7_Template_input_ngModelChange_4_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.TaxEditName, $event) || (ctx_r1.TaxEditName = $event); return i0.ɵɵresetView($event); });
|
|
133
|
+
i0.ɵɵelementEnd()();
|
|
134
|
+
i0.ɵɵelementStart(5, "div", 67)(6, "label", 68);
|
|
135
|
+
i0.ɵɵtext(7, "Description");
|
|
136
|
+
i0.ɵɵelementEnd();
|
|
137
|
+
i0.ɵɵelementStart(8, "textarea", 70);
|
|
138
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_7_Template_textarea_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.TaxEditDescription, $event) || (ctx_r1.TaxEditDescription = $event); return i0.ɵɵresetView($event); });
|
|
139
|
+
i0.ɵɵelementEnd()();
|
|
140
|
+
i0.ɵɵelementStart(9, "div", 71)(10, "button", 72);
|
|
141
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_7_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SaveEditTag()); });
|
|
142
|
+
i0.ɵɵtext(11, "Save");
|
|
143
|
+
i0.ɵɵelementEnd();
|
|
144
|
+
i0.ɵɵelementStart(12, "button", 73);
|
|
145
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_7_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.CancelEditTag()); });
|
|
146
|
+
i0.ɵɵtext(13, "Cancel");
|
|
147
|
+
i0.ɵɵelementEnd()()();
|
|
148
|
+
} if (rf & 2) {
|
|
149
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
150
|
+
i0.ɵɵadvance(4);
|
|
151
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.TaxEditName);
|
|
152
|
+
i0.ɵɵadvance(4);
|
|
153
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.TaxEditDescription);
|
|
154
|
+
} }
|
|
155
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
156
|
+
i0.ɵɵelementStart(0, "span", 58);
|
|
157
|
+
i0.ɵɵtext(1);
|
|
158
|
+
i0.ɵɵelementEnd();
|
|
159
|
+
} if (rf & 2) {
|
|
160
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
161
|
+
i0.ɵɵadvance();
|
|
162
|
+
i0.ɵɵtextInterpolate(ctx_r1.Synonyms.length);
|
|
163
|
+
} }
|
|
164
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
165
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
166
|
+
i0.ɵɵelementStart(0, "div", 79)(1, "button", 81);
|
|
167
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_26_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OpenCreateChildTag()); });
|
|
168
|
+
i0.ɵɵelement(2, "i", 16);
|
|
169
|
+
i0.ɵɵtext(3, " Add Child");
|
|
170
|
+
i0.ɵɵelementEnd();
|
|
171
|
+
i0.ɵɵelementStart(4, "button", 81);
|
|
172
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_26_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.StartEditTag()); });
|
|
173
|
+
i0.ɵɵelement(5, "i", 65);
|
|
174
|
+
i0.ɵɵtext(6, " Rename");
|
|
175
|
+
i0.ɵɵelementEnd();
|
|
176
|
+
i0.ɵɵelementStart(7, "button", 81);
|
|
177
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_26_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OpenMoveDialog(ctx_r1.TaxSelectedNode)); });
|
|
178
|
+
i0.ɵɵelement(8, "i", 82);
|
|
179
|
+
i0.ɵɵtext(9, " Move");
|
|
180
|
+
i0.ɵɵelementEnd();
|
|
181
|
+
i0.ɵɵelementStart(10, "button", 81);
|
|
182
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_26_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OpenMergeIntoDialog(ctx_r1.TaxSelectedNode)); });
|
|
183
|
+
i0.ɵɵelement(11, "i", 83);
|
|
184
|
+
i0.ɵɵtext(12, " Merge Into...");
|
|
185
|
+
i0.ɵɵelementEnd();
|
|
186
|
+
i0.ɵɵelementStart(13, "button", 81);
|
|
187
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_26_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OpenSplitDialog(ctx_r1.TaxSelectedNode)); });
|
|
188
|
+
i0.ɵɵelement(14, "i", 84);
|
|
189
|
+
i0.ɵɵtext(15, " Split");
|
|
190
|
+
i0.ɵɵelementEnd();
|
|
191
|
+
i0.ɵɵelementStart(16, "button", 85);
|
|
192
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_26_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.DeleteTag(ctx_r1.TaxSelectedNode)); });
|
|
193
|
+
i0.ɵɵelement(17, "i", 86);
|
|
194
|
+
i0.ɵɵtext(18, " Delete");
|
|
195
|
+
i0.ɵɵelementEnd()();
|
|
196
|
+
} }
|
|
197
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_27_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
198
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
199
|
+
i0.ɵɵelementStart(0, "span", 90);
|
|
200
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_27_For_5_Template_span_click_0_listener() { const child_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.SelectTaxNode(child_r13)); });
|
|
201
|
+
i0.ɵɵtext(1);
|
|
202
|
+
i0.ɵɵelementStart(2, "span", 91);
|
|
203
|
+
i0.ɵɵtext(3);
|
|
204
|
+
i0.ɵɵelementEnd()();
|
|
205
|
+
} if (rf & 2) {
|
|
206
|
+
const child_r13 = ctx.$implicit;
|
|
207
|
+
i0.ɵɵadvance();
|
|
208
|
+
i0.ɵɵtextInterpolate1(" ", child_r13.Name, " ");
|
|
209
|
+
i0.ɵɵadvance(2);
|
|
210
|
+
i0.ɵɵtextInterpolate(child_r13.ItemCount);
|
|
211
|
+
} }
|
|
212
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
213
|
+
i0.ɵɵelementStart(0, "div", 80)(1, "div", 87);
|
|
214
|
+
i0.ɵɵtext(2, "Child Tags");
|
|
215
|
+
i0.ɵɵelementEnd();
|
|
216
|
+
i0.ɵɵelementStart(3, "div", 88);
|
|
217
|
+
i0.ɵɵrepeaterCreate(4, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_27_For_5_Template, 4, 2, "span", 89, _forTrack0);
|
|
218
|
+
i0.ɵɵelementEnd()();
|
|
219
|
+
} if (rf & 2) {
|
|
220
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
221
|
+
i0.ɵɵadvance(4);
|
|
222
|
+
i0.ɵɵrepeater(ctx_r1.TaxSelectedNode.Children);
|
|
223
|
+
} }
|
|
224
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_28_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
225
|
+
i0.ɵɵelementStart(0, "div", 93)(1, "div", 94);
|
|
226
|
+
i0.ɵɵelement(2, "i");
|
|
227
|
+
i0.ɵɵelementEnd();
|
|
228
|
+
i0.ɵɵelementStart(3, "div", 95);
|
|
229
|
+
i0.ɵɵtext(4);
|
|
230
|
+
i0.ɵɵelementEnd();
|
|
231
|
+
i0.ɵɵelementStart(5, "div", 96);
|
|
232
|
+
i0.ɵɵtext(6);
|
|
233
|
+
i0.ɵɵelementEnd();
|
|
234
|
+
i0.ɵɵelementStart(7, "div", 97);
|
|
235
|
+
i0.ɵɵtext(8);
|
|
236
|
+
i0.ɵɵelementEnd()();
|
|
237
|
+
} if (rf & 2) {
|
|
238
|
+
const item_r14 = ctx.$implicit;
|
|
239
|
+
i0.ɵɵadvance(2);
|
|
240
|
+
i0.ɵɵclassMap(item_r14.Icon);
|
|
241
|
+
i0.ɵɵadvance(2);
|
|
242
|
+
i0.ɵɵtextInterpolate(item_r14.Name);
|
|
243
|
+
i0.ɵɵadvance(2);
|
|
244
|
+
i0.ɵɵtextInterpolate(item_r14.Weight.toFixed(2));
|
|
245
|
+
i0.ɵɵadvance(2);
|
|
246
|
+
i0.ɵɵtextInterpolate(item_r14.Date);
|
|
247
|
+
} }
|
|
248
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_28_Template(rf, ctx) { if (rf & 1) {
|
|
249
|
+
i0.ɵɵelementStart(0, "div", 80)(1, "div", 87);
|
|
250
|
+
i0.ɵɵtext(2, "Recently Tagged Items");
|
|
251
|
+
i0.ɵɵelementEnd();
|
|
252
|
+
i0.ɵɵelementStart(3, "div", 92);
|
|
253
|
+
i0.ɵɵrepeaterCreate(4, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_28_For_5_Template, 9, 5, "div", 93, i0.ɵɵrepeaterTrackByIndex);
|
|
254
|
+
i0.ɵɵelementEnd()();
|
|
255
|
+
} if (rf & 2) {
|
|
256
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
257
|
+
i0.ɵɵadvance(4);
|
|
258
|
+
i0.ɵɵrepeater(ctx_r1.TaxRecentItems);
|
|
259
|
+
} }
|
|
260
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
261
|
+
i0.ɵɵelementStart(0, "div", 74)(1, "div", 75)(2, "div", 76);
|
|
262
|
+
i0.ɵɵtext(3);
|
|
263
|
+
i0.ɵɵelementEnd();
|
|
264
|
+
i0.ɵɵelementStart(4, "div", 77);
|
|
265
|
+
i0.ɵɵtext(5, "Items Tagged");
|
|
266
|
+
i0.ɵɵelementEnd()();
|
|
267
|
+
i0.ɵɵelementStart(6, "div", 75)(7, "div", 76);
|
|
268
|
+
i0.ɵɵtext(8);
|
|
269
|
+
i0.ɵɵelementEnd();
|
|
270
|
+
i0.ɵɵelementStart(9, "div", 77);
|
|
271
|
+
i0.ɵɵtext(10, "Avg Weight");
|
|
272
|
+
i0.ɵɵelementEnd()();
|
|
273
|
+
i0.ɵɵelementStart(11, "div", 75)(12, "div", 76);
|
|
274
|
+
i0.ɵɵtext(13);
|
|
275
|
+
i0.ɵɵelementEnd();
|
|
276
|
+
i0.ɵɵelementStart(14, "div", 77);
|
|
277
|
+
i0.ɵɵtext(15, "Children");
|
|
278
|
+
i0.ɵɵelementEnd()();
|
|
279
|
+
i0.ɵɵelementStart(16, "div", 75)(17, "div", 76);
|
|
280
|
+
i0.ɵɵtext(18);
|
|
281
|
+
i0.ɵɵelementEnd();
|
|
282
|
+
i0.ɵɵelementStart(19, "div", 77);
|
|
283
|
+
i0.ɵɵtext(20, "Depth");
|
|
284
|
+
i0.ɵɵelementEnd()();
|
|
285
|
+
i0.ɵɵelementStart(21, "div", 75)(22, "div", 78);
|
|
286
|
+
i0.ɵɵtext(23);
|
|
287
|
+
i0.ɵɵelementEnd();
|
|
288
|
+
i0.ɵɵelementStart(24, "div", 77);
|
|
289
|
+
i0.ɵɵtext(25, "First Seen");
|
|
290
|
+
i0.ɵɵelementEnd()()();
|
|
291
|
+
i0.ɵɵconditionalCreate(26, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_26_Template, 19, 0, "div", 79);
|
|
292
|
+
i0.ɵɵconditionalCreate(27, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_27_Template, 6, 0, "div", 80);
|
|
293
|
+
i0.ɵɵconditionalCreate(28, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Conditional_28_Template, 6, 0, "div", 80);
|
|
294
|
+
} if (rf & 2) {
|
|
295
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
296
|
+
i0.ɵɵadvance(3);
|
|
297
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxSelectedNode.ItemCount);
|
|
298
|
+
i0.ɵɵadvance(5);
|
|
299
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxSelectedNode.AvgWeight.toFixed(2));
|
|
300
|
+
i0.ɵɵadvance(5);
|
|
301
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxSelectedNode.Children.length);
|
|
302
|
+
i0.ɵɵadvance(5);
|
|
303
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxSelectedNode.Depth);
|
|
304
|
+
i0.ɵɵadvance(5);
|
|
305
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxSelectedNode.FirstSeen);
|
|
306
|
+
i0.ɵɵadvance(3);
|
|
307
|
+
i0.ɵɵconditional(!ctx_r1.TaxIsEditing ? 26 : -1);
|
|
308
|
+
i0.ɵɵadvance();
|
|
309
|
+
i0.ɵɵconditional(ctx_r1.TaxSelectedNode.Children.length > 0 ? 27 : -1);
|
|
310
|
+
i0.ɵɵadvance();
|
|
311
|
+
i0.ɵɵconditional(ctx_r1.TaxRecentItems.length > 0 ? 28 : -1);
|
|
312
|
+
} }
|
|
313
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
314
|
+
i0.ɵɵelementStart(0, "div", 98);
|
|
315
|
+
i0.ɵɵelement(1, "i", 99);
|
|
316
|
+
i0.ɵɵtext(2, " Loading governance\u2026");
|
|
317
|
+
i0.ɵɵelementEnd();
|
|
318
|
+
} }
|
|
319
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
320
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
321
|
+
i0.ɵɵelementStart(0, "div", 100)(1, "mj-switch", 101);
|
|
322
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template_mj_switch_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.GovIsFrozen, $event) || (ctx_r1.GovIsFrozen = $event); return i0.ɵɵresetView($event); });
|
|
323
|
+
i0.ɵɵelementEnd();
|
|
324
|
+
i0.ɵɵelementStart(2, "div", 102)(3, "div", 103);
|
|
325
|
+
i0.ɵɵtext(4, "Frozen subtree");
|
|
326
|
+
i0.ɵɵelementEnd();
|
|
327
|
+
i0.ɵɵelementStart(5, "div", 104);
|
|
328
|
+
i0.ɵɵtext(6, "Blocks all auto-grow below this node");
|
|
329
|
+
i0.ɵɵelementEnd()()();
|
|
330
|
+
i0.ɵɵelementStart(7, "div", 100)(8, "mj-switch", 101);
|
|
331
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template_mj_switch_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.GovAllowAutoGrow, $event) || (ctx_r1.GovAllowAutoGrow = $event); return i0.ɵɵresetView($event); });
|
|
332
|
+
i0.ɵɵelementEnd();
|
|
333
|
+
i0.ɵɵelementStart(9, "div", 102)(10, "div", 103);
|
|
334
|
+
i0.ɵɵtext(11, "Allow auto-grow");
|
|
335
|
+
i0.ɵɵelementEnd();
|
|
336
|
+
i0.ɵɵelementStart(12, "div", 104);
|
|
337
|
+
i0.ɵɵtext(13, "Classifier may create children under this node");
|
|
338
|
+
i0.ɵɵelementEnd()()();
|
|
339
|
+
i0.ɵɵelementStart(14, "div", 100)(15, "mj-switch", 101);
|
|
340
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template_mj_switch_ngModelChange_15_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.GovRequiresReview, $event) || (ctx_r1.GovRequiresReview = $event); return i0.ɵɵresetView($event); });
|
|
341
|
+
i0.ɵɵelementEnd();
|
|
342
|
+
i0.ɵɵelementStart(16, "div", 102)(17, "div", 103);
|
|
343
|
+
i0.ɵɵtext(18, "Requires review");
|
|
344
|
+
i0.ɵɵelementEnd();
|
|
345
|
+
i0.ɵɵelementStart(19, "div", 104);
|
|
346
|
+
i0.ɵɵtext(20, "Every classifier hit on this tag routes to review instead of auto-applying");
|
|
347
|
+
i0.ɵɵelementEnd()()();
|
|
348
|
+
i0.ɵɵelementStart(21, "div", 105)(22, "div", 67)(23, "label", 68);
|
|
349
|
+
i0.ɵɵtext(24, "Max children");
|
|
350
|
+
i0.ɵɵelementEnd();
|
|
351
|
+
i0.ɵɵelementStart(25, "input", 106);
|
|
352
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template_input_ngModelChange_25_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.GovMaxChildren, $event) || (ctx_r1.GovMaxChildren = $event); return i0.ɵɵresetView($event); });
|
|
353
|
+
i0.ɵɵelementEnd()();
|
|
354
|
+
i0.ɵɵelementStart(26, "div", 67)(27, "label", 68);
|
|
355
|
+
i0.ɵɵtext(28, "Max depth below");
|
|
356
|
+
i0.ɵɵelementEnd();
|
|
357
|
+
i0.ɵɵelementStart(29, "input", 106);
|
|
358
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template_input_ngModelChange_29_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.GovMaxDescendantDepth, $event) || (ctx_r1.GovMaxDescendantDepth = $event); return i0.ɵɵresetView($event); });
|
|
359
|
+
i0.ɵɵelementEnd()();
|
|
360
|
+
i0.ɵɵelementStart(30, "div", 67)(31, "label", 68);
|
|
361
|
+
i0.ɵɵtext(32, "Min weight (0\u20131)");
|
|
362
|
+
i0.ɵɵelementEnd();
|
|
363
|
+
i0.ɵɵelementStart(33, "input", 107);
|
|
364
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template_input_ngModelChange_33_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.GovMinWeight, $event) || (ctx_r1.GovMinWeight = $event); return i0.ɵɵresetView($event); });
|
|
365
|
+
i0.ɵɵelementEnd()()();
|
|
366
|
+
i0.ɵɵelementStart(34, "div", 108);
|
|
367
|
+
i0.ɵɵelement(35, "i", 55);
|
|
368
|
+
i0.ɵɵelementStart(36, "span")(37, "b");
|
|
369
|
+
i0.ɵɵtext(38, "Subtree impact:");
|
|
370
|
+
i0.ɵɵelementEnd();
|
|
371
|
+
i0.ɵɵtext(39);
|
|
372
|
+
i0.ɵɵelementEnd()();
|
|
373
|
+
i0.ɵɵelementStart(40, "div", 71)(41, "button", 109);
|
|
374
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template_button_click_41_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SaveGovernance()); });
|
|
375
|
+
i0.ɵɵelement(42, "i", 110);
|
|
376
|
+
i0.ɵɵtext(43, " Save governance ");
|
|
377
|
+
i0.ɵɵelementEnd();
|
|
378
|
+
i0.ɵɵelementStart(44, "button", 111);
|
|
379
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template_button_click_44_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.ResetGovernance()); });
|
|
380
|
+
i0.ɵɵtext(45, "Reset");
|
|
381
|
+
i0.ɵɵelementEnd()();
|
|
382
|
+
} if (rf & 2) {
|
|
383
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
384
|
+
i0.ɵɵadvance();
|
|
385
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.GovIsFrozen);
|
|
386
|
+
i0.ɵɵadvance(7);
|
|
387
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.GovAllowAutoGrow);
|
|
388
|
+
i0.ɵɵadvance(7);
|
|
389
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.GovRequiresReview);
|
|
390
|
+
i0.ɵɵadvance(10);
|
|
391
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.GovMaxChildren);
|
|
392
|
+
i0.ɵɵadvance(4);
|
|
393
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.GovMaxDescendantDepth);
|
|
394
|
+
i0.ɵɵadvance(4);
|
|
395
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.GovMinWeight);
|
|
396
|
+
i0.ɵɵadvance(6);
|
|
397
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.GovernanceImpactHint);
|
|
398
|
+
i0.ɵɵadvance(2);
|
|
399
|
+
i0.ɵɵproperty("disabled", ctx_r1.GovernanceSaving);
|
|
400
|
+
i0.ɵɵadvance(3);
|
|
401
|
+
i0.ɵɵproperty("disabled", ctx_r1.GovernanceSaving);
|
|
402
|
+
} }
|
|
403
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
404
|
+
i0.ɵɵelementStart(0, "div", 98);
|
|
405
|
+
i0.ɵɵtext(1, "Unable to load governance for this tag.");
|
|
406
|
+
i0.ɵɵelementEnd();
|
|
407
|
+
} }
|
|
408
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
409
|
+
i0.ɵɵelementStart(0, "div", 60);
|
|
410
|
+
i0.ɵɵconditionalCreate(1, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_1_Template, 3, 0, "div", 98)(2, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_2_Template, 46, 9)(3, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Conditional_3_Template, 2, 0, "div", 98);
|
|
411
|
+
i0.ɵɵelementEnd();
|
|
412
|
+
} if (rf & 2) {
|
|
413
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
414
|
+
i0.ɵɵadvance();
|
|
415
|
+
i0.ɵɵconditional(ctx_r1.GovernanceLoading ? 1 : ctx_r1.GovernanceTag ? 2 : 3);
|
|
416
|
+
} }
|
|
417
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
418
|
+
i0.ɵɵelementStart(0, "div", 98);
|
|
419
|
+
i0.ɵɵelement(1, "i", 99);
|
|
420
|
+
i0.ɵɵtext(2, " Loading synonyms\u2026");
|
|
421
|
+
i0.ɵɵelementEnd();
|
|
422
|
+
} }
|
|
423
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
424
|
+
i0.ɵɵelementStart(0, "div", 112);
|
|
425
|
+
i0.ɵɵelement(1, "i", 117);
|
|
426
|
+
i0.ɵɵtext(2);
|
|
427
|
+
i0.ɵɵelementEnd();
|
|
428
|
+
} if (rf & 2) {
|
|
429
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
430
|
+
i0.ɵɵadvance(2);
|
|
431
|
+
i0.ɵɵtextInterpolate2(" ", ctx_r1.PendingSynonymCount, " proposed ", ctx_r1.PendingSynonymCount === 1 ? "synonym" : "synonyms", " awaiting review \u2014 these don't resolve until approved. ");
|
|
432
|
+
} }
|
|
433
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
434
|
+
const _r17 = i0.ɵɵgetCurrentView();
|
|
435
|
+
i0.ɵɵelementStart(0, "span", 122);
|
|
436
|
+
i0.ɵɵtext(1, "Pending");
|
|
437
|
+
i0.ɵɵelementEnd();
|
|
438
|
+
i0.ɵɵelementStart(2, "button", 123);
|
|
439
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_5_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r17); const syn_r18 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.ApproveSynonym(syn_r18)); });
|
|
440
|
+
i0.ɵɵelement(3, "i", 110);
|
|
441
|
+
i0.ɵɵtext(4, " Approve ");
|
|
442
|
+
i0.ɵɵelementEnd();
|
|
443
|
+
i0.ɵɵelementStart(5, "button", 124);
|
|
444
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_5_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r17); const syn_r18 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.RejectSynonym(syn_r18)); });
|
|
445
|
+
i0.ɵɵelement(6, "i", 125);
|
|
446
|
+
i0.ɵɵtext(7, " Reject ");
|
|
447
|
+
i0.ɵɵelementEnd();
|
|
448
|
+
} if (rf & 2) {
|
|
449
|
+
const ctx_r1 = i0.ɵɵnextContext(7);
|
|
450
|
+
i0.ɵɵadvance(2);
|
|
451
|
+
i0.ɵɵproperty("disabled", ctx_r1.SynonymSaving);
|
|
452
|
+
i0.ɵɵadvance(3);
|
|
453
|
+
i0.ɵɵproperty("disabled", ctx_r1.SynonymSaving);
|
|
454
|
+
} }
|
|
455
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_6_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
456
|
+
i0.ɵɵelementStart(0, "span", 126);
|
|
457
|
+
i0.ɵɵtext(1, "Rejected");
|
|
458
|
+
i0.ɵɵelementEnd();
|
|
459
|
+
} }
|
|
460
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
461
|
+
const _r19 = i0.ɵɵgetCurrentView();
|
|
462
|
+
i0.ɵɵconditionalCreate(0, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_6_Conditional_0_Template, 2, 0, "span", 126);
|
|
463
|
+
i0.ɵɵelementStart(1, "button", 127);
|
|
464
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_6_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r19); const syn_r18 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.DeleteSynonym(syn_r18)); });
|
|
465
|
+
i0.ɵɵelement(2, "i", 128);
|
|
466
|
+
i0.ɵɵelementEnd();
|
|
467
|
+
} if (rf & 2) {
|
|
468
|
+
const syn_r18 = i0.ɵɵnextContext().$implicit;
|
|
469
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
470
|
+
i0.ɵɵconditional(syn_r18.Status === "Rejected" ? 0 : -1);
|
|
471
|
+
i0.ɵɵadvance();
|
|
472
|
+
i0.ɵɵproperty("disabled", ctx_r1.SynonymSaving);
|
|
473
|
+
} }
|
|
474
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
475
|
+
i0.ɵɵelementStart(0, "div", 119)(1, "span", 120);
|
|
476
|
+
i0.ɵɵtext(2);
|
|
477
|
+
i0.ɵɵelementEnd();
|
|
478
|
+
i0.ɵɵelementStart(3, "span", 121);
|
|
479
|
+
i0.ɵɵtext(4);
|
|
480
|
+
i0.ɵɵelementEnd();
|
|
481
|
+
i0.ɵɵconditionalCreate(5, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_5_Template, 8, 2)(6, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Conditional_6_Template, 3, 2);
|
|
482
|
+
i0.ɵɵelementEnd();
|
|
483
|
+
} if (rf & 2) {
|
|
484
|
+
const syn_r18 = ctx.$implicit;
|
|
485
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
486
|
+
i0.ɵɵclassProp("at-syn-item-pending", syn_r18.Status === "Pending");
|
|
487
|
+
i0.ɵɵadvance(2);
|
|
488
|
+
i0.ɵɵtextInterpolate(syn_r18.Synonym);
|
|
489
|
+
i0.ɵɵadvance();
|
|
490
|
+
i0.ɵɵclassMap(ctx_r1.GetSynonymSourceClass(syn_r18.Source));
|
|
491
|
+
i0.ɵɵadvance();
|
|
492
|
+
i0.ɵɵtextInterpolate(syn_r18.Source);
|
|
493
|
+
i0.ɵɵadvance();
|
|
494
|
+
i0.ɵɵconditional(syn_r18.Status === "Pending" ? 5 : 6);
|
|
495
|
+
} }
|
|
496
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
497
|
+
i0.ɵɵelementStart(0, "div", 113);
|
|
498
|
+
i0.ɵɵrepeaterCreate(1, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_For_2_Template, 7, 7, "div", 118, _forTrack0);
|
|
499
|
+
i0.ɵɵelementEnd();
|
|
500
|
+
} if (rf & 2) {
|
|
501
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
502
|
+
i0.ɵɵadvance();
|
|
503
|
+
i0.ɵɵrepeater(ctx_r1.Synonyms);
|
|
504
|
+
} }
|
|
505
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
506
|
+
i0.ɵɵelementStart(0, "div", 114);
|
|
507
|
+
i0.ɵɵtext(1, "No synonyms yet for this tag.");
|
|
508
|
+
i0.ɵɵelementEnd();
|
|
509
|
+
} }
|
|
510
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
511
|
+
const _r16 = i0.ɵɵgetCurrentView();
|
|
512
|
+
i0.ɵɵconditionalCreate(0, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_0_Template, 3, 2, "div", 112);
|
|
513
|
+
i0.ɵɵconditionalCreate(1, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_1_Template, 3, 0, "div", 113)(2, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Conditional_2_Template, 2, 0, "div", 114);
|
|
514
|
+
i0.ɵɵelementStart(3, "div", 115)(4, "input", 116);
|
|
515
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Template_input_ngModelChange_4_listener($event) { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.NewSynonymText, $event) || (ctx_r1.NewSynonymText = $event); return i0.ɵɵresetView($event); });
|
|
516
|
+
i0.ɵɵlistener("keyup.enter", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Template_input_keyup_enter_4_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.AddSynonym()); });
|
|
517
|
+
i0.ɵɵelementEnd();
|
|
518
|
+
i0.ɵɵelementStart(5, "button", 109);
|
|
519
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.AddSynonym()); });
|
|
520
|
+
i0.ɵɵelement(6, "i", 16);
|
|
521
|
+
i0.ɵɵtext(7, " Add ");
|
|
522
|
+
i0.ɵɵelementEnd()();
|
|
523
|
+
} if (rf & 2) {
|
|
524
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
525
|
+
i0.ɵɵconditional(ctx_r1.PendingSynonymCount > 0 ? 0 : -1);
|
|
526
|
+
i0.ɵɵadvance();
|
|
527
|
+
i0.ɵɵconditional(ctx_r1.Synonyms.length > 0 ? 1 : 2);
|
|
528
|
+
i0.ɵɵadvance(3);
|
|
529
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.NewSynonymText);
|
|
530
|
+
i0.ɵɵadvance();
|
|
531
|
+
i0.ɵɵproperty("disabled", ctx_r1.SynonymSaving || !ctx_r1.NewSynonymText.trim());
|
|
532
|
+
} }
|
|
533
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Template(rf, ctx) { if (rf & 1) {
|
|
534
|
+
i0.ɵɵelementStart(0, "div", 60);
|
|
535
|
+
i0.ɵɵconditionalCreate(1, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_1_Template, 3, 0, "div", 98)(2, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Conditional_2_Template, 8, 4);
|
|
536
|
+
i0.ɵɵelementEnd();
|
|
537
|
+
} if (rf & 2) {
|
|
538
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
539
|
+
i0.ɵɵadvance();
|
|
540
|
+
i0.ɵɵconditional(ctx_r1.SynonymsLoading ? 1 : 2);
|
|
541
|
+
} }
|
|
542
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
543
|
+
i0.ɵɵelementStart(0, "div", 98);
|
|
544
|
+
i0.ɵɵelement(1, "i", 99);
|
|
545
|
+
i0.ɵɵtext(2, " Loading scope\u2026");
|
|
546
|
+
i0.ɵɵelementEnd();
|
|
547
|
+
} }
|
|
548
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Conditional_0_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
549
|
+
const _r22 = i0.ɵɵgetCurrentView();
|
|
550
|
+
i0.ɵɵelementStart(0, "div", 135)(1, "span", 136);
|
|
551
|
+
i0.ɵɵtext(2);
|
|
552
|
+
i0.ɵɵelementEnd();
|
|
553
|
+
i0.ɵɵelementStart(3, "span", 137);
|
|
554
|
+
i0.ɵɵtext(4);
|
|
555
|
+
i0.ɵɵelementEnd();
|
|
556
|
+
i0.ɵɵelementStart(5, "button", 138);
|
|
557
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Conditional_0_For_2_Template_button_click_5_listener() { const scope_r23 = i0.ɵɵrestoreView(_r22).$implicit; const ctx_r1 = i0.ɵɵnextContext(7); return i0.ɵɵresetView(ctx_r1.DeleteScope(scope_r23)); });
|
|
558
|
+
i0.ɵɵelement(6, "i", 128);
|
|
559
|
+
i0.ɵɵelementEnd()();
|
|
560
|
+
} if (rf & 2) {
|
|
561
|
+
const scope_r23 = ctx.$implicit;
|
|
562
|
+
const ctx_r1 = i0.ɵɵnextContext(7);
|
|
563
|
+
i0.ɵɵadvance(2);
|
|
564
|
+
i0.ɵɵtextInterpolate(scope_r23.ScopeEntity);
|
|
565
|
+
i0.ɵɵadvance(2);
|
|
566
|
+
i0.ɵɵtextInterpolate(scope_r23.ScopeRecordID);
|
|
567
|
+
i0.ɵɵadvance();
|
|
568
|
+
i0.ɵɵproperty("disabled", ctx_r1.ScopeSaving);
|
|
569
|
+
} }
|
|
570
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
571
|
+
i0.ɵɵelementStart(0, "div", 130);
|
|
572
|
+
i0.ɵɵrepeaterCreate(1, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Conditional_0_For_2_Template, 7, 3, "div", 135, _forTrack0);
|
|
573
|
+
i0.ɵɵelementEnd();
|
|
574
|
+
} if (rf & 2) {
|
|
575
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
576
|
+
i0.ɵɵadvance();
|
|
577
|
+
i0.ɵɵrepeater(ctx_r1.Scopes);
|
|
578
|
+
} }
|
|
579
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
580
|
+
i0.ɵɵelementStart(0, "div", 114);
|
|
581
|
+
i0.ɵɵtext(1, "No scope restrictions \u2014 add one to limit visibility.");
|
|
582
|
+
i0.ɵɵelementEnd();
|
|
583
|
+
} }
|
|
584
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
585
|
+
const _r21 = i0.ɵɵgetCurrentView();
|
|
586
|
+
i0.ɵɵconditionalCreate(0, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Conditional_0_Template, 3, 0, "div", 130)(1, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Conditional_1_Template, 2, 0, "div", 114);
|
|
587
|
+
i0.ɵɵelementStart(2, "div", 131)(3, "mj-combobox", 132);
|
|
588
|
+
i0.ɵɵlistener("ValueChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Template_mj_combobox_ValueChange_3_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.OnScopeEntitySelected($event)); });
|
|
589
|
+
i0.ɵɵelementEnd();
|
|
590
|
+
i0.ɵɵelementStart(4, "input", 133);
|
|
591
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Template_input_ngModelChange_4_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(5); i0.ɵɵtwoWayBindingSet(ctx_r1.NewScopeRecordID, $event) || (ctx_r1.NewScopeRecordID = $event); return i0.ɵɵresetView($event); });
|
|
592
|
+
i0.ɵɵelementEnd();
|
|
593
|
+
i0.ɵɵelementStart(5, "button", 109);
|
|
594
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.AddScope()); });
|
|
595
|
+
i0.ɵɵelement(6, "i", 16);
|
|
596
|
+
i0.ɵɵtext(7, " Add ");
|
|
597
|
+
i0.ɵɵelementEnd()();
|
|
598
|
+
i0.ɵɵelementStart(8, "div", 134);
|
|
599
|
+
i0.ɵɵelement(9, "i", 55);
|
|
600
|
+
i0.ɵɵtext(10, " Children inherit their parent's scope. ");
|
|
601
|
+
i0.ɵɵelementEnd();
|
|
602
|
+
} if (rf & 2) {
|
|
603
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
604
|
+
i0.ɵɵconditional(ctx_r1.Scopes.length > 0 ? 0 : 1);
|
|
605
|
+
i0.ɵɵadvance(3);
|
|
606
|
+
i0.ɵɵproperty("Data", ctx_r1.ScopeEntityOptions)("ValuePrimitive", true)("ngModel", ctx_r1.NewScopeEntityID);
|
|
607
|
+
i0.ɵɵadvance();
|
|
608
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.NewScopeRecordID);
|
|
609
|
+
i0.ɵɵadvance();
|
|
610
|
+
i0.ɵɵproperty("disabled", ctx_r1.ScopeSaving || !ctx_r1.NewScopeEntityID || !ctx_r1.NewScopeRecordID.trim());
|
|
611
|
+
} }
|
|
612
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
613
|
+
const _r20 = i0.ɵɵgetCurrentView();
|
|
614
|
+
i0.ɵɵelementStart(0, "div", 100)(1, "mj-switch", 129);
|
|
615
|
+
i0.ɵɵlistener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Template_mj_switch_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.ToggleTagGlobal($event)); });
|
|
616
|
+
i0.ɵɵelementEnd();
|
|
617
|
+
i0.ɵɵelementStart(2, "div", 102)(3, "div", 103);
|
|
618
|
+
i0.ɵɵtext(4, "Global tag");
|
|
619
|
+
i0.ɵɵelementEnd();
|
|
620
|
+
i0.ɵɵelementStart(5, "div", 104);
|
|
621
|
+
i0.ɵɵtext(6, "Visible to every tenant/scope when on");
|
|
622
|
+
i0.ɵɵelementEnd()()();
|
|
623
|
+
i0.ɵɵconditionalCreate(7, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Conditional_7_Template, 11, 6);
|
|
624
|
+
} if (rf & 2) {
|
|
625
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
626
|
+
i0.ɵɵadvance();
|
|
627
|
+
i0.ɵɵproperty("ngModel", ctx_r1.IsTagGlobal)("Disabled", ctx_r1.ScopeSaving);
|
|
628
|
+
i0.ɵɵadvance(6);
|
|
629
|
+
i0.ɵɵconditional(!ctx_r1.IsTagGlobal ? 7 : -1);
|
|
630
|
+
} }
|
|
631
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
632
|
+
i0.ɵɵelementStart(0, "div", 98);
|
|
633
|
+
i0.ɵɵtext(1, "Unable to load scope for this tag.");
|
|
634
|
+
i0.ɵɵelementEnd();
|
|
635
|
+
} }
|
|
636
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
637
|
+
i0.ɵɵelementStart(0, "div", 60);
|
|
638
|
+
i0.ɵɵconditionalCreate(1, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_1_Template, 3, 0, "div", 98)(2, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_2_Template, 8, 3)(3, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Conditional_3_Template, 2, 0, "div", 98);
|
|
639
|
+
i0.ɵɵelementEnd();
|
|
640
|
+
} if (rf & 2) {
|
|
641
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
642
|
+
i0.ɵɵadvance();
|
|
643
|
+
i0.ɵɵconditional(ctx_r1.ScopesLoading || ctx_r1.GovernanceLoading ? 1 : ctx_r1.GovernanceTag ? 2 : 3);
|
|
644
|
+
} }
|
|
645
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
646
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
647
|
+
i0.ɵɵelementStart(0, "div", 49)(1, "div", 50);
|
|
648
|
+
i0.ɵɵrepeaterCreate(2, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_For_3_Template, 4, 1, null, null, _forTrack0);
|
|
649
|
+
i0.ɵɵelementStart(4, "span", 51);
|
|
650
|
+
i0.ɵɵtext(5);
|
|
651
|
+
i0.ɵɵelementEnd()();
|
|
652
|
+
i0.ɵɵconditionalCreate(6, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_6_Template, 5, 2)(7, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_7_Template, 14, 2, "div", 52);
|
|
653
|
+
i0.ɵɵelementEnd();
|
|
654
|
+
i0.ɵɵelementStart(8, "div", 53)(9, "button", 54);
|
|
655
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SwitchTagEditorSubTab("overview")); });
|
|
656
|
+
i0.ɵɵelement(10, "i", 55);
|
|
657
|
+
i0.ɵɵtext(11, " Overview ");
|
|
658
|
+
i0.ɵɵelementEnd();
|
|
659
|
+
i0.ɵɵelementStart(12, "button", 54);
|
|
660
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SwitchTagEditorSubTab("governance")); });
|
|
661
|
+
i0.ɵɵelement(13, "i", 56);
|
|
662
|
+
i0.ɵɵtext(14, " Governance ");
|
|
663
|
+
i0.ɵɵelementEnd();
|
|
664
|
+
i0.ɵɵelementStart(15, "button", 54);
|
|
665
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SwitchTagEditorSubTab("synonyms")); });
|
|
666
|
+
i0.ɵɵelement(16, "i", 57);
|
|
667
|
+
i0.ɵɵtext(17, " Synonyms ");
|
|
668
|
+
i0.ɵɵconditionalCreate(18, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_18_Template, 2, 1, "span", 58);
|
|
669
|
+
i0.ɵɵelementEnd();
|
|
670
|
+
i0.ɵɵelementStart(19, "button", 54);
|
|
671
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SwitchTagEditorSubTab("scope")); });
|
|
672
|
+
i0.ɵɵelement(20, "i", 59);
|
|
673
|
+
i0.ɵɵtext(21, " Scope ");
|
|
674
|
+
i0.ɵɵelementEnd()();
|
|
675
|
+
i0.ɵɵconditionalCreate(22, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_22_Template, 29, 8);
|
|
676
|
+
i0.ɵɵconditionalCreate(23, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_23_Template, 4, 1, "div", 60);
|
|
677
|
+
i0.ɵɵconditionalCreate(24, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_24_Template, 3, 1, "div", 60);
|
|
678
|
+
i0.ɵɵconditionalCreate(25, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Conditional_25_Template, 4, 1, "div", 60);
|
|
679
|
+
} if (rf & 2) {
|
|
680
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
681
|
+
i0.ɵɵadvance(2);
|
|
682
|
+
i0.ɵɵrepeater(ctx_r1.GetTaxBreadcrumb(ctx_r1.TaxSelectedNode));
|
|
683
|
+
i0.ɵɵadvance(3);
|
|
684
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxSelectedNode.Name);
|
|
685
|
+
i0.ɵɵadvance();
|
|
686
|
+
i0.ɵɵconditional(!ctx_r1.TaxIsEditing ? 6 : 7);
|
|
687
|
+
i0.ɵɵadvance(3);
|
|
688
|
+
i0.ɵɵclassProp("at-tag-editor-subtab-active", ctx_r1.TagEditorSubTab === "overview");
|
|
689
|
+
i0.ɵɵadvance(3);
|
|
690
|
+
i0.ɵɵclassProp("at-tag-editor-subtab-active", ctx_r1.TagEditorSubTab === "governance");
|
|
691
|
+
i0.ɵɵadvance(3);
|
|
692
|
+
i0.ɵɵclassProp("at-tag-editor-subtab-active", ctx_r1.TagEditorSubTab === "synonyms");
|
|
693
|
+
i0.ɵɵadvance(3);
|
|
694
|
+
i0.ɵɵconditional(ctx_r1.Synonyms.length > 0 ? 18 : -1);
|
|
695
|
+
i0.ɵɵadvance();
|
|
696
|
+
i0.ɵɵclassProp("at-tag-editor-subtab-active", ctx_r1.TagEditorSubTab === "scope");
|
|
697
|
+
i0.ɵɵadvance(3);
|
|
698
|
+
i0.ɵɵconditional(ctx_r1.TagEditorSubTab === "overview" ? 22 : -1);
|
|
699
|
+
i0.ɵɵadvance();
|
|
700
|
+
i0.ɵɵconditional(ctx_r1.TagEditorSubTab === "governance" ? 23 : -1);
|
|
701
|
+
i0.ɵɵadvance();
|
|
702
|
+
i0.ɵɵconditional(ctx_r1.TagEditorSubTab === "synonyms" ? 24 : -1);
|
|
703
|
+
i0.ɵɵadvance();
|
|
704
|
+
i0.ɵɵconditional(ctx_r1.TagEditorSubTab === "scope" ? 25 : -1);
|
|
705
|
+
} }
|
|
706
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
707
|
+
i0.ɵɵelementStart(0, "div", 24);
|
|
708
|
+
i0.ɵɵelement(1, "i", 139);
|
|
709
|
+
i0.ɵɵelementStart(2, "p");
|
|
710
|
+
i0.ɵɵtext(3, "Select a tag from the tree to view details");
|
|
711
|
+
i0.ɵɵelementEnd()();
|
|
712
|
+
} }
|
|
713
|
+
function ClassifyTaxonomyTabComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
714
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
715
|
+
i0.ɵɵelementStart(0, "div", 11)(1, "div", 12)(2, "div", 13)(3, "input", 14);
|
|
716
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_11_Template_input_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.TaxTreeSearch, $event) || (ctx_r1.TaxTreeSearch = $event); return i0.ɵɵresetView($event); });
|
|
717
|
+
i0.ɵɵlistener("input", function ClassifyTaxonomyTabComponent_Conditional_11_Template_input_input_3_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.FilterTaxTree()); });
|
|
718
|
+
i0.ɵɵelementEnd();
|
|
719
|
+
i0.ɵɵelementStart(4, "button", 15);
|
|
720
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OpenCreateRootTag()); });
|
|
721
|
+
i0.ɵɵelement(5, "i", 16);
|
|
722
|
+
i0.ɵɵelementEnd();
|
|
723
|
+
i0.ɵɵelementStart(6, "button", 17);
|
|
724
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_11_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleMultiSelectMode()); });
|
|
725
|
+
i0.ɵɵelement(7, "i", 18);
|
|
726
|
+
i0.ɵɵelementEnd()();
|
|
727
|
+
i0.ɵɵelementStart(8, "div", 19);
|
|
728
|
+
i0.ɵɵlistener("dragover", function ClassifyTaxonomyTabComponent_Conditional_11_Template_div_dragover_8_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView($event.preventDefault()); })("drop", function ClassifyTaxonomyTabComponent_Conditional_11_Template_div_drop_8_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnDropToRoot($event)); });
|
|
729
|
+
i0.ɵɵconditionalCreate(9, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_9_Template, 4, 0, "div", 20);
|
|
730
|
+
i0.ɵɵrepeaterCreate(10, ClassifyTaxonomyTabComponent_Conditional_11_For_11_Template, 10, 22, "div", 21, _forTrack0);
|
|
731
|
+
i0.ɵɵelementEnd();
|
|
732
|
+
i0.ɵɵconditionalCreate(12, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_12_Template, 2, 0, "div", 22);
|
|
733
|
+
i0.ɵɵelementEnd();
|
|
734
|
+
i0.ɵɵelementStart(13, "div", 23);
|
|
735
|
+
i0.ɵɵconditionalCreate(14, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_14_Template, 26, 15)(15, ClassifyTaxonomyTabComponent_Conditional_11_Conditional_15_Template, 4, 0, "div", 24);
|
|
736
|
+
i0.ɵɵelementEnd()();
|
|
737
|
+
i0.ɵɵelementStart(16, "div", 25)(17, "span", 26);
|
|
738
|
+
i0.ɵɵtext(18, "Taxonomy Health");
|
|
739
|
+
i0.ɵɵelementEnd();
|
|
740
|
+
i0.ɵɵelementStart(19, "div", 27);
|
|
741
|
+
i0.ɵɵelement(20, "span", 28);
|
|
742
|
+
i0.ɵɵelementStart(21, "span", 29);
|
|
743
|
+
i0.ɵɵtext(22);
|
|
744
|
+
i0.ɵɵelementEnd();
|
|
745
|
+
i0.ɵɵelementStart(23, "span", 30);
|
|
746
|
+
i0.ɵɵtext(24, "Total");
|
|
747
|
+
i0.ɵɵelementEnd()();
|
|
748
|
+
i0.ɵɵelementStart(25, "div", 27);
|
|
749
|
+
i0.ɵɵelement(26, "span", 31);
|
|
750
|
+
i0.ɵɵelementStart(27, "span", 32);
|
|
751
|
+
i0.ɵɵtext(28);
|
|
752
|
+
i0.ɵɵelementEnd();
|
|
753
|
+
i0.ɵɵelementStart(29, "span", 30);
|
|
754
|
+
i0.ɵɵtext(30, "Healthy");
|
|
755
|
+
i0.ɵɵelementEnd()();
|
|
756
|
+
i0.ɵɵelementStart(31, "div", 27);
|
|
757
|
+
i0.ɵɵelement(32, "span", 33);
|
|
758
|
+
i0.ɵɵelementStart(33, "span", 34);
|
|
759
|
+
i0.ɵɵtext(34);
|
|
760
|
+
i0.ɵɵelementEnd();
|
|
761
|
+
i0.ɵɵelementStart(35, "span", 30);
|
|
762
|
+
i0.ɵɵtext(36, "Need Attention");
|
|
763
|
+
i0.ɵɵelementEnd()();
|
|
764
|
+
i0.ɵɵelementStart(37, "div", 27);
|
|
765
|
+
i0.ɵɵelement(38, "span", 35);
|
|
766
|
+
i0.ɵɵelementStart(39, "span", 36);
|
|
767
|
+
i0.ɵɵtext(40);
|
|
768
|
+
i0.ɵɵelementEnd();
|
|
769
|
+
i0.ɵɵelementStart(41, "span", 30);
|
|
770
|
+
i0.ɵɵtext(42, "Orphaned");
|
|
771
|
+
i0.ɵɵelementEnd()();
|
|
772
|
+
i0.ɵɵelementStart(43, "div", 27);
|
|
773
|
+
i0.ɵɵelement(44, "span", 37);
|
|
774
|
+
i0.ɵɵelementStart(45, "span", 38);
|
|
775
|
+
i0.ɵɵtext(46);
|
|
776
|
+
i0.ɵɵelementEnd();
|
|
777
|
+
i0.ɵɵelementStart(47, "span", 30);
|
|
778
|
+
i0.ɵɵtext(48, "Duplicate Candidates");
|
|
779
|
+
i0.ɵɵelementEnd()()();
|
|
780
|
+
} if (rf & 2) {
|
|
781
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
782
|
+
i0.ɵɵadvance(3);
|
|
783
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.TaxTreeSearch);
|
|
784
|
+
i0.ɵɵadvance(3);
|
|
785
|
+
i0.ɵɵclassProp("active", ctx_r1.TaxMultiSelectMode);
|
|
786
|
+
i0.ɵɵadvance(3);
|
|
787
|
+
i0.ɵɵconditional(ctx_r1.TaxFilteredNodes.length === 0 ? 9 : -1);
|
|
788
|
+
i0.ɵɵadvance();
|
|
789
|
+
i0.ɵɵrepeater(ctx_r1.TaxFilteredNodes);
|
|
790
|
+
i0.ɵɵadvance(2);
|
|
791
|
+
i0.ɵɵconditional(ctx_r1.TaxTreeSaving ? 12 : -1);
|
|
792
|
+
i0.ɵɵadvance(2);
|
|
793
|
+
i0.ɵɵconditional(ctx_r1.TaxSelectedNode ? 14 : 15);
|
|
794
|
+
i0.ɵɵadvance(8);
|
|
795
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxHealth.Total);
|
|
796
|
+
i0.ɵɵadvance(6);
|
|
797
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxHealth.Healthy);
|
|
798
|
+
i0.ɵɵadvance(6);
|
|
799
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxHealth.NeedAttention);
|
|
800
|
+
i0.ɵɵadvance(6);
|
|
801
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxHealth.Orphaned);
|
|
802
|
+
i0.ɵɵadvance(6);
|
|
803
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxHealth.Duplicates);
|
|
804
|
+
} }
|
|
805
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
806
|
+
i0.ɵɵelementStart(0, "div", 20);
|
|
807
|
+
i0.ɵɵelement(1, "i", 146);
|
|
808
|
+
i0.ɵɵelementStart(2, "p");
|
|
809
|
+
i0.ɵɵtext(3, "No duplicate tags detected");
|
|
810
|
+
i0.ɵɵelementEnd()();
|
|
811
|
+
} }
|
|
812
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
813
|
+
i0.ɵɵelement(0, "i", 99);
|
|
814
|
+
i0.ɵɵtext(1, " Merging... ");
|
|
815
|
+
} }
|
|
816
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_1_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
817
|
+
i0.ɵɵtext(0, " Merge ");
|
|
818
|
+
} }
|
|
819
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
820
|
+
const _r24 = i0.ɵɵgetCurrentView();
|
|
821
|
+
i0.ɵɵelementStart(0, "div", 148);
|
|
822
|
+
i0.ɵɵtext(1);
|
|
823
|
+
i0.ɵɵelementEnd();
|
|
824
|
+
i0.ɵɵelementStart(2, "div", 149)(3, "span", 150);
|
|
825
|
+
i0.ɵɵelement(4, "i", 151);
|
|
826
|
+
i0.ɵɵtext(5);
|
|
827
|
+
i0.ɵɵelementEnd()();
|
|
828
|
+
i0.ɵɵelementStart(6, "div", 152)(7, "button", 153);
|
|
829
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_1_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r24); const pair_r25 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MergeTags(pair_r25.TagAID, pair_r25.TagBID, pair_r25.TagA, pair_r25.TagB)); });
|
|
830
|
+
i0.ɵɵconditionalCreate(8, ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_1_Conditional_8_Template, 2, 0)(9, ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_1_Conditional_9_Template, 1, 0);
|
|
831
|
+
i0.ɵɵelementEnd();
|
|
832
|
+
i0.ɵɵelementStart(10, "button", 154);
|
|
833
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_1_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r24); const pair_r25 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.DismissDuplicate(pair_r25)); });
|
|
834
|
+
i0.ɵɵtext(11, "Dismiss");
|
|
835
|
+
i0.ɵɵelementEnd()();
|
|
836
|
+
} if (rf & 2) {
|
|
837
|
+
const pair_r25 = i0.ɵɵnextContext().$implicit;
|
|
838
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
839
|
+
i0.ɵɵadvance();
|
|
840
|
+
i0.ɵɵtextInterpolate(pair_r25.TagA);
|
|
841
|
+
i0.ɵɵadvance(4);
|
|
842
|
+
i0.ɵɵtextInterpolate1("\u00A0", pair_r25.ExactDuplicateCount, " identical records ");
|
|
843
|
+
i0.ɵɵadvance(2);
|
|
844
|
+
i0.ɵɵproperty("disabled", ctx_r1.IsMerging);
|
|
845
|
+
i0.ɵɵadvance();
|
|
846
|
+
i0.ɵɵconditional(ctx_r1.IsMerging ? 8 : 9);
|
|
847
|
+
} }
|
|
848
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
849
|
+
i0.ɵɵelement(0, "i", 99);
|
|
850
|
+
i0.ɵɵtext(1, " Merging... ");
|
|
851
|
+
} }
|
|
852
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
853
|
+
i0.ɵɵtext(0, " Merge ");
|
|
854
|
+
} }
|
|
855
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
856
|
+
const _r26 = i0.ɵɵgetCurrentView();
|
|
857
|
+
i0.ɵɵelementStart(0, "div", 148);
|
|
858
|
+
i0.ɵɵtext(1);
|
|
859
|
+
i0.ɵɵelementEnd();
|
|
860
|
+
i0.ɵɵelementStart(2, "div", 155);
|
|
861
|
+
i0.ɵɵelement(3, "i", 156);
|
|
862
|
+
i0.ɵɵelementEnd();
|
|
863
|
+
i0.ɵɵelementStart(4, "div", 149)(5, "div", 157);
|
|
864
|
+
i0.ɵɵelement(6, "div", 158);
|
|
865
|
+
i0.ɵɵelementEnd();
|
|
866
|
+
i0.ɵɵelementStart(7, "span", 159);
|
|
867
|
+
i0.ɵɵtext(8);
|
|
868
|
+
i0.ɵɵelementEnd()();
|
|
869
|
+
i0.ɵɵelementStart(9, "div", 155);
|
|
870
|
+
i0.ɵɵelement(10, "i", 156);
|
|
871
|
+
i0.ɵɵelementEnd();
|
|
872
|
+
i0.ɵɵelementStart(11, "div", 148);
|
|
873
|
+
i0.ɵɵtext(12);
|
|
874
|
+
i0.ɵɵelementEnd();
|
|
875
|
+
i0.ɵɵelementStart(13, "div", 152)(14, "button", 153);
|
|
876
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r26); const pair_r25 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MergeTags(pair_r25.TagAID, pair_r25.TagBID, pair_r25.TagA, pair_r25.TagB)); });
|
|
877
|
+
i0.ɵɵconditionalCreate(15, ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Conditional_15_Template, 2, 0)(16, ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Conditional_16_Template, 1, 0);
|
|
878
|
+
i0.ɵɵelementEnd();
|
|
879
|
+
i0.ɵɵelementStart(17, "button", 154);
|
|
880
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r26); const pair_r25 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MakeChildTag(pair_r25.TagAID, pair_r25.TagBID)); });
|
|
881
|
+
i0.ɵɵtext(18, "Make Child");
|
|
882
|
+
i0.ɵɵelementEnd();
|
|
883
|
+
i0.ɵɵelementStart(19, "button", 154);
|
|
884
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r26); const pair_r25 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.DismissDuplicate(pair_r25)); });
|
|
885
|
+
i0.ɵɵtext(20, "Dismiss");
|
|
886
|
+
i0.ɵɵelementEnd()();
|
|
887
|
+
} if (rf & 2) {
|
|
888
|
+
const pair_r25 = i0.ɵɵnextContext().$implicit;
|
|
889
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
890
|
+
i0.ɵɵadvance();
|
|
891
|
+
i0.ɵɵtextInterpolate(pair_r25.TagA);
|
|
892
|
+
i0.ɵɵadvance(5);
|
|
893
|
+
i0.ɵɵclassMap(pair_r25.SeverityClass);
|
|
894
|
+
i0.ɵɵstyleProp("width", pair_r25.Similarity, "%");
|
|
895
|
+
i0.ɵɵadvance();
|
|
896
|
+
i0.ɵɵclassMap(pair_r25.SeverityClass);
|
|
897
|
+
i0.ɵɵadvance();
|
|
898
|
+
i0.ɵɵtextInterpolate1("", pair_r25.Similarity, "%");
|
|
899
|
+
i0.ɵɵadvance(4);
|
|
900
|
+
i0.ɵɵtextInterpolate(pair_r25.TagB);
|
|
901
|
+
i0.ɵɵadvance(2);
|
|
902
|
+
i0.ɵɵproperty("disabled", ctx_r1.IsMerging);
|
|
903
|
+
i0.ɵɵadvance();
|
|
904
|
+
i0.ɵɵconditional(ctx_r1.IsMerging ? 15 : 16);
|
|
905
|
+
} }
|
|
906
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_For_16_Template(rf, ctx) { if (rf & 1) {
|
|
907
|
+
i0.ɵɵelementStart(0, "div", 147);
|
|
908
|
+
i0.ɵɵconditionalCreate(1, ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_1_Template, 12, 4)(2, ClassifyTaxonomyTabComponent_Conditional_12_For_16_Conditional_2_Template, 21, 11);
|
|
909
|
+
i0.ɵɵelementEnd();
|
|
910
|
+
} if (rf & 2) {
|
|
911
|
+
const pair_r25 = ctx.$implicit;
|
|
912
|
+
i0.ɵɵclassProp("at-tax-dup-high", pair_r25.SeverityClass === "high")("at-tax-dup-moderate", pair_r25.SeverityClass === "moderate");
|
|
913
|
+
i0.ɵɵadvance();
|
|
914
|
+
i0.ɵɵconditional(pair_r25.IsExactDuplicate ? 1 : 2);
|
|
915
|
+
} }
|
|
916
|
+
function ClassifyTaxonomyTabComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
917
|
+
i0.ɵɵelementStart(0, "div", 140)(1, "div", 141)(2, "strong");
|
|
918
|
+
i0.ɵɵtext(3);
|
|
919
|
+
i0.ɵɵelementEnd();
|
|
920
|
+
i0.ɵɵtext(4, " candidates found");
|
|
921
|
+
i0.ɵɵelementEnd();
|
|
922
|
+
i0.ɵɵelementStart(5, "div", 142)(6, "strong");
|
|
923
|
+
i0.ɵɵtext(7);
|
|
924
|
+
i0.ɵɵelementEnd();
|
|
925
|
+
i0.ɵɵtext(8, " high confidence (>85%)");
|
|
926
|
+
i0.ɵɵelementEnd();
|
|
927
|
+
i0.ɵɵelementStart(9, "div", 143)(10, "strong");
|
|
928
|
+
i0.ɵɵtext(11);
|
|
929
|
+
i0.ɵɵelementEnd();
|
|
930
|
+
i0.ɵɵtext(12, " moderate (70-85%)");
|
|
931
|
+
i0.ɵɵelementEnd()();
|
|
932
|
+
i0.ɵɵconditionalCreate(13, ClassifyTaxonomyTabComponent_Conditional_12_Conditional_13_Template, 4, 0, "div", 20);
|
|
933
|
+
i0.ɵɵelementStart(14, "div", 144);
|
|
934
|
+
i0.ɵɵrepeaterCreate(15, ClassifyTaxonomyTabComponent_Conditional_12_For_16_Template, 3, 5, "div", 145, i0.ɵɵrepeaterTrackByIndex);
|
|
935
|
+
i0.ɵɵelementEnd();
|
|
936
|
+
} if (rf & 2) {
|
|
937
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
938
|
+
i0.ɵɵadvance(3);
|
|
939
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxDuplicates.length);
|
|
940
|
+
i0.ɵɵadvance(4);
|
|
941
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxHighConfidenceDupeCount);
|
|
942
|
+
i0.ɵɵadvance(4);
|
|
943
|
+
i0.ɵɵtextInterpolate(ctx_r1.TaxModerateDupeCount);
|
|
944
|
+
i0.ɵɵadvance(2);
|
|
945
|
+
i0.ɵɵconditional(ctx_r1.TaxDuplicates.length === 0 ? 13 : -1);
|
|
946
|
+
i0.ɵɵadvance(2);
|
|
947
|
+
i0.ɵɵrepeater(ctx_r1.TaxDuplicates);
|
|
948
|
+
} }
|
|
949
|
+
function ClassifyTaxonomyTabComponent_Conditional_13_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
950
|
+
i0.ɵɵelement(0, "i", 165);
|
|
951
|
+
} }
|
|
952
|
+
function ClassifyTaxonomyTabComponent_Conditional_13_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
953
|
+
i0.ɵɵelement(0, "i", 166);
|
|
954
|
+
} }
|
|
955
|
+
function ClassifyTaxonomyTabComponent_Conditional_13_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
956
|
+
i0.ɵɵelementStart(0, "div", 20);
|
|
957
|
+
i0.ɵɵelement(1, "i", 146);
|
|
958
|
+
i0.ɵɵelementStart(2, "p");
|
|
959
|
+
i0.ɵɵtext(3, "No orphaned tags");
|
|
960
|
+
i0.ɵɵelementEnd()();
|
|
961
|
+
} }
|
|
962
|
+
function ClassifyTaxonomyTabComponent_Conditional_13_For_19_Template(rf, ctx) { if (rf & 1) {
|
|
963
|
+
const _r28 = i0.ɵɵgetCurrentView();
|
|
964
|
+
i0.ɵɵelementStart(0, "div", 170)(1, "div", 171)(2, "span", 172);
|
|
965
|
+
i0.ɵɵtext(3);
|
|
966
|
+
i0.ɵɵelementEnd();
|
|
967
|
+
i0.ɵɵelementStart(4, "input", 173);
|
|
968
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_13_For_19_Template_input_change_4_listener() { const orphan_r29 = i0.ɵɵrestoreView(_r28).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleOrphanSelection(orphan_r29)); })("click", function ClassifyTaxonomyTabComponent_Conditional_13_For_19_Template_input_click_4_listener($event) { i0.ɵɵrestoreView(_r28); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
969
|
+
i0.ɵɵelementEnd()();
|
|
970
|
+
i0.ɵɵelementStart(5, "div", 174)(6, "span");
|
|
971
|
+
i0.ɵɵtext(7, "Usage: ");
|
|
972
|
+
i0.ɵɵelementStart(8, "strong");
|
|
973
|
+
i0.ɵɵtext(9);
|
|
974
|
+
i0.ɵɵelementEnd()();
|
|
975
|
+
i0.ɵɵelementStart(10, "span");
|
|
976
|
+
i0.ɵɵtext(11, "Avg Weight: ");
|
|
977
|
+
i0.ɵɵelementStart(12, "strong");
|
|
978
|
+
i0.ɵɵtext(13);
|
|
979
|
+
i0.ɵɵelementEnd()()();
|
|
980
|
+
i0.ɵɵelementStart(14, "div", 175)(15, "span");
|
|
981
|
+
i0.ɵɵtext(16);
|
|
982
|
+
i0.ɵɵelementEnd();
|
|
983
|
+
i0.ɵɵelementStart(17, "span");
|
|
984
|
+
i0.ɵɵtext(18);
|
|
985
|
+
i0.ɵɵelementEnd()();
|
|
986
|
+
i0.ɵɵelementStart(19, "div", 176)(20, "button", 177);
|
|
987
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_13_For_19_Template_button_click_20_listener() { const orphan_r29 = i0.ɵɵrestoreView(_r28).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.DeleteOrphan(orphan_r29)); });
|
|
988
|
+
i0.ɵɵtext(21, "Delete");
|
|
989
|
+
i0.ɵɵelementEnd();
|
|
990
|
+
i0.ɵɵelementStart(22, "button", 178);
|
|
991
|
+
i0.ɵɵtext(23, "Ignore");
|
|
992
|
+
i0.ɵɵelementEnd()()();
|
|
993
|
+
} if (rf & 2) {
|
|
994
|
+
const orphan_r29 = ctx.$implicit;
|
|
995
|
+
i0.ɵɵadvance(3);
|
|
996
|
+
i0.ɵɵtextInterpolate(orphan_r29.Name);
|
|
997
|
+
i0.ɵɵadvance();
|
|
998
|
+
i0.ɵɵproperty("checked", orphan_r29.IsSelected);
|
|
999
|
+
i0.ɵɵadvance(5);
|
|
1000
|
+
i0.ɵɵtextInterpolate(orphan_r29.UsageCount);
|
|
1001
|
+
i0.ɵɵadvance(4);
|
|
1002
|
+
i0.ɵɵtextInterpolate(orphan_r29.AvgWeight.toFixed(2));
|
|
1003
|
+
i0.ɵɵadvance(3);
|
|
1004
|
+
i0.ɵɵtextInterpolate1("First: ", orphan_r29.FirstSeen);
|
|
1005
|
+
i0.ɵɵadvance(2);
|
|
1006
|
+
i0.ɵɵtextInterpolate1("Last: ", orphan_r29.LastSeen);
|
|
1007
|
+
} }
|
|
1008
|
+
function ClassifyTaxonomyTabComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
1009
|
+
const _r27 = i0.ɵɵgetCurrentView();
|
|
1010
|
+
i0.ɵɵelementStart(0, "div", 160)(1, "span", 161);
|
|
1011
|
+
i0.ɵɵtext(2);
|
|
1012
|
+
i0.ɵɵelementEnd();
|
|
1013
|
+
i0.ɵɵelementStart(3, "span", 162);
|
|
1014
|
+
i0.ɵɵtext(4, "\u2014 no parent, no children, low usage");
|
|
1015
|
+
i0.ɵɵelementEnd();
|
|
1016
|
+
i0.ɵɵelementStart(5, "div", 163)(6, "button", 164);
|
|
1017
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_13_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r27); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleAllOrphans()); });
|
|
1018
|
+
i0.ɵɵconditionalCreate(7, ClassifyTaxonomyTabComponent_Conditional_13_Conditional_7_Template, 1, 0, "i", 165)(8, ClassifyTaxonomyTabComponent_Conditional_13_Conditional_8_Template, 1, 0, "i", 166);
|
|
1019
|
+
i0.ɵɵtext(9, " Select All ");
|
|
1020
|
+
i0.ɵɵelementEnd();
|
|
1021
|
+
i0.ɵɵelementStart(10, "button", 167);
|
|
1022
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_13_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r27); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.BulkDeleteOrphans()); });
|
|
1023
|
+
i0.ɵɵelement(11, "i", 86);
|
|
1024
|
+
i0.ɵɵtext(12, " Bulk Delete ");
|
|
1025
|
+
i0.ɵɵelementEnd();
|
|
1026
|
+
i0.ɵɵelementStart(13, "button", 167);
|
|
1027
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_13_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r27); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.DeleteAllOrphans()); });
|
|
1028
|
+
i0.ɵɵelement(14, "i", 168);
|
|
1029
|
+
i0.ɵɵtext(15);
|
|
1030
|
+
i0.ɵɵelementEnd()()();
|
|
1031
|
+
i0.ɵɵconditionalCreate(16, ClassifyTaxonomyTabComponent_Conditional_13_Conditional_16_Template, 4, 0, "div", 20);
|
|
1032
|
+
i0.ɵɵelementStart(17, "div", 169);
|
|
1033
|
+
i0.ɵɵrepeaterCreate(18, ClassifyTaxonomyTabComponent_Conditional_13_For_19_Template, 24, 6, "div", 170, _forTrack0);
|
|
1034
|
+
i0.ɵɵelementEnd();
|
|
1035
|
+
} if (rf & 2) {
|
|
1036
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1037
|
+
i0.ɵɵadvance(2);
|
|
1038
|
+
i0.ɵɵtextInterpolate1("", ctx_r1.TaxOrphans.length, " orphaned tags");
|
|
1039
|
+
i0.ɵɵadvance(5);
|
|
1040
|
+
i0.ɵɵconditional(ctx_r1.TaxAllOrphansSelected ? 7 : 8);
|
|
1041
|
+
i0.ɵɵadvance(8);
|
|
1042
|
+
i0.ɵɵtextInterpolate1(" Delete All (", ctx_r1.TaxOrphans.length, ") ");
|
|
1043
|
+
i0.ɵɵadvance();
|
|
1044
|
+
i0.ɵɵconditional(ctx_r1.TaxOrphans.length === 0 ? 16 : -1);
|
|
1045
|
+
i0.ɵɵadvance(2);
|
|
1046
|
+
i0.ɵɵrepeater(ctx_r1.TaxOrphans);
|
|
1047
|
+
} }
|
|
1048
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1049
|
+
i0.ɵɵelementStart(0, "div", 180)(1, "div", 183);
|
|
1050
|
+
i0.ɵɵtext(2);
|
|
1051
|
+
i0.ɵɵelementEnd();
|
|
1052
|
+
i0.ɵɵelementStart(3, "div", 184);
|
|
1053
|
+
i0.ɵɵtext(4);
|
|
1054
|
+
i0.ɵɵelementEnd()();
|
|
1055
|
+
} if (rf & 2) {
|
|
1056
|
+
const kpi_r30 = ctx.$implicit;
|
|
1057
|
+
i0.ɵɵadvance(2);
|
|
1058
|
+
i0.ɵɵtextInterpolate(kpi_r30.Value);
|
|
1059
|
+
i0.ɵɵadvance(2);
|
|
1060
|
+
i0.ɵɵtextInterpolate(kpi_r30.Label);
|
|
1061
|
+
} }
|
|
1062
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
1063
|
+
i0.ɵɵelementStart(0, "div", 20);
|
|
1064
|
+
i0.ɵɵelement(1, "i", 185);
|
|
1065
|
+
i0.ɵɵelementStart(2, "p");
|
|
1066
|
+
i0.ɵɵtext(3, "No taxonomy data to visualize");
|
|
1067
|
+
i0.ɵɵelementEnd()();
|
|
1068
|
+
} }
|
|
1069
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_4_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1070
|
+
const _r31 = i0.ɵɵgetCurrentView();
|
|
1071
|
+
i0.ɵɵelementStart(0, "div", 187);
|
|
1072
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_4_For_2_Template_div_click_0_listener() { const cell_r32 = i0.ɵɵrestoreView(_r31).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OpenTreemapDrillIn(cell_r32)); });
|
|
1073
|
+
i0.ɵɵelementStart(1, "span", 188);
|
|
1074
|
+
i0.ɵɵtext(2);
|
|
1075
|
+
i0.ɵɵelementEnd();
|
|
1076
|
+
i0.ɵɵelementStart(3, "span", 189);
|
|
1077
|
+
i0.ɵɵtext(4);
|
|
1078
|
+
i0.ɵɵelementEnd()();
|
|
1079
|
+
} if (rf & 2) {
|
|
1080
|
+
const cell_r32 = ctx.$implicit;
|
|
1081
|
+
i0.ɵɵclassMap(cell_r32.ColorClass);
|
|
1082
|
+
i0.ɵɵstyleProp("grid-row", cell_r32.RowSpan > 1 ? "span " + cell_r32.RowSpan : "");
|
|
1083
|
+
i0.ɵɵadvance(2);
|
|
1084
|
+
i0.ɵɵtextInterpolate(cell_r32.Name);
|
|
1085
|
+
i0.ɵɵadvance(2);
|
|
1086
|
+
i0.ɵɵtextInterpolate1("", cell_r32.ItemCount, " items");
|
|
1087
|
+
} }
|
|
1088
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
1089
|
+
i0.ɵɵelementStart(0, "div", 181);
|
|
1090
|
+
i0.ɵɵrepeaterCreate(1, ClassifyTaxonomyTabComponent_Conditional_14_Conditional_4_For_2_Template, 5, 6, "div", 186, i0.ɵɵrepeaterTrackByIndex);
|
|
1091
|
+
i0.ɵɵelementEnd();
|
|
1092
|
+
} if (rf & 2) {
|
|
1093
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
1094
|
+
i0.ɵɵadvance();
|
|
1095
|
+
i0.ɵɵrepeater(ctx_r1.TaxTreemapCells);
|
|
1096
|
+
} }
|
|
1097
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Conditional_25_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
1098
|
+
i0.ɵɵelementStart(0, "span", 89);
|
|
1099
|
+
i0.ɵɵtext(1);
|
|
1100
|
+
i0.ɵɵelementStart(2, "span", 91);
|
|
1101
|
+
i0.ɵɵtext(3);
|
|
1102
|
+
i0.ɵɵelementEnd()();
|
|
1103
|
+
} if (rf & 2) {
|
|
1104
|
+
const child_r34 = ctx.$implicit;
|
|
1105
|
+
i0.ɵɵadvance();
|
|
1106
|
+
i0.ɵɵtextInterpolate1("", child_r34.Name, " ");
|
|
1107
|
+
i0.ɵɵadvance(2);
|
|
1108
|
+
i0.ɵɵtextInterpolate(child_r34.ItemCount);
|
|
1109
|
+
} }
|
|
1110
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
1111
|
+
i0.ɵɵelementStart(0, "div", 80)(1, "div", 87);
|
|
1112
|
+
i0.ɵɵtext(2, "Child Tags");
|
|
1113
|
+
i0.ɵɵelementEnd();
|
|
1114
|
+
i0.ɵɵelementStart(3, "div", 88);
|
|
1115
|
+
i0.ɵɵrepeaterCreate(4, ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Conditional_25_For_5_Template, 4, 2, "span", 89, _forTrack0);
|
|
1116
|
+
i0.ɵɵelementEnd()();
|
|
1117
|
+
} if (rf & 2) {
|
|
1118
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
1119
|
+
i0.ɵɵadvance(4);
|
|
1120
|
+
i0.ɵɵrepeater(ctx_r1.TreemapDrillInNode.Children);
|
|
1121
|
+
} }
|
|
1122
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Conditional_26_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
1123
|
+
i0.ɵɵelementStart(0, "div", 93)(1, "div", 94);
|
|
1124
|
+
i0.ɵɵelement(2, "i");
|
|
1125
|
+
i0.ɵɵelementEnd();
|
|
1126
|
+
i0.ɵɵelementStart(3, "div", 95);
|
|
1127
|
+
i0.ɵɵtext(4);
|
|
1128
|
+
i0.ɵɵelementEnd();
|
|
1129
|
+
i0.ɵɵelementStart(5, "div", 96);
|
|
1130
|
+
i0.ɵɵtext(6);
|
|
1131
|
+
i0.ɵɵelementEnd();
|
|
1132
|
+
i0.ɵɵelementStart(7, "div", 97);
|
|
1133
|
+
i0.ɵɵtext(8);
|
|
1134
|
+
i0.ɵɵelementEnd()();
|
|
1135
|
+
} if (rf & 2) {
|
|
1136
|
+
const item_r35 = ctx.$implicit;
|
|
1137
|
+
i0.ɵɵadvance(2);
|
|
1138
|
+
i0.ɵɵclassMap(item_r35.Icon);
|
|
1139
|
+
i0.ɵɵadvance(2);
|
|
1140
|
+
i0.ɵɵtextInterpolate(item_r35.Name);
|
|
1141
|
+
i0.ɵɵadvance(2);
|
|
1142
|
+
i0.ɵɵtextInterpolate(item_r35.Weight.toFixed(2));
|
|
1143
|
+
i0.ɵɵadvance(2);
|
|
1144
|
+
i0.ɵɵtextInterpolate(item_r35.Date);
|
|
1145
|
+
} }
|
|
1146
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
1147
|
+
i0.ɵɵelementStart(0, "div", 80)(1, "div", 87);
|
|
1148
|
+
i0.ɵɵtext(2, "Recently Tagged Items");
|
|
1149
|
+
i0.ɵɵelementEnd();
|
|
1150
|
+
i0.ɵɵelementStart(3, "div", 92);
|
|
1151
|
+
i0.ɵɵrepeaterCreate(4, ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Conditional_26_For_5_Template, 9, 5, "div", 93, i0.ɵɵrepeaterTrackByIndex);
|
|
1152
|
+
i0.ɵɵelementEnd()();
|
|
1153
|
+
} if (rf & 2) {
|
|
1154
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
1155
|
+
i0.ɵɵadvance(4);
|
|
1156
|
+
i0.ɵɵrepeater(ctx_r1.TaxRecentItems);
|
|
1157
|
+
} }
|
|
1158
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
1159
|
+
const _r33 = i0.ɵɵgetCurrentView();
|
|
1160
|
+
i0.ɵɵelementStart(0, "div", 190);
|
|
1161
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.CloseTreemapDrillIn()); });
|
|
1162
|
+
i0.ɵɵelementStart(1, "div", 191);
|
|
1163
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r33); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
1164
|
+
i0.ɵɵelementStart(2, "div", 192)(3, "h3");
|
|
1165
|
+
i0.ɵɵelement(4, "i", 193);
|
|
1166
|
+
i0.ɵɵtext(5);
|
|
1167
|
+
i0.ɵɵelementEnd();
|
|
1168
|
+
i0.ɵɵelementStart(6, "button", 194);
|
|
1169
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.CloseTreemapDrillIn()); });
|
|
1170
|
+
i0.ɵɵelement(7, "i", 128);
|
|
1171
|
+
i0.ɵɵelementEnd()();
|
|
1172
|
+
i0.ɵɵelementStart(8, "div", 195)(9, "div", 74)(10, "div", 75)(11, "div", 76);
|
|
1173
|
+
i0.ɵɵtext(12);
|
|
1174
|
+
i0.ɵɵelementEnd();
|
|
1175
|
+
i0.ɵɵelementStart(13, "div", 77);
|
|
1176
|
+
i0.ɵɵtext(14, "Items Tagged");
|
|
1177
|
+
i0.ɵɵelementEnd()();
|
|
1178
|
+
i0.ɵɵelementStart(15, "div", 75)(16, "div", 76);
|
|
1179
|
+
i0.ɵɵtext(17);
|
|
1180
|
+
i0.ɵɵelementEnd();
|
|
1181
|
+
i0.ɵɵelementStart(18, "div", 77);
|
|
1182
|
+
i0.ɵɵtext(19, "Avg Weight");
|
|
1183
|
+
i0.ɵɵelementEnd()();
|
|
1184
|
+
i0.ɵɵelementStart(20, "div", 75)(21, "div", 76);
|
|
1185
|
+
i0.ɵɵtext(22);
|
|
1186
|
+
i0.ɵɵelementEnd();
|
|
1187
|
+
i0.ɵɵelementStart(23, "div", 77);
|
|
1188
|
+
i0.ɵɵtext(24, "Children");
|
|
1189
|
+
i0.ɵɵelementEnd()()();
|
|
1190
|
+
i0.ɵɵconditionalCreate(25, ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Conditional_25_Template, 6, 0, "div", 80);
|
|
1191
|
+
i0.ɵɵconditionalCreate(26, ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Conditional_26_Template, 6, 0, "div", 80);
|
|
1192
|
+
i0.ɵɵelementEnd();
|
|
1193
|
+
i0.ɵɵelementStart(27, "div", 196)(28, "button", 73);
|
|
1194
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Template_button_click_28_listener() { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.DrillInToTreeView(ctx_r1.TreemapDrillInNode)); });
|
|
1195
|
+
i0.ɵɵelement(29, "i", 39);
|
|
1196
|
+
i0.ɵɵtext(30, " View in Tree ");
|
|
1197
|
+
i0.ɵɵelementEnd()()()();
|
|
1198
|
+
} if (rf & 2) {
|
|
1199
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
1200
|
+
i0.ɵɵadvance(5);
|
|
1201
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.TreemapDrillInNode.Name);
|
|
1202
|
+
i0.ɵɵadvance(7);
|
|
1203
|
+
i0.ɵɵtextInterpolate(ctx_r1.TreemapDrillInNode.ItemCount);
|
|
1204
|
+
i0.ɵɵadvance(5);
|
|
1205
|
+
i0.ɵɵtextInterpolate(ctx_r1.TreemapDrillInNode.AvgWeight.toFixed(2));
|
|
1206
|
+
i0.ɵɵadvance(5);
|
|
1207
|
+
i0.ɵɵtextInterpolate(ctx_r1.TreemapDrillInNode.Children.length);
|
|
1208
|
+
i0.ɵɵadvance(3);
|
|
1209
|
+
i0.ɵɵconditional(ctx_r1.TreemapDrillInNode.Children.length > 0 ? 25 : -1);
|
|
1210
|
+
i0.ɵɵadvance();
|
|
1211
|
+
i0.ɵɵconditional(ctx_r1.TaxRecentItems.length > 0 ? 26 : -1);
|
|
1212
|
+
} }
|
|
1213
|
+
function ClassifyTaxonomyTabComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
1214
|
+
i0.ɵɵelementStart(0, "div", 179);
|
|
1215
|
+
i0.ɵɵrepeaterCreate(1, ClassifyTaxonomyTabComponent_Conditional_14_For_2_Template, 5, 2, "div", 180, _forTrack1);
|
|
1216
|
+
i0.ɵɵelementEnd();
|
|
1217
|
+
i0.ɵɵconditionalCreate(3, ClassifyTaxonomyTabComponent_Conditional_14_Conditional_3_Template, 4, 0, "div", 20)(4, ClassifyTaxonomyTabComponent_Conditional_14_Conditional_4_Template, 3, 0, "div", 181);
|
|
1218
|
+
i0.ɵɵconditionalCreate(5, ClassifyTaxonomyTabComponent_Conditional_14_Conditional_5_Template, 31, 6, "div", 182);
|
|
1219
|
+
} if (rf & 2) {
|
|
1220
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1221
|
+
i0.ɵɵadvance();
|
|
1222
|
+
i0.ɵɵrepeater(ctx_r1.TaxTreemapKPIs);
|
|
1223
|
+
i0.ɵɵadvance(2);
|
|
1224
|
+
i0.ɵɵconditional(ctx_r1.TaxTreemapCells.length === 0 ? 3 : 4);
|
|
1225
|
+
i0.ɵɵadvance(2);
|
|
1226
|
+
i0.ɵɵconditional(ctx_r1.ShowTreemapDrillIn && ctx_r1.TreemapDrillInNode ? 5 : -1);
|
|
1227
|
+
} }
|
|
1228
|
+
function ClassifyTaxonomyTabComponent_Conditional_15_Conditional_28_Template(rf, ctx) { if (rf & 1) {
|
|
1229
|
+
i0.ɵɵelementStart(0, "div", 20);
|
|
1230
|
+
i0.ɵɵelement(1, "i", 204);
|
|
1231
|
+
i0.ɵɵelementStart(2, "p");
|
|
1232
|
+
i0.ɵɵtext(3, "No audit events match the current filters");
|
|
1233
|
+
i0.ɵɵelementEnd()();
|
|
1234
|
+
} }
|
|
1235
|
+
function ClassifyTaxonomyTabComponent_Conditional_15_For_31_Template(rf, ctx) { if (rf & 1) {
|
|
1236
|
+
i0.ɵɵelementStart(0, "div", 203)(1, "div", 205);
|
|
1237
|
+
i0.ɵɵelement(2, "i");
|
|
1238
|
+
i0.ɵɵelementEnd();
|
|
1239
|
+
i0.ɵɵelementStart(3, "div", 206)(4, "div", 207);
|
|
1240
|
+
i0.ɵɵtext(5);
|
|
1241
|
+
i0.ɵɵelementStart(6, "span", 208);
|
|
1242
|
+
i0.ɵɵtext(7);
|
|
1243
|
+
i0.ɵɵelementEnd()();
|
|
1244
|
+
i0.ɵɵelementStart(8, "div", 209)(9, "span");
|
|
1245
|
+
i0.ɵɵtext(10);
|
|
1246
|
+
i0.ɵɵelementEnd();
|
|
1247
|
+
i0.ɵɵelementStart(11, "span");
|
|
1248
|
+
i0.ɵɵtext(12);
|
|
1249
|
+
i0.ɵɵelementEnd()()()();
|
|
1250
|
+
} if (rf & 2) {
|
|
1251
|
+
const event_r37 = ctx.$implicit;
|
|
1252
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
1253
|
+
i0.ɵɵadvance();
|
|
1254
|
+
i0.ɵɵclassMap(event_r37.Type);
|
|
1255
|
+
i0.ɵɵadvance();
|
|
1256
|
+
i0.ɵɵclassMap(ctx_r1.GetTaxAuditIcon(event_r37.Type));
|
|
1257
|
+
i0.ɵɵadvance(3);
|
|
1258
|
+
i0.ɵɵtextInterpolate1(" ", event_r37.Description, " ");
|
|
1259
|
+
i0.ɵɵadvance(2);
|
|
1260
|
+
i0.ɵɵtextInterpolate(event_r37.TagRef);
|
|
1261
|
+
i0.ɵɵadvance(3);
|
|
1262
|
+
i0.ɵɵtextInterpolate(event_r37.User);
|
|
1263
|
+
i0.ɵɵadvance(2);
|
|
1264
|
+
i0.ɵɵtextInterpolate(event_r37.Timestamp);
|
|
1265
|
+
} }
|
|
1266
|
+
function ClassifyTaxonomyTabComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
1267
|
+
const _r36 = i0.ɵɵgetCurrentView();
|
|
1268
|
+
i0.ɵɵelementStart(0, "div", 197)(1, "span", 198);
|
|
1269
|
+
i0.ɵɵtext(2, "Filter");
|
|
1270
|
+
i0.ɵɵelementEnd();
|
|
1271
|
+
i0.ɵɵelementStart(3, "div", 199)(4, "label", 200)(5, "input", 201);
|
|
1272
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_15_Template_input_change_5_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleTaxAuditFilter("created")); });
|
|
1273
|
+
i0.ɵɵelementEnd();
|
|
1274
|
+
i0.ɵɵtext(6, " Created ");
|
|
1275
|
+
i0.ɵɵelementEnd();
|
|
1276
|
+
i0.ɵɵelementStart(7, "label", 200)(8, "input", 201);
|
|
1277
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_15_Template_input_change_8_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleTaxAuditFilter("merged")); });
|
|
1278
|
+
i0.ɵɵelementEnd();
|
|
1279
|
+
i0.ɵɵtext(9, " Merged ");
|
|
1280
|
+
i0.ɵɵelementEnd();
|
|
1281
|
+
i0.ɵɵelementStart(10, "label", 200)(11, "input", 201);
|
|
1282
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_15_Template_input_change_11_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleTaxAuditFilter("moved")); });
|
|
1283
|
+
i0.ɵɵelementEnd();
|
|
1284
|
+
i0.ɵɵtext(12, " Moved ");
|
|
1285
|
+
i0.ɵɵelementEnd();
|
|
1286
|
+
i0.ɵɵelementStart(13, "label", 200)(14, "input", 201);
|
|
1287
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_15_Template_input_change_14_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleTaxAuditFilter("deleted")); });
|
|
1288
|
+
i0.ɵɵelementEnd();
|
|
1289
|
+
i0.ɵɵtext(15, " Deleted ");
|
|
1290
|
+
i0.ɵɵelementEnd();
|
|
1291
|
+
i0.ɵɵelementStart(16, "label", 200)(17, "input", 201);
|
|
1292
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_15_Template_input_change_17_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleTaxAuditFilter("renamed")); });
|
|
1293
|
+
i0.ɵɵelementEnd();
|
|
1294
|
+
i0.ɵɵtext(18, " Renamed ");
|
|
1295
|
+
i0.ɵɵelementEnd();
|
|
1296
|
+
i0.ɵɵelementStart(19, "label", 200)(20, "input", 201);
|
|
1297
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_15_Template_input_change_20_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleTaxAuditFilter("deprecated")); });
|
|
1298
|
+
i0.ɵɵelementEnd();
|
|
1299
|
+
i0.ɵɵtext(21, " Deprecated ");
|
|
1300
|
+
i0.ɵɵelementEnd();
|
|
1301
|
+
i0.ɵɵelementStart(22, "label", 200)(23, "input", 201);
|
|
1302
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_15_Template_input_change_23_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleTaxAuditFilter("split")); });
|
|
1303
|
+
i0.ɵɵelementEnd();
|
|
1304
|
+
i0.ɵɵtext(24, " Split ");
|
|
1305
|
+
i0.ɵɵelementEnd();
|
|
1306
|
+
i0.ɵɵelementStart(25, "label", 200)(26, "input", 201);
|
|
1307
|
+
i0.ɵɵlistener("change", function ClassifyTaxonomyTabComponent_Conditional_15_Template_input_change_26_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleTaxAuditFilter("reactivated")); });
|
|
1308
|
+
i0.ɵɵelementEnd();
|
|
1309
|
+
i0.ɵɵtext(27, " Reactivated ");
|
|
1310
|
+
i0.ɵɵelementEnd()()();
|
|
1311
|
+
i0.ɵɵconditionalCreate(28, ClassifyTaxonomyTabComponent_Conditional_15_Conditional_28_Template, 4, 0, "div", 20);
|
|
1312
|
+
i0.ɵɵelementStart(29, "div", 202);
|
|
1313
|
+
i0.ɵɵrepeaterCreate(30, ClassifyTaxonomyTabComponent_Conditional_15_For_31_Template, 13, 8, "div", 203, i0.ɵɵrepeaterTrackByIndex);
|
|
1314
|
+
i0.ɵɵelementEnd();
|
|
1315
|
+
} if (rf & 2) {
|
|
1316
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1317
|
+
i0.ɵɵadvance(5);
|
|
1318
|
+
i0.ɵɵproperty("checked", ctx_r1.TaxAuditFilterTypes.has("created"));
|
|
1319
|
+
i0.ɵɵadvance(3);
|
|
1320
|
+
i0.ɵɵproperty("checked", ctx_r1.TaxAuditFilterTypes.has("merged"));
|
|
1321
|
+
i0.ɵɵadvance(3);
|
|
1322
|
+
i0.ɵɵproperty("checked", ctx_r1.TaxAuditFilterTypes.has("moved"));
|
|
1323
|
+
i0.ɵɵadvance(3);
|
|
1324
|
+
i0.ɵɵproperty("checked", ctx_r1.TaxAuditFilterTypes.has("deleted"));
|
|
1325
|
+
i0.ɵɵadvance(3);
|
|
1326
|
+
i0.ɵɵproperty("checked", ctx_r1.TaxAuditFilterTypes.has("renamed"));
|
|
1327
|
+
i0.ɵɵadvance(3);
|
|
1328
|
+
i0.ɵɵproperty("checked", ctx_r1.TaxAuditFilterTypes.has("deprecated"));
|
|
1329
|
+
i0.ɵɵadvance(3);
|
|
1330
|
+
i0.ɵɵproperty("checked", ctx_r1.TaxAuditFilterTypes.has("split"));
|
|
1331
|
+
i0.ɵɵadvance(3);
|
|
1332
|
+
i0.ɵɵproperty("checked", ctx_r1.TaxAuditFilterTypes.has("reactivated"));
|
|
1333
|
+
i0.ɵɵadvance(2);
|
|
1334
|
+
i0.ɵɵconditional(ctx_r1.GetFilteredAuditEvents().length === 0 ? 28 : -1);
|
|
1335
|
+
i0.ɵɵadvance(2);
|
|
1336
|
+
i0.ɵɵrepeater(ctx_r1.GetFilteredAuditEvents());
|
|
1337
|
+
} }
|
|
1338
|
+
function ClassifyTaxonomyTabComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
1339
|
+
const _r38 = i0.ɵɵgetCurrentView();
|
|
1340
|
+
i0.ɵɵelementStart(0, "div", 210);
|
|
1341
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_16_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ConfirmDialogCancel()); });
|
|
1342
|
+
i0.ɵɵelementStart(1, "div", 211);
|
|
1343
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_16_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r38); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
1344
|
+
i0.ɵɵelementStart(2, "div", 212)(3, "h3");
|
|
1345
|
+
i0.ɵɵelement(4, "i", 213);
|
|
1346
|
+
i0.ɵɵtext(5);
|
|
1347
|
+
i0.ɵɵelementEnd();
|
|
1348
|
+
i0.ɵɵelementStart(6, "button", 194);
|
|
1349
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_16_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ConfirmDialogCancel()); });
|
|
1350
|
+
i0.ɵɵelement(7, "i", 128);
|
|
1351
|
+
i0.ɵɵelementEnd()();
|
|
1352
|
+
i0.ɵɵelementStart(8, "div", 214)(9, "p", 215);
|
|
1353
|
+
i0.ɵɵtext(10);
|
|
1354
|
+
i0.ɵɵelementEnd()();
|
|
1355
|
+
i0.ɵɵelementStart(11, "div", 216)(12, "button", 217);
|
|
1356
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_16_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ConfirmDialogAccept()); });
|
|
1357
|
+
i0.ɵɵelement(13, "i", 110);
|
|
1358
|
+
i0.ɵɵtext(14, " Confirm ");
|
|
1359
|
+
i0.ɵɵelementEnd();
|
|
1360
|
+
i0.ɵɵelementStart(15, "button", 73);
|
|
1361
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_16_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ConfirmDialogCancel()); });
|
|
1362
|
+
i0.ɵɵtext(16, "Cancel");
|
|
1363
|
+
i0.ɵɵelementEnd()()()();
|
|
1364
|
+
} if (rf & 2) {
|
|
1365
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1366
|
+
i0.ɵɵadvance(5);
|
|
1367
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.ConfirmDialogTitle);
|
|
1368
|
+
i0.ɵɵadvance(5);
|
|
1369
|
+
i0.ɵɵtextInterpolate(ctx_r1.ConfirmDialogMessage);
|
|
1370
|
+
} }
|
|
1371
|
+
function ClassifyTaxonomyTabComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
1372
|
+
const _r39 = i0.ɵɵgetCurrentView();
|
|
1373
|
+
i0.ɵɵelementStart(0, "div", 210);
|
|
1374
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_17_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r39); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseSplitDialog()); });
|
|
1375
|
+
i0.ɵɵelementStart(1, "div", 211);
|
|
1376
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_17_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r39); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
1377
|
+
i0.ɵɵelementStart(2, "div", 212)(3, "h3");
|
|
1378
|
+
i0.ɵɵelement(4, "i", 84);
|
|
1379
|
+
i0.ɵɵtext(5, " Split Tag");
|
|
1380
|
+
i0.ɵɵelementEnd();
|
|
1381
|
+
i0.ɵɵelementStart(6, "button", 194);
|
|
1382
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_17_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r39); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseSplitDialog()); });
|
|
1383
|
+
i0.ɵɵelement(7, "i", 128);
|
|
1384
|
+
i0.ɵɵelementEnd()();
|
|
1385
|
+
i0.ɵɵelementStart(8, "div", 214)(9, "div", 218)(10, "label");
|
|
1386
|
+
i0.ɵɵtext(11, "New tag names (comma-separated)");
|
|
1387
|
+
i0.ɵɵelementEnd();
|
|
1388
|
+
i0.ɵɵelementStart(12, "input", 219);
|
|
1389
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_17_Template_input_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r39); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.SplitChildNames, $event) || (ctx_r1.SplitChildNames = $event); return i0.ɵɵresetView($event); });
|
|
1390
|
+
i0.ɵɵelementEnd()();
|
|
1391
|
+
i0.ɵɵelementStart(13, "p", 215);
|
|
1392
|
+
i0.ɵɵtext(14, "New tags will be created as siblings of the original tag under the same parent.");
|
|
1393
|
+
i0.ɵɵelementEnd()();
|
|
1394
|
+
i0.ɵɵelementStart(15, "div", 216)(16, "button", 220);
|
|
1395
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_17_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r39); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ExecuteSplit()); });
|
|
1396
|
+
i0.ɵɵelement(17, "i", 84);
|
|
1397
|
+
i0.ɵɵtext(18, " Create Tags ");
|
|
1398
|
+
i0.ɵɵelementEnd();
|
|
1399
|
+
i0.ɵɵelementStart(19, "button", 73);
|
|
1400
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_17_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r39); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseSplitDialog()); });
|
|
1401
|
+
i0.ɵɵtext(20, "Cancel");
|
|
1402
|
+
i0.ɵɵelementEnd()()()();
|
|
1403
|
+
} if (rf & 2) {
|
|
1404
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1405
|
+
i0.ɵɵadvance(12);
|
|
1406
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.SplitChildNames);
|
|
1407
|
+
i0.ɵɵadvance(4);
|
|
1408
|
+
i0.ɵɵproperty("disabled", !ctx_r1.SplitChildNames.trim());
|
|
1409
|
+
} }
|
|
1410
|
+
function ClassifyTaxonomyTabComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
1411
|
+
const _r40 = i0.ɵɵgetCurrentView();
|
|
1412
|
+
i0.ɵɵelementStart(0, "div", 210);
|
|
1413
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_18_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r40); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseCreateTagDialog()); });
|
|
1414
|
+
i0.ɵɵelementStart(1, "div", 211);
|
|
1415
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_18_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r40); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
1416
|
+
i0.ɵɵelementStart(2, "div", 212)(3, "h3");
|
|
1417
|
+
i0.ɵɵelement(4, "i", 16);
|
|
1418
|
+
i0.ɵɵtext(5, " Create Tag");
|
|
1419
|
+
i0.ɵɵelementEnd();
|
|
1420
|
+
i0.ɵɵelementStart(6, "button", 194);
|
|
1421
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_18_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r40); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseCreateTagDialog()); });
|
|
1422
|
+
i0.ɵɵelement(7, "i", 128);
|
|
1423
|
+
i0.ɵɵelementEnd()();
|
|
1424
|
+
i0.ɵɵelementStart(8, "div", 214)(9, "div", 221);
|
|
1425
|
+
i0.ɵɵtext(10);
|
|
1426
|
+
i0.ɵɵelementEnd();
|
|
1427
|
+
i0.ɵɵelementStart(11, "div", 218)(12, "label");
|
|
1428
|
+
i0.ɵɵtext(13, "Name");
|
|
1429
|
+
i0.ɵɵelementEnd();
|
|
1430
|
+
i0.ɵɵelementStart(14, "input", 222);
|
|
1431
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_18_Template_input_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r40); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.CreateTagName, $event) || (ctx_r1.CreateTagName = $event); return i0.ɵɵresetView($event); });
|
|
1432
|
+
i0.ɵɵlistener("keydown.enter", function ClassifyTaxonomyTabComponent_Conditional_18_Template_input_keydown_enter_14_listener() { i0.ɵɵrestoreView(_r40); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SaveNewTag()); });
|
|
1433
|
+
i0.ɵɵelementEnd()();
|
|
1434
|
+
i0.ɵɵelementStart(15, "div", 218)(16, "label");
|
|
1435
|
+
i0.ɵɵtext(17, "Description (optional)");
|
|
1436
|
+
i0.ɵɵelementEnd();
|
|
1437
|
+
i0.ɵɵelementStart(18, "textarea", 223);
|
|
1438
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_18_Template_textarea_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r40); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.CreateTagDescription, $event) || (ctx_r1.CreateTagDescription = $event); return i0.ɵɵresetView($event); });
|
|
1439
|
+
i0.ɵɵelementEnd()()();
|
|
1440
|
+
i0.ɵɵelementStart(19, "div", 216)(20, "button", 220);
|
|
1441
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_18_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r40); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SaveNewTag()); });
|
|
1442
|
+
i0.ɵɵelement(21, "i", 110);
|
|
1443
|
+
i0.ɵɵtext(22, " Create ");
|
|
1444
|
+
i0.ɵɵelementEnd();
|
|
1445
|
+
i0.ɵɵelementStart(23, "button", 73);
|
|
1446
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_18_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r40); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseCreateTagDialog()); });
|
|
1447
|
+
i0.ɵɵtext(24, "Cancel");
|
|
1448
|
+
i0.ɵɵelementEnd()()()();
|
|
1449
|
+
} if (rf & 2) {
|
|
1450
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1451
|
+
i0.ɵɵadvance(10);
|
|
1452
|
+
i0.ɵɵtextInterpolate(ctx_r1.CreateTagParentLabel);
|
|
1453
|
+
i0.ɵɵadvance(4);
|
|
1454
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.CreateTagName);
|
|
1455
|
+
i0.ɵɵadvance(4);
|
|
1456
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.CreateTagDescription);
|
|
1457
|
+
i0.ɵɵadvance(2);
|
|
1458
|
+
i0.ɵɵproperty("disabled", !ctx_r1.CreateTagName.trim());
|
|
1459
|
+
} }
|
|
1460
|
+
function ClassifyTaxonomyTabComponent_Conditional_19_For_16_Template(rf, ctx) { if (rf & 1) {
|
|
1461
|
+
i0.ɵɵelementStart(0, "option", 225);
|
|
1462
|
+
i0.ɵɵtext(1);
|
|
1463
|
+
i0.ɵɵelementEnd();
|
|
1464
|
+
} if (rf & 2) {
|
|
1465
|
+
const opt_r42 = ctx.$implicit;
|
|
1466
|
+
i0.ɵɵproperty("ngValue", opt_r42.ID);
|
|
1467
|
+
i0.ɵɵadvance();
|
|
1468
|
+
i0.ɵɵtextInterpolate2("", "\u00A0\u00A0".repeat(opt_r42.Depth), "", opt_r42.Name);
|
|
1469
|
+
} }
|
|
1470
|
+
function ClassifyTaxonomyTabComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
1471
|
+
const _r41 = i0.ɵɵgetCurrentView();
|
|
1472
|
+
i0.ɵɵelementStart(0, "div", 210);
|
|
1473
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_19_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r41); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseMoveDialog()); });
|
|
1474
|
+
i0.ɵɵelementStart(1, "div", 211);
|
|
1475
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_19_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r41); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
1476
|
+
i0.ɵɵelementStart(2, "div", 212)(3, "h3");
|
|
1477
|
+
i0.ɵɵelement(4, "i", 82);
|
|
1478
|
+
i0.ɵɵtext(5, " Move Tag");
|
|
1479
|
+
i0.ɵɵelementEnd();
|
|
1480
|
+
i0.ɵɵelementStart(6, "button", 194);
|
|
1481
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_19_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r41); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseMoveDialog()); });
|
|
1482
|
+
i0.ɵɵelement(7, "i", 128);
|
|
1483
|
+
i0.ɵɵelementEnd()();
|
|
1484
|
+
i0.ɵɵelementStart(8, "div", 214)(9, "div", 218)(10, "label");
|
|
1485
|
+
i0.ɵɵtext(11, "New parent tag");
|
|
1486
|
+
i0.ɵɵelementEnd();
|
|
1487
|
+
i0.ɵɵelementStart(12, "select", 224);
|
|
1488
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTaxonomyTabComponent_Conditional_19_Template_select_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r41); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.MoveNewParentID, $event) || (ctx_r1.MoveNewParentID = $event); return i0.ɵɵresetView($event); });
|
|
1489
|
+
i0.ɵɵelementStart(13, "option", 225);
|
|
1490
|
+
i0.ɵɵtext(14, "(Root level \u2014 no parent)");
|
|
1491
|
+
i0.ɵɵelementEnd();
|
|
1492
|
+
i0.ɵɵrepeaterCreate(15, ClassifyTaxonomyTabComponent_Conditional_19_For_16_Template, 2, 3, "option", 225, _forTrack0);
|
|
1493
|
+
i0.ɵɵelementEnd()()();
|
|
1494
|
+
i0.ɵɵelementStart(17, "div", 216)(18, "button", 72);
|
|
1495
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_19_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r41); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ExecuteMove()); });
|
|
1496
|
+
i0.ɵɵelement(19, "i", 110);
|
|
1497
|
+
i0.ɵɵtext(20, " Move ");
|
|
1498
|
+
i0.ɵɵelementEnd();
|
|
1499
|
+
i0.ɵɵelementStart(21, "button", 73);
|
|
1500
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_19_Template_button_click_21_listener() { i0.ɵɵrestoreView(_r41); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseMoveDialog()); });
|
|
1501
|
+
i0.ɵɵtext(22, "Cancel");
|
|
1502
|
+
i0.ɵɵelementEnd()()()();
|
|
1503
|
+
} if (rf & 2) {
|
|
1504
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1505
|
+
i0.ɵɵadvance(12);
|
|
1506
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.MoveNewParentID);
|
|
1507
|
+
i0.ɵɵadvance();
|
|
1508
|
+
i0.ɵɵproperty("ngValue", null);
|
|
1509
|
+
i0.ɵɵadvance(2);
|
|
1510
|
+
i0.ɵɵrepeater(ctx_r1.GetMoveTargetOptions());
|
|
1511
|
+
} }
|
|
1512
|
+
function ClassifyTaxonomyTabComponent_Conditional_20_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
1513
|
+
i0.ɵɵelement(0, "i", 99);
|
|
1514
|
+
i0.ɵɵtext(1, " Merging... ");
|
|
1515
|
+
} }
|
|
1516
|
+
function ClassifyTaxonomyTabComponent_Conditional_20_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
1517
|
+
i0.ɵɵelement(0, "i", 83);
|
|
1518
|
+
i0.ɵɵtext(1, " Merge ");
|
|
1519
|
+
} }
|
|
1520
|
+
function ClassifyTaxonomyTabComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
1521
|
+
const _r43 = i0.ɵɵgetCurrentView();
|
|
1522
|
+
i0.ɵɵelementStart(0, "div", 210);
|
|
1523
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_20_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r43); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseMergeIntoDialog()); });
|
|
1524
|
+
i0.ɵɵelementStart(1, "div", 211);
|
|
1525
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_20_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r43); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
1526
|
+
i0.ɵɵelementStart(2, "div", 212)(3, "h3");
|
|
1527
|
+
i0.ɵɵelement(4, "i", 83);
|
|
1528
|
+
i0.ɵɵtext(5);
|
|
1529
|
+
i0.ɵɵelementEnd();
|
|
1530
|
+
i0.ɵɵelementStart(6, "button", 194);
|
|
1531
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_20_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r43); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseMergeIntoDialog()); });
|
|
1532
|
+
i0.ɵɵelement(7, "i", 128);
|
|
1533
|
+
i0.ɵɵelementEnd()();
|
|
1534
|
+
i0.ɵɵelementStart(8, "div", 214)(9, "p", 226);
|
|
1535
|
+
i0.ɵɵtext(10);
|
|
1536
|
+
i0.ɵɵelementEnd();
|
|
1537
|
+
i0.ɵɵelementStart(11, "div", 218)(12, "label");
|
|
1538
|
+
i0.ɵɵtext(13, "Merge into");
|
|
1539
|
+
i0.ɵɵelementEnd();
|
|
1540
|
+
i0.ɵɵelementStart(14, "mj-combobox", 227);
|
|
1541
|
+
i0.ɵɵlistener("ValueChange", function ClassifyTaxonomyTabComponent_Conditional_20_Template_mj_combobox_ValueChange_14_listener($event) { i0.ɵɵrestoreView(_r43); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnMergeTargetSelected($event)); });
|
|
1542
|
+
i0.ɵɵelementEnd()()();
|
|
1543
|
+
i0.ɵɵelementStart(15, "div", 216)(16, "button", 220);
|
|
1544
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_20_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r43); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ExecuteMergeInto()); });
|
|
1545
|
+
i0.ɵɵconditionalCreate(17, ClassifyTaxonomyTabComponent_Conditional_20_Conditional_17_Template, 2, 0)(18, ClassifyTaxonomyTabComponent_Conditional_20_Conditional_18_Template, 2, 0);
|
|
1546
|
+
i0.ɵɵelementEnd();
|
|
1547
|
+
i0.ɵɵelementStart(19, "button", 73);
|
|
1548
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Conditional_20_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r43); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseMergeIntoDialog()); });
|
|
1549
|
+
i0.ɵɵtext(20, "Cancel");
|
|
1550
|
+
i0.ɵɵelementEnd()()()();
|
|
1551
|
+
} if (rf & 2) {
|
|
1552
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1553
|
+
i0.ɵɵadvance(5);
|
|
1554
|
+
i0.ɵɵtextInterpolate1(" Merge \"", ctx_r1.MergeSourceTag == null ? null : ctx_r1.MergeSourceTag.Name, "\" Into...");
|
|
1555
|
+
i0.ɵɵadvance(5);
|
|
1556
|
+
i0.ɵɵtextInterpolate1(" All tagged items will be moved to the target tag, then \"", ctx_r1.MergeSourceTag == null ? null : ctx_r1.MergeSourceTag.Name, "\" will be deleted. ");
|
|
1557
|
+
i0.ɵɵadvance(4);
|
|
1558
|
+
i0.ɵɵproperty("Data", ctx_r1.MergeTargetData)("Filterable", true)("ValuePrimitive", true);
|
|
1559
|
+
i0.ɵɵadvance(2);
|
|
1560
|
+
i0.ɵɵproperty("disabled", !ctx_r1.MergeTargetID || ctx_r1.IsMerging);
|
|
1561
|
+
i0.ɵɵadvance();
|
|
1562
|
+
i0.ɵɵconditional(ctx_r1.IsMerging ? 17 : 18);
|
|
1563
|
+
} }
|
|
1564
|
+
export class ClassifyTaxonomyTabComponent extends BaseAngularComponent {
|
|
1565
|
+
cdr = inject(ChangeDetectorRef);
|
|
1566
|
+
/** Shared raw `MJ: Content Item Tags` rows, supplied by the host orchestrator. */
|
|
1567
|
+
_contentTags = [];
|
|
1568
|
+
set ContentTags(value) {
|
|
1569
|
+
this._contentTags = value ?? [];
|
|
1570
|
+
}
|
|
1571
|
+
get ContentTags() {
|
|
1572
|
+
return this._contentTags;
|
|
1573
|
+
}
|
|
1574
|
+
/** Fired after a governance mutation so the host can refresh its own surfaces if needed. */
|
|
1575
|
+
DataChanged = new EventEmitter();
|
|
1576
|
+
// ── Taxonomy Governance state ──
|
|
1577
|
+
TaxSubTab = 'tree';
|
|
1578
|
+
TaxTreeNodes = [];
|
|
1579
|
+
TaxFlatNodes = [];
|
|
1580
|
+
TaxFilteredNodes = [];
|
|
1581
|
+
TaxSelectedNode = null;
|
|
1582
|
+
TaxTreeSearch = '';
|
|
1583
|
+
TaxDuplicates = [];
|
|
1584
|
+
TaxOrphans = [];
|
|
1585
|
+
TaxAllOrphansSelected = false;
|
|
1586
|
+
TaxTreemapCells = [];
|
|
1587
|
+
TaxAuditEvents = [];
|
|
1588
|
+
TaxAuditFilterTypes = new Set(['created', 'merged', 'moved', 'deleted', 'renamed', 'deprecated', 'descriptionchanged', 'reactivated', 'split']);
|
|
1589
|
+
TaxHealth = { Total: 0, Healthy: 0, NeedAttention: 0, Orphaned: 0, Duplicates: 0 };
|
|
1590
|
+
TaxRecentItems = [];
|
|
1591
|
+
TaxTreemapKPIs = [];
|
|
1592
|
+
TaxIsEditing = false;
|
|
1593
|
+
// ── Create Tag Dialog ──
|
|
1594
|
+
ShowCreateTagDialog = false;
|
|
1595
|
+
CreateTagName = '';
|
|
1596
|
+
CreateTagDescription = '';
|
|
1597
|
+
CreateTagParentID = null;
|
|
1598
|
+
/** Label shown in the create dialog to indicate context (e.g., "under AI Agent") */
|
|
1599
|
+
CreateTagParentLabel = '';
|
|
1600
|
+
// ── Multi-select for drag reparenting ──
|
|
1601
|
+
TaxMultiSelectMode = false;
|
|
1602
|
+
TaxSelectedIDs = new Set();
|
|
1603
|
+
/** The node currently being dragged over (drop target highlight) */
|
|
1604
|
+
TaxDragOverNodeID = null;
|
|
1605
|
+
/** True while a drag-reparent operation is saving */
|
|
1606
|
+
TaxTreeSaving = false;
|
|
1607
|
+
/** Count of high-confidence duplicate pairs (>85% similarity) */
|
|
1608
|
+
get TaxHighConfidenceDupeCount() {
|
|
1609
|
+
return this.TaxDuplicates.filter(d => d.SeverityClass === 'high').length;
|
|
1610
|
+
}
|
|
1611
|
+
/** Count of moderate-confidence duplicate pairs (70-85% similarity) */
|
|
1612
|
+
get TaxModerateDupeCount() {
|
|
1613
|
+
return this.TaxDuplicates.filter(d => d.SeverityClass === 'moderate').length;
|
|
1614
|
+
}
|
|
1615
|
+
TaxEditName = '';
|
|
1616
|
+
TaxEditDescription = '';
|
|
1617
|
+
// ── Selected-node editor sub-tabs (Overview / Governance / Synonyms / Scope) ──
|
|
1618
|
+
/** Active sub-tab in the selected-node editor. Only visible when a node is selected. */
|
|
1619
|
+
TagEditorSubTab = 'overview';
|
|
1620
|
+
// ── Governance panel state ──
|
|
1621
|
+
/** The strongly-typed MJ: Tags entity backing the governance editor for the selected node. */
|
|
1622
|
+
GovernanceTag = null;
|
|
1623
|
+
/** True while the governance entity is loading. */
|
|
1624
|
+
GovernanceLoading = false;
|
|
1625
|
+
/** True while a governance save is in flight. */
|
|
1626
|
+
GovernanceSaving = false;
|
|
1627
|
+
/** Editable copies of the governance flags so we don't mutate the entity until Save(). */
|
|
1628
|
+
GovIsFrozen = false;
|
|
1629
|
+
GovAllowAutoGrow = false;
|
|
1630
|
+
GovRequiresReview = false;
|
|
1631
|
+
GovMaxChildren = null;
|
|
1632
|
+
GovMaxDescendantDepth = null;
|
|
1633
|
+
GovMinWeight = null;
|
|
1634
|
+
// ── Synonyms panel state ──
|
|
1635
|
+
/** Synonyms for the selected tag (typed entity objects, loaded lazily per-tag). */
|
|
1636
|
+
Synonyms = [];
|
|
1637
|
+
/** True while synonyms are loading. */
|
|
1638
|
+
SynonymsLoading = false;
|
|
1639
|
+
/** New synonym text to add. */
|
|
1640
|
+
NewSynonymText = '';
|
|
1641
|
+
/** True while a synonym add/delete is in flight. */
|
|
1642
|
+
SynonymSaving = false;
|
|
1643
|
+
// ── Scope panel state ──
|
|
1644
|
+
/** Scopes for the selected tag (typed entity objects, loaded lazily per-tag). */
|
|
1645
|
+
Scopes = [];
|
|
1646
|
+
/** True while scopes are loading. */
|
|
1647
|
+
ScopesLoading = false;
|
|
1648
|
+
/** True while a scope/global mutation is in flight. */
|
|
1649
|
+
ScopeSaving = false;
|
|
1650
|
+
/** Selected entity ID for the "Add scope" affordance. */
|
|
1651
|
+
NewScopeEntityID = null;
|
|
1652
|
+
/** RecordID text for the "Add scope" affordance. */
|
|
1653
|
+
NewScopeRecordID = '';
|
|
1654
|
+
// Raw taxonomy data cache
|
|
1655
|
+
tagsRaw = [];
|
|
1656
|
+
taggedItemsRaw = [];
|
|
1657
|
+
tagAuditLogsRaw = [];
|
|
1658
|
+
/** Cached per-tag aggregates from server-side SQL (weights + counts) */
|
|
1659
|
+
tagAggregateWeights = new Map();
|
|
1660
|
+
tagAggregateCounts = new Map();
|
|
1661
|
+
// ── Confirmation dialog state ──
|
|
1662
|
+
/** Whether a generic confirmation overlay is visible */
|
|
1663
|
+
ShowConfirmDialog = false;
|
|
1664
|
+
/** Title text for the confirmation dialog */
|
|
1665
|
+
ConfirmDialogTitle = '';
|
|
1666
|
+
/** Body message for the confirmation dialog */
|
|
1667
|
+
ConfirmDialogMessage = '';
|
|
1668
|
+
/** Callback invoked when user confirms */
|
|
1669
|
+
confirmDialogAction = null;
|
|
1670
|
+
// ── Split dialog state ──
|
|
1671
|
+
/** Whether the split-tag dialog is visible */
|
|
1672
|
+
ShowSplitDialog = false;
|
|
1673
|
+
/** Comma-separated new child tag names for the split operation */
|
|
1674
|
+
SplitChildNames = '';
|
|
1675
|
+
/** The node currently being split */
|
|
1676
|
+
splitTargetNode = null;
|
|
1677
|
+
// ── Move dialog state ──
|
|
1678
|
+
/** Whether the move-tag dialog is visible */
|
|
1679
|
+
ShowMoveDialog = false;
|
|
1680
|
+
/** Selected new parent tag ID for the move operation */
|
|
1681
|
+
MoveNewParentID = null;
|
|
1682
|
+
/** The node currently being moved */
|
|
1683
|
+
moveTargetNode = null;
|
|
1684
|
+
// ── Merge Into dialog state ──
|
|
1685
|
+
ShowMergeIntoDialog = false;
|
|
1686
|
+
MergeSourceTag = null;
|
|
1687
|
+
MergeTargetID = null;
|
|
1688
|
+
MergeTargetData = [];
|
|
1689
|
+
// ── Treemap drill-in state ──
|
|
1690
|
+
/** Whether the treemap drill-in panel is visible */
|
|
1691
|
+
ShowTreemapDrillIn = false;
|
|
1692
|
+
/** Tag node currently displayed in treemap drill-in */
|
|
1693
|
+
TreemapDrillInNode = null;
|
|
1694
|
+
IsMerging = false;
|
|
1695
|
+
/** Subtitle rendered in the per-section `<mj-page-header-interior>`. */
|
|
1696
|
+
get Subtitle() {
|
|
1697
|
+
return `Manage tag hierarchy, resolve duplicates, and monitor taxonomy health — ${this.TaxHealth.Total} total tags`;
|
|
1698
|
+
}
|
|
1699
|
+
async ngOnInit() {
|
|
1700
|
+
await this.loadTaxonomyData();
|
|
1701
|
+
}
|
|
1702
|
+
/** Taxonomy sub-tabs as `TabConfig[]` for `<mj-tab-nav>`. */
|
|
1703
|
+
get taxSubTabsConfig() {
|
|
1704
|
+
return [
|
|
1705
|
+
{ key: 'tree', label: 'Tree View', icon: 'fa-solid fa-sitemap' },
|
|
1706
|
+
{ key: 'duplicates', label: 'Duplicates', icon: 'fa-solid fa-link',
|
|
1707
|
+
badge: this.TaxDuplicates.length > 0 ? this.TaxDuplicates.length : null,
|
|
1708
|
+
badgeVariant: 'warning' },
|
|
1709
|
+
{ key: 'orphans', label: 'Orphans', icon: 'fa-solid fa-ban',
|
|
1710
|
+
badge: this.TaxOrphans.length > 0 ? this.TaxOrphans.length : null,
|
|
1711
|
+
badgeVariant: 'error' },
|
|
1712
|
+
{ key: 'treemap', label: 'Treemap', icon: 'fa-solid fa-chart-tree-map' },
|
|
1713
|
+
{ key: 'audit', label: 'Audit Log', icon: 'fa-solid fa-scroll' }
|
|
1714
|
+
];
|
|
1715
|
+
}
|
|
1716
|
+
/** Adapter for `<mj-tab-nav>`'s string-typed `(TabChange)` output. */
|
|
1717
|
+
onTaxSubTabChange(key) {
|
|
1718
|
+
if (key === 'tree' || key === 'duplicates' || key === 'orphans' || key === 'treemap' || key === 'audit') {
|
|
1719
|
+
this.SwitchTaxSubTab(key);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
SwitchTaxSubTab(sub) {
|
|
1723
|
+
this.TaxSubTab = sub;
|
|
1724
|
+
this.cdr.detectChanges();
|
|
1725
|
+
}
|
|
1726
|
+
/**
|
|
1727
|
+
* Loads all data needed by the Taxonomy Governance sub-tabs:
|
|
1728
|
+
* Tags, Tagged Items, Tag Audit Logs, and cross-references content item tags.
|
|
1729
|
+
*/
|
|
1730
|
+
async loadTaxonomyData() {
|
|
1731
|
+
try {
|
|
1732
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1733
|
+
const [tagsResult, taggedItemsResult, auditResult] = await rv.RunViews([
|
|
1734
|
+
{ EntityName: 'MJ: Tags', OrderBy: 'Name', ResultType: 'simple' },
|
|
1735
|
+
{ EntityName: 'MJ: Tagged Items', ResultType: 'simple' },
|
|
1736
|
+
{ EntityName: 'MJ: Tag Audit Logs', OrderBy: '__mj_CreatedAt DESC', MaxRows: 200, ResultType: 'simple' }
|
|
1737
|
+
]);
|
|
1738
|
+
this.tagsRaw = tagsResult.Success ? tagsResult.Results : [];
|
|
1739
|
+
this.taggedItemsRaw = taggedItemsResult.Success ? taggedItemsResult.Results : [];
|
|
1740
|
+
this.tagAuditLogsRaw = auditResult.Success ? auditResult.Results : [];
|
|
1741
|
+
// Load per-tag aggregates (weights + counts) via server-side SQL
|
|
1742
|
+
await this.loadTagAggregates();
|
|
1743
|
+
this.buildTaxTree();
|
|
1744
|
+
this.buildTaxDuplicates();
|
|
1745
|
+
this.buildTaxOrphans();
|
|
1746
|
+
this.buildTaxTreemap();
|
|
1747
|
+
this.buildTaxAuditLog();
|
|
1748
|
+
this.buildTaxHealth();
|
|
1749
|
+
this.cdr.detectChanges();
|
|
1750
|
+
}
|
|
1751
|
+
catch (error) {
|
|
1752
|
+
console.error('[Autotagging] Error loading taxonomy data:', error);
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
// ── Tree View ──
|
|
1756
|
+
/**
|
|
1757
|
+
* Builds the taxonomy tree from raw tag data, wiring up parent-child
|
|
1758
|
+
* relationships and attaching item counts and average weights.
|
|
1759
|
+
*/
|
|
1760
|
+
buildTaxTree() {
|
|
1761
|
+
const tagMap = new Map();
|
|
1762
|
+
const tagItemCounts = this.tagAggregateCounts;
|
|
1763
|
+
const tagAvgWeights = this.tagAggregateWeights;
|
|
1764
|
+
// Create flat node list from raw tags (exclude merged/soft-deleted tags)
|
|
1765
|
+
const activeTags = this.tagsRaw.filter(t => t['Status']?.toLowerCase() !== 'merged');
|
|
1766
|
+
for (const tag of activeTags) {
|
|
1767
|
+
const id = tag['ID'];
|
|
1768
|
+
const normalizedId = NormalizeUUID(id);
|
|
1769
|
+
const name = tag['Name'] ?? 'Unnamed';
|
|
1770
|
+
const itemCount = tagItemCounts.get(normalizedId) ?? 0;
|
|
1771
|
+
const avgWeight = tagAvgWeights.get(normalizedId) ?? 0;
|
|
1772
|
+
tagMap.set(normalizedId, {
|
|
1773
|
+
ID: id,
|
|
1774
|
+
Name: name,
|
|
1775
|
+
DisplayName: tag['DisplayName'] ?? name,
|
|
1776
|
+
Description: tag['Description'] ?? '',
|
|
1777
|
+
ParentID: tag['ParentID'] ?? null,
|
|
1778
|
+
Depth: 0,
|
|
1779
|
+
Children: [],
|
|
1780
|
+
ItemCount: itemCount,
|
|
1781
|
+
AvgWeight: avgWeight,
|
|
1782
|
+
HealthColor: this.computeTagHealth(itemCount, avgWeight),
|
|
1783
|
+
IsExpanded: false,
|
|
1784
|
+
IsSelected: false,
|
|
1785
|
+
FirstSeen: formatShortDate(tag['__mj_CreatedAt'] ?? '')
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
// Build parent-child relationships
|
|
1789
|
+
const roots = [];
|
|
1790
|
+
for (const node of tagMap.values()) {
|
|
1791
|
+
const normalizedParent = node.ParentID ? NormalizeUUID(node.ParentID) : null;
|
|
1792
|
+
if (normalizedParent && tagMap.has(normalizedParent)) {
|
|
1793
|
+
tagMap.get(normalizedParent).Children.push(node);
|
|
1794
|
+
}
|
|
1795
|
+
else {
|
|
1796
|
+
roots.push(node);
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
// Compute depths and aggregate child counts
|
|
1800
|
+
this.computeTreeDepths(roots, 0);
|
|
1801
|
+
this.propagateItemCounts(roots);
|
|
1802
|
+
// Sort children alphabetically
|
|
1803
|
+
this.sortTreeNodes(roots);
|
|
1804
|
+
// Expand top two levels by default
|
|
1805
|
+
for (const root of roots) {
|
|
1806
|
+
root.IsExpanded = true;
|
|
1807
|
+
for (const child of root.Children) {
|
|
1808
|
+
child.IsExpanded = true;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
this.TaxTreeNodes = roots;
|
|
1812
|
+
this.TaxFlatNodes = this.flattenTree(roots);
|
|
1813
|
+
this.TaxFilteredNodes = this.TaxFlatNodes;
|
|
1814
|
+
// Select first node if available
|
|
1815
|
+
if (this.TaxFlatNodes.length > 0) {
|
|
1816
|
+
this.SelectTaxNode(this.TaxFlatNodes[0]);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
computeTreeDepths(nodes, depth) {
|
|
1820
|
+
for (const node of nodes) {
|
|
1821
|
+
node.Depth = depth;
|
|
1822
|
+
this.computeTreeDepths(node.Children, depth + 1);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
propagateItemCounts(nodes) {
|
|
1826
|
+
let total = 0;
|
|
1827
|
+
for (const node of nodes) {
|
|
1828
|
+
const childCount = this.propagateItemCounts(node.Children);
|
|
1829
|
+
node.ItemCount = node.ItemCount + childCount;
|
|
1830
|
+
total += node.ItemCount;
|
|
1831
|
+
}
|
|
1832
|
+
return total;
|
|
1833
|
+
}
|
|
1834
|
+
sortTreeNodes(nodes) {
|
|
1835
|
+
nodes.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
1836
|
+
for (const node of nodes) {
|
|
1837
|
+
this.sortTreeNodes(node.Children);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
flattenTree(nodes) {
|
|
1841
|
+
const result = [];
|
|
1842
|
+
for (const node of nodes) {
|
|
1843
|
+
result.push(node);
|
|
1844
|
+
if (node.IsExpanded && node.Children.length > 0) {
|
|
1845
|
+
result.push(...this.flattenTree(node.Children));
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
return result;
|
|
1849
|
+
}
|
|
1850
|
+
computeTagHealth(itemCount, avgWeight) {
|
|
1851
|
+
if (itemCount === 0)
|
|
1852
|
+
return 'red';
|
|
1853
|
+
if (itemCount <= 2 || avgWeight < 0.3)
|
|
1854
|
+
return 'yellow';
|
|
1855
|
+
return 'green';
|
|
1856
|
+
}
|
|
1857
|
+
/**
|
|
1858
|
+
* Counts the number of items referencing each tag, combining both
|
|
1859
|
+
* Tagged Items and Content Item Tags. Uses NormalizeUUID for
|
|
1860
|
+
* cross-platform UUID case consistency.
|
|
1861
|
+
*/
|
|
1862
|
+
countItemsByTag() {
|
|
1863
|
+
const counts = new Map();
|
|
1864
|
+
for (const ti of this.taggedItemsRaw) {
|
|
1865
|
+
const tagId = ti['TagID'];
|
|
1866
|
+
if (tagId) {
|
|
1867
|
+
const key = NormalizeUUID(tagId);
|
|
1868
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
// Also count from content item tags that reference TagID
|
|
1872
|
+
for (const cit of this._contentTags) {
|
|
1873
|
+
const tagId = cit['TagID'];
|
|
1874
|
+
if (tagId) {
|
|
1875
|
+
const key = NormalizeUUID(tagId);
|
|
1876
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
return counts;
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* Loads per-tag average weights and item counts via the "Tag Aggregates" saved query.
|
|
1883
|
+
* This runs a SQL GROUP BY on the server, avoiding loading 17K+ TaggedItem rows to the browser.
|
|
1884
|
+
*/
|
|
1885
|
+
async loadTagAggregates() {
|
|
1886
|
+
this.tagAggregateWeights.clear();
|
|
1887
|
+
this.tagAggregateCounts.clear();
|
|
1888
|
+
try {
|
|
1889
|
+
const rq = new RunQuery();
|
|
1890
|
+
const result = await rq.RunQuery({
|
|
1891
|
+
QueryName: 'Tag Aggregates',
|
|
1892
|
+
CategoryPath: '/MJ/Tags'
|
|
1893
|
+
});
|
|
1894
|
+
if (result.Success) {
|
|
1895
|
+
for (const row of result.Results) {
|
|
1896
|
+
const tagId = row['TagID'];
|
|
1897
|
+
if (tagId) {
|
|
1898
|
+
const key = NormalizeUUID(tagId);
|
|
1899
|
+
this.tagAggregateWeights.set(key, Number(row['AvgWeight'] ?? 0));
|
|
1900
|
+
this.tagAggregateCounts.set(key, Number(row['ItemCount'] ?? 0));
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
catch (error) {
|
|
1906
|
+
console.error('[Autotagging] Error loading tag aggregates:', error);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
ToggleTaxNode(node) {
|
|
1910
|
+
if (node.Children.length > 0) {
|
|
1911
|
+
node.IsExpanded = !node.IsExpanded;
|
|
1912
|
+
this.TaxFlatNodes = this.flattenTree(this.TaxTreeNodes);
|
|
1913
|
+
this.applyTaxTreeFilter();
|
|
1914
|
+
this.cdr.detectChanges();
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
SelectTaxNode(node) {
|
|
1918
|
+
// Deselect previous
|
|
1919
|
+
for (const n of this.TaxFlatNodes) {
|
|
1920
|
+
n.IsSelected = false;
|
|
1921
|
+
}
|
|
1922
|
+
node.IsSelected = true;
|
|
1923
|
+
this.TaxSelectedNode = node;
|
|
1924
|
+
this.TaxIsEditing = false;
|
|
1925
|
+
this.resetEditorPanels();
|
|
1926
|
+
this.loadRecentItemsForTag(node);
|
|
1927
|
+
// Lazy-load the data for whichever sub-tab is currently active.
|
|
1928
|
+
void this.ensureEditorSubTabLoaded();
|
|
1929
|
+
this.cdr.detectChanges();
|
|
1930
|
+
}
|
|
1931
|
+
/**
|
|
1932
|
+
* Clears the lazily-loaded governance/synonyms/scope panel state so a newly
|
|
1933
|
+
* selected node starts fresh. Data is re-fetched on demand when its sub-tab opens.
|
|
1934
|
+
*/
|
|
1935
|
+
resetEditorPanels() {
|
|
1936
|
+
this.GovernanceTag = null;
|
|
1937
|
+
this.Synonyms = [];
|
|
1938
|
+
this.Scopes = [];
|
|
1939
|
+
this.NewSynonymText = '';
|
|
1940
|
+
this.NewScopeEntityID = null;
|
|
1941
|
+
this.NewScopeRecordID = '';
|
|
1942
|
+
}
|
|
1943
|
+
FilterTaxTree() {
|
|
1944
|
+
this.applyTaxTreeFilter();
|
|
1945
|
+
this.cdr.detectChanges();
|
|
1946
|
+
}
|
|
1947
|
+
applyTaxTreeFilter() {
|
|
1948
|
+
const q = this.TaxTreeSearch.toLowerCase().trim();
|
|
1949
|
+
if (!q) {
|
|
1950
|
+
this.TaxFilteredNodes = this.TaxFlatNodes;
|
|
1951
|
+
}
|
|
1952
|
+
else {
|
|
1953
|
+
this.TaxFilteredNodes = this.TaxFlatNodes.filter(n => n.Name.toLowerCase().includes(q) || n.DisplayName.toLowerCase().includes(q));
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
GetTaxBreadcrumb(node) {
|
|
1957
|
+
const breadcrumb = [];
|
|
1958
|
+
const tagMap = new Map();
|
|
1959
|
+
for (const t of this.tagsRaw) {
|
|
1960
|
+
tagMap.set(t['ID'], t);
|
|
1961
|
+
}
|
|
1962
|
+
let currentID = node.ParentID;
|
|
1963
|
+
while (currentID) {
|
|
1964
|
+
const parent = tagMap.get(currentID);
|
|
1965
|
+
if (!parent)
|
|
1966
|
+
break;
|
|
1967
|
+
breadcrumb.unshift({ ID: currentID, Name: parent['Name'] ?? '' });
|
|
1968
|
+
currentID = parent['ParentID'] ?? null;
|
|
1969
|
+
}
|
|
1970
|
+
return breadcrumb;
|
|
1971
|
+
}
|
|
1972
|
+
NavigateToBreadcrumb(tagId) {
|
|
1973
|
+
const node = this.TaxFlatNodes.find(n => UUIDsEqual(n.ID, tagId));
|
|
1974
|
+
if (node) {
|
|
1975
|
+
this.SelectTaxNode(node);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
loadRecentItemsForTag(node) {
|
|
1979
|
+
// Find content item tags that reference this tag's ID.
|
|
1980
|
+
// Use the 'Item' view field (ContentItem name) directly from the tag record
|
|
1981
|
+
// instead of looking up from the capped contentItemsRaw array.
|
|
1982
|
+
const matchingTags = this._contentTags.filter(cit => UUIDsEqual(cit['TagID'], node.ID)).slice(0, 5);
|
|
1983
|
+
this.TaxRecentItems = matchingTags.map(cit => ({
|
|
1984
|
+
Name: cit['Item'] ?? 'Unnamed Item',
|
|
1985
|
+
Weight: Number(cit['Weight'] ?? 0.5),
|
|
1986
|
+
Date: formatShortDate(cit['__mj_CreatedAt'] ?? ''),
|
|
1987
|
+
Icon: 'fa-solid fa-file-lines'
|
|
1988
|
+
}));
|
|
1989
|
+
}
|
|
1990
|
+
// ── Selected-Node Editor Sub-Tabs ──
|
|
1991
|
+
/**
|
|
1992
|
+
* Switches the selected-node editor sub-tab and lazy-loads the data for
|
|
1993
|
+
* the newly opened sub-tab if it hasn't been fetched yet for this node.
|
|
1994
|
+
*/
|
|
1995
|
+
SwitchTagEditorSubTab(sub) {
|
|
1996
|
+
this.TagEditorSubTab = sub;
|
|
1997
|
+
void this.ensureEditorSubTabLoaded();
|
|
1998
|
+
this.cdr.detectChanges();
|
|
1999
|
+
}
|
|
2000
|
+
/** Loads the data backing the currently active editor sub-tab on demand. */
|
|
2001
|
+
async ensureEditorSubTabLoaded() {
|
|
2002
|
+
if (!this.TaxSelectedNode)
|
|
2003
|
+
return;
|
|
2004
|
+
switch (this.TagEditorSubTab) {
|
|
2005
|
+
case 'governance':
|
|
2006
|
+
if (!this.GovernanceTag)
|
|
2007
|
+
await this.loadGovernanceTag();
|
|
2008
|
+
break;
|
|
2009
|
+
case 'synonyms':
|
|
2010
|
+
await this.loadSynonyms();
|
|
2011
|
+
break;
|
|
2012
|
+
case 'scope':
|
|
2013
|
+
if (!this.GovernanceTag)
|
|
2014
|
+
await this.loadGovernanceTag();
|
|
2015
|
+
await this.loadScopes();
|
|
2016
|
+
break;
|
|
2017
|
+
default:
|
|
2018
|
+
break;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
// ── Governance Panel ──
|
|
2022
|
+
/** Lazy-loads the strongly-typed MJ: Tags entity for the selected node. */
|
|
2023
|
+
async loadGovernanceTag() {
|
|
2024
|
+
if (!this.TaxSelectedNode)
|
|
2025
|
+
return;
|
|
2026
|
+
this.GovernanceLoading = true;
|
|
2027
|
+
this.cdr.detectChanges();
|
|
2028
|
+
try {
|
|
2029
|
+
const p = this.ProviderToUse;
|
|
2030
|
+
const tag = await p.GetEntityObject('MJ: Tags', p.CurrentUser);
|
|
2031
|
+
const loaded = await tag.Load(this.TaxSelectedNode.ID);
|
|
2032
|
+
if (loaded) {
|
|
2033
|
+
this.GovernanceTag = tag;
|
|
2034
|
+
this.syncGovernanceFromEntity(tag);
|
|
2035
|
+
}
|
|
2036
|
+
else {
|
|
2037
|
+
this.GovernanceTag = null;
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
catch (error) {
|
|
2041
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2042
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error loading governance: ${msg}`, 'error', 4000);
|
|
2043
|
+
}
|
|
2044
|
+
this.GovernanceLoading = false;
|
|
2045
|
+
this.cdr.detectChanges();
|
|
2046
|
+
}
|
|
2047
|
+
/** Copies governance flags from the entity into the editable view fields. */
|
|
2048
|
+
syncGovernanceFromEntity(tag) {
|
|
2049
|
+
this.GovIsFrozen = tag.IsFrozen;
|
|
2050
|
+
this.GovAllowAutoGrow = tag.AllowAutoGrow;
|
|
2051
|
+
this.GovRequiresReview = tag.RequiresReview;
|
|
2052
|
+
this.GovMaxChildren = tag.MaxChildren;
|
|
2053
|
+
this.GovMaxDescendantDepth = tag.MaxDescendantDepth;
|
|
2054
|
+
this.GovMinWeight = tag.MinWeight;
|
|
2055
|
+
}
|
|
2056
|
+
/** A one-line subtree-impact hint derived from the selected tree node. */
|
|
2057
|
+
get GovernanceImpactHint() {
|
|
2058
|
+
const node = this.TaxSelectedNode;
|
|
2059
|
+
if (!node)
|
|
2060
|
+
return '';
|
|
2061
|
+
const children = node.Children.length;
|
|
2062
|
+
const items = node.ItemCount;
|
|
2063
|
+
return `Affects ${children} direct child${children === 1 ? '' : 'ren'} and ${items} tagged item${items === 1 ? '' : 's'} in this subtree.`;
|
|
2064
|
+
}
|
|
2065
|
+
/** Resets the governance editor fields back to the loaded entity values. */
|
|
2066
|
+
ResetGovernance() {
|
|
2067
|
+
if (this.GovernanceTag) {
|
|
2068
|
+
this.syncGovernanceFromEntity(this.GovernanceTag);
|
|
2069
|
+
this.cdr.detectChanges();
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
/** Persists the edited governance flags to the MJ: Tags entity. */
|
|
2073
|
+
async SaveGovernance() {
|
|
2074
|
+
const tag = this.GovernanceTag;
|
|
2075
|
+
if (!tag)
|
|
2076
|
+
return;
|
|
2077
|
+
this.GovernanceSaving = true;
|
|
2078
|
+
this.cdr.detectChanges();
|
|
2079
|
+
try {
|
|
2080
|
+
tag.IsFrozen = this.GovIsFrozen;
|
|
2081
|
+
tag.AllowAutoGrow = this.GovAllowAutoGrow;
|
|
2082
|
+
tag.RequiresReview = this.GovRequiresReview;
|
|
2083
|
+
tag.MaxChildren = this.GovMaxChildren;
|
|
2084
|
+
tag.MaxDescendantDepth = this.GovMaxDescendantDepth;
|
|
2085
|
+
tag.MinWeight = this.GovMinWeight;
|
|
2086
|
+
const saved = await tag.Save();
|
|
2087
|
+
if (saved) {
|
|
2088
|
+
this.syncGovernanceFromEntity(tag);
|
|
2089
|
+
MJNotificationService.Instance.CreateSimpleNotification('Governance saved', 'success', 2500);
|
|
2090
|
+
this.DataChanged.emit();
|
|
2091
|
+
}
|
|
2092
|
+
else {
|
|
2093
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to save governance: ${tag.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
catch (error) {
|
|
2097
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2098
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2099
|
+
}
|
|
2100
|
+
this.GovernanceSaving = false;
|
|
2101
|
+
this.cdr.detectChanges();
|
|
2102
|
+
}
|
|
2103
|
+
// ── Synonyms Panel ──
|
|
2104
|
+
/** Lazy-loads MJ: Tag Synonyms rows for the selected tag. */
|
|
2105
|
+
async loadSynonyms() {
|
|
2106
|
+
if (!this.TaxSelectedNode)
|
|
2107
|
+
return;
|
|
2108
|
+
this.SynonymsLoading = true;
|
|
2109
|
+
this.cdr.detectChanges();
|
|
2110
|
+
try {
|
|
2111
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2112
|
+
const result = await rv.RunView({
|
|
2113
|
+
EntityName: 'MJ: Tag Synonyms',
|
|
2114
|
+
ExtraFilter: `TagID='${this.TaxSelectedNode.ID}'`,
|
|
2115
|
+
OrderBy: 'Synonym',
|
|
2116
|
+
ResultType: 'entity_object'
|
|
2117
|
+
});
|
|
2118
|
+
this.Synonyms = result.Success ? result.Results : [];
|
|
2119
|
+
}
|
|
2120
|
+
catch (error) {
|
|
2121
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2122
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error loading synonyms: ${msg}`, 'error', 4000);
|
|
2123
|
+
this.Synonyms = [];
|
|
2124
|
+
}
|
|
2125
|
+
this.SynonymsLoading = false;
|
|
2126
|
+
this.cdr.detectChanges();
|
|
2127
|
+
}
|
|
2128
|
+
/** Returns a colored-pill CSS class for a synonym Source. */
|
|
2129
|
+
GetSynonymSourceClass(source) {
|
|
2130
|
+
switch (source) {
|
|
2131
|
+
case 'Manual': return 'at-syn-pill-manual';
|
|
2132
|
+
case 'LLM': return 'at-syn-pill-llm';
|
|
2133
|
+
case 'Imported': return 'at-syn-pill-imported';
|
|
2134
|
+
case 'Merged': return 'at-syn-pill-merged';
|
|
2135
|
+
default: return 'at-syn-pill-manual';
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
/** Creates a new Manual synonym for the selected tag. */
|
|
2139
|
+
async AddSynonym() {
|
|
2140
|
+
const text = this.NewSynonymText.trim();
|
|
2141
|
+
if (!text || !this.TaxSelectedNode)
|
|
2142
|
+
return;
|
|
2143
|
+
this.SynonymSaving = true;
|
|
2144
|
+
this.cdr.detectChanges();
|
|
2145
|
+
try {
|
|
2146
|
+
const p = this.ProviderToUse;
|
|
2147
|
+
const syn = await p.GetEntityObject('MJ: Tag Synonyms', p.CurrentUser);
|
|
2148
|
+
syn.NewRecord();
|
|
2149
|
+
syn.TagID = this.TaxSelectedNode.ID;
|
|
2150
|
+
syn.Synonym = text;
|
|
2151
|
+
syn.Source = 'Manual';
|
|
2152
|
+
// Manually-added synonyms are trusted and resolve immediately.
|
|
2153
|
+
// Machine-proposed synonyms (Source = LLM/Imported) arrive as 'Pending'
|
|
2154
|
+
// and only resolve once approved via ApproveSynonym() below.
|
|
2155
|
+
syn.Status = 'Active';
|
|
2156
|
+
const saved = await syn.Save();
|
|
2157
|
+
if (saved) {
|
|
2158
|
+
this.NewSynonymText = '';
|
|
2159
|
+
MJNotificationService.Instance.CreateSimpleNotification('Synonym added', 'success', 2500);
|
|
2160
|
+
await this.loadSynonyms();
|
|
2161
|
+
}
|
|
2162
|
+
else {
|
|
2163
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to add synonym: ${syn.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
catch (error) {
|
|
2167
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2168
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2169
|
+
}
|
|
2170
|
+
this.SynonymSaving = false;
|
|
2171
|
+
this.cdr.detectChanges();
|
|
2172
|
+
}
|
|
2173
|
+
/** Deletes a synonym row. */
|
|
2174
|
+
async DeleteSynonym(syn) {
|
|
2175
|
+
this.SynonymSaving = true;
|
|
2176
|
+
this.cdr.detectChanges();
|
|
2177
|
+
try {
|
|
2178
|
+
const deleted = await syn.Delete();
|
|
2179
|
+
if (deleted) {
|
|
2180
|
+
this.Synonyms = this.Synonyms.filter(s => !UUIDsEqual(s.ID, syn.ID));
|
|
2181
|
+
MJNotificationService.Instance.CreateSimpleNotification('Synonym removed', 'success', 2500);
|
|
2182
|
+
}
|
|
2183
|
+
else {
|
|
2184
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to remove synonym: ${syn.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
catch (error) {
|
|
2188
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2189
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2190
|
+
}
|
|
2191
|
+
this.SynonymSaving = false;
|
|
2192
|
+
this.cdr.detectChanges();
|
|
2193
|
+
}
|
|
2194
|
+
/** Count of synonyms awaiting review (Source = LLM/Imported, Status = Pending). */
|
|
2195
|
+
get PendingSynonymCount() {
|
|
2196
|
+
return this.Synonyms.filter(s => s.Status === 'Pending').length;
|
|
2197
|
+
}
|
|
2198
|
+
/** Approves a pending (machine-proposed) synonym so it begins resolving to its tag. */
|
|
2199
|
+
async ApproveSynonym(syn) {
|
|
2200
|
+
await this.setSynonymStatus(syn, 'Active', 'Synonym approved');
|
|
2201
|
+
}
|
|
2202
|
+
/** Rejects a pending synonym; retained for audit and to suppress re-proposal. */
|
|
2203
|
+
async RejectSynonym(syn) {
|
|
2204
|
+
await this.setSynonymStatus(syn, 'Rejected', 'Synonym rejected');
|
|
2205
|
+
}
|
|
2206
|
+
/** Shared transition for approve/reject of a synonym's Status. */
|
|
2207
|
+
async setSynonymStatus(syn, status, successMsg) {
|
|
2208
|
+
this.SynonymSaving = true;
|
|
2209
|
+
this.cdr.detectChanges();
|
|
2210
|
+
try {
|
|
2211
|
+
syn.Status = status;
|
|
2212
|
+
const saved = await syn.Save();
|
|
2213
|
+
if (saved) {
|
|
2214
|
+
MJNotificationService.Instance.CreateSimpleNotification(successMsg, 'success', 2500);
|
|
2215
|
+
await this.loadSynonyms();
|
|
2216
|
+
}
|
|
2217
|
+
else {
|
|
2218
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to update synonym: ${syn.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
catch (error) {
|
|
2222
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2223
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2224
|
+
}
|
|
2225
|
+
this.SynonymSaving = false;
|
|
2226
|
+
this.cdr.detectChanges();
|
|
2227
|
+
}
|
|
2228
|
+
// ── Scope Panel ──
|
|
2229
|
+
/** Entity options for the "Add scope" combobox, sorted by name. */
|
|
2230
|
+
get ScopeEntityOptions() {
|
|
2231
|
+
return this.ProviderToUse.Entities
|
|
2232
|
+
.map(e => ({ ID: e.ID, Name: e.Name }))
|
|
2233
|
+
.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
2234
|
+
}
|
|
2235
|
+
/** Whether the selected tag is global (read from the governance entity). */
|
|
2236
|
+
get IsTagGlobal() {
|
|
2237
|
+
return this.GovernanceTag?.IsGlobal ?? false;
|
|
2238
|
+
}
|
|
2239
|
+
/** Lazy-loads MJ: Tag Scopes rows for the selected tag. */
|
|
2240
|
+
async loadScopes() {
|
|
2241
|
+
if (!this.TaxSelectedNode)
|
|
2242
|
+
return;
|
|
2243
|
+
this.ScopesLoading = true;
|
|
2244
|
+
this.cdr.detectChanges();
|
|
2245
|
+
try {
|
|
2246
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2247
|
+
const result = await rv.RunView({
|
|
2248
|
+
EntityName: 'MJ: Tag Scopes',
|
|
2249
|
+
ExtraFilter: `TagID='${this.TaxSelectedNode.ID}'`,
|
|
2250
|
+
OrderBy: 'ScopeEntity',
|
|
2251
|
+
ResultType: 'entity_object'
|
|
2252
|
+
});
|
|
2253
|
+
this.Scopes = result.Success ? result.Results : [];
|
|
2254
|
+
}
|
|
2255
|
+
catch (error) {
|
|
2256
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2257
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error loading scopes: ${msg}`, 'error', 4000);
|
|
2258
|
+
this.Scopes = [];
|
|
2259
|
+
}
|
|
2260
|
+
this.ScopesLoading = false;
|
|
2261
|
+
this.cdr.detectChanges();
|
|
2262
|
+
}
|
|
2263
|
+
/** Adapter for the entity combobox's string-typed value output. */
|
|
2264
|
+
OnScopeEntitySelected(value) {
|
|
2265
|
+
this.NewScopeEntityID = value != null ? String(value) : null;
|
|
2266
|
+
}
|
|
2267
|
+
/** Toggles the tag's IsGlobal flag and persists it. */
|
|
2268
|
+
async ToggleTagGlobal(value) {
|
|
2269
|
+
if (!this.GovernanceTag)
|
|
2270
|
+
return;
|
|
2271
|
+
this.ScopeSaving = true;
|
|
2272
|
+
this.cdr.detectChanges();
|
|
2273
|
+
try {
|
|
2274
|
+
this.GovernanceTag.IsGlobal = value;
|
|
2275
|
+
const saved = await this.GovernanceTag.Save();
|
|
2276
|
+
if (saved) {
|
|
2277
|
+
MJNotificationService.Instance.CreateSimpleNotification(value ? 'Tag is now global' : 'Tag is now scoped', 'success', 2500);
|
|
2278
|
+
this.DataChanged.emit();
|
|
2279
|
+
}
|
|
2280
|
+
else {
|
|
2281
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to update scope: ${this.GovernanceTag.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
catch (error) {
|
|
2285
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2286
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2287
|
+
}
|
|
2288
|
+
this.ScopeSaving = false;
|
|
2289
|
+
this.cdr.detectChanges();
|
|
2290
|
+
}
|
|
2291
|
+
/** Creates a new MJ: Tag Scopes row for the selected tag. */
|
|
2292
|
+
async AddScope() {
|
|
2293
|
+
const entityId = this.NewScopeEntityID;
|
|
2294
|
+
const recordId = this.NewScopeRecordID.trim();
|
|
2295
|
+
if (!entityId || !recordId || !this.TaxSelectedNode)
|
|
2296
|
+
return;
|
|
2297
|
+
this.ScopeSaving = true;
|
|
2298
|
+
this.cdr.detectChanges();
|
|
2299
|
+
try {
|
|
2300
|
+
const p = this.ProviderToUse;
|
|
2301
|
+
const scope = await p.GetEntityObject('MJ: Tag Scopes', p.CurrentUser);
|
|
2302
|
+
scope.NewRecord();
|
|
2303
|
+
scope.TagID = this.TaxSelectedNode.ID;
|
|
2304
|
+
scope.ScopeEntityID = entityId;
|
|
2305
|
+
scope.ScopeRecordID = recordId;
|
|
2306
|
+
const saved = await scope.Save();
|
|
2307
|
+
if (saved) {
|
|
2308
|
+
this.NewScopeEntityID = null;
|
|
2309
|
+
this.NewScopeRecordID = '';
|
|
2310
|
+
MJNotificationService.Instance.CreateSimpleNotification('Scope added', 'success', 2500);
|
|
2311
|
+
await this.loadScopes();
|
|
2312
|
+
}
|
|
2313
|
+
else {
|
|
2314
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to add scope: ${scope.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
catch (error) {
|
|
2318
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2319
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2320
|
+
}
|
|
2321
|
+
this.ScopeSaving = false;
|
|
2322
|
+
this.cdr.detectChanges();
|
|
2323
|
+
}
|
|
2324
|
+
/** Deletes a scope row. */
|
|
2325
|
+
async DeleteScope(scope) {
|
|
2326
|
+
this.ScopeSaving = true;
|
|
2327
|
+
this.cdr.detectChanges();
|
|
2328
|
+
try {
|
|
2329
|
+
const deleted = await scope.Delete();
|
|
2330
|
+
if (deleted) {
|
|
2331
|
+
this.Scopes = this.Scopes.filter(s => !UUIDsEqual(s.ID, scope.ID));
|
|
2332
|
+
MJNotificationService.Instance.CreateSimpleNotification('Scope removed', 'success', 2500);
|
|
2333
|
+
}
|
|
2334
|
+
else {
|
|
2335
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to remove scope: ${scope.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
catch (error) {
|
|
2339
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2340
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2341
|
+
}
|
|
2342
|
+
this.ScopeSaving = false;
|
|
2343
|
+
this.cdr.detectChanges();
|
|
2344
|
+
}
|
|
2345
|
+
// ── Tag Operations ──
|
|
2346
|
+
StartEditTag() {
|
|
2347
|
+
if (!this.TaxSelectedNode)
|
|
2348
|
+
return;
|
|
2349
|
+
this.TaxIsEditing = true;
|
|
2350
|
+
this.TaxEditName = this.TaxSelectedNode.Name;
|
|
2351
|
+
this.TaxEditDescription = this.TaxSelectedNode.Description;
|
|
2352
|
+
this.cdr.detectChanges();
|
|
2353
|
+
}
|
|
2354
|
+
CancelEditTag() {
|
|
2355
|
+
this.TaxIsEditing = false;
|
|
2356
|
+
this.cdr.detectChanges();
|
|
2357
|
+
}
|
|
2358
|
+
async SaveEditTag() {
|
|
2359
|
+
if (!this.TaxSelectedNode)
|
|
2360
|
+
return;
|
|
2361
|
+
try {
|
|
2362
|
+
const md = this.ProviderToUse;
|
|
2363
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2364
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: this.TaxSelectedNode.ID }]));
|
|
2365
|
+
tag.Name = this.TaxEditName;
|
|
2366
|
+
tag.Description = this.TaxEditDescription;
|
|
2367
|
+
const saved = await tag.Save();
|
|
2368
|
+
if (saved) {
|
|
2369
|
+
this.TaxSelectedNode.Name = this.TaxEditName;
|
|
2370
|
+
this.TaxSelectedNode.DisplayName = this.TaxEditName;
|
|
2371
|
+
this.TaxSelectedNode.Description = this.TaxEditDescription;
|
|
2372
|
+
this.TaxIsEditing = false;
|
|
2373
|
+
this.addTaxAuditEntry('renamed', this.TaxEditName);
|
|
2374
|
+
MJNotificationService.Instance.CreateSimpleNotification('Tag updated', 'success', 2500);
|
|
2375
|
+
}
|
|
2376
|
+
else {
|
|
2377
|
+
MJNotificationService.Instance.CreateSimpleNotification('Failed to update tag', 'error', 3000);
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
catch (error) {
|
|
2381
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2382
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2383
|
+
}
|
|
2384
|
+
this.cdr.detectChanges();
|
|
2385
|
+
}
|
|
2386
|
+
async MoveTag(node, newParentId) {
|
|
2387
|
+
try {
|
|
2388
|
+
const md = this.ProviderToUse;
|
|
2389
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2390
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: node.ID }]));
|
|
2391
|
+
tag.ParentID = newParentId;
|
|
2392
|
+
const saved = await tag.Save();
|
|
2393
|
+
if (saved) {
|
|
2394
|
+
this.addTaxAuditEntry('moved', node.Name);
|
|
2395
|
+
MJNotificationService.Instance.CreateSimpleNotification('Tag moved', 'success', 2500);
|
|
2396
|
+
await this.RefreshTaxonomyData();
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
catch (error) {
|
|
2400
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2401
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
DeleteTag(node) {
|
|
2405
|
+
this.OpenConfirmDialog('Delete Tag', `Delete tag "${node.Name}"? This will also remove all tagged item associations.`, async () => {
|
|
2406
|
+
try {
|
|
2407
|
+
const md = this.ProviderToUse;
|
|
2408
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2409
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: node.ID }]));
|
|
2410
|
+
const deleted = await tag.Delete();
|
|
2411
|
+
if (deleted) {
|
|
2412
|
+
this.addTaxAuditEntry('deleted', node.Name);
|
|
2413
|
+
MJNotificationService.Instance.CreateSimpleNotification('Tag deleted', 'success', 2500);
|
|
2414
|
+
await this.RefreshTaxonomyData();
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
catch (error) {
|
|
2418
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2419
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2420
|
+
}
|
|
2421
|
+
});
|
|
2422
|
+
}
|
|
2423
|
+
// ── Create Tag ──
|
|
2424
|
+
/** Open create tag dialog for a root-level tag */
|
|
2425
|
+
OpenCreateRootTag() {
|
|
2426
|
+
this.CreateTagParentID = null;
|
|
2427
|
+
this.CreateTagParentLabel = 'Root level';
|
|
2428
|
+
this.CreateTagName = '';
|
|
2429
|
+
this.CreateTagDescription = '';
|
|
2430
|
+
this.ShowCreateTagDialog = true;
|
|
2431
|
+
this.cdr.detectChanges();
|
|
2432
|
+
}
|
|
2433
|
+
/** Open create tag dialog as child of the selected node */
|
|
2434
|
+
OpenCreateChildTag() {
|
|
2435
|
+
if (!this.TaxSelectedNode)
|
|
2436
|
+
return;
|
|
2437
|
+
this.OpenCreateChildTagFor(this.TaxSelectedNode);
|
|
2438
|
+
}
|
|
2439
|
+
/** Open create tag dialog as child of a specific node */
|
|
2440
|
+
OpenCreateChildTagFor(node) {
|
|
2441
|
+
this.CreateTagParentID = node.ID;
|
|
2442
|
+
this.CreateTagParentLabel = `under "${node.Name}"`;
|
|
2443
|
+
this.CreateTagName = '';
|
|
2444
|
+
this.CreateTagDescription = '';
|
|
2445
|
+
this.ShowCreateTagDialog = true;
|
|
2446
|
+
this.cdr.detectChanges();
|
|
2447
|
+
}
|
|
2448
|
+
/** Close create tag dialog */
|
|
2449
|
+
CloseCreateTagDialog() {
|
|
2450
|
+
this.ShowCreateTagDialog = false;
|
|
2451
|
+
this.cdr.detectChanges();
|
|
2452
|
+
}
|
|
2453
|
+
/** Save the new tag */
|
|
2454
|
+
async SaveNewTag() {
|
|
2455
|
+
const name = this.CreateTagName.trim();
|
|
2456
|
+
if (!name)
|
|
2457
|
+
return;
|
|
2458
|
+
try {
|
|
2459
|
+
const md = this.ProviderToUse;
|
|
2460
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2461
|
+
tag.NewRecord();
|
|
2462
|
+
tag.Name = name;
|
|
2463
|
+
tag.DisplayName = name;
|
|
2464
|
+
tag.Description = this.CreateTagDescription.trim() || null;
|
|
2465
|
+
tag.ParentID = this.CreateTagParentID;
|
|
2466
|
+
const saved = await tag.Save();
|
|
2467
|
+
if (saved) {
|
|
2468
|
+
this.addTaxAuditEntry('created', name);
|
|
2469
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Tag "${name}" created`, 'success', 2500);
|
|
2470
|
+
this.ShowCreateTagDialog = false;
|
|
2471
|
+
await this.RefreshTaxonomyData();
|
|
2472
|
+
}
|
|
2473
|
+
else {
|
|
2474
|
+
MJNotificationService.Instance.CreateSimpleNotification('Failed to save tag', 'error', 4000);
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
catch (error) {
|
|
2478
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2479
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
// ── Multi-Select & Drag Reparent ──
|
|
2483
|
+
/** Toggle multi-select mode on/off */
|
|
2484
|
+
ToggleMultiSelectMode() {
|
|
2485
|
+
this.TaxMultiSelectMode = !this.TaxMultiSelectMode;
|
|
2486
|
+
if (!this.TaxMultiSelectMode) {
|
|
2487
|
+
this.TaxSelectedIDs.clear();
|
|
2488
|
+
}
|
|
2489
|
+
this.cdr.detectChanges();
|
|
2490
|
+
}
|
|
2491
|
+
/** Toggle a node's selection in multi-select mode */
|
|
2492
|
+
ToggleNodeSelection(node, event) {
|
|
2493
|
+
event.stopPropagation();
|
|
2494
|
+
if (this.TaxSelectedIDs.has(node.ID)) {
|
|
2495
|
+
this.TaxSelectedIDs.delete(node.ID);
|
|
2496
|
+
}
|
|
2497
|
+
else {
|
|
2498
|
+
this.TaxSelectedIDs.add(node.ID);
|
|
2499
|
+
}
|
|
2500
|
+
this.cdr.detectChanges();
|
|
2501
|
+
}
|
|
2502
|
+
/** Check if a node is selected in multi-select mode */
|
|
2503
|
+
IsNodeMultiSelected(nodeID) {
|
|
2504
|
+
return this.TaxSelectedIDs.has(nodeID);
|
|
2505
|
+
}
|
|
2506
|
+
/** Handle drag start on a tree node */
|
|
2507
|
+
OnTreeNodeDragStart(event, node) {
|
|
2508
|
+
if (!event.dataTransfer)
|
|
2509
|
+
return;
|
|
2510
|
+
// If dragging a multi-selected node, drag all selected; otherwise just this one
|
|
2511
|
+
const dragIDs = this.TaxMultiSelectMode && this.TaxSelectedIDs.has(node.ID)
|
|
2512
|
+
? [...this.TaxSelectedIDs]
|
|
2513
|
+
: [node.ID];
|
|
2514
|
+
event.dataTransfer.setData('text/plain', JSON.stringify(dragIDs));
|
|
2515
|
+
event.dataTransfer.effectAllowed = 'move';
|
|
2516
|
+
}
|
|
2517
|
+
/** Handle drag over a tree node (drop target) */
|
|
2518
|
+
OnTreeNodeDragOver(event, node) {
|
|
2519
|
+
event.preventDefault();
|
|
2520
|
+
if (event.dataTransfer)
|
|
2521
|
+
event.dataTransfer.dropEffect = 'move';
|
|
2522
|
+
this.TaxDragOverNodeID = node.ID;
|
|
2523
|
+
}
|
|
2524
|
+
/** Handle drag leave */
|
|
2525
|
+
OnTreeNodeDragLeave() {
|
|
2526
|
+
this.TaxDragOverNodeID = null;
|
|
2527
|
+
}
|
|
2528
|
+
/** Handle drop — reparent dragged node(s) under the drop target */
|
|
2529
|
+
async OnTreeNodeDrop(event, targetNode) {
|
|
2530
|
+
event.preventDefault();
|
|
2531
|
+
this.TaxDragOverNodeID = null;
|
|
2532
|
+
const data = event.dataTransfer?.getData('text/plain');
|
|
2533
|
+
if (!data)
|
|
2534
|
+
return;
|
|
2535
|
+
let dragIDs;
|
|
2536
|
+
try {
|
|
2537
|
+
dragIDs = JSON.parse(data);
|
|
2538
|
+
}
|
|
2539
|
+
catch {
|
|
2540
|
+
return;
|
|
2541
|
+
}
|
|
2542
|
+
// Prevent dropping onto itself or a descendant
|
|
2543
|
+
const targetDescendants = this.collectDescendantIds(targetNode);
|
|
2544
|
+
const validIDs = dragIDs.filter(id => !UUIDsEqual(id, targetNode.ID) && !targetDescendants.has(NormalizeUUID(id)));
|
|
2545
|
+
if (validIDs.length === 0)
|
|
2546
|
+
return;
|
|
2547
|
+
this.TaxTreeSaving = true;
|
|
2548
|
+
this.cdr.detectChanges();
|
|
2549
|
+
const md = this.ProviderToUse;
|
|
2550
|
+
let movedCount = 0;
|
|
2551
|
+
for (const tagID of validIDs) {
|
|
2552
|
+
try {
|
|
2553
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2554
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: tagID }]));
|
|
2555
|
+
tag.ParentID = targetNode.ID;
|
|
2556
|
+
const saved = await tag.Save();
|
|
2557
|
+
if (saved)
|
|
2558
|
+
movedCount++;
|
|
2559
|
+
}
|
|
2560
|
+
catch {
|
|
2561
|
+
// continue with remaining
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
if (movedCount > 0) {
|
|
2565
|
+
const label = movedCount === 1 ? '1 tag' : `${movedCount} tags`;
|
|
2566
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Moved ${label} under "${targetNode.Name}"`, 'success', 2500);
|
|
2567
|
+
this.addTaxAuditEntry('moved', `${movedCount} tag(s) → ${targetNode.Name}`);
|
|
2568
|
+
this.TaxSelectedIDs.clear();
|
|
2569
|
+
await this.RefreshTaxonomyData();
|
|
2570
|
+
}
|
|
2571
|
+
this.TaxTreeSaving = false;
|
|
2572
|
+
this.cdr.detectChanges();
|
|
2573
|
+
}
|
|
2574
|
+
/** Handle drop on the "Root" drop zone (make root-level) */
|
|
2575
|
+
async OnDropToRoot(event) {
|
|
2576
|
+
event.preventDefault();
|
|
2577
|
+
this.TaxDragOverNodeID = null;
|
|
2578
|
+
const data = event.dataTransfer?.getData('text/plain');
|
|
2579
|
+
if (!data)
|
|
2580
|
+
return;
|
|
2581
|
+
let dragIDs;
|
|
2582
|
+
try {
|
|
2583
|
+
dragIDs = JSON.parse(data);
|
|
2584
|
+
}
|
|
2585
|
+
catch {
|
|
2586
|
+
return;
|
|
2587
|
+
}
|
|
2588
|
+
this.TaxTreeSaving = true;
|
|
2589
|
+
this.cdr.detectChanges();
|
|
2590
|
+
const md = this.ProviderToUse;
|
|
2591
|
+
let movedCount = 0;
|
|
2592
|
+
for (const tagID of dragIDs) {
|
|
2593
|
+
try {
|
|
2594
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2595
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: tagID }]));
|
|
2596
|
+
if (tag.ParentID != null) {
|
|
2597
|
+
tag.ParentID = null;
|
|
2598
|
+
const saved = await tag.Save();
|
|
2599
|
+
if (saved)
|
|
2600
|
+
movedCount++;
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
catch {
|
|
2604
|
+
// continue
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
if (movedCount > 0) {
|
|
2608
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Moved ${movedCount} tag(s) to root`, 'success', 2500);
|
|
2609
|
+
this.addTaxAuditEntry('moved', `${movedCount} tag(s) → root`);
|
|
2610
|
+
this.TaxSelectedIDs.clear();
|
|
2611
|
+
await this.RefreshTaxonomyData();
|
|
2612
|
+
}
|
|
2613
|
+
this.TaxTreeSaving = false;
|
|
2614
|
+
this.cdr.detectChanges();
|
|
2615
|
+
}
|
|
2616
|
+
async MergeTags(sourceTagId, targetTagId, sourceName, targetName) {
|
|
2617
|
+
if (this.IsMerging)
|
|
2618
|
+
return; // Prevent duplicate calls from button spam
|
|
2619
|
+
this.IsMerging = true;
|
|
2620
|
+
this.cdr.detectChanges();
|
|
2621
|
+
try {
|
|
2622
|
+
// Re-parent tagged items from source to target
|
|
2623
|
+
const itemsToMove = this.taggedItemsRaw.filter(ti => ti['TagID'] === sourceTagId);
|
|
2624
|
+
const md = this.ProviderToUse;
|
|
2625
|
+
for (const ti of itemsToMove) {
|
|
2626
|
+
const taggedItem = await md.GetEntityObject('MJ: Tagged Items', md.CurrentUser);
|
|
2627
|
+
await taggedItem.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: ti['ID'] }]));
|
|
2628
|
+
taggedItem.TagID = targetTagId;
|
|
2629
|
+
if (!await taggedItem.Save()) {
|
|
2630
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Merge failed: ${taggedItem.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2631
|
+
return;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
// Re-parent children of source under target
|
|
2635
|
+
const childTags = this.tagsRaw.filter(t => t['ParentID'] === sourceTagId);
|
|
2636
|
+
for (const child of childTags) {
|
|
2637
|
+
const childTag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2638
|
+
await childTag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: child['ID'] }]));
|
|
2639
|
+
childTag.ParentID = targetTagId;
|
|
2640
|
+
if (!await childTag.Save()) {
|
|
2641
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Merge failed: ${childTag.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2642
|
+
return;
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
// Clean up co-occurrence records before delete (FK constraint)
|
|
2646
|
+
await this.cleanupTagReferences(sourceTagId);
|
|
2647
|
+
// Delete source tag (original behavior — hard delete)
|
|
2648
|
+
const sourceEntity = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2649
|
+
await sourceEntity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: sourceTagId }]));
|
|
2650
|
+
if (!await sourceEntity.Delete()) {
|
|
2651
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Merge failed: ${sourceEntity.LatestResult?.CompleteMessage ?? 'unknown error'}`, 'error', 4000);
|
|
2652
|
+
return;
|
|
2653
|
+
}
|
|
2654
|
+
this.addTaxAuditEntry('merged', `${sourceName} into ${targetName}`);
|
|
2655
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Merged "${sourceName}" into "${targetName}"`, 'success', 3000);
|
|
2656
|
+
await this.RefreshTaxonomyData();
|
|
2657
|
+
}
|
|
2658
|
+
catch (error) {
|
|
2659
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2660
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Merge error: ${msg}`, 'error', 4000);
|
|
2661
|
+
}
|
|
2662
|
+
finally {
|
|
2663
|
+
this.IsMerging = false;
|
|
2664
|
+
this.cdr.detectChanges();
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
async MakeChildTag(childTagId, parentTagId) {
|
|
2668
|
+
try {
|
|
2669
|
+
const md = this.ProviderToUse;
|
|
2670
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2671
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: childTagId }]));
|
|
2672
|
+
tag.ParentID = parentTagId;
|
|
2673
|
+
const saved = await tag.Save();
|
|
2674
|
+
if (saved) {
|
|
2675
|
+
this.addTaxAuditEntry('moved', tag.Name ?? 'tag');
|
|
2676
|
+
MJNotificationService.Instance.CreateSimpleNotification('Tag reparented', 'success', 2500);
|
|
2677
|
+
await this.RefreshTaxonomyData();
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
catch (error) {
|
|
2681
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2682
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
DismissDuplicate(pair) {
|
|
2686
|
+
this.TaxDuplicates = this.TaxDuplicates.filter(d => d !== pair);
|
|
2687
|
+
this.TaxHealth.Duplicates = this.TaxDuplicates.length;
|
|
2688
|
+
this.cdr.detectChanges();
|
|
2689
|
+
}
|
|
2690
|
+
// ── Duplicates ──
|
|
2691
|
+
buildTaxDuplicates() {
|
|
2692
|
+
const tags = this.tagsRaw
|
|
2693
|
+
.filter(t => t['Status']?.toLowerCase() !== 'merged')
|
|
2694
|
+
.map(t => ({
|
|
2695
|
+
ID: t['ID'],
|
|
2696
|
+
Name: t['Name'] ?? ''
|
|
2697
|
+
}));
|
|
2698
|
+
const pairs = [];
|
|
2699
|
+
// 1. Group exact-name duplicates (case-insensitive) into single entries
|
|
2700
|
+
const exactGroups = this.groupExactNameDuplicates(tags);
|
|
2701
|
+
const consumedIDs = new Set();
|
|
2702
|
+
for (const [, group] of exactGroups) {
|
|
2703
|
+
if (group.length < 2)
|
|
2704
|
+
continue;
|
|
2705
|
+
// Emit one consolidated entry per group of exact-name duplicates
|
|
2706
|
+
pairs.push({
|
|
2707
|
+
TagA: group[0].Name,
|
|
2708
|
+
TagB: group[0].Name,
|
|
2709
|
+
TagAID: group[0].ID,
|
|
2710
|
+
TagBID: group[1].ID,
|
|
2711
|
+
Similarity: 100,
|
|
2712
|
+
SeverityClass: 'high',
|
|
2713
|
+
IsExactDuplicate: true,
|
|
2714
|
+
ExactDuplicateCount: group.length,
|
|
2715
|
+
AllIDs: group.map(t => t.ID)
|
|
2716
|
+
});
|
|
2717
|
+
for (const t of group)
|
|
2718
|
+
consumedIDs.add(t.ID);
|
|
2719
|
+
}
|
|
2720
|
+
// 2. Fuzzy/similar pairs — skip any tags already covered by exact-name groups
|
|
2721
|
+
for (let i = 0; i < tags.length; i++) {
|
|
2722
|
+
if (consumedIDs.has(tags[i].ID))
|
|
2723
|
+
continue;
|
|
2724
|
+
for (let j = i + 1; j < tags.length; j++) {
|
|
2725
|
+
if (consumedIDs.has(tags[j].ID))
|
|
2726
|
+
continue;
|
|
2727
|
+
const sim = this.computeStringSimilarity(tags[i].Name, tags[j].Name);
|
|
2728
|
+
if (sim >= 0.70) {
|
|
2729
|
+
pairs.push({
|
|
2730
|
+
TagA: tags[i].Name,
|
|
2731
|
+
TagB: tags[j].Name,
|
|
2732
|
+
TagAID: tags[i].ID,
|
|
2733
|
+
TagBID: tags[j].ID,
|
|
2734
|
+
Similarity: Math.round(sim * 100),
|
|
2735
|
+
SeverityClass: sim >= 0.85 ? 'high' : 'moderate',
|
|
2736
|
+
IsExactDuplicate: false,
|
|
2737
|
+
ExactDuplicateCount: 0,
|
|
2738
|
+
AllIDs: []
|
|
2739
|
+
});
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
pairs.sort((a, b) => b.Similarity - a.Similarity);
|
|
2744
|
+
this.TaxDuplicates = pairs;
|
|
2745
|
+
}
|
|
2746
|
+
/** Group tags by case-insensitive name, returning only groups with 2+ members */
|
|
2747
|
+
groupExactNameDuplicates(tags) {
|
|
2748
|
+
const groups = new Map();
|
|
2749
|
+
for (const tag of tags) {
|
|
2750
|
+
const key = tag.Name.toLowerCase().trim();
|
|
2751
|
+
const group = groups.get(key);
|
|
2752
|
+
if (group) {
|
|
2753
|
+
group.push(tag);
|
|
2754
|
+
}
|
|
2755
|
+
else {
|
|
2756
|
+
groups.set(key, [tag]);
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
return groups;
|
|
2760
|
+
}
|
|
2761
|
+
/**
|
|
2762
|
+
* Enhanced string similarity: separator normalization, abbreviation,
|
|
2763
|
+
* pluralization, token-overlap Jaccard, containment, and Levenshtein.
|
|
2764
|
+
* Returns the highest score among all heuristics.
|
|
2765
|
+
*/
|
|
2766
|
+
computeStringSimilarity(a, b) {
|
|
2767
|
+
const la = a.toLowerCase().trim();
|
|
2768
|
+
const lb = b.toLowerCase().trim();
|
|
2769
|
+
if (la === lb)
|
|
2770
|
+
return 1.0;
|
|
2771
|
+
// Strip separators and compare
|
|
2772
|
+
const normA = la.replace(/[\s\-_&]+/g, '');
|
|
2773
|
+
const normB = lb.replace(/[\s\-_&]+/g, '');
|
|
2774
|
+
if (normA === normB)
|
|
2775
|
+
return 0.98;
|
|
2776
|
+
let best = 0;
|
|
2777
|
+
// Abbreviation
|
|
2778
|
+
if (this.isAbbreviationOf(la, lb) || this.isAbbreviationOf(lb, la)) {
|
|
2779
|
+
best = Math.max(best, 0.90);
|
|
2780
|
+
}
|
|
2781
|
+
// Pluralization
|
|
2782
|
+
best = Math.max(best, this.computePluralizationScore(la, lb));
|
|
2783
|
+
// Token Jaccard
|
|
2784
|
+
best = Math.max(best, this.computeTokenJaccardSimilarity(la, lb));
|
|
2785
|
+
// Containment
|
|
2786
|
+
if (lb.includes(la) || la.includes(lb)) {
|
|
2787
|
+
const shorter = la.length < lb.length ? la : lb;
|
|
2788
|
+
const longer = la.length < lb.length ? lb : la;
|
|
2789
|
+
best = Math.max(best, shorter.length / longer.length);
|
|
2790
|
+
}
|
|
2791
|
+
// Levenshtein
|
|
2792
|
+
const dist = this.levenshteinDistance(la, lb);
|
|
2793
|
+
const maxLen = Math.max(la.length, lb.length);
|
|
2794
|
+
if (maxLen > 0) {
|
|
2795
|
+
best = Math.max(best, 1 - dist / maxLen);
|
|
2796
|
+
}
|
|
2797
|
+
return best;
|
|
2798
|
+
}
|
|
2799
|
+
/** Scores simple English pluralization differences */
|
|
2800
|
+
computePluralizationScore(a, b) {
|
|
2801
|
+
const shorter = a.length <= b.length ? a : b;
|
|
2802
|
+
const longer = a.length <= b.length ? b : a;
|
|
2803
|
+
if (longer === shorter + 's')
|
|
2804
|
+
return 0.95;
|
|
2805
|
+
if (longer === shorter + 'es')
|
|
2806
|
+
return 0.95;
|
|
2807
|
+
if (shorter.endsWith('y') && longer === shorter.slice(0, -1) + 'ies')
|
|
2808
|
+
return 0.95;
|
|
2809
|
+
return 0;
|
|
2810
|
+
}
|
|
2811
|
+
/** Jaccard similarity on word tokens */
|
|
2812
|
+
computeTokenJaccardSimilarity(a, b) {
|
|
2813
|
+
const tokensA = new Set(a.split(/[\s\-_&]+/).filter(w => w.length > 0));
|
|
2814
|
+
const tokensB = new Set(b.split(/[\s\-_&]+/).filter(w => w.length > 0));
|
|
2815
|
+
if (tokensA.size === 0 || tokensB.size === 0)
|
|
2816
|
+
return 0;
|
|
2817
|
+
let intersection = 0;
|
|
2818
|
+
for (const token of tokensA) {
|
|
2819
|
+
if (tokensB.has(token))
|
|
2820
|
+
intersection++;
|
|
2821
|
+
}
|
|
2822
|
+
const union = tokensA.size + tokensB.size - intersection;
|
|
2823
|
+
return union > 0 ? intersection / union : 0;
|
|
2824
|
+
}
|
|
2825
|
+
isAbbreviationOf(short, long) {
|
|
2826
|
+
if (short.length >= long.length)
|
|
2827
|
+
return false;
|
|
2828
|
+
if (short.length < 2)
|
|
2829
|
+
return false;
|
|
2830
|
+
// Check if short is initials of words in long
|
|
2831
|
+
const words = long.split(/[\s\-_&]+/).filter(w => w.length > 0);
|
|
2832
|
+
if (words.length < 2)
|
|
2833
|
+
return false;
|
|
2834
|
+
const initials = words.map(w => w[0]).join('');
|
|
2835
|
+
return initials === short;
|
|
2836
|
+
}
|
|
2837
|
+
levenshteinDistance(a, b) {
|
|
2838
|
+
const m = a.length;
|
|
2839
|
+
const n = b.length;
|
|
2840
|
+
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
|
|
2841
|
+
for (let i = 0; i <= m; i++)
|
|
2842
|
+
dp[i][0] = i;
|
|
2843
|
+
for (let j = 0; j <= n; j++)
|
|
2844
|
+
dp[0][j] = j;
|
|
2845
|
+
for (let i = 1; i <= m; i++) {
|
|
2846
|
+
for (let j = 1; j <= n; j++) {
|
|
2847
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
2848
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
return dp[m][n];
|
|
2852
|
+
}
|
|
2853
|
+
// ── Orphans ──
|
|
2854
|
+
/**
|
|
2855
|
+
* Finds orphan tags: no parent, no children, and zero usage.
|
|
2856
|
+
* A tag with even 1 connection is not orphaned — it's just a leaf.
|
|
2857
|
+
* Uses NormalizeUUID for consistent cross-platform UUID comparisons.
|
|
2858
|
+
*/
|
|
2859
|
+
buildTaxOrphans() {
|
|
2860
|
+
const tagItemCounts = this.tagAggregateCounts;
|
|
2861
|
+
const tagAvgWeights = this.tagAggregateWeights;
|
|
2862
|
+
const hasChildren = new Set();
|
|
2863
|
+
for (const t of this.tagsRaw) {
|
|
2864
|
+
const pid = t['ParentID'];
|
|
2865
|
+
if (pid)
|
|
2866
|
+
hasChildren.add(NormalizeUUID(pid));
|
|
2867
|
+
}
|
|
2868
|
+
this.TaxOrphans = this.tagsRaw
|
|
2869
|
+
.filter(t => {
|
|
2870
|
+
const normalizedId = NormalizeUUID(t['ID']);
|
|
2871
|
+
const parentId = t['ParentID'];
|
|
2872
|
+
const status = t['Status']?.toLowerCase();
|
|
2873
|
+
const itemCount = tagItemCounts.get(normalizedId) ?? 0;
|
|
2874
|
+
// Skip merged tags — they're soft-deleted
|
|
2875
|
+
if (status === 'merged')
|
|
2876
|
+
return false;
|
|
2877
|
+
// Orphan: no parent, no children, and zero connections
|
|
2878
|
+
return !parentId && !hasChildren.has(normalizedId) && itemCount === 0;
|
|
2879
|
+
})
|
|
2880
|
+
.map(t => {
|
|
2881
|
+
const id = t['ID'];
|
|
2882
|
+
const normalizedId = NormalizeUUID(id);
|
|
2883
|
+
const itemCount = tagItemCounts.get(normalizedId) ?? 0;
|
|
2884
|
+
return {
|
|
2885
|
+
ID: id,
|
|
2886
|
+
Name: t['Name'] ?? 'Unnamed',
|
|
2887
|
+
UsageCount: itemCount,
|
|
2888
|
+
AvgWeight: tagAvgWeights.get(normalizedId) ?? 0,
|
|
2889
|
+
FirstSeen: formatShortDate(t['__mj_CreatedAt'] ?? ''),
|
|
2890
|
+
LastSeen: formatShortDate(t['__mj_UpdatedAt'] ?? ''),
|
|
2891
|
+
IsSelected: false
|
|
2892
|
+
};
|
|
2893
|
+
})
|
|
2894
|
+
.sort((a, b) => a.UsageCount - b.UsageCount);
|
|
2895
|
+
}
|
|
2896
|
+
ToggleOrphanSelection(orphan) {
|
|
2897
|
+
orphan.IsSelected = !orphan.IsSelected;
|
|
2898
|
+
this.TaxAllOrphansSelected = this.TaxOrphans.every(o => o.IsSelected);
|
|
2899
|
+
this.cdr.detectChanges();
|
|
2900
|
+
}
|
|
2901
|
+
ToggleAllOrphans() {
|
|
2902
|
+
this.TaxAllOrphansSelected = !this.TaxAllOrphansSelected;
|
|
2903
|
+
for (const o of this.TaxOrphans) {
|
|
2904
|
+
o.IsSelected = this.TaxAllOrphansSelected;
|
|
2905
|
+
}
|
|
2906
|
+
this.cdr.detectChanges();
|
|
2907
|
+
}
|
|
2908
|
+
/**
|
|
2909
|
+
* Clean up TagCoOccurrence records that reference a tag before deleting it.
|
|
2910
|
+
* Without this, the FK constraint on TagCoOccurrence blocks the delete.
|
|
2911
|
+
*/
|
|
2912
|
+
async cleanupTagReferences(tagId) {
|
|
2913
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2914
|
+
const coOccResult = await rv.RunView({
|
|
2915
|
+
EntityName: 'MJ: Tag Co Occurrences',
|
|
2916
|
+
ExtraFilter: `TagAID='${tagId}' OR TagBID='${tagId}'`,
|
|
2917
|
+
ResultType: 'entity_object'
|
|
2918
|
+
});
|
|
2919
|
+
if (coOccResult.Success) {
|
|
2920
|
+
for (const coOcc of coOccResult.Results) {
|
|
2921
|
+
await coOcc.Delete();
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
DeleteOrphan(orphan) {
|
|
2926
|
+
this.OpenConfirmDialog('Delete Orphan Tag', `Delete orphan tag "${orphan.Name}"?`, async () => {
|
|
2927
|
+
try {
|
|
2928
|
+
await this.cleanupTagReferences(orphan.ID);
|
|
2929
|
+
const md = this.ProviderToUse;
|
|
2930
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2931
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: orphan.ID }]));
|
|
2932
|
+
const deleted = await tag.Delete();
|
|
2933
|
+
if (deleted) {
|
|
2934
|
+
this.addTaxAuditEntry('deleted', orphan.Name);
|
|
2935
|
+
MJNotificationService.Instance.CreateSimpleNotification('Orphan tag deleted', 'success', 2500);
|
|
2936
|
+
this.TaxOrphans = this.TaxOrphans.filter(o => !UUIDsEqual(o.ID, orphan.ID));
|
|
2937
|
+
this.TaxHealth.Orphaned = this.TaxOrphans.length;
|
|
2938
|
+
this.cdr.detectChanges();
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
catch (error) {
|
|
2942
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2943
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
2944
|
+
}
|
|
2945
|
+
});
|
|
2946
|
+
}
|
|
2947
|
+
BulkDeleteOrphans() {
|
|
2948
|
+
const selected = this.TaxOrphans.filter(o => o.IsSelected);
|
|
2949
|
+
if (selected.length === 0)
|
|
2950
|
+
return;
|
|
2951
|
+
this.OpenConfirmDialog('Bulk Delete Orphan Tags', `Delete ${selected.length} selected orphan tag${selected.length > 1 ? 's' : ''}? This cannot be undone.`, async () => {
|
|
2952
|
+
const md = this.ProviderToUse;
|
|
2953
|
+
let deletedCount = 0;
|
|
2954
|
+
for (const orphan of selected) {
|
|
2955
|
+
try {
|
|
2956
|
+
await this.cleanupTagReferences(orphan.ID);
|
|
2957
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2958
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: orphan.ID }]));
|
|
2959
|
+
if (await tag.Delete()) {
|
|
2960
|
+
deletedCount++;
|
|
2961
|
+
this.addTaxAuditEntry('deleted', orphan.Name);
|
|
2962
|
+
}
|
|
2963
|
+
}
|
|
2964
|
+
catch {
|
|
2965
|
+
// continue with remaining
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Deleted ${deletedCount} tags`, 'success', 3000);
|
|
2969
|
+
this.TaxOrphans = this.TaxOrphans.filter(o => !o.IsSelected);
|
|
2970
|
+
this.TaxHealth.Orphaned = this.TaxOrphans.length;
|
|
2971
|
+
this.TaxAllOrphansSelected = false;
|
|
2972
|
+
this.cdr.detectChanges();
|
|
2973
|
+
});
|
|
2974
|
+
}
|
|
2975
|
+
/** Delete all orphan tags at once with a styled confirmation dialog */
|
|
2976
|
+
DeleteAllOrphans() {
|
|
2977
|
+
if (this.TaxOrphans.length === 0)
|
|
2978
|
+
return;
|
|
2979
|
+
this.OpenConfirmDialog('Delete All Orphaned Tags', `Delete all ${this.TaxOrphans.length} orphaned tag${this.TaxOrphans.length > 1 ? 's' : ''}? This cannot be undone.`, async () => {
|
|
2980
|
+
const md = this.ProviderToUse;
|
|
2981
|
+
let deletedCount = 0;
|
|
2982
|
+
for (const orphan of this.TaxOrphans) {
|
|
2983
|
+
try {
|
|
2984
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
2985
|
+
await tag.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: orphan.ID }]));
|
|
2986
|
+
if (await tag.Delete()) {
|
|
2987
|
+
deletedCount++;
|
|
2988
|
+
this.addTaxAuditEntry('deleted', orphan.Name);
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
catch {
|
|
2992
|
+
// continue with remaining
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Deleted ${deletedCount} orphan tags`, 'success', 3000);
|
|
2996
|
+
this.TaxOrphans = [];
|
|
2997
|
+
this.TaxHealth.Orphaned = 0;
|
|
2998
|
+
this.TaxAllOrphansSelected = false;
|
|
2999
|
+
this.cdr.detectChanges();
|
|
3000
|
+
});
|
|
3001
|
+
}
|
|
3002
|
+
// ── Treemap ──
|
|
3003
|
+
buildTaxTreemap() {
|
|
3004
|
+
// Build treemap cells from root-level tags, sized by item count
|
|
3005
|
+
const tagItemCounts = this.countItemsByTag();
|
|
3006
|
+
// Group tags by root parent
|
|
3007
|
+
const rootGroups = new Map();
|
|
3008
|
+
for (const node of this.TaxTreeNodes) {
|
|
3009
|
+
rootGroups.set(node.ID, { Name: node.Name, TotalItems: node.ItemCount });
|
|
3010
|
+
}
|
|
3011
|
+
const colorFamilies = ['at-tm-blue', 'at-tm-green', 'at-tm-purple', 'at-tm-orange'];
|
|
3012
|
+
const cells = [];
|
|
3013
|
+
let colorIdx = 0;
|
|
3014
|
+
// For each root, add children as cells
|
|
3015
|
+
for (const root of this.TaxTreeNodes) {
|
|
3016
|
+
const family = colorFamilies[colorIdx % colorFamilies.length];
|
|
3017
|
+
let shadeIdx = 1;
|
|
3018
|
+
// Add root children (or the root itself if it has no children)
|
|
3019
|
+
const childNodes = root.Children.length > 0 ? root.Children : [root];
|
|
3020
|
+
const sortedChildren = [...childNodes].sort((a, b) => b.ItemCount - a.ItemCount);
|
|
3021
|
+
for (const child of sortedChildren.slice(0, 4)) {
|
|
3022
|
+
cells.push({
|
|
3023
|
+
ID: child.ID,
|
|
3024
|
+
Name: child.Name,
|
|
3025
|
+
ItemCount: child.ItemCount,
|
|
3026
|
+
ColorClass: `${family}-${shadeIdx}`,
|
|
3027
|
+
RowSpan: child.ItemCount > 10 ? 2 : 1
|
|
3028
|
+
});
|
|
3029
|
+
shadeIdx++;
|
|
3030
|
+
}
|
|
3031
|
+
colorIdx++;
|
|
3032
|
+
}
|
|
3033
|
+
this.TaxTreemapCells = cells;
|
|
3034
|
+
// KPIs
|
|
3035
|
+
const totalTags = this.tagsRaw.length;
|
|
3036
|
+
const maxDepth = this.TaxFlatNodes.length > 0
|
|
3037
|
+
? Math.max(...this.TaxFlatNodes.map(n => n.Depth))
|
|
3038
|
+
: 0;
|
|
3039
|
+
const avgDepth = this.TaxFlatNodes.length > 0
|
|
3040
|
+
? (this.TaxFlatNodes.reduce((sum, n) => sum + n.Depth, 0) / this.TaxFlatNodes.length).toFixed(1)
|
|
3041
|
+
: '0';
|
|
3042
|
+
const mostUsed = this.TaxFlatNodes.length > 0
|
|
3043
|
+
? [...this.TaxFlatNodes].sort((a, b) => b.ItemCount - a.ItemCount)[0]?.Name ?? 'None'
|
|
3044
|
+
: 'None';
|
|
3045
|
+
this.TaxTreemapKPIs = [
|
|
3046
|
+
{ Label: 'Total Tags', Value: String(totalTags) },
|
|
3047
|
+
{ Label: 'Avg Depth', Value: avgDepth },
|
|
3048
|
+
{ Label: 'Max Depth', Value: String(maxDepth) },
|
|
3049
|
+
{ Label: 'Most Used Tag', Value: mostUsed }
|
|
3050
|
+
];
|
|
3051
|
+
}
|
|
3052
|
+
// ── Audit Log ──
|
|
3053
|
+
/**
|
|
3054
|
+
* Builds the audit timeline from the MJ: Tag Audit Logs entity.
|
|
3055
|
+
* Falls back to synthesizing "created" events from tag creation dates
|
|
3056
|
+
* if no real audit log records exist yet.
|
|
3057
|
+
*/
|
|
3058
|
+
buildTaxAuditLog() {
|
|
3059
|
+
if (this.tagAuditLogsRaw.length > 0) {
|
|
3060
|
+
this.TaxAuditEvents = this.buildAuditEventsFromLogs();
|
|
3061
|
+
}
|
|
3062
|
+
else {
|
|
3063
|
+
this.TaxAuditEvents = this.synthesizeAuditEventsFromTags();
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
/**
|
|
3067
|
+
* Maps real Tag Audit Log records into TaxAuditEvent objects.
|
|
3068
|
+
* Uses the view's denormalized Tag, PerformedByUser, and RelatedTag fields.
|
|
3069
|
+
*/
|
|
3070
|
+
buildAuditEventsFromLogs() {
|
|
3071
|
+
const events = [];
|
|
3072
|
+
for (const log of this.tagAuditLogsRaw) {
|
|
3073
|
+
const action = log['Action'] ?? '';
|
|
3074
|
+
const type = this.mapAuditActionToType(action);
|
|
3075
|
+
if (!type)
|
|
3076
|
+
continue;
|
|
3077
|
+
const tagName = log['Tag'] ?? 'Unknown';
|
|
3078
|
+
const relatedTag = log['RelatedTag'] ?? '';
|
|
3079
|
+
const user = log['PerformedByUser'] ?? 'System';
|
|
3080
|
+
const createdAt = log['__mj_CreatedAt'] ?? '';
|
|
3081
|
+
const details = this.parseAuditDetails(log['Details']);
|
|
3082
|
+
events.push({
|
|
3083
|
+
Type: type,
|
|
3084
|
+
Description: this.buildAuditDescription(type, tagName, relatedTag, details),
|
|
3085
|
+
TagRef: tagName,
|
|
3086
|
+
User: user,
|
|
3087
|
+
Timestamp: formatDate(createdAt),
|
|
3088
|
+
DayHeader: this.formatDayHeader(createdAt)
|
|
3089
|
+
});
|
|
3090
|
+
}
|
|
3091
|
+
return events;
|
|
3092
|
+
}
|
|
3093
|
+
/**
|
|
3094
|
+
* Synthesizes audit events from tag __mj_CreatedAt dates when no
|
|
3095
|
+
* real audit log records exist. Used as a fallback only.
|
|
3096
|
+
*/
|
|
3097
|
+
synthesizeAuditEventsFromTags() {
|
|
3098
|
+
const events = [];
|
|
3099
|
+
for (const tag of this.tagsRaw) {
|
|
3100
|
+
const name = tag['Name'] ?? 'Unnamed';
|
|
3101
|
+
const createdAt = tag['__mj_CreatedAt'];
|
|
3102
|
+
if (createdAt) {
|
|
3103
|
+
events.push({
|
|
3104
|
+
Type: 'created',
|
|
3105
|
+
Description: 'Tag created',
|
|
3106
|
+
TagRef: name,
|
|
3107
|
+
User: 'System',
|
|
3108
|
+
Timestamp: formatDate(createdAt),
|
|
3109
|
+
DayHeader: this.formatDayHeader(createdAt)
|
|
3110
|
+
});
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
3113
|
+
events.sort((a, b) => b.Timestamp.localeCompare(a.Timestamp));
|
|
3114
|
+
return events.slice(0, 50);
|
|
3115
|
+
}
|
|
3116
|
+
/**
|
|
3117
|
+
* Maps a PascalCase DB Action value (e.g. "Renamed") to the lowercase
|
|
3118
|
+
* TaxAuditAction type used in the UI. Returns null for unrecognized values.
|
|
3119
|
+
*/
|
|
3120
|
+
mapAuditActionToType(action) {
|
|
3121
|
+
const mapped = action.toLowerCase();
|
|
3122
|
+
const validTypes = new Set([
|
|
3123
|
+
'created', 'merged', 'moved', 'deleted', 'renamed',
|
|
3124
|
+
'deprecated', 'descriptionchanged', 'reactivated', 'split'
|
|
3125
|
+
]);
|
|
3126
|
+
return validTypes.has(mapped) ? mapped : null;
|
|
3127
|
+
}
|
|
3128
|
+
/**
|
|
3129
|
+
* Safely parses the JSON Details column from a Tag Audit Log record.
|
|
3130
|
+
* Returns an empty object on parse failure.
|
|
3131
|
+
*/
|
|
3132
|
+
parseAuditDetails(details) {
|
|
3133
|
+
if (!details)
|
|
3134
|
+
return {};
|
|
3135
|
+
try {
|
|
3136
|
+
return JSON.parse(details);
|
|
3137
|
+
}
|
|
3138
|
+
catch {
|
|
3139
|
+
return {};
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
/**
|
|
3143
|
+
* Builds a human-readable description for an audit event based on the
|
|
3144
|
+
* action type and any additional context from the related tag or details JSON.
|
|
3145
|
+
*/
|
|
3146
|
+
buildAuditDescription(type, tagName, relatedTag, details) {
|
|
3147
|
+
switch (type) {
|
|
3148
|
+
case 'created':
|
|
3149
|
+
return 'Tag created';
|
|
3150
|
+
case 'renamed': {
|
|
3151
|
+
const oldName = details['OldName'];
|
|
3152
|
+
return oldName ? `Renamed from "${oldName}"` : 'Tag renamed';
|
|
3153
|
+
}
|
|
3154
|
+
case 'moved': {
|
|
3155
|
+
return 'Tag moved to new parent';
|
|
3156
|
+
}
|
|
3157
|
+
case 'merged':
|
|
3158
|
+
return relatedTag ? `Merged into "${relatedTag}"` : 'Tags merged';
|
|
3159
|
+
case 'split':
|
|
3160
|
+
return relatedTag ? `Split from "${relatedTag}"` : 'Tag split';
|
|
3161
|
+
case 'deleted':
|
|
3162
|
+
return 'Tag deleted';
|
|
3163
|
+
case 'deprecated':
|
|
3164
|
+
return 'Tag deprecated';
|
|
3165
|
+
case 'reactivated':
|
|
3166
|
+
return 'Tag reactivated';
|
|
3167
|
+
case 'descriptionchanged':
|
|
3168
|
+
return 'Description updated';
|
|
3169
|
+
default:
|
|
3170
|
+
return `Tag ${type}`;
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
/**
|
|
3174
|
+
* Adds a local-only audit entry to the top of the timeline for
|
|
3175
|
+
* immediate UI feedback after a user action (merge, delete, etc.).
|
|
3176
|
+
*/
|
|
3177
|
+
addTaxAuditEntry(type, tagRef) {
|
|
3178
|
+
const now = new Date().toISOString();
|
|
3179
|
+
this.TaxAuditEvents.unshift({
|
|
3180
|
+
Type: type,
|
|
3181
|
+
Description: this.buildAuditDescription(type, tagRef, '', {}),
|
|
3182
|
+
TagRef: tagRef,
|
|
3183
|
+
User: 'You',
|
|
3184
|
+
Timestamp: formatDate(now),
|
|
3185
|
+
DayHeader: 'Today'
|
|
3186
|
+
});
|
|
3187
|
+
}
|
|
3188
|
+
ToggleTaxAuditFilter(type) {
|
|
3189
|
+
if (this.TaxAuditFilterTypes.has(type)) {
|
|
3190
|
+
this.TaxAuditFilterTypes.delete(type);
|
|
3191
|
+
}
|
|
3192
|
+
else {
|
|
3193
|
+
this.TaxAuditFilterTypes.add(type);
|
|
3194
|
+
}
|
|
3195
|
+
this.cdr.detectChanges();
|
|
3196
|
+
}
|
|
3197
|
+
GetFilteredAuditEvents() {
|
|
3198
|
+
return this.TaxAuditEvents.filter(e => this.TaxAuditFilterTypes.has(e.Type));
|
|
3199
|
+
}
|
|
3200
|
+
formatDayHeader(dateStr) {
|
|
3201
|
+
try {
|
|
3202
|
+
const d = new Date(dateStr);
|
|
3203
|
+
const today = new Date();
|
|
3204
|
+
const yesterday = new Date(today);
|
|
3205
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
3206
|
+
if (d.toDateString() === today.toDateString())
|
|
3207
|
+
return 'Today';
|
|
3208
|
+
if (d.toDateString() === yesterday.toDateString())
|
|
3209
|
+
return 'Yesterday';
|
|
3210
|
+
return d.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' });
|
|
3211
|
+
}
|
|
3212
|
+
catch {
|
|
3213
|
+
return '';
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
// ── Health Stats ──
|
|
3217
|
+
buildTaxHealth() {
|
|
3218
|
+
const total = this.tagsRaw.length;
|
|
3219
|
+
const orphaned = this.TaxOrphans.length;
|
|
3220
|
+
const duplicates = this.TaxDuplicates.length;
|
|
3221
|
+
const needAttention = this.TaxFlatNodes.filter(n => n.HealthColor === 'yellow').length;
|
|
3222
|
+
const healthy = total - orphaned - needAttention;
|
|
3223
|
+
this.TaxHealth = { Total: total, Healthy: Math.max(0, healthy), NeedAttention: needAttention, Orphaned: orphaned, Duplicates: duplicates };
|
|
3224
|
+
}
|
|
3225
|
+
/** Returns the Font Awesome icon class for an audit event action type. */
|
|
3226
|
+
GetTaxAuditIcon(type) {
|
|
3227
|
+
const map = {
|
|
3228
|
+
'created': 'fa-solid fa-plus',
|
|
3229
|
+
'merged': 'fa-solid fa-code-merge',
|
|
3230
|
+
'moved': 'fa-solid fa-arrows-up-down',
|
|
3231
|
+
'deleted': 'fa-solid fa-trash',
|
|
3232
|
+
'renamed': 'fa-solid fa-pen',
|
|
3233
|
+
'deprecated': 'fa-solid fa-ban',
|
|
3234
|
+
'descriptionchanged': 'fa-solid fa-file-pen',
|
|
3235
|
+
'reactivated': 'fa-solid fa-rotate-left',
|
|
3236
|
+
'split': 'fa-solid fa-code-branch'
|
|
3237
|
+
};
|
|
3238
|
+
return map[type] ?? 'fa-solid fa-circle';
|
|
3239
|
+
}
|
|
3240
|
+
// ── Confirmation Dialog ──
|
|
3241
|
+
/** Opens a styled confirmation dialog, replacing browser `confirm()`. */
|
|
3242
|
+
OpenConfirmDialog(title, message, action) {
|
|
3243
|
+
this.ConfirmDialogTitle = title;
|
|
3244
|
+
this.ConfirmDialogMessage = message;
|
|
3245
|
+
this.confirmDialogAction = action;
|
|
3246
|
+
this.ShowConfirmDialog = true;
|
|
3247
|
+
this.cdr.detectChanges();
|
|
3248
|
+
}
|
|
3249
|
+
/** User confirmed the dialog action */
|
|
3250
|
+
async ConfirmDialogAccept() {
|
|
3251
|
+
this.ShowConfirmDialog = false;
|
|
3252
|
+
if (this.confirmDialogAction) {
|
|
3253
|
+
await this.confirmDialogAction();
|
|
3254
|
+
}
|
|
3255
|
+
this.confirmDialogAction = null;
|
|
3256
|
+
this.cdr.detectChanges();
|
|
3257
|
+
}
|
|
3258
|
+
/** User cancelled the confirmation dialog */
|
|
3259
|
+
ConfirmDialogCancel() {
|
|
3260
|
+
this.ShowConfirmDialog = false;
|
|
3261
|
+
this.confirmDialogAction = null;
|
|
3262
|
+
this.cdr.detectChanges();
|
|
3263
|
+
}
|
|
3264
|
+
// ── Split Dialog ──
|
|
3265
|
+
/** Opens the split-tag dialog for a given tree node */
|
|
3266
|
+
OpenSplitDialog(node) {
|
|
3267
|
+
this.splitTargetNode = node;
|
|
3268
|
+
this.SplitChildNames = '';
|
|
3269
|
+
this.ShowSplitDialog = true;
|
|
3270
|
+
this.cdr.detectChanges();
|
|
3271
|
+
}
|
|
3272
|
+
/** Closes the split-tag dialog without action */
|
|
3273
|
+
CloseSplitDialog() {
|
|
3274
|
+
this.ShowSplitDialog = false;
|
|
3275
|
+
this.splitTargetNode = null;
|
|
3276
|
+
this.SplitChildNames = '';
|
|
3277
|
+
this.cdr.detectChanges();
|
|
3278
|
+
}
|
|
3279
|
+
/** Executes the split operation, creating child tags from comma-separated names */
|
|
3280
|
+
async ExecuteSplit() {
|
|
3281
|
+
if (!this.splitTargetNode || !this.SplitChildNames.trim())
|
|
3282
|
+
return;
|
|
3283
|
+
const names = this.SplitChildNames.split(',')
|
|
3284
|
+
.map(n => n.trim())
|
|
3285
|
+
.filter(n => n.length > 0);
|
|
3286
|
+
if (names.length === 0)
|
|
3287
|
+
return;
|
|
3288
|
+
this.ShowSplitDialog = false;
|
|
3289
|
+
const nodeName = this.splitTargetNode.Name;
|
|
3290
|
+
const parentId = this.splitTargetNode.ParentID;
|
|
3291
|
+
try {
|
|
3292
|
+
const md = this.ProviderToUse;
|
|
3293
|
+
for (const name of names) {
|
|
3294
|
+
const tag = await md.GetEntityObject('MJ: Tags', md.CurrentUser);
|
|
3295
|
+
tag.NewRecord();
|
|
3296
|
+
tag.Name = name;
|
|
3297
|
+
tag.DisplayName = name;
|
|
3298
|
+
tag.ParentID = parentId;
|
|
3299
|
+
await tag.Save();
|
|
3300
|
+
}
|
|
3301
|
+
this.addTaxAuditEntry('split', `${nodeName} into ${names.join(', ')}`);
|
|
3302
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Split "${nodeName}" into ${names.length} new tags`, 'success', 3000);
|
|
3303
|
+
await this.RefreshTaxonomyData();
|
|
3304
|
+
}
|
|
3305
|
+
catch (error) {
|
|
3306
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
3307
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Split error: ${msg}`, 'error', 4000);
|
|
3308
|
+
}
|
|
3309
|
+
this.splitTargetNode = null;
|
|
3310
|
+
this.SplitChildNames = '';
|
|
3311
|
+
this.cdr.detectChanges();
|
|
3312
|
+
}
|
|
3313
|
+
// ── Move Dialog ──
|
|
3314
|
+
/** Opens the move-tag dialog for a given tree node */
|
|
3315
|
+
OpenMoveDialog(node) {
|
|
3316
|
+
this.moveTargetNode = node;
|
|
3317
|
+
this.MoveNewParentID = node.ParentID;
|
|
3318
|
+
this.ShowMoveDialog = true;
|
|
3319
|
+
this.cdr.detectChanges();
|
|
3320
|
+
}
|
|
3321
|
+
/** Closes the move-tag dialog without action */
|
|
3322
|
+
CloseMoveDialog() {
|
|
3323
|
+
this.ShowMoveDialog = false;
|
|
3324
|
+
this.moveTargetNode = null;
|
|
3325
|
+
this.MoveNewParentID = null;
|
|
3326
|
+
this.cdr.detectChanges();
|
|
3327
|
+
}
|
|
3328
|
+
/** Returns flat list of tags eligible as move targets (excludes the node being moved and its descendants) */
|
|
3329
|
+
GetMoveTargetOptions() {
|
|
3330
|
+
if (!this.moveTargetNode)
|
|
3331
|
+
return [];
|
|
3332
|
+
const excludeIds = this.collectDescendantIds(this.moveTargetNode);
|
|
3333
|
+
excludeIds.add(NormalizeUUID(this.moveTargetNode.ID));
|
|
3334
|
+
return this.TaxFlatNodes
|
|
3335
|
+
.filter(n => !excludeIds.has(NormalizeUUID(n.ID)))
|
|
3336
|
+
.map(n => ({ ID: n.ID, Name: n.Name, Depth: n.Depth }));
|
|
3337
|
+
}
|
|
3338
|
+
/** Collects IDs of all descendants of a node */
|
|
3339
|
+
collectDescendantIds(node) {
|
|
3340
|
+
const ids = new Set();
|
|
3341
|
+
for (const child of node.Children) {
|
|
3342
|
+
ids.add(NormalizeUUID(child.ID));
|
|
3343
|
+
for (const id of this.collectDescendantIds(child)) {
|
|
3344
|
+
ids.add(id);
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
return ids;
|
|
3348
|
+
}
|
|
3349
|
+
/** Executes the move operation */
|
|
3350
|
+
async ExecuteMove() {
|
|
3351
|
+
if (!this.moveTargetNode)
|
|
3352
|
+
return;
|
|
3353
|
+
const newParent = this.MoveNewParentID;
|
|
3354
|
+
this.ShowMoveDialog = false;
|
|
3355
|
+
await this.MoveTag(this.moveTargetNode, newParent);
|
|
3356
|
+
this.moveTargetNode = null;
|
|
3357
|
+
this.MoveNewParentID = null;
|
|
3358
|
+
this.cdr.detectChanges();
|
|
3359
|
+
}
|
|
3360
|
+
// ── Merge Into Dialog ──
|
|
3361
|
+
OpenMergeIntoDialog(node) {
|
|
3362
|
+
this.MergeSourceTag = node;
|
|
3363
|
+
this.MergeTargetID = null;
|
|
3364
|
+
this.MergeTargetData = this.GetMergeTargetOptions().map(o => ({
|
|
3365
|
+
ID: o.ID,
|
|
3366
|
+
Label: `${' '.repeat(o.Depth)}${o.Name} (${o.ItemCount})`
|
|
3367
|
+
}));
|
|
3368
|
+
this.ShowMergeIntoDialog = true;
|
|
3369
|
+
this.cdr.detectChanges();
|
|
3370
|
+
}
|
|
3371
|
+
OnMergeTargetSelected(value) {
|
|
3372
|
+
this.MergeTargetID = value != null ? String(value) : null;
|
|
3373
|
+
}
|
|
3374
|
+
CloseMergeIntoDialog() {
|
|
3375
|
+
this.ShowMergeIntoDialog = false;
|
|
3376
|
+
this.MergeSourceTag = null;
|
|
3377
|
+
this.MergeTargetID = null;
|
|
3378
|
+
this.cdr.detectChanges();
|
|
3379
|
+
}
|
|
3380
|
+
/** Returns flat list of tags eligible as merge targets (excludes the source tag) */
|
|
3381
|
+
GetMergeTargetOptions() {
|
|
3382
|
+
if (!this.MergeSourceTag)
|
|
3383
|
+
return [];
|
|
3384
|
+
const sourceNormalized = NormalizeUUID(this.MergeSourceTag.ID);
|
|
3385
|
+
return this.TaxFlatNodes
|
|
3386
|
+
.filter(n => NormalizeUUID(n.ID) !== sourceNormalized)
|
|
3387
|
+
.map(n => ({ ID: n.ID, Name: n.Name, Depth: n.Depth, ItemCount: n.ItemCount }));
|
|
3388
|
+
}
|
|
3389
|
+
async ExecuteMergeInto() {
|
|
3390
|
+
if (!this.MergeSourceTag || !this.MergeTargetID)
|
|
3391
|
+
return;
|
|
3392
|
+
const targetNode = this.TaxFlatNodes.find(n => UUIDsEqual(n.ID, this.MergeTargetID));
|
|
3393
|
+
const targetName = targetNode?.Name ?? 'Unknown';
|
|
3394
|
+
const sourceName = this.MergeSourceTag.Name;
|
|
3395
|
+
const sourceId = this.MergeSourceTag.ID;
|
|
3396
|
+
const targetId = this.MergeTargetID;
|
|
3397
|
+
this.ShowMergeIntoDialog = false;
|
|
3398
|
+
await this.MergeTags(sourceId, targetId, sourceName, targetName);
|
|
3399
|
+
this.MergeSourceTag = null;
|
|
3400
|
+
this.MergeTargetID = null;
|
|
3401
|
+
}
|
|
3402
|
+
// ── Treemap Drill-In ──
|
|
3403
|
+
/** Opens treemap drill-in panel for the given cell */
|
|
3404
|
+
OpenTreemapDrillIn(cell) {
|
|
3405
|
+
const node = this.TaxFlatNodes.find(n => UUIDsEqual(n.ID, cell.ID));
|
|
3406
|
+
if (node) {
|
|
3407
|
+
this.TreemapDrillInNode = node;
|
|
3408
|
+
this.ShowTreemapDrillIn = true;
|
|
3409
|
+
this.loadRecentItemsForTag(node);
|
|
3410
|
+
this.cdr.detectChanges();
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
/** Closes treemap drill-in panel */
|
|
3414
|
+
CloseTreemapDrillIn() {
|
|
3415
|
+
this.ShowTreemapDrillIn = false;
|
|
3416
|
+
this.TreemapDrillInNode = null;
|
|
3417
|
+
this.cdr.detectChanges();
|
|
3418
|
+
}
|
|
3419
|
+
/** Navigate from treemap drill-in to the tag in the tree view */
|
|
3420
|
+
DrillInToTreeView(node) {
|
|
3421
|
+
this.CloseTreemapDrillIn();
|
|
3422
|
+
this.SwitchTaxSubTab('tree');
|
|
3423
|
+
this.SelectTaxNode(node);
|
|
3424
|
+
}
|
|
3425
|
+
async RefreshTaxonomyData() {
|
|
3426
|
+
await this.loadTaxonomyData();
|
|
3427
|
+
this.DataChanged.emit();
|
|
3428
|
+
this.cdr.detectChanges();
|
|
3429
|
+
}
|
|
3430
|
+
static ɵfac = /*@__PURE__*/ (() => { let ɵClassifyTaxonomyTabComponent_BaseFactory; return function ClassifyTaxonomyTabComponent_Factory(__ngFactoryType__) { return (ɵClassifyTaxonomyTabComponent_BaseFactory || (ɵClassifyTaxonomyTabComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ClassifyTaxonomyTabComponent)))(__ngFactoryType__ || ClassifyTaxonomyTabComponent); }; })();
|
|
3431
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ClassifyTaxonomyTabComponent, selectors: [["classify-taxonomy-tab"]], inputs: { ContentTags: "ContentTags" }, outputs: { DataChanged: "DataChanged" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 21, vars: 15, consts: [["Title", "Taxonomy", 3, "Subtitle"], ["toolbar", ""], [3, "TabChange", "Tabs", "ActiveKey"], ["actions", ""], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "mj-action-label"], [3, "Padding", "Flex"], [1, "at-main-area"], [1, "at-page-body"], [1, "at-schedule-overlay"], [1, "at-tax-split-view"], [1, "at-tax-tree-panel", 2, "position", "relative"], [1, "at-tax-tree-toolbar"], ["type", "text", "placeholder", "Search tags...", 1, "at-search-input", 2, "flex", "1", 3, "ngModelChange", "input", "ngModel"], ["title", "Add root tag", 1, "at-tax-toolbar-btn", 3, "click"], [1, "fa-solid", "fa-plus"], ["title", "Toggle multi-select for drag reparenting", 1, "at-tax-toolbar-btn", 3, "click"], [1, "fa-solid", "fa-check-double"], [1, "at-tax-tree-body", 3, "dragover", "drop"], [1, "at-empty-state"], [1, "at-tax-tree-node", 3, "at-tax-node-selected", "at-tax-node-drag-over", "at-tax-node-multi-selected", "padding-left"], [1, "at-tax-tree-saving-overlay"], [1, "at-tax-details-panel"], [1, "at-empty-state", 2, "height", "100%"], [1, "at-tax-health-bar"], [1, "at-tax-health-label"], [1, "at-tax-health-stat"], [1, "at-tax-dot", "at-tax-dot-total"], [1, "at-tax-health-value"], [1, "at-tax-health-text"], [1, "at-tax-dot", "at-tax-dot-healthy"], [1, "at-tax-health-value", "at-tax-val-success"], [1, "at-tax-dot", "at-tax-dot-attention"], [1, "at-tax-health-value", "at-tax-val-warning"], [1, "at-tax-dot", "at-tax-dot-orphaned"], [1, "at-tax-health-value", "at-tax-val-error"], [1, "at-tax-dot", "at-tax-dot-duplicates"], [1, "at-tax-health-value", "at-tax-val-info"], [1, "fa-solid", "fa-sitemap"], [1, "at-tax-tree-node", 3, "dragstart", "dragover", "dragleave", "drop", "click"], ["type", "checkbox", 1, "at-tax-tree-checkbox", 3, "checked"], [1, "at-tax-tree-arrow", 3, "click"], [1, "at-tax-health-dot"], [1, "at-tax-tree-label"], [1, "at-tax-tree-count"], ["title", "Add child tag", 1, "at-tax-tree-add-child", 3, "click"], ["type", "checkbox", 1, "at-tax-tree-checkbox", 3, "click", "checked"], ["text", "Moving tags...", "size", "small"], [1, "at-tax-details-header"], [1, "at-tax-breadcrumb"], [1, "at-tax-bc-current"], [1, "at-tax-edit-form"], [1, "at-tag-editor-subtabs"], ["type", "button", 1, "at-tag-editor-subtab", 3, "click"], [1, "fa-solid", "fa-circle-info"], [1, "fa-solid", "fa-shield-halved"], [1, "fa-solid", "fa-arrows-turn-right"], [1, "at-tag-editor-subtab-badge"], [1, "fa-solid", "fa-users-viewfinder"], [1, "at-tag-editor-pane"], [1, "at-tax-bc-link", 3, "click"], [1, "at-tax-bc-sep"], [1, "at-tax-details-title"], ["title", "Edit name", 1, "at-tax-edit-icon", 3, "click"], [1, "fa-solid", "fa-pen"], [1, "at-tax-details-desc"], [1, "at-form-group"], [1, "at-form-label"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["rows", "3", 1, "at-form-textarea", 3, "ngModelChange", "ngModel"], [1, "at-form-actions"], [1, "at-action-btn", "at-primary-btn", 3, "click"], [1, "at-action-btn", "at-secondary-btn", 3, "click"], [1, "at-tax-stats-row"], [1, "at-tax-stat-item"], [1, "at-tax-stat-value"], [1, "at-tax-stat-label"], [1, "at-tax-stat-value", "at-tax-stat-date"], [1, "at-tax-action-toolbar"], [1, "at-tax-detail-section"], [1, "at-tax-action-btn", 3, "click"], [1, "fa-solid", "fa-arrows-up-down"], [1, "fa-solid", "fa-compress"], [1, "fa-solid", "fa-code-branch"], [1, "at-tax-action-btn", "at-tax-action-danger", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "at-tax-section-title"], [1, "at-tax-child-chips"], [1, "at-tax-child-chip"], [1, "at-tax-child-chip", 3, "click"], [1, "at-tax-chip-count"], [1, "at-tax-recent-list"], [1, "at-tax-recent-item"], [1, "at-tax-recent-icon"], [1, "at-tax-recent-name"], [1, "at-tax-recent-weight"], [1, "at-tax-recent-date"], [1, "at-tag-editor-loading"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "at-gov-toggle-row"], [3, "ngModelChange", "ngModel"], [1, "at-gov-toggle-text"], [1, "at-gov-toggle-label"], [1, "at-gov-toggle-sub"], [1, "at-gov-field-row"], ["type", "number", "min", "0", "placeholder", "Unlimited", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "0", "max", "1", "step", "0.01", "placeholder", "None", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "at-gov-impact"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click", "disabled"], [1, "fa-solid", "fa-check"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], [1, "at-syn-pending-bar"], [1, "at-syn-list"], [1, "at-tag-editor-empty"], [1, "at-syn-add"], ["type", "text", "placeholder", "Add a synonym\u2026", 1, "at-form-input", 3, "ngModelChange", "keyup.enter", "ngModel"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "at-syn-item", 3, "at-syn-item-pending"], [1, "at-syn-item"], [1, "at-syn-name"], [1, "at-syn-pill"], [1, "at-syn-pill", "at-syn-pill-pending"], ["mjButton", "", "variant", "success", "size", "sm", "title", "Approve synonym", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", "size", "sm", "title", "Reject synonym", 3, "click", "disabled"], [1, "fa-solid", "fa-xmark"], [1, "at-syn-pill", "at-syn-pill-rejected"], ["type", "button", "title", "Remove synonym", 1, "at-syn-delete", 3, "click", "disabled"], [1, "fa-solid", "fa-times"], [3, "ngModelChange", "ngModel", "Disabled"], [1, "at-scope-list"], [1, "at-scope-add"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Pick an entity\u2026", 1, "at-scope-entity-picker", 3, "ValueChange", "Data", "ValuePrimitive", "ngModel"], ["type", "text", "placeholder", "Record ID\u2026", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "at-scope-note"], [1, "at-scope-item"], [1, "at-scope-entity"], [1, "at-scope-record"], ["type", "button", "title", "Remove scope", 1, "at-syn-delete", 3, "click", "disabled"], [1, "fa-solid", "fa-hand-pointer"], [1, "at-tax-dup-stats-bar"], [1, "at-tax-dup-stat"], [1, "at-tax-dup-stat", "at-tax-dup-high"], [1, "at-tax-dup-stat", "at-tax-dup-moderate"], [1, "at-tax-dup-list"], [1, "at-tax-dup-card", 3, "at-tax-dup-high", "at-tax-dup-moderate"], [1, "fa-solid", "fa-check-circle"], [1, "at-tax-dup-card"], [1, "at-tax-dup-tag"], [1, "at-tax-dup-similarity"], [1, "at-tax-sim-percent", "high"], [1, "fa-solid", "fa-clone"], [1, "at-tax-dup-actions"], [1, "at-tax-dup-btn", "at-tax-dup-btn-primary", 3, "click", "disabled"], [1, "at-tax-dup-btn", 3, "click"], [1, "at-tax-dup-arrow"], [1, "fa-solid", "fa-arrows-left-right"], [1, "at-tax-sim-bar-bg"], [1, "at-tax-sim-bar-fill"], [1, "at-tax-sim-percent"], [1, "at-tax-orphan-toolbar"], [1, "at-tax-orphan-count"], [1, "at-tax-orphan-desc"], [1, "at-tax-orphan-bulk"], [1, "at-tax-bulk-btn", 3, "click"], [1, "fa-solid", "fa-square-check"], [1, "fa-regular", "fa-square"], [1, "at-tax-bulk-btn", "at-tax-bulk-danger", 3, "click"], [1, "fa-solid", "fa-trash-can"], [1, "at-tax-orphan-grid"], [1, "at-tax-orphan-card"], [1, "at-tax-orphan-header"], [1, "at-tax-orphan-name"], ["type", "checkbox", 1, "at-tax-orphan-checkbox", 3, "change", "click", "checked"], [1, "at-tax-orphan-stats"], [1, "at-tax-orphan-dates"], [1, "at-tax-orphan-actions"], [1, "at-tax-orphan-btn", "at-tax-orphan-delete", 3, "click"], [1, "at-tax-orphan-btn"], [1, "at-tax-treemap-kpi-strip"], [1, "at-tax-treemap-kpi"], [1, "at-tax-treemap-container"], [1, "at-tax-drillin-overlay"], [1, "at-tax-treemap-kpi-value"], [1, "at-tax-treemap-kpi-label"], [1, "fa-solid", "fa-chart-tree-map"], [1, "at-tax-treemap-cell", "at-tax-treemap-cell-clickable", 3, "class", "grid-row"], [1, "at-tax-treemap-cell", "at-tax-treemap-cell-clickable", 3, "click"], [1, "at-tax-cell-name"], [1, "at-tax-cell-count"], [1, "at-tax-drillin-overlay", 3, "click"], [1, "at-tax-drillin-panel", 3, "click"], [1, "at-tax-drillin-header"], [1, "fa-solid", "fa-tag"], ["aria-label", "Close", 1, "at-schedule-dialog-close", 3, "click"], [1, "at-tax-drillin-body"], [1, "at-tax-drillin-footer"], [1, "at-tax-audit-filters"], [1, "at-tax-audit-filter-label"], [1, "at-tax-audit-checkbox-group"], [1, "at-tax-audit-checkbox"], ["type", "checkbox", 3, "change", "checked"], [1, "at-tax-audit-timeline"], [1, "at-tax-audit-event"], [1, "fa-solid", "fa-scroll"], [1, "at-tax-audit-event-icon"], [1, "at-tax-audit-event-body"], [1, "at-tax-audit-event-desc"], [1, "at-tax-tag-ref"], [1, "at-tax-audit-event-meta"], [1, "at-schedule-overlay", 3, "click"], [1, "at-schedule-dialog", 3, "click"], [1, "at-schedule-dialog-header"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "at-schedule-dialog-body"], [1, "at-confirm-message"], [1, "at-schedule-dialog-footer"], [1, "at-action-btn", "at-danger-btn", 3, "click"], [1, "at-schedule-field"], ["type", "text", "placeholder", "Tag A, Tag B, Tag C", 1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [1, "at-action-btn", "at-primary-btn", 3, "click", "disabled"], [1, "at-tax-create-context"], ["type", "text", "placeholder", "Tag name", 1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "keydown.enter", "ngModel"], ["rows", "3", "placeholder", "Brief description of this tag", 1, "mj-textarea", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [3, "ngValue"], [2, "font-size", "0.85rem", "color", "var(--mj-text-secondary)", "margin", "0 0 12px"], ["TextField", "Label", "ValueField", "ID", "Placeholder", "Search and select a tag...", 3, "ValueChange", "Data", "Filterable", "ValuePrimitive"]], template: function ClassifyTaxonomyTabComponent_Template(rf, ctx) { if (rf & 1) {
|
|
3432
|
+
i0.ɵɵelementStart(0, "mj-page-header-interior", 0)(1, "div", 1)(2, "mj-tab-nav", 2);
|
|
3433
|
+
i0.ɵɵlistener("TabChange", function ClassifyTaxonomyTabComponent_Template_mj_tab_nav_TabChange_2_listener($event) { return ctx.onTaxSubTabChange($event); });
|
|
3434
|
+
i0.ɵɵelementEnd()();
|
|
3435
|
+
i0.ɵɵelementStart(3, "div", 3)(4, "button", 4);
|
|
3436
|
+
i0.ɵɵlistener("click", function ClassifyTaxonomyTabComponent_Template_button_click_4_listener() { return ctx.RefreshTaxonomyData(); });
|
|
3437
|
+
i0.ɵɵelement(5, "i", 5);
|
|
3438
|
+
i0.ɵɵelementStart(6, "span", 6);
|
|
3439
|
+
i0.ɵɵtext(7, "Refresh");
|
|
3440
|
+
i0.ɵɵelementEnd()()()();
|
|
3441
|
+
i0.ɵɵelementStart(8, "mj-page-body-interior", 7)(9, "div", 8)(10, "div", 9);
|
|
3442
|
+
i0.ɵɵconditionalCreate(11, ClassifyTaxonomyTabComponent_Conditional_11_Template, 49, 11);
|
|
3443
|
+
i0.ɵɵconditionalCreate(12, ClassifyTaxonomyTabComponent_Conditional_12_Template, 17, 4);
|
|
3444
|
+
i0.ɵɵconditionalCreate(13, ClassifyTaxonomyTabComponent_Conditional_13_Template, 20, 4);
|
|
3445
|
+
i0.ɵɵconditionalCreate(14, ClassifyTaxonomyTabComponent_Conditional_14_Template, 6, 2);
|
|
3446
|
+
i0.ɵɵconditionalCreate(15, ClassifyTaxonomyTabComponent_Conditional_15_Template, 32, 9);
|
|
3447
|
+
i0.ɵɵelementEnd()()();
|
|
3448
|
+
i0.ɵɵconditionalCreate(16, ClassifyTaxonomyTabComponent_Conditional_16_Template, 17, 2, "div", 10);
|
|
3449
|
+
i0.ɵɵconditionalCreate(17, ClassifyTaxonomyTabComponent_Conditional_17_Template, 21, 2, "div", 10);
|
|
3450
|
+
i0.ɵɵconditionalCreate(18, ClassifyTaxonomyTabComponent_Conditional_18_Template, 25, 4, "div", 10);
|
|
3451
|
+
i0.ɵɵconditionalCreate(19, ClassifyTaxonomyTabComponent_Conditional_19_Template, 23, 2, "div", 10);
|
|
3452
|
+
i0.ɵɵconditionalCreate(20, ClassifyTaxonomyTabComponent_Conditional_20_Template, 21, 7, "div", 10);
|
|
3453
|
+
} if (rf & 2) {
|
|
3454
|
+
i0.ɵɵproperty("Subtitle", ctx.Subtitle);
|
|
3455
|
+
i0.ɵɵadvance(2);
|
|
3456
|
+
i0.ɵɵproperty("Tabs", ctx.taxSubTabsConfig)("ActiveKey", ctx.TaxSubTab);
|
|
3457
|
+
i0.ɵɵadvance(6);
|
|
3458
|
+
i0.ɵɵproperty("Padding", false)("Flex", true);
|
|
3459
|
+
i0.ɵɵadvance(3);
|
|
3460
|
+
i0.ɵɵconditional(ctx.TaxSubTab === "tree" ? 11 : -1);
|
|
3461
|
+
i0.ɵɵadvance();
|
|
3462
|
+
i0.ɵɵconditional(ctx.TaxSubTab === "duplicates" ? 12 : -1);
|
|
3463
|
+
i0.ɵɵadvance();
|
|
3464
|
+
i0.ɵɵconditional(ctx.TaxSubTab === "orphans" ? 13 : -1);
|
|
3465
|
+
i0.ɵɵadvance();
|
|
3466
|
+
i0.ɵɵconditional(ctx.TaxSubTab === "treemap" ? 14 : -1);
|
|
3467
|
+
i0.ɵɵadvance();
|
|
3468
|
+
i0.ɵɵconditional(ctx.TaxSubTab === "audit" ? 15 : -1);
|
|
3469
|
+
i0.ɵɵadvance();
|
|
3470
|
+
i0.ɵɵconditional(ctx.ShowConfirmDialog ? 16 : -1);
|
|
3471
|
+
i0.ɵɵadvance();
|
|
3472
|
+
i0.ɵɵconditional(ctx.ShowSplitDialog ? 17 : -1);
|
|
3473
|
+
i0.ɵɵadvance();
|
|
3474
|
+
i0.ɵɵconditional(ctx.ShowCreateTagDialog ? 18 : -1);
|
|
3475
|
+
i0.ɵɵadvance();
|
|
3476
|
+
i0.ɵɵconditional(ctx.ShowMoveDialog ? 19 : -1);
|
|
3477
|
+
i0.ɵɵadvance();
|
|
3478
|
+
i0.ɵɵconditional(ctx.ShowMergeIntoDialog ? 20 : -1);
|
|
3479
|
+
} }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.MinValidator, i1.MaxValidator, i1.NgModel, i2.LoadingComponent, i3.MJButtonDirective, i3.MJComboboxComponent, i3.MJSwitchComponent, i3.MJPageHeaderInteriorComponent, i3.MJPageBodyInteriorComponent, i3.MJTabNavComponent], styles: ["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.at-tag-editor-subtabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n border-bottom: 1px solid var(--mj-border-default);\n margin: 12px 0 16px;\n}\n.at-tag-editor-subtab[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n margin-bottom: -1px;\n}\n.at-tag-editor-subtab[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n.at-tag-editor-subtab-active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n.at-tag-editor-subtab-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: var(--mj-radius-full, 999px);\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 700;\n}\n\n\n\n.at-tag-editor-pane[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n.at-tag-editor-loading[_ngcontent-%COMP%], \n.at-tag-editor-empty[_ngcontent-%COMP%] {\n padding: 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n\n\n.at-gov-toggle-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius, 8px);\n}\n.at-gov-toggle-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n.at-gov-toggle-sub[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n.at-gov-field-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 12px;\n}\n.at-gov-impact[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-info-border);\n border-radius: var(--mj-radius, 8px);\n color: var(--mj-status-info-text);\n font-size: 12.5px;\n}\n.at-gov-impact[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-top: 2px;\n color: var(--mj-status-info);\n}\n\n\n\n.at-syn-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.at-syn-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius, 8px);\n}\n.at-syn-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n.at-syn-pill[_ngcontent-%COMP%] {\n padding: 2px 10px;\n border-radius: var(--mj-radius-full, 999px);\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n.at-syn-pill-manual[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n.at-syn-pill-llm[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n color: var(--mj-status-info-text);\n}\n.at-syn-pill-imported[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n.at-syn-pill-merged[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 14%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text);\n}\n.at-syn-pill-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 18%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text);\n}\n.at-syn-pill-rejected[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n.at-syn-item-pending[_ngcontent-%COMP%] {\n border-color: var(--mj-status-warning-border);\n background: color-mix(in srgb, var(--mj-status-warning) 6%, var(--mj-bg-surface-card));\n}\n.at-syn-pending-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 9px 12px;\n margin-bottom: 10px;\n font-size: 12px;\n border-radius: var(--mj-radius, 8px);\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n.at-syn-delete[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n border-radius: var(--mj-radius-sm, 4px);\n}\n.at-syn-delete[_ngcontent-%COMP%]:hover:not(:disabled) {\n color: var(--mj-status-error);\n background: var(--mj-bg-surface-hover);\n}\n.at-syn-delete[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.at-syn-add[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.at-syn-add[_ngcontent-%COMP%] .at-form-input[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n\n\n.at-scope-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.at-scope-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius, 8px);\n}\n.at-scope-entity[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n.at-scope-record[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-family: var(--mj-font-mono, monospace);\n}\n.at-scope-add[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.at-scope-entity-picker[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n.at-scope-add[_ngcontent-%COMP%] .at-form-input[_ngcontent-%COMP%] {\n flex: 1;\n}\n.at-scope-note[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}"] });
|
|
3480
|
+
}
|
|
3481
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ClassifyTaxonomyTabComponent, [{
|
|
3482
|
+
type: Component,
|
|
3483
|
+
args: [{ standalone: false, selector: 'classify-taxonomy-tab', template: "<mj-page-header-interior\n Title=\"Taxonomy\"\n [Subtitle]=\"Subtitle\">\n <div toolbar>\n <mj-tab-nav\n [Tabs]=\"taxSubTabsConfig\"\n [ActiveKey]=\"TaxSubTab\"\n (TabChange)=\"onTaxSubTabChange($event)\">\n </mj-tab-nav>\n </div>\n <div actions>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"RefreshTaxonomyData()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> <span class=\"mj-action-label\">Refresh</span>\n </button>\n </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior [Padding]=\"false\" [Flex]=\"true\">\n<div class=\"at-main-area\">\n\n <div class=\"at-page-body\">\n\n <!-- \u2550\u2550 SUB-TAB 1: TREE VIEW \u2550\u2550 -->\n @if (TaxSubTab === 'tree') {\n <div class=\"at-tax-split-view\">\n <!-- Tree panel -->\n <div class=\"at-tax-tree-panel\" style=\"position: relative;\">\n <div class=\"at-tax-tree-toolbar\">\n <input type=\"text\" class=\"at-search-input\" style=\"flex: 1;\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TaxTreeSearch\" (input)=\"FilterTaxTree()\">\n <button class=\"at-tax-toolbar-btn\" title=\"Add root tag\" (click)=\"OpenCreateRootTag()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"at-tax-toolbar-btn\" [class.active]=\"TaxMultiSelectMode\"\n title=\"Toggle multi-select for drag reparenting\" (click)=\"ToggleMultiSelectMode()\">\n <i class=\"fa-solid fa-check-double\"></i>\n </button>\n </div>\n <div class=\"at-tax-tree-body\"\n (dragover)=\"$event.preventDefault()\"\n (drop)=\"OnDropToRoot($event)\">\n @if (TaxFilteredNodes.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-sitemap\"></i>\n <p>No tags found</p>\n </div>\n }\n @for (node of TaxFilteredNodes; track node.ID) {\n <div class=\"at-tax-tree-node\"\n [class.at-tax-node-selected]=\"node.IsSelected\"\n [class.at-tax-node-drag-over]=\"TaxDragOverNodeID === node.ID\"\n [class.at-tax-node-multi-selected]=\"IsNodeMultiSelected(node.ID)\"\n [style.padding-left.px]=\"16 + node.Depth * 20\"\n [attr.draggable]=\"true\"\n (dragstart)=\"OnTreeNodeDragStart($event, node)\"\n (dragover)=\"OnTreeNodeDragOver($event, node)\"\n (dragleave)=\"OnTreeNodeDragLeave()\"\n (drop)=\"OnTreeNodeDrop($event, node); $event.stopPropagation()\"\n (click)=\"SelectTaxNode(node)\">\n @if (TaxMultiSelectMode) {\n <input type=\"checkbox\" class=\"at-tax-tree-checkbox\"\n [checked]=\"IsNodeMultiSelected(node.ID)\"\n (click)=\"ToggleNodeSelection(node, $event)\">\n }\n <span class=\"at-tax-tree-arrow\"\n [class.at-tax-arrow-expanded]=\"node.IsExpanded && node.Children.length > 0\"\n [class.at-tax-arrow-collapsed]=\"!node.IsExpanded && node.Children.length > 0\"\n [class.at-tax-arrow-leaf]=\"node.Children.length === 0\"\n (click)=\"ToggleTaxNode(node); $event.stopPropagation()\"></span>\n <span class=\"at-tax-health-dot\" [class]=\"node.HealthColor\"></span>\n <span class=\"at-tax-tree-label\" [class.at-tax-tree-label-selected]=\"node.IsSelected\">{{ node.Name }}</span>\n <span class=\"at-tax-tree-count\">({{ node.ItemCount }})</span>\n <span class=\"at-tax-tree-add-child\" title=\"Add child tag\"\n (click)=\"OpenCreateChildTagFor(node); $event.stopPropagation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </span>\n </div>\n }\n </div>\n @if (TaxTreeSaving) {\n <div class=\"at-tax-tree-saving-overlay\">\n <mj-loading text=\"Moving tags...\" size=\"small\"></mj-loading>\n </div>\n }\n </div>\n\n <!-- Details panel -->\n <div class=\"at-tax-details-panel\">\n @if (TaxSelectedNode) {\n <div class=\"at-tax-details-header\">\n <!-- Breadcrumb -->\n <div class=\"at-tax-breadcrumb\">\n @for (bc of GetTaxBreadcrumb(TaxSelectedNode); track bc.ID) {\n <span class=\"at-tax-bc-link\" (click)=\"NavigateToBreadcrumb(bc.ID)\">{{ bc.Name }}</span>\n <span class=\"at-tax-bc-sep\">›</span>\n }\n <span class=\"at-tax-bc-current\">{{ TaxSelectedNode.Name }}</span>\n </div>\n\n @if (!TaxIsEditing) {\n <div class=\"at-tax-details-title\">\n {{ TaxSelectedNode.DisplayName }}\n <span class=\"at-tax-edit-icon\" (click)=\"StartEditTag()\" title=\"Edit name\">\n <i class=\"fa-solid fa-pen\"></i>\n </span>\n </div>\n @if (TaxSelectedNode.Description) {\n <div class=\"at-tax-details-desc\">{{ TaxSelectedNode.Description }}</div>\n }\n } @else {\n <div class=\"at-tax-edit-form\">\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"TaxEditName\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Description</label>\n <textarea class=\"at-form-textarea\" rows=\"3\" [(ngModel)]=\"TaxEditDescription\"></textarea>\n </div>\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveEditTag()\">Save</button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CancelEditTag()\">Cancel</button>\n </div>\n </div>\n }\n </div>\n\n <!-- Editor sub-tab nav: Overview / Governance / Synonyms / Scope -->\n <div class=\"at-tag-editor-subtabs\">\n <button type=\"button\" class=\"at-tag-editor-subtab\" [class.at-tag-editor-subtab-active]=\"TagEditorSubTab === 'overview'\"\n (click)=\"SwitchTagEditorSubTab('overview')\">\n <i class=\"fa-solid fa-circle-info\"></i> Overview\n </button>\n <button type=\"button\" class=\"at-tag-editor-subtab\" [class.at-tag-editor-subtab-active]=\"TagEditorSubTab === 'governance'\"\n (click)=\"SwitchTagEditorSubTab('governance')\">\n <i class=\"fa-solid fa-shield-halved\"></i> Governance\n </button>\n <button type=\"button\" class=\"at-tag-editor-subtab\" [class.at-tag-editor-subtab-active]=\"TagEditorSubTab === 'synonyms'\"\n (click)=\"SwitchTagEditorSubTab('synonyms')\">\n <i class=\"fa-solid fa-arrows-turn-right\"></i> Synonyms\n @if (Synonyms.length > 0) {\n <span class=\"at-tag-editor-subtab-badge\">{{ Synonyms.length }}</span>\n }\n </button>\n <button type=\"button\" class=\"at-tag-editor-subtab\" [class.at-tag-editor-subtab-active]=\"TagEditorSubTab === 'scope'\"\n (click)=\"SwitchTagEditorSubTab('scope')\">\n <i class=\"fa-solid fa-users-viewfinder\"></i> Scope\n </button>\n </div>\n\n @if (TagEditorSubTab === 'overview') {\n <!-- Stats row -->\n <div class=\"at-tax-stats-row\">\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.ItemCount }}</div>\n <div class=\"at-tax-stat-label\">Items Tagged</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.AvgWeight.toFixed(2) }}</div>\n <div class=\"at-tax-stat-label\">Avg Weight</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.Children.length }}</div>\n <div class=\"at-tax-stat-label\">Children</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.Depth }}</div>\n <div class=\"at-tax-stat-label\">Depth</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value at-tax-stat-date\">{{ TaxSelectedNode.FirstSeen }}</div>\n <div class=\"at-tax-stat-label\">First Seen</div>\n </div>\n </div>\n\n <!-- Action toolbar -->\n @if (!TaxIsEditing) {\n <div class=\"at-tax-action-toolbar\">\n <button class=\"at-tax-action-btn\" (click)=\"OpenCreateChildTag()\"><i class=\"fa-solid fa-plus\"></i> Add Child</button>\n <button class=\"at-tax-action-btn\" (click)=\"StartEditTag()\"><i class=\"fa-solid fa-pen\"></i> Rename</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenMoveDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-arrows-up-down\"></i> Move</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenMergeIntoDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-compress\"></i> Merge Into...</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenSplitDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-code-branch\"></i> Split</button>\n <button class=\"at-tax-action-btn at-tax-action-danger\" (click)=\"DeleteTag(TaxSelectedNode)\"><i class=\"fa-solid fa-trash\"></i> Delete</button>\n </div>\n }\n\n <!-- Child tags -->\n @if (TaxSelectedNode.Children.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Child Tags</div>\n <div class=\"at-tax-child-chips\">\n @for (child of TaxSelectedNode.Children; track child.ID) {\n <span class=\"at-tax-child-chip\" (click)=\"SelectTaxNode(child)\">\n {{ child.Name }}\n <span class=\"at-tax-chip-count\">{{ child.ItemCount }}</span>\n </span>\n }\n </div>\n </div>\n }\n\n <!-- Recently tagged items -->\n @if (TaxRecentItems.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Recently Tagged Items</div>\n <div class=\"at-tax-recent-list\">\n @for (item of TaxRecentItems; track $index) {\n <div class=\"at-tax-recent-item\">\n <div class=\"at-tax-recent-icon\"><i [class]=\"item.Icon\"></i></div>\n <div class=\"at-tax-recent-name\">{{ item.Name }}</div>\n <div class=\"at-tax-recent-weight\">{{ item.Weight.toFixed(2) }}</div>\n <div class=\"at-tax-recent-date\">{{ item.Date }}</div>\n </div>\n }\n </div>\n </div>\n }\n }\n\n <!-- \u2500\u2500 Governance panel \u2500\u2500 -->\n @if (TagEditorSubTab === 'governance') {\n <div class=\"at-tag-editor-pane\">\n @if (GovernanceLoading) {\n <div class=\"at-tag-editor-loading\"><i class=\"fa-solid fa-spinner fa-spin\"></i> Loading governance\u2026</div>\n } @else if (GovernanceTag) {\n <div class=\"at-gov-toggle-row\">\n <mj-switch [(ngModel)]=\"GovIsFrozen\"></mj-switch>\n <div class=\"at-gov-toggle-text\">\n <div class=\"at-gov-toggle-label\">Frozen subtree</div>\n <div class=\"at-gov-toggle-sub\">Blocks all auto-grow below this node</div>\n </div>\n </div>\n <div class=\"at-gov-toggle-row\">\n <mj-switch [(ngModel)]=\"GovAllowAutoGrow\"></mj-switch>\n <div class=\"at-gov-toggle-text\">\n <div class=\"at-gov-toggle-label\">Allow auto-grow</div>\n <div class=\"at-gov-toggle-sub\">Classifier may create children under this node</div>\n </div>\n </div>\n <div class=\"at-gov-toggle-row\">\n <mj-switch [(ngModel)]=\"GovRequiresReview\"></mj-switch>\n <div class=\"at-gov-toggle-text\">\n <div class=\"at-gov-toggle-label\">Requires review</div>\n <div class=\"at-gov-toggle-sub\">Every classifier hit on this tag routes to review instead of auto-applying</div>\n </div>\n </div>\n\n <div class=\"at-gov-field-row\">\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Max children</label>\n <input type=\"number\" min=\"0\" class=\"at-form-input\" [(ngModel)]=\"GovMaxChildren\" placeholder=\"Unlimited\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Max depth below</label>\n <input type=\"number\" min=\"0\" class=\"at-form-input\" [(ngModel)]=\"GovMaxDescendantDepth\" placeholder=\"Unlimited\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Min weight (0\u20131)</label>\n <input type=\"number\" min=\"0\" max=\"1\" step=\"0.01\" class=\"at-form-input\" [(ngModel)]=\"GovMinWeight\" placeholder=\"None\">\n </div>\n </div>\n\n <div class=\"at-gov-impact\">\n <i class=\"fa-solid fa-circle-info\"></i>\n <span><b>Subtree impact:</b> {{ GovernanceImpactHint }}</span>\n </div>\n\n <div class=\"at-form-actions\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"GovernanceSaving\" (click)=\"SaveGovernance()\">\n <i class=\"fa-solid fa-check\"></i> Save governance\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"GovernanceSaving\" (click)=\"ResetGovernance()\">Reset</button>\n </div>\n } @else {\n <div class=\"at-tag-editor-loading\">Unable to load governance for this tag.</div>\n }\n </div>\n }\n\n <!-- \u2500\u2500 Synonyms panel \u2500\u2500 -->\n @if (TagEditorSubTab === 'synonyms') {\n <div class=\"at-tag-editor-pane\">\n @if (SynonymsLoading) {\n <div class=\"at-tag-editor-loading\"><i class=\"fa-solid fa-spinner fa-spin\"></i> Loading synonyms\u2026</div>\n } @else {\n @if (PendingSynonymCount > 0) {\n <div class=\"at-syn-pending-bar\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n {{ PendingSynonymCount }} proposed {{ PendingSynonymCount === 1 ? 'synonym' : 'synonyms' }} awaiting review \u2014 these don't resolve until approved.\n </div>\n }\n @if (Synonyms.length > 0) {\n <div class=\"at-syn-list\">\n @for (syn of Synonyms; track syn.ID) {\n <div class=\"at-syn-item\" [class.at-syn-item-pending]=\"syn.Status === 'Pending'\">\n <span class=\"at-syn-name\">{{ syn.Synonym }}</span>\n <span class=\"at-syn-pill\" [class]=\"GetSynonymSourceClass(syn.Source)\">{{ syn.Source }}</span>\n @if (syn.Status === 'Pending') {\n <span class=\"at-syn-pill at-syn-pill-pending\">Pending</span>\n <button mjButton variant=\"success\" size=\"sm\" title=\"Approve synonym\"\n [disabled]=\"SynonymSaving\" (click)=\"ApproveSynonym(syn)\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button mjButton variant=\"outline\" size=\"sm\" title=\"Reject synonym\"\n [disabled]=\"SynonymSaving\" (click)=\"RejectSynonym(syn)\">\n <i class=\"fa-solid fa-xmark\"></i> Reject\n </button>\n } @else {\n @if (syn.Status === 'Rejected') {\n <span class=\"at-syn-pill at-syn-pill-rejected\">Rejected</span>\n }\n <button type=\"button\" class=\"at-syn-delete\" title=\"Remove synonym\"\n [disabled]=\"SynonymSaving\" (click)=\"DeleteSynonym(syn)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"at-tag-editor-empty\">No synonyms yet for this tag.</div>\n }\n\n <div class=\"at-syn-add\">\n <input type=\"text\" class=\"at-form-input\" placeholder=\"Add a synonym\u2026\"\n [(ngModel)]=\"NewSynonymText\" (keyup.enter)=\"AddSynonym()\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"SynonymSaving || !NewSynonymText.trim()\" (click)=\"AddSynonym()\">\n <i class=\"fa-solid fa-plus\"></i> Add\n </button>\n </div>\n }\n </div>\n }\n\n <!-- \u2500\u2500 Scope panel \u2500\u2500 -->\n @if (TagEditorSubTab === 'scope') {\n <div class=\"at-tag-editor-pane\">\n @if (ScopesLoading || GovernanceLoading) {\n <div class=\"at-tag-editor-loading\"><i class=\"fa-solid fa-spinner fa-spin\"></i> Loading scope\u2026</div>\n } @else if (GovernanceTag) {\n <div class=\"at-gov-toggle-row\">\n <mj-switch [ngModel]=\"IsTagGlobal\" (ngModelChange)=\"ToggleTagGlobal($event)\" [Disabled]=\"ScopeSaving\"></mj-switch>\n <div class=\"at-gov-toggle-text\">\n <div class=\"at-gov-toggle-label\">Global tag</div>\n <div class=\"at-gov-toggle-sub\">Visible to every tenant/scope when on</div>\n </div>\n </div>\n\n @if (!IsTagGlobal) {\n @if (Scopes.length > 0) {\n <div class=\"at-scope-list\">\n @for (scope of Scopes; track scope.ID) {\n <div class=\"at-scope-item\">\n <span class=\"at-scope-entity\">{{ scope.ScopeEntity }}</span>\n <span class=\"at-scope-record\">{{ scope.ScopeRecordID }}</span>\n <button type=\"button\" class=\"at-syn-delete\" title=\"Remove scope\"\n [disabled]=\"ScopeSaving\" (click)=\"DeleteScope(scope)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n } @else {\n <div class=\"at-tag-editor-empty\">No scope restrictions \u2014 add one to limit visibility.</div>\n }\n\n <div class=\"at-scope-add\">\n <mj-combobox class=\"at-scope-entity-picker\"\n [Data]=\"ScopeEntityOptions\" TextField=\"Name\" ValueField=\"ID\"\n [ValuePrimitive]=\"true\" Placeholder=\"Pick an entity\u2026\"\n [ngModel]=\"NewScopeEntityID\" (ValueChange)=\"OnScopeEntitySelected($event)\">\n </mj-combobox>\n <input type=\"text\" class=\"at-form-input\" placeholder=\"Record ID\u2026\" [(ngModel)]=\"NewScopeRecordID\">\n <button mjButton variant=\"primary\" size=\"sm\"\n [disabled]=\"ScopeSaving || !NewScopeEntityID || !NewScopeRecordID.trim()\" (click)=\"AddScope()\">\n <i class=\"fa-solid fa-plus\"></i> Add\n </button>\n </div>\n\n <div class=\"at-scope-note\">\n <i class=\"fa-solid fa-circle-info\"></i> Children inherit their parent's scope.\n </div>\n }\n } @else {\n <div class=\"at-tag-editor-loading\">Unable to load scope for this tag.</div>\n }\n </div>\n }\n } @else {\n <div class=\"at-empty-state\" style=\"height: 100%;\">\n <i class=\"fa-solid fa-hand-pointer\"></i>\n <p>Select a tag from the tree to view details</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Health bar -->\n <div class=\"at-tax-health-bar\">\n <span class=\"at-tax-health-label\">Taxonomy Health</span>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-total\"></span>\n <span class=\"at-tax-health-value\">{{ TaxHealth.Total }}</span>\n <span class=\"at-tax-health-text\">Total</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-healthy\"></span>\n <span class=\"at-tax-health-value at-tax-val-success\">{{ TaxHealth.Healthy }}</span>\n <span class=\"at-tax-health-text\">Healthy</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-attention\"></span>\n <span class=\"at-tax-health-value at-tax-val-warning\">{{ TaxHealth.NeedAttention }}</span>\n <span class=\"at-tax-health-text\">Need Attention</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-orphaned\"></span>\n <span class=\"at-tax-health-value at-tax-val-error\">{{ TaxHealth.Orphaned }}</span>\n <span class=\"at-tax-health-text\">Orphaned</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-duplicates\"></span>\n <span class=\"at-tax-health-value at-tax-val-info\">{{ TaxHealth.Duplicates }}</span>\n <span class=\"at-tax-health-text\">Duplicate Candidates</span>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 2: DUPLICATES \u2550\u2550 -->\n @if (TaxSubTab === 'duplicates') {\n <div class=\"at-tax-dup-stats-bar\">\n <div class=\"at-tax-dup-stat\"><strong>{{ TaxDuplicates.length }}</strong> candidates found</div>\n <div class=\"at-tax-dup-stat at-tax-dup-high\"><strong>{{ TaxHighConfidenceDupeCount }}</strong> high confidence (>85%)</div>\n <div class=\"at-tax-dup-stat at-tax-dup-moderate\"><strong>{{ TaxModerateDupeCount }}</strong> moderate (70-85%)</div>\n </div>\n\n @if (TaxDuplicates.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <p>No duplicate tags detected</p>\n </div>\n }\n\n <div class=\"at-tax-dup-list\">\n @for (pair of TaxDuplicates; track $index) {\n <div class=\"at-tax-dup-card\" [class.at-tax-dup-high]=\"pair.SeverityClass === 'high'\" [class.at-tax-dup-moderate]=\"pair.SeverityClass === 'moderate'\">\n @if (pair.IsExactDuplicate) {\n <!-- Exact-name duplicates: show single tag name with count -->\n <div class=\"at-tax-dup-tag\">{{ pair.TagA }}</div>\n <div class=\"at-tax-dup-similarity\">\n <span class=\"at-tax-sim-percent high\">\n <i class=\"fa-solid fa-clone\"></i> {{ pair.ExactDuplicateCount }} identical records\n </span>\n </div>\n <div class=\"at-tax-dup-actions\">\n <button class=\"at-tax-dup-btn at-tax-dup-btn-primary\" (click)=\"MergeTags(pair.TagAID, pair.TagBID, pair.TagA, pair.TagB)\" [disabled]=\"IsMerging\">@if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { Merge }</button>\n <button class=\"at-tax-dup-btn\" (click)=\"DismissDuplicate(pair)\">Dismiss</button>\n </div>\n } @else {\n <!-- Similar (non-exact) pairs: show both tags with similarity -->\n <div class=\"at-tax-dup-tag\">{{ pair.TagA }}</div>\n <div class=\"at-tax-dup-arrow\"><i class=\"fa-solid fa-arrows-left-right\"></i></div>\n <div class=\"at-tax-dup-similarity\">\n <div class=\"at-tax-sim-bar-bg\">\n <div class=\"at-tax-sim-bar-fill\" [class]=\"pair.SeverityClass\" [style.width.%]=\"pair.Similarity\"></div>\n </div>\n <span class=\"at-tax-sim-percent\" [class]=\"pair.SeverityClass\">{{ pair.Similarity }}%</span>\n </div>\n <div class=\"at-tax-dup-arrow\"><i class=\"fa-solid fa-arrows-left-right\"></i></div>\n <div class=\"at-tax-dup-tag\">{{ pair.TagB }}</div>\n <div class=\"at-tax-dup-actions\">\n <button class=\"at-tax-dup-btn at-tax-dup-btn-primary\" (click)=\"MergeTags(pair.TagAID, pair.TagBID, pair.TagA, pair.TagB)\" [disabled]=\"IsMerging\">@if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { Merge }</button>\n <button class=\"at-tax-dup-btn\" (click)=\"MakeChildTag(pair.TagAID, pair.TagBID)\">Make Child</button>\n <button class=\"at-tax-dup-btn\" (click)=\"DismissDuplicate(pair)\">Dismiss</button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 3: ORPHANS \u2550\u2550 -->\n @if (TaxSubTab === 'orphans') {\n <div class=\"at-tax-orphan-toolbar\">\n <span class=\"at-tax-orphan-count\">{{ TaxOrphans.length }} orphaned tags</span>\n <span class=\"at-tax-orphan-desc\">— no parent, no children, low usage</span>\n <div class=\"at-tax-orphan-bulk\">\n <button class=\"at-tax-bulk-btn\" (click)=\"ToggleAllOrphans()\">\n @if (TaxAllOrphansSelected) { <i class=\"fa-solid fa-square-check\"></i> } @else { <i class=\"fa-regular fa-square\"></i> }\n Select All\n </button>\n <button class=\"at-tax-bulk-btn at-tax-bulk-danger\" (click)=\"BulkDeleteOrphans()\">\n <i class=\"fa-solid fa-trash\"></i> Bulk Delete\n </button>\n <button class=\"at-tax-bulk-btn at-tax-bulk-danger\" (click)=\"DeleteAllOrphans()\">\n <i class=\"fa-solid fa-trash-can\"></i> Delete All ({{ TaxOrphans.length }})\n </button>\n </div>\n </div>\n\n @if (TaxOrphans.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <p>No orphaned tags</p>\n </div>\n }\n\n <div class=\"at-tax-orphan-grid\">\n @for (orphan of TaxOrphans; track orphan.ID) {\n <div class=\"at-tax-orphan-card\">\n <div class=\"at-tax-orphan-header\">\n <span class=\"at-tax-orphan-name\">{{ orphan.Name }}</span>\n <input type=\"checkbox\" class=\"at-tax-orphan-checkbox\" [checked]=\"orphan.IsSelected\"\n (change)=\"ToggleOrphanSelection(orphan)\" (click)=\"$event.stopPropagation()\">\n </div>\n <div class=\"at-tax-orphan-stats\">\n <span>Usage: <strong>{{ orphan.UsageCount }}</strong></span>\n <span>Avg Weight: <strong>{{ orphan.AvgWeight.toFixed(2) }}</strong></span>\n </div>\n <div class=\"at-tax-orphan-dates\">\n <span>First: {{ orphan.FirstSeen }}</span>\n <span>Last: {{ orphan.LastSeen }}</span>\n </div>\n <div class=\"at-tax-orphan-actions\">\n <button class=\"at-tax-orphan-btn at-tax-orphan-delete\" (click)=\"DeleteOrphan(orphan)\">Delete</button>\n <button class=\"at-tax-orphan-btn\">Ignore</button>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 4: TREEMAP \u2550\u2550 -->\n @if (TaxSubTab === 'treemap') {\n <div class=\"at-tax-treemap-kpi-strip\">\n @for (kpi of TaxTreemapKPIs; track kpi.Label) {\n <div class=\"at-tax-treemap-kpi\">\n <div class=\"at-tax-treemap-kpi-value\">{{ kpi.Value }}</div>\n <div class=\"at-tax-treemap-kpi-label\">{{ kpi.Label }}</div>\n </div>\n }\n </div>\n\n @if (TaxTreemapCells.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-chart-tree-map\"></i>\n <p>No taxonomy data to visualize</p>\n </div>\n } @else {\n <div class=\"at-tax-treemap-container\">\n @for (cell of TaxTreemapCells; track $index) {\n <div class=\"at-tax-treemap-cell at-tax-treemap-cell-clickable\" [class]=\"cell.ColorClass\"\n [style.grid-row]=\"cell.RowSpan > 1 ? 'span ' + cell.RowSpan : ''\"\n (click)=\"OpenTreemapDrillIn(cell)\">\n <span class=\"at-tax-cell-name\">{{ cell.Name }}</span>\n <span class=\"at-tax-cell-count\">{{ cell.ItemCount }} items</span>\n </div>\n }\n </div>\n }\n\n <!-- Treemap Drill-In Panel -->\n @if (ShowTreemapDrillIn && TreemapDrillInNode) {\n <div class=\"at-tax-drillin-overlay\" (click)=\"CloseTreemapDrillIn()\">\n <div class=\"at-tax-drillin-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-tax-drillin-header\">\n <h3><i class=\"fa-solid fa-tag\"></i> {{ TreemapDrillInNode.Name }}</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseTreemapDrillIn()\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-tax-drillin-body\">\n <div class=\"at-tax-stats-row\">\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.ItemCount }}</div>\n <div class=\"at-tax-stat-label\">Items Tagged</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.AvgWeight.toFixed(2) }}</div>\n <div class=\"at-tax-stat-label\">Avg Weight</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.Children.length }}</div>\n <div class=\"at-tax-stat-label\">Children</div>\n </div>\n </div>\n\n @if (TreemapDrillInNode.Children.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Child Tags</div>\n <div class=\"at-tax-child-chips\">\n @for (child of TreemapDrillInNode.Children; track child.ID) {\n <span class=\"at-tax-child-chip\">{{ child.Name }} <span class=\"at-tax-chip-count\">{{ child.ItemCount }}</span></span>\n }\n </div>\n </div>\n }\n\n @if (TaxRecentItems.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Recently Tagged Items</div>\n <div class=\"at-tax-recent-list\">\n @for (item of TaxRecentItems; track $index) {\n <div class=\"at-tax-recent-item\">\n <div class=\"at-tax-recent-icon\"><i [class]=\"item.Icon\"></i></div>\n <div class=\"at-tax-recent-name\">{{ item.Name }}</div>\n <div class=\"at-tax-recent-weight\">{{ item.Weight.toFixed(2) }}</div>\n <div class=\"at-tax-recent-date\">{{ item.Date }}</div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tax-drillin-footer\">\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"DrillInToTreeView(TreemapDrillInNode)\">\n <i class=\"fa-solid fa-sitemap\"></i> View in Tree\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n <!-- \u2550\u2550 SUB-TAB 5: AUDIT LOG \u2550\u2550 -->\n @if (TaxSubTab === 'audit') {\n <div class=\"at-tax-audit-filters\">\n <span class=\"at-tax-audit-filter-label\">Filter</span>\n <div class=\"at-tax-audit-checkbox-group\">\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('created')\" (change)=\"ToggleTaxAuditFilter('created')\"> Created\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('merged')\" (change)=\"ToggleTaxAuditFilter('merged')\"> Merged\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('moved')\" (change)=\"ToggleTaxAuditFilter('moved')\"> Moved\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('deleted')\" (change)=\"ToggleTaxAuditFilter('deleted')\"> Deleted\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('renamed')\" (change)=\"ToggleTaxAuditFilter('renamed')\"> Renamed\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('deprecated')\" (change)=\"ToggleTaxAuditFilter('deprecated')\"> Deprecated\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('split')\" (change)=\"ToggleTaxAuditFilter('split')\"> Split\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('reactivated')\" (change)=\"ToggleTaxAuditFilter('reactivated')\"> Reactivated\n </label>\n </div>\n </div>\n\n @if (GetFilteredAuditEvents().length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-scroll\"></i>\n <p>No audit events match the current filters</p>\n </div>\n }\n\n <div class=\"at-tax-audit-timeline\">\n @for (event of GetFilteredAuditEvents(); track $index) {\n <div class=\"at-tax-audit-event\">\n <div class=\"at-tax-audit-event-icon\" [class]=\"event.Type\">\n <i [class]=\"GetTaxAuditIcon(event.Type)\"></i>\n </div>\n <div class=\"at-tax-audit-event-body\">\n <div class=\"at-tax-audit-event-desc\">\n {{ event.Description }} <span class=\"at-tax-tag-ref\">{{ event.TagRef }}</span>\n </div>\n <div class=\"at-tax-audit-event-meta\">\n <span>{{ event.User }}</span>\n <span>{{ event.Timestamp }}</span>\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n</div>\n</mj-page-body-interior>\n\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 CONFIRMATION DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowConfirmDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"ConfirmDialogCancel()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-triangle-exclamation\"></i> {{ ConfirmDialogTitle }}</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"ConfirmDialogCancel()\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <p class=\"at-confirm-message\">{{ ConfirmDialogMessage }}</p>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-danger-btn\" (click)=\"ConfirmDialogAccept()\">\n <i class=\"fa-solid fa-check\"></i> Confirm\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"ConfirmDialogCancel()\">Cancel</button>\n </div>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 SPLIT DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowSplitDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseSplitDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-code-branch\"></i> Split Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseSplitDialog()\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>New tag names (comma-separated)</label>\n <input type=\"text\" class=\"mj-input\" style=\"width: 100%;\"\n [(ngModel)]=\"SplitChildNames\"\n placeholder=\"Tag A, Tag B, Tag C\" />\n </div>\n <p class=\"at-confirm-message\">New tags will be created as siblings of the original tag under the same parent.</p>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteSplit()\" [disabled]=\"!SplitChildNames.trim()\">\n <i class=\"fa-solid fa-code-branch\"></i> Create Tags\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseSplitDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 CREATE TAG DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowCreateTagDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseCreateTagDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-plus\"></i> Create Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseCreateTagDialog()\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-tax-create-context\">{{ CreateTagParentLabel }}</div>\n <div class=\"at-schedule-field\">\n <label>Name</label>\n <input type=\"text\" class=\"mj-input\" style=\"width: 100%;\" [(ngModel)]=\"CreateTagName\"\n placeholder=\"Tag name\" (keydown.enter)=\"SaveNewTag()\">\n </div>\n <div class=\"at-schedule-field\">\n <label>Description (optional)</label>\n <textarea class=\"mj-textarea\" rows=\"3\" style=\"width: 100%;\" [(ngModel)]=\"CreateTagDescription\"\n placeholder=\"Brief description of this tag\"></textarea>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveNewTag()\" [disabled]=\"!CreateTagName.trim()\">\n <i class=\"fa-solid fa-check\"></i> Create\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseCreateTagDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 MOVE DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowMoveDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseMoveDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-arrows-up-down\"></i> Move Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseMoveDialog()\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>New parent tag</label>\n <select class=\"mj-input\" style=\"width: 100%;\" [(ngModel)]=\"MoveNewParentID\">\n <option [ngValue]=\"null\">(Root level — no parent)</option>\n @for (opt of GetMoveTargetOptions(); track opt.ID) {\n <option [ngValue]=\"opt.ID\">{{ '\u00A0\u00A0'.repeat(opt.Depth) }}{{ opt.Name }}</option>\n }\n </select>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteMove()\">\n <i class=\"fa-solid fa-check\"></i> Move\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseMoveDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 MERGE-INTO DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowMergeIntoDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseMergeIntoDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-compress\"></i> Merge \"{{ MergeSourceTag?.Name }}\" Into...</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseMergeIntoDialog()\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <p style=\"font-size: 0.85rem; color: var(--mj-text-secondary); margin: 0 0 12px;\">\n All tagged items will be moved to the target tag, then \"{{ MergeSourceTag?.Name }}\" will be deleted.\n </p>\n <div class=\"at-schedule-field\">\n <label>Merge into</label>\n <mj-combobox\n [Data]=\"MergeTargetData\"\n TextField=\"Label\"\n ValueField=\"ID\"\n [Filterable]=\"true\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Search and select a tag...\"\n (ValueChange)=\"OnMergeTargetSelected($event)\">\n </mj-combobox>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteMergeInto()\" [disabled]=\"!MergeTargetID || IsMerging\">\n @if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { <i class=\"fa-solid fa-compress\"></i> Merge }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseMergeIntoDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n}\n", styles: ["/*\n * Taxonomy Governance tab styles.\n *\n * The host (AutotaggingPipelineResourceComponent) uses ViewEncapsulation.None,\n * so its `.at-*` / `.at-tax-*` rules are global and already style this tab's\n * markup while it renders inside the host shell. Tab-specific rules would live\n * here; none are needed during the transition.\n *\n * NEW: the selected-node editor sub-tabs (Overview / Governance / Synonyms /\n * Scope) and their panels. These classes are genuinely new and not provided by\n * the host, so they're defined here using design tokens only.\n */\n\n/* \u2500\u2500 Editor sub-tab nav \u2500\u2500 */\n.at-tag-editor-subtabs {\n display: flex;\n gap: 4px;\n border-bottom: 1px solid var(--mj-border-default);\n margin: 12px 0 16px;\n}\n.at-tag-editor-subtab {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n margin-bottom: -1px;\n}\n.at-tag-editor-subtab:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n.at-tag-editor-subtab-active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n.at-tag-editor-subtab-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: var(--mj-radius-full, 999px);\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 700;\n}\n\n/* \u2500\u2500 Editor panes (shared) \u2500\u2500 */\n.at-tag-editor-pane {\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n.at-tag-editor-loading,\n.at-tag-editor-empty {\n padding: 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n/* \u2500\u2500 Governance \u2500\u2500 */\n.at-gov-toggle-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius, 8px);\n}\n.at-gov-toggle-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n.at-gov-toggle-sub {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n.at-gov-field-row {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 12px;\n}\n.at-gov-impact {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-info-border);\n border-radius: var(--mj-radius, 8px);\n color: var(--mj-status-info-text);\n font-size: 12.5px;\n}\n.at-gov-impact i {\n margin-top: 2px;\n color: var(--mj-status-info);\n}\n\n/* \u2500\u2500 Synonyms \u2500\u2500 */\n.at-syn-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.at-syn-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius, 8px);\n}\n.at-syn-name {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n.at-syn-pill {\n padding: 2px 10px;\n border-radius: var(--mj-radius-full, 999px);\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n.at-syn-pill-manual {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n.at-syn-pill-llm {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n color: var(--mj-status-info-text);\n}\n.at-syn-pill-imported {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n.at-syn-pill-merged {\n background: color-mix(in srgb, var(--mj-status-warning) 14%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text);\n}\n.at-syn-pill-pending {\n background: color-mix(in srgb, var(--mj-status-warning) 18%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text);\n}\n.at-syn-pill-rejected {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n.at-syn-item-pending {\n border-color: var(--mj-status-warning-border);\n background: color-mix(in srgb, var(--mj-status-warning) 6%, var(--mj-bg-surface-card));\n}\n.at-syn-pending-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 9px 12px;\n margin-bottom: 10px;\n font-size: 12px;\n border-radius: var(--mj-radius, 8px);\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n.at-syn-delete {\n background: transparent;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n border-radius: var(--mj-radius-sm, 4px);\n}\n.at-syn-delete:hover:not(:disabled) {\n color: var(--mj-status-error);\n background: var(--mj-bg-surface-hover);\n}\n.at-syn-delete:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.at-syn-add {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.at-syn-add .at-form-input {\n flex: 1;\n}\n\n/* \u2500\u2500 Scope \u2500\u2500 */\n.at-scope-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.at-scope-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius, 8px);\n}\n.at-scope-entity {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n.at-scope-record {\n flex: 1;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-family: var(--mj-font-mono, monospace);\n}\n.at-scope-add {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.at-scope-entity-picker {\n flex: 1;\n min-width: 0;\n}\n.at-scope-add .at-form-input {\n flex: 1;\n}\n.at-scope-note {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n"] }]
|
|
3484
|
+
}], null, { ContentTags: [{
|
|
3485
|
+
type: Input
|
|
3486
|
+
}], DataChanged: [{
|
|
3487
|
+
type: Output
|
|
3488
|
+
}] }); })();
|
|
3489
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ClassifyTaxonomyTabComponent, { className: "ClassifyTaxonomyTabComponent", filePath: "src/AI/components/autotagging/tabs/taxonomy-tab.component.ts", lineNumber: 34 }); })();
|
|
3490
|
+
//# sourceMappingURL=taxonomy-tab.component.js.map
|