@mattisvensson/strapi-plugin-webatlas 0.9.6 → 0.10.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 (132) hide show
  1. package/README.md +24 -36
  2. package/dist/{_chunks/SettingTitle-77mvMRg_.mjs → admin/SettingTitle-DbsxB1V9.mjs} +2 -2
  3. package/dist/{_chunks/SettingTitle-DLj_Wwqy.js → admin/SettingTitle-uw1S5OmC.js} +2 -2
  4. package/dist/{_chunks/de-C-uxto84.mjs → admin/de-B5pRvs13.mjs} +13 -7
  5. package/dist/{_chunks/de-CGXL_3o_.js → admin/de-CqU1FU8C.js} +13 -7
  6. package/dist/{_chunks/en-B1CHnIH7.mjs → admin/en-BE-zzIv8.mjs} +13 -7
  7. package/dist/{_chunks/en-DWEd5BXK.js → admin/en-C7I90FwV.js} +13 -7
  8. package/dist/{_chunks/index-5OG4i6qO.mjs → admin/index-B07KlG03.mjs} +40 -84
  9. package/dist/{_chunks/index-BRKi-K-v.mjs → admin/index-BKWY9Ta-.mjs} +61 -24
  10. package/dist/admin/index-BXt-QjKo.js +9368 -0
  11. package/dist/{_chunks/index-VXuAEnpX.js → admin/index-BYlmJycd.js} +3 -3
  12. package/dist/{_chunks/index-Dt-AXdaw.js → admin/index-CGsC8P9P.js} +40 -84
  13. package/dist/{_chunks/index-DwaKIwAz.mjs → admin/index-CIr8o1RP.mjs} +403 -356
  14. package/dist/{_chunks/index-3pYLMhui.mjs → admin/index-CUaBX_v-.mjs} +3 -3
  15. package/dist/{_chunks/index-COfk3YSm.js → admin/index-DC5WwNdi.js} +402 -355
  16. package/dist/{_chunks/index-DTsHvlTa.js → admin/index-DkqiqVx2.js} +61 -24
  17. package/dist/admin/index-tPrfjOIn.mjs +9368 -0
  18. package/dist/admin/index.js +3 -2
  19. package/dist/admin/index.mjs +1 -1
  20. package/dist/server/index.js +5266 -4524
  21. package/dist/server/index.mjs +5264 -4523
  22. package/dist/server/src/index.d.ts +33 -13
  23. package/package.json +19 -7
  24. package/dist/_chunks/index-BOtvXSPU.js +0 -8310
  25. package/dist/_chunks/index-BWzalvVi.mjs +0 -8310
  26. package/dist/admin/src/components/CMEditViewAside/Path.d.ts +0 -5
  27. package/dist/admin/src/components/CMEditViewAside/index.d.ts +0 -3
  28. package/dist/admin/src/components/Initializer.d.ts +0 -5
  29. package/dist/admin/src/components/PathInfo.d.ts +0 -7
  30. package/dist/admin/src/components/PluginIcon.d.ts +0 -3
  31. package/dist/admin/src/components/Tooltip.d.ts +0 -3
  32. package/dist/admin/src/components/UI/Center.d.ts +0 -5
  33. package/dist/admin/src/components/UI/EmptyBox.d.ts +0 -5
  34. package/dist/admin/src/components/UI/FullLoader.d.ts +0 -3
  35. package/dist/admin/src/components/UI/index.d.ts +0 -4
  36. package/dist/admin/src/components/modals/Delete.d.ts +0 -14
  37. package/dist/admin/src/components/modals/NavCreate.d.ts +0 -1
  38. package/dist/admin/src/components/modals/NavEdit.d.ts +0 -7
  39. package/dist/admin/src/components/modals/NavModal.d.ts +0 -17
  40. package/dist/admin/src/components/modals/NavOverview.d.ts +0 -8
  41. package/dist/admin/src/components/modals/externalItem/index.d.ts +0 -15
  42. package/dist/admin/src/components/modals/index.d.ts +0 -12
  43. package/dist/admin/src/components/modals/internalItem/internalItemCreate.d.ts +0 -3
  44. package/dist/admin/src/components/modals/internalItem/internalItemEdit.d.ts +0 -3
  45. package/dist/admin/src/components/modals/useModalSharedLogic.d.ts +0 -2
  46. package/dist/admin/src/components/modals/withModalSharedLogic.d.ts +0 -3
  47. package/dist/admin/src/components/modals/wrapperItem/index.d.ts +0 -15
  48. package/dist/admin/src/contexts/index.d.ts +0 -13
  49. package/dist/admin/src/hooks/index.d.ts +0 -6
  50. package/dist/admin/src/hooks/useAllContentTypes.d.ts +0 -7
  51. package/dist/admin/src/hooks/useAllEntities.d.ts +0 -7
  52. package/dist/admin/src/hooks/useApi.d.ts +0 -17
  53. package/dist/admin/src/hooks/useNavigations.d.ts +0 -7
  54. package/dist/admin/src/hooks/usePluginConfig.d.ts +0 -9
  55. package/dist/admin/src/pages/Navigation/Page.d.ts +0 -2
  56. package/dist/admin/src/pages/Navigation/PageWrapper.d.ts +0 -7
  57. package/dist/admin/src/pages/Navigation/RouteItem.d.ts +0 -17
  58. package/dist/admin/src/pages/Navigation/SortableRouteItem.d.ts +0 -2
  59. package/dist/admin/src/pages/Navigation/index.d.ts +0 -2
  60. package/dist/admin/src/pages/Paths/PageWrapper.d.ts +0 -4
  61. package/dist/admin/src/pages/Paths/PathTable.d.ts +0 -8
  62. package/dist/admin/src/pages/Paths/SearchInput.d.ts +0 -6
  63. package/dist/admin/src/pages/Paths/TableHeader.d.ts +0 -5
  64. package/dist/admin/src/pages/Paths/TableRow.d.ts +0 -4
  65. package/dist/admin/src/pages/Paths/compareBy.d.ts +0 -3
  66. package/dist/admin/src/pages/Paths/index.d.ts +0 -2
  67. package/dist/admin/src/pages/Settings/ContentBox.d.ts +0 -5
  68. package/dist/admin/src/pages/Settings/General/ContentTypeAccordion.d.ts +0 -7
  69. package/dist/admin/src/pages/Settings/General/index.d.ts +0 -2
  70. package/dist/admin/src/pages/Settings/Navigation/index.d.ts +0 -2
  71. package/dist/admin/src/pages/Settings/PageWrapper.d.ts +0 -8
  72. package/dist/admin/src/pages/Settings/SettingTitle.d.ts +0 -4
  73. package/dist/admin/src/pages/Settings/index.d.ts +0 -4
  74. package/dist/admin/src/permissions.d.ts +0 -23
  75. package/dist/admin/src/types/index.d.ts +0 -1
  76. package/dist/admin/src/types/modal.d.ts +0 -0
  77. package/dist/admin/src/types/route.d.ts +0 -2
  78. package/dist/admin/src/utils/countChildren.d.ts +0 -2
  79. package/dist/admin/src/utils/createTempNavItemObject.d.ts +0 -24
  80. package/dist/admin/src/utils/debounce.d.ts +0 -1
  81. package/dist/admin/src/utils/dnd.d.ts +0 -13
  82. package/dist/admin/src/utils/duplicateCheck.d.ts +0 -9
  83. package/dist/admin/src/utils/getTranslation.d.ts +0 -2
  84. package/dist/admin/src/utils/index.d.ts +0 -7
  85. package/dist/admin/src/utils/typeChecks.d.ts +0 -3
  86. package/dist/server/src/bootstrap.d.ts +0 -5
  87. package/dist/server/src/config/index.d.ts +0 -10
  88. package/dist/server/src/content-types/index.d.ts +0 -184
  89. package/dist/server/src/content-types/navigation/index.d.ts +0 -50
  90. package/dist/server/src/content-types/navigation/schema.d.ts +0 -48
  91. package/dist/server/src/content-types/navitem/index.d.ts +0 -51
  92. package/dist/server/src/content-types/navitem/schema.d.ts +0 -49
  93. package/dist/server/src/content-types/route/index.d.ts +0 -83
  94. package/dist/server/src/content-types/route/schema.d.ts +0 -81
  95. package/dist/server/src/controllers/admin.d.ts +0 -14
  96. package/dist/server/src/controllers/client.d.ts +0 -8
  97. package/dist/server/src/controllers/index.d.ts +0 -22
  98. package/dist/server/src/destroy.d.ts +0 -5
  99. package/dist/server/src/middlewares/index.d.ts +0 -2
  100. package/dist/server/src/policies/has-permissions.d.ts +0 -2
  101. package/dist/server/src/policies/index.d.ts +0 -4
  102. package/dist/server/src/register.d.ts +0 -5
  103. package/dist/server/src/routes/admin.d.ts +0 -17
  104. package/dist/server/src/routes/client.d.ts +0 -12
  105. package/dist/server/src/routes/index.d.ts +0 -30
  106. package/dist/server/src/services/admin.d.ts +0 -17
  107. package/dist/server/src/services/client.d.ts +0 -8
  108. package/dist/server/src/services/index.d.ts +0 -24
  109. package/dist/server/src/utils/buildStructuredNavigation.d.ts +0 -11
  110. package/dist/server/src/utils/cleanRootKeys.d.ts +0 -1
  111. package/dist/server/src/utils/duplicateCheck.d.ts +0 -1
  112. package/dist/server/src/utils/extractRouteAndItems.d.ts +0 -2
  113. package/dist/server/src/utils/index.d.ts +0 -11
  114. package/dist/server/src/utils/navItemHandler.d.ts +0 -5
  115. package/dist/server/src/utils/pluginHelpers.d.ts +0 -3
  116. package/dist/server/src/utils/populateDeep.d.ts +0 -4
  117. package/dist/server/src/utils/reduceDepthOfOrphanedItems.d.ts +0 -2
  118. package/dist/server/src/utils/removeWaFields.d.ts +0 -1
  119. package/dist/server/src/utils/routeHandler.d.ts +0 -3
  120. package/dist/types/api.d.ts +0 -7
  121. package/dist/types/index.d.ts +0 -5
  122. package/dist/types/modal.d.ts +0 -36
  123. package/dist/types/navigation.d.ts +0 -65
  124. package/dist/types/route.d.ts +0 -32
  125. package/dist/types/strapi.d.ts +0 -53
  126. package/dist/utils/getPath.d.ts +0 -1
  127. package/dist/utils/index.d.ts +0 -5
  128. package/dist/utils/pluginConstants.d.ts +0 -3
  129. package/dist/utils/pluginId.d.ts +0 -4
  130. package/dist/utils/transformToUrl.d.ts +0 -1
  131. /package/dist/{_chunks → admin}/FullLoader-Cmsf8xS6.js +0 -0
  132. /package/dist/{_chunks → admin}/FullLoader-CrPED_dY.mjs +0 -0
