@localazy/strapi-plugin 1.1.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/_chunks/{FetchIdentity-Dl2vx6zB.js → FetchIdentity-BpFOT163.js} +2 -2
  2. package/dist/_chunks/{FetchIdentity-C8-hFqEW.mjs → FetchIdentity-Cor4ooZv.mjs} +2 -2
  3. package/dist/_chunks/{LanguagesSelector-vu-Lj7L6.mjs → LanguagesSelector-BbrMKwQY.mjs} +3 -3
  4. package/dist/_chunks/{LanguagesSelector-DsW3aJ7p.js → LanguagesSelector-CC1ecWnc.js} +3 -3
  5. package/dist/_chunks/{LocalazyApp-BIll8u_G.js → LocalazyApp-D0JGRQeF.js} +87 -10
  6. package/dist/_chunks/{LocalazyApp-Dxygk1mM.mjs → LocalazyApp-DpFR8p10.mjs} +88 -11
  7. package/dist/_chunks/{LocalazyContentTransferSetup-BhEjlIgE.js → LocalazyContentTransferSetup-Cr7D-BUi.js} +5 -5
  8. package/dist/_chunks/{LocalazyContentTransferSetup-Cz88htly.mjs → LocalazyContentTransferSetup-Dael1Q4w.mjs} +5 -5
  9. package/dist/_chunks/{LocalazyGlobalSettings-B3Z8f4G8.js → LocalazyGlobalSettings-D3nG4zl7.js} +6 -6
  10. package/dist/_chunks/{LocalazyGlobalSettings-CgOADY93.mjs → LocalazyGlobalSettings-DzBI5M-K.mjs} +6 -6
  11. package/dist/_chunks/{LocalazyPanel-CQ8-K88T.js → LocalazyPanel-KQPLxTDz.js} +3 -3
  12. package/dist/_chunks/{LocalazyPanel-BjrSVZpI.mjs → LocalazyPanel-W6j8N1WC.mjs} +3 -3
  13. package/dist/_chunks/{LocalazyStatusColumn-CA34yhSE.js → LocalazyStatusColumn-B7Q_U2Lu.js} +2 -2
  14. package/dist/_chunks/{LocalazyStatusColumn-D0b2LCpg.mjs → LocalazyStatusColumn-CrhsCjgp.mjs} +2 -2
  15. package/dist/_chunks/{RequireLocalazyAuth-DpimzlRh.mjs → RequireLocalazyAuth-BwoGRfJq.mjs} +4 -4
  16. package/dist/_chunks/{RequireLocalazyAuth-BPsrUlFm.js → RequireLocalazyAuth-D3GeZPDh.js} +4 -4
  17. package/dist/_chunks/{entry-exclusion-service-nJswJPwF.js → entry-exclusion-service-Bwruvyce.js} +1 -1
  18. package/dist/_chunks/{entry-exclusion-service-DNJZg3U2.mjs → entry-exclusion-service-D7gaRHPE.mjs} +1 -1
  19. package/dist/_chunks/{has-model-changed-BnL6D-eR.js → has-model-changed-5IV9WI_-.js} +2 -2
  20. package/dist/_chunks/{has-model-changed-D6fjlIdc.mjs → has-model-changed-Dp2Vkwjw.mjs} +2 -2
  21. package/dist/_chunks/{i18n-CAsbU4pi.js → i18n-C_5tJvr0.js} +5 -1
  22. package/dist/_chunks/{i18n-QelOdIB2.mjs → i18n-o24yXf-j.mjs} +5 -1
  23. package/dist/_chunks/{index-CHjIMO9T.mjs → index-BjL9XpRh.mjs} +4 -3
  24. package/dist/_chunks/{index-CPBTdynk.mjs → index-C9hN3KbD.mjs} +8 -8
  25. package/dist/_chunks/{index-BK7lmZSN.js → index-CTkxoioB.js} +1 -0
  26. package/dist/_chunks/{index-BXPaiO0d.js → index-jAg6jjCu.js} +8 -8
  27. package/dist/_chunks/strapi-api-base-CAzGcwF6.mjs +23 -0
  28. package/dist/_chunks/strapi-api-base-IG3Pe5Sg.js +22 -0
  29. package/dist/admin/index.js +1 -1
  30. package/dist/admin/index.mjs +1 -1
  31. package/dist/admin/src/modules/@common/api/strapi-api-base.d.ts +19 -4
  32. package/dist/admin/src/modules/@common/utils/sort-by-model-name.d.ts +1 -1
  33. package/dist/admin/src/modules/activity-logs/locale/en.d.ts +4 -0
  34. package/dist/admin/src/modules/activity-logs/services/debug-bundle-service.d.ts +10 -0
  35. package/dist/server/index.js +510 -5
  36. package/dist/server/index.mjs +510 -6
  37. package/dist/server/src/controllers/debug-bundle-controller.d.ts +7 -0
  38. package/dist/server/src/controllers/index.d.ts +5 -0
  39. package/dist/server/src/core/index.d.ts +2 -0
  40. package/dist/server/src/db/model/activity-logs.d.ts +10 -0
  41. package/dist/server/src/index.d.ts +7 -0
  42. package/dist/server/src/routes/debug-bundle-routes.d.ts +9 -0
  43. package/dist/server/src/services/activity-logs-service.d.ts +3 -1
  44. package/dist/server/src/services/index.d.ts +2 -0
  45. package/dist/server/src/utils/build-debug-bundle.d.ts +68 -0
  46. package/dist/server/src/utils/sanitize-debug-bundle.d.ts +25 -0
  47. package/package.json +2 -2
  48. package/dist/_chunks/strapi-api-base-DkjMgMHl.js +0 -2425
  49. package/dist/_chunks/strapi-api-base-GgrMbYak.mjs +0 -2426
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- const strapiApiBase = require("./strapi-api-base-DkjMgMHl.js");
3
- const index = require("./index-BK7lmZSN.js");
2
+ const strapiApiBase = require("./strapi-api-base-IG3Pe5Sg.js");
3
+ const index = require("./index-CTkxoioB.js");
4
4
  const styled = require("styled-components");
