@localazy/strapi-plugin 1.0.9 → 1.0.11

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 (48) hide show
  1. package/dist/_chunks/{FetchIdentity-4kkW9N7Y.js → FetchIdentity-BB5V79aG.js} +9 -1
  2. package/dist/_chunks/{FetchIdentity-BWSQAXt-.mjs → FetchIdentity-CkL7UYRt.mjs} +9 -1
  3. package/dist/_chunks/{LanguagesSelector-DwAGgpcR.mjs → LanguagesSelector-BUSLrXE9.mjs} +3 -3
  4. package/dist/_chunks/{LanguagesSelector-yWC_Yb_S.js → LanguagesSelector-DDjJ90sz.js} +3 -3
  5. package/dist/_chunks/{LocalazyApp-DnaA768k.js → LocalazyApp-BzcT9jmq.js} +104 -29
  6. package/dist/_chunks/{LocalazyApp-zySanVTu.mjs → LocalazyApp-H3kYTy7p.mjs} +104 -29
  7. package/dist/_chunks/{LocalazyContentTransferSetup-C7qVIeix.mjs → LocalazyContentTransferSetup-BrLho135.mjs} +5 -5
  8. package/dist/_chunks/{LocalazyContentTransferSetup-CeOM6bYA.js → LocalazyContentTransferSetup-rrXuAqRA.js} +5 -5
  9. package/dist/_chunks/{LocalazyGlobalSettings-ewETL3oG.js → LocalazyGlobalSettings-Dj93M25t.js} +22 -7
  10. package/dist/_chunks/{LocalazyGlobalSettings-QvuLdsLe.mjs → LocalazyGlobalSettings-NhjPAqfZ.mjs} +22 -7
  11. package/dist/_chunks/{LocalazyPanel-BXVLvFgD.js → LocalazyPanel-C1r8FU9w.js} +3 -3
  12. package/dist/_chunks/{LocalazyPanel-BotUsX-y.mjs → LocalazyPanel-DokDDR0T.mjs} +3 -3
  13. package/dist/_chunks/{LocalazyStatusColumn-C81HewMg.mjs → LocalazyStatusColumn-CaAL-caH.mjs} +2 -2
  14. package/dist/_chunks/{LocalazyStatusColumn-Dt96YcGQ.js → LocalazyStatusColumn-D50ZkXY-.js} +2 -2
  15. package/dist/_chunks/{RequireLocalazyAuth-CWBWETzC.js → RequireLocalazyAuth-C9qzj01C.js} +13 -6
  16. package/dist/_chunks/{RequireLocalazyAuth-CDuyGCrT.mjs → RequireLocalazyAuth-c-nP7C0A.mjs} +13 -6
  17. package/dist/_chunks/{entry-exclusion-service-CGV6iOkB.js → entry-exclusion-service-0Ul5AWi-.js} +1 -1
  18. package/dist/_chunks/{entry-exclusion-service-BVPICve2.mjs → entry-exclusion-service-Db6jzNVM.mjs} +1 -1
  19. package/dist/_chunks/{has-model-changed-DVYRxVhM.js → has-model-changed-CmZh9bwD.js} +2 -2
  20. package/dist/_chunks/{has-model-changed-DZL36gWh.mjs → has-model-changed-VkgGfN-6.mjs} +2 -2
  21. package/dist/_chunks/{i18n-RoETLXdU.mjs → i18n-Bga-GG_Z.mjs} +8 -1
  22. package/dist/_chunks/{i18n-0dV2P-Hm.js → i18n-DaBjUC3Y.js} +8 -1
  23. package/dist/_chunks/{index-CgI_aKe_.mjs → index-BIHAiJnE.mjs} +60 -8
  24. package/dist/_chunks/{index-CaY3BYnQ.js → index-BSNW1ypR.js} +59 -7
  25. package/dist/_chunks/{index-DsrYI6aB.mjs → index-C_svJuLd.mjs} +9 -9
  26. package/dist/_chunks/{index-CCxXsn7Z.js → index-CaHacyle.js} +9 -9
  27. package/dist/_chunks/{strapi-api-base-DjeKGUw7.mjs → strapi-api-base-BTpukPev.mjs} +1 -1
  28. package/dist/_chunks/{strapi-api-base-BE8VMlaA.js → strapi-api-base-DJi1gdZT.js} +1 -1
  29. package/dist/admin/index.js +1 -1
  30. package/dist/admin/index.mjs +1 -1
  31. package/dist/admin/src/modules/@common/components/TransferReport.d.ts +8 -1
  32. package/dist/admin/src/modules/localazy-download/locale/en.d.ts +5 -0
  33. package/dist/admin/src/modules/plugin-settings/locale/en.d.ts +2 -0
  34. package/dist/admin/src/modules/plugin-settings/services/plugin-settings-service.d.ts +1 -0
  35. package/dist/server/index.js +4114 -3975
  36. package/dist/server/index.mjs +4113 -3974
  37. package/dist/server/src/controllers/index.d.ts +1 -0
  38. package/dist/server/src/controllers/plugin-settings-controller.d.ts +1 -0
  39. package/dist/server/src/core/index.d.ts +8 -5
  40. package/dist/server/src/db/model/sync-cursor.d.ts +9 -0
  41. package/dist/server/src/index.d.ts +9 -5
  42. package/dist/server/src/services/helpers/plugin-settings-service-helper.d.ts +1 -0
  43. package/dist/server/src/services/index.d.ts +8 -5
  44. package/dist/server/src/services/localazy-transfer-download-service.d.ts +2 -1
  45. package/dist/server/src/services/plugin-settings-service.d.ts +3 -0
  46. package/dist/server/src/services/strapi-i18n-service.d.ts +2 -2
  47. package/dist/server/src/services/strapi-localazy-i18n-service.d.ts +2 -2
  48. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const strapiApiBase = require("./strapi-api-base-BE8VMlaA.js");
