@memberjunction/ng-dashboards 3.2.0 → 3.3.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/APIKeys/api-applications-panel.component.d.ts +167 -0
- package/dist/APIKeys/api-applications-panel.component.d.ts.map +1 -0
- package/dist/APIKeys/api-applications-panel.component.js +1059 -0
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -0
- package/dist/APIKeys/api-key-create-dialog.component.d.ts +124 -0
- package/dist/APIKeys/api-key-create-dialog.component.d.ts.map +1 -0
- package/dist/APIKeys/api-key-create-dialog.component.js +743 -0
- package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -0
- package/dist/APIKeys/api-key-edit-panel.component.d.ts +149 -0
- package/dist/APIKeys/api-key-edit-panel.component.d.ts.map +1 -0
- package/dist/APIKeys/api-key-edit-panel.component.js +1061 -0
- package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -0
- package/dist/APIKeys/api-key-list.component.d.ts +130 -0
- package/dist/APIKeys/api-key-list.component.d.ts.map +1 -0
- package/dist/APIKeys/api-key-list.component.js +814 -0
- package/dist/APIKeys/api-key-list.component.js.map +1 -0
- package/dist/APIKeys/api-keys-resource.component.d.ts +209 -0
- package/dist/APIKeys/api-keys-resource.component.d.ts.map +1 -0
- package/dist/APIKeys/api-keys-resource.component.js +1165 -0
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -0
- package/dist/APIKeys/api-scopes-panel.component.d.ts +98 -0
- package/dist/APIKeys/api-scopes-panel.component.d.ts.map +1 -0
- package/dist/APIKeys/api-scopes-panel.component.js +652 -0
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -0
- package/dist/APIKeys/api-usage-panel.component.d.ts +174 -0
- package/dist/APIKeys/api-usage-panel.component.d.ts.map +1 -0
- package/dist/APIKeys/api-usage-panel.component.js +1013 -0
- package/dist/APIKeys/api-usage-panel.component.js.map +1 -0
- package/dist/APIKeys/index.d.ts +7 -0
- package/dist/APIKeys/index.d.ts.map +1 -0
- package/dist/APIKeys/index.js +8 -0
- package/dist/APIKeys/index.js.map +1 -0
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +4 -2
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +3 -3
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +22 -6
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +2 -2
- package/dist/module.d.ts +39 -32
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +44 -4
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +7 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +24 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +32 -32
|
@@ -0,0 +1,1013 @@
|
|
|
1
|
+
import { Component } from '@angular/core';
|
|
2
|
+
import { Metadata, RunView } from '@memberjunction/core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "@angular/common";
|
|
5
|
+
import * as i2 from "@progress/kendo-angular-dialog";
|
|
6
|
+
import * as i3 from "@progress/kendo-angular-buttons";
|
|
7
|
+
import * as i4 from "@memberjunction/ng-shared-generic";
|
|
8
|
+
function APIUsagePanelComponent_mj_loading_1_Template(rf, ctx) { if (rf & 1) {
|
|
9
|
+
i0.ɵɵelement(0, "mj-loading", 4);
|
|
10
|
+
} }
|
|
11
|
+
function APIUsagePanelComponent_ng_container_2_div_77_div_2_div_3_Template(rf, ctx) { if (rf & 1) {
|
|
12
|
+
i0.ɵɵelement(0, "div", 60);
|
|
13
|
+
} if (rf & 2) {
|
|
14
|
+
const bucket_r3 = i0.ɵɵnextContext().$implicit;
|
|
15
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
16
|
+
i0.ɵɵstyleProp("height", ctx_r1.getErrorBarHeight(bucket_r3), "%");
|
|
17
|
+
} }
|
|
18
|
+
function APIUsagePanelComponent_ng_container_2_div_77_div_2_Template(rf, ctx) { if (rf & 1) {
|
|
19
|
+
i0.ɵɵelementStart(0, "div", 55)(1, "div", 56)(2, "div", 57);
|
|
20
|
+
i0.ɵɵtemplate(3, APIUsagePanelComponent_ng_container_2_div_77_div_2_div_3_Template, 1, 2, "div", 58);
|
|
21
|
+
i0.ɵɵelementEnd()();
|
|
22
|
+
i0.ɵɵelementStart(4, "div", 59);
|
|
23
|
+
i0.ɵɵtext(5);
|
|
24
|
+
i0.ɵɵelementEnd()();
|
|
25
|
+
} if (rf & 2) {
|
|
26
|
+
const bucket_r3 = ctx.$implicit;
|
|
27
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
28
|
+
i0.ɵɵproperty("title", bucket_r3.requests + " requests, " + bucket_r3.errors + " errors");
|
|
29
|
+
i0.ɵɵadvance(2);
|
|
30
|
+
i0.ɵɵstyleProp("height", ctx_r1.getBarHeight(bucket_r3.requests), "%");
|
|
31
|
+
i0.ɵɵadvance();
|
|
32
|
+
i0.ɵɵproperty("ngIf", bucket_r3.errors > 0);
|
|
33
|
+
i0.ɵɵadvance(2);
|
|
34
|
+
i0.ɵɵtextInterpolate(bucket_r3.label);
|
|
35
|
+
} }
|
|
36
|
+
function APIUsagePanelComponent_ng_container_2_div_77_Template(rf, ctx) { if (rf & 1) {
|
|
37
|
+
i0.ɵɵelementStart(0, "div", 51)(1, "div", 52);
|
|
38
|
+
i0.ɵɵtemplate(2, APIUsagePanelComponent_ng_container_2_div_77_div_2_Template, 6, 5, "div", 53);
|
|
39
|
+
i0.ɵɵelementEnd();
|
|
40
|
+
i0.ɵɵelementStart(3, "div", 54)(4, "span");
|
|
41
|
+
i0.ɵɵtext(5);
|
|
42
|
+
i0.ɵɵelementEnd();
|
|
43
|
+
i0.ɵɵelementStart(6, "span");
|
|
44
|
+
i0.ɵɵtext(7);
|
|
45
|
+
i0.ɵɵelementEnd();
|
|
46
|
+
i0.ɵɵelementStart(8, "span");
|
|
47
|
+
i0.ɵɵtext(9, "0");
|
|
48
|
+
i0.ɵɵelementEnd()()();
|
|
49
|
+
} if (rf & 2) {
|
|
50
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
51
|
+
i0.ɵɵadvance(2);
|
|
52
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.TimeBuckets);
|
|
53
|
+
i0.ɵɵadvance(3);
|
|
54
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatNumber(ctx_r1.MaxRequests));
|
|
55
|
+
i0.ɵɵadvance(2);
|
|
56
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatNumber(ctx_r1.Math.round(ctx_r1.MaxRequests / 2)));
|
|
57
|
+
} }
|
|
58
|
+
function APIUsagePanelComponent_ng_container_2_div_78_Template(rf, ctx) { if (rf & 1) {
|
|
59
|
+
i0.ɵɵelementStart(0, "div", 61);
|
|
60
|
+
i0.ɵɵelement(1, "i", 62);
|
|
61
|
+
i0.ɵɵelementStart(2, "span");
|
|
62
|
+
i0.ɵɵtext(3, "No usage data available");
|
|
63
|
+
i0.ɵɵelementEnd()();
|
|
64
|
+
} }
|
|
65
|
+
function APIUsagePanelComponent_ng_container_2_div_86_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
66
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
67
|
+
i0.ɵɵelementStart(0, "div", 65);
|
|
68
|
+
i0.ɵɵlistener("click", function APIUsagePanelComponent_ng_container_2_div_86_div_1_Template_div_click_0_listener() { const ep_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.drillDownEndpoint(ep_r5)); });
|
|
69
|
+
i0.ɵɵelementStart(1, "div", 66)(2, "span", 67);
|
|
70
|
+
i0.ɵɵtext(3);
|
|
71
|
+
i0.ɵɵelementEnd();
|
|
72
|
+
i0.ɵɵelementStart(4, "span", 68);
|
|
73
|
+
i0.ɵɵtext(5);
|
|
74
|
+
i0.ɵɵelementEnd()();
|
|
75
|
+
i0.ɵɵelementStart(6, "div", 69)(7, "span", 70);
|
|
76
|
+
i0.ɵɵtext(8);
|
|
77
|
+
i0.ɵɵelementEnd();
|
|
78
|
+
i0.ɵɵelementStart(9, "span", 71);
|
|
79
|
+
i0.ɵɵtext(10);
|
|
80
|
+
i0.ɵɵelementEnd();
|
|
81
|
+
i0.ɵɵelementStart(11, "span", 72);
|
|
82
|
+
i0.ɵɵtext(12);
|
|
83
|
+
i0.ɵɵelementEnd()()();
|
|
84
|
+
} if (rf & 2) {
|
|
85
|
+
const ep_r5 = ctx.$implicit;
|
|
86
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
87
|
+
i0.ɵɵadvance(2);
|
|
88
|
+
i0.ɵɵproperty("ngClass", ctx_r1.getMethodClass(ep_r5.method));
|
|
89
|
+
i0.ɵɵadvance();
|
|
90
|
+
i0.ɵɵtextInterpolate1(" ", ep_r5.method, " ");
|
|
91
|
+
i0.ɵɵadvance(2);
|
|
92
|
+
i0.ɵɵtextInterpolate(ep_r5.endpoint);
|
|
93
|
+
i0.ɵɵadvance(3);
|
|
94
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatNumber(ep_r5.requests));
|
|
95
|
+
i0.ɵɵadvance(2);
|
|
96
|
+
i0.ɵɵtextInterpolate1("", ep_r5.avgResponseTime, "ms");
|
|
97
|
+
i0.ɵɵadvance();
|
|
98
|
+
i0.ɵɵclassProp("has-errors", ep_r5.errorRate > 0);
|
|
99
|
+
i0.ɵɵadvance();
|
|
100
|
+
i0.ɵɵtextInterpolate1(" ", ep_r5.errorRate, "% err ");
|
|
101
|
+
} }
|
|
102
|
+
function APIUsagePanelComponent_ng_container_2_div_86_Template(rf, ctx) { if (rf & 1) {
|
|
103
|
+
i0.ɵɵelementStart(0, "div", 63);
|
|
104
|
+
i0.ɵɵtemplate(1, APIUsagePanelComponent_ng_container_2_div_86_div_1_Template, 13, 8, "div", 64);
|
|
105
|
+
i0.ɵɵelementEnd();
|
|
106
|
+
} if (rf & 2) {
|
|
107
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
108
|
+
i0.ɵɵadvance();
|
|
109
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.TopEndpoints);
|
|
110
|
+
} }
|
|
111
|
+
function APIUsagePanelComponent_ng_container_2_div_87_Template(rf, ctx) { if (rf & 1) {
|
|
112
|
+
i0.ɵɵelementStart(0, "div", 73);
|
|
113
|
+
i0.ɵɵelement(1, "i", 28);
|
|
114
|
+
i0.ɵɵelementStart(2, "span");
|
|
115
|
+
i0.ɵɵtext(3, "No endpoint data");
|
|
116
|
+
i0.ɵɵelementEnd()();
|
|
117
|
+
} }
|
|
118
|
+
function APIUsagePanelComponent_ng_container_2_div_94_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
119
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
120
|
+
i0.ɵɵelementStart(0, "div", 76);
|
|
121
|
+
i0.ɵɵlistener("click", function APIUsagePanelComponent_ng_container_2_div_94_div_1_Template_div_click_0_listener() { const key_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.drillDownKey(key_r7)); });
|
|
122
|
+
i0.ɵɵelementStart(1, "div", 77)(2, "span", 78);
|
|
123
|
+
i0.ɵɵtext(3);
|
|
124
|
+
i0.ɵɵelementEnd();
|
|
125
|
+
i0.ɵɵelementStart(4, "span", 79);
|
|
126
|
+
i0.ɵɵtext(5);
|
|
127
|
+
i0.ɵɵelementEnd()();
|
|
128
|
+
i0.ɵɵelementStart(6, "div", 80);
|
|
129
|
+
i0.ɵɵtext(7);
|
|
130
|
+
i0.ɵɵelementEnd()();
|
|
131
|
+
} if (rf & 2) {
|
|
132
|
+
const key_r7 = ctx.$implicit;
|
|
133
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
134
|
+
i0.ɵɵadvance(3);
|
|
135
|
+
i0.ɵɵtextInterpolate(key_r7.label);
|
|
136
|
+
i0.ɵɵadvance(2);
|
|
137
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatDate(key_r7.lastUsed));
|
|
138
|
+
i0.ɵɵadvance(2);
|
|
139
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatNumber(key_r7.requests));
|
|
140
|
+
} }
|
|
141
|
+
function APIUsagePanelComponent_ng_container_2_div_94_Template(rf, ctx) { if (rf & 1) {
|
|
142
|
+
i0.ɵɵelementStart(0, "div", 74);
|
|
143
|
+
i0.ɵɵtemplate(1, APIUsagePanelComponent_ng_container_2_div_94_div_1_Template, 8, 3, "div", 75);
|
|
144
|
+
i0.ɵɵelementEnd();
|
|
145
|
+
} if (rf & 2) {
|
|
146
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
147
|
+
i0.ɵɵadvance();
|
|
148
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.TopKeys);
|
|
149
|
+
} }
|
|
150
|
+
function APIUsagePanelComponent_ng_container_2_div_95_Template(rf, ctx) { if (rf & 1) {
|
|
151
|
+
i0.ɵɵelementStart(0, "div", 73);
|
|
152
|
+
i0.ɵɵelement(1, "i", 26);
|
|
153
|
+
i0.ɵɵelementStart(2, "span");
|
|
154
|
+
i0.ɵɵtext(3, "No key data");
|
|
155
|
+
i0.ɵɵelementEnd()();
|
|
156
|
+
} }
|
|
157
|
+
function APIUsagePanelComponent_ng_container_2_div_102_div_2_Template(rf, ctx) { if (rf & 1) {
|
|
158
|
+
i0.ɵɵelement(0, "div", 86);
|
|
159
|
+
} if (rf & 2) {
|
|
160
|
+
const group_r8 = ctx.$implicit;
|
|
161
|
+
i0.ɵɵstyleProp("width", group_r8.percentage, "%")("background-color", group_r8.color);
|
|
162
|
+
i0.ɵɵproperty("title", group_r8.label + ": " + group_r8.count + " (" + group_r8.percentage + "%)");
|
|
163
|
+
} }
|
|
164
|
+
function APIUsagePanelComponent_ng_container_2_div_102_div_4_Template(rf, ctx) { if (rf & 1) {
|
|
165
|
+
i0.ɵɵelementStart(0, "div", 87);
|
|
166
|
+
i0.ɵɵelement(1, "span", 88);
|
|
167
|
+
i0.ɵɵelementStart(2, "span", 89);
|
|
168
|
+
i0.ɵɵtext(3);
|
|
169
|
+
i0.ɵɵelementEnd();
|
|
170
|
+
i0.ɵɵelementStart(4, "span", 90);
|
|
171
|
+
i0.ɵɵtext(5);
|
|
172
|
+
i0.ɵɵelementEnd()();
|
|
173
|
+
} if (rf & 2) {
|
|
174
|
+
const group_r9 = ctx.$implicit;
|
|
175
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
176
|
+
i0.ɵɵadvance();
|
|
177
|
+
i0.ɵɵstyleProp("background-color", group_r9.color);
|
|
178
|
+
i0.ɵɵadvance(2);
|
|
179
|
+
i0.ɵɵtextInterpolate(group_r9.label);
|
|
180
|
+
i0.ɵɵadvance(2);
|
|
181
|
+
i0.ɵɵtextInterpolate2("", ctx_r1.formatNumber(group_r9.count), " (", group_r9.percentage, "%)");
|
|
182
|
+
} }
|
|
183
|
+
function APIUsagePanelComponent_ng_container_2_div_102_Template(rf, ctx) { if (rf & 1) {
|
|
184
|
+
i0.ɵɵelementStart(0, "div", 81)(1, "div", 82);
|
|
185
|
+
i0.ɵɵtemplate(2, APIUsagePanelComponent_ng_container_2_div_102_div_2_Template, 1, 5, "div", 83);
|
|
186
|
+
i0.ɵɵelementEnd();
|
|
187
|
+
i0.ɵɵelementStart(3, "div", 84);
|
|
188
|
+
i0.ɵɵtemplate(4, APIUsagePanelComponent_ng_container_2_div_102_div_4_Template, 6, 5, "div", 85);
|
|
189
|
+
i0.ɵɵelementEnd()();
|
|
190
|
+
} if (rf & 2) {
|
|
191
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
192
|
+
i0.ɵɵadvance(2);
|
|
193
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.StatusGroups);
|
|
194
|
+
i0.ɵɵadvance(2);
|
|
195
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.StatusGroups);
|
|
196
|
+
} }
|
|
197
|
+
function APIUsagePanelComponent_ng_container_2_div_103_Template(rf, ctx) { if (rf & 1) {
|
|
198
|
+
i0.ɵɵelementStart(0, "div", 73);
|
|
199
|
+
i0.ɵɵelement(1, "i", 44);
|
|
200
|
+
i0.ɵɵelementStart(2, "span");
|
|
201
|
+
i0.ɵɵtext(3, "No status data");
|
|
202
|
+
i0.ɵɵelementEnd()();
|
|
203
|
+
} }
|
|
204
|
+
function APIUsagePanelComponent_ng_container_2_div_109_div_15_Template(rf, ctx) { if (rf & 1) {
|
|
205
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "span", 93);
|
|
206
|
+
i0.ɵɵtext(2);
|
|
207
|
+
i0.ɵɵelementEnd();
|
|
208
|
+
i0.ɵɵelementStart(3, "span", 94);
|
|
209
|
+
i0.ɵɵtext(4);
|
|
210
|
+
i0.ɵɵelementEnd();
|
|
211
|
+
i0.ɵɵelementStart(5, "span", 95)(6, "span", 67);
|
|
212
|
+
i0.ɵɵtext(7);
|
|
213
|
+
i0.ɵɵelementEnd()();
|
|
214
|
+
i0.ɵɵelementStart(8, "span", 96);
|
|
215
|
+
i0.ɵɵtext(9);
|
|
216
|
+
i0.ɵɵelementEnd();
|
|
217
|
+
i0.ɵɵelementStart(10, "span", 102);
|
|
218
|
+
i0.ɵɵtext(11);
|
|
219
|
+
i0.ɵɵelementEnd();
|
|
220
|
+
i0.ɵɵelementStart(12, "span", 98);
|
|
221
|
+
i0.ɵɵtext(13);
|
|
222
|
+
i0.ɵɵelementEnd()();
|
|
223
|
+
} if (rf & 2) {
|
|
224
|
+
const log_r10 = ctx.$implicit;
|
|
225
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
226
|
+
i0.ɵɵadvance(2);
|
|
227
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatDate(log_r10.timestamp));
|
|
228
|
+
i0.ɵɵadvance(2);
|
|
229
|
+
i0.ɵɵtextInterpolate(log_r10.keyLabel);
|
|
230
|
+
i0.ɵɵadvance(2);
|
|
231
|
+
i0.ɵɵproperty("ngClass", ctx_r1.getMethodClass(log_r10.method));
|
|
232
|
+
i0.ɵɵadvance();
|
|
233
|
+
i0.ɵɵtextInterpolate1(" ", log_r10.method, " ");
|
|
234
|
+
i0.ɵɵadvance(2);
|
|
235
|
+
i0.ɵɵtextInterpolate(log_r10.endpoint);
|
|
236
|
+
i0.ɵɵadvance();
|
|
237
|
+
i0.ɵɵproperty("ngClass", ctx_r1.getStatusClass(log_r10.statusCode));
|
|
238
|
+
i0.ɵɵadvance();
|
|
239
|
+
i0.ɵɵtextInterpolate1(" ", log_r10.statusCode, " ");
|
|
240
|
+
i0.ɵɵadvance(2);
|
|
241
|
+
i0.ɵɵtextInterpolate1("", log_r10.responseTime, "ms");
|
|
242
|
+
} }
|
|
243
|
+
function APIUsagePanelComponent_ng_container_2_div_109_Template(rf, ctx) { if (rf & 1) {
|
|
244
|
+
i0.ɵɵelementStart(0, "div", 91)(1, "div", 92)(2, "span", 93);
|
|
245
|
+
i0.ɵɵtext(3, "Time");
|
|
246
|
+
i0.ɵɵelementEnd();
|
|
247
|
+
i0.ɵɵelementStart(4, "span", 94);
|
|
248
|
+
i0.ɵɵtext(5, "API Key");
|
|
249
|
+
i0.ɵɵelementEnd();
|
|
250
|
+
i0.ɵɵelementStart(6, "span", 95);
|
|
251
|
+
i0.ɵɵtext(7, "Method");
|
|
252
|
+
i0.ɵɵelementEnd();
|
|
253
|
+
i0.ɵɵelementStart(8, "span", 96);
|
|
254
|
+
i0.ɵɵtext(9, "Endpoint");
|
|
255
|
+
i0.ɵɵelementEnd();
|
|
256
|
+
i0.ɵɵelementStart(10, "span", 97);
|
|
257
|
+
i0.ɵɵtext(11, "Status");
|
|
258
|
+
i0.ɵɵelementEnd();
|
|
259
|
+
i0.ɵɵelementStart(12, "span", 98);
|
|
260
|
+
i0.ɵɵtext(13, "Duration");
|
|
261
|
+
i0.ɵɵelementEnd()();
|
|
262
|
+
i0.ɵɵelementStart(14, "div", 99);
|
|
263
|
+
i0.ɵɵtemplate(15, APIUsagePanelComponent_ng_container_2_div_109_div_15_Template, 14, 8, "div", 100);
|
|
264
|
+
i0.ɵɵelementEnd()();
|
|
265
|
+
} if (rf & 2) {
|
|
266
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
267
|
+
i0.ɵɵadvance(15);
|
|
268
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.RecentLogs);
|
|
269
|
+
} }
|
|
270
|
+
function APIUsagePanelComponent_ng_container_2_div_110_Template(rf, ctx) { if (rf & 1) {
|
|
271
|
+
i0.ɵɵelementStart(0, "div", 103);
|
|
272
|
+
i0.ɵɵelement(1, "i", 104);
|
|
273
|
+
i0.ɵɵelementStart(2, "span");
|
|
274
|
+
i0.ɵɵtext(3, "No requests logged yet");
|
|
275
|
+
i0.ɵɵelementEnd();
|
|
276
|
+
i0.ɵɵelementStart(4, "p");
|
|
277
|
+
i0.ɵɵtext(5, "API usage will appear here once keys are used");
|
|
278
|
+
i0.ɵɵelementEnd()();
|
|
279
|
+
} }
|
|
280
|
+
function APIUsagePanelComponent_ng_container_2_Template(rf, ctx) { if (rf & 1) {
|
|
281
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
282
|
+
i0.ɵɵelementContainerStart(0);
|
|
283
|
+
i0.ɵɵelementStart(1, "div", 5)(2, "div", 6)(3, "h3", 7);
|
|
284
|
+
i0.ɵɵelement(4, "i", 8);
|
|
285
|
+
i0.ɵɵtext(5, " API Usage Analytics ");
|
|
286
|
+
i0.ɵɵelementEnd();
|
|
287
|
+
i0.ɵɵelementStart(6, "p", 9);
|
|
288
|
+
i0.ɵɵtext(7, "Monitor API key usage, performance, and trends");
|
|
289
|
+
i0.ɵɵelementEnd()();
|
|
290
|
+
i0.ɵɵelementStart(8, "div", 10)(9, "button", 11);
|
|
291
|
+
i0.ɵɵlistener("click", function APIUsagePanelComponent_ng_container_2_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setTimeRange("day")); });
|
|
292
|
+
i0.ɵɵtext(10, "24 Hours");
|
|
293
|
+
i0.ɵɵelementEnd();
|
|
294
|
+
i0.ɵɵelementStart(11, "button", 11);
|
|
295
|
+
i0.ɵɵlistener("click", function APIUsagePanelComponent_ng_container_2_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setTimeRange("week")); });
|
|
296
|
+
i0.ɵɵtext(12, "7 Days");
|
|
297
|
+
i0.ɵɵelementEnd();
|
|
298
|
+
i0.ɵɵelementStart(13, "button", 11);
|
|
299
|
+
i0.ɵɵlistener("click", function APIUsagePanelComponent_ng_container_2_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setTimeRange("month")); });
|
|
300
|
+
i0.ɵɵtext(14, "30 Days");
|
|
301
|
+
i0.ɵɵelementEnd();
|
|
302
|
+
i0.ɵɵelementStart(15, "button", 11);
|
|
303
|
+
i0.ɵɵlistener("click", function APIUsagePanelComponent_ng_container_2_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setTimeRange("all")); });
|
|
304
|
+
i0.ɵɵtext(16, "All Time");
|
|
305
|
+
i0.ɵɵelementEnd()()();
|
|
306
|
+
i0.ɵɵelementStart(17, "div", 12)(18, "div", 13)(19, "div", 14);
|
|
307
|
+
i0.ɵɵelement(20, "i", 15);
|
|
308
|
+
i0.ɵɵelementEnd();
|
|
309
|
+
i0.ɵɵelementStart(21, "div", 16)(22, "div", 17);
|
|
310
|
+
i0.ɵɵtext(23);
|
|
311
|
+
i0.ɵɵelementEnd();
|
|
312
|
+
i0.ɵɵelementStart(24, "div", 18);
|
|
313
|
+
i0.ɵɵtext(25, "Total Requests");
|
|
314
|
+
i0.ɵɵelementEnd()()();
|
|
315
|
+
i0.ɵɵelementStart(26, "div", 13)(27, "div", 19);
|
|
316
|
+
i0.ɵɵelement(28, "i", 20);
|
|
317
|
+
i0.ɵɵelementEnd();
|
|
318
|
+
i0.ɵɵelementStart(29, "div", 16)(30, "div", 17);
|
|
319
|
+
i0.ɵɵtext(31);
|
|
320
|
+
i0.ɵɵelementEnd();
|
|
321
|
+
i0.ɵɵelementStart(32, "div", 18);
|
|
322
|
+
i0.ɵɵtext(33, "Success Rate");
|
|
323
|
+
i0.ɵɵelementEnd()()();
|
|
324
|
+
i0.ɵɵelementStart(34, "div", 13)(35, "div", 21);
|
|
325
|
+
i0.ɵɵelement(36, "i", 22);
|
|
326
|
+
i0.ɵɵelementEnd();
|
|
327
|
+
i0.ɵɵelementStart(37, "div", 16)(38, "div", 17);
|
|
328
|
+
i0.ɵɵtext(39);
|
|
329
|
+
i0.ɵɵelementEnd();
|
|
330
|
+
i0.ɵɵelementStart(40, "div", 18);
|
|
331
|
+
i0.ɵɵtext(41, "Errors");
|
|
332
|
+
i0.ɵɵelementEnd()()();
|
|
333
|
+
i0.ɵɵelementStart(42, "div", 13)(43, "div", 23);
|
|
334
|
+
i0.ɵɵelement(44, "i", 24);
|
|
335
|
+
i0.ɵɵelementEnd();
|
|
336
|
+
i0.ɵɵelementStart(45, "div", 16)(46, "div", 17);
|
|
337
|
+
i0.ɵɵtext(47);
|
|
338
|
+
i0.ɵɵelementEnd();
|
|
339
|
+
i0.ɵɵelementStart(48, "div", 18);
|
|
340
|
+
i0.ɵɵtext(49, "Avg Response Time");
|
|
341
|
+
i0.ɵɵelementEnd()()();
|
|
342
|
+
i0.ɵɵelementStart(50, "div", 13)(51, "div", 25);
|
|
343
|
+
i0.ɵɵelement(52, "i", 26);
|
|
344
|
+
i0.ɵɵelementEnd();
|
|
345
|
+
i0.ɵɵelementStart(53, "div", 16)(54, "div", 17);
|
|
346
|
+
i0.ɵɵtext(55);
|
|
347
|
+
i0.ɵɵelementEnd();
|
|
348
|
+
i0.ɵɵelementStart(56, "div", 18);
|
|
349
|
+
i0.ɵɵtext(57, "Active Keys");
|
|
350
|
+
i0.ɵɵelementEnd()()();
|
|
351
|
+
i0.ɵɵelementStart(58, "div", 13)(59, "div", 27);
|
|
352
|
+
i0.ɵɵelement(60, "i", 28);
|
|
353
|
+
i0.ɵɵelementEnd();
|
|
354
|
+
i0.ɵɵelementStart(61, "div", 16)(62, "div", 17);
|
|
355
|
+
i0.ɵɵtext(63);
|
|
356
|
+
i0.ɵɵelementEnd();
|
|
357
|
+
i0.ɵɵelementStart(64, "div", 18);
|
|
358
|
+
i0.ɵɵtext(65, "Unique Endpoints");
|
|
359
|
+
i0.ɵɵelementEnd()()()();
|
|
360
|
+
i0.ɵɵelementStart(66, "div", 29)(67, "div", 30)(68, "h4");
|
|
361
|
+
i0.ɵɵtext(69, "Request Volume");
|
|
362
|
+
i0.ɵɵelementEnd();
|
|
363
|
+
i0.ɵɵelementStart(70, "div", 31)(71, "span", 32);
|
|
364
|
+
i0.ɵɵelement(72, "span", 33);
|
|
365
|
+
i0.ɵɵtext(73, " Requests ");
|
|
366
|
+
i0.ɵɵelementEnd();
|
|
367
|
+
i0.ɵɵelementStart(74, "span", 32);
|
|
368
|
+
i0.ɵɵelement(75, "span", 34);
|
|
369
|
+
i0.ɵɵtext(76, " Errors ");
|
|
370
|
+
i0.ɵɵelementEnd()()();
|
|
371
|
+
i0.ɵɵtemplate(77, APIUsagePanelComponent_ng_container_2_div_77_Template, 10, 3, "div", 35)(78, APIUsagePanelComponent_ng_container_2_div_78_Template, 4, 0, "div", 36);
|
|
372
|
+
i0.ɵɵelementEnd();
|
|
373
|
+
i0.ɵɵelementStart(79, "div", 37)(80, "div", 38)(81, "div", 39)(82, "h4");
|
|
374
|
+
i0.ɵɵelement(83, "i", 28);
|
|
375
|
+
i0.ɵɵtext(84, " Top Endpoints ");
|
|
376
|
+
i0.ɵɵelementEnd()();
|
|
377
|
+
i0.ɵɵelementStart(85, "div", 40);
|
|
378
|
+
i0.ɵɵtemplate(86, APIUsagePanelComponent_ng_container_2_div_86_Template, 2, 1, "div", 41)(87, APIUsagePanelComponent_ng_container_2_div_87_Template, 4, 0, "div", 42);
|
|
379
|
+
i0.ɵɵelementEnd()();
|
|
380
|
+
i0.ɵɵelementStart(88, "div", 38)(89, "div", 39)(90, "h4");
|
|
381
|
+
i0.ɵɵelement(91, "i", 26);
|
|
382
|
+
i0.ɵɵtext(92, " Most Active Keys ");
|
|
383
|
+
i0.ɵɵelementEnd()();
|
|
384
|
+
i0.ɵɵelementStart(93, "div", 40);
|
|
385
|
+
i0.ɵɵtemplate(94, APIUsagePanelComponent_ng_container_2_div_94_Template, 2, 1, "div", 43)(95, APIUsagePanelComponent_ng_container_2_div_95_Template, 4, 0, "div", 42);
|
|
386
|
+
i0.ɵɵelementEnd()();
|
|
387
|
+
i0.ɵɵelementStart(96, "div", 38)(97, "div", 39)(98, "h4");
|
|
388
|
+
i0.ɵɵelement(99, "i", 44);
|
|
389
|
+
i0.ɵɵtext(100, " Status Distribution ");
|
|
390
|
+
i0.ɵɵelementEnd()();
|
|
391
|
+
i0.ɵɵelementStart(101, "div", 40);
|
|
392
|
+
i0.ɵɵtemplate(102, APIUsagePanelComponent_ng_container_2_div_102_Template, 5, 2, "div", 45)(103, APIUsagePanelComponent_ng_container_2_div_103_Template, 4, 0, "div", 42);
|
|
393
|
+
i0.ɵɵelementEnd()()();
|
|
394
|
+
i0.ɵɵelementStart(104, "div", 46)(105, "div", 47)(106, "h4");
|
|
395
|
+
i0.ɵɵelement(107, "i", 48);
|
|
396
|
+
i0.ɵɵtext(108, " Recent Requests ");
|
|
397
|
+
i0.ɵɵelementEnd()();
|
|
398
|
+
i0.ɵɵtemplate(109, APIUsagePanelComponent_ng_container_2_div_109_Template, 16, 1, "div", 49)(110, APIUsagePanelComponent_ng_container_2_div_110_Template, 6, 0, "div", 50);
|
|
399
|
+
i0.ɵɵelementEnd();
|
|
400
|
+
i0.ɵɵelementContainerEnd();
|
|
401
|
+
} if (rf & 2) {
|
|
402
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
403
|
+
i0.ɵɵadvance(9);
|
|
404
|
+
i0.ɵɵclassProp("active", ctx_r1.TimeRange === "day");
|
|
405
|
+
i0.ɵɵadvance(2);
|
|
406
|
+
i0.ɵɵclassProp("active", ctx_r1.TimeRange === "week");
|
|
407
|
+
i0.ɵɵadvance(2);
|
|
408
|
+
i0.ɵɵclassProp("active", ctx_r1.TimeRange === "month");
|
|
409
|
+
i0.ɵɵadvance(2);
|
|
410
|
+
i0.ɵɵclassProp("active", ctx_r1.TimeRange === "all");
|
|
411
|
+
i0.ɵɵadvance(8);
|
|
412
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatNumber(ctx_r1.TotalRequests));
|
|
413
|
+
i0.ɵɵadvance(3);
|
|
414
|
+
i0.ɵɵclassProp("success", ctx_r1.SuccessRate >= 95);
|
|
415
|
+
i0.ɵɵadvance(5);
|
|
416
|
+
i0.ɵɵtextInterpolate1("", ctx_r1.SuccessRate, "%");
|
|
417
|
+
i0.ɵɵadvance(3);
|
|
418
|
+
i0.ɵɵclassProp("warning", ctx_r1.TotalErrors > 0);
|
|
419
|
+
i0.ɵɵadvance(5);
|
|
420
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatNumber(ctx_r1.TotalErrors));
|
|
421
|
+
i0.ɵɵadvance(8);
|
|
422
|
+
i0.ɵɵtextInterpolate1("", ctx_r1.AvgResponseTime, "ms");
|
|
423
|
+
i0.ɵɵadvance(8);
|
|
424
|
+
i0.ɵɵtextInterpolate(ctx_r1.UniqueKeys);
|
|
425
|
+
i0.ɵɵadvance(8);
|
|
426
|
+
i0.ɵɵtextInterpolate(ctx_r1.UniqueEndpoints);
|
|
427
|
+
i0.ɵɵadvance(14);
|
|
428
|
+
i0.ɵɵproperty("ngIf", ctx_r1.TimeBuckets.length > 0);
|
|
429
|
+
i0.ɵɵadvance();
|
|
430
|
+
i0.ɵɵproperty("ngIf", ctx_r1.TimeBuckets.length === 0);
|
|
431
|
+
i0.ɵɵadvance(8);
|
|
432
|
+
i0.ɵɵproperty("ngIf", ctx_r1.TopEndpoints.length > 0);
|
|
433
|
+
i0.ɵɵadvance();
|
|
434
|
+
i0.ɵɵproperty("ngIf", ctx_r1.TopEndpoints.length === 0);
|
|
435
|
+
i0.ɵɵadvance(7);
|
|
436
|
+
i0.ɵɵproperty("ngIf", ctx_r1.TopKeys.length > 0);
|
|
437
|
+
i0.ɵɵadvance();
|
|
438
|
+
i0.ɵɵproperty("ngIf", ctx_r1.TopKeys.length === 0);
|
|
439
|
+
i0.ɵɵadvance(7);
|
|
440
|
+
i0.ɵɵproperty("ngIf", ctx_r1.StatusGroups.length > 0);
|
|
441
|
+
i0.ɵɵadvance();
|
|
442
|
+
i0.ɵɵproperty("ngIf", ctx_r1.StatusGroups.length === 0);
|
|
443
|
+
i0.ɵɵadvance(6);
|
|
444
|
+
i0.ɵɵproperty("ngIf", ctx_r1.RecentLogs.length > 0);
|
|
445
|
+
i0.ɵɵadvance();
|
|
446
|
+
i0.ɵɵproperty("ngIf", ctx_r1.RecentLogs.length === 0);
|
|
447
|
+
} }
|
|
448
|
+
function APIUsagePanelComponent_kendo_window_3_span_6_Template(rf, ctx) { if (rf & 1) {
|
|
449
|
+
i0.ɵɵelementStart(0, "span", 114);
|
|
450
|
+
i0.ɵɵtext(1);
|
|
451
|
+
i0.ɵɵelementEnd();
|
|
452
|
+
} if (rf & 2) {
|
|
453
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
454
|
+
i0.ɵɵadvance();
|
|
455
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.LogsFilter.endpoint, " ");
|
|
456
|
+
} }
|
|
457
|
+
function APIUsagePanelComponent_kendo_window_3_span_7_Template(rf, ctx) { if (rf & 1) {
|
|
458
|
+
i0.ɵɵelementStart(0, "span", 114);
|
|
459
|
+
i0.ɵɵtext(1);
|
|
460
|
+
i0.ɵɵelementEnd();
|
|
461
|
+
} if (rf & 2) {
|
|
462
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
463
|
+
i0.ɵɵadvance();
|
|
464
|
+
i0.ɵɵtextInterpolate1(" Key: ", ctx_r1.KeyMap.get(ctx_r1.LogsFilter.keyId) || "Unknown", " ");
|
|
465
|
+
} }
|
|
466
|
+
function APIUsagePanelComponent_kendo_window_3_mj_loading_11_Template(rf, ctx) { if (rf & 1) {
|
|
467
|
+
i0.ɵɵelement(0, "mj-loading", 115);
|
|
468
|
+
} }
|
|
469
|
+
function APIUsagePanelComponent_kendo_window_3_div_12_div_16_Template(rf, ctx) { if (rf & 1) {
|
|
470
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "span", 93);
|
|
471
|
+
i0.ɵɵtext(2);
|
|
472
|
+
i0.ɵɵelementEnd();
|
|
473
|
+
i0.ɵɵelementStart(3, "span", 94);
|
|
474
|
+
i0.ɵɵtext(4);
|
|
475
|
+
i0.ɵɵelementEnd();
|
|
476
|
+
i0.ɵɵelementStart(5, "span", 95)(6, "span", 67);
|
|
477
|
+
i0.ɵɵtext(7);
|
|
478
|
+
i0.ɵɵelementEnd()();
|
|
479
|
+
i0.ɵɵelementStart(8, "span", 96);
|
|
480
|
+
i0.ɵɵtext(9);
|
|
481
|
+
i0.ɵɵelementEnd();
|
|
482
|
+
i0.ɵɵelementStart(10, "span", 102);
|
|
483
|
+
i0.ɵɵtext(11);
|
|
484
|
+
i0.ɵɵelementEnd();
|
|
485
|
+
i0.ɵɵelementStart(12, "span", 98);
|
|
486
|
+
i0.ɵɵtext(13);
|
|
487
|
+
i0.ɵɵelementEnd()();
|
|
488
|
+
} if (rf & 2) {
|
|
489
|
+
const log_r12 = ctx.$implicit;
|
|
490
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
491
|
+
i0.ɵɵadvance(2);
|
|
492
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatDate(log_r12.timestamp));
|
|
493
|
+
i0.ɵɵadvance(2);
|
|
494
|
+
i0.ɵɵtextInterpolate(log_r12.keyLabel);
|
|
495
|
+
i0.ɵɵadvance(2);
|
|
496
|
+
i0.ɵɵproperty("ngClass", ctx_r1.getMethodClass(log_r12.method));
|
|
497
|
+
i0.ɵɵadvance();
|
|
498
|
+
i0.ɵɵtextInterpolate1(" ", log_r12.method, " ");
|
|
499
|
+
i0.ɵɵadvance(2);
|
|
500
|
+
i0.ɵɵtextInterpolate(log_r12.endpoint);
|
|
501
|
+
i0.ɵɵadvance();
|
|
502
|
+
i0.ɵɵproperty("ngClass", ctx_r1.getStatusClass(log_r12.statusCode));
|
|
503
|
+
i0.ɵɵadvance();
|
|
504
|
+
i0.ɵɵtextInterpolate1(" ", log_r12.statusCode, " ");
|
|
505
|
+
i0.ɵɵadvance(2);
|
|
506
|
+
i0.ɵɵtextInterpolate1("", log_r12.responseTime, "ms");
|
|
507
|
+
} }
|
|
508
|
+
function APIUsagePanelComponent_kendo_window_3_div_12_Template(rf, ctx) { if (rf & 1) {
|
|
509
|
+
i0.ɵɵelementStart(0, "div", 116)(1, "div", 91)(2, "div", 92)(3, "span", 93);
|
|
510
|
+
i0.ɵɵtext(4, "Time");
|
|
511
|
+
i0.ɵɵelementEnd();
|
|
512
|
+
i0.ɵɵelementStart(5, "span", 94);
|
|
513
|
+
i0.ɵɵtext(6, "API Key");
|
|
514
|
+
i0.ɵɵelementEnd();
|
|
515
|
+
i0.ɵɵelementStart(7, "span", 95);
|
|
516
|
+
i0.ɵɵtext(8, "Method");
|
|
517
|
+
i0.ɵɵelementEnd();
|
|
518
|
+
i0.ɵɵelementStart(9, "span", 96);
|
|
519
|
+
i0.ɵɵtext(10, "Endpoint");
|
|
520
|
+
i0.ɵɵelementEnd();
|
|
521
|
+
i0.ɵɵelementStart(11, "span", 97);
|
|
522
|
+
i0.ɵɵtext(12, "Status");
|
|
523
|
+
i0.ɵɵelementEnd();
|
|
524
|
+
i0.ɵɵelementStart(13, "span", 98);
|
|
525
|
+
i0.ɵɵtext(14, "Duration");
|
|
526
|
+
i0.ɵɵelementEnd()();
|
|
527
|
+
i0.ɵɵelementStart(15, "div", 117);
|
|
528
|
+
i0.ɵɵtemplate(16, APIUsagePanelComponent_kendo_window_3_div_12_div_16_Template, 14, 8, "div", 100);
|
|
529
|
+
i0.ɵɵelementEnd()()();
|
|
530
|
+
} if (rf & 2) {
|
|
531
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
532
|
+
i0.ɵɵadvance(16);
|
|
533
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.RecentLogs);
|
|
534
|
+
} }
|
|
535
|
+
function APIUsagePanelComponent_kendo_window_3_Template(rf, ctx) { if (rf & 1) {
|
|
536
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
537
|
+
i0.ɵɵelementStart(0, "kendo-window", 105);
|
|
538
|
+
i0.ɵɵlistener("close", function APIUsagePanelComponent_kendo_window_3_Template_kendo_window_close_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeLogsPanel()); });
|
|
539
|
+
i0.ɵɵelementStart(1, "kendo-window-titlebar")(2, "div", 106);
|
|
540
|
+
i0.ɵɵelement(3, "i", 107);
|
|
541
|
+
i0.ɵɵelementStart(4, "span");
|
|
542
|
+
i0.ɵɵtext(5, "Request Details");
|
|
543
|
+
i0.ɵɵelementEnd();
|
|
544
|
+
i0.ɵɵtemplate(6, APIUsagePanelComponent_kendo_window_3_span_6_Template, 2, 1, "span", 108)(7, APIUsagePanelComponent_kendo_window_3_span_7_Template, 2, 1, "span", 108);
|
|
545
|
+
i0.ɵɵelementEnd();
|
|
546
|
+
i0.ɵɵelementStart(8, "button", 109);
|
|
547
|
+
i0.ɵɵlistener("click", function APIUsagePanelComponent_kendo_window_3_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeLogsPanel()); });
|
|
548
|
+
i0.ɵɵelement(9, "i", 110);
|
|
549
|
+
i0.ɵɵelementEnd()();
|
|
550
|
+
i0.ɵɵelementStart(10, "div", 111);
|
|
551
|
+
i0.ɵɵtemplate(11, APIUsagePanelComponent_kendo_window_3_mj_loading_11_Template, 1, 0, "mj-loading", 112)(12, APIUsagePanelComponent_kendo_window_3_div_12_Template, 17, 1, "div", 113);
|
|
552
|
+
i0.ɵɵelementEnd()();
|
|
553
|
+
} if (rf & 2) {
|
|
554
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
555
|
+
i0.ɵɵproperty("width", 800)("minWidth", 600)("height", 500)("minHeight", 400)("resizable", true)("draggable", true)("top", 80);
|
|
556
|
+
i0.ɵɵadvance(6);
|
|
557
|
+
i0.ɵɵproperty("ngIf", ctx_r1.LogsFilter.endpoint);
|
|
558
|
+
i0.ɵɵadvance();
|
|
559
|
+
i0.ɵɵproperty("ngIf", ctx_r1.LogsFilter.keyId);
|
|
560
|
+
i0.ɵɵadvance(4);
|
|
561
|
+
i0.ɵɵproperty("ngIf", ctx_r1.IsLoadingLogs);
|
|
562
|
+
i0.ɵɵadvance();
|
|
563
|
+
i0.ɵɵproperty("ngIf", !ctx_r1.IsLoadingLogs);
|
|
564
|
+
} }
|
|
565
|
+
/** Tree shaking prevention function */
|
|
566
|
+
export function LoadAPIUsagePanel() {
|
|
567
|
+
// This function prevents tree shaking
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* API Usage Analytics Panel Component
|
|
571
|
+
* Comprehensive usage statistics and drill-down capabilities
|
|
572
|
+
*/
|
|
573
|
+
export class APIUsagePanelComponent {
|
|
574
|
+
md = new Metadata();
|
|
575
|
+
cdr;
|
|
576
|
+
// Loading states
|
|
577
|
+
IsLoading = true;
|
|
578
|
+
IsLoadingLogs = false;
|
|
579
|
+
// Time range filter
|
|
580
|
+
TimeRange = 'week';
|
|
581
|
+
// Summary KPIs
|
|
582
|
+
TotalRequests = 0;
|
|
583
|
+
TotalErrors = 0;
|
|
584
|
+
AvgResponseTime = 0;
|
|
585
|
+
SuccessRate = 0;
|
|
586
|
+
UniqueKeys = 0;
|
|
587
|
+
UniqueEndpoints = 0;
|
|
588
|
+
// Trend data (vs previous period)
|
|
589
|
+
RequestsTrend = 0;
|
|
590
|
+
ErrorsTrend = 0;
|
|
591
|
+
ResponseTimeTrend = 0;
|
|
592
|
+
// Chart data
|
|
593
|
+
TimeBuckets = [];
|
|
594
|
+
MaxRequests = 0;
|
|
595
|
+
MaxErrors = 0;
|
|
596
|
+
// Breakdown data
|
|
597
|
+
TopEndpoints = [];
|
|
598
|
+
TopKeys = [];
|
|
599
|
+
StatusGroups = [];
|
|
600
|
+
// Recent logs
|
|
601
|
+
RecentLogs = [];
|
|
602
|
+
ShowLogsPanel = false;
|
|
603
|
+
LogsFilter = {};
|
|
604
|
+
// Key map for labels
|
|
605
|
+
KeyMap = new Map();
|
|
606
|
+
// Expose Math for template
|
|
607
|
+
Math = Math;
|
|
608
|
+
constructor(cdr) {
|
|
609
|
+
this.cdr = cdr;
|
|
610
|
+
}
|
|
611
|
+
async ngOnInit() {
|
|
612
|
+
await this.loadData();
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Load all usage data
|
|
616
|
+
*/
|
|
617
|
+
async loadData() {
|
|
618
|
+
this.IsLoading = true;
|
|
619
|
+
try {
|
|
620
|
+
// Load keys for label lookup
|
|
621
|
+
await this.loadKeys();
|
|
622
|
+
// Load usage data
|
|
623
|
+
await this.loadUsageStats();
|
|
624
|
+
}
|
|
625
|
+
catch (error) {
|
|
626
|
+
console.error('Error loading usage data:', error);
|
|
627
|
+
}
|
|
628
|
+
finally {
|
|
629
|
+
this.IsLoading = false;
|
|
630
|
+
this.cdr.markForCheck();
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Load API keys for label lookup
|
|
635
|
+
*/
|
|
636
|
+
async loadKeys() {
|
|
637
|
+
const rv = new RunView();
|
|
638
|
+
const result = await rv.RunView({
|
|
639
|
+
EntityName: 'MJ: API Keys',
|
|
640
|
+
Fields: ['ID', 'Label'],
|
|
641
|
+
ResultType: 'simple'
|
|
642
|
+
});
|
|
643
|
+
if (result.Success) {
|
|
644
|
+
for (const key of result.Results) {
|
|
645
|
+
this.KeyMap.set(key.ID, key.Label);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Load usage statistics based on time range
|
|
651
|
+
*/
|
|
652
|
+
async loadUsageStats() {
|
|
653
|
+
const rv = new RunView();
|
|
654
|
+
const filter = this.getTimeFilter();
|
|
655
|
+
const result = await rv.RunView({
|
|
656
|
+
EntityName: 'MJ: API Key Usage Logs',
|
|
657
|
+
ExtraFilter: filter,
|
|
658
|
+
OrderBy: '__mj_CreatedAt DESC',
|
|
659
|
+
MaxRows: 5000,
|
|
660
|
+
ResultType: 'entity_object'
|
|
661
|
+
});
|
|
662
|
+
if (result.Success) {
|
|
663
|
+
const logs = result.Results;
|
|
664
|
+
this.calculateSummaryKPIs(logs);
|
|
665
|
+
this.buildTimeBuckets(logs);
|
|
666
|
+
this.buildEndpointStats(logs);
|
|
667
|
+
this.buildKeyStats(logs);
|
|
668
|
+
this.buildStatusGroups(logs);
|
|
669
|
+
this.RecentLogs = logs.slice(0, 20).map(log => this.mapLogToItem(log));
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Get time filter for RunView based on selected range
|
|
674
|
+
*/
|
|
675
|
+
getTimeFilter() {
|
|
676
|
+
const now = new Date();
|
|
677
|
+
let startDate;
|
|
678
|
+
switch (this.TimeRange) {
|
|
679
|
+
case 'day':
|
|
680
|
+
startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
|
681
|
+
break;
|
|
682
|
+
case 'week':
|
|
683
|
+
startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
684
|
+
break;
|
|
685
|
+
case 'month':
|
|
686
|
+
startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
687
|
+
break;
|
|
688
|
+
case 'all':
|
|
689
|
+
default:
|
|
690
|
+
return '';
|
|
691
|
+
}
|
|
692
|
+
return `__mj_CreatedAt >= '${startDate.toISOString()}'`;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Calculate summary KPIs
|
|
696
|
+
*/
|
|
697
|
+
calculateSummaryKPIs(logs) {
|
|
698
|
+
this.TotalRequests = logs.length;
|
|
699
|
+
// Count errors (4xx and 5xx status codes)
|
|
700
|
+
this.TotalErrors = logs.filter(l => l.StatusCode >= 400).length;
|
|
701
|
+
// Calculate average response time
|
|
702
|
+
const totalResponseTime = logs.reduce((sum, l) => sum + (l.ResponseTimeMs || 0), 0);
|
|
703
|
+
this.AvgResponseTime = this.TotalRequests > 0
|
|
704
|
+
? Math.round(totalResponseTime / this.TotalRequests)
|
|
705
|
+
: 0;
|
|
706
|
+
// Success rate
|
|
707
|
+
this.SuccessRate = this.TotalRequests > 0
|
|
708
|
+
? Math.round(((this.TotalRequests - this.TotalErrors) / this.TotalRequests) * 100)
|
|
709
|
+
: 100;
|
|
710
|
+
// Unique counts
|
|
711
|
+
const keySet = new Set(logs.map(l => l.APIKeyID));
|
|
712
|
+
const endpointSet = new Set(logs.map(l => l.Endpoint));
|
|
713
|
+
this.UniqueKeys = keySet.size;
|
|
714
|
+
this.UniqueEndpoints = endpointSet.size;
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Build time buckets for chart
|
|
718
|
+
*/
|
|
719
|
+
buildTimeBuckets(logs) {
|
|
720
|
+
const bucketCount = this.TimeRange === 'day' ? 24 : this.TimeRange === 'week' ? 7 : 30;
|
|
721
|
+
const bucketDuration = this.TimeRange === 'day' ? 60 * 60 * 1000 : 24 * 60 * 60 * 1000;
|
|
722
|
+
const now = new Date();
|
|
723
|
+
const buckets = [];
|
|
724
|
+
for (let i = bucketCount - 1; i >= 0; i--) {
|
|
725
|
+
const bucketDate = new Date(now.getTime() - i * bucketDuration);
|
|
726
|
+
const bucketLogs = logs.filter(l => {
|
|
727
|
+
const logDate = new Date(l.__mj_CreatedAt);
|
|
728
|
+
const nextBucket = new Date(bucketDate.getTime() + bucketDuration);
|
|
729
|
+
return logDate >= bucketDate && logDate < nextBucket;
|
|
730
|
+
});
|
|
731
|
+
const errors = bucketLogs.filter(l => l.StatusCode >= 400).length;
|
|
732
|
+
const totalTime = bucketLogs.reduce((sum, l) => sum + (l.ResponseTimeMs || 0), 0);
|
|
733
|
+
buckets.push({
|
|
734
|
+
label: this.formatBucketLabel(bucketDate),
|
|
735
|
+
date: bucketDate,
|
|
736
|
+
requests: bucketLogs.length,
|
|
737
|
+
errors,
|
|
738
|
+
avgResponseTime: bucketLogs.length > 0 ? Math.round(totalTime / bucketLogs.length) : 0
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
this.TimeBuckets = buckets;
|
|
742
|
+
this.MaxRequests = Math.max(...buckets.map(b => b.requests), 1);
|
|
743
|
+
this.MaxErrors = Math.max(...buckets.map(b => b.errors), 1);
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Format bucket label based on time range
|
|
747
|
+
*/
|
|
748
|
+
formatBucketLabel(date) {
|
|
749
|
+
if (this.TimeRange === 'day') {
|
|
750
|
+
return date.toLocaleTimeString('en-US', { hour: 'numeric' });
|
|
751
|
+
}
|
|
752
|
+
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Build endpoint statistics
|
|
756
|
+
*/
|
|
757
|
+
buildEndpointStats(logs) {
|
|
758
|
+
const endpointMap = new Map();
|
|
759
|
+
for (const log of logs) {
|
|
760
|
+
const key = `${log.Method}:${log.Endpoint}`;
|
|
761
|
+
const existing = endpointMap.get(key);
|
|
762
|
+
if (existing) {
|
|
763
|
+
existing.requests++;
|
|
764
|
+
existing.totalTime += log.ResponseTimeMs || 0;
|
|
765
|
+
if (log.StatusCode >= 400)
|
|
766
|
+
existing.errors++;
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
endpointMap.set(key, {
|
|
770
|
+
endpoint: log.Endpoint,
|
|
771
|
+
method: log.Method,
|
|
772
|
+
requests: 1,
|
|
773
|
+
totalTime: log.ResponseTimeMs || 0,
|
|
774
|
+
errors: log.StatusCode >= 400 ? 1 : 0
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
this.TopEndpoints = Array.from(endpointMap.values())
|
|
779
|
+
.map(e => ({
|
|
780
|
+
endpoint: e.endpoint,
|
|
781
|
+
method: e.method,
|
|
782
|
+
requests: e.requests,
|
|
783
|
+
avgResponseTime: Math.round(e.totalTime / e.requests),
|
|
784
|
+
errorRate: Math.round((e.errors / e.requests) * 100)
|
|
785
|
+
}))
|
|
786
|
+
.sort((a, b) => b.requests - a.requests)
|
|
787
|
+
.slice(0, 10);
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Build key statistics
|
|
791
|
+
*/
|
|
792
|
+
buildKeyStats(logs) {
|
|
793
|
+
const keyMap = new Map();
|
|
794
|
+
for (const log of logs) {
|
|
795
|
+
const existing = keyMap.get(log.APIKeyID);
|
|
796
|
+
const logDate = new Date(log.__mj_CreatedAt);
|
|
797
|
+
if (existing) {
|
|
798
|
+
existing.requests++;
|
|
799
|
+
if (!existing.lastUsed || logDate > existing.lastUsed) {
|
|
800
|
+
existing.lastUsed = logDate;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
804
|
+
keyMap.set(log.APIKeyID, {
|
|
805
|
+
requests: 1,
|
|
806
|
+
lastUsed: logDate
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
this.TopKeys = Array.from(keyMap.entries())
|
|
811
|
+
.map(([keyId, stats]) => ({
|
|
812
|
+
keyId,
|
|
813
|
+
label: this.KeyMap.get(keyId) || 'Unknown Key',
|
|
814
|
+
requests: stats.requests,
|
|
815
|
+
lastUsed: stats.lastUsed
|
|
816
|
+
}))
|
|
817
|
+
.sort((a, b) => b.requests - a.requests)
|
|
818
|
+
.slice(0, 10);
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Build status code groups
|
|
822
|
+
*/
|
|
823
|
+
buildStatusGroups(logs) {
|
|
824
|
+
const groups = {
|
|
825
|
+
'2xx': { count: 0, label: 'Success (2xx)', color: '#10b981' },
|
|
826
|
+
'3xx': { count: 0, label: 'Redirect (3xx)', color: '#3b82f6' },
|
|
827
|
+
'4xx': { count: 0, label: 'Client Error (4xx)', color: '#f59e0b' },
|
|
828
|
+
'5xx': { count: 0, label: 'Server Error (5xx)', color: '#ef4444' }
|
|
829
|
+
};
|
|
830
|
+
for (const log of logs) {
|
|
831
|
+
const code = Math.floor(log.StatusCode / 100);
|
|
832
|
+
const key = `${code}xx`;
|
|
833
|
+
if (groups[key]) {
|
|
834
|
+
groups[key].count++;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
this.StatusGroups = Object.entries(groups)
|
|
838
|
+
.filter(([_, v]) => v.count > 0)
|
|
839
|
+
.map(([code, v]) => ({
|
|
840
|
+
code,
|
|
841
|
+
label: v.label,
|
|
842
|
+
count: v.count,
|
|
843
|
+
percentage: this.TotalRequests > 0 ? Math.round((v.count / this.TotalRequests) * 100) : 0,
|
|
844
|
+
color: v.color
|
|
845
|
+
}));
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Map log entity to display item
|
|
849
|
+
*/
|
|
850
|
+
mapLogToItem(log) {
|
|
851
|
+
return {
|
|
852
|
+
id: log.ID,
|
|
853
|
+
timestamp: new Date(log.__mj_CreatedAt),
|
|
854
|
+
endpoint: log.Endpoint,
|
|
855
|
+
method: log.Method,
|
|
856
|
+
statusCode: log.StatusCode,
|
|
857
|
+
responseTime: log.ResponseTimeMs || 0,
|
|
858
|
+
keyLabel: this.KeyMap.get(log.APIKeyID) || 'Unknown',
|
|
859
|
+
keyId: log.APIKeyID
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Change time range and reload
|
|
864
|
+
*/
|
|
865
|
+
async setTimeRange(range) {
|
|
866
|
+
this.TimeRange = range;
|
|
867
|
+
await this.loadData();
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Get bar height percentage for chart
|
|
871
|
+
*/
|
|
872
|
+
getBarHeight(value) {
|
|
873
|
+
if (this.MaxRequests === 0)
|
|
874
|
+
return 0;
|
|
875
|
+
return Math.max(2, (value / this.MaxRequests) * 100);
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Get error bar height for chart
|
|
879
|
+
*/
|
|
880
|
+
getErrorBarHeight(bucket) {
|
|
881
|
+
if (bucket.requests === 0)
|
|
882
|
+
return 0;
|
|
883
|
+
return (bucket.errors / bucket.requests) * 100;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Drill down into endpoint
|
|
887
|
+
*/
|
|
888
|
+
drillDownEndpoint(endpoint) {
|
|
889
|
+
this.LogsFilter = { endpoint: endpoint.endpoint };
|
|
890
|
+
this.loadFilteredLogs();
|
|
891
|
+
this.ShowLogsPanel = true;
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Drill down into key
|
|
895
|
+
*/
|
|
896
|
+
drillDownKey(key) {
|
|
897
|
+
this.LogsFilter = { keyId: key.keyId };
|
|
898
|
+
this.loadFilteredLogs();
|
|
899
|
+
this.ShowLogsPanel = true;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Load filtered logs for drill-down
|
|
903
|
+
*/
|
|
904
|
+
async loadFilteredLogs() {
|
|
905
|
+
this.IsLoadingLogs = true;
|
|
906
|
+
const rv = new RunView();
|
|
907
|
+
let filter = this.getTimeFilter();
|
|
908
|
+
if (this.LogsFilter.endpoint) {
|
|
909
|
+
filter += filter ? ' AND ' : '';
|
|
910
|
+
filter += `Endpoint = '${this.LogsFilter.endpoint}'`;
|
|
911
|
+
}
|
|
912
|
+
if (this.LogsFilter.keyId) {
|
|
913
|
+
filter += filter ? ' AND ' : '';
|
|
914
|
+
filter += `APIKeyID = '${this.LogsFilter.keyId}'`;
|
|
915
|
+
}
|
|
916
|
+
const result = await rv.RunView({
|
|
917
|
+
EntityName: 'MJ: API Key Usage Logs',
|
|
918
|
+
ExtraFilter: filter,
|
|
919
|
+
OrderBy: '__mj_CreatedAt DESC',
|
|
920
|
+
MaxRows: 100,
|
|
921
|
+
ResultType: 'entity_object'
|
|
922
|
+
});
|
|
923
|
+
if (result.Success) {
|
|
924
|
+
this.RecentLogs = result.Results.map(log => this.mapLogToItem(log));
|
|
925
|
+
}
|
|
926
|
+
this.IsLoadingLogs = false;
|
|
927
|
+
this.cdr.markForCheck();
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Close logs panel
|
|
931
|
+
*/
|
|
932
|
+
closeLogsPanel() {
|
|
933
|
+
this.ShowLogsPanel = false;
|
|
934
|
+
this.LogsFilter = {};
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Get status class for HTTP status code
|
|
938
|
+
*/
|
|
939
|
+
getStatusClass(statusCode) {
|
|
940
|
+
if (statusCode >= 200 && statusCode < 300)
|
|
941
|
+
return 'status-success';
|
|
942
|
+
if (statusCode >= 300 && statusCode < 400)
|
|
943
|
+
return 'status-info';
|
|
944
|
+
if (statusCode >= 400 && statusCode < 500)
|
|
945
|
+
return 'status-warning';
|
|
946
|
+
if (statusCode >= 500)
|
|
947
|
+
return 'status-error';
|
|
948
|
+
return '';
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Get method badge class
|
|
952
|
+
*/
|
|
953
|
+
getMethodClass(method) {
|
|
954
|
+
const m = method.toUpperCase();
|
|
955
|
+
if (m === 'GET')
|
|
956
|
+
return 'method-get';
|
|
957
|
+
if (m === 'POST')
|
|
958
|
+
return 'method-post';
|
|
959
|
+
if (m === 'PUT' || m === 'PATCH')
|
|
960
|
+
return 'method-put';
|
|
961
|
+
if (m === 'DELETE')
|
|
962
|
+
return 'method-delete';
|
|
963
|
+
return 'method-other';
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Format date for display
|
|
967
|
+
*/
|
|
968
|
+
formatDate(date) {
|
|
969
|
+
if (!date)
|
|
970
|
+
return 'Never';
|
|
971
|
+
const d = new Date(date);
|
|
972
|
+
const now = new Date();
|
|
973
|
+
const diff = now.getTime() - d.getTime();
|
|
974
|
+
const minutes = Math.floor(diff / 60000);
|
|
975
|
+
const hours = Math.floor(diff / 3600000);
|
|
976
|
+
if (minutes < 1)
|
|
977
|
+
return 'Just now';
|
|
978
|
+
if (minutes < 60)
|
|
979
|
+
return `${minutes}m ago`;
|
|
980
|
+
if (hours < 24)
|
|
981
|
+
return `${hours}h ago`;
|
|
982
|
+
return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' });
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Format number with K/M suffix
|
|
986
|
+
*/
|
|
987
|
+
formatNumber(num) {
|
|
988
|
+
if (num >= 1000000)
|
|
989
|
+
return (num / 1000000).toFixed(1) + 'M';
|
|
990
|
+
if (num >= 1000)
|
|
991
|
+
return (num / 1000).toFixed(1) + 'K';
|
|
992
|
+
return num.toString();
|
|
993
|
+
}
|
|
994
|
+
static ɵfac = function APIUsagePanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || APIUsagePanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
995
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: APIUsagePanelComponent, selectors: [["mj-api-usage-panel"]], decls: 4, vars: 3, consts: [[1, "usage-panel"], ["text", "Loading usage analytics...", 4, "ngIf"], [4, "ngIf"], [3, "width", "minWidth", "height", "minHeight", "resizable", "draggable", "top", "close", 4, "ngIf"], ["text", "Loading usage analytics..."], [1, "panel-header"], [1, "header-left"], [1, "panel-title"], [1, "fa-solid", "fa-chart-line"], [1, "panel-subtitle"], [1, "time-filters"], [1, "time-btn", 3, "click"], [1, "kpi-grid"], [1, "kpi-card"], [1, "kpi-icon", "requests"], [1, "fa-solid", "fa-arrow-right-arrow-left"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-icon", "success-rate"], [1, "fa-solid", "fa-check-circle"], [1, "kpi-icon", "errors"], [1, "fa-solid", "fa-circle-exclamation"], [1, "kpi-icon", "response-time"], [1, "fa-solid", "fa-gauge-high"], [1, "kpi-icon", "keys"], [1, "fa-solid", "fa-key"], [1, "kpi-icon", "endpoints"], [1, "fa-solid", "fa-code-branch"], [1, "chart-section"], [1, "chart-header"], [1, "chart-legend"], [1, "legend-item"], [1, "legend-color", "requests"], [1, "legend-color", "errors"], ["class", "chart-container", 4, "ngIf"], ["class", "empty-chart", 4, "ngIf"], [1, "breakdown-grid"], [1, "breakdown-card"], [1, "breakdown-header"], [1, "breakdown-content"], ["class", "endpoint-list", 4, "ngIf"], ["class", "empty-state", 4, "ngIf"], ["class", "key-list", 4, "ngIf"], [1, "fa-solid", "fa-circle-half-stroke"], ["class", "status-distribution", 4, "ngIf"], [1, "logs-section"], [1, "logs-header"], [1, "fa-solid", "fa-list"], ["class", "logs-table", 4, "ngIf"], ["class", "empty-state large", 4, "ngIf"], [1, "chart-container"], [1, "chart-bars"], ["class", "bar-group", 3, "title", 4, "ngFor", "ngForOf"], [1, "chart-y-axis"], [1, "bar-group", 3, "title"], [1, "bar-wrapper"], [1, "bar", "requests-bar"], ["class", "bar errors-bar", 3, "height", 4, "ngIf"], [1, "bar-label"], [1, "bar", "errors-bar"], [1, "empty-chart"], [1, "fa-solid", "fa-chart-area"], [1, "endpoint-list"], ["class", "endpoint-item", 3, "click", 4, "ngFor", "ngForOf"], [1, "endpoint-item", 3, "click"], [1, "endpoint-info"], [1, "method-badge", 3, "ngClass"], [1, "endpoint-path"], [1, "endpoint-stats"], [1, "endpoint-requests"], [1, "endpoint-time"], [1, "endpoint-error"], [1, "empty-state"], [1, "key-list"], ["class", "key-item", 3, "click", 4, "ngFor", "ngForOf"], [1, "key-item", 3, "click"], [1, "key-info"], [1, "key-label"], [1, "key-last-used"], [1, "key-requests"], [1, "status-distribution"], [1, "status-bar"], ["class", "status-segment", 3, "width", "backgroundColor", "title", 4, "ngFor", "ngForOf"], [1, "status-legend"], ["class", "status-legend-item", 4, "ngFor", "ngForOf"], [1, "status-segment", 3, "title"], [1, "status-legend-item"], [1, "status-color"], [1, "status-label"], [1, "status-count"], [1, "logs-table"], [1, "logs-table-header"], [1, "col-time"], [1, "col-key"], [1, "col-method"], [1, "col-endpoint"], [1, "col-status"], [1, "col-duration"], [1, "logs-table-body"], ["class", "log-row", 4, "ngFor", "ngForOf"], [1, "log-row"], [1, "col-status", 3, "ngClass"], [1, "empty-state", "large"], [1, "fa-solid", "fa-inbox"], [3, "close", "width", "minWidth", "height", "minHeight", "resizable", "draggable", "top"], [1, "drilldown-title"], [1, "fa-solid", "fa-magnifying-glass-chart"], ["class", "filter-badge", 4, "ngIf"], ["kendoButton", "", "fillMode", "flat", 1, "window-close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "drilldown-content"], ["text", "Loading requests...", 4, "ngIf"], ["class", "drilldown-logs", 4, "ngIf"], [1, "filter-badge"], ["text", "Loading requests..."], [1, "drilldown-logs"], [1, "logs-table-body", "scrollable"]], template: function APIUsagePanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
996
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
997
|
+
i0.ɵɵtemplate(1, APIUsagePanelComponent_mj_loading_1_Template, 1, 0, "mj-loading", 1)(2, APIUsagePanelComponent_ng_container_2_Template, 111, 28, "ng-container", 2)(3, APIUsagePanelComponent_kendo_window_3_Template, 13, 11, "kendo-window", 3);
|
|
998
|
+
i0.ɵɵelementEnd();
|
|
999
|
+
} if (rf & 2) {
|
|
1000
|
+
i0.ɵɵadvance();
|
|
1001
|
+
i0.ɵɵproperty("ngIf", ctx.IsLoading);
|
|
1002
|
+
i0.ɵɵadvance();
|
|
1003
|
+
i0.ɵɵproperty("ngIf", !ctx.IsLoading);
|
|
1004
|
+
i0.ɵɵadvance();
|
|
1005
|
+
i0.ɵɵproperty("ngIf", ctx.ShowLogsPanel);
|
|
1006
|
+
} }, dependencies: [i1.NgClass, i1.NgForOf, i1.NgIf, i2.WindowComponent, i2.WindowTitleBarComponent, i3.ButtonComponent, i4.LoadingComponent], styles: [".usage-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 24px;\n background: #f8fafc;\n min-height: 100%;\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 24px;\n flex-wrap: wrap;\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 24px;\n font-weight: 700;\n color: #1f2937;\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6366f1;\n}\n\n.panel-subtitle[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: #6b7280;\n}\n\n\n\n.time-filters[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n background: white;\n padding: 4px;\n border-radius: 10px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.time-btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: #6b7280;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.time-btn[_ngcontent-%COMP%]:hover {\n color: #374151;\n background: #f3f4f6;\n}\n\n.time-btn.active[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);\n color: white;\n box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);\n}\n\n\n\n.kpi-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 16px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px 20px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n transition: all 0.2s ease;\n}\n\n.kpi-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n}\n\n.kpi-card.success[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);\n}\n\n.kpi-card.warning[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n font-size: 18px;\n}\n\n.kpi-icon.requests[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);\n color: #2563eb;\n}\n\n.kpi-icon.success-rate[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);\n color: #059669;\n}\n\n.kpi-icon.errors[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);\n color: #dc2626;\n}\n\n.kpi-icon.response-time[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%);\n color: #4f46e5;\n}\n\n.kpi-icon.keys[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n color: #d97706;\n}\n\n.kpi-icon.endpoints[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f3e8ff 0%, #e9d5ff 100%);\n color: #7c3aed;\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 22px;\n font-weight: 700;\n color: #1f2937;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #6b7280;\n}\n\n\n\n.chart-section[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 20px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.chart-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.chart-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #1f2937;\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: #6b7280;\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n}\n\n.legend-color.requests[_ngcontent-%COMP%] {\n background: #6366f1;\n}\n\n.legend-color.errors[_ngcontent-%COMP%] {\n background: #ef4444;\n}\n\n.chart-container[_ngcontent-%COMP%] {\n display: flex;\n height: 200px;\n gap: 8px;\n}\n\n.chart-bars[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: flex-end;\n gap: 4px;\n padding-bottom: 24px;\n}\n\n.bar-group[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n min-width: 0;\n}\n\n.bar-wrapper[_ngcontent-%COMP%] {\n width: 100%;\n height: 160px;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n}\n\n.bar[_ngcontent-%COMP%] {\n width: 100%;\n max-width: 32px;\n border-radius: 4px 4px 0 0;\n transition: all 0.3s ease;\n position: relative;\n}\n\n.bar.requests-bar[_ngcontent-%COMP%] {\n background: linear-gradient(180deg, #6366f1 0%, #818cf8 100%);\n}\n\n.bar.requests-bar[_ngcontent-%COMP%]:hover {\n background: linear-gradient(180deg, #4f46e5 0%, #6366f1 100%);\n}\n\n.bar.errors-bar[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 0;\n left: 0;\n width: 100%;\n background: #ef4444;\n border-radius: 0;\n}\n\n.bar-label[_ngcontent-%COMP%] {\n margin-top: 8px;\n font-size: 10px;\n color: #9ca3af;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n max-width: 100%;\n}\n\n.chart-y-axis[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n padding-bottom: 24px;\n font-size: 10px;\n color: #9ca3af;\n text-align: right;\n min-width: 40px;\n}\n\n.empty-chart[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: #9ca3af;\n}\n\n.empty-chart[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 8px;\n opacity: 0.5;\n}\n\n\n\n.breakdown-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n gap: 20px;\n}\n\n.breakdown-card[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n}\n\n.breakdown-header[_ngcontent-%COMP%] {\n padding: 16px 20px;\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n}\n\n.breakdown-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.breakdown-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6b7280;\n}\n\n.breakdown-content[_ngcontent-%COMP%] {\n padding: 12px;\n max-height: 280px;\n overflow-y: auto;\n}\n\n\n\n.endpoint-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.endpoint-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 12px;\n background: #f9fafb;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.endpoint-item[_ngcontent-%COMP%]:hover {\n background: #f3f4f6;\n}\n\n.endpoint-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex: 1;\n}\n\n.method-badge[_ngcontent-%COMP%] {\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.method-get[_ngcontent-%COMP%] { background: #dbeafe; color: #2563eb; }\n.method-post[_ngcontent-%COMP%] { background: #d1fae5; color: #059669; }\n.method-put[_ngcontent-%COMP%] { background: #fef3c7; color: #d97706; }\n.method-delete[_ngcontent-%COMP%] { background: #fee2e2; color: #dc2626; }\n.method-other[_ngcontent-%COMP%] { background: #f3f4f6; color: #6b7280; }\n\n.endpoint-path[_ngcontent-%COMP%] {\n font-size: 12px;\n font-family: 'Fira Code', monospace;\n color: #374151;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.endpoint-stats[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.endpoint-requests[_ngcontent-%COMP%] {\n font-weight: 600;\n color: #6366f1;\n}\n\n.endpoint-time[_ngcontent-%COMP%] {\n color: #6b7280;\n}\n\n.endpoint-error[_ngcontent-%COMP%] {\n color: #10b981;\n}\n\n.endpoint-error.has-errors[_ngcontent-%COMP%] {\n color: #ef4444;\n font-weight: 500;\n}\n\n\n\n.key-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.key-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 12px;\n background: #f9fafb;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item[_ngcontent-%COMP%]:hover {\n background: #f3f4f6;\n}\n\n.key-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.key-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: #374151;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-last-used[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #9ca3af;\n}\n\n.key-requests[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #6366f1;\n}\n\n\n\n.status-distribution[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.status-bar[_ngcontent-%COMP%] {\n display: flex;\n height: 24px;\n border-radius: 6px;\n overflow: hidden;\n background: #f3f4f6;\n}\n\n.status-segment[_ngcontent-%COMP%] {\n transition: all 0.3s ease;\n}\n\n.status-segment[_ngcontent-%COMP%]:hover {\n filter: brightness(1.1);\n}\n\n.status-legend[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.status-legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n}\n\n.status-color[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n}\n\n.status-label[_ngcontent-%COMP%] {\n flex: 1;\n color: #374151;\n}\n\n.status-count[_ngcontent-%COMP%] {\n color: #6b7280;\n font-weight: 500;\n}\n\n\n\n.logs-section[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n}\n\n.logs-header[_ngcontent-%COMP%] {\n padding: 16px 20px;\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n}\n\n.logs-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.logs-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6b7280;\n}\n\n.logs-table[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.logs-table-header[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 100px 120px 70px 1fr 70px 80px;\n gap: 12px;\n padding: 12px 20px;\n background: #f3f4f6;\n font-size: 11px;\n font-weight: 600;\n color: #6b7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.logs-table-body[_ngcontent-%COMP%] {\n max-height: 320px;\n overflow-y: auto;\n}\n\n.logs-table-body.scrollable[_ngcontent-%COMP%] {\n max-height: 380px;\n}\n\n.log-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 100px 120px 70px 1fr 70px 80px;\n gap: 12px;\n padding: 12px 20px;\n border-bottom: 1px solid #f3f4f6;\n font-size: 13px;\n align-items: center;\n transition: background 0.2s ease;\n}\n\n.log-row[_ngcontent-%COMP%]:hover {\n background: #f9fafb;\n}\n\n.col-time[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 12px;\n}\n\n.col-key[_ngcontent-%COMP%] {\n color: #374151;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.col-endpoint[_ngcontent-%COMP%] {\n font-family: 'Fira Code', monospace;\n font-size: 12px;\n color: #374151;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.col-status[_ngcontent-%COMP%] {\n font-weight: 600;\n text-align: center;\n}\n\n.col-status.status-success[_ngcontent-%COMP%] { color: #10b981; }\n.col-status.status-info[_ngcontent-%COMP%] { color: #3b82f6; }\n.col-status.status-warning[_ngcontent-%COMP%] { color: #f59e0b; }\n.col-status.status-error[_ngcontent-%COMP%] { color: #ef4444; }\n\n.col-duration[_ngcontent-%COMP%] {\n color: #6b7280;\n text-align: right;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px 20px;\n color: #9ca3af;\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 8px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: #6b7280;\n}\n\n.empty-state.large[_ngcontent-%COMP%] {\n padding: 48px 24px;\n}\n\n.empty-state.large[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 8px 0 0 0;\n font-size: 12px;\n}\n\n\n\n.drilldown-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 15px;\n}\n\n.drilldown-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6366f1;\n}\n\n.filter-badge[_ngcontent-%COMP%] {\n padding: 4px 10px;\n background: #e0e7ff;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: #4f46e5;\n}\n\n.window-close-btn[_ngcontent-%COMP%] {\n margin-left: auto;\n color: #9ca3af;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n}\n\n.window-close-btn[_ngcontent-%COMP%]:hover {\n color: #374151;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.drilldown-content[_ngcontent-%COMP%] {\n height: 100%;\n overflow: hidden;\n}\n\n.drilldown-logs[_ngcontent-%COMP%] {\n height: 100%;\n}\n\n\n\n[_nghost-%COMP%] kendo-window {\n border-radius: 12px !important;\n overflow: hidden;\n box-shadow: 0 20px 50px rgba(0, 0, 0, 0.15) !important;\n}\n\n[_nghost-%COMP%] kendo-window .k-window-content {\n padding: 0 !important;\n}\n\n[_nghost-%COMP%] kendo-window-titlebar {\n padding: 16px 20px !important;\n background: #f9fafb !important;\n border-bottom: 1px solid #e5e7eb !important;\n}\n\n\n\n@media (max-width: 1400px) {\n .kpi-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(3, 1fr);\n }\n}\n\n@media (max-width: 1200px) {\n .breakdown-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 1fr;\n }\n}\n\n@media (max-width: 900px) {\n .kpi-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .breakdown-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .logs-table-header[_ngcontent-%COMP%], \n .log-row[_ngcontent-%COMP%] {\n grid-template-columns: 80px 100px 60px 1fr 60px;\n }\n\n .col-duration[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n@media (max-width: 600px) {\n .panel-header[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .time-filters[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n\n .kpi-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .logs-table-header[_ngcontent-%COMP%], \n .log-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 60px;\n }\n\n .col-key[_ngcontent-%COMP%], \n .col-method[_ngcontent-%COMP%], \n .col-endpoint[_ngcontent-%COMP%] {\n display: none;\n }\n}"] });
|
|
1007
|
+
}
|
|
1008
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIUsagePanelComponent, [{
|
|
1009
|
+
type: Component,
|
|
1010
|
+
args: [{ selector: 'mj-api-usage-panel', template: "<div class=\"usage-panel\">\n <mj-loading *ngIf=\"IsLoading\" text=\"Loading usage analytics...\"></mj-loading>\n\n <ng-container *ngIf=\"!IsLoading\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <h3 class=\"panel-title\">\n <i class=\"fa-solid fa-chart-line\"></i>\n API Usage Analytics\n </h3>\n <p class=\"panel-subtitle\">Monitor API key usage, performance, and trends</p>\n </div>\n <div class=\"time-filters\">\n <button class=\"time-btn\" [class.active]=\"TimeRange === 'day'\"\n (click)=\"setTimeRange('day')\">24 Hours</button>\n <button class=\"time-btn\" [class.active]=\"TimeRange === 'week'\"\n (click)=\"setTimeRange('week')\">7 Days</button>\n <button class=\"time-btn\" [class.active]=\"TimeRange === 'month'\"\n (click)=\"setTimeRange('month')\">30 Days</button>\n <button class=\"time-btn\" [class.active]=\"TimeRange === 'all'\"\n (click)=\"setTimeRange('all')\">All Time</button>\n </div>\n </div>\n\n <!-- Summary KPIs -->\n <div class=\"kpi-grid\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon requests\">\n <i class=\"fa-solid fa-arrow-right-arrow-left\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{formatNumber(TotalRequests)}}</div>\n <div class=\"kpi-label\">Total Requests</div>\n </div>\n </div>\n\n <div class=\"kpi-card\" [class.success]=\"SuccessRate >= 95\">\n <div class=\"kpi-icon success-rate\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{SuccessRate}}%</div>\n <div class=\"kpi-label\">Success Rate</div>\n </div>\n </div>\n\n <div class=\"kpi-card\" [class.warning]=\"TotalErrors > 0\">\n <div class=\"kpi-icon errors\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{formatNumber(TotalErrors)}}</div>\n <div class=\"kpi-label\">Errors</div>\n </div>\n </div>\n\n <div class=\"kpi-card\">\n <div class=\"kpi-icon response-time\">\n <i class=\"fa-solid fa-gauge-high\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{AvgResponseTime}}ms</div>\n <div class=\"kpi-label\">Avg Response Time</div>\n </div>\n </div>\n\n <div class=\"kpi-card\">\n <div class=\"kpi-icon keys\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{UniqueKeys}}</div>\n <div class=\"kpi-label\">Active Keys</div>\n </div>\n </div>\n\n <div class=\"kpi-card\">\n <div class=\"kpi-icon endpoints\">\n <i class=\"fa-solid fa-code-branch\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{UniqueEndpoints}}</div>\n <div class=\"kpi-label\">Unique Endpoints</div>\n </div>\n </div>\n </div>\n\n <!-- Usage Chart -->\n <div class=\"chart-section\">\n <div class=\"chart-header\">\n <h4>Request Volume</h4>\n <div class=\"chart-legend\">\n <span class=\"legend-item\">\n <span class=\"legend-color requests\"></span> Requests\n </span>\n <span class=\"legend-item\">\n <span class=\"legend-color errors\"></span> Errors\n </span>\n </div>\n </div>\n <div class=\"chart-container\" *ngIf=\"TimeBuckets.length > 0\">\n <div class=\"chart-bars\">\n <div class=\"bar-group\" *ngFor=\"let bucket of TimeBuckets\" [title]=\"bucket.requests + ' requests, ' + bucket.errors + ' errors'\">\n <div class=\"bar-wrapper\">\n <div class=\"bar requests-bar\"\n [style.height.%]=\"getBarHeight(bucket.requests)\">\n <div class=\"bar errors-bar\"\n [style.height.%]=\"getErrorBarHeight(bucket)\"\n *ngIf=\"bucket.errors > 0\">\n </div>\n </div>\n </div>\n <div class=\"bar-label\">{{bucket.label}}</div>\n </div>\n </div>\n <div class=\"chart-y-axis\">\n <span>{{formatNumber(MaxRequests)}}</span>\n <span>{{formatNumber(Math.round(MaxRequests / 2))}}</span>\n <span>0</span>\n </div>\n </div>\n <div class=\"empty-chart\" *ngIf=\"TimeBuckets.length === 0\">\n <i class=\"fa-solid fa-chart-area\"></i>\n <span>No usage data available</span>\n </div>\n </div>\n\n <!-- Breakdown Grid -->\n <div class=\"breakdown-grid\">\n <!-- Top Endpoints -->\n <div class=\"breakdown-card\">\n <div class=\"breakdown-header\">\n <h4>\n <i class=\"fa-solid fa-code-branch\"></i>\n Top Endpoints\n </h4>\n </div>\n <div class=\"breakdown-content\">\n <div class=\"endpoint-list\" *ngIf=\"TopEndpoints.length > 0\">\n <div class=\"endpoint-item\" *ngFor=\"let ep of TopEndpoints\"\n (click)=\"drillDownEndpoint(ep)\">\n <div class=\"endpoint-info\">\n <span class=\"method-badge\" [ngClass]=\"getMethodClass(ep.method)\">\n {{ep.method}}\n </span>\n <span class=\"endpoint-path\">{{ep.endpoint}}</span>\n </div>\n <div class=\"endpoint-stats\">\n <span class=\"endpoint-requests\">{{formatNumber(ep.requests)}}</span>\n <span class=\"endpoint-time\">{{ep.avgResponseTime}}ms</span>\n <span class=\"endpoint-error\" [class.has-errors]=\"ep.errorRate > 0\">\n {{ep.errorRate}}% err\n </span>\n </div>\n </div>\n </div>\n <div class=\"empty-state\" *ngIf=\"TopEndpoints.length === 0\">\n <i class=\"fa-solid fa-code-branch\"></i>\n <span>No endpoint data</span>\n </div>\n </div>\n </div>\n\n <!-- Top Keys -->\n <div class=\"breakdown-card\">\n <div class=\"breakdown-header\">\n <h4>\n <i class=\"fa-solid fa-key\"></i>\n Most Active Keys\n </h4>\n </div>\n <div class=\"breakdown-content\">\n <div class=\"key-list\" *ngIf=\"TopKeys.length > 0\">\n <div class=\"key-item\" *ngFor=\"let key of TopKeys\"\n (click)=\"drillDownKey(key)\">\n <div class=\"key-info\">\n <span class=\"key-label\">{{key.label}}</span>\n <span class=\"key-last-used\">{{formatDate(key.lastUsed)}}</span>\n </div>\n <div class=\"key-requests\">{{formatNumber(key.requests)}}</div>\n </div>\n </div>\n <div class=\"empty-state\" *ngIf=\"TopKeys.length === 0\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No key data</span>\n </div>\n </div>\n </div>\n\n <!-- Status Distribution -->\n <div class=\"breakdown-card\">\n <div class=\"breakdown-header\">\n <h4>\n <i class=\"fa-solid fa-circle-half-stroke\"></i>\n Status Distribution\n </h4>\n </div>\n <div class=\"breakdown-content\">\n <div class=\"status-distribution\" *ngIf=\"StatusGroups.length > 0\">\n <div class=\"status-bar\">\n <div class=\"status-segment\" *ngFor=\"let group of StatusGroups\"\n [style.width.%]=\"group.percentage\"\n [style.backgroundColor]=\"group.color\"\n [title]=\"group.label + ': ' + group.count + ' (' + group.percentage + '%)'\">\n </div>\n </div>\n <div class=\"status-legend\">\n <div class=\"status-legend-item\" *ngFor=\"let group of StatusGroups\">\n <span class=\"status-color\" [style.backgroundColor]=\"group.color\"></span>\n <span class=\"status-label\">{{group.label}}</span>\n <span class=\"status-count\">{{formatNumber(group.count)}} ({{group.percentage}}%)</span>\n </div>\n </div>\n </div>\n <div class=\"empty-state\" *ngIf=\"StatusGroups.length === 0\">\n <i class=\"fa-solid fa-circle-half-stroke\"></i>\n <span>No status data</span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Recent Logs -->\n <div class=\"logs-section\">\n <div class=\"logs-header\">\n <h4>\n <i class=\"fa-solid fa-list\"></i>\n Recent Requests\n </h4>\n </div>\n <div class=\"logs-table\" *ngIf=\"RecentLogs.length > 0\">\n <div class=\"logs-table-header\">\n <span class=\"col-time\">Time</span>\n <span class=\"col-key\">API Key</span>\n <span class=\"col-method\">Method</span>\n <span class=\"col-endpoint\">Endpoint</span>\n <span class=\"col-status\">Status</span>\n <span class=\"col-duration\">Duration</span>\n </div>\n <div class=\"logs-table-body\">\n <div class=\"log-row\" *ngFor=\"let log of RecentLogs\">\n <span class=\"col-time\">{{formatDate(log.timestamp)}}</span>\n <span class=\"col-key\">{{log.keyLabel}}</span>\n <span class=\"col-method\">\n <span class=\"method-badge\" [ngClass]=\"getMethodClass(log.method)\">\n {{log.method}}\n </span>\n </span>\n <span class=\"col-endpoint\">{{log.endpoint}}</span>\n <span class=\"col-status\" [ngClass]=\"getStatusClass(log.statusCode)\">\n {{log.statusCode}}\n </span>\n <span class=\"col-duration\">{{log.responseTime}}ms</span>\n </div>\n </div>\n </div>\n <div class=\"empty-state large\" *ngIf=\"RecentLogs.length === 0\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No requests logged yet</span>\n <p>API usage will appear here once keys are used</p>\n </div>\n </div>\n </ng-container>\n\n <!-- Drill-down Panel -->\n <kendo-window *ngIf=\"ShowLogsPanel\"\n [width]=\"800\"\n [minWidth]=\"600\"\n [height]=\"500\"\n [minHeight]=\"400\"\n [resizable]=\"true\"\n [draggable]=\"true\"\n [top]=\"80\"\n (close)=\"closeLogsPanel()\">\n <kendo-window-titlebar>\n <div class=\"drilldown-title\">\n <i class=\"fa-solid fa-magnifying-glass-chart\"></i>\n <span>Request Details</span>\n <span class=\"filter-badge\" *ngIf=\"LogsFilter.endpoint\">\n {{LogsFilter.endpoint}}\n </span>\n <span class=\"filter-badge\" *ngIf=\"LogsFilter.keyId\">\n Key: {{KeyMap.get(LogsFilter.keyId) || 'Unknown'}}\n </span>\n </div>\n <button kendoButton fillMode=\"flat\" (click)=\"closeLogsPanel()\" class=\"window-close-btn\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </kendo-window-titlebar>\n\n <div class=\"drilldown-content\">\n <mj-loading *ngIf=\"IsLoadingLogs\" text=\"Loading requests...\"></mj-loading>\n <div class=\"drilldown-logs\" *ngIf=\"!IsLoadingLogs\">\n <div class=\"logs-table\">\n <div class=\"logs-table-header\">\n <span class=\"col-time\">Time</span>\n <span class=\"col-key\">API Key</span>\n <span class=\"col-method\">Method</span>\n <span class=\"col-endpoint\">Endpoint</span>\n <span class=\"col-status\">Status</span>\n <span class=\"col-duration\">Duration</span>\n </div>\n <div class=\"logs-table-body scrollable\">\n <div class=\"log-row\" *ngFor=\"let log of RecentLogs\">\n <span class=\"col-time\">{{formatDate(log.timestamp)}}</span>\n <span class=\"col-key\">{{log.keyLabel}}</span>\n <span class=\"col-method\">\n <span class=\"method-badge\" [ngClass]=\"getMethodClass(log.method)\">\n {{log.method}}\n </span>\n </span>\n <span class=\"col-endpoint\">{{log.endpoint}}</span>\n <span class=\"col-status\" [ngClass]=\"getStatusClass(log.statusCode)\">\n {{log.statusCode}}\n </span>\n <span class=\"col-duration\">{{log.responseTime}}ms</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </kendo-window>\n</div>\n", styles: [".usage-panel {\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 24px;\n background: #f8fafc;\n min-height: 100%;\n}\n\n/* Header */\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 24px;\n flex-wrap: wrap;\n}\n\n.header-left {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 24px;\n font-weight: 700;\n color: #1f2937;\n}\n\n.panel-title i {\n color: #6366f1;\n}\n\n.panel-subtitle {\n margin: 0;\n font-size: 14px;\n color: #6b7280;\n}\n\n/* Time Filters */\n.time-filters {\n display: flex;\n gap: 4px;\n background: white;\n padding: 4px;\n border-radius: 10px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.time-btn {\n padding: 8px 16px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: #6b7280;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.time-btn:hover {\n color: #374151;\n background: #f3f4f6;\n}\n\n.time-btn.active {\n background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);\n color: white;\n box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);\n}\n\n/* KPI Grid */\n.kpi-grid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 16px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px 20px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n transition: all 0.2s ease;\n}\n\n.kpi-card:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n}\n\n.kpi-card.success {\n background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);\n}\n\n.kpi-card.warning {\n background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n}\n\n.kpi-icon {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n font-size: 18px;\n}\n\n.kpi-icon.requests {\n background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);\n color: #2563eb;\n}\n\n.kpi-icon.success-rate {\n background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);\n color: #059669;\n}\n\n.kpi-icon.errors {\n background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);\n color: #dc2626;\n}\n\n.kpi-icon.response-time {\n background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%);\n color: #4f46e5;\n}\n\n.kpi-icon.keys {\n background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n color: #d97706;\n}\n\n.kpi-icon.endpoints {\n background: linear-gradient(135deg, #f3e8ff 0%, #e9d5ff 100%);\n color: #7c3aed;\n}\n\n.kpi-content {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.kpi-value {\n font-size: 22px;\n font-weight: 700;\n color: #1f2937;\n}\n\n.kpi-label {\n font-size: 12px;\n color: #6b7280;\n}\n\n/* Chart Section */\n.chart-section {\n background: white;\n border-radius: 12px;\n padding: 20px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.chart-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.chart-header h4 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #1f2937;\n}\n\n.chart-legend {\n display: flex;\n gap: 16px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: #6b7280;\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n}\n\n.legend-color.requests {\n background: #6366f1;\n}\n\n.legend-color.errors {\n background: #ef4444;\n}\n\n.chart-container {\n display: flex;\n height: 200px;\n gap: 8px;\n}\n\n.chart-bars {\n flex: 1;\n display: flex;\n align-items: flex-end;\n gap: 4px;\n padding-bottom: 24px;\n}\n\n.bar-group {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n min-width: 0;\n}\n\n.bar-wrapper {\n width: 100%;\n height: 160px;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n}\n\n.bar {\n width: 100%;\n max-width: 32px;\n border-radius: 4px 4px 0 0;\n transition: all 0.3s ease;\n position: relative;\n}\n\n.bar.requests-bar {\n background: linear-gradient(180deg, #6366f1 0%, #818cf8 100%);\n}\n\n.bar.requests-bar:hover {\n background: linear-gradient(180deg, #4f46e5 0%, #6366f1 100%);\n}\n\n.bar.errors-bar {\n position: absolute;\n bottom: 0;\n left: 0;\n width: 100%;\n background: #ef4444;\n border-radius: 0;\n}\n\n.bar-label {\n margin-top: 8px;\n font-size: 10px;\n color: #9ca3af;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n max-width: 100%;\n}\n\n.chart-y-axis {\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n padding-bottom: 24px;\n font-size: 10px;\n color: #9ca3af;\n text-align: right;\n min-width: 40px;\n}\n\n.empty-chart {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: #9ca3af;\n}\n\n.empty-chart i {\n font-size: 32px;\n margin-bottom: 8px;\n opacity: 0.5;\n}\n\n/* Breakdown Grid */\n.breakdown-grid {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n gap: 20px;\n}\n\n.breakdown-card {\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n}\n\n.breakdown-header {\n padding: 16px 20px;\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n}\n\n.breakdown-header h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.breakdown-header h4 i {\n color: #6b7280;\n}\n\n.breakdown-content {\n padding: 12px;\n max-height: 280px;\n overflow-y: auto;\n}\n\n/* Endpoint List */\n.endpoint-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.endpoint-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 12px;\n background: #f9fafb;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.endpoint-item:hover {\n background: #f3f4f6;\n}\n\n.endpoint-info {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex: 1;\n}\n\n.method-badge {\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n\n.method-get { background: #dbeafe; color: #2563eb; }\n.method-post { background: #d1fae5; color: #059669; }\n.method-put { background: #fef3c7; color: #d97706; }\n.method-delete { background: #fee2e2; color: #dc2626; }\n.method-other { background: #f3f4f6; color: #6b7280; }\n\n.endpoint-path {\n font-size: 12px;\n font-family: 'Fira Code', monospace;\n color: #374151;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.endpoint-stats {\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.endpoint-requests {\n font-weight: 600;\n color: #6366f1;\n}\n\n.endpoint-time {\n color: #6b7280;\n}\n\n.endpoint-error {\n color: #10b981;\n}\n\n.endpoint-error.has-errors {\n color: #ef4444;\n font-weight: 500;\n}\n\n/* Key List */\n.key-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.key-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 12px;\n background: #f9fafb;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item:hover {\n background: #f3f4f6;\n}\n\n.key-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.key-label {\n font-size: 13px;\n font-weight: 500;\n color: #374151;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-last-used {\n font-size: 11px;\n color: #9ca3af;\n}\n\n.key-requests {\n font-size: 14px;\n font-weight: 600;\n color: #6366f1;\n}\n\n/* Status Distribution */\n.status-distribution {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.status-bar {\n display: flex;\n height: 24px;\n border-radius: 6px;\n overflow: hidden;\n background: #f3f4f6;\n}\n\n.status-segment {\n transition: all 0.3s ease;\n}\n\n.status-segment:hover {\n filter: brightness(1.1);\n}\n\n.status-legend {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.status-legend-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n}\n\n.status-color {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n}\n\n.status-label {\n flex: 1;\n color: #374151;\n}\n\n.status-count {\n color: #6b7280;\n font-weight: 500;\n}\n\n/* Logs Section */\n.logs-section {\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n}\n\n.logs-header {\n padding: 16px 20px;\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n}\n\n.logs-header h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.logs-header h4 i {\n color: #6b7280;\n}\n\n.logs-table {\n width: 100%;\n}\n\n.logs-table-header {\n display: grid;\n grid-template-columns: 100px 120px 70px 1fr 70px 80px;\n gap: 12px;\n padding: 12px 20px;\n background: #f3f4f6;\n font-size: 11px;\n font-weight: 600;\n color: #6b7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.logs-table-body {\n max-height: 320px;\n overflow-y: auto;\n}\n\n.logs-table-body.scrollable {\n max-height: 380px;\n}\n\n.log-row {\n display: grid;\n grid-template-columns: 100px 120px 70px 1fr 70px 80px;\n gap: 12px;\n padding: 12px 20px;\n border-bottom: 1px solid #f3f4f6;\n font-size: 13px;\n align-items: center;\n transition: background 0.2s ease;\n}\n\n.log-row:hover {\n background: #f9fafb;\n}\n\n.col-time {\n color: #6b7280;\n font-size: 12px;\n}\n\n.col-key {\n color: #374151;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.col-endpoint {\n font-family: 'Fira Code', monospace;\n font-size: 12px;\n color: #374151;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.col-status {\n font-weight: 600;\n text-align: center;\n}\n\n.col-status.status-success { color: #10b981; }\n.col-status.status-info { color: #3b82f6; }\n.col-status.status-warning { color: #f59e0b; }\n.col-status.status-error { color: #ef4444; }\n\n.col-duration {\n color: #6b7280;\n text-align: right;\n}\n\n/* Empty States */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px 20px;\n color: #9ca3af;\n text-align: center;\n}\n\n.empty-state i {\n font-size: 32px;\n margin-bottom: 8px;\n opacity: 0.5;\n}\n\n.empty-state span {\n font-size: 13px;\n font-weight: 500;\n color: #6b7280;\n}\n\n.empty-state.large {\n padding: 48px 24px;\n}\n\n.empty-state.large i {\n font-size: 48px;\n}\n\n.empty-state p {\n margin: 8px 0 0 0;\n font-size: 12px;\n}\n\n/* Drill-down Window */\n.drilldown-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 15px;\n}\n\n.drilldown-title i {\n color: #6366f1;\n}\n\n.filter-badge {\n padding: 4px 10px;\n background: #e0e7ff;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: #4f46e5;\n}\n\n.window-close-btn {\n margin-left: auto;\n color: #9ca3af;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n}\n\n.window-close-btn:hover {\n color: #374151;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.drilldown-content {\n height: 100%;\n overflow: hidden;\n}\n\n.drilldown-logs {\n height: 100%;\n}\n\n/* Kendo Window Styling */\n:host ::ng-deep kendo-window {\n border-radius: 12px !important;\n overflow: hidden;\n box-shadow: 0 20px 50px rgba(0, 0, 0, 0.15) !important;\n}\n\n:host ::ng-deep kendo-window .k-window-content {\n padding: 0 !important;\n}\n\n:host ::ng-deep kendo-window-titlebar {\n padding: 16px 20px !important;\n background: #f9fafb !important;\n border-bottom: 1px solid #e5e7eb !important;\n}\n\n/* Responsive */\n@media (max-width: 1400px) {\n .kpi-grid {\n grid-template-columns: repeat(3, 1fr);\n }\n}\n\n@media (max-width: 1200px) {\n .breakdown-grid {\n grid-template-columns: 1fr 1fr;\n }\n}\n\n@media (max-width: 900px) {\n .kpi-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .breakdown-grid {\n grid-template-columns: 1fr;\n }\n\n .logs-table-header,\n .log-row {\n grid-template-columns: 80px 100px 60px 1fr 60px;\n }\n\n .col-duration {\n display: none;\n }\n}\n\n@media (max-width: 600px) {\n .panel-header {\n flex-direction: column;\n }\n\n .time-filters {\n width: 100%;\n justify-content: center;\n }\n\n .kpi-grid {\n grid-template-columns: 1fr;\n }\n\n .logs-table-header,\n .log-row {\n grid-template-columns: 1fr 60px;\n }\n\n .col-key,\n .col-method,\n .col-endpoint {\n display: none;\n }\n}\n"] }]
|
|
1011
|
+
}], () => [{ type: i0.ChangeDetectorRef }], null); })();
|
|
1012
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(APIUsagePanelComponent, { className: "APIUsagePanelComponent", filePath: "src/APIKeys/api-usage-panel.component.ts", lineNumber: 66 }); })();
|
|
1013
|
+
//# sourceMappingURL=api-usage-panel.component.js.map
|