@@ -3,10 +3,10 @@ import { useRef, useEffect, useState, useCallback, createContext, useMemo, creat
3
3
  import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
4
4
  import { Link, List, Information } from "@strapi/icons";
5
5
  import { useFetchClient, unstable_useContentManagerContext, useRBAC } from "@strapi/strapi/admin";
6
- import { Box, Typography, Flex, Divider, Field, Checkbox } from "@strapi/design-system";
6
+ import { Box, Typography, Flex, Checkbox, Field, SingleSelect, SingleSelectOption, Divider } from "@strapi/design-system";
7
+ import { useIntl } from "react-intl";
7
8
  import * as ReactDOM from "react-dom";
8
9
  import ReactDOM__default, { flushSync } from "react-dom";
9
- import { useIntl } from "react-intl";
10
10
  const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
11
11
  const v = glob[path];
12
12
  if (v) {
@@ -34,6 +34,7 @@ function transformToUrl(input) {
34
34
  input = input.replace(/\/+/g, "/");
35
35
  input = input.startsWith("/") ? input.slice(1) : input;
36
36
  input = input.endsWith("/") ? input.slice(0, -1) : input;
37
+ input = input.replace(/\//g, "-");
37
38
  for (const char in specialCharMap) {
38
39
  const regex = new RegExp(char, "g");
39
40
  input = input.replace(regex, specialCharMap[char]);
@@ -44,122 +45,11 @@ function transformToUrl(input) {
44
45
  input = input.replace(/-+/g, "-");
45
46
  return input;
46
47
  }
47
- const version = "0.9.5";
48
- const keywords = [];
49
- const type = "commonjs";
50
- const exports = {
51
- "./package.json": "./package.json",
52
- "./strapi-admin": {
53
- types: "./dist/admin/src/index.d.ts",
54
- source: "./admin/src/index.tsx",
55
- "import": "./dist/admin/index.mjs",
56
- require: "./dist/admin/index.js",
57
- "default": "./dist/admin/index.js"
58
- },
59
- "./strapi-server": {
60
- types: "./dist/server/src/index.d.ts",
61
- source: "./server/src/index.ts",
62
- "import": "./dist/server/index.mjs",
63
- require: "./dist/server/index.js",
64
- "default": "./dist/server/index.js"
65
- }
66
- };
67
- const files = [
68
- "dist"
69
- ];
70
- const scripts = {
71
- build: "strapi-plugin build && yalc push --publish",
72
- watch: "strapi-plugin watch",
73
- "watch:link": "strapi-plugin watch:link",
74
- verify: "strapi-plugin verify",
75
- "test:ts:front": "tsc -p admin/tsconfig.json",
76
- "test:ts:back": "tsc -p server/tsconfig.json",
77
- "test:jest": "ENV_PATH=./playground/.env jest --verbose --runInBand --forceExit",
78
- "test:cypress": "cypress run",
79
- "test:cypress:open": "cypress open",
80
- preversion: "yarn build",
81
- postversion: "git push && git push --tags"
82
- };
83
- const dependencies = {
84
- "@dnd-kit/core": "^6.3.1",
85
- "@dnd-kit/sortable": "^10.0.0",
86
- "@dnd-kit/utilities": "^3.2.2",
87
- "@strapi/design-system": "^2.0.0-rc.14",
88
- "@strapi/icons": "^2.0.0-rc.14",
89
- "react-intl": "^7.1.0"
90
- };
91
- const devDependencies = {
92
- "@strapi/sdk-plugin": "^5.0.0",
93
- "@strapi/strapi": "^5.0.0",
94
- "@strapi/typescript-utils": "^5.0.0",
95
- "@types/react": "^19.0.0",
96
- "@types/react-dom": "^19.0.0",
97
- cypress: "^13.9.0",
98
- "cypress-terminal-report": "^6.0.2",
99
- jest: "^29.7.0",
100
- prettier: "^3.4.2",
101
- react: "^19.0.0",
102
- "react-router-dom": "^6.0.0",
103
- supertest: "^7.0.0",
104
- typescript: "^5.7.2"
105
- };
106
- const peerDependencies = {
107
- "@strapi/strapi": "^5.0.0",
108
- react: "^17.0.0 || ^18.0.0",
109
- "react-dom": "^17.0.0 || ^18.0.0",
110
- "react-router-dom": "^6.0.0",
111
- "styled-components": "^6.0.0"
112
- };
113
- const description = "A strapi plugin to manage URL routes and navigations.";
114
- const strapi = {
115
- name: "webatlas",
116
- displayName: "Webatlas",
117
- description: "A strapi plugin to manage URL routes and navigations.",
118
- kind: "plugin"
119
- };
120
- const name = "@mattisvensson/strapi-plugin-webatlas";
121
- const license = "MIT";
122
- const repository = {
123
- type: "git",
124
- url: "git+ssh://git@github.com:mattisvensson/strapi-plugin-webatlas.git"
125
- };
126
- const bugs = {
127
- url: "https://github.com/mattisvensson/strapi-plugin-webatlas/issues"
128
- };
129
- const homepage = "https://github.com/mattisvensson/strapi-plugin-webatlas#readme";
130
- const author = {
131
- name: "Matti Svensson",
132
- email: "mattisvensson@web.de",
133
- url: "https://mattisvensson.dev"
134
- };
135
- const maintainers = [
136
- {
137
- name: "Matti Svensson",
138
- email: "mattisvensson@web.de",
139
- url: "https://mattisvensson.dev"
140
- }
141
- ];
142
- const packageManager = "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e";
48
+ const version = "0.10.0";
49
+ const strapi$1 = { "name": "webatlas", "displayName": "Webatlas" };
143
50
  const pluginPkg = {
144
51
  version,
145
- keywords,
146
- type,
147
- exports,
148
- files,
149
- scripts,
150
- dependencies,
151
- devDependencies,
152
- peerDependencies,
153
- description,
154
- strapi,
155
- name,
156
- license,
157
- repository,
158
- bugs,
159
- homepage,
160
- author,
161
- maintainers,
162
- packageManager
52
+ strapi: strapi$1
163
53
  };
164
54
  const PLUGIN_ID = pluginPkg.strapi.name.replace(/^(@[^-,.][\w,-]+\/|strapi-)plugin-/i, "") || "webatlas";
165
55
  const PLUGIN_NAME = pluginPkg.strapi.displayName;
@@ -180,7 +70,7 @@ function useApi() {
180
70
  const { data } = await get("/content-manager/content-types");
181
71
  return data.data;
182
72
  } catch (error) {
183
- console.warn("Cannot fetch all content types:", error);
73
+ strapi.log.error("Cannot fetch all content types:", error);
184
74
  return [];
185
75
  }
186
76
  };
@@ -195,7 +85,7 @@ function useApi() {
195
85
  const configuredUIDs = new Set(configuredTypes.map((ct) => ct.uid));
196
86
  return allContentTypes.filter((ct) => configuredUIDs.has(ct.uid));
197
87
  } catch (err) {
198
- console.error("Error fetching configured content types:", err);
88
+ strapi.log.error("Error fetching configured content types:", err);
199
89
  return [];
200
90
  }
201
91
  };
@@ -219,7 +109,7 @@ function useApi() {
219
109
  contentType
220
110
  };
221
111
  } catch (err) {
222
- console.warn(`Cannot access entities for ${contentType.uid}:`, err);
112
+ strapi.log.error(`Cannot access entities for ${contentType.uid}:`, err);
223
113
  return null;
224
114
  }
225
115
  })
