@samanhappy/mcphub 1.0.36 → 1.0.37

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.
Files changed (84) hide show
  1. package/README.fr.md +47 -17
  2. package/README.md +44 -36
  3. package/README.zh.md +45 -35
  4. package/dist/controllers/groupController.js +63 -14
  5. package/dist/controllers/groupController.js.map +1 -1
  6. package/dist/controllers/serverController.js +18 -0
  7. package/dist/controllers/serverController.js.map +1 -1
  8. package/dist/dao/GroupDaoDbImpl.js +18 -0
  9. package/dist/dao/GroupDaoDbImpl.js.map +1 -1
  10. package/dist/db/connection.js +3 -2
  11. package/dist/db/connection.js.map +1 -1
  12. package/dist/db/entities/Group.js +9 -1
  13. package/dist/db/entities/Group.js.map +1 -1
  14. package/dist/db/groupSchema.js +29 -0
  15. package/dist/db/groupSchema.js.map +1 -0
  16. package/dist/routes/index.js +4 -3
  17. package/dist/routes/index.js.map +1 -1
  18. package/dist/services/groupService.js +57 -23
  19. package/dist/services/groupService.js.map +1 -1
  20. package/dist/services/logService.js +11 -2
  21. package/dist/services/logService.js.map +1 -1
  22. package/dist/services/mcpService.js +49 -12
  23. package/dist/services/mcpService.js.map +1 -1
  24. package/dist/services/oauthClientRegistration.js +22 -7
  25. package/dist/services/oauthClientRegistration.js.map +1 -1
  26. package/dist/services/oauthSettingsStore.js +3 -0
  27. package/dist/services/oauthSettingsStore.js.map +1 -1
  28. package/dist/services/sseService.js +63 -7
  29. package/dist/services/sseService.js.map +1 -1
  30. package/dist/utils/groupAccess.js +17 -0
  31. package/dist/utils/groupAccess.js.map +1 -0
  32. package/dist/utils/migration.js +2 -0
  33. package/dist/utils/migration.js.map +1 -1
  34. package/dist/utils/rateLimit.js +85 -18
  35. package/dist/utils/rateLimit.js.map +1 -1
  36. package/frontend/dist/assets/{ActivityPage-ZRx6b9hm.js → ActivityPage-Bx5-Jrxq.js} +2 -2
  37. package/frontend/dist/assets/{ActivityPage-ZRx6b9hm.js.map → ActivityPage-Bx5-Jrxq.js.map} +1 -1
  38. package/frontend/dist/assets/{CredentialsPage-C9vnh01H.js → CredentialsPage-BGbk_kBx.js} +2 -2
  39. package/frontend/dist/assets/{CredentialsPage-C9vnh01H.js.map → CredentialsPage-BGbk_kBx.js.map} +1 -1
  40. package/frontend/dist/assets/{Dashboard-BDGDQNz1.js → Dashboard-gHeXLPEn.js} +2 -2
  41. package/frontend/dist/assets/{Dashboard-BDGDQNz1.js.map → Dashboard-gHeXLPEn.js.map} +1 -1
  42. package/frontend/dist/assets/{EndpointCopy-BY51t0Ks.js → EndpointCopy-BRwX7Dpv.js} +2 -2
  43. package/frontend/dist/assets/{EndpointCopy-BY51t0Ks.js.map → EndpointCopy-BRwX7Dpv.js.map} +1 -1
  44. package/frontend/dist/assets/GroupsPage-grCAx55k.js +33 -0
  45. package/frontend/dist/assets/GroupsPage-grCAx55k.js.map +1 -0
  46. package/frontend/dist/assets/{LoginPage-CZOKlkR_.js → LoginPage-C7-m2jmB.js} +2 -2
  47. package/frontend/dist/assets/{LoginPage-CZOKlkR_.js.map → LoginPage-C7-m2jmB.js.map} +1 -1
  48. package/frontend/dist/assets/{LogsPage-FDWOOIPg.js → LogsPage-B00XTokA.js} +2 -2
  49. package/frontend/dist/assets/{LogsPage-FDWOOIPg.js.map → LogsPage-B00XTokA.js.map} +1 -1
  50. package/frontend/dist/assets/{MarketPage-DKfZgoIs.js → MarketPage-CVJMdSDD.js} +2 -2
  51. package/frontend/dist/assets/{MarketPage-DKfZgoIs.js.map → MarketPage-CVJMdSDD.js.map} +1 -1
  52. package/frontend/dist/assets/{OAuthConsentPage-Hk_DJ0dW.js → OAuthConsentPage-znW3HtpR.js} +2 -2
  53. package/frontend/dist/assets/{OAuthConsentPage-Hk_DJ0dW.js.map → OAuthConsentPage-znW3HtpR.js.map} +1 -1
  54. package/frontend/dist/assets/{PromptsPage-CT0C0_BI.js → PromptsPage-DGcNS3fO.js} +2 -2
  55. package/frontend/dist/assets/{PromptsPage-CT0C0_BI.js.map → PromptsPage-DGcNS3fO.js.map} +1 -1
  56. package/frontend/dist/assets/{ResourcesPage-CBgu-N5m.js → ResourcesPage-CfyZoadu.js} +2 -2
  57. package/frontend/dist/assets/{ResourcesPage-CBgu-N5m.js.map → ResourcesPage-CfyZoadu.js.map} +1 -1
  58. package/frontend/dist/assets/{ServersPage-CvcP8LFv.js → ServersPage-BlC0RdIu.js} +4 -4
  59. package/frontend/dist/assets/{ServersPage-CvcP8LFv.js.map → ServersPage-BlC0RdIu.js.map} +1 -1
  60. package/frontend/dist/assets/{SettingsPage-DDSVt_xk.js → SettingsPage-CiVNDyr_.js} +2 -2
  61. package/frontend/dist/assets/{SettingsPage-DDSVt_xk.js.map → SettingsPage-CiVNDyr_.js.map} +1 -1
  62. package/frontend/dist/assets/{StatusDot-uIIW4IuH.js → StatusDot-DYO56shE.js} +2 -2
  63. package/frontend/dist/assets/{StatusDot-uIIW4IuH.js.map → StatusDot-DYO56shE.js.map} +1 -1
  64. package/frontend/dist/assets/{ToggleGroup-BToroeZy.js → ToggleGroup-r8yGt_Fq.js} +2 -2
  65. package/frontend/dist/assets/{ToggleGroup-BToroeZy.js.map → ToggleGroup-r8yGt_Fq.js.map} +1 -1
  66. package/frontend/dist/assets/{UsersPage-BjgJjf6L.js → UsersPage-B3muXE90.js} +2 -2
  67. package/frontend/dist/assets/{UsersPage-BjgJjf6L.js.map → UsersPage-B3muXE90.js.map} +1 -1
  68. package/frontend/dist/assets/index-B-aT0HW5.js +3 -0
  69. package/frontend/dist/assets/index-B-aT0HW5.js.map +1 -0
  70. package/frontend/dist/assets/{resourceService-sD9dxx3E.js → resourceService-CSXOSi7M.js} +2 -2
  71. package/frontend/dist/assets/{resourceService-sD9dxx3E.js.map → resourceService-CSXOSi7M.js.map} +1 -1
  72. package/frontend/dist/assets/{useCostData-QoPbsqyD.js → useCostData-BOxUFQAH.js} +2 -2
  73. package/frontend/dist/assets/{useCostData-QoPbsqyD.js.map → useCostData-BOxUFQAH.js.map} +1 -1
  74. package/frontend/dist/assets/useSettingsData-DmpLlRI6.js +2 -0
  75. package/frontend/dist/assets/{useSettingsData-C4JrLqDh.js.map → useSettingsData-DmpLlRI6.js.map} +1 -1
  76. package/frontend/dist/assets/{variableDetection-iFAhGAKs.js → variableDetection-cmwwuSWB.js} +2 -2
  77. package/frontend/dist/assets/{variableDetection-iFAhGAKs.js.map → variableDetection-cmwwuSWB.js.map} +1 -1
  78. package/frontend/dist/index.html +1 -1
  79. package/package.json +1 -1
  80. package/frontend/dist/assets/GroupsPage-DyHyW7NW.js +0 -33
  81. package/frontend/dist/assets/GroupsPage-DyHyW7NW.js.map +0 -1
  82. package/frontend/dist/assets/index-DjNOC0Ov.js +0 -3
  83. package/frontend/dist/assets/index-DjNOC0Ov.js.map +0 -1
  84. package/frontend/dist/assets/useSettingsData-C4JrLqDh.js +0 -2
@@ -1,35 +1,102 @@
1
1
  import rateLimit from 'express-rate-limit';
2
+ import dotenv from 'dotenv';
3
+ import { logger } from './logger.js';
4
+ // Self-contained so the limits below do not depend on this module being
5
+ // evaluated after src/config, which also loads the environment.
6
+ dotenv.config({ quiet: true });
2
7
  const isTestEnv = process.env.NODE_ENV === 'test' ||
3
8
  process.env.JEST_WORKER_ID !== undefined ||
4
9
  process.env.VITEST_WORKER_ID !== undefined;
