@mattisvensson/strapi-plugin-webatlas 0.9.5 → 0.10.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 (117) hide show
  1. package/README.md +24 -36
  2. package/dist/_chunks/FullLoader-Cmsf8xS6.js +0 -1
  3. package/dist/_chunks/FullLoader-CrPED_dY.mjs +0 -1
  4. package/dist/_chunks/{SettingTitle-CiMKrd_1.mjs → SettingTitle-CdR3SVn_.mjs} +1 -2
  5. package/dist/_chunks/{SettingTitle-CAoYbTar.js → SettingTitle-RU1azFIM.js} +1 -1
  6. package/dist/_chunks/{de-C-uxto84.mjs → de-B5pRvs13.mjs} +13 -8
  7. package/dist/_chunks/{de-CGXL_3o_.js → de-CqU1FU8C.js} +13 -8
  8. package/dist/_chunks/{en-B1CHnIH7.mjs → en-BE-zzIv8.mjs} +13 -8
  9. package/dist/_chunks/{en-DWEd5BXK.js → en-C7I90FwV.js} +13 -8
  10. package/dist/_chunks/{index-Bqsd7oPS.mjs → index-B07UVUOa.mjs} +387 -230
  11. package/dist/_chunks/{index-DJBnQbrp.mjs → index-BmyxSosC.mjs} +3 -3
  12. package/dist/_chunks/{index-BOZDZiAv.js → index-BucL4va6.js} +38 -82
  13. package/dist/_chunks/{index-DU58LJ2w.mjs → index-BvcX9hcc.mjs} +61 -25
  14. package/dist/_chunks/{index-ezabqLEP.js → index-BxpDM360.js} +386 -228
  15. package/dist/_chunks/{index-qrC_n9-7.mjs → index-CIM-JzLK.mjs} +38 -82
  16. package/dist/_chunks/{index-qrrfKpw1.mjs → index-CNKWb8pn.mjs} +615 -321
  17. package/dist/_chunks/{index-m2ivL3ht.js → index-D-vJE_K8.js} +3 -3
  18. package/dist/_chunks/{index-BkB1x9Sn.js → index-IRSCe8PX.js} +610 -316
  19. package/dist/_chunks/{index-CC073vGB.js → index-d09V61nm.js} +61 -24
  20. package/dist/admin/index.js +1 -2
  21. package/dist/admin/index.mjs +1 -2
  22. package/dist/admin/src/components/CMEditViewAside/NewPathInfo.d.ts +2 -0
  23. package/dist/admin/src/components/CMEditViewAside/OverrideCheckbox.d.ts +7 -0
  24. package/dist/admin/src/components/CMEditViewAside/Panel.d.ts +5 -0
  25. package/dist/admin/src/components/CMEditViewAside/PathInput.d.ts +11 -0
  26. package/dist/admin/src/components/CMEditViewAside/RouteStructure.d.ts +3 -0
  27. package/dist/admin/src/components/CMEditViewAside/UidPathDisplay.d.ts +4 -0
  28. package/dist/admin/src/components/PathInfo.d.ts +2 -3
  29. package/dist/admin/src/components/modals/externalItem/index.d.ts +1 -1
  30. package/dist/admin/src/components/modals/internalItem/ItemDetails.d.ts +13 -0
  31. package/dist/admin/src/components/modals/internalItem/internalItemCreate.d.ts +1 -1
  32. package/dist/admin/src/components/modals/internalItem/internalItemEdit.d.ts +1 -1
  33. package/dist/admin/src/components/modals/useModalSharedLogic.d.ts +1 -1
  34. package/dist/admin/src/components/modals/wrapperItem/index.d.ts +1 -1
  35. package/dist/admin/src/hooks/useApi.d.ts +4 -3
  36. package/dist/admin/src/pages/Navigation/RouteItem.d.ts +1 -15
  37. package/dist/admin/src/pages/Navigation/RouteItemBadge.d.ts +4 -0
  38. package/dist/admin/src/pages/Navigation/RouteItemIcon.d.ts +5 -0
  39. package/dist/admin/src/pages/Navigation/RouteItemMenu.d.ts +10 -0
  40. package/dist/admin/src/pages/Navigation/RouteItemStatus.d.ts +5 -0
  41. package/dist/admin/src/pages/Navigation/SortableRouteItem.d.ts +1 -1
  42. package/dist/admin/src/types/index.d.ts +3 -0
  43. package/dist/admin/src/types/modal.d.ts +56 -0
  44. package/dist/admin/src/types/navigation.d.ts +18 -0
  45. package/dist/admin/src/types/panel.d.ts +41 -0
  46. package/dist/admin/src/types/route.d.ts +1 -1
  47. package/dist/admin/src/utils/buildBreadcrumbString.d.ts +16 -0
  48. package/dist/admin/src/utils/createTempNavItemObject.d.ts +6 -8
  49. package/dist/admin/src/utils/duplicateCheck.d.ts +10 -4
  50. package/dist/admin/src/utils/findParentNavItem.d.ts +13 -0
  51. package/dist/admin/src/utils/index.d.ts +3 -2
  52. package/dist/server/index.js +636 -209
  53. package/dist/server/index.mjs +636 -209
  54. package/dist/server/src/content-types/index.d.ts +18 -0
  55. package/dist/server/src/content-types/route/index.d.ts +18 -0
  56. package/dist/server/src/content-types/route/schema.d.ts +18 -0
  57. package/dist/server/src/controllers/admin.d.ts +3 -2
  58. package/dist/server/src/controllers/index.d.ts +3 -2
  59. package/dist/server/src/index.d.ts +24 -4
  60. package/dist/server/src/migrations/001-canonical-path.d.ts +7 -0
  61. package/dist/server/src/migrations/index.d.ts +3 -0
  62. package/dist/server/src/services/admin.d.ts +3 -2
  63. package/dist/server/src/services/index.d.ts +3 -2
  64. package/dist/server/src/utils/buildCanonicalPath.d.ts +1 -0
  65. package/dist/server/src/utils/buildNavigationPath.d.ts +5 -0
  66. package/dist/server/src/utils/cascadeCanonicalPathUpdates.d.ts +1 -0
  67. package/dist/server/src/utils/getNonInternalRouteIds.d.ts +1 -0
  68. package/dist/server/src/utils/getRouteAncestors.d.ts +1 -0
  69. package/dist/server/src/utils/getRouteDescendants.d.ts +1 -0
  70. package/dist/server/src/utils/index.d.ts +10 -2
  71. package/dist/server/src/utils/navigationItemStructure.d.ts +27 -0
  72. package/dist/server/src/utils/routeHandler.d.ts +4 -2
  73. package/dist/server/src/utils/validateRouteDependencies.d.ts +4 -0
  74. package/dist/types/index.d.ts +0 -1
  75. package/dist/types/navigation.d.ts +13 -12
  76. package/dist/types/route.d.ts +7 -2
  77. package/dist/types/strapi.d.ts +1 -2
  78. package/dist/utils/index.d.ts +1 -2
  79. package/package.json +1 -1
  80. package/dist/_chunks/FullLoader-Cmsf8xS6.js.map +0 -1
  81. package/dist/_chunks/FullLoader-CrPED_dY.mjs.map +0 -1
  82. package/dist/_chunks/SettingTitle-ByAhjihc.js +0 -68
  83. package/dist/_chunks/SettingTitle-ByAhjihc.js.map +0 -1
  84. package/dist/_chunks/SettingTitle-CiMKrd_1.mjs.map +0 -1
  85. package/dist/_chunks/SettingTitle-ZM5Yf2b4.mjs +0 -68
  86. package/dist/_chunks/de-C-uxto84.mjs.map +0 -1
  87. package/dist/_chunks/de-CGXL_3o_.js.map +0 -1
  88. package/dist/_chunks/en-B1CHnIH7.mjs.map +0 -1
  89. package/dist/_chunks/en-DWEd5BXK.js.map +0 -1
  90. package/dist/_chunks/index-BqceJPRl.js +0 -235
  91. package/dist/_chunks/index-BqceJPRl.js.map +0 -1
  92. package/dist/_chunks/index-Bqsd7oPS.mjs.map +0 -1
  93. package/dist/_chunks/index-CK1wisw5.mjs +0 -129
  94. package/dist/_chunks/index-CK1wisw5.mjs.map +0 -1
  95. package/dist/_chunks/index-CQ2raqxe.js +0 -129
  96. package/dist/_chunks/index-CQ2raqxe.js.map +0 -1
  97. package/dist/_chunks/index-Ca9T36AU.mjs +0 -263
  98. package/dist/_chunks/index-Ca9T36AU.mjs.map +0 -1
  99. package/dist/_chunks/index-DDN4T6c7.mjs +0 -4188
  100. package/dist/_chunks/index-DH4Rd7aA.mjs +0 -8311
  101. package/dist/_chunks/index-DH4Rd7aA.mjs.map +0 -1
  102. package/dist/_chunks/index-DU58LJ2w.mjs.map +0 -1
  103. package/dist/_chunks/index-DnE_cDwy.js +0 -8311
  104. package/dist/_chunks/index-DnE_cDwy.js.map +0 -1
  105. package/dist/_chunks/index-DzpXVfQ_.js +0 -263
  106. package/dist/_chunks/index-DzpXVfQ_.js.map +0 -1
  107. package/dist/_chunks/index-R7qsEu2N.js +0 -4205
  108. package/dist/_chunks/index-R7qsEu2N.js.map +0 -1
  109. package/dist/_chunks/index-fbC3magu.mjs +0 -234
  110. package/dist/admin/index.js.map +0 -1
  111. package/dist/admin/index.mjs.map +0 -1
  112. package/dist/admin/src/components/CMEditViewAside/Path.d.ts +0 -5
  113. package/dist/admin/src/utils/countChildren.d.ts +0 -2
  114. package/dist/server/index.js.map +0 -1
  115. package/dist/server/index.mjs.map +0 -1
  116. package/dist/types/modal.d.ts +0 -36
  117. package/dist/utils/getPath.d.ts +0 -1