@@ -227,7 +117,7 @@ function useApi() {
227
117
  entities = entityResults.map((result) => result.status === "fulfilled" ? result.value : null).filter(Boolean);
228
118
  return entities;
229
119
  } catch (err) {
230
- console.error("Error fetching entities:", err);
120
+ strapi.log.error("Error fetching entities:", err);
231
121
  throw err;
232
122
  }
233
123
  };
@@ -235,16 +125,16 @@ function useApi() {
235
125
  const { data } = await get(`/${PLUGIN_ID}/route/related?documentId=${relatedDocumentId}`);
236
126
  return data;
237
127
  };
238
- const getRoutes = async () => {
128
+ const getRoute = async (documentId) => {
129
+ const { data } = await get(`/${PLUGIN_ID}/route/${documentId}`);
130
+ return data;
131
+ };
132
+ const getAllRoutes = async () => {
239
133
  const { data } = await get(`/${PLUGIN_ID}/route`);
240
134
  return data;
241
135
  };
242
- const updateRoute = async (body, documentId) => {
243
- const { data } = await put(`/${PLUGIN_ID}/route?documentId=${documentId}`, {
244
- data: {
245
- ...body
246
- }
247
- });
136
+ const getProhibitedRouteIds = async (documentId) => {
137
+ const { data } = await get(`/${PLUGIN_ID}/route/prohibitedIds/${documentId ? `${documentId}` : ""}`);
248
138
  return data;
249
139
  };
250
140
  const getNavigation = async ({ documentId, variant } = {}) => {
@@ -282,8 +172,9 @@ function useApi() {
282
172
  fetchConfiguredContentTypes,
283
173
  fetchAllEntities,
284
174
  getRelatedRoute,
285
- getRoutes,
286
- updateRoute,
175
+ getRoute,
176
+ getAllRoutes,
177
+ getProhibitedRouteIds,
287
178
  getNavigation,
288
179
  createNavigation,
289
180
  deleteNavigation,
@@ -327,10 +218,10 @@ function usePluginConfig() {
327
218
  throw new Error(`Couldn't fetch plugin config`);
328
219
  }
329
220
  const allowedContentTypes = contentTypesArray.filter(
330
- (type2) => type2.pluginOptions?.webatlas?.enabled === true
221
+ (type) => type.pluginOptions?.webatlas?.enabled === true
331
222
  );
332
- const contentTypeUids = new Set(allowedContentTypes.map((type2) => type2.uid));
333
- const activeContentTypes = config2.selectedContentTypes.filter((type2) => contentTypeUids.has(type2.uid));
223
+ const contentTypeUids = new Set(allowedContentTypes.map((type) => type.uid));
224
+ const activeContentTypes = config2.selectedContentTypes.filter((type) => contentTypeUids.has(type.uid));
334
225
  const displayConfig = {
335
226
  ...config2,
336
227
  selectedContentTypes: activeContentTypes
@@ -353,6 +244,113 @@ function usePluginConfig() {
353
244
  }
354
245
  return { config, loading, fetchError, setConfig };
355
246
  }
247
+ function debounce(func, wait) {
248
+ let timeout;
249
+ return function executedFunction(...args) {
250
+ const later = () => {
251
+ clearTimeout(timeout);
252
+ func(...args);
253
+ };
254
+ clearTimeout(timeout);
255
+ timeout = setTimeout(later, wait);
256
+ };
257
+ }
258
+ async function duplicateCheck({
259
+ fetchFunction,
260
+ path,
261
+ routeDocumentId,
262
+ withoutTransform = false
263
+ }) {
264
+ if (!path) throw new Error("URL is required");
265
+ try {
266
+ const pathToCheck = withoutTransform ? path : transformToUrl(path);
267
+ const { data } = await fetchFunction(`/${PLUGIN_ID}/checkUniquePath?path=${pathToCheck}${routeDocumentId ? `&targetRouteDocumentId=${routeDocumentId}` : ""}`);
268
+ if (!data.uniquePath) {
269
+ throw new Error("Network response was not ok");
270
+ }
271
+ return data.uniquePath;
272
+ } catch (err) {
273
+ throw new Error("Failed to check URL uniqueness: " + err.message);
274
+ }
275
+ }
276
+ const getTranslation = (id) => `${PLUGIN_ID}.${id}`;
277
+ function PathInfo({ validationState, replacement }) {
278
+ const [color, setColor] = useState("neutral800");
279
+ const [text, setText] = useState(null);
280
+ const { formatMessage } = useIntl();
281
+ useEffect(() => {
282
+ if (validationState === "initial") return;
283
+ if (validationState === "checking") {
284
+ setColor("neutral800");
285
+ setText(formatMessage({
286
+ id: getTranslation("components.pathInfo.checking"),
287
+ defaultMessage: "Checking if path is available..."
288
+ }));
289
+ } else if (validationState === "done") {
290
+ setColor(replacement ? "danger500" : "success500");
291
+ setText(replacement ? `${formatMessage({
292
+ id: getTranslation("components.pathInfo.notAvailable"),
293
+ defaultMessage: "Path is not available. Replaced with"
294
+ })} "${replacement}".` : formatMessage({
295
+ id: getTranslation("components.pathInfo.available"),
296
+ defaultMessage: "Path is available."
297
+ }));
298
+ }
299
+ }, [validationState, replacement, formatMessage]);
300
+ return /* @__PURE__ */ jsx(Box, { paddingTop: 1, children: /* @__PURE__ */ jsx(Typography, { textColor: color, children: text }) });
301
+ }
302
+ function OverrideCheckbox({ isOverride, setIsOverride, disabledCondition }) {
303
+ const { formatMessage } = useIntl();
304
+ return /* @__PURE__ */ jsx(
305
+ Flex,
306
+ {
307
+ gap: 2,
308
+ paddingTop: 2,
309
+ children: /* @__PURE__ */ jsx(
310
+ Checkbox,
311
+ {
312
+ id: "path-override-checkbox",
313
+ checked: isOverride,
314
+ onCheckedChange: () => setIsOverride(!isOverride),
315
+ disabled: disabledCondition,
316
+ children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({
317
+ id: getTranslation("components.CMEditViewAside.path.overrideCheckbox"),
318
+ defaultMessage: "Override automatic path generation"
319
+ }) })
320
+ }
321
+ )
322
+ }
323
+ );
324
+ }
325
+ function NewPathInfo() {
326
+ const { formatMessage } = useIntl();
327
+ return /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({
328
+ id: getTranslation("components.CMEditViewAside.path.newPathInfo"),
329
+ defaultMessage: "A new path will be created upon saving this entry."
330
+ }) });
331
+ }
332
+ function UidPathDisplay({ path }) {
333
+ const { formatMessage } = useIntl();
334
+ return /* @__PURE__ */ jsxs(
335
+ Field.Root,
336
+ {
337
+ hint: formatMessage({
338
+ id: getTranslation("components.CMEditViewAside.path.uidPath.hint"),
339
+ defaultMessage: "Permanent UID path, cannot be changed"
340
+ }),
341
+ children: [
342
+ /* @__PURE__ */ jsx(
343
+ Field.Input,
344
+ {
345
+ value: path,
346
+ disabled: true
347
+ }
348
+ ),
349
+ /* @__PURE__ */ jsx(Field.Hint, {})
350
+ ]
351
+ }
352
+ );
353
+ }
356
354
  function _extends() {
357
355
  return _extends = Object.assign ? Object.assign.bind() : function(n) {
358
356
  for (var e = 1; e < arguments.length; e++) {
@@ -782,14 +780,14 @@ function $5cb92bef7577960e$var$dispatchUpdate() {
782
780
  const event = new CustomEvent($5cb92bef7577960e$var$CONTEXT_UPDATE);
783
781
  document.dispatchEvent(event);
784
782
  }
785
- function $5cb92bef7577960e$var$handleAndDispatchCustomEvent(name2, handler, detail, { discrete }) {
783
+ function $5cb92bef7577960e$var$handleAndDispatchCustomEvent(name, handler, detail, { discrete }) {
786
784
  const target = detail.originalEvent.target;
787
- const event = new CustomEvent(name2, {
785
+ const event = new CustomEvent(name, {
788
786
  bubbles: false,
789
787
  cancelable: true,
790
788
  detail
791
789
  });
792
- if (handler) target.addEventListener(name2, handler, {
790
+ if (handler) target.addEventListener(name, handler, {
793
791
  once: true
794
792
  });
795
793
  if (discrete) $8927f6f2acc4f386$export$6d1a0317bde7de7f(target, event);
@@ -1017,7 +1015,7 @@ const computePosition$1 = async (reference, floating, config) => {
1017
1015
  let resetCount = 0;
1018
1016
  for (let i = 0; i < validMiddleware.length; i++) {
1019
1017
  const {
1020
- name: name2,
1018
+ name,
1021
1019
  fn
1022
1020
  } = validMiddleware[i];
1023
1021
  const {
@@ -1043,8 +1041,8 @@ const computePosition$1 = async (reference, floating, config) => {
1043
1041
  y = nextY != null ? nextY : y;
1044
1042
  middlewareData = {
1045
1043
  ...middlewareData,
1046
- [name2]: {
1047
- ...middlewareData[name2],
1044
+ [name]: {
1045
+ ...middlewareData[name],
1048
1046
  ...data
1049
1047
  }
1050
1048
  };
@@ -3144,7 +3142,7 @@ const $ea1ef594cf570d83$export$439d29a4e110a164 = /* @__PURE__ */ forwardRef((pr
3144
3142
  }));
3145
3143
  });
3146
3144
  const $ea1ef594cf570d83$export$be92b6f5f03c0fe9 = $ea1ef594cf570d83$export$439d29a4e110a164;
3147
- const [$a093c7e1ec25a057$var$createTooltipContext, $a093c7e1ec25a057$export$1c540a2224f0d865] = $c512c27ab02ef895$export$50c7b4e9d9f19c1("Tooltip", [
3145
+ const [$a093c7e1ec25a057$var$createTooltipContext] = $c512c27ab02ef895$export$50c7b4e9d9f19c1("Tooltip", [
3148
3146
  $cf1ac5d9fe0e8206$export$722aac194ae923
3149
3147
  ]);
3150
3148
  const $a093c7e1ec25a057$var$usePopperScope = $cf1ac5d9fe0e8206$export$722aac194ae923();
@@ -3635,7 +3633,7 @@ const $a093c7e1ec25a057$export$be92b6f5f03c0fe9 = $a093c7e1ec25a057$export$28c66
3635
3633
  const $a093c7e1ec25a057$export$41fb9f06171c75f4 = $a093c7e1ec25a057$export$8c610744efcf8a1d;
3636
3634
  const $a093c7e1ec25a057$export$602eac185826482c = $a093c7e1ec25a057$export$7b36b8f925ab7497;
3637
3635
  const $a093c7e1ec25a057$export$7c6e2c02157bb7d2 = $a093c7e1ec25a057$export$e9003e2be37ec060;
3638
- function Tooltip({ description: description2 }) {
3636
+ function Tooltip({ description }) {
3639
3637
  return /* @__PURE__ */ jsx($a093c7e1ec25a057$export$2881499e37b75b9a, { children: /* @__PURE__ */ jsxs($a093c7e1ec25a057$export$be92b6f5f03c0fe9, { children: [
3640
3638
  /* @__PURE__ */ jsx($a093c7e1ec25a057$export$41fb9f06171c75f4, { asChild: true, children: /* @__PURE__ */ jsx(Information, { "aria-hidden": "true" }) }),
3641
3639
  /* @__PURE__ */ jsx($a093c7e1ec25a057$export$602eac185826482c, { children: /* @__PURE__ */ jsx($a093c7e1ec25a057$export$7c6e2c02157bb7d2, { sideOffset: 5, style: { zIndex: 9999 }, children: /* @__PURE__ */ jsx(
@@ -3647,75 +3645,137 @@ function Tooltip({ description: description2 }) {
3647
3645
  hasRadius: true,
3648
3646
  shadow: "filterShadow",
3649
3647
  maxWidth: "300px",
3650
- children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral0", children: description2 })
3648
+ children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral0", children: description })
3651
3649
  }
3652
3650
  ) }) })
3653
3651
  ] }) });
3654
3652
  }
3655
- function debounce(func, wait) {
3656
- let timeout;
3657
- return function executedFunction(...args) {
3658
- const later = () => {
3659
- clearTimeout(timeout);
3660
- func(...args);
3661
- };
3662
- clearTimeout(timeout);
3663
- timeout = setTimeout(later, wait);
3664
- };
3665
- }
3666
- async function duplicateCheck(get, url, routeDocumentId) {
3667
- if (!url) throw new Error("URL is required");
3668
- try {
3669
- const { data } = await get(`/${PLUGIN_ID}/checkUniquePath?path=${transformToUrl(url)}${routeDocumentId ? `&targetRouteDocumentId=${routeDocumentId}` : ""}`);
3670
- if (!data.uniquePath) {
3671
- throw new Error("Network response was not ok");
3653
+ function PathInput({ path, dispatchPath, isOverride, config }) {
3654
+ const { formatMessage } = useIntl();
3655
+ const displayedPath = isOverride && path.overridePath !== void 0 ? path.overridePath : path.value ?? "";
3656
+ const inputBorder = path.replacement === null ? "" : path.replacement ? "1px solid #ee5e52" : "1px solid #5cb176";
3657
+ return /* @__PURE__ */ jsxs(
3658
+ Field.Root,
3659
+ {
3660
+ hint: config.default ? formatMessage({
3661
+ id: getTranslation("components.CMEditViewAside.path.input.start"),
3662
+ defaultMessage: "Edit the"
3663
+ }) + ' "' + config.default + '" ' + formatMessage({
3664
+ id: getTranslation("components.CMEditViewAside.path.input.end"),
3665
+ defaultMessage: "field to generate a path"
3666
+ }) : formatMessage({
3667
+ id: getTranslation("components.CMEditViewAside.path.input.noSourceField"),
3668
+ defaultMessage: "Use the override option to set a custom path"
3669
+ }),
3670
+ children: [
3671
+ /* @__PURE__ */ jsxs(Field.Label, { children: [
3672
+ formatMessage({
3673
+ id: getTranslation("components.CMEditViewAside.path.input.label"),
3674
+ defaultMessage: "Path"
3675
+ }),
3676
+ /* @__PURE__ */ jsx(Tooltip, { description: formatMessage({
3677
+ id: getTranslation("components.CMEditViewAside.path.input.tooltip"),
3678
+ defaultMessage: "The following characters are valid: A-Z, a-z, 0-9, /, -, _, $, ., +, !, *, ', (, )"
3679
+ }) })
3680
+ ] }),
3681
+ /* @__PURE__ */ jsx(
3682
+ Field.Input,
3683
+ {
3684
+ id: "path-input",
3685
+ value: displayedPath,
3686
+ onChange: (e) => dispatchPath({ type: "SET_OVERRIDEPATH", payload: e.target.value }),
3687
+ disabled: !isOverride,
3688
+ onBlur: (e) => {
3689
+ if (e.target.value === path.prevValue) return;
3690
+ dispatchPath({ type: "DEFAULT", payload: e.target.value });
3691
+ },
3692
+ style: { outline: inputBorder }
3693
+ }
3694
+ ),
3695
+ /* @__PURE__ */ jsx(Field.Hint, {})
3696
+ ]
3672
3697
  }
3673
- return data.uniquePath;
3674
- } catch (err) {
3675
- console.error("Error in duplicateCheck:", err);
3676
- throw new Error("Failed to check URL uniqueness");
3677
- }
3698
+ );
3678
3699
  }
3679
- const getTranslation = (id) => `${PLUGIN_ID}.${id}`;
3680
- function PathInfo({ validationState, replacement, setUrlStatus }) {
3681
- const [color, setColor] = useState(null);
3682
- const [text, setText] = useState(null);
3700
+ function RouteStructure({ routes, selectedParent, setSelectedParent, canonicalPath, prohibitedRouteIds }) {
3683
3701
  const { formatMessage } = useIntl();
3684
- useEffect(() => {
3685
- if (validationState === "initial") return;
3686
- if (validationState === "checking") {
3687
- setColor("neutral800");
3688
- setText(formatMessage({
3689
- id: getTranslation("components.pathInfo.checking"),
3690
- defaultMessage: "Checking if path is available..."
3691
- }));
3692
- } else if (validationState === "done") {
3693
- setColor(replacement ? "danger500" : "success500");
3694
- setText(replacement ? `${formatMessage({
3695
- id: getTranslation("components.pathInfo.notAvailable"),
3696
- defaultMessage: "Path is not available. Replaced with"
3697
- })} "${replacement}".` : formatMessage({
3698
- id: getTranslation("components.pathInfo.available"),
3699
- defaultMessage: "Path is available."
3700
- }));
3701
- if (setUrlStatus) setUrlStatus(replacement ? "invalid" : "valid");
3702
- }
3703
- }, [validationState, replacement, formatMessage, setUrlStatus]);
3704
- return /* @__PURE__ */ jsx(Box, { paddingTop: 2, children: /* @__PURE__ */ jsx(Typography, { textColor: color, children: text }) });
3702
+ const sortedRoutes = useMemo(() => {
3703
+ return [...routes].sort((a, b) => a.title.localeCompare(b.title));
3704
+ }, [routes]);
3705
+ const handleSelectParent = (value) => {
3706
+ const parentRoute = routes.find((route) => route.documentId === value) || null;
3707
+ setSelectedParent(parentRoute);
3708
+ };
3709
+ return /* @__PURE__ */ jsxs(Box, { paddingBottom: 2, children: [
3710
+ /* @__PURE__ */ jsxs(Field.Root, { children: [
3711
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
3712
+ id: getTranslation("components.CMEditViewAside.path.input.parentSelect.label"),
3713
+ defaultMessage: "Place under"
3714
+ }) }),
3715
+ /* @__PURE__ */ jsxs(
3716
+ SingleSelect,
3717
+ {
3718
+ value: selectedParent?.documentId || "",
3719
+ onValueChange: handleSelectParent,
3720
+ children: [
3721
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "", children: formatMessage({
3722
+ id: getTranslation("components.CMEditViewAside.path.input.parentSelect.rootPath"),
3723
+ defaultMessage: "None (root path)"
3724
+ }) }),
3725
+ sortedRoutes.filter((route) => !prohibitedRouteIds?.includes(route.documentId) || route.documentId === selectedParent?.documentId).map(
3726
+ (route) => /* @__PURE__ */ jsx(
3727
+ SingleSelectOption,
3728
+ {
3729
+ value: route.documentId,
3730
+ children: route.title
3731
+ },
3732
+ route.documentId
3733
+ )
3734
+ )
3735
+ ]
3736
+ }
3737
+ )
3738
+ ] }),
3739
+ /* @__PURE__ */ jsxs(Field.Root, { marginTop: 4, children: [
3740
+ /* @__PURE__ */ jsxs(Field.Label, { children: [
3741
+ formatMessage({
3742
+ id: getTranslation("components.CMEditViewAside.canonicalPath.input.label"),
3743
+ defaultMessage: "Canonical Path"
3744
+ }),
3745
+ /* @__PURE__ */ jsx(Tooltip, { description: formatMessage({
3746
+ id: getTranslation("components.CMEditViewAside.canonicalPath.input.tooltip"),
3747
+ defaultMessage: "The path determined by your content's natural hierarchy, independent of where it appears in navigation menus."
3748
+ }) })
3749
+ ] }),
3750
+ /* @__PURE__ */ jsx(
3751
+ Field.Input,
3752
+ {
3753
+ id: "canonicalPath-input",
3754
+ value: canonicalPath,
3755
+ disabled: true
3756
+ }
3757
+ ),
3758
+ /* @__PURE__ */ jsx(Field.Hint, {})
3759
+ ] })
3760
+ ] });
3761
+ }
3762
+ function getCanonicalPath(selectedParent, sourceFieldValue) {
3763
+ const parentPath = selectedParent ? selectedParent.canonicalPath + "/" : "";
3764
+ return `${parentPath}${transformToUrl(sourceFieldValue)}`;
3705
3765
  }
3706
3766
  function reducer(state, action) {
3707
3767
  switch (action.type) {
3708
3768
  case "DEFAULT":
3709
3769
  return {
3710
3770
  ...state,
3711
- value: transformToUrl(action.payload),
3771
+ value: action.payload,
3712
3772
  prevValue: state.value,
3713
3773
  needsUrlCheck: true
3714
3774
  };
3715
3775
  case "NO_URL_CHECK":
3716
3776
  return {
3717
3777
  ...state,
3718
- value: transformToUrl(action.payload),
3778
+ value: action.payload,
3719
3779
  prevValue: state.value,
3720
3780
  needsUrlCheck: false
3721
3781
  };
@@ -3728,16 +3788,22 @@ function reducer(state, action) {
3728
3788
  };
3729
3789
  case "RESET_URL_CHECK_FLAG":
3730
3790
  return { ...state, needsUrlCheck: false };
3791
+ case "SET_REPLACEMENT":
3792
+ return { ...state, replacement: action.payload };
3731
3793
  case "SET_UIDPATH":
3732
- return { ...state, uIdPath: action.payload };
3794
+ return { ...state, uidPath: action.payload };
3795
+ case "SET_CANONICALPATH":
3796
+ return { ...state, canonicalPath: action.payload };
3797
+ case "SET_OVERRIDEPATH":
3798
+ return { ...state, overridePath: action.payload };
3733
3799
  default:
3734
3800
  throw new Error();
3735
3801
  }
3736
3802
  }
3737
- const Path = ({ config }) => {
3803
+ const Panel = ({ config }) => {
3738
3804
  const { form, model } = unstable_useContentManagerContext();
3739
3805
  const { initialValues, values, onChange } = form;
3740
- const { getRelatedRoute } = useApi();
3806
+ const { getRelatedRoute, getAllRoutes, getProhibitedRouteIds } = useApi();
3741
3807
  const { formatMessage } = useIntl();
3742
3808
  const { get } = useFetchClient();
3743
3809
  const { allowedActions: {
@@ -3757,26 +3823,39 @@ const Path = ({ config }) => {
3757
3823
  conditions: []
3758
3824
  }
3759
3825
  ]);
3760
- const [routeId, setRouteId] = useState();
3826
+ const [route, setRoute] = useState(null);
3827
+ const [routes, setRoutes] = useState([]);
3828
+ const [prohibitedRouteIds, setProhibitedRouteIds] = useState([]);
3829
+ const [selectedParent, setSelectedParent] = useState(null);
3761
3830
  const [isOverride, setIsOverride] = useState(false);
3762
3831
  const [validationState, setValidationState] = useState("initial");
3763
- const [replacement, setReplacement] = useState("");
3764
3832
  const [initialLoadComplete, setInitialLoadComplete] = useState(false);
3765
- const [urlIsValid, setUrlIsValid] = useState(null);
3766
3833
  const [path, dispatchPath] = useReducer(reducer, {
3767
3834
  needsUrlCheck: false,
3768
3835
  value: "",
3769
3836
  prevValue: "",
3770
- uIdPath: ""
3837
+ replacement: null,
3838
+ uidPath: "",
3839
+ canonicalPath: "",
3840
+ overridePath: ""
3771
3841
  });
3772
3842
  const hasUserChangedField = useRef(false);
3773
3843
  const initialPath = useRef("");
3774
- const prevValueRef = useRef(null);
3775
- const debouncedCheckUrl = useCallback(debounce(checkUrl, 250), []);
3844
+ const prevSourceValueRef = useRef(null);
3845
+ const sourceFieldValue = useMemo(() => {
3846
+ const key = config?.default;
3847
+ if (!key) return "";
3848
+ const currentValue = values[key];
3849
+ if (!currentValue) return "";
3850
+ return currentValue;
3851
+ }, [values, config]);
3852
+ const debouncedCheckPath = useCallback(debounce(checkPath, 250), []);
3853
+ const debouncedCheckCanonicalPath = useCallback(debounce(checkCanonicalPath, 250), []);
3776
3854
  useEffect(() => {
3777
- onChange("webatlas_path", path.value);
3855
+ if (isOverride) onChange("webatlas_path", path.overridePath);
3778
3856
  onChange("webatlas_override", isOverride);
3779
- }, [path.value, isOverride]);
3857
+ onChange("webatlas_parent", selectedParent?.documentId || null);
3858
+ }, [path.value, path.overridePath, isOverride, selectedParent]);
3780
3859
  const debouncedValueEffect = useMemo(() => debounce((currentValues) => {
3781
3860
  const key = config?.default;
3782
3861
  if (!key) return;
@@ -3785,38 +3864,37 @@ const Path = ({ config }) => {
3785
3864
  dispatchPath({ type: "NO_URL_CHECK", payload: "" });
3786
3865
  return;
3787
3866
  }
3788
- if (initialLoadComplete && (hasUserChangedField.current || !routeId) && prevValueRef.current !== currentValue && !isOverride) {
3789
- const path2 = config.pattern ? `${config.pattern}/${currentValue}` : `${currentValue}`;
3867
+ if (initialLoadComplete && (hasUserChangedField.current || !route) && prevSourceValueRef.current !== currentValue && !isOverride) {
3868
+ const path2 = getCanonicalPath(selectedParent, currentValue);
3790
3869
  if (currentValue === initialValues[key]) {
3791
3870
  dispatchPath({ type: "NO_URL_CHECK", payload: path2 });
3792
3871
  } else {
3793
3872
  dispatchPath({ type: "DEFAULT", payload: path2 });
3794
3873
  }
3795
- prevValueRef.current = currentValue;
3874
+ prevSourceValueRef.current = currentValue;
3796
3875
  }
3797
- }, 500), [config?.default, config?.pattern, initialValues, isOverride, initialLoadComplete, routeId]);
3876
+ }, 500), [config?.default, initialValues, isOverride, initialLoadComplete, route, selectedParent]);
3798
3877
  useEffect(() => {
3799
3878
  const key = config?.default;
3800
3879
  if (!key) return;
3801
3880
  const currentValue = values[key];
3802
3881
  const initialValue = initialValues[key];
3803
- if (currentValue && !isOverride) {
3804
- const path2 = config.pattern ? `${config.pattern}/${currentValue}` : `${currentValue}`;
3805
- onChange("webatlas_path", transformToUrl(path2));
3882
+ if (currentValue !== initialValue && currentValue && !isOverride) {
3883
+ onChange("webatlas_path", transformToUrl(currentValue));
3806
3884
  }
3807
3885
  if (!initialLoadComplete) return;
3808
3886
  if (currentValue !== initialValue) {
3809
3887
  hasUserChangedField.current = true;
3810
3888
  }
3811
3889
  debouncedValueEffect(values);
3812
- }, [values, debouncedValueEffect, initialLoadComplete]);
3890
+ }, [values, debouncedValueEffect, initialLoadComplete, selectedParent]);
3813
3891
  useEffect(() => {
3814
3892
  if (path.needsUrlCheck && path.value) {
3815
- if (path.uIdPath === path.value || initialPath.current === path.value) return;
3816
- debouncedCheckUrl(path.value);
3893
+ if (path.uidPath === path.value || initialPath.current === path.value) return;
3894
+ debouncedCheckPath(path.value, route?.documentId || null);
3817
3895
  dispatchPath({ type: "RESET_URL_CHECK_FLAG" });
3818
3896
  }
3819
- }, [path.needsUrlCheck]);
3897
+ }, [path.needsUrlCheck, path.value, path.uidPath, route]);
3820
3898
  useEffect(() => {
3821
3899
  async function getTypes() {
3822
3900
  if (!initialValues.documentId) {
@@ -3824,42 +3902,84 @@ const Path = ({ config }) => {
3824
3902
  return;
3825
3903
  }
3826
3904
  try {
3827
- const route = await getRelatedRoute(initialValues.documentId);
3828
- if (!route) return;
3829
- initialPath.current = initialValues.webatlas_path || route.uidPath;
3830
- setRouteId(route.id);
3831
- setIsOverride(route.isOverride || false);
3832
- dispatchPath({ type: "NO_TRANSFORM_AND_CHECK", payload: route.path || "" });
3833
- dispatchPath({ type: "SET_UIDPATH", payload: route.uidPath || "" });
3905
+ const route2 = await getRelatedRoute(initialValues.documentId);
3906
+ if (!route2) return;
3907
+ initialPath.current = initialValues.webatlas_path || route2.uidPath;
3908
+ setRoute(route2);
3909
+ setIsOverride(route2.isOverride || false);
3910
+ if (route2.isOverride) {
3911
+ dispatchPath({ type: "SET_OVERRIDEPATH", payload: route2.path || "" });
3912
+ } else {
3913
+ dispatchPath({ type: "NO_TRANSFORM_AND_CHECK", payload: route2.path || "" });
3914
+ }
3915
+ dispatchPath({ type: "SET_UIDPATH", payload: route2.uidPath || "" });
3834
3916
  const key = config?.default;
3835
3917
  if (key) {
3836
- prevValueRef.current = values[key];
3918
+ prevSourceValueRef.current = values[key];
3837
3919
  }
3838
3920
  } catch (err) {
3839
- setRouteId(null);
3840
- console.log(err);
3921
+ setRoute(null);
3922
+ strapi.log.error(err);
3841
3923
  }
3842
3924
  setInitialLoadComplete(true);
3843
3925
  }
3844
3926
  getTypes();
3845
3927
  }, [config]);
3928
+ useEffect(() => {
3929
+ if (initialValues.webatlas_parent && routes.length > 0 && !selectedParent) {
3930
+ const parentRoute = routes.find((route2) => route2.documentId === initialValues.webatlas_parent);
3931
+ if (parentRoute) {
3932
+ setSelectedParent(parentRoute);
3933
+ const canonicalPath = getCanonicalPath(parentRoute, sourceFieldValue);
3934
+ dispatchPath({ type: "DEFAULT", payload: canonicalPath });
3935
+ }
3936
+ }
3937
+ }, [initialValues, routes]);
3846
3938
  useEffect(() => {
3847
3939
  if (initialValues.webatlas_path) dispatchPath({ type: "NO_URL_CHECK", payload: initialValues.webatlas_path });
3848
3940
  if (initialValues.webatlas_override) setIsOverride(initialValues.webatlas_override);
3941
+ async function fetchAllRoutes() {
3942
+ const allRoutes = await getAllRoutes();
3943
+ setRoutes(allRoutes);
3944
+ }
3945
+ fetchAllRoutes();
3849
3946
  }, []);
3850
- async function checkUrl(url) {
3851
- if (!url) return;
3947
+ useEffect(() => {
3948
+ async function fetchProhibitedRouteIds() {
3949
+ const prohibitedIds = await getProhibitedRouteIds(route?.documentId);
3950
+ setProhibitedRouteIds(prohibitedIds);
3951
+ }
3952
+ fetchProhibitedRouteIds();
3953
+ }, [route]);
3954
+ useEffect(() => {
3955
+ if (!sourceFieldValue) return;
3956
+ const canonicalPath = getCanonicalPath(selectedParent, sourceFieldValue);
3957
+ !isOverride && dispatchPath({ type: "DEFAULT", payload: canonicalPath });
3958
+ dispatchPath({ type: "SET_CANONICALPATH", payload: canonicalPath });
3959
+ debouncedCheckCanonicalPath(canonicalPath, route?.documentId || null);
3960
+ dispatchPath({ type: "RESET_URL_CHECK_FLAG" });
3961
+ }, [selectedParent, sourceFieldValue, route, isOverride]);
3962
+ async function checkCanonicalPath(path2, documentId) {
3963
+ if (!path2) return;
3964
+ try {
3965
+ const result = await duplicateCheck({ fetchFunction: get, path: path2, routeDocumentId: documentId, withoutTransform: true });
3966
+ dispatchPath({ type: "SET_CANONICALPATH", payload: result });
3967
+ } catch (err) {
3968
+ strapi.log.error(err);
3969
+ }
3970
+ }
3971
+ async function checkPath(path2, route2) {
3972
+ if (!path2) return;
3852
3973
  setValidationState("checking");
3853
- setReplacement("");
3974
+ dispatchPath({ type: "SET_REPLACEMENT", payload: "" });
3854
3975
  try {
3855
- const data = await duplicateCheck(get, url);
3856
- if (!data || data === url) return;
3976
+ const data = await duplicateCheck({ fetchFunction: get, path: path2, routeDocumentId: route2, withoutTransform: true });
3977
+ if (!data || data === path2) return;
3857
3978
  dispatchPath({ type: "NO_URL_CHECK", payload: data });
3858
- setReplacement(data);
3979
+ dispatchPath({ type: "SET_REPLACEMENT", payload: data });
3859
3980
  } catch (err) {
3860
- console.log(err);
3981
+ strapi.log.error(err);
3861
3982
  } finally {
3862
- setUrlIsValid(null);
3863
3983
  setValidationState("done");
3864
3984
  }
3865
3985
  }
@@ -3870,7 +3990,7 @@ const Path = ({ config }) => {
3870
3990
  return /* @__PURE__ */ jsx(
3871
3991
  Box,
3872
3992
  {
3873
- as: "aside",
3993
+ tag: "aside",
3874
3994
  "aria-labelledby": "URL Route",
3875
3995
  width: "100%",
3876
3996
  children: /* @__PURE__ */ jsxs(
@@ -3878,101 +3998,52 @@ const Path = ({ config }) => {
3878
3998
  {
3879
3999
  direction: "column",
3880
4000
  alignItems: "stretch",
3881
- gap: 4,
4001
+ gap: 1,
3882
4002
  children: [
4003
+ !route && /* @__PURE__ */ jsxs(Fragment$1, { children: [
4004
+ /* @__PURE__ */ jsx(NewPathInfo, {}),
4005
+ /* @__PURE__ */ jsx(Divider, { marginTop: 2, marginBottom: 2 })
4006
+ ] }),
4007
+ /* @__PURE__ */ jsx(
4008
+ RouteStructure,
4009
+ {
4010
+ canonicalPath: path.canonicalPath,
4011
+ routes,
4012
+ selectedParent,
4013
+ setSelectedParent,
4014
+ prohibitedRouteIds
4015
+ }
4016
+ ),
4017
+ /* @__PURE__ */ jsx(Divider, { marginTop: 2, marginBottom: 2 }),
3883
4018
  /* @__PURE__ */ jsxs(Box, { children: [
3884
- !routeId && /* @__PURE__ */ jsxs(Fragment$1, { children: [
3885
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", marginBottom: 2, children: formatMessage({
3886
- id: getTranslation("components.CMEditViewAside.path.newPathInfo"),
3887
- defaultMessage: "A new path will be created upon saving this entry."
3888
- }) }),
3889
- /* @__PURE__ */ jsx(Box, { paddingBottom: 2, paddingTop: 2, children: /* @__PURE__ */ jsx(Divider, {}) })
3890
- ] }),
3891
- /* @__PURE__ */ jsxs(
3892
- Field.Root,
4019
+ /* @__PURE__ */ jsx(
4020
+ PathInput,
3893
4021
  {
3894
- hint: config.default ? formatMessage({
3895
- id: getTranslation("components.CMEditViewAside.path.input.start"),
3896
- defaultMessage: "Edit the"
3897
- }) + ' "' + config.default + '" ' + formatMessage({
3898
- id: getTranslation("components.CMEditViewAside.path.input.end"),
3899
- defaultMessage: "field to generate a path"
3900
- }) : formatMessage({
3901
- id: getTranslation("components.CMEditViewAside.path.input.noSourceField"),
3902
- defaultMessage: "Use the override option to set a custom path"
3903
- }),
3904
- children: [
3905
- /* @__PURE__ */ jsxs(Field.Label, { children: [
3906
- formatMessage({
3907
- id: getTranslation("components.CMEditViewAside.path.input.label"),
3908
- defaultMessage: "Path"
3909
- }),
3910
- /* @__PURE__ */ jsx(Tooltip, { description: formatMessage({
3911
- id: getTranslation("components.CMEditViewAside.path.input.tooltip"),
3912
- defaultMessage: "The following characters are valid: A-Z, a-z, 0-9, /, -, _, $, ., +, !, *, ', (, )"
3913
- }) })
3914
- ] }),
3915
- /* @__PURE__ */ jsx(
3916
- Field.Input,
3917
- {
3918
- id: "path-input",
3919
- value: path.value,
3920
- onChange: (e) => dispatchPath({ type: "NO_TRANSFORM_AND_CHECK", payload: e.target.value }),
3921
- disabled: !isOverride,
3922
- onBlur: (e) => {
3923
- if (e.target.value === path.prevValue) return;
3924
- dispatchPath({ type: "DEFAULT", payload: e.target.value });
3925
- },
3926
- style: { outline: urlIsValid !== null ? urlIsValid === "valid" ? "1px solid #5cb176" : "1px solid #ee5e52" : void 0 }
3927
- }
3928
- ),
3929
- /* @__PURE__ */ jsx(Field.Hint, {})
3930
- ]
4022
+ path,
4023
+ dispatchPath,
4024
+ isOverride,
4025
+ config
3931
4026
  }
3932
4027
  ),
3933
- /* @__PURE__ */ jsx(PathInfo, { validationState, replacement, setUrlStatus: setUrlIsValid }),
3934
- /* @__PURE__ */ jsx(
3935
- Flex,
4028
+ validationState !== "initial" && /* @__PURE__ */ jsx(
4029
+ PathInfo,
3936
4030
  {
3937
- gap: 2,
3938
- paddingTop: 2,
3939
- children: /* @__PURE__ */ jsx(
3940
- Checkbox,
3941
- {
3942
- id: "path-override-checkbox",
3943
- checked: isOverride,
3944
- onCheckedChange: () => setIsOverride((prev) => !prev),
3945
- disabled: !routeId && !canCreate || routeId && !canUpdate,
3946
- children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({
3947
- id: getTranslation("components.CMEditViewAside.path.overrideCheckbox"),
3948
- defaultMessage: "Override automatic path generation"
3949
- }) })
3950
- }
3951
- )
4031
+ validationState,
4032
+ replacement: path.replacement
3952
4033
  }
3953
4034
  )
3954
4035
  ] }),
3955
- path.uIdPath && /* @__PURE__ */ jsxs(Fragment$1, { children: [
3956
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Divider, {}) }),
3957
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(
3958
- Field.Root,
3959
- {
3960
- hint: formatMessage({
3961
- id: getTranslation("components.CMEditViewAside.path.uidPath.hint"),
3962
- defaultMessage: "Permanent UID path, cannot be changed"
3963
- }),
3964
- children: [
3965
- /* @__PURE__ */ jsx(
3966
- Field.Input,
3967
- {
3968
- value: path.uIdPath,
3969
- disabled: true
3970
- }
3971
- ),
3972
- /* @__PURE__ */ jsx(Field.Hint, {})
3973
- ]
3974
- }
3975
- ) })
4036
+ /* @__PURE__ */ jsx(
4037
+ OverrideCheckbox,
4038
+ {
4039
+ isOverride,
4040
+ setIsOverride,
4041
+ disabledCondition: !canCreate && !canUpdate
4042
+ }
4043
+ ),
4044
+ path.uidPath && /* @__PURE__ */ jsxs(Fragment$1, { children: [
4045
+ /* @__PURE__ */ jsx(Divider, { marginTop: 2, marginBottom: 2 }),
4046
+ /* @__PURE__ */ jsx(UidPathDisplay, { path: path.uidPath })
3976
4047
  ] })
3977
4048
  ]
3978
4049
  }
@@ -3987,14 +4058,7 @@ const pluginPermissions = {
3987
4058
  "settings.general": [{ action: `plugin::${PLUGIN_ID}.settings.general`, subject: null }],
3988
4059
  "settings.navigation": [{ action: `plugin::${PLUGIN_ID}.settings.navigation`, subject: null }]
3989
4060
  };
3990
- const CMEditViewAside = ({
3991
- // activeTab,
3992
- // collectionType,
3993
- // document,
3994
- documentId,
3995
- // meta,
3996
- model
3997
- }) => {
4061
+ const CMEditViewAside = ({ documentId, model }) => {
3998
4062
  const { contentTypes } = useAllContentTypes();
3999
4063
  const { config } = usePluginConfig();
4000
4064
  const { formatMessage } = useIntl();
@@ -4039,10 +4103,10 @@ const CMEditViewAside = ({
4039
4103
  if (!config) return;
4040
4104
  setIsActiveContentType(false);
4041
4105
  setContentTypeConfig(null);
4042
- config?.selectedContentTypes?.forEach((type2) => {
4043
- if (type2.uid === model) {
4106
+ config?.selectedContentTypes?.forEach((type) => {
4107
+ if (type.uid === model) {
4044
4108
  setIsActiveContentType(true);
4045
- setContentTypeConfig(type2);
4109
+ setContentTypeConfig(type);
4046
4110
  }
4047
4111
  });
4048
4112
  setIsLoading(false);
@@ -4054,7 +4118,7 @@ const CMEditViewAside = ({
4054
4118
  });
4055
4119
  if (!canAside || !isAllowedContentType || !isActiveContentType || !contentTypeConfig) return null;
4056
4120
  if (!config) {
4057
- console.error("CMEditViewAside: Plugin is not configured.");
4121
+ strapi.log.error("CMEditViewAside: Plugin is not configured.");
4058
4122
  return null;
4059
4123
  }
4060
4124
  if (isLoading) return {
@@ -4066,37 +4130,31 @@ const CMEditViewAside = ({
4066
4130
  };
4067
4131
  return {
4068
4132
  title: panelTitle,
4069
- content: /* @__PURE__ */ jsx(Path, { config: contentTypeConfig })
4133
+ content: /* @__PURE__ */ jsx(Panel, { config: contentTypeConfig })
4070
4134
  };
4071
4135
  };
4072
4136
  const index = {
4073
4137
  register(app) {
4074
4138
  app.addMenuLink({
4075
- to: `/plugins/${PLUGIN_ID}/paths`,
4139
+ to: `plugins/${PLUGIN_ID}/paths`,
4076
4140
  icon: PathIcon,
4077
4141
  intlLabel: {
4078
4142
  id: `${PLUGIN_ID}.link.paths`,
4079
4143
  defaultMessage: "Paths"
4080
4144
  },
4081
- Component: async () => {
4082
- const component = await import("./index-BRKi-K-v.mjs");
4083
- return { default: component.default };
4084
- },
4145
+ Component: () => import("./index-BKWY9Ta-.mjs"),
4085
4146
  permissions: [
4086
4147
  pluginPermissions["page.routes"][0]
4087
4148
  ]
4088
4149
  });
4089
4150
  app.addMenuLink({
4090
- to: `/plugins/${PLUGIN_ID}/navigation`,
4151
+ to: `plugins/${PLUGIN_ID}/navigation`,
4091
4152
  icon: NavigationIcon,
4092
4153
  intlLabel: {
4093
4154
  id: `${PLUGIN_ID}.link.navigation`,
4094
4155
  defaultMessage: "Navigation"
4095
4156
  },
4096
- Component: async () => {
4097
- const component = await import("./index-BWzalvVi.mjs");
4098
- return { default: component.default };
4099
- },
4157
+ Component: () => import("./index-tPrfjOIn.mjs"),
4100
4158
  permissions: [
4101
4159
  pluginPermissions["page.navigation"][0]
4102
4160
  ]
@@ -4115,13 +4173,8 @@ const index = {
4115
4173
  defaultMessage: "General"
4116
4174
  },
4117
4175
  id: `${PLUGIN_ID}-general`,
4118
- to: `/settings/${PLUGIN_ID}/general`,
4119
- Component: async () => {
4120
- return await import(
4121
- /* webpackChunkName: "webatlas-settings-general-page" */
4122
- "./index-5OG4i6qO.mjs"
4123
- );
4124
- },
4176
+ to: `${PLUGIN_ID}/general`,
4177
+ Component: () => import("./index-B07KlG03.mjs"),
4125
4178
  permissions: [
4126
4179
  pluginPermissions["settings.general"][0]
4127
4180
  ]
@@ -4135,13 +4188,8 @@ const index = {
4135
4188
  defaultMessage: "Navigation"
4136
4189
  },
4137
4190
  id: `${PLUGIN_ID}-navigation`,
4138
- to: `/settings/${PLUGIN_ID}/navigation`,
4139
- Component: async () => {
4140
- return await import(
4141
- /* webpackChunkName: "webatlas-settings-navigation-page" */
4142
- "./index-3pYLMhui.mjs"
4143
- );
4144
- },
4191
+ to: `${PLUGIN_ID}/navigation`,
4192
+ Component: () => import("./index-CUaBX_v-.mjs"),
4145
4193
  permissions: [
4146
4194
  pluginPermissions["settings.navigation"][0]
4147
4195
  ]
@@ -4161,7 +4209,7 @@ const index = {
4161
4209
  return Promise.all(
4162
4210
  locales.map(async (locale) => {
4163
4211
  try {
4164
- const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-C-uxto84.mjs"), "./translations/en.json": () => import("./en-B1CHnIH7.mjs") }), `./translations/${locale}.json`, 3);
4212
+ const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-B5pRvs13.mjs"), "./translations/en.json": () => import("./en-BE-zzIv8.mjs") }), `./translations/${locale}.json`, 3);
4165
4213
  return { data, locale };
4166
4214
  } catch {
4167
4215
  return { data: {}, locale };
@@ -4183,6 +4231,5 @@ export {
4183
4231
  PLUGIN_VERSION as h,
4184
4232
  index as i,
4185
4233
  pluginPermissions as p,
4186
- transformToUrl as t,
4187
4234
  useApi as u
4188
4235
  };