strapi-plugin-magic-sessionmanager 4.0.1 → 4.0.2

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 (57) hide show
  1. package/README.md +2 -2
  2. package/admin/src/components/OnlineUsersWidget.jsx +11 -7
  3. package/admin/src/components/SessionDetailModal.jsx +42 -38
  4. package/admin/src/components/SessionInfoPanel.jsx +29 -20
  5. package/admin/src/index.js +9 -0
  6. package/admin/src/pages/HomePage.jsx +128 -161
  7. package/admin/src/pages/License.jsx +3 -3
  8. package/admin/src/pages/Settings.jsx +139 -135
  9. package/admin/src/pages/UpgradePage.jsx +448 -0
  10. package/admin/src/pluginId.js +1 -0
  11. package/admin/src/translations/de.json +294 -15
  12. package/admin/src/translations/en.json +293 -14
  13. package/admin/src/translations/es.json +284 -18
  14. package/admin/src/translations/fr.json +284 -18
  15. package/admin/src/translations/pt.json +284 -18
  16. package/admin/src/utils/theme.js +85 -0
  17. package/dist/_chunks/{Analytics-Dv9f_0eZ.mjs → Analytics-DTE_zmRV.mjs} +2 -2
  18. package/dist/_chunks/{Analytics-BBdv1I5y.js → Analytics-lw_JaOVy.js} +2 -2
  19. package/dist/_chunks/{App-CJaZPNjt.js → App-DDKYCjKw.js} +216 -206
  20. package/dist/_chunks/{App-CIQ-7sa7.mjs → App-DJW1ZNl5.mjs} +216 -206
  21. package/dist/_chunks/{License-nrmFxoBm.mjs → License-DaOFuImm.mjs} +4 -8
  22. package/dist/_chunks/{License-D24rgaZQ.js → License-Tk-6UfPl.js} +4 -8
  23. package/dist/_chunks/{OnlineUsersWidget-B8JS1xZu.js → OnlineUsersWidget-C1qTpsws.js} +11 -7
  24. package/dist/_chunks/{OnlineUsersWidget-ArMl0nen.mjs → OnlineUsersWidget-CADphbXG.mjs} +11 -7
  25. package/dist/_chunks/{Settings-D5dLEGc_.mjs → Settings-C9xvckgq.mjs} +191 -179
  26. package/dist/_chunks/{Settings-CqxgjU0y.js → Settings-DyEAuTNQ.js} +191 -179
  27. package/dist/_chunks/UpgradePage-Dssk8A0Z.js +354 -0
  28. package/dist/_chunks/UpgradePage-cINvE9zY.mjs +352 -0
  29. package/dist/_chunks/de-CDA1V0rF.mjs +292 -0
  30. package/dist/_chunks/de-I-Q-pWqu.js +292 -0
  31. package/dist/_chunks/en-Bd7_h-4e.js +292 -0
  32. package/dist/_chunks/en-DzmOCyzQ.mjs +292 -0
  33. package/dist/_chunks/es-BcAx18XG.js +277 -0
  34. package/dist/_chunks/es-Cx-SN6qV.mjs +277 -0
  35. package/dist/_chunks/fr-DCzYMuJ-.js +277 -0
  36. package/dist/_chunks/fr-DXlXE5Eo.mjs +277 -0
  37. package/dist/_chunks/{index-WH04CS1c.js → index-CWcvrfXc.js} +45 -42
  38. package/dist/_chunks/{index-Duk1_Wrz.mjs → index-DQO9bNP7.mjs} +45 -42
  39. package/dist/_chunks/pt-21-MAb72.js +277 -0
  40. package/dist/_chunks/pt-zsdTSjba.mjs +277 -0
  41. package/dist/_chunks/{useLicense-BwOlCyhc.js → useLicense-DtvJOszr.js} +1 -1
  42. package/dist/_chunks/{useLicense-Ce8GaxB0.mjs → useLicense-DxbD4Wf8.mjs} +1 -1
  43. package/dist/admin/index.js +1 -1
  44. package/dist/admin/index.mjs +1 -1
  45. package/dist/server/index.js +1 -1
  46. package/dist/server/index.mjs +1 -1
  47. package/package.json +1 -1
  48. package/dist/_chunks/de-BxFx1pwE.js +0 -23
  49. package/dist/_chunks/de-CdO3s01z.mjs +0 -23
  50. package/dist/_chunks/en-CsPpPJL3.mjs +0 -23
  51. package/dist/_chunks/en-RqmpDHdS.js +0 -23
  52. package/dist/_chunks/es-CuLHazN1.js +0 -23
  53. package/dist/_chunks/es-Dkmjhy9c.mjs +0 -23
  54. package/dist/_chunks/fr-BAJp2yhI.js +0 -23
  55. package/dist/_chunks/fr-Bssg_3UF.mjs +0 -23
  56. package/dist/_chunks/pt-BAP9cKs3.js +0 -23
  57. package/dist/_chunks/pt-BVNoNcuY.mjs +0 -23
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  const react = require("react");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
+ const reactIntl = require("react-intl");
4
5
  const designSystem = require("@strapi/design-system");