5
- export const createStandardRateLimiter = (options) => rateLimit({
6
- ...options,
7
- standardHeaders: true,
8
- legacyHeaders: false,
9
- skip: () => isTestEnv,
10
- });
10
+ /**
11
+ * Reads a positive integer from the environment, falling back to the built-in
12
+ * default when the variable is unset, empty, or not a positive integer. Every
13
+ * limit below keeps its previous value when the variable is absent, so this is
14
+ * opt-in for operators who need different thresholds.
15
+ */
16
+ const envInt = (name, fallback) => {
17
+ const raw = process.env[name];
18
+ if (raw === undefined || raw.trim() === '') {
19
+ return fallback;
20
+ }
21
+ const parsed = Number(raw);
22
+ if (!Number.isInteger(parsed) || parsed <= 0) {
23
+ logger.warn(`Ignoring invalid ${name}="${raw}"; expected a positive integer. Using ${fallback}.`);
24
+ return fallback;
25
+ }
26
+ return parsed;
27
+ };
28
+ /**
29
+ * Reads a request cap, additionally accepting `0` or `off` to mean "no limit".
30
+ *
31
+ * The value cannot simply be forwarded to express-rate-limit: since v7 a `limit`
32
+ * of 0 rejects every request instead of disabling the limiter, so an operator
33
+ * reaching for "unlimited" would lock themselves out completely. Disabling is
34
+ * expressed through `skip` instead.
35
+ */
36
+ const envLimit = (name, fallback) => {
37
+ const raw = process.env[name];
38
+ if (raw === undefined || raw.trim() === '') {
39
+ return fallback;
40
+ }
41
+ const normalized = raw.trim().toLowerCase();
42
+ if (normalized === '0' || normalized === 'off' || normalized === 'unlimited') {
43
+ logger.warn(`Rate limiting disabled by ${name}="${raw}". Requests to these routes are no longer capped; only do this where the deployment is protected by other means.`);
44
+ return UNLIMITED;
45
+ }
46
+ return envInt(name, fallback);
47
+ };
48
+ const UNLIMITED = Symbol('unlimited');
49
+ const MINUTES_15 = 15 * 60 * 1000;
50
+ const MINUTE_1 = 60 * 1000;
51
+ export const createStandardRateLimiter = (options) => {
52
+ const { max, ...rest } = options;
53
+ return rateLimit({
54
+ ...rest,
55
+ // Kept positive so the middleware never blocks; `skip` is what disables it.
56
+ max: max === UNLIMITED ? Number.MAX_SAFE_INTEGER : max,
57
+ standardHeaders: true,
58
+ legacyHeaders: false,
59
+ skip: () => isTestEnv || max === UNLIMITED,
60
+ // The rest of the API answers with JSON; without this the 429 body is bare
61
+ // text, so clients that parse the response as JSON lose the error entirely.
62
+ message: { success: false, message: 'Too many requests, please try again later.' },
63
+ });
64
+ };
11
65
  export const templateRateLimiter = createStandardRateLimiter({
12
- windowMs: 15 * 60 * 1000,
13
- max: 200,
66
+ windowMs: envInt('TEMPLATE_RATE_LIMIT_WINDOW_MS', MINUTES_15),
67
+ max: envLimit('TEMPLATE_RATE_LIMIT_MAX', 200),
14
68
  });
15
69
  export const authenticatedRouteRateLimiter = createStandardRateLimiter({
16
- windowMs: 15 * 60 * 1000,
17
- max: 600,
70
+ windowMs: envInt('API_RATE_LIMIT_WINDOW_MS', MINUTES_15),
71
+ max: envLimit('API_RATE_LIMIT_MAX', 600),
18
72
  });
19
73
  export const hostedInternalEventRateLimiter = createStandardRateLimiter({
20
- windowMs: 60 * 1000,
21
- max: 600,
74
+ windowMs: envInt('HOSTED_EVENT_RATE_LIMIT_WINDOW_MS', MINUTE_1),
75
+ max: envLimit('HOSTED_EVENT_RATE_LIMIT_MAX', 600),
22
76
  });
23
77
  export const mcpConnectionRateLimiter = createStandardRateLimiter({
24
- windowMs: 60 * 1000,
25
- max: 480,
78
+ windowMs: envInt('MCP_RATE_LIMIT_WINDOW_MS', MINUTE_1),
79
+ max: envLimit('MCP_RATE_LIMIT_MAX', 480),
26
80
  });
27
81
  export const authAttemptRateLimiter = createStandardRateLimiter({
28
- windowMs: 15 * 60 * 1000,
29
- max: 20,
82
+ windowMs: envInt('AUTH_RATE_LIMIT_WINDOW_MS', MINUTES_15),
83
+ max: envLimit('AUTH_RATE_LIMIT_MAX', 20),
84
+ // Brute-force protection is about failed credentials. Counting successful
85
+ // logins adds no protection but locks out legitimate clients that hold no
86
+ // session -- API consumers and service accounts re-authenticate on every
87
+ // token expiry, and a burst of concurrent renewals exhausts the window.
88
+ skipSuccessfulRequests: true,
89
+ });
90
+ // /auth/register is ungated and a successful request creates an account, so this
91
+ // limiter deliberately counts every request -- successes are the thing being
92
+ // capped. It is separate from the login limiter so the two cannot exhaust each
93
+ // other's budget.
94
+ export const authRegistrationRateLimiter = createStandardRateLimiter({
95
+ windowMs: envInt('REGISTER_RATE_LIMIT_WINDOW_MS', MINUTES_15),
96
+ max: envLimit('REGISTER_RATE_LIMIT_MAX', 20),
30
97
  });
31
98
  export const spaPageRateLimiter = createStandardRateLimiter({
32
- windowMs: 60 * 1000,
33
- max: 600,
99
+ windowMs: envInt('SPA_RATE_LIMIT_WINDOW_MS', MINUTE_1),
100
+ max: envLimit('SPA_RATE_LIMIT_MAX', 600),
34
101
  });
35
102
  //# sourceMappingURL=rateLimit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../src/utils/rateLimit.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAE3C,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;IAC/B,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,SAAS;IACxC,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC;AAE7C,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,OAA0C,EAAE,EAAE,CACtF,SAAS,CAAC;IACR,GAAG,OAAO;IACV,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,KAAK;IACpB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;CACtB,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;IAC3D,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;IACxB,GAAG,EAAE,GAAG;CACT,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,yBAAyB,CAAC;IACrE,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;IACxB,GAAG,EAAE,GAAG;CACT,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,8BAA8B,GAAG,yBAAyB,CAAC;IACtE,QAAQ,EAAE,EAAE,GAAG,IAAI;IACnB,GAAG,EAAE,GAAG;CACT,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,yBAAyB,CAAC;IAChE,QAAQ,EAAE,EAAE,GAAG,IAAI;IACnB,GAAG,EAAE,GAAG;CACT,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;IAC9D,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;IACxB,GAAG,EAAE,EAAE;CACR,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;IAC1D,QAAQ,EAAE,EAAE,GAAG,IAAI;IACnB,GAAG,EAAE,GAAG;CACT,CAAC,CAAC"}
