@strapi/admin 4.14.5 → 4.15.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 (226) hide show
  1. package/admin/src/StrapiApp.js +13 -12
  2. package/admin/src/components/AuthenticatedApp.tsx +187 -0
  3. package/admin/src/components/ConfigurationProvider.tsx +2 -1
  4. package/admin/src/components/GuidedTour/Homepage.tsx +111 -0
  5. package/admin/src/components/GuidedTour/Modal.tsx +303 -0
  6. package/admin/src/components/GuidedTour/Ornaments.tsx +74 -0
  7. package/admin/src/components/GuidedTour/Provider.tsx +253 -0
  8. package/admin/src/components/GuidedTour/{layout.js → constants.ts} +13 -3
  9. package/admin/src/components/LanguageProvider.tsx +1 -0
  10. package/admin/src/components/Providers.tsx +125 -0
  11. package/admin/src/components/RBACProvider.tsx +124 -0
  12. package/admin/src/components/Theme.tsx +4 -2
  13. package/admin/src/components/ThemeToggleProvider.tsx +23 -9
  14. package/admin/src/components/__mocks__/{LanguageProvider.js → LanguageProvider.ts} +2 -0
  15. package/admin/src/{constants.js → constants.ts} +48 -0
  16. package/admin/src/content-manager/components/BlocksEditor/Toolbar/index.js +75 -51
  17. package/admin/src/content-manager/components/BlocksEditor/hooks/useBlocksStore.js +72 -14
  18. package/admin/src/content-manager/pages/App/selectors.js +1 -1
  19. package/admin/src/content-manager/pages/App/useContentManagerInitData.js +3 -1
  20. package/admin/src/content-manager/pages/EditView/selectors.js +1 -1
  21. package/admin/src/content-manager/pages/EditViewLayoutManager/index.js +3 -1
  22. package/admin/src/content-manager/pages/ListView/components/Body/index.js +53 -56
  23. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +5 -3
  24. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
  25. package/admin/src/content-manager/pages/ListView/index.js +33 -50
  26. package/admin/src/content-manager/pages/ListView/selectors.js +1 -1
  27. package/admin/src/contexts/admin.ts +1 -0
  28. package/admin/src/contexts/apiTokenPermissions.tsx +64 -0
  29. package/admin/src/contexts/themeToggle.ts +3 -1
  30. package/admin/src/core/store/configure.ts +91 -0
  31. package/admin/src/core/store/hooks.ts +15 -0
  32. package/admin/src/hooks/index.js +0 -1
  33. package/admin/src/hooks/{useContentTypes/useContentTypes.js → useContentTypes.ts} +39 -16
  34. package/admin/src/hooks/useSettingsForm/index.js +14 -2
  35. package/admin/src/hooks/useSettingsMenu/constants.js +39 -0
  36. package/admin/src/index.js +2 -4
  37. package/admin/src/layouts/{AppLayout/index.js → AppLayout.tsx} +7 -10
  38. package/admin/src/layouts/UnauthenticatedLayout.tsx +77 -0
  39. package/admin/src/pages/Admin/index.js +11 -5
  40. package/admin/src/pages/App/index.js +7 -4
  41. package/admin/src/pages/App/selectors.js +1 -1
  42. package/admin/src/pages/AuthPage/components/ForgotPassword/index.js +2 -1
  43. package/admin/src/pages/AuthPage/components/ForgotPasswordSuccess/index.js +2 -1
  44. package/admin/src/pages/AuthPage/components/Login/index.js +1 -1
  45. package/admin/src/pages/AuthPage/components/Oops/index.js +2 -1
  46. package/admin/src/pages/AuthPage/components/Register/index.js +1 -1
  47. package/admin/src/pages/AuthPage/components/ResetPassword/index.js +2 -1
  48. package/admin/src/pages/AuthPage/index.js +2 -3
  49. package/admin/src/pages/HomePage/index.js +6 -3
  50. package/admin/src/pages/{InternalErrorPage/index.js → InternalErrorPage.tsx} +10 -6
  51. package/admin/src/pages/{NotFoundPage/index.js → NotFoundPage.tsx} +9 -7
  52. package/admin/src/pages/ProfilePage/components/Preferences/index.js +23 -9
  53. package/admin/src/pages/ProfilePage/index.js +1 -1
  54. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +20 -0
  55. package/admin/src/pages/SettingsPage/constants.js +33 -0
  56. package/admin/src/pages/SettingsPage/index.js +2 -2
  57. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +1 -1
  58. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +1 -1
  59. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +1 -1
  60. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -2
  61. package/admin/src/pages/SettingsPage/pages/AuditLogs/SalesPage.js +50 -0
  62. package/admin/src/pages/SettingsPage/pages/ReviewWorkflows/SalesPage.js +53 -0
  63. package/admin/src/pages/SettingsPage/pages/SingleSignOn/SalesPage.js +53 -0
  64. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
  65. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +2 -1
  66. package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
  67. package/admin/src/pages/{UseCasePage/index.js → UseCasePage.tsx} +10 -12
  68. package/admin/src/translations/en.json +5 -0
  69. package/admin/src/utils/createRoute.tsx +54 -0
  70. package/admin/src/utils/formatAPIErrors.ts +18 -0
  71. package/admin/src/utils/getFullName.ts +3 -0
  72. package/admin/src/utils/{uniqueAdminHash.js → hashAdminUserEmail.ts} +6 -3
  73. package/admin/src/utils/makeUniqueRoutes.ts +11 -0
  74. package/build/{1049.9236e785.chunk.js → 1049.ecc10c97.chunk.js} +1 -1
  75. package/build/1217.96155682.chunk.js +35 -0
  76. package/build/{1227.e0f7447b.chunk.js → 1227.947ceaf9.chunk.js} +1 -1
  77. package/build/1306.2699df52.chunk.js +79 -0
  78. package/build/{1386.07f2bbb3.chunk.js → 1386.eabd8a1e.chunk.js} +1 -1
  79. package/build/{2379.b0bc4013.chunk.js → 2379.7ce8e110.chunk.js} +1 -1
  80. package/build/{2395.d37b1025.chunk.js → 2395.acb961a8.chunk.js} +3 -3
  81. package/build/{2801.12522720.chunk.js → 2801.4711ea5a.chunk.js} +1 -1
  82. package/build/{3019.0d74d080.chunk.js → 3019.fde2e1be.chunk.js} +2 -2
  83. package/build/3460.8644e608.chunk.js +146 -0
  84. package/build/{3483.8f1b25f8.chunk.js → 3483.db8c1520.chunk.js} +1 -1
  85. package/build/{4174.2c4f958e.chunk.js → 4174.49cedb6a.chunk.js} +1 -1
  86. package/build/4732.149f5f8f.chunk.js +1 -0
  87. package/build/{502.b845473a.chunk.js → 502.f536f78b.chunk.js} +1 -1
  88. package/build/{7464.91341b4f.chunk.js → 7464.579564ac.chunk.js} +1 -1
  89. package/build/7811.fdbe09af.chunk.js +103 -0
  90. package/build/{7897.dffa5ad5.chunk.js → 7897.63ba0a00.chunk.js} +1 -1
  91. package/build/{8276.e9698944.chunk.js → 8276.9abe4679.chunk.js} +3 -3
  92. package/build/8773.ee67141c.chunk.js +48 -0
  93. package/build/9077.2cc01ac8.chunk.js +105 -0
  94. package/build/{9218.306ad178.chunk.js → 9218.b2d367f8.chunk.js} +1 -1
  95. package/build/Admin-authenticatedApp.059dc48f.chunk.js +79 -0
  96. package/build/Admin_InternalErrorPage.06eeef20.chunk.js +1 -0
  97. package/build/Admin_homePage.56b9eb3f.chunk.js +81 -0
  98. package/build/{Admin_marketplace.0db78604.chunk.js → Admin_marketplace.d693a435.chunk.js} +1 -1
  99. package/build/{Admin_pluginsPage.1083f7f0.chunk.js → Admin_pluginsPage.ae2c872a.chunk.js} +1 -1
  100. package/build/Admin_profilePage.89099d5b.chunk.js +13 -0
  101. package/build/Admin_settingsPage.88c45586.chunk.js +12 -0
  102. package/build/{Upload_ConfigureTheView.3cfeb108.chunk.js → Upload_ConfigureTheView.44f28145.chunk.js} +1 -1
  103. package/build/admin-app.990e112f.chunk.js +69 -0
  104. package/build/{admin-edit-roles-page.556fac52.chunk.js → admin-edit-roles-page.4e1eb4a9.chunk.js} +3 -3
  105. package/build/admin-edit-users.5b91404e.chunk.js +10 -0
  106. package/build/{admin-roles-list.15918328.chunk.js → admin-roles-list.89dd94fe.chunk.js} +1 -1
  107. package/build/{admin-users.74fddc87.chunk.js → admin-users.7be4fc5f.chunk.js} +2 -2
  108. package/build/{api-tokens-create-page.c08ae118.chunk.js → api-tokens-create-page.571920e5.chunk.js} +1 -1
  109. package/build/{api-tokens-edit-page.ce18efdc.chunk.js → api-tokens-edit-page.cbdc81b1.chunk.js} +1 -1
  110. package/build/{api-tokens-list-page.783b7569.chunk.js → api-tokens-list-page.de0c49e8.chunk.js} +2 -2
  111. package/build/audit-logs-sales-page.2955db88.chunk.js +1 -0
  112. package/build/{audit-logs-settings-page.12aeea8c.chunk.js → audit-logs-settings-page.b0cb5164.chunk.js} +1 -1
  113. package/build/content-manager.de7ae330.chunk.js +1241 -0
  114. package/build/{content-type-builder-list-view.38ed3935.chunk.js → content-type-builder-list-view.6c8d3213.chunk.js} +1 -1
  115. package/build/{content-type-builder-translation-en-json.43f9d7bc.chunk.js → content-type-builder-translation-en-json.74d80f18.chunk.js} +1 -1
  116. package/build/{content-type-builder.758a9d23.chunk.js → content-type-builder.0bc97051.chunk.js} +13 -23
  117. package/build/{email-settings-page.e08a587e.chunk.js → email-settings-page.07712efc.chunk.js} +1 -1
  118. package/build/en-json.5b907f67.chunk.js +1 -0
  119. package/build/{i18n-settings-page.3186e3e9.chunk.js → i18n-settings-page.5c34f012.chunk.js} +1 -1
  120. package/build/index.html +1 -1
  121. package/build/main.f84563f1.js +2665 -0
  122. package/build/review-workflows-sales-page.f46a8f00.chunk.js +1 -0
  123. package/build/{review-workflows-settings-create-view.5cdc4d64.chunk.js → review-workflows-settings-create-view.d0544fb0.chunk.js} +1 -1
  124. package/build/{review-workflows-settings-edit-view.53bf7865.chunk.js → review-workflows-settings-edit-view.aabf49ef.chunk.js} +1 -1
  125. package/build/review-workflows-settings-list-view.8b0525ab.chunk.js +56 -0
  126. package/build/runtime~main.270fd45f.js +2 -0
  127. package/build/sso-sales-page.ef22e469.chunk.js +1 -0
  128. package/build/sso-settings-page.21e16ae4.chunk.js +1 -0
  129. package/build/{transfer-tokens-create-page.2662d519.chunk.js → transfer-tokens-create-page.3366204d.chunk.js} +1 -1
  130. package/build/{transfer-tokens-edit-page.f64d8d8c.chunk.js → transfer-tokens-edit-page.15cf0f73.chunk.js} +1 -1
  131. package/build/{transfer-tokens-list-page.e6fd5f87.chunk.js → transfer-tokens-list-page.0bc0e682.chunk.js} +2 -2
  132. package/build/{upload-settings.450a1de0.chunk.js → upload-settings.1319dca0.chunk.js} +1 -1
  133. package/build/{upload.0d53e7a3.chunk.js → upload.1ced11be.chunk.js} +1 -1
  134. package/build/{users-advanced-settings-page.4a1f1f6d.chunk.js → users-advanced-settings-page.8e657084.chunk.js} +1 -1
  135. package/build/{users-email-settings-page.ea81fe82.chunk.js → users-email-settings-page.e57745e5.chunk.js} +1 -1
  136. package/build/{users-providers-settings-page.10280cdb.chunk.js → users-providers-settings-page.55796d13.chunk.js} +1 -1
  137. package/build/{users-roles-settings-page.4a7158be.chunk.js → users-roles-settings-page.57079245.chunk.js} +1 -1
  138. package/build/webhook-edit-page.3a28b2e7.chunk.js +33 -0
  139. package/build/{webhook-list-page.f57285ca.chunk.js → webhook-list-page.ee80767b.chunk.js} +1 -1
  140. package/ee/admin/pages/AuthPage/components/Login/index.js +1 -1
  141. package/ee/admin/pages/AuthPage/components/Providers/index.js +2 -1
  142. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/selectors.js +1 -1
  143. package/ee/server/bootstrap.js +1 -1
  144. package/ee/server/controllers/admin.js +1 -1
  145. package/ee/server/controllers/user.js +1 -1
  146. package/ee/server/destroy.js +1 -1
  147. package/ee/server/register.js +1 -1
  148. package/ee/server/routes/utils.js +1 -1
  149. package/ee/server/services/audit-logs.js +1 -1
  150. package/ee/server/services/passport/sso.js +1 -1
  151. package/ee/server/services/passport.js +1 -1
  152. package/ee/server/services/seat-enforcement.js +1 -1
  153. package/ee/server/utils/sso-lock.js +1 -1
  154. package/ee/server/validation/role.js +1 -1
  155. package/ee/server/validation/user.js +1 -1
  156. package/package.json +15 -16
  157. package/server/controllers/admin.js +1 -1
  158. package/shared/entities.ts +1 -1
  159. package/shared/permissions.ts +35 -35
  160. package/shared/schema.ts +9 -0
  161. package/admin/src/components/AuthenticatedApp/index.js +0 -116
  162. package/admin/src/components/AuthenticatedApp/utils/api.js +0 -47
  163. package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.ts +0 -13
  164. package/admin/src/components/AuthenticatedApp/utils/fetchStrapiLatestRelease.ts +0 -19
  165. package/admin/src/components/GuidedTour/Homepage/components/Step.js +0 -61
  166. package/admin/src/components/GuidedTour/Homepage/components/Stepper.js +0 -61
  167. package/admin/src/components/GuidedTour/Homepage/index.js +0 -71
  168. package/admin/src/components/GuidedTour/Modal/components/Content.js +0 -66
  169. package/admin/src/components/GuidedTour/Modal/components/Modal.js +0 -72
  170. package/admin/src/components/GuidedTour/Modal/components/StepNumberWithPadding.js +0 -26
  171. package/admin/src/components/GuidedTour/Modal/components/Stepper.js +0 -118
  172. package/admin/src/components/GuidedTour/Modal/index.js +0 -94
  173. package/admin/src/components/GuidedTour/Modal/reducer.js +0 -29
  174. package/admin/src/components/GuidedTour/Stepper/StepLine.js +0 -29
  175. package/admin/src/components/GuidedTour/Stepper/StepNumber.js +0 -71
  176. package/admin/src/components/GuidedTour/constants.js +0 -3
  177. package/admin/src/components/GuidedTour/index.js +0 -102
  178. package/admin/src/components/GuidedTour/init.js +0 -37
  179. package/admin/src/components/GuidedTour/reducer.js +0 -50
  180. package/admin/src/components/GuidedTour/utils/arePreviousSectionsDone.js +0 -13
  181. package/admin/src/components/GuidedTour/utils/arePreviousStepsDone.js +0 -12
  182. package/admin/src/components/GuidedTour/utils/isGuidedTourCompleted.js +0 -6
  183. package/admin/src/components/GuidedTour/utils/persistStateToLocaleStorage.js +0 -34
  184. package/admin/src/components/Providers/index.js +0 -156
  185. package/admin/src/components/RBACProvider/actions.js +0 -10
  186. package/admin/src/components/RBACProvider/constants.js +0 -2
  187. package/admin/src/components/RBACProvider/index.js +0 -39
  188. package/admin/src/components/RBACProvider/reducer.js +0 -51
  189. package/admin/src/contexts/ApiTokenPermissions/index.js +0 -25
  190. package/admin/src/core/store/configureStore.js +0 -47
  191. package/admin/src/exposedHooks.js +0 -27
  192. package/admin/src/hooks/useContentTypes/index.js +0 -1
  193. package/admin/src/injectionZones.js +0 -25
  194. package/admin/src/layouts/UnauthenticatedLayout/LocaleToggle/index.js +0 -29
  195. package/admin/src/layouts/UnauthenticatedLayout/index.js +0 -55
  196. package/admin/src/reducers.js +0 -23
  197. package/admin/src/utils/checkFormValidity.js +0 -15
  198. package/admin/src/utils/createRoute.js +0 -50
  199. package/admin/src/utils/formatAPIErrors.js +0 -17
  200. package/admin/src/utils/getAttributesToDisplay.js +0 -19
  201. package/admin/src/utils/getExistingActions.js +0 -32
  202. package/admin/src/utils/getFullName.js +0 -9
  203. package/admin/src/utils/index.js +0 -9
  204. package/admin/src/utils/makeUniqueRoutes.js +0 -6
  205. package/admin/src/utils/sortLinks.js +0 -5
  206. package/build/1222.fe92c653.chunk.js +0 -35
  207. package/build/2225.a2147b8f.chunk.js +0 -79
  208. package/build/3021.33ad47fb.chunk.js +0 -103
  209. package/build/6373.1a21d665.chunk.js +0 -105
  210. package/build/8894.5ca4852a.chunk.js +0 -26
  211. package/build/9302.550cf5b7.chunk.js +0 -146
  212. package/build/Admin-authenticatedApp.e897fccb.chunk.js +0 -79
  213. package/build/Admin_InternalErrorPage.e2431a95.chunk.js +0 -1
  214. package/build/Admin_homePage.71ef8d06.chunk.js +0 -81
  215. package/build/Admin_profilePage.61704b7d.chunk.js +0 -13
  216. package/build/Admin_settingsPage.39cb9fca.chunk.js +0 -111
  217. package/build/admin-app.06f5e70a.chunk.js +0 -69
  218. package/build/admin-edit-users.64fd1318.chunk.js +0 -10
  219. package/build/content-manager.2e3f660b.chunk.js +0 -1220
  220. package/build/en-json.bd611a8e.chunk.js +0 -1
  221. package/build/main.00ea6f5a.js +0 -2665
  222. package/build/review-workflows-settings-list-view.b4a8aefb.chunk.js +0 -56
  223. package/build/runtime~main.e3bf3980.js +0 -2
  224. package/build/sso-settings-page.6a35d473.chunk.js +0 -1
  225. package/build/webhook-edit-page.65ac30ee.chunk.js +0 -33
  226. /package/admin/src/hooks/{useContentTypes/__mocks__/index.js → __mocks__/useContentTypes.ts} +0 -0
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
 