2
+ const strapiApiBase = require("./strapi-api-base-DJi1gdZT.js");
3
3
  const React = require("react");
4
4
  const jsxRuntime = require("react/jsx-runtime");
5
5
  const emptyIdentity = {
@@ -71,6 +71,14 @@ class PluginSettingsService {
71
71
  throw e;
72
72
  }
73
73
  }
74
+ static async getSyncCursor() {
75
+ try {
76
+ const result = await axiosInstance.get(`${BASE_PATH$1}/sync-cursor`);
77
+ return result.data;
78
+ } catch (e) {
79
+ throw e;
80
+ }
81
+ }
74
82
  }
75
83
  const BASE_PATH = "/user";
76
84
  const strapiApiInstance = strapiApiBase.createStrapiApiAxiosInstance();
@@ -1,4 +1,4 @@
1
- import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-DjeKGUw7.mjs";
1
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-BTpukPev.mjs";
2
2
  import { useState, useMemo, createContext, useContext, useEffect } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  const emptyIdentity = {
@@ -70,6 +70,14 @@ class PluginSettingsService {
70
70
  throw e;
71
71
  }
72
72
  }
73
+ static async getSyncCursor() {
74
+ try {
75
+ const result = await axiosInstance.get(`${BASE_PATH$1}/sync-cursor`);
76
+ return result.data;
77
+ } catch (e) {
78
+ throw e;
79
+ }
80
+ }
73
81
  }
74
82
  const BASE_PATH = "/user";
75
83
  const strapiApiInstance = createStrapiApiAxiosInstance();
@@ -1,8 +1,8 @@
1
- import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-DjeKGUw7.mjs";
1
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-BTpukPev.mjs";
2
2
  import { jsxs, jsx } from "react/jsx-runtime";
3
3
  import { useState, useEffect } from "react";
4
- import { c as cloneDeep } from "./FetchIdentity-BWSQAXt-.mjs";
5
- import { F as Field, M as MultiSelect, b as MultiSelectOption } from "./index-CgI_aKe_.mjs";
4
+ import { c as cloneDeep } from "./FetchIdentity-CkL7UYRt.mjs";
5
+ import { F as Field, M as MultiSelect, b as MultiSelectOption } from "./index-BIHAiJnE.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-BE8VMlaA.js");
2
+ const strapiApiBase = require("./strapi-api-base-DJi1gdZT.js");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
- const FetchIdentity = require("./FetchIdentity-4kkW9N7Y.js");
6
- const index = require("./index-CaY3BYnQ.js");
5
+ const FetchIdentity = require("./FetchIdentity-BB5V79aG.js");
6
+ const index = require("./index-BSNW1ypR.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-CaY3BYnQ.js");
5
+ const index$1 = require("./index-BSNW1ypR.js");
6
6
  const React = require("react");
7
- const FetchIdentity = require("./FetchIdentity-4kkW9N7Y.js");
8
- const index = require("./index-CCxXsn7Z.js");
7
+ const FetchIdentity = require("./FetchIdentity-BB5V79aG.js");
8
+ const index = require("./index-CaHacyle.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-BE8VMlaA.js");
12
- const LanguagesSelector = require("./LanguagesSelector-yWC_Yb_S.js");
11
+ const strapiApiBase = require("./strapi-api-base-DJi1gdZT.js");
12
+ const LanguagesSelector = require("./LanguagesSelector-DDjJ90sz.js");
13
13
  const admin = require("@strapi/strapi/admin");
14
- require("./i18n-0dV2P-Hm.js");
15
- const hasModelChanged = require("./has-model-changed-DVYRxVhM.js");
14
+ require("./i18n-DaBjUC3Y.js");
15
+ const hasModelChanged = require("./has-model-changed-CmZh9bwD.js");
16
16
  var PLUGIN_ROUTES = /* @__PURE__ */ ((PLUGIN_ROUTES2) => {
17
17
  PLUGIN_ROUTES2["ROOT"] = "";
18
18
  PLUGIN_ROUTES2["LOGIN"] = "login";
@@ -1576,6 +1576,19 @@ const areLocalesCompatible = async (defaultLocale = null, sourceLanguage = null)
1576
1576
  return false;
1577
1577
  }
1578
1578
  };
