@strapi/admin 4.15.0-alpha.0 → 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 (472) hide show
  1. package/.eslintrc.js +4 -1
  2. package/admin/.eslintrc.js +28 -0
  3. package/admin/custom.d.ts +28 -0
  4. package/admin/src/StrapiApp.js +27 -28
  5. package/admin/src/components/AuthenticatedApp.tsx +187 -0
  6. package/admin/src/components/ConfigurationProvider.tsx +68 -0
  7. package/admin/src/components/{DragLayer/DragLayer.js → DragLayer.tsx} +18 -10
  8. package/admin/src/components/GuidedTour/Homepage.tsx +111 -0
  9. package/admin/src/components/GuidedTour/Modal.tsx +303 -0
  10. package/admin/src/components/GuidedTour/Ornaments.tsx +74 -0
  11. package/admin/src/components/GuidedTour/Provider.tsx +253 -0
  12. package/admin/src/components/GuidedTour/{layout.js → constants.ts} +13 -3
  13. package/admin/src/components/LanguageProvider.tsx +130 -0
  14. package/admin/src/components/{LeftMenu/index.js → LeftMenu.tsx} +23 -18
  15. package/admin/src/components/{NpsSurvey/index.js → NpsSurvey.tsx} +68 -21
  16. package/admin/src/components/PluginsInitializer.tsx +124 -0
  17. package/admin/src/components/PrivateRoute.tsx +42 -0
  18. package/admin/src/components/Providers.tsx +125 -0
  19. package/admin/src/components/RBACProvider.tsx +124 -0
  20. package/admin/src/components/Theme.tsx +41 -0
  21. package/admin/src/components/ThemeToggleProvider.tsx +64 -0
  22. package/admin/src/components/{UnauthenticatedLogo/index.js → UnauthenticatedLogo.tsx} +3 -5
  23. package/admin/src/components/{LocalesProvider/__mocks__/useLocalesProvider.js → __mocks__/LanguageProvider.ts} +3 -1
  24. package/admin/src/{constants.js → constants.ts} +48 -0
  25. package/admin/src/content-manager/components/BlocksEditor/BlocksInput/index.js +68 -9
  26. package/admin/src/content-manager/components/BlocksEditor/Toolbar/index.js +433 -202
  27. package/admin/src/content-manager/components/BlocksEditor/hooks/useBlocksStore.js +463 -135
  28. package/admin/src/content-manager/components/BlocksEditor/hooks/useModifiersStore.js +23 -6
  29. package/admin/src/content-manager/components/BlocksEditor/index.js +97 -20
  30. package/admin/src/content-manager/components/BlocksEditor/plugins/index.js +4 -0
  31. package/admin/src/content-manager/components/BlocksEditor/plugins/withLinks.js +61 -0
  32. package/admin/src/content-manager/components/BlocksEditor/plugins/withStrapiSchema.js +33 -0
  33. package/admin/src/content-manager/components/BlocksEditor/utils/links.js +90 -0
  34. package/admin/src/content-manager/components/InputUID/index.js +1 -1
  35. package/admin/src/content-manager/hooks/useAllowedAttributes.js +9 -1
  36. package/admin/src/content-manager/pages/App/selectors.js +1 -1
  37. package/admin/src/content-manager/pages/App/useContentManagerInitData.js +3 -1
  38. package/admin/src/content-manager/pages/EditSettingsView/index.js +1 -0
  39. package/admin/src/content-manager/pages/EditSettingsView/utils/createPossibleMainFieldsForModelsAndComponents.js +1 -0
  40. package/admin/src/content-manager/pages/EditView/selectors.js +1 -1
  41. package/admin/src/content-manager/pages/EditViewLayoutManager/index.js +3 -1
  42. package/admin/src/content-manager/pages/ListSettingsView/constants.js +1 -0
  43. package/admin/src/content-manager/pages/ListView/components/Body/index.js +53 -56
  44. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +5 -3
  45. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
  46. package/admin/src/content-manager/pages/ListView/index.js +35 -51
  47. package/admin/src/content-manager/pages/ListView/selectors.js +1 -1
  48. package/admin/src/content-manager/utils/checkIfAttributeIsDisplayable.js +1 -1
  49. package/admin/src/content-manager/utils/schema.js +2 -2
  50. package/admin/src/contexts/admin.ts +19 -0
  51. package/admin/src/contexts/apiTokenPermissions.tsx +64 -0
  52. package/admin/src/contexts/configuration.ts +25 -0
  53. package/admin/src/contexts/themeToggle.ts +18 -0
  54. package/admin/src/core/store/configure.ts +91 -0
  55. package/admin/src/core/store/hooks.ts +15 -0
  56. package/admin/src/hooks/{useConfigurations/__mocks__/index.js → __mocks__/useConfigurations.ts} +4 -2
  57. package/admin/src/hooks/index.js +0 -8
  58. package/admin/src/hooks/{useAdminRoles/index.js → useAdminRoles.ts} +26 -10
  59. package/admin/src/hooks/useAdminUsers.ts +64 -0
  60. package/admin/src/hooks/useConfiguration.ts +5 -0
  61. package/admin/src/hooks/{useContentTypes/useContentTypes.js → useContentTypes.ts} +39 -16
  62. package/admin/src/hooks/useDebounce.ts +17 -0
  63. package/admin/src/hooks/{useEnterprise/useEnterprise.js → useEnterprise.ts} +15 -5
  64. package/admin/src/hooks/useLicenseLimitNotification.ts +3 -0
  65. package/admin/src/hooks/useMenu.ts +153 -0
  66. package/admin/src/hooks/useSettingsForm/index.js +14 -2
  67. package/admin/src/hooks/useSettingsMenu/constants.js +39 -0
  68. package/admin/src/hooks/useThemeToggle.ts +9 -0
  69. package/admin/src/index.js +7 -6
  70. package/admin/src/layouts/{AppLayout/index.js → AppLayout.tsx} +7 -10
  71. package/admin/src/layouts/UnauthenticatedLayout.tsx +77 -0
  72. package/admin/src/pages/Admin/index.js +15 -8
  73. package/admin/src/pages/App/index.js +13 -8
  74. package/admin/src/pages/App/selectors.js +1 -1
  75. package/admin/src/pages/AuthPage/components/ForgotPassword/index.js +3 -2
  76. package/admin/src/pages/AuthPage/components/ForgotPasswordSuccess/index.js +3 -2
  77. package/admin/src/pages/AuthPage/components/Login/BaseLogin.js +1 -1
  78. package/admin/src/pages/AuthPage/components/Login/index.js +1 -1
  79. package/admin/src/pages/AuthPage/components/Oops/index.js +3 -2
  80. package/admin/src/pages/AuthPage/components/Register/index.js +30 -35
  81. package/admin/src/pages/AuthPage/components/ResetPassword/index.js +3 -2
  82. package/admin/src/pages/AuthPage/index.js +4 -5
  83. package/admin/src/pages/HomePage/index.js +6 -3
  84. package/admin/src/pages/{InternalErrorPage/index.js → InternalErrorPage.tsx} +10 -6
  85. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/index.js +0 -2
  86. package/admin/src/pages/MarketplacePage/hooks/__mocks__/useNavigatorOnline.ts +1 -0
  87. package/admin/src/{hooks/useNavigatorOnLine/index.js → pages/MarketplacePage/hooks/useNavigatorOnline.ts} +4 -6
  88. package/admin/src/pages/MarketplacePage/index.js +3 -3
  89. package/admin/src/pages/{NotFoundPage/index.js → NotFoundPage.tsx} +9 -7
  90. package/admin/src/pages/ProfilePage/components/Preferences/index.js +23 -9
  91. package/admin/src/pages/ProfilePage/index.js +4 -4
  92. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +20 -0
  93. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +1 -1
  94. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +119 -87
  95. package/admin/src/pages/SettingsPage/constants.js +33 -0
  96. package/admin/src/{hooks/useRegenerate/index.js → pages/SettingsPage/hooks/useRegenerate.ts} +13 -7
  97. package/admin/src/pages/SettingsPage/index.js +2 -2
  98. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +1 -1
  99. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +1 -1
  100. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +1 -1
  101. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +1 -1
  102. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -2
  103. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/CustomizationInfos/index.js +2 -2
  104. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +2 -2
  105. package/admin/src/pages/SettingsPage/pages/AuditLogs/SalesPage.js +50 -0
  106. package/admin/src/pages/SettingsPage/pages/ReviewWorkflows/SalesPage.js +53 -0
  107. package/admin/src/pages/SettingsPage/pages/Roles/CreatePage/index.js +1 -1
  108. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/index.js +1 -1
  109. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +1 -1
  110. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/index.js +1 -1
  111. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/SubActionRow/index.js +1 -1
  112. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/GlobalActions/index.js +1 -1
  113. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PermissionsDataManagerProvider/index.js +1 -1
  114. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PluginsAndSettings/SubCategory/index.js +1 -1
  115. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/hooks/usePermissionsDataManager.ts +28 -0
  116. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +1 -1
  117. package/admin/src/{hooks/useAdminRolePermissions/index.js → pages/SettingsPage/pages/Roles/hooks/useAdminRolePermissions.ts} +13 -6
  118. package/admin/src/pages/SettingsPage/pages/SingleSignOn/SalesPage.js +53 -0
  119. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
  120. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +3 -5
  121. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +2 -1
  122. package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
  123. package/admin/src/pages/{UseCasePage/index.js → UseCasePage.tsx} +10 -12
  124. package/admin/src/shared/hooks/index.js +0 -1
  125. package/admin/src/shared/hooks/useInjectionZone/index.js +2 -2
  126. package/admin/src/translations/en.json +13 -0
  127. package/admin/src/types/adminAPI.ts +29 -0
  128. package/admin/src/utils/createRoute.tsx +54 -0
  129. package/admin/src/utils/formatAPIErrors.ts +18 -0
  130. package/admin/src/utils/getFullName.ts +3 -0
  131. package/admin/src/utils/{uniqueAdminHash.js → hashAdminUserEmail.ts} +6 -3
  132. package/admin/src/utils/makeUniqueRoutes.ts +11 -0
  133. package/admin/tsconfig.build.json +4 -0
  134. package/admin/tsconfig.json +11 -0
  135. package/build/0cd5f8915b265d5b1856.png +0 -0
  136. package/build/1049.ecc10c97.chunk.js +1 -0
  137. package/build/1217.96155682.chunk.js +35 -0
  138. package/build/1227.947ceaf9.chunk.js +1 -0
  139. package/build/1306.2699df52.chunk.js +79 -0
  140. package/build/135.ad267b59.chunk.js +1 -0
  141. package/build/1386.eabd8a1e.chunk.js +7 -0
  142. package/build/1727.b49f0713.chunk.js +1 -0
  143. package/build/1835.eaa696ba.chunk.js +1 -0
  144. package/build/19eb2dfcf2603eb55733.png +0 -0
  145. package/build/2325.d705b39a.chunk.js +1 -0
  146. package/build/2379.7ce8e110.chunk.js +1 -0
  147. package/build/2395.acb961a8.chunk.js +26 -0
  148. package/build/2421.79e5b3d0.chunk.js +1 -0
  149. package/build/267.073a3bcb.chunk.js +1 -0
  150. package/build/27d16aefee06412db90a.png +0 -0
  151. package/build/2801.4711ea5a.chunk.js +1 -0
  152. package/build/2878.145ebf7c.chunk.js +1 -0
  153. package/build/2950.216f2e89.chunk.js +1 -0
  154. package/build/2953.284a63c0.chunk.js +1 -0
  155. package/build/3019.fde2e1be.chunk.js +181 -0
  156. package/build/3100.2ba4df95.chunk.js +1 -0
  157. package/build/311.cb0884bb.chunk.js +1 -0
  158. package/build/3460.8644e608.chunk.js +146 -0
  159. package/build/3483.db8c1520.chunk.js +1 -0
  160. package/build/3911.488fbde3.chunk.js +95 -0
  161. package/build/4174.49cedb6a.chunk.js +1 -0
  162. package/build/4429.7f044dc7.chunk.js +1 -0
  163. package/build/4555.c883d697.chunk.js +1 -0
  164. package/build/4663.b906cc10.chunk.js +1 -0
  165. package/build/4732.149f5f8f.chunk.js +1 -0
  166. package/build/4916.480053a6.chunk.js +1 -0
  167. package/build/4996.d285c30b.chunk.js +1 -0
  168. package/build/502.f536f78b.chunk.js +1 -0
  169. package/build/570.2f3b4c56.chunk.js +1 -0
  170. package/build/5858.493b31ec.chunk.js +1 -0
  171. package/build/6158.c3c13c20.chunk.js +1 -0
  172. package/build/6345.334e7678.chunk.js +1 -0
  173. package/build/6453.4160b5b7.chunk.js +1 -0
  174. package/build/7030.b98dcedf.chunk.js +1 -0
  175. package/build/70674f63fc3904c20de0.svg +7 -0
  176. package/build/7448.6fd14dd3.chunk.js +1 -0
  177. package/build/7464.579564ac.chunk.js +1 -0
  178. package/build/7735.9e7c9fdd.chunk.js +10 -0
  179. package/build/78.dcc6df5c.chunk.js +1 -0
  180. package/build/7811.fdbe09af.chunk.js +103 -0
  181. package/build/782.7243b183.chunk.js +1 -0
  182. package/build/7849.2a500ed8.chunk.js +1 -0
  183. package/build/7897.63ba0a00.chunk.js +6 -0
  184. package/build/7e9af4fb7e723fcebf1f.svg +48 -0
  185. package/build/8162.7d1100a0.chunk.js +1 -0
  186. package/build/8276.9abe4679.chunk.js +26 -0
  187. package/build/8773.ee67141c.chunk.js +48 -0
  188. package/build/8980.f0045cc1.chunk.js +1 -0
  189. package/build/9077.2cc01ac8.chunk.js +105 -0
  190. package/build/9153.42c1428a.chunk.js +1 -0
  191. package/build/918.54414509.chunk.js +1 -0
  192. package/build/9218.b2d367f8.chunk.js +1 -0
  193. package/build/9285.5f174057.chunk.js +1 -0
  194. package/build/9547.62987774.chunk.js +1 -0
  195. package/build/9754.b4e73779.chunk.js +1 -0
  196. package/build/9d5d788027e86620c234.svg +5 -0
  197. package/build/Admin-authenticatedApp.059dc48f.chunk.js +79 -0
  198. package/build/Admin_InternalErrorPage.06eeef20.chunk.js +1 -0
  199. package/build/Admin_homePage.56b9eb3f.chunk.js +81 -0
  200. package/build/Admin_marketplace.d693a435.chunk.js +44 -0
  201. package/build/Admin_pluginsPage.ae2c872a.chunk.js +6 -0
  202. package/build/Admin_profilePage.89099d5b.chunk.js +13 -0
  203. package/build/Admin_settingsPage.88c45586.chunk.js +12 -0
  204. package/build/Upload_ConfigureTheView.44f28145.chunk.js +1 -0
  205. package/build/admin-app.990e112f.chunk.js +69 -0
  206. package/build/admin-edit-roles-page.4e1eb4a9.chunk.js +267 -0
  207. package/build/admin-edit-users.5b91404e.chunk.js +10 -0
  208. package/build/admin-roles-list.89dd94fe.chunk.js +22 -0
  209. package/build/admin-users.7be4fc5f.chunk.js +11 -0
  210. package/build/api-tokens-create-page.571920e5.chunk.js +1 -0
  211. package/build/api-tokens-edit-page.cbdc81b1.chunk.js +1 -0
  212. package/build/api-tokens-list-page.de0c49e8.chunk.js +16 -0
  213. package/build/ar-json.74e40bc7.chunk.js +1 -0
  214. package/build/audit-logs-sales-page.2955db88.chunk.js +1 -0
  215. package/build/audit-logs-settings-page.b0cb5164.chunk.js +1 -0
  216. package/build/bb3108f7fd1e6179bde1.svg +1 -0
  217. package/build/bb4d0d527bdfb161bc5a.svg +1 -0
  218. package/build/ca-json.fc6001d3.chunk.js +1 -0
  219. package/build/content-manager.de7ae330.chunk.js +1241 -0
  220. package/build/content-type-builder-list-view.6c8d3213.chunk.js +211 -0
  221. package/build/content-type-builder-translation-ar-json.3e808e2f.chunk.js +1 -0
  222. package/build/content-type-builder-translation-cs-json.1ef9e106.chunk.js +1 -0
  223. package/build/content-type-builder-translation-de-json.63fcff7b.chunk.js +1 -0
  224. package/build/content-type-builder-translation-dk-json.fd626b67.chunk.js +1 -0
  225. package/build/content-type-builder-translation-en-json.74d80f18.chunk.js +1 -0
  226. package/build/content-type-builder-translation-es-json.a4a361a9.chunk.js +1 -0
  227. package/build/content-type-builder-translation-fr-json.499c3a46.chunk.js +1 -0
  228. package/build/content-type-builder-translation-id-json.65255f93.chunk.js +1 -0
  229. package/build/content-type-builder-translation-it-json.e268ab74.chunk.js +1 -0
  230. package/build/content-type-builder-translation-ja-json.9be0d5b2.chunk.js +1 -0
  231. package/build/content-type-builder-translation-ko-json.04cb309d.chunk.js +1 -0
  232. package/build/content-type-builder-translation-ms-json.f6b743b9.chunk.js +1 -0
  233. package/build/content-type-builder-translation-nl-json.997fe8cc.chunk.js +1 -0
  234. package/build/content-type-builder-translation-pl-json.634f638b.chunk.js +1 -0
  235. package/build/content-type-builder-translation-pt-BR-json.6a95dc71.chunk.js +1 -0
  236. package/build/content-type-builder-translation-pt-json.ddb44f8c.chunk.js +1 -0
  237. package/build/content-type-builder-translation-ru-json.3af65503.chunk.js +1 -0
  238. package/build/content-type-builder-translation-sk-json.c6078082.chunk.js +1 -0
  239. package/build/content-type-builder-translation-sv-json.a6df2462.chunk.js +1 -0
  240. package/build/content-type-builder-translation-th-json.122277cc.chunk.js +1 -0
  241. package/build/content-type-builder-translation-tr-json.41f44f77.chunk.js +1 -0
  242. package/build/content-type-builder-translation-uk-json.e1315acd.chunk.js +1 -0
  243. package/build/content-type-builder-translation-zh-Hans-json.6ff57db6.chunk.js +1 -0
  244. package/build/content-type-builder-translation-zh-json.3532b962.chunk.js +1 -0
  245. package/build/content-type-builder.0bc97051.chunk.js +136 -0
  246. package/build/cs-json.4b44411c.chunk.js +1 -0
  247. package/build/de-json.e72545cf.chunk.js +1 -0
  248. package/build/dk-json.e77140ef.chunk.js +1 -0
  249. package/build/email-settings-page.07712efc.chunk.js +11 -0
  250. package/build/en-json.5b907f67.chunk.js +1 -0
  251. package/build/es-json.b1f2284b.chunk.js +1 -0
  252. package/build/eu-json.63d0a898.chunk.js +1 -0
  253. package/build/fr-json.33c6428b.chunk.js +1 -0
  254. package/build/gu-json.7efe8cc2.chunk.js +1 -0
  255. package/build/he-json.3cf0b48a.chunk.js +1 -0
  256. package/build/hi-json.0d633692.chunk.js +1 -0
  257. package/build/highlight.js.28a1547e.chunk.js +85 -0
  258. package/build/hu-json.c74b6a1e.chunk.js +1 -0
  259. package/build/i18n-settings-page.5c34f012.chunk.js +9 -0
  260. package/build/i18n-translation-de-json.362384a6.chunk.js +1 -0
  261. package/build/i18n-translation-dk-json.89401417.chunk.js +1 -0
  262. package/build/i18n-translation-en-json.1ec7becf.chunk.js +1 -0
  263. package/build/i18n-translation-es-json.87b494d1.chunk.js +1 -0
  264. package/build/i18n-translation-fr-json.57ddc77e.chunk.js +1 -0
  265. package/build/i18n-translation-ko-json.ef4f9471.chunk.js +1 -0
  266. package/build/i18n-translation-pl-json.dfac513d.chunk.js +1 -0
  267. package/build/i18n-translation-ru-json.a3dbc125.chunk.js +1 -0
  268. package/build/i18n-translation-tr-json.3bfc812f.chunk.js +1 -0
  269. package/build/i18n-translation-zh-Hans-json.757ce62d.chunk.js +1 -0
  270. package/build/i18n-translation-zh-json.bef2dc07.chunk.js +1 -0
  271. package/build/id-json.41e07c46.chunk.js +1 -0
  272. package/build/index.html +1 -0
  273. package/build/it-json.bfe27ed8.chunk.js +1 -0
  274. package/build/ja-json.e1959a1c.chunk.js +1 -0
  275. package/build/ko-json.ce5d6d94.chunk.js +1 -0
  276. package/build/main.f84563f1.js +2665 -0
  277. package/build/ml-json.940d7ace.chunk.js +1 -0
  278. package/build/ms-json.0eddffd9.chunk.js +1 -0
  279. package/build/nl-json.fe38f0fb.chunk.js +1 -0
  280. package/build/no-json.19a2dbfa.chunk.js +1 -0
  281. package/build/pl-json.d55e8e78.chunk.js +1 -0
  282. package/build/pt-BR-json.ae0a0d2e.chunk.js +1 -0
  283. package/build/pt-json.ee554a41.chunk.js +1 -0
  284. package/build/review-workflows-sales-page.f46a8f00.chunk.js +1 -0
  285. package/build/review-workflows-settings-create-view.d0544fb0.chunk.js +1 -0
  286. package/build/review-workflows-settings-edit-view.aabf49ef.chunk.js +1 -0
  287. package/build/review-workflows-settings-list-view.8b0525ab.chunk.js +56 -0
  288. package/build/ru-json.1c976644.chunk.js +1 -0
  289. package/build/runtime~main.270fd45f.js +2 -0
  290. package/build/sa-json.2c03ef4e.chunk.js +1 -0
  291. package/build/sk-json.b41847e8.chunk.js +1 -0
  292. package/build/sso-sales-page.ef22e469.chunk.js +1 -0
  293. package/build/sso-settings-page.21e16ae4.chunk.js +1 -0
  294. package/build/sv-json.568cb7ae.chunk.js +1 -0
  295. package/build/th-json.5f659396.chunk.js +1 -0
  296. package/build/tr-json.c9f22432.chunk.js +1 -0
  297. package/build/transfer-tokens-create-page.3366204d.chunk.js +1 -0
  298. package/build/transfer-tokens-edit-page.15cf0f73.chunk.js +1 -0
  299. package/build/transfer-tokens-list-page.0bc0e682.chunk.js +16 -0
  300. package/build/uk-json.b7e38370.chunk.js +1 -0
  301. package/build/upload-settings.1319dca0.chunk.js +14 -0
  302. package/build/upload-translation-ca-json.57954414.chunk.js +1 -0
  303. package/build/upload-translation-de-json.420c943b.chunk.js +1 -0
  304. package/build/upload-translation-dk-json.bbb2fa05.chunk.js +1 -0
  305. package/build/upload-translation-en-json.8b7573ce.chunk.js +1 -0
  306. package/build/upload-translation-es-json.ba2eb03a.chunk.js +1 -0
  307. package/build/upload-translation-fr-json.baab9911.chunk.js +1 -0
  308. package/build/upload-translation-he-json.0a830937.chunk.js +1 -0
  309. package/build/upload-translation-it-json.e87d7966.chunk.js +1 -0
  310. package/build/upload-translation-ja-json.44b88e7a.chunk.js +1 -0
  311. package/build/upload-translation-ko-json.a52eab64.chunk.js +1 -0
  312. package/build/upload-translation-ms-json.74f6d746.chunk.js +1 -0
  313. package/build/upload-translation-pl-json.426f31c9.chunk.js +1 -0
  314. package/build/upload-translation-pt-BR-json.d1704f0b.chunk.js +1 -0
  315. package/build/upload-translation-pt-json.6b937fdf.chunk.js +1 -0
  316. package/build/upload-translation-ru-json.675f6b93.chunk.js +1 -0
  317. package/build/upload-translation-sk-json.483a18f6.chunk.js +1 -0
  318. package/build/upload-translation-th-json.98d35574.chunk.js +1 -0
  319. package/build/upload-translation-tr-json.74117e5c.chunk.js +1 -0
  320. package/build/upload-translation-uk-json.9950466a.chunk.js +1 -0
  321. package/build/upload-translation-zh-Hans-json.db163b6b.chunk.js +1 -0
  322. package/build/upload-translation-zh-json.e1dd6eb2.chunk.js +1 -0
  323. package/build/upload.1ced11be.chunk.js +58 -0
  324. package/build/users-advanced-settings-page.8e657084.chunk.js +9 -0
  325. package/build/users-email-settings-page.e57745e5.chunk.js +9 -0
  326. package/build/users-permissions-translation-ar-json.7d87d54d.chunk.js +1 -0
  327. package/build/users-permissions-translation-cs-json.7e23424a.chunk.js +1 -0
  328. package/build/users-permissions-translation-de-json.a6fb670f.chunk.js +1 -0
  329. package/build/users-permissions-translation-dk-json.60e50f48.chunk.js +1 -0
  330. package/build/users-permissions-translation-en-json.4b302272.chunk.js +1 -0
  331. package/build/users-permissions-translation-es-json.35007573.chunk.js +1 -0
  332. package/build/users-permissions-translation-fr-json.7e55bbbb.chunk.js +1 -0
  333. package/build/users-permissions-translation-id-json.a5a0fb59.chunk.js +1 -0
  334. package/build/users-permissions-translation-it-json.0705465d.chunk.js +1 -0
  335. package/build/users-permissions-translation-ja-json.891fe76e.chunk.js +1 -0
  336. package/build/users-permissions-translation-ko-json.357d7a33.chunk.js +1 -0
  337. package/build/users-permissions-translation-ms-json.c83f87c4.chunk.js +1 -0
  338. package/build/users-permissions-translation-nl-json.c9f92a3c.chunk.js +1 -0
  339. package/build/users-permissions-translation-pl-json.0a7287d1.chunk.js +1 -0
  340. package/build/users-permissions-translation-pt-BR-json.1b6d2920.chunk.js +1 -0
  341. package/build/users-permissions-translation-pt-json.a7eda429.chunk.js +1 -0
  342. package/build/users-permissions-translation-ru-json.8e883c67.chunk.js +1 -0
  343. package/build/users-permissions-translation-sk-json.7f37180f.chunk.js +1 -0
  344. package/build/users-permissions-translation-sv-json.17187818.chunk.js +1 -0
  345. package/build/users-permissions-translation-th-json.1e9c0247.chunk.js +1 -0
  346. package/build/users-permissions-translation-tr-json.2bd7ff98.chunk.js +1 -0
  347. package/build/users-permissions-translation-uk-json.6a0a1572.chunk.js +1 -0
  348. package/build/users-permissions-translation-vi-json.6722a8a2.chunk.js +1 -0
  349. package/build/users-permissions-translation-zh-Hans-json.8d82c809.chunk.js +1 -0
  350. package/build/users-permissions-translation-zh-json.7978eaa6.chunk.js +1 -0
  351. package/build/users-providers-settings-page.55796d13.chunk.js +14 -0
  352. package/build/users-roles-settings-page.57079245.chunk.js +55 -0
  353. package/build/vi-json.ee4c5537.chunk.js +1 -0
  354. package/build/webhook-edit-page.3a28b2e7.chunk.js +33 -0
  355. package/build/webhook-list-page.ee80767b.chunk.js +63 -0
  356. package/build/zh-Hans-json.97efd015.chunk.js +1 -0
  357. package/build/zh-json.bfc2e036.chunk.js +1 -0
  358. package/ee/admin/hooks/{useLicenseLimitNotification.js → useLicenseLimitNotification.ts} +4 -4
  359. package/ee/admin/pages/AuthPage/components/Login/index.js +1 -1
  360. package/ee/admin/pages/AuthPage/components/Providers/index.js +3 -2
  361. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/selectors.js +1 -1
  362. package/ee/admin/pages/SettingsPage/pages/Users/ListPage/index.js +1 -3
  363. package/ee/server/bootstrap.js +1 -1
  364. package/ee/server/controllers/admin.js +1 -1
  365. package/ee/server/controllers/user.js +1 -1
  366. package/ee/server/destroy.js +1 -1
  367. package/ee/server/register.js +1 -1
  368. package/ee/server/routes/utils.js +1 -1
  369. package/ee/server/services/audit-logs.js +1 -1
  370. package/ee/server/services/passport/sso.js +1 -1
  371. package/ee/server/services/passport.js +1 -1
  372. package/ee/server/services/seat-enforcement.js +1 -1
  373. package/ee/server/utils/sso-lock.js +1 -1
  374. package/ee/server/validation/role.js +1 -1
  375. package/ee/server/validation/user.js +1 -1
  376. package/jest.config.front.js +4 -0
  377. package/package.json +28 -22
  378. package/scripts/build.js +6 -2
  379. package/server/controllers/admin.js +4 -3
  380. package/shared/entities.ts +33 -0
  381. package/shared/permissions.ts +52 -0
  382. package/shared/schema.ts +9 -0
  383. package/webpack.config.js +1 -0
  384. package/admin/src/components/AuthenticatedApp/index.js +0 -120
  385. package/admin/src/components/AuthenticatedApp/utils/api.js +0 -85
  386. package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +0 -11
  387. package/admin/src/components/ConfigurationsProvider/index.js +0 -66
  388. package/admin/src/components/ConfigurationsProvider/reducer.js +0 -29
  389. package/admin/src/components/DragLayer/index.js +0 -1
  390. package/admin/src/components/GlobalStyle/index.js +0 -9
  391. package/admin/src/components/GuidedTour/Homepage/components/Step.js +0 -61
  392. package/admin/src/components/GuidedTour/Homepage/components/Stepper.js +0 -61
  393. package/admin/src/components/GuidedTour/Homepage/index.js +0 -71
  394. package/admin/src/components/GuidedTour/Modal/components/Content.js +0 -66
  395. package/admin/src/components/GuidedTour/Modal/components/Modal.js +0 -72
  396. package/admin/src/components/GuidedTour/Modal/components/StepNumberWithPadding.js +0 -26
  397. package/admin/src/components/GuidedTour/Modal/components/Stepper.js +0 -118
  398. package/admin/src/components/GuidedTour/Modal/index.js +0 -94
  399. package/admin/src/components/GuidedTour/Modal/reducer.js +0 -29
  400. package/admin/src/components/GuidedTour/Stepper/StepLine.js +0 -29
  401. package/admin/src/components/GuidedTour/Stepper/StepNumber.js +0 -71
  402. package/admin/src/components/GuidedTour/constants.js +0 -3
  403. package/admin/src/components/GuidedTour/index.js +0 -102
  404. package/admin/src/components/GuidedTour/init.js +0 -37
  405. package/admin/src/components/GuidedTour/reducer.js +0 -50
  406. package/admin/src/components/GuidedTour/utils/arePreviousSectionsDone.js +0 -13
  407. package/admin/src/components/GuidedTour/utils/arePreviousStepsDone.js +0 -12
  408. package/admin/src/components/GuidedTour/utils/isGuidedTourCompleted.js +0 -6
  409. package/admin/src/components/GuidedTour/utils/persistStateToLocaleStorage.js +0 -34
  410. package/admin/src/components/LanguageProvider/index.js +0 -54
  411. package/admin/src/components/LanguageProvider/init.js +0 -13
  412. package/admin/src/components/LanguageProvider/reducer.js +0 -30
  413. package/admin/src/components/LanguageProvider/utils/localStorageKey.js +0 -3
  414. package/admin/src/components/LocalesProvider/context.js +0 -5
  415. package/admin/src/components/LocalesProvider/index.js +0 -21
  416. package/admin/src/components/LocalesProvider/useLocalesProvider.js +0 -11
  417. package/admin/src/components/NpsSurvey/hooks/useNpsSurveySettings.js +0 -17
  418. package/admin/src/components/PluginsInitializer/index.js +0 -68
  419. package/admin/src/components/PluginsInitializer/init.js +0 -11
  420. package/admin/src/components/PluginsInitializer/reducer.js +0 -22
  421. package/admin/src/components/PrivateRoute/index.js +0 -46
  422. package/admin/src/components/Providers/index.js +0 -156
  423. package/admin/src/components/RBACProvider/actions.js +0 -10
  424. package/admin/src/components/RBACProvider/constants.js +0 -2
  425. package/admin/src/components/RBACProvider/index.js +0 -39
  426. package/admin/src/components/RBACProvider/reducer.js +0 -51
  427. package/admin/src/components/Theme/index.js +0 -26
  428. package/admin/src/components/ThemeToggleProvider/index.js +0 -79
  429. package/admin/src/contexts/Admin/index.js +0 -5
  430. package/admin/src/contexts/ApiTokenPermissions/index.js +0 -25
  431. package/admin/src/contexts/Configurations/index.js +0 -5
  432. package/admin/src/contexts/MarketPlace/index.js +0 -18
  433. package/admin/src/contexts/PermisssionsDataManagerContext/index.js +0 -5
  434. package/admin/src/contexts/ThemeToggle/index.js +0 -5
  435. package/admin/src/contexts/index.js +0 -4
  436. package/admin/src/core/store/configureStore.js +0 -47
  437. package/admin/src/exposedHooks.js +0 -27
  438. package/admin/src/hooks/useAdminRoles/__mocks__/index.js +0 -5
  439. package/admin/src/hooks/useAdminUsers/index.js +0 -1
  440. package/admin/src/hooks/useAdminUsers/useAdminUsers.js +0 -47
  441. package/admin/src/hooks/useConfigurations/index.js +0 -11
  442. package/admin/src/hooks/useContentTypes/index.js +0 -1
  443. package/admin/src/hooks/useDebounce/index.js +0 -19
  444. package/admin/src/hooks/useEnterprise/index.js +0 -1
  445. package/admin/src/hooks/useLicenseLimitNotification/index.js +0 -5
  446. package/admin/src/hooks/useMenu/index.js +0 -86
  447. package/admin/src/hooks/useMenu/utils/checkPermissions.js +0 -13
  448. package/admin/src/hooks/useMenu/utils/getGeneralLinks.js +0 -31
  449. package/admin/src/hooks/useMenu/utils/getPluginSectionLinks.js +0 -17
  450. package/admin/src/hooks/usePermissionsDataManager/index.js +0 -7
  451. package/admin/src/hooks/useReleaseNotification/index.js +0 -31
  452. package/admin/src/hooks/useReleaseNotification/utils/api.js +0 -20
  453. package/admin/src/hooks/useReleaseNotification/utils/checkLatestStrapiVersion.js +0 -11
  454. package/admin/src/hooks/useThemeToggle/index.js +0 -11
  455. package/admin/src/injectionZones.js +0 -25
  456. package/admin/src/layouts/UnauthenticatedLayout/LocaleToggle/index.js +0 -29
  457. package/admin/src/layouts/UnauthenticatedLayout/index.js +0 -55
  458. package/admin/src/reducers.js +0 -23
  459. package/admin/src/shared/hooks/useAdminProvider/index.js +0 -11
  460. package/admin/src/tsconfig.json +0 -10
  461. package/admin/src/utils/checkFormValidity.js +0 -15
  462. package/admin/src/utils/createRoute.js +0 -47
  463. package/admin/src/utils/formatAPIErrors.js +0 -17
  464. package/admin/src/utils/getAttributesToDisplay.js +0 -19
  465. package/admin/src/utils/getExistingActions.js +0 -32
  466. package/admin/src/utils/getFullName.js +0 -9
  467. package/admin/src/utils/index.js +0 -9
  468. package/admin/src/utils/makeUniqueRoutes.js +0 -6
  469. package/admin/src/utils/sortLinks.js +0 -5
  470. /package/admin/src/hooks/{useAdminUsers/__mocks__/index.js → __mocks__/useAdminUsers.ts} +0 -0
  471. /package/admin/src/hooks/{useContentTypes/__mocks__/index.js → __mocks__/useContentTypes.ts} +0 -0
  472. /package/admin/src/{hooks/useAdminRolePermissions/__mocks__/index.js → pages/SettingsPage/pages/Roles/hooks/__mocks__/useAdminRolePermissions.ts} +0 -0
