@memberjunction/ng-dashboards 5.40.2 → 5.42.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/analytics/ai-analytics-resource.component.d.ts +38 -4
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.js +148 -20
- package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-management-data.d.ts +216 -0
- package/dist/AI/components/analytics/realtime/realtime-management-data.d.ts.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-management-data.js +313 -0
- package/dist/AI/components/analytics/realtime/realtime-management-data.js.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-management.component.d.ts +103 -0
- package/dist/AI/components/analytics/realtime/realtime-management.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-management.component.js +1060 -0
- package/dist/AI/components/analytics/realtime/realtime-management.component.js.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-overview.component.d.ts +87 -0
- package/dist/AI/components/analytics/realtime/realtime-overview.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-overview.component.js +710 -0
- package/dist/AI/components/analytics/realtime/realtime-overview.component.js.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts +127 -0
- package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-session-data.js +233 -0
- package/dist/AI/components/analytics/realtime/realtime-session-data.js.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-sessions.component.d.ts +94 -0
- package/dist/AI/components/analytics/realtime/realtime-sessions.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/realtime/realtime-sessions.component.js +728 -0
- package/dist/AI/components/analytics/realtime/realtime-sessions.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +2 -2
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +2 -2
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +2 -2
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/index.d.ts +5 -0
- package/dist/AI/index.d.ts.map +1 -1
- package/dist/AI/index.js +7 -0
- package/dist/AI/index.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/Home/home-dashboard.component.js +12 -8
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.d.ts +12 -0
- package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +419 -333
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +5 -5
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.d.ts +16 -2
- package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +37 -5
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +22 -19
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +18 -0
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +1 -1
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +3 -1
- package/dist/core-dashboards.module.js.map +1 -1
- package/package.json +55 -55
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Realtime Voice — sessions management grid.
|
|
3
|
+
*
|
|
4
|
+
* Every long-lived `MJ: AI Agent Sessions` row across the platform — live
|
|
5
|
+
* calls, idle holds, and closed history — with the channels each session
|
|
6
|
+
* opened and the agent runs it delegated. KPI strip up top, a filter bar
|
|
7
|
+
* (search · status · target agent · user · host), the data grid (Agent →
|
|
8
|
+
* Target, status pills incl. the persisted close cause — explicit / janitor /
|
|
9
|
+
* shutdown / error / unknown-legacy, channel icons, run count, tokens / cost,
|
|
10
|
+
* started, duration, host instance), and row drill-in to the session record.
|
|
11
|
+
*/
|
|
12
|
+
import { Component, Input, ChangeDetectorRef, inject } from '@angular/core';
|
|
13
|
+
import { CompositeKey } from '@memberjunction/core';
|
|
14
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
15
|
+
import { SharedService } from '@memberjunction/ng-shared';
|
|
16
|
+
import { LoadRealtimeSessionsDataset, FormatSessionDuration, FormatTokenCount, FormatSessionCost, FormatSessionStart, ChannelIconClass, BuildSessionStatusDisplay } from './realtime-session-data';
|
|
17
|
+
import * as i0 from "@angular/core";
|
|
18
|
+
import * as i1 from "@angular/forms";
|
|
19
|
+
import * as i2 from "@memberjunction/ng-shared-generic";
|
|
20
|
+
import * as i3 from "../../widgets/kpi-card.component";
|
|
21
|
+
import * as i4 from "@memberjunction/ng-ui-components";
|
|
22
|
+
const _forTrack0 = ($index, $item) => $item.title;
|
|
23
|
+
const _forTrack1 = ($index, $item) => $item.Value;
|
|
24
|
+
const _forTrack2 = ($index, $item) => $item.ID;
|
|
25
|
+
const _forTrack3 = ($index, $item) => $item.Name;
|
|
26
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
27
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
28
|
+
i0.ɵɵelement(1, "mj-loading", 1);
|
|
29
|
+
i0.ɵɵelementEnd();
|
|
30
|
+
} }
|
|
31
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
32
|
+
i0.ɵɵelement(0, "app-kpi-card", 3);
|
|
33
|
+
} if (rf & 2) {
|
|
34
|
+
const kpi_r2 = ctx.$implicit;
|
|
35
|
+
i0.ɵɵproperty("data", kpi_r2);
|
|
36
|
+
} }
|
|
37
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_20_Template(rf, ctx) { if (rf & 1) {
|
|
38
|
+
i0.ɵɵelementStart(0, "option", 13);
|
|
39
|
+
i0.ɵɵtext(1);
|
|
40
|
+
i0.ɵɵelementEnd();
|
|
41
|
+
} if (rf & 2) {
|
|
42
|
+
const opt_r4 = ctx.$implicit;
|
|
43
|
+
i0.ɵɵproperty("value", opt_r4.Value);
|
|
44
|
+
i0.ɵɵadvance();
|
|
45
|
+
i0.ɵɵtextInterpolate(opt_r4.Label);
|
|
46
|
+
} }
|
|
47
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_25_Template(rf, ctx) { if (rf & 1) {
|
|
48
|
+
i0.ɵɵelementStart(0, "option", 13);
|
|
49
|
+
i0.ɵɵtext(1);
|
|
50
|
+
i0.ɵɵelementEnd();
|
|
51
|
+
} if (rf & 2) {
|
|
52
|
+
const opt_r5 = ctx.$implicit;
|
|
53
|
+
i0.ɵɵproperty("value", opt_r5.Value);
|
|
54
|
+
i0.ɵɵadvance();
|
|
55
|
+
i0.ɵɵtextInterpolate(opt_r5.Label);
|
|
56
|
+
} }
|
|
57
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_30_Template(rf, ctx) { if (rf & 1) {
|
|
58
|
+
i0.ɵɵelementStart(0, "option", 13);
|
|
59
|
+
i0.ɵɵtext(1);
|
|
60
|
+
i0.ɵɵelementEnd();
|
|
61
|
+
} if (rf & 2) {
|
|
62
|
+
const opt_r6 = ctx.$implicit;
|
|
63
|
+
i0.ɵɵproperty("value", opt_r6.Value);
|
|
64
|
+
i0.ɵɵadvance();
|
|
65
|
+
i0.ɵɵtextInterpolate(opt_r6.Label);
|
|
66
|
+
} }
|
|
67
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_Conditional_62_Template(rf, ctx) { if (rf & 1) {
|
|
68
|
+
i0.ɵɵelementStart(0, "tr")(1, "td", 25);
|
|
69
|
+
i0.ɵɵtext(2, "No sessions match the current filters");
|
|
70
|
+
i0.ɵɵelementEnd()();
|
|
71
|
+
} }
|
|
72
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
73
|
+
i0.ɵɵelementStart(0, "span", 30);
|
|
74
|
+
i0.ɵɵelement(1, "i", 45);
|
|
75
|
+
i0.ɵɵtext(2, " resumed ");
|
|
76
|
+
i0.ɵɵelementEnd();
|
|
77
|
+
} }
|
|
78
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
79
|
+
i0.ɵɵelement(0, "span", 33);
|
|
80
|
+
} }
|
|
81
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
82
|
+
i0.ɵɵelement(0, "i");
|
|
83
|
+
} if (rf & 2) {
|
|
84
|
+
const row_r8 = i0.ɵɵnextContext().$implicit;
|
|
85
|
+
i0.ɵɵclassMap(row_r8.StatusIcon);
|
|
86
|
+
} }
|
|
87
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_For_18_Template(rf, ctx) { if (rf & 1) {
|
|
88
|
+
i0.ɵɵelement(0, "i", 46);
|
|
89
|
+
} if (rf & 2) {
|
|
90
|
+
const chan_r9 = ctx.$implicit;
|
|
91
|
+
i0.ɵɵclassMap(chan_r9.Icon);
|
|
92
|
+
i0.ɵɵproperty("title", chan_r9.Name);
|
|
93
|
+
} }
|
|
94
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
95
|
+
i0.ɵɵelementStart(0, "span", 37);
|
|
96
|
+
i0.ɵɵtext(1);
|
|
97
|
+
i0.ɵɵelementEnd();
|
|
98
|
+
} if (rf & 2) {
|
|
99
|
+
const row_r8 = i0.ɵɵnextContext().$implicit;
|
|
100
|
+
i0.ɵɵadvance();
|
|
101
|
+
i0.ɵɵtextInterpolate(row_r8.ChannelCount);
|
|
102
|
+
} }
|
|
103
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Template(rf, ctx) { if (rf & 1) {
|
|
104
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
105
|
+
i0.ɵɵelementStart(0, "tr", 26);
|
|
106
|
+
i0.ɵɵlistener("click", function AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Template_tr_click_0_listener() { const row_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OpenSession(row_r8.ID)); });
|
|
107
|
+
i0.ɵɵelementStart(1, "td")(2, "div", 27);
|
|
108
|
+
i0.ɵɵtext(3);
|
|
109
|
+
i0.ɵɵelementEnd();
|
|
110
|
+
i0.ɵɵelementStart(4, "div", 28);
|
|
111
|
+
i0.ɵɵelement(5, "i", 29);
|
|
112
|
+
i0.ɵɵtext(6);
|
|
113
|
+
i0.ɵɵconditionalCreate(7, AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Conditional_7_Template, 3, 0, "span", 30);
|
|
114
|
+
i0.ɵɵelementEnd()();
|
|
115
|
+
i0.ɵɵelementStart(8, "td", 31);
|
|
116
|
+
i0.ɵɵtext(9);
|
|
117
|
+
i0.ɵɵelementEnd();
|
|
118
|
+
i0.ɵɵelementStart(10, "td")(11, "span", 32);
|
|
119
|
+
i0.ɵɵconditionalCreate(12, AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Conditional_12_Template, 1, 0, "span", 33)(13, AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Conditional_13_Template, 1, 2, "i", 34);
|
|
120
|
+
i0.ɵɵtext(14);
|
|
121
|
+
i0.ɵɵelementEnd()();
|
|
122
|
+
i0.ɵɵelementStart(15, "td")(16, "span", 35);
|
|
123
|
+
i0.ɵɵrepeaterCreate(17, AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_For_18_Template, 1, 3, "i", 36, _forTrack3);
|
|
124
|
+
i0.ɵɵelementEnd();
|
|
125
|
+
i0.ɵɵconditionalCreate(19, AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Conditional_19_Template, 2, 1, "span", 37);
|
|
126
|
+
i0.ɵɵelementEnd();
|
|
127
|
+
i0.ɵɵelementStart(20, "td", 38);
|
|
128
|
+
i0.ɵɵtext(21);
|
|
129
|
+
i0.ɵɵelementEnd();
|
|
130
|
+
i0.ɵɵelementStart(22, "td", 39);
|
|
131
|
+
i0.ɵɵtext(23);
|
|
132
|
+
i0.ɵɵelementEnd();
|
|
133
|
+
i0.ɵɵelementStart(24, "td", 39);
|
|
134
|
+
i0.ɵɵtext(25);
|
|
135
|
+
i0.ɵɵelementEnd();
|
|
136
|
+
i0.ɵɵelementStart(26, "td", 40);
|
|
137
|
+
i0.ɵɵtext(27);
|
|
138
|
+
i0.ɵɵelementEnd();
|
|
139
|
+
i0.ɵɵelementStart(28, "td", 39);
|
|
140
|
+
i0.ɵɵtext(29);
|
|
141
|
+
i0.ɵɵelementEnd();
|
|
142
|
+
i0.ɵɵelementStart(30, "td", 41);
|
|
143
|
+
i0.ɵɵtext(31);
|
|
144
|
+
i0.ɵɵelementEnd();
|
|
145
|
+
i0.ɵɵelementStart(32, "td", 42)(33, "button", 43);
|
|
146
|
+
i0.ɵɵlistener("click", function AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Template_button_click_33_listener($event) { const row_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.OpenSession(row_r8.ID); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
147
|
+
i0.ɵɵelement(34, "i", 44);
|
|
148
|
+
i0.ɵɵelementEnd()()();
|
|
149
|
+
} if (rf & 2) {
|
|
150
|
+
const row_r8 = ctx.$implicit;
|
|
151
|
+
i0.ɵɵadvance(3);
|
|
152
|
+
i0.ɵɵtextInterpolate(row_r8.Agent);
|
|
153
|
+
i0.ɵɵadvance(3);
|
|
154
|
+
i0.ɵɵtextInterpolate1(" ", row_r8.Target, " ");
|
|
155
|
+
i0.ɵɵadvance();
|
|
156
|
+
i0.ɵɵconditional(row_r8.IsResumed ? 7 : -1);
|
|
157
|
+
i0.ɵɵadvance(2);
|
|
158
|
+
i0.ɵɵtextInterpolate(row_r8.User);
|
|
159
|
+
i0.ɵɵadvance(2);
|
|
160
|
+
i0.ɵɵclassMap(row_r8.StatusClass);
|
|
161
|
+
i0.ɵɵproperty("title", row_r8.StatusTitle);
|
|
162
|
+
i0.ɵɵadvance();
|
|
163
|
+
i0.ɵɵconditional(row_r8.Status === "Active" ? 12 : row_r8.StatusIcon ? 13 : -1);
|
|
164
|
+
i0.ɵɵadvance(2);
|
|
165
|
+
i0.ɵɵtextInterpolate1(" ", row_r8.StatusLabel, " ");
|
|
166
|
+
i0.ɵɵadvance(3);
|
|
167
|
+
i0.ɵɵrepeater(row_r8.ChannelIcons);
|
|
168
|
+
i0.ɵɵadvance(2);
|
|
169
|
+
i0.ɵɵconditional(row_r8.ChannelCount > 0 ? 19 : -1);
|
|
170
|
+
i0.ɵɵadvance(2);
|
|
171
|
+
i0.ɵɵtextInterpolate(row_r8.Runs);
|
|
172
|
+
i0.ɵɵadvance(2);
|
|
173
|
+
i0.ɵɵtextInterpolate(row_r8.Tokens);
|
|
174
|
+
i0.ɵɵadvance(2);
|
|
175
|
+
i0.ɵɵtextInterpolate(row_r8.Cost);
|
|
176
|
+
i0.ɵɵadvance(2);
|
|
177
|
+
i0.ɵɵtextInterpolate(row_r8.Started);
|
|
178
|
+
i0.ɵɵadvance(2);
|
|
179
|
+
i0.ɵɵtextInterpolate(row_r8.Duration);
|
|
180
|
+
i0.ɵɵadvance();
|
|
181
|
+
i0.ɵɵproperty("title", row_r8.Host);
|
|
182
|
+
i0.ɵɵadvance();
|
|
183
|
+
i0.ɵɵtextInterpolate(row_r8.Host);
|
|
184
|
+
} }
|
|
185
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_Conditional_68_Template(rf, ctx) { if (rf & 1) {
|
|
186
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
187
|
+
i0.ɵɵelementStart(0, "div", 24)(1, "button", 47);
|
|
188
|
+
i0.ɵɵlistener("click", function AnalyticsRealtimeSessionsComponent_Conditional_1_Conditional_68_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.PrevPage()); });
|
|
189
|
+
i0.ɵɵelement(2, "i", 48);
|
|
190
|
+
i0.ɵɵelementEnd();
|
|
191
|
+
i0.ɵɵelementStart(3, "span", 49);
|
|
192
|
+
i0.ɵɵtext(4);
|
|
193
|
+
i0.ɵɵelementEnd();
|
|
194
|
+
i0.ɵɵelementStart(5, "button", 47);
|
|
195
|
+
i0.ɵɵlistener("click", function AnalyticsRealtimeSessionsComponent_Conditional_1_Conditional_68_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.NextPage()); });
|
|
196
|
+
i0.ɵɵelement(6, "i", 50);
|
|
197
|
+
i0.ɵɵelementEnd()();
|
|
198
|
+
} if (rf & 2) {
|
|
199
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
200
|
+
i0.ɵɵadvance();
|
|
201
|
+
i0.ɵɵproperty("disabled", ctx_r2.PageIndex === 0);
|
|
202
|
+
i0.ɵɵadvance(3);
|
|
203
|
+
i0.ɵɵtextInterpolate2("Page ", ctx_r2.PageIndex + 1, " of ", ctx_r2.PageCount);
|
|
204
|
+
i0.ɵɵadvance();
|
|
205
|
+
i0.ɵɵproperty("disabled", ctx_r2.PageIndex >= ctx_r2.PageCount - 1);
|
|
206
|
+
} }
|
|
207
|
+
function AnalyticsRealtimeSessionsComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
208
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
209
|
+
i0.ɵɵelementStart(0, "div", 2);
|
|
210
|
+
i0.ɵɵrepeaterCreate(1, AnalyticsRealtimeSessionsComponent_Conditional_1_For_2_Template, 1, 1, "app-kpi-card", 3, _forTrack0);
|
|
211
|
+
i0.ɵɵelementEnd();
|
|
212
|
+
i0.ɵɵelementStart(3, "div", 4)(4, "div", 5);
|
|
213
|
+
i0.ɵɵelement(5, "i", 6);
|
|
214
|
+
i0.ɵɵelementStart(6, "input", 7);
|
|
215
|
+
i0.ɵɵlistener("input", function AnalyticsRealtimeSessionsComponent_Conditional_1_Template_input_input_6_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnSearchChanged($event)); });
|
|
216
|
+
i0.ɵɵelementEnd()();
|
|
217
|
+
i0.ɵɵelementStart(7, "select", 8);
|
|
218
|
+
i0.ɵɵlistener("change", function AnalyticsRealtimeSessionsComponent_Conditional_1_Template_select_change_7_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnStatusFilterChanged($event)); });
|
|
219
|
+
i0.ɵɵelementStart(8, "option", 9);
|
|
220
|
+
i0.ɵɵtext(9, "Status: All");
|
|
221
|
+
i0.ɵɵelementEnd();
|
|
222
|
+
i0.ɵɵelementStart(10, "option", 10);
|
|
223
|
+
i0.ɵɵtext(11, "Active");
|
|
224
|
+
i0.ɵɵelementEnd();
|
|
225
|
+
i0.ɵɵelementStart(12, "option", 11);
|
|
226
|
+
i0.ɵɵtext(13, "Idle");
|
|
227
|
+
i0.ɵɵelementEnd();
|
|
228
|
+
i0.ɵɵelementStart(14, "option", 12);
|
|
229
|
+
i0.ɵɵtext(15, "Closed");
|
|
230
|
+
i0.ɵɵelementEnd()();
|
|
231
|
+
i0.ɵɵelementStart(16, "select", 8);
|
|
232
|
+
i0.ɵɵlistener("change", function AnalyticsRealtimeSessionsComponent_Conditional_1_Template_select_change_16_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnTargetFilterChanged($event)); });
|
|
233
|
+
i0.ɵɵelementStart(17, "option", 9);
|
|
234
|
+
i0.ɵɵtext(18, "Target: All");
|
|
235
|
+
i0.ɵɵelementEnd();
|
|
236
|
+
i0.ɵɵrepeaterCreate(19, AnalyticsRealtimeSessionsComponent_Conditional_1_For_20_Template, 2, 2, "option", 13, _forTrack1);
|
|
237
|
+
i0.ɵɵelementEnd();
|
|
238
|
+
i0.ɵɵelementStart(21, "select", 8);
|
|
239
|
+
i0.ɵɵlistener("change", function AnalyticsRealtimeSessionsComponent_Conditional_1_Template_select_change_21_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnUserFilterChanged($event)); });
|
|
240
|
+
i0.ɵɵelementStart(22, "option", 9);
|
|
241
|
+
i0.ɵɵtext(23, "User: All");
|
|
242
|
+
i0.ɵɵelementEnd();
|
|
243
|
+
i0.ɵɵrepeaterCreate(24, AnalyticsRealtimeSessionsComponent_Conditional_1_For_25_Template, 2, 2, "option", 13, _forTrack1);
|
|
244
|
+
i0.ɵɵelementEnd();
|
|
245
|
+
i0.ɵɵelementStart(26, "select", 8);
|
|
246
|
+
i0.ɵɵlistener("change", function AnalyticsRealtimeSessionsComponent_Conditional_1_Template_select_change_26_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnHostFilterChanged($event)); });
|
|
247
|
+
i0.ɵɵelementStart(27, "option", 9);
|
|
248
|
+
i0.ɵɵtext(28, "Host: All");
|
|
249
|
+
i0.ɵɵelementEnd();
|
|
250
|
+
i0.ɵɵrepeaterCreate(29, AnalyticsRealtimeSessionsComponent_Conditional_1_For_30_Template, 2, 2, "option", 13, _forTrack1);
|
|
251
|
+
i0.ɵɵelementEnd();
|
|
252
|
+
i0.ɵɵelementStart(31, "span", 14);
|
|
253
|
+
i0.ɵɵtext(32);
|
|
254
|
+
i0.ɵɵelementEnd();
|
|
255
|
+
i0.ɵɵelementStart(33, "button", 15);
|
|
256
|
+
i0.ɵɵlistener("click", function AnalyticsRealtimeSessionsComponent_Conditional_1_Template_button_click_33_listener() { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.LoadData()); });
|
|
257
|
+
i0.ɵɵelement(34, "i", 16);
|
|
258
|
+
i0.ɵɵelementEnd()();
|
|
259
|
+
i0.ɵɵelementStart(35, "div", 17)(36, "div", 18)(37, "table", 19)(38, "thead")(39, "tr")(40, "th");
|
|
260
|
+
i0.ɵɵtext(41, "Agent / Target");
|
|
261
|
+
i0.ɵɵelementEnd();
|
|
262
|
+
i0.ɵɵelementStart(42, "th");
|
|
263
|
+
i0.ɵɵtext(43, "User");
|
|
264
|
+
i0.ɵɵelementEnd();
|
|
265
|
+
i0.ɵɵelementStart(44, "th");
|
|
266
|
+
i0.ɵɵtext(45, "Status");
|
|
267
|
+
i0.ɵɵelementEnd();
|
|
268
|
+
i0.ɵɵelementStart(46, "th");
|
|
269
|
+
i0.ɵɵtext(47, "Channels");
|
|
270
|
+
i0.ɵɵelementEnd();
|
|
271
|
+
i0.ɵɵelementStart(48, "th", 20);
|
|
272
|
+
i0.ɵɵtext(49, "Runs");
|
|
273
|
+
i0.ɵɵelementEnd();
|
|
274
|
+
i0.ɵɵelementStart(50, "th", 20);
|
|
275
|
+
i0.ɵɵtext(51, "Tokens");
|
|
276
|
+
i0.ɵɵelementEnd();
|
|
277
|
+
i0.ɵɵelementStart(52, "th", 20);
|
|
278
|
+
i0.ɵɵtext(53, "Cost");
|
|
279
|
+
i0.ɵɵelementEnd();
|
|
280
|
+
i0.ɵɵelementStart(54, "th");
|
|
281
|
+
i0.ɵɵtext(55, "Started");
|
|
282
|
+
i0.ɵɵelementEnd();
|
|
283
|
+
i0.ɵɵelementStart(56, "th", 20);
|
|
284
|
+
i0.ɵɵtext(57, "Duration");
|
|
285
|
+
i0.ɵɵelementEnd();
|
|
286
|
+
i0.ɵɵelementStart(58, "th");
|
|
287
|
+
i0.ɵɵtext(59, "Host instance");
|
|
288
|
+
i0.ɵɵelementEnd();
|
|
289
|
+
i0.ɵɵelement(60, "th");
|
|
290
|
+
i0.ɵɵelementEnd()();
|
|
291
|
+
i0.ɵɵelementStart(61, "tbody");
|
|
292
|
+
i0.ɵɵconditionalCreate(62, AnalyticsRealtimeSessionsComponent_Conditional_1_Conditional_62_Template, 3, 0, "tr");
|
|
293
|
+
i0.ɵɵrepeaterCreate(63, AnalyticsRealtimeSessionsComponent_Conditional_1_For_64_Template, 35, 17, "tr", 21, _forTrack2);
|
|
294
|
+
i0.ɵɵelementEnd()()()();
|
|
295
|
+
i0.ɵɵelementStart(65, "div", 22)(66, "span", 23);
|
|
296
|
+
i0.ɵɵtext(67);
|
|
297
|
+
i0.ɵɵelementEnd();
|
|
298
|
+
i0.ɵɵconditionalCreate(68, AnalyticsRealtimeSessionsComponent_Conditional_1_Conditional_68_Template, 7, 4, "div", 24);
|
|
299
|
+
i0.ɵɵelementEnd();
|
|
300
|
+
} if (rf & 2) {
|
|
301
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
302
|
+
i0.ɵɵadvance();
|
|
303
|
+
i0.ɵɵrepeater(ctx_r2.KPICards);
|
|
304
|
+
i0.ɵɵadvance(5);
|
|
305
|
+
i0.ɵɵproperty("value", ctx_r2.SearchTerm);
|
|
306
|
+
i0.ɵɵadvance();
|
|
307
|
+
i0.ɵɵproperty("value", ctx_r2.StatusFilter);
|
|
308
|
+
i0.ɵɵadvance(9);
|
|
309
|
+
i0.ɵɵproperty("value", ctx_r2.TargetFilter);
|
|
310
|
+
i0.ɵɵadvance(3);
|
|
311
|
+
i0.ɵɵrepeater(ctx_r2.TargetOptions);
|
|
312
|
+
i0.ɵɵadvance(2);
|
|
313
|
+
i0.ɵɵproperty("value", ctx_r2.UserFilter);
|
|
314
|
+
i0.ɵɵadvance(3);
|
|
315
|
+
i0.ɵɵrepeater(ctx_r2.UserOptions);
|
|
316
|
+
i0.ɵɵadvance(2);
|
|
317
|
+
i0.ɵɵproperty("value", ctx_r2.HostFilter);
|
|
318
|
+
i0.ɵɵadvance(3);
|
|
319
|
+
i0.ɵɵrepeater(ctx_r2.HostOptions);
|
|
320
|
+
i0.ɵɵadvance(3);
|
|
321
|
+
i0.ɵɵtextInterpolate2("", ctx_r2.FilteredRows.length, " results \u00B7 ", ctx_r2.LiveCount, " live");
|
|
322
|
+
i0.ɵɵadvance(30);
|
|
323
|
+
i0.ɵɵconditional(ctx_r2.PagedRows.length === 0 ? 62 : -1);
|
|
324
|
+
i0.ɵɵadvance();
|
|
325
|
+
i0.ɵɵrepeater(ctx_r2.PagedRows);
|
|
326
|
+
i0.ɵɵadvance(4);
|
|
327
|
+
i0.ɵɵtextInterpolate5(" Showing ", ctx_r2.PagedRows.length, " of ", ctx_r2.FilteredRows.length, " \u00B7 ", ctx_r2.LiveCount, " live \u00B7 ", ctx_r2.IdleCount, " idle \u00B7 ", ctx_r2.ClosedCount, " closed ");
|
|
328
|
+
i0.ɵɵadvance();
|
|
329
|
+
i0.ɵɵconditional(ctx_r2.PageCount > 1 ? 68 : -1);
|
|
330
|
+
} }
|
|
331
|
+
const PAGE_SIZE = 25;
|
|
332
|
+
export class AnalyticsRealtimeSessionsComponent extends BaseAngularComponent {
|
|
333
|
+
_timeRange = '7d';
|
|
334
|
+
set TimeRange(value) {
|
|
335
|
+
const prev = this._timeRange;
|
|
336
|
+
this._timeRange = value;
|
|
337
|
+
if (prev !== value && this.initialized)
|
|
338
|
+
this.LoadData();
|
|
339
|
+
}
|
|
340
|
+
get TimeRange() { return this._timeRange; }
|
|
341
|
+
initialized = false;
|
|
342
|
+
cdr = inject(ChangeDetectorRef);
|
|
343
|
+
dataset = null;
|
|
344
|
+
allRows = [];
|
|
345
|
+
IsLoading = false;
|
|
346
|
+
KPICards = [];
|
|
347
|
+
FilteredRows = [];
|
|
348
|
+
PagedRows = [];
|
|
349
|
+
TargetOptions = [];
|
|
350
|
+
UserOptions = [];
|
|
351
|
+
HostOptions = [];
|
|
352
|
+
SearchTerm = '';
|
|
353
|
+
StatusFilter = '';
|
|
354
|
+
TargetFilter = '';
|
|
355
|
+
UserFilter = '';
|
|
356
|
+
HostFilter = '';
|
|
357
|
+
PageIndex = 0;
|
|
358
|
+
get LiveCount() {
|
|
359
|
+
return this.FilteredRows.filter(r => r.Status === 'Active').length;
|
|
360
|
+
}
|
|
361
|
+
get IdleCount() {
|
|
362
|
+
return this.FilteredRows.filter(r => r.Status === 'Idle').length;
|
|
363
|
+
}
|
|
364
|
+
get ClosedCount() {
|
|
365
|
+
return this.FilteredRows.filter(r => r.Status === 'Closed').length;
|
|
366
|
+
}
|
|
367
|
+
get PageCount() {
|
|
368
|
+
return Math.max(1, Math.ceil(this.FilteredRows.length / PAGE_SIZE));
|
|
369
|
+
}
|
|
370
|
+
ngOnInit() {
|
|
371
|
+
this.initialized = true;
|
|
372
|
+
this.LoadData();
|
|
373
|
+
}
|
|
374
|
+
// ── Data loading ──
|
|
375
|
+
/** Reloads everything for the current time range. */
|
|
376
|
+
async LoadData() {
|
|
377
|
+
this.IsLoading = true;
|
|
378
|
+
this.cdr.detectChanges();
|
|
379
|
+
try {
|
|
380
|
+
this.dataset = await LoadRealtimeSessionsDataset(this.ProviderToUse, this.TimeRange);
|
|
381
|
+
this.buildRows();
|
|
382
|
+
this.buildKPICards();
|
|
383
|
+
this.buildFilterOptions();
|
|
384
|
+
this.applyFilters();
|
|
385
|
+
}
|
|
386
|
+
catch (e) {
|
|
387
|
+
console.error('Realtime sessions load error:', e);
|
|
388
|
+
}
|
|
389
|
+
finally {
|
|
390
|
+
this.IsLoading = false;
|
|
391
|
+
this.cdr.detectChanges();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// ── Drill-in ──
|
|
395
|
+
/** Opens the AIAgentSession record via the shared Explorer record-open path. */
|
|
396
|
+
OpenSession(sessionId) {
|
|
397
|
+
const key = new CompositeKey();
|
|
398
|
+
key.LoadFromSingleKeyValuePair('ID', sessionId);
|
|
399
|
+
SharedService.Instance.OpenEntityRecord('MJ: AI Agent Sessions', key);
|
|
400
|
+
}
|
|
401
|
+
// ── Filter handlers ──
|
|
402
|
+
OnSearchChanged(event) {
|
|
403
|
+
this.SearchTerm = event.target.value;
|
|
404
|
+
this.applyFilters();
|
|
405
|
+
}
|
|
406
|
+
OnStatusFilterChanged(event) {
|
|
407
|
+
this.StatusFilter = event.target.value;
|
|
408
|
+
this.applyFilters();
|
|
409
|
+
}
|
|
410
|
+
OnTargetFilterChanged(event) {
|
|
411
|
+
this.TargetFilter = event.target.value;
|
|
412
|
+
this.applyFilters();
|
|
413
|
+
}
|
|
414
|
+
OnUserFilterChanged(event) {
|
|
415
|
+
this.UserFilter = event.target.value;
|
|
416
|
+
this.applyFilters();
|
|
417
|
+
}
|
|
418
|
+
OnHostFilterChanged(event) {
|
|
419
|
+
this.HostFilter = event.target.value;
|
|
420
|
+
this.applyFilters();
|
|
421
|
+
}
|
|
422
|
+
PrevPage() {
|
|
423
|
+
if (this.PageIndex > 0) {
|
|
424
|
+
this.PageIndex--;
|
|
425
|
+
this.applyPaging();
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
NextPage() {
|
|
429
|
+
if (this.PageIndex < this.PageCount - 1) {
|
|
430
|
+
this.PageIndex++;
|
|
431
|
+
this.applyPaging();
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// ── Builders ──
|
|
435
|
+
buildRows() {
|
|
436
|
+
const sessions = this.dataset?.Sessions ?? [];
|
|
437
|
+
this.allRows = [...sessions]
|
|
438
|
+
.sort((a, b) => b.StartedAt.getTime() - a.StartedAt.getTime())
|
|
439
|
+
.map(s => this.toGridRow(s));
|
|
440
|
+
}
|
|
441
|
+
toGridRow(s) {
|
|
442
|
+
const target = s.TargetAgentName ?? (s.TargetAgentID ? 'Unknown agent' : '—');
|
|
443
|
+
const host = s.Record.HostInstanceID ?? '—';
|
|
444
|
+
const user = s.Record.User;
|
|
445
|
+
const agent = s.Record.Agent ?? 'Unknown';
|
|
446
|
+
const statusDisplay = BuildSessionStatusDisplay(s.Record.Status, s.CloseReason);
|
|
447
|
+
return {
|
|
448
|
+
ID: s.Record.ID,
|
|
449
|
+
Agent: agent,
|
|
450
|
+
Target: target,
|
|
451
|
+
User: user,
|
|
452
|
+
Status: s.Record.Status,
|
|
453
|
+
StatusLabel: statusDisplay.Label,
|
|
454
|
+
StatusClass: 'status-pill status-' + s.Record.Status.toLowerCase(),
|
|
455
|
+
StatusTitle: statusDisplay.Title,
|
|
456
|
+
StatusIcon: statusDisplay.Icon,
|
|
457
|
+
IsResumed: s.IsResumed,
|
|
458
|
+
ChannelIcons: s.ChannelNames.map(name => ({ Icon: ChannelIconClass(name), Name: name })),
|
|
459
|
+
ChannelCount: s.ChannelNames.length,
|
|
460
|
+
Runs: s.DelegatedRunCount,
|
|
461
|
+
Tokens: FormatTokenCount(s.TotalTokens),
|
|
462
|
+
Cost: FormatSessionCost(s.TotalCost),
|
|
463
|
+
Started: FormatSessionStart(s.StartedAt),
|
|
464
|
+
StartedAt: s.StartedAt,
|
|
465
|
+
Duration: FormatSessionDuration(s.DurationMs),
|
|
466
|
+
Host: host,
|
|
467
|
+
SearchText: [agent, target, user, host, s.Record.ID, s.Record.ConversationID ?? '']
|
|
468
|
+
.join(' ').toLowerCase()
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
buildKPICards() {
|
|
472
|
+
const sessions = this.dataset?.Sessions ?? [];
|
|
473
|
+
const all = this.dataset?.AllSessions ?? [];
|
|
474
|
+
const activeCount = sessions.filter(s => s.Record.Status === 'Active').length;
|
|
475
|
+
const idleCount = sessions.filter(s => s.Record.Status === 'Idle').length;
|
|
476
|
+
const now = new Date();
|
|
477
|
+
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
478
|
+
const startOfYesterday = new Date(startOfToday.getTime() - 86_400_000);
|
|
479
|
+
const todaySessions = all.filter(s => s.StartedAt >= startOfToday);
|
|
480
|
+
const yesterdaySessions = all.filter(s => s.StartedAt >= startOfYesterday && s.StartedAt < startOfToday);
|
|
481
|
+
const todayCost = todaySessions.reduce((a, s) => a + s.TotalCost, 0);
|
|
482
|
+
const delegatedTotal = sessions.reduce((a, s) => a + s.DelegatedRunCount, 0);
|
|
483
|
+
const trendPct = yesterdaySessions.length > 0
|
|
484
|
+
? Math.round(((todaySessions.length - yesterdaySessions.length) / yesterdaySessions.length) * 100)
|
|
485
|
+
: 0;
|
|
486
|
+
this.KPICards = [
|
|
487
|
+
{
|
|
488
|
+
title: 'Active now',
|
|
489
|
+
value: activeCount,
|
|
490
|
+
subtitle: 'live duplex sessions',
|
|
491
|
+
icon: 'fa-tower-broadcast',
|
|
492
|
+
color: 'success'
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
title: 'Idle (holding)',
|
|
496
|
+
value: idleCount,
|
|
497
|
+
subtitle: 'past idle threshold',
|
|
498
|
+
icon: 'fa-pause',
|
|
499
|
+
color: 'warning'
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
title: 'Sessions today',
|
|
503
|
+
value: todaySessions.length,
|
|
504
|
+
icon: 'fa-clock',
|
|
505
|
+
color: 'primary',
|
|
506
|
+
trend: yesterdaySessions.length > 0 ? {
|
|
507
|
+
direction: trendPct > 0 ? 'up' : trendPct < 0 ? 'down' : 'stable',
|
|
508
|
+
percentage: Math.abs(trendPct),
|
|
509
|
+
period: 'vs yesterday'
|
|
510
|
+
} : undefined,
|
|
511
|
+
subtitle: yesterdaySessions.length > 0 ? undefined : 'no sessions yesterday'
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
title: `Delegated runs (${this.TimeRange})`,
|
|
515
|
+
value: delegatedTotal,
|
|
516
|
+
subtitle: 'agent runs via AgentSessionID',
|
|
517
|
+
icon: 'fa-diagram-project',
|
|
518
|
+
color: 'info'
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
title: 'Cost today',
|
|
522
|
+
value: FormatSessionCost(todayCost),
|
|
523
|
+
subtitle: 'co-agent + delegated',
|
|
524
|
+
icon: 'fa-coins',
|
|
525
|
+
color: 'danger'
|
|
526
|
+
}
|
|
527
|
+
];
|
|
528
|
+
}
|
|
529
|
+
buildFilterOptions() {
|
|
530
|
+
const targets = new Map();
|
|
531
|
+
const users = new Map();
|
|
532
|
+
const hosts = new Set();
|
|
533
|
+
for (const row of this.allRows) {
|
|
534
|
+
if (row.Target && row.Target !== '—')
|
|
535
|
+
targets.set(row.Target, row.Target);
|
|
536
|
+
if (row.User)
|
|
537
|
+
users.set(row.User, row.User);
|
|
538
|
+
if (row.Host && row.Host !== '—')
|
|
539
|
+
hosts.add(row.Host);
|
|
540
|
+
}
|
|
541
|
+
const toOptions = (values) => Array.from(values).sort((a, b) => a.localeCompare(b)).map(v => ({ Value: v, Label: v }));
|
|
542
|
+
this.TargetOptions = toOptions(targets.keys());
|
|
543
|
+
this.UserOptions = toOptions(users.keys());
|
|
544
|
+
this.HostOptions = toOptions(hosts);
|
|
545
|
+
}
|
|
546
|
+
applyFilters() {
|
|
547
|
+
const search = this.SearchTerm.trim().toLowerCase();
|
|
548
|
+
this.FilteredRows = this.allRows.filter(row => {
|
|
549
|
+
if (this.StatusFilter && row.Status !== this.StatusFilter)
|
|
550
|
+
return false;
|
|
551
|
+
if (this.TargetFilter && row.Target !== this.TargetFilter)
|
|
552
|
+
return false;
|
|
553
|
+
if (this.UserFilter && row.User !== this.UserFilter)
|
|
554
|
+
return false;
|
|
555
|
+
if (this.HostFilter && row.Host !== this.HostFilter)
|
|
556
|
+
return false;
|
|
557
|
+
if (search && !row.SearchText.includes(search))
|
|
558
|
+
return false;
|
|
559
|
+
return true;
|
|
560
|
+
});
|
|
561
|
+
this.PageIndex = 0;
|
|
562
|
+
this.applyPaging();
|
|
563
|
+
}
|
|
564
|
+
applyPaging() {
|
|
565
|
+
const start = this.PageIndex * PAGE_SIZE;
|
|
566
|
+
this.PagedRows = this.FilteredRows.slice(start, start + PAGE_SIZE);
|
|
567
|
+
this.cdr.detectChanges();
|
|
568
|
+
}
|
|
569
|
+
static ɵfac = /*@__PURE__*/ (() => { let ɵAnalyticsRealtimeSessionsComponent_BaseFactory; return function AnalyticsRealtimeSessionsComponent_Factory(__ngFactoryType__) { return (ɵAnalyticsRealtimeSessionsComponent_BaseFactory || (ɵAnalyticsRealtimeSessionsComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AnalyticsRealtimeSessionsComponent)))(__ngFactoryType__ || AnalyticsRealtimeSessionsComponent); }; })();
|
|
570
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AnalyticsRealtimeSessionsComponent, selectors: [["app-analytics-realtime-sessions"]], inputs: { TimeRange: "TimeRange" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "loading-container"], ["text", "Loading agent sessions..."], [1, "kpi-grid"], [3, "data"], [1, "filterbar"], [1, "search-input"], [1, "fa-solid", "fa-magnifying-glass"], ["type", "text", "placeholder", "Search sessions, users, hosts\u2026", 3, "input", "value"], [1, "filter-select", 3, "change", "value"], ["value", ""], ["value", "Active"], ["value", "Idle"], ["value", "Closed"], [3, "value"], [1, "result-pill"], ["mjButton", "", "variant", "secondary", "size", "sm", "title", "Refresh", 3, "click"], [1, "fa-solid", "fa-rotate"], [1, "panel"], [1, "table-wrapper"], [1, "data-table"], [1, "th-numeric"], [1, "session-row"], [1, "grid-footer"], [1, "grid-summary"], [1, "pager"], ["colspan", "11", 1, "empty-row"], [1, "session-row", 3, "click"], [1, "cell-strong"], [1, "cell-sub"], [1, "fa-solid", "fa-arrow-right-long"], ["title", "Resumed from a prior session", 1, "resumed-pill"], [1, "cell-user"], [1, "status-pill", 3, "title"], [1, "dot", "dot--live"], [3, "class"], [1, "chan-icons"], [3, "class", "title"], [1, "chan-count"], [1, "cell-numeric"], [1, "cell-numeric", "mono"], [1, "cell-time"], [1, "cell-host", "mono", 3, "title"], [1, "cell-action"], ["mjButton", "", "variant", "icon", "size", "sm", "title", "Open session record", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "fa-solid", "fa-link"], [3, "title"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-left"], [1, "pager-label"], [1, "fa-solid", "fa-chevron-right"]], template: function AnalyticsRealtimeSessionsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
571
|
+
i0.ɵɵconditionalCreate(0, AnalyticsRealtimeSessionsComponent_Conditional_0_Template, 2, 0, "div", 0)(1, AnalyticsRealtimeSessionsComponent_Conditional_1_Template, 69, 14);
|
|
572
|
+
} if (rf & 2) {
|
|
573
|
+
i0.ɵɵconditional(ctx.IsLoading ? 0 : 1);
|
|
574
|
+
} }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i2.LoadingComponent, i3.KPICardComponent, i4.MJButtonDirective], styles: ["[_nghost-%COMP%] { display: block; }\n\n .loading-container[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n }\n\n \n\n .kpi-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 12px;\n margin-bottom: 16px;\n }\n\n \n\n .filterbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 10px 14px;\n margin-bottom: 16px;\n }\n\n .search-input[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 6px 10px;\n min-width: 240px;\n flex: 1;\n max-width: 360px;\n }\n\n .search-input[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n }\n\n .search-input[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n border: none;\n outline: none;\n background: transparent;\n color: var(--mj-text-primary);\n font-size: 13px;\n width: 100%;\n }\n\n .search-input[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--mj-text-disabled); }\n\n .filter-select[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 12.5px;\n padding: 6px 8px;\n max-width: 200px;\n }\n\n .result-pill[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 12px;\n padding: 4px 12px;\n white-space: nowrap;\n }\n\n \n\n .panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n }\n\n .table-wrapper[_ngcontent-%COMP%] { overflow-x: auto; }\n\n .data-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n }\n\n .data-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .data-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 14px;\n text-align: left;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .data-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n background: var(--mj-bg-surface-card);\n white-space: nowrap;\n }\n\n .th-numeric[_ngcontent-%COMP%] { text-align: right; }\n\n .session-row[_ngcontent-%COMP%] { cursor: pointer; transition: background 0.15s; }\n .session-row[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n\n .cell-strong[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n }\n\n .cell-sub[_ngcontent-%COMP%] {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 6px;\n white-space: nowrap;\n }\n\n .cell-user[_ngcontent-%COMP%] {\n max-width: 200px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--mj-text-secondary);\n }\n\n .cell-numeric[_ngcontent-%COMP%] {\n text-align: right;\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-secondary);\n }\n\n .cell-time[_ngcontent-%COMP%] {\n white-space: nowrap;\n color: var(--mj-text-muted);\n font-size: 12px;\n }\n\n .cell-host[_ngcontent-%COMP%] {\n max-width: 160px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--mj-text-muted);\n }\n\n .cell-action[_ngcontent-%COMP%] { text-align: right; white-space: nowrap; }\n\n .mono[_ngcontent-%COMP%] {\n font-family: var(--mj-font-mono, monospace);\n font-size: 12px;\n }\n\n .empty-row[_ngcontent-%COMP%] {\n text-align: center;\n color: var(--mj-text-disabled);\n padding: 24px;\n }\n\n \n\n .status-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.3px;\n white-space: nowrap;\n }\n\n .status-active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n\n .status-idle[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n }\n\n .status-closed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-text-disabled) 12%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n }\n\n .dot--live[_ngcontent-%COMP%] {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--mj-status-success);\n animation: _ngcontent-%COMP%_pulse-live 1.6s ease-in-out infinite;\n }\n\n @keyframes _ngcontent-%COMP%_pulse-live {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.35; }\n }\n\n .resumed-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n .chan-icons[_ngcontent-%COMP%] {\n display: inline-flex;\n gap: 8px;\n color: var(--mj-text-secondary);\n font-size: 13px;\n }\n\n .chan-count[_ngcontent-%COMP%] {\n margin-left: 6px;\n font-size: 11px;\n color: var(--mj-text-muted);\n }\n\n \n\n .grid-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 14px;\n flex-wrap: wrap;\n }\n\n .grid-summary[_ngcontent-%COMP%] {\n font-size: 12.5px;\n color: var(--mj-text-muted);\n }\n\n .pager[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .pager-label[_ngcontent-%COMP%] {\n font-size: 12.5px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n }"] });
|
|
575
|
+
}
|
|
576
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AnalyticsRealtimeSessionsComponent, [{
|
|
577
|
+
type: Component,
|
|
578
|
+
args: [{ standalone: false, selector: 'app-analytics-realtime-sessions', template: `
|
|
579
|
+
@if (IsLoading) {
|
|
580
|
+
<div class="loading-container">
|
|
581
|
+
<mj-loading text="Loading agent sessions..."></mj-loading>
|
|
582
|
+
</div>
|
|
583
|
+
} @else {
|
|
584
|
+
<!-- KPI strip -->
|
|
585
|
+
<div class="kpi-grid">
|
|
586
|
+
@for (kpi of KPICards; track kpi.title) {
|
|
587
|
+
<app-kpi-card [data]="kpi"></app-kpi-card>
|
|
588
|
+
}
|
|
589
|
+
</div>
|
|
590
|
+
|
|
591
|
+
<!-- Filter bar: search · status · target agent · user · host -->
|
|
592
|
+
<div class="filterbar">
|
|
593
|
+
<div class="search-input">
|
|
594
|
+
<i class="fa-solid fa-magnifying-glass"></i>
|
|
595
|
+
<input type="text"
|
|
596
|
+
placeholder="Search sessions, users, hosts…"
|
|
597
|
+
[value]="SearchTerm"
|
|
598
|
+
(input)="OnSearchChanged($event)" />
|
|
599
|
+
</div>
|
|
600
|
+
<select class="filter-select" [value]="StatusFilter" (change)="OnStatusFilterChanged($event)">
|
|
601
|
+
<option value="">Status: All</option>
|
|
602
|
+
<option value="Active">Active</option>
|
|
603
|
+
<option value="Idle">Idle</option>
|
|
604
|
+
<option value="Closed">Closed</option>
|
|
605
|
+
</select>
|
|
606
|
+
<select class="filter-select" [value]="TargetFilter" (change)="OnTargetFilterChanged($event)">
|
|
607
|
+
<option value="">Target: All</option>
|
|
608
|
+
@for (opt of TargetOptions; track opt.Value) {
|
|
609
|
+
<option [value]="opt.Value">{{ opt.Label }}</option>
|
|
610
|
+
}
|
|
611
|
+
</select>
|
|
612
|
+
<select class="filter-select" [value]="UserFilter" (change)="OnUserFilterChanged($event)">
|
|
613
|
+
<option value="">User: All</option>
|
|
614
|
+
@for (opt of UserOptions; track opt.Value) {
|
|
615
|
+
<option [value]="opt.Value">{{ opt.Label }}</option>
|
|
616
|
+
}
|
|
617
|
+
</select>
|
|
618
|
+
<select class="filter-select" [value]="HostFilter" (change)="OnHostFilterChanged($event)">
|
|
619
|
+
<option value="">Host: All</option>
|
|
620
|
+
@for (opt of HostOptions; track opt.Value) {
|
|
621
|
+
<option [value]="opt.Value">{{ opt.Label }}</option>
|
|
622
|
+
}
|
|
623
|
+
</select>
|
|
624
|
+
<span class="result-pill">{{ FilteredRows.length }} results · {{ LiveCount }} live</span>
|
|
625
|
+
<button mjButton variant="secondary" size="sm" title="Refresh" (click)="LoadData()">
|
|
626
|
+
<i class="fa-solid fa-rotate"></i>
|
|
627
|
+
</button>
|
|
628
|
+
</div>
|
|
629
|
+
|
|
630
|
+
<!-- Sessions grid -->
|
|
631
|
+
<div class="panel">
|
|
632
|
+
<div class="table-wrapper">
|
|
633
|
+
<table class="data-table">
|
|
634
|
+
<thead>
|
|
635
|
+
<tr>
|
|
636
|
+
<th>Agent / Target</th>
|
|
637
|
+
<th>User</th>
|
|
638
|
+
<th>Status</th>
|
|
639
|
+
<th>Channels</th>
|
|
640
|
+
<th class="th-numeric">Runs</th>
|
|
641
|
+
<th class="th-numeric">Tokens</th>
|
|
642
|
+
<th class="th-numeric">Cost</th>
|
|
643
|
+
<th>Started</th>
|
|
644
|
+
<th class="th-numeric">Duration</th>
|
|
645
|
+
<th>Host instance</th>
|
|
646
|
+
<th></th>
|
|
647
|
+
</tr>
|
|
648
|
+
</thead>
|
|
649
|
+
<tbody>
|
|
650
|
+
@if (PagedRows.length === 0) {
|
|
651
|
+
<tr><td colspan="11" class="empty-row">No sessions match the current filters</td></tr>
|
|
652
|
+
}
|
|
653
|
+
@for (row of PagedRows; track row.ID) {
|
|
654
|
+
<tr class="session-row" (click)="OpenSession(row.ID)">
|
|
655
|
+
<td>
|
|
656
|
+
<div class="cell-strong">{{ row.Agent }}</div>
|
|
657
|
+
<div class="cell-sub">
|
|
658
|
+
<i class="fa-solid fa-arrow-right-long"></i> {{ row.Target }}
|
|
659
|
+
@if (row.IsResumed) {
|
|
660
|
+
<span class="resumed-pill" title="Resumed from a prior session">
|
|
661
|
+
<i class="fa-solid fa-link"></i> resumed
|
|
662
|
+
</span>
|
|
663
|
+
}
|
|
664
|
+
</div>
|
|
665
|
+
</td>
|
|
666
|
+
<td class="cell-user">{{ row.User }}</td>
|
|
667
|
+
<td>
|
|
668
|
+
<span class="status-pill" [class]="row.StatusClass" [title]="row.StatusTitle">
|
|
669
|
+
@if (row.Status === 'Active') { <span class="dot dot--live"></span> }
|
|
670
|
+
@else if (row.StatusIcon) { <i [class]="row.StatusIcon"></i> }
|
|
671
|
+
{{ row.StatusLabel }}
|
|
672
|
+
</span>
|
|
673
|
+
</td>
|
|
674
|
+
<td>
|
|
675
|
+
<span class="chan-icons">
|
|
676
|
+
@for (chan of row.ChannelIcons; track chan.Name) {
|
|
677
|
+
<i [class]="chan.Icon" [title]="chan.Name"></i>
|
|
678
|
+
}
|
|
679
|
+
</span>
|
|
680
|
+
@if (row.ChannelCount > 0) {
|
|
681
|
+
<span class="chan-count">{{ row.ChannelCount }}</span>
|
|
682
|
+
}
|
|
683
|
+
</td>
|
|
684
|
+
<td class="cell-numeric">{{ row.Runs }}</td>
|
|
685
|
+
<td class="cell-numeric mono">{{ row.Tokens }}</td>
|
|
686
|
+
<td class="cell-numeric mono">{{ row.Cost }}</td>
|
|
687
|
+
<td class="cell-time">{{ row.Started }}</td>
|
|
688
|
+
<td class="cell-numeric mono">{{ row.Duration }}</td>
|
|
689
|
+
<td class="cell-host mono" [title]="row.Host">{{ row.Host }}</td>
|
|
690
|
+
<td class="cell-action">
|
|
691
|
+
<button mjButton variant="icon" size="sm" title="Open session record"
|
|
692
|
+
(click)="OpenSession(row.ID); $event.stopPropagation()">
|
|
693
|
+
<i class="fa-solid fa-arrow-up-right-from-square"></i>
|
|
694
|
+
</button>
|
|
695
|
+
</td>
|
|
696
|
+
</tr>
|
|
697
|
+
}
|
|
698
|
+
</tbody>
|
|
699
|
+
</table>
|
|
700
|
+
</div>
|
|
701
|
+
</div>
|
|
702
|
+
|
|
703
|
+
<!-- Pagination / summary -->
|
|
704
|
+
<div class="grid-footer">
|
|
705
|
+
<span class="grid-summary">
|
|
706
|
+
Showing {{ PagedRows.length }} of {{ FilteredRows.length }}
|
|
707
|
+
· {{ LiveCount }} live · {{ IdleCount }} idle · {{ ClosedCount }} closed
|
|
708
|
+
</span>
|
|
709
|
+
@if (PageCount > 1) {
|
|
710
|
+
<div class="pager">
|
|
711
|
+
<button mjButton variant="secondary" size="sm" [disabled]="PageIndex === 0" (click)="PrevPage()">
|
|
712
|
+
<i class="fa-solid fa-chevron-left"></i>
|
|
713
|
+
</button>
|
|
714
|
+
<span class="pager-label">Page {{ PageIndex + 1 }} of {{ PageCount }}</span>
|
|
715
|
+
<button mjButton variant="secondary" size="sm" [disabled]="PageIndex >= PageCount - 1" (click)="NextPage()">
|
|
716
|
+
<i class="fa-solid fa-chevron-right"></i>
|
|
717
|
+
</button>
|
|
718
|
+
</div>
|
|
719
|
+
}
|
|
720
|
+
</div>
|
|
721
|
+
}
|
|
722
|
+
`, styles: ["\n :host { display: block; }\n\n .loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n }\n\n /* \u2500\u2500 KPI Grid \u2500\u2500 */\n .kpi-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 12px;\n margin-bottom: 16px;\n }\n\n /* \u2500\u2500 Filter bar \u2500\u2500 */\n .filterbar {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 10px 14px;\n margin-bottom: 16px;\n }\n\n .search-input {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 6px 10px;\n min-width: 240px;\n flex: 1;\n max-width: 360px;\n }\n\n .search-input i {\n color: var(--mj-text-muted);\n font-size: 12px;\n }\n\n .search-input input {\n border: none;\n outline: none;\n background: transparent;\n color: var(--mj-text-primary);\n font-size: 13px;\n width: 100%;\n }\n\n .search-input input::placeholder { color: var(--mj-text-disabled); }\n\n .filter-select {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 12.5px;\n padding: 6px 8px;\n max-width: 200px;\n }\n\n .result-pill {\n margin-left: auto;\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 12px;\n padding: 4px 12px;\n white-space: nowrap;\n }\n\n /* \u2500\u2500 Panel + table (matches sibling analytics sections) \u2500\u2500 */\n .panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n }\n\n .table-wrapper { overflow-x: auto; }\n\n .data-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n }\n\n .data-table th,\n .data-table td {\n padding: 10px 14px;\n text-align: left;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .data-table th {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n background: var(--mj-bg-surface-card);\n white-space: nowrap;\n }\n\n .th-numeric { text-align: right; }\n\n .session-row { cursor: pointer; transition: background 0.15s; }\n .session-row:hover { background: var(--mj-bg-surface-hover); }\n\n .cell-strong {\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n }\n\n .cell-sub {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 6px;\n white-space: nowrap;\n }\n\n .cell-user {\n max-width: 200px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--mj-text-secondary);\n }\n\n .cell-numeric {\n text-align: right;\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-secondary);\n }\n\n .cell-time {\n white-space: nowrap;\n color: var(--mj-text-muted);\n font-size: 12px;\n }\n\n .cell-host {\n max-width: 160px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--mj-text-muted);\n }\n\n .cell-action { text-align: right; white-space: nowrap; }\n\n .mono {\n font-family: var(--mj-font-mono, monospace);\n font-size: 12px;\n }\n\n .empty-row {\n text-align: center;\n color: var(--mj-text-disabled);\n padding: 24px;\n }\n\n /* \u2500\u2500 Status pills \u2500\u2500 */\n .status-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.3px;\n white-space: nowrap;\n }\n\n .status-active {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n\n .status-idle {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n }\n\n .status-closed {\n background: color-mix(in srgb, var(--mj-text-disabled) 12%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n }\n\n .dot--live {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--mj-status-success);\n animation: pulse-live 1.6s ease-in-out infinite;\n }\n\n @keyframes pulse-live {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.35; }\n }\n\n .resumed-pill {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n .chan-icons {\n display: inline-flex;\n gap: 8px;\n color: var(--mj-text-secondary);\n font-size: 13px;\n }\n\n .chan-count {\n margin-left: 6px;\n font-size: 11px;\n color: var(--mj-text-muted);\n }\n\n /* \u2500\u2500 Footer / pager \u2500\u2500 */\n .grid-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 14px;\n flex-wrap: wrap;\n }\n\n .grid-summary {\n font-size: 12.5px;\n color: var(--mj-text-muted);\n }\n\n .pager {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .pager-label {\n font-size: 12.5px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n }\n "] }]
|
|
723
|
+
}], null, { TimeRange: [{
|
|
724
|
+
type: Input
|
|
725
|
+
}] }); })();
|
|
726
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AnalyticsRealtimeSessionsComponent, { className: "AnalyticsRealtimeSessionsComponent", filePath: "src/AI/components/analytics/realtime/realtime-sessions.component.ts", lineNumber: 477 }); })();
|
|
727
|
+
export function LoadAnalyticsRealtimeSessions() { }
|
|
728
|
+
//# sourceMappingURL=realtime-sessions.component.js.map
|