@strapi/admin 4.12.0 → 4.12.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 (190) hide show
  1. package/admin/src/components/LeftMenu/index.js +1 -1
  2. package/admin/src/components/PluginsInitializer/index.js +23 -0
  3. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +9 -14
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +1 -1
  5. package/admin/src/content-manager/components/InputUID/index.js +2 -3
  6. package/admin/src/content-manager/components/RelationInput/RelationInput.js +1 -1
  7. package/admin/src/content-manager/components/RelationInputDataManager/utils/getRelationLink.js +1 -3
  8. package/admin/src/content-manager/components/RelationInputDataManager/utils/select.js +4 -6
  9. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +7 -9
  10. package/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js +1 -3
  11. package/admin/src/content-manager/pages/EditSettingsView/index.js +31 -18
  12. package/admin/src/content-manager/pages/ListSettingsView/components/EditFieldForm.js +1 -3
  13. package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +1 -3
  14. package/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.js +14 -32
  15. package/admin/src/content-manager/pages/ListSettingsView/index.js +50 -40
  16. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +7 -2
  17. package/admin/src/content-manager/pages/ListView/components/CellContent/RelationMultiple/index.js +2 -2
  18. package/admin/src/content-manager/pages/ListView/index.js +10 -4
  19. package/admin/src/content-manager/sharedReducers/crudReducer/reducer.js +1 -1
  20. package/admin/src/content-manager/utils/checkIfAttributeIsDisplayable.js +2 -4
  21. package/admin/src/content-manager/utils/index.js +0 -1
  22. package/admin/src/hooks/index.js +0 -3
  23. package/admin/src/hooks/useAdminRolePermissions/__mocks__/index.js +5 -0
  24. package/admin/src/hooks/useAdminRolePermissions/index.js +34 -0
  25. package/admin/src/hooks/useAdminRoles/__mocks__/index.js +5 -0
  26. package/admin/src/hooks/useAdminRoles/index.js +40 -0
  27. package/admin/src/pages/AuthPage/components/Register/index.js +4 -0
  28. package/admin/src/pages/AuthPage/constants.js +2 -2
  29. package/admin/src/pages/InstalledPluginsPage/Plugins.js +2 -2
  30. package/admin/src/pages/InstalledPluginsPage/hooks/usePlugins/index.js +29 -0
  31. package/admin/src/pages/MarketplacePage/hooks/useFetchMarketplacePlugins/index.js +44 -0
  32. package/admin/src/pages/MarketplacePage/hooks/useFetchMarketplaceProviders/index.js +44 -0
  33. package/admin/src/pages/MarketplacePage/utils/useMarketplaceData.js +2 -2
  34. package/admin/src/pages/SettingsPage/pages/Roles/CreatePage/index.js +24 -9
  35. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/RoleForm/index.js +1 -0
  36. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +34 -20
  37. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +31 -84
  38. package/admin/src/pages/SettingsPage/pages/Roles/hooks/useAdminRolePermissionLayout/index.js +23 -0
  39. package/admin/src/translations/ar.json +9 -3
  40. package/admin/src/translations/ca.json +8 -2
  41. package/admin/src/translations/de.json +8 -2
  42. package/admin/src/translations/dk.json +8 -2
  43. package/admin/src/translations/en.json +9 -3
  44. package/admin/src/translations/es.json +9 -3
  45. package/admin/src/translations/eu.json +8 -2
  46. package/admin/src/translations/fr.json +9 -2
  47. package/admin/src/translations/gu.json +8 -2
  48. package/admin/src/translations/hi.json +9 -3
  49. package/admin/src/translations/hu.json +9 -3
  50. package/admin/src/translations/ja.json +12 -6
  51. package/admin/src/translations/ko.json +12 -6
  52. package/admin/src/translations/ml.json +8 -2
  53. package/admin/src/translations/nl.json +8 -2
  54. package/admin/src/translations/pl.json +8 -2
  55. package/admin/src/translations/pt-BR.json +8 -2
  56. package/admin/src/translations/ru.json +8 -2
  57. package/admin/src/translations/sa.json +9 -3
  58. package/admin/src/translations/sk.json +8 -2
  59. package/admin/src/translations/sv.json +7 -2
  60. package/admin/src/translations/tr.json +8 -2
  61. package/admin/src/translations/zh-Hans.json +8 -2
  62. package/admin/src/translations/zh.json +8 -2
  63. package/admin/src/utils/index.js +0 -1
  64. package/build/1049.f76cb14b.chunk.js +1 -0
  65. package/build/1386.879bcd90.chunk.js +7 -0
  66. package/build/{2225.15d1df72.chunk.js → 2225.c6244756.chunk.js} +1 -1
  67. package/build/2379.f1641312.chunk.js +1 -0
  68. package/build/2395.46f8d0c1.chunk.js +26 -0
  69. package/build/2801.5cef5ec8.chunk.js +1 -0
  70. package/build/{3483.e2ee2547.chunk.js → 3483.03c24f96.chunk.js} +1 -1
  71. package/build/3929.5632f24d.chunk.js +114 -0
  72. package/build/4546.cfafae68.chunk.js +1 -0
  73. package/build/6691.4985ef22.chunk.js +105 -0
  74. package/build/7464.3e64a1d5.chunk.js +1 -0
  75. package/build/8276.10a3f883.chunk.js +26 -0
  76. package/build/{9806.aa25371d.chunk.js → 9806.3392505e.chunk.js} +2 -2
  77. package/build/{Admin-authenticatedApp.376233ff.chunk.js → Admin-authenticatedApp.3c585a0d.chunk.js} +3 -3
  78. package/build/{Admin_marketplace.f0b87fce.chunk.js → Admin_marketplace.dde9c148.chunk.js} +6 -6
  79. package/build/Admin_pluginsPage.bbe79434.chunk.js +6 -0
  80. package/build/{Admin_profilePage.a968035f.chunk.js → Admin_profilePage.192edc52.chunk.js} +1 -1
  81. package/build/{Admin_settingsPage.8c600d1a.chunk.js → Admin_settingsPage.97cb9d41.chunk.js} +1 -1
  82. package/build/admin-app.91898385.chunk.js +36 -0
  83. package/build/admin-edit-roles-page.6d567273.chunk.js +267 -0
  84. package/build/{admin-edit-users.67704088.chunk.js → admin-edit-users.79eeb125.chunk.js} +1 -1
  85. package/build/admin-roles-list.23ddff26.chunk.js +22 -0
  86. package/build/{admin-users.3279ffb0.chunk.js → admin-users.123aa08e.chunk.js} +1 -1
  87. package/build/ar-json.74e40bc7.chunk.js +1 -0
  88. package/build/{ca-json.a53c10b6.chunk.js → ca-json.fc6001d3.chunk.js} +1 -1
  89. package/build/content-manager.2af15f57.chunk.js +1099 -0
  90. package/build/{de-json.b3be02c7.chunk.js → de-json.e72545cf.chunk.js} +1 -1
  91. package/build/dk-json.e77140ef.chunk.js +1 -0
  92. package/build/{en-json.e34140fc.chunk.js → en-json.08c05fcf.chunk.js} +1 -1
  93. package/build/es-json.b1f2284b.chunk.js +1 -0
  94. package/build/{eu-json.633025f0.chunk.js → eu-json.63d0a898.chunk.js} +1 -1
  95. package/build/{fr-json.aa8839d2.chunk.js → fr-json.33c6428b.chunk.js} +1 -1
  96. package/build/{gu-json.5bd62812.chunk.js → gu-json.7efe8cc2.chunk.js} +1 -1
  97. package/build/{hi-json.9104eb78.chunk.js → hi-json.0d633692.chunk.js} +1 -1
  98. package/build/{hu-json.9f4aae42.chunk.js → hu-json.c74b6a1e.chunk.js} +1 -1
  99. package/build/index.html +1 -1
  100. package/build/{ja-json.91286391.chunk.js → ja-json.e1959a1c.chunk.js} +1 -1
  101. package/build/{ko-json.fcf3ec4b.chunk.js → ko-json.ce5d6d94.chunk.js} +1 -1
  102. package/build/main.f13fc96c.js +2856 -0
  103. package/build/{ml-json.557aa14c.chunk.js → ml-json.940d7ace.chunk.js} +1 -1
  104. package/build/{nl-json.b2b16eea.chunk.js → nl-json.fe38f0fb.chunk.js} +1 -1
  105. package/build/{pl-json.f094a417.chunk.js → pl-json.d55e8e78.chunk.js} +1 -1
  106. package/build/{pt-BR-json.dec7fb01.chunk.js → pt-BR-json.ae0a0d2e.chunk.js} +1 -1
  107. package/build/review-workflows-settings-create-view.cb08cfa2.chunk.js +1 -0
  108. package/build/review-workflows-settings-edit-view.3c7cbe63.chunk.js +1 -0
  109. package/build/review-workflows-settings-list-view.1611dc1f.chunk.js +56 -0
  110. package/build/{ru-json.8193d8c4.chunk.js → ru-json.1c976644.chunk.js} +1 -1
  111. package/build/{runtime~main.58ec8df6.js → runtime~main.2902859a.js} +1 -1
  112. package/build/{sa-json.a56836f1.chunk.js → sa-json.2c03ef4e.chunk.js} +1 -1
  113. package/build/sk-json.b41847e8.chunk.js +1 -0
  114. package/build/sso-settings-page.12b6d8ae.chunk.js +1 -0
  115. package/build/{sv-json.fd0e86c6.chunk.js → sv-json.568cb7ae.chunk.js} +1 -1
  116. package/build/{tr-json.56c32cf6.chunk.js → tr-json.c9f22432.chunk.js} +1 -1
  117. package/build/upload-settings.7f93d4c0.chunk.js +14 -0
  118. package/build/upload.37488080.chunk.js +58 -0
  119. package/build/users-advanced-settings-page.f0760eb8.chunk.js +9 -0
  120. package/build/users-email-settings-page.ff4b32f3.chunk.js +9 -0
  121. package/build/users-providers-settings-page.48de0306.chunk.js +14 -0
  122. package/build/users-roles-settings-page.3f9f063e.chunk.js +30 -0
  123. package/build/{zh-Hans-json.36d81cdc.chunk.js → zh-Hans-json.937b395b.chunk.js} +1 -1
  124. package/build/{zh-json.1cc86ff0.chunk.js → zh-json.bfc2e036.chunk.js} +1 -1
  125. package/ee/admin/hooks/useAuthProviders/index.js +1 -3
  126. package/ee/admin/pages/AuthResponse/index.js +1 -3
  127. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +35 -32
  128. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/CreateView.js +1 -7
  129. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/EditView.js +16 -14
  130. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/ListView.js +32 -31
  131. package/ee/admin/pages/SettingsPage/pages/SingleSignOn/index.js +16 -26
  132. package/ee/server/config/admin-actions.js +6 -6
  133. package/ee/server/services/review-workflows/entity-service-decorator.js +4 -3
  134. package/index.js +2 -0
  135. package/package.json +16 -16
  136. package/scripts/build.js +1 -0
  137. package/server/controllers/role.js +9 -1
  138. package/server/middlewares/rateLimit.js +6 -2
  139. package/server/services/role.js +3 -2
  140. package/server/services/transfer/token.js +27 -4
  141. package/server/validation/authentication/register.js +2 -2
  142. package/webpack.config.js +2 -1
  143. package/admin/src/content-manager/components/SingleTypeFormWrapper/utils/getRequestUrl.js +0 -5
  144. package/admin/src/content-manager/components/SingleTypeFormWrapper/utils/index.js +0 -2
  145. package/admin/src/content-manager/pages/EditSettingsView/utils/api.js +0 -16
  146. package/admin/src/content-manager/pages/ListSettingsView/init.js +0 -9
  147. package/admin/src/content-manager/utils/getRequestUrl.js +0 -4
  148. package/admin/src/hooks/marketplace/useFetchMarketplacePlugins/index.js +0 -44
  149. package/admin/src/hooks/marketplace/useFetchMarketplaceProviders/index.js +0 -44
  150. package/admin/src/hooks/useFetchEnabledPlugins/index.js +0 -24
  151. package/admin/src/hooks/useFetchEnabledPlugins/utils/api.js +0 -10
  152. package/admin/src/hooks/useFetchPermissionsLayout/index.js +0 -42
  153. package/admin/src/hooks/useFetchPermissionsLayout/reducer.js +0 -35
  154. package/admin/src/hooks/useFetchRole/index.js +0 -68
  155. package/admin/src/hooks/useFetchRole/reducer.js +0 -33
  156. package/admin/src/hooks/useRolesList/index.js +0 -58
  157. package/admin/src/hooks/useRolesList/init.js +0 -5
  158. package/admin/src/hooks/useRolesList/reducer.js +0 -31
  159. package/admin/src/utils/getRequestUrl.js +0 -3
  160. package/build/1049.758a01f5.chunk.js +0 -1
  161. package/build/1386.762d6eb8.chunk.js +0 -7
  162. package/build/2379.0ca87a89.chunk.js +0 -1
  163. package/build/2395.df7a044a.chunk.js +0 -26
  164. package/build/2801.b1140c9b.chunk.js +0 -1
  165. package/build/4546.ff9fdf30.chunk.js +0 -1
  166. package/build/6691.f880a0b6.chunk.js +0 -105
  167. package/build/7065.ec811562.chunk.js +0 -114
  168. package/build/7464.8a6c1e6c.chunk.js +0 -1
  169. package/build/8276.6c7b8e6e.chunk.js +0 -26
  170. package/build/Admin_pluginsPage.8728ff6e.chunk.js +0 -6
  171. package/build/admin-app.1c3f7fd6.chunk.js +0 -36
  172. package/build/admin-edit-roles-page.a49b9f4f.chunk.js +0 -267
  173. package/build/admin-roles-list.0c129e98.chunk.js +0 -23
  174. package/build/ar-json.f530bc3f.chunk.js +0 -1
  175. package/build/content-manager.e9205db1.chunk.js +0 -1103
  176. package/build/dk-json.842aa391.chunk.js +0 -1
  177. package/build/es-json.f57b5335.chunk.js +0 -1
  178. package/build/main.1e3b0985.js +0 -2856
  179. package/build/review-workflows-settings-create-view.05758184.chunk.js +0 -1
  180. package/build/review-workflows-settings-edit-view.c33f7c58.chunk.js +0 -1
  181. package/build/review-workflows-settings-list-view.f055e1be.chunk.js +0 -56
  182. package/build/sk-json.bf2f057a.chunk.js +0 -1
  183. package/build/sso-settings-page.7c9b2fd9.chunk.js +0 -1
  184. package/build/upload-settings.cac210a0.chunk.js +0 -14
  185. package/build/upload.cbfeefa5.chunk.js +0 -58
  186. package/build/users-advanced-settings-page.18379a56.chunk.js +0 -9
  187. package/build/users-email-settings-page.a87978e5.chunk.js +0 -9
  188. package/build/users-providers-settings-page.8876c1ee.chunk.js +0 -14
  189. package/build/users-roles-settings-page.0431f48c.chunk.js +0 -30
  190. /package/admin/src/{hooks/marketplace → pages/MarketplacePage}/constants.js +0 -0