@@ -0,0 +1,130 @@
1
+ /*
2
+ *
3
+ * LanguageProvider
4
+ *
5
+ * this component connects the redux state language locale to the
6
+ * IntlProvider component and i18n messages (loaded from `app/translations`)
7
+ */
8
+
9
+ import * as React from 'react';
10
+
11
+ import defaultsDeep from 'lodash/defaultsDeep';
12
+ import { IntlProvider } from 'react-intl';
13
+
14
+ /* -------------------------------------------------------------------------------------------------
15
+ * LocalesContext
16
+ * -----------------------------------------------------------------------------------------------*/
17
+
18
+ interface LocalesContextValue {
19
+ changeLocale: (locale: keyof State['localeNames']) => void;
20
+ localeNames: Record<string, string>;
21
+ }
22
+
23
+ const LocalesContext = React.createContext<LocalesContextValue>({
24
+ changeLocale: () => {
25
+ throw new Error('LocalesContext: changeLocale() is not implemented');
26
+ },
27
+ localeNames: {},
28
+ });
29
+
30
+ const useLocales = () => React.useContext(LocalesContext);
31
+
32
+ /* -------------------------------------------------------------------------------------------------
33
+ * LanguageProvider
34
+ * -----------------------------------------------------------------------------------------------*/
35
+
36
+ const LANGUAGE_LOCAL_STORAGE_KEY = 'strapi-admin-language';
37
+
38
+ interface LanguageProviderProps {
39
+ children: React.ReactNode;
40
+ localeNames: Record<string, string>;
41
+ messages: Record<string, Record<string, string>>;
42
+ }
43
+
44
+ const LanguageProvider = ({ children, localeNames, messages }: LanguageProviderProps) => {
45
+ const [{ locale }, dispatch] = React.useReducer<React.Reducer<State, Action>, State>(
46
+ reducer,
47
+ initialState,
48
+ () => {
49
+ const languageFromLocaleStorage = window.localStorage.getItem(LANGUAGE_LOCAL_STORAGE_KEY);
50
+ if (languageFromLocaleStorage && localeNames[languageFromLocaleStorage]) {
51
+ return {
52
+ locale: languageFromLocaleStorage,
53
+ localeNames,
54
+ };
55
+ } else {
56
+ return {
57
+ locale: 'en',
58
+ localeNames,
59
+ };
60
+ }
61
+ }
62
+ );
63
+
64
+ React.useEffect(() => {
65
+ // Set user language in local storage.
66
+ window.localStorage.setItem(LANGUAGE_LOCAL_STORAGE_KEY, locale);
67
+ document.documentElement.setAttribute('lang', locale);
68
+ }, [locale]);
69
+
70
+ const changeLocale = React.useCallback((locale: keyof State['localeNames']) => {
71
+ dispatch({
72
+ type: 'CHANGE_LOCALE',
73
+ locale,
74
+ });
75
+ }, []);
76
+
77
+ const appMessages = defaultsDeep(messages[locale], messages.en);
78
+
79
+ const contextValue = React.useMemo(
80
+ () => ({ changeLocale, localeNames }),
81
+ [changeLocale, localeNames]
82
+ );
83
+
84
+ return (
85
+ <IntlProvider locale={locale} defaultLocale="en" messages={appMessages} textComponent="span">
86
+ <LocalesContext.Provider value={contextValue}>{children}</LocalesContext.Provider>
87
+ </IntlProvider>
88
+ );
89
+ };
90
+
91
+ /* -------------------------------------------------------------------------------------------------
92
+ * Reducer
93
+ * -----------------------------------------------------------------------------------------------*/
94
+
95
+ interface State {
96
+ localeNames: Record<string, string>;
97
+ locale: keyof State['localeNames'];
98
+ }
99
+
100
+ const initialState: State = {
101
+ localeNames: { en: 'English' },
102
+ locale: 'en',
103
+ };
104
+
105
+ interface ChangeLocaleAction {
106
+ type: 'CHANGE_LOCALE';
107
+ locale: keyof State['localeNames'];
108
+ }
109
+
110
+ type Action = ChangeLocaleAction;
111
+
112
+ const reducer = (state = initialState, action: Action) => {
113
+ switch (action.type) {
114
+ case 'CHANGE_LOCALE': {
115
+ const { locale } = action;
116
+
117
+ if (!state.localeNames[locale]) {
118
+ return state;
119
+ }
120
+
121
+ return { ...state, locale };
122
+ }
123
+ default: {
124
+ return state;
125
+ }
126
+ }
127
+ };
128
+
129
+ export { LanguageProvider, useLocales, LANGUAGE_LOCAL_STORAGE_KEY };
130
+ export type { LanguageProviderProps, LocalesContextValue };
@@ -1,4 +1,4 @@
1
- import React, { useRef, useState } from 'react';
1
+ import * as React from 'react';
2
2
 