5
6
  const icons = require("@strapi/icons");
6
7
  const admin = require("@strapi/strapi/admin");
@@ -12,6 +13,7 @@ const pluginPkg = {
12
13
  strapi
13
14
  };
14
15
  const pluginId = "magic-sessionmanager";
16
+ const PLUGIN_ID = pluginId;
15
17
  const Initializer = () => {
16
18
  react.useEffect(() => {
17
19
  console.log("[magic-sessionmanager] Plugin initialized");
@@ -81,13 +83,16 @@ const parseUserAgent = (userAgent) => {
81
83
  os
82
84
  };
83
85
  };
86
+ const getTranslation = (id) => `${PLUGIN_ID}.${id}`;
84
87
  const SessionInfoPanel = ({ documentId, model, document }) => {
88
+ const { formatMessage } = reactIntl.useIntl();
85
89
  const [sessions, setSessions] = react.useState([]);
86
90
  const [loading, setLoading] = react.useState(true);
87
91
  const [isBlocked, setIsBlocked] = react.useState(false);
88
92
  const [actionLoading, setActionLoading] = react.useState(false);
89
93
  const { get, post: postRequest } = admin.useFetchClient();
90
94
  const { toggleNotification } = admin.useNotification();
95
+ const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
91
96
  const userId = document?.documentId || documentId;
92
97
  react.useEffect(() => {
93
98
  if (model !== "plugin::users-permissions.user" || !userId) {
@@ -116,14 +121,14 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
116
121
  if (response.data?.success) {
117
122
  toggleNotification({
118
123
  type: "success",
119
- message: "All sessions terminated successfully"
124
+ message: t("notifications.success.terminatedAll", "All sessions terminated successfully")
120
125
  });
121
126
  setSessions([]);
122
127
  }
123
128
  } catch (error) {
124
129
  toggleNotification({
125
130
  type: "warning",
126
- message: "Failed to terminate sessions"
131
+ message: t("notifications.error.terminateAll", "Failed to terminate sessions")
127
132
  });
128
133
  console.error("[SessionInfoPanel] Logout all error:", error);
129
134
  } finally {
@@ -140,7 +145,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
140
145
  setIsBlocked(newBlockedStatus);
141
146
  toggleNotification({
142
147
  type: "success",
143
- message: newBlockedStatus ? "User blocked successfully" : "User unblocked successfully"
148
+ message: newBlockedStatus ? t("notifications.success.blocked", "User blocked successfully") : t("notifications.success.unblocked", "User unblocked successfully")
144
149
  });
145
150
  if (newBlockedStatus) {
146
151
  setSessions([]);
@@ -149,7 +154,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
149
154
  } catch (error) {
150
155
  toggleNotification({
151
156
  type: "warning",
152
- message: "Failed to update user status"
157
+ message: t("notifications.error.block", "Failed to update user status")
153
158
  });
154
159
  console.error("[SessionInfoPanel] Toggle block error:", error);
155
160
  } finally {
@@ -166,13 +171,13 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
166
171
  }
167
172
  if (loading) {
168
173
  return {
169
- title: "Session Info",
170
- content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, background: "neutral0", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Loading..." }) })
174
+ title: t("panel.title", "Session Info"),
175
+ content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, background: "neutral0", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("panel.loading", "Loading...") }) })
171
176
  };
172
177
  }
173
178
  const isOnline = sessions.length > 0;
174
179
  return {
175
- title: "Session Info",
180
+ title: t("panel.title", "Session Info"),
176
181
  content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 4, alignItems: "stretch", children: [
177
182
  /* @__PURE__ */ jsxRuntime.jsx(
178
183
  designSystem.Box,
@@ -192,14 +197,10 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
192
197
  textColor: "neutral0",
193
198
  size: "M",
194
199
  style: { fontSize: "14px", padding: "6px 12px" },
195
- children: isOnline ? "ACTIVE" : "OFFLINE"
200
+ children: isOnline ? t("panel.status.active", "ACTIVE") : t("panel.status.offline", "OFFLINE")
196
201
  }
197
202
  ),
198
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", textColor: isOnline ? "success700" : "neutral700", children: [
199
- sessions.length,
200
- " active session",
201
- sessions.length !== 1 ? "s" : ""
202
- ] })
203
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", textColor: isOnline ? "success700" : "neutral700", children: t("panel.sessions.count", "{count} active session{count, plural, one {} other {s}}", { count: sessions.length }) })
203
204
  ] })
