@strapi-community/plugin-io 1.0.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.
@@ -0,0 +1,752 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { useFetchClient, useNotification } from "@strapi/strapi/admin";
4
+ import styled, { css, keyframes } from "styled-components";
5
+ import { Box, Loader, Flex, Field, TextInput, Badge, Typography } from "@strapi/design-system";
6
+ import { u as useIntl } from "./index-CEh8vkxY.mjs";
7
+ import { P as PLUGIN_ID } from "./index-DLXtrAtk.mjs";
8
+ const UsersIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" }) });
9
+ const BoltIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m3.75 13.5 10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75Z" }) });
10
+ const ChartBarIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" }) });
11
+ const HomeIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" }) });
12
+ const ArrowPathIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" }) });
13
+ const TrashIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" }) });
14
+ const PlayIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z" }) });
15
+ const SignalIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9.348 14.652a3.75 3.75 0 0 1 0-5.304m5.304 0a3.75 3.75 0 0 1 0 5.304m-7.425 2.121a6.75 6.75 0 0 1 0-9.546m9.546 0a6.75 6.75 0 0 1 0 9.546M5.106 18.894c-3.808-3.807-3.808-9.98 0-13.788m13.788 0c3.808 3.807 3.808 9.98 0 13.788M12 12h.008v.008H12V12Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" }) });
16
+ const customColors = {
17
+ primary: { 100: "#E0F2FE", 500: "#0EA5E9", 600: "#0284C7" },
18
+ secondary: { 100: "#EDE9FE", 500: "#A855F7", 600: "#9333EA" },
19
+ success: { 100: "#DCFCE7", 500: "#22C55E", 600: "#16A34A" },
20
+ warning: { 100: "#FEF3C7", 500: "#F59E0B", 600: "#D97706" }
21
+ };
22
+ const fadeIn = keyframes`
23
+ from { opacity: 0; transform: translateY(20px); }
24
+ to { opacity: 1; transform: translateY(0); }
25
+ `;
26
+ const shimmer = keyframes`
27
+ 0% { background-position: -200% 0; }
28
+ 100% { background-position: 200% 0; }
29
+ `;
30
+ const float = keyframes`
31
+ 0%, 100% { transform: translateY(0); }
32
+ 50% { transform: translateY(-8px); }
33
+ `;
34
+ const Container = styled(Box)`
35
+ ${css`animation: ${fadeIn} 0.6s;`}
36
+ min-height: 100vh;
37
+ max-width: 1440px;
38
+ margin: 0 auto;
39
+ padding: 24px 16px 0;
40
+
41
+ @media (min-width: 768px) {
42
+ padding: 32px 24px 0;
43
+ }
44
+ `;
45
+ const Header = styled(Box)`
46
+ background: linear-gradient(135deg, ${customColors.primary[600]} 0%, ${customColors.secondary[600]} 100%);
47
+ border-radius: 12px;
48
+ padding: 20px 16px;
49
+ margin-bottom: 20px;
50
+ position: relative;
51
+ overflow: hidden;
52
+ box-shadow: ${({ theme }) => theme.shadows.tableShadow};
53
+
54
+ @media (min-width: 768px) {
55
+ border-radius: 16px;
56
+ padding: 32px 48px;
57
+ margin-bottom: 32px;
58
+ }
59
+
60
+ &::before {
61
+ content: '';
62
+ position: absolute;
63
+ top: 0;
64
+ left: -100%;
65
+ width: 200%;
66
+ height: 100%;
67
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.15), transparent);
68
+ ${css`animation: ${shimmer} 3s infinite;`}
69
+ }
70
+ `;
71
+ const Title = styled(Typography)`
72
+ color: #fff;
73
+ font-size: 1.5rem;
74
+ font-weight: 700;
75
+ display: flex;
76
+ align-items: center;
77
+ gap: 10px;
78
+ margin-bottom: 6px;
79
+
80
+ @media (min-width: 768px) {
81
+ font-size: 2.25rem;
82
+ gap: 16px;
83
+ margin-bottom: 8px;
84
+ }
85
+
86
+ svg {
87
+ width: 24px;
88
+ height: 24px;
89
+ ${css`animation: ${float} 3s ease-in-out infinite;`}
90
+
91
+ @media (min-width: 768px) {
92
+ width: 32px;
93
+ height: 32px;
94
+ }
95
+ }
96
+ `;
97
+ const Subtitle = styled(Typography)`
98
+ color: rgba(255,255,255,0.95);
99
+ font-size: 0.875rem;
100
+
101
+ @media (min-width: 768px) {
102
+ font-size: 1rem;
103
+ }
104
+ `;
105
+ const StatsGrid = styled.div`
106
+ display: grid;
107
+ grid-template-columns: repeat(2, 1fr);
108
+ gap: 12px;
109
+ margin-bottom: 24px;
110
+
111
+ @media (min-width: 640px) {
112
+ gap: 16px;
113
+ margin-bottom: 32px;
114
+ }
115
+
116
+ @media (min-width: 1024px) {
117
+ grid-template-columns: repeat(4, 1fr);
118
+ gap: 24px;
119
+ margin-bottom: 40px;
120
+ }
121
+ `;
122
+ const StatCard = styled(Box)`
123
+ background: ${({ theme }) => theme.colors.neutral0};
124
+ border-radius: 10px;
125
+ padding: 16px;
126
+ transition: all 0.2s;
127
+ ${css`animation: ${fadeIn} 0.5s backwards;`}
128
+ animation-delay: ${(p) => p.$delay || "0s"};
129
+ box-shadow: ${({ theme }) => theme.shadows.filterShadow};
130
+ border: 1px solid ${({ theme }) => theme.colors.neutral200};
131
+ text-align: center;
132
+ display: flex;
133
+ flex-direction: column;
134
+ align-items: center;
135
+
136
+ @media (min-width: 640px) {
137
+ border-radius: 12px;
138
+ padding: 20px;
139
+ }
140
+
141
+ @media (min-width: 1024px) {
142
+ padding: 32px;
143
+ }
144
+
145
+ &:hover {
146
+ transform: translateY(-4px);
147
+ box-shadow: ${({ theme }) => theme.shadows.tableShadow};
148
+ border-color: ${(p) => p.$borderColor || customColors.primary[500]};
149
+
150
+ .stat-icon {
151
+ transform: scale(1.1);
152
+ }
153
+
154
+ .stat-value {
155
+ transform: scale(1.05);
156
+ color: ${(p) => p.$accentColor || customColors.primary[600]};
157
+ }
158
+ }
159
+ `;
160
+ const StatIcon = styled(Box)`
161
+ width: 48px;
162
+ height: 48px;
163
+ border-radius: 10px;
164
+ display: flex;
165
+ align-items: center;
166
+ justify-content: center;
167
+ background: ${(p) => p.$bg || customColors.primary[100]};
168
+ transition: all 0.2s;
169
+ margin: 0 auto 12px;
170
+ box-shadow: ${({ theme }) => theme.shadows.filterShadow};
171
+
172
+ @media (min-width: 640px) {
173
+ width: 60px;
174
+ height: 60px;
175
+ border-radius: 12px;
176
+ margin-bottom: 16px;
177
+ }
178
+
179
+ @media (min-width: 1024px) {
180
+ width: 80px;
181
+ height: 80px;
182
+ margin-bottom: 24px;
183
+ }
184
+
185
+ svg {
186
+ width: 24px;
187
+ height: 24px;
188
+ color: ${(p) => p.$color || customColors.primary[600]};
189
+
190
+ @media (min-width: 640px) {
191
+ width: 30px;
192
+ height: 30px;
193
+ }
194
+
195
+ @media (min-width: 1024px) {
196
+ width: 40px;
197
+ height: 40px;
198
+ }
199
+ }
200
+ `;
201
+ const StatValue = styled(Typography)`
202
+ font-size: 2rem;
203
+ font-weight: 700;
204
+ color: ${({ theme }) => theme.colors.neutral800};
205
+ line-height: 1;
206
+ margin-bottom: 6px;
207
+ transition: all 0.2s;
208
+
209
+ @media (min-width: 640px) {
210
+ font-size: 2.5rem;
211
+ margin-bottom: 8px;
212
+ }
213
+
214
+ @media (min-width: 1024px) {
215
+ font-size: 3.5rem;
216
+ margin-bottom: 12px;
217
+ }
218
+ `;
219
+ const StatLabel = styled(Typography)`
220
+ font-size: 0.75rem;
221
+ color: ${({ theme }) => theme.colors.neutral600};
222
+ font-weight: 500;
223
+
224
+ @media (min-width: 640px) {
225
+ font-size: 0.875rem;
226
+ }
227
+
228
+ @media (min-width: 1024px) {
229
+ font-size: 1rem;
230
+ }
231
+ `;
232
+ const Card = styled(Box)`
233
+ background: ${({ theme }) => theme.colors.neutral0};
234
+ border-radius: 10px;
235
+ padding: 16px;
236
+ box-shadow: ${({ theme }) => theme.shadows.filterShadow};
237
+ border: 1px solid ${({ theme }) => theme.colors.neutral200};
238
+ margin-bottom: 16px;
239
+ transition: all 0.2s;
240
+
241
+ @media (min-width: 640px) {
242
+ border-radius: 12px;
243
+ padding: 20px;
244
+ margin-bottom: 20px;
245
+ }
246
+
247
+ @media (min-width: 1024px) {
248
+ padding: 28px;
249
+ margin-bottom: 28px;
250
+ box-shadow: ${({ theme }) => theme.shadows.tableShadow};
251
+ }
252
+
253
+ &:hover {
254
+ box-shadow: ${({ theme }) => theme.shadows.tableShadow};
255
+ border-color: ${customColors.primary[100]};
256
+
257
+ @media (min-width: 1024px) {
258
+ box-shadow: ${({ theme }) => theme.shadows.popupShadow};
259
+ }
260
+ }
261
+ `;
262
+ const CardTitle = styled(Typography)`
263
+ font-size: 1rem;
264
+ font-weight: 700;
265
+ color: ${({ theme }) => theme.colors.neutral800};
266
+ margin-bottom: 12px;
267
+ display: flex;
268
+ align-items: center;
269
+ gap: 8px;
270
+
271
+ @media (min-width: 640px) {
272
+ font-size: 1.125rem;
273
+ margin-bottom: 16px;
274
+ gap: 10px;
275
+ }
276
+
277
+ @media (min-width: 1024px) {
278
+ font-size: 1.25rem;
279
+ margin-bottom: 20px;
280
+ gap: 12px;
281
+ }
282
+
283
+ svg {
284
+ width: 20px;
285
+ height: 20px;
286
+ color: ${customColors.primary[600]};
287
+
288
+ @media (min-width: 1024px) {
289
+ width: 24px;
290
+ height: 24px;
291
+ }
292
+ }
293
+ `;
294
+ const ClientItem = styled(Box)`
295
+ background: ${({ theme }) => theme.colors.neutral100};
296
+ border-radius: 8px;
297
+ padding: 12px;
298
+ margin-bottom: 10px;
299
+ border: 1px solid ${({ theme }) => theme.colors.neutral200};
300
+ transition: all 0.15s;
301
+
302
+ @media (min-width: 640px) {
303
+ border-radius: 10px;
304
+ padding: 16px 20px;
305
+ margin-bottom: 12px;
306
+ }
307
+
308
+ &:hover {
309
+ background: ${({ theme }) => theme.colors.neutral150};
310
+ border-color: ${customColors.primary[100]};
311
+ }
312
+ `;
313
+ const EventItem = styled(Box)`
314
+ background: ${({ theme }) => theme.colors.neutral100};
315
+ border-radius: 8px;
316
+ padding: 10px 12px;
317
+ margin-bottom: 8px;
318
+ border: 1px solid ${({ theme }) => theme.colors.neutral200};
319
+ transition: all 0.15s;
320
+
321
+ @media (min-width: 640px) {
322
+ border-radius: 10px;
323
+ padding: 14px 18px;
324
+ margin-bottom: 10px;
325
+ }
326
+
327
+ &:hover {
328
+ background: ${({ theme }) => theme.colors.neutral150};
329
+ border-color: ${customColors.success[500]};
330
+ }
331
+ `;
332
+ const EmptyState = styled(Box)`
333
+ text-align: center;
334
+ padding: 24px 16px;
335
+ display: flex;
336
+ flex-direction: column;
337
+ align-items: center;
338
+ justify-content: center;
339
+
340
+ @media (min-width: 640px) {
341
+ padding: 36px 24px;
342
+ }
343
+
344
+ @media (min-width: 1024px) {
345
+ padding: 48px 24px;
346
+ }
347
+
348
+ svg {
349
+ width: 32px;
350
+ height: 32px;
351
+ color: ${({ theme }) => theme.colors.neutral400};
352
+ margin-bottom: 12px;
353
+
354
+ @media (min-width: 1024px) {
355
+ width: 48px;
356
+ height: 48px;
357
+ margin-bottom: 16px;
358
+ }
359
+ }
360
+ `;
361
+ const ActionButton = styled.button`
362
+ display: inline-flex;
363
+ align-items: center;
364
+ gap: 6px;
365
+ padding: 8px 12px;
366
+ border-radius: 6px;
367
+ font-size: 13px;
368
+ font-weight: 600;
369
+ cursor: pointer;
370
+ transition: all 0.15s;
371
+ border: none;
372
+ white-space: nowrap;
373
+
374
+ @media (min-width: 640px) {
375
+ gap: 8px;
376
+ padding: 10px 16px;
377
+ border-radius: 8px;
378
+ font-size: 14px;
379
+ }
380
+
381
+ @media (min-width: 1024px) {
382
+ padding: 10px 20px;
383
+ }
384
+
385
+ svg {
386
+ width: 16px;
387
+ height: 16px;
388
+
389
+ @media (min-width: 1024px) {
390
+ width: 18px;
391
+ height: 18px;
392
+ }
393
+ }
394
+
395
+ &.primary {
396
+ background: ${({ theme }) => theme.colors.primary600};
397
+ color: ${({ theme }) => theme.colors.neutral0};
398
+ box-shadow: 0 2px 8px rgba(14,165,233,0.3);
399
+
400
+ @media (min-width: 1024px) {
401
+ box-shadow: 0 4px 12px rgba(14,165,233,0.3);
402
+ }
403
+
404
+ &:hover {
405
+ transform: translateY(-2px);
406
+ background: ${({ theme }) => theme.colors.primary700};
407
+ box-shadow: 0 4px 12px rgba(14,165,233,0.4);
408
+
409
+ @media (min-width: 1024px) {
410
+ box-shadow: 0 6px 16px rgba(14,165,233,0.4);
411
+ }
412
+ }
413
+ }
414
+
415
+ &.secondary {
416
+ background: ${({ theme }) => theme.colors.neutral150};
417
+ color: ${({ theme }) => theme.colors.neutral700};
418
+ border: 1px solid ${({ theme }) => theme.colors.neutral200};
419
+
420
+ &:hover {
421
+ background: ${({ theme }) => theme.colors.neutral200};
422
+ }
423
+ }
424
+
425
+ &.danger {
426
+ background: ${({ theme }) => theme.colors.danger100};
427
+ color: ${({ theme }) => theme.colors.danger700};
428
+ border: 1px solid ${({ theme }) => theme.colors.danger200};
429
+
430
+ &:hover {
431
+ background: ${({ theme }) => theme.colors.danger200};
432
+ }
433
+ }
434
+ `;
435
+ const ResponsiveGrid = styled.div`
436
+ display: flex;
437
+ flex-direction: column;
438
+ gap: 16px;
439
+
440
+ @media (min-width: 1024px) {
441
+ display: grid;
442
+ grid-template-columns: repeat(2, 1fr);
443
+ gap: 24px;
444
+ }
445
+ `;
446
+ const ResponsiveBox = styled(Box)`
447
+ min-width: 100%;
448
+
449
+ @media (min-width: 1024px) {
450
+ min-width: 400px;
451
+ }
452
+ `;
453
+ const StyledSelect = styled.select`
454
+ padding: 6px 12px;
455
+ border-radius: 4px;
456
+ border: 1px solid ${({ theme }) => theme.colors.neutral200};
457
+ font-size: 13px;
458
+ cursor: pointer;
459
+ background: ${({ theme }) => theme.colors.neutral0};
460
+ color: ${({ theme }) => theme.colors.neutral800};
461
+ transition: all 0.15s;
462
+
463
+ &:hover {
464
+ border-color: ${({ theme }) => theme.colors.primary600};
465
+ }
466
+
467
+ &:focus {
468
+ outline: none;
469
+ border-color: ${({ theme }) => theme.colors.primary600};
470
+ box-shadow: 0 0 0 2px ${({ theme }) => theme.colors.primary100};
471
+ }
472
+
473
+ option {
474
+ background: ${({ theme }) => theme.colors.neutral0};
475
+ color: ${({ theme }) => theme.colors.neutral800};
476
+ }
477
+ `;
478
+ const MonitoringPage = () => {
479
+ const { get, post } = useFetchClient();
480
+ const { toggleNotification } = useNotification();
481
+ const { formatMessage } = useIntl();
482
+ const t = (id, def) => formatMessage({ id: `${PLUGIN_ID}.${id}`, defaultMessage: def });
483
+ const [stats, setStats] = useState(null);
484
+ const [eventLog, setEventLog] = useState([]);
485
+ const [isLoading, setIsLoading] = useState(true);
486
+ const [testEventName, setTestEventName] = useState("test");
487
+ const [testEventData, setTestEventData] = useState("{}");
488
+ const [eventTypeFilter, setEventTypeFilter] = useState("all");
489
+ const [searchTerm, setSearchTerm] = useState("");
490
+ useEffect(() => {
491
+ fetchStats();
492
+ const interval = setInterval(fetchStats, 6e4);
493
+ return () => clearInterval(interval);
494
+ }, []);
495
+ const fetchStats = async () => {
496
+ try {
497
+ const [s, l] = await Promise.all([
498
+ get(`/${PLUGIN_ID}/stats`),
499
+ get(`/${PLUGIN_ID}/event-log?limit=50`)
500
+ ]);
501
+ if (s.data?.data) setStats(s.data.data);
502
+ if (l.data?.data) setEventLog(l.data.data);
503
+ setIsLoading(false);
504
+ } catch (e) {
505
+ setIsLoading(false);
506
+ }
507
+ };
508
+ const handleSendTestEvent = async () => {
509
+ try {
510
+ const data = JSON.parse(testEventData);
511
+ await post(`/${PLUGIN_ID}/test-event`, { eventName: testEventName, data });
512
+ toggleNotification({ type: "success", message: "Test event sent!" });
513
+ fetchStats();
514
+ } catch {
515
+ toggleNotification({ type: "warning", message: "Invalid JSON" });
516
+ }
517
+ };
518
+ const handleResetStats = async () => {
519
+ try {
520
+ await post(`/${PLUGIN_ID}/reset-stats`);
521
+ toggleNotification({ type: "success", message: "Stats reset!" });
522
+ fetchStats();
523
+ } catch {
524
+ toggleNotification({ type: "danger", message: "Error" });
525
+ }
526
+ };
527
+ const filteredEvents = eventLog.filter((event) => {
528
+ if (eventTypeFilter !== "all" && event.type !== eventTypeFilter) return false;
529
+ if (searchTerm && !JSON.stringify(event).toLowerCase().includes(searchTerm.toLowerCase())) {
530
+ return false;
531
+ }
532
+ return true;
533
+ });
534
+ const eventTypes = ["all", ...new Set(eventLog.map((e) => e.type))];
535
+ if (isLoading) {
536
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(Box, { padding: 8, style: { textAlign: "center" }, children: /* @__PURE__ */ jsx(Loader, { children: "Loading..." }) }) });
537
+ }
538
+ return /* @__PURE__ */ jsxs(Container, { children: [
539
+ /* @__PURE__ */ jsx(Header, { children: /* @__PURE__ */ jsxs(
540
+ Flex,
541
+ {
542
+ direction: { base: "column", tablet: "row" },
543
+ justifyContent: "space-between",
544
+ alignItems: { base: "flex-start", tablet: "center" },
545
+ gap: 3,
546
+ style: { position: "relative", zIndex: 1 },
547
+ children: [
548
+ /* @__PURE__ */ jsxs(Box, { children: [
549
+ /* @__PURE__ */ jsxs(Title, { children: [
550
+ /* @__PURE__ */ jsx(SignalIcon, {}),
551
+ t("monitoring.title", "Monitoring & Logging")
552
+ ] }),
553
+ /* @__PURE__ */ jsx(Subtitle, { children: t("monitoring.description", "Real-time connection and event statistics") })
554
+ ] }),
555
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
556
+ /* @__PURE__ */ jsxs(ActionButton, { className: "secondary", onClick: fetchStats, children: [
557
+ /* @__PURE__ */ jsx(ArrowPathIcon, {}),
558
+ /* @__PURE__ */ jsx("span", { style: { display: "none" }, children: "Refresh" }),
559
+ /* @__PURE__ */ jsx("span", { style: { display: "inline" }, children: "↻" })
560
+ ] }),
561
+ /* @__PURE__ */ jsxs(ActionButton, { className: "danger", onClick: handleResetStats, children: [
562
+ /* @__PURE__ */ jsx(TrashIcon, {}),
563
+ /* @__PURE__ */ jsx("span", { style: { display: "none" }, children: "Reset" }),
564
+ /* @__PURE__ */ jsx("span", { style: { display: "inline" }, children: "✕" })
565
+ ] })
566
+ ] })
567
+ ]
568
+ }
569
+ ) }),
570
+ /* @__PURE__ */ jsxs(StatsGrid, { children: [
571
+ /* @__PURE__ */ jsxs(StatCard, { $delay: "0.1s", $borderColor: customColors.primary[500], $accentColor: customColors.primary[600], children: [
572
+ /* @__PURE__ */ jsx(StatIcon, { className: "stat-icon", $bg: customColors.primary[100], $color: customColors.primary[600], children: /* @__PURE__ */ jsx(UsersIcon, {}) }),
573
+ /* @__PURE__ */ jsx(StatValue, { className: "stat-value", children: stats?.connections?.connected || 0 }),
574
+ /* @__PURE__ */ jsx(StatLabel, { children: t("monitoring.connectedClients", "Connected Clients") })
575
+ ] }),
576
+ /* @__PURE__ */ jsxs(StatCard, { $delay: "0.2s", $borderColor: customColors.success[500], $accentColor: customColors.success[600], children: [
577
+ /* @__PURE__ */ jsx(StatIcon, { className: "stat-icon", $bg: customColors.success[100], $color: customColors.success[600], children: /* @__PURE__ */ jsx(BoltIcon, {}) }),
578
+ /* @__PURE__ */ jsx(StatValue, { className: "stat-value", children: stats?.events?.totalEvents || 0 }),
579
+ /* @__PURE__ */ jsx(StatLabel, { children: t("monitoring.totalEvents", "Total Events") })
580
+ ] }),
581
+ /* @__PURE__ */ jsxs(StatCard, { $delay: "0.3s", $borderColor: customColors.warning[500], $accentColor: customColors.warning[600], children: [
582
+ /* @__PURE__ */ jsx(StatIcon, { className: "stat-icon", $bg: customColors.warning[100], $color: customColors.warning[600], children: /* @__PURE__ */ jsx(ChartBarIcon, {}) }),
583
+ /* @__PURE__ */ jsx(StatValue, { className: "stat-value", children: stats?.events?.eventsPerSecond || "0.00" }),
584
+ /* @__PURE__ */ jsx(StatLabel, { children: t("monitoring.eventsPerSecond", "Events/Second") })
585
+ ] }),
586
+ /* @__PURE__ */ jsxs(StatCard, { $delay: "0.4s", $borderColor: customColors.secondary[500], $accentColor: customColors.secondary[600], children: [
587
+ /* @__PURE__ */ jsx(StatIcon, { className: "stat-icon", $bg: customColors.secondary[100], $color: customColors.secondary[600], children: /* @__PURE__ */ jsx(HomeIcon, {}) }),
588
+ /* @__PURE__ */ jsx(StatValue, { className: "stat-value", children: stats?.connections?.rooms?.length || 0 }),
589
+ /* @__PURE__ */ jsx(StatLabel, { children: t("monitoring.rooms", "Active Rooms") })
590
+ ] })
591
+ ] }),
592
+ /* @__PURE__ */ jsxs(Card, { children: [
593
+ /* @__PURE__ */ jsxs(CardTitle, { children: [
594
+ /* @__PURE__ */ jsx(PlayIcon, {}),
595
+ t("monitoring.testEvent", "Send Test Event")
596
+ ] }),
597
+ /* @__PURE__ */ jsxs(
598
+ Flex,
599
+ {
600
+ direction: { base: "column", tablet: "row" },
601
+ gap: 3,
602
+ alignItems: { base: "stretch", tablet: "flex-end" },
603
+ children: [
604
+ /* @__PURE__ */ jsx(Box, { style: { width: "100%", maxWidth: "220px" }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
605
+ /* @__PURE__ */ jsx(Field.Label, { children: "Event Name" }),
606
+ /* @__PURE__ */ jsx(
607
+ TextInput,
608
+ {
609
+ value: testEventName,
610
+ onChange: (e) => setTestEventName(e.target.value),
611
+ placeholder: "test"
612
+ }
613
+ )
614
+ ] }) }),
615
+ /* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
616
+ /* @__PURE__ */ jsx(Field.Label, { children: "Event Data (JSON)" }),
617
+ /* @__PURE__ */ jsx(
618
+ TextInput,
619
+ {
620
+ value: testEventData,
621
+ onChange: (e) => setTestEventData(e.target.value),
622
+ placeholder: '{"message":"Hello"}'
623
+ }
624
+ )
625
+ ] }) }),
626
+ /* @__PURE__ */ jsxs(ActionButton, { className: "primary", onClick: handleSendTestEvent, style: { alignSelf: "flex-end" }, children: [
627
+ /* @__PURE__ */ jsx(PlayIcon, {}),
628
+ "Send"
629
+ ] })
630
+ ]
631
+ }
632
+ )
633
+ ] }),
634
+ /* @__PURE__ */ jsxs(ResponsiveGrid, { children: [
635
+ /* @__PURE__ */ jsx(ResponsiveBox, { children: /* @__PURE__ */ jsxs(Card, { style: { minHeight: "280px" }, children: [
636
+ /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 3, children: [
637
+ /* @__PURE__ */ jsxs(CardTitle, { style: { marginBottom: 0 }, children: [
638
+ /* @__PURE__ */ jsx(UsersIcon, {}),
639
+ /* @__PURE__ */ jsx("span", { style: { display: "none" }, children: t("monitoring.connectedClientsList", "Connected Clients") }),
640
+ /* @__PURE__ */ jsx("span", { style: { display: "inline" }, children: "Clients" })
641
+ ] }),
642
+ /* @__PURE__ */ jsxs(Badge, { active: true, children: [
643
+ stats?.connections?.connected || 0,
644
+ " online"
645
+ ] })
646
+ ] }),
647
+ stats?.connections?.sockets?.length > 0 ? /* @__PURE__ */ jsx(Box, { style: { maxHeight: "220px", overflowY: "auto" }, children: stats.connections.sockets.map((s) => /* @__PURE__ */ jsx(ClientItem, { children: /* @__PURE__ */ jsxs(
648
+ Flex,
649
+ {
650
+ direction: { base: "column", tablet: "row" },
651
+ justifyContent: "space-between",
652
+ alignItems: { base: "flex-start", tablet: "center" },
653
+ gap: 2,
654
+ children: [
655
+ /* @__PURE__ */ jsxs(Box, { style: { flex: 1, minWidth: 0 }, children: [
656
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", children: s.user ? s.user.username : "Anonymous" }),
657
+ /* @__PURE__ */ jsxs(Flex, { gap: 1, wrap: "wrap", children: [
658
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: s.user?.email || s.handshake.address }),
659
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral400", children: "•" }),
660
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", style: { fontSize: "12px" }, children: s.user?.role || "public" })
661
+ ] }),
662
+ /* @__PURE__ */ jsx(
663
+ Typography,
664
+ {
665
+ variant: "pi",
666
+ textColor: "neutral300",
667
+ style: { fontFamily: "monospace", fontSize: "10px", wordBreak: "break-all" },
668
+ children: s.id
669
+ }
670
+ )
671
+ ] }),
672
+ /* @__PURE__ */ jsx(Badge, { active: s.connected, children: s.connected ? "Online" : "Offline" })
673
+ ]
674
+ }
675
+ ) }, s.id)) }) : /* @__PURE__ */ jsxs(EmptyState, { children: [
676
+ /* @__PURE__ */ jsx(UsersIcon, {}),
677
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", textColor: "neutral600", children: t("monitoring.noClients", "No clients connected") })
678
+ ] })
679
+ ] }) }),
680
+ /* @__PURE__ */ jsx(ResponsiveBox, { children: /* @__PURE__ */ jsxs(Card, { style: { minHeight: "280px" }, children: [
681
+ /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 2, children: [
682
+ /* @__PURE__ */ jsxs(CardTitle, { style: { marginBottom: 0 }, children: [
683
+ /* @__PURE__ */ jsx(BoltIcon, {}),
684
+ /* @__PURE__ */ jsx("span", { style: { display: "none" }, children: t("monitoring.eventLog", "Recent Events") }),
685
+ /* @__PURE__ */ jsx("span", { style: { display: "inline" }, children: "Events" })
686
+ ] }),
687
+ /* @__PURE__ */ jsx(Badge, { children: filteredEvents.length })
688
+ ] }),
689
+ /* @__PURE__ */ jsxs(
690
+ Flex,
691
+ {
692
+ direction: { base: "column", tablet: "row" },
693
+ gap: 2,
694
+ marginBottom: 3,
695
+ children: [
696
+ /* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
697
+ TextInput,
698
+ {
699
+ placeholder: t("monitoring.searchEvents", "Search events..."),
700
+ value: searchTerm,
701
+ onChange: (e) => setSearchTerm(e.target.value),
702
+ size: "S"
703
+ }
704
+ ) }),
705
+ /* @__PURE__ */ jsx(
706
+ StyledSelect,
707
+ {
708
+ value: eventTypeFilter,
709
+ onChange: (e) => setEventTypeFilter(e.target.value),
710
+ children: eventTypes.map((type) => /* @__PURE__ */ jsx("option", { value: type, children: type === "all" ? "All Types" : type }, type))
711
+ }
712
+ )
713
+ ]
714
+ }
715
+ ),
716
+ filteredEvents.length > 0 ? /* @__PURE__ */ jsx(Box, { style: { maxHeight: "180px", overflowY: "auto" }, children: filteredEvents.slice().reverse().slice(0, 10).map((e, i) => /* @__PURE__ */ jsx(EventItem, { children: /* @__PURE__ */ jsx(
717
+ Flex,
718
+ {
719
+ direction: { base: "column", tablet: "row" },
720
+ justifyContent: "space-between",
721
+ alignItems: { base: "flex-start", tablet: "center" },
722
+ gap: 2,
723
+ children: /* @__PURE__ */ jsxs(Box, { style: { flex: 1, minWidth: 0 }, children: [
724
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", marginBottom: 1, children: [
725
+ /* @__PURE__ */ jsx(Badge, { children: e.type }),
726
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", style: { fontSize: "11px" }, children: new Date(e.timestamp).toLocaleTimeString() })
727
+ ] }),
728
+ /* @__PURE__ */ jsxs(
729
+ Typography,
730
+ {
731
+ variant: "pi",
732
+ style: { fontFamily: "monospace", fontSize: "11px", wordBreak: "break-all" },
733
+ textColor: "neutral600",
734
+ children: [
735
+ JSON.stringify(e.data).substring(0, 50),
736
+ "..."
737
+ ]
738
+ }
739
+ )
740
+ ] })
741
+ }
742
+ ) }, i)) }) : /* @__PURE__ */ jsxs(EmptyState, { children: [
743
+ /* @__PURE__ */ jsx(BoltIcon, {}),
744
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", textColor: "neutral600", children: searchTerm || eventTypeFilter !== "all" ? t("monitoring.noMatchingEvents", "No matching events") : t("monitoring.noEvents", "No events logged") })
745
+ ] })
746
+ ] }) })
747
+ ] })
748
+ ] });
749
+ };
750
+ export {
751
+ MonitoringPage
752
+ };