@localazy/strapi-plugin 1.1.0 → 1.1.1

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 (65) hide show
  1. package/dist/_chunks/{FetchIdentity-DfV1OWMB.js → FetchIdentity-CevvxeEj.js} +73 -46
  2. package/dist/_chunks/{FetchIdentity-lkoWjYjn.mjs → FetchIdentity-DeThazz9.mjs} +43 -16
  3. package/dist/_chunks/{LanguagesSelector-BmWfSZq6.js → LanguagesSelector-BExpl4Vx.js} +15 -3
  4. package/dist/_chunks/{LanguagesSelector-vSZvVGUT.mjs → LanguagesSelector-D62gLZsM.mjs} +15 -3
  5. package/dist/_chunks/{LocalazyApp-st8mwIbM.mjs → LocalazyApp-Czkb4s5J.mjs} +791 -61
  6. package/dist/_chunks/{LocalazyApp-BUfYt7UL.js → LocalazyApp-DIcO748C.js} +791 -59
  7. package/dist/_chunks/{LocalazyContentTransferSetup-BjLBgqFO.js → LocalazyContentTransferSetup-DAyZdwi9.js} +13 -10
  8. package/dist/_chunks/{LocalazyContentTransferSetup-D2YvBYs_.mjs → LocalazyContentTransferSetup-Dx0Z6DXc.mjs} +13 -10
  9. package/dist/_chunks/{LocalazyGlobalSettings-DHCU2_RH.mjs → LocalazyGlobalSettings-DWMBqlN4.mjs} +149 -12
  10. package/dist/_chunks/{LocalazyGlobalSettings-Do5tOyhB.js → LocalazyGlobalSettings-DjrXGVxl.js} +148 -11
  11. package/dist/_chunks/{LocalazyPanel-CulgT97p.mjs → LocalazyPanel-B-0HBTL_.mjs} +4 -4
  12. package/dist/_chunks/{LocalazyPanel-BDxUI_RH.js → LocalazyPanel-nBOpQo5B.js} +4 -4
  13. package/dist/_chunks/{LocalazyStatusColumn-DoTWD2eL.mjs → LocalazyStatusColumn-CpO3yccG.mjs} +9 -7
  14. package/dist/_chunks/{LocalazyStatusColumn-Dpwoc5Ig.js → LocalazyStatusColumn-cGsUDMlX.js} +9 -7
  15. package/dist/_chunks/{RequireLocalazyAuth-BzM7C6Yw.js → RequireLocalazyAuth-56K8HUNR.js} +4 -4
  16. package/dist/_chunks/{RequireLocalazyAuth-CqHrZ1Ah.mjs → RequireLocalazyAuth-Dh-mAMcg.mjs} +4 -4
  17. package/dist/_chunks/{entry-exclusion-service-DWFMKgkA.mjs → entry-exclusion-service-Dm5_iP7I.mjs} +1 -1
  18. package/dist/_chunks/{entry-exclusion-service-Cvu8PQUI.js → entry-exclusion-service-Rf4Tr0zW.js} +1 -1
  19. package/dist/_chunks/{has-model-changed-CWdMNRB1.mjs → has-model-changed-6p1lR-Ho.mjs} +2 -2
  20. package/dist/_chunks/{has-model-changed-D1f6is8z.js → has-model-changed-CGyDQARr.js} +2 -2
  21. package/dist/_chunks/{i18n-DaBjUC3Y.js → i18n-CAsbU4pi.js} +62 -4
  22. package/dist/_chunks/{i18n-Bga-GG_Z.mjs → i18n-QelOdIB2.mjs} +62 -4
  23. package/dist/_chunks/{index-BSNW1ypR.js → index-BK7lmZSN.js} +57 -19
  24. package/dist/_chunks/{index-CtvR-R3c.mjs → index-Bpf1Mw2A.mjs} +8 -8
  25. package/dist/_chunks/{index-BgPI2yQD.js → index-BsQ_ie4C.js} +8 -8
  26. package/dist/_chunks/{index-BIHAiJnE.mjs → index-CHjIMO9T.mjs} +78 -40
  27. package/dist/_chunks/{strapi-api-base-CturxOqD.mjs → strapi-api-base-Bem_CGuz.mjs} +2 -2
  28. package/dist/_chunks/{strapi-api-base-CN6q5tPh.js → strapi-api-base-W_bUTSlY.js} +2 -2
  29. package/dist/admin/index.js +1 -1
  30. package/dist/admin/index.mjs +1 -1
  31. package/dist/admin/src/components/PluginErrorBoundary.d.ts +5 -0
  32. package/dist/admin/src/modules/@common/locale/en.d.ts +4 -0
  33. package/dist/admin/src/modules/@common/services/project-service.d.ts +9 -0
  34. package/dist/admin/src/modules/@common/styles/heading-fix.d.ts +7 -0
  35. package/dist/admin/src/modules/@common/utils/export-json.d.ts +1 -0
  36. package/dist/admin/src/modules/@common/utils/redirect-to-plugin-route.d.ts +1 -0
  37. package/dist/admin/src/modules/activity-logs/components/HighlightMatch.d.ts +6 -0
  38. package/dist/admin/src/modules/activity-logs/components/SessionMetadata.d.ts +7 -0
  39. package/dist/admin/src/modules/activity-logs/components/SessionsTable.d.ts +17 -0
  40. package/dist/admin/src/modules/activity-logs/components/SortableHeader.d.ts +10 -0
  41. package/dist/admin/src/modules/activity-logs/components/StatusLabel.d.ts +6 -0
  42. package/dist/admin/src/modules/activity-logs/hooks/use-debounced-search.d.ts +6 -0
  43. package/dist/admin/src/modules/activity-logs/locale/en.d.ts +33 -0
  44. package/dist/admin/src/modules/activity-logs/models/activity-logs.d.ts +19 -0
  45. package/dist/admin/src/modules/activity-logs/services/activity-logs-service.d.ts +6 -0
  46. package/dist/admin/src/modules/activity-logs/utils/export-logs.d.ts +1 -0
  47. package/dist/admin/src/modules/activity-logs/utils/format-utils.d.ts +4 -0
  48. package/dist/admin/src/modules/plugin-settings/components/WebhookSetup.d.ts +2 -0
  49. package/dist/admin/src/modules/plugin-settings/locale/en.d.ts +21 -0
  50. package/dist/admin/src/pages/ActivityLogDetail.d.ts +7 -0
  51. package/dist/admin/src/pages/ActivityLogs.d.ts +7 -0
  52. package/dist/server/index.js +392 -47
  53. package/dist/server/index.mjs +392 -47
  54. package/dist/server/src/controllers/activity-logs-controller.d.ts +10 -0
  55. package/dist/server/src/controllers/index.d.ts +12 -1
  56. package/dist/server/src/controllers/localazy-project-controller.d.ts +4 -1
  57. package/dist/server/src/core/index.d.ts +13 -0
  58. package/dist/server/src/db/model/activity-logs.d.ts +20 -0
  59. package/dist/server/src/db/model/plugin-settings.d.ts +14 -0
  60. package/dist/server/src/index.d.ts +27 -1
  61. package/dist/server/src/routes/activity-logs-routes.d.ts +9 -0
  62. package/dist/server/src/services/activity-logs-service.d.ts +17 -0
  63. package/dist/server/src/services/index.d.ts +15 -0
  64. package/dist/server/src/services/localazy-pubapi-service.d.ts +2 -0
  65. package/package.json +1 -1
@@ -2,23 +2,27 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const reactRouterDom = require("react-router-dom");
5
- const index$1 = require("./index-BSNW1ypR.js");
5
+ const index$1 = require("./index-BK7lmZSN.js");
6
6
  const React = require("react");