204
205
  }
205
206
  ),
@@ -210,8 +211,8 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
210
211
  background: "danger100",
211
212
  hasRadius: true,
212
213
  children: [
213
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", textColor: "danger700", marginBottom: 1, children: "User is blocked" }),
214
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "danger600", children: "Authentication disabled" })
214
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", textColor: "danger700", marginBottom: 1, children: t("panel.blocked.title", "User is blocked") }),
215
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "danger600", children: t("panel.blocked.description", "Authentication disabled") })
215
216
  ]
216
217
  }
217
218
  ),
@@ -220,7 +221,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
220
221
  textAlign: "left",
221
222
  letterSpacing: "0.5px",
222
223
  fontSize: "12px"
223
- }, children: "Active Sessions" }),
224
+ }, children: t("panel.sessions.title", "Active Sessions") }),
224
225
  sessions.slice(0, 5).map((session) => {
225
226
  const deviceInfo = parseUserAgent(session.userAgent);
226
227
  const DeviceIcon = getDeviceIcon(deviceInfo.device);
@@ -254,7 +255,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
254
255
  backgroundColor: "success600",
255
256
  textColor: "neutral0",
256
257
  size: "S",
257
- children: "Active"
258
+ children: t("panel.sessions.active", "Active")
258
259
  }
259
260
  ),
260
261
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
@@ -276,21 +277,13 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
276
277
  minute: "2-digit"
277
278
  }) })
278
279
  ] }),
279
- session.minutesSinceActive !== void 0 && session.minutesSinceActive < 60 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "success600", fontWeight: "semiBold", children: [
280
- "Active ",
281
- session.minutesSinceActive === 0 ? "now" : `${session.minutesSinceActive} min ago`
282
- ] })
280
+ session.minutesSinceActive !== void 0 && session.minutesSinceActive < 60 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "success600", fontWeight: "semiBold", children: session.minutesSinceActive === 0 ? t("panel.sessions.activeNow", "Active now") : t("panel.sessions.activeAgo", "Active {minutes} min ago", { minutes: session.minutesSinceActive }) })
283
281
  ] })
284
282
  },
285
283
  session.id
286
284
  );
287
285
  }),