5
5
  const React = require("react");
6
6
  const jsxRuntime = require("react/jsx-runtime");
@@ -1,5 +1,5 @@
1
- import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-GgrMbYak.mjs";
2
- import { U as darkTheme, V as lightTheme } from "./index-CHjIMO9T.mjs";
1
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-CAzGcwF6.mjs";
2
+ import { V as darkTheme, W as lightTheme } from "./index-BjL9XpRh.mjs";
3
3
  import { createGlobalStyle } from "styled-components";
4
4
  import { useState, useMemo, createContext, useContext, useEffect } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -1,8 +1,8 @@
1
- import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-GgrMbYak.mjs";
1
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-CAzGcwF6.mjs";
2
2
  import { jsxs, jsx } from "react/jsx-runtime";
3
3
  import { useState, useEffect } from "react";
4
- import { c as cloneDeep } from "./FetchIdentity-C8-hFqEW.mjs";
5
- import { F as Field, M as MultiSelect, b as MultiSelectOption } from "./index-CHjIMO9T.mjs";
4
+ import { c as cloneDeep } from "./FetchIdentity-Cor4ooZv.mjs";
5
+ import { F as Field, M as MultiSelect, b as MultiSelectOption } from "./index-BjL9XpRh.mjs";
6
6
  import { u as useTranslation } from "./useTranslation-CZQ4lU1m.mjs";
7
7
  const strapiApiInstance = createStrapiApiAxiosInstance();
8
8
  class ProjectService {
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
- const strapiApiBase = require("./strapi-api-base-DkjMgMHl.js");
2
+ const strapiApiBase = require("./strapi-api-base-IG3Pe5Sg.js");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
- const FetchIdentity = require("./FetchIdentity-Dl2vx6zB.js");
6
- const index = require("./index-BK7lmZSN.js");
5
+ const FetchIdentity = require("./FetchIdentity-BpFOT163.js");
6
+ const index = require("./index-CTkxoioB.js");
7
7
  const useTranslation = require("./useTranslation-BdIl-aLe.js");
8
8
  const strapiApiInstance = strapiApiBase.createStrapiApiAxiosInstance();
9
9
  class ProjectService {
@@ -2,17 +2,17 @@
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-BK7lmZSN.js");
5
+ const index$1 = require("./index-CTkxoioB.js");
6
6
  const React = require("react");
7
- const FetchIdentity = require("./FetchIdentity-Dl2vx6zB.js");
8
- const index = require("./index-BXPaiO0d.js");
7
+ const FetchIdentity = require("./FetchIdentity-BpFOT163.js");
8
+ const index = require("./index-jAg6jjCu.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-DkjMgMHl.js");
12
- const LanguagesSelector = require("./LanguagesSelector-DsW3aJ7p.js");
11
+ const strapiApiBase = require("./strapi-api-base-IG3Pe5Sg.js");
12
+ const LanguagesSelector = require("./LanguagesSelector-CC1ecWnc.js");
13
13
  const admin = require("@strapi/strapi/admin");
14
- require("./i18n-CAsbU4pi.js");
15
- const hasModelChanged = require("./has-model-changed-BnL6D-eR.js");
14
+ require("./i18n-C_5tJvr0.js");
15
+ const hasModelChanged = require("./has-model-changed-5IV9WI_-.js");
16
16
  const styled = require("styled-components");
17
17
  const _interopDefault = (e2) => e2 && e2.__esModule ? e2 : { default: e2 };
18
18
  const React__default = /* @__PURE__ */ _interopDefault(React);
@@ -1591,7 +1591,7 @@ class LocalazyUploadService {
1591
1591
  const result = await strapiApiInstance2.post(`${BASE_PATH$2}/upload`, data);
1592
1592
  return result.data;
1593
1593
  } catch (e2) {
1594
- throw e2.data;
1594
+ throw e2.response?.data ?? e2;
1595
1595
  }
1596
1596
  }
1597
1597
  }
@@ -5167,7 +5167,7 @@ class LocalazyDownloadService {
5167
5167
  const result = await strapiApiInstance2.post(`${BASE_PATH$1}/download`, data);
5168
5168
  return result.data;
5169
5169
  } catch (e2) {
5170
- throw e2.data;
5170
+ throw e2.response?.data ?? e2;
5171
5171
  }
5172
5172
  }
5173
5173
  }
@@ -5901,6 +5901,45 @@ const ActivityLogs = (props) => {
5901
5901
  ] }) })
5902
5902
  ] });
5903
5903
  };
