@strapi/admin 4.14.4 → 4.14.5

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 (235) hide show
  1. package/admin/.eslintrc.js +12 -0
  2. package/admin/custom.d.ts +20 -0
  3. package/admin/src/StrapiApp.js +14 -16
  4. package/admin/src/components/AuthenticatedApp/index.js +4 -4
  5. package/admin/src/components/ConfigurationProvider.tsx +67 -0
  6. package/admin/src/components/LanguageProvider.tsx +129 -0
  7. package/admin/src/components/{LeftMenu/index.js → LeftMenu.tsx} +23 -18
  8. package/admin/src/components/{NpsSurvey/index.js → NpsSurvey.tsx} +68 -21
  9. package/admin/src/components/PluginsInitializer.tsx +124 -0
  10. package/admin/src/components/Providers/index.js +6 -6
  11. package/admin/src/components/UnauthenticatedLogo.tsx +2 -2
  12. package/admin/src/components/{LocalesProvider/__mocks__/useLocalesProvider.js → __mocks__/LanguageProvider.js} +1 -1
  13. package/admin/src/content-manager/components/BlocksEditor/BlocksInput/index.js +48 -8
  14. package/admin/src/content-manager/components/BlocksEditor/Toolbar/index.js +146 -68
  15. package/admin/src/content-manager/components/BlocksEditor/hooks/useBlocksStore.js +50 -47
  16. package/admin/src/content-manager/components/BlocksEditor/hooks/useModifiersStore.js +11 -9
  17. package/admin/src/content-manager/components/BlocksEditor/index.js +1 -14
  18. package/admin/src/contexts/admin.ts +18 -0
  19. package/admin/src/contexts/configuration.ts +14 -4
  20. package/admin/src/hooks/__mocks__/useConfigurations.ts +2 -2
  21. package/admin/src/hooks/index.js +0 -3
  22. package/admin/src/hooks/{useAdminRoles/index.js → useAdminRoles.ts} +26 -10
  23. package/admin/src/hooks/useAdminUsers.ts +64 -0
  24. package/admin/src/hooks/useConfiguration.ts +5 -0
  25. package/admin/src/hooks/{useEnterprise/useEnterprise.js → useEnterprise.ts} +15 -5
  26. package/admin/src/hooks/useMenu.ts +153 -0
  27. package/admin/src/index.js +5 -2
  28. package/admin/src/layouts/UnauthenticatedLayout/LocaleToggle/index.js +2 -2
  29. package/admin/src/pages/Admin/index.js +4 -3
  30. package/admin/src/pages/App/index.js +5 -3
  31. package/admin/src/pages/AuthPage/components/Register/index.js +28 -33
  32. package/admin/src/pages/AuthPage/index.js +2 -2
  33. package/admin/src/pages/ProfilePage/index.js +2 -2
  34. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +119 -87
  35. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/CustomizationInfos/index.js +2 -2
  36. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +2 -2
  37. package/admin/src/pages/SettingsPage/pages/Roles/CreatePage/index.js +1 -1
  38. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/index.js +1 -1
  39. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +1 -1
  40. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/index.js +1 -1
  41. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/SubActionRow/index.js +1 -1
  42. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/GlobalActions/index.js +1 -1
  43. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PermissionsDataManagerProvider/index.js +1 -1
  44. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PluginsAndSettings/SubCategory/index.js +1 -1
  45. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/hooks/usePermissionsDataManager.ts +28 -0
  46. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +1 -1
  47. package/admin/src/{hooks/useAdminRolePermissions/index.js → pages/SettingsPage/pages/Roles/hooks/useAdminRolePermissions.ts} +13 -6
  48. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +3 -5
  49. package/admin/src/shared/hooks/index.js +0 -1
  50. package/admin/src/shared/hooks/useInjectionZone/index.js +2 -2
  51. package/admin/src/types/adminAPI.ts +29 -0
  52. package/admin/src/utils/createRoute.js +4 -1
  53. package/admin/tsconfig.build.json +4 -0
  54. package/admin/tsconfig.json +7 -1
  55. package/build/{1049.f7aed23d.chunk.js → 1049.9236e785.chunk.js} +1 -1
  56. package/build/1222.fe92c653.chunk.js +35 -0
  57. package/build/{1227.f9c74718.chunk.js → 1227.e0f7447b.chunk.js} +1 -1
  58. package/build/135.ad267b59.chunk.js +1 -0
  59. package/build/{1386.6b8819c6.chunk.js → 1386.07f2bbb3.chunk.js} +1 -1
  60. package/build/1835.eaa696ba.chunk.js +1 -0
  61. package/build/{2225.d1bcf7e3.chunk.js → 2225.a2147b8f.chunk.js} +2 -2
  62. package/build/2325.d705b39a.chunk.js +1 -0
  63. package/build/2379.b0bc4013.chunk.js +1 -0
  64. package/build/{2395.aca6ce66.chunk.js → 2395.d37b1025.chunk.js} +1 -1
  65. package/build/2421.79e5b3d0.chunk.js +1 -0
  66. package/build/267.073a3bcb.chunk.js +1 -0
  67. package/build/2801.12522720.chunk.js +1 -0
  68. package/build/2878.145ebf7c.chunk.js +1 -0
  69. package/build/2950.216f2e89.chunk.js +1 -0
  70. package/build/2953.284a63c0.chunk.js +1 -0
  71. package/build/{8743.31c921b1.chunk.js → 3019.0d74d080.chunk.js} +123 -139
  72. package/build/3021.33ad47fb.chunk.js +103 -0
  73. package/build/{3483.5df8e010.chunk.js → 3483.8f1b25f8.chunk.js} +1 -1
  74. package/build/3911.488fbde3.chunk.js +95 -0
  75. package/build/{4174.df9aa09a.chunk.js → 4174.2c4f958e.chunk.js} +1 -1
  76. package/build/4429.7f044dc7.chunk.js +1 -0
  77. package/build/4555.c883d697.chunk.js +1 -0
  78. package/build/4663.b906cc10.chunk.js +1 -0
  79. package/build/4916.480053a6.chunk.js +1 -0
  80. package/build/4996.d285c30b.chunk.js +1 -0
  81. package/build/502.b845473a.chunk.js +1 -0
  82. package/build/5858.493b31ec.chunk.js +1 -0
  83. package/build/6345.334e7678.chunk.js +1 -0
  84. package/build/6373.1a21d665.chunk.js +105 -0
  85. package/build/6453.4160b5b7.chunk.js +1 -0
  86. package/build/7448.6fd14dd3.chunk.js +1 -0
  87. package/build/7464.91341b4f.chunk.js +1 -0
  88. package/build/7735.9e7c9fdd.chunk.js +10 -0
  89. package/build/782.7243b183.chunk.js +1 -0
  90. package/build/7849.2a500ed8.chunk.js +1 -0
  91. package/build/7897.dffa5ad5.chunk.js +6 -0
  92. package/build/8162.7d1100a0.chunk.js +1 -0
  93. package/build/{8276.d4426fd8.chunk.js → 8276.e9698944.chunk.js} +2 -2
  94. package/build/8894.5ca4852a.chunk.js +26 -0
  95. package/build/8980.f0045cc1.chunk.js +1 -0
  96. package/build/9153.42c1428a.chunk.js +1 -0
  97. package/build/{9218.8bc01ab9.chunk.js → 9218.306ad178.chunk.js} +1 -1
  98. package/build/9285.5f174057.chunk.js +1 -0
  99. package/build/9302.550cf5b7.chunk.js +146 -0
  100. package/build/9547.62987774.chunk.js +1 -0
  101. package/build/9754.b4e73779.chunk.js +1 -0
  102. package/build/Admin-authenticatedApp.e897fccb.chunk.js +79 -0
  103. package/build/{Admin_InternalErrorPage.b66ee9c1.chunk.js → Admin_InternalErrorPage.e2431a95.chunk.js} +1 -1
  104. package/build/Admin_homePage.71ef8d06.chunk.js +81 -0
  105. package/build/{Admin_marketplace.31b962b8.chunk.js → Admin_marketplace.0db78604.chunk.js} +1 -1
  106. package/build/{Admin_pluginsPage.9217101d.chunk.js → Admin_pluginsPage.1083f7f0.chunk.js} +1 -1
  107. package/build/{Admin_profilePage.680123d9.chunk.js → Admin_profilePage.61704b7d.chunk.js} +2 -2
  108. package/build/Admin_settingsPage.39cb9fca.chunk.js +111 -0
  109. package/build/{Upload_ConfigureTheView.b40eea4d.chunk.js → Upload_ConfigureTheView.3cfeb108.chunk.js} +1 -1
  110. package/build/admin-app.06f5e70a.chunk.js +69 -0
  111. package/build/admin-edit-roles-page.556fac52.chunk.js +267 -0
  112. package/build/admin-edit-users.64fd1318.chunk.js +10 -0
  113. package/build/admin-roles-list.15918328.chunk.js +22 -0
  114. package/build/admin-users.74fddc87.chunk.js +11 -0
  115. package/build/{api-tokens-create-page.0dd63e91.chunk.js → api-tokens-create-page.c08ae118.chunk.js} +1 -1
  116. package/build/{api-tokens-edit-page.78d877f8.chunk.js → api-tokens-edit-page.ce18efdc.chunk.js} +1 -1
  117. package/build/api-tokens-list-page.783b7569.chunk.js +16 -0
  118. package/build/audit-logs-settings-page.12aeea8c.chunk.js +1 -0
  119. package/build/content-manager.2e3f660b.chunk.js +1220 -0
  120. package/build/{content-type-builder-list-view.3fffae65.chunk.js → content-type-builder-list-view.38ed3935.chunk.js} +7 -7
  121. package/build/{content-type-builder.98c71164.chunk.js → content-type-builder.758a9d23.chunk.js} +4 -4
  122. package/build/email-settings-page.e08a587e.chunk.js +11 -0
  123. package/build/{i18n-settings-page.a9708926.chunk.js → i18n-settings-page.3186e3e9.chunk.js} +1 -1
  124. package/build/index.html +1 -1
  125. package/build/main.00ea6f5a.js +2665 -0
  126. package/build/{review-workflows-settings-create-view.b7b0c6c5.chunk.js → review-workflows-settings-create-view.5cdc4d64.chunk.js} +1 -1
  127. package/build/{review-workflows-settings-edit-view.c331b3fe.chunk.js → review-workflows-settings-edit-view.53bf7865.chunk.js} +1 -1
  128. package/build/review-workflows-settings-list-view.b4a8aefb.chunk.js +56 -0
  129. package/build/runtime~main.e3bf3980.js +2 -0
  130. package/build/sso-settings-page.6a35d473.chunk.js +1 -0
  131. package/build/{transfer-tokens-create-page.e7f541d3.chunk.js → transfer-tokens-create-page.2662d519.chunk.js} +1 -1
  132. package/build/{transfer-tokens-edit-page.bd1276c2.chunk.js → transfer-tokens-edit-page.f64d8d8c.chunk.js} +1 -1
  133. package/build/transfer-tokens-list-page.e6fd5f87.chunk.js +16 -0
  134. package/build/{upload-settings.97ef4c92.chunk.js → upload-settings.450a1de0.chunk.js} +1 -1
  135. package/build/{upload.f08715a1.chunk.js → upload.0d53e7a3.chunk.js} +1 -1
  136. package/build/{users-advanced-settings-page.36a3c363.chunk.js → users-advanced-settings-page.4a1f1f6d.chunk.js} +1 -1
  137. package/build/users-email-settings-page.ea81fe82.chunk.js +9 -0
  138. package/build/users-providers-settings-page.10280cdb.chunk.js +14 -0
  139. package/build/{users-roles-settings-page.d5a8e8a1.chunk.js → users-roles-settings-page.4a7158be.chunk.js} +1 -1
  140. package/build/{webhook-edit-page.87456194.chunk.js → webhook-edit-page.65ac30ee.chunk.js} +2 -2
  141. package/build/{webhook-list-page.c88a382b.chunk.js → webhook-list-page.f57285ca.chunk.js} +1 -1
  142. package/jest.config.front.js +4 -0
  143. package/package.json +23 -17
  144. package/scripts/build.js +1 -1
  145. package/server/controllers/admin.js +3 -2
  146. package/shared/entities.ts +33 -0
  147. package/shared/permissions.ts +52 -0
  148. package/admin/src/components/ConfigurationsProvider/index.js +0 -66
  149. package/admin/src/components/ConfigurationsProvider/reducer.js +0 -29
  150. package/admin/src/components/LanguageProvider/index.js +0 -54
  151. package/admin/src/components/LanguageProvider/init.js +0 -13
  152. package/admin/src/components/LanguageProvider/reducer.js +0 -30
  153. package/admin/src/components/LanguageProvider/utils/localStorageKey.js +0 -3
  154. package/admin/src/components/LocalesProvider/context.js +0 -5
  155. package/admin/src/components/LocalesProvider/index.js +0 -21
  156. package/admin/src/components/LocalesProvider/useLocalesProvider.js +0 -11
  157. package/admin/src/components/NpsSurvey/hooks/useNpsSurveySettings.js +0 -17
  158. package/admin/src/components/PluginsInitializer/index.js +0 -68
  159. package/admin/src/components/PluginsInitializer/init.js +0 -11
  160. package/admin/src/components/PluginsInitializer/reducer.js +0 -22
  161. package/admin/src/contexts/Admin/index.js +0 -5
  162. package/admin/src/contexts/MarketPlace/index.js +0 -18
  163. package/admin/src/contexts/PermisssionsDataManagerContext/index.js +0 -5
  164. package/admin/src/contexts/index.js +0 -3
  165. package/admin/src/hooks/useAdminRoles/__mocks__/index.js +0 -5
  166. package/admin/src/hooks/useAdminUsers/index.js +0 -1
  167. package/admin/src/hooks/useAdminUsers/useAdminUsers.js +0 -47
  168. package/admin/src/hooks/useConfigurations.ts +0 -5
  169. package/admin/src/hooks/useEnterprise/index.js +0 -1
  170. package/admin/src/hooks/useMenu/index.js +0 -86
  171. package/admin/src/hooks/useMenu/utils/checkPermissions.js +0 -13
  172. package/admin/src/hooks/useMenu/utils/getGeneralLinks.js +0 -31
  173. package/admin/src/hooks/useMenu/utils/getPluginSectionLinks.js +0 -17
  174. package/admin/src/hooks/usePermissionsDataManager/index.js +0 -7
  175. package/admin/src/shared/hooks/useAdminProvider/index.js +0 -11
  176. package/build/2224.8af54440.chunk.js +0 -138
  177. package/build/2379.f0baf826.chunk.js +0 -1
  178. package/build/2421.a478ba24.chunk.js +0 -105
  179. package/build/2801.c49f88a1.chunk.js +0 -1
  180. package/build/3911.d4fada48.chunk.js +0 -95
  181. package/build/412.72afdf0c.chunk.js +0 -689
  182. package/build/502.8666bbef.chunk.js +0 -25
  183. package/build/5702.5b433d50.chunk.js +0 -1
  184. package/build/6186.c33ce082.chunk.js +0 -116
  185. package/build/6715.48e37308.chunk.js +0 -1
  186. package/build/6812.00ef5b0d.chunk.js +0 -26
  187. package/build/7464.43a4527c.chunk.js +0 -1
  188. package/build/7818.d2196a53.chunk.js +0 -29
  189. package/build/7897.5c03247b.chunk.js +0 -25
  190. package/build/8690.33243bba.chunk.js +0 -38
  191. package/build/Admin-authenticatedApp.27545a1b.chunk.js +0 -112
  192. package/build/Admin_homePage.a6281dd6.chunk.js +0 -124
  193. package/build/Admin_settingsPage.33378310.chunk.js +0 -111
  194. package/build/admin-app.e8c52c37.chunk.js +0 -36
  195. package/build/admin-edit-roles-page.fcf056bf.chunk.js +0 -275
  196. package/build/admin-edit-users.89efe3c4.chunk.js +0 -10
  197. package/build/admin-roles-list.8b77704a.chunk.js +0 -22
  198. package/build/admin-users.e3f1be14.chunk.js +0 -19
  199. package/build/api-tokens-list-page.ae13346c.chunk.js +0 -16
  200. package/build/audit-logs-settings-page.e9c92a75.chunk.js +0 -9
  201. package/build/content-manager.5849dbe3.chunk.js +0 -1226
  202. package/build/email-settings-page.ecfec9b3.chunk.js +0 -11
  203. package/build/email-translation-ar-json.88304564.chunk.js +0 -1
  204. package/build/email-translation-cs-json.6eaeec6a.chunk.js +0 -1
  205. package/build/email-translation-de-json.1b334230.chunk.js +0 -1
  206. package/build/email-translation-dk-json.85402492.chunk.js +0 -1
  207. package/build/email-translation-en-json.4211d4d0.chunk.js +0 -1
  208. package/build/email-translation-es-json.0b6b1006.chunk.js +0 -1
  209. package/build/email-translation-fr-json.78be2787.chunk.js +0 -1
  210. package/build/email-translation-id-json.c97239fe.chunk.js +0 -1
  211. package/build/email-translation-it-json.a2ed8c78.chunk.js +0 -1
  212. package/build/email-translation-ja-json.63eebd02.chunk.js +0 -1
  213. package/build/email-translation-ko-json.4de49b23.chunk.js +0 -1
  214. package/build/email-translation-ms-json.7390477e.chunk.js +0 -1
  215. package/build/email-translation-nl-json.377bdd9f.chunk.js +0 -1
  216. package/build/email-translation-pl-json.97d0db97.chunk.js +0 -1
  217. package/build/email-translation-pt-BR-json.81cca553.chunk.js +0 -1
  218. package/build/email-translation-pt-json.2a2a0643.chunk.js +0 -1
  219. package/build/email-translation-ru-json.6bce37dd.chunk.js +0 -1
  220. package/build/email-translation-sk-json.53da2fcd.chunk.js +0 -1
  221. package/build/email-translation-th-json.660fa9a8.chunk.js +0 -1
  222. package/build/email-translation-tr-json.e6c0f8fc.chunk.js +0 -1
  223. package/build/email-translation-uk-json.bd1fb6bf.chunk.js +0 -1
  224. package/build/email-translation-vi-json.9fb7e6d7.chunk.js +0 -1
  225. package/build/email-translation-zh-Hans-json.c6841563.chunk.js +0 -1
  226. package/build/email-translation-zh-json.7a2232ea.chunk.js +0 -1
  227. package/build/main.3abb6f34.js +0 -3278
  228. package/build/review-workflows-settings-list-view.70218dc1.chunk.js +0 -75
  229. package/build/runtime~main.450561b1.js +0 -2
  230. package/build/sso-settings-page.1a9e7f8f.chunk.js +0 -1
  231. package/build/transfer-tokens-list-page.5de6bb9f.chunk.js +0 -16
  232. package/build/users-email-settings-page.47b47962.chunk.js +0 -149
  233. package/build/users-providers-settings-page.1e0c8376.chunk.js +0 -154
  234. /package/admin/src/hooks/{useAdminUsers/__mocks__/index.js → __mocks__/useAdminUsers.ts} +0 -0
  235. /package/admin/src/{hooks/useAdminRolePermissions/__mocks__/index.js → pages/SettingsPage/pages/Roles/hooks/__mocks__/useAdminRolePermissions.ts} +0 -0