288
- sessions.length > 5 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 3, background: "primary100", hasRadius: true, textAlign: "center", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "primary600", fontWeight: "semiBold", children: [
289
- "+",
290
- sessions.length - 5,
291
- " more session",
292
- sessions.length - 5 !== 1 ? "s" : ""
293
- ] }) })
286
+ sessions.length > 5 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 3, background: "primary100", hasRadius: true, textAlign: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "primary600", fontWeight: "semiBold", children: t("panel.sessions.more", "+{count} more session{count, plural, one {} other {s}}", { count: sessions.length - 5 }) }) })
294
287
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(
295
288
  designSystem.Box,
296
289
  {
@@ -311,8 +304,8 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
311
304
  children: "💤"
312
305
  }
313
306
  ),
314
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", textColor: "neutral700", children: "No active sessions" }),
315
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", style: { fontSize: "13px" }, children: "User has not logged in yet" })
307
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", textColor: "neutral700", children: t("panel.empty.title", "No active sessions") }),
308
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", style: { fontSize: "13px" }, children: t("panel.empty.description", "User has not logged in yet") })
316
309
  ] })
317
310
  }
318
311
  ),
@@ -322,7 +315,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
322
315
  textAlign: "left",
323
316
  letterSpacing: "0.5px",
324
317
  fontSize: "12px"
325
- }, children: "Actions" }),
318
+ }, children: t("panel.actions.title", "Actions") }),
326
319
  /* @__PURE__ */ jsxRuntime.jsx(
327
320
  designSystem.Button,
328
321
  {
@@ -350,7 +343,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
350
343
  e.currentTarget.style.color = "#dc2626";
351
344
  }
352
345
  },
353
- children: "Terminate All Sessions"
346
+ children: t("panel.actions.terminateAll", "Terminate All Sessions")
354
347
  }
355
348
  ),
356
349
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -380,7 +373,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
380
373
  e.currentTarget.style.color = isBlocked ? "#16a34a" : "#dc2626";
381
374
  }
382
375
  },
383
- children: isBlocked ? "Unblock User" : "Block User"
376
+ children: isBlocked ? t("panel.actions.unblockUser", "Unblock User") : t("panel.actions.blockUser", "Block User")
384
377
  }
385
378
  )
386
379
  ] })
@@ -404,7 +397,7 @@ const index = {
404
397
  id: `${pluginId}.plugin.name`,
405
398
  defaultMessage: pluginPkg.strapi.displayName
406
399
  },
407
- Component: () => Promise.resolve().then(() => require("./App-CJaZPNjt.js"))
400
+ Component: () => Promise.resolve().then(() => require("./App-DDKYCjKw.js"))
408
401
  });