1579
+ const TransferReportItem = ({ item }) => {
1580
+ if (typeof item === "string") {
1581
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: item });
1582
+ }
1583
+ const { message, links } = item;
1584
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1585
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: message }),
1586
+ links && /* @__PURE__ */ jsxRuntime.jsxs(index$1.Box, { paddingTop: 2, children: [
1587
+ links.strapi && /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "pi", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: links.strapi, target: "_blank", rel: "noopener noreferrer", style: { marginRight: "12px" }, children: "Open in Strapi" }) }),
1588
+ links.localazy && /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "pi", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: links.localazy, target: "_blank", rel: "noopener noreferrer", children: "View in Localazy" }) })
1589
+ ] })
1590
+ ] });
1591
+ };
1579
1592
  const TransferReport = (props) => {
1580
1593
  const { t: t2 } = useTranslation.useTranslation();
1581
1594
  const [reportLocal, setReportLocal] = React.useState(props.report);
@@ -1591,7 +1604,17 @@ const TransferReport = (props) => {
1591
1604
  return null;
1592
1605
  }
1593
1606
  return reportLocal.map((item, index2) => {
1594
- return /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { marginTop: 4, marginBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Alert, { onClose: () => onCloseItem(index2), closeLabel: t2("upload.close"), variant: "default", children: item }, index2) }, index2);
1607
+ const hasLinks = typeof item !== "string" && item.links;
1608
+ return /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { marginTop: 4, marginBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
1609
+ index$1.Alert,
1610
+ {
1611
+ onClose: () => onCloseItem(index2),
1612
+ closeLabel: t2("upload.close"),
1613
+ variant: hasLinks ? "danger" : "default",
1614
+ children: /* @__PURE__ */ jsxRuntime.jsx(TransferReportItem, { item })
1615
+ },
1616
+ index2
1617
+ ) }, index2);
1595
1618
  });
1596
1619
  };
1597
1620
  const ReadDocsButton = () => {
@@ -5123,6 +5146,8 @@ const Download = (props) => {
5123
5146
  report: []
5124
5147
  });
5125
5148
  const [isDownloading, setIsDownloading] = React.useState(false);
5149
+ const [hasSyncCursor, setHasSyncCursor] = React.useState(false);
5150
+ const [showFullSyncConfirm, setShowFullSyncConfirm] = React.useState(false);
5126
5151
  const onTranslateInLocalazyClick = () => {
5127
5152
  window.open(identity.project.url, "_blank");
5128
5153
  };
@@ -5138,29 +5163,36 @@ const Download = (props) => {
5138
5163
  console.error(e2.message);
5139
5164
  }
5140
5165
  };