@@ -37,6 +37,10 @@ import styled, { css } from 'styled-components';
37
37
  import { composeRefs } from '../../../utils';
38
38
  import { editLink, removeLink } from '../utils/links';
39
39
 
40
+ const StyledBaseLink = styled(BaseLink)`
41
+ text-decoration: none;
42
+ `;
43
+
40
44
  const H1 = styled(Typography).attrs({ as: 'h1' })`
41
45
  font-size: ${42 / 16}rem;
42
46
  line-height: ${({ theme }) => theme.lineHeights[1]};
@@ -67,33 +71,6 @@ const H6 = styled(Typography).attrs({ as: 'h6' })`
67
71
  line-height: ${({ theme }) => theme.lineHeights[1]};
68
72
  `;
69
73
 
70
- const Heading = ({ attributes, children, element }) => {
71
- switch (element.level) {
72
- case 1:
73
- return <H1 {...attributes}>{children}</H1>;
74
- case 2:
75
- return <H2 {...attributes}>{children}</H2>;
76
- case 3:
77
- return <H3 {...attributes}>{children}</H3>;
78
- case 4:
79
- return <H4 {...attributes}>{children}</H4>;
80
- case 5:
81
- return <H5 {...attributes}>{children}</H5>;
82
- case 6:
83
- return <H6 {...attributes}>{children}</H6>;
84
- default: // do nothing
85
- return null;
86
- }
87
- };
88
-
89
- Heading.propTypes = {
90
- attributes: PropTypes.object.isRequired,
91
- children: PropTypes.node.isRequired,
92
- element: PropTypes.shape({
93
- level: PropTypes.oneOf([1, 2, 3, 4, 5, 6]).isRequired,
94
- }).isRequired,
95
- };
96
-
97
74
  const CodeBlock = styled.pre.attrs({ role: 'code' })`
