@memberjunction/ng-dashboards 5.39.0 → 5.40.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/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +128 -4
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +548 -145
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts +56 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js +423 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts +70 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js +308 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts +29 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +186 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts +69 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js +278 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts +73 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js +393 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts +122 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js +908 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +100 -2
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +603 -213
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -1
- package/dist/AI/components/autotagging/shared/classify.format.d.ts +15 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -1
- package/dist/AI/components/autotagging/shared/classify.format.js +51 -0
- package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -1
- package/dist/AI/components/autotagging/shared/classify.types.d.ts +43 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -1
- package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -1
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +38 -1
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/tabs/history-tab.component.js +185 -68
- package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -1
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +10 -1
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +249 -188
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +12 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +377 -296
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +8 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js +112 -68
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -1
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +9 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/tabs/types-tab.component.js +87 -36
- package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +3 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +15 -3
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +1 -1
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +1 -0
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +28 -6
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +3 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +330 -302
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +2 -2
- package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +31 -340
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +468 -1958
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js +10 -0
- package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +12 -9
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +27 -2
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +244 -120
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts +65 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js +176 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js.map +1 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts +81 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js +308 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js.map +1 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts +85 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js +362 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/index.d.ts +3 -0
- package/dist/KnowledgeHub/index.d.ts.map +1 -1
- package/dist/KnowledgeHub/index.js +3 -0
- package/dist/KnowledgeHub/index.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
- package/dist/QueryBrowser/query-browser-resource.component.js +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +48 -38
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +41 -1
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/data-explorer-dashboards.module.d.ts +12 -14
- package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
- package/dist/data-explorer-dashboards.module.js +5 -14
- package/dist/data-explorer-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +3 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +57 -55
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +0 -79
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +0 -1
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +0 -195
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +0 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +0 -226
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +0 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +0 -861
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +0 -1
|
@@ -11,32 +11,50 @@
|
|
|
11
11
|
import { Component, ChangeDetectorRef, EventEmitter, Input, Output, inject } from '@angular/core';
|
|
12
12
|
import { NormalizeUUID } from '@memberjunction/global';
|
|
13
13
|
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
14
|
-
import { formatWeight, tagFontSize, formatShortDate } from '../shared/classify.format';
|
|
14
|
+
import { formatWeight, tagFontSize, formatShortDate, deriveDisplayName } from '../shared/classify.format';
|
|
15
15
|
import * as i0 from "@angular/core";
|
|
16
16
|
import * as i1 from "@angular/forms";
|
|
17
|
-
import * as i2 from "@memberjunction/ng-
|
|
18
|
-
import * as i3 from "@memberjunction/ng-
|
|
17
|
+
import * as i2 from "@memberjunction/ng-shared-generic";
|
|
18
|
+
import * as i3 from "@memberjunction/ng-ui-components";
|
|
19
|
+
import * as i4 from "@memberjunction/ng-word-cloud";
|
|
19
20
|
const _forTrack0 = ($index, $item) => $item.Tag;
|
|
20
21
|
const _forTrack1 = ($index, $item) => $item.SourceName;
|
|
21
22
|
const _forTrack2 = ($index, $item) => $item.ID;
|
|
22
|
-
function
|
|
23
|
+
function ClassifyTagsTabComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
24
|
+
i0.ɵɵelement(0, "i", 27);
|
|
25
|
+
i0.ɵɵelementStart(1, "span", 28);
|
|
26
|
+
i0.ɵɵtext(2, "Refreshing\u2026");
|
|
27
|
+
i0.ɵɵelementEnd();
|
|
28
|
+
} }
|
|
29
|
+
function ClassifyTagsTabComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
30
|
+
i0.ɵɵelement(0, "i", 29);
|
|
31
|
+
i0.ɵɵelementStart(1, "span", 28);
|
|
32
|
+
i0.ɵɵtext(2, "Refresh");
|
|
33
|
+
i0.ɵɵelementEnd();
|
|
34
|
+
} }
|
|
35
|
+
function ClassifyTagsTabComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
36
|
+
i0.ɵɵelementStart(0, "div", 7);
|
|
37
|
+
i0.ɵɵelement(1, "mj-loading", 30);
|
|
38
|
+
i0.ɵɵelementEnd();
|
|
39
|
+
} }
|
|
40
|
+
function ClassifyTagsTabComponent_For_32_Template(rf, ctx) { if (rf & 1) {
|
|
23
41
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
24
|
-
i0.ɵɵelementStart(0, "tr",
|
|
25
|
-
i0.ɵɵlistener("click", function
|
|
26
|
-
i0.ɵɵelementStart(1, "td",
|
|
42
|
+
i0.ɵɵelementStart(0, "tr", 31);
|
|
43
|
+
i0.ɵɵlistener("click", function ClassifyTagsTabComponent_For_32_Template_tr_click_0_listener() { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.DrillDownTag(row_r2.Tag)); });
|
|
44
|
+
i0.ɵɵelementStart(1, "td", 32);
|
|
27
45
|
i0.ɵɵtext(2);
|
|
28
46
|
i0.ɵɵelementEnd();
|
|
29
47
|
i0.ɵɵelementStart(3, "td");
|
|
30
48
|
i0.ɵɵtext(4);
|
|
31
49
|
i0.ɵɵelementEnd();
|
|
32
|
-
i0.ɵɵelementStart(5, "td")(6, "div",
|
|
33
|
-
i0.ɵɵelement(8, "div",
|
|
50
|
+
i0.ɵɵelementStart(5, "td")(6, "div", 33)(7, "div", 34);
|
|
51
|
+
i0.ɵɵelement(8, "div", 35);
|
|
34
52
|
i0.ɵɵelementEnd();
|
|
35
|
-
i0.ɵɵelementStart(9, "span",
|
|
53
|
+
i0.ɵɵelementStart(9, "span", 36);
|
|
36
54
|
i0.ɵɵtext(10);
|
|
37
55
|
i0.ɵɵelementEnd()()();
|
|
38
|
-
i0.ɵɵelementStart(11, "td")(12, "div",
|
|
39
|
-
i0.ɵɵelement(13, "div",
|
|
56
|
+
i0.ɵɵelementStart(11, "td")(12, "div", 37);
|
|
57
|
+
i0.ɵɵelement(13, "div", 38);
|
|
40
58
|
i0.ɵɵelementEnd()();
|
|
41
59
|
i0.ɵɵelementStart(14, "td");
|
|
42
60
|
i0.ɵɵtext(15);
|
|
@@ -64,15 +82,15 @@ function ClassifyTagsTabComponent_For_27_Template(rf, ctx) { if (rf & 1) {
|
|
|
64
82
|
i0.ɵɵadvance(2);
|
|
65
83
|
i0.ɵɵtextInterpolate(row_r2.FirstSeen);
|
|
66
84
|
} }
|
|
67
|
-
function
|
|
68
|
-
i0.ɵɵelementStart(0, "div",
|
|
85
|
+
function ClassifyTagsTabComponent_Conditional_33_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
i0.ɵɵelementStart(0, "div", 45)(1, "p");
|
|
69
87
|
i0.ɵɵtext(2, "No content items found for this tag.");
|
|
70
88
|
i0.ɵɵelementEnd()();
|
|
71
89
|
} }
|
|
72
|
-
function
|
|
90
|
+
function ClassifyTagsTabComponent_Conditional_33_Conditional_9_For_13_Template(rf, ctx) { if (rf & 1) {
|
|
73
91
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
74
|
-
i0.ɵɵelementStart(0, "tr",
|
|
75
|
-
i0.ɵɵlistener("click", function
|
|
92
|
+
i0.ɵɵelementStart(0, "tr", 31);
|
|
93
|
+
i0.ɵɵlistener("click", function ClassifyTagsTabComponent_Conditional_33_Conditional_9_For_13_Template_tr_click_0_listener() { const di_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onOpenItemDetail(di_r6.ID)); });
|
|
76
94
|
i0.ɵɵelementStart(1, "td");
|
|
77
95
|
i0.ɵɵtext(2);
|
|
78
96
|
i0.ɵɵelementEnd();
|
|
@@ -97,8 +115,8 @@ function ClassifyTagsTabComponent_Conditional_28_Conditional_9_For_13_Template(r
|
|
|
97
115
|
i0.ɵɵadvance(2);
|
|
98
116
|
i0.ɵɵtextInterpolate(di_r6.UpdatedAt);
|
|
99
117
|
} }
|
|
100
|
-
function
|
|
101
|
-
i0.ɵɵelementStart(0, "table",
|
|
118
|
+
function ClassifyTagsTabComponent_Conditional_33_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
119
|
+
i0.ɵɵelementStart(0, "table", 13)(1, "thead")(2, "tr")(3, "th");
|
|
102
120
|
i0.ɵɵtext(4, "Name");
|
|
103
121
|
i0.ɵɵelementEnd();
|
|
104
122
|
i0.ɵɵelementStart(5, "th");
|
|
@@ -111,25 +129,25 @@ function ClassifyTagsTabComponent_Conditional_28_Conditional_9_Template(rf, ctx)
|
|
|
111
129
|
i0.ɵɵtext(10, "Updated");
|
|
112
130
|
i0.ɵɵelementEnd()()();
|
|
113
131
|
i0.ɵɵelementStart(11, "tbody");
|
|
114
|
-
i0.ɵɵrepeaterCreate(12,
|
|
132
|
+
i0.ɵɵrepeaterCreate(12, ClassifyTagsTabComponent_Conditional_33_Conditional_9_For_13_Template, 9, 4, "tr", 46, _forTrack2);
|
|
115
133
|
i0.ɵɵelementEnd()();
|
|
116
134
|
} if (rf & 2) {
|
|
117
135
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
118
136
|
i0.ɵɵadvance(12);
|
|
119
137
|
i0.ɵɵrepeater(ctx_r2.TagDrillDownItems);
|
|
120
138
|
} }
|
|
121
|
-
function
|
|
139
|
+
function ClassifyTagsTabComponent_Conditional_33_Template(rf, ctx) { if (rf & 1) {
|
|
122
140
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
123
|
-
i0.ɵɵelementStart(0, "div",
|
|
124
|
-
i0.ɵɵelement(3, "i",
|
|
141
|
+
i0.ɵɵelementStart(0, "div", 15)(1, "div", 39)(2, "span", 40);
|
|
142
|
+
i0.ɵɵelement(3, "i", 41);
|
|
125
143
|
i0.ɵɵtext(4);
|
|
126
144
|
i0.ɵɵelementEnd();
|
|
127
|
-
i0.ɵɵelementStart(5, "button",
|
|
128
|
-
i0.ɵɵlistener("click", function
|
|
129
|
-
i0.ɵɵelement(6, "i",
|
|
145
|
+
i0.ɵɵelementStart(5, "button", 42);
|
|
146
|
+
i0.ɵɵlistener("click", function ClassifyTagsTabComponent_Conditional_33_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseDrillDownTag()); });
|
|
147
|
+
i0.ɵɵelement(6, "i", 43);
|
|
130
148
|
i0.ɵɵelementEnd()();
|
|
131
|
-
i0.ɵɵelementStart(7, "div",
|
|
132
|
-
i0.ɵɵconditionalCreate(8,
|
|
149
|
+
i0.ɵɵelementStart(7, "div", 44);
|
|
150
|
+
i0.ɵɵconditionalCreate(8, ClassifyTagsTabComponent_Conditional_33_Conditional_8_Template, 3, 0, "div", 45)(9, ClassifyTagsTabComponent_Conditional_33_Conditional_9_Template, 14, 0, "table", 13);
|
|
133
151
|
i0.ɵɵelementEnd()();
|
|
134
152
|
} if (rf & 2) {
|
|
135
153
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
@@ -138,19 +156,19 @@ function ClassifyTagsTabComponent_Conditional_28_Template(rf, ctx) { if (rf & 1)
|
|
|
138
156
|
i0.ɵɵadvance(4);
|
|
139
157
|
i0.ɵɵconditional(ctx_r2.TagDrillDownItems.length === 0 ? 8 : 9);
|
|
140
158
|
} }
|
|
141
|
-
function
|
|
142
|
-
i0.ɵɵelement(0, "mj-word-cloud",
|
|
159
|
+
function ClassifyTagsTabComponent_Conditional_39_Template(rf, ctx) { if (rf & 1) {
|
|
160
|
+
i0.ɵɵelement(0, "mj-word-cloud", 20);
|
|
143
161
|
} if (rf & 2) {
|
|
144
162
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
145
163
|
i0.ɵɵproperty("Items", ctx_r2.TagCloudWordItems)("MaxFontSize", 40)("MinFontSize", 12)("MaxItems", 20)("Interactive", true)("Animate", true);
|
|
146
164
|
} }
|
|
147
|
-
function
|
|
148
|
-
i0.ɵɵelementStart(0, "div",
|
|
165
|
+
function ClassifyTagsTabComponent_Conditional_40_Template(rf, ctx) { if (rf & 1) {
|
|
166
|
+
i0.ɵɵelementStart(0, "div", 21);
|
|
149
167
|
i0.ɵɵtext(1, "No tags yet");
|
|
150
168
|
i0.ɵɵelementEnd();
|
|
151
169
|
} }
|
|
152
|
-
function
|
|
153
|
-
i0.ɵɵelementStart(0, "div",
|
|
170
|
+
function ClassifyTagsTabComponent_For_47_Template(rf, ctx) { if (rf & 1) {
|
|
171
|
+
i0.ɵɵelementStart(0, "div", 26)(1, "span");
|
|
154
172
|
i0.ɵɵtext(2);
|
|
155
173
|
i0.ɵɵelementEnd();
|
|
156
174
|
i0.ɵɵelementStart(3, "strong");
|
|
@@ -183,6 +201,8 @@ export class ClassifyTagsTabComponent extends BaseAngularComponent {
|
|
|
183
201
|
get ContentItems() {
|
|
184
202
|
return this._contentItems;
|
|
185
203
|
}
|
|
204
|
+
/** Shown while a manual Refresh() rebuilds the tag view models. */
|
|
205
|
+
IsLoading = false;
|
|
186
206
|
TagRows = [];
|
|
187
207
|
FilteredTagRows = [];
|
|
188
208
|
TagCloudWordItems = [];
|
|
@@ -209,6 +229,18 @@ export class ClassifyTagsTabComponent extends BaseAngularComponent {
|
|
|
209
229
|
this.buildTagsBySource();
|
|
210
230
|
this.FilterTags();
|
|
211
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Rebuild the tag view models from the current host-supplied inputs. The tag
|
|
234
|
+
* data is host-owned (flows in via [ContentTags]/[ContentItems]); Refresh
|
|
235
|
+
* recomputes the rows/cloud/breakdown and surfaces a brief loading state.
|
|
236
|
+
*/
|
|
237
|
+
async Refresh() {
|
|
238
|
+
this.IsLoading = true;
|
|
239
|
+
this.cdr.detectChanges();
|
|
240
|
+
this.rebuild();
|
|
241
|
+
this.IsLoading = false;
|
|
242
|
+
this.cdr.detectChanges();
|
|
243
|
+
}
|
|
212
244
|
// ── External control surface (host deep-link + agent tool) ──
|
|
213
245
|
/** Apply a search query programmatically (used by the agent tool + deep link). Returns the match count. */
|
|
214
246
|
ApplySearch(query) {
|
|
@@ -292,7 +324,7 @@ export class ClassifyTagsTabComponent extends BaseAngularComponent {
|
|
|
292
324
|
if (weight !== undefined) {
|
|
293
325
|
this.TagDrillDownItems.push({
|
|
294
326
|
ID: item['ID'],
|
|
295
|
-
Name: item['Name']
|
|
327
|
+
Name: deriveDisplayName({ Name: item['Name'], Description: item['Description'] }),
|
|
296
328
|
SourceName: item['ContentSource'] ?? 'Unknown',
|
|
297
329
|
Weight: weight,
|
|
298
330
|
UpdatedAt: formatShortDate(item['__mj_UpdatedAt'] ?? ''),
|
|
@@ -377,66 +409,78 @@ export class ClassifyTagsTabComponent extends BaseAngularComponent {
|
|
|
377
409
|
return result;
|
|
378
410
|
}
|
|
379
411
|
static ɵfac = /*@__PURE__*/ (() => { let ɵClassifyTagsTabComponent_BaseFactory; return function ClassifyTagsTabComponent_Factory(__ngFactoryType__) { return (ɵClassifyTagsTabComponent_BaseFactory || (ɵClassifyTagsTabComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ClassifyTagsTabComponent)))(__ngFactoryType__ || ClassifyTagsTabComponent); }; })();
|
|
380
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ClassifyTagsTabComponent, selectors: [["classify-tags-tab"]], inputs: { ContentTags: "ContentTags", ContentItems: "ContentItems" }, outputs: { OpenItemDetailRequested: "OpenItemDetailRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
381
|
-
i0.ɵɵelementStart(0, "mj-page-header-interior", 0)(1, "div", 1)(2, "
|
|
382
|
-
i0.ɵɵ
|
|
383
|
-
i0.ɵɵ
|
|
412
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ClassifyTagsTabComponent, selectors: [["classify-tags-tab"]], inputs: { ContentTags: "ContentTags", ContentItems: "ContentItems" }, outputs: { OpenItemDetailRequested: "OpenItemDetailRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 48, vars: 9, consts: [["Title", "Tag Library", 3, "Subtitle"], ["actions", ""], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], ["toolbar", ""], ["type", "text", "placeholder", "Search tags...", 1, "at-search-input", 3, "ngModelChange", "input", "ngModel"], [3, "Padding", "Flex"], [1, "at-main-area"], [1, "at-loading-overlay"], [1, "at-page-body"], [1, "at-tag-lib-layout"], [1, "at-tag-lib-main"], [1, "at-card"], [1, "at-card-body", 2, "max-height", "500px", "overflow-y", "auto"], [1, "at-tag-table"], [1, "at-tag-row-clickable", 3, "at-tag-row-selected"], [1, "at-card", 2, "margin-top", "12px"], [1, "at-tag-lib-sidebar"], [1, "at-card", "at-tag-cloud-card"], [1, "at-card-title", 2, "margin-bottom", "12px"], [1, "fa-solid", "fa-cloud"], ["Layout", "spiral", "ColorMode", "weight-gradient", 3, "Items", "MaxFontSize", "MinFontSize", "MaxItems", "Interactive", "Animate"], [1, "at-tag-cloud-empty"], [1, "at-card", 2, "padding", "16px", "margin-top", "12px"], [1, "at-card-title", 2, "margin-bottom", "10px"], [1, "fa-solid", "fa-chart-pie"], [1, "at-tags-by-source"], [1, "at-tag-source-row"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "mj-action-label"], [1, "fa-solid", "fa-arrows-rotate"], ["text", "Refreshing tags\u2026"], [1, "at-tag-row-clickable", 3, "click"], [1, "at-tag-name-cell"], [1, "at-weight-indicator"], [1, "at-weight-bar"], [1, "at-weight-bar-fill"], [1, "at-weight-value"], [1, "at-tag-bar"], [1, "at-tag-bar-fill"], [1, "at-card-header"], [1, "at-card-title"], [1, "fa-solid", "fa-tag"], ["aria-label", "Close", 1, "at-slide-close", 2, "background", "none", "border", "none", "cursor", "pointer", "color", "var(--mj-text-muted)", 3, "click"], [1, "fa-solid", "fa-times"], [1, "at-card-body", 2, "max-height", "300px", "overflow-y", "auto"], [1, "at-empty-state"], [1, "at-tag-row-clickable"]], template: function ClassifyTagsTabComponent_Template(rf, ctx) { if (rf & 1) {
|
|
413
|
+
i0.ɵɵelementStart(0, "mj-page-header-interior", 0)(1, "div", 1)(2, "button", 2);
|
|
414
|
+
i0.ɵɵlistener("click", function ClassifyTagsTabComponent_Template_button_click_2_listener() { return ctx.Refresh(); });
|
|
415
|
+
i0.ɵɵconditionalCreate(3, ClassifyTagsTabComponent_Conditional_3_Template, 3, 0)(4, ClassifyTagsTabComponent_Conditional_4_Template, 3, 0);
|
|
416
|
+
i0.ɵɵelementEnd()();
|
|
417
|
+
i0.ɵɵelementStart(5, "div", 3)(6, "input", 4);
|
|
418
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTagsTabComponent_Template_input_ngModelChange_6_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.TagSearchQuery, $event) || (ctx.TagSearchQuery = $event); return $event; });
|
|
419
|
+
i0.ɵɵlistener("input", function ClassifyTagsTabComponent_Template_input_input_6_listener() { return ctx.FilterTags(); });
|
|
384
420
|
i0.ɵɵelementEnd()()();
|
|
385
|
-
i0.ɵɵelementStart(
|
|
386
|
-
i0.ɵɵ
|
|
421
|
+
i0.ɵɵelementStart(7, "mj-page-body-interior", 5)(8, "div", 6);
|
|
422
|
+
i0.ɵɵconditionalCreate(9, ClassifyTagsTabComponent_Conditional_9_Template, 2, 0, "div", 7);
|
|
423
|
+
i0.ɵɵelementStart(10, "div", 8)(11, "div", 9)(12, "div", 10)(13, "div", 11)(14, "div", 12)(15, "table", 13)(16, "thead")(17, "tr")(18, "th");
|
|
424
|
+
i0.ɵɵtext(19, "Tag");
|
|
387
425
|
i0.ɵɵelementEnd();
|
|
388
|
-
i0.ɵɵelementStart(
|
|
389
|
-
i0.ɵɵtext(
|
|
426
|
+
i0.ɵɵelementStart(20, "th");
|
|
427
|
+
i0.ɵɵtext(21, "Count");
|
|
390
428
|
i0.ɵɵelementEnd();
|
|
391
|
-
i0.ɵɵelementStart(
|
|
392
|
-
i0.ɵɵtext(
|
|
429
|
+
i0.ɵɵelementStart(22, "th");
|
|
430
|
+
i0.ɵɵtext(23, "Avg Weight");
|
|
393
431
|
i0.ɵɵelementEnd();
|
|
394
|
-
i0.ɵɵelementStart(
|
|
395
|
-
i0.ɵɵtext(
|
|
432
|
+
i0.ɵɵelementStart(24, "th");
|
|
433
|
+
i0.ɵɵtext(25, "Distribution");
|
|
396
434
|
i0.ɵɵelementEnd();
|
|
397
|
-
i0.ɵɵelementStart(
|
|
398
|
-
i0.ɵɵtext(
|
|
435
|
+
i0.ɵɵelementStart(26, "th");
|
|
436
|
+
i0.ɵɵtext(27, "Top Source");
|
|
399
437
|
i0.ɵɵelementEnd();
|
|
400
|
-
i0.ɵɵelementStart(
|
|
401
|
-
i0.ɵɵtext(
|
|
438
|
+
i0.ɵɵelementStart(28, "th");
|
|
439
|
+
i0.ɵɵtext(29, "First Seen");
|
|
402
440
|
i0.ɵɵelementEnd()()();
|
|
403
|
-
i0.ɵɵelementStart(
|
|
404
|
-
i0.ɵɵrepeaterCreate(
|
|
441
|
+
i0.ɵɵelementStart(30, "tbody");
|
|
442
|
+
i0.ɵɵrepeaterCreate(31, ClassifyTagsTabComponent_For_32_Template, 18, 17, "tr", 14, _forTrack0);
|
|
405
443
|
i0.ɵɵelementEnd()()()();
|
|
406
|
-
i0.ɵɵconditionalCreate(
|
|
444
|
+
i0.ɵɵconditionalCreate(33, ClassifyTagsTabComponent_Conditional_33_Template, 10, 3, "div", 15);
|
|
407
445
|
i0.ɵɵelementEnd();
|
|
408
|
-
i0.ɵɵelementStart(
|
|
409
|
-
i0.ɵɵelement(
|
|
410
|
-
i0.ɵɵtext(
|
|
446
|
+
i0.ɵɵelementStart(34, "div", 16)(35, "div", 17)(36, "div", 18);
|
|
447
|
+
i0.ɵɵelement(37, "i", 19);
|
|
448
|
+
i0.ɵɵtext(38, " Tag Cloud");
|
|
411
449
|
i0.ɵɵelementEnd();
|
|
412
|
-
i0.ɵɵconditionalCreate(
|
|
450
|
+
i0.ɵɵconditionalCreate(39, ClassifyTagsTabComponent_Conditional_39_Template, 1, 6, "mj-word-cloud", 20)(40, ClassifyTagsTabComponent_Conditional_40_Template, 2, 0, "div", 21);
|
|
413
451
|
i0.ɵɵelementEnd();
|
|
414
|
-
i0.ɵɵelementStart(
|
|
415
|
-
i0.ɵɵelement(
|
|
416
|
-
i0.ɵɵtext(
|
|
452
|
+
i0.ɵɵelementStart(41, "div", 22)(42, "div", 23);
|
|
453
|
+
i0.ɵɵelement(43, "i", 24);
|
|
454
|
+
i0.ɵɵtext(44, " By Source");
|
|
417
455
|
i0.ɵɵelementEnd();
|
|
418
|
-
i0.ɵɵelementStart(
|
|
419
|
-
i0.ɵɵrepeaterCreate(
|
|
456
|
+
i0.ɵɵelementStart(45, "div", 25);
|
|
457
|
+
i0.ɵɵrepeaterCreate(46, ClassifyTagsTabComponent_For_47_Template, 5, 2, "div", 26, _forTrack1);
|
|
420
458
|
i0.ɵɵelementEnd()()()()()()();
|
|
421
459
|
} if (rf & 2) {
|
|
422
460
|
i0.ɵɵproperty("Subtitle", ctx.Subtitle);
|
|
423
461
|
i0.ɵɵadvance(2);
|
|
462
|
+
i0.ɵɵproperty("disabled", ctx.IsLoading);
|
|
463
|
+
i0.ɵɵadvance();
|
|
464
|
+
i0.ɵɵconditional(ctx.IsLoading ? 3 : 4);
|
|
465
|
+
i0.ɵɵadvance(3);
|
|
424
466
|
i0.ɵɵtwoWayProperty("ngModel", ctx.TagSearchQuery);
|
|
425
467
|
i0.ɵɵadvance();
|
|
426
468
|
i0.ɵɵproperty("Padding", false)("Flex", true);
|
|
427
|
-
i0.ɵɵadvance(
|
|
469
|
+
i0.ɵɵadvance(2);
|
|
470
|
+
i0.ɵɵconditional(ctx.IsLoading ? 9 : -1);
|
|
471
|
+
i0.ɵɵadvance(22);
|
|
428
472
|
i0.ɵɵrepeater(ctx.FilteredTagRows);
|
|
429
473
|
i0.ɵɵadvance(2);
|
|
430
|
-
i0.ɵɵconditional(ctx.SelectedDrillDownTag ?
|
|
474
|
+
i0.ɵɵconditional(ctx.SelectedDrillDownTag ? 33 : -1);
|
|
431
475
|
i0.ɵɵadvance(6);
|
|
432
|
-
i0.ɵɵconditional(ctx.TagCloudWordItems.length > 0 ?
|
|
476
|
+
i0.ɵɵconditional(ctx.TagCloudWordItems.length > 0 ? 39 : 40);
|
|
433
477
|
i0.ɵɵadvance(7);
|
|
434
478
|
i0.ɵɵrepeater(ctx.TagsBySource);
|
|
435
|
-
} }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, i2.MJPageHeaderInteriorComponent,
|
|
479
|
+
} }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, i2.LoadingComponent, i3.MJButtonDirective, i3.MJPageHeaderInteriorComponent, i3.MJPageBodyInteriorComponent, i4.MJWordCloudComponent], encapsulation: 2 });
|
|
436
480
|
}
|
|
437
481
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ClassifyTagsTabComponent, [{
|
|
438
482
|
type: Component,
|
|
439
|
-
args: [{ standalone: false, selector: 'classify-tags-tab', template: "<mj-page-header-interior\n Title=\"Tag Library\"\n [Subtitle]=\"Subtitle\">\n <div toolbar>\n <input type=\"text\" class=\"at-search-input\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TagSearchQuery\" (input)=\"FilterTags()\">\n </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior [Padding]=\"false\" [Flex]=\"true\">\n <div class=\"at-main-area\">\n <div class=\"at-page-body\">\n <div class=\"at-tag-lib-layout\">\n <div class=\"at-tag-lib-main\">\n <div class=\"at-card\">\n <div class=\"at-card-body\" style=\"max-height: 500px; overflow-y: auto;\">\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Count</th>\n <th>Avg Weight</th>\n <th>Distribution</th>\n <th>Top Source</th>\n <th>First Seen</th>\n </tr>\n </thead>\n <tbody>\n @for (row of FilteredTagRows; track row.Tag) {\n <tr class=\"at-tag-row-clickable\" (click)=\"DrillDownTag(row.Tag)\"\n [class.at-tag-row-selected]=\"SelectedDrillDownTag === row.Tag\">\n <td class=\"at-tag-name-cell\">{{ row.Tag }}</td>\n <td>{{ row.UsageCount }}</td>\n <td>\n <div class=\"at-weight-indicator\">\n <div class=\"at-weight-bar\">\n <div class=\"at-weight-bar-fill\" [style.width.%]=\"row.AvgWeight * 100\"\n [class.at-weight-high]=\"row.AvgWeight >= 0.7\"\n [class.at-weight-medium]=\"row.AvgWeight >= 0.4 && row.AvgWeight < 0.7\"\n [class.at-weight-low]=\"row.AvgWeight < 0.4\"></div>\n </div>\n <span class=\"at-weight-value\">{{ row.AvgWeight.toFixed(2) }}</span>\n </div>\n </td>\n <td>\n <div class=\"at-tag-bar\">\n <div class=\"at-tag-bar-fill\" [style.width.%]=\"row.BarWidthPct\"></div>\n </div>\n </td>\n <td>{{ row.TopSource }}</td>\n <td>{{ row.FirstSeen }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Tag drill-down: content items matching selected tag -->\n @if (SelectedDrillDownTag) {\n <div class=\"at-card\" style=\"margin-top: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\">\n <i class=\"fa-solid fa-tag\"></i>\n Content items tagged \"{{ SelectedDrillDownTag }}\"\n ({{ TagDrillDownItems.length }})\n </span>\n <button class=\"at-slide-close\" (click)=\"CloseDrillDownTag()\" style=\"background:none;border:none;cursor:pointer;color:var(--mj-text-muted)\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-card-body\" style=\"max-height: 300px; overflow-y: auto;\">\n @if (TagDrillDownItems.length === 0) {\n <div class=\"at-empty-state\"><p>No content items found for this tag.</p></div>\n } @else {\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Name</th>\n <th>Source</th>\n <th>Weight</th>\n <th>Updated</th>\n </tr>\n </thead>\n <tbody>\n @for (di of TagDrillDownItems; track di.ID) {\n <tr class=\"at-tag-row-clickable\" (click)=\"onOpenItemDetail(di.ID)\">\n <td>{{ di.Name }}</td>\n <td>{{ di.SourceName }}</td>\n <td>{{ FormatWeight(di.Weight) }}</td>\n <td>{{ di.UpdatedAt }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tag-lib-sidebar\">\n <div class=\"at-card at-tag-cloud-card\">\n <div class=\"at-card-title\" style=\"margin-bottom: 12px;\"><i class=\"fa-solid fa-cloud\"></i> Tag Cloud</div>\n @if (TagCloudWordItems.length > 0) {\n <mj-word-cloud\n [Items]=\"TagCloudWordItems\"\n [MaxFontSize]=\"40\"\n [MinFontSize]=\"12\"\n [MaxItems]=\"20\"\n Layout=\"spiral\"\n ColorMode=\"weight-gradient\"\n [Interactive]=\"true\"\n [Animate]=\"true\">\n </mj-word-cloud>\n } @else {\n <div class=\"at-tag-cloud-empty\">No tags yet</div>\n }\n </div>\n <div class=\"at-card\" style=\"padding: 16px; margin-top: 12px;\">\n <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-pie\"></i> By Source</div>\n <div class=\"at-tags-by-source\">\n @for (s of TagsBySource; track s.SourceName) {\n <div class=\"at-tag-source-row\">\n <span>{{ s.SourceName }}</span>\n <strong>{{ s.Count }}</strong>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</mj-page-body-interior>\n", styles: ["/*\n * Tag Library tab styles.\n *\n * The host (AutotaggingPipelineResourceComponent) uses ViewEncapsulation.None,\n * so its `.at-*` rules are global and already style this tab's markup while it\n * renders inside the host shell. Tab-specific rules live here as the shared CSS\n * is partitioned during the host-slim step.\n */\n"] }]
|
|
483
|
+
args: [{ standalone: false, selector: 'classify-tags-tab', template: "<mj-page-header-interior\n Title=\"Tag Library\"\n [Subtitle]=\"Subtitle\">\n <div actions>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"Refresh()\" [disabled]=\"IsLoading\">\n @if (IsLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> <span class=\"mj-action-label\">Refreshing\u2026</span>\n } @else {\n <i class=\"fa-solid fa-arrows-rotate\"></i> <span class=\"mj-action-label\">Refresh</span>\n }\n </button>\n </div>\n <div toolbar>\n <input type=\"text\" class=\"at-search-input\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TagSearchQuery\" (input)=\"FilterTags()\">\n </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior [Padding]=\"false\" [Flex]=\"true\">\n <div class=\"at-main-area\">\n @if (IsLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Refreshing tags\u2026\"></mj-loading>\n </div>\n }\n <div class=\"at-page-body\">\n <div class=\"at-tag-lib-layout\">\n <div class=\"at-tag-lib-main\">\n <div class=\"at-card\">\n <div class=\"at-card-body\" style=\"max-height: 500px; overflow-y: auto;\">\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Count</th>\n <th>Avg Weight</th>\n <th>Distribution</th>\n <th>Top Source</th>\n <th>First Seen</th>\n </tr>\n </thead>\n <tbody>\n @for (row of FilteredTagRows; track row.Tag) {\n <tr class=\"at-tag-row-clickable\" (click)=\"DrillDownTag(row.Tag)\"\n [class.at-tag-row-selected]=\"SelectedDrillDownTag === row.Tag\">\n <td class=\"at-tag-name-cell\">{{ row.Tag }}</td>\n <td>{{ row.UsageCount }}</td>\n <td>\n <div class=\"at-weight-indicator\">\n <div class=\"at-weight-bar\">\n <div class=\"at-weight-bar-fill\" [style.width.%]=\"row.AvgWeight * 100\"\n [class.at-weight-high]=\"row.AvgWeight >= 0.7\"\n [class.at-weight-medium]=\"row.AvgWeight >= 0.4 && row.AvgWeight < 0.7\"\n [class.at-weight-low]=\"row.AvgWeight < 0.4\"></div>\n </div>\n <span class=\"at-weight-value\">{{ row.AvgWeight.toFixed(2) }}</span>\n </div>\n </td>\n <td>\n <div class=\"at-tag-bar\">\n <div class=\"at-tag-bar-fill\" [style.width.%]=\"row.BarWidthPct\"></div>\n </div>\n </td>\n <td>{{ row.TopSource }}</td>\n <td>{{ row.FirstSeen }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Tag drill-down: content items matching selected tag -->\n @if (SelectedDrillDownTag) {\n <div class=\"at-card\" style=\"margin-top: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\">\n <i class=\"fa-solid fa-tag\"></i>\n Content items tagged \"{{ SelectedDrillDownTag }}\"\n ({{ TagDrillDownItems.length }})\n </span>\n <button class=\"at-slide-close\" (click)=\"CloseDrillDownTag()\" style=\"background:none;border:none;cursor:pointer;color:var(--mj-text-muted)\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-card-body\" style=\"max-height: 300px; overflow-y: auto;\">\n @if (TagDrillDownItems.length === 0) {\n <div class=\"at-empty-state\"><p>No content items found for this tag.</p></div>\n } @else {\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Name</th>\n <th>Source</th>\n <th>Weight</th>\n <th>Updated</th>\n </tr>\n </thead>\n <tbody>\n @for (di of TagDrillDownItems; track di.ID) {\n <tr class=\"at-tag-row-clickable\" (click)=\"onOpenItemDetail(di.ID)\">\n <td>{{ di.Name }}</td>\n <td>{{ di.SourceName }}</td>\n <td>{{ FormatWeight(di.Weight) }}</td>\n <td>{{ di.UpdatedAt }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tag-lib-sidebar\">\n <div class=\"at-card at-tag-cloud-card\">\n <div class=\"at-card-title\" style=\"margin-bottom: 12px;\"><i class=\"fa-solid fa-cloud\"></i> Tag Cloud</div>\n @if (TagCloudWordItems.length > 0) {\n <mj-word-cloud\n [Items]=\"TagCloudWordItems\"\n [MaxFontSize]=\"40\"\n [MinFontSize]=\"12\"\n [MaxItems]=\"20\"\n Layout=\"spiral\"\n ColorMode=\"weight-gradient\"\n [Interactive]=\"true\"\n [Animate]=\"true\">\n </mj-word-cloud>\n } @else {\n <div class=\"at-tag-cloud-empty\">No tags yet</div>\n }\n </div>\n <div class=\"at-card\" style=\"padding: 16px; margin-top: 12px;\">\n <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-pie\"></i> By Source</div>\n <div class=\"at-tags-by-source\">\n @for (s of TagsBySource; track s.SourceName) {\n <div class=\"at-tag-source-row\">\n <span>{{ s.SourceName }}</span>\n <strong>{{ s.Count }}</strong>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</mj-page-body-interior>\n", styles: ["/*\n * Tag Library tab styles.\n *\n * The host (AutotaggingPipelineResourceComponent) uses ViewEncapsulation.None,\n * so its `.at-*` rules are global and already style this tab's markup while it\n * renders inside the host shell. Tab-specific rules live here as the shared CSS\n * is partitioned during the host-slim step.\n */\n"] }]
|
|
440
484
|
}], null, { ContentTags: [{
|
|
441
485
|
type: Input
|
|
442
486
|
}], ContentItems: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tags-tab.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/autotagging/tabs/tags-tab.component.ts","../../../../../src/AI/components/autotagging/tabs/tags-tab.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Classify · Tag Library tab.\n *\n * Self-contained sub-page: owns its header-interior (with the tag search box),\n * the tag rows table, the word cloud, the tags-by-source breakdown, and the\n * per-tag drill-down. Receives the shared raw tag + item rows from the host\n * orchestrator via `[ContentTags]`/`[ContentItems]` and rebuilds its view\n * models from them. Opening a content item from the drill-down is a cross-tab\n * concern owned by the host's slide-in, so it bubbles up via @Output.\n */\nimport { Component, ChangeDetectorRef, EventEmitter, Input, Output, inject } from '@angular/core';\nimport { NormalizeUUID } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { WordCloudItem } from '@memberjunction/ng-word-cloud';\nimport { TagRow, TagBySource } from '../shared/classify.types';\nimport { formatWeight, tagFontSize, formatShortDate } from '../shared/classify.format';\n\n/** One row in the per-tag drill-down (content items carrying a given tag). */\ninterface TagDrillDownItem {\n ID: string;\n Name: string;\n SourceName: string;\n Weight: number;\n UpdatedAt: string;\n FeedIndex: number;\n}\n\n@Component({\n standalone: false,\n selector: 'classify-tags-tab',\n templateUrl: './tags-tab.component.html',\n styleUrls: ['./tags-tab.component.css']\n})\nexport class ClassifyTagsTabComponent extends BaseAngularComponent {\n private cdr = inject(ChangeDetectorRef);\n\n /** Shared raw `MJ: Content Item Tags` rows, supplied by the host orchestrator. */\n private _contentTags: Record<string, unknown>[] = [];\n @Input()\n set ContentTags(value: Record<string, unknown>[]) {\n this._contentTags = value ?? [];\n this.rebuild();\n }\n get ContentTags(): Record<string, unknown>[] {\n return this._contentTags;\n }\n\n /** Shared raw `MJ: Content Items` rows — used for source mapping and drill-down. */\n private _contentItems: Record<string, unknown>[] = [];\n @Input()\n set ContentItems(value: Record<string, unknown>[]) {\n this._contentItems = value ?? [];\n this.rebuild();\n }\n get ContentItems(): Record<string, unknown>[] {\n return this._contentItems;\n }\n\n public TagRows: TagRow[] = [];\n public FilteredTagRows: TagRow[] = [];\n public TagCloudWordItems: WordCloudItem[] = [];\n public TagsBySource: TagBySource[] = [];\n public TagSearchQuery = '';\n public SelectedDrillDownTag: string | null = null;\n public TagDrillDownItems: TagDrillDownItem[] = [];\n\n /** Subtitle reflects the live tag count, mirroring the former host subtitle. */\n public get Subtitle(): string {\n return `${this.TagRows.length} unique tags across all content sources`;\n }\n\n // Template-facing formatters (shared pure helpers exposed for the view).\n public readonly TagFontSize = tagFontSize;\n public readonly FormatWeight = formatWeight;\n\n /** Bubble a request to open a content item's detail slide-in (host-owned). */\n @Output() OpenItemDetailRequested = new EventEmitter<string>();\n\n public onOpenItemDetail(contentItemID: string): void {\n this.OpenItemDetailRequested.emit(contentItemID);\n }\n\n /** Rebuild all tag-tab view models from the current inputs. */\n private rebuild(): void {\n this.buildTagRows();\n this.buildTagCloud();\n this.buildTagsBySource();\n this.FilterTags();\n }\n\n // ── External control surface (host deep-link + agent tool) ──\n\n /** Apply a search query programmatically (used by the agent tool + deep link). Returns the match count. */\n public ApplySearch(query: string): number {\n this.TagSearchQuery = query;\n this.FilterTags();\n return this.FilteredTagRows.length;\n }\n\n // ── View-model building ──\n\n private buildTagRows(): void {\n const tagCounts = this.countAllTags();\n const avgWeights = this.computeAvgWeights();\n const tagSourceMap = this.getTopSourcePerTag();\n const tagFirstSeen = this.getFirstSeenPerTag();\n const sorted = Array.from(tagCounts.entries()).sort((a, b) => b[1] - a[1]);\n const maxCount = sorted.length > 0 ? sorted[0][1] : 1;\n\n this.TagRows = sorted.map(([tag, count]) => ({\n Tag: tag,\n UsageCount: count,\n AvgWeight: avgWeights.get(tag) ?? 1.0,\n BarWidthPct: Math.round((count / maxCount) * 100),\n TopSource: tagSourceMap.get(tag) ?? 'Unknown',\n FirstSeen: tagFirstSeen.get(tag) ?? ''\n }));\n }\n\n private buildTagCloud(): void {\n const tagCounts = this.countAllTags();\n const avgWeights = this.computeAvgWeights();\n // Sort by a combined score: usage count * avg weight (so high-weight, high-count tags bubble up)\n const scored = Array.from(tagCounts.entries()).map(([tag, count]) => {\n const weight = avgWeights.get(tag) ?? 1.0;\n return { tag, count, weight, score: count * weight };\n }).sort((a, b) => b.score - a.score).slice(0, 20);\n const maxScore = scored.length > 0 ? scored[0].score : 1;\n\n // Build WordCloudItem[] for the mj-word-cloud component\n this.TagCloudWordItems = scored.map(s => ({\n Text: s.tag,\n Weight: maxScore > 0 ? s.score / maxScore : 0,\n Metadata: { Count: s.count, AvgWeight: s.weight }\n }));\n }\n\n private buildTagsBySource(): void {\n const sourceTagCounts = new Map<string, number>();\n const itemSourceMap = new Map<string, string>();\n for (const item of this._contentItems) {\n itemSourceMap.set(item['ID'] as string, (item['ContentSource'] as string) ?? 'Unknown');\n }\n for (const tag of this._contentTags) {\n const source = itemSourceMap.get(tag['ItemID'] as string) ?? 'Unknown';\n sourceTagCounts.set(source, (sourceTagCounts.get(source) ?? 0) + 1);\n }\n this.TagsBySource = Array.from(sourceTagCounts.entries())\n .sort((a, b) => b[1] - a[1])\n .map(([name, count]) => ({ SourceName: name, Count: count }));\n }\n\n public FilterTags(): void {\n const q = this.TagSearchQuery.toLowerCase().trim();\n this.FilteredTagRows = q\n ? this.TagRows.filter(r => r.Tag.toLowerCase().includes(q))\n : this.TagRows;\n this.cdr.detectChanges();\n }\n\n /** Drill down into content items matching a specific tag. */\n public DrillDownTag(tagName: string): void {\n if (this.SelectedDrillDownTag === tagName) {\n this.CloseDrillDownTag();\n return;\n }\n this.SelectedDrillDownTag = tagName;\n\n // Find all content items that have this tag\n const matchingItemIDs = new Map<string, number>(); // itemID → weight\n for (const tag of this._contentTags) {\n if ((tag['Tag'] as string) === tagName) {\n matchingItemIDs.set(\n NormalizeUUID(tag['ItemID'] as string),\n Number(tag['Weight'] ?? 1)\n );\n }\n }\n\n this.TagDrillDownItems = [];\n for (let i = 0; i < this._contentItems.length; i++) {\n const item = this._contentItems[i];\n const normalizedID = NormalizeUUID(item['ID'] as string);\n const weight = matchingItemIDs.get(normalizedID);\n if (weight !== undefined) {\n this.TagDrillDownItems.push({\n ID: item['ID'] as string,\n Name: (item['Name'] as string) ?? 'Unnamed',\n SourceName: (item['ContentSource'] as string) ?? 'Unknown',\n Weight: weight,\n UpdatedAt: formatShortDate((item['__mj_UpdatedAt'] as string) ?? ''),\n FeedIndex: i,\n });\n }\n }\n\n // Sort by weight descending\n this.TagDrillDownItems.sort((a, b) => b.Weight - a.Weight);\n this.cdr.detectChanges();\n }\n\n public CloseDrillDownTag(): void {\n this.SelectedDrillDownTag = null;\n this.TagDrillDownItems = [];\n this.cdr.detectChanges();\n }\n\n // ── Aggregation utilities (read only the tag + item inputs) ──\n\n private countAllTags(): Map<string, number> {\n const counts = new Map<string, number>();\n for (const tag of this._contentTags) {\n const t = tag['Tag'] as string;\n if (t) counts.set(t, (counts.get(t) ?? 0) + 1);\n }\n return counts;\n }\n\n /** Compute average weight per tag across all occurrences. */\n private computeAvgWeights(): Map<string, number> {\n const sums = new Map<string, number>();\n const counts = new Map<string, number>();\n for (const tag of this._contentTags) {\n const t = tag['Tag'] as string;\n const w = Number(tag['Weight'] ?? 0.5);\n if (t) {\n sums.set(t, (sums.get(t) ?? 0) + w);\n counts.set(t, (counts.get(t) ?? 0) + 1);\n }\n }\n const avgs = new Map<string, number>();\n for (const [t, sum] of sums) {\n avgs.set(t, Math.round((sum / (counts.get(t) ?? 1)) * 100) / 100);\n }\n return avgs;\n }\n\n private getTopSourcePerTag(): Map<string, string> {\n const tagSourceCounts = new Map<string, Map<string, number>>();\n const itemSourceMap = new Map<string, string>();\n for (const item of this._contentItems) {\n itemSourceMap.set(item['ID'] as string, (item['ContentSource'] as string) ?? 'Unknown');\n }\n for (const tag of this._contentTags) {\n const t = tag['Tag'] as string;\n const source = itemSourceMap.get(tag['ItemID'] as string) ?? 'Unknown';\n if (!tagSourceCounts.has(t)) tagSourceCounts.set(t, new Map());\n const inner = tagSourceCounts.get(t)!;\n inner.set(source, (inner.get(source) ?? 0) + 1);\n }\n const result = new Map<string, string>();\n for (const [tag, sourceCounts] of tagSourceCounts) {\n let maxSource = 'Unknown';\n let maxCount = 0;\n for (const [source, count] of sourceCounts) {\n if (count > maxCount) { maxSource = source; maxCount = count; }\n }\n result.set(tag, maxSource);\n }\n return result;\n }\n\n private getFirstSeenPerTag(): Map<string, string> {\n const result = new Map<string, string>();\n for (const tag of this._contentTags) {\n const t = tag['Tag'] as string;\n if (t && !result.has(t)) {\n const date = tag['__mj_CreatedAt'] as string;\n result.set(t, date ? formatShortDate(date) : '');\n }\n }\n return result;\n }\n}\n","<mj-page-header-interior\n Title=\"Tag Library\"\n [Subtitle]=\"Subtitle\">\n <div toolbar>\n <input type=\"text\" class=\"at-search-input\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TagSearchQuery\" (input)=\"FilterTags()\">\n </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior [Padding]=\"false\" [Flex]=\"true\">\n <div class=\"at-main-area\">\n <div class=\"at-page-body\">\n <div class=\"at-tag-lib-layout\">\n <div class=\"at-tag-lib-main\">\n <div class=\"at-card\">\n <div class=\"at-card-body\" style=\"max-height: 500px; overflow-y: auto;\">\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Count</th>\n <th>Avg Weight</th>\n <th>Distribution</th>\n <th>Top Source</th>\n <th>First Seen</th>\n </tr>\n </thead>\n <tbody>\n @for (row of FilteredTagRows; track row.Tag) {\n <tr class=\"at-tag-row-clickable\" (click)=\"DrillDownTag(row.Tag)\"\n [class.at-tag-row-selected]=\"SelectedDrillDownTag === row.Tag\">\n <td class=\"at-tag-name-cell\">{{ row.Tag }}</td>\n <td>{{ row.UsageCount }}</td>\n <td>\n <div class=\"at-weight-indicator\">\n <div class=\"at-weight-bar\">\n <div class=\"at-weight-bar-fill\" [style.width.%]=\"row.AvgWeight * 100\"\n [class.at-weight-high]=\"row.AvgWeight >= 0.7\"\n [class.at-weight-medium]=\"row.AvgWeight >= 0.4 && row.AvgWeight < 0.7\"\n [class.at-weight-low]=\"row.AvgWeight < 0.4\"></div>\n </div>\n <span class=\"at-weight-value\">{{ row.AvgWeight.toFixed(2) }}</span>\n </div>\n </td>\n <td>\n <div class=\"at-tag-bar\">\n <div class=\"at-tag-bar-fill\" [style.width.%]=\"row.BarWidthPct\"></div>\n </div>\n </td>\n <td>{{ row.TopSource }}</td>\n <td>{{ row.FirstSeen }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Tag drill-down: content items matching selected tag -->\n @if (SelectedDrillDownTag) {\n <div class=\"at-card\" style=\"margin-top: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\">\n <i class=\"fa-solid fa-tag\"></i>\n Content items tagged \"{{ SelectedDrillDownTag }}\"\n ({{ TagDrillDownItems.length }})\n </span>\n <button class=\"at-slide-close\" (click)=\"CloseDrillDownTag()\" style=\"background:none;border:none;cursor:pointer;color:var(--mj-text-muted)\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-card-body\" style=\"max-height: 300px; overflow-y: auto;\">\n @if (TagDrillDownItems.length === 0) {\n <div class=\"at-empty-state\"><p>No content items found for this tag.</p></div>\n } @else {\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Name</th>\n <th>Source</th>\n <th>Weight</th>\n <th>Updated</th>\n </tr>\n </thead>\n <tbody>\n @for (di of TagDrillDownItems; track di.ID) {\n <tr class=\"at-tag-row-clickable\" (click)=\"onOpenItemDetail(di.ID)\">\n <td>{{ di.Name }}</td>\n <td>{{ di.SourceName }}</td>\n <td>{{ FormatWeight(di.Weight) }}</td>\n <td>{{ di.UpdatedAt }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tag-lib-sidebar\">\n <div class=\"at-card at-tag-cloud-card\">\n <div class=\"at-card-title\" style=\"margin-bottom: 12px;\"><i class=\"fa-solid fa-cloud\"></i> Tag Cloud</div>\n @if (TagCloudWordItems.length > 0) {\n <mj-word-cloud\n [Items]=\"TagCloudWordItems\"\n [MaxFontSize]=\"40\"\n [MinFontSize]=\"12\"\n [MaxItems]=\"20\"\n Layout=\"spiral\"\n ColorMode=\"weight-gradient\"\n [Interactive]=\"true\"\n [Animate]=\"true\">\n </mj-word-cloud>\n } @else {\n <div class=\"at-tag-cloud-empty\">No tags yet</div>\n }\n </div>\n <div class=\"at-card\" style=\"padding: 16px; margin-top: 12px;\">\n <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-pie\"></i> By Source</div>\n <div class=\"at-tags-by-source\">\n @for (s of TagsBySource; track s.SourceName) {\n <div class=\"at-tag-source-row\">\n <span>{{ s.SourceName }}</span>\n <strong>{{ s.Count }}</strong>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</mj-page-body-interior>\n"]}
|
|
1
|
+
{"version":3,"file":"tags-tab.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/autotagging/tabs/tags-tab.component.ts","../../../../../src/AI/components/autotagging/tabs/tags-tab.component.html"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;;;;;;;;;;ICTlG,wBAA2C;IAAC,gCAA8B;IAAA,gCAAW;IAAA,iBAAO;;;IAE5F,wBAAyC;IAAC,gCAA8B;IAAA,uBAAO;IAAA,iBAAO;;;IAaxF,8BAAgC;IAC9B,iCAAiD;IACnD,iBAAM;;;;IAoBwB,8BACmE;IADlC,0MAAS,+BAAqB,KAAC;IAE5D,8BAA6B;IAAA,YAAa;IAAA,iBAAK;IAC/C,0BAAI;IAAA,YAAoB;IAAA,iBAAK;IAGrB,AADJ,AADJ,0BAAI,cACiC,cACF;IACvB,0BAGuD;IAC3D,iBAAM;IACN,gCAA8B;IAAA,aAA8B;IAEpE,AADI,AADgE,iBAAO,EACjE,EACL;IAED,AADJ,2BAAI,eACwB;IACpB,2BAAqE;IAE7E,AADI,iBAAM,EACL;IACL,2BAAI;IAAA,aAAmB;IAAA,iBAAK;IAC5B,2BAAI;IAAA,aAAmB;IAC3B,AAD2B,iBAAK,EAC3B;;;;IArBD,iFAA8D;IACjC,eAAa;IAAb,gCAAa;IACtC,eAAoB;IAApB,uCAAoB;IAIoB,eAAqC;IAArC,oDAAqC;IAGhE,AADA,AADA,yDAA6C,uEACyB,yCAC3B;IAEtB,eAA8B;IAA9B,iDAA8B;IAK/B,eAAiC;IAAjC,gDAAiC;IAGlE,eAAmB;IAAnB,sCAAmB;IACnB,eAAmB;IAAnB,sCAAmB;;;IAuBH,AAA5B,+BAA4B,QAAG;IAAA,oDAAoC;IAAI,AAAJ,iBAAI,EAAM;;;;IAajE,8BAAmE;IAAlC,uOAAS,iCAAuB,KAAC;IAC9D,0BAAI;IAAA,YAAa;IAAA,iBAAK;IACtB,0BAAI;IAAA,YAAmB;IAAA,iBAAK;IAC5B,0BAAI;IAAA,YAA6B;IAAA,iBAAK;IACtC,0BAAI;IAAA,YAAkB;IAC1B,AAD0B,iBAAK,EAC1B;;;;IAJG,eAAa;IAAb,gCAAa;IACb,eAAmB;IAAnB,sCAAmB;IACnB,eAA6B;IAA7B,uDAA6B;IAC7B,eAAkB;IAAlB,qCAAkB;;;IAZ1B,AADJ,AADJ,AADJ,iCAA4B,YACjB,SACC,SACI;IAAA,oBAAI;IAAA,iBAAK;IACb,0BAAI;IAAA,sBAAM;IAAA,iBAAK;IACf,0BAAI;IAAA,sBAAM;IAAA,iBAAK;IACf,0BAAI;IAAA,wBAAO;IAEnB,AADI,AADe,iBAAK,EACf,EACD;IACR,8BAAO;IACH,0HAOC;IAET,AADI,iBAAQ,EACJ;;;IATA,gBAOC;IAPD,uCAOC;;;;IA9Bb,AADJ,AADJ,+BAA+C,cACf,eACI;IACxB,wBAA+B;IAC/B,YAEJ;IAAA,iBAAO;IACP,kCAA8J;IAA/H,6LAAS,0BAAmB,KAAC;IACxD,wBAAiC;IAEzC,AADI,iBAAS,EACP;IACN,+BAAuE;IAGjE,AAFF,0GAAsC,uFAE7B;IAuBjB,AADI,iBAAM,EACJ;;;IAjCM,eAEJ;IAFI,6HAEJ;IAMA,eAuBC;IAvBD,+DAuBC;;;IASL,oCASgB;;;IADZ,AADA,AAHA,AADA,AADA,AADA,gDAA2B,mBACT,mBACA,gBACH,qBAGK,iBACJ;;;IAGpB,+BAAgC;IAAA,2BAAW;IAAA,iBAAM;;;IAQzC,AADJ,+BAA+B,WACrB;IAAA,YAAkB;IAAA,iBAAO;IAC/B,8BAAQ;IAAA,YAAa;IACzB,AADyB,iBAAS,EAC5B;;;IAFI,eAAkB;IAAlB,qCAAkB;IAChB,eAAa;IAAb,gCAAa;;ADzGrD,MAAM,OAAO,wBAAyB,SAAQ,oBAAoB;IACtD,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAExC,kFAAkF;IAC1E,YAAY,GAA8B,EAAE,CAAC;IACrD,IACI,WAAW,CAAC,KAAgC;QAC5C,IAAI,CAAC,YAAY,GAAG,KAAK,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;IACD,IAAI,WAAW;QACX,OAAO,IAAI,CAAC,YAAY,CAAC;IAC7B,CAAC;IAED,oFAAoF;IAC5E,aAAa,GAA8B,EAAE,CAAC;IACtD,IACI,YAAY,CAAC,KAAgC;QAC7C,IAAI,CAAC,aAAa,GAAG,KAAK,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;IACD,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED,mEAAmE;IAC5D,SAAS,GAAG,KAAK,CAAC;IAElB,OAAO,GAAa,EAAE,CAAC;IACvB,eAAe,GAAa,EAAE,CAAC;IAC/B,iBAAiB,GAAoB,EAAE,CAAC;IACxC,YAAY,GAAkB,EAAE,CAAC;IACjC,cAAc,GAAG,EAAE,CAAC;IACpB,oBAAoB,GAAkB,IAAI,CAAC;IAC3C,iBAAiB,GAAuB,EAAE,CAAC;IAElD,gFAAgF;IAChF,IAAW,QAAQ;QACf,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,yCAAyC,CAAC;IAC3E,CAAC;IAED,yEAAyE;IACzD,WAAW,GAAG,WAAW,CAAC;IAC1B,YAAY,GAAG,YAAY,CAAC;IAE5C,8EAA8E;IACpE,uBAAuB,GAAG,IAAI,YAAY,EAAU,CAAC;IAExD,gBAAgB,CAAC,aAAqB;QACzC,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACrD,CAAC;IAED,+DAA+D;IACvD,OAAO;QACX,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,EAAE,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,OAAO;QAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,+DAA+D;IAE/D,2GAA2G;IACpG,WAAW,CAAC,KAAa;QAC5B,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;IACvC,CAAC;IAED,4BAA4B;IAEpB,YAAY;QAChB,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEtD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;YACzC,GAAG,EAAE,GAAG;YACR,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG;YACrC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC;YACjD,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,SAAS;YAC7C,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE;SACzC,CAAC,CAAC,CAAC;IACR,CAAC;IAEO,aAAa;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC5C,iGAAiG;QACjG,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAChE,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;YAC1C,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC;QACzD,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,wDAAwD;QACxD,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACtC,IAAI,EAAE,CAAC,CAAC,GAAG;YACX,MAAM,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC7C,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;SACpD,CAAC,CAAC,CAAC;IACR,CAAC;IAEO,iBAAiB;QACrB,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;QAClD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;QAChD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACpC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAW,EAAG,IAAI,CAAC,eAAe,CAAY,IAAI,SAAS,CAAC,CAAC;QAC5F,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAW,CAAC,IAAI,SAAS,CAAC;YACvE,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;aACpD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;aAC3B,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACtE,CAAC;IAEM,UAAU;QACb,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,eAAe,GAAG,CAAC;YACpB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC3D,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,6DAA6D;IACtD,YAAY,CAAC,OAAe;QAC/B,IAAI,IAAI,CAAC,oBAAoB,KAAK,OAAO,EAAE,CAAC;YACxC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,OAAO;QACX,CAAC;QACD,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC;QAEpC,4CAA4C;QAC5C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,kBAAkB;QACrE,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,IAAK,GAAG,CAAC,KAAK,CAAY,KAAK,OAAO,EAAE,CAAC;gBACrC,eAAe,CAAC,GAAG,CACf,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAW,CAAC,EACtC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAC7B,CAAC;YACN,CAAC;QACL,CAAC;QAED,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAW,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACjD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACvB,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;oBACxB,EAAE,EAAE,IAAI,CAAC,IAAI,CAAW;oBACxB,IAAI,EAAE,iBAAiB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAkB,EAAE,WAAW,EAAE,IAAI,CAAC,aAAa,CAAkB,EAAE,CAAC;oBACnH,UAAU,EAAG,IAAI,CAAC,eAAe,CAAY,IAAI,SAAS;oBAC1D,MAAM,EAAE,MAAM;oBACd,SAAS,EAAE,eAAe,CAAE,IAAI,CAAC,gBAAgB,CAAY,IAAI,EAAE,CAAC;oBACpE,SAAS,EAAE,CAAC;iBACf,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,4BAA4B;QAC5B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAEM,iBAAiB;QACpB,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACjC,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,gEAAgE;IAExD,YAAY;QAChB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAW,CAAC;YAC/B,IAAI,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,6DAA6D;IACrD,iBAAiB;QACrB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAW,CAAC;YAC/B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;YACvC,IAAI,CAAC,EAAE,CAAC;gBACJ,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACpC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5C,CAAC;QACL,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;QACvC,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,kBAAkB;QACtB,MAAM,eAAe,GAAG,IAAI,GAAG,EAA+B,CAAC;QAC/D,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;QAChD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACpC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAW,EAAG,IAAI,CAAC,eAAe,CAAY,IAAI,SAAS,CAAC,CAAC;QAC5F,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAW,CAAC;YAC/B,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAW,CAAC,IAAI,SAAS,CAAC;YACvE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;YAC/D,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC;YACtC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,eAAe,EAAE,CAAC;YAChD,IAAI,SAAS,GAAG,SAAS,CAAC;YAC1B,IAAI,QAAQ,GAAG,CAAC,CAAC;YACjB,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,YAAY,EAAE,CAAC;gBACzC,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;oBAAC,SAAS,GAAG,MAAM,CAAC;oBAAC,QAAQ,GAAG,KAAK,CAAC;gBAAC,CAAC;YACnE,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,kBAAkB;QACtB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAW,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,GAAG,GAAG,CAAC,gBAAgB,CAAW,CAAC;gBAC7C,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACrD,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;6QA/PQ,wBAAwB,yBAAxB,wBAAwB;6DAAxB,wBAAwB;YC7BjC,AADF,AAHF,kDAE0B,aACX,gBAC+E;YAA3C,qGAAS,aAAS,IAAC;YAG9D,AAFF,gFAAiB,0DAER;YAIb,AADE,iBAAS,EACL;YAEJ,AADF,8BAAa,eAEgD;YAApD,8NAA4B;YAAC,oGAAS,gBAAY,IAAC;YAE9D,AADE,AAFE,iBAC2D,EACvD,EACkB;YAGxB,AADF,gDAAuD,aAC3B;YACxB,0FAAiB;YAae,AADJ,AADJ,AADJ,AADJ,AADJ,AADJ,AADJ,AADJ,+BAA0B,cACS,eACE,eACJ,eACsD,iBACvC,aACjB,UACC,UACI;YAAA,oBAAG;YAAA,iBAAK;YACZ,2BAAI;YAAA,sBAAK;YAAA,iBAAK;YACd,2BAAI;YAAA,2BAAU;YAAA,iBAAK;YACnB,2BAAI;YAAA,6BAAY;YAAA,iBAAK;YACrB,2BAAI;YAAA,2BAAU;YAAA,iBAAK;YACnB,2BAAI;YAAA,2BAAU;YAEtB,AADI,AADkB,iBAAK,EAClB,EACD;YACR,8BAAO;YACH,+FAwBC;YAIjB,AADI,AADI,AADI,iBAAQ,EACJ,EACN,EACJ;YAGN,8FAA4B;YAwChC,iBAAM;YAGE,AADJ,AADJ,gCAAgC,eACW,eACqB;YAAA,yBAAiC;YAAC,2BAAS;YAAA,iBAAM;YAYvG,AAXF,uGAAoC,uEAW3B;YAGb,iBAAM;YAEF,AADJ,gCAA8D,eACF;YAAA,yBAAqC;YAAC,2BAAS;YAAA,iBAAM;YAC7G,gCAA+B;YAC3B,8FAKC;YAOzB,AADE,AADE,AADI,AADI,AADI,AADI,iBAAM,EACJ,EACJ,EACJ,EACJ,EACF,EACgB;;YAjJpB,uCAAqB;YAE8C,eAAsB;YAAtB,wCAAsB;YACvF,cAIC;YAJD,uCAIC;YAKI,eAA4B;YAA5B,kDAA4B;YAIhB,cAAiB;YAAC,AAAlB,+BAAiB,cAAc;YAElD,eAIC;YAJD,wCAIC;YAkB2B,gBAwBC;YAxBD,kCAwBC;YAOjB,eAuCC;YAvCD,oDAuCC;YAKG,eAaC;YAbD,4DAaC;YAKG,eAKC;YALD,+BAKC;;;iFD3GZ,wBAAwB;cANpC,SAAS;6BACM,KAAK,YACP,mBAAmB;;kBAS5B,KAAK;;kBAWL,KAAK;;kBA8BL,MAAM;;kFA9CE,wBAAwB","sourcesContent":["/**\n * @fileoverview Classify · Tag Library tab.\n *\n * Self-contained sub-page: owns its header-interior (with the tag search box),\n * the tag rows table, the word cloud, the tags-by-source breakdown, and the\n * per-tag drill-down. Receives the shared raw tag + item rows from the host\n * orchestrator via `[ContentTags]`/`[ContentItems]` and rebuilds its view\n * models from them. Opening a content item from the drill-down is a cross-tab\n * concern owned by the host's slide-in, so it bubbles up via @Output.\n */\nimport { Component, ChangeDetectorRef, EventEmitter, Input, Output, inject } from '@angular/core';\nimport { NormalizeUUID } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { WordCloudItem } from '@memberjunction/ng-word-cloud';\nimport { TagRow, TagBySource } from '../shared/classify.types';\nimport { formatWeight, tagFontSize, formatShortDate, deriveDisplayName } from '../shared/classify.format';\n\n/** One row in the per-tag drill-down (content items carrying a given tag). */\ninterface TagDrillDownItem {\n ID: string;\n Name: string;\n SourceName: string;\n Weight: number;\n UpdatedAt: string;\n FeedIndex: number;\n}\n\n@Component({\n standalone: false,\n selector: 'classify-tags-tab',\n templateUrl: './tags-tab.component.html',\n styleUrls: ['./tags-tab.component.css']\n})\nexport class ClassifyTagsTabComponent extends BaseAngularComponent {\n private cdr = inject(ChangeDetectorRef);\n\n /** Shared raw `MJ: Content Item Tags` rows, supplied by the host orchestrator. */\n private _contentTags: Record<string, unknown>[] = [];\n @Input()\n set ContentTags(value: Record<string, unknown>[]) {\n this._contentTags = value ?? [];\n this.rebuild();\n }\n get ContentTags(): Record<string, unknown>[] {\n return this._contentTags;\n }\n\n /** Shared raw `MJ: Content Items` rows — used for source mapping and drill-down. */\n private _contentItems: Record<string, unknown>[] = [];\n @Input()\n set ContentItems(value: Record<string, unknown>[]) {\n this._contentItems = value ?? [];\n this.rebuild();\n }\n get ContentItems(): Record<string, unknown>[] {\n return this._contentItems;\n }\n\n /** Shown while a manual Refresh() rebuilds the tag view models. */\n public IsLoading = false;\n\n public TagRows: TagRow[] = [];\n public FilteredTagRows: TagRow[] = [];\n public TagCloudWordItems: WordCloudItem[] = [];\n public TagsBySource: TagBySource[] = [];\n public TagSearchQuery = '';\n public SelectedDrillDownTag: string | null = null;\n public TagDrillDownItems: TagDrillDownItem[] = [];\n\n /** Subtitle reflects the live tag count, mirroring the former host subtitle. */\n public get Subtitle(): string {\n return `${this.TagRows.length} unique tags across all content sources`;\n }\n\n // Template-facing formatters (shared pure helpers exposed for the view).\n public readonly TagFontSize = tagFontSize;\n public readonly FormatWeight = formatWeight;\n\n /** Bubble a request to open a content item's detail slide-in (host-owned). */\n @Output() OpenItemDetailRequested = new EventEmitter<string>();\n\n public onOpenItemDetail(contentItemID: string): void {\n this.OpenItemDetailRequested.emit(contentItemID);\n }\n\n /** Rebuild all tag-tab view models from the current inputs. */\n private rebuild(): void {\n this.buildTagRows();\n this.buildTagCloud();\n this.buildTagsBySource();\n this.FilterTags();\n }\n\n /**\n * Rebuild the tag view models from the current host-supplied inputs. The tag\n * data is host-owned (flows in via [ContentTags]/[ContentItems]); Refresh\n * recomputes the rows/cloud/breakdown and surfaces a brief loading state.\n */\n public async Refresh(): Promise<void> {\n this.IsLoading = true;\n this.cdr.detectChanges();\n this.rebuild();\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n\n // ── External control surface (host deep-link + agent tool) ──\n\n /** Apply a search query programmatically (used by the agent tool + deep link). Returns the match count. */\n public ApplySearch(query: string): number {\n this.TagSearchQuery = query;\n this.FilterTags();\n return this.FilteredTagRows.length;\n }\n\n // ── View-model building ──\n\n private buildTagRows(): void {\n const tagCounts = this.countAllTags();\n const avgWeights = this.computeAvgWeights();\n const tagSourceMap = this.getTopSourcePerTag();\n const tagFirstSeen = this.getFirstSeenPerTag();\n const sorted = Array.from(tagCounts.entries()).sort((a, b) => b[1] - a[1]);\n const maxCount = sorted.length > 0 ? sorted[0][1] : 1;\n\n this.TagRows = sorted.map(([tag, count]) => ({\n Tag: tag,\n UsageCount: count,\n AvgWeight: avgWeights.get(tag) ?? 1.0,\n BarWidthPct: Math.round((count / maxCount) * 100),\n TopSource: tagSourceMap.get(tag) ?? 'Unknown',\n FirstSeen: tagFirstSeen.get(tag) ?? ''\n }));\n }\n\n private buildTagCloud(): void {\n const tagCounts = this.countAllTags();\n const avgWeights = this.computeAvgWeights();\n // Sort by a combined score: usage count * avg weight (so high-weight, high-count tags bubble up)\n const scored = Array.from(tagCounts.entries()).map(([tag, count]) => {\n const weight = avgWeights.get(tag) ?? 1.0;\n return { tag, count, weight, score: count * weight };\n }).sort((a, b) => b.score - a.score).slice(0, 20);\n const maxScore = scored.length > 0 ? scored[0].score : 1;\n\n // Build WordCloudItem[] for the mj-word-cloud component\n this.TagCloudWordItems = scored.map(s => ({\n Text: s.tag,\n Weight: maxScore > 0 ? s.score / maxScore : 0,\n Metadata: { Count: s.count, AvgWeight: s.weight }\n }));\n }\n\n private buildTagsBySource(): void {\n const sourceTagCounts = new Map<string, number>();\n const itemSourceMap = new Map<string, string>();\n for (const item of this._contentItems) {\n itemSourceMap.set(item['ID'] as string, (item['ContentSource'] as string) ?? 'Unknown');\n }\n for (const tag of this._contentTags) {\n const source = itemSourceMap.get(tag['ItemID'] as string) ?? 'Unknown';\n sourceTagCounts.set(source, (sourceTagCounts.get(source) ?? 0) + 1);\n }\n this.TagsBySource = Array.from(sourceTagCounts.entries())\n .sort((a, b) => b[1] - a[1])\n .map(([name, count]) => ({ SourceName: name, Count: count }));\n }\n\n public FilterTags(): void {\n const q = this.TagSearchQuery.toLowerCase().trim();\n this.FilteredTagRows = q\n ? this.TagRows.filter(r => r.Tag.toLowerCase().includes(q))\n : this.TagRows;\n this.cdr.detectChanges();\n }\n\n /** Drill down into content items matching a specific tag. */\n public DrillDownTag(tagName: string): void {\n if (this.SelectedDrillDownTag === tagName) {\n this.CloseDrillDownTag();\n return;\n }\n this.SelectedDrillDownTag = tagName;\n\n // Find all content items that have this tag\n const matchingItemIDs = new Map<string, number>(); // itemID → weight\n for (const tag of this._contentTags) {\n if ((tag['Tag'] as string) === tagName) {\n matchingItemIDs.set(\n NormalizeUUID(tag['ItemID'] as string),\n Number(tag['Weight'] ?? 1)\n );\n }\n }\n\n this.TagDrillDownItems = [];\n for (let i = 0; i < this._contentItems.length; i++) {\n const item = this._contentItems[i];\n const normalizedID = NormalizeUUID(item['ID'] as string);\n const weight = matchingItemIDs.get(normalizedID);\n if (weight !== undefined) {\n this.TagDrillDownItems.push({\n ID: item['ID'] as string,\n Name: deriveDisplayName({ Name: item['Name'] as string | null, Description: item['Description'] as string | null }),\n SourceName: (item['ContentSource'] as string) ?? 'Unknown',\n Weight: weight,\n UpdatedAt: formatShortDate((item['__mj_UpdatedAt'] as string) ?? ''),\n FeedIndex: i,\n });\n }\n }\n\n // Sort by weight descending\n this.TagDrillDownItems.sort((a, b) => b.Weight - a.Weight);\n this.cdr.detectChanges();\n }\n\n public CloseDrillDownTag(): void {\n this.SelectedDrillDownTag = null;\n this.TagDrillDownItems = [];\n this.cdr.detectChanges();\n }\n\n // ── Aggregation utilities (read only the tag + item inputs) ──\n\n private countAllTags(): Map<string, number> {\n const counts = new Map<string, number>();\n for (const tag of this._contentTags) {\n const t = tag['Tag'] as string;\n if (t) counts.set(t, (counts.get(t) ?? 0) + 1);\n }\n return counts;\n }\n\n /** Compute average weight per tag across all occurrences. */\n private computeAvgWeights(): Map<string, number> {\n const sums = new Map<string, number>();\n const counts = new Map<string, number>();\n for (const tag of this._contentTags) {\n const t = tag['Tag'] as string;\n const w = Number(tag['Weight'] ?? 0.5);\n if (t) {\n sums.set(t, (sums.get(t) ?? 0) + w);\n counts.set(t, (counts.get(t) ?? 0) + 1);\n }\n }\n const avgs = new Map<string, number>();\n for (const [t, sum] of sums) {\n avgs.set(t, Math.round((sum / (counts.get(t) ?? 1)) * 100) / 100);\n }\n return avgs;\n }\n\n private getTopSourcePerTag(): Map<string, string> {\n const tagSourceCounts = new Map<string, Map<string, number>>();\n const itemSourceMap = new Map<string, string>();\n for (const item of this._contentItems) {\n itemSourceMap.set(item['ID'] as string, (item['ContentSource'] as string) ?? 'Unknown');\n }\n for (const tag of this._contentTags) {\n const t = tag['Tag'] as string;\n const source = itemSourceMap.get(tag['ItemID'] as string) ?? 'Unknown';\n if (!tagSourceCounts.has(t)) tagSourceCounts.set(t, new Map());\n const inner = tagSourceCounts.get(t)!;\n inner.set(source, (inner.get(source) ?? 0) + 1);\n }\n const result = new Map<string, string>();\n for (const [tag, sourceCounts] of tagSourceCounts) {\n let maxSource = 'Unknown';\n let maxCount = 0;\n for (const [source, count] of sourceCounts) {\n if (count > maxCount) { maxSource = source; maxCount = count; }\n }\n result.set(tag, maxSource);\n }\n return result;\n }\n\n private getFirstSeenPerTag(): Map<string, string> {\n const result = new Map<string, string>();\n for (const tag of this._contentTags) {\n const t = tag['Tag'] as string;\n if (t && !result.has(t)) {\n const date = tag['__mj_CreatedAt'] as string;\n result.set(t, date ? formatShortDate(date) : '');\n }\n }\n return result;\n }\n}\n","<mj-page-header-interior\n Title=\"Tag Library\"\n [Subtitle]=\"Subtitle\">\n <div actions>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"Refresh()\" [disabled]=\"IsLoading\">\n @if (IsLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> <span class=\"mj-action-label\">Refreshing…</span>\n } @else {\n <i class=\"fa-solid fa-arrows-rotate\"></i> <span class=\"mj-action-label\">Refresh</span>\n }\n </button>\n </div>\n <div toolbar>\n <input type=\"text\" class=\"at-search-input\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TagSearchQuery\" (input)=\"FilterTags()\">\n </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior [Padding]=\"false\" [Flex]=\"true\">\n <div class=\"at-main-area\">\n @if (IsLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Refreshing tags…\"></mj-loading>\n </div>\n }\n <div class=\"at-page-body\">\n <div class=\"at-tag-lib-layout\">\n <div class=\"at-tag-lib-main\">\n <div class=\"at-card\">\n <div class=\"at-card-body\" style=\"max-height: 500px; overflow-y: auto;\">\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Count</th>\n <th>Avg Weight</th>\n <th>Distribution</th>\n <th>Top Source</th>\n <th>First Seen</th>\n </tr>\n </thead>\n <tbody>\n @for (row of FilteredTagRows; track row.Tag) {\n <tr class=\"at-tag-row-clickable\" (click)=\"DrillDownTag(row.Tag)\"\n [class.at-tag-row-selected]=\"SelectedDrillDownTag === row.Tag\">\n <td class=\"at-tag-name-cell\">{{ row.Tag }}</td>\n <td>{{ row.UsageCount }}</td>\n <td>\n <div class=\"at-weight-indicator\">\n <div class=\"at-weight-bar\">\n <div class=\"at-weight-bar-fill\" [style.width.%]=\"row.AvgWeight * 100\"\n [class.at-weight-high]=\"row.AvgWeight >= 0.7\"\n [class.at-weight-medium]=\"row.AvgWeight >= 0.4 && row.AvgWeight < 0.7\"\n [class.at-weight-low]=\"row.AvgWeight < 0.4\"></div>\n </div>\n <span class=\"at-weight-value\">{{ row.AvgWeight.toFixed(2) }}</span>\n </div>\n </td>\n <td>\n <div class=\"at-tag-bar\">\n <div class=\"at-tag-bar-fill\" [style.width.%]=\"row.BarWidthPct\"></div>\n </div>\n </td>\n <td>{{ row.TopSource }}</td>\n <td>{{ row.FirstSeen }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Tag drill-down: content items matching selected tag -->\n @if (SelectedDrillDownTag) {\n <div class=\"at-card\" style=\"margin-top: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\">\n <i class=\"fa-solid fa-tag\"></i>\n Content items tagged \"{{ SelectedDrillDownTag }}\"\n ({{ TagDrillDownItems.length }})\n </span>\n <button class=\"at-slide-close\" (click)=\"CloseDrillDownTag()\" style=\"background:none;border:none;cursor:pointer;color:var(--mj-text-muted)\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-card-body\" style=\"max-height: 300px; overflow-y: auto;\">\n @if (TagDrillDownItems.length === 0) {\n <div class=\"at-empty-state\"><p>No content items found for this tag.</p></div>\n } @else {\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Name</th>\n <th>Source</th>\n <th>Weight</th>\n <th>Updated</th>\n </tr>\n </thead>\n <tbody>\n @for (di of TagDrillDownItems; track di.ID) {\n <tr class=\"at-tag-row-clickable\" (click)=\"onOpenItemDetail(di.ID)\">\n <td>{{ di.Name }}</td>\n <td>{{ di.SourceName }}</td>\n <td>{{ FormatWeight(di.Weight) }}</td>\n <td>{{ di.UpdatedAt }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tag-lib-sidebar\">\n <div class=\"at-card at-tag-cloud-card\">\n <div class=\"at-card-title\" style=\"margin-bottom: 12px;\"><i class=\"fa-solid fa-cloud\"></i> Tag Cloud</div>\n @if (TagCloudWordItems.length > 0) {\n <mj-word-cloud\n [Items]=\"TagCloudWordItems\"\n [MaxFontSize]=\"40\"\n [MinFontSize]=\"12\"\n [MaxItems]=\"20\"\n Layout=\"spiral\"\n ColorMode=\"weight-gradient\"\n [Interactive]=\"true\"\n [Animate]=\"true\">\n </mj-word-cloud>\n } @else {\n <div class=\"at-tag-cloud-empty\">No tags yet</div>\n }\n </div>\n <div class=\"at-card\" style=\"padding: 16px; margin-top: 12px;\">\n <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-pie\"></i> By Source</div>\n <div class=\"at-tags-by-source\">\n @for (s of TagsBySource; track s.SourceName) {\n <div class=\"at-tag-source-row\">\n <span>{{ s.SourceName }}</span>\n <strong>{{ s.Count }}</strong>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</mj-page-body-interior>\n"]}
|
|
@@ -13,6 +13,9 @@ import { ContentTypeCard } from '../shared/classify.types';
|
|
|
13
13
|
import { formatNumber } from '../shared/classify.format';
|
|
14
14
|
import * as i0 from "@angular/core";
|
|
15
15
|
export declare class ClassifyTypesTabComponent extends BaseAngularComponent {
|
|
16
|
+
private cdr;
|
|
17
|
+
/** Shown while a manual Refresh() recomputes the content-type cards. */
|
|
18
|
+
IsLoading: boolean;
|
|
16
19
|
/** Raw `MJ: Content Types` rows — the primary source for the cards. */
|
|
17
20
|
private _contentTypes;
|
|
18
21
|
set ContentTypes(value: Record<string, unknown>[]);
|
|
@@ -35,6 +38,12 @@ export declare class ClassifyTypesTabComponent extends BaseAngularComponent {
|
|
|
35
38
|
/** Bubble Add/Edit intents to the host, which owns the slide-in CRUD form. */
|
|
36
39
|
AddTypeRequested: EventEmitter<void>;
|
|
37
40
|
EditTypeRequested: EventEmitter<ContentTypeCard>;
|
|
41
|
+
/**
|
|
42
|
+
* Recompute the content-type cards from the current host-supplied inputs. The
|
|
43
|
+
* data is host-owned (flows in via @Input); Refresh rebuilds the view models
|
|
44
|
+
* and surfaces a brief loading state for user feedback.
|
|
45
|
+
*/
|
|
46
|
+
Refresh(): Promise<void>;
|
|
38
47
|
onAddType(): void;
|
|
39
48
|
onEditType(card: ContentTypeCard): void;
|
|
40
49
|
/** Rebuild the card view models from the current inputs. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-tab.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/autotagging/tabs/types-tab.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"types-tab.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/autotagging/tabs/types-tab.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAgC,YAAY,EAAyB,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;;AAEzD,qBAMa,yBAA0B,SAAQ,oBAAoB;IAC/D,OAAO,CAAC,GAAG,CAA6B;IAExC,wEAAwE;IACjE,SAAS,UAAS;IAEzB,uEAAuE;IACvE,OAAO,CAAC,aAAa,CAAiC;IACtD,IACI,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAGhD;IACD,IAAI,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAE5C;IAED,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAiC;IACjD,IACI,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAG3C;IACD,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAEvC;IAED,2EAA2E;IAC3E,OAAO,CAAC,MAAM,CAAiC;IAC/C,IACI,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAGzC;IACD,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAErC;IAED,6FAA6F;IAC7F,OAAO,CAAC,eAAe,CAAK;IAC5B,IACI,cAAc,CAAC,KAAK,EAAE,MAAM,EAG/B;IACD,IAAI,cAAc,IAAI,MAAM,CAE3B;IAEM,gBAAgB,EAAE,eAAe,EAAE,CAAM;IAEhD,uFAAuF;IACvF,SAAgB,YAAY,sBAAgB;IAE5C,8EAA8E;IACpE,gBAAgB,qBAA4B;IAC5C,iBAAiB,gCAAuC;IAElE;;;;OAIG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B,SAAS,IAAI,IAAI;IAIjB,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI;IAI9C,4DAA4D;IAC5D,OAAO,CAAC,OAAO;IA8Bf,OAAO,CAAC,yBAAyB;IASjC,OAAO,CAAC,uBAAuB;yCAxHtB,yBAAyB;2CAAzB,yBAAyB;CAgIrC"}
|