5141
- const onDownloadClick = async () => {
5166
+ const onDownloadClick = async (fullSync = false) => {
5142
5167
  setIsDownloading(true);
5143
5168
  setshowDownloadFinishedModal(false);
5144
5169
  setDownloadResult({
5145
5170
  success: false,
5146
5171
  report: []
5147
5172
  });
5148
- const result = await LocalazyDownloadService.download();
5173
+ const result = await LocalazyDownloadService.download({ fullSync });
5149
5174
  const { streamIdentifier } = result;
5150
5175
  downloadAlertsService.setStreamIdentifier(streamIdentifier);
5151
5176
  downloadAlertsService.onDownload((data) => {
5152
5177
  setDownloadResult((old) => ({
5153
5178
  success: data.success,
5154
- report: [...old.report || [], data.message]
5179
+ report: [...old.report || [], { message: data.message, links: data.links }]
5155
5180
  }));
5156
5181
  });
5157
- downloadAlertsService.onDownloadFinished((data) => {
5182
+ downloadAlertsService.onDownloadFinished(async (data) => {
5158
5183
  setDownloadResult((old) => ({
5159
5184
  success: data.success,
5160
- report: [...old.report || [], data.message]
5185
+ report: [...old.report || [], { message: data.message, links: data.links }]
5161
5186
  }));
5162
5187
  setIsDownloading(false);
5163
5188
  setshowDownloadFinishedModal(true);
5189
+ try {
5190
+ const cursor = await FetchIdentity.PluginSettingsService.getSyncCursor();
5191
+ setHasSyncCursor(
5192
+ cursor?.processedKeys !== void 0 && Object.keys(cursor.processedKeys).length > 0
5193
+ );
5194
+ } catch (_e) {
5195
+ }
5164
5196
  });
5165
5197
  ProductAnalyticsService.trackDownloadToStrapi(identity.user.id, identity.project, {
5166
5198
  "Target Languages Codes": "all"
@@ -5169,14 +5201,18 @@ const Download = (props) => {
5169
5201
  React.useEffect(() => {
5170
5202
  async function initComponent() {
5171
5203
  setIsLoading(true);
5172
- const [modelChangedResult, localesCompatibleResult, project, globalSettings] = await Promise.all([
5204
+ const [modelChangedResult, localesCompatibleResult, project, globalSettings, syncCursor] = await Promise.all([
5173
5205
  hasModelChanged.hasModelChanged(),
5174
5206
  areLocalesCompatible(),
5175
5207
  LanguagesSelector.ProjectService.getConnectedProject(),
5176
- FetchIdentity.PluginSettingsService.getPluginSettings()
5208
+ FetchIdentity.PluginSettingsService.getPluginSettings(),
5209
+ FetchIdentity.PluginSettingsService.getSyncCursor()
5177
5210
  ]);
5178
5211
  setModelChanged(modelChangedResult);
5179
5212
  setLocalesIncompatible(!localesCompatibleResult);
5213
+ setHasSyncCursor(
5214
+ syncCursor?.processedKeys !== void 0 && Object.keys(syncCursor.processedKeys).length > 0
5215
+ );
5180
5216
  const projectLanguagesWithoutDefaultLanguage = project?.languages?.filter((language) => language.id !== project.sourceLanguage) || [];
5181
5217
  setProjectLanguages(projectLanguagesWithoutDefaultLanguage);
5182
5218
  setFormModel(globalSettings);
@@ -5191,16 +5227,28 @@ const Download = (props) => {
5191
5227
  {
5192
5228
  title: props.title,
5193
5229
  subtitle: props.subtitle,
5194
- primaryAction: /* @__PURE__ */ jsxRuntime.jsx(
5195
- index$1.Button,
5196
- {
5197
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$3P, {}),
5198
- disabled: isLoading || modelChanged || localesIncompatible,
5199
- loading: isDownloading,
5200
- onClick: onDownloadClick,
5201
- children: t2("download.download_to_strapi")
5202
- }
5203
- ),
5230
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsxs(index$1.Flex, { gap: 2, children: [
5231
+ /* @__PURE__ */ jsxRuntime.jsx(
5232
+ index$1.Button,
5233
+ {
5234
+ variant: "secondary",
5235
+ disabled: isLoading || modelChanged || localesIncompatible,
5236
+ loading: isDownloading,
5237
+ onClick: () => setShowFullSyncConfirm(true),
5238
+ children: t2("download.full_sync")
5239
+ }
5240
+ ),
5241
+ /* @__PURE__ */ jsxRuntime.jsx(
5242
+ index$1.Button,
5243
+ {
5244
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(index$1.ForwardRef$3P, {}),
5245
+ disabled: isLoading || modelChanged || localesIncompatible || !hasSyncCursor,
5246
+ loading: isDownloading,
5247
+ onClick: () => onDownloadClick(false),
5248
+ children: t2("download.incremental_download")
5249
+ }
5250
+ )
5251
+ ] }),
5204
5252
  as: "h2"
5205
5253
  }
5206
5254
  ),
@@ -5274,29 +5322,56 @@ const Download = (props) => {
5274
5322
  children: t2("download.please_update_your_content")
5275
5323
  }
5276
5324
  ) }),
5325
+ !hasSyncCursor && /* @__PURE__ */ jsxRuntime.jsx(index$1.Box, { marginTop: 4, marginBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Alert, { title: t2("download.incremental_disabled_hint"), variant: "default", children: t2("download.incremental_disabled_hint") }) }),
5277
5326
  downloadResult.report && downloadResult.report.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(TransferReport, { report: downloadResult.report })
5278
- ] })
5327
+ ] }),
5328
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Root, { open: showFullSyncConfirm, onOpenChange: setShowFullSyncConfirm, children: /* @__PURE__ */ jsxRuntime.jsxs(index$1.Dialog.Content, { children: [
5329
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Header, { children: t2("download.full_sync_confirm_title") }),
5330
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Typography, { variant: "omega", children: t2("download.full_sync_confirm_message") }) }),
5331
+ /* @__PURE__ */ jsxRuntime.jsxs(index$1.Dialog.Footer, { children: [
5332
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(index$1.Button, { variant: "tertiary", children: t2("download.close") }) }),
5333
+ /* @__PURE__ */ jsxRuntime.jsx(index$1.Dialog.Action, { children: /* @__PURE__ */ jsxRuntime.jsx(
5334
+ index$1.Button,
5335
+ {
5336
+ variant: "danger-light",
5337
+ onClick: () => {
5338
+ setShowFullSyncConfirm(false);
5339
+ onDownloadClick(true);
5340
+ },
5341
+ children: t2("download.full_sync")
5342
+ }
5343
+ ) })
5344
+ ] })
5345
+ ] }) })
5279
5346
  ] });
5280
5347
  };