5904
+ const LOCALAZY_HEADER = { "X-Localazy-Initiated-By": "strapi-plugin-localazy" };
5905
+ const fallbackFilename = (sessionId) => `localazy-debug-bundle-${sessionId.slice(0, 8)}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.zip`;
5906
+ const parseFilenameFromContentDisposition = (header) => {
5907
+ if (!header) return null;
5908
+ const match = /filename="?([^";]+)"?/i.exec(header);
5909
+ return match ? match[1] : null;
5910
+ };
5911
+ const triggerBrowserDownload = (blob, filename) => {
5912
+ const url2 = URL.createObjectURL(blob);
5913
+ const a2 = document.createElement("a");
5914
+ a2.href = url2;
5915
+ a2.download = filename;
5916
+ document.body.appendChild(a2);
5917
+ a2.click();
5918
+ document.body.removeChild(a2);
5919
+ setTimeout(() => URL.revokeObjectURL(url2), 3e4);
5920
+ };
5921
+ const downloadDebugBundle = async (sessionId, token, browserInfo) => {
5922
+ const backendURL = window.strapi?.backendURL ?? "";
5923
+ const encodedBrowser = btoa(unescape(encodeURIComponent(JSON.stringify(browserInfo))));
5924
+ const url2 = `${backendURL}/${index.PLUGIN_ID}/activity-logs/${encodeURIComponent(sessionId)}/bundle?browser=${encodeURIComponent(encodedBrowser)}`;
5925
+ const headers = { ...LOCALAZY_HEADER };
5926
+ if (token) {
5927
+ headers.Authorization = `Bearer ${token}`;
5928
+ }
5929
+ const response = await fetch(url2, { method: "GET", headers });
5930
+ if (!response.ok) {
5931
+ let detail = `${response.status} ${response.statusText}`;
5932
+ try {
5933
+ const text = await response.text();
5934
+ if (text) detail = `${detail} — ${text.slice(0, 200)}`;
5935
+ } catch {
5936
+ }
5937
+ throw new Error(`Failed to download debug bundle: ${detail}`);
5938
+ }
5939
+ const blob = await response.blob();
5940
+ const filename = parseFilenameFromContentDisposition(response.headers.get("content-disposition")) ?? fallbackFilename(sessionId);
5941
+ triggerBrowserDownload(blob, filename);
5942
+ };
5904
5943
  const SessionMetadata = ({ session, showEntryCount }) => {
5905
5944
  const { t: t2 } = useTranslation.useTranslation();
5906
5945
  return /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { gap: 6, wrap: "wrap", children: [
@@ -5935,8 +5974,11 @@ const ActivityLogDetail = (props) => {
5935
5974
  const { t: t2 } = useTranslation.useTranslation();
5936
5975
  const theme = styled.useTheme();
5937
5976
  const { sessionId } = reactRouterDom.useParams();
5977
+ const token = admin.useAuth("ActivityLogDetail", (state) => state.token);
5978
+ const { toggleNotification } = admin.useNotification();
5938
5979
  const [isLoading, setIsLoading] = React.useState(true);
5939
5980
  const [session, setSession] = React.useState(null);
5981
+ const [isBuildingBundle, setIsBuildingBundle] = React.useState(false);
5940
5982
  const { searchInput, searchQuery, onSearchChange } = useDebouncedSearch();
5941
5983
  React.useEffect(() => {
5942
5984
  const fetchSession = async () => {
@@ -5952,6 +5994,30 @@ const ActivityLogDetail = (props) => {
5952
5994
  };
5953
5995
  void fetchSession();
5954
5996
  }, [sessionId]);
5997
+ const onDownloadBundle = async () => {
5998
+ if (!sessionId || isBuildingBundle) return;
5999
+ setIsBuildingBundle(true);
6000
+ try {
6001
+ await downloadDebugBundle(sessionId, token, {
6002
+ userAgent: navigator.userAgent,
6003
+ language: navigator.language,
6004
+ viewport: { width: window.innerWidth, height: window.innerHeight }
6005
+ });
6006
+ toggleNotification({
6007
+ type: "success",
6008
+ message: t2("activity_logs.download_bundle_success"),
6009
+ timeout: 5e3
6010
+ });
6011
+ } catch (e2) {
6012
+ console.error("Failed to build debug bundle:", e2);
6013
+ toggleNotification({
6014
+ type: "danger",
6015
+ message: t2("activity_logs.download_bundle_error")
6016
+ });
6017
+ } finally {
6018
+ setIsBuildingBundle(false);
6019
+ }
6020
+ };
5955
6021
  const filteredEntries = (session?.entries || []).filter((entry) => {
5956
6022
  if (!searchQuery) return true;
5957
6023
  const query = searchQuery.toLowerCase();
@@ -5963,7 +6029,18 @@ const ActivityLogDetail = (props) => {
5963
6029
  {
5964
6030
  title: props.title,
5965
6031
  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") })
6032
+ 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") }),
6033
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsx(index$1.TooltipImpl, { label: t2("activity_logs.download_bundle_warning"), children: /* @__PURE__ */ jsxRuntime.jsx(
6034
+ index$1.Button,
6035
+ {
6036
+ variant: "secondary",
6037
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$3P, {}),
6038
+ onClick: onDownloadBundle,
6039
+ loading: isBuildingBundle,
6040
+ disabled: !session || isBuildingBundle,
6041
+ children: t2("activity_logs.download_bundle")
6042
+ }
6043
+ ) })
5967
6044
  }
5968
6045
  ),
5969
6046
  isLoading && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
@@ -1,16 +1,16 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { useNavigate, useLocation, NavLink, useParams, Routes, Route } from "react-router-dom";
3
- import { o as ForwardRef$2H, p as ForwardRef$d, q as ForwardRef$3P, r as ForwardRef$4j, c as Flex, L as Loader, e as Button, B as Box, T as Typography, g as Link, s as SubNav, t as SubNavHeader, u as SubNavSections, v as SubNavSection, w as SubNavLink, x as ForwardRef$L, G as Grid, j as Divider, f as ForwardRef$3, A as Alert, D as Dialog, y as ForwardRef$4L, z as ForwardRef$4N, P as Pagination, E as PreviousLink, H as PageLink, I as Dots, N as NextLink, J as lodashExports, K as ForwardRef$j, i as ForwardRef$2x, F as Field, O as DatePicker$1, Q as Tabs, R as ForwardRef$57, l as DesignSystemProvider } from "./index-CHjIMO9T.mjs";
3
+ import { o as ForwardRef$2H, p as ForwardRef$d, q as ForwardRef$3P, r as ForwardRef$4j, c as Flex, L as Loader, e as Button, B as Box, T as Typography, g as Link, s as SubNav, t as SubNavHeader, u as SubNavSections, v as SubNavSection, w as SubNavLink, x as ForwardRef$L, G as Grid, j as Divider, f as ForwardRef$3, A as Alert, D as Dialog, y as ForwardRef$4L, z as ForwardRef$4N, P as Pagination, E as PreviousLink, H as PageLink, I as Dots, N as NextLink, J as lodashExports, K as ForwardRef$j, i as ForwardRef$2x, F as Field, O as DatePicker$1, Q as Tabs, R as TooltipImpl, U as ForwardRef$57, l as DesignSystemProvider } from "./index-BjL9XpRh.mjs";
4
4
  import React__default, { useState, useEffect, useCallback, useMemo, useRef } from "react";
5
- import { u as useLocalazyIdentity, w as LocalazyUserService, x as emptyIdentity, P as PluginSettingsService, c as cloneDeep, s as set, g as getDefaultTheme, H as HeadingFixGlobalStyle, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-C8-hFqEW.mjs";
6
- import { P as PLUGIN_ID } from "./index-CPBTdynk.mjs";
5
+ import { u as useLocalazyIdentity, w as LocalazyUserService, x as emptyIdentity, P as PluginSettingsService, c as cloneDeep, s as set, g as getDefaultTheme, H as HeadingFixGlobalStyle, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-Cor4ooZv.mjs";
6
+ import { P as PLUGIN_ID } from "./index-C9hN3KbD.mjs";
7
7
  import { u as useTranslation } from "./useTranslation-CZQ4lU1m.mjs";
8
8
  import { g as getDefaultExportFromCjs } from "./_commonjsHelpers-DWwsNxpa.mjs";
9
- import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-GgrMbYak.mjs";
10
- import { P as ProjectService, L as LanguagesSelector } from "./LanguagesSelector-vu-Lj7L6.mjs";
11
- import { Layouts, Page } from "@strapi/strapi/admin";
12
- import "./i18n-QelOdIB2.mjs";
13
- import { h as hasModelChanged } from "./has-model-changed-D6fjlIdc.mjs";
9
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-CAzGcwF6.mjs";
10
+ import { P as ProjectService, L as LanguagesSelector } from "./LanguagesSelector-BbrMKwQY.mjs";
11
+ import { Layouts, useAuth, useNotification, Page } from "@strapi/strapi/admin";
12
+ import "./i18n-o24yXf-j.mjs";
13
+ import { h as hasModelChanged } from "./has-model-changed-Dp2Vkwjw.mjs";
14
14
  import { useTheme } from "styled-components";
15
15
  var PLUGIN_ROUTES = /* @__PURE__ */ ((PLUGIN_ROUTES2) => {
16
16
  PLUGIN_ROUTES2["ROOT"] = "";
@@ -1587,7 +1587,7 @@ class LocalazyUploadService {
1587
1587
  const result = await strapiApiInstance2.post(`${BASE_PATH$2}/upload`, data);
1588
1588
  return result.data;
1589
1589
  } catch (e2) {
1590
- throw e2.data;
1590
+ throw e2.response?.data ?? e2;
1591
1591
  }
1592
1592
  }
1593
1593
  }
@@ -5163,7 +5163,7 @@ class LocalazyDownloadService {
5163
5163
  const result = await strapiApiInstance2.post(`${BASE_PATH$1}/download`, data);
5164
5164
  return result.data;
5165
5165
  } catch (e2) {
5166
- throw e2.data;
5166
+ throw e2.response?.data ?? e2;
5167
5167
  }
5168
5168
  }
5169
5169
  }
@@ -5897,6 +5897,45 @@ const ActivityLogs = (props) => {
5897
5897
  ] }) })
5898
5898
  ] });