@@ -1,11 +1,11 @@
1
1
  import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
- import { useNavigate, useParams, Routes, Route } from "react-router-dom";
3
- import { Trash, Pencil, Check, Drag, More, Link, OneToMany, ExternalLink, Plus } from "@strapi/icons";
4
- import { Box, Typography, Dialog, Button, Modal, Flex, SingleSelect, SingleSelectOption, Grid, Field, Toggle, Divider, Status, SimpleMenu, IconButton, MenuItem } from "@strapi/design-system";
5
- import { useState, useEffect, createContext, useRef, useContext, useReducer, useCallback, useMemo, forwardRef } from "react";
2
+ import { useNavigate, Link, useParams, Routes, Route } from "react-router-dom";
3
+ import { Trash, Pencil, Check, WarningCircle, More, Link as Link$1, OneToMany, ExternalLink, Drag, Plus } from "@strapi/icons";
4
+ import { Box, Typography, Dialog, Button, Modal, Flex, SingleSelect, SingleSelectOption, Grid, Field, Toggle, Divider, Badge, SimpleMenu, IconButton, MenuItem } from "@strapi/design-system";
5
+ import { useState, useEffect, createContext, useRef, useContext, useMemo, useReducer, useCallback, forwardRef } from "react";
6
6
  import { createPortal } from "react-dom";
7
7
  import { useIntl } from "react-intl";
8
- import { u as useApi, g as getTranslation, P as PLUGIN_ID, d as debounce, a as duplicateCheck, t as transformToUrl, b as PathInfo, c as usePluginConfig, p as pluginPermissions } from "./index-DDN4T6c7.mjs";
8
+ import { u as useApi, g as getTranslation, P as PLUGIN_ID, d as debounce, a as duplicateCheck, T as Tooltip, b as PathInfo, c as usePluginConfig, p as pluginPermissions } from "./index-B07UVUOa.mjs";
9
9
  import { useNotification, useFetchClient, Page, Layouts } from "@strapi/strapi/admin";
10
10
  import { C as Center, F as FullLoader } from "./FullLoader-CrPED_dY.mjs";
11
11
  import { EmptyDocuments } from "@strapi/icons/symbols";
@@ -33,7 +33,7 @@ const useAllEntities = () => {
33
33
  return { entities, loading, error };
34
34
  };