5281
5348
  const App = () => {
5282
5349
  const { navigateToPluginRoute } = useRedirectToPluginRoute();
5350
+ const location2 = reactRouterDom.useLocation();
5283
5351
  const { isLoggedIn, isFetchingIdentity } = FetchIdentity.useLocalazyIdentity();
5284
5352
  const headerTitle = useHeaderTitle();
5285
5353
  const headerSubtitle = useHeaderSubtitle();
5354
+ const normalizedPath = location2.pathname.replace(/\/+$/, "");
5355
+ const pluginRoot = `/plugins/${index.PLUGIN_ID}`;
5356
+ const isAtPluginRoot = normalizedPath === pluginRoot;
5357
+ const isAtLoginRoute = normalizedPath === `${pluginRoot}/login`;
5358
+ const shouldRedirect = isAtPluginRoot || isAtLoginRoute;
5286
5359
  React.useEffect(() => {
5287
5360
  const fetchData = async () => {
5288
5361
  if (isFetchingIdentity) {
5289
5362
  return;
5290
5363
  }
5291
5364
  if (!isLoggedIn) {
5292
- navigateToPluginRoute(PLUGIN_ROUTES.LOGIN);
5293
- } else {
5365
+ if (!isAtLoginRoute) {
5366
+ navigateToPluginRoute(PLUGIN_ROUTES.LOGIN);
5367
+ }
5368
+ } else if (shouldRedirect) {
5294
5369
  const lastRoute = (await FetchIdentity.PluginSettingsService.getPluginSettings()).defaultRoute || PLUGIN_ROUTES.UPLOAD;
5295
5370
  navigateToPluginRoute(lastRoute);
5296
5371
  }
5297
5372
  };
5298
5373
  fetchData();
5299
- }, [isLoggedIn, isFetchingIdentity]);
5374
+ }, [isLoggedIn, isFetchingIdentity, normalizedPath]);
5300
5375
  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: [
5301
5376
  isFetchingIdentity && /* @__PURE__ */ jsxRuntime.jsx(PluginPageLoader, {}),
5302
5377
  /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
@@ -1,16 +1,16 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { useNavigate, useLocation, NavLink, Routes, Route } from "react-router-dom";
3
- import { i as ForwardRef$2H, j as ForwardRef$d, k as ForwardRef$3P, c as Flex, L as Loader, B as Button, e as Box, T as Typography, l as Link, m as SubNav, n as SubNavHeader, o as SubNavSections, p as SubNavSection, q as SubNavLink, r as ForwardRef$L, G as Grid, D as Divider, s as darkTheme, t as lightTheme, A as Alert, u as DesignSystemProvider } from "./index-CgI_aKe_.mjs";
3
+ import { i as ForwardRef$2H, j as ForwardRef$d, k as ForwardRef$3P, c as Flex, L as Loader, B as Button, e as Box, T as Typography, l as Link, m as SubNav, n as SubNavHeader, o as SubNavSections, p as SubNavSection, q as SubNavLink, r as ForwardRef$L, G as Grid, D as Divider, s as darkTheme, t as lightTheme, A as Alert, u as Dialog, v as DesignSystemProvider } from "./index-BIHAiJnE.mjs";
4
4
  import { useState, useEffect } from "react";
5
- import { u as useLocalazyIdentity, v as LocalazyUserService, w as emptyIdentity, P as PluginSettingsService, c as cloneDeep, s as set, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-BWSQAXt-.mjs";
6
- import { P as PLUGIN_ID } from "./index-DsrYI6aB.mjs";
5
+ import { u as useLocalazyIdentity, v as LocalazyUserService, w as emptyIdentity, P as PluginSettingsService, c as cloneDeep, s as set, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-CkL7UYRt.mjs";
6
+ import { P as PLUGIN_ID } from "./index-C_svJuLd.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-DjeKGUw7.mjs";
10
- import { P as ProjectService, L as LanguagesSelector } from "./LanguagesSelector-DwAGgpcR.mjs";
9
+ import { c as createStrapiApiAxiosInstance } from "./strapi-api-base-BTpukPev.mjs";
10
+ import { P as ProjectService, L as LanguagesSelector } from "./LanguagesSelector-BUSLrXE9.mjs";
11
11
  import { Layouts, Page } from "@strapi/strapi/admin";
12
- import "./i18n-RoETLXdU.mjs";
13
- import { h as hasModelChanged } from "./has-model-changed-DZL36gWh.mjs";
12
+ import "./i18n-Bga-GG_Z.mjs";
13
+ import { h as hasModelChanged } from "./has-model-changed-VkgGfN-6.mjs";
14
14
  var PLUGIN_ROUTES = /* @__PURE__ */ ((PLUGIN_ROUTES2) => {
15
15
  PLUGIN_ROUTES2["ROOT"] = "";
16
16
  PLUGIN_ROUTES2["LOGIN"] = "login";
@@ -1574,6 +1574,19 @@ const areLocalesCompatible = async (defaultLocale = null, sourceLanguage = null)
1574
1574
  return false;
1575
1575
  }
1576
1576
  };
1577
+ const TransferReportItem = ({ item }) => {
1578
+ if (typeof item === "string") {
1579
+ return /* @__PURE__ */ jsx(Fragment, { children: item });
1580
+ }
1581
+ const { message, links } = item;
1582
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1583
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", children: message }),
1584
+ links && /* @__PURE__ */ jsxs(Box, { paddingTop: 2, children: [
1585
+ links.strapi && /* @__PURE__ */ jsx(Typography, { variant: "pi", children: /* @__PURE__ */ jsx("a", { href: links.strapi, target: "_blank", rel: "noopener noreferrer", style: { marginRight: "12px" }, children: "Open in Strapi" }) }),
1586
+ links.localazy && /* @__PURE__ */ jsx(Typography, { variant: "pi", children: /* @__PURE__ */ jsx("a", { href: links.localazy, target: "_blank", rel: "noopener noreferrer", children: "View in Localazy" }) })
1587
+ ] })
1588
+ ] });
1589
+ };
1577
1590
  const TransferReport = (props) => {
1578
1591
  const { t: t2 } = useTranslation();
1579
1592
  const [reportLocal, setReportLocal] = useState(props.report);
@@ -1589,7 +1602,17 @@ const TransferReport = (props) => {
1589
1602
  return null;
1590
1603
  }
1591
1604
  return reportLocal.map((item, index) => {
1592
- return /* @__PURE__ */ jsx(Box, { marginTop: 4, marginBottom: 4, children: /* @__PURE__ */ jsx(Alert, { onClose: () => onCloseItem(index), closeLabel: t2("upload.close"), variant: "default", children: item }, index) }, index);
1605
+ const hasLinks = typeof item !== "string" && item.links;
1606
+ return /* @__PURE__ */ jsx(Box, { marginTop: 4, marginBottom: 4, children: /* @__PURE__ */ jsx(
1607
+ Alert,
1608
+ {
1609
+ onClose: () => onCloseItem(index),
1610
+ closeLabel: t2("upload.close"),
1611
+ variant: hasLinks ? "danger" : "default",
1612
+ children: /* @__PURE__ */ jsx(TransferReportItem, { item })
1613
+ },
1614
+ index
1615
+ ) }, index);
1593
1616
  });
1594
1617
  };