409
402
  app.createSettingSection(
410
403
  {
@@ -413,6 +406,15 @@ const index = {
413
406
  to: `/settings/${pluginId}`
414
407
  },
415
408
  [
409
+ {
410
+ intlLabel: {
411
+ id: `${pluginId}.settings.upgrade`,
412
+ defaultMessage: "Upgrade"
413
+ },
414
+ id: "upgrade",
415
+ to: `/settings/${pluginId}/upgrade`,
416
+ Component: () => Promise.resolve().then(() => require("./UpgradePage-Dssk8A0Z.js"))
417
+ },
416
418
  {
417
419
  intlLabel: {
418
420
  id: `${pluginId}.settings.general`,
@@ -420,7 +422,7 @@ const index = {
420
422
  },
421
423
  id: "general",
422
424
  to: `/settings/${pluginId}/general`,
423
- Component: () => Promise.resolve().then(() => require("./Settings-CqxgjU0y.js"))
425
+ Component: () => Promise.resolve().then(() => require("./Settings-DyEAuTNQ.js"))
424
426
  },
425
427
  {
426
428
  intlLabel: {
@@ -429,7 +431,7 @@ const index = {
429
431
  },
430
432
  id: "analytics",
431
433
  to: `/settings/${pluginId}/analytics`,
432
- Component: () => Promise.resolve().then(() => require("./Analytics-BBdv1I5y.js"))
434
+ Component: () => Promise.resolve().then(() => require("./Analytics-lw_JaOVy.js"))
433
435
  },
434
436
  {
435
437
  intlLabel: {
@@ -438,7 +440,7 @@ const index = {
438
440
  },
439
441
  id: "license",
440
442
  to: `/settings/${pluginId}/license`,
441
- Component: () => Promise.resolve().then(() => require("./License-D24rgaZQ.js"))
443
+ Component: () => Promise.resolve().then(() => require("./License-Tk-6UfPl.js"))
442
444
  }
443
445
  ]
444
446
  );
@@ -456,7 +458,7 @@ const index = {
456
458
  defaultMessage: "Online Users"
457
459
  },
458
460
  component: async () => {
459
- const component = await Promise.resolve().then(() => require("./OnlineUsersWidget-B8JS1xZu.js"));
461
+ const component = await Promise.resolve().then(() => require("./OnlineUsersWidget-C1qTpsws.js"));
460
462
  return component.default;
461
463
  },
462
464
  id: "online-users-widget",
@@ -482,11 +484,11 @@ const index = {
482
484
  },
483
485
  async registerTrads({ locales }) {
484
486
  const importedTrads = {
485
- en: () => Promise.resolve().then(() => require("./en-RqmpDHdS.js")),
486
- de: () => Promise.resolve().then(() => require("./de-BxFx1pwE.js")),
487
- es: () => Promise.resolve().then(() => require("./es-CuLHazN1.js")),
488
- fr: () => Promise.resolve().then(() => require("./fr-BAJp2yhI.js")),
489
- pt: () => Promise.resolve().then(() => require("./pt-BAP9cKs3.js"))
487
+ en: () => Promise.resolve().then(() => require("./en-Bd7_h-4e.js")),
488
+ de: () => Promise.resolve().then(() => require("./de-I-Q-pWqu.js")),
489
+ es: () => Promise.resolve().then(() => require("./es-BcAx18XG.js")),
490
+ fr: () => Promise.resolve().then(() => require("./fr-DCzYMuJ-.js")),
491
+ pt: () => Promise.resolve().then(() => require("./pt-21-MAb72.js"))
490
492
  };
491
493
  const translatedLanguages = Object.keys(importedTrads).filter(
492
494
  (lang) => locales.includes(lang)
@@ -505,6 +507,7 @@ const index = {
505
507
  return Promise.resolve(translations);
506
508
  }
507
509
  };
510
+ exports.getTranslation = getTranslation;
508
511
  exports.index = index;
509
512
  exports.parseUserAgent = parseUserAgent;
510
513
  exports.pluginId = pluginId;
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useState } from "react";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useIntl } from "react-intl";
3
4
  import { Box, Typography, Flex, Badge, Divider, Button } from "@strapi/design-system";
4
5
  import { Server, Clock, Cross, Check, Phone, Monitor } from "@strapi/icons";
5
6
  import { useFetchClient, useNotification } from "@strapi/strapi/admin";
@@ -11,6 +12,7 @@ const pluginPkg = {
11
12
  strapi
12
13
  };
13
14
  const pluginId = "magic-sessionmanager";
15
+ const PLUGIN_ID = pluginId;
14
16
  const Initializer = () => {
15
17
  useEffect(() => {
16
18
  console.log("[magic-sessionmanager] Plugin initialized");
@@ -80,13 +82,16 @@ const parseUserAgent = (userAgent) => {
80
82
  os
81
83
  };
82
84
  };
85
+ const getTranslation = (id) => `${PLUGIN_ID}.${id}`;
83
86
  const SessionInfoPanel = ({ documentId, model, document }) => {
87
+ const { formatMessage } = useIntl();
84
88
  const [sessions, setSessions] = useState([]);
85
89
  const [loading, setLoading] = useState(true);
86
90
  const [isBlocked, setIsBlocked] = useState(false);
87
91
  const [actionLoading, setActionLoading] = useState(false);
88
92
  const { get, post: postRequest } = useFetchClient();
89
93
  const { toggleNotification } = useNotification();
94
+ const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
90
95
  const userId = document?.documentId || documentId;
91
96
  useEffect(() => {
92
97
  if (model !== "plugin::users-permissions.user" || !userId) {
@@ -115,14 +120,14 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
115
120
  if (response.data?.success) {
116
121
  toggleNotification({
117
122
  type: "success",
118
- message: "All sessions terminated successfully"
123
+ message: t("notifications.success.terminatedAll", "All sessions terminated successfully")
119
124
  });
120
125
  setSessions([]);
121
126
  }
122
127
  } catch (error) {
123
128
  toggleNotification({
124
129
  type: "warning",
125
- message: "Failed to terminate sessions"
130
+ message: t("notifications.error.terminateAll", "Failed to terminate sessions")
126
131
  });
127
132
  console.error("[SessionInfoPanel] Logout all error:", error);
128
133
  } finally {
@@ -139,7 +144,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
139
144
  setIsBlocked(newBlockedStatus);
140
145
  toggleNotification({
141
146
  type: "success",
142
- message: newBlockedStatus ? "User blocked successfully" : "User unblocked successfully"
147
+ message: newBlockedStatus ? t("notifications.success.blocked", "User blocked successfully") : t("notifications.success.unblocked", "User unblocked successfully")
143
148
  });
144
149
  if (newBlockedStatus) {
145
150
  setSessions([]);
@@ -148,7 +153,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
148
153
  } catch (error) {
149
154
  toggleNotification({
150
155
  type: "warning",
151
- message: "Failed to update user status"
156
+ message: t("notifications.error.block", "Failed to update user status")
152
157
  });
153
158
  console.error("[SessionInfoPanel] Toggle block error:", error);
154
159
  } finally {
@@ -165,13 +170,13 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
165
170
  }
166
171
  if (loading) {
167
172
  return {
168
- title: "Session Info",
169
- content: /* @__PURE__ */ jsx(Box, { padding: 4, background: "neutral0", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Loading..." }) })
173
+ title: t("panel.title", "Session Info"),
174
+ content: /* @__PURE__ */ jsx(Box, { padding: 4, background: "neutral0", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t("panel.loading", "Loading...") }) })
170
175
  };
171
176
  }
172
177
  const isOnline = sessions.length > 0;
173
178
  return {
174
- title: "Session Info",
179
+ title: t("panel.title", "Session Info"),
175
180
  content: /* @__PURE__ */ jsx(Box, { style: { width: "100%" }, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, alignItems: "stretch", children: [
176
181
  /* @__PURE__ */ jsx(
177
182
  Box,
@@ -191,14 +196,10 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
191
196
  textColor: "neutral0",
192
197
  size: "M",
193
198
  style: { fontSize: "14px", padding: "6px 12px" },
194
- children: isOnline ? "ACTIVE" : "OFFLINE"
199
+ children: isOnline ? t("panel.status.active", "ACTIVE") : t("panel.status.offline", "OFFLINE")
195
200
  }
196
201
  ),
197
- /* @__PURE__ */ jsxs(Typography, { variant: "omega", fontWeight: "semiBold", textColor: isOnline ? "success700" : "neutral700", children: [
198
- sessions.length,
199
- " active session",
200
- sessions.length !== 1 ? "s" : ""
201
- ] })
202
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", textColor: isOnline ? "success700" : "neutral700", children: t("panel.sessions.count", "{count} active session{count, plural, one {} other {s}}", { count: sessions.length }) })
202
203
  ] })
203
204
  }
204
205
  ),
@@ -209,8 +210,8 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
209
210
  background: "danger100",
210
211
  hasRadius: true,
211
212
  children: [
212
- /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", textColor: "danger700", marginBottom: 1, children: "User is blocked" }),
213
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "danger600", children: "Authentication disabled" })
213
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", textColor: "danger700", marginBottom: 1, children: t("panel.blocked.title", "User is blocked") }),
214
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "danger600", children: t("panel.blocked.description", "Authentication disabled") })
214
215
  ]
215
216
  }
216
217
  ),
@@ -219,7 +220,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
219
220
  textAlign: "left",
220
221
  letterSpacing: "0.5px",
221
222
  fontSize: "12px"
222
- }, children: "Active Sessions" }),
223
+ }, children: t("panel.sessions.title", "Active Sessions") }),
223
224
  sessions.slice(0, 5).map((session) => {
224
225
  const deviceInfo = parseUserAgent(session.userAgent);
225
226
  const DeviceIcon = getDeviceIcon(deviceInfo.device);
@@ -253,7 +254,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
253
254
  backgroundColor: "success600",
254
255
  textColor: "neutral0",
255
256
  size: "S",
256
- children: "Active"
257
+ children: t("panel.sessions.active", "Active")
257
258
  }
258
259
  ),