35
35
  function createTempNavItemObject({
36
- parentId,
36
+ actionItemParentId,
37
37
  entityRoute,
38
38
  selectedNavigation,
39
39
  navItemState,
@@ -42,6 +42,12 @@ function createTempNavItemObject({
42
42
  path,
43
43
  type = "internal"
44
44
  }) {
45
+ const clientModifications = {
46
+ type: "create",
47
+ route: entityRoute?.documentId ?? null,
48
+ parent: actionItemParentId ?? null,
49
+ navigation: selectedNavigation?.documentId ?? null
50
+ };
45
51
  const tempNavItem = {
46
52
  id: Math.floor(Math.random() * -1e6),
47
53
  // Temporary negative ID
@@ -51,25 +57,23 @@ function createTempNavItemObject({
51
57
  depth: 0,
52
58
  status: null,
53
59
  order: 0,
54
- parent: parentId ? { documentId: parentId } : null,
60
+ parent: actionItemParentId ? { documentId: actionItemParentId } : null,
55
61
  items: [],
56
- isNew: {
57
- route: entityRoute?.documentId ?? null,
58
- parent: parentId ?? null,
59
- navigation: selectedNavigation?.documentId ?? null
60
- },
62
+ clientModifications: { ...clientModifications },
63
+ initialClientModifications: { ...clientModifications },
61
64
  route: {
62
65
  active: navItemState.active || false,
63
66
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
64
67
  documentId: "",
65
68
  path: path?.value || "",
69
+ canonicalPath: "",
66
70
  id: 0,
67
71
  type,
68
72
  isOverride: navItemState.isOverride || false,
69
- relatedContentType: selectedContentType ? JSON.stringify(selectedContentType.contentType) : "",
73
+ relatedContentType: selectedContentType ? selectedContentType.contentType.uid : "",
70
74
  relatedDocumentId: selectedEntity ? selectedEntity.documentId : "",
71
75
  relatedId: selectedEntity ? selectedEntity.id : 0,
72
- slug: path?.value || "",
76
+ slug: path?.slug || "",
73
77
  title: navItemState.title || "",
74
78
  uidPath: path?.uidPath || "",
75
79
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -78,6 +82,56 @@ function createTempNavItemObject({
78
82
  };
79
83
  return tempNavItem;
80
84
  }
85
+ function findParentNavItem({
86
+ navigationItems,
87
+ targetItem,
88
+ onlyInternalItems = false
89
+ }) {
90
+ if (!navigationItems || !Array.isArray(navigationItems)) return null;
91
+ if (!targetItem || typeof targetItem.depth !== "number" || targetItem.depth <= 0) return null;
92
+ const targetIndex = navigationItems.findIndex(
93
+ (navItem) => navItem.documentId === targetItem.documentId
94
+ );
95
+ if (targetIndex === -1) return null;
96
+ for (let i = targetIndex - 1; i >= 0; i--) {
97
+ const candidate = navigationItems[i];
98
+ if (candidate.depth === 0) {
99
+ if (onlyInternalItems && candidate.route.type !== "internal") {
100
+ return null;
101
+ }
102
+ return candidate;
103
+ }
104
+ if (candidate.clientModifications?.type === "delete" || typeof candidate.depth === "number" && candidate.depth >= targetItem.depth || onlyInternalItems && candidate.route.type !== "internal") {
105
+ continue;
106
+ }
107
+ return candidate;
108
+ }
109
+ return null;
110
+ }
111
+ function buildBreadcrumbString({
112
+ navigationItems,
113
+ targetItem,
114
+ includeTarget = true
115
+ }) {
116
+ if (!navigationItems || !Array.isArray(navigationItems)) return null;
117
+ if (!targetItem || typeof targetItem.depth !== "number") return null;
118
+ if (targetItem.depth <= 0) return targetItem.route.title;
119
+ const targetIndex = navigationItems.findIndex(
120
+ (navItem) => navItem.documentId === targetItem.documentId
121
+ );
122
+ if (targetIndex === -1) return null;
123
+ const parts = [];
124
+ for (let i = targetIndex - 1; i >= 0; i--) {
125
+ const candidate = navigationItems[i];
126
+ if (candidate.clientModifications?.type === "delete") continue;
127
+ parts.unshift(candidate.route.title);
128
+ if (typeof candidate.depth === "number" && candidate.depth === 0) break;
129
+ }
130
+ if (includeTarget) {
131
+ parts.push(targetItem.route.title);
132
+ }
133
+ return parts.join(" > ");
134
+ }
81
135
  function EmptyBox({ msg }) {
82
136
  return /* @__PURE__ */ jsxs(Fragment, { children: [
83
137
  /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem", height: "6rem" }),
@@ -100,11 +154,17 @@ function Delete({ variant, item, onDelete }) {
100
154
  await deleteNavigation(item.documentId);
101
155
  onDelete(item);
102
156
  } else if (variant === "ItemDelete") {
103
- const editedItem = { ...item, deleted: true };
157
+ const editedItem = {
158
+ ...item,
159
+ clientModifications: {
160
+ ...item.clientModifications,
161
+ type: "delete"
162
+ }
163
+ };
104
164
  onDelete(editedItem);
105
165
  }
106
166
  } catch (err) {
107
- console.log(err);
167
+ strapi.log.error(err);
108
168
  }
109
169
  setModalType(closeModalState.current);
110
170
  };
@@ -241,7 +301,7 @@ function NavCreate() {
241
301
  navigate(`/plugins/${PLUGIN_ID}/navigation/${data.documentId}`);
242
302
  setModalType("");
243
303
  } catch (err) {
244
- console.log(err);
304
+ strapi.log.error(err);
245
305
  toggleNotification({
246
306
  type: "danger",
247
307
  message: formatMessage({
@@ -296,7 +356,7 @@ function NavEdit({ item, onEdit }) {
296
356
  setModalType("NavOverview");
297
357
  onEdit({ ...item, name, visible });
298
358
  } catch (err) {
299
- console.log(err);
359
+ strapi.log.error(err);
300
360
  toggleNotification({
301
361
  type: "danger",
302
362
  message: formatMessage({
@@ -437,12 +497,10 @@ function NavOverview({ navigations, setActionItem }) {
437
497
  }
438
498
  );
439
499
  }
440
- function itemStateReducer(navItemState, action) {
500
+ function navItemStateReducer(navItemState, action) {
441
501
  switch (action.type) {
442
502
  case "SET_TITLE":
443
503
  return { ...navItemState, title: action.payload };
444
- case "SET_SLUG":
445
- return { ...navItemState, slug: action.payload };
446
504
  case "SET_ACTIVE":
447
505
  return { ...navItemState, active: action.payload };
448
506
  case "SET_OVERRIDE":
@@ -456,14 +514,14 @@ function pathReducer(state, action) {
456
514
  case "DEFAULT":
457
515
  return {
458
516
  ...state,
459
- value: transformToUrl(action.payload),
517
+ value: action.payload,
460
518
  prevValue: state.value,
461
519
  needsUrlCheck: true
462
520
  };
463
521
  case "NO_URL_CHECK":
464
522
  return {
465
523
  ...state,
466
- value: transformToUrl(action.payload),
524
+ value: action.payload,
467
525
  prevValue: state.value,
468
526
  needsUrlCheck: false
469
527
  };
@@ -476,8 +534,14 @@ function pathReducer(state, action) {
476
534
  };
477
535
  case "RESET_URL_CHECK_FLAG":
478
536
  return { ...state, needsUrlCheck: false };
537
+ case "SET_REPLACEMENT":
538
+ return { ...state, replacement: action.payload };
479
539
  case "SET_UIDPATH":
480
540
  return { ...state, uidPath: action.payload };
541
+ case "SET_SLUG":
542
+ return { ...state, slug: action.payload };
543
+ case "SET_CANONICALPATH":
544
+ return { ...state, canonicalPath: action.payload };
481
545
  case "SET_INITIALPATH":
482
546
  return { ...state, initialPath: action.payload };
483
547
  default:
@@ -485,61 +549,64 @@ function pathReducer(state, action) {
485
549
  }
486
550
  }
487
551
  function useModalSharedLogic() {
488
- const [availableEntities, setAvailableEntities] = useState([]);
489
- const [selectedEntity, setSelectedEntity] = useState();
490
552
  const [selectedContentType, setSelectedContentType] = useState();
491
- const [entityRoute, setEntityRoute] = useState();
492
- const [replacement, setReplacement] = useState("");
493
553
  const [validationState, setValidationState] = useState("initial");
494
554
  const { entities } = useAllEntities();
495
- const { updateRoute, getRelatedRoute } = useApi();
496
555
  const { get } = useFetchClient();
556
+ const availableEntities = useMemo(() => {
557
+ if (!entities) return [];
558
+ return entities;
559
+ }, [entities]);
497
560
  const initialState = useRef({
498
561
  title: "",
499
562
  slug: "",
500
563
  active: true,
501
- internal: true,
564
+ type: "internal",
502
565
  isOverride: false
503
566
  });
504
- const [navItemState, dispatchItemState] = useReducer(itemStateReducer, initialState.current);
505
- const [path, dispatchPath] = useReducer(pathReducer, { needsUrlCheck: false });
567
+ const [navItemState, dispatchNavItemState] = useReducer(navItemStateReducer, initialState.current);
568
+ const [path, dispatchPath] = useReducer(pathReducer, {
569
+ needsUrlCheck: false,
570
+ value: "",
571
+ prevValue: "",
572
+ slug: "",
573
+ replacement: null,
574
+ uidPath: "",
575
+ canonicalPath: "",
576
+ initialPath: ""
577
+ });
506
578
  const debouncedCheckUrl = useCallback(debounce(checkUrl, 500), []);
507
579
  const { modalType, setModalType } = useContext(ModalContext);
508
580
  const { selectedNavigation } = useContext(SelectedNavigationContext);
509
- async function checkUrl(url, routeDocumentId) {
581
+ async function checkUrl({
582
+ url,
583
+ routeDocumentId,
584
+ withoutTransform = false
585
+ }) {
510
586
  if (!url) return;
511
587
  setValidationState("checking");
512
- setReplacement("");
588
+ dispatchPath({ type: "SET_REPLACEMENT", payload: "" });
513
589
  try {
514
- const data = await duplicateCheck(get, url, routeDocumentId);
590
+ const data = await duplicateCheck({ fetchFunction: get, path: url, routeDocumentId, withoutTransform });
515
591
  if (!data || data === url) return;
516
592
  dispatchPath({ type: "NO_URL_CHECK", payload: data });
517
- setReplacement(data);
593
+ dispatchPath({ type: "SET_REPLACEMENT", payload: data });
518
594
  } catch (err) {
519
- console.log(err);
595
+ strapi.log.error(err);
520
596
  } finally {
521
597
  setValidationState("done");
522
598
  }
523
599
  }
524
- const modalSharedLogic2 = {
600
+ const modalSharedLogic = {
525
601
  availableEntities,
526
- setAvailableEntities,
527
- selectedEntity,
528
- setSelectedEntity,
529
602
  selectedContentType,
530
603
  setSelectedContentType,
531
- entityRoute,
532
- setEntityRoute,
533
604
  entities,
534
- updateRoute,
535
- getRelatedRoute,
536
- replacement,
537
- setReplacement,
538
605
  validationState,
539
606
  setValidationState,
540
607
  initialState,
541
608
  navItemState,
542
- dispatchItemState,
609
+ dispatchNavItemState,
543
610
  path,
544
611
  dispatchPath,
545
612
  debouncedCheckUrl,
@@ -547,7 +614,7 @@ function useModalSharedLogic() {
547
614
  setModalType,
548
615
  selectedNavigation
549
616
  };
550
- return modalSharedLogic2;
617
+ return modalSharedLogic;
551
618
  }
552
619
  function withModalSharedLogic(Component) {
553
620
  return function WrappedComponent(props) {
@@ -565,39 +632,39 @@ function ExternalItemComponent(props) {
565
632
  const {
566
633
  variant,
567
634
  navItemState,
568
- dispatchItemState,
635
+ dispatchNavItemState,
569
636
  path,
570
637
  dispatchPath,
571
638
  setModalType,
572
639
  selectedNavigation
573
640
  } = props;
574
- const parentId = isExternalCreateProps(props) ? props.parentId : void 0;
641
+ const actionItemParentId = isExternalCreateProps(props) ? props.actionItemParentId : void 0;
575
642
  const onCreate = isExternalCreateProps(props) ? props.onCreate : void 0;
576
643
  const onSave = isExternalEditProps(props) ? props.onSave : void 0;
577
644
  const item = isExternalEditProps(props) ? props.item : void 0;
578
645
  const { formatMessage } = useIntl();
579
646
  useEffect(() => {
580
647
  if (variant !== "ExternalEdit" || !item) return;
581
- dispatchItemState({ type: "SET_TITLE", payload: item.route.title });
582
- dispatchItemState({ type: "SET_ACTIVE", payload: item.route.active });
648
+ dispatchNavItemState({ type: "SET_TITLE", payload: item.route.title });
649
+ dispatchNavItemState({ type: "SET_ACTIVE", payload: item.route.active });
583
650
  dispatchPath({ type: "NO_TRANSFORM_AND_CHECK", payload: item.route.path });
584
- }, [variant, item, dispatchItemState, dispatchPath]);
651
+ }, [variant, item, dispatchNavItemState, dispatchPath]);
585
652
  const handleConfirm = async () => {
586
653
  try {
587
654
  if (!path || path.value?.trim() === "" || !navItemState.title || navItemState.title?.trim() === "" || !selectedNavigation) return;
588
655
  if (variant === "ExternalEdit" && item && onSave) {
589
656
  onSave({
590
657
  ...item,
591
- update: {
658
+ clientModifications: {
659
+ ...item.clientModifications,
660
+ type: "update",
592
661
  title: navItemState.title,
593
- path: path.value
594
- // internal: false,
595
- // active: navItemState.active,
662
+ slug: path.value
596
663
  }
597
664
  });
598
665
  } else if (onCreate) {
599
666
  const newItem = createTempNavItemObject({
600
- parentId,
667
+ actionItemParentId,
601
668
  entityRoute: null,
602
669
  selectedNavigation,
603
670
  navItemState,
@@ -610,7 +677,7 @@ function ExternalItemComponent(props) {
610
677
  }
611
678
  setModalType("");
612
679
  } catch (err) {
613
- console.log(err);
680
+ strapi.log.error(err);
614
681
  }
615
682
  };
616
683
  return /* @__PURE__ */ jsx(
@@ -640,7 +707,7 @@ function ExternalItemComponent(props) {
640
707
  }),
641
708
  name: "title",
642
709
  value: navItemState.title || "",
643
- onChange: (e) => dispatchItemState({ type: "SET_TITLE", payload: e.target.value }),
710
+ onChange: (e) => dispatchNavItemState({ type: "SET_TITLE", payload: e.target.value }),
644
711
  required: true
645
712
  }
646
713
  )
@@ -669,10 +736,79 @@ function ExternalItemComponent(props) {
669
736
  );
670
737
  }
671
738
  const ExternalItem = withModalSharedLogic(ExternalItemComponent);
672
- function ItemDetails({ navItemState, dispatchItemState, path, dispatchPath, validationState, replacement }) {
739
+ function Warning({ main, info }) {
740
+ return /* @__PURE__ */ jsx(Grid.Item, { col: 12, s: 12, alignItems: "baseline", children: /* @__PURE__ */ jsx(Badge, { variant: "warning", minWidth: "100%", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
741
+ /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, children: [
742
+ /* @__PURE__ */ jsx(WarningCircle, {}),
743
+ /* @__PURE__ */ jsx(Typography, { children: main })
744
+ ] }),
745
+ info && /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: info })
746
+ ] }) }) });
747
+ }
748
+ function ItemDetails({
749
+ navItemState,
750
+ dispatchNavItemState,
751
+ path,
752
+ dispatchPath,
753
+ validationState,
754
+ parentNavItem,
755
+ navigationItems,
756
+ navigations,
757
+ debouncedCheckUrl,
758
+ item,
759
+ route,
760
+ modalVariant
761
+ }) {
673
762
  const { formatMessage } = useIntl();
674
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Grid.Root, { gap: 4, children: [
675
- /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, alignItems: "baseline", children: /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(Field.Root, { children: [
763
+ const breadcrumbString = useMemo(() => {
764
+ if (!navigationItems) return null;
765
+ const targetItem = item || parentNavItem;
766
+ if (!targetItem || typeof targetItem.depth !== "number") return null;
767
+ return buildBreadcrumbString({ navigationItems, targetItem, includeTarget: modalVariant === "create" });
768
+ }, [parentNavItem, navigationItems, item, modalVariant]);
769
+ const navigationWhereRouteExists = useMemo(() => {
770
+ if (!navigations || !route) return false;
771
+ return navigations.find((nav) => nav.items.some((r) => r.route.documentId === route.documentId || r.route.relatedContentType === route.relatedContentType && r.route.relatedDocumentId === route.relatedDocumentId));
772
+ }, [navigations, route, navigationItems]);
773
+ useEffect(() => {
774
+ if (path.needsUrlCheck && path.value) {
775
+ if (path.uidPath === path.value || path.initialPath === path.value) return;
776
+ debouncedCheckUrl({ url: path.value, routeDocumentId: route.documentId, withoutTransform: true });
777
+ dispatchPath({ type: "RESET_URL_CHECK_FLAG" });
778
+ }
779
+ }, [path.needsUrlCheck, route.documentId]);
780
+ useEffect(() => {
781
+ if (!path.slug) return;
782
+ const parentPath = parentNavItem?.clientModifications?.path || parentNavItem?.route.path || "";
783
+ const newPath = parentPath ? `${parentPath}/${path.slug}` : path.slug;
784
+ dispatchPath({ type: "DEFAULT", payload: newPath });
785
+ }, [path.slug, parentNavItem]);
786
+ return /* @__PURE__ */ jsxs(Grid.Root, { gap: 4, children: [
787
+ path.canonicalPath !== path.value && /* @__PURE__ */ jsx(
788
+ Warning,
789
+ {
790
+ main: formatMessage({
791
+ id: getTranslation("modal.item.canonicalPathMismatch"),
792
+ defaultMessage: "Warning: Canonical Path does not match navigation path"
793
+ })
794
+ }
795
+ ),
796
+ navigationWhereRouteExists && /* @__PURE__ */ jsx(
797
+ Warning,
798
+ {
799
+ main: formatMessage({
800
+ id: getTranslation("modal.item.routeAlreadyUsed"),
801
+ defaultMessage: 'Warning: This route is already used in the navigation "{navigationName}"'
802
+ }, {
803
+ navigationName: navigationWhereRouteExists.name
804
+ }),
805
+ info: formatMessage({
806
+ id: getTranslation("modal.item.routeAlreadyUsed.info"),
807
+ defaultMessage: "Changing the path for this item will also update the path in the existing item."
808
+ })
809
+ }
810
+ ),
811
+ /* @__PURE__ */ jsx(Grid.Item, { col: 12, s: 12, alignItems: "baseline", children: /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
676
812
  /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
677
813
  id: getTranslation("modal.item.titleField.label"),
678
814
  defaultMessage: "Title"
@@ -680,17 +816,65 @@ function ItemDetails({ navItemState, dispatchItemState, path, dispatchPath, vali
680
816
  /* @__PURE__ */ jsx(
681
817
  Field.Input,
682
818
  {
683
- placeholder: formatMessage({
684
- id: getTranslation("modal.item.titleField.placeholder"),
685
- defaultMessage: "e.g. About us"
686
- }),
687
819
  name: "title",
688
820
  value: navItemState?.title || "",
689
- onChange: (e) => dispatchItemState({ type: "SET_TITLE", payload: e.target.value }),
821
+ onChange: (e) => dispatchNavItemState({ type: "SET_TITLE", payload: e.target.value }),
690
822
  required: true
691
823
  }
692
824
  )
693
825
  ] }) }) }),
826
+ /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, alignItems: "baseline", children: /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(Field.Root, { children: [
827
+ /* @__PURE__ */ jsxs(Field.Label, { children: [
828
+ formatMessage({
829
+ id: getTranslation("modal.item.canonicalPathField.label"),
830
+ defaultMessage: "Canonical Path"
831
+ }),
832
+ /* @__PURE__ */ jsx(Tooltip, { description: formatMessage({
833
+ id: getTranslation("modal.item.canonicalPathField.tooltip"),
834
+ defaultMessage: "Based on content hierarchy"
835
+ }) })
836
+ ] }),
837
+ /* @__PURE__ */ jsx(
838
+ Field.Input,
839
+ {
840
+ name: "canonicalPath",
841
+ value: route.canonicalPath || "",
842
+ disabled: true
843
+ }
844
+ ),
845
+ /* @__PURE__ */ jsx(Field.Hint, {})
846
+ ] }) }) }),
847
+ /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, alignItems: "baseline", children: /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
848
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
849
+ id: getTranslation("modal.item.slugField.label"),
850
+ defaultMessage: "Slug"
851
+ }) }),
852
+ /* @__PURE__ */ jsx(
853
+ Field.Input,
854
+ {
855
+ name: "slug",
856
+ value: path.slug,
857
+ onChange: (e) => dispatchPath({ type: "SET_SLUG", payload: e.target.value }),
858
+ onBlur: (e) => {
859
+ dispatchPath({ type: "SET_SLUG", payload: e.target.value });
860
+ }
861
+ }
862
+ )
863
+ ] }) }) }),
864
+ /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, alignItems: "baseline", children: /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(Field.Root, { children: [
865
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
866
+ id: getTranslation("modal.item.navigationPosition.label"),
867
+ defaultMessage: "Navigation Position"
868
+ }) }),
869
+ /* @__PURE__ */ jsx(
870
+ Field.Input,
871
+ {
872
+ name: "navigationPosition",
873
+ value: breadcrumbString || "Root",
874
+ disabled: true
875
+ }
876
+ )
877
+ ] }) }) }),
694
878
  /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxs(Box, { width: "100%", children: [
695
879
  /* @__PURE__ */ jsxs(Field.Root, { children: [
696
880
  /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
@@ -700,113 +884,80 @@ function ItemDetails({ navItemState, dispatchItemState, path, dispatchPath, vali
700
884
  /* @__PURE__ */ jsx(
701
885
  Field.Input,
702
886
  {
703
- required: true,
704
- placeholder: formatMessage({
705
- id: getTranslation("modal.item.pathField.placeholder"),
706
- defaultMessage: "e.g. about/"
707
- }),
708
- name: "slug",
709
- value: path?.value || "",
710
- onChange: (e) => dispatchPath({ type: "NO_TRANSFORM_AND_CHECK", payload: e.target.value }),
711
- onBlur: (e) => {
712
- if (e.target.value === path.prevValue) return;
713
- dispatchPath({ type: "DEFAULT", payload: e.target.value });
714
- }
887
+ name: "path",
888
+ value: path.value,
889
+ disabled: true
715
890
  }
716
891
  )
717
892
  ] }),
718
- /* @__PURE__ */ jsx(PathInfo, { validationState, replacement })
893
+ /* @__PURE__ */ jsx(PathInfo, { validationState, replacement: path.replacement })
719
894
  ] }) })
720
- ] }) });
895
+ ] });
721
896
  }