5899
5899
  };
5900
+ const LOCALAZY_HEADER = { "X-Localazy-Initiated-By": "strapi-plugin-localazy" };
5901
+ const fallbackFilename = (sessionId) => `localazy-debug-bundle-${sessionId.slice(0, 8)}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.zip`;
5902
+ const parseFilenameFromContentDisposition = (header) => {
5903
+ if (!header) return null;
5904
+ const match = /filename="?([^";]+)"?/i.exec(header);
5905
+ return match ? match[1] : null;
5906
+ };
5907
+ const triggerBrowserDownload = (blob, filename) => {
5908
+ const url2 = URL.createObjectURL(blob);
5909
+ const a2 = document.createElement("a");
5910
+ a2.href = url2;
5911
+ a2.download = filename;
5912
+ document.body.appendChild(a2);
5913
+ a2.click();
5914
+ document.body.removeChild(a2);
5915
+ setTimeout(() => URL.revokeObjectURL(url2), 3e4);
5916
+ };
5917
+ const downloadDebugBundle = async (sessionId, token, browserInfo) => {
5918
+ const backendURL = window.strapi?.backendURL ?? "";
5919
+ const encodedBrowser = btoa(unescape(encodeURIComponent(JSON.stringify(browserInfo))));
5920
+ const url2 = `${backendURL}/${PLUGIN_ID}/activity-logs/${encodeURIComponent(sessionId)}/bundle?browser=${encodeURIComponent(encodedBrowser)}`;
5921
+ const headers = { ...LOCALAZY_HEADER };
5922
+ if (token) {
5923
+ headers.Authorization = `Bearer ${token}`;
5924
+ }
5925
+ const response = await fetch(url2, { method: "GET", headers });
5926
+ if (!response.ok) {
5927
+ let detail = `${response.status} ${response.statusText}`;
5928
+ try {
5929
+ const text = await response.text();
5930
+ if (text) detail = `${detail} — ${text.slice(0, 200)}`;
5931
+ } catch {
5932
+ }
5933
+ throw new Error(`Failed to download debug bundle: ${detail}`);
5934
+ }
5935
+ const blob = await response.blob();
5936
+ const filename = parseFilenameFromContentDisposition(response.headers.get("content-disposition")) ?? fallbackFilename(sessionId);
5937
+ triggerBrowserDownload(blob, filename);
5938
+ };
5900
5939
  const SessionMetadata = ({ session, showEntryCount }) => {
5901
5940
  const { t: t2 } = useTranslation();
5902
5941
  return /* @__PURE__ */ jsxs(Flex, { gap: 6, wrap: "wrap", children: [
@@ -5931,8 +5970,11 @@ const ActivityLogDetail = (props) => {
5931
5970
  const { t: t2 } = useTranslation();
5932
5971
  const theme = useTheme();
5933
5972
  const { sessionId } = useParams();
5973
+ const token = useAuth("ActivityLogDetail", (state) => state.token);
5974
+ const { toggleNotification } = useNotification();
5934
5975
  const [isLoading, setIsLoading] = useState(true);
5935
5976
  const [session, setSession] = useState(null);
5977
+ const [isBuildingBundle, setIsBuildingBundle] = useState(false);
5936
5978
  const { searchInput, searchQuery, onSearchChange } = useDebouncedSearch();
5937
5979
  useEffect(() => {
5938
5980
  const fetchSession = async () => {
@@ -5948,6 +5990,30 @@ const ActivityLogDetail = (props) => {
5948
5990
  };
5949
5991
  void fetchSession();
5950
5992
  }, [sessionId]);
5993
+ const onDownloadBundle = async () => {
5994
+ if (!sessionId || isBuildingBundle) return;
5995
+ setIsBuildingBundle(true);
5996
+ try {
5997
+ await downloadDebugBundle(sessionId, token, {
5998
+ userAgent: navigator.userAgent,
5999
+ language: navigator.language,
6000
+ viewport: { width: window.innerWidth, height: window.innerHeight }
6001
+ });
6002
+ toggleNotification({
6003
+ type: "success",
6004
+ message: t2("activity_logs.download_bundle_success"),
6005
+ timeout: 5e3
6006
+ });
6007
+ } catch (e2) {
6008
+ console.error("Failed to build debug bundle:", e2);
6009
+ toggleNotification({
6010
+ type: "danger",
6011
+ message: t2("activity_logs.download_bundle_error")
6012
+ });
6013
+ } finally {
6014
+ setIsBuildingBundle(false);
6015
+ }
6016
+ };
5951
6017
  const filteredEntries = (session?.entries || []).filter((entry) => {
5952
6018
  if (!searchQuery) return true;
5953
6019
  const query = searchQuery.toLowerCase();
@@ -5959,7 +6025,18 @@ const ActivityLogDetail = (props) => {
5959
6025
  {
5960
6026
  title: props.title,
5961
6027
  subtitle: props.subtitle,
5962
- navigationAction: /* @__PURE__ */ jsx(Link, { tag: NavLink, to: `/plugins/${PLUGIN_ID}/activity-logs`, startIcon: /* @__PURE__ */ jsx(ForwardRef$57, {}), children: t2("activity_logs.back_to_list") })
6028
+ navigationAction: /* @__PURE__ */ jsx(Link, { tag: NavLink, to: `/plugins/${PLUGIN_ID}/activity-logs`, startIcon: /* @__PURE__ */ jsx(ForwardRef$57, {}), children: t2("activity_logs.back_to_list") }),
6029
+ primaryAction: /* @__PURE__ */ jsx(TooltipImpl, { label: t2("activity_logs.download_bundle_warning"), children: /* @__PURE__ */ jsx(
6030
+ Button,
6031
+ {
6032
+ variant: "secondary",
6033
+ startIcon: /* @__PURE__ */ jsx(ForwardRef$3P, {}),
6034
+ onClick: onDownloadBundle,
6035
+ loading: isBuildingBundle,
6036
+ disabled: !session || isBuildingBundle,
6037
+ children: t2("activity_logs.download_bundle")
6038
+ }
6039
+ ) })
5963
6040
  }
5964
6041
  ),
5965
6042
  isLoading && /* @__PURE__ */ jsx(PluginPageLoader, {}),
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
- const index = require("./index-BK7lmZSN.js");
4
+ const index = require("./index-CTkxoioB.js");
5
5
  const React = require("react");
6
- const RequireLocalazyAuth = require("./RequireLocalazyAuth-BPsrUlFm.js");
7
- const FetchIdentity = require("./FetchIdentity-Dl2vx6zB.js");
6
+ const RequireLocalazyAuth = require("./RequireLocalazyAuth-D3GeZPDh.js");
7
+ const FetchIdentity = require("./FetchIdentity-BpFOT163.js");
8
8
  const admin = require("@strapi/strapi/admin");
9
- const hasModelChanged = require("./has-model-changed-BnL6D-eR.js");
9
+ const hasModelChanged = require("./has-model-changed-5IV9WI_-.js");
10
10
  const useTranslation = require("./useTranslation-BdIl-aLe.js");
11
11
  const styled = require("styled-components");
12
12
  const index$1 = require("./index-1he9s_bs.js");
13
- require("./i18n-CAsbU4pi.js");
13
+ require("./i18n-C_5tJvr0.js");
14
14
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
15
15
  const styled__default = /* @__PURE__ */ _interopDefault(styled);
16
16
  const getFilteredModelsSchemas = (models) => {
@@ -1,14 +1,14 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { C as CheckboxImpl, B as Box, m as Accordion, c as Flex, n as SwitchImpl, T as Typography, e as Button, d as ForwardRef$4z, A as Alert, j as Divider, l as DesignSystemProvider } from "./index-CHjIMO9T.mjs";
2
+ import { C as CheckboxImpl, B as Box, m as Accordion, c as Flex, n as SwitchImpl, T as Typography, e as Button, d as ForwardRef$4z, A as Alert, j as Divider, l as DesignSystemProvider } from "./index-BjL9XpRh.mjs";
3
3
  import { forwardRef, useState, useEffect } from "react";
4
- import { i as isEqual, R as RequireLocalazyAuth } from "./RequireLocalazyAuth-DpimzlRh.mjs";
5
- import { s as set, n as keys, o as isArrayLike, p as arrayEach, l as isArray, q as isObject, P as PluginSettingsService, c as cloneDeep, g as getDefaultTheme, H as HeadingFixGlobalStyle, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-C8-hFqEW.mjs";
4
+ import { i as isEqual, R as RequireLocalazyAuth } from "./RequireLocalazyAuth-BwoGRfJq.mjs";
5
+ import { s as set, n as keys, o as isArrayLike, p as arrayEach, l as isArray, q as isObject, P as PluginSettingsService, c as cloneDeep, g as getDefaultTheme, H as HeadingFixGlobalStyle, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-Cor4ooZv.mjs";
6
6
  import { Layouts } from "@strapi/strapi/admin";
7
- import { S as SUPPORTED_CONTENT_TYPE_FIELDS, a as SUPPORTED_CUSTOM_FIELD_PLUGINS, g as getContentTransferSetupKeysSets, b as get, f as findModelValueByKey, c as StrapiModelService, d as getModelsTree, h as hasModelChanged } from "./has-model-changed-D6fjlIdc.mjs";
7
+ import { S as SUPPORTED_CONTENT_TYPE_FIELDS, a as SUPPORTED_CUSTOM_FIELD_PLUGINS, g as getContentTransferSetupKeysSets, b as get, f as findModelValueByKey, c as StrapiModelService, d as getModelsTree, h as hasModelChanged } from "./has-model-changed-Dp2Vkwjw.mjs";
8
8
  import { u as useTranslation } from "./useTranslation-CZQ4lU1m.mjs";
9
9
  import styled from "styled-components";
10
10
  import { Trans } from "./index-BIbKC7-V.mjs";
11
- import "./i18n-QelOdIB2.mjs";
11
+ import "./i18n-o24yXf-j.mjs";
12
12
  const getFilteredModelsSchemas = (models) => {
13
13
  if (!models) {
14
14
  return [];
@@ -1,15 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
- const index = require("./index-BK7lmZSN.js");
4
+ const index = require("./index-CTkxoioB.js");
5
5
  const React = require("react");
6
- const FetchIdentity = require("./FetchIdentity-Dl2vx6zB.js");
6
+ const FetchIdentity = require("./FetchIdentity-BpFOT163.js");
7
7
  const admin = require("@strapi/strapi/admin");
8
- const RequireLocalazyAuth = require("./RequireLocalazyAuth-BPsrUlFm.js");
9
- const LanguagesSelector = require("./LanguagesSelector-DsW3aJ7p.js");
8
+ const RequireLocalazyAuth = require("./RequireLocalazyAuth-D3GeZPDh.js");
9
+ const LanguagesSelector = require("./LanguagesSelector-CC1ecWnc.js");
10
10
  const useTranslation = require("./useTranslation-BdIl-aLe.js");
11
- const strapiApiBase = require("./strapi-api-base-DkjMgMHl.js");
12
- require("./i18n-CAsbU4pi.js");
11
+ const strapiApiBase = require("./strapi-api-base-IG3Pe5Sg.js");
12
+ require("./i18n-C_5tJvr0.js");
13
13
  const WEBHOOK_PATH = "/api/localazy/public/transfer/download";
14
14
  const LOCALAZY_DOCS_URL = "https://localazy.com/docs/general/webhooks";
15
15
  function WebhookSetup() {
@@ -1,13 +1,13 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { c as Flex, L as Loader, T as Typography, B as Box, A as Alert, d as ForwardRef$4z, e as Button, f as ForwardRef$3, g as Link, h as ForwardRef$2l, D as Dialog, F as Field, i as ForwardRef$2x, a as Toggle, M as MultiSelect, b as MultiSelectOption, j as Divider, S as SingleSelect, k as SingleSelectOption, l as DesignSystemProvider } from "./index-CHjIMO9T.mjs";
2
+ import { c as Flex, L as Loader, T as Typography, B as Box, A as Alert, d as ForwardRef$4z, e as Button, f as ForwardRef$3, g as Link, h as ForwardRef$2l, D as Dialog, F as Field, i as ForwardRef$2x, a as Toggle, M as MultiSelect, b as MultiSelectOption, j as Divider, S as SingleSelect, k as SingleSelectOption, l as DesignSystemProvider } from "./index-BjL9XpRh.mjs";
3
3
  import { useState, useEffect } from "react";
4
- import { P as PluginSettingsService$1, c as cloneDeep, s as set, g as getDefaultTheme, H as HeadingFixGlobalStyle, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-C8-hFqEW.mjs";
4
+ import { P as PluginSettingsService$1, c as cloneDeep, s as set, g as getDefaultTheme, H as HeadingFixGlobalStyle, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-Cor4ooZv.mjs";
5
5
  import { Layouts } from "@strapi/strapi/admin";
6
- import { i as isEqual, R as RequireLocalazyAuth } from "./RequireLocalazyAuth-DpimzlRh.mjs";
7
- import { P as ProjectService, L as LanguagesSelector } from "./LanguagesSelector-vu-Lj7L6.mjs";
6
+ import { i as isEqual, R as RequireLocalazyAuth } from "./RequireLocalazyAuth-BwoGRfJq.mjs";
7
+ import { P as ProjectService, L as LanguagesSelector } from "./LanguagesSelector-BbrMKwQY.mjs";
8
8
  import { u as useTranslation } from "./useTranslation-CZQ4lU1m.mjs";
9
- import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-GgrMbYak.mjs";
10
- import "./i18n-QelOdIB2.mjs";
9
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-CAzGcwF6.mjs";
10
+ import "./i18n-o24yXf-j.mjs";
11
11
  const WEBHOOK_PATH = "/api/localazy/public/transfer/download";
12
12
  const LOCALAZY_DOCS_URL = "https://localazy.com/docs/general/webhooks";
13
13
  function WebhookSetup() {
@@ -3,9 +3,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const reactRouterDom = require("react-router-dom");
6
- const index = require("./index-BK7lmZSN.js");
7
- const entryExclusionService = require("./entry-exclusion-service-nJswJPwF.js");
8
- require("./i18n-CAsbU4pi.js");
6
+ const index = require("./index-CTkxoioB.js");
7
+ const entryExclusionService = require("./entry-exclusion-service-Bwruvyce.js");
8
+ require("./i18n-C_5tJvr0.js");
9
9
  const useTranslation = require("./useTranslation-BdIl-aLe.js");
10
10
  const LocalazyPanel = () => {
11
11
  const { t } = useTranslation.useTranslation();
@@ -1,9 +1,9 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useState, useEffect } from "react";
3
3
  import { useLocation } from "react-router-dom";
4
- import { T as Typography, a as Toggle } from "./index-CHjIMO9T.mjs";
5
- import EntryExclusionService from "./entry-exclusion-service-DNJZg3U2.mjs";
6
- import "./i18n-QelOdIB2.mjs";
4
+ import { T as Typography, a as Toggle } from "./index-BjL9XpRh.mjs";
5
+ import EntryExclusionService from "./entry-exclusion-service-D7gaRHPE.mjs";
6
+ import "./i18n-o24yXf-j.mjs";
7
7
  import { u as useTranslation } from "./useTranslation-CZQ4lU1m.mjs";
8
8
  const LocalazyPanel = () => {
9
9
  const { t } = useTranslation();
@@ -3,8 +3,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const styled = require("styled-components");
6
- const entryExclusionService = require("./entry-exclusion-service-nJswJPwF.js");
7
- require("./i18n-CAsbU4pi.js");
6
+ const entryExclusionService = require("./entry-exclusion-service-Bwruvyce.js");
7
+ require("./i18n-C_5tJvr0.js");
8
8
  const useTranslation = require("./useTranslation-BdIl-aLe.js");
9
9
  const LocalazyStatusColumn = ({ data, model }) => {
10
10
  const { t } = useTranslation.useTranslation();
@@ -1,8 +1,8 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useState, useEffect } from "react";
3
3
  import { useTheme } from "styled-components";
4
- import EntryExclusionService from "./entry-exclusion-service-DNJZg3U2.mjs";
5
- import "./i18n-QelOdIB2.mjs";
4
+ import EntryExclusionService from "./entry-exclusion-service-D7gaRHPE.mjs";
5
+ import "./i18n-o24yXf-j.mjs";
6
6
  import { u as useTranslation } from "./useTranslation-CZQ4lU1m.mjs";
7
7
  const LocalazyStatusColumn = ({ data, model }) => {
8
8
  const { t } = useTranslation();
@@ -1,9 +1,9 @@
1
- import { S as SetCache, a as cacheHas, b as Symbol$1, e as eq, U as Uint8Array, d as setToArray, f as getAllKeys, h as getTag, i as isBuffer, j as Stack, k as isTypedArray, l as isArray, m as isObjectLike, u as useLocalazyIdentity } from "./FetchIdentity-C8-hFqEW.mjs";
1
+ import { S as SetCache, a as cacheHas, b as Symbol$1, e as eq, U as Uint8Array, d as setToArray, f as getAllKeys, h as getTag, i as isBuffer, j as Stack, k as isTypedArray, l as isArray, m as isObjectLike, u as useLocalazyIdentity } from "./FetchIdentity-Cor4ooZv.mjs";
2
2
  import { jsxs, Fragment, jsx } from "react/jsx-runtime";
3
- import { P as PLUGIN_ID } from "./index-CPBTdynk.mjs";
4
- import { B as Box, T as Typography } from "./index-CHjIMO9T.mjs";
3
+ import { P as PLUGIN_ID } from "./index-C9hN3KbD.mjs";
4
+ import { B as Box, T as Typography } from "./index-BjL9XpRh.mjs";
5
5
  import { Layouts } from "@strapi/strapi/admin";
6
- import "./i18n-QelOdIB2.mjs";
6
+ import "./i18n-o24yXf-j.mjs";
7
7
  import { u as useTranslation } from "./useTranslation-CZQ4lU1m.mjs";
8
8
  function arraySome(array, predicate) {
9
9
  var index = -1, length = array == null ? 0 : array.length;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
- const FetchIdentity = require("./FetchIdentity-Dl2vx6zB.js");
2
+ const FetchIdentity = require("./FetchIdentity-BpFOT163.js");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
- const index$1 = require("./index-BXPaiO0d.js");
5
- const index = require("./index-BK7lmZSN.js");
4
+ const index$1 = require("./index-jAg6jjCu.js");
5
+ const index = require("./index-CTkxoioB.js");
6
6
  const admin = require("@strapi/strapi/admin");
7
- require("./i18n-CAsbU4pi.js");
7
+ require("./i18n-C_5tJvr0.js");
8
8
  const useTranslation = require("./useTranslation-BdIl-aLe.js");
9
9
  function arraySome(array, predicate) {
10
10
  var index2 = -1, length = array == null ? 0 : array.length;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const strapiApiBase = require("./strapi-api-base-DkjMgMHl.js");
3
+ const strapiApiBase = require("./strapi-api-base-IG3Pe5Sg.js");
4
4
  const BASE_PATH = "/entry-exclusion";
5
5
  const axiosInstance = strapiApiBase.createStrapiApiAxiosInstance();
6
6
  class EntryExclusionService {
@@ -1,4 +1,4 @@
1
- import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-GgrMbYak.mjs";
1
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-CAzGcwF6.mjs";
2
2
  const BASE_PATH = "/entry-exclusion";
3
3
  const axiosInstance = createStrapiApiAxiosInstance();
4
4
  class EntryExclusionService {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- const FetchIdentity = require("./FetchIdentity-Dl2vx6zB.js");
3
- const strapiApiBase = require("./strapi-api-base-DkjMgMHl.js");
2
+ const FetchIdentity = require("./FetchIdentity-BpFOT163.js");
3
+ const strapiApiBase = require("./strapi-api-base-IG3Pe5Sg.js");
4
4
  const _commonjsHelpers = require("./_commonjsHelpers-Bc2YnDe1.js");
5
5
  function baseGet(object, path) {
6
6
  path = FetchIdentity.castPath(path, object);
@@ -1,5 +1,5 @@
1
- import { r as castPath, t as toKey, v as Set, d as setToArray, S as SetCache, a as cacheHas, P as PluginSettingsService } from "./FetchIdentity-C8-hFqEW.mjs";
2
- import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-GgrMbYak.mjs";
1
+ import { r as castPath, t as toKey, v as Set, d as setToArray, S as SetCache, a as cacheHas, P as PluginSettingsService } from "./FetchIdentity-Cor4ooZv.mjs";
2
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-CAzGcwF6.mjs";
3
3
  import { g as getDefaultExportFromCjs } from "./_commonjsHelpers-DWwsNxpa.mjs";
4
4
  function baseGet(object, path) {
5
5
  path = castPath(path, object);
@@ -2413,7 +2413,11 @@ const en_activity_logs = {
2413
2413
  clear: "Clear",
2414
2414
  date_from: "From",
2415
2415
  date_to: "To",
2416
- retention_info: "Activity logs are retained for the past year. Older entries are automatically removed."
2416
+ retention_info: "Activity logs are retained for the past year. Older entries are automatically removed.",
2417
+ download_bundle: "Download troubleshooting bundle",
2418
+ download_bundle_warning: "Bundle includes entry content — review before sharing.",
2419
+ download_bundle_success: "Troubleshooting bundle downloaded.",
2420
+ download_bundle_error: "Failed to build the troubleshooting bundle."
2417
2421
  };
2418
2422
  const initI18nParams = () => {
2419
2423
  return {
@@ -2411,7 +2411,11 @@ const en_activity_logs = {
2411
2411
  clear: "Clear",
2412
2412
  date_from: "From",
2413
2413
  date_to: "To",
2414
- retention_info: "Activity logs are retained for the past year. Older entries are automatically removed."
2414
+ retention_info: "Activity logs are retained for the past year. Older entries are automatically removed.",
2415
+ download_bundle: "Download troubleshooting bundle",
2416
+ download_bundle_warning: "Bundle includes entry content — review before sharing.",
2417
+ download_bundle_success: "Troubleshooting bundle downloaded.",
2418
+ download_bundle_error: "Failed to build the troubleshooting bundle."
2415
2419
  };
2416
2420
  const initI18nParams = () => {
2417
2421
  return {
@@ -51097,11 +51097,12 @@ export {
51097
51097
  DatePicker$1 as O,
51098
51098
  Pagination as P,
51099
51099
  Tabs as Q,
51100
- ForwardRef$57 as R,
51100
+ TooltipImpl as R,
51101
51101
  SingleSelect as S,
51102
51102
  Typography as T,
51103
- darkTheme as U,
51104
- lightTheme as V,
51103
+ ForwardRef$57 as U,
51104
+ darkTheme as V,
51105
+ lightTheme as W,
51105
51106
  Toggle as a,
51106
51107
  MultiSelectOption as b,
51107
51108
  Flex as c,