259
260
  /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
@@ -275,21 +276,13 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
275
276
  minute: "2-digit"
276
277
  }) })
277
278
  ] }),
278
- session.minutesSinceActive !== void 0 && session.minutesSinceActive < 60 && /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "success600", fontWeight: "semiBold", children: [
279
- "Active ",
280
- session.minutesSinceActive === 0 ? "now" : `${session.minutesSinceActive} min ago`
281
- ] })
279
+ session.minutesSinceActive !== void 0 && session.minutesSinceActive < 60 && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "success600", fontWeight: "semiBold", children: session.minutesSinceActive === 0 ? t("panel.sessions.activeNow", "Active now") : t("panel.sessions.activeAgo", "Active {minutes} min ago", { minutes: session.minutesSinceActive }) })
282
280
  ] })
283
281
  },
284
282
  session.id
285
283
  );
286
284
  }),
287
- sessions.length > 5 && /* @__PURE__ */ jsx(Box, { padding: 3, background: "primary100", hasRadius: true, textAlign: "center", children: /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "primary600", fontWeight: "semiBold", children: [
288
- "+",
289
- sessions.length - 5,
290
- " more session",
291
- sessions.length - 5 !== 1 ? "s" : ""
292
- ] }) })
285
+ sessions.length > 5 && /* @__PURE__ */ jsx(Box, { padding: 3, background: "primary100", hasRadius: true, textAlign: "center", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "primary600", fontWeight: "semiBold", children: t("panel.sessions.more", "+{count} more session{count, plural, one {} other {s}}", { count: sessions.length - 5 }) }) })
293
286
  ] }) : /* @__PURE__ */ jsx(
294
287
  Box,
295
288
  {
@@ -310,8 +303,8 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
310
303
  children: "💤"
311
304
  }
312
305
  ),