722
897
  function ItemCreateComponent({
723
898
  availableEntities,
724
- setAvailableEntities,
725
- selectedEntity,
726
- setSelectedEntity,
727
899
  selectedContentType,
728
900
  setSelectedContentType,
729
- entityRoute,
730
- setEntityRoute,
731
- entities,
732
- getRelatedRoute,
733
- replacement,
734
901
  validationState,
735
- initialState,
736
902
  navItemState,
737
- dispatchItemState,
903
+ dispatchNavItemState,
738
904
  path,
739
905
  dispatchPath,
740
906
  debouncedCheckUrl,
741
907
  setModalType,
742
908
  selectedNavigation,
743
- parentId,
744
- onCreate
909
+ actionItemParent,
910
+ onCreate,
911
+ navigationItems,
912
+ navigations
745
913
  }) {
746
- const [loading, setLoading] = useState(false);
914
+ const [route, setRoute] = useState(null);
915
+ const [entity, setEntity] = useState(null);
747
916
  const [loadingRoute, setLoadingRoute] = useState(true);
748
917
  const { formatMessage } = useIntl();
749
- useEffect(() => {
750
- if (!entities) return;
751
- setAvailableEntities(entities);
752
- }, [entities]);
753
- useEffect(() => {
754
- if (path.needsUrlCheck && path.value) {
755
- if (path.uidPath === path.value || path.initialPath === path.value) return;
756
- debouncedCheckUrl(path.value, entityRoute?.documentId);
757
- dispatchPath({ type: "RESET_URL_CHECK_FLAG" });
758
- }
759
- }, [path.needsUrlCheck, entityRoute?.documentId]);
918
+ const { getRelatedRoute } = useApi();
760
919
  useEffect(() => {
761
920
  async function fetchRoute() {
762
- if (!selectedContentType?.contentType || !selectedEntity?.documentId) return setLoadingRoute(false);
921
+ if (!selectedContentType?.contentType || !entity?.documentId) return setLoadingRoute(false);
763
922
  setLoadingRoute(true);
764
923
  try {
765
- const route = await getRelatedRoute(selectedEntity.documentId);
766
- if (!route) throw new Error("No route found for the selected entity");
767
- dispatchPath({ type: "NO_URL_CHECK", payload: route.path });
768
- dispatchPath({ type: "SET_UIDPATH", payload: route.uidPath });
769
- dispatchPath({ type: "SET_INITIALPATH", payload: route.path });
770
- dispatchItemState({ type: "SET_TITLE", payload: route.title });
771
- dispatchItemState({ type: "SET_ACTIVE", payload: route.active });
772
- dispatchItemState({ type: "SET_OVERRIDE", payload: route.isOverride });
773
- initialState.current = {
774
- title: route.title,
775
- slug: route.path,
776
- active: route.active,
777
- isOverride: route.isOverride
778
- };
779
- setEntityRoute(route);
924
+ const relatedRoute = await getRelatedRoute(entity.documentId);
925
+ if (!relatedRoute) throw new Error("No route found for the selected entity");
926
+ dispatchPath({ type: "NO_URL_CHECK", payload: relatedRoute.path });
927
+ dispatchPath({ type: "SET_SLUG", payload: relatedRoute.slug });
928
+ dispatchPath({ type: "SET_INITIALPATH", payload: relatedRoute.path });
929
+ dispatchPath({ type: "SET_CANONICALPATH", payload: relatedRoute.canonicalPath });
930
+ dispatchNavItemState({ type: "SET_TITLE", payload: relatedRoute.title });
931
+ dispatchNavItemState({ type: "SET_ACTIVE", payload: relatedRoute.active });
932
+ dispatchNavItemState({ type: "SET_OVERRIDE", payload: relatedRoute.isOverride });
933
+ setRoute(relatedRoute);
780
934
  } catch (err) {
781
- console.log(err);
935
+ strapi.log.error(err);
782
936
  } finally {
783
937
  setLoadingRoute(false);
784
938
  }
785
939
  }
786
940
  fetchRoute();
787
- }, [selectedEntity]);
941
+ }, [entity]);
788
942
  const addItem = async () => {
789
943
  try {
790
- setLoading(true);
791
- if (!selectedContentType?.contentType || !selectedEntity?.documentId || !path || !path.value?.trim() || !navItemState.title || !navItemState.title?.trim() || !selectedNavigation || !entityRoute) return;
944
+ if (!selectedContentType?.contentType || !entity?.documentId || !path || !path.value?.trim() || !navItemState.title || !navItemState.title?.trim() || !selectedNavigation || !route) return;
792
945
  const newItem = createTempNavItemObject({
793
- parentId,
794
- entityRoute,
946
+ actionItemParentId: actionItemParent?.documentId,
947
+ entityRoute: route,
795
948
  selectedNavigation,
796
949
  navItemState,
797
- selectedEntity,
950
+ selectedEntity: entity,
798
951
  selectedContentType,
799
952
  path
800
953
  });
801
954
  onCreate(newItem);
802
955
  setModalType("");
803
956
  } catch (err) {
804
- console.log(err);
805
- } finally {
806
- setLoading(false);
957
+ strapi.log.error(err);
807
958
  }
808
959
  };