7
- const FetchIdentity = require("./FetchIdentity-DfV1OWMB.js");
8
- const index = require("./index-BgPI2yQD.js");
7
+ const FetchIdentity = require("./FetchIdentity-CevvxeEj.js");
8
+ const index = require("./index-BsQ_ie4C.js");
9
9
  const useTranslation = require("./useTranslation-BdIl-aLe.js");
10
10
  const _commonjsHelpers = require("./_commonjsHelpers-Bc2YnDe1.js");
11
- const strapiApiBase = require("./strapi-api-base-CN6q5tPh.js");
12
- const LanguagesSelector = require("./LanguagesSelector-BmWfSZq6.js");
11
+ const strapiApiBase = require("./strapi-api-base-W_bUTSlY.js");
12
+ const LanguagesSelector = require("./LanguagesSelector-BExpl4Vx.js");
13
13
  const admin = require("@strapi/strapi/admin");
14
- require("./i18n-DaBjUC3Y.js");
15
- const hasModelChanged = require("./has-model-changed-D1f6is8z.js");
14
+ require("./i18n-CAsbU4pi.js");
15
+ const hasModelChanged = require("./has-model-changed-CGyDQARr.js");
16
+ const styled = require("styled-components");
17
+ const _interopDefault = (e2) => e2 && e2.__esModule ? e2 : { default: e2 };
18
+ const React__default = /* @__PURE__ */ _interopDefault(React);
16
19
  var PLUGIN_ROUTES = /* @__PURE__ */ ((PLUGIN_ROUTES2) => {
17
20
  PLUGIN_ROUTES2["ROOT"] = "";
18
21
  PLUGIN_ROUTES2["LOGIN"] = "login";
19
22
  PLUGIN_ROUTES2["UPLOAD"] = "upload";
20
23
  PLUGIN_ROUTES2["DOWNLOAD"] = "download";
21
24
  PLUGIN_ROUTES2["OVERVIEW"] = "overview";
25
+ PLUGIN_ROUTES2["ACTIVITY_LOGS"] = "activity-logs";
22
26
  PLUGIN_ROUTES2["CONTENT_TRANSFER_SETUP"] = "content-transfer-setup";
23
27
  PLUGIN_ROUTES2["GLOBAL_SETTINGS"] = "global-settings";
24
28
  return PLUGIN_ROUTES2;
@@ -66,6 +70,14 @@ const useNav = () => {
66
70
  icon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$3P, {}),
67
71
  to: `/plugins/${index.PLUGIN_ID}/download`,
68
72
  active: false
73
+ },
74
+ {
75
+ id: "activity-logs",
76
+ label: t2("common.activity_logs"),
77
+ description: t2("activity_logs.description"),
78
+ icon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$4j, {}),
79
+ to: `/plugins/${index.PLUGIN_ID}/activity-logs`,
80
+ active: false
69
81
  }
70
82
  ];
71
83
  };
@@ -1117,12 +1129,12 @@ function l(t2, e2) {
1117
1129
  const n2 = e2 || "https://localazy.com";
1118
1130
  return "/" !== new URL(n2).pathname ? `${n2}?${a2.toString()}` : `${n2}/oauth/authorize?${a2.toString()}`;
1119
1131
  }
1120
- const BASE_PATH$2 = "/auth";
1121
- const axiosInstance = strapiApiBase.createStrapiApiAxiosInstance();
1132
+ const BASE_PATH$3 = "/auth";
1133
+ const axiosInstance$1 = strapiApiBase.createStrapiApiAxiosInstance();
1122
1134
  class LocalazyLoginService {
1123
1135
  static async generateKeys() {
1124
1136
  try {
1125
- const result = await axiosInstance.get(`${BASE_PATH$2}/generate-keys`);
1137
+ const result = await axiosInstance$1.get(`${BASE_PATH$3}/generate-keys`);
1126
1138
  return result.data;
1127
1139
  } catch (e2) {
1128
1140
  throw e2;
@@ -1130,7 +1142,7 @@ class LocalazyLoginService {
1130
1142
  }
1131
1143
  static async continuousPoll(readKey) {
1132
1144
  try {
1133
- const result = await axiosInstance.get(`${BASE_PATH$2}/continuous-poll?readKey=${readKey}`);
1145
+ const result = await axiosInstance$1.get(`${BASE_PATH$3}/continuous-poll?readKey=${readKey}`);
1134
1146
  return result.data;
1135
1147
  } catch (e2) {
1136
1148
  throw e2;
@@ -1379,7 +1391,7 @@ const Login = ({ title, subtitle, isLoading = false }) => {
1379
1391
  };
1380
1392
  React.useEffect(() => {
1381
1393
  if (isLoggedIn && identity.user && identity.project) {
1382
- ProductAnalyticsService.trackAppConnected(identity.user.id, identity.project);
1394
+ void ProductAnalyticsService.trackAppConnected(identity.user.id, identity.project);
1383
1395
  }
1384
1396
  }, [isLoggedIn, identity]);
1385
1397
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -1430,7 +1442,7 @@ const LogoutButton = (props) => {
1430
1442
  const { setIdentity } = FetchIdentity.useLocalazyIdentity();
1431
1443
  const logout = async () => {
1432
1444
  setIsLoading(true);
1433
- FetchIdentity.LocalazyUserService.deleteIdentity();
1445
+ void FetchIdentity.LocalazyUserService.deleteIdentity();
1434
1446
  setIdentity(FetchIdentity.emptyIdentity);
1435
1447
  setIsLoading(false);
1436
1448
  props.onResultFetched();
@@ -1466,13 +1478,13 @@ const Overview = ({ title, subtitle, isLoadingProp = false }) => {
1466
1478
  setIsLoading(true);
1467
1479
  const project = await LanguagesSelector.ProjectService.getConnectedProject();
1468
1480
  setConnectedProject(project);
1469
- FetchIdentity.PluginSettingsService.updatePluginSettings({ defaultRoute: PLUGIN_ROUTES.OVERVIEW });
1481
+ void FetchIdentity.PluginSettingsService.updatePluginSettings({ defaultRoute: PLUGIN_ROUTES.OVERVIEW });
1470
1482
  setIsLoading(false);
1471
1483
  }
1472
- initComponent();
1484
+ void initComponent();
1473
1485
  }, []);
1474
1486
  const onLoggedOut = () => {
1475
- ProductAnalyticsService.trackAppDisconnected(identity.user.id, identity.project);
1487
+ void ProductAnalyticsService.trackAppDisconnected(identity.user.id, identity.project);
1476
1488
  navigateToPluginRoute(PLUGIN_ROUTES.LOGIN);
1477
1489
  };
1478
1490
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -1481,8 +1493,7 @@ const Overview = ({ title, subtitle, isLoadingProp = false }) => {
1481
1493
  {
1482
1494
  title,
1483
1495
  subtitle,
1484
- primaryAction: /* @__PURE__ */ jsxRuntime.jsx(LogoutButton, { onResultFetched: onLoggedOut }),
1485
- as: "h2"
1496
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsx(LogoutButton, { onResultFetched: onLoggedOut })
1486
1497
  }
1487
1498
  ),
1488
1499
  (isLoadingProp || isLoading) && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
@@ -1528,21 +1539,56 @@ const Overview = ({ title, subtitle, isLoadingProp = false }) => {
1528
1539
  ) })
1529
1540
  ] });
1530
1541
  };