98
75
  border-radius: ${({ theme }) => theme.borderRadius};
99
76
  background-color: ${({ theme }) => theme.colors.neutral100};
@@ -113,8 +90,9 @@ const CodeBlock = styled.pre.attrs({ role: 'code' })`
113
90
  const Blockquote = styled.blockquote.attrs({ role: 'blockquote' })`
114
91
  margin: ${({ theme }) => `${theme.spaces[4]} 0`};
115
92
  font-weight: ${({ theme }) => theme.fontWeights.regular};
116
- border-left: ${({ theme }) => `${theme.spaces[1]} solid ${theme.colors.neutral150}`};
93
+ border-left: ${({ theme }) => `${theme.spaces[1]} solid ${theme.colors.neutral200}`};
117
94
  padding: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[5]};
95
+ color: ${({ theme }) => theme.colors.neutral600};
118
96
  `;
119
97
 
120
98
  const listStyle = css`
@@ -227,8 +205,18 @@ const handleEnterKeyOnList = (editor) => {
227
205
  // Move the selection to the newly created paragraph
228
206
  Transforms.select(editor, createdParagraphPath);
229
207
  } else {
230
- // Otherwise just create a new list item by splitting the current one
231
- Transforms.splitNodes(editor, { always: true });
208
+ // Check if the cursor is at the end of the list item
209
+ const isNodeEnd = Editor.isEnd(editor, editor.selection.anchor, currentListItemPath);
210
+
211
+ if (isNodeEnd) {
212
+ // If there was nothing after the cursor, create a fresh new list item,
213
+ // in order to avoid carrying over the modifiers from the previous list item
214
+ Transforms.insertNodes(editor, { type: 'list-item', children: [{ type: 'text', text: '' }] });
215
+ } else {
216
+ // If there is something after the cursor, split the current list item,
217
+ // so that we keep the content and the modifiers
218
+ Transforms.splitNodes(editor);
219
+ }
232
220
  }