313
- /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", textColor: "neutral700", children: "No active sessions" }),
314
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", style: { fontSize: "13px" }, children: "User has not logged in yet" })
306
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", textColor: "neutral700", children: t("panel.empty.title", "No active sessions") }),
307
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", style: { fontSize: "13px" }, children: t("panel.empty.description", "User has not logged in yet") })
315
308
  ] })
316
309
  }
317
310
  ),
@@ -321,7 +314,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
321
314
  textAlign: "left",
322
315
  letterSpacing: "0.5px",
323
316
  fontSize: "12px"
324
- }, children: "Actions" }),
317
+ }, children: t("panel.actions.title", "Actions") }),
325
318
  /* @__PURE__ */ jsx(
326
319
  Button,
327
320
  {
@@ -349,7 +342,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
349
342
  e.currentTarget.style.color = "#dc2626";
350
343
  }
351
344
  },
352
- children: "Terminate All Sessions"
345
+ children: t("panel.actions.terminateAll", "Terminate All Sessions")
353
346
  }
354
347
  ),
355
348
  /* @__PURE__ */ jsx(
@@ -379,7 +372,7 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
379
372
  e.currentTarget.style.color = isBlocked ? "#16a34a" : "#dc2626";
380
373
  }
381
374
  },
382
- children: isBlocked ? "Unblock User" : "Block User"
375
+ children: isBlocked ? t("panel.actions.unblockUser", "Unblock User") : t("panel.actions.blockUser", "Block User")
383
376
  }