809
- if (availableEntities && availableEntities.length === 0 || loadingRoute) {
960
+ if (availableEntities && availableEntities.length === 0) {
810
961
  return /* @__PURE__ */ jsx(
811
962
  NavModal,
812
963
  {
@@ -826,11 +977,10 @@ function ItemCreateComponent({
826
977
  titleText: formatMessage({ id: getTranslation("modal.internalItem.titleText.create"), defaultMessage: "Add new navigation item" }),
827
978
  loadingText: formatMessage({ id: getTranslation("modal.internalItem.loadingText.create"), defaultMessage: "Creating" }),
828
979
  onConfirm: addItem,
829
- loading,
830
980
  modalToOpen: "",
831
981
  currentModalType: "ItemCreate",
832
982
  currentModalMode: "create",
833
- disabled: !selectedContentType?.contentType || !selectedEntity?.documentId || !path || !path.value?.trim() || !navItemState.title || !navItemState.title?.trim(),
983
+ disabled: !selectedContentType?.contentType || !entity?.documentId || !path || !path.value?.trim() || !path.slug?.trim() || !navItemState.title || !navItemState.title?.trim(),
834
984
  children: [
835
985
  /* @__PURE__ */ jsxs(Grid.Root, { gap: 4, children: [
836
986
  /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(Field.Root, { children: [
@@ -850,7 +1000,7 @@ function ItemCreateComponent({
850
1000
  const [contentType] = availableEntities.filter((group) => group.contentType.label === value);
851
1001
  if (contentType) {
852
1002
  setSelectedContentType(contentType);
853
- setSelectedEntity(null);
1003
+ setEntity(null);
854
1004
  }
855
1005
  },
856
1006
  disabled: availableEntities && availableEntities.length === 0,
@@ -866,39 +1016,40 @@ function ItemCreateComponent({
866
1016
  /* @__PURE__ */ jsx(
867
1017
  SingleSelect,
868
1018
  {
869
- value: selectedEntity ? selectedEntity.id : "",
1019
+ value: entity ? entity.documentId : "",
870
1020
  placeholder: formatMessage({
871
1021
  id: getTranslation("modal.internalItem.entity.placeholder"),
872
1022
  defaultMessage: "Select an entity"
873
1023
  }),
874
1024
  onChange: (value) => {
875
1025
  const flatEntities = availableEntities.flatMap((group) => group.entities);
876
- const route = flatEntities.find((route2) => route2.id === Number(value));
877
- if (route) setSelectedEntity(route);
1026
+ const route2 = flatEntities.find((route3) => route3.documentId === value);
1027
+ if (route2) setEntity(route2);
878
1028
  },
879
1029
  disabled: !selectedContentType || selectedContentType?.entities && selectedContentType?.entities.length === 0,
880
1030
  children: selectedContentType && selectedContentType.entities?.map(
881
- (entity) => /* @__PURE__ */ jsxs(SingleSelectOption, { value: entity.id, children: [
882
- entity.id,
883
- " - ",
884
- entity[selectedContentType.contentType.default]
885
- ] }, entity.id)
1031
+ (entity2) => /* @__PURE__ */ jsx(SingleSelectOption, { value: entity2.documentId, children: entity2[selectedContentType.contentType.default] }, entity2.id)
886
1032
  )
887
1033
  }
888
1034
  )
889
1035
  ] }) }) })
890
1036
  ] }),
891
- selectedEntity && selectedContentType && /* @__PURE__ */ jsxs(Fragment, { children: [
1037
+ entity && selectedContentType && /* @__PURE__ */ jsxs(Fragment, { children: [
892
1038
  /* @__PURE__ */ jsx(Box, { paddingBottom: 6, paddingTop: 6, children: /* @__PURE__ */ jsx(Divider, {}) }),
893
- /* @__PURE__ */ jsx(
1039
+ loadingRoute || !route ? /* @__PURE__ */ jsx(FullLoader, { height: 50 }) : /* @__PURE__ */ jsx(
894
1040
  ItemDetails,
895
1041
  {
896
1042
  navItemState,
897
- dispatchItemState,
1043
+ dispatchNavItemState,
898
1044
  path,
899
1045
  dispatchPath,
900
1046
  validationState,
901
- replacement
1047
+ parentNavItem: actionItemParent,
1048
+ navigationItems,
1049
+ navigations,
1050
+ debouncedCheckUrl,
1051
+ route,
1052
+ modalVariant: "create"
902
1053
  }
903
1054
  )
904
1055
  ] })
@@ -6398,23 +6549,35 @@ function ItemEditComponent({
6398
6549
  selectedContentType,
6399
6550
  setSelectedContentType,
6400
6551
  entities,
6401
- replacement,
6402
6552
  validationState,
6403
6553
  initialState,
6404
6554
  navItemState,
6405
- dispatchItemState,
6555
+ dispatchNavItemState,
6406
6556
  path,
6407
6557
  dispatchPath,
6408
6558
  debouncedCheckUrl,
6409
6559
  setModalType,
6560
+ navigationItems,
6410
6561
  onEdit
6411
6562
  }) {
6412
6563
  const { formatMessage } = useIntl();
6564
+ const parentNavItem = useMemo(() => {
6565
+ return findParentNavItem({
6566
+ navigationItems,
6567
+ targetItem: item,
6568
+ onlyInternalItems: true
6569
+ });
6570
+ }, [navigationItems, item]);
6413
6571
  useEffect(() => {
6414
- dispatchPath({ type: "NO_TRANSFORM_AND_CHECK", payload: item.route.path });
6415
- dispatchItemState({ type: "SET_TITLE", payload: item.route.title });
6416
- dispatchItemState({ type: "SET_SLUG", payload: item.route.slug });
6417
- dispatchItemState({ type: "SET_ACTIVE", payload: item.route.active });
6572
+ const parentPath = parentNavItem?.clientModifications?.path || parentNavItem?.route.path || "";
6573
+ const initialPath = `${parentPath}/${item.route.slug}`;
6574
+ dispatchPath({ type: "DEFAULT", payload: initialPath });
6575
+ dispatchPath({ type: "SET_SLUG", payload: item.route.slug });
6576
+ dispatchPath({ type: "SET_INITIALPATH", payload: initialPath });
6577
+ dispatchPath({ type: "SET_CANONICALPATH", payload: item.route.canonicalPath });
6578
+ dispatchNavItemState({ type: "SET_TITLE", payload: item.route.title });
6579
+ dispatchNavItemState({ type: "SET_ACTIVE", payload: item.route.active });
6580
+ dispatchNavItemState({ type: "SET_OVERRIDE", payload: item.route.isOverride });
6418
6581
  const initialValues = {
6419
6582
  title: item.route.title,
6420
6583
  active: item.route.active,
@@ -6422,8 +6585,7 @@ function ItemEditComponent({
6422
6585
  slug: item.route.slug
6423
6586
  };
6424
6587
  initialState.current = initialValues;
6425
- dispatchPath({ type: "SET_INITIALPATH", payload: item.route.path });
6426
- }, []);
6588
+ }, [navigationItems, item, parentNavItem]);
6427
6589
  useEffect(() => {
6428
6590
  if (!entities) return;
6429
6591
  const contentType = entities.find((group) => group.contentType.uid === item.route.relatedContentType);
@@ -6432,38 +6594,27 @@ function ItemEditComponent({
6432
6594
  useEffect(() => {
6433
6595
  if (path.needsUrlCheck && path.value) {
6434
6596
  if (path.uidPath === path.value || path.initialPath === path.value) return;
6435
- debouncedCheckUrl(path.value, item.route.documentId);
6597
+ debouncedCheckUrl({ url: path.value, routeDocumentId: item.route.documentId });
6436
6598
  dispatchPath({ type: "RESET_URL_CHECK_FLAG" });
6437
6599
  }
6438
6600
  }, [path.needsUrlCheck, item.route.documentId]);
6439
- const debouncedValueEffect = useMemo(
6440
- () => debounce((path2) => {
6441
- dispatchPath({ type: "DEFAULT", payload: path2 });
6442
- }, 500),
6443
- []
6444
- );
6445
- const handlePathChange = (newPath) => {
6446
- if (newPath === path.prevValue) return;
6447
- dispatchPath({ type: "NO_TRANSFORM_AND_CHECK", payload: newPath });
6448
- if (newPath === "") return;
6449
- debouncedValueEffect(newPath);
6450
- };
6451
6601
  const updateItem = async () => {
6452
6602
  try {
6453
6603
  if (lodashExports.isEqual(navItemState, initialState.current) && path.value === path.initialPath) return;
6454
6604
  const isOverride = path.value !== item.route.path ? true : navItemState.isOverride;
6455
6605
  onEdit({
6456
6606
  ...item,
6457
- update: {
6607
+ clientModifications: {
6608
+ type: "update",
6458
6609
  title: navItemState.title,
6459
- slug: navItemState.slug,
6610
+ slug: path.slug,
6460
6611
  path: path.value,
6461
6612
  isOverride
6462
6613
  }
6463
6614
  });
6464
6615
  setModalType("");
6465
6616
  } catch (err) {
6466
- console.log(err);
6617
+ strapi.log.error(err);
6467
6618
  }
6468
6619
  };
6469
6620
  if (!selectedContentType) return null;
@@ -6508,53 +6659,25 @@ function ItemEditComponent({
6508
6659
  )
6509
6660
  ] }) }) })
6510
6661
  ] }),
6511
- /* @__PURE__ */ jsx(Box, { paddingBottom: 6, paddingTop: 6, children: /* @__PURE__ */ jsx(Divider, {}) }),
6512
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Grid.Root, { gap: 8, children: [
6513
- /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, alignItems: "baseline", children: /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(Field.Root, { children: [
6514
- /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
6515
- id: getTranslation("modal.item.titleField.label"),
6516
- defaultMessage: "Title"
6517
- }) }),
6518
- /* @__PURE__ */ jsx(
6519
- Field.Input,
6520
- {
6521
- placeholder: formatMessage({
6522
- id: getTranslation("modal.item.titleField.placeholder"),
6523
- defaultMessage: "e.g. About us"
6524
- }),
6525
- name: "title",
6526
- value: navItemState.title || "",
6527
- onChange: (e) => dispatchItemState({ type: "SET_TITLE", payload: e.target.value }),
6528
- required: true
6529
- }
6530
- )
6531
- ] }) }) }),
6532
- /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxs(Box, { width: "100%", children: [
6533
- /* @__PURE__ */ jsxs(Field.Root, { children: [
6534
- /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
6535
- id: getTranslation("modal.item.pathField.label"),
6536
- defaultMessage: "Path"
6537
- }) }),
6538
- /* @__PURE__ */ jsx(
6539
- Field.Input,
6540
- {
6541
- placeholder: formatMessage({
6542
- id: getTranslation("modal.item.pathField.placeholder"),
6543
- defaultMessage: "e.g. about/"
6544
- }),
6545
- value: path.value || "",
6546
- onChange: (e) => handlePathChange(e.target.value),
6547
- onBlur: (e) => {
6548
- if (e.target.value === path.prevValue) return;
6549
- dispatchPath({ type: "DEFAULT", payload: e.target.value });
6550
- },
6551
- required: true
6552
- }
6553
- )
6554
- ] }),
6555
- /* @__PURE__ */ jsx(PathInfo, { validationState, replacement })
6556
- ] }) })
6557
- ] }) })
6662
+ item && /* @__PURE__ */ jsxs(Fragment, { children: [
6663
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, paddingTop: 6, children: /* @__PURE__ */ jsx(Divider, {}) }),
6664
+ /* @__PURE__ */ jsx(
6665
+ ItemDetails,
6666
+ {
6667
+ navItemState,
6668
+ dispatchNavItemState,
6669
+ path,
6670
+ dispatchPath,
6671
+ validationState,
6672
+ parentNavItem,
6673
+ navigationItems,
6674
+ debouncedCheckUrl,
6675
+ item,
6676
+ route: item.route,
6677
+ modalVariant: "edit"
6678
+ }
6679
+ )
6680
+ ] })
6558
6681
  ]