3
3
  import { Box, Divider, Flex, FocusTrap, Typography } from '@strapi/design-system';
4
4
  import {
@@ -19,12 +19,12 @@ import {
19
19
  useTracking,
20
20
  } from '@strapi/helper-plugin';
21
21
  import { Exit, Write } from '@strapi/icons';
22
- import PropTypes from 'prop-types';
23
22
  import { useIntl } from 'react-intl';
24
23
  import { NavLink as RouterNavLink, useHistory, useLocation } from 'react-router-dom';
25
24
  import styled from 'styled-components';
26
25
 
27
- import { useConfigurations } from '../../hooks';
26
+ import { useConfiguration } from '../hooks/useConfiguration';
27
+ import { Menu } from '../hooks/useMenu';
28
28
 
29
29
  const LinkUserWrapper = styled(Box)`
30
30
  width: ${150 / 16}rem;
@@ -33,7 +33,7 @@ const LinkUserWrapper = styled(Box)`
33
33
  left: ${({ theme }) => theme.spaces[5]};
34
34
  `;
35
35
 
36
- const LinkUser = styled(RouterNavLink)`
36
+ const LinkUser = styled(RouterNavLink)<{ logout?: boolean }>`
37
37
  display: flex;
38
38
  justify-content: space-between;
39
39
  align-items: center;
@@ -54,12 +54,14 @@ const LinkUser = styled(RouterNavLink)`
54
54
  }
