@strapi/content-manager 5.51.0 → 5.51.2

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 (116) hide show
  1. package/dist/admin/components/ConfigurationForm/Form.js +14 -16
  2. package/dist/admin/components/ConfigurationForm/Form.js.map +1 -1
  3. package/dist/admin/components/ConfigurationForm/Form.mjs +14 -16
  4. package/dist/admin/components/ConfigurationForm/Form.mjs.map +1 -1
  5. package/dist/admin/history/components/VersionHeader.js +1 -1
  6. package/dist/admin/history/components/VersionHeader.js.map +1 -1
  7. package/dist/admin/history/components/VersionHeader.mjs +1 -1
  8. package/dist/admin/history/components/VersionHeader.mjs.map +1 -1
  9. package/dist/admin/history/components/VersionsList.js +1 -1
  10. package/dist/admin/history/components/VersionsList.js.map +1 -1
  11. package/dist/admin/history/components/VersionsList.mjs +1 -1
  12. package/dist/admin/history/components/VersionsList.mjs.map +1 -1
  13. package/dist/admin/hooks/useDocument.js.map +1 -1
  14. package/dist/admin/hooks/useDocument.mjs.map +1 -1
  15. package/dist/admin/layout.js +77 -7
  16. package/dist/admin/layout.js.map +1 -1
  17. package/dist/admin/layout.mjs +58 -8
  18. package/dist/admin/layout.mjs.map +1 -1
  19. package/dist/admin/pages/EditView/components/DocumentActions.js +109 -81
  20. package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
  21. package/dist/admin/pages/EditView/components/DocumentActions.mjs +108 -76
  22. package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
  23. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Link.js +2 -2
  24. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Link.js.map +1 -1
  25. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Link.mjs +2 -2
  26. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Link.mjs.map +1 -1
  27. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js +1 -1
  28. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js.map +1 -1
  29. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs +1 -1
  30. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs.map +1 -1
  31. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.js +102 -7
  32. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.js.map +1 -1
  33. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.mjs +84 -8
  34. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.mjs.map +1 -1
  35. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js +2 -1
  36. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js.map +1 -1
  37. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs +2 -1
  38. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs.map +1 -1
  39. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +14 -5
  40. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
  41. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +14 -5
  42. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs.map +1 -1
  43. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +17 -16
  44. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
  45. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +17 -13
  46. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
  47. package/dist/admin/pages/EditView/components/FormInputs/UID.js +2 -2
  48. package/dist/admin/pages/EditView/components/FormInputs/UID.js.map +1 -1
  49. package/dist/admin/pages/EditView/components/FormInputs/UID.mjs +2 -2
  50. package/dist/admin/pages/EditView/components/FormInputs/UID.mjs.map +1 -1
  51. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.js +2 -1
  52. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.js.map +1 -1
  53. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.mjs +2 -1
  54. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.mjs.map +1 -1
  55. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.js +7 -0
  56. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.js.map +1 -1
  57. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.mjs +7 -0
  58. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.mjs.map +1 -1
  59. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +3 -1
  60. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +2 -0
  61. package/dist/admin/src/pages/EditView/components/FormInputs/Relations/RelationModal.d.ts +4 -0
  62. package/dist/admin/src/utils/previewImage.d.ts +3 -0
  63. package/dist/admin/translations/en.json.js +1 -0
  64. package/dist/admin/translations/en.json.js.map +1 -1
  65. package/dist/admin/translations/en.json.mjs +1 -0
  66. package/dist/admin/translations/en.json.mjs.map +1 -1
  67. package/dist/admin/utils/objects.js +3 -1
  68. package/dist/admin/utils/objects.js.map +1 -1
  69. package/dist/admin/utils/objects.mjs +3 -1
  70. package/dist/admin/utils/objects.mjs.map +1 -1
  71. package/dist/admin/utils/previewImage.js +14 -0
  72. package/dist/admin/utils/previewImage.js.map +1 -0
  73. package/dist/admin/utils/previewImage.mjs +12 -0
  74. package/dist/admin/utils/previewImage.mjs.map +1 -0
  75. package/dist/admin/utils/validation.js +2 -2
  76. package/dist/admin/utils/validation.js.map +1 -1
  77. package/dist/admin/utils/validation.mjs +2 -2
  78. package/dist/admin/utils/validation.mjs.map +1 -1
  79. package/dist/server/controllers/utils/clone.js +1 -5
  80. package/dist/server/controllers/utils/clone.js.map +1 -1
  81. package/dist/server/controllers/utils/clone.mjs +2 -2
  82. package/dist/server/controllers/utils/clone.mjs.map +1 -1
  83. package/dist/server/controllers/validation/index.js +1 -1
  84. package/dist/server/controllers/validation/index.js.map +1 -1
  85. package/dist/server/controllers/validation/index.mjs +1 -1
  86. package/dist/server/controllers/validation/index.mjs.map +1 -1
  87. package/dist/server/homepage/services/homepage.js +24 -7
  88. package/dist/server/homepage/services/homepage.js.map +1 -1
  89. package/dist/server/homepage/services/homepage.mjs +24 -7
  90. package/dist/server/homepage/services/homepage.mjs.map +1 -1
  91. package/dist/server/services/document-manager.js +1 -1
  92. package/dist/server/services/document-manager.js.map +1 -1
  93. package/dist/server/services/document-manager.mjs +1 -1
  94. package/dist/server/services/document-manager.mjs.map +1 -1
  95. package/dist/server/services/document-metadata.js +24 -2
  96. package/dist/server/services/document-metadata.js.map +1 -1
  97. package/dist/server/services/document-metadata.mjs +24 -2
  98. package/dist/server/services/document-metadata.mjs.map +1 -1
  99. package/dist/server/services/utils/draft.js +19 -3
  100. package/dist/server/services/utils/draft.js.map +1 -1
  101. package/dist/server/services/utils/draft.mjs +1 -1
  102. package/dist/server/services/utils/draft.mjs.map +1 -1
  103. package/dist/server/services/utils/populate.js +22 -6
  104. package/dist/server/services/utils/populate.js.map +1 -1
  105. package/dist/server/services/utils/populate.mjs +1 -1
  106. package/dist/server/services/utils/populate.mjs.map +1 -1
  107. package/dist/server/src/homepage/services/homepage.d.ts.map +1 -1
  108. package/dist/server/src/index.d.ts.map +1 -1
  109. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  110. package/dist/server/src/services/index.d.ts.map +1 -1
  111. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  112. package/dist/shared/contracts/components.d.ts +1 -1
  113. package/dist/shared/contracts/components.d.ts.map +1 -1
  114. package/dist/shared/contracts/homepage.d.ts +2 -2
  115. package/dist/shared/contracts/homepage.d.ts.map +1 -1
  116. package/package.json +8 -8
@@ -1,6 +1,7 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import 'react';
3
- import { useIsMobile, Page, SubNav, Layouts, LazyOutlet } from '@strapi/admin/strapi-admin';
2
+ import * as React from 'react';
3
+ import { useIsMobile, useQueryParams, useAuth, Page, SubNav, Layouts, LazyOutlet, useNotification } from '@strapi/admin/strapi-admin';
4
+ import { stringify } from 'qs';
4
5
  import { useIntl } from 'react-intl';
5
6
  import { useMatch, useLocation, Navigate } from 'react-router-dom';
6
7
  import { DragLayer } from './components/DragLayer.mjs';
@@ -24,6 +25,8 @@ import { getTranslation } from './utils/translations.mjs';
24
25
  ].sort((a, b)=>a.title.localeCompare(b.title));
25
26
  const { pathname } = useLocation();
26
27
  const { formatMessage } = useIntl();
28
+ const [{ query }] = useQueryParams();
29
+ const permissions = useAuth('Layout', (state)=>state.permissions);
27
30
  if (isLoading) {
28
31
  return /*#__PURE__*/ jsxs(Fragment, {
29
32
  children: [
@@ -41,18 +44,45 @@ import { getTranslation } from './utils/translations.mjs';
41
44
  const supportedModelsToDisplay = models.filter(({ isDisplayed })=>isDisplayed);
42
45
  // Redirect the user to the 403 page
43
46
  if (authorisedModels.length === 0 && supportedModelsToDisplay.length > 0 && pathname !== '/content-manager/403') {
44
- return /*#__PURE__*/ jsx(Navigate, {
45
- to: "/403"
46
- });
47
+ const requestedLocale = query.plugins?.i18n?.locale;
48
+ const localeScopedPermissions = permissions.filter((permission)=>permission.action === 'plugin::content-manager.explorer.read' && Array.isArray(permission.properties?.locales));
49
+ const contentTypePermissions = localeScopedPermissions.filter((permission)=>permission.subject === contentTypeMatch?.params.uid);
50
+ const accessibleLocales = Array.from(new Set((contentTypePermissions.length > 0 ? contentTypePermissions : localeScopedPermissions).flatMap((permission)=>permission.properties?.locales)));
51
+ if (typeof requestedLocale === 'string' && accessibleLocales.length > 0) {
52
+ if (!accessibleLocales.includes(requestedLocale)) {
53
+ const search = stringify({
54
+ ...query,
55
+ plugins: {
56
+ ...query.plugins,
57
+ i18n: {
58
+ ...query.plugins?.i18n,
59
+ locale: accessibleLocales[0]
60
+ }
61
+ }
62
+ });
63
+ return /*#__PURE__*/ jsx(NavigateWithLocaleWarning, {
64
+ to: {
65
+ pathname,
66
+ search
67
+ }
68
+ });
69
+ }
70
+ } else {
71
+ return /*#__PURE__*/ jsx(Navigate, {
72
+ to: "/content-manager/403",
73
+ replace: true
74
+ });
75
+ }
47
76
  }
48
77
  // Redirect the user to the create content type page
49
- if (supportedModelsToDisplay.length === 0 && pathname !== '/no-content-types') {
78
+ if (supportedModelsToDisplay.length === 0 && pathname !== '/content-manager/no-content-types') {
50
79
  return /*#__PURE__*/ jsx(Navigate, {
51
- to: "/no-content-types"
80
+ to: "/content-manager/no-content-types",
81
+ replace: true
52
82
  });
53
83
  }
54
84
  // On /content-manager base route
55
- if (!contentTypeMatch && authorisedModels.length > 0) {
85
+ if (!contentTypeMatch && authorisedModels.length > 0 && pathname !== '/content-manager/403' && pathname !== '/content-manager/no-content-types') {
56
86
  // On desktop: redirect to first collection type
57
87
  if (!isMobile) {
58
88
  return /*#__PURE__*/ jsx(Navigate, {
@@ -102,6 +132,26 @@ import { getTranslation } from './utils/translations.mjs';
102
132
  ]
103
133
  });
104
134
  };
135
+ const NavigateWithLocaleWarning = ({ to })=>{
136
+ const { toggleNotification } = useNotification();
137
+ const { formatMessage } = useIntl();
138
+ React.useEffect(()=>{
139
+ toggleNotification({
140
+ type: 'warning',
141
+ message: formatMessage({
142
+ id: getTranslation('permissions.not-allowed.locale'),
143
+ defaultMessage: "You don't have the permissions to access this content for the requested locale"
144
+ })
145
+ });
146
+ }, [
147
+ toggleNotification,
148
+ formatMessage
149
+ ]);
150
+ return /*#__PURE__*/ jsx(Navigate, {
151
+ to: to,
152
+ replace: true
153
+ });
154
+ };
105
155
  /* -------------------------------------------------------------------------------------------------
106
156
  * renderDraglayerItem
107
157
  * -----------------------------------------------------------------------------------------------*/ function renderDraglayerItem({ type, item }) {
@@ -1 +1 @@
1
- {"version":3,"file":"layout.mjs","sources":["../../admin/src/layout.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport * as React from 'react';\n\nimport { Page, Layouts, SubNav, useIsMobile, LazyOutlet } from '@strapi/admin/strapi-admin';\nimport { useIntl } from 'react-intl';\nimport { Navigate, useLocation, useMatch } from 'react-router-dom';\n\nimport { DragLayer, DragLayerProps } from './components/DragLayer';\nimport { CardDragPreview } from './components/DragPreviews/CardDragPreview';\nimport { ComponentDragPreview } from './components/DragPreviews/ComponentDragPreview';\nimport { RelationDragPreview } from './components/DragPreviews/RelationDragPreview';\nimport { LeftMenu } from './components/LeftMenu';\nimport { ItemTypes } from './constants/dragAndDrop';\nimport { useContentManagerInitData } from './hooks/useContentManagerInitData';\nimport { getTranslation } from './utils/translations';\n\nimport type { CardDragPreviewProps } from './components/DragPreviews/CardDragPreview';\nimport type { ComponentDragPreviewProps } from './components/DragPreviews/ComponentDragPreview';\nimport type { RelationDragPreviewProps } from './components/DragPreviews/RelationDragPreview';\n\n/* -------------------------------------------------------------------------------------------------\n * Layout\n * -----------------------------------------------------------------------------------------------*/\n\nconst Layout = () => {\n const contentTypeMatch = useMatch('/content-manager/:kind/:uid/*');\n const isMobile = useIsMobile();\n\n const { isLoading, collectionTypeLinks, models, singleTypeLinks } = useContentManagerInitData();\n const authorisedModels = [...collectionTypeLinks, ...singleTypeLinks].sort((a, b) =>\n a.title.localeCompare(b.title)\n );\n\n const { pathname } = useLocation();\n const { formatMessage } = useIntl();\n\n if (isLoading) {\n return (\n <>\n <Page.Title>\n {formatMessage({\n id: getTranslation('plugin.name'),\n defaultMessage: 'Content Manager',\n })}\n </Page.Title>\n <Page.Loading />\n </>\n );\n }\n\n // Array of models that are displayed in the content manager\n const supportedModelsToDisplay = models.filter(({ isDisplayed }) => isDisplayed);\n\n // Redirect the user to the 403 page\n if (\n authorisedModels.length === 0 &&\n supportedModelsToDisplay.length > 0 &&\n pathname !== '/content-manager/403'\n ) {\n return <Navigate to=\"/403\" />;\n }\n\n // Redirect the user to the create content type page\n if (supportedModelsToDisplay.length === 0 && pathname !== '/no-content-types') {\n return <Navigate to=\"/no-content-types\" />;\n }\n\n // On /content-manager base route\n if (!contentTypeMatch && authorisedModels.length > 0) {\n // On desktop: redirect to first collection type\n if (!isMobile) {\n return (\n <Navigate\n to={{\n pathname: authorisedModels[0].to,\n search: authorisedModels[0].search ?? '',\n }}\n replace\n />\n );\n }\n\n // On mobile: show navigation page\n return (\n <>\n <Page.Title>\n {formatMessage({\n id: getTranslation('plugin.name'),\n defaultMessage: 'Content Manager',\n })}\n </Page.Title>\n <SubNav.PageWrapper>\n <LeftMenu isFullPage />\n </SubNav.PageWrapper>\n </>\n );\n }\n\n return (\n <>\n <Page.Title>\n {formatMessage({\n id: getTranslation('plugin.name'),\n defaultMessage: 'Content Manager',\n })}\n </Page.Title>\n <Layouts.Root sideNav={<LeftMenu />}>\n <DragLayer renderItem={renderDraglayerItem} />\n <LazyOutlet nested />\n </Layouts.Root>\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * renderDraglayerItem\n * -----------------------------------------------------------------------------------------------*/\n\nfunction renderDraglayerItem({ type, item }: Parameters<DragLayerProps['renderItem']>[0]) {\n if (!type || (type && typeof type !== 'string')) {\n return null;\n }\n\n /**\n * Because a user may have multiple relations / dynamic zones / repeable fields in the same content type,\n * we append the fieldName for the item type to make them unique, however, we then want to extract that\n * first type to apply the correct preview.\n */\n const [actualType] = type.split('_');\n\n switch (actualType) {\n case ItemTypes.EDIT_FIELD:\n case ItemTypes.FIELD:\n return isCardDragItem(item) ? <CardDragPreview label={item.label} /> : null;\n case ItemTypes.COMPONENT:\n case ItemTypes.DYNAMIC_ZONE:\n return isComponentDragItem(item) ? (\n <ComponentDragPreview displayedValue={item.displayedValue} />\n ) : null;\n\n case ItemTypes.RELATION:\n return isRelationDragItem(item) ? <RelationDragPreview {...item} /> : null;\n\n default:\n return null;\n }\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return value !== null && typeof value === 'object';\n};\n\nconst isCardDragItem = (item: unknown): item is CardDragPreviewProps => {\n return isRecord(item) && typeof item.label === 'string';\n};\n\nconst isComponentDragItem = (item: unknown): item is ComponentDragPreviewProps => {\n return isRecord(item) && typeof item.displayedValue === 'string';\n};\n\nconst isRelationDragItem = (item: unknown): item is RelationDragPreviewProps => {\n return (\n isRecord(item) &&\n typeof item.displayedValue === 'string' &&\n (typeof item.id === 'string' || typeof item.id === 'number') &&\n typeof item.index === 'number' &&\n typeof item.width === 'number' &&\n (item.status === undefined || typeof item.status === 'string')\n );\n};\n\nexport { Layout };\n"],"names":["Layout","contentTypeMatch","useMatch","isMobile","useIsMobile","isLoading","collectionTypeLinks","models","singleTypeLinks","useContentManagerInitData","authorisedModels","sort","a","b","title","localeCompare","pathname","useLocation","formatMessage","useIntl","_jsxs","_Fragment","_jsx","Page","Title","id","getTranslation","defaultMessage","Loading","supportedModelsToDisplay","filter","isDisplayed","length","Navigate","to","search","replace","SubNav","PageWrapper","LeftMenu","isFullPage","Layouts","Root","sideNav","DragLayer","renderItem","renderDraglayerItem","LazyOutlet","nested","type","item","actualType","split","ItemTypes","EDIT_FIELD","FIELD","isCardDragItem","CardDragPreview","label","COMPONENT","DYNAMIC_ZONE","isComponentDragItem","ComponentDragPreview","displayedValue","RELATION","isRelationDragItem","RelationDragPreview","isRecord","value","index","width","status","undefined"],"mappings":"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"}
1
+ {"version":3,"file":"layout.mjs","sources":["../../admin/src/layout.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport * as React from 'react';\n\nimport {\n Page,\n Layouts,\n SubNav,\n useIsMobile,\n LazyOutlet,\n useQueryParams,\n useNotification,\n useAuth,\n} from '@strapi/admin/strapi-admin';\nimport { stringify } from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Navigate, useLocation, useMatch } from 'react-router-dom';\n\nimport { DragLayer, DragLayerProps } from './components/DragLayer';\nimport { CardDragPreview } from './components/DragPreviews/CardDragPreview';\nimport { ComponentDragPreview } from './components/DragPreviews/ComponentDragPreview';\nimport { RelationDragPreview } from './components/DragPreviews/RelationDragPreview';\nimport { LeftMenu } from './components/LeftMenu';\nimport { ItemTypes } from './constants/dragAndDrop';\nimport { useContentManagerInitData } from './hooks/useContentManagerInitData';\nimport { getTranslation } from './utils/translations';\n\nimport type { CardDragPreviewProps } from './components/DragPreviews/CardDragPreview';\nimport type { ComponentDragPreviewProps } from './components/DragPreviews/ComponentDragPreview';\nimport type { RelationDragPreviewProps } from './components/DragPreviews/RelationDragPreview';\nimport type { To } from 'react-router-dom';\n\n/* -------------------------------------------------------------------------------------------------\n * Layout\n * -----------------------------------------------------------------------------------------------*/\n\nconst Layout = () => {\n const contentTypeMatch = useMatch('/content-manager/:kind/:uid/*');\n const isMobile = useIsMobile();\n\n const { isLoading, collectionTypeLinks, models, singleTypeLinks } = useContentManagerInitData();\n const authorisedModels = [...collectionTypeLinks, ...singleTypeLinks].sort((a, b) =>\n a.title.localeCompare(b.title)\n );\n\n const { pathname } = useLocation();\n const { formatMessage } = useIntl();\n const [{ query }] = useQueryParams<{ plugins?: { i18n?: { locale?: string } } }>();\n const permissions = useAuth('Layout', (state) => state.permissions);\n\n if (isLoading) {\n return (\n <>\n <Page.Title>\n {formatMessage({\n id: getTranslation('plugin.name'),\n defaultMessage: 'Content Manager',\n })}\n </Page.Title>\n <Page.Loading />\n </>\n );\n }\n\n // Array of models that are displayed in the content manager\n const supportedModelsToDisplay = models.filter(({ isDisplayed }) => isDisplayed);\n\n // Redirect the user to the 403 page\n if (\n authorisedModels.length === 0 &&\n supportedModelsToDisplay.length > 0 &&\n pathname !== '/content-manager/403'\n ) {\n const requestedLocale = query.plugins?.i18n?.locale;\n const localeScopedPermissions = permissions.filter(\n (permission) =>\n permission.action === 'plugin::content-manager.explorer.read' &&\n Array.isArray(permission.properties?.locales)\n );\n const contentTypePermissions = localeScopedPermissions.filter(\n (permission) => permission.subject === contentTypeMatch?.params.uid\n );\n const accessibleLocales = Array.from(\n new Set(\n (contentTypePermissions.length > 0\n ? contentTypePermissions\n : localeScopedPermissions\n ).flatMap((permission) => permission.properties?.locales as string[])\n )\n );\n\n if (typeof requestedLocale === 'string' && accessibleLocales.length > 0) {\n if (!accessibleLocales.includes(requestedLocale)) {\n const search = stringify({\n ...query,\n plugins: {\n ...query.plugins,\n i18n: { ...query.plugins?.i18n, locale: accessibleLocales[0] },\n },\n });\n\n return <NavigateWithLocaleWarning to={{ pathname, search }} />;\n }\n } else {\n return <Navigate to=\"/content-manager/403\" replace />;\n }\n }\n\n // Redirect the user to the create content type page\n if (supportedModelsToDisplay.length === 0 && pathname !== '/content-manager/no-content-types') {\n return <Navigate to=\"/content-manager/no-content-types\" replace />;\n }\n\n // On /content-manager base route\n if (\n !contentTypeMatch &&\n authorisedModels.length > 0 &&\n pathname !== '/content-manager/403' &&\n pathname !== '/content-manager/no-content-types'\n ) {\n // On desktop: redirect to first collection type\n if (!isMobile) {\n return (\n <Navigate\n to={{\n pathname: authorisedModels[0].to,\n search: authorisedModels[0].search ?? '',\n }}\n replace\n />\n );\n }\n\n // On mobile: show navigation page\n return (\n <>\n <Page.Title>\n {formatMessage({\n id: getTranslation('plugin.name'),\n defaultMessage: 'Content Manager',\n })}\n </Page.Title>\n <SubNav.PageWrapper>\n <LeftMenu isFullPage />\n </SubNav.PageWrapper>\n </>\n );\n }\n\n return (\n <>\n <Page.Title>\n {formatMessage({\n id: getTranslation('plugin.name'),\n defaultMessage: 'Content Manager',\n })}\n </Page.Title>\n <Layouts.Root sideNav={<LeftMenu />}>\n <DragLayer renderItem={renderDraglayerItem} />\n <LazyOutlet nested />\n </Layouts.Root>\n </>\n );\n};\n\nconst NavigateWithLocaleWarning = ({ to }: { to: To }) => {\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n\n React.useEffect(() => {\n toggleNotification({\n type: 'warning',\n message: formatMessage({\n id: getTranslation('permissions.not-allowed.locale'),\n defaultMessage:\n \"You don't have the permissions to access this content for the requested locale\",\n }),\n });\n }, [toggleNotification, formatMessage]);\n\n return <Navigate to={to} replace />;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * renderDraglayerItem\n * -----------------------------------------------------------------------------------------------*/\n\nfunction renderDraglayerItem({ type, item }: Parameters<DragLayerProps['renderItem']>[0]) {\n if (!type || (type && typeof type !== 'string')) {\n return null;\n }\n\n /**\n * Because a user may have multiple relations / dynamic zones / repeable fields in the same content type,\n * we append the fieldName for the item type to make them unique, however, we then want to extract that\n * first type to apply the correct preview.\n */\n const [actualType] = type.split('_');\n\n switch (actualType) {\n case ItemTypes.EDIT_FIELD:\n case ItemTypes.FIELD:\n return isCardDragItem(item) ? <CardDragPreview label={item.label} /> : null;\n case ItemTypes.COMPONENT:\n case ItemTypes.DYNAMIC_ZONE:\n return isComponentDragItem(item) ? (\n <ComponentDragPreview displayedValue={item.displayedValue} />\n ) : null;\n\n case ItemTypes.RELATION:\n return isRelationDragItem(item) ? <RelationDragPreview {...item} /> : null;\n\n default:\n return null;\n }\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return value !== null && typeof value === 'object';\n};\n\nconst isCardDragItem = (item: unknown): item is CardDragPreviewProps => {\n return isRecord(item) && typeof item.label === 'string';\n};\n\nconst isComponentDragItem = (item: unknown): item is ComponentDragPreviewProps => {\n return isRecord(item) && typeof item.displayedValue === 'string';\n};\n\nconst isRelationDragItem = (item: unknown): item is RelationDragPreviewProps => {\n return (\n isRecord(item) &&\n typeof item.displayedValue === 'string' &&\n (typeof item.id === 'string' || typeof item.id === 'number') &&\n typeof item.index === 'number' &&\n typeof item.width === 'number' &&\n (item.status === undefined || typeof item.status === 'string')\n );\n};\n\nexport { Layout };\n"],"names":["Layout","contentTypeMatch","useMatch","isMobile","useIsMobile","isLoading","collectionTypeLinks","models","singleTypeLinks","useContentManagerInitData","authorisedModels","sort","a","b","title","localeCompare","pathname","useLocation","formatMessage","useIntl","query","useQueryParams","permissions","useAuth","state","_jsxs","_Fragment","_jsx","Page","Title","id","getTranslation","defaultMessage","Loading","supportedModelsToDisplay","filter","isDisplayed","length","requestedLocale","plugins","i18n","locale","localeScopedPermissions","permission","action","Array","isArray","properties","locales","contentTypePermissions","subject","params","uid","accessibleLocales","from","Set","flatMap","includes","search","stringify","NavigateWithLocaleWarning","to","Navigate","replace","SubNav","PageWrapper","LeftMenu","isFullPage","Layouts","Root","sideNav","DragLayer","renderItem","renderDraglayerItem","LazyOutlet","nested","toggleNotification","useNotification","React","useEffect","type","message","item","actualType","split","ItemTypes","EDIT_FIELD","FIELD","isCardDragItem","CardDragPreview","label","COMPONENT","DYNAMIC_ZONE","isComponentDragItem","ComponentDragPreview","displayedValue","RELATION","isRelationDragItem","RelationDragPreview","isRecord","value","index","width","status","undefined"],"mappings":"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"}
@@ -5,10 +5,6 @@ var React = require('react');
5
5
  var strapiAdmin = require('@strapi/admin/strapi-admin');
6
6
  var designSystem = require('@strapi/design-system');
7
7
  var Icons = require('@strapi/icons');
8
- var mapValues = require('lodash/fp/mapValues');
9
- var get = require('lodash/get');
10
- var merge = require('lodash/merge');
11
- var set = require('lodash/set');
12
8
  var reactIntl = require('react-intl');
13
9
  var reactRouterDom = require('react-router-dom');
14
10
  var attributes = require('../../../constants/attributes.js');
@@ -21,14 +17,13 @@ var Preview = require('../../../preview/pages/Preview.js');
21
17
  var router = require('../../../router.js');
22
18
  var documents = require('../../../services/documents.js');
23
19
  var api = require('../../../utils/api.js');
20
+ var objects = require('../../../utils/objects.js');
24
21
  var translations = require('../../../utils/translations.js');
25
22
  var data = require('../utils/data.js');
26
23
  var draftRelationCounts = require('../utils/draftRelationCounts.js');
27
24
  var keyboardShortcuts = require('../utils/keyboardShortcuts.js');
28
25
  var RelationModal = require('./FormInputs/Relations/RelationModal.js');
29
26
 
30
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
31
-
32
27
  function _interopNamespace(e) {
33
28
  if (e && e.__esModule) return e;
34
29
  var n = Object.create(null);
@@ -48,46 +43,48 @@ function _interopNamespace(e) {
48
43
  }
49
44
 
50
45
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
51
- var mapValues__default = /*#__PURE__*/_interopDefault(mapValues);
52
- var get__default = /*#__PURE__*/_interopDefault(get);
53
- var merge__default = /*#__PURE__*/_interopDefault(merge);
54
- var set__default = /*#__PURE__*/_interopDefault(set);
55
46
 
56
47
  const publishConfirmDialogOpeners = new Map();
57
48
  const openPublishConfirmDialog = (scope)=>{
58
49
  publishConfirmDialogOpeners.get(scope)?.();
59
50
  };
60
51
  const connectRelationToParent = (parentDataToUpdate, fieldToConnect, data, fieldToConnectUID)=>{
52
+ const relationToConnect = {
53
+ id: data.documentId,
54
+ documentId: data.documentId,
55
+ locale: data.locale
56
+ };
61
57
  /*
62
58
  * Check if the fieldToConnect is already present in the parentDataToUpdate.
63
59
  * This happens in particular when in the parentDocument you have created
64
60
  * a new component without saving.
65
- */ const isFieldPresent = !!get__default.default(parentDataToUpdate, fieldToConnect);
66
- const fieldToConnectPath = isFieldPresent ? fieldToConnect : fieldToConnect.split('.').slice(0, -1).join('.');
67
- const fieldToConnectValue = isFieldPresent ? {
68
- connect: [
69
- {
70
- id: data.documentId,
71
- documentId: data.documentId,
72
- locale: data.locale
73
- }
74
- ]
61
+ */ const fieldValue = objects.getIn(parentDataToUpdate, fieldToConnect);
62
+ const relationFieldValue = objects.isObject(fieldValue) ? fieldValue : undefined;
63
+ const isFieldPresent = relationFieldValue !== undefined;
64
+ const fieldPath = fieldToConnect.split('.');
65
+ const fieldName = fieldPath.at(-1);
66
+ if (!fieldName) {
67
+ return parentDataToUpdate;
68
+ }
69
+ const parentPath = fieldPath.slice(0, -1).join('.');
70
+ const existingConnect = Array.isArray(relationFieldValue?.connect) ? relationFieldValue.connect : [];
71
+ // A relation is identified by documentId and locale; numeric ids are not stable across locales.
72
+ const connect = existingConnect.some((relation)=>relation.documentId === relationToConnect.documentId && relation.locale === relationToConnect.locale) ? existingConnect : [
73
+ ...existingConnect,
74
+ relationToConnect
75
+ ];
76
+ const relationValue = isFieldPresent ? {
77
+ ...relationFieldValue,
78
+ connect
75
79
  } : {
76
- [fieldToConnect.split('.').pop()]: {
77
- connect: [
78
- {
79
- id: data.documentId,
80
- documentId: data.documentId,
81
- locale: data.locale
82
- }
83
- ],
84
- disconnect: []
85
- },
86
- // In case the object was not present you need to pass the componentUID of the parent document
87
- __component: fieldToConnectUID
80
+ connect,
81
+ disconnect: []
88
82
  };
89
- const objectToConnect = set__default.default({}, fieldToConnectPath, fieldToConnectValue);
90
- return merge__default.default(parentDataToUpdate, objectToConnect);
83
+ const dataWithRelation = objects.setIn(parentDataToUpdate, fieldToConnect, relationValue);
84
+ if (!isFieldPresent && fieldToConnectUID && parentPath) {
85
+ return objects.setIn(dataWithRelation, `${parentPath}.__component`, fieldToConnectUID);
86
+ }
87
+ return dataWithRelation;
91
88
  };
92
89
  const DocumentActions = ({ actions })=>{
93
90
  const { formatMessage } = reactIntl.useIntl();
@@ -260,7 +257,7 @@ const DocumentActionsMenu = ({ actions, children, label, variant = 'tertiary' })
260
257
  const [dialogId, setDialogId] = React__namespace.useState(null);
261
258
  const { formatMessage } = reactIntl.useIntl();
262
259
  const { toggleNotification } = strapiAdmin.useNotification();
263
- const isDisabled = actions.every((action)=>action.disabled) || actions.length === 0;
260
+ const isDisabled = actions.every((action)=>action.disabled);
264
261
  const triggerRef = React__namespace.useRef(null);
265
262
  const handleClick = (action)=>async (e)=>{
266
263
  const { onClick = ()=>false, dialog, id } = action;
@@ -464,11 +461,26 @@ const transformData = (data)=>{
464
461
  if ('apiData' in data) {
465
462
  return data.apiData;
466
463
  }
467
- return mapValues__default.default((value)=>transformData(value))(data);
464
+ return Object.fromEntries(Object.entries(data).map(([key, value])=>[
465
+ key,
466
+ transformData(value)
467
+ ]));
468
468
  }
469
469
  return data;
470
470
  };
471
471
  const transformDocumentData = (data)=>transformData(data);
472
+ const prepareParentDataForRelationUpdate = (parentFormValues, fallbackParentFormValues, options)=>{
473
+ const parentDataToUpdate = parentFormValues ?? fallbackParentFormValues;
474
+ if (!parentDataToUpdate) {
475
+ return parentDataToUpdate;
476
+ }
477
+ const { data: data$1 } = data.handleInvisibleAttributes(transformDocumentData(parentDataToUpdate), {
478
+ ...options,
479
+ // The live snapshot can omit saved invisible fields, so retain the parent's saved initial values.
480
+ initialValues: fallbackParentFormValues
481
+ });
482
+ return data$1;
483
+ };
472
484
  /* -------------------------------------------------------------------------------------------------
473
485
  * DocumentActionComponents
474
486
  * -----------------------------------------------------------------------------------------------*/ const PublishAction = ({ activeTab, documentId, model, collectionType, meta, document })=>{
@@ -508,6 +520,7 @@ const transformDocumentData = (data)=>transformData(data);
508
520
  const dispatch = RelationModal.useRelationModal('PublishAction', (state)=>state.dispatch);
509
521
  const fieldToConnect = RelationModal.useRelationModal('PublishAction', (state)=>state.state.fieldToConnect, false);
510
522
  const fieldToConnectUID = RelationModal.useRelationModal('PublishAction', (state)=>state.state.fieldToConnectUID, false);
523
+ const getParentFormValues = RelationModal.useRelationModal('PublishAction', (state)=>state.state.getParentFormValues, false);
511
524
  const documentHistory = RelationModal.useRelationModal('PublishAction', (state)=>state.state.documentHistory, false);
512
525
  const rootDocumentMeta = RelationModal.useRelationModal('PublishAction', (state)=>state.rootDocumentMeta);
513
526
  const dispatchGuidedTour = strapiAdmin.useGuidedTour('PublishAction', (s)=>s.dispatch);
@@ -678,33 +691,39 @@ const transformDocumentData = (data)=>transformData(data);
678
691
  * Check if in history we have the parent relation otherwise use the
679
692
  * rootDocument
680
693
  */ if (fieldToConnect && documentHistory && (parentDocumentMetaToUpdate.documentId || parentDocumentMetaToUpdate.collectionType === collections.SINGLE_TYPES)) {
681
- const parentDataToUpdate = parentDocumentMetaToUpdate.collectionType === collections.SINGLE_TYPES ? getInitialFormValues() : parentDocumentData.getInitialFormValues();
694
+ const fallbackParentFormValues = parentDocumentMetaToUpdate.collectionType === collections.SINGLE_TYPES ? getInitialFormValues() : parentDocumentData.getInitialFormValues();
695
+ const parentDataToUpdate = prepareParentDataForRelationUpdate(getParentFormValues?.(), fallbackParentFormValues, {
696
+ schema: parentDocumentData.schema,
697
+ components: parentDocumentData.components
698
+ });
682
699
  const metaDocumentToUpdate = documentHistory.at(-2) ?? rootDocumentMeta;
683
- const dataToUpdate = connectRelationToParent(parentDataToUpdate, fieldToConnect, res.data, fieldToConnectUID);
684
- try {
685
- const updateRes = await updateDocumentMutation({
686
- collectionType: metaDocumentToUpdate.collectionType,
687
- model: metaDocumentToUpdate.model,
688
- documentId: metaDocumentToUpdate.collectionType !== collections.SINGLE_TYPES ? metaDocumentToUpdate.documentId : undefined,
689
- params: metaDocumentToUpdate.params,
690
- data: dataToUpdate
691
- });
692
- if ('error' in updateRes) {
700
+ if (parentDataToUpdate) {
701
+ const dataToUpdate = connectRelationToParent(parentDataToUpdate, fieldToConnect, res.data, fieldToConnectUID);
702
+ try {
703
+ const updateRes = await updateDocumentMutation({
704
+ collectionType: metaDocumentToUpdate.collectionType,
705
+ model: metaDocumentToUpdate.model,
706
+ documentId: metaDocumentToUpdate.collectionType !== collections.SINGLE_TYPES ? metaDocumentToUpdate.documentId : undefined,
707
+ params: metaDocumentToUpdate.params,
708
+ data: dataToUpdate
709
+ });
710
+ if ('error' in updateRes) {
711
+ toggleNotification({
712
+ type: 'danger',
713
+ message: formatAPIError(updateRes.error)
714
+ });
715
+ return;
716
+ }
717
+ } catch (err) {
693
718
  toggleNotification({
694
719
  type: 'danger',
695
- message: formatAPIError(updateRes.error)
720
+ message: formatMessage({
721
+ id: 'notification.error',
722
+ defaultMessage: 'An error occurred'
723
+ })
696
724
  });
697
- return;
725
+ throw err;
698
726
  }
699
- } catch (err) {
700
- toggleNotification({
701
- type: 'danger',
702
- message: formatMessage({
703
- id: 'notification.error',
704
- defaultMessage: 'An error occurred'
705
- })
706
- });
707
- throw err;
708
727
  }
709
728
  }
710
729
  dispatch({
@@ -888,6 +907,7 @@ const UpdateAction = ({ activeTab, documentId, model, collectionType })=>{
888
907
  const relationalModalSchema = RelationModal.useRelationModal('UpdateAction', (state)=>state.currentDocument.schema, false);
889
908
  const fieldToConnect = RelationModal.useRelationModal('UpdateAction', (state)=>state.state.fieldToConnect, false);
890
909
  const fieldToConnectUID = RelationModal.useRelationModal('PublishAction', (state)=>state.state.fieldToConnectUID, false);
910
+ const getParentFormValues = RelationModal.useRelationModal('UpdateAction', (state)=>state.state.getParentFormValues, false);
891
911
  const documentHistory = RelationModal.useRelationModal('UpdateAction', (state)=>state.state.documentHistory, false);
892
912
  const rootDocumentMeta = RelationModal.useRelationModal('UpdateAction', (state)=>state.rootDocumentMeta);
893
913
  const fromRelationModal = relationContext != undefined;
@@ -998,34 +1018,40 @@ const UpdateAction = ({ activeTab, documentId, model, collectionType })=>{
998
1018
  * Check if in history we have the parent relation otherwise use the
999
1019
  * rootDocument
1000
1020
  */ if (fieldToConnect && documentHistory && (parentDocumentMetaToUpdate.documentId || parentDocumentMetaToUpdate.collectionType === collections.SINGLE_TYPES)) {
1001
- const parentDataToUpdate = parentDocumentMetaToUpdate.collectionType === collections.SINGLE_TYPES ? getInitialFormValues() : parentDocumentData.getInitialFormValues();
1002
- const dataToUpdate = connectRelationToParent(parentDataToUpdate, fieldToConnect, res.data, fieldToConnectUID);
1003
- try {
1004
- const updateRes = await updateDocumentMutation({
1005
- collectionType: parentDocumentMetaToUpdate.collectionType,
1006
- model: parentDocumentMetaToUpdate.model,
1007
- documentId: parentDocumentMetaToUpdate.collectionType !== collections.SINGLE_TYPES ? parentDocumentMetaToUpdate.documentId : undefined,
1008
- params: parentDocumentMetaToUpdate.params,
1009
- data: {
1010
- ...dataToUpdate
1021
+ const fallbackParentFormValues = parentDocumentMetaToUpdate.collectionType === collections.SINGLE_TYPES ? getInitialFormValues() : parentDocumentData.getInitialFormValues();
1022
+ const parentDataToUpdate = prepareParentDataForRelationUpdate(getParentFormValues?.(), fallbackParentFormValues, {
1023
+ schema: parentDocumentData.schema,
1024
+ components: parentDocumentData.components
1025
+ });
1026
+ if (parentDataToUpdate) {
1027
+ const dataToUpdate = connectRelationToParent(parentDataToUpdate, fieldToConnect, res.data, fieldToConnectUID);
1028
+ try {
1029
+ const updateRes = await updateDocumentMutation({
1030
+ collectionType: parentDocumentMetaToUpdate.collectionType,
1031
+ model: parentDocumentMetaToUpdate.model,
1032
+ documentId: parentDocumentMetaToUpdate.collectionType !== collections.SINGLE_TYPES ? parentDocumentMetaToUpdate.documentId : undefined,
1033
+ params: parentDocumentMetaToUpdate.params,
1034
+ data: {
1035
+ ...dataToUpdate
1036
+ }
1037
+ });
1038
+ if ('error' in updateRes) {
1039
+ toggleNotification({
1040
+ type: 'danger',
1041
+ message: formatAPIError(updateRes.error)
1042
+ });
1043
+ return;
1011
1044
  }
1012
- });
1013
- if ('error' in updateRes) {
1045
+ } catch (err) {
1014
1046
  toggleNotification({
1015
1047
  type: 'danger',
1016
- message: formatAPIError(updateRes.error)
1048
+ message: formatMessage({
1049
+ id: 'notification.error',
1050
+ defaultMessage: 'An error occurred'
1051
+ })
1017
1052
  });
1018
- return;
1053
+ throw err;
1019
1054
  }
1020
- } catch (err) {
1021
- toggleNotification({
1022
- type: 'danger',
1023
- message: formatMessage({
1024
- id: 'notification.error',
1025
- defaultMessage: 'An error occurred'
1026
- })
1027
- });
1028
- throw err;
1029
1055
  }
1030
1056
  }
1031
1057
  dispatch({
@@ -1325,5 +1351,7 @@ exports.DEFAULT_ACTIONS = DEFAULT_ACTIONS;
1325
1351
  exports.DocumentActionButton = DocumentActionButton;
1326
1352
  exports.DocumentActions = DocumentActions;
1327
1353
  exports.DocumentActionsMenu = DocumentActionsMenu;
1354
+ exports.PublishAction = PublishAction;
1355
+ exports.UpdateAction = UpdateAction;
1328
1356
  exports.openPublishConfirmDialog = openPublishConfirmDialog;
1329
1357
  //# sourceMappingURL=DocumentActions.js.map