@strapi/admin 4.6.0-beta.2 → 4.6.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 (160) hide show
  1. package/admin/src/components/ConfigurationsProvider/index.js +21 -18
  2. package/admin/src/components/ConfigurationsProvider/reducer.js +1 -0
  3. package/admin/src/components/LeftMenu/index.js +53 -50
  4. package/admin/src/components/UnauthenticatedLogo/index.js +1 -1
  5. package/admin/src/content-manager/components/Hint/index.js +4 -17
  6. package/admin/src/content-manager/components/InputUID/index.js +3 -14
  7. package/admin/src/content-manager/components/PreviewWysiwyg/Wrapper.js +22 -27
  8. package/admin/src/content-manager/components/Wysiwyg/EditorLayout.js +19 -28
  9. package/admin/src/content-manager/components/Wysiwyg/index.js +4 -8
  10. package/admin/src/content-manager/pages/App/LeftMenu/index.js +3 -8
  11. package/admin/src/content-manager/pages/App/LeftMenu/utils/index.js +1 -0
  12. package/admin/src/content-manager/pages/App/LeftMenu/utils/matchByTitle.js +24 -0
  13. package/admin/src/content-manager/pages/EditView/{Informations → Information}/index.js +55 -39
  14. package/admin/src/content-manager/pages/EditView/{Informations → Information}/utils/getUnits.js +0 -0
  15. package/admin/src/content-manager/pages/EditView/index.js +3 -3
  16. package/admin/src/core/store/configureStore.js +22 -4
  17. package/admin/src/core/utils/axiosInstance.js +4 -2
  18. package/admin/src/hooks/useSettingsMenu/init.js +2 -25
  19. package/admin/src/hooks/useSettingsMenu/utils/adminLinks.js +4 -0
  20. package/admin/src/hooks/useSettingsMenu/utils/customAdminLinks.js +1 -0
  21. package/admin/src/hooks/useSettingsMenu/utils/defaultAdminLinks.js +21 -0
  22. package/admin/src/index.js +3 -3
  23. package/admin/src/pages/App/index.js +6 -2
  24. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/CustomizationInfos/index.js +142 -0
  25. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/{Form → CustomizationInfos}/init.js +3 -0
  26. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/{Form → CustomizationInfos}/reducer.js +20 -0
  27. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/index.js +21 -17
  28. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +68 -42
  29. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +5 -1
  30. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/index.js +1 -1
  31. package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +0 -11
  32. package/admin/src/permissions/defaultPermissions.js +4 -0
  33. package/admin/src/translations/en.json +22 -16
  34. package/build/2607.ce06608e.chunk.js +66 -0
  35. package/build/{2743.692b1f21.chunk.js → 2743.dea372fb.chunk.js} +14 -14
  36. package/build/3075.03ebe93d.chunk.js +115 -0
  37. package/build/3632.963ac97d.chunk.js +138 -0
  38. package/build/{4318.87affaf2.chunk.js → 4318.8cb388a5.chunk.js} +1 -1
  39. package/build/4656.a0d43cca.chunk.js +159 -0
  40. package/build/{5015.f5e15fdb.chunk.js → 5015.8e3fe50b.chunk.js} +1 -1
  41. package/build/{3557.e7115160.chunk.js → 5910.a5374848.chunk.js} +130 -90
  42. package/build/{8633.6f546066.chunk.js → 8633.4af74a50.chunk.js} +1 -1
  43. package/build/9641.a311b612.chunk.js +276 -0
  44. package/build/9707.62831b4d.chunk.js +101 -0
  45. package/build/Admin-authenticatedApp.50dc27f9.chunk.js +75 -0
  46. package/build/Admin_homePage.79ab880c.chunk.js +77 -0
  47. package/build/Admin_marketplace.eabf21b2.chunk.js +26 -0
  48. package/build/{Admin_pluginsPage.d2a9a619.chunk.js → Admin_pluginsPage.953e796b.chunk.js} +1 -1
  49. package/build/{Admin_profilePage.5e830ceb.chunk.js → Admin_profilePage.5c2efda5.chunk.js} +1 -1
  50. package/build/Admin_settingsPage.19cfb9ca.chunk.js +178 -0
  51. package/build/{Upload_ConfigureTheView.9bdf41b5.chunk.js → Upload_ConfigureTheView.3f2b6e6a.chunk.js} +1 -1
  52. package/build/admin-app.34295b50.chunk.js +112 -0
  53. package/build/{admin-edit-roles-page.32bfe5ea.chunk.js → admin-edit-roles-page.d50d9654.chunk.js} +1 -1
  54. package/build/admin-edit-users.912b856d.chunk.js +10 -0
  55. package/build/admin-users.e36e7111.chunk.js +11 -0
  56. package/build/{api-tokens-list-page.a55e427c.chunk.js → api-tokens-list-page.1cd86136.chunk.js} +1 -1
  57. package/build/audit-logs-settings-page.308a6250.chunk.js +1 -0
  58. package/build/{content-manager.ad929a94.chunk.js → content-manager.851f40ce.chunk.js} +128 -132
  59. package/build/content-type-builder-list-view.4243b2b1.chunk.js +198 -0
  60. package/build/{content-type-builder-translation-de-json.29df67b8.chunk.js → content-type-builder-translation-de-json.0979cccb.chunk.js} +1 -1
  61. package/build/{content-type-builder-translation-dk-json.e22d2527.chunk.js → content-type-builder-translation-dk-json.e05583e9.chunk.js} +1 -1
  62. package/build/content-type-builder-translation-en-json.e577d595.chunk.js +1 -0
  63. package/build/{content-type-builder-translation-es-json.1044b252.chunk.js → content-type-builder-translation-es-json.fe4daad8.chunk.js} +1 -1
  64. package/build/{content-type-builder-translation-fr-json.2183e6b3.chunk.js → content-type-builder-translation-fr-json.b1eb52f6.chunk.js} +1 -1
  65. package/build/{content-type-builder-translation-id-json.ba3e8891.chunk.js → content-type-builder-translation-id-json.ee3b36bb.chunk.js} +1 -1
  66. package/build/{content-type-builder-translation-it-json.d4661201.chunk.js → content-type-builder-translation-it-json.13b3c26a.chunk.js} +1 -1
  67. package/build/{content-type-builder-translation-ko-json.57ff7f51.chunk.js → content-type-builder-translation-ko-json.8a274be5.chunk.js} +1 -1
  68. package/build/{content-type-builder-translation-pl-json.a057b51e.chunk.js → content-type-builder-translation-pl-json.24a34349.chunk.js} +1 -1
  69. package/build/{content-type-builder-translation-pt-BR-json.446df9da.chunk.js → content-type-builder-translation-pt-BR-json.97f71a9d.chunk.js} +1 -1
  70. package/build/{content-type-builder-translation-ru-json.8c51843e.chunk.js → content-type-builder-translation-ru-json.54d11230.chunk.js} +1 -1
  71. package/build/{content-type-builder-translation-sv-json.af6ecca1.chunk.js → content-type-builder-translation-sv-json.59f5e1e5.chunk.js} +1 -1
  72. package/build/{content-type-builder-translation-tr-json.da83a07e.chunk.js → content-type-builder-translation-tr-json.cea4d226.chunk.js} +1 -1
  73. package/build/{content-type-builder-translation-zh-json.42f94cb3.chunk.js → content-type-builder-translation-zh-json.faedd610.chunk.js} +1 -1
  74. package/build/content-type-builder.365b6bf4.chunk.js +125 -0
  75. package/build/email-settings-page.379552b1.chunk.js +15 -0
  76. package/build/en-json.38d182e5.chunk.js +1 -0
  77. package/build/i18n-settings-page.3ab28b1a.chunk.js +65 -0
  78. package/build/{i18n-translation-de-json.dc876c08.chunk.js → i18n-translation-de-json.362384a6.chunk.js} +1 -1
  79. package/build/{i18n-translation-dk-json.49aaf933.chunk.js → i18n-translation-dk-json.89401417.chunk.js} +1 -1
  80. package/build/{i18n-translation-en-json.ac9ebc1b.chunk.js → i18n-translation-en-json.60af6722.chunk.js} +1 -1
  81. package/build/{i18n-translation-es-json.57072ed3.chunk.js → i18n-translation-es-json.87b494d1.chunk.js} +1 -1
  82. package/build/{i18n-translation-fr-json.84733f34.chunk.js → i18n-translation-fr-json.57ddc77e.chunk.js} +1 -1
  83. package/build/{i18n-translation-ko-json.fc73fe20.chunk.js → i18n-translation-ko-json.ef4f9471.chunk.js} +1 -1
  84. package/build/{i18n-translation-pl-json.16e5df90.chunk.js → i18n-translation-pl-json.dfac513d.chunk.js} +1 -1
  85. package/build/{i18n-translation-tr-json.cb39c048.chunk.js → i18n-translation-tr-json.10f0600d.chunk.js} +1 -1
  86. package/build/{i18n-translation-zh-Hans-json.2cf82d2d.chunk.js → i18n-translation-zh-Hans-json.757ce62d.chunk.js} +1 -1
  87. package/build/{i18n-translation-zh-json.ed1d272e.chunk.js → i18n-translation-zh-json.bef2dc07.chunk.js} +1 -1
  88. package/build/index.html +1 -1
  89. package/build/main.9f31732e.js +4454 -0
  90. package/build/runtime~main.2b8e2318.js +2 -0
  91. package/build/sso-settings-page.b64a44e8.chunk.js +41 -0
  92. package/build/upload-settings.6c26ff37.chunk.js +89 -0
  93. package/build/upload.2c69d238.chunk.js +38 -0
  94. package/build/users-advanced-settings-page.c4270682.chunk.js +13 -0
  95. package/build/users-email-settings-page.60422a2f.chunk.js +28 -0
  96. package/build/users-providers-settings-page.e1834060.chunk.js +104 -0
  97. package/build/{users-roles-settings-page.ad28ab42.chunk.js → users-roles-settings-page.3ef35132.chunk.js} +1 -1
  98. package/build/webhook-edit-page.c0080dc1.chunk.js +75 -0
  99. package/build/webhook-list-page.f75ba3f2.chunk.js +42 -0
  100. package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +17 -0
  101. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/Modal/ActionBody.js +0 -0
  102. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/Modal/ActionItem.js +0 -0
  103. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/Modal/index.js +5 -1
  104. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/PaginationFooter/index.js +0 -0
  105. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/TableRows/index.js +0 -0
  106. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/hooks/useFormatTimeStamp.js +0 -0
  107. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/index.js +7 -7
  108. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/utils/getActionTypesDefaultMessages.js +3 -0
  109. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ListView/utils/tableHeaders.js +0 -0
  110. package/{admin/src → ee/admin}/pages/SettingsPage/pages/AuditLogs/ProtectedListPage/index.js +1 -1
  111. package/ee/admin/pages/SettingsPage/{SingleSignOn → pages/SingleSignOn}/index.js +3 -3
  112. package/ee/admin/pages/SettingsPage/{SingleSignOn → pages/SingleSignOn}/utils/schema.js +0 -0
  113. package/ee/admin/pages/SettingsPage/utils/customRoutes.js +28 -16
  114. package/ee/server/bootstrap.js +2 -0
  115. package/ee/server/routes/index.js +94 -10
  116. package/ee/server/services/audit-logs.js +19 -1
  117. package/ee/server/services/passport/sso.js +13 -1
  118. package/ee/server/services/passport.js +1 -4
  119. package/package.json +11 -16
  120. package/server/controllers/admin.js +3 -2
  121. package/server/register.js +7 -7
  122. package/server/services/project-settings.js +10 -6
  123. package/server/services/user.js +3 -1
  124. package/server/validation/project-settings.js +19 -10
  125. package/strapi-server.js +1 -1
  126. package/admin/src/core/store/createReducer.js +0 -5
  127. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/index.js +0 -85
  128. package/build/2235.746d3cf7.chunk.js +0 -106
  129. package/build/2598.01c96bd5.chunk.js +0 -159
  130. package/build/4958.1979bbf5.chunk.js +0 -276
  131. package/build/5052.c2eacff2.chunk.js +0 -65
  132. package/build/7295.4e2dfbbb.chunk.js +0 -114
  133. package/build/805.da20168c.chunk.js +0 -138
  134. package/build/874.be41e4b3.chunk.js +0 -104
  135. package/build/9707.a07db355.chunk.js +0 -101
  136. package/build/Admin-authenticatedApp.9933974c.chunk.js +0 -75
  137. package/build/Admin_homePage.045bb0c8.chunk.js +0 -77
  138. package/build/Admin_marketplace.bf3ac090.chunk.js +0 -26
  139. package/build/Admin_settingsPage.53fa00a4.chunk.js +0 -178
  140. package/build/admin-app.8ed108ca.chunk.js +0 -112
  141. package/build/admin-audit-logs.68f833bf.chunk.js +0 -1
  142. package/build/admin-edit-users.795f155c.chunk.js +0 -10
  143. package/build/admin-users.cbd9bcf7.chunk.js +0 -11
  144. package/build/content-type-builder-list-view.3048854d.chunk.js +0 -198
  145. package/build/content-type-builder-translation-en-json.08e28f4e.chunk.js +0 -1
  146. package/build/content-type-builder.4edd1c22.chunk.js +0 -127
  147. package/build/email-settings-page.7c9e6c5e.chunk.js +0 -15
  148. package/build/en-json.d65a13ef.chunk.js +0 -1
  149. package/build/i18n-settings-page.fbccdf12.chunk.js +0 -1
  150. package/build/main.6bbf9950.js +0 -4417
  151. package/build/runtime~main.c2bf62af.js +0 -2
  152. package/build/sso-settings-page.4031de9e.chunk.js +0 -41
  153. package/build/upload-settings.657790fd.chunk.js +0 -89
  154. package/build/upload.608a9856.chunk.js +0 -38
  155. package/build/users-advanced-settings-page.e3ab865f.chunk.js +0 -13
  156. package/build/users-email-settings-page.57adf9b7.chunk.js +0 -28
  157. package/build/users-providers-settings-page.7d1fb45c.chunk.js +0 -1
  158. package/build/webhook-edit-page.1dd6d040.chunk.js +0 -75
  159. package/build/webhook-list-page.98afa3ea.chunk.js +0 -42
  160. package/ee/server/routes/features-routes.js +0 -66