1531
- const THEME_KEY = "STRAPI_THEME";
1532
- const getDefaultThemeName = () => {
1533
- const persistedTheme = localStorage.getItem(THEME_KEY);
1534
- return persistedTheme || "system";
1535
- };
1536
- const getDefaultTheme = () => {
1537
- const themeName = getDefaultThemeName();
1538
- return themeName === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? index$1.darkTheme : index$1.lightTheme : themeName === "dark" ? index$1.darkTheme : index$1.lightTheme;
1542
+ class ErrorBoundaryInner extends React__default.default.Component {
1543
+ constructor(props) {
1544
+ super(props);
1545
+ this.state = { hasError: false, error: null };
1546
+ }
1547
+ static getDerivedStateFromError(error) {
1548
+ return { hasError: true, error };
1549
+ }
1550
+ reset = () => {
1551
+ this.setState({ hasError: false, error: null });
1552
+ };
1553
+ render() {
1554
+ if (this.state.hasError && this.state.error) {
1555
+ return this.props.fallback(this.state.error, this.reset);
1556
+ }
1557
+ return this.props.children;
1558
+ }
1559
+ }
1560
+ const ErrorFallback = ({ error, reset }) => {
1561
+ const { t: t2 } = useTranslation.useTranslation();
1562
+ const { setIdentity } = FetchIdentity.useLocalazyIdentity();
1563
+ const handleDisconnect = React.useCallback(() => {
1564
+ void FetchIdentity.LocalazyUserService.deleteIdentity();
1565
+ setIdentity(FetchIdentity.emptyIdentity);
1566
+ reset();
1567
+ }, [setIdentity, reset]);
1568
+ return /* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { padding: 10, children: /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { direction: "column", alignItems: "center", gap: 6, paddingTop: 10, children: [
1569
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$3, { width: 48, height: 48, fill: "danger600" }),
1570
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "alpha", textColor: "neutral800", children: t2("common.error_boundary_title") }),
1571
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { maxWidth: "600px", children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", textColor: "neutral600", textAlign: "center", children: t2("common.error_boundary_description") }) }),
1572
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { padding: 4, background: "neutral100", hasRadius: true, maxWidth: "600px", width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
1573
+ index$1.Typography,
1574
+ {
1575
+ variant: "pi",
1576
+ textColor: "neutral500",
1577
+ tag: "pre",
1578
+ style: { whiteSpace: "pre-wrap", wordBreak: "break-word" },
1579
+ children: error.message
1580
+ }
1581
+ ) }),
1582
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Button, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$L, {}), variant: "danger-light", onClick: handleDisconnect, children: t2("common.error_boundary_disconnect") })
1583
+ ] }) }) });
1539
1584
  };
1540
- const BASE_PATH$1 = "/transfer";
1585
+ const PluginErrorBoundary = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundaryInner, { fallback: (error, reset) => /* @__PURE__ */ jsxRuntime.jsx(ErrorFallback, { error, reset }), children });
1586
+ const BASE_PATH$2 = "/transfer";
1541
1587
  class LocalazyUploadService {
1542
1588
  static async upload(data = {}) {
1543
1589
  try {
1544
1590
  const strapiApiInstance2 = strapiApiBase.createStrapiApiAxiosInstance();
1545
- const result = await strapiApiInstance2.post(`${BASE_PATH$1}/upload`, data);
1591
+ const result = await strapiApiInstance2.post(`${BASE_PATH$2}/upload`, data);
1546
1592
  return result.data;
1547
1593
  } catch (e2) {
1548
1594
  throw e2.data;
@@ -5002,7 +5048,7 @@ const Upload = (props) => {
5002
5048
  setIsUploading(false);
5003
5049
  setShowUploadFinishedModal(true);
5004
5050
  });
5005
- ProductAnalyticsService.trackUploadToLocalazy(identity.user.id, identity.project, {
5051
+ void ProductAnalyticsService.trackUploadToLocalazy(identity.user.id, identity.project, {
5006
5052
  "Source Language Code": localazySourceLanguage.code
5007
5053
  });
5008
5054
  };
@@ -5019,10 +5065,10 @@ const Upload = (props) => {
5019
5065
  setLocalazySourceLanguage(sourceLanguage);
5020
5066
  setModelChanged(modelChangedResult);
5021
5067
  setLocalesIncompatible(!localesCompatibleResult);
5022
- FetchIdentity.PluginSettingsService.updatePluginSettings({ defaultRoute: PLUGIN_ROUTES.UPLOAD });
5068
+ void FetchIdentity.PluginSettingsService.updatePluginSettings({ defaultRoute: PLUGIN_ROUTES.UPLOAD });
5023
5069
  setIsLoading(false);
5024
5070
  }
5025
- initComponent();
5071
+ void initComponent();
5026
5072
  }, []);
5027
5073
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5028
5074
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5039,8 +5085,7 @@ const Upload = (props) => {
5039
5085
  onClick: onUploadClick,
5040
5086
  children: t2("upload.upload_to_localazy")
5041
5087
  }
5042
- ),
5043
- as: "h2"
5088
+ )
5044
5089
  }
5045
5090
  ),
5046
5091
  isLoading && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
@@ -5114,12 +5159,12 @@ const Upload = (props) => {
5114
5159
  ] })
5115
5160
  ] });
5116
5161
  };
5117
- const BASE_PATH = "/transfer";
5162
+ const BASE_PATH$1 = "/transfer";
5118
5163
  class LocalazyDownloadService {
5119
5164
  static async download(data = {}) {
5120
5165
  try {
5121
5166
  const strapiApiInstance2 = strapiApiBase.createStrapiApiAxiosInstance();
5122
- const result = await strapiApiInstance2.post(`${BASE_PATH}/download`, data);
5167
+ const result = await strapiApiInstance2.post(`${BASE_PATH$1}/download`, data);
5123
5168
  return result.data;
5124
5169
  } catch (e2) {
5125
5170
  throw e2.data;
@@ -5159,7 +5204,7 @@ const Download = (props) => {
5159
5204
  FetchIdentity.set(newFormModel, "download.uiLanguages", languages);
5160
5205
  setFormModel(newFormModel);
5161
5206
  try {
5162
- FetchIdentity.PluginSettingsService.updatePluginSettings(newFormModel);
5207
+ void FetchIdentity.PluginSettingsService.updatePluginSettings(newFormModel);
5163
5208
  } catch (e2) {
5164
5209
  console.error(e2.message);
5165
5210
  }
@@ -5193,7 +5238,7 @@ const Download = (props) => {
5193
5238
  } catch {
5194
5239
  }
5195
5240
  });
5196
- ProductAnalyticsService.trackDownloadToStrapi(identity.user.id, identity.project, {
5241
+ void ProductAnalyticsService.trackDownloadToStrapi(identity.user.id, identity.project, {
5197
5242
  "Target Languages Codes": "all"
5198
5243
  });
5199
5244
  };
@@ -5213,10 +5258,10 @@ const Download = (props) => {
5213
5258
  const projectLanguagesWithoutDefaultLanguage = project?.languages?.filter((language) => language.id !== project.sourceLanguage) || [];
5214
5259
  setProjectLanguages(projectLanguagesWithoutDefaultLanguage);
5215
5260
  setFormModel(globalSettings);
5216
- FetchIdentity.PluginSettingsService.updatePluginSettings({ defaultRoute: PLUGIN_ROUTES.DOWNLOAD });
5261
+ void FetchIdentity.PluginSettingsService.updatePluginSettings({ defaultRoute: PLUGIN_ROUTES.DOWNLOAD });
5217
5262
  setIsLoading(false);
5218
5263
  }
5219
- initComponent();
5264
+ void initComponent();
5220
5265
  }, []);
5221
5266
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5222
5267
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5245,8 +5290,7 @@ const Download = (props) => {
5245
5290
  children: t2("download.incremental_download")
5246
5291
  }
5247
5292
  )