384
377
  )
385
378
  ] })
@@ -403,7 +396,7 @@ const index = {
403
396
  id: `${pluginId}.plugin.name`,
404
397
  defaultMessage: pluginPkg.strapi.displayName
405
398
  },
406
- Component: () => import("./App-CIQ-7sa7.mjs")
399
+ Component: () => import("./App-DJW1ZNl5.mjs")
407
400
  });
408
401
  app.createSettingSection(
409
402
  {
@@ -412,6 +405,15 @@ const index = {
412
405
  to: `/settings/${pluginId}`
413
406
  },
414
407
  [
408
+ {
409
+ intlLabel: {
410
+ id: `${pluginId}.settings.upgrade`,
411
+ defaultMessage: "Upgrade"
412
+ },
413
+ id: "upgrade",
414
+ to: `/settings/${pluginId}/upgrade`,
415
+ Component: () => import("./UpgradePage-cINvE9zY.mjs")
416
+ },
415
417
  {
416
418
  intlLabel: {
417
419
  id: `${pluginId}.settings.general`,
@@ -419,7 +421,7 @@ const index = {
419
421
  },
420
422
  id: "general",
421
423
  to: `/settings/${pluginId}/general`,
422
- Component: () => import("./Settings-D5dLEGc_.mjs")
424
+ Component: () => import("./Settings-C9xvckgq.mjs")
423
425
  },
424
426
  {
425
427
  intlLabel: {
@@ -428,7 +430,7 @@ const index = {
428
430
  },
429
431
  id: "analytics",
430
432
  to: `/settings/${pluginId}/analytics`,
431
- Component: () => import("./Analytics-Dv9f_0eZ.mjs")
433
+ Component: () => import("./Analytics-DTE_zmRV.mjs")
432
434
  },
433
435
  {
434
436
  intlLabel: {
@@ -437,7 +439,7 @@ const index = {
437
439
  },
438
440
  id: "license",
439
441
  to: `/settings/${pluginId}/license`,
440
- Component: () => import("./License-nrmFxoBm.mjs")
442
+ Component: () => import("./License-DaOFuImm.mjs")
441
443
  }
442
444
  ]
443
445
  );
@@ -455,7 +457,7 @@ const index = {
455
457
  defaultMessage: "Online Users"
456
458
  },
457
459
  component: async () => {
458
- const component = await import("./OnlineUsersWidget-ArMl0nen.mjs");
460
+ const component = await import("./OnlineUsersWidget-CADphbXG.mjs");
459
461
  return component.default;
460
462
  },
461
463
  id: "online-users-widget",
@@ -481,11 +483,11 @@ const index = {
481
483
  },
482
484
  async registerTrads({ locales }) {
483
485
  const importedTrads = {
484
- en: () => import("./en-CsPpPJL3.mjs"),
485
- de: () => import("./de-CdO3s01z.mjs"),
486
- es: () => import("./es-Dkmjhy9c.mjs"),
487
- fr: () => import("./fr-Bssg_3UF.mjs"),
488
- pt: () => import("./pt-BVNoNcuY.mjs")
486
+ en: () => import("./en-DzmOCyzQ.mjs"),
487
+ de: () => import("./de-CDA1V0rF.mjs"),
488
+ es: () => import("./es-Cx-SN6qV.mjs"),
489
+ fr: () => import("./fr-DXlXE5Eo.mjs"),
490
+ pt: () => import("./pt-zsdTSjba.mjs")
489
491
  };
490
492
  const translatedLanguages = Object.keys(importedTrads).filter(
491
493
  (lang) => locales.includes(lang)
@@ -506,6 +508,7 @@ const index = {
506
508
  };
507
509
  export {
508
510
  pluginId as a,
511
+ getTranslation as g,
509
512
  index as i,
510
513
  parseUserAgent as p
511
514
  };