@@ -1,25 +1,40 @@
1
1
  import React, { useRef } from 'react';
2
+ import propTypes from 'prop-types';
2
3
  import { useIntl } from 'react-intl';
3
4
  import { useCMEditViewDataManager } from '@strapi/helper-plugin';
4
- import { Box } from '@strapi/design-system/Box';
5
- import { Divider } from '@strapi/design-system/Divider';
6
- import { Typography } from '@strapi/design-system/Typography';
7
- import { Flex } from '@strapi/design-system/Flex';
8
- import { Stack } from '@strapi/design-system/Stack';
5
+ import { Box, Divider, Flex, Stack, Typography } from '@strapi/design-system';
6
+
9
7
  import { getTrad } from '../../../utils';
10
8
  import getUnits from './utils/getUnits';
11
9
  import { getFullName } from '../../../../utils';
12
10
 
13
- const Informations = () => {
11
+ const KeyValuePair = ({ label, value }) => {
12
+ return (
13
+ <Flex justifyContent="space-between">
14
+ <Typography as="dt" fontWeight="bold" textColor="neutral600">
15
+ {label}
16
+ </Typography>
17
+ <Typography as="dd">{value}</Typography>
18
+ </Flex>
19
+ );
20
+ };
21
+
22
+ KeyValuePair.propTypes = {
23
+ label: propTypes.string.isRequired,
24
+ value: propTypes.string.isRequired,
25
+ };
26
+
27
+ const Information = () => {
14
28
  const { formatMessage, formatRelativeTime } = useIntl();
15
29
  const { initialData, isCreatingEntry } = useCMEditViewDataManager();
16
30
  const currentTime = useRef(Date.now());
17
31
 
18
32
  const getFieldInfo = (atField, byField) => {
19
- const userFirstname = initialData[byField]?.firstname || '';
20
- const userLastname = initialData[byField]?.lastname || '';
21
- const userUsername = initialData[byField]?.username;
22
- const user = userUsername || getFullName(userFirstname, userLastname);
33
+ const { firstname, lastname, username } = initialData[byField] ?? {};
34
+
35
+ const userFirstname = firstname ?? '';
36
+ const userLastname = lastname ?? '';
37
+ const user = username ?? getFullName(userFirstname, userLastname);
23
38
  const timestamp = initialData[atField] ? new Date(initialData[atField]).getTime() : Date.now();
24
39
  const elapsed = timestamp - currentTime.current;
25
40
  const { unit, value } = getUnits(-elapsed);
@@ -34,56 +49,57 @@ const Informations = () => {
34
49
  const created = getFieldInfo('createdAt', 'createdBy');
35
50
 
36
51
  return (
37
- <Box>
38
- <Typography variant="sigma" textColor="neutral600" id="additional-informations">
52
+ <Stack spacing={2}>
53
+ <Typography variant="sigma" textColor="neutral600" id="additional-information">
39
54
  {formatMessage({
40
55
  id: getTrad('containers.Edit.information'),
41
56
  defaultMessage: 'Information',
42
57
  })}
43
58
  </Typography>
44
- <Box paddingTop={2} paddingBottom={6}>
59
+
60
+ <Box paddingBottom={4}>
45
61
  <Divider />
46
62
  </Box>
63
+
47
64
  <Stack spacing={4}>
48
- <Flex justifyContent="space-between">
49
- <Typography fontWeight="bold">
50
- {formatMessage({
65
+ <Stack spacing={2} as="dl">
66
+ <KeyValuePair
67
+ label={formatMessage({
51
68
  id: getTrad('containers.Edit.information.created'),
52
69
  defaultMessage: 'Created',
53
70
  })}
54
- </Typography>
55
- <Typography>{created.at}</Typography>
56
- </Flex>
57
- <Flex justifyContent="space-between">
58
- <Typography fontWeight="bold">
59
- {formatMessage({
71
+ value={created.at}
72
+ />
73
+
74
+ <KeyValuePair
75
+ label={formatMessage({
60
76
  id: getTrad('containers.Edit.information.by'),
61
77
  defaultMessage: 'By',
62
78
  })}
63
- </Typography>
64
- <Typography>{created.by}</Typography>
65
- </Flex>
66
- <Flex justifyContent="space-between">
67
- <Typography fontWeight="bold">
68
- {formatMessage({
79
+ value={created.by}
80
+ />
81
+ </Stack>
82
+
83
+ <Stack spacing={2} as="dl">
84
+ <KeyValuePair
85
+ label={formatMessage({
69
86
  id: getTrad('containers.Edit.information.lastUpdate'),
70
87
  defaultMessage: 'Last update',
71
88
  })}
72
- </Typography>
73
- <Typography>{updated.at}</Typography>
74
- </Flex>
75
- <Flex justifyContent="space-between">
76
- <Typography fontWeight="bold">
77
- {formatMessage({
89
+ value={updated.at}
90
+ />
91
+
92
+ <KeyValuePair
93
+ label={formatMessage({
78
94
  id: getTrad('containers.Edit.information.by'),
79
95
  defaultMessage: 'By',
80
96
  })}
81
- </Typography>
82
- <Typography>{updated.by}</Typography>
83
- </Flex>
97
+ value={updated.by}
98
+ />
99
+ </Stack>
84
100
  </Stack>
85
- </Box>
101
+ </Stack>
86
102
  );
87
103
  };
88
104
 
89
- export default Informations;
105
+ export default Information;
@@ -25,7 +25,7 @@ import SingleTypeFormWrapper from '../../components/SingleTypeFormWrapper';
25
25
  import { getTrad } from '../../utils';
26
26
  import useLazyComponents from '../../hooks/useLazyComponents';
27
27
  import DraftAndPublishBadge from './DraftAndPublishBadge';
28
- import Informations from './Informations';
28
+ import Information from './Information';
29
29
  import Header from './Header';
30
30
  import { getFieldsActionMatchingPermissions } from './utils';
31
31
  import DeleteLink from './DeleteLink';
@@ -175,7 +175,7 @@ const EditView = ({ allowedActions, isSingleType, goBack, slug, id, origin, user
175
175
  <DraftAndPublishBadge />
176
176
  <Box
177
177
  as="aside"
178
- aria-labelledby="additional-informations"
178
+ aria-labelledby="additional-information"
179
179
  background="neutral0"
180
180
  borderColor="neutral150"
181
181
  hasRadius
@@ -185,7 +185,7 @@ const EditView = ({ allowedActions, isSingleType, goBack, slug, id, origin, user
185
185
  paddingTop={6}
186
186
  shadow="tableShadow"
187
187
  >
188
- <Informations />
188
+ <Information />
189
189
  <InjectionZone area="contentManager.editView.informations" />
190
190
  </Box>
191
191
  <Box as="aside" aria-labelledby="links">
@@ -1,5 +1,4 @@
1
- import { createStore, applyMiddleware, compose } from 'redux';
2
- import createReducer from './createReducer';
1
+ import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
3
2
 
4
3
  const configureStore = (appMiddlewares, appReducers) => {
5
4
  let composeEnhancers = compose;
@@ -19,11 +18,30 @@ const configureStore = (appMiddlewares, appReducers) => {
19
18
  composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({});
20
19
  }
21
20
 
22
- return createStore(
23
- createReducer(appReducers),
21
+ const store = createStore(
22
+ createReducer(appReducers, {}),
24
23
  {},
25
24
  composeEnhancers(applyMiddleware(...middlewares))
26
25
  );
26
+
27
+ // Add a dictionary to keep track of the registered async reducers
28
+ store.asyncReducers = {};
29
+
30
+ // Create an inject reducer function
31
+ // This function adds the async reducer, and creates a new combined reducer
32
+ store.injectReducer = (key, asyncReducer) => {
33
+ store.asyncReducers[key] = asyncReducer;
34
+ store.replaceReducer(createReducer(appReducers, store.asyncReducers));
35
+ };
36
+
37
+ return store;
38
+ };
39
+
40
+ const createReducer = (appReducers, asyncReducers) => {
41
+ return combineReducers({
42
+ ...appReducers,
43
+ ...asyncReducers,
44
+ });
27
45
  };
28
46
 
29
47
  export default configureStore;
@@ -3,14 +3,16 @@ import { auth, wrapAxiosInstance } from '@strapi/helper-plugin';
3
3
 
4
4
  const instance = axios.create({
5
5
  baseURL: process.env.STRAPI_ADMIN_BACKEND_URL,
6
+ headers: {
7
+ Accept: 'application/json',
8
+ 'Content-Type': 'application/json',
9
+ },
6
10
  });
7
11
 
8
12
  instance.interceptors.request.use(
9
13
  async (config) => {
10
14
  config.headers = {
11
15
  Authorization: `Bearer ${auth.getToken()}`,
12
- Accept: 'application/json',
13
- 'Content-Type': 'application/json',
14
16
  };
15
17
 
16
18
  return config;
@@ -1,7 +1,7 @@
1
1
  import omit from 'lodash/omit';
2
2
  import sortLinks from './utils/sortLinks';
3
- import adminPermissions from '../../permissions';
4
3
  import formatLinks from './utils/formatLinks';
4
+ import adminLinks from './utils/adminLinks';
5
5
  import globalLinks from './utils/globalLinks';
6
6
 
7
7
  const init = (initialState, { settings, shouldUpdateStrapi }) => {
@@ -23,30 +23,7 @@ const init = (initialState, { settings, shouldUpdateStrapi }) => {
23
23
  {
24
24
  id: 'permissions',
25
25
  intlLabel: { id: 'Settings.permissions', defaultMessage: 'Administration Panel' },
26
- links: [
27
- {
28
- intlLabel: { id: 'global.auditLogs', defaultMessage: 'Audit Logs' },
29
- to: '/settings/audit-logs?pageSize=50&page=1&sort=date:DESC',
30
- id: 'auditLogs',
31
- isDisplayed: false,
32
- permissions: adminPermissions.settings.auditLogs.main,
33
- },
34
- {
35
- intlLabel: { id: 'global.roles', defaultMessage: 'Roles' },
36
- to: '/settings/roles',
37
- id: 'roles',
38
- isDisplayed: false,
39
- permissions: adminPermissions.settings.roles.main,
40
- },
41
- {
42
- intlLabel: { id: 'global.users' },
43
- // Init the search params directly
44
- to: '/settings/users?pageSize=10&page=1&sort=firstname',
45
- id: 'users',
46
- isDisplayed: false,
47
- permissions: adminPermissions.settings.users.main,
48
- },
49
- ],
26
+ links: adminLinks,
50
27
  },
51
28
  ...otherSections,
52
29
  ];
@@ -0,0 +1,4 @@
1
+ import customAdminLinks from 'ee_else_ce/hooks/useSettingsMenu/utils/customAdminLinks';
2
+ import defaultAdminLinks from './defaultAdminLinks';
3
+
4
+ export default [...customAdminLinks, ...defaultAdminLinks];
@@ -0,0 +1 @@
1
+ export default [];
@@ -0,0 +1,21 @@
1
+ import adminPermissions from '../../../permissions';
2
+
3
+ const defaultAdminLinks = [
4
+ {
5
+ intlLabel: { id: 'global.roles', defaultMessage: 'Roles' },
6
+ to: '/settings/roles',
7
+ id: 'roles',
8
+ isDisplayed: false,
9
+ permissions: adminPermissions.settings.roles.main,
10
+ },
11
+ {
12
+ intlLabel: { id: 'global.users' },
13
+ // Init the search params directly
14
+ to: '/settings/users?pageSize=10&page=1&sort=firstname',
15
+ id: 'users',
16
+ isDisplayed: false,
17
+ permissions: adminPermissions.settings.users.main,
18
+ },
19
+ ];
20
+
21
+ export default defaultAdminLinks;
@@ -1,7 +1,7 @@
1
1
  import ReactDOM from 'react-dom';
2
+ import appCustomisations from './app';
2
3
  import { Components, Fields, Middlewares, Reducers } from './core/apis';
3
4
  import { axiosInstance } from './core/utils';
4
- import appCustomisations from './app';
5
5
  // eslint-disable-next-line import/extensions
6
6
  import plugins from './plugins';
7
7
  import appReducers from './reducers';
@@ -12,6 +12,7 @@ window.strapi = {
12
12
  telemetryDisabled: process.env.STRAPI_TELEMETRY_DISABLED ?? false,
13
13
  features: {
14
14
  SSO: 'sso',
15
+ AUDIT_LOGS: 'audit-logs',
15
16
  },
16
17
  projectType: 'Community',
17
18
  };
@@ -38,8 +39,7 @@ const run = async () => {
38
39
  window.strapi.isEE = isEE;
39
40
  window.strapi.features = {
40
41
  ...window.strapi.features,
41
- allFeatures: features,
42
- isEnabled: (f) => features.includes(f),
42
+ isEnabled: (featureName) => features.some((feature) => feature.name === featureName),
43
43
  };
44
44
 
45
45
  window.strapi.projectType = isEE ? 'Enterprise' : 'Community';
@@ -80,11 +80,15 @@ function App() {
80
80
  try {
81
81
  const {
82
82
  data: {
83
- data: { hasAdmin, uuid, menuLogo },
83
+ data: { hasAdmin, uuid, menuLogo, authLogo },
84
84
  },
85
85
  } = await axios.get(`${strapi.backendURL}/admin/init`);
86
86
 
87
- updateProjectSettings({ menuLogo: prefixFileUrlWithBackendUrl(menuLogo) });
87
+ updateProjectSettings({
88
+ menuLogo: prefixFileUrlWithBackendUrl(menuLogo),
89
+ authLogo: prefixFileUrlWithBackendUrl(authLogo),
90
+ });
91
+
88
92
  const deviceId = await getUID();
89
93
 
90
94
  if (uuid) {
@@ -0,0 +1,142 @@
1
+ import React, { useReducer, forwardRef, useImperativeHandle } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { useTracking } from '@strapi/helper-plugin';
5
+ import { Grid, GridItem } from '@strapi/design-system/Grid';
6
+ import { Box } from '@strapi/design-system/Box';
7
+ import { Typography } from '@strapi/design-system/Typography';
8
+ import { useConfigurations } from '../../../../../../hooks';
9
+ import { DIMENSION, SIZE } from '../../utils/constants';
10
+ import LogoInput from '../LogoInput';
11
+ import reducer, { initialState } from './reducer';
12
+ import init from './init';
13
+
14
+ const CustomizationInfos = forwardRef(({ canUpdate, projectSettingsStored }, ref) => {
15
+ const { formatMessage } = useIntl();
16
+ const { trackUsage } = useTracking();
17
+ const {
18
+ logos: { menu, auth },
19
+ } = useConfigurations();
20
+ const [{ menuLogo, authLogo }, dispatch] = useReducer(reducer, initialState, () =>
21
+ init(initialState, projectSettingsStored)
22
+ );
23
+
24
+ const handleChangeMenuLogo = (asset) => {
25
+ dispatch({
26
+ type: 'SET_CUSTOM_MENU_LOGO',
27
+ value: asset,
28
+ });
29
+ };
30
+
31
+ const handleResetMenuLogo = () => {
32
+ trackUsage('didClickResetLogo', {
33
+ logo: 'menu',
34
+ });
35
+
36
+ dispatch({
37
+ type: 'RESET_CUSTOM_MENU_LOGO',
38
+ });
39
+ };
40
+
41
+ const handleChangeAuthLogo = (asset) => {
42
+ dispatch({
43
+ type: 'SET_CUSTOM_AUTH_LOGO',
44
+ value: asset,
45
+ });
46
+ };
47
+
48
+ const handleResetAuthLogo = () => {
49
+ trackUsage('didClickResetLogo', {
50
+ logo: 'auth',
51
+ });
52
+
53
+ dispatch({
54
+ type: 'RESET_CUSTOM_AUTH_LOGO',
55
+ });
56
+ };
57
+
58
+ useImperativeHandle(ref, () => ({
59
+ getValues: () => ({ menuLogo: menuLogo.submit, authLogo: authLogo.submit }),
60
+ }));
61
+
62
+ return (
63
+ <Box
64
+ hasRadius
65
+ background="neutral0"
66
+ shadow="tableShadow"
67
+ paddingTop={6}
68
+ paddingBottom={6}
69
+ paddingRight={7}
70
+ paddingLeft={7}
71
+ >
72
+ <Typography variant="delta" as="h3">
73
+ {formatMessage({
74
+ id: 'Settings.application.customization',
75
+ defaultMessage: 'Customization',
76
+ })}
77
+ </Typography>
78
+ <Typography variant="pi" textColor="neutral600">
79
+ {formatMessage(
80
+ {
81
+ id: 'Settings.application.customization.size-details',
82
+ defaultMessage: 'Max dimension: {dimension}×{dimension}, Max file size: {size}KB',
83
+ },
84
+ { dimension: DIMENSION, size: SIZE }
85
+ )}
86
+ </Typography>
87
+ <Grid paddingTop={4} gap={4}>
88
+ <GridItem col={6} s={12}>
89
+ <LogoInput
90
+ canUpdate={canUpdate}
91
+ customLogo={menuLogo.display}
92
+ defaultLogo={menu.default}
93
+ hint={formatMessage({
94
+ id: 'Settings.application.customization.menu-logo.carousel-hint',
95
+ defaultMessage: 'Replace the logo in the main navigation',
96
+ })}
97
+ label={formatMessage({
98
+ id: 'Settings.application.customization.carousel.menu-logo.title',
99
+ defaultMessage: 'Menu logo',
100
+ })}
101
+ onChangeLogo={handleChangeMenuLogo}
102
+ onResetLogo={handleResetMenuLogo}
103
+ />
104
+ </GridItem>
105
+ <GridItem col={6} s={12}>
106
+ <LogoInput
107
+ canUpdate={canUpdate}
108
+ customLogo={authLogo.display}
109
+ defaultLogo={auth.default}
110
+ hint={formatMessage({
111
+ id: 'Settings.application.customization.auth-logo.carousel-hint',
112
+ defaultMessage: 'Replace the logo in the authentication pages',
113
+ })}
114
+ label={formatMessage({
115
+ id: 'Settings.application.customization.carousel.auth-logo.title',
116
+ defaultMessage: 'Auth logo',
117
+ })}
118
+ onChangeLogo={handleChangeAuthLogo}
119
+ onResetLogo={handleResetAuthLogo}
120
+ />
121
+ </GridItem>
122
+ </Grid>
123
+ </Box>
124
+ );
125
+ });
126
+
127
+ CustomizationInfos.defaultProps = {
128
+ canUpdate: false,
129
+ projectSettingsStored: null,
130
+ };
131
+
132
+ CustomizationInfos.propTypes = {
133
+ canUpdate: PropTypes.bool,
134
+ projectSettingsStored: PropTypes.shape({
135
+ menuLogo: PropTypes.shape({
136
+ url: PropTypes.string,
137
+ name: PropTypes.string,
138
+ }),
139
+ }),
140
+ };
141
+
142
+ export default CustomizationInfos;
@@ -5,6 +5,9 @@ const init = (initialState, projectSettingsStored) => {
5
5
  menuLogo: {
6
6
  display: projectSettingsStored.menuLogo,
7
7
  },
8
+ authLogo: {
9
+ display: projectSettingsStored.authLogo,
10
+ },
8
11
  });
9
12
 
10
13
  return copyInitialState;
@@ -15,6 +15,13 @@ const initialState = {
15
15
  isReset: false,
16
16
  },
17
17
  },
18
+ authLogo: {
19
+ display: null,
20
+ submit: {
21
+ rawFile: null,
22
+ isReset: false,
23
+ },
24
+ },
18
25
  };
19
26
 
20
27
  const reducer = (state = initialState, action) =>
@@ -25,6 +32,11 @@ const reducer = (state = initialState, action) =>
25
32
  draftState.menuLogo.submit.rawFile = action.value.rawFile;
26
33
  break;
27
34
  }
35
+ case 'SET_CUSTOM_AUTH_LOGO': {
36
+ draftState.authLogo.display = action.value;
37
+ draftState.authLogo.submit.rawFile = action.value.rawFile;
38
+ break;
39
+ }
28
40
  case 'RESET_CUSTOM_MENU_LOGO': {
29
41
  draftState.menuLogo.display = null;
30
42
  draftState.menuLogo.submit = {
@@ -33,6 +45,14 @@ const reducer = (state = initialState, action) =>
33
45
  };
34
46
  break;
35
47
  }
48
+ case 'RESET_CUSTOM_AUTH_LOGO': {
49
+ draftState.authLogo.display = null;
50
+ draftState.authLogo.submit = {
51
+ rawFile: null,
52
+ isReset: true,
53
+ };
54
+ break;
55
+ }
36
56
  default: {
37
57
  return draftState;
38
58
  }
@@ -6,12 +6,19 @@ import { IconButton } from '@strapi/design-system/IconButton';
6
6
  import { Box } from '@strapi/design-system/Box';
7
7
  import Plus from '@strapi/icons/Plus';
8
8
  import Refresh from '@strapi/icons/Refresh';
9
- import reducer, { initialState } from './reducer';
10
9
  import LogoModalStepper from '../LogoModalStepper';
11
- import { SIZE, DIMENSION } from '../../utils/constants';
10
+ import reducer, { initialState } from './reducer';
12
11
  import stepper from './stepper';
13
12
 
14
- const LogoInput = ({ customLogo, defaultLogo, onChangeLogo, onResetMenuLogo }) => {
13
+ const LogoInput = ({
14
+ canUpdate,
15
+ customLogo,
16
+ defaultLogo,
17
+ hint,
18
+ label,
19
+ onChangeLogo,
20
+ onResetLogo,
21
+ }) => {
15
22
  const [{ currentStep }, dispatch] = useReducer(reducer, initialState);
16
23
  const { Component, next, prev, modalTitle } = stepper[currentStep] || {};
17
24
  const { formatMessage } = useIntl();
@@ -26,19 +33,9 @@ const LogoInput = ({ customLogo, defaultLogo, onChangeLogo, onResetMenuLogo }) =
26
33
  return (
27
34
  <>
28
35
  <CarouselInput
29
- label={formatMessage({
30
- id: 'Settings.application.customization.carousel.title',
31
- defaultMessage: 'Logo',
32
- })}
36
+ label={label}
33
37
  selectedSlide={0}
34
- hint={formatMessage(
35
- {
36
- id: 'Settings.application.customization.carousel-hint',
37
- defaultMessage:
38
- 'Change the admin panel logo (Max dimension: {dimension}x{dimension}, Max file size: {size}KB)',
39
- },
40
- { size: SIZE, dimension: DIMENSION }
41
- )}
38
+ hint={hint}
42
39
  // Carousel is used here for a single media,
43
40
  // we don't need previous and next labels but these props are required
44
41
  previousLabel=""
@@ -49,6 +46,7 @@ const LogoInput = ({ customLogo, defaultLogo, onChangeLogo, onResetMenuLogo }) =
49
46
  actions={
50
47
  <CarouselActions>
51
48
  <IconButton
49
+ disabled={!canUpdate}
52
50
  onClick={() => goTo(customLogo ? 'pending' : 'upload')}
53
51
  label={formatMessage({
54
52
  id: 'Settings.application.customization.carousel.change-action',
@@ -58,7 +56,8 @@ const LogoInput = ({ customLogo, defaultLogo, onChangeLogo, onResetMenuLogo }) =
58
56
  />
59
57
  {customLogo && (
60
58
  <IconButton
61
- onClick={onResetMenuLogo}
59
+ disabled={!canUpdate}
60
+ onClick={onResetLogo}
62
61
  label={formatMessage({
63
62
  id: 'Settings.application.customization.carousel.reset-action',
64
63
  defaultMessage: 'Reset logo',
@@ -102,17 +101,22 @@ const LogoInput = ({ customLogo, defaultLogo, onChangeLogo, onResetMenuLogo }) =
102
101
  };
103
102
 
104
103
  LogoInput.defaultProps = {
104
+ canUpdate: false,
105
105
  customLogo: null,
106
+ hint: null,
106
107
  };
107
108
 
108
109
  LogoInput.propTypes = {
110
+ canUpdate: PropTypes.bool,
109
111
  customLogo: PropTypes.shape({
110
112
  url: PropTypes.string,
111
113
  name: PropTypes.string,
112
114
  }),
115
+ label: PropTypes.string.isRequired,
116
+ hint: PropTypes.string,
113
117
  defaultLogo: PropTypes.string.isRequired,
114
118
  onChangeLogo: PropTypes.func.isRequired,
115
- onResetMenuLogo: PropTypes.func.isRequired,
119
+ onResetLogo: PropTypes.func.isRequired,
116
120
  };
117
121
 
118
122
  export default LogoInput;