6559
6682
  }
6560
6683
  );
@@ -6570,40 +6693,37 @@ function WrapperItemComponent(props) {
6570
6693
  const {
6571
6694
  variant,
6572
6695
  navItemState,
6573
- dispatchItemState,
6696
+ dispatchNavItemState,
6574
6697
  dispatchPath,
6575
6698
  setModalType,
6576
6699
  selectedNavigation
6577
6700
  } = props;
6578
- const parentId = isWrapperCreateProps(props) ? props.parentId : void 0;
6701
+ const actionItemParentId = isWrapperCreateProps(props) ? props.actionItemParentId : void 0;
6579
6702
  const onCreate = isWrapperCreateProps(props) ? props.onCreate : void 0;
6580
6703
  const onSave = isWrapperEditProps(props) ? props.onSave : void 0;
6581
6704
  const item = isWrapperEditProps(props) ? props.item : void 0;
6582
6705
  const { formatMessage } = useIntl();
6583
6706
  useEffect(() => {
6584
6707
  if (variant !== "WrapperEdit" || !item) return;
6585
- dispatchItemState({ type: "SET_TITLE", payload: item.route.title });
6586
- dispatchItemState({ type: "SET_ACTIVE", payload: item.route.active });
6708
+ dispatchNavItemState({ type: "SET_TITLE", payload: item.route.title });
6709
+ dispatchNavItemState({ type: "SET_ACTIVE", payload: item.route.active });
6587
6710
  dispatchPath({ type: "NO_TRANSFORM_AND_CHECK", payload: item.route.path });
6588
6711
  }, []);
6589
6712
  const onConfirm = async () => {
6590
6713
  try {
6591
6714
  if (!navItemState.title || !selectedNavigation) return;
6592
- const data = {
6593
- title: navItemState.title,
6594
- active: navItemState.active,
6595
- type: "wrapper"
6596
- };
6597
6715
  if (variant === "WrapperEdit" && item && onSave) {
6598
6716
  onSave({
6599
6717
  ...item,
6600
- update: {
6601
- ...data
6718
+ clientModifications: {
6719
+ ...item.clientModifications,
6720
+ type: "update",
6721
+ title: navItemState.title
6602
6722
  }
6603
6723
  });
6604
6724
  } else if (onCreate) {
6605
6725
  const newItem = createTempNavItemObject({
6606
- parentId,
6726
+ actionItemParentId,
6607
6727
  entityRoute: null,
6608
6728
  selectedNavigation,
6609
6729
  navItemState,
@@ -6615,7 +6735,7 @@ function WrapperItemComponent(props) {
6615
6735
  }
6616
6736
  setModalType("");
6617
6737
  } catch (err) {
6618
- console.log(err);
6738
+ strapi.log.error(err);
6619
6739
  }
6620
6740
  };
6621
6741
  return /* @__PURE__ */ jsx(
@@ -6644,7 +6764,7 @@ function WrapperItemComponent(props) {
6644
6764
  }),
6645
6765
  name: "title",
6646
6766
  value: navItemState.title || "",
6647
- onChange: (e) => dispatchItemState({ type: "SET_TITLE", payload: e.target.value }),
6767
+ onChange: (e) => dispatchNavItemState({ type: "SET_TITLE", payload: e.target.value }),
6648
6768
  required: true
6649
6769
  }
6650
6770
  )
@@ -6687,32 +6807,111 @@ function getMaxDepth({ previousItem, maxDepthValue }) {
6687
6807
  function getDragDepth(offset, indentationWidth2) {
6688
6808
  return Math.round(offset / indentationWidth2);
6689
6809
  }
6690
- function RouteIcon({ type, color = "neutral800" }) {
6810
+ function RouteItemMenu({
6811
+ item,
6812
+ depth,
6813
+ maxDepth,
6814
+ handleEdit,
6815
+ handleAddChildren,
6816
+ handleDelete,
6817
+ handleRestore
6818
+ }) {
6819
+ const { formatMessage } = useIntl();
6820
+ const viewEntityTo = item.route.relatedContentType && item.route.relatedDocumentId ? `/content-manager/collection-types/${item.route.relatedContentType}/${item.route.relatedDocumentId}` : null;
6821
+ return /* @__PURE__ */ jsxs(SimpleMenu, { label: "Item actions", tag: IconButton, icon: /* @__PURE__ */ jsx(More, {}), children: [
6822
+ (item.clientModifications?.type === "delete" || item.clientModifications?.type === "update") && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleRestore(), children: formatMessage({
6823
+ id: getTranslation("restore.metadata"),
6824
+ defaultMessage: "Restore Metadata"
6825
+ }) }) }),
6826
+ item.clientModifications?.type !== "delete" && /* @__PURE__ */ jsxs(Fragment, { children: [
6827
+ /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleEdit(), children: formatMessage({
6828
+ id: getTranslation("edit"),
6829
+ defaultMessage: "Edit"
6830
+ }) }),
6831
+ item.route.type === "internal" && viewEntityTo && /* @__PURE__ */ jsx(
6832
+ MenuItem,
6833
+ {
6834
+ isLink: true,
6835
+ as: Link,
6836
+ to: viewEntityTo,
6837
+ children: /* @__PURE__ */ jsx(Typography, { children: formatMessage({
6838
+ id: getTranslation("navigation.page.navItem.viewEntity"),
6839
+ defaultMessage: "View Entity"
6840
+ }) })
6841
+ }
6842
+ ),
6843
+ depth !== void 0 && depth < maxDepth && /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleAddChildren(), children: formatMessage({
6844
+ id: getTranslation("navigation.page.navItem.addChildren"),
6845
+ defaultMessage: "Add children"
6846
+ }) }),
6847
+ /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleDelete(), children: /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: formatMessage({
6848
+ id: getTranslation("delete"),
6849
+ defaultMessage: "Delete"
6850
+ }) }) })
6851
+ ] })
6852
+ ] });
6853
+ }
6854
+ function RouteItemStatus({
6855
+ item,
6856
+ isUpdated = false
6857
+ }) {
6858
+ if (!item) return null;
6859
+ const { formatMessage } = useIntl();
6860
+ if (item.clientModifications?.type === "create")
6861
+ return /* @__PURE__ */ jsx(
6862
+ Badge,
6863
+ {
6864
+ backgroundColor: "success100",
6865
+ textColor: "success600",
6866
+ borderColor: "success200",
6867
+ children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({
6868
+ id: getTranslation("new"),
6869
+ defaultMessage: "New"
6870
+ }) })
6871
+ }
6872
+ );
6873
+ if (item.clientModifications?.type === "update" || isUpdated)
6874
+ return /* @__PURE__ */ jsx(
6875
+ Badge,
6876
+ {
6877
+ backgroundColor: "warning100",
6878
+ textColor: "warning600",
6879
+ borderColor: "warning200",
6880
+ children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({
6881
+ id: getTranslation("updated"),
6882
+ defaultMessage: "Updated"
6883
+ }) })
6884
+ }
6885
+ );
6886
+ if (item.clientModifications?.type === "delete")
6887
+ return /* @__PURE__ */ jsx(
6888
+ Badge,
6889
+ {
6890
+ backgroundColor: "danger100",
6891
+ textColor: "danger600",
6892
+ borderColor: "danger200",
6893
+ children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({
6894
+ id: getTranslation("deleted"),
6895
+ defaultMessage: "Deleted"
6896
+ }) })
6897
+ }
6898
+ );
6899
+ return null;
6900
+ }
6901
+ function RouteItemIcon({ type, color = "neutral800" }) {
6691
6902
  switch (type) {
6692
6903
  case "external":
6693
6904
  return /* @__PURE__ */ jsx(ExternalLink, { color });
6694
6905
  case "wrapper":
6695
6906
  return /* @__PURE__ */ jsx(OneToMany, { color });
6696
6907
  case "internal":
6697
- return /* @__PURE__ */ jsx(Link, { color });
6908
+ return /* @__PURE__ */ jsx(Link$1, { color });
6698
6909
  default:
6699
6910
  return /* @__PURE__ */ jsx(Box, { width: "16px", height: "16px" });
6700
6911
  }
6701
6912
  }