5248
- ] }),
5249
- as: "h2"
5293
+ ] })
5250
5294
  }
5251
5295
  ),
5252
5296
  isLoading && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
@@ -5333,7 +5377,7 @@ const Download = (props) => {
5333
5377
  variant: "danger-light",
5334
5378
  onClick: () => {
5335
5379
  setShowFullSyncConfirm(false);
5336
- onDownloadClick(true);
5380
+ void onDownloadClick(true);
5337
5381
  },
5338
5382
  children: t2("download.full_sync")
5339
5383
  }
@@ -5342,6 +5386,677 @@ const Download = (props) => {
5342
5386
  ] }) })
5343
5387
  ] });
5344
5388
  };
5389
+ const BASE_PATH = "/activity-logs";
5390
+ const axiosInstance = strapiApiBase.createStrapiApiAxiosInstance();
5391
+ class ActivityLogsService {
5392
+ static async getSessions(type) {
5393
+ const params = type ? `?type=${type}` : "";
5394
+ const result = await axiosInstance.get(`${BASE_PATH}${params}`);
5395
+ return result.data;
5396
+ }
5397
+ static async getSession(sessionId) {
5398
+ const result = await axiosInstance.get(`${BASE_PATH}/${sessionId}`);
5399
+ return result.data;
5400
+ }
5401
+ static async exportSessions() {
5402
+ const result = await axiosInstance.get(`${BASE_PATH}/export`);
5403
+ return result.data;
5404
+ }
5405
+ static async clearSessions() {
5406
+ const result = await axiosInstance.delete(`${BASE_PATH}`);
5407
+ return result.data;
5408
+ }
5409
+ }
5410
+ const exportAsJson = (data, filename) => {
5411
+ const json = JSON.stringify(data, null, 2);
5412
+ const blob = new Blob([json], { type: "application/json" });
5413
+ const url2 = URL.createObjectURL(blob);
5414
+ const a2 = document.createElement("a");
5415
+ a2.href = url2;
5416
+ a2.download = filename.endsWith(".json") ? filename : `${filename}.json`;
5417
+ a2.click();
5418
+ URL.revokeObjectURL(url2);
5419
+ };
5420
+ const exportLogsAsJson = async () => {
5421
+ const sessions = await ActivityLogsService.exportSessions();
5422
+ exportAsJson(sessions, `localazy-activity-logs-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`);
5423
+ };
5424
+ const formatDate = (timestamp) => {
5425
+ return new Date(timestamp).toLocaleString();
5426
+ };
5427
+ const formatTime = (timestamp) => {
5428
+ return new Date(timestamp).toLocaleTimeString(void 0, {
5429
+ hour: "2-digit",
5430
+ minute: "2-digit",
5431
+ second: "2-digit",
5432
+ fractionalSecondDigits: 3
5433
+ });
5434
+ };
5435
+ const formatDuration = (start, end) => {
5436
+ if (!end) return "-";
5437
+ const diff = end - start;
5438
+ if (diff < 1e3) return `${diff}ms`;
5439
+ if (diff < 6e4) return `${Math.round(diff / 1e3)}s`;
5440
+ return `${Math.round(diff / 6e4)}m ${Math.round(diff % 6e4 / 1e3)}s`;
5441
+ };
5442
+ const getStatusColor = (status) => {
5443
+ switch (status) {
5444
+ case "completed":
5445
+ return "success600";
5446
+ case "failed":
5447
+ return "danger600";
5448
+ case "in-progress":
5449
+ return "warning600";
5450
+ default:
5451
+ return "neutral600";
5452
+ }
5453
+ };
5454
+ const SortableHeader = ({ label, sortKey, activeSortKey, direction, onSort }) => {
5455
+ const isActive = sortKey === activeSortKey;
5456
+ const theme = styled.useTheme();
5457
+ return /* @__PURE__ */ jsxRuntime.jsx(
5458
+ "th",
5459
+ {
5460
+ onClick: () => onSort(sortKey),
5461
+ style: {
5462
+ textAlign: "left",
5463
+ padding: "12px 16px",
5464
+ borderBottom: `1px solid ${theme.colors.neutral150}`,
5465
+ cursor: "pointer",
5466
+ userSelect: "none"
5467
+ },
5468
+ children: /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { alignItems: "center", gap: 1, children: [
5469
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "sigma", textColor: isActive ? "primary600" : "neutral600", children: label }),
5470
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { width: 8, display: "inline-flex", flexShrink: 0 }, children: isActive && (direction === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$4L, { width: 8, height: 8 }) : /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$4N, { width: 8, height: 8 })) })
5471
+ ] })
5472
+ }
5473
+ );
5474
+ };
5475
+ const HighlightMatch = ({ text, query }) => {
5476
+ const theme = styled.useTheme();
5477
+ if (!query) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: text });
5478
+ const escaped = query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5479
+ const parts2 = text.split(new RegExp(`(${escaped})`, "gi"));
5480
+ if (parts2.length === 1) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: text });
5481
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: parts2.map(
5482
+ (part, i2) => part.toLowerCase() === query.toLowerCase() ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { backgroundColor: theme.colors.warning200, borderRadius: "2px", padding: "0 1px" }, children: part }, i2) : part
5483
+ ) });
5484
+ };
5485
+ const StatusLabel = ({ status, searchQuery }) => {
5486
+ const { t: t2 } = useTranslation.useTranslation();
5487
+ const label = status === "in-progress" ? t2("activity_logs.status_in_progress") : status === "completed" ? t2("activity_logs.status_completed") : t2("activity_logs.status_failed");
5488
+ return /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", textColor: getStatusColor(status), children: searchQuery ? /* @__PURE__ */ jsxRuntime.jsx(HighlightMatch, { text: label, query: searchQuery }) : label });
5489
+ };
5490
+ const DEFAULT_SORT = { key: "startedAt", direction: "desc" };
5491
+ const PAGE_SIZE = 20;
5492
+ const getDuration = (session) => {
5493
+ if (!session.finishedAt) return Infinity;
5494
+ return session.finishedAt - session.startedAt;
5495
+ };
5496
+ const compareSessions = (a2, b, sortKey, direction) => {
5497
+ let cmp = 0;
5498
+ switch (sortKey) {
5499
+ case "status":
5500
+ cmp = a2.status.localeCompare(b.status);
5501
+ break;
5502
+ case "startedAt":
5503
+ cmp = a2.startedAt - b.startedAt;
5504
+ break;
5505
+ case "duration":
5506
+ cmp = getDuration(a2) - getDuration(b);
5507
+ break;
5508
+ case "initiatedBy":
5509
+ cmp = a2.initiatedBy.localeCompare(b.initiatedBy);
5510
+ break;
5511
+ case "summary":
5512
+ cmp = (a2.summary || "").localeCompare(b.summary || "");
5513
+ break;
5514
+ }
5515
+ return direction === "asc" ? cmp : -cmp;
5516
+ };
5517
+ const SessionsTable = ({ sessions, searchQuery, dateFrom, dateTo, eventType, sortPreferences, onSortChange, onSessionClick, t: t2 }) => {
5518
+ const theme = styled.useTheme();
5519
+ const stored = sortPreferences[eventType];
5520
+ const [sortKey, setSortKey] = React.useState(stored?.key || DEFAULT_SORT.key);
5521
+ const [sortDirection, setSortDirection] = React.useState(
5522
+ stored?.direction || DEFAULT_SORT.direction
5523
+ );
5524
+ const [page, setPage] = React.useState(1);
5525
+ React.useEffect(() => {
5526
+ const pref = sortPreferences[eventType];
5527
+ if (pref?.key) setSortKey(pref.key);
5528
+ if (pref?.direction) setSortDirection(pref.direction);
5529
+ }, [eventType, sortPreferences]);
5530
+ React.useEffect(() => {
5531
+ setPage(1);
5532
+ }, [searchQuery, dateFrom, dateTo, eventType]);
5533
+ const onSort = (key) => {
5534
+ const newDirection = key === sortKey ? sortDirection === "asc" ? "desc" : "asc" : "asc";
5535
+ setSortKey(key);
5536
+ setSortDirection(newDirection);
5537
+ onSortChange(eventType, key, newDirection);
5538
+ setPage(1);
5539
+ };
5540
+ const filteredSessions = sessions.filter((session) => {
5541
+ if (dateFrom) {
5542
+ const startOfDay = new Date(dateFrom.getUTCFullYear(), dateFrom.getUTCMonth(), dateFrom.getUTCDate()).getTime();
5543
+ if (session.startedAt < startOfDay) return false;
5544
+ }
5545
+ if (dateTo) {
5546
+ const endOfDay = new Date(
5547
+ dateTo.getUTCFullYear(),
5548
+ dateTo.getUTCMonth(),
5549
+ dateTo.getUTCDate(),
5550
+ 23,
5551
+ 59,
5552
+ 59,
5553
+ 999
5554
+ ).getTime();
5555
+ if (session.startedAt > endOfDay) return false;
5556
+ }
5557
+ if (!searchQuery) return true;
5558
+ const query = searchQuery.toLowerCase();
5559
+ return session.summary.toLowerCase().includes(query) || session.initiatedBy.toLowerCase().includes(query) || session.status.toLowerCase().includes(query) || formatDate(session.startedAt).toLowerCase().includes(query);
5560
+ }).sort((a2, b) => compareSessions(a2, b, sortKey, sortDirection));
5561
+ const totalCount = filteredSessions.length;
5562
+ const totalPages = Math.max(1, Math.ceil(totalCount / PAGE_SIZE));
5563
+ const safePage = Math.min(page, totalPages);
5564
+ const paginatedSessions = filteredSessions.slice((safePage - 1) * PAGE_SIZE, safePage * PAGE_SIZE);
5565
+ if (filteredSessions.length === 0) {
5566
+ return /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", textColor: "neutral600", children: t2("activity_logs.no_sessions") }) });
5567
+ }
5568
+ return /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { children: [
5569
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
5570
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
5571
+ /* @__PURE__ */ jsxRuntime.jsx(
5572
+ SortableHeader,
5573
+ {
5574
+ label: t2("activity_logs.status"),
5575
+ sortKey: "status",
5576
+ activeSortKey: sortKey,
5577
+ direction: sortDirection,
5578
+ onSort
5579
+ }
5580
+ ),
5581
+ /* @__PURE__ */ jsxRuntime.jsx(
5582
+ SortableHeader,
5583
+ {
5584
+ label: t2("activity_logs.started_at"),
5585
+ sortKey: "startedAt",
5586
+ activeSortKey: sortKey,
5587
+ direction: sortDirection,
5588
+ onSort
5589
+ }
5590
+ ),
5591
+ /* @__PURE__ */ jsxRuntime.jsx(
5592
+ SortableHeader,
5593
+ {
5594
+ label: t2("activity_logs.duration"),
5595
+ sortKey: "duration",
5596
+ activeSortKey: sortKey,
5597
+ direction: sortDirection,
5598
+ onSort
5599
+ }
5600
+ ),
5601
+ /* @__PURE__ */ jsxRuntime.jsx(
5602
+ SortableHeader,
5603
+ {
5604
+ label: t2("activity_logs.initiated_by"),
5605
+ sortKey: "initiatedBy",
5606
+ activeSortKey: sortKey,
5607
+ direction: sortDirection,
5608
+ onSort
5609
+ }
5610
+ ),
5611
+ /* @__PURE__ */ jsxRuntime.jsx(
5612
+ SortableHeader,
5613
+ {
5614
+ label: t2("activity_logs.summary"),
5615
+ sortKey: "summary",
5616
+ activeSortKey: sortKey,
5617
+ direction: sortDirection,
5618
+ onSort
5619
+ }
5620
+ )
5621
+ ] }) }),
5622
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: paginatedSessions.map((session) => /* @__PURE__ */ jsxRuntime.jsxs(
5623
+ "tr",
5624
+ {
5625
+ onClick: () => onSessionClick(session.id),
5626
+ style: { cursor: "pointer", borderBottom: `1px solid ${theme.colors.neutral150}` },
5627
+ onMouseEnter: (e2) => {
5628
+ e2.currentTarget.style.backgroundColor = theme.colors.neutral100;
5629
+ },
5630
+ onMouseLeave: (e2) => {
5631
+ e2.currentTarget.style.backgroundColor = "transparent";
5632
+ },
5633
+ children: [
5634
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 16px" }, children: /* @__PURE__ */ jsxRuntime.jsx(StatusLabel, { status: session.status, searchQuery }) }),
5635
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 16px" }, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: /* @__PURE__ */ jsxRuntime.jsx(HighlightMatch, { text: formatDate(session.startedAt), query: searchQuery }) }) }),
5636
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 16px" }, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: formatDuration(session.startedAt, session.finishedAt) }) }),
5637
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 16px" }, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: /* @__PURE__ */ jsxRuntime.jsx(HighlightMatch, { text: session.initiatedBy, query: searchQuery }) }) }),
5638
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 16px" }, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: /* @__PURE__ */ jsxRuntime.jsx(HighlightMatch, { text: session.summary || "-", query: searchQuery }) }) })
5639
+ ]
5640
+ },
5641
+ session.id
5642
+ )) })
5643
+ ] }),
5644
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { paddingTop: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(index$1.Pagination, { activePage: safePage, pageCount: totalPages, children: [
5645
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.PreviousLink, { onClick: () => setPage(Math.max(1, safePage - 1)) }),
5646
+ (() => {
5647
+ const pages = [];
5648
+ const WINDOW = 2;
5649
+ if (totalPages <= 7) {
5650
+ for (let i2 = 1; i2 <= totalPages; i2++) {
5651
+ pages.push(/* @__PURE__ */ jsxRuntime.jsx(index$1.PageLink, { number: i2, onClick: () => setPage(i2) }, i2));
5652
+ }
5653
+ } else {
5654
+ pages.push(/* @__PURE__ */ jsxRuntime.jsx(index$1.PageLink, { number: 1, onClick: () => setPage(1) }, 1));
5655
+ if (safePage > 1 + WINDOW + 1) {
5656
+ pages.push(/* @__PURE__ */ jsxRuntime.jsx(index$1.Dots, {}, "dots-start"));
5657
+ }
5658
+ const start = Math.max(2, safePage - WINDOW);
5659
+ const end = Math.min(totalPages - 1, safePage + WINDOW);
5660
+ for (let i2 = start; i2 <= end; i2++) {
5661
+ pages.push(/* @__PURE__ */ jsxRuntime.jsx(index$1.PageLink, { number: i2, onClick: () => setPage(i2) }, i2));
5662
+ }
5663
+ if (safePage < totalPages - WINDOW - 1) {
5664
+ pages.push(/* @__PURE__ */ jsxRuntime.jsx(index$1.Dots, {}, "dots-end"));
5665
+ }
5666
+ pages.push(/* @__PURE__ */ jsxRuntime.jsx(index$1.PageLink, { number: totalPages, onClick: () => setPage(totalPages) }, totalPages));
5667
+ }
5668
+ return pages;
5669
+ })(),
5670
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.NextLink, { onClick: () => setPage(Math.min(totalPages, safePage + 1)) })
5671
+ ] }) })
5672
+ ] });
5673
+ };
5674
+ const DEBOUNCE_MS = 300;
5675
+ const useDebouncedSearch = () => {
5676
+ const [searchInput, setSearchInput] = React.useState("");
5677
+ const [searchQuery, setSearchQuery] = React.useState("");
5678
+ const debouncedSetQuery = React.useMemo(() => index$1.lodashExports.debounce((value2) => setSearchQuery(value2), DEBOUNCE_MS), []);
5679
+ React.useEffect(() => {
5680
+ return () => {
5681
+ debouncedSetQuery.cancel();
5682
+ };
5683
+ }, [debouncedSetQuery]);
5684
+ const onSearchChange = React.useCallback(
5685
+ (value2) => {
5686
+ setSearchInput(value2);
5687
+ debouncedSetQuery(value2);
5688
+ },
5689
+ [debouncedSetQuery]
5690
+ );
5691
+ return { searchInput, searchQuery, onSearchChange };
5692
+ };
5693
+ const ActivityLogs = (props) => {
5694
+ const { t: t2 } = useTranslation.useTranslation();
5695
+ const navigate = reactRouterDom.useNavigate();
5696
+ const [isLoading, setIsLoading] = React.useState(true);
5697
+ const [sessions, setSessions] = React.useState([]);
5698
+ const [activeTab, setActiveTab] = React.useState("upload");
5699
+ const { searchInput, searchQuery, onSearchChange } = useDebouncedSearch();
5700
+ const [dateFrom, setDateFrom] = React.useState(void 0);
5701
+ const [dateTo, setDateTo] = React.useState(void 0);
5702
+ const [showClearConfirm, setShowClearConfirm] = React.useState(false);
5703
+ const [clearSuccess, setClearSuccess] = React.useState(false);
5704
+ const [sortPreferences, setSortPreferences] = React.useState({});
5705
+ const saveSortTimerRef = React.useRef(null);
5706
+ const debouncedSaveSortPrefs = React.useCallback((prefs) => {
5707
+ if (saveSortTimerRef.current) clearTimeout(saveSortTimerRef.current);
5708
+ saveSortTimerRef.current = setTimeout(() => {
5709
+ void FetchIdentity.PluginSettingsService.updatePluginSettings({ activityLogsSort: prefs });
5710
+ }, 1e3);
5711
+ }, []);
5712
+ const onSortChange = (eventType, key, direction) => {
5713
+ const updated = { ...sortPreferences, [eventType]: { key, direction } };
5714
+ setSortPreferences(updated);
5715
+ debouncedSaveSortPrefs(updated);
5716
+ };
5717
+ const fetchSessions = async (type, showLoader = true) => {
5718
+ if (showLoader) setIsLoading(true);
5719
+ try {
5720
+ const data = await ActivityLogsService.getSessions(type);
5721
+ setSessions(data || []);
5722
+ } catch (e2) {
5723
+ console.error("Failed to fetch activity logs:", e2);
5724
+ setSessions([]);
5725
+ }
5726
+ if (showLoader) setIsLoading(false);
5727
+ };
5728
+ const onTabChange = (value2) => {
5729
+ setActiveTab(value2);
5730
+ void fetchSessions(value2, false);
5731
+ };
5732
+ const onSessionClick = (sessionId) => {
5733
+ navigate(`/plugins/${index.PLUGIN_ID}/activity-logs/${sessionId}`);
5734
+ };
5735
+ const onExportLogs = async () => {
5736
+ try {
5737
+ await exportLogsAsJson();
5738
+ } catch (e2) {
5739
+ console.error("Failed to export activity logs:", e2);
5740
+ }
5741
+ };
5742
+ const onClearLogs = async () => {
5743
+ try {
5744
+ await ActivityLogsService.clearSessions();
5745
+ setSessions([]);
5746
+ setClearSuccess(true);
5747
+ setShowClearConfirm(false);
5748
+ setTimeout(() => setClearSuccess(false), 3e3);
5749
+ } catch (e2) {
5750
+ console.error("Failed to clear activity logs:", e2);
5751
+ }
5752
+ };
5753
+ React.useEffect(() => {
5754
+ const init = async () => {
5755
+ try {
5756
+ const settings = await FetchIdentity.PluginSettingsService.getPluginSettings();
5757
+ if (settings?.activityLogsSort) {
5758
+ setSortPreferences(settings.activityLogsSort);
5759
+ }
5760
+ } catch {
5761
+ }
5762
+ void fetchSessions("upload");
5763
+ };
5764
+ void init();
5765
+ void FetchIdentity.PluginSettingsService.updatePluginSettings({ defaultRoute: PLUGIN_ROUTES.ACTIVITY_LOGS });
5766
+ }, []);
5767
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5768
+ /* @__PURE__ */ jsxRuntime.jsx(
5769
+ admin.Layouts.Header,
5770
+ {
5771
+ title: props.title,
5772
+ subtitle: props.subtitle,
5773
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { gap: 2, children: [
5774
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Button, { variant: "secondary", startIcon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$3P, {}), onClick: onExportLogs, children: t2("activity_logs.export_logs") }),
5775
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Button, { variant: "danger-light", startIcon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$j, {}), onClick: () => setShowClearConfirm(true), children: t2("activity_logs.clear_logs") })
5776
+ ] })
5777
+ }
5778
+ ),
5779
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { paddingRight: 10, paddingLeft: 10, paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { gap: 2, alignItems: "center", children: [
5780
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$2x, { width: 14, height: 14, fill: "neutral500" }),
5781
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "pi", textColor: "neutral500", children: t2("activity_logs.retention_info") })
5782
+ ] }) }),
5783
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
5784
+ !isLoading && /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { paddingRight: 10, paddingLeft: 10, children: [
5785
+ clearSuccess && /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { marginBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Alert, { onClose: () => setClearSuccess(false), closeLabel: t2("activity_logs.close"), variant: "success", children: t2("activity_logs.clear_logs_success") }) }),
5786
+ /* @__PURE__ */ jsxRuntime.jsxs(
5787
+ index$1.Box,
5788
+ {
5789
+ background: "neutral0",
5790
+ paddingTop: 6,
5791
+ paddingRight: 7,
5792
+ paddingBottom: 6,
5793
+ paddingLeft: 7,
5794
+ hasRadius: true,
5795
+ shadow: "tableShadow",
5796
+ children: [
5797
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { marginBottom: 4, gap: 3, wrap: "wrap", alignItems: "center", children: [
5798
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { grow: 1, basis: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Field.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(
5799
+ index$1.Field.Input,
5800
+ {
5801
+ placeholder: t2("activity_logs.search_placeholder"),
5802
+ value: searchInput,
5803
+ onChange: (e2) => onSearchChange(e2.target.value)
5804
+ }
5805
+ ) }) }),
5806
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { basis: "160px", children: /* @__PURE__ */ jsxRuntime.jsx(
5807
+ index$1.DatePicker$1,
5808
+ {
5809
+ placeholder: t2("activity_logs.date_from"),
5810
+ value: dateFrom,
5811
+ onChange: (date) => {
5812
+ if (!date) {
5813
+ setDateFrom(void 0);
5814
+ return;
5815
+ }
5816
+ setDateFrom(new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())));
5817
+ },
5818
+ onClear: () => setDateFrom(void 0),
5819
+ clearLabel: t2("activity_logs.clear"),
5820
+ size: "M"
5821
+ }
5822
+ ) }),
5823
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { basis: "160px", children: /* @__PURE__ */ jsxRuntime.jsx(
5824
+ index$1.DatePicker$1,
5825
+ {
5826
+ placeholder: t2("activity_logs.date_to"),
5827
+ value: dateTo,
5828
+ onChange: (date) => {
5829
+ if (!date) {
5830
+ setDateTo(void 0);
5831
+ return;
5832
+ }
5833
+ setDateTo(new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())));
5834
+ },
5835
+ onClear: () => setDateTo(void 0),
5836
+ clearLabel: t2("activity_logs.clear"),
5837
+ size: "M"
5838
+ }
5839
+ ) })
5840
+ ] }),
5841
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Tabs.Root, { value: activeTab, onValueChange: onTabChange, children: [
5842
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Tabs.List, { children: [
5843
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Tabs.Trigger, { value: "upload", children: t2("activity_logs.tab_upload") }),
5844
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Tabs.Trigger, { value: "download", children: t2("activity_logs.tab_download") }),
5845
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Tabs.Trigger, { value: "webhook", children: t2("activity_logs.tab_webhooks") })
5846
+ ] }),
5847
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Tabs.Content, { value: "upload", children: /* @__PURE__ */ jsxRuntime.jsx(
5848
+ SessionsTable,
5849
+ {
5850
+ sessions,
5851
+ searchQuery,
5852
+ dateFrom,
5853
+ dateTo,
5854
+ eventType: "upload",
5855
+ sortPreferences,
5856
+ onSortChange,
5857
+ onSessionClick,
5858
+ t: t2
5859
+ }
5860
+ ) }),
5861
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Tabs.Content, { value: "download", children: /* @__PURE__ */ jsxRuntime.jsx(
5862
+ SessionsTable,
5863
+ {
5864
+ sessions,
5865
+ searchQuery,
5866
+ dateFrom,
5867
+ dateTo,
5868
+ eventType: "download",
5869
+ sortPreferences,
5870
+ onSortChange,
5871
+ onSessionClick,
5872
+ t: t2
5873
+ }
5874
+ ) }),
5875
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Tabs.Content, { value: "webhook", children: /* @__PURE__ */ jsxRuntime.jsx(
5876
+ SessionsTable,
5877
+ {
5878
+ sessions,
5879
+ searchQuery,
5880
+ dateFrom,
5881
+ dateTo,
5882
+ eventType: "webhook",
5883
+ sortPreferences,
5884
+ onSortChange,
5885
+ onSessionClick,
5886
+ t: t2
5887
+ }
5888
+ ) })
5889
+ ] })
5890
+ ]
5891
+ }
5892
+ )
5893
+ ] }),
5894
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Root, { open: showClearConfirm, onOpenChange: setShowClearConfirm, children: /* @__PURE__ */ jsxRuntime.jsxs(index$1.Dialog.Content, { children: [
5895
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Header, { children: t2("activity_logs.clear_logs") }),
5896
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: t2("activity_logs.clear_logs_confirm") }) }),
5897
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Dialog.Footer, { children: [
5898
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Button, { variant: "tertiary", children: t2("activity_logs.close") }) }),
5899
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Action, { children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Button, { variant: "danger-light", onClick: onClearLogs, children: t2("activity_logs.clear_logs") }) })
5900
+ ] })
5901
+ ] }) })
5902
+ ] });
5903
+ };
5904
+ const SessionMetadata = ({ session, showEntryCount }) => {
5905
+ const { t: t2 } = useTranslation.useTranslation();
5906
+ return /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { gap: 6, wrap: "wrap", children: [
5907
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { children: [
5908
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "sigma", textColor: "neutral600", children: t2("activity_logs.status") }),
5909
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
5910
+ /* @__PURE__ */ jsxRuntime.jsx(StatusLabel, { status: session.status })
5911
+ ] }),
5912
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { children: [
5913
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "sigma", textColor: "neutral600", children: t2("activity_logs.started_at") }),
5914
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
5915
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: formatDate(session.startedAt) })
5916
+ ] }),
5917
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { children: [
5918
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "sigma", textColor: "neutral600", children: t2("activity_logs.duration") }),
5919
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
5920
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: formatDuration(session.startedAt, session.finishedAt) })
5921
+ ] }),
5922
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { children: [
5923
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "sigma", textColor: "neutral600", children: t2("activity_logs.initiated_by") }),
5924
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
5925
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: session.initiatedBy })
5926
+ ] }),
5927
+ showEntryCount !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { children: [
5928
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "sigma", textColor: "neutral600", children: t2("activity_logs.entries_count") }),
5929
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
5930
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: showEntryCount })
5931
+ ] })
5932
+ ] });
5933
+ };
5934
+ const ActivityLogDetail = (props) => {
5935
+ const { t: t2 } = useTranslation.useTranslation();
5936
+ const theme = styled.useTheme();
5937
+ const { sessionId } = reactRouterDom.useParams();
5938
+ const [isLoading, setIsLoading] = React.useState(true);
5939
+ const [session, setSession] = React.useState(null);
5940
+ const { searchInput, searchQuery, onSearchChange } = useDebouncedSearch();
5941
+ React.useEffect(() => {
5942
+ const fetchSession = async () => {
5943
+ if (!sessionId) return;
5944
+ setIsLoading(true);
5945
+ try {
5946
+ const data = await ActivityLogsService.getSession(sessionId);
5947
+ setSession(data);
5948
+ } catch (e2) {
5949
+ console.error("Failed to fetch session detail:", e2);
5950
+ }
5951
+ setIsLoading(false);
5952
+ };
5953
+ void fetchSession();
5954
+ }, [sessionId]);
5955
+ const filteredEntries = (session?.entries || []).filter((entry) => {
5956
+ if (!searchQuery) return true;
5957
+ const query = searchQuery.toLowerCase();
5958
+ return entry.message.toLowerCase().includes(query) || formatTime(entry.timestamp).toLowerCase().includes(query);
5959
+ });
5960
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5961
+ /* @__PURE__ */ jsxRuntime.jsx(
5962
+ admin.Layouts.Header,
5963
+ {
5964
+ title: props.title,
5965
+ subtitle: props.subtitle,
5966
+ navigationAction: /* @__PURE__ */ jsxRuntime.jsx(index$1.Link, { tag: reactRouterDom.NavLink, to: `/plugins/${index.PLUGIN_ID}/activity-logs`, startIcon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$57, {}), children: t2("activity_logs.back_to_list") })
5967
+ }
5968
+ ),
5969
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
5970
+ !isLoading && !session && /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { paddingRight: 10, paddingLeft: 10, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: t2("activity_logs.no_sessions") }) }),
5971
+ !isLoading && session && /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { paddingRight: 10, paddingLeft: 10, children: [
5972
+ /* @__PURE__ */ jsxRuntime.jsxs(
5973
+ index$1.Box,
5974
+ {
5975
+ background: "neutral0",
5976
+ paddingTop: 6,
5977
+ paddingRight: 7,
5978
+ paddingBottom: 6,
5979
+ paddingLeft: 7,
5980
+ hasRadius: true,
5981
+ shadow: "tableShadow",
5982
+ children: [
5983
+ /* @__PURE__ */ jsxRuntime.jsx(SessionMetadata, { session, showEntryCount: session.entries.length }),
5984
+ session.summary && /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { marginTop: 4, children: [
5985
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "sigma", textColor: "neutral600", children: t2("activity_logs.summary") }),
5986
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
5987
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: session.summary })
5988
+ ] })
5989
+ ]
5990
+ }
5991
+ ),
5992
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
5993
+ index$1.Box,
5994
+ {
5995
+ background: "neutral0",
5996
+ paddingTop: 6,
5997
+ paddingRight: 7,
5998
+ paddingBottom: 6,
5999
+ paddingLeft: 7,
6000
+ hasRadius: true,
6001
+ shadow: "tableShadow",
6002
+ children: [
6003
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { marginBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Field.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(
6004
+ index$1.Field.Input,
6005
+ {
6006
+ placeholder: t2("activity_logs.search_entries_placeholder"),
6007
+ value: searchInput,
6008
+ onChange: (e2) => onSearchChange(e2.target.value)
6009
+ }
6010
+ ) }) }),
6011
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Divider, {}),
6012
+ filteredEntries.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", textColor: "neutral600", children: t2("activity_logs.no_entries") }) }),
6013
+ filteredEntries.map((entry, index2) => /* @__PURE__ */ jsxRuntime.jsxs(
6014
+ index$1.Box,
6015
+ {
6016
+ paddingTop: 3,
6017
+ paddingBottom: 3,
6018
+ paddingLeft: 4,
6019
+ paddingRight: 4,
6020
+ style: {
6021
+ borderBottom: index2 < filteredEntries.length - 1 ? `1px solid ${theme.colors.neutral150}` : "none",
6022
+ fontFamily: "monospace"
6023
+ },
6024
+ children: [
6025
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { gap: 3, children: [
6026
+ /* @__PURE__ */ jsxRuntime.jsx(
6027
+ index$1.Typography,
6028
+ {
6029
+ variant: "pi",
6030
+ textColor: "neutral500",
6031
+ style: { whiteSpace: "nowrap", fontFamily: "monospace" },
6032
+ children: /* @__PURE__ */ jsxRuntime.jsx(HighlightMatch, { text: formatTime(entry.timestamp), query: searchQuery })
6033
+ }
6034
+ ),
6035
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", style: { fontFamily: "monospace" }, children: /* @__PURE__ */ jsxRuntime.jsx(HighlightMatch, { text: entry.message, query: searchQuery }) })
6036
+ ] }),
6037
+ entry.data && /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { marginTop: 2, marginLeft: 6, children: /* @__PURE__ */ jsxRuntime.jsx(
6038
+ index$1.Typography,
6039
+ {
6040
+ variant: "pi",
6041
+ textColor: "neutral500",
6042
+ style: {
6043
+ fontFamily: "monospace",
6044
+ whiteSpace: "pre-wrap",
6045
+ wordBreak: "break-all"
6046
+ },
6047
+ children: JSON.stringify(entry.data, null, 2)
6048
+ }
6049
+ ) })
6050
+ ]
6051
+ },
6052
+ index2
6053
+ ))
6054
+ ]
6055
+ }
6056
+ ) })
6057
+ ] })
6058
+ ] });
6059
+ };
5345
6060
  const App = () => {
5346
6061
  const { navigateToPluginRoute } = useRedirectToPluginRoute();
5347
6062
  const location2 = reactRouterDom.useLocation();
@@ -5367,24 +6082,41 @@ const App = () => {
5367
6082
  navigateToPluginRoute(lastRoute);
5368
6083
  }
5369
6084
  };