55
55
  `;
56
56
 
57
- const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
58
- const buttonRef = useRef();
59
- const [userLinksVisible, setUserLinksVisible] = useState(false);
57
+ interface LeftMenuProps extends Pick<Menu, 'generalSectionLinks' | 'pluginsSectionLinks'> {}
58
+
59
+ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }: LeftMenuProps) => {
60
+ const navUserRef = React.useRef<HTMLDivElement>(null!);
61
+ const [userLinksVisible, setUserLinksVisible] = React.useState(false);
60
62
  const {
61
63
  logos: { menu },
62
- } = useConfigurations();
64
+ } = useConfiguration();
63
65
  const [condensed, setCondensed] = usePersistentState('navbar-condensed', false);
64
66
  const { userDisplayName } = useAppInfo();
65
67
  const { formatMessage } = useIntl();
@@ -83,16 +85,19 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
83
85
  history.push('/auth/login');
84
86
  };
85
87
 
86
- const handleBlur = (e) => {
88
+ const handleBlur: React.FocusEventHandler = (e) => {
87
89
  if (
88
90
  !e.currentTarget.contains(e.relatedTarget) &&
91
+ /**
92
+ * TODO: can we replace this by just using the navUserRef?
93
+ */
89
94
  e.relatedTarget?.parentElement?.id !== 'main-nav-user-button'
90
95
  ) {
91
96
  setUserLinksVisible(false);
92
97
  }
93
98
  };
94
99
 
95
- const handleClickOnLink = (destination = null) => {
100
+ const handleClickOnLink = (destination: string) => {
96
101
  trackUsage('willNavigate', { from: pathname, to: destination });
97
102
  };
98
103
 
@@ -126,6 +131,7 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
126
131
  <NavSections>
127
132
  <NavLink
128
133
  as={RouterNavLink}
134
+ // @ts-expect-error the props from the passed as prop are not inferred // joined together
129
135
  to="/content-manager"
130
136
  icon={<Write />}
131
137
  onClick={() => handleClickOnLink('/content-manager')}
@@ -146,6 +152,7 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
146
152
  return (
147
153
  <NavLink
148
154
  as={RouterNavLink}
155
+ // @ts-expect-error the props from the passed as prop are not inferred // joined together
149
156
  to={link.to}
150
157
  key={link.to}
151
158
  icon={<Icon />}
@@ -172,8 +179,11 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
172
179
  <NavLink
173
180
  as={RouterNavLink}
174
181
  badgeContent={
175
- (link.notificationsCount > 0 && link.notificationsCount.toString()) || undefined
182
+ link.notificationsCount && link.notificationsCount > 0
183
+ ? link.notificationsCount.toString()
184
+ : undefined
176
185
  }
186
+ // @ts-expect-error the props from the passed as prop are not inferred // joined together
177
187
  to={link.to}
178
188
  key={link.to}
179
189
  icon={<LinkIcon />}
@@ -190,7 +200,7 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
190
200
  <NavFooter>
191
201
  <NavUser
192
202
  id="main-nav-user-button"
193
- ref={buttonRef}
203
+ ref={navUserRef}
194
204
  onClick={handleToggleUserLinks}
195
205
  initials={initials}
196
206
  >
@@ -244,9 +254,4 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
244
254
  );
245
255
  };
246
256
 
247
- LeftMenu.propTypes = {
248
- generalSectionLinks: PropTypes.array.isRequired,
249
- pluginsSectionLinks: PropTypes.array.isRequired,
250
- };
251
-
252
- export default LeftMenu;
257
+ export { LeftMenu };
@@ -13,7 +13,7 @@ import {
13
13
  FieldInput,
14
14
  VisuallyHidden,
15
15
  } from '@strapi/design-system';
16
- import { auth, useNotification, useAppInfo } from '@strapi/helper-plugin';
16
+ import { auth, useNotification, useAppInfo, usePersistentState } from '@strapi/helper-plugin';
17
17
  import { Cross } from '@strapi/icons';
18
18
  import { Formik, Form } from 'formik';
19
19
  import { useIntl } from 'react-intl';
@@ -21,8 +21,6 @@ import { useMutation } from 'react-query';
21
21
  import styled, { useTheme } from 'styled-components';
22
22
  import * as yup from 'yup';
23
23
 
24
- import { useNpsSurveySettings } from './hooks/useNpsSurveySettings';
25
-
26
24
  const FieldWrapper = styled(Field)`