3
+ import { bindActionCreators } from '@reduxjs/toolkit';
3
4
  import {
4
5
  Main,
5
6
  ActionLayout,
@@ -39,11 +40,11 @@ import PropTypes from 'prop-types';
39
40
  import { stringify } from 'qs';
40
41
  import { useIntl } from 'react-intl';
41
42
  import { useMutation } from 'react-query';
42
- import { connect, useSelector } from 'react-redux';
43
+ import { useDispatch } from 'react-redux';
43
44
  import { useHistory, useLocation, Link as ReactRouterLink } from 'react-router-dom';
44
- import { bindActionCreators, compose } from 'redux';
45
45
 
46
- import { INJECT_COLUMN_IN_TABLE } from '../../../exposedHooks';
46
+ import { HOOKS } from '../../../constants';
47
+ import { useTypedSelector } from '../../../core/store/hooks';
47
48
  import { useAdminUsers } from '../../../hooks/useAdminUsers';
48
49
  import { useEnterprise } from '../../../hooks/useEnterprise';
49
50
  import { InjectionZone } from '../../../shared/components';
@@ -53,7 +54,7 @@ import { CREATOR_FIELDS } from '../../constants/attributes';
53
54
  import { useAllowedAttributes } from '../../hooks/useAllowedAttributes';
54
55
  import { getTrad, getDisplayName } from '../../utils';
55
56
 
56
- import { getData, getDataSucceeded, onChangeListHeaders, onResetListHeaders } from './actions';
57
+ import * as Actions from './actions';
57
58
  import { Body } from './components/Body';
58
59
  import BulkActionButtons from './components/BulkActionButtons';
59
60
  import CellContent from './components/CellContent';
@@ -61,24 +62,23 @@ import { ViewSettingsMenu } from './components/ViewSettingsMenu';
61
62
  import makeSelectListView, { selectDisplayedHeaders } from './selectors';
62
63
  import { buildValidGetParams } from './utils';
63
64
 
65
+ const { INJECT_COLUMN_IN_TABLE } = HOOKS;
64
66
  const REVIEW_WORKFLOW_COLUMNS_CE = null;
65
67
  const REVIEW_WORKFLOW_COLUMNS_CELL_CE = () => null;
66
68
  const REVIEW_WORKFLOW_FILTER_CE = [];
67
69
  const USER_FILTER_ATTRIBUTES = [...CREATOR_FIELDS, 'strapi_assignee'];
68
70
 
69
- function ListView({
70
- canCreate,
71
- canDelete,
72
- canRead,
73
- canPublish,
74
- data,
75
- getData,
76
- getDataSucceeded,
77
- isLoading,
78
- layout,
79
- pagination,
80
- slug,
81
- }) {
71
+ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) {
72
+ const dispatch = useDispatch();
73
+ const { getData, getDataSucceeded } = React.useMemo(
74
+ () =>
75
+ bindActionCreators(
76
+ { getData: Actions.getData, getDataSucceeded: Actions.getDataSucceeded },
77
+ dispatch
78
+ ),
79
+ [dispatch]
80
+ );
81
+ const { pagination, isLoading, data } = useTypedSelector(makeSelectListView());
82
82
  const { total } = pagination;
83
83
  const { contentType } = layout;
84
84
  const {
@@ -468,7 +468,7 @@ function ListView({
468
468
  });
469
469
 
470
470
  const { runHookWaterfall } = useStrapiApp();
471
- const displayedHeaders = useSelector(selectDisplayedHeaders);
471
+ const displayedHeaders = useTypedSelector(selectDisplayedHeaders);
472
472
 
473
473
  const tableHeaders = React.useMemo(() => {
474
474
  const headers = runHookWaterfall(INJECT_COLUMN_IN_TABLE, {
@@ -731,9 +731,11 @@ function ListView({
731
731
  >
732
732
  {data.map((rowData, index) => {
733
733
  return (
734
- <Tr cursor="pointer" key={data.id} onClick={handleRowClick(rowData.id)}>
734
+ <Tr cursor="pointer" key={rowData.id} onClick={handleRowClick(rowData.id)}>
735
735
  {/* Bulk action row checkbox */}
736
- <Body.CheckboxDataCell rowId={rowData.id} index={index} />
736
+ <Td>
737
+ <Body.CheckboxDataCell rowId={rowData.id} index={index} />
738
+ </Td>
737
739
  {/* Field data */}
738
740
  {tableHeaders.map(({ key, name, cellFormatter, ...rest }) => {
739
741
  if (hasDraftAndPublish && name === 'publishedAt') {
@@ -832,14 +834,16 @@ function ListView({
832
834
  })}
833
835
  {/* Actions: edit, duplicate, delete */}
834
836
  {(canDelete || canPublish) && isBulkable && (
835
- <Body.EntityActionsDataCell
836
- rowId={rowData.id}
837
- index={index}
838
- setIsConfirmDeleteRowOpen={setIsConfirmDeleteRowOpen}
839
- canCreate={canCreate}
840
- canDelete={canDelete}
841
- handleCloneClick={handleCloneClick}
842
- />
837
+ <Td>
838
+ <Body.EntityActionsDataCell
839
+ rowId={rowData.id}
840
+ index={index}
841
+ setIsConfirmDeleteRowOpen={setIsConfirmDeleteRowOpen}
842
+ canCreate={canCreate}
843
+ canDelete={canDelete}
844
+ handleCloneClick={handleCloneClick}
845
+ />
846
+ </Td>
843
847
  )}
844
848
  </Tr>
845
849
  );
@@ -865,7 +869,6 @@ ListView.propTypes = {
865
869
  canDelete: PropTypes.bool.isRequired,
866
870
  canRead: PropTypes.bool.isRequired,
867
871
  canPublish: PropTypes.bool.isRequired,
868
- data: PropTypes.array.isRequired,
869
872
  layout: PropTypes.exact({
870
873
  components: PropTypes.object.isRequired,
871
874
  contentType: PropTypes.shape({
@@ -880,27 +883,7 @@ ListView.propTypes = {
880
883
  settings: PropTypes.object.isRequired,
881
884
  }).isRequired,
882
885
  }).isRequired,
883
- isLoading: PropTypes.bool.isRequired,
884
- getData: PropTypes.func.isRequired,
885
- getDataSucceeded: PropTypes.func.isRequired,
886
- pagination: PropTypes.shape({ total: PropTypes.number.isRequired, pageCount: PropTypes.number })
887
- .isRequired,
888
886
  slug: PropTypes.string.isRequired,
889
887
  };
890
888
 
891
- const mapStateToProps = makeSelectListView();
892
-
893
- export function mapDispatchToProps(dispatch) {
894
- return bindActionCreators(
895
- {
896
- getData,
897
- getDataSucceeded,
898
- onChangeListHeaders,
899
- onResetListHeaders,
900
- },
901
- dispatch
902
- );
903
- }
904
- const withConnect = connect(mapStateToProps, mapDispatchToProps);
905
-
906
- export default compose(withConnect)(React.memo(ListView, isEqual));
889
+ export default React.memo(ListView, isEqual);
@@ -1,4 +1,4 @@
1
- import { createSelector } from 'reselect';
1
+ import { createSelector } from '@reduxjs/toolkit';
2
2
 
3
3
  import { initialState } from './reducer';
4
4
 
@@ -16,3 +16,4 @@ const AdminContext = React.createContext<AdminContextValue>({
16
16
  const useAdmin = () => React.useContext(AdminContext);
17
17
 
18
18
  export { AdminContext, useAdmin };
19
+ export type { AdminContextValue };
@@ -0,0 +1,64 @@
1
+ /* eslint-disable check-file/filename-naming-convention */
2
+
3
+ import * as React from 'react';
4
+
5
+ import { Entity } from '@strapi/types';
6
+
7
+ interface PseudoEvent {
8
+ target: { value: string };
9
+ }
10
+
11
+ interface ApiTokenPermissionsContextValue {
12
+ selectedAction: string[] | null;
13
+ routes: string[];
14
+ selectedActions: string[];
15
+ data: {
16
+ allActionsIds: Entity.ID[];
17
+ permissions: {
18
+ apiId: string;
19
+ label: string;
20
+ controllers: { controller: string; actions: { actionId: string; action: string } }[];
21
+ }[];
22
+ };
23
+ onChange: ({ target: { value } }: PseudoEvent) => void;
24
+ onChangeSelectAll: ({ target: { value } }: PseudoEvent) => void;
25
+ setSelectedAction: ({ target: { value } }: PseudoEvent) => void;
26
+ }
27
+
28
+ interface ApiTokenPermissionsContextProviderProps extends ApiTokenPermissionsContextValue {
29
+ children: React.ReactNode[];
30
+ }
31
+
32
+ const ApiTokenPermissionsContext = React.createContext<ApiTokenPermissionsContextValue>({
33
+ selectedAction: null,
34
+ routes: [],
35
+ selectedActions: [],
36
+ data: {
37
+ allActionsIds: [],
38
+ permissions: [],
39
+ },
40
+ onChange: () => {},
41
+ onChangeSelectAll: () => {},
42
+ setSelectedAction: () => {},
43
+ });
44
+
45
+ const ApiTokenPermissionsContextProvider = ({
46
+ children,
47
+ ...rest
48
+ }: ApiTokenPermissionsContextProviderProps) => {
49
+ return (
50
+ <ApiTokenPermissionsContext.Provider value={rest}>
51
+ {children}
52
+ </ApiTokenPermissionsContext.Provider>
53
+ );
54
+ };
55
+
56
+ const useApiTokenPermissionsContext = () => React.useContext(ApiTokenPermissionsContext);
57
+
58
+ export {
59
+ ApiTokenPermissionsContext,
60
+ ApiTokenPermissionsContextProvider,
61
+ useApiTokenPermissionsContext,
62
+ };
63
+
64
+ export type { ApiTokenPermissionsContextValue, ApiTokenPermissionsContextProviderProps };
@@ -2,7 +2,8 @@ import { createContext } from 'react';
2
2
 
3
3
  import { DefaultTheme } from 'styled-components';
4
4
 
5
- export type ThemeName = 'light' | 'dark';
5
+ export type ThemeName = 'light' | 'dark' | 'system';
6
+ export type NonSystemThemeName = Exclude<ThemeName, 'system'>;
6
7
 
7
8
  interface ThemeToggleContextContextValue {
8
9
  currentTheme?: ThemeName;
@@ -11,6 +12,7 @@ interface ThemeToggleContextContextValue {
11
12
  dark: DefaultTheme;
12
13
  light: DefaultTheme;
13
14
  };
15
+ systemTheme?: NonSystemThemeName;
14
16
  }
15
17
 
16
18
  export const ThemeToggleContext = createContext<ThemeToggleContextContextValue>({});
@@ -0,0 +1,91 @@
1
+ import {
2
+ configureStore,
3
+ StoreEnhancer,
4
+ Middleware,
5
+ Reducer,
6
+ combineReducers,
7
+ } from '@reduxjs/toolkit';
8
+
9
+ import { RBACReducer } from '../../components/RBACProvider';
10
+ // @ts-expect-error no types, yet.
11
+ import rbacManagerReducer from '../../content-manager/hooks/useSyncRbac/reducer';
12
+ // @ts-expect-error no types, yet.
13
+ import cmAppReducer from '../../content-manager/pages/App/reducer';
14
+ // @ts-expect-error no types, yet.
15
+ import editViewLayoutManagerReducer from '../../content-manager/pages/EditViewLayoutManager/reducer';
16
+ // @ts-expect-error no types, yet.
17
+ import listViewReducer from '../../content-manager/pages/ListView/reducer';
18
+ // @ts-expect-error no types, yet.
19
+ import editViewCrudReducer from '../../content-manager/sharedReducers/crudReducer/reducer';
20
+ // @ts-expect-error no types, yet.
21
+ import appReducer from '../../pages/App/reducer';
22
+
23
+ /**
24
+ * @description Static reducers are ones we know, they live in the admin package.
25
+ */
26
+ const staticReducers = {
27
+ admin_app: appReducer,
28
+ rbacProvider: RBACReducer,
29
+ 'content-manager_app': cmAppReducer,
30
+ 'content-manager_listView': listViewReducer,
31
+ 'content-manager_rbacManager': rbacManagerReducer,
32
+ 'content-manager_editViewLayoutManager': editViewLayoutManagerReducer,
33
+ 'content-manager_editViewCrudReducer': editViewCrudReducer,
34
+ } as const;
35
+
36
+ const injectReducerStoreEnhancer: (appReducers: Record<string, Reducer>) => StoreEnhancer =
37
+ (appReducers) =>
38
+ (next) =>
39
+ (...args) => {
40
+ const store = next(...args);
41
+
42
+ const asyncReducers: Record<string, Reducer> = {};
43
+
44
+ return {
45
+ ...store,
46
+ asyncReducers,
47
+ injectReducer: (key: string, asyncReducer: Reducer) => {
48
+ asyncReducers[key] = asyncReducer;
49
+ store.replaceReducer(
50
+ // @ts-expect-error we dynamically add reducers which makes the types uncomfortable.
51
+ combineReducers({
52
+ ...appReducers,
53
+ ...asyncReducers,
54
+ })
55
+ );
56
+ },
57
+ };
58
+ };
59
+
60
+ /**
61
+ * @description This is the main store configuration function, injected Reducers use our legacy app.addReducer API,
62
+ * which we're trying to phase out. App Middlewares could potentially be improved...?
63
+ */
64
+ const configureStoreImpl = (
65
+ appMiddlewares: Array<() => Middleware> = [],
66
+ injectedReducers: Record<string, Reducer> = {}
67
+ ) => {
68
+ const coreReducers = { ...staticReducers, ...injectedReducers } as const;
69
+
70
+ const store = configureStore({
71
+ reducer: coreReducers,
72
+ devTools: process.env.NODE_ENV !== 'production',
73
+ middleware: (getDefaultMiddleware) => [
74
+ ...getDefaultMiddleware(),
75
+ ...appMiddlewares.map((m) => m()),
76
+ ],
77
+ enhancers: [injectReducerStoreEnhancer(coreReducers)],
78
+ });
79
+
80
+ return store;
81
+ };
82
+
83
+ type Store = ReturnType<typeof configureStoreImpl> & {
84
+ asyncReducers: Record<string, Reducer>;
85
+ injectReducer: (key: string, asyncReducer: Reducer) => void;
86
+ };
87
+
88
+ type RootState = ReturnType<Store['getState']>;
89
+
90
+ export { configureStoreImpl as configureStore };
91
+ export type { RootState, Store };
@@ -0,0 +1,15 @@
1
+ import { createSelector, Selector } from '@reduxjs/toolkit';
2
+ import { useDispatch, useStore, TypedUseSelectorHook, useSelector } from 'react-redux';
3
+
4
+ import type { RootState, Store } from './configure';
5
+
6
+ type AppDispatch = Store['dispatch'];
7
+
8
+ const useTypedDispatch: () => AppDispatch = useDispatch;
9
+ const useTypedStore = useStore as () => Store;
10
+ const useTypedSelector: TypedUseSelectorHook<RootState> = useSelector;
11
+
12
+ const createTypedSelector = <TResult>(selector: Selector<RootState, TResult>) =>
13
+ createSelector((state: RootState) => state, selector);
14
+
15
+ export { useTypedDispatch, useTypedStore, useTypedSelector, createTypedSelector };
@@ -1,3 +1,2 @@
1
- export { useContentTypes } from './useContentTypes';
2
1
  export { default as useSettingsForm } from './useSettingsForm';
3
2
  export { default as useSettingsMenu } from './useSettingsMenu';
@@ -1,32 +1,55 @@
1
1
  import * as React from 'react';
2
2
 
3
3
  import { useAPIErrorHandler, useFetchClient, useNotification } from '@strapi/helper-plugin';
4
+ import { AxiosError } from 'axios';
4
5
  import { useQueries } from 'react-query';
5
6
 
7
+ import { Component, ContentType } from '../../../shared/schema';
8
+ import { APIResponse } from '../types/adminAPI';
9
+
6
10
  export function useContentTypes() {
7
11
  const { get } = useFetchClient();
8
12
  const { formatAPIError } = useAPIErrorHandler();
9
13
  const toggleNotification = useNotification();
10
- const queries = useQueries(
11
- ['components', 'content-types'].map((type) => {
12
- return {
13
- queryKey: ['content-manager', type],
14
- async queryFn() {
15
- const {
16
- data: { data },
17
- } = await get(`/content-manager/${type}`);
18
-
19
- return data;
20
- },
21
- onError(error) {
14
+ const queries = useQueries([
15
+ {
16
+ queryKey: ['content-manager', 'components'],
17
+ async queryFn() {
18
+ const {
19
+ data: { data },
20
+ } = await get<APIResponse<Component[]>>(`/content-manager/components`);
21
+
22
+ return data;
23
+ },
24
+ onError(error: unknown) {
25
+ if (error instanceof AxiosError) {
26
+ toggleNotification({
27
+ type: 'warning',
28
+ message: formatAPIError(error),
29
+ });
30
+ }
31
+ },
32
+ },
33
+
34
+ {
35
+ queryKey: ['content-manager', 'content-types'],
36
+ async queryFn() {
37
+ const {
38
+ data: { data },
39
+ } = await get<APIResponse<ContentType[]>>(`/content-manager/content-types`);
40
+
41
+ return data;
42
+ },
43
+ onError(error: unknown) {
44
+ if (error instanceof AxiosError) {
22
45
  toggleNotification({
23
46
  type: 'warning',
24
47
  message: formatAPIError(error),
25
48
  });
26
- },
27
- };
28
- })
29
- );
49
+ }
50
+ },
51
+ },
52
+ ]);
30
53
 
31
54
  const [components, contentTypes] = queries;
32
55
  const isLoading = components.isLoading || contentTypes.isLoading;
@@ -1,13 +1,25 @@
1
1
  import { useEffect, useReducer } from 'react';
2
2
 
3
- import { useFetchClient, useNotification, useOverlayBlocker } from '@strapi/helper-plugin';
3
+ import { getYupInnerErrors, useFetchClient, useNotification, useOverlayBlocker } from '@strapi/helper-plugin';
4
4
  import omit from 'lodash/omit';
5
5
 
6
- import { checkFormValidity, formatAPIErrors } from '../../utils';
6
+ import { formatAPIErrors } from '../../utils/formatAPIErrors';
7
7
 
8
8
  import init from './init';
9
9
  import { initialState, reducer } from './reducer';
10
10
 
11
+ const checkFormValidity = async (data, schema) => {
12
+ let errors = null;
13
+
14
+ try {
15
+ await schema.validate(data, { abortEarly: false });
16
+ } catch (err) {
17
+ errors = getYupInnerErrors(err);
18
+ }
19
+
20
+ return errors;
21
+ };
22
+
11
23
  /**
12
24
  * TODO: refactor this, it's confusing and hard to read.
13
25
  * It's also only used in `Settings/pages/SingleSignOn` so it can
@@ -21,6 +21,34 @@ export const LINKS_CE = {
21
21
  to: '/settings/transfer-tokens?sort=name:ASC',
22
22
  id: 'transfer-tokens',
23
23
  },
24
+ // If the Enterprise feature is not enabled and if the config doesn't disable it, we promote the Enterprise feature by displaying them in the settings menu.
25
+ // Disable this by adding "promoteEE: false" to your `./config/admin.js` file
26
+ ...(!window.strapi.features.isEnabled(window.strapi.features.SSO) &&
27
+ window.strapi?.flags?.promoteEE
28
+ ? [
29
+ {
30
+ intlLabel: { id: 'Settings.sso.title', defaultMessage: 'Single Sign-On' },
31
+ to: '/settings/purchase-single-sign-on',
32
+ id: 'sso',
33
+ lockIcon: true,
34
+ },
35
+ ]
36
+ : []),
37
+
38
+ ...(!window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS) &&
39
+ window.strapi?.flags?.promoteEE
40
+ ? [
41
+ {
42
+ intlLabel: {
43
+ id: 'Settings.review-workflows.page.title',
44
+ defaultMessage: 'Review Workflows',
45
+ },
46
+ to: '/settings/purchase-review-workflows',
47
+ id: 'review-workflows',
48
+ lockIcon: true,
49
+ },
50
+ ]
51
+ : []),
24
52
  ],
25
53
 
26
54
  admin: [
@@ -35,5 +63,16 @@ export const LINKS_CE = {
35
63
  to: '/settings/users?pageSize=10&page=1&sort=firstname',
36
64
  id: 'users',
37
65
  },
66
+ ...(!window.strapi.features.isEnabled(window.strapi.features.AUDIT_LOGS) &&
67
+ window.strapi?.flags?.promoteEE
68
+ ? [
69
+ {
70
+ intlLabel: { id: 'global.auditLogs', defaultMessage: 'Audit Logs' },
71
+ to: '/settings/purchase-audit-logs',
72
+ id: 'auditLogs',
73
+ lockIcon: true,
74
+ },
75
+ ]
76
+ : []),
38
77
  ],
39
78
  };
@@ -2,10 +2,9 @@ import { getFetchClient } from '@strapi/helper-plugin';
2
2
  import { createRoot } from 'react-dom/client';
3
3
 
4
4
  import appCustomisations from './app';
5
- import { Components, Fields, Middlewares, Reducers } from './core/apis';
5
+ import { Components, Fields, Middlewares } from './core/apis';
6
6
  // eslint-disable-next-line import/extensions
7
7
  import plugins from './plugins';
8
- import appReducers from './reducers';
9
8
 
10
9
  window.strapi = {
11
10
  /**
@@ -25,6 +24,7 @@ window.strapi = {
25
24
  projectType: 'Community',
26
25
  flags: {
27
26
  nps: false,
27
+ promoteEE: true,
28
28
  },
29
29
  };
30
30
 
@@ -35,7 +35,6 @@ const library = {
35
35
  fields: Fields(),
36
36
  };
37
37
  const middlewares = Middlewares();
38
- const reducers = Reducers({ appReducers });
39
38
 
40
39
  const MOUNT_NODE = document.getElementById('app');
41
40
 
@@ -69,7 +68,6 @@ const run = async () => {
69
68
  adminConfig: customConfig,
70
69
  bootstrap: customConfig,
71
70
  middlewares,
72
- reducers,
73
71
  });
74
72
 
75
73
  await app.bootstrapAdmin();
@@ -1,7 +1,6 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
2
 
3
3
  import { Box, Flex, SkipToContent } from '@strapi/design-system';
4
- import PropTypes from 'prop-types';
5
4
  import { useIntl } from 'react-intl';
6
5
  import styled from 'styled-components';
7
6
 
@@ -9,7 +8,12 @@ const FlexBox = styled(Box)`
9
8
  flex: 1;
10
9
  `;
11
10
 
12
- const AppLayout = ({ children, sideNav }) => {
11
+ interface AppLayoutProps {
12
+ children: React.ReactNode;
13
+ sideNav: React.ReactNode;
14
+ }
15
+
16
+ export const AppLayout = ({ children, sideNav }: AppLayoutProps) => {
13
17
  const { formatMessage } = useIntl();
14
18
 
15
19
  return (
@@ -24,10 +28,3 @@ const AppLayout = ({ children, sideNav }) => {
24
28
  </Box>
25
29
  );
26
30
  };
27
-
28
- AppLayout.propTypes = {
29
- children: PropTypes.node.isRequired,
30
- sideNav: PropTypes.node.isRequired,
31
- };
32
-
33
- export default AppLayout;
@@ -0,0 +1,77 @@
1
+ import * as React from 'react';
2
+
3
+ import { Box, Flex, SingleSelect, SingleSelectOption } from '@strapi/design-system';
4
+ import { useIntl } from 'react-intl';
5
+ import styled from 'styled-components';
6
+
7
+ import { useLocales } from '../components/LanguageProvider';
8
+
9
+ const Wrapper = styled(Box)`
10
+ margin: 0 auto;
11
+ width: 552px;
12
+ `;
13
+
14
+ export const Column = styled(Flex)`
15
+ flex-direction: column;
16
+ `;
17
+
18
+ const LocaleToggle = () => {
19
+ const { changeLocale, localeNames } = useLocales();
20
+ const { formatMessage, locale } = useIntl();
21
+
22
+ return (
23
+ <SingleSelect
24
+ aria-label={formatMessage({
25
+ id: 'global.localeToggle.label',
26
+ defaultMessage: 'Select interface language',
27
+ })}
28
+ value={locale}
29
+ onChange={(language) => {
30
+ changeLocale(language as string);
31
+ }}
32
+ >
33
+ {Object.entries(localeNames).map(([language, name]) => (
34
+ <SingleSelectOption key={language} value={language}>
35
+ {name}
36
+ </SingleSelectOption>
37
+ ))}
38
+ </SingleSelect>
39
+ );
40
+ };
41
+
42
+ interface LayoutContentProps {
43
+ children: React.ReactNode;
44
+ }
45
+
46
+ export const LayoutContent = ({ children }: LayoutContentProps) => (
47
+ <Wrapper
48
+ shadow="tableShadow"
49
+ hasRadius
50
+ paddingTop={9}
51
+ paddingBottom={9}
52
+ paddingLeft={10}
53
+ paddingRight={10}
54
+ background="neutral0"
55
+ >
56
+ {children}
57
+ </Wrapper>
58
+ );
59
+
60
+ interface UnauthenticatedLayoutProps {
61
+ children: React.ReactNode;
62
+ }
63
+
64
+ export const UnauthenticatedLayout = ({ children }: UnauthenticatedLayoutProps) => {
65
+ return (
66
+ <div>
67
+ <Flex as="header" justifyContent="flex-end">
68
+ <Box paddingTop={6} paddingRight={8}>
69
+ <LocaleToggle />
70
+ </Box>
71
+ </Flex>
72
+ <Box paddingTop={2} paddingBottom={11}>
73
+ {children}
74
+ </Box>
75
+ </div>
76
+ );
77
+ };