1595
1618
  const ReadDocsButton = () => {
@@ -5121,6 +5144,8 @@ const Download = (props) => {
5121
5144
  report: []
5122
5145
  });
5123
5146
  const [isDownloading, setIsDownloading] = useState(false);
5147
+ const [hasSyncCursor, setHasSyncCursor] = useState(false);
5148
+ const [showFullSyncConfirm, setShowFullSyncConfirm] = useState(false);
5124
5149
  const onTranslateInLocalazyClick = () => {
5125
5150
  window.open(identity.project.url, "_blank");
5126
5151
  };
@@ -5136,29 +5161,36 @@ const Download = (props) => {
5136
5161
  console.error(e2.message);
5137
5162
  }
5138
5163
  };
5139
- const onDownloadClick = async () => {
5164
+ const onDownloadClick = async (fullSync = false) => {
5140
5165
  setIsDownloading(true);
5141
5166
  setshowDownloadFinishedModal(false);
5142
5167
  setDownloadResult({
5143
5168
  success: false,
5144
5169
  report: []
5145
5170
  });
5146
- const result = await LocalazyDownloadService.download();
5171
+ const result = await LocalazyDownloadService.download({ fullSync });
5147
5172
  const { streamIdentifier } = result;
5148
5173
  downloadAlertsService.setStreamIdentifier(streamIdentifier);
5149
5174
  downloadAlertsService.onDownload((data) => {
5150
5175
  setDownloadResult((old) => ({
5151
5176
  success: data.success,
5152
- report: [...old.report || [], data.message]
5177
+ report: [...old.report || [], { message: data.message, links: data.links }]
5153
5178
  }));
5154
5179
  });
5155
- downloadAlertsService.onDownloadFinished((data) => {
5180
+ downloadAlertsService.onDownloadFinished(async (data) => {
5156
5181
  setDownloadResult((old) => ({
5157
5182
  success: data.success,
5158
- report: [...old.report || [], data.message]
5183
+ report: [...old.report || [], { message: data.message, links: data.links }]
5159
5184
  }));
5160
5185
  setIsDownloading(false);
5161
5186
  setshowDownloadFinishedModal(true);
5187
+ try {
5188
+ const cursor = await PluginSettingsService.getSyncCursor();
5189
+ setHasSyncCursor(
5190
+ cursor?.processedKeys !== void 0 && Object.keys(cursor.processedKeys).length > 0
5191
+ );
5192
+ } catch (_e) {
5193
+ }
5162
5194
  });
5163
5195
  ProductAnalyticsService.trackDownloadToStrapi(identity.user.id, identity.project, {
5164
5196
  "Target Languages Codes": "all"
@@ -5167,14 +5199,18 @@ const Download = (props) => {
5167
5199
  useEffect(() => {
5168
5200
  async function initComponent() {
5169
5201
  setIsLoading(true);
5170
- const [modelChangedResult, localesCompatibleResult, project, globalSettings] = await Promise.all([
5202
+ const [modelChangedResult, localesCompatibleResult, project, globalSettings, syncCursor] = await Promise.all([
5171
5203
  hasModelChanged(),
5172
5204
  areLocalesCompatible(),
5173
5205
  ProjectService.getConnectedProject(),
5174
- PluginSettingsService.getPluginSettings()
5206
+ PluginSettingsService.getPluginSettings(),
5207
+ PluginSettingsService.getSyncCursor()
5175
5208
  ]);
5176
5209
  setModelChanged(modelChangedResult);
5177
5210
  setLocalesIncompatible(!localesCompatibleResult);
5211
+ setHasSyncCursor(
5212
+ syncCursor?.processedKeys !== void 0 && Object.keys(syncCursor.processedKeys).length > 0
5213
+ );
5178
5214
  const projectLanguagesWithoutDefaultLanguage = project?.languages?.filter((language) => language.id !== project.sourceLanguage) || [];
5179
5215
  setProjectLanguages(projectLanguagesWithoutDefaultLanguage);
5180
5216
  setFormModel(globalSettings);
@@ -5189,16 +5225,28 @@ const Download = (props) => {
5189
5225
  {
5190
5226
  title: props.title,
5191
5227
  subtitle: props.subtitle,
5192
- primaryAction: /* @__PURE__ */ jsx(
5193
- Button,
5194
- {
5195
- startIcon: /* @__PURE__ */ jsx(ForwardRef$3P, {}),
5196
- disabled: isLoading || modelChanged || localesIncompatible,
5197
- loading: isDownloading,
5198
- onClick: onDownloadClick,
5199
- children: t2("download.download_to_strapi")
5200
- }
5201
- ),
5228
+ primaryAction: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
5229
+ /* @__PURE__ */ jsx(
5230
+ Button,
5231
+ {
5232
+ variant: "secondary",
5233
+ disabled: isLoading || modelChanged || localesIncompatible,
5234
+ loading: isDownloading,
5235
+ onClick: () => setShowFullSyncConfirm(true),
5236
+ children: t2("download.full_sync")
5237
+ }
5238
+ ),
5239
+ /* @__PURE__ */ jsx(
5240
+ Button,
5241
+ {
5242
+ startIcon: /* @__PURE__ */ jsx(ForwardRef$3P, {}),
5243
+ disabled: isLoading || modelChanged || localesIncompatible || !hasSyncCursor,
5244
+ loading: isDownloading,
5245
+ onClick: () => onDownloadClick(false),
5246
+ children: t2("download.incremental_download")
5247
+ }
5248
+ )
5249
+ ] }),
5202
5250
  as: "h2"
5203
5251
  }
5204
5252
  ),
@@ -5272,29 +5320,56 @@ const Download = (props) => {
5272
5320
  children: t2("download.please_update_your_content")
5273
5321
  }
5274
5322
  ) }),
5323
+ !hasSyncCursor && /* @__PURE__ */ jsx(Box, { marginTop: 4, marginBottom: 4, children: /* @__PURE__ */ jsx(Alert, { title: t2("download.incremental_disabled_hint"), variant: "default", children: t2("download.incremental_disabled_hint") }) }),
5275
5324
  downloadResult.report && downloadResult.report.length > 0 && /* @__PURE__ */ jsx(TransferReport, { report: downloadResult.report })
5276
- ] })
5325
+ ] }),
5326
+ /* @__PURE__ */ jsx(Dialog.Root, { open: showFullSyncConfirm, onOpenChange: setShowFullSyncConfirm, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
5327
+ /* @__PURE__ */ jsx(Dialog.Header, { children: t2("download.full_sync_confirm_title") }),
5328
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: t2("download.full_sync_confirm_message") }) }),
5329
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
5330
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: t2("download.close") }) }),
5331
+ /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(
5332
+ Button,
5333
+ {
5334
+ variant: "danger-light",
5335
+ onClick: () => {
5336
+ setShowFullSyncConfirm(false);
5337
+ onDownloadClick(true);
5338
+ },
5339
+ children: t2("download.full_sync")
5340
+ }
5341
+ ) })
5342
+ ] })
5343
+ ] }) })
5277
5344
  ] });