5370
- fetchData();
6085
+ void fetchData();
5371
6086
  }, [isLoggedIn, isFetchingIdentity, normalizedPath]);
5372
- return /* @__PURE__ */ jsxRuntime.jsx(index$1.DesignSystemProvider, { theme: getDefaultTheme(), children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { background: "neutral100", children: /* @__PURE__ */ jsxRuntime.jsxs(admin.Layouts.Root, { sideNav: isLoggedIn && /* @__PURE__ */ jsxRuntime.jsx(SideNav, {}), children: [
5373
- isFetchingIdentity && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
5374
- /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
5375
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: `login`, element: /* @__PURE__ */ jsxRuntime.jsx(Login, { title: headerTitle, subtitle: headerSubtitle, isLoading: false }) }),
5376
- /* @__PURE__ */ jsxRuntime.jsx(
5377
- reactRouterDom.Route,
5378
- {
5379
- path: `overview`,
5380
- element: /* @__PURE__ */ jsxRuntime.jsx(Overview, { title: headerTitle, subtitle: headerSubtitle, isLoadingProp: false })
5381
- }
5382
- ),
5383
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: `upload`, element: /* @__PURE__ */ jsxRuntime.jsx(Upload, { title: headerTitle, subtitle: headerSubtitle }) }),
5384
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: `download`, element: /* @__PURE__ */ jsxRuntime.jsx(Download, { title: headerTitle, subtitle: headerSubtitle }) }),
5385
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "*", element: /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Error, {}) })
5386
- ] })
5387
- ] }) }) });
6087
+ return /* @__PURE__ */ jsxRuntime.jsxs(index$1.DesignSystemProvider, { theme: FetchIdentity.getDefaultTheme(), children: [
6088
+ /* @__PURE__ */ jsxRuntime.jsx(FetchIdentity.HeadingFixGlobalStyle, {}),
6089
+ /* @__PURE__ */ jsxRuntime.jsx(PluginErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { background: "neutral100", children: /* @__PURE__ */ jsxRuntime.jsxs(admin.Layouts.Root, { sideNav: isLoggedIn && /* @__PURE__ */ jsxRuntime.jsx(SideNav, {}), children: [
6090
+ isFetchingIdentity && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
6091
+ /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
6092
+ /* @__PURE__ */ jsxRuntime.jsx(
6093
+ reactRouterDom.Route,
6094
+ {
6095
+ path: `login`,
6096
+ element: /* @__PURE__ */ jsxRuntime.jsx(Login, { title: headerTitle, subtitle: headerSubtitle, isLoading: false })
6097
+ }
6098
+ ),
6099
+ /* @__PURE__ */ jsxRuntime.jsx(
6100
+ reactRouterDom.Route,
6101
+ {
6102
+ path: `overview`,
6103
+ element: /* @__PURE__ */ jsxRuntime.jsx(Overview, { title: headerTitle, subtitle: headerSubtitle, isLoadingProp: false })
6104
+ }
6105
+ ),
6106
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: `upload`, element: /* @__PURE__ */ jsxRuntime.jsx(Upload, { title: headerTitle, subtitle: headerSubtitle }) }),
6107
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: `download`, element: /* @__PURE__ */ jsxRuntime.jsx(Download, { title: headerTitle, subtitle: headerSubtitle }) }),
6108
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: `activity-logs`, element: /* @__PURE__ */ jsxRuntime.jsx(ActivityLogs, { title: headerTitle, subtitle: headerSubtitle }) }),
6109
+ /* @__PURE__ */ jsxRuntime.jsx(
6110
+ reactRouterDom.Route,
6111
+ {
6112
+ path: `activity-logs/:sessionId`,
6113
+ element: /* @__PURE__ */ jsxRuntime.jsx(ActivityLogDetail, { title: headerTitle, subtitle: headerSubtitle })
6114
+ }
6115
+ ),
6116
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "*", element: /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Error, {}) })
6117
+ ] })
6118
+ ] }) }) })
6119
+ ] });
5388
6120
  };
5389
6121
  const LocalazyApp = () => /* @__PURE__ */ jsxRuntime.jsxs(FetchIdentity.LocalazyIdentityProvider, { children: [
5390
6122
  /* @__PURE__ */ jsxRuntime.jsx(FetchIdentity.FetchIdentity, {}),