233
221
  };
234
222
 
@@ -320,7 +308,7 @@ const Link = React.forwardRef(({ element, children, ...attributes }, forwardedRe
320
308
 
321
309
  return (
322
310
  <>
323
- <BaseLink
311
+ <StyledBaseLink
324
312
  {...attributes}
325
313
  ref={composedRefs}
326
314
  href={element.url}
@@ -328,7 +316,7 @@ const Link = React.forwardRef(({ element, children, ...attributes }, forwardedRe
328
316
  color="primary600"
329
317
  >
330
318
  {children}
331
- </BaseLink>
319
+ </StyledBaseLink>
332
320
  {popoverOpen && (
333
321
  <Popover source={linkRef} onDismiss={handleDismiss} padding={4} contentEditable={false}>
334
322
  {isEditing ? (
@@ -382,9 +370,11 @@ const Link = React.forwardRef(({ element, children, ...attributes }, forwardedRe
382
370
  ) : (
383
371
  <Flex direction="column" gap={4} alignItems="start" width="400px">
384
372
  <Typography>{elementText}</Typography>
385
- <BaseLink href={element.url} target="_blank" color="primary600">
386
- {element.url}
387
- </BaseLink>
373
+ <Typography>
374
+ <StyledBaseLink href={element.url} target="_blank" color="primary600">
375
+ {element.url}
376
+ </StyledBaseLink>
377
+ </Typography>
388
378
  <Flex justifyContent="end" width="100%" gap={2}>
389
379
  <IconButton
390
380
  icon={<Trash />}
@@ -461,13 +451,18 @@ export function useBlocksStore() {
461
451
  * after the cursor, while retaining all the children, modifiers etc.
462
452
  */
463
453
  Transforms.splitNodes(editor, {
464
- /**
465
- * Makes sure we always create a new node,
466
- * even if there's nothing to the right of the cursor in the node.
467
- */
454
+ // Makes sure we always create a new node,
455
+ // even if there's nothing to the right of the cursor in the node.
468
456
  always: true,
469
457
  });
470
458
 
459
+ // Check if the created node is empty (if there was no text after the cursor in the node)
460
+ // This lets us know if we need to carry over the modifiers from the previous node
461
+ const [, parentBlockPath] = Editor.above(editor, {
462
+ match: (n) => n.type !== 'text',
463
+ });
464
+ const isNodeEnd = Editor.isEnd(editor, editor.selection.anchor, parentBlockPath);
465
+
471
466
  /**
472
467
  * Delete and recreate the node that was created at the right of the cursor.
473
468
  * This is to avoid node pollution
@@ -481,12 +476,14 @@ export function useBlocksStore() {
481
476
  // Check if after the current position there is another node
482
477
  const hasNextNode = editor.children.length - anchorPathInitialPosition[0] > 1;
483
478
 
484
- // Insert the new node at the right position. The next line after the editor selection if present or otherwise at the end of the editor.
479
+ // Insert the new node at the right position.
480
+ // The next line after the editor selection if present or otherwise at the end of the editor.
485
481
  Transforms.insertNodes(
486
482
  editor,
487
483
  {
488
484
  type: 'paragraph',
489
- children: fragmentedNode.children,
485
+ // Don't carry over the modifiers from the previous node if there was no text after the cursor
486
+ children: isNodeEnd ? [{ type: 'text', text: '' }] : fragmentedNode.children,
490
487
  },
491
488
  {
492
489
  at: hasNextNode ? [anchorPathInitialPosition[0] + 1] : [editor.children.length],
@@ -503,7 +500,7 @@ export function useBlocksStore() {
503
500
  },
504
501
  },
505
502
  'heading-one': {
506
- renderElement: (props) => <Heading {...props} />,
503
+ renderElement: (props) => <H1 {...props.attributes}>{props.children}</H1>,
507
504
  icon: HeadingOne,
508
505
  label: {
509
506
  id: 'components.Blocks.blocks.heading1',
@@ -517,7 +514,7 @@ export function useBlocksStore() {
517
514
  isInBlocksSelector: true,
518
515
  },
519
516
  'heading-two': {
520
- renderElement: (props) => <Heading {...props} />,
517
+ renderElement: (props) => <H2 {...props.attributes}>{props.children}</H2>,
521
518
  icon: HeadingTwo,
522
519
  label: {
523
520
  id: 'components.Blocks.blocks.heading2',
@@ -531,7 +528,7 @@ export function useBlocksStore() {
531
528
  isInBlocksSelector: true,
532
529
  },
533
530
  'heading-three': {
534
- renderElement: (props) => <Heading {...props} />,
531
+ renderElement: (props) => <H3 {...props.attributes}>{props.children}</H3>,
535
532
  icon: HeadingThree,
536
533
  label: {
537
534
  id: 'components.Blocks.blocks.heading3',
@@ -545,7 +542,7 @@ export function useBlocksStore() {
545
542
  isInBlocksSelector: true,
546
543
  },
547
544
  'heading-four': {
548
- renderElement: (props) => <Heading {...props} />,
545
+ renderElement: (props) => <H4 {...props.attributes}>{props.children}</H4>,
549
546
  icon: HeadingFour,
550
547
  label: {
551
548
  id: 'components.Blocks.blocks.heading4',
@@ -559,7 +556,7 @@ export function useBlocksStore() {
559
556
  isInBlocksSelector: true,
560
557
  },
561
558
  'heading-five': {
562
- renderElement: (props) => <Heading {...props} />,
559
+ renderElement: (props) => <H5 {...props.attributes}>{props.children}</H5>,
563
560
  icon: HeadingFive,
564
561
  label: {
565
562
  id: 'components.Blocks.blocks.heading5',
@@ -573,7 +570,7 @@ export function useBlocksStore() {
573
570
  isInBlocksSelector: true,
574
571
  },
575
572
  'heading-six': {
576
- renderElement: (props) => <Heading {...props} />,
573
+ renderElement: (props) => <H6 {...props.attributes}>{props.children}</H6>,
577
574
  icon: HeadingSix,
578
575
  label: {
579
576
  id: 'components.Blocks.blocks.heading6',
@@ -690,6 +687,12 @@ export function useBlocksStore() {
690
687
  } else {
691
688
  // Otherwise insert a new line within the quote node
692
689
  Transforms.insertText(editor, '\n');
690
+
691
+ // If there's nothing after the cursor, disable modifiers
692
+ if (isNodeEnd) {
693
+ Editor.removeMark(editor, 'bold');
694
+ Editor.removeMark(editor, 'italic');
695
+ }
693
696
  }
694
697
  },
695
698
  },
@@ -4,27 +4,29 @@ import { Typography } from '@strapi/design-system';
4
4
  import { Bold, Italic, Underline, StrikeThrough, Code } from '@strapi/icons';
5
5
  import { Editor } from 'slate';
6
6
  import { useSlate } from 'slate-react';
7
- import styled from 'styled-components';
7
+ import styled, { css } from 'styled-components';
8
8
 
9
- const BoldText = styled(Typography).attrs({ fontWeight: 'bold' })`
9
+ const stylesToInherit = css`
10
10
  font-size: inherit;
11
11
  color: inherit;
12
+ line-height: inherit;
13
+ `;
14
+
15
+ const BoldText = styled(Typography).attrs({ fontWeight: 'bold' })`
16
+ ${stylesToInherit}
12
17
  `;
13
18
 
14
19
  const ItalicText = styled(Typography)`
15
20
  font-style: italic;
16
- font-size: inherit;
17
- color: inherit;
21
+ ${stylesToInherit}
18
22
  `;
19
23
 
20
24
  const UnderlineText = styled(Typography).attrs({ textDecoration: 'underline' })`
21
- font-size: inherit;
22
- color: inherit;
25
+ ${stylesToInherit}
23
26
  `;
24
27
 
25
28
  const StrikeThroughText = styled(Typography).attrs({ textDecoration: 'line-through' })`
26
- font-size: inherit;
27
- color: inherit;
29
+ ${stylesToInherit}
28
30
  `;
29
31
 
30
32
  const InlineCode = styled.code`
@@ -70,7 +72,7 @@ export function useModifiersStore() {
70
72
  * @param {string} name - The name of the modifier to toggle
71
73
  */
72
74
  const baseHandleToggle = (name) => {
73
- if (modifiers[name]) {
75
+ if (modifiers?.[name]) {
74
76
  Editor.removeMark(editor, name);
75
77
  } else {
76
78
  Editor.addMark(editor, name, true);
@@ -28,17 +28,6 @@ const EditorDivider = styled(Divider)`
28
28
  background: ${({ theme }) => theme.colors.neutral200};
29
29
  `;
30
30
 
31
- const Wrapper = styled(Box)`
32
- width: 100%;
33
- overflow: auto;
34
- padding: ${({ theme }) => `${theme.spaces[3]} ${theme.spaces[4]}`};
35
- font-size: ${({ theme }) => theme.fontSizes[2]};
36
- background-color: ${({ theme }) => theme.colors.neutral0};
37
- color: ${({ theme }) => theme.colors.neutral800};
38
- line-height: ${({ theme }) => theme.lineHeights[6]};
39
- border-radius: ${({ theme }) => theme.borderRadius};
40
- `;
41
-
42
31
  /**
43
32
  * Images are void elements. They handle the rendering of their children instead of Slate.
44
33
  * See the Slate documentation for more information:
@@ -164,9 +153,7 @@ const BlocksEditor = React.forwardRef(
164
153
  <InputWrapper direction="column" alignItems="flex-start" height="512px">
165
154
  <BlocksToolbar disabled={disabled} />
166
155
  <EditorDivider width="100%" />
167
- <Wrapper grow={1}>
168
- <BlocksInput disabled={disabled} placeholder={formattedPlaceholder} />
169
- </Wrapper>
156
+ <BlocksInput disabled={disabled} placeholder={formattedPlaceholder} />
170
157
  </InputWrapper>
171
158
  </Slate>
172
159
  <Hint hint={hint} name={name} error={error} />
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+
3
+ interface AdminContextValue {
4
+ /**
5
+ * TODO: this should come from `StrapiApp['getAdminInjectedComponents']`
6
+ */
7
+ getAdminInjectedComponents: () => unknown;
8
+ }
9
+
10
+ const AdminContext = React.createContext<AdminContextValue>({
11
+ getAdminInjectedComponents() {
12
+ throw new Error('AdminContext: getAdminInjectedComponents() not implemented');
13
+ },
14
+ });
15
+
16
+ const useAdmin = () => React.useContext(AdminContext);
17
+
18
+ export { AdminContext, useAdmin };
@@ -1,15 +1,25 @@
1
1
  import { createContext } from 'react';
2
2
 
3
- interface ConfigurationsContextValue {
3
+ export interface ConfigurationContextValue {
4
4
  logos: {
5
- auth: { custom?: string; default: string };
5
+ auth: { custom?: string | null; default: string };
6
+ menu: { custom?: string | null; default: string };
6
7
  };
8
+ showTutorials: boolean;
9
+ showReleaseNotification: boolean;
10
+ updateProjectSettings: (settings: { authLogo?: string; menuLogo?: string }) => void;
7
11
  }
8
12
 
9
- const ConfigurationsContext = createContext<ConfigurationsContextValue>({
13
+ const ConfigurationContext = createContext<ConfigurationContextValue>({
10
14
  logos: {
11
15
  auth: { default: '' },
16
+ menu: { default: '' },
17
+ },
18
+ showTutorials: false,
19
+ showReleaseNotification: false,
20
+ updateProjectSettings: () => {
21
+ throw new Error('updateProjectSettings was not implemented');
12
22
  },
13
23
  });
14
24
 
15
- export { ConfigurationsContext };
25
+ export { ConfigurationContext };
@@ -1,4 +1,4 @@
1
- const useConfigurations = () => {
1
+ const useConfiguration = () => {
2
2
  return {
3
3
  logos: {
4
4
  auth: { custom: 'customAuthLogo.png', default: 'defaultAuthLogo.png' },
@@ -6,4 +6,4 @@ const useConfigurations = () => {
6
6
  };
7
7
  };
8
8
 
9
- export { useConfigurations };
9
+ export { useConfiguration };
@@ -1,6 +1,3 @@
1
- export { useConfigurations } from './useConfigurations';
2
1
  export { useContentTypes } from './useContentTypes';
3
- export { default as useMenu } from './useMenu';
4
- export { default as usePermissionsDataManager } from './usePermissionsDataManager';
5
2
  export { default as useSettingsForm } from './useSettingsForm';
6
3
  export { default as useSettingsMenu } from './useSettingsMenu';
@@ -1,10 +1,18 @@
1
1
  import * as React from 'react';
2
2
 
3
3
  import { useCollator, useFetchClient } from '@strapi/helper-plugin';
4
+ import { Entity } from '@strapi/types';
4
5
  import { useIntl } from 'react-intl';
5
6
  import { useQuery } from 'react-query';
6
7
 
7
- export const useAdminRoles = (params = {}, queryOptions = {}) => {
8
+ import { RoleEntity } from '../../../shared/entities';
9
+ import { APIBaseParams, APIResponse } from '../types/adminAPI';
10
+
11
+ export interface APIRolesQueryParams extends APIBaseParams {
12
+ id?: null | Entity.ID;
13
+ }
14
+
15
+ export const useAdminRoles = (params: APIRolesQueryParams = {}, queryOptions = {}) => {
8
16
  const { id = '', ...queryParams } = params;
9
17
 
10
18
  const { get } = useFetchClient();
@@ -15,9 +23,15 @@ export const useAdminRoles = (params = {}, queryOptions = {}) => {
15
23
  const { data, error, isError, isLoading, refetch } = useQuery(
16
24
  ['roles', id, queryParams],
17
25
  async () => {
18
- const { data } = await get(`/admin/roles/${id ?? ''}`, {
19
- params: queryParams,
20
- });
26
+ /**
27
+ * TODO: can we infer if it's an array or not based on the appearance of `id`?
28
+ */
29
+ const { data } = await get<APIResponse<RoleEntity | RoleEntity[]>>(
30
+ `/admin/roles/${id ?? ''}`,
31
+ {
32
+ params: queryParams,
33
+ }
34
+ );
21
35
 
22
36
  return data;
23
37
  },
@@ -29,16 +43,18 @@ export const useAdminRoles = (params = {}, queryOptions = {}) => {
29
43
  // value, which later on triggers infinite loops if used in the
30
44
  // dependency arrays of other hooks
31
45
  const roles = React.useMemo(() => {
32
- let roles = [];
46
+ let roles: RoleEntity[] = [];
33
47
 
34
- if (id && data) {
35
- roles = [data.data];
36
- } else if (Array.isArray(data?.data)) {
37
- roles = data.data;
48
+ if (data) {
49
+ if (Array.isArray(data.data)) {
50
+ roles = data.data;
51
+ } else {
52
+ roles = [data.data];
53
+ }
38
54
  }
39
55
 
40
56
  return [...roles].sort((a, b) => formatter.compare(a.name, b.name));
41
- }, [data, id, formatter]);
57
+ }, [data, formatter]);
42
58
 
43
59
  return {
44
60
  roles,
@@ -0,0 +1,64 @@
1
+ import * as React from 'react';
2
+
3
+ import { useFetchClient } from '@strapi/helper-plugin';
4
+ import { Entity } from '@strapi/types';
5
+ import { useQuery } from 'react-query';
6
+
7
+ import { UserEntity } from '../../../shared/entities';
8
+ import { APIBaseParams, APIResponsePagination, APIResponseUsersLegacy } from '../types/adminAPI';
9
+
10
+ export interface APIUsersQueryParams extends APIBaseParams {
11
+ id?: null | Entity.ID;
12
+ }
13
+
14
+ export function useAdminUsers(params: APIUsersQueryParams = {}, queryOptions = {}) {
15
+ const { id = '', ...queryParams } = params;
16
+
17
+ const { get } = useFetchClient();
18
+
19
+ const { data, isError, isLoading, refetch } = useQuery(
20
+ ['users', id, queryParams],
21
+ async () => {
22
+ const {
23
+ data: { data },
24
+ } = await get<
25
+ APIResponseUsersLegacy<
26
+ UserEntity | { pagination: APIResponsePagination; results: UserEntity[] }
27
+ >
28
+ >(`/admin/users/${id}`, {
29
+ params: queryParams,
30
+ });
31
+
32
+ return data;
33
+ },
34
+ queryOptions
35
+ );
36
+
37
+ // the return value needs to be memoized, because intantiating
38
+ // an empty array as default value would lead to an unstable return
39
+ // value, which later on triggers infinite loops if used in the
40
+ // dependency arrays of other hooks
41
+ const users = React.useMemo(() => {
42
+ let users: UserEntity[] = [];
43
+
44
+ if (data) {
45
+ if ('results' in data) {
46
+ if (Array.isArray(data.results)) {
47
+ users = data.results;
48
+ }
49
+ } else {
50
+ users = [data];
51
+ }
52
+ }
53
+
54
+ return users;
55
+ }, [data]);
56
+
57
+ return {
58
+ users,
59
+ pagination: React.useMemo(() => (data && 'pagination' in data) ?? null, [data]),
60
+ isLoading,
61
+ isError,
62
+ refetch,
63
+ };
64
+ }
@@ -0,0 +1,5 @@
1
+ import { useContext } from 'react';
2
+
3
+ import { ConfigurationContext } from '../contexts/configuration';
4
+
5
+ export const useConfiguration = () => useContext(ConfigurationContext);
@@ -6,17 +6,27 @@ function isEnterprise() {
6
6
  return window.strapi.isEE;
7
7
  }
8
8
 
9
- export function useEnterprise(
10
- ceData,
11
- eeCallback,
12
- { defaultValue = null, combine = (ceData, eeData) => eeData, enabled = true } = {}
9
+ export interface UseEnterpriseOptions<TCEData, TEEData, TCombinedData> {
10
+ defaultValue?: TCEData | TEEData | null;
11
+ combine?: (ceData: TCEData, eeData: TEEData) => TCEData | TEEData | TCombinedData;
12
+ enabled?: boolean;
13
+ }
14
+
15
+ export function useEnterprise<TCEData, TEEData, TCombinedData = unknown>(
16
+ ceData: TCEData,
17
+ eeCallback: () => Promise<TEEData>,
18
+ {
19
+ defaultValue = null,
20
+ combine = (ceData: TCEData, eeData: TEEData) => eeData,
21
+ enabled = true,
22
+ }: UseEnterpriseOptions<TCEData, TEEData, TCombinedData> = {}
13
23
  ) {
14
24
  const eeCallbackRef = useCallbackRef(eeCallback);
15
25
  const combineCallbackRef = useCallbackRef(combine);
16
26
 
17
27
  // We have to use a nested object here, because functions (e.g. Components)
18
28
  // can not be stored as value directly
19
- const [{ data }, setData] = React.useState({
29
+ const [{ data }, setData] = React.useState<{ data: TCEData | TEEData | TCombinedData | null }>({
20
30
  data: isEnterprise() && enabled ? defaultValue : ceData,
21
31
  });
22
32
 
@@ -0,0 +1,153 @@
1
+ import * as React from 'react';
2
+
3
+ import {
4
+ Permission,
5
+ hasPermissions,
6
+ useAppInfo,
7
+ useRBACProvider,
8
+ useStrapiApp,
9
+ StrapiAppContextValue,
10
+ } from '@strapi/helper-plugin';
11
+ import { Cog, Puzzle, ShoppingCart } from '@strapi/icons';
12
+ import cloneDeep from 'lodash/cloneDeep';
13
+ import { useSelector } from 'react-redux';
14
+
15
+ // @ts-expect-error - no types, yet.
16
+ import { selectAdminPermissions } from '../pages/App/selectors';
17
+
18
+ /* -------------------------------------------------------------------------------------------------
19
+ * useMenu
20
+ * -----------------------------------------------------------------------------------------------*/
21
+
22
+ type MenuItem = StrapiAppContextValue['menu'][number];
23
+
24
+ export interface Menu {
25
+ generalSectionLinks: MenuItem[];
26
+ pluginsSectionLinks: MenuItem[];
27
+ isLoading: boolean;
28
+ }
29
+
30
+ const useMenu = () => {
31
+ const { allPermissions: userPermissions } = useRBACProvider();
32
+ const { shouldUpdateStrapi } = useAppInfo();
33
+ const { menu } = useStrapiApp();
34
+ const permissions = useSelector(selectAdminPermissions);
35
+ const [menuWithUserPermissions, setMenuWithUserPermissions] = React.useState<Menu>({
36
+ generalSectionLinks: [
37
+ {
38
+ icon: Puzzle,
39
+ intlLabel: {
40
+ id: 'global.plugins',
41
+ defaultMessage: 'Plugins',
42
+ },
43
+ to: '/list-plugins',
44
+ // @ts-expect-error - we need the permissions type from the plugin
45
+ permissions: permissions.marketplace.main,
46
+ },
47
+ {
48
+ icon: ShoppingCart,
49
+ intlLabel: {
50
+ id: 'global.marketplace',
51
+ defaultMessage: 'Marketplace',
52
+ },
53
+ to: '/marketplace',
54
+ // @ts-expect-error - we need the permissions type from the plugin
55
+ permissions: permissions.marketplace.main,
56
+ },
57
+ {
58
+ icon: Cog,
59
+ intlLabel: {
60
+ id: 'global.settings',
61
+ defaultMessage: 'Settings',
62
+ },
63
+ to: '/settings',
64
+ // Permissions of this link are retrieved in the init phase
65
+ // using the settings menu
66
+ permissions: [],
67
+ notificationsCount: 0,
68
+ },
69
+ ],
70
+ pluginsSectionLinks: [],
71
+ isLoading: true,
72
+ });
73
+ const generalSectionLinksRef = React.useRef(menuWithUserPermissions.generalSectionLinks);
74
+
75
+ React.useEffect(() => {
76
+ async function applyMenuPermissions() {
77
+ const authorizedPluginSectionLinks = await getPluginSectionLinks(userPermissions, menu);
78
+
79
+ const authorizedGeneralSectionLinks = await getGeneralLinks(
80
+ userPermissions,
81
+ generalSectionLinksRef.current,
82
+ shouldUpdateStrapi
83
+ );
84
+
85
+ setMenuWithUserPermissions((state) => ({
86
+ ...state,
87
+ generalSectionLinks: authorizedGeneralSectionLinks,
88
+ pluginsSectionLinks: authorizedPluginSectionLinks,
89
+ isLoading: false,
90
+ }));
91
+ }
92
+
93
+ applyMenuPermissions();
94
+ }, [
95
+ setMenuWithUserPermissions,
96
+ generalSectionLinksRef,
97
+ userPermissions,
98
+ menu,
99
+ permissions,
100
+ shouldUpdateStrapi,
101
+ ]);
102
+
103
+ return menuWithUserPermissions;
104
+ };
105
+
106
+ /* -------------------------------------------------------------------------------------------------
107
+ * Utils
108
+ * -----------------------------------------------------------------------------------------------*/
109
+
110
+ const getGeneralLinks = async (
111
+ userPermissions: Permission[],
112
+ generalSectionRawLinks: MenuItem[],
113
+ shouldUpdateStrapi: boolean = false
114
+ ) => {
115
+ const generalSectionLinksPermissions = await Promise.all(
116
+ generalSectionRawLinks.map(({ permissions }) => hasPermissions(userPermissions, permissions))
117
+ );
118
+
119
+ const authorizedGeneralSectionLinks = generalSectionRawLinks.filter(
120
+ (_, index) => generalSectionLinksPermissions[index]
121
+ );
122
+
123
+ const settingsLinkIndex = authorizedGeneralSectionLinks.findIndex(
124
+ (obj) => obj.to === '/settings'
125
+ );
126
+
127
+ if (settingsLinkIndex === -1) {
128
+ return [];
129
+ }
130
+
131
+ const authorizedGeneralLinksClone = cloneDeep(authorizedGeneralSectionLinks);
132
+
133
+ authorizedGeneralLinksClone[settingsLinkIndex].notificationsCount = shouldUpdateStrapi ? 1 : 0;
134
+
135
+ return authorizedGeneralLinksClone;
136
+ };
137
+
138
+ const getPluginSectionLinks = async (
139
+ userPermissions: Permission[],
140
+ pluginsSectionRawLinks: MenuItem[]
141
+ ) => {
142
+ const pluginSectionLinksPermissions = await Promise.all(
143
+ pluginsSectionRawLinks.map(({ permissions }) => hasPermissions(userPermissions, permissions))
144
+ );
145
+
146
+ const authorizedPluginSectionLinks = pluginsSectionRawLinks.filter(
147
+ (_, index) => pluginSectionLinksPermissions[index]
148
+ );
149
+
150
+ return authorizedPluginSectionLinks;
151
+ };
152
+
153
+ export { useMenu };