5278
5345
  };
5279
5346
  const App = () => {
5280
5347
  const { navigateToPluginRoute } = useRedirectToPluginRoute();
5348
+ const location2 = useLocation();
5281
5349
  const { isLoggedIn, isFetchingIdentity } = useLocalazyIdentity();
5282
5350
  const headerTitle = useHeaderTitle();
5283
5351
  const headerSubtitle = useHeaderSubtitle();
5352
+ const normalizedPath = location2.pathname.replace(/\/+$/, "");
5353
+ const pluginRoot = `/plugins/${PLUGIN_ID}`;
5354
+ const isAtPluginRoot = normalizedPath === pluginRoot;
5355
+ const isAtLoginRoute = normalizedPath === `${pluginRoot}/login`;
5356
+ const shouldRedirect = isAtPluginRoot || isAtLoginRoute;
5284
5357
  useEffect(() => {
5285
5358
  const fetchData = async () => {
5286
5359
  if (isFetchingIdentity) {
5287
5360
  return;
5288
5361
  }
5289
5362
  if (!isLoggedIn) {
5290
- navigateToPluginRoute(PLUGIN_ROUTES.LOGIN);
5291
- } else {
5363
+ if (!isAtLoginRoute) {
5364
+ navigateToPluginRoute(PLUGIN_ROUTES.LOGIN);
5365
+ }
5366
+ } else if (shouldRedirect) {
5292
5367
  const lastRoute = (await PluginSettingsService.getPluginSettings()).defaultRoute || PLUGIN_ROUTES.UPLOAD;
5293
5368
  navigateToPluginRoute(lastRoute);
5294
5369
  }
5295
5370
  };
5296
5371
  fetchData();
5297
- }, [isLoggedIn, isFetchingIdentity]);
5372
+ }, [isLoggedIn, isFetchingIdentity, normalizedPath]);
5298
5373
  return /* @__PURE__ */ jsx(DesignSystemProvider, { theme: getDefaultTheme(), children: /* @__PURE__ */ jsx(Box, { background: "neutral100", children: /* @__PURE__ */ jsxs(Layouts.Root, { sideNav: isLoggedIn && /* @__PURE__ */ jsx(SideNav, {}), children: [
5299
5374
  isFetchingIdentity && /* @__PURE__ */ jsx(PluginPageLoader, {}),
5300
5375
  /* @__PURE__ */ jsxs(Routes, { children: [
@@ -1,14 +1,14 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { forwardRef, useState, useEffect } from "react";
3
- import { i as isEqual, R as RequireLocalazyAuth } from "./RequireLocalazyAuth-CDuyGCrT.mjs";
4
- import { s as set, m as keys, n as isArrayLike, o as arrayEach, k as isArray, p as isObject, P as PluginSettingsService, c as cloneDeep, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-BWSQAXt-.mjs";
3
+ import { i as isEqual, R as RequireLocalazyAuth } from "./RequireLocalazyAuth-c-nP7C0A.mjs";
4
+ import { s as set, m as keys, n as isArrayLike, o as arrayEach, k as isArray, p as isObject, P as PluginSettingsService, c as cloneDeep, L as LocalazyIdentityProvider, F as FetchIdentity } from "./FetchIdentity-CkL7UYRt.mjs";
5
5
  import { Layouts } from "@strapi/strapi/admin";
6
- import { C as CheckboxImpl, e as Box, g as Accordion, c as Flex, h as SwitchImpl, T as Typography, B as Button, d as ForwardRef$4z, A as Alert, D as Divider } from "./index-CgI_aKe_.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-DZL36gWh.mjs";
6
+ import { C as CheckboxImpl, e as Box, g as Accordion, c as Flex, h as SwitchImpl, T as Typography, B as Button, d as ForwardRef$4z, A as Alert, D as Divider } from "./index-BIHAiJnE.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-VkgGfN-6.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-RoETLXdU.mjs";
11
+ import "./i18n-Bga-GG_Z.mjs";
12
12
  const getFilteredModelsSchemas = (models) => {
13
13
  if (!models) {
14
14
  return [];
@@ -2,15 +2,15 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
- const RequireLocalazyAuth = require("./RequireLocalazyAuth-CWBWETzC.js");
6
- const FetchIdentity = require("./FetchIdentity-4kkW9N7Y.js");
5
+ const RequireLocalazyAuth = require("./RequireLocalazyAuth-C9qzj01C.js");
6
+ const FetchIdentity = require("./FetchIdentity-BB5V79aG.js");
7
7
  const admin = require("@strapi/strapi/admin");
8
- const index = require("./index-CaY3BYnQ.js");
9
- const hasModelChanged = require("./has-model-changed-DVYRxVhM.js");
8
+ const index = require("./index-BSNW1ypR.js");
9
+ const hasModelChanged = require("./has-model-changed-CmZh9bwD.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-0dV2P-Hm.js");
13
+ require("./i18n-DaBjUC3Y.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) => {
@@ -2,13 +2,13 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
- const FetchIdentity = require("./FetchIdentity-4kkW9N7Y.js");
5
+ const FetchIdentity = require("./FetchIdentity-BB5V79aG.js");
6
6
  const admin = require("@strapi/strapi/admin");
7
- const index = require("./index-CaY3BYnQ.js");
8
- const RequireLocalazyAuth = require("./RequireLocalazyAuth-CWBWETzC.js");
9
- const LanguagesSelector = require("./LanguagesSelector-yWC_Yb_S.js");
10
- const strapiApiBase = require("./strapi-api-base-BE8VMlaA.js");
11
- require("./i18n-0dV2P-Hm.js");
7
+ const index = require("./index-BSNW1ypR.js");
8
+ const RequireLocalazyAuth = require("./RequireLocalazyAuth-C9qzj01C.js");
9
+ const LanguagesSelector = require("./LanguagesSelector-DDjJ90sz.js");
10
+ const strapiApiBase = require("./strapi-api-base-DJi1gdZT.js");
11
+ require("./i18n-DaBjUC3Y.js");
12
12
  const useTranslation = require("./useTranslation-BdIl-aLe.js");
13
13
  class PluginSettingsService {
14
14
  static async getAdminPanelUsers() {
@@ -226,7 +226,22 @@ const GlobalSettings = () => {
226
226
  hint: t("plugin_settings.webhook_languages_info"),
227
227
  placeholder: t("plugin_settings.webhook_languages_placeholder")
228
228
  }
229
- )
229
+ ),
230
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
231
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
232
+ /* @__PURE__ */ jsxRuntime.jsxs(index.Field.Root, { hint: t("plugin_settings.webhook_incremental_sync_info"), children: [
233
+ /* @__PURE__ */ jsxRuntime.jsx(index.Field.Label, { children: t("plugin_settings.webhook_incremental_sync") }),
234
+ /* @__PURE__ */ jsxRuntime.jsx(
235
+ index.Toggle,
236
+ {
237
+ offLabel: t("plugin_settings.off"),
238
+ onLabel: t("plugin_settings.on"),
239
+ checked: typeof formModel?.download?.webhookIncrementalSync === "boolean" ? formModel.download.webhookIncrementalSync : true,
240
+ onChange: (e) => patchFormModel("download.webhookIncrementalSync", e.target.checked)
241
+ }
242
+ ),
243
+ /* @__PURE__ */ jsxRuntime.jsx(index.Field.Hint, {})
244
+ ] })
230
245
  ]
231
246
  }
232
247
  ) })