1
+ {"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../src/utils/rateLimit.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAC3C,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,wEAAwE;AACxE,gEAAgE;AAChE,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAE/B,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;IAC/B,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,SAAS;IACxC,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAU,EAAE;IACxD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CACT,oBAAoB,IAAI,KAAK,GAAG,yCAAyC,QAAQ,GAAG,CACrF,CAAC;QACF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,QAAgB,EAA6B,EAAE;IAC7E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;QAC7E,MAAM,CAAC,IAAI,CACT,6BAA6B,IAAI,KAAK,GAAG,kHAAkH,CAC5J,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAEtC,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAClC,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC;AAE3B,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,OAIzC,EAAE,EAAE;IACH,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEjC,OAAO,SAAS,CAAC;QACf,GAAG,IAAI;QACP,4EAA4E;QAC5E,GAAG,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG;QACtD,eAAe,EAAE,IAAI;QACrB,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,IAAI,GAAG,KAAK,SAAS;QAC1C,2EAA2E;QAC3E,4EAA4E;QAC5E,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,4CAA4C,EAAE;KACnF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;IAC3D,QAAQ,EAAE,MAAM,CAAC,+BAA+B,EAAE,UAAU,CAAC;IAC7D,GAAG,EAAE,QAAQ,CAAC,yBAAyB,EAAE,GAAG,CAAC;CAC9C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,yBAAyB,CAAC;IACrE,QAAQ,EAAE,MAAM,CAAC,0BAA0B,EAAE,UAAU,CAAC;IACxD,GAAG,EAAE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,CAAC;CACzC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,8BAA8B,GAAG,yBAAyB,CAAC;IACtE,QAAQ,EAAE,MAAM,CAAC,mCAAmC,EAAE,QAAQ,CAAC;IAC/D,GAAG,EAAE,QAAQ,CAAC,6BAA6B,EAAE,GAAG,CAAC;CAClD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,yBAAyB,CAAC;IAChE,QAAQ,EAAE,MAAM,CAAC,0BAA0B,EAAE,QAAQ,CAAC;IACtD,GAAG,EAAE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,CAAC;CACzC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;IAC9D,QAAQ,EAAE,MAAM,CAAC,2BAA2B,EAAE,UAAU,CAAC;IACzD,GAAG,EAAE,QAAQ,CAAC,qBAAqB,EAAE,EAAE,CAAC;IACxC,0EAA0E;IAC1E,0EAA0E;IAC1E,yEAAyE;IACzE,wEAAwE;IACxE,sBAAsB,EAAE,IAAI;CAC7B,CAAC,CAAC;AAEH,iFAAiF;AACjF,6EAA6E;AAC7E,+EAA+E;AAC/E,kBAAkB;AAClB,MAAM,CAAC,MAAM,2BAA2B,GAAG,yBAAyB,CAAC;IACnE,QAAQ,EAAE,MAAM,CAAC,+BAA+B,EAAE,UAAU,CAAC;IAC7D,GAAG,EAAE,QAAQ,CAAC,yBAAyB,EAAE,EAAE,CAAC;CAC7C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;IAC1D,QAAQ,EAAE,MAAM,CAAC,0BAA0B,EAAE,QAAQ,CAAC;IACtD,GAAG,EAAE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,CAAC;CACzC,CAAC,CAAC"}
@@ -1,2 +1,2 @@
1
- import{r,j as e}from"./framework-vendor-_YL27Pfc.js";import{r as ee,t as te,v as ae,w as se,x as le}from"./index-DjNOC0Ov.js";import{P as re}from"./Pagination-CLUvn47x.js";import{u as ie}from"./i18n-vendor-BMaj5qV8.js";import"./icons-vendor-VW-UwEhw.js";const I=["success","error"],ce=a=>I.includes(a),he=()=>{const{t:a}=ie(),[m,V]=r.useState([]),[n,$]=r.useState(null),[l,J]=r.useState(null),[i,U]=r.useState(null),[o,d]=r.useState(1),[j,G]=r.useState(10),[f,A]=r.useState(!0),[F,N]=r.useState(null),[c,H]=r.useState(null),[K,R]=r.useState(!1),[B,D]=r.useState({}),[p,w]=r.useState(""),[v,k]=r.useState(""),[x,S]=r.useState(""),[g,C]=r.useState(""),[y,L]=r.useState(""),[b,P]=r.useState(""),z=r.useCallback(async()=>{A(!0),N(null);try{const t={...B},[s,u,h]=await Promise.all([ee(o,j,t),te(t),ae()]);s!=null&&s.success&&Array.isArray(s.data)&&(V(s.data),s.pagination&&U(s.pagination)),u!=null&&u.success&&u.data&&$(u.data),h!=null&&h.success&&h.data&&J(h.data)}catch(t){console.error("Error fetching activity data:",t),N(a("activity.fetchError"))}finally{A(!1)}},[o,j,B,a]);r.useEffect(()=>{z()},[z]),r.useEffect(()=>{if(!i)return;const t=Math.max(1,i.totalPages||1);o>t&&d(t)},[i,o]);const W=async t=>{try{const s=await le(t.id);s!=null&&s.success&&s.data&&(H(s.data),R(!0))}catch(s){console.error("Error fetching activity details:",s)}},_=async()=>{var t;if(window.confirm(a("activity.confirmCleanup")))try{const s=await se(30);s!=null&&s.success&&(alert(a("activity.cleanupSuccess",{count:((t=s.data)==null?void 0:t.deletedCount)||0})),z())}catch(s){console.error("Error cleaning up activities:",s),alert(a("activity.cleanupError"))}},q=()=>{const t={};p&&(t.server=p),v&&(t.tool=v),x&&ce(x)&&(t.status=x),g&&(t.group=g),y&&(t.username=y),b&&(t.keyName=b),D(t),d(1)},O=()=>{w(""),k(""),S(""),C(""),L(""),P(""),D({}),d(1)},M=t=>t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(2)}s`:`${(t/6e4).toFixed(2)}m`,E=t=>new Date(t).toLocaleString(),T=t=>{if(!t)return null;try{return JSON.parse(t)}catch{return t}},Q=()=>n?e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4",children:[{label:a("activity.totalCalls"),value:n.totalCalls,tone:"default"},{label:a("activity.successCount"),value:n.successCount,tone:"ok"},{label:a("activity.errorCount"),value:n.errorCount,tone:"err"},{label:a("activity.avgDuration"),value:M(n.avgDuration),tone:"default"}].map(t=>e.jsxs("div",{className:"hub-card",style:{padding:"12px 14px"},children:[e.jsx("div",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:t.label}),e.jsx("div",{className:"hub-num",style:{fontSize:22,fontWeight:500,lineHeight:1.1,marginTop:6,letterSpacing:"-0.02em",color:t.tone==="ok"?"oklch(0.4 0.13 145)":t.tone==="err"?"oklch(0.45 0.18 25)":"var(--hub-ink)"},children:t.value})]},t.label))}):null,X=()=>e.jsx("div",{className:"hub-card px-4 py-3 mb-4",children:e.jsxs("div",{className:"flex flex-wrap gap-3 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-server",children:a("activity.server")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-server",type:"text",value:p,onChange:t=>w(t.target.value),placeholder:a("activity.searchServer"),className:"hub-input pr-9",list:"server-options"}),p&&e.jsx("button",{onClick:()=>w(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.servers)&&e.jsx("datalist",{id:"server-options",children:l.servers.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-tool",children:a("activity.tool")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-tool",type:"text",value:v,onChange:t=>k(t.target.value),placeholder:a("activity.searchTool"),className:"hub-input pr-9",list:"tool-options"}),v&&e.jsx("button",{onClick:()=>k(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.tools)&&e.jsx("datalist",{id:"tool-options",children:l.tools.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-status",children:a("activity.status")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-status",type:"text",value:x,onChange:t=>S(t.target.value.toLowerCase()),placeholder:a("activity.searchStatus"),className:"hub-input pr-9",list:"activity-status-options"}),x&&e.jsx("button",{onClick:()=>S(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),e.jsx("datalist",{id:"activity-status-options",children:I.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-group",children:a("activity.group")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-group",type:"text",value:g,onChange:t=>C(t.target.value),placeholder:a("activity.searchGroup"),className:"hub-input pr-9",list:"group-options"}),g&&e.jsx("button",{onClick:()=>C(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.groups)&&e.jsx("datalist",{id:"group-options",children:l.groups.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-username",children:a("activity.user")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-username",type:"text",value:y,onChange:t=>L(t.target.value),placeholder:a("activity.searchUsername"),className:"hub-input pr-9",list:"username-options"}),y&&e.jsx("button",{onClick:()=>L(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.usernames)&&e.jsx("datalist",{id:"username-options",children:l.usernames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-keyname",children:a("activity.keyName")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-keyname",type:"text",value:b,onChange:t=>P(t.target.value),placeholder:a("activity.searchKeyName"),className:"hub-input pr-9",list:"keyname-options"}),b&&e.jsx("button",{onClick:()=>P(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.keyNames)&&e.jsx("datalist",{id:"keyname-options",children:l.keyNames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-shrink-0 flex items-center gap-2",children:[e.jsxs("button",{onClick:q,className:"hub-btn primary whitespace-nowrap",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",clipRule:"evenodd"})}),a("common.search")]}),e.jsx("button",{onClick:O,className:"hub-btn whitespace-nowrap",children:a("common.clear")})]})]})}),Y=()=>m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("activity.noData")}):e.jsx("div",{className:"hub-card overflow-hidden",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full",children:[e.jsx("thead",{style:{background:"var(--hub-bg-2)"},children:e.jsx("tr",{children:[a("activity.timestamp"),a("activity.server"),a("activity.tool"),a("activity.duration"),a("activity.status"),a("activity.group"),a("activity.user"),a("activity.key"),a("activity.sourceIp"),a("common.actions")].map(t=>e.jsx("th",{className:"hub-mono",style:{padding:"9px 14px",textAlign:"left",fontSize:11,color:"var(--hub-ink-3)",textTransform:"uppercase",letterSpacing:"0.08em",fontWeight:500},children:t},t))})}),e.jsx("tbody",{children:m.map(t=>e.jsxs("tr",{className:"transition-colors hover:bg-[var(--hub-surface-hover)]",style:{borderTop:"1px solid var(--hub-line-2)"},children:[e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:E(t.timestamp)}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag",children:t.server})}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag accent",children:t.tool})}),e.jsx("td",{className:"hub-mono hub-num whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:M(t.duration)}),e.jsx("td",{style:{padding:"10px 14px"},className:"whitespace-nowrap",children:e.jsxs("span",{className:`hub-status ${t.status==="success"?"ok":"err"}`,children:[e.jsx("span",{className:"hub-dot"}),t.status==="success"?a("activity.statusSuccess"):a("activity.statusError")]})}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.group||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.username||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.keyName||"—"}),e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.sourceIp||"—"}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("button",{onClick:()=>W(t),className:"hub-btn ghost sm",style:{color:"var(--hub-accent)"},children:a("common.view")})})]},t.id))})]})})}),Z=()=>{if(!K||!c)return null;const t=T(c.input),s=T(c.output);return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50",children:e.jsxs("div",{className:"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden",style:{boxShadow:"0 8px 24px rgba(0,0,0,0.12)"},children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsx("h3",{className:"hub-card-title",children:a("activity.details")}),e.jsx("button",{onClick:()=>R(!1),className:"hub-icon-btn sm","aria-label":"close",children:e.jsx("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),e.jsxs("div",{className:"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 mb-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.timestamp")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:E(c.timestamp)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.duration")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:M(c.duration)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.server")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.server})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.tool")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.tool})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.status")}),e.jsx("span",{className:`px-2 py-1 rounded text-xs font-medium ${c.status==="success"?"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200":"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200"}`,children:c.status==="success"?a("activity.statusSuccess"):a("activity.statusError")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.group")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.group||"-"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.user")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.username||"-"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.sourceIp")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.sourceIp||"-"})]}),c.keyName&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.key")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.keyName})]})]}),c.errorMessage&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-red-500 mb-1",children:a("activity.errorMessage")}),e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200",children:c.errorMessage})]}),t&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.input")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof t=="string"?t:JSON.stringify(t,null,2)})]}),s&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.output")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof s=="string"?s:JSON.stringify(s,null,2)})]})]})]})})};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:a("activity.title")}),e.jsxs("p",{className:"hub-sub",children:[e.jsx("span",{className:"hub-num",children:(i==null?void 0:i.total)??m.length})," entries"]})]}),e.jsxs("button",{onClick:_,className:"hub-btn danger",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}),a("activity.cleanup")]})]}),F&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-4",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsx("span",{className:"truncate text-[13px]",children:F}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>N(null),"aria-label":"close",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3 w-3",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),f&&m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("app.loading")}):e.jsxs(e.Fragment,{children:[Q(),X(),Y(),e.jsxs("div",{className:"flex items-center mt-6",children:[e.jsx("div",{className:"flex-[2] text-sm text-gray-500 dark:text-gray-400",children:i&&a("common.showing",{start:(i.page-1)*i.limit+1,end:Math.min(i.page*i.limit,i.total),total:i.total})}),e.jsx("div",{className:"flex-[4] flex justify-center",children:i&&i.totalPages>1&&e.jsx(re,{currentPage:o,totalPages:i.totalPages,onPageChange:d,disabled:f})}),e.jsxs("div",{className:"flex-[2] flex items-center justify-end space-x-2",children:[e.jsxs("label",{htmlFor:"perPage",className:"text-sm text-gray-500 dark:text-gray-400",children:[a("common.itemsPerPage"),":"]}),e.jsxs("select",{id:"perPage",value:j,onChange:t=>{G(Number(t.target.value)),d(1)},disabled:f,className:"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed",children:[e.jsx("option",{value:10,children:"10"}),e.jsx("option",{value:20,children:"20"}),e.jsx("option",{value:50,children:"50"}),e.jsx("option",{value:100,children:"100"})]})]})]})]}),Z()]})};export{he as default};
2
- //# sourceMappingURL=ActivityPage-ZRx6b9hm.js.map
1
+ import{r,j as e}from"./framework-vendor-_YL27Pfc.js";import{r as ee,t as te,v as ae,w as se,x as le}from"./index-B-aT0HW5.js";import{P as re}from"./Pagination-CLUvn47x.js";import{u as ie}from"./i18n-vendor-BMaj5qV8.js";import"./icons-vendor-VW-UwEhw.js";const I=["success","error"],ce=a=>I.includes(a),he=()=>{const{t:a}=ie(),[m,V]=r.useState([]),[n,$]=r.useState(null),[l,J]=r.useState(null),[i,U]=r.useState(null),[o,d]=r.useState(1),[j,G]=r.useState(10),[f,A]=r.useState(!0),[F,N]=r.useState(null),[c,H]=r.useState(null),[K,R]=r.useState(!1),[B,D]=r.useState({}),[p,w]=r.useState(""),[v,k]=r.useState(""),[x,S]=r.useState(""),[g,C]=r.useState(""),[y,L]=r.useState(""),[b,P]=r.useState(""),z=r.useCallback(async()=>{A(!0),N(null);try{const t={...B},[s,u,h]=await Promise.all([ee(o,j,t),te(t),ae()]);s!=null&&s.success&&Array.isArray(s.data)&&(V(s.data),s.pagination&&U(s.pagination)),u!=null&&u.success&&u.data&&$(u.data),h!=null&&h.success&&h.data&&J(h.data)}catch(t){console.error("Error fetching activity data:",t),N(a("activity.fetchError"))}finally{A(!1)}},[o,j,B,a]);r.useEffect(()=>{z()},[z]),r.useEffect(()=>{if(!i)return;const t=Math.max(1,i.totalPages||1);o>t&&d(t)},[i,o]);const W=async t=>{try{const s=await le(t.id);s!=null&&s.success&&s.data&&(H(s.data),R(!0))}catch(s){console.error("Error fetching activity details:",s)}},_=async()=>{var t;if(window.confirm(a("activity.confirmCleanup")))try{const s=await se(30);s!=null&&s.success&&(alert(a("activity.cleanupSuccess",{count:((t=s.data)==null?void 0:t.deletedCount)||0})),z())}catch(s){console.error("Error cleaning up activities:",s),alert(a("activity.cleanupError"))}},q=()=>{const t={};p&&(t.server=p),v&&(t.tool=v),x&&ce(x)&&(t.status=x),g&&(t.group=g),y&&(t.username=y),b&&(t.keyName=b),D(t),d(1)},O=()=>{w(""),k(""),S(""),C(""),L(""),P(""),D({}),d(1)},M=t=>t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(2)}s`:`${(t/6e4).toFixed(2)}m`,E=t=>new Date(t).toLocaleString(),T=t=>{if(!t)return null;try{return JSON.parse(t)}catch{return t}},Q=()=>n?e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4",children:[{label:a("activity.totalCalls"),value:n.totalCalls,tone:"default"},{label:a("activity.successCount"),value:n.successCount,tone:"ok"},{label:a("activity.errorCount"),value:n.errorCount,tone:"err"},{label:a("activity.avgDuration"),value:M(n.avgDuration),tone:"default"}].map(t=>e.jsxs("div",{className:"hub-card",style:{padding:"12px 14px"},children:[e.jsx("div",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:t.label}),e.jsx("div",{className:"hub-num",style:{fontSize:22,fontWeight:500,lineHeight:1.1,marginTop:6,letterSpacing:"-0.02em",color:t.tone==="ok"?"oklch(0.4 0.13 145)":t.tone==="err"?"oklch(0.45 0.18 25)":"var(--hub-ink)"},children:t.value})]},t.label))}):null,X=()=>e.jsx("div",{className:"hub-card px-4 py-3 mb-4",children:e.jsxs("div",{className:"flex flex-wrap gap-3 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-server",children:a("activity.server")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-server",type:"text",value:p,onChange:t=>w(t.target.value),placeholder:a("activity.searchServer"),className:"hub-input pr-9",list:"server-options"}),p&&e.jsx("button",{onClick:()=>w(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.servers)&&e.jsx("datalist",{id:"server-options",children:l.servers.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-tool",children:a("activity.tool")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-tool",type:"text",value:v,onChange:t=>k(t.target.value),placeholder:a("activity.searchTool"),className:"hub-input pr-9",list:"tool-options"}),v&&e.jsx("button",{onClick:()=>k(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.tools)&&e.jsx("datalist",{id:"tool-options",children:l.tools.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-status",children:a("activity.status")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-status",type:"text",value:x,onChange:t=>S(t.target.value.toLowerCase()),placeholder:a("activity.searchStatus"),className:"hub-input pr-9",list:"activity-status-options"}),x&&e.jsx("button",{onClick:()=>S(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),e.jsx("datalist",{id:"activity-status-options",children:I.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-group",children:a("activity.group")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-group",type:"text",value:g,onChange:t=>C(t.target.value),placeholder:a("activity.searchGroup"),className:"hub-input pr-9",list:"group-options"}),g&&e.jsx("button",{onClick:()=>C(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.groups)&&e.jsx("datalist",{id:"group-options",children:l.groups.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-username",children:a("activity.user")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-username",type:"text",value:y,onChange:t=>L(t.target.value),placeholder:a("activity.searchUsername"),className:"hub-input pr-9",list:"username-options"}),y&&e.jsx("button",{onClick:()=>L(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.usernames)&&e.jsx("datalist",{id:"username-options",children:l.usernames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-keyname",children:a("activity.keyName")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-keyname",type:"text",value:b,onChange:t=>P(t.target.value),placeholder:a("activity.searchKeyName"),className:"hub-input pr-9",list:"keyname-options"}),b&&e.jsx("button",{onClick:()=>P(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.keyNames)&&e.jsx("datalist",{id:"keyname-options",children:l.keyNames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-shrink-0 flex items-center gap-2",children:[e.jsxs("button",{onClick:q,className:"hub-btn primary whitespace-nowrap",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",clipRule:"evenodd"})}),a("common.search")]}),e.jsx("button",{onClick:O,className:"hub-btn whitespace-nowrap",children:a("common.clear")})]})]})}),Y=()=>m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("activity.noData")}):e.jsx("div",{className:"hub-card overflow-hidden",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full",children:[e.jsx("thead",{style:{background:"var(--hub-bg-2)"},children:e.jsx("tr",{children:[a("activity.timestamp"),a("activity.server"),a("activity.tool"),a("activity.duration"),a("activity.status"),a("activity.group"),a("activity.user"),a("activity.key"),a("activity.sourceIp"),a("common.actions")].map(t=>e.jsx("th",{className:"hub-mono",style:{padding:"9px 14px",textAlign:"left",fontSize:11,color:"var(--hub-ink-3)",textTransform:"uppercase",letterSpacing:"0.08em",fontWeight:500},children:t},t))})}),e.jsx("tbody",{children:m.map(t=>e.jsxs("tr",{className:"transition-colors hover:bg-[var(--hub-surface-hover)]",style:{borderTop:"1px solid var(--hub-line-2)"},children:[e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:E(t.timestamp)}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag",children:t.server})}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag accent",children:t.tool})}),e.jsx("td",{className:"hub-mono hub-num whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:M(t.duration)}),e.jsx("td",{style:{padding:"10px 14px"},className:"whitespace-nowrap",children:e.jsxs("span",{className:`hub-status ${t.status==="success"?"ok":"err"}`,children:[e.jsx("span",{className:"hub-dot"}),t.status==="success"?a("activity.statusSuccess"):a("activity.statusError")]})}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.group||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.username||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.keyName||"—"}),e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.sourceIp||"—"}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("button",{onClick:()=>W(t),className:"hub-btn ghost sm",style:{color:"var(--hub-accent)"},children:a("common.view")})})]},t.id))})]})})}),Z=()=>{if(!K||!c)return null;const t=T(c.input),s=T(c.output);return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50",children:e.jsxs("div",{className:"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden",style:{boxShadow:"0 8px 24px rgba(0,0,0,0.12)"},children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsx("h3",{className:"hub-card-title",children:a("activity.details")}),e.jsx("button",{onClick:()=>R(!1),className:"hub-icon-btn sm","aria-label":"close",children:e.jsx("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),e.jsxs("div",{className:"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 mb-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.timestamp")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:E(c.timestamp)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.duration")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:M(c.duration)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.server")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.server})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.tool")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.tool})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.status")}),e.jsx("span",{className:`px-2 py-1 rounded text-xs font-medium ${c.status==="success"?"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200":"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200"}`,children:c.status==="success"?a("activity.statusSuccess"):a("activity.statusError")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.group")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.group||"-"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.user")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.username||"-"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.sourceIp")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.sourceIp||"-"})]}),c.keyName&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.key")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.keyName})]})]}),c.errorMessage&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-red-500 mb-1",children:a("activity.errorMessage")}),e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200",children:c.errorMessage})]}),t&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.input")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof t=="string"?t:JSON.stringify(t,null,2)})]}),s&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.output")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof s=="string"?s:JSON.stringify(s,null,2)})]})]})]})})};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:a("activity.title")}),e.jsxs("p",{className:"hub-sub",children:[e.jsx("span",{className:"hub-num",children:(i==null?void 0:i.total)??m.length})," entries"]})]}),e.jsxs("button",{onClick:_,className:"hub-btn danger",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}),a("activity.cleanup")]})]}),F&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-4",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsx("span",{className:"truncate text-[13px]",children:F}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>N(null),"aria-label":"close",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3 w-3",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),f&&m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("app.loading")}):e.jsxs(e.Fragment,{children:[Q(),X(),Y(),e.jsxs("div",{className:"flex items-center mt-6",children:[e.jsx("div",{className:"flex-[2] text-sm text-gray-500 dark:text-gray-400",children:i&&a("common.showing",{start:(i.page-1)*i.limit+1,end:Math.min(i.page*i.limit,i.total),total:i.total})}),e.jsx("div",{className:"flex-[4] flex justify-center",children:i&&i.totalPages>1&&e.jsx(re,{currentPage:o,totalPages:i.totalPages,onPageChange:d,disabled:f})}),e.jsxs("div",{className:"flex-[2] flex items-center justify-end space-x-2",children:[e.jsxs("label",{htmlFor:"perPage",className:"text-sm text-gray-500 dark:text-gray-400",children:[a("common.itemsPerPage"),":"]}),e.jsxs("select",{id:"perPage",value:j,onChange:t=>{G(Number(t.target.value)),d(1)},disabled:f,className:"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed",children:[e.jsx("option",{value:10,children:"10"}),e.jsx("option",{value:20,children:"20"}),e.jsx("option",{value:50,children:"50"}),e.jsx("option",{value:100,children:"100"})]})]})]})]}),Z()]})};export{he as default};
2
+ //# sourceMappingURL=ActivityPage-Bx5-Jrxq.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ActivityPage-ZRx6b9hm.js","sources":["../../src/pages/ActivityPage.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Activity,\n ActivityStats,\n ActivityFilter,\n ActivityFilterOptions,\n ActivityStatus,\n} from '@/types';\nimport {\n getActivities,\n getActivityById,\n getActivityStats,\n getActivityFilterOptions,\n deleteOldActivities,\n} from '@/services/activityService';\nimport Pagination from '@/components/ui/Pagination';\n\n// Pagination info type\ninterface PaginationInfo {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n hasNextPage: boolean;\n hasPrevPage: boolean;\n}\n\nconst STATUS_OPTIONS: ActivityStatus[] = ['success', 'error'];\n\nconst isValidStatus = (value: string): value is ActivityStatus =>\n STATUS_OPTIONS.includes(value as ActivityStatus);\n\nconst ActivityPage: React.FC = () => {\n const { t } = useTranslation();\n\n // State\n const [activities, setActivities] = useState<Activity[]>([]);\n const [stats, setStats] = useState<ActivityStats | null>(null);\n const [filterOptions, setFilterOptions] = useState<ActivityFilterOptions | null>(null);\n const [pagination, setPagination] = useState<PaginationInfo | null>(null);\n const [currentPage, setCurrentPage] = useState(1);\n const [itemsPerPage, setItemsPerPage] = useState(10);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedActivity, setSelectedActivity] = useState<Activity | null>(null);\n const [showDetailModal, setShowDetailModal] = useState(false);\n\n // Filter state\n const [appliedFilters, setAppliedFilters] = useState<ActivityFilter>({});\n const [searchServer, setSearchServer] = useState('');\n const [searchTool, setSearchTool] = useState('');\n const [searchStatus, setSearchStatus] = useState<string>('');\n const [searchGroup, setSearchGroup] = useState('');\n const [searchUsername, setSearchUsername] = useState('');\n const [searchKeyName, setSearchKeyName] = useState('');\n\n // Fetch data\n const fetchData = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Use appliedFilters directly for fetching\n const currentFilter = { ...appliedFilters };\n\n // Fetch activities, stats, and filter options in parallel\n const [activitiesRes, statsRes, optionsRes] = await Promise.all([\n getActivities(currentPage, itemsPerPage, currentFilter),\n getActivityStats(currentFilter),\n getActivityFilterOptions(),\n ]);\n\n if (activitiesRes?.success && Array.isArray(activitiesRes.data)) {\n setActivities(activitiesRes.data);\n if (activitiesRes.pagination) {\n setPagination(activitiesRes.pagination);\n }\n }\n\n if (statsRes?.success && statsRes.data) {\n setStats(statsRes.data);\n }\n\n if (optionsRes?.success && optionsRes.data) {\n setFilterOptions(optionsRes.data);\n }\n } catch (err) {\n console.error('Error fetching activity data:', err);\n setError(t('activity.fetchError'));\n } finally {\n setIsLoading(false);\n }\n }, [currentPage, itemsPerPage, appliedFilters, t]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n useEffect(() => {\n if (!pagination) {\n return;\n }\n\n const totalPages = Math.max(1, pagination.totalPages || 1);\n if (currentPage > totalPages) {\n setCurrentPage(totalPages);\n }\n }, [pagination, currentPage]);\n\n // Handle view activity details\n const handleViewDetails = async (activity: Activity) => {\n try {\n const response = await getActivityById(activity.id);\n if (response?.success && response.data) {\n setSelectedActivity(response.data);\n setShowDetailModal(true);\n }\n } catch (err) {\n console.error('Error fetching activity details:', err);\n }\n };\n\n // Handle cleanup old activities\n const handleCleanup = async () => {\n if (!window.confirm(t('activity.confirmCleanup'))) {\n return;\n }\n\n try {\n const response = await deleteOldActivities(30);\n if (response?.success) {\n alert(t('activity.cleanupSuccess', { count: response.data?.deletedCount || 0 }));\n fetchData();\n }\n } catch (err) {\n console.error('Error cleaning up activities:', err);\n alert(t('activity.cleanupError'));\n }\n };\n\n // Handle search\n const handleSearch = () => {\n const filters: ActivityFilter = {};\n if (searchServer) filters.server = searchServer;\n if (searchTool) filters.tool = searchTool;\n if (searchStatus && isValidStatus(searchStatus)) {\n filters.status = searchStatus;\n }\n if (searchGroup) filters.group = searchGroup;\n if (searchUsername) filters.username = searchUsername;\n if (searchKeyName) filters.keyName = searchKeyName;\n\n setAppliedFilters(filters);\n setCurrentPage(1);\n };\n\n // Handle clear filters\n const handleClearFilters = () => {\n setSearchServer('');\n setSearchTool('');\n setSearchStatus('');\n setSearchGroup('');\n setSearchUsername('');\n setSearchKeyName('');\n setAppliedFilters({});\n setCurrentPage(1);\n };\n\n // Format duration\n const formatDuration = (ms: number): string => {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;\n return `${(ms / 60000).toFixed(2)}m`;\n };\n\n // Format timestamp\n const formatTimestamp = (timestamp: string): string => {\n return new Date(timestamp).toLocaleString();\n };\n\n // Parse JSON safely\n const safeParseJSON = (str: string | undefined): any => {\n if (!str) return null;\n try {\n return JSON.parse(str);\n } catch {\n return str;\n }\n };\n\n // Render stats cards\n const renderStats = () => {\n if (!stats) return null;\n\n return (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4\">\n {[\n { label: t('activity.totalCalls'), value: stats.totalCalls, tone: 'default' as const },\n { label: t('activity.successCount'), value: stats.successCount, tone: 'ok' as const },\n { label: t('activity.errorCount'), value: stats.errorCount, tone: 'err' as const },\n {\n label: t('activity.avgDuration'),\n value: formatDuration(stats.avgDuration),\n tone: 'default' as const,\n },\n ].map((s) => (\n <div key={s.label} className=\"hub-card\" style={{ padding: '12px 14px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {s.label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 22,\n fontWeight: 500,\n lineHeight: 1.1,\n marginTop: 6,\n letterSpacing: '-0.02em',\n color:\n s.tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : s.tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : 'var(--hub-ink)',\n }}\n >\n {s.value}\n </div>\n </div>\n ))}\n </div>\n );\n };\n\n // Render filters\n const renderFilters = () => {\n return (\n <div className=\"hub-card px-4 py-3 mb-4\">\n <div className=\"flex flex-wrap gap-3 items-end\">\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-server\">\n {t('activity.server')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-server\"\n type=\"text\"\n value={searchServer}\n onChange={(e) => setSearchServer(e.target.value)}\n placeholder={t('activity.searchServer')}\n className=\"hub-input pr-9\"\n list=\"server-options\"\n />\n {searchServer && (\n <button\n onClick={() => setSearchServer('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.servers && (\n <datalist id=\"server-options\">\n {filterOptions.servers.map((s) => (\n <option key={s} value={s} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-tool\">\n {t('activity.tool')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-tool\"\n type=\"text\"\n value={searchTool}\n onChange={(e) => setSearchTool(e.target.value)}\n placeholder={t('activity.searchTool')}\n className=\"hub-input pr-9\"\n list=\"tool-options\"\n />\n {searchTool && (\n <button\n onClick={() => setSearchTool('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.tools && (\n <datalist id=\"tool-options\">\n {filterOptions.tools.map((t) => (\n <option key={t} value={t} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-status\">\n {t('activity.status')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-status\"\n type=\"text\"\n value={searchStatus}\n onChange={(e) => setSearchStatus(e.target.value.toLowerCase())}\n placeholder={t('activity.searchStatus')}\n className=\"hub-input pr-9\"\n list=\"activity-status-options\"\n />\n {searchStatus && (\n <button\n onClick={() => setSearchStatus('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n <datalist id=\"activity-status-options\">\n {STATUS_OPTIONS.map((status) => (\n <option key={status} value={status} />\n ))}\n </datalist>\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-group\">\n {t('activity.group')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-group\"\n type=\"text\"\n value={searchGroup}\n onChange={(e) => setSearchGroup(e.target.value)}\n placeholder={t('activity.searchGroup')}\n className=\"hub-input pr-9\"\n list=\"group-options\"\n />\n {searchGroup && (\n <button\n onClick={() => setSearchGroup('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.groups && (\n <datalist id=\"group-options\">\n {filterOptions.groups.map((g) => (\n <option key={g} value={g} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-username\">\n {t('activity.user')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-username\"\n type=\"text\"\n value={searchUsername}\n onChange={(e) => setSearchUsername(e.target.value)}\n placeholder={t('activity.searchUsername')}\n className=\"hub-input pr-9\"\n list=\"username-options\"\n />\n {searchUsername && (\n <button\n onClick={() => setSearchUsername('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.usernames && (\n <datalist id=\"username-options\">\n {filterOptions.usernames.map((username) => (\n <option key={username} value={username} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-keyname\">\n {t('activity.keyName')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-keyname\"\n type=\"text\"\n value={searchKeyName}\n onChange={(e) => setSearchKeyName(e.target.value)}\n placeholder={t('activity.searchKeyName')}\n className=\"hub-input pr-9\"\n list=\"keyname-options\"\n />\n {searchKeyName && (\n <button\n onClick={() => setSearchKeyName('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.keyNames && (\n <datalist id=\"keyname-options\">\n {filterOptions.keyNames.map((k) => (\n <option key={k} value={k} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-shrink-0 flex items-center gap-2\">\n <button onClick={handleSearch} className=\"hub-btn primary whitespace-nowrap\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('common.search')}\n </button>\n <button onClick={handleClearFilters} className=\"hub-btn whitespace-nowrap\">\n {t('common.clear')}\n </button>\n </div>\n </div>\n </div>\n );\n };\n\n // Render activity table\n const renderActivityTable = () => {\n if (activities.length === 0) {\n return (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('activity.noData')}\n </div>\n );\n }\n\n return (\n <div className=\"hub-card overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full\">\n <thead style={{ background: 'var(--hub-bg-2)' }}>\n <tr>\n {[\n t('activity.timestamp'),\n t('activity.server'),\n t('activity.tool'),\n t('activity.duration'),\n t('activity.status'),\n t('activity.group'),\n t('activity.user'),\n t('activity.key'),\n t('activity.sourceIp'),\n t('common.actions'),\n ].map((label) => (\n <th\n key={label}\n className=\"hub-mono\"\n style={{\n padding: '9px 14px',\n textAlign: 'left',\n fontSize: 11,\n color: 'var(--hub-ink-3)',\n textTransform: 'uppercase',\n letterSpacing: '0.08em',\n fontWeight: 500,\n }}\n >\n {label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {activities.map((activity) => (\n <tr\n key={activity.id}\n className=\"transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatTimestamp(activity.timestamp)}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag\">{activity.server}</span>\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag accent\">{activity.tool}</span>\n </td>\n <td\n className=\"hub-mono hub-num whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatDuration(activity.duration)}\n </td>\n <td style={{ padding: '10px 14px' }} className=\"whitespace-nowrap\">\n <span\n className={`hub-status ${activity.status === 'success' ? 'ok' : 'err'}`}\n >\n <span className=\"hub-dot\" />\n {activity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.group || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.username || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.keyName || '—'}\n </td>\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.sourceIp || '—'}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <button\n onClick={() => handleViewDetails(activity)}\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-accent)' }}\n >\n {t('common.view')}\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n };\n\n // Render detail modal\n const renderDetailModal = () => {\n if (!showDetailModal || !selectedActivity) return null;\n\n const inputData = safeParseJSON(selectedActivity.input);\n const outputData = safeParseJSON(selectedActivity.output);\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div\n className=\"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden\"\n style={{ boxShadow: '0 8px 24px rgba(0,0,0,0.12)' }}\n >\n <div\n className=\"flex items-center justify-between px-5 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('activity.details')}</h3>\n <button\n onClick={() => setShowDetailModal(false)}\n className=\"hub-icon-btn sm\"\n aria-label=\"close\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n <div className=\"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]\">\n <div className=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.timestamp')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatTimestamp(selectedActivity.timestamp)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.duration')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatDuration(selectedActivity.duration)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.server')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.server}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.tool')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.tool}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.status')}\n </label>\n <span\n className={`px-2 py-1 rounded text-xs font-medium ${\n selectedActivity.status === 'success'\n ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'\n : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'\n }`}\n >\n {selectedActivity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.group')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.group || '-'}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.user')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.username || '-'}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.sourceIp')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">\n {selectedActivity.sourceIp || '-'}\n </p>\n </div>\n {selectedActivity.keyName && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.key')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.keyName}</p>\n </div>\n )}\n </div>\n\n {selectedActivity.errorMessage && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-red-500 mb-1\">\n {t('activity.errorMessage')}\n </label>\n <div className=\"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200\">\n {selectedActivity.errorMessage}\n </div>\n </div>\n )}\n\n {inputData && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.input')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof inputData === 'string' ? inputData : JSON.stringify(inputData, null, 2)}\n </pre>\n </div>\n )}\n\n {outputData && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.output')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof outputData === 'string'\n ? outputData\n : JSON.stringify(outputData, null, 2)}\n </pre>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <div>\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('activity.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{pagination?.total ?? activities.length}</span> entries\n </p>\n </div>\n <button onClick={handleCleanup} className=\"hub-btn danger\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('activity.cleanup')}\n </button>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-4\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <span className=\"truncate text-[13px]\">{error}</span>\n <button className=\"hub-icon-btn sm\" onClick={() => setError(null)} aria-label=\"close\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3 w-3\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n )}\n\n {isLoading && activities.length === 0 ? (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('app.loading')}\n </div>\n ) : (\n <>\n {renderStats()}\n {renderFilters()}\n {renderActivityTable()}\n\n {/* Pagination */}\n <div className=\"flex items-center mt-6\">\n <div className=\"flex-[2] text-sm text-gray-500 dark:text-gray-400\">\n {pagination &&\n t('common.showing', {\n start: (pagination.page - 1) * pagination.limit + 1,\n end: Math.min(pagination.page * pagination.limit, pagination.total),\n total: pagination.total,\n })}\n </div>\n <div className=\"flex-[4] flex justify-center\">\n {pagination && pagination.totalPages > 1 && (\n <Pagination\n currentPage={currentPage}\n totalPages={pagination.totalPages}\n onPageChange={setCurrentPage}\n disabled={isLoading}\n />\n )}\n </div>\n <div className=\"flex-[2] flex items-center justify-end space-x-2\">\n <label htmlFor=\"perPage\" className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('common.itemsPerPage')}:\n </label>\n <select\n id=\"perPage\"\n value={itemsPerPage}\n onChange={(e) => {\n setItemsPerPage(Number(e.target.value));\n setCurrentPage(1);\n }}\n disabled={isLoading}\n className=\"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <option value={10}>10</option>\n <option value={20}>20</option>\n <option value={50}>50</option>\n <option value={100}>100</option>\n </select>\n </div>\n </div>\n </>\n )}\n\n {renderDetailModal()}\n </div>\n );\n};\n\nexport default ActivityPage;\n"],"names":["STATUS_OPTIONS","isValidStatus","value","ActivityPage","t","useTranslation","activities","setActivities","useState","stats","setStats","filterOptions","setFilterOptions","pagination","setPagination","currentPage","setCurrentPage","itemsPerPage","setItemsPerPage","isLoading","setIsLoading","error","setError","selectedActivity","setSelectedActivity","showDetailModal","setShowDetailModal","appliedFilters","setAppliedFilters","searchServer","setSearchServer","searchTool","setSearchTool","searchStatus","setSearchStatus","searchGroup","setSearchGroup","searchUsername","setSearchUsername","searchKeyName","setSearchKeyName","fetchData","useCallback","currentFilter","activitiesRes","statsRes","optionsRes","getActivities","getActivityStats","getActivityFilterOptions","err","useEffect","totalPages","handleViewDetails","activity","response","getActivityById","handleCleanup","deleteOldActivities","_a","handleSearch","filters","handleClearFilters","formatDuration","ms","formatTimestamp","timestamp","safeParseJSON","str","renderStats","jsx","s","jsxs","renderFilters","e","status","g","username","k","renderActivityTable","label","renderDetailModal","inputData","outputData","Fragment","Pagination"],"mappings":"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"}
1
+ {"version":3,"file":"ActivityPage-Bx5-Jrxq.js","sources":["../../src/pages/ActivityPage.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Activity,\n ActivityStats,\n ActivityFilter,\n ActivityFilterOptions,\n ActivityStatus,\n} from '@/types';\nimport {\n getActivities,\n getActivityById,\n getActivityStats,\n getActivityFilterOptions,\n deleteOldActivities,\n} from '@/services/activityService';\nimport Pagination from '@/components/ui/Pagination';\n\n// Pagination info type\ninterface PaginationInfo {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n hasNextPage: boolean;\n hasPrevPage: boolean;\n}\n\nconst STATUS_OPTIONS: ActivityStatus[] = ['success', 'error'];\n\nconst isValidStatus = (value: string): value is ActivityStatus =>\n STATUS_OPTIONS.includes(value as ActivityStatus);\n\nconst ActivityPage: React.FC = () => {\n const { t } = useTranslation();\n\n // State\n const [activities, setActivities] = useState<Activity[]>([]);\n const [stats, setStats] = useState<ActivityStats | null>(null);\n const [filterOptions, setFilterOptions] = useState<ActivityFilterOptions | null>(null);\n const [pagination, setPagination] = useState<PaginationInfo | null>(null);\n const [currentPage, setCurrentPage] = useState(1);\n const [itemsPerPage, setItemsPerPage] = useState(10);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedActivity, setSelectedActivity] = useState<Activity | null>(null);\n const [showDetailModal, setShowDetailModal] = useState(false);\n\n // Filter state\n const [appliedFilters, setAppliedFilters] = useState<ActivityFilter>({});\n const [searchServer, setSearchServer] = useState('');\n const [searchTool, setSearchTool] = useState('');\n const [searchStatus, setSearchStatus] = useState<string>('');\n const [searchGroup, setSearchGroup] = useState('');\n const [searchUsername, setSearchUsername] = useState('');\n const [searchKeyName, setSearchKeyName] = useState('');\n\n // Fetch data\n const fetchData = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Use appliedFilters directly for fetching\n const currentFilter = { ...appliedFilters };\n\n // Fetch activities, stats, and filter options in parallel\n const [activitiesRes, statsRes, optionsRes] = await Promise.all([\n getActivities(currentPage, itemsPerPage, currentFilter),\n getActivityStats(currentFilter),\n getActivityFilterOptions(),\n ]);\n\n if (activitiesRes?.success && Array.isArray(activitiesRes.data)) {\n setActivities(activitiesRes.data);\n if (activitiesRes.pagination) {\n setPagination(activitiesRes.pagination);\n }\n }\n\n if (statsRes?.success && statsRes.data) {\n setStats(statsRes.data);\n }\n\n if (optionsRes?.success && optionsRes.data) {\n setFilterOptions(optionsRes.data);\n }\n } catch (err) {\n console.error('Error fetching activity data:', err);\n setError(t('activity.fetchError'));\n } finally {\n setIsLoading(false);\n }\n }, [currentPage, itemsPerPage, appliedFilters, t]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n useEffect(() => {\n if (!pagination) {\n return;\n }\n\n const totalPages = Math.max(1, pagination.totalPages || 1);\n if (currentPage > totalPages) {\n setCurrentPage(totalPages);\n }\n }, [pagination, currentPage]);\n\n // Handle view activity details\n const handleViewDetails = async (activity: Activity) => {\n try {\n const response = await getActivityById(activity.id);\n if (response?.success && response.data) {\n setSelectedActivity(response.data);\n setShowDetailModal(true);\n }\n } catch (err) {\n console.error('Error fetching activity details:', err);\n }\n };\n\n // Handle cleanup old activities\n const handleCleanup = async () => {\n if (!window.confirm(t('activity.confirmCleanup'))) {\n return;\n }\n\n try {\n const response = await deleteOldActivities(30);\n if (response?.success) {\n alert(t('activity.cleanupSuccess', { count: response.data?.deletedCount || 0 }));\n fetchData();\n }\n } catch (err) {\n console.error('Error cleaning up activities:', err);\n alert(t('activity.cleanupError'));\n }\n };\n\n // Handle search\n const handleSearch = () => {\n const filters: ActivityFilter = {};\n if (searchServer) filters.server = searchServer;\n if (searchTool) filters.tool = searchTool;\n if (searchStatus && isValidStatus(searchStatus)) {\n filters.status = searchStatus;\n }\n if (searchGroup) filters.group = searchGroup;\n if (searchUsername) filters.username = searchUsername;\n if (searchKeyName) filters.keyName = searchKeyName;\n\n setAppliedFilters(filters);\n setCurrentPage(1);\n };\n\n // Handle clear filters\n const handleClearFilters = () => {\n setSearchServer('');\n setSearchTool('');\n setSearchStatus('');\n setSearchGroup('');\n setSearchUsername('');\n setSearchKeyName('');\n setAppliedFilters({});\n setCurrentPage(1);\n };\n\n // Format duration\n const formatDuration = (ms: number): string => {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;\n return `${(ms / 60000).toFixed(2)}m`;\n };\n\n // Format timestamp\n const formatTimestamp = (timestamp: string): string => {\n return new Date(timestamp).toLocaleString();\n };\n\n // Parse JSON safely\n const safeParseJSON = (str: string | undefined): any => {\n if (!str) return null;\n try {\n return JSON.parse(str);\n } catch {\n return str;\n }\n };\n\n // Render stats cards\n const renderStats = () => {\n if (!stats) return null;\n\n return (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4\">\n {[\n { label: t('activity.totalCalls'), value: stats.totalCalls, tone: 'default' as const },\n { label: t('activity.successCount'), value: stats.successCount, tone: 'ok' as const },\n { label: t('activity.errorCount'), value: stats.errorCount, tone: 'err' as const },\n {\n label: t('activity.avgDuration'),\n value: formatDuration(stats.avgDuration),\n tone: 'default' as const,\n },\n ].map((s) => (\n <div key={s.label} className=\"hub-card\" style={{ padding: '12px 14px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {s.label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 22,\n fontWeight: 500,\n lineHeight: 1.1,\n marginTop: 6,\n letterSpacing: '-0.02em',\n color:\n s.tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : s.tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : 'var(--hub-ink)',\n }}\n >\n {s.value}\n </div>\n </div>\n ))}\n </div>\n );\n };\n\n // Render filters\n const renderFilters = () => {\n return (\n <div className=\"hub-card px-4 py-3 mb-4\">\n <div className=\"flex flex-wrap gap-3 items-end\">\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-server\">\n {t('activity.server')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-server\"\n type=\"text\"\n value={searchServer}\n onChange={(e) => setSearchServer(e.target.value)}\n placeholder={t('activity.searchServer')}\n className=\"hub-input pr-9\"\n list=\"server-options\"\n />\n {searchServer && (\n <button\n onClick={() => setSearchServer('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.servers && (\n <datalist id=\"server-options\">\n {filterOptions.servers.map((s) => (\n <option key={s} value={s} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-tool\">\n {t('activity.tool')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-tool\"\n type=\"text\"\n value={searchTool}\n onChange={(e) => setSearchTool(e.target.value)}\n placeholder={t('activity.searchTool')}\n className=\"hub-input pr-9\"\n list=\"tool-options\"\n />\n {searchTool && (\n <button\n onClick={() => setSearchTool('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.tools && (\n <datalist id=\"tool-options\">\n {filterOptions.tools.map((t) => (\n <option key={t} value={t} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-status\">\n {t('activity.status')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-status\"\n type=\"text\"\n value={searchStatus}\n onChange={(e) => setSearchStatus(e.target.value.toLowerCase())}\n placeholder={t('activity.searchStatus')}\n className=\"hub-input pr-9\"\n list=\"activity-status-options\"\n />\n {searchStatus && (\n <button\n onClick={() => setSearchStatus('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n <datalist id=\"activity-status-options\">\n {STATUS_OPTIONS.map((status) => (\n <option key={status} value={status} />\n ))}\n </datalist>\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-group\">\n {t('activity.group')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-group\"\n type=\"text\"\n value={searchGroup}\n onChange={(e) => setSearchGroup(e.target.value)}\n placeholder={t('activity.searchGroup')}\n className=\"hub-input pr-9\"\n list=\"group-options\"\n />\n {searchGroup && (\n <button\n onClick={() => setSearchGroup('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.groups && (\n <datalist id=\"group-options\">\n {filterOptions.groups.map((g) => (\n <option key={g} value={g} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-username\">\n {t('activity.user')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-username\"\n type=\"text\"\n value={searchUsername}\n onChange={(e) => setSearchUsername(e.target.value)}\n placeholder={t('activity.searchUsername')}\n className=\"hub-input pr-9\"\n list=\"username-options\"\n />\n {searchUsername && (\n <button\n onClick={() => setSearchUsername('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.usernames && (\n <datalist id=\"username-options\">\n {filterOptions.usernames.map((username) => (\n <option key={username} value={username} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-keyname\">\n {t('activity.keyName')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-keyname\"\n type=\"text\"\n value={searchKeyName}\n onChange={(e) => setSearchKeyName(e.target.value)}\n placeholder={t('activity.searchKeyName')}\n className=\"hub-input pr-9\"\n list=\"keyname-options\"\n />\n {searchKeyName && (\n <button\n onClick={() => setSearchKeyName('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.keyNames && (\n <datalist id=\"keyname-options\">\n {filterOptions.keyNames.map((k) => (\n <option key={k} value={k} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-shrink-0 flex items-center gap-2\">\n <button onClick={handleSearch} className=\"hub-btn primary whitespace-nowrap\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('common.search')}\n </button>\n <button onClick={handleClearFilters} className=\"hub-btn whitespace-nowrap\">\n {t('common.clear')}\n </button>\n </div>\n </div>\n </div>\n );\n };\n\n // Render activity table\n const renderActivityTable = () => {\n if (activities.length === 0) {\n return (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('activity.noData')}\n </div>\n );\n }\n\n return (\n <div className=\"hub-card overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full\">\n <thead style={{ background: 'var(--hub-bg-2)' }}>\n <tr>\n {[\n t('activity.timestamp'),\n t('activity.server'),\n t('activity.tool'),\n t('activity.duration'),\n t('activity.status'),\n t('activity.group'),\n t('activity.user'),\n t('activity.key'),\n t('activity.sourceIp'),\n t('common.actions'),\n ].map((label) => (\n <th\n key={label}\n className=\"hub-mono\"\n style={{\n padding: '9px 14px',\n textAlign: 'left',\n fontSize: 11,\n color: 'var(--hub-ink-3)',\n textTransform: 'uppercase',\n letterSpacing: '0.08em',\n fontWeight: 500,\n }}\n >\n {label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {activities.map((activity) => (\n <tr\n key={activity.id}\n className=\"transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatTimestamp(activity.timestamp)}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag\">{activity.server}</span>\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag accent\">{activity.tool}</span>\n </td>\n <td\n className=\"hub-mono hub-num whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatDuration(activity.duration)}\n </td>\n <td style={{ padding: '10px 14px' }} className=\"whitespace-nowrap\">\n <span\n className={`hub-status ${activity.status === 'success' ? 'ok' : 'err'}`}\n >\n <span className=\"hub-dot\" />\n {activity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.group || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.username || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.keyName || '—'}\n </td>\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.sourceIp || '—'}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <button\n onClick={() => handleViewDetails(activity)}\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-accent)' }}\n >\n {t('common.view')}\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n };\n\n // Render detail modal\n const renderDetailModal = () => {\n if (!showDetailModal || !selectedActivity) return null;\n\n const inputData = safeParseJSON(selectedActivity.input);\n const outputData = safeParseJSON(selectedActivity.output);\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div\n className=\"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden\"\n style={{ boxShadow: '0 8px 24px rgba(0,0,0,0.12)' }}\n >\n <div\n className=\"flex items-center justify-between px-5 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('activity.details')}</h3>\n <button\n onClick={() => setShowDetailModal(false)}\n className=\"hub-icon-btn sm\"\n aria-label=\"close\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n <div className=\"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]\">\n <div className=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.timestamp')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatTimestamp(selectedActivity.timestamp)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.duration')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatDuration(selectedActivity.duration)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.server')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.server}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.tool')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.tool}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.status')}\n </label>\n <span\n className={`px-2 py-1 rounded text-xs font-medium ${\n selectedActivity.status === 'success'\n ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'\n : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'\n }`}\n >\n {selectedActivity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.group')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.group || '-'}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.user')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.username || '-'}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.sourceIp')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">\n {selectedActivity.sourceIp || '-'}\n </p>\n </div>\n {selectedActivity.keyName && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.key')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.keyName}</p>\n </div>\n )}\n </div>\n\n {selectedActivity.errorMessage && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-red-500 mb-1\">\n {t('activity.errorMessage')}\n </label>\n <div className=\"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200\">\n {selectedActivity.errorMessage}\n </div>\n </div>\n )}\n\n {inputData && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.input')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof inputData === 'string' ? inputData : JSON.stringify(inputData, null, 2)}\n </pre>\n </div>\n )}\n\n {outputData && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.output')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof outputData === 'string'\n ? outputData\n : JSON.stringify(outputData, null, 2)}\n </pre>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <div>\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('activity.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{pagination?.total ?? activities.length}</span> entries\n </p>\n </div>\n <button onClick={handleCleanup} className=\"hub-btn danger\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('activity.cleanup')}\n </button>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-4\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <span className=\"truncate text-[13px]\">{error}</span>\n <button className=\"hub-icon-btn sm\" onClick={() => setError(null)} aria-label=\"close\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3 w-3\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n )}\n\n {isLoading && activities.length === 0 ? (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('app.loading')}\n </div>\n ) : (\n <>\n {renderStats()}\n {renderFilters()}\n {renderActivityTable()}\n\n {/* Pagination */}\n <div className=\"flex items-center mt-6\">\n <div className=\"flex-[2] text-sm text-gray-500 dark:text-gray-400\">\n {pagination &&\n t('common.showing', {\n start: (pagination.page - 1) * pagination.limit + 1,\n end: Math.min(pagination.page * pagination.limit, pagination.total),\n total: pagination.total,\n })}\n </div>\n <div className=\"flex-[4] flex justify-center\">\n {pagination && pagination.totalPages > 1 && (\n <Pagination\n currentPage={currentPage}\n totalPages={pagination.totalPages}\n onPageChange={setCurrentPage}\n disabled={isLoading}\n />\n )}\n </div>\n <div className=\"flex-[2] flex items-center justify-end space-x-2\">\n <label htmlFor=\"perPage\" className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('common.itemsPerPage')}:\n </label>\n <select\n id=\"perPage\"\n value={itemsPerPage}\n onChange={(e) => {\n setItemsPerPage(Number(e.target.value));\n setCurrentPage(1);\n }}\n disabled={isLoading}\n className=\"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <option value={10}>10</option>\n <option value={20}>20</option>\n <option value={50}>50</option>\n <option value={100}>100</option>\n </select>\n </div>\n </div>\n </>\n )}\n\n {renderDetailModal()}\n </div>\n );\n};\n\nexport default ActivityPage;\n"],"names":["STATUS_OPTIONS","isValidStatus","value","ActivityPage","t","useTranslation","activities","setActivities","useState","stats","setStats","filterOptions","setFilterOptions","pagination","setPagination","currentPage","setCurrentPage","itemsPerPage","setItemsPerPage","isLoading","setIsLoading","error","setError","selectedActivity","setSelectedActivity","showDetailModal","setShowDetailModal","appliedFilters","setAppliedFilters","searchServer","setSearchServer","searchTool","setSearchTool","searchStatus","setSearchStatus","searchGroup","setSearchGroup","searchUsername","setSearchUsername","searchKeyName","setSearchKeyName","fetchData","useCallback","currentFilter","activitiesRes","statsRes","optionsRes","getActivities","getActivityStats","getActivityFilterOptions","err","useEffect","totalPages","handleViewDetails","activity","response","getActivityById","handleCleanup","deleteOldActivities","_a","handleSearch","filters","handleClearFilters","formatDuration","ms","formatTimestamp","timestamp","safeParseJSON","str","renderStats","jsx","s","jsxs","renderFilters","e","status","g","username","k","renderActivityTable","label","renderDetailModal","inputData","outputData","Fragment","Pagination"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{i as f,r as l,j as s}from"./framework-vendor-_YL27Pfc.js";import{e as b,f as v,h as j}from"./index-DjNOC0Ov.js";import{u as p}from"./i18n-vendor-BMaj5qV8.js";import"./icons-vendor-VW-UwEhw.js";const N=({binding:a,onChange:d})=>{const{t:r}=p(),[o,u]=l.useState({}),[m,h]=l.useState(!1),[n,c]=l.useState(""),i=async t=>{h(!0),c("");try{const e=`/credentials/${encodeURIComponent(a.serverName)}`,x=t?await v(e):await j(e,{values:o});if(!x.success)throw new Error(x.message||r("credentials.failed"));u({}),c(r(t?"credentials.deleted":"credentials.saved")),await d()}catch(e){c(e instanceof Error?e.message:r("credentials.failed"))}finally{h(!1)}};return s.jsxs("form",{className:"hub-card p-5 space-y-4",onSubmit:t=>{t.preventDefault(),i(!1)},children:[s.jsxs("div",{className:"flex items-center justify-between gap-3",children:[s.jsx("h2",{className:"font-semibold",children:a.serverName}),s.jsx("span",{className:"hub-tag",children:r(a.configured?"credentials.configured":"credentials.required")})]}),s.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:r("credentials.writeOnly")}),a.credentialTemplate.map(t=>{const e=`${t.target}.${t.name}`;return s.jsxs("label",{className:"block space-y-1 text-sm",children:[s.jsxs("span",{className:"font-medium",children:[t.label||t.name," ",s.jsxs("span",{className:"hub-mono text-xs font-normal text-[var(--hub-ink-3)]",children:["(",e,")"]})]}),s.jsx("input",{type:"password",required:!0,autoComplete:"new-password",maxLength:16384,value:o[e]||"",placeholder:r(a.configuredSlots.includes(e)?"credentials.replaceValue":"credentials.enterValue"),className:"hub-input",onChange:x=>u({...o,[e]:x.target.value})})]},e)}),s.jsxs("div",{className:"flex flex-wrap gap-2",children:[s.jsx("button",{type:"submit",className:"hub-btn primary",disabled:m,children:r("credentials.save")}),s.jsx("button",{type:"button",className:"hub-btn danger",disabled:m||!a.updatedAt,onClick:()=>void i(!0),children:r("credentials.delete")})]}),n&&s.jsx("p",{role:"status",className:"text-sm text-[var(--hub-ink-2)]",children:n})]})};function k(){const{t:a}=p(),[d,r]=f(),[o,u]=l.useState([]),[m,h]=l.useState(!0),[n,c]=l.useState(""),i=l.useCallback(async()=>{try{const e=await b("/credentials");if(!e.success)throw new Error(e.message||a("credentials.failed"));u(e.data||[]),c("")}catch(e){c(e instanceof Error?e.message:a("credentials.failed"))}finally{h(!1)}},[a]);l.useEffect(()=>{i()},[i]);const t=o.filter(e=>!d.get("server")||e.serverName===d.get("server"));return s.jsxs("div",{className:"max-w-4xl mx-auto space-y-5",children:[s.jsxs("div",{children:[s.jsx("h1",{className:"hub-h1",children:a("credentials.title")}),s.jsx("p",{className:"hub-sub",children:a("credentials.description")})]}),d.has("server")&&s.jsx("button",{className:"hub-btn",onClick:()=>r({}),children:a("credentials.showAll")}),n&&s.jsx("div",{className:"hub-card px-4 py-3 text-sm",style:{color:"var(--hub-err)"},role:"alert",children:n}),m?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.loading")}):!t.length&&!n?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.empty")}):null,t.map(e=>s.jsx(N,{binding:e,onChange:i},e.serverName))]})}export{k as default};
2
- //# sourceMappingURL=CredentialsPage-C9vnh01H.js.map
1
+ import{i as f,r as l,j as s}from"./framework-vendor-_YL27Pfc.js";import{e as b,f as v,h as j}from"./index-B-aT0HW5.js";import{u as p}from"./i18n-vendor-BMaj5qV8.js";import"./icons-vendor-VW-UwEhw.js";const N=({binding:a,onChange:d})=>{const{t:r}=p(),[o,u]=l.useState({}),[m,h]=l.useState(!1),[n,c]=l.useState(""),i=async t=>{h(!0),c("");try{const e=`/credentials/${encodeURIComponent(a.serverName)}`,x=t?await v(e):await j(e,{values:o});if(!x.success)throw new Error(x.message||r("credentials.failed"));u({}),c(r(t?"credentials.deleted":"credentials.saved")),await d()}catch(e){c(e instanceof Error?e.message:r("credentials.failed"))}finally{h(!1)}};return s.jsxs("form",{className:"hub-card p-5 space-y-4",onSubmit:t=>{t.preventDefault(),i(!1)},children:[s.jsxs("div",{className:"flex items-center justify-between gap-3",children:[s.jsx("h2",{className:"font-semibold",children:a.serverName}),s.jsx("span",{className:"hub-tag",children:r(a.configured?"credentials.configured":"credentials.required")})]}),s.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:r("credentials.writeOnly")}),a.credentialTemplate.map(t=>{const e=`${t.target}.${t.name}`;return s.jsxs("label",{className:"block space-y-1 text-sm",children:[s.jsxs("span",{className:"font-medium",children:[t.label||t.name," ",s.jsxs("span",{className:"hub-mono text-xs font-normal text-[var(--hub-ink-3)]",children:["(",e,")"]})]}),s.jsx("input",{type:"password",required:!0,autoComplete:"new-password",maxLength:16384,value:o[e]||"",placeholder:r(a.configuredSlots.includes(e)?"credentials.replaceValue":"credentials.enterValue"),className:"hub-input",onChange:x=>u({...o,[e]:x.target.value})})]},e)}),s.jsxs("div",{className:"flex flex-wrap gap-2",children:[s.jsx("button",{type:"submit",className:"hub-btn primary",disabled:m,children:r("credentials.save")}),s.jsx("button",{type:"button",className:"hub-btn danger",disabled:m||!a.updatedAt,onClick:()=>void i(!0),children:r("credentials.delete")})]}),n&&s.jsx("p",{role:"status",className:"text-sm text-[var(--hub-ink-2)]",children:n})]})};function k(){const{t:a}=p(),[d,r]=f(),[o,u]=l.useState([]),[m,h]=l.useState(!0),[n,c]=l.useState(""),i=l.useCallback(async()=>{try{const e=await b("/credentials");if(!e.success)throw new Error(e.message||a("credentials.failed"));u(e.data||[]),c("")}catch(e){c(e instanceof Error?e.message:a("credentials.failed"))}finally{h(!1)}},[a]);l.useEffect(()=>{i()},[i]);const t=o.filter(e=>!d.get("server")||e.serverName===d.get("server"));return s.jsxs("div",{className:"max-w-4xl mx-auto space-y-5",children:[s.jsxs("div",{children:[s.jsx("h1",{className:"hub-h1",children:a("credentials.title")}),s.jsx("p",{className:"hub-sub",children:a("credentials.description")})]}),d.has("server")&&s.jsx("button",{className:"hub-btn",onClick:()=>r({}),children:a("credentials.showAll")}),n&&s.jsx("div",{className:"hub-card px-4 py-3 text-sm",style:{color:"var(--hub-err)"},role:"alert",children:n}),m?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.loading")}):!t.length&&!n?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.empty")}):null,t.map(e=>s.jsx(N,{binding:e,onChange:i},e.serverName))]})}export{k as default};
2
+ //# sourceMappingURL=CredentialsPage-BGbk_kBx.js.map