6702
- const RouteItem = forwardRef(({
6703
- item,
6704
- setParentId,
6705
- setActionItem,
6706
- setNavigationItems,
6707
- ghost,
6708
- depth,
6709
- maxDepth,
6710
- style,
6711
- wrapperRef,
6712
- handleProps
6713
- }, ref) => {
6714
- if (!item || !item.route) return null;
6715
- const { setModalType } = useContext(ModalContext);
6913
+ function RouteItemBadge({ item }) {
6914
+ if (item.route.type !== "internal" || !item.status) return null;
6716
6915
  const { formatMessage } = useIntl();
6717
6916
  const itemStatusOptions = {
6718
6917
  published: {
@@ -6720,25 +6919,119 @@ const RouteItem = forwardRef(({
6720
6919
  id: getTranslation("published"),
6721
6920
  defaultMessage: "Published"
6722
6921
  }),
6723
- variant: "primary"
6922
+ backgroundColor: "success100",
6923
+ textColor: "success600",
6924
+ borderColor: "success200"
6724
6925
  },
6725
6926
  draft: {
6726
6927
  status: formatMessage({
6727
6928
  id: getTranslation("draft"),
6728
6929
  defaultMessage: "Draft"
6729
6930
  }),
6730
- variant: "secondary"
6931
+ backgroundColor: "secondary100",
6932
+ textColor: "secondary600",
6933
+ borderColor: "secondary200"
6731
6934
  },
6732
6935
  modified: {
6733
6936
  status: formatMessage({
6734
6937
  id: getTranslation("modified"),
6735
6938
  defaultMessage: "Modified"
6736
6939
  }),
6737
- variant: "alternative"
6940
+ backgroundColor: "alternative100",
6941
+ textColor: "alternative600",
6942
+ borderColor: "alternative200"
6943
+ }
6944
+ };
6945
+ return /* @__PURE__ */ jsx(
6946
+ Badge,
6947
+ {
6948
+ backgroundColor: itemStatusOptions[item.status].backgroundColor,
6949
+ textColor: itemStatusOptions[item.status].textColor,
6950
+ borderColor: itemStatusOptions[item.status].borderColor,
6951
+ children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: itemStatusOptions[item.status].status })
6738
6952
  }
6953
+ );
6954
+ }
6955
+ const RouteItem = forwardRef(({
6956
+ item,
6957
+ initialItem,
6958
+ setActionItemParent,
6959
+ setActionItem,
6960
+ setNavigationItems,
6961
+ ghost,
6962
+ depth,
6963
+ maxDepth,
6964
+ style,
6965
+ wrapperRef,
6966
+ handleProps,
6967
+ navigationItems
6968
+ }, ref) => {
6969
+ const { setModalType } = useContext(ModalContext);
6970
+ const parentNavItem = useMemo(() => findParentNavItem({
6971
+ navigationItems,
6972
+ targetItem: item,
6973
+ onlyInternalItems: true
6974
+ }), [navigationItems, item]);
6975
+ const hasStructureChanges = useMemo(() => {
6976
+ if (!initialItem) return false;
6977
+ return initialItem.order !== item.order || initialItem.depth !== item.depth;
6978
+ }, [initialItem, item.order, item.depth]);
6979
+ const isUpdated = item.clientModifications?.type === "update" || hasStructureChanges;
6980
+ const itemPath = useMemo(() => {
6981
+ if (!item.route) return "";
6982
+ if (item.route.type !== "internal") return item.route.path;
6983
+ const parentPath = parentNavItem ? `${parentNavItem.clientModifications?.path || parentNavItem.route.path}/` : "";
6984
+ const itemSlug = item.clientModifications?.slug || item.route.slug;
6985
+ return `${parentPath}${itemSlug}`;
6986
+ }, [item, parentNavItem, isUpdated]);
6987
+ const updateNavItem = (navItems) => {
6988
+ if (!navItems) return navItems;
6989
+ return navItems.map((navItem) => {
6990
+ if (navItem.documentId === item.documentId) {
6991
+ if (navItem.clientModifications?.path === itemPath) {
6992
+ return navItem;
6993
+ }
6994
+ return {
6995
+ ...navItem,
6996
+ clientModifications: navItem.clientModifications ? {
6997
+ ...navItem.clientModifications,
6998
+ path: itemPath
6999
+ } : {
7000
+ type: "update",
7001
+ path: itemPath,
7002
+ autoGenerated: true
7003
+ }
7004
+ };
7005
+ }
7006
+ return navItem;
7007
+ });
6739
7008
  };
7009
+ const removeNavItemModifications = (navItems) => {
7010
+ if (!navItems) return navItems;
7011
+ return navItems.map((navItem) => {
7012
+ if (navItem.documentId === item.documentId) {
7013
+ const { clientModifications, ...rest } = navItem;
7014
+ return rest;
7015
+ }
7016
+ return navItem;
7017
+ });
7018
+ };
7019
+ useEffect(() => {
7020
+ if (item.route?.type !== "internal") return;
7021
+ const shouldSyncPath = item.clientModifications?.path !== itemPath && (item.clientModifications?.type === "update" || itemPath !== item.route.path);
7022
+ if (shouldSyncPath) {
7023
+ setNavigationItems(updateNavItem);
7024
+ }
7025
+ }, [itemPath, item.documentId, item.route?.type, item.route?.path, item.clientModifications?.type, item.clientModifications?.path, setNavigationItems]);
7026
+ useEffect(() => {
7027
+ if (item.route?.type !== "internal") return;
7028
+ const canBeRemoved = item.clientModifications?.autoGenerated && item.route.path === itemPath && !hasStructureChanges;
7029
+ if (canBeRemoved) {
7030
+ setNavigationItems(removeNavItemModifications);
7031
+ }
7032
+ }, [itemPath, item.documentId, item.route?.type, item.route?.path, item.clientModifications?.autoGenerated, hasStructureChanges, setNavigationItems]);
6740
7033
  const handleAddChildren = () => {
6741
- setParentId(item.documentId);
7034
+ setActionItemParent(item);
6742
7035
  setModalType("ItemCreate");
6743
7036
  };
6744
7037
  const handleEdit = () => {
@@ -6756,8 +7049,8 @@ const RouteItem = forwardRef(({
6756
7049
  setNavigationItems(
6757
7050
  (navItems) => navItems?.map((navItem) => {
6758
7051
  if (navItem.documentId === item.documentId) {
6759
- delete navItem.update;
6760
- delete navItem.deleted;
7052
+ const { clientModifications: _, ...rest } = navItem;
7053
+ return navItem.initialClientModifications ? { ...rest, clientModifications: navItem.initialClientModifications } : rest;
6761
7054
  }
6762
7055
  return navItem;
6763
7056
  })
@@ -6765,9 +7058,10 @@ const RouteItem = forwardRef(({
6765
7058
  };
6766
7059
  const elStyle = {
6767
7060
  marginLeft: depth !== void 0 ? depth * 48 : 0,
6768
- opacity: ghost || item.deleted ? 0.5 : 1,
7061
+ opacity: ghost || item.clientModifications?.type === "delete" ? 0.5 : 1,
6769
7062
  ...style
6770
7063
  };
7064
+ if (!item || !item.route) return null;
6771
7065
  return /* @__PURE__ */ jsx(
6772
7066
  Box,
6773
7067
  {
@@ -6776,8 +7070,8 @@ const RouteItem = forwardRef(({
6776
7070
  children: /* @__PURE__ */ jsx(
6777
7071
  Box,
6778
7072
  {
6779
- background: item.route?.active ? "neutral0" : "neutral100",
6780
- borderColor: "neutral150",
7073
+ background: "neutral0",
7074
+ borderColor: item.clientModifications?.type === "delete" ? "danger500" : "neutral150",
6781
7075
  hasRadius: true,
6782
7076
  paddingBottom: 4,
6783
7077
  paddingLeft: 4,
@@ -6796,49 +7090,30 @@ const RouteItem = forwardRef(({
6796
7090
  background: "neutral150"
6797
7091
  }
6798
7092
  ),
6799
- /* @__PURE__ */ jsx(RouteIcon, { type: item.route.type }),
7093
+ /* @__PURE__ */ jsx(RouteItemIcon, { type: item.route.type }),
6800
7094
  /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
6801
- /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: item.update?.title ? item.update.title : item.route.title }),
6802
- /* @__PURE__ */ jsxs(Typography, { textColor: "neutral400", children: [
6803
- item.route.type === "internal" && "/",
6804
- item.update?.path ? item.update.path : item.route.path
7095
+ /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: item.clientModifications?.title ? item.clientModifications.title : item.route.title }),
7096
+ itemPath && /* @__PURE__ */ jsxs(Typography, { textColor: "neutral400", children: [
7097
+ "/",
7098
+ itemPath
6805
7099
  ] })
6806
7100
  ] }),
6807
- item.isNew && !item.deleted && /* @__PURE__ */ jsx(Status, { variant: "alternative", size: "S", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({
6808
- id: getTranslation("new"),
6809
- defaultMessage: "New"
6810
- }) }) }),
6811
- item.update && !item.deleted && /* @__PURE__ */ jsx(Status, { variant: "alternative", size: "S", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({
6812
- id: getTranslation("updated"),
6813
- defaultMessage: "Updated"
6814
- }) }) }),
6815
- item.deleted && /* @__PURE__ */ jsx(Status, { size: "S", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "danger500", children: formatMessage({
6816
- id: getTranslation("deleted"),
6817
- defaultMessage: "Deleted"
6818
- }) }) })
7101
+ /* @__PURE__ */ jsx(RouteItemStatus, { item, isUpdated: hasStructureChanges })
6819
7102
  ] }),
6820
7103
  /* @__PURE__ */ jsxs(Flex, { direction: "row", gap: 4, children: [
6821
- item.route.type === "internal" && item.status && /* @__PURE__ */ jsx(Status, { variant: itemStatusOptions[item.status].variant, size: "S", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: itemStatusOptions[item.status].status }) }),
6822
- /* @__PURE__ */ jsxs(SimpleMenu, { label: "Item actions", tag: IconButton, icon: /* @__PURE__ */ jsx(More, {}), children: [
6823
- !item.deleted && /* @__PURE__ */ jsxs(Fragment, { children: [
6824
- /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleEdit(), children: formatMessage({
6825
- id: getTranslation("edit"),
6826
- defaultMessage: "Edit"
6827
- }) }),
6828
- depth !== void 0 && depth < maxDepth && /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleAddChildren(), children: formatMessage({
6829
- id: getTranslation("navigation.page.navItem.addChildren"),
6830
- defaultMessage: "Add children"
6831
- }) }),
6832
- /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleDelete(), children: /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: formatMessage({
6833
- id: getTranslation("delete"),
6834
- defaultMessage: "Delete"
6835
- }) }) })
6836
- ] }),
6837
- (item.deleted || item.update) && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleRestore(), children: formatMessage({
6838
- id: getTranslation("restore"),
6839
- defaultMessage: "Restore"
6840
- }) }) })
6841
- ] })
7104
+ /* @__PURE__ */ jsx(RouteItemBadge, { item }),
7105
+ /* @__PURE__ */ jsx(
7106
+ RouteItemMenu,
7107
+ {
7108
+ item,
7109
+ depth,
7110
+ maxDepth,
7111
+ handleEdit,
7112
+ handleAddChildren,
7113
+ handleDelete,
7114
+ handleRestore
7115
+ }
7116
+ )
6842
7117
  ] })