@@ -1,10 +1,10 @@
1
- import React, { memo, useContext, useReducer, useState } from 'react';
1
+ import React, { useContext, useReducer, useState } from 'react';
2
2
 
3
3
  import {
4
- Box,
5
4
  Button,
6
5
  ContentLayout,
7
6
  Divider,
7
+ Flex,
8
8
  HeaderLayout,
9
9
  Layout,
10
10
  Main,
@@ -17,10 +17,7 @@ import {
17
17
  useTracking,
18
18
  } from '@strapi/helper-plugin';
19
19
  import { ArrowLeft, Check } from '@strapi/icons';
20
- import get from 'lodash/get';
21
- import isEmpty from 'lodash/isEmpty';
22
20
  import isEqual from 'lodash/isEqual';
23
- import pick from 'lodash/pick';
24
21
  import upperFirst from 'lodash/upperFirst';
25
22
  import PropTypes from 'prop-types';
26
23
  import { stringify } from 'qs';
@@ -31,11 +28,10 @@ import ModelsContext from '../../contexts/ModelsContext';
31
28
  import { usePluginsQueryParams } from '../../hooks';
32
29
  import { checkIfAttributeIsDisplayable, getTrad } from '../../utils';
33
30
 
34
- import EditFieldForm from './components/EditFieldForm';
35
- import Settings from './components/Settings';
36
- import SortDisplayedFields from './components/SortDisplayedFields';
31
+ import { EditFieldForm } from './components/EditFieldForm';
32
+ import { Settings } from './components/Settings';
33
+ import { SortDisplayedFields } from './components/SortDisplayedFields';
37
34
  import { EXCLUDED_SORT_ATTRIBUTE_TYPES } from './constants';
38
- import init from './init';
39
35
  import reducer, { initialState } from './reducer';
40
36
 
41
37
  const ListSettingsView = ({ layout, slug }) => {
@@ -45,14 +41,19 @@ const ListSettingsView = ({ layout, slug }) => {
45
41
  const pluginsQueryParams = usePluginsQueryParams();
46
42
  const toggleNotification = useNotification();
47
43
  const { refetchData } = useContext(ModelsContext);
48
-
49
44
  const [showWarningSubmit, setWarningSubmit] = useState(false);
50
45
  const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
51
- const [reducerState, dispatch] = useReducer(reducer, initialState, () =>
52
- init(initialState, layout)
46
+ const [{ fieldToEdit, fieldForm, initialData, modifiedData }, dispatch] = useReducer(
47
+ reducer,
48
+ initialState,
49
+ () => ({
50
+ ...initialState,
51
+ initialData: layout,
52
+ modifiedData: layout,
53
+ })
53
54
  );
54
- const { fieldToEdit, fieldForm, initialData, modifiedData } = reducerState;
55
- const isModalFormOpen = !isEmpty(fieldForm);
55
+
56
+ const isModalFormOpen = Object.keys(fieldForm).length !== 0;
56
57
 
57
58
  const { attributes } = layout;
58
59
  const displayedFields = modifiedData.layouts.list;
@@ -84,9 +85,30 @@ const ListSettingsView = ({ layout, slug }) => {
84
85
  });
85
86
  };
86
87
 
88
+ const { isLoading: isSubmittingForm, mutate } = useMutation(
89
+ (body) => put(`/content-manager/content-types/${slug}/configuration`, body),
90
+ {
91
+ onSuccess() {
92
+ trackUsage('didEditListSettings');
93
+ refetchData();
94
+ },
95
+ onError() {
96
+ toggleNotification({
97
+ type: 'warning',
98
+ message: { id: 'notification.error' },
99
+ });
100
+ },
101
+ }
102
+ );
103
+
87
104
  const handleConfirm = async () => {
88
- const body = pick(modifiedData, ['layouts', 'settings', 'metadatas']);
89
- submitMutation.mutate(body);
105
+ const { layouts, settings, metadatas } = modifiedData;
106
+
107
+ mutate({
108
+ layouts,
109
+ settings,
110
+ metadatas,
111
+ });
90
112
  };
91
113
 
92
114
  const handleAddField = (item) => {
@@ -139,23 +161,6 @@ const ListSettingsView = ({ layout, slug }) => {
139
161
  handleCloseModal();
140
162
  };
141
163
 
142
- const submitMutation = useMutation(
143
- (body) => put(`/content-manager/content-types/${slug}/configuration`, body),
144
- {
145
- onSuccess() {
146
- trackUsage('didEditListSettings');
147
- refetchData();
148
- },
149
- onError() {
150
- toggleNotification({
151
- type: 'warning',
152
- message: { id: 'notification.error' },
153
- });
154
- },
155
- }
156
- );
157
- const { isLoading: isSubmittingForm } = submitMutation;
158
-
159
164
  const handleChangeEditLabel = ({ target: { name, value } }) => {
160
165
  dispatch({
161
166
  type: 'ON_CHANGE_FIELD_METAS',
@@ -217,8 +222,11 @@ const ListSettingsView = ({ layout, slug }) => {
217
222
  )}
218
223
  />
219
224
  <ContentLayout>
220
- <Box
225
+ <Flex
226
+ alignItems="stretch"
221
227
  background="neutral0"
228
+ direction="column"
229
+ gap={6}
222
230
  hasRadius
223
231
  shadow="tableShadow"
224
232
  paddingTop={6}
@@ -231,9 +239,9 @@ const ListSettingsView = ({ layout, slug }) => {
231
239
  onChange={handleChange}
232
240
  sortOptions={sortOptions}
233
241
  />
234
- <Box paddingTop={6} paddingBottom={6}>
235
- <Divider />
236
- </Box>
242
+
243
+ <Divider />
244
+
237
245
  <SortDisplayedFields
238
246
  listRemainingFields={listRemainingFields}
239
247
  displayedFields={displayedFields}
@@ -243,8 +251,9 @@ const ListSettingsView = ({ layout, slug }) => {
243
251
  onRemoveField={handleRemoveField}
244
252
  metadatas={modifiedData.metadatas}
245
253
  />
246
- </Box>
254
+ </Flex>
247
255
  </ContentLayout>
256
+
248
257
  <ConfirmDialog
249
258
  bodyText={{
250
259
  id: getTrad('popUpWarning.warning.updateAllSettings'),
@@ -258,6 +267,7 @@ const ListSettingsView = ({ layout, slug }) => {
258
267
  variantRightButton="success-light"
259
268
  />
260
269
  </form>
270
+
261
271
  {isModalFormOpen && (
262
272
  <EditFieldForm
263
273
  attributes={attributes}
@@ -266,7 +276,7 @@ const ListSettingsView = ({ layout, slug }) => {
266
276
  onChangeEditLabel={handleChangeEditLabel}
267
277
  onCloseModal={handleCloseModal}
268
278
  onSubmit={handleSubmitFieldEdit}
269
- type={get(attributes, [fieldToEdit, 'type'], 'text')}
279
+ type={attributes?.[fieldToEdit]?.type ?? 'text'}
270
280
  />
271
281
  )}
272
282
  </Main>
@@ -296,4 +306,4 @@ ListSettingsView.propTypes = {
296
306
  slug: PropTypes.string.isRequired,
297
307
  };
298
308
 
299
- export default memo(ListSettingsView);
309
+ export default ListSettingsView;
@@ -261,7 +261,11 @@ const SelectedEntriesModalContent = ({
261
261
  const selectedEntriesWithErrorsCount = rowsToDisplay.filter(
262
262
  ({ id }) => selectedEntries.includes(id) && validationErrors[id]
263
263
  ).length;
264
- const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount;
264
+ const selectedEntriesPublished = rowsToDisplay.filter(
265
+ ({ id, publishedAt }) => selectedEntries.includes(id) && publishedAt
266
+ ).length;
267
+ const selectedEntriesWithNoErrorsCount =
268
+ selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
265
269
 
266
270
  const bulkPublishMutation = useMutation(
267
271
  (data) =>
@@ -331,11 +335,12 @@ const SelectedEntriesModalContent = ({
331
335
  {
332
336
  id: getTrad('containers.ListPage.selectedEntriesModal.selectedCount'),
333
337
  defaultMessage:
334
- '<b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action.',
338
+ '<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action.',
335
339
  },
336
340
  {
337
341
  readyToPublishCount: selectedEntriesWithNoErrorsCount,
338
342
  withErrorsCount: selectedEntriesWithErrorsCount,
343
+ alreadyPublishedCount: selectedEntriesPublished,
339
344
  b: BoldChunk,
340
345
  }
341
346
  );
@@ -8,7 +8,7 @@ import { useIntl } from 'react-intl';
8
8
  import { useQuery } from 'react-query';
9
9
  import styled from 'styled-components';
10
10
 
11
- import { getRequestUrl, getTrad } from '../../../../../utils';
11
+ import { getTrad } from '../../../../../utils';
12
12
  import CellValue from '../CellValue';
13
13
 
14
14
  const RelationMultiple = ({ fieldSchema, metadatas, name, entityId, value, contentType }) => {
@@ -24,7 +24,7 @@ const RelationMultiple = ({ fieldSchema, metadatas, name, entityId, value, conte
24
24
  const {
25
25
  data: { results, pagination },
26
26
  } = await get(
27
- getRequestUrl(`relations/${contentType.uid}/${entityId}/${name.split('.')[0]}`)
27
+ `/content-manager/relations/${contentType.uid}/${entityId}/${name.split('.')[0]}`
28
28
  );
29
29
 
30
30
  return { results, pagination };
@@ -50,7 +50,7 @@ import { useEnterprise } from '../../../hooks/useEnterprise';
50
50
  import { selectAdminPermissions } from '../../../pages/App/selectors';
51
51
  import { InjectionZone } from '../../../shared/components';
52
52
  import AttributeFilter from '../../components/AttributeFilter';
53
- import { getRequestUrl, getTrad } from '../../utils';
53
+ import { getTrad } from '../../utils';
54
54
 
55
55
  import { getData, getDataSucceeded, onChangeListHeaders, onResetListHeaders } from './actions';
56
56
  import { Body } from './components/Body';
@@ -247,7 +247,7 @@ function ListView({
247
247
  try {
248
248
  await del(`/content-manager/collection-types/${slug}/${idToDelete}`);
249
249
 
250
- const requestUrl = getRequestUrl(`collection-types/${slug}`);
250
+ const requestUrl = `/content-manager/collection-types/${slug}`;
251
251
  fetchData(requestUrl, { params });
252
252
 
253
253
  toggleNotification({
@@ -273,7 +273,7 @@ function ListView({
273
273
  const source = CancelToken.source();
274
274
 
275
275
  const shouldSendRequest = canRead;
276
- const requestUrl = getRequestUrl(`collection-types/${slug}`);
276
+ const requestUrl = `/content-manager/collection-types/${slug}`;
277
277
 
278
278
  if (shouldSendRequest && requestUrl.includes(requestUrlRef.current)) {
279
279
  fetchData(requestUrl, { cancelToken: source.token, params });
@@ -575,7 +575,7 @@ function ListView({
575
575
  {/* Bulk action row checkbox */}
576
576
  <Body.CheckboxDataCell rowId={rowData.id} index={index} />
577
577
  {/* Field data */}
578
- {tableHeaders.map(({ key, name, ...rest }) => {
578
+ {tableHeaders.map(({ key, name, cellFormatter, ...rest }) => {
579
579
  if (hasDraftAndPublish && name === 'publishedAt') {
580
580
  return (
581
581
  <Td key={key}>
@@ -622,6 +622,12 @@ function ListView({
622
622
  );
623
623
  }
624
624
 
625
+ if (typeof cellFormatter === 'function') {
626
+ return (
627
+ <Td key={key}>{cellFormatter(rowData, { key, name, ...rest })}</Td>
628
+ );
629
+ }
630
+
625
631
  return (
626
632
  <Td key={key}>
627
633
  <CellContent
@@ -4,7 +4,7 @@ import produce from 'immer';
4
4
  // NOTE: instead of creating a shared reducer here, we could also create a hook
5
5
  // that returns the dispatch and the state, however it will mess with the linter
6
6
  // and force us to either disable the linter for the hooks dependencies array rule or
7
- // require us to add the dispatch to the array wich is not wanted. This refacto does not require us to
7
+ // require us to add the dispatch to the array which is not wanted. This refacto does not require us to
8
8
  // to do any of this.
9
9
  import {
10
10
  CLEAR_SET_MODIFIED_DATA_ONLY,
@@ -1,10 +1,8 @@
1
- import toLower from 'lodash/toLower';
2
-
3
1
  const checkIfAttributeIsDisplayable = (attribute) => {
4
- const type = attribute.type;
2
+ const { type } = attribute;
5
3
 
6
4
  if (type === 'relation') {
7
- return !toLower(attribute.relationType).includes('morph');
5
+ return !(attribute?.relationType ?? '').toLowerCase().includes('morph');
8
6
  }
9
7
 
10
8
  return !['json', 'dynamiczone', 'richtext', 'password'].includes(type) && !!type;
@@ -6,7 +6,6 @@ export { default as formatLayoutToApi } from './formatLayoutToApi';
6
6
  export { default as generatePermissionsObject } from './generatePermissionsObject';
7
7
  export { default as getFieldName } from './getFieldName';
8
8
  export { default as getMaxTempKey } from './getMaxTempKey';
9
- export { default as getRequestUrl } from './getRequestUrl';
10
9
  export { default as getTrad } from './getTrad';
11
10
  export { default as ItemTypes } from './ItemTypes';
12
11
  export { default as mergeMetasWithSchema } from './mergeMetasWithSchema';
@@ -1,13 +1,10 @@
1
1
  export { default as useConfigurations } from './useConfigurations';
2
2
  export { useContentTypes } from './useContentTypes';
3
- export { default as useFetchPermissionsLayout } from './useFetchPermissionsLayout';
4
- export { default as useFetchRole } from './useFetchRole';
5
3
  export { default as useLicenseLimitNotification } from './useLicenseLimitNotification';
6
4
  export { default as useMenu } from './useMenu';
7
5
  export { default as usePermissionsDataManager } from './usePermissionsDataManager';
8
6
  export { default as useRegenerate } from './useRegenerate';
9
7
  export { default as useReleaseNotification } from './useReleaseNotification';
10
- export { default as useRolesList } from './useRolesList';
11
8
  export { default as useSettingsForm } from './useSettingsForm';
12
9
  export { default as useSettingsMenu } from './useSettingsMenu';
13
10
  export { default as useThemeToggle } from './useThemeToggle';
@@ -0,0 +1,5 @@
1
+ export const useAdminRolePermissions = jest.fn().mockReturnValue({
2
+ permissions: [],
3
+ isLoading: false,
4
+ isError: false,
5
+ });
@@ -0,0 +1,34 @@
1
+ import { useFetchClient } from '@strapi/helper-plugin';
2
+ import { useQuery } from 'react-query';
3
+
4
+ export const useAdminRolePermissions = (params = {}, queryOptions = {}) => {
5
+ const { id, ...queryParams } = params;
6
+
7
+ const { get } = useFetchClient();
8
+
9
+ if (!id && (queryOptions?.enabled === undefined || !!queryOptions?.enabled === true)) {
10
+ throw new Error('"id" is a required argument');
11
+ }
12
+
13
+ const {
14
+ data: permissions,
15
+ error,
16
+ isError,
17
+ isLoading,
18
+ refetch,
19
+ } = useQuery(
20
+ ['roles', id, 'permissions', queryParams],
21
+ async () => {
22
+ const {
23
+ data: { data },
24
+ } = await get(`/admin/roles/${id}/permissions`, {
25
+ params: queryParams,
26
+ });
27
+
28
+ return data;
29
+ },
30
+ queryOptions
31
+ );
32
+
33
+ return { permissions, error, isError, isLoading, refetch };
34
+ };
@@ -0,0 +1,5 @@
1
+ export const useAdminRoles = jest.fn().mockReturnValue({
2
+ roles: [],
3
+ isLoading: false,
4
+ isError: false,
5
+ });
@@ -0,0 +1,40 @@
1
+ import { useCollator, useFetchClient } from '@strapi/helper-plugin';
2
+ import { useIntl } from 'react-intl';
3
+ import { useQuery } from 'react-query';
4
+
5
+ export const useAdminRoles = (params = {}, queryOptions = {}) => {
6
+ const { id = '', ...queryParams } = params;
7
+
8
+ const { get } = useFetchClient();
9
+ const { locale } = useIntl();
10
+ const formatter = useCollator(locale, {
11
+ sensitivity: 'base',
12
+ });
13
+ const { data, error, isError, isLoading, refetch } = useQuery(
14
+ ['roles', id, queryParams],
15
+ async () => {
16
+ const { data } = await get(`/admin/roles/${id ?? ''}`, {
17
+ params: queryParams,
18
+ });
19
+
20
+ return data;
21
+ },
22
+ queryOptions
23
+ );
24
+
25
+ let roles = [];
26
+
27
+ if (id && data) {
28
+ roles = [data.data];
29
+ } else if (Array.isArray(data?.data)) {
30
+ roles = data.data;
31
+ }
32
+
33
+ return {
34
+ roles: roles.sort((a, b) => formatter.compare(a.name, b.name)),
35
+ error,
36
+ isError,
37
+ isLoading,
38
+ refetch,
39
+ };
40
+ };
@@ -98,6 +98,10 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
98
98
 
99
99
  if (!['password', 'confirmPassword'].includes(key) && typeof value === 'string') {
100
100
  normalizedvalue = normalizedvalue.trim();
101
+
102
+ if (key === 'lastname') {
103
+ normalizedvalue = normalizedvalue || null;
104
+ }
101
105
  }
102
106
 
103
107
  acc[key] = normalizedvalue;
@@ -55,7 +55,7 @@ export const FORMS = {
55
55
  fieldsToOmit: ['userInfo.confirmPassword', 'userInfo.news', 'userInfo.email'],
56
56
  schema: yup.object().shape({
57
57
  firstname: yup.string().trim().required(translatedErrors.required),
58
- lastname: yup.string(),
58
+ lastname: yup.string().nullable(),
59
59
  password: yup
60
60
  .string()
61
61
  .min(8, translatedErrors.minLength)
@@ -79,7 +79,7 @@ export const FORMS = {
79
79
  fieldsToOmit: ['confirmPassword', 'news'],
80
80
  schema: yup.object().shape({
81
81
  firstname: yup.string().trim().required(translatedErrors.required),
82
- lastname: yup.string(),
82
+ lastname: yup.string().nullable(),
83
83
  password: yup
84
84
  .string()
85
85
  .min(8, translatedErrors.minLength)
@@ -17,7 +17,7 @@ import {
17
17
  import { LoadingIndicatorPage, useFocusWhenNavigate } from '@strapi/helper-plugin';
18
18
  import { useIntl } from 'react-intl';
19
19
 
20
- import useFetchEnabledPlugins from '../../hooks/useFetchEnabledPlugins';
20
+ import { usePlugins } from './hooks/usePlugins';
21
21
 
22
22
  const Plugins = () => {
23
23
  const { formatMessage } = useIntl();
@@ -41,7 +41,7 @@ const Plugins = () => {
41
41
  );
42
42
  };
43
43
 
44
- const { status, data } = useFetchEnabledPlugins(notifyPluginPageLoad);
44
+ const { status, data } = usePlugins(notifyPluginPageLoad);
45
45
 
46
46
  const isLoading = status !== 'success' && status !== 'error';
47
47
 
@@ -0,0 +1,29 @@
1
+ import { useFetchClient, useNotification } from '@strapi/helper-plugin';
2
+ import { useQuery } from 'react-query';
3
+
4
+ export const usePlugins = (notifyLoad) => {
5
+ const toggleNotification = useNotification();
6
+ const { get } = useFetchClient();
7
+
8
+ return useQuery(
9
+ ['plugins'],
10
+ async () => {
11
+ const { data } = await get('/admin/plugins');
12
+
13
+ return data;
14
+ },
15
+ {
16
+ onSuccess() {
17
+ if (notifyLoad) {
18
+ notifyLoad();
19
+ }
20
+ },
21
+ onError() {
22
+ toggleNotification({
23
+ type: 'warning',
24
+ message: { id: 'notification.error', defaultMessage: 'An error occured' },
25
+ });
26
+ },
27
+ }
28
+ );
29
+ };
@@ -0,0 +1,44 @@
1
+ import { useNotification } from '@strapi/helper-plugin';
2
+ import qs from 'qs';
3
+ import { useQuery } from 'react-query';
4
+
5
+ import { MARKETPLACE_API_URL } from '../../constants';
6
+
7
+ export const useFetchMarketplacePlugins = (notifyLoad, params = {}) => {
8
+ const toggleNotification = useNotification();
9
+
10
+ return useQuery(
11
+ ['marketplace', 'plugins', params],
12
+ async () => {
13
+ try {
14
+ const queryString = qs.stringify(qs.parse(params));
15
+ const res = await fetch(`${MARKETPLACE_API_URL}/plugins?${queryString}`);
16
+
17
+ if (!res.ok) {
18
+ throw new Error('Failed to fetch marketplace plugins.');
19
+ }
20
+
21
+ const data = await res.json();
22
+
23
+ return data;
24
+ } catch (error) {
25
+ // silence
26
+ }
27
+
28
+ return null;
29
+ },
30
+ {
31
+ onSuccess() {
32
+ if (notifyLoad) {
33
+ notifyLoad();
34
+ }
35
+ },
36
+ onError() {
37
+ toggleNotification({
38
+ type: 'warning',
39
+ message: { id: 'notification.error', defaultMessage: 'An error occured' },
40
+ });
41
+ },
42
+ }
43
+ );
44
+ };
@@ -0,0 +1,44 @@
1
+ import { useNotification } from '@strapi/helper-plugin';
2
+ import qs from 'qs';
3
+ import { useQuery } from 'react-query';
4
+
5
+ import { MARKETPLACE_API_URL } from '../../constants';
6
+
7
+ export const useFetchMarketplaceProviders = (notifyLoad, params = {}) => {
8
+ const toggleNotification = useNotification();
9
+
10
+ return useQuery(
11
+ ['marketplace', 'providers', params],
12
+ async () => {
13
+ try {
14
+ const queryString = qs.stringify(qs.parse(params));
15
+ const res = await fetch(`${MARKETPLACE_API_URL}/providers?${queryString}`);
16
+
17
+ if (!res.ok) {
18
+ throw new Error('Failed to fetch marketplace providers.');
19
+ }
20
+
21
+ const data = await res.json();
22
+
23
+ return data;
24
+ } catch (error) {
25
+ // silence
26
+ }
27
+
28
+ return null;
29
+ },
30
+ {
31
+ onSuccess() {
32
+ if (notifyLoad) {
33
+ notifyLoad();
34
+ }
35
+ },
36
+ onError() {
37
+ toggleNotification({
38
+ type: 'warning',
39
+ message: { id: 'notification.error', defaultMessage: 'An error occured' },
40
+ });
41
+ },
42
+ }
43
+ );
44
+ };
@@ -3,8 +3,8 @@ import { useEffect, useState } from 'react';
3
3
  import { useNotifyAT } from '@strapi/design-system';
4
4
  import { useIntl } from 'react-intl';
5
5
 
6
- import useFetchMarketplacePlugins from '../../../hooks/marketplace/useFetchMarketplacePlugins';
7
- import useFetchMarketplaceProviders from '../../../hooks/marketplace/useFetchMarketplaceProviders';
6
+ import { useFetchMarketplacePlugins } from '../hooks/useFetchMarketplacePlugins';
7
+ import { useFetchMarketplaceProviders } from '../hooks/useFetchMarketplaceProviders';
8
8
 
9
9
  function useMarketplaceData({ npmPackageType, debouncedSearch, query, tabQuery }) {
10
10
  const { notifyStatus } = useNotifyAT();