27
25
  height: ${32 / 16}rem;
28
26
  width: ${32 / 16}rem;
@@ -67,21 +65,27 @@ const delays = {
67
65
 
68
66
  const ratingArray = [...Array(11).keys()];
69
67
 
70
- const checkIfShouldShowSurvey = (settings) => {
68
+ const checkIfShouldShowSurvey = (settings: NpsSurveySettings) => {
71
69
  const { enabled, lastResponseDate, firstDismissalDate, lastDismissalDate } = settings;
72
70
 
73
71
  // This function goes through all the cases where we'd want to not show the survey:
74
- // 1. If the survey is disabled, abort mission, don't bother checking the other settings.
75
- // 2. If the user has already responded to the survey, check if enough time has passed since the last response.
76
- // 3. If the user has dismissed the survey twice or more before, check if enough time has passed since the last dismissal.
77
- // 4. If the user has only dismissed the survey once before, check if enough time has passed since the first dismissal.
72
+ // 1. If the survey is disabled by strapi, abort mission, don't bother checking the other settings.
73
+ // 2. If the survey is disabled by user, abort mission, don't bother checking the other settings.
74
+ // 3. If the user has already responded to the survey, check if enough time has passed since the last response.
75
+ // 4. If the user has dismissed the survey twice or more before, check if enough time has passed since the last dismissal.
76
+ // 5. If the user has only dismissed the survey once before, check if enough time has passed since the first dismissal.
78
77
  // If none of these cases check out, then we show the survey.
79
78
  // Note that submitting a response resets the dismissal counts.
80
- // Checks 3 and 4 should not be reversed, since the first dismissal will also exist if the user has dismissed the survey twice or more before.
79
+ // Checks 4 and 5 should not be reversed, since the first dismissal will also exist if the user has dismissed the survey twice or more before.
81
80
 
82
81
  // For users who had created an account before the NPS feature was introduced,
83
82
  // we assume that they would have enabled the NPS feature if they had the chance.
84
83
 
84
+ // Global strapi disable for NSP.
85
+ if (window.strapi.flags.nps === false) {
86
+ return false;
87
+ }
88
+
85
89
  // User chose not to enable the NPS feature when signing up
86
90
  if (enabled === false) {
87
91
  return false;
@@ -132,7 +136,16 @@ const NpsSurvey = () => {
132
136
  const toggleNotification = useNotification();
133
137
  const { currentEnvironment, strapiVersion } = useAppInfo();
134
138
 
135
- const { mutate, isLoading } = useMutation(
139
+ interface NpsSurveyMutationBody {
140
+ email: string;
141
+ rating: number | null;
142
+ comment: string;
143
+ environment?: string;
144
+ version?: string;
145
+ license: 'Enterprise' | 'Community';
146
+ }
147
+
148
+ const { mutate, isLoading } = useMutation<unknown, unknown, NpsSurveyMutationBody>(
136
149
  async (form) => {
137
150
  const res = await fetch('https://analytics.strapi.io/submit-nps', {
138
151
  method: 'POST',
@@ -152,7 +165,7 @@ const NpsSurvey = () => {
152
165
  onSuccess() {
153
166
  setNpsSurveySettings((settings) => ({
154
167
  ...settings,
155
- lastResponseDate: new Date(),
168
+ lastResponseDate: new Date().toString(),
156
169
  firstDismissalDate: null,
157
170
  lastDismissalDate: null,
158
171
  }));
@@ -165,7 +178,7 @@ const NpsSurvey = () => {
165
178
  onError() {
166
179
  toggleNotification({
167
180
  type: 'warning',
168
- message: formatMessage({ id: 'notification.error' }),
181
+ message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),
169
182
  });
170
183
  },
171
184
  }
@@ -197,12 +210,18 @@ const NpsSurvey = () => {
197
210
  return null;
198
211
  }
199
212
 
200
- const handleSubmitResponse = ({ npsSurveyRating: rating, npsSurveyFeedback: comment }) => {
201
- const { email } = auth.getUserInfo();
213
+ const handleSubmitResponse = ({
214
+ npsSurveyRating,
215
+ npsSurveyFeedback,
216
+ }: {
217
+ npsSurveyRating: NpsSurveyMutationBody['rating'];
218
+ npsSurveyFeedback: NpsSurveyMutationBody['comment'];
219
+ }) => {
220
+ const userInfo = auth.getUserInfo();
202
221
  mutate({
203
- email,
204
- rating,
205
- comment,
222
+ email: typeof userInfo === 'object' && userInfo !== null ? userInfo.email : '',
223
+ rating: npsSurveyRating,
224
+ comment: npsSurveyFeedback,
206
225
  environment: currentEnvironment,
207
226
  version: strapiVersion,
208
227
  license: window.strapi.projectType,
@@ -218,10 +237,10 @@ const NpsSurvey = () => {
218
237
 
219
238
  if (settings.firstDismissalDate) {
220
239
  // If the user dismisses the survey for the second time
221
- nextSettings.lastDismissalDate = new Date();
240
+ nextSettings.lastDismissalDate = new Date().toString();
222
241
  } else {
223
242
  // If the user dismisses the survey for the first time
224
- nextSettings.firstDismissalDate = new Date();
243
+ nextSettings.firstDismissalDate = new Date().toString();
225
244
  }
226
245
 
227
246
  return nextSettings;
@@ -295,7 +314,7 @@ const NpsSurvey = () => {
295
314
  return (
296
315
  <FieldWrapper
297
316
  key={number}
298
- className={values.npsSurveyRating === number ? 'selected' : null} // "selected" class added when child radio button is checked
317
+ className={values.npsSurveyRating === number ? 'selected' : undefined} // "selected" class added when child radio button is checked
299
318
  hasRadius
300
319
  background="primary100"
301
320
  borderColor="primary200"
@@ -365,4 +384,32 @@ const NpsSurvey = () => {
365
384
  );
366
385
  };
367
386
 
368
- export default NpsSurvey;
387
+ interface NpsSurveySettings {
388
+ enabled: boolean;
389
+ lastResponseDate: string | null;
390
+ firstDismissalDate: string | null;
391
+ lastDismissalDate: string | null;
392
+ }
393
+
394
+ /**
395
+ * We exported to make it available during admin user registration.
396
+ * Because we only enable the NPS for users who subscribe to the newsletter when signing up
397
+ */
398
+ function useNpsSurveySettings() {
399
+ const [npsSurveySettings, setNpsSurveySettings] = usePersistentState<NpsSurveySettings>(
400
+ 'STRAPI_NPS_SURVEY_SETTINGS',
401
+ {
402
+ enabled: true,
403
+ lastResponseDate: null,
404
+ firstDismissalDate: null,
405
+ lastDismissalDate: null,
406
+ }
407
+ );
408
+
409
+ /**
410
+ * TODO: should this just be an array so we can alias the `usePersistentState` hook?
411
+ */
412
+ return { npsSurveySettings, setNpsSurveySettings };
413
+ }
414
+
415
+ export { NpsSurvey, useNpsSurveySettings };
@@ -0,0 +1,124 @@
1
+ import * as React from 'react';
2
+
3
+ import {
4
+ LoadingIndicatorPage,
5
+ useStrapiApp,
6
+ type StrapiAppContextValue,
7
+ } from '@strapi/helper-plugin';
8
+ import produce from 'immer';
9
+ import set from 'lodash/set';
10
+
11
+ // @ts-expect-error pages/Admin has not been converted yet.
12
+ import Admin from '../pages/Admin';
13
+
14
+ /**
15
+ * TODO: this isn't great, and we really should focus on fixing this.
16
+ */
17
+ const PluginsInitializer = () => {
18
+ const { plugins: appPlugins } = useStrapiApp();
19
+ const [{ plugins }, dispatch] = React.useReducer<React.Reducer<State, Action>, State>(
20
+ reducer,
21
+ initialState,
22
+ () => init(appPlugins)
23
+ );
24
+ const setPlugin = React.useRef((pluginId: string) => {
25
+ dispatch({ type: 'SET_PLUGIN_READY', pluginId });
26
+ });
27
+
28
+ const hasApluginNotReady = Object.keys(plugins).some(
29
+ (plugin) => plugins[plugin].isReady === false
30
+ );
31
+
32
+ /**
33
+ *
34
+ * I have spent some time trying to understand what is happening here, and wanted to
35
+ * leave that knowledge for my future me:
36
+ *
37
+ * `initializer` is an undocumented property of the `registerPlugin` API. At the time
38
+ * of writing it seems only to be used by the i18n plugin.
39
+ *
40
+ * How does it work?
41
+ *
42
+ * Every plugin that has an `initializer` component defined, receives the
43
+ * `setPlugin` function as a component prop. In the case of i18n the plugin fetches locales
44
+ * first and calls `setPlugin` with `pluginId` once they are loaded, which then triggers the
45
+ * reducer of the admin app defined above.
46
+ *
47
+ * Once all plugins are set to `isReady: true` the app renders.
48
+ *
49
+ * This API is used to block rendering of the admin app. We should remove that in v5 completely
50
+ * and make sure plugins can inject data into the global store before they are initialized, to avoid
51
+ * having a new prop-callback based communication channel between plugins and the core admin app.
52
+ *
53
+ */
54
+
55
+ if (hasApluginNotReady) {
56
+ const initializers = Object.keys(plugins).reduce((acc, current) => {
57
+ const InitializerComponent = plugins[current].initializer;
58
+
59
+ if (InitializerComponent) {
60
+ const key = plugins[current].pluginId;
61
+
62
+ acc.push(<InitializerComponent key={key} setPlugin={setPlugin.current} />);
63
+ }
64
+
65
+ return acc;
66
+ }, [] as React.ReactNode[]);
67
+
68
+ return (
69
+ <>
70
+ {initializers}
71
+ <LoadingIndicatorPage />
72
+ </>
73
+ );
74
+ }
75
+
76
+ return <Admin />;
77
+ };
78
+
79
+ /* -------------------------------------------------------------------------------------------------
80
+ * Reducer
81
+ * -----------------------------------------------------------------------------------------------*/
82
+
83
+ interface State {
84
+ plugins: StrapiAppContextValue['plugins'];
85
+ }
86
+
87
+ const initialState: State = {
88
+ plugins: {},
89
+ };
90
+
91
+ type SetPluginReadyAction = {
92
+ type: 'SET_PLUGIN_READY';
93
+ pluginId: string;
94
+ };
95
+
96
+ type Action = SetPluginReadyAction;
97
+
98
+ const reducer: React.Reducer<State, Action> = (state = initialState, action: Action): State =>
99
+ produce(state, (draftState) => {
100
+ switch (action.type) {
101
+ case 'SET_PLUGIN_READY': {
102
+ set(draftState, ['plugins', action.pluginId, 'isReady'], true);
103
+ break;
104
+ }
105
+ default:
106
+ return draftState;
107
+ }
108
+ });
109
+
110
+ /* -------------------------------------------------------------------------------------------------
111
+ * Init state
112
+ * -----------------------------------------------------------------------------------------------*/
113
+
114
+ const init = (plugins: State['plugins']): State => {
115
+ return {
116
+ plugins: Object.keys(plugins).reduce<State['plugins']>((acc, current) => {
117
+ acc[current] = { ...plugins[current] };
118
+
119
+ return acc;
120
+ }, {}),
121
+ };
122
+ };
123
+
124
+ export { PluginsInitializer };
@@ -0,0 +1,42 @@
1
+ import * as React from 'react';
2
+
3
+ import { auth } from '@strapi/helper-plugin';
4
+ import { Redirect, Route, useLocation } from 'react-router-dom';
5
+
6
+ type PropsOf<T> = T extends React.ComponentType<infer P> ? P : object;
7
+
8
+ type PrivateRouteProps<TComponent extends React.ElementType> = {
9
+ component: TComponent;
10
+ path: string;
11
+ } & PropsOf<TComponent>;
12
+
13
+ const PrivateRoute = <TComponent extends React.ElementType>({
14
+ component: Component,
15
+ path,
16
+ ...rest
17
+ }: PrivateRouteProps<TComponent>) => {
18
+ const { pathname, search } = useLocation();
19
+
20
+ return (
21
+ <Route
22
+ path={path}
23
+ render={(props) =>
24
+ auth.getToken() !== null ? (
25
+ <Component {...rest} {...props} />
26
+ ) : (
27
+ <Redirect
28
+ to={{
29
+ pathname: '/auth/login',
30
+ search:
31
+ pathname !== '/'
32
+ ? `?redirectTo=${encodeURIComponent(`${pathname}${search}`)}`
33
+ : undefined,
34
+ }}
35
+ />
36
+ )
37
+ }
38
+ />
39
+ );
40
+ };
41
+
42
+ export { PrivateRoute };