6843
7118
  ] })
6844
7119
  }
@@ -7907,7 +8182,7 @@ const Navigation = () => {
7907
8182
  const [navigationItems, setNavigationItems] = useState();
7908
8183
  const initialNavigationItemsRef = useRef(null);
7909
8184
  const [actionItem, setActionItem] = useState();
7910
- const [parentId, setParentId] = useState();
8185
+ const [actionItemParent, setActionItemParent] = useState(null);
7911
8186
  const { getNavigation, updateNavigationItemStructure } = useApi();
7912
8187
  const [isSavingNavigation, setIsSavingNavigation] = useState(false);
7913
8188
  const [loading, setLoading] = useState(true);
@@ -7937,7 +8212,7 @@ const Navigation = () => {
7937
8212
  const { data: data2 } = await get(`/content-manager/collection-types/${ct}/${id}`);
7938
8213
  return { ...item, status: data2.data.status };
7939
8214
  } catch (err) {
7940
- console.error(err);
8215
+ strapi.log.error(err);
7941
8216
  return item;
7942
8217
  }
7943
8218
  })
@@ -7961,7 +8236,7 @@ const Navigation = () => {
7961
8236
  cachedNavigations.current = updatedNavigations;
7962
8237
  switchNavigation(selectedNav, updatedNavigations);
7963
8238
  } catch (error) {
7964
- console.error("Error fetching navigations: ", error);
8239
+ strapi.log.error("Error fetching navigations: ", error);
7965
8240
  toggleNotification({
7966
8241
  type: "danger",
7967
8242
  message: formatMessage({
@@ -8003,17 +8278,27 @@ const Navigation = () => {
8003
8278
  useEffect(() => {
8004
8279
  if (modalType === "NavOverview" || modalType === "") {
8005
8280
  setActionItem(void 0);
8006
- setParentId(void 0);
8281
+ setActionItemParent(null);
8007
8282
  }
8008
8283
  }, [modalType]);
8284
+ useEffect(() => {
8285
+ if (!selectedNavigation || !navigationItems) return;
8286
+ setNavigations(navigations.map((nav) => {
8287
+ if (nav.documentId !== selectedNavigation.documentId) return nav;
8288
+ return {
8289
+ ...nav,
8290
+ items: navigationItems
8291
+ };
8292
+ }));
8293
+ }, [setNavigations, navigationItems, selectedNavigation]);
8009
8294
  useEffect(() => {
8010
8295
  if (!activeId || !navigationItems) return;
8011
8296
  const item = navigationItems.find(({ id }) => id === activeId);
8012
8297
  setActiveItem(item);
8013
8298
  }, [navigationItems, activeId]);
8014
8299
  function handleSoftAddedItem(newItem) {
8015
- if (newItem.isNew?.parent) {
8016
- const parentIndex = navigationItems?.findIndex((item) => item.documentId === newItem.isNew?.parent);
8300
+ if (newItem.clientModifications?.parent) {
8301
+ const parentIndex = navigationItems?.findIndex((item) => item.documentId === newItem.clientModifications?.parent);
8017
8302
  if (parentIndex !== void 0 && parentIndex >= 0) {
8018
8303
  const parentDepth = navigationItems ? navigationItems[parentIndex].depth || 0 : 0;
8019
8304
  newItem.depth = parentDepth + 1;
@@ -8041,7 +8326,7 @@ const Navigation = () => {
8041
8326
  })
8042
8327
  });
8043
8328
  } catch (e) {
8044
- console.error(e);
8329
+ strapi.log.error(e);
8045
8330
  toggleNotification({
8046
8331
  type: "danger",
8047
8332
  message: formatMessage({
@@ -8143,28 +8428,34 @@ const Navigation = () => {
8143
8428
  onDragCancel: () => handleDragCancel(),
8144
8429
  measuring,
8145
8430
  children: /* @__PURE__ */ jsxs(SortableContext, { items: navigationItems, strategy: verticalListSortingStrategy, children: [
8146
- navigationItems.map((item, index) => config?.navigation.maxDepth && /* @__PURE__ */ jsx(
8147
- SortableRouteItem,
8148
- {
8149
- item,
8150
- setParentId,
8151
- setActionItem,
8152
- setNavigationItems,
8153
- indentationWidth,
8154
- depth: item.id === activeId && projected ? projected.depth : item.depth,
8155
- maxDepth: config.navigation.maxDepth
8156
- },
8157
- item.documentId || index
8158
- )),
8431
+ navigationItems.map((item, index) => {
8432
+ const initialItem = initialNavigationItemsRef.current?.find((i) => i.documentId === item.documentId);
8433
+ return config?.navigation.maxDepth && /* @__PURE__ */ jsx(
8434
+ SortableRouteItem,
8435
+ {
8436
+ item,
8437
+ initialItem,
8438
+ setActionItemParent,
8439
+ setActionItem,
8440
+ setNavigationItems,
8441
+ indentationWidth,
8442
+ depth: item.id === activeId && projected ? projected.depth : item.depth,
8443
+ maxDepth: config.navigation.maxDepth,
8444
+ navigationItems
8445
+ },
8446
+ item.documentId || index
8447
+ );
8448
+ }),
8159
8449
  createPortal(
8160
8450
  /* @__PURE__ */ jsx(DragOverlay, { children: activeId && activeItem ? config?.navigation.maxDepth && /* @__PURE__ */ jsx(
8161
8451
  SortableRouteItem,
8162
8452
  {
8163
8453
  item: activeItem,
8164
- setParentId,
8454
+ setActionItemParent,
8165
8455
  setActionItem,
8166
8456
  setNavigationItems,
8167
- maxDepth: config.navigation.maxDepth
8457
+ maxDepth: config.navigation.maxDepth,
8458
+ navigationItems
8168
8459
  }
8169
8460
  ) : null }),
8170
8461
  document.body
@@ -8224,7 +8515,9 @@ const Navigation = () => {
8224
8515
  modalType === "ItemCreate" && /* @__PURE__ */ jsx(
8225
8516
  ItemCreate,
8226
8517
  {
8227
- parentId,
8518
+ actionItemParent,
8519
+ navigationItems: navigationItems || [],
8520
+ navigations,
8228
8521
  onCreate: (newItem) => {
8229
8522
  handleSoftAddedItem(newItem);
8230
8523
  }
@@ -8246,6 +8539,7 @@ const Navigation = () => {
8246
8539
  ItemEdit,
8247
8540
  {
8248
8541
  item: actionItem,
8542
+ navigationItems: navigationItems || [],
8249
8543
  onEdit: (editedItem) => {
8250
8544
  setNavigationItems(
8251
8545
  (items) => items?.map((item) => item.id === editedItem.id ? editedItem : item)
@@ -8257,7 +8551,7 @@ const Navigation = () => {
8257
8551
  ExternalItem,
8258
8552
  {
8259
8553
  variant: modalType,
8260
- parentId,
8554
+ actionItemParentId: actionItemParent?.documentId,
8261
8555
  onCreate: (newItem) => {
8262
8556
  handleSoftAddedItem(newItem);
8263
8557
  }
@@ -8279,7 +8573,7 @@ const Navigation = () => {
8279
8573
  WrapperItem,
8280
8574
  {
8281
8575
  variant: modalType,
8282
- parentId,
8576
+ actionItemParentId: actionItemParent?.documentId,
8283
8577
  onCreate: (newItem) => {
8284
8578
  handleSoftAddedItem(newItem);
8285
8579
  }