@strapi/admin 4.12.6 → 4.13.0-alpha.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 (211) hide show
  1. package/admin/src/StrapiApp.js +1 -1
  2. package/admin/src/components/AuthenticatedApp/index.js +118 -0
  3. package/admin/src/components/AuthenticatedApp/utils/api.js +85 -0
  4. package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +11 -0
  5. package/admin/src/components/GuidedTour/Modal/index.js +3 -1
  6. package/admin/src/components/NpsSurvey/hooks/useNpsSurveySettings.js +17 -0
  7. package/admin/src/components/NpsSurvey/index.js +365 -0
  8. package/admin/src/components/PluginsInitializer/index.js +68 -0
  9. package/admin/src/components/PluginsInitializer/init.js +11 -0
  10. package/admin/src/components/PluginsInitializer/reducer.js +22 -0
  11. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumns.js +2 -0
  12. package/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js +1 -1
  13. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +8 -1
  14. package/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.js +42 -0
  15. package/admin/src/content-manager/components/Filter/Filter.js +54 -0
  16. package/admin/src/content-manager/components/Filter/index.js +1 -0
  17. package/admin/src/content-manager/components/InputUID/index.js +222 -216
  18. package/admin/src/content-manager/components/RelationInput/RelationInput.js +4 -0
  19. package/admin/src/content-manager/components/RepeatableComponent/index.js +32 -2
  20. package/admin/src/content-manager/components/Wysiwyg/Editor.js +432 -68
  21. package/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.js +0 -7
  22. package/admin/src/content-manager/components/Wysiwyg/index.js +147 -152
  23. package/admin/src/content-manager/hooks/useAllowedAttributes.js +47 -0
  24. package/admin/src/content-manager/pages/App/index.js +16 -5
  25. package/admin/src/content-manager/pages/EditView/Information/index.js +9 -8
  26. package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +40 -7
  27. package/admin/src/content-manager/pages/ListSettingsView/index.js +6 -2
  28. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +2 -2
  29. package/admin/src/content-manager/pages/ListView/components/FieldPicker/index.js +67 -69
  30. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
  31. package/admin/src/content-manager/pages/ListView/components/ViewSettingsMenu/index.js +80 -0
  32. package/admin/src/content-manager/pages/ListView/index.js +236 -67
  33. package/admin/src/content-manager/utils/getDisplayName.js +33 -0
  34. package/admin/src/content-manager/utils/index.js +1 -0
  35. package/admin/src/hooks/useSettingsForm/index.js +3 -14
  36. package/admin/src/hooks/useSettingsMenu/index.js +2 -2
  37. package/admin/src/hooks/useSettingsMenu/utils/formatLinks.js +3 -1
  38. package/admin/src/hooks/useSettingsMenu/utils/sortLinks.js +3 -1
  39. package/admin/src/index.js +1 -1
  40. package/admin/src/layouts/AppLayout/index.js +33 -0
  41. package/admin/src/pages/Admin/Onboarding/index.js +3 -1
  42. package/admin/src/pages/Admin/index.js +73 -77
  43. package/admin/src/pages/App/constants.js +1 -1
  44. package/admin/src/pages/App/index.js +122 -160
  45. package/admin/src/pages/AuthPage/components/Register/index.js +5 -0
  46. package/admin/src/pages/AuthPage/index.js +4 -2
  47. package/admin/src/pages/HomePage/index.js +3 -1
  48. package/admin/src/pages/InstalledPluginsPage/index.js +3 -1
  49. package/admin/src/pages/{InternalErrorPage.js → InternalErrorPage/index.js} +4 -3
  50. package/admin/src/pages/{NotFoundPage.js → NotFoundPage/index.js} +3 -1
  51. package/admin/src/pages/ProfilePage/index.js +4 -2
  52. package/admin/src/pages/SettingsPage/constants.js +132 -67
  53. package/admin/src/pages/SettingsPage/index.js +18 -23
  54. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +1 -1
  55. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
  56. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +1 -2
  57. package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
  58. package/admin/src/pages/UseCasePage/index.js +175 -0
  59. package/admin/src/plugins.js +7 -8
  60. package/admin/src/translations/en.json +10 -1
  61. package/admin/src/utils/checkFormValidity.js +15 -0
  62. package/admin/src/utils/createRoute.js +7 -5
  63. package/admin/src/utils/formatAPIErrors.js +3 -1
  64. package/admin/src/utils/getAttributesToDisplay.js +19 -0
  65. package/admin/src/utils/getExistingActions.js +32 -0
  66. package/admin/src/utils/getFullName.js +1 -1
  67. package/admin/src/utils/index.js +9 -0
  68. package/admin/src/utils/makeUniqueRoutes.js +6 -0
  69. package/admin/src/utils/sortLinks.js +3 -1
  70. package/admin/src/utils/uniqueAdminHash.js +9 -2
  71. package/build/{1049.9d69d231.chunk.js → 1049.ec69f5e0.chunk.js} +1 -1
  72. package/build/1227.9f37e1dc.chunk.js +1 -0
  73. package/build/1386.ea73b677.chunk.js +7 -0
  74. package/build/{2225.33287e1b.chunk.js → 2225.649fb7bc.chunk.js} +2 -2
  75. package/build/{2237.03792b63.chunk.js → 2237.b832ae6e.chunk.js} +4 -4
  76. package/build/{2379.401f56f3.chunk.js → 2379.1f98a31a.chunk.js} +1 -1
  77. package/build/{2395.e6a79fbb.chunk.js → 2395.0e5e8ded.chunk.js} +1 -1
  78. package/build/{2801.31393ffe.chunk.js → 2801.8e1aa82a.chunk.js} +1 -1
  79. package/build/3483.19381b40.chunk.js +1 -0
  80. package/build/3739.63e352f1.chunk.js +103 -0
  81. package/build/4174.f1f39e40.chunk.js +1 -0
  82. package/build/448.829e1344.chunk.js +1 -0
  83. package/build/4546.a5946d22.chunk.js +1 -0
  84. package/build/4724.aea5c8c1.chunk.js +6 -0
  85. package/build/{502.8dd074ff.chunk.js → 502.7bba43b1.chunk.js} +1 -1
  86. package/build/6158.c3c13c20.chunk.js +1 -0
  87. package/build/6691.4985ef22.chunk.js +105 -0
  88. package/build/{7464.592a9295.chunk.js → 7464.eb057bec.chunk.js} +1 -1
  89. package/build/78.dcc6df5c.chunk.js +1 -0
  90. package/build/{8276.e519a707.chunk.js → 8276.be3ed581.chunk.js} +2 -2
  91. package/build/{2747.d1442a90.chunk.js → 9806.5d5a0e8d.chunk.js} +64 -72
  92. package/build/9944.7af075a5.chunk.js +26 -0
  93. package/build/Admin-authenticatedApp.43b6ec9a.chunk.js +79 -0
  94. package/build/Admin_InternalErrorPage.38155af3.chunk.js +1 -0
  95. package/build/Admin_homePage.6f128523.chunk.js +81 -0
  96. package/build/Admin_marketplace.061a6e5a.chunk.js +55 -0
  97. package/build/Admin_pluginsPage.16f837b8.chunk.js +6 -0
  98. package/build/Admin_profilePage.678bce24.chunk.js +13 -0
  99. package/build/Admin_settingsPage.af7309e4.chunk.js +111 -0
  100. package/build/{Upload_ConfigureTheView.345ac1e0.chunk.js → Upload_ConfigureTheView.3fc1c100.chunk.js} +1 -1
  101. package/build/admin-app.d63bd229.chunk.js +36 -0
  102. package/build/{admin-edit-roles-page.24bdf746.chunk.js → admin-edit-roles-page.38a6c863.chunk.js} +3 -3
  103. package/build/admin-edit-users.545fc882.chunk.js +10 -0
  104. package/build/{admin-roles-list.23ddff26.chunk.js → admin-roles-list.1e2e814d.chunk.js} +1 -1
  105. package/build/admin-users.b8ea5677.chunk.js +11 -0
  106. package/build/{api-tokens-create-page.46c2ea84.chunk.js → api-tokens-create-page.e0c15627.chunk.js} +1 -1
  107. package/build/{api-tokens-edit-page.58139df9.chunk.js → api-tokens-edit-page.9f2dce47.chunk.js} +1 -1
  108. package/build/{api-tokens-list-page.0af7d431.chunk.js → api-tokens-list-page.d747051c.chunk.js} +2 -2
  109. package/build/{audit-logs-settings-page.0f73ccf8.chunk.js → audit-logs-settings-page.96f9d608.chunk.js} +1 -1
  110. package/build/content-manager.ccff1078.chunk.js +1097 -0
  111. package/build/{content-type-builder-list-view.bf9be456.chunk.js → content-type-builder-list-view.b71cf240.chunk.js} +1 -1
  112. package/build/{content-type-builder.66066281.chunk.js → content-type-builder.e5669749.chunk.js} +18 -18
  113. package/build/{email-settings-page.2f7e35c0.chunk.js → email-settings-page.2809f0bf.chunk.js} +1 -1
  114. package/build/en-json.e12fd5fc.chunk.js +1 -0
  115. package/build/{i18n-settings-page.47f78016.chunk.js → i18n-settings-page.5f716172.chunk.js} +1 -1
  116. package/build/index.html +1 -1
  117. package/build/main.c6c9e04c.js +2859 -0
  118. package/build/{review-workflows-settings-create-view.d24a32b9.chunk.js → review-workflows-settings-create-view.4a156a19.chunk.js} +1 -1
  119. package/build/{review-workflows-settings-edit-view.6044b022.chunk.js → review-workflows-settings-edit-view.ce984d1f.chunk.js} +1 -1
  120. package/build/{review-workflows-settings-list-view.3f0ef4bc.chunk.js → review-workflows-settings-list-view.419b8deb.chunk.js} +2 -2
  121. package/build/runtime~main.dcf1cb45.js +2 -0
  122. package/build/{sso-settings-page.4dba0670.chunk.js → sso-settings-page.45153df5.chunk.js} +1 -1
  123. package/build/{transfer-tokens-create-page.1597e6ab.chunk.js → transfer-tokens-create-page.ebba16d8.chunk.js} +1 -1
  124. package/build/{transfer-tokens-edit-page.8741529f.chunk.js → transfer-tokens-edit-page.d7bb2b3e.chunk.js} +1 -1
  125. package/build/{transfer-tokens-list-page.d6986b03.chunk.js → transfer-tokens-list-page.cfe1736c.chunk.js} +2 -2
  126. package/build/{upload-settings.7f93d4c0.chunk.js → upload-settings.cc5ad813.chunk.js} +1 -1
  127. package/build/{upload.37488080.chunk.js → upload.756efc28.chunk.js} +1 -1
  128. package/build/{users-advanced-settings-page.17052d72.chunk.js → users-advanced-settings-page.818d84eb.chunk.js} +1 -1
  129. package/build/{users-email-settings-page.3de8ea50.chunk.js → users-email-settings-page.c1967c09.chunk.js} +1 -1
  130. package/build/{users-providers-settings-page.0eaa916d.chunk.js → users-providers-settings-page.11893e08.chunk.js} +1 -1
  131. package/build/{users-roles-settings-page.957ad48b.chunk.js → users-roles-settings-page.2b051e6a.chunk.js} +1 -1
  132. package/build/webhook-edit-page.de45c635.chunk.js +33 -0
  133. package/build/{webhook-list-page.65e1b5bb.chunk.js → webhook-list-page.ca91df8b.chunk.js} +1 -1
  134. package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js +42 -0
  135. package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/StageFilter.js +70 -0
  136. package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js +71 -0
  137. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +9 -217
  138. package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/AssigneeSelect.js +147 -0
  139. package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/index.js +1 -0
  140. package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/StageSelect.js +243 -0
  141. package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/index.js +1 -0
  142. package/ee/admin/content-manager/pages/EditView/InformationBox/constants.js +2 -0
  143. package/ee/admin/content-manager/pages/ListSettingsView/constants.js +7 -0
  144. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js +21 -0
  145. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js +44 -17
  146. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/index.js +1 -0
  147. package/ee/admin/pages/App/constants.js +5 -6
  148. package/ee/admin/pages/SettingsPage/constants.js +42 -27
  149. package/ee/server/constants/workflows.js +1 -0
  150. package/ee/server/controllers/index.js +1 -0
  151. package/ee/server/controllers/workflows/assignees/index.js +44 -0
  152. package/ee/server/routes/review-workflows.js +17 -0
  153. package/ee/server/services/index.js +1 -0
  154. package/ee/server/services/review-workflows/assignees.js +54 -0
  155. package/ee/server/services/review-workflows/metrics/index.js +5 -0
  156. package/ee/server/services/review-workflows/review-workflows.js +20 -11
  157. package/ee/server/validation/review-workflows.js +8 -0
  158. package/index.js +2 -6
  159. package/package.json +9 -9
  160. package/scripts/build.js +15 -15
  161. package/scripts/create-dev-plugins-file.js +5 -38
  162. package/server/controllers/role.js +2 -0
  163. package/server/controllers/user.js +2 -0
  164. package/server/services/permission/permissions-manager/index.js +3 -1
  165. package/server/services/permission/permissions-manager/sanitize.js +19 -7
  166. package/server/services/permission/permissions-manager/validate.js +218 -0
  167. package/utils/create-cache-dir.js +62 -16
  168. package/utils/create-plugins-exclude-path.js +3 -23
  169. package/utils/get-plugins.js +110 -0
  170. package/utils/index.js +1 -1
  171. package/webpack.config.js +10 -13
  172. package/admin/src/components/AuthenticatedApp.js +0 -229
  173. package/admin/src/content-manager/components/AttributeFilter/Filters.js +0 -58
  174. package/admin/src/content-manager/components/AttributeFilter/hooks/useAllowedAttributes.js +0 -42
  175. package/admin/src/content-manager/components/AttributeFilter/index.js +0 -40
  176. package/admin/src/content-manager/components/Wysiwyg/EditorStylesContainer.js +0 -344
  177. package/admin/src/pages/UseCasePage.js +0 -174
  178. package/build/2166.c837469a.chunk.js +0 -1
  179. package/build/3483.8517171f.chunk.js +0 -1
  180. package/build/3984.dda474f7.chunk.js +0 -1
  181. package/build/4546.7a3c0d03.chunk.js +0 -1
  182. package/build/5483.5bfbb00d.chunk.js +0 -6
  183. package/build/6158.c974fd83.chunk.js +0 -1
  184. package/build/748.fd2e5afd.chunk.js +0 -105
  185. package/build/773.6381d62d.chunk.js +0 -18
  186. package/build/7826.399afe81.chunk.js +0 -103
  187. package/build/8261.2525d35c.chunk.js +0 -7
  188. package/build/8299.62b67c72.chunk.js +0 -1
  189. package/build/Admin-AuthPage.90d64342.chunk.js +0 -35
  190. package/build/Admin-AuthenticatedApp.379ac945.chunk.js +0 -24
  191. package/build/Admin-UseCasePage.1f757db5.chunk.js +0 -13
  192. package/build/Admin_GuidedTourModal.8ccf1fbc.chunk.js +0 -12
  193. package/build/Admin_InternalErrorPage.9de92c6d.chunk.js +0 -9
  194. package/build/Admin_NotFoundPage.21620424.chunk.js +0 -9
  195. package/build/Admin_Onboarding.dbfa32f6.chunk.js +0 -43
  196. package/build/Admin_homePage.2000cbe9.chunk.js +0 -86
  197. package/build/Admin_marketplace.ec80e29b.chunk.js +0 -63
  198. package/build/Admin_pluginsPage.0c6851f8.chunk.js +0 -14
  199. package/build/Admin_profilePage.78cd8495.chunk.js +0 -21
  200. package/build/Admin_settingsPage.1760c3ce.chunk.js +0 -119
  201. package/build/StrapiApp.221fac30.chunk.js +0 -5
  202. package/build/admin-edit-users.5d10d444.chunk.js +0 -10
  203. package/build/admin-users.2b3e4305.chunk.js +0 -11
  204. package/build/content-manager.fb0833bd.chunk.js +0 -1099
  205. package/build/en-json.08c05fcf.chunk.js +0 -1
  206. package/build/main.ee3c1938.js +0 -2859
  207. package/build/runtime~main.397ee447.js +0 -2
  208. package/build/webhook-edit-page.665210af.chunk.js +0 -33
  209. package/scripts/create-plugins-file.js +0 -92
  210. package/utils/get-plugins-path.js +0 -41
  211. /package/server/services/permission/permissions-manager/{query-builers.js → query-builders.js} +0 -0
@@ -1,4 +1,4 @@
1
- import React, { useRef, useState } from 'react';
1
+ import React, { forwardRef, useRef, useState } from 'react';
2
2
 
3
3
  import { Box, Flex, Typography } from '@strapi/design-system';
4
4
  import { prefixFileUrlWithBackendUrl, useLibrary } from '@strapi/helper-plugin';
@@ -30,160 +30,155 @@ const TypographyAsterisk = styled(Typography)`
30
30
  line-height: 0;
31
31
  `;
32
32
 
33
- const Wysiwyg = ({
34
- hint,
35
- disabled,
36
- error,
37
- intlLabel,
38
- labelAction,
39
- name,
40
- onChange,
41
- placeholder,
42
- value,
43
- required,
44
- }) => {
45
- const { formatMessage } = useIntl();
46
- const textareaRef = useRef(null);
47
- const editorRef = useRef(null);
48
- const [isPreviewMode, setIsPreviewMode] = useState(false);
49
- const [mediaLibVisible, setMediaLibVisible] = useState(false);
50
- const [isExpandMode, setIsExpandMode] = useState(false);
51
- const { components } = useLibrary();
52
-
53
- const MediaLibraryDialog = components['media-library'];
54
-
55
- const handleToggleMediaLib = () => setMediaLibVisible((prev) => !prev);
56
- const handleTogglePreviewMode = () => setIsPreviewMode((prev) => !prev);
57
- const handleToggleExpand = () => {
58
- setIsPreviewMode(false);
59
- setIsExpandMode((prev) => !prev);
60
- };
61
-
62
- const handleActionClick = (value, currentEditorRef, togglePopover) => {
63
- switch (value) {
64
- case 'Link':
65
- case 'Strikethrough': {
66
- markdownHandler(currentEditorRef, value);
67
- togglePopover();
68
- break;
33
+ const Wysiwyg = forwardRef(
34
+ (
35
+ { hint, disabled, error, intlLabel, labelAction, name, onChange, placeholder, value, required },
36
+ forwardedRef
37
+ ) => {
38
+ const { formatMessage } = useIntl();
39
+ const textareaRef = useRef(null);
40
+ const editorRef = useRef(null);
41
+ const [isPreviewMode, setIsPreviewMode] = useState(false);
42
+ const [mediaLibVisible, setMediaLibVisible] = useState(false);
43
+ const [isExpandMode, setIsExpandMode] = useState(false);
44
+ const { components } = useLibrary();
45
+
46
+ const MediaLibraryDialog = components['media-library'];
47
+
48
+ const handleToggleMediaLib = () => setMediaLibVisible((prev) => !prev);
49
+ const handleTogglePreviewMode = () => setIsPreviewMode((prev) => !prev);
50
+ const handleToggleExpand = () => {
51
+ setIsPreviewMode(false);
52
+ setIsExpandMode((prev) => !prev);
53
+ };
54
+
55
+ const handleActionClick = (value, currentEditorRef, togglePopover) => {
56
+ switch (value) {
57
+ case 'Link':
58
+ case 'Strikethrough': {
59
+ markdownHandler(currentEditorRef, value);
60
+ togglePopover();
61
+ break;
62
+ }
63
+ case 'Code':
64
+ case 'Quote': {
65
+ quoteAndCodeHandler(currentEditorRef, value);
66
+ togglePopover();
67
+ break;
68
+ }
69
+ case 'Bold':
70
+ case 'Italic':
71
+ case 'Underline': {
72
+ markdownHandler(currentEditorRef, value);
73
+ break;
74
+ }
75
+ case 'BulletList':
76
+ case 'NumberList': {
77
+ listHandler(currentEditorRef, value);
78
+ togglePopover();
79
+ break;
80
+ }
81
+ case 'h1':
82
+ case 'h2':
83
+ case 'h3':
84
+ case 'h4':
85
+ case 'h5':
86
+ case 'h6': {
87
+ titleHandler(currentEditorRef, value);
88
+ break;
89
+ }
90
+ default: {
91
+ // Nothing
92
+ }
69
93
  }
70
- case 'Code':
71
- case 'Quote': {
72
- quoteAndCodeHandler(currentEditorRef, value);
73
- togglePopover();
74
- break;
75
- }
76
- case 'Bold':
77
- case 'Italic':
78
- case 'Underline': {
79
- markdownHandler(currentEditorRef, value);
80
- break;
81
- }
82
- case 'BulletList':
83
- case 'NumberList': {
84
- listHandler(currentEditorRef, value);
85
- togglePopover();
86
- break;
87
- }
88
- case 'h1':
89
- case 'h2':
90
- case 'h3':
91
- case 'h4':
92
- case 'h5':
93
- case 'h6': {
94
- titleHandler(currentEditorRef, value);
95
- break;
96
- }
97
- default: {
98
- // Nothing
99
- }
100
- }
101
- };
102
-
103
- const handleSelectAssets = (files) => {
104
- const formattedFiles = files.map((f) => ({
105
- alt: f.alternativeText || f.name,
106
- url: prefixFileUrlWithBackendUrl(f.url),
107
- mime: f.mime,
108
- }));
109
-
110
- insertFile(editorRef, formattedFiles);
111
- setMediaLibVisible(false);
112
- };
113
-
114
- const formattedPlaceholder = placeholder
115
- ? formatMessage(
116
- { id: placeholder.id, defaultMessage: placeholder.defaultMessage },
117
- { ...placeholder.values }
118
- )
119
- : '';
120
-
121
- const label = intlLabel.id
122
- ? formatMessage(
123
- { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
124
- { ...intlLabel.values }
125
- )
126
- : name;
127
-
128
- return (
129
- <>
130
- <Flex direction="column" alignItems="stretch" gap={1}>
131
- <Flex gap={1}>
132
- <Typography variant="pi" fontWeight="bold" textColor="neutral800">
133
- {label}
134
- {required && <TypographyAsterisk textColor="danger600">*</TypographyAsterisk>}
135
- </Typography>
136
- {labelAction && <LabelAction paddingLeft={1}>{labelAction}</LabelAction>}
137
- </Flex>
138
-
139
- <EditorLayout
140
- isExpandMode={isExpandMode}
141
- error={error}
142
- previewContent={value}
143
- onCollapse={handleToggleExpand}
144
- >
145
- <WysiwygNav
146
- isExpandMode={isExpandMode}
147
- editorRef={editorRef}
148
- isPreviewMode={isPreviewMode}
149
- onActionClick={handleActionClick}
150
- onToggleMediaLib={handleToggleMediaLib}
151
- onTogglePreviewMode={isExpandMode ? undefined : handleTogglePreviewMode}
152
- disabled={disabled}
153
- />
154
-
155
- <Editor
156
- disabled={disabled}
94
+ };
95
+
96
+ const handleSelectAssets = (files) => {
97
+ const formattedFiles = files.map((f) => ({
98
+ alt: f.alternativeText || f.name,
99
+ url: prefixFileUrlWithBackendUrl(f.url),
100
+ mime: f.mime,
101
+ }));
102
+
103
+ insertFile(editorRef, formattedFiles);
104
+ setMediaLibVisible(false);
105
+ };
106
+
107
+ const formattedPlaceholder = placeholder
108
+ ? formatMessage(
109
+ { id: placeholder.id, defaultMessage: placeholder.defaultMessage },
110
+ { ...placeholder.values }
111
+ )
112
+ : '';
113
+
114
+ const label = intlLabel.id
115
+ ? formatMessage(
116
+ { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
117
+ { ...intlLabel.values }
118
+ )
119
+ : name;
120
+
121
+ return (
122
+ <>
123
+ <Flex direction="column" alignItems="stretch" gap={1}>
124
+ <Flex gap={1}>
125
+ <Typography variant="pi" fontWeight="bold" textColor="neutral800">
126
+ {label}
127
+ {required && <TypographyAsterisk textColor="danger600">*</TypographyAsterisk>}
128
+ </Typography>
129
+ {labelAction && <LabelAction paddingLeft={1}>{labelAction}</LabelAction>}
130
+ </Flex>
131
+
132
+ <EditorLayout
157
133
  isExpandMode={isExpandMode}
158
- editorRef={editorRef}
159
134
  error={error}
160
- isPreviewMode={isPreviewMode}
161
- name={name}
162
- onChange={onChange}
163
- placeholder={formattedPlaceholder}
164
- textareaRef={textareaRef}
165
- value={value}
166
- />
167
-
168
- {!isExpandMode && <WysiwygFooter onToggleExpand={handleToggleExpand} />}
169
- </EditorLayout>
170
- <Hint hint={hint} name={name} error={error} />
171
- </Flex>
172
-
173
- {error && (
174
- <Box paddingTop={1}>
175
- <Typography variant="pi" textColor="danger600" data-strapi-field-error>
176
- {error}
177
- </Typography>
178
- </Box>
179
- )}
180
-
181
- {mediaLibVisible && (
182
- <MediaLibraryDialog onClose={handleToggleMediaLib} onSelectAssets={handleSelectAssets} />
183
- )}
184
- </>
185
- );
186
- };
135
+ previewContent={value}
136
+ onCollapse={handleToggleExpand}
137
+ >
138
+ <WysiwygNav
139
+ isExpandMode={isExpandMode}
140
+ editorRef={editorRef}
141
+ isPreviewMode={isPreviewMode}
142
+ onActionClick={handleActionClick}
143
+ onToggleMediaLib={handleToggleMediaLib}
144
+ onTogglePreviewMode={isExpandMode ? undefined : handleTogglePreviewMode}
145
+ disabled={disabled}
146
+ />
147
+
148
+ <Editor
149
+ disabled={disabled}
150
+ isExpandMode={isExpandMode}
151
+ editorRef={editorRef}
152
+ error={error}
153
+ isPreviewMode={isPreviewMode}
154
+ name={name}
155
+ onChange={onChange}
156
+ placeholder={formattedPlaceholder}
157
+ textareaRef={textareaRef}
158
+ value={value}
159
+ ref={forwardedRef}
160
+ />
161
+
162
+ {!isExpandMode && <WysiwygFooter onToggleExpand={handleToggleExpand} />}
163
+ </EditorLayout>
164
+ <Hint hint={hint} name={name} error={error} />
165
+ </Flex>
166
+
167
+ {error && (
168
+ <Box paddingTop={1}>
169
+ <Typography variant="pi" textColor="danger600" data-strapi-field-error>
170
+ {error}
171
+ </Typography>
172
+ </Box>
173
+ )}
174
+
175
+ {mediaLibVisible && (
176
+ <MediaLibraryDialog onClose={handleToggleMediaLib} onSelectAssets={handleSelectAssets} />
177
+ )}
178
+ </>
179
+ );
180
+ }
181
+ );
187
182
 
188
183
  Wysiwyg.defaultProps = {
189
184
  disabled: false,
@@ -0,0 +1,47 @@
1
+ import { useRBACProvider, findMatchingPermissions } from '@strapi/helper-plugin';
2
+
3
+ const NOT_ALLOWED_FILTERS = ['json', 'component', 'media', 'richtext', 'dynamiczone', 'password'];
4
+ const TIMESTAMPS = ['createdAt', 'updatedAt'];
5
+ const CREATOR_ATTRIBUTES = ['createdBy', 'updatedBy'];
6
+
7
+ export const useAllowedAttributes = (contentType, slug) => {
8
+ const { allPermissions } = useRBACProvider();
9
+
10
+ const readPermissionsForSlug = findMatchingPermissions(allPermissions, [
11
+ {
12
+ action: 'plugin::content-manager.explorer.read',
13
+ subject: slug,
14
+ },
15
+ ]);
16
+
17
+ const canReadAdminUsers =
18
+ findMatchingPermissions(allPermissions, [
19
+ {
20
+ action: 'admin::users.read',
21
+ subject: null,
22
+ },
23
+ ]).length > 0;
24
+
25
+ const attributesWithReadPermissions = readPermissionsForSlug?.[0]?.properties?.fields ?? [];
26
+
27
+ const allowedAttributes = attributesWithReadPermissions.filter((attr) => {
28
+ const current = contentType?.attributes?.[attr] ?? {};
29
+
30
+ if (!current.type) {
31
+ return false;
32
+ }
33
+
34
+ if (NOT_ALLOWED_FILTERS.includes(current.type)) {
35
+ return false;
36
+ }
37
+
38
+ return true;
39
+ });
40
+
41
+ return [
42
+ 'id',
43
+ ...allowedAttributes,
44
+ ...TIMESTAMPS,
45
+ ...(canReadAdminUsers ? CREATOR_ATTRIBUTES : []),
46
+ ];
47
+ };
@@ -61,7 +61,7 @@ function renderDraglayerItem({ type, item }) {
61
61
  }
62
62
  }
63
63
 
64
- export const ContentManger = () => {
64
+ const App = () => {
65
65
  const contentTypeMatch = useRouteMatch(`/content-manager/:kind/:uid`);
66
66
  const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } =
67
67
  useContentManagerInitData();
@@ -123,10 +123,6 @@ export const ContentManger = () => {
123
123
 
124
124
  return (
125
125
  <Layout sideNav={<LeftMenu />}>
126
- <Helmet
127
- title={formatMessage({ id: getTrad('plugin.name'), defaultMessage: 'Content Manager' })}
128
- />
129
-
130
126
  <DragLayer renderItem={renderDraglayerItem} />
131
127
  <ModelsContext.Provider value={{ refetchData }}>
132
128
  <Switch>
@@ -153,3 +149,18 @@ export const ContentManger = () => {
153
149
  </Layout>
154
150
  );
155
151
  };
152
+
153
+ export { App };
154
+
155
+ export default function () {
156
+ const { formatMessage } = useIntl();
157
+
158
+ return (
159
+ <>
160
+ <Helmet
161
+ title={formatMessage({ id: getTrad('plugin.name'), defaultMessage: 'Content Manager' })}
162
+ />
163
+ <App />
164
+ </>
165
+ );
166
+ }
@@ -5,8 +5,7 @@ import { useCMEditViewDataManager } from '@strapi/helper-plugin';
5
5
  import PropTypes from 'prop-types';
6
6
  import { useIntl } from 'react-intl';
7
7
 
8
- import { getFullName } from '../../../../utils/getFullName';
9
- import { getTrad } from '../../../utils';
8
+ import { getTrad, getDisplayName } from '../../../utils';
10
9
 
11
10
  import getUnits from './utils/getUnits';
12
11
 
@@ -42,9 +41,13 @@ const KeyValuePair = ({ label, value }) => {
42
41
  );
43
42
  };
44
43
 
44
+ KeyValuePair.defaultProps = {
45
+ value: '-',
46
+ };
47
+
45
48
  KeyValuePair.propTypes = {
46
49
  label: PropTypes.string.isRequired,
47
- value: PropTypes.string.isRequired,
50
+ value: PropTypes.string,
48
51
  };
49
52
 
50
53
  const Body = () => {
@@ -53,18 +56,16 @@ const Body = () => {
53
56
  const currentTime = useRef(Date.now());
54
57
 
55
58
  const getFieldInfo = (atField, byField) => {
56
- const { firstname, lastname, username } = initialData[byField] ?? {};
59
+ const user = initialData[byField] ?? {};
57
60
 
58
- const userFirstname = firstname ?? '';
59
- const userLastname = lastname ?? '';
60
- const user = username ?? getFullName(userFirstname, userLastname);
61
+ const displayName = getDisplayName(user, formatMessage);
61
62
  const timestamp = initialData[atField] ? new Date(initialData[atField]).getTime() : Date.now();
62
63
  const elapsed = timestamp - currentTime.current;
63
64
  const { unit, value } = getUnits(-elapsed);
64
65
 
65
66
  return {
66
67
  at: formatRelativeTime(value, unit, { numeric: 'auto' }),
67
- by: isCreatingEntry ? '-' : user,
68
+ by: isCreatingEntry ? '-' : displayName,
68
69
  };
69
70
  };
70
71
 
@@ -10,14 +10,41 @@ import {
10
10
  ToggleInput,
11
11
  Typography,
12
12
  } from '@strapi/design-system';
13
+ import { useCollator } from '@strapi/helper-plugin';
13
14
  import PropTypes from 'prop-types';
14
15
  import { useIntl } from 'react-intl';
15
16
 
17
+ import { useEnterprise } from '../../../../hooks/useEnterprise';
16
18
  import { getTrad } from '../../../utils';
17
19
 
18
- export const Settings = ({ modifiedData, onChange, sortOptions }) => {
19
- const { formatMessage } = useIntl();
20
- const { settings, metadatas } = modifiedData;
20
+ export const Settings = ({
21
+ contentTypeOptions,
22
+ modifiedData,
23
+ onChange,
24
+ sortOptions: sortOptionsCE,
25
+ }) => {
26
+ const { formatMessage, locale } = useIntl();
27
+ const formatter = useCollator(locale, {
28
+ sensitivity: 'base',
29
+ });
30
+ const sortOptions = useEnterprise(
31
+ sortOptionsCE,
32
+ async () =>
33
+ (await import('../../../../../../ee/admin/content-manager/pages/ListSettingsView/constants'))
34
+ .REVIEW_WORKFLOW_STAGE_SORT_OPTION_NAME,
35
+ {
36
+ combine(ceOptions, eeOption) {
37
+ return [...ceOptions, { ...eeOption, label: formatMessage(eeOption.label) }];
38
+ },
39
+
40
+ defaultValue: sortOptionsCE,
41
+
42
+ enabled: !!contentTypeOptions?.reviewWorkflows,
43
+ }
44
+ );
45
+
46
+ const sortOptionsSorted = sortOptions.sort((a, b) => formatter.compare(a.label, b.label));
47
+ const { settings } = modifiedData;
21
48
 
22
49
  return (
23
50
  <Flex direction="column" alignItems="stretch" gap={4}>
@@ -129,9 +156,9 @@ export const Settings = ({ modifiedData, onChange, sortOptions }) => {
129
156
  name="settings.defaultSortBy"
130
157
  value={modifiedData.settings.defaultSortBy || ''}
131
158
  >
132
- {sortOptions.map((sortBy) => (
133
- <Option key={sortBy} value={sortBy}>
134
- {metadatas[sortBy].list.label || sortBy}
159
+ {sortOptionsSorted.map(({ value, label }) => (
160
+ <Option key={value} value={value}>
161
+ {label}
135
162
  </Option>
136
163
  ))}
137
164
  </Select>
@@ -164,7 +191,13 @@ Settings.defaultProps = {
164
191
  };
165
192
 
166
193
  Settings.propTypes = {
194
+ contentTypeOptions: PropTypes.object.isRequired,
167
195
  modifiedData: PropTypes.object,
168
196
  onChange: PropTypes.func.isRequired,
169
- sortOptions: PropTypes.array,
197
+ sortOptions: PropTypes.arrayOf(
198
+ PropTypes.shape({
199
+ value: PropTypes.string,
200
+ label: PropTypes.string,
201
+ }).isRequired
202
+ ),
170
203
  };
@@ -47,7 +47,7 @@ export const ListSettingsView = ({ layout, slug }) => {
47
47
 
48
48
  const isModalFormOpen = Object.keys(fieldForm).length !== 0;
49
49
 
50
- const { attributes } = layout;
50
+ const { attributes, options } = layout;
51
51
  const displayedFields = modifiedData.layouts.list;
52
52
 
53
53
  const goBackUrl = () => {
@@ -169,7 +169,10 @@ export const ListSettingsView = ({ layout, slug }) => {
169
169
 
170
170
  const sortOptions = Object.entries(attributes)
171
171
  .filter(([, attribute]) => !EXCLUDED_SORT_ATTRIBUTE_TYPES.includes(attribute.type))
172
- .map(([name]) => name);
172
+ .map(([name]) => ({
173
+ value: name,
174
+ label: layout.metadatas[name].list.label,
175
+ }));
173
176
 
174
177
  const move = (originalIndex, atIndex) => {
175
178
  dispatch({
@@ -225,6 +228,7 @@ export const ListSettingsView = ({ layout, slug }) => {
225
228
  paddingRight={7}
226
229
  >
227
230
  <Settings
231
+ contentTypeOptions={options}
228
232
  modifiedData={modifiedData}
229
233
  onChange={handleChange}
230
234
  sortOptions={sortOptions}
@@ -32,7 +32,7 @@ import { useSelector } from 'react-redux';
32
32
  import { Link, useHistory } from 'react-router-dom';
33
33
  import styled from 'styled-components';
34
34
 
35
- import { formatAPIErrors } from '../../../../../../utils/formatAPIErrors';
35
+ import formatAPIError from '../../../../../../utils/formatAPIErrors';
36
36
  import { getTrad, createYupSchema } from '../../../../../utils';
37
37
  import { listViewDomain } from '../../../selectors';
38
38
  import { Body } from '../../Body';
@@ -301,7 +301,7 @@ const SelectedEntriesModalContent = ({
301
301
  onError(error) {
302
302
  toggleNotification({
303
303
  type: 'warning',
304
- message: formatAPIErrors(error),
304
+ message: formatAPIError(error),
305
305
  });
306
306
  },
307
307
  }