@strapi/admin 4.12.6 → 4.12.7

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 (159) hide show
  1. package/admin/src/StrapiApp.js +1 -1
  2. package/admin/src/components/AuthenticatedApp/index.js +118 -0
  3. package/admin/src/components/AuthenticatedApp/utils/api.js +85 -0
  4. package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +11 -0
  5. package/admin/src/components/GuidedTour/Modal/index.js +3 -1
  6. package/admin/src/components/PluginsInitializer/index.js +68 -0
  7. package/admin/src/components/PluginsInitializer/init.js +11 -0
  8. package/admin/src/components/PluginsInitializer/reducer.js +22 -0
  9. package/admin/src/content-manager/pages/App/index.js +16 -5
  10. package/admin/src/content-manager/pages/EditView/Information/index.js +1 -1
  11. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +2 -2
  12. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
  13. package/admin/src/hooks/useSettingsForm/index.js +3 -14
  14. package/admin/src/hooks/useSettingsMenu/index.js +2 -2
  15. package/admin/src/hooks/useSettingsMenu/utils/formatLinks.js +3 -1
  16. package/admin/src/hooks/useSettingsMenu/utils/sortLinks.js +3 -1
  17. package/admin/src/index.js +1 -1
  18. package/admin/src/layouts/AppLayout/index.js +33 -0
  19. package/admin/src/pages/Admin/Onboarding/index.js +3 -1
  20. package/admin/src/pages/Admin/index.js +74 -80
  21. package/admin/src/pages/App/constants.js +1 -1
  22. package/admin/src/pages/App/index.js +122 -160
  23. package/admin/src/pages/AuthPage/index.js +4 -2
  24. package/admin/src/pages/HomePage/index.js +3 -1
  25. package/admin/src/pages/InstalledPluginsPage/index.js +3 -1
  26. package/admin/src/pages/{InternalErrorPage.js → InternalErrorPage/index.js} +4 -3
  27. package/admin/src/pages/{NotFoundPage.js → NotFoundPage/index.js} +3 -1
  28. package/admin/src/pages/ProfilePage/index.js +4 -2
  29. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +3 -3
  30. package/admin/src/pages/SettingsPage/constants.js +132 -67
  31. package/admin/src/pages/SettingsPage/index.js +36 -31
  32. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +1 -1
  33. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +35 -69
  34. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +23 -0
  35. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/prefixAllUrls.js +17 -0
  36. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
  37. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +1 -2
  38. package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
  39. package/admin/src/pages/SettingsPage/utils/createSectionsRoutes.js +11 -0
  40. package/admin/src/pages/SettingsPage/utils/getSectionsToDisplay.js +5 -0
  41. package/admin/src/pages/SettingsPage/utils/index.js +2 -0
  42. package/admin/src/pages/UseCasePage/index.js +175 -0
  43. package/admin/src/utils/checkFormValidity.js +15 -0
  44. package/admin/src/utils/createRoute.js +7 -5
  45. package/admin/src/utils/formatAPIErrors.js +3 -1
  46. package/admin/src/utils/getAttributesToDisplay.js +19 -0
  47. package/admin/src/utils/getExistingActions.js +32 -0
  48. package/admin/src/utils/getFullName.js +1 -1
  49. package/admin/src/utils/index.js +9 -0
  50. package/admin/src/utils/makeUniqueRoutes.js +6 -0
  51. package/admin/src/utils/sortLinks.js +3 -1
  52. package/admin/src/utils/uniqueAdminHash.js +9 -2
  53. package/build/{1049.9d69d231.chunk.js → 1049.f76cb14b.chunk.js} +1 -1
  54. package/build/1386.879bcd90.chunk.js +7 -0
  55. package/build/2225.c6244756.chunk.js +79 -0
  56. package/build/2379.f1641312.chunk.js +1 -0
  57. package/build/2395.46f8d0c1.chunk.js +26 -0
  58. package/build/2801.5cef5ec8.chunk.js +1 -0
  59. package/build/3483.03c24f96.chunk.js +1 -0
  60. package/build/3739.63e352f1.chunk.js +103 -0
  61. package/build/3929.5632f24d.chunk.js +114 -0
  62. package/build/448.829e1344.chunk.js +1 -0
  63. package/build/502.8ae8ef60.chunk.js +1 -0
  64. package/build/5483.6dd2e776.chunk.js +6 -0
  65. package/build/5542.2415a393.chunk.js +63 -0
  66. package/build/6691.4985ef22.chunk.js +105 -0
  67. package/build/7464.3e64a1d5.chunk.js +1 -0
  68. package/build/8276.10a3f883.chunk.js +26 -0
  69. package/build/{2747.d1442a90.chunk.js → 9806.5d5a0e8d.chunk.js} +64 -72
  70. package/build/9944.7af075a5.chunk.js +26 -0
  71. package/build/Admin-authenticatedApp.31497f74.chunk.js +79 -0
  72. package/build/Admin_InternalErrorPage.f45f2462.chunk.js +1 -0
  73. package/build/Admin_homePage.ac9dfb86.chunk.js +81 -0
  74. package/build/Admin_marketplace.c94239f6.chunk.js +55 -0
  75. package/build/Admin_pluginsPage.bbe79434.chunk.js +6 -0
  76. package/build/Admin_profilePage.192edc52.chunk.js +13 -0
  77. package/build/Admin_settingsPage.97cb9d41.chunk.js +111 -0
  78. package/build/admin-app.91898385.chunk.js +36 -0
  79. package/build/{admin-edit-roles-page.24bdf746.chunk.js → admin-edit-roles-page.6d567273.chunk.js} +1 -1
  80. package/build/admin-edit-users.acfd4128.chunk.js +10 -0
  81. package/build/{admin-users.2b3e4305.chunk.js → admin-users.00e20017.chunk.js} +2 -2
  82. package/build/{content-manager.fb0833bd.chunk.js → content-manager.b40f79c0.chunk.js} +78 -78
  83. package/build/{content-type-builder.66066281.chunk.js → content-type-builder.cd999f6e.chunk.js} +18 -18
  84. package/build/email-settings-page.d494d1eb.chunk.js +11 -0
  85. package/build/index.html +1 -1
  86. package/build/main.9dbe4579.js +2859 -0
  87. package/build/review-workflows-settings-create-view.cb08cfa2.chunk.js +1 -0
  88. package/build/review-workflows-settings-edit-view.3c7cbe63.chunk.js +1 -0
  89. package/build/review-workflows-settings-list-view.1611dc1f.chunk.js +56 -0
  90. package/build/runtime~main.d515c521.js +2 -0
  91. package/build/{sso-settings-page.4dba0670.chunk.js → sso-settings-page.12b6d8ae.chunk.js} +1 -1
  92. package/build/users-advanced-settings-page.f0760eb8.chunk.js +9 -0
  93. package/build/users-email-settings-page.ff4b32f3.chunk.js +9 -0
  94. package/build/users-providers-settings-page.48de0306.chunk.js +14 -0
  95. package/build/users-roles-settings-page.9d9a1eff.chunk.js +30 -0
  96. package/build/webhook-edit-page.6cb479ff.chunk.js +33 -0
  97. package/ee/admin/hooks/index.js +4 -0
  98. package/ee/admin/hooks/useAuthProviders/index.js +50 -0
  99. package/ee/admin/hooks/useAuthProviders/reducer.js +26 -0
  100. package/ee/admin/hooks/{useLicenseLimitNotification.js → useLicenseLimitNotification/index.js} +4 -2
  101. package/ee/admin/hooks/useLicenseLimits/index.js +1 -0
  102. package/ee/admin/hooks/{useLicenseLimits.js → useLicenseLimits/useLicenseLimits.js} +1 -4
  103. package/ee/admin/pages/App/constants.js +5 -6
  104. package/ee/admin/pages/AuthPage/components/Login/index.js +4 -8
  105. package/ee/admin/pages/AuthPage/components/Providers/index.js +5 -8
  106. package/ee/admin/pages/HomePage/index.js +1 -1
  107. package/ee/admin/pages/SettingsPage/constants.js +42 -27
  108. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/CreateView.js +1 -1
  109. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/EditView.js +1 -1
  110. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/ListView.js +1 -1
  111. package/ee/admin/pages/SettingsPage/pages/Users/ListPage/CreateAction/index.js +1 -1
  112. package/ee/admin/pages/SettingsPage/pages/Users/ListPage/index.js +1 -1
  113. package/package.json +8 -8
  114. package/admin/src/components/AuthenticatedApp.js +0 -229
  115. package/admin/src/pages/UseCasePage.js +0 -174
  116. package/build/1504.eff012f7.chunk.js +0 -95
  117. package/build/2166.c837469a.chunk.js +0 -1
  118. package/build/2225.33287e1b.chunk.js +0 -79
  119. package/build/2237.03792b63.chunk.js +0 -114
  120. package/build/2379.401f56f3.chunk.js +0 -1
  121. package/build/2395.e6a79fbb.chunk.js +0 -26
  122. package/build/2801.31393ffe.chunk.js +0 -1
  123. package/build/3483.8517171f.chunk.js +0 -1
  124. package/build/502.8dd074ff.chunk.js +0 -1
  125. package/build/5483.5bfbb00d.chunk.js +0 -6
  126. package/build/7464.592a9295.chunk.js +0 -1
  127. package/build/748.fd2e5afd.chunk.js +0 -105
  128. package/build/773.6381d62d.chunk.js +0 -18
  129. package/build/7826.399afe81.chunk.js +0 -103
  130. package/build/8261.2525d35c.chunk.js +0 -7
  131. package/build/8276.e519a707.chunk.js +0 -26
  132. package/build/8299.62b67c72.chunk.js +0 -1
  133. package/build/Admin-AuthPage.90d64342.chunk.js +0 -35
  134. package/build/Admin-AuthenticatedApp.379ac945.chunk.js +0 -24
  135. package/build/Admin-UseCasePage.1f757db5.chunk.js +0 -13
  136. package/build/Admin_GuidedTourModal.8ccf1fbc.chunk.js +0 -12
  137. package/build/Admin_InternalErrorPage.9de92c6d.chunk.js +0 -9
  138. package/build/Admin_NotFoundPage.21620424.chunk.js +0 -9
  139. package/build/Admin_Onboarding.dbfa32f6.chunk.js +0 -43
  140. package/build/Admin_homePage.2000cbe9.chunk.js +0 -86
  141. package/build/Admin_marketplace.ec80e29b.chunk.js +0 -63
  142. package/build/Admin_pluginsPage.0c6851f8.chunk.js +0 -14
  143. package/build/Admin_profilePage.78cd8495.chunk.js +0 -21
  144. package/build/Admin_settingsPage.1760c3ce.chunk.js +0 -119
  145. package/build/StrapiApp.221fac30.chunk.js +0 -5
  146. package/build/admin-edit-users.5d10d444.chunk.js +0 -10
  147. package/build/email-settings-page.2f7e35c0.chunk.js +0 -11
  148. package/build/main.ee3c1938.js +0 -2859
  149. package/build/review-workflows-settings-create-view.d24a32b9.chunk.js +0 -1
  150. package/build/review-workflows-settings-edit-view.6044b022.chunk.js +0 -1
  151. package/build/review-workflows-settings-list-view.3f0ef4bc.chunk.js +0 -56
  152. package/build/runtime~main.397ee447.js +0 -2
  153. package/build/users-advanced-settings-page.17052d72.chunk.js +0 -9
  154. package/build/users-email-settings-page.3de8ea50.chunk.js +0 -9
  155. package/build/users-providers-settings-page.0eaa916d.chunk.js +0 -14
  156. package/build/users-roles-settings-page.957ad48b.chunk.js +0 -55
  157. package/build/webhook-edit-page.665210af.chunk.js +0 -33
  158. package/ee/admin/hooks/useAuthProviders.js +0 -25
  159. /package/ee/admin/hooks/{__mocks__/useLicenseLimits.js → useLicenseLimits/__mocks__/index.js} +0 -0
@@ -28,14 +28,14 @@ import { useMutation, useQuery, useQueryClient } from 'react-query';
28
28
 
29
29
  import useLocalesProvider from '../../components/LocalesProvider/useLocalesProvider';
30
30
  import { useThemeToggle } from '../../hooks';
31
- import { getFullName } from '../../utils/getFullName';
31
+ import { getFullName } from '../../utils';
32
32
 
33
33
  import Password from './components/Password';
34
34
  import Preferences from './components/Preferences';
35
35
  import UserInfo from './components/UserInfo';
36
36
  import schema from './utils/schema';
37
37
 
38
- export const ProfilePage = () => {
38
+ const ProfilePage = () => {
39
39
  const { changeLocale, localeNames } = useLocalesProvider();
40
40
  const { setUserDisplayName } = useAppInfo();
41
41
  const queryClient = useQueryClient();
@@ -231,3 +231,5 @@ export const ProfilePage = () => {
231
231
  </Main>
232
232
  );
233
233
  };
234
+
235
+ export default ProfilePage;
@@ -12,14 +12,14 @@ import PropTypes from 'prop-types';
12
12
  import { useIntl } from 'react-intl';
13
13
  import { NavLink, useLocation } from 'react-router-dom';
14
14
 
15
+ import { getSectionsToDisplay } from '../../utils';
16
+
15
17
  const SettingsNav = ({ menu }) => {
16
18
  const { formatMessage } = useIntl();
17
19
  const { trackUsage } = useTracking();
18
20
  const { pathname } = useLocation();
19
21
 
20
- const filteredMenu = menu.filter(
21
- (section) => !section.links.every((link) => link.isDisplayed === false)
22
- );
22
+ const filteredMenu = getSectionsToDisplay(menu);
23
23
 
24
24
  const sections = filteredMenu.map((section) => {
25
25
  return {
@@ -1,102 +1,167 @@
1
- import * as React from 'react';
2
-
3
- export const SETTINGS_ROUTES_CE = [
1
+ export const ROUTES_CE = [
4
2
  {
5
- component: React.lazy(() =>
6
- import(/* webpackChunkName: "admin-roles-list" */ './pages/Roles/ProtectedListPage')
7
- ),
8
- path: '/settings/roles',
3
+ async Component() {
4
+ const component = await import(
5
+ /* webpackChunkName: "admin-roles-list" */ './pages/Roles/ProtectedListPage'
6
+ );
7
+
8
+ return component;
9
+ },
10
+ to: '/settings/roles',
11
+ exact: true,
9
12
  },
10
13
  {
11
- component: React.lazy(() =>
12
- import(/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/CreatePage')
13
- ),
14
- path: '/settings/roles/duplicate/:id',
14
+ async Component() {
15
+ const component = await import(
16
+ /* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/CreatePage'
17
+ );
18
+
19
+ return component;
20
+ },
21
+ to: '/settings/roles/duplicate/:id',
22
+ exact: true,
15
23
  },
16
24
  {
17
- component: React.lazy(() =>
18
- import(/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/CreatePage')
19
- ),
20
- path: '/settings/roles/new',
25
+ async Component() {
26
+ const component = await import(
27
+ /* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/CreatePage'
28
+ );
29
+
30
+ return component;
31
+ },
32
+ to: '/settings/roles/new',
33
+ exact: true,
21
34
  },
22
35
  {
23
- component: React.lazy(() =>
24
- import(/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/ProtectedEditPage')
25
- ),
26
- path: '/settings/roles/:id',
36
+ async Component() {
37
+ const component = await import(
38
+ /* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/ProtectedEditPage'
39
+ );
40
+
41
+ return component;
42
+ },
43
+ to: '/settings/roles/:id',
44
+ exact: true,
27
45
  },
28
46
  {
29
- component: React.lazy(() =>
30
- import(/* webpackChunkName: "admin-users" */ './pages/Users/ProtectedListPage')
31
- ),
32
- path: '/settings/users',
47
+ async Component() {
48
+ const component = await import(
49
+ /* webpackChunkName: "admin-users" */ './pages/Users/ProtectedListPage'
50
+ );
51
+
52
+ return component;
53
+ },
54
+ to: '/settings/users',
55
+ exact: true,
33
56
  },
34
57
  {
35
- component: React.lazy(() =>
36
- import(/* webpackChunkName: "admin-edit-users" */ './pages/Users/ProtectedEditPage')
37
- ),
38
- path: '/settings/users/:id',
58
+ async Component() {
59
+ const component = await import(
60
+ /* webpackChunkName: "admin-edit-users" */ './pages/Users/ProtectedEditPage'
61
+ );
62
+
63
+ return component;
64
+ },
65
+ to: '/settings/users/:id',
66
+ exact: true,
39
67
  },
40
68
  {
41
- component: React.lazy(() =>
42
- import(/* webpackChunkName: "webhook-edit-page" */ './pages/Webhooks/ProtectedCreateView')
43
- ),
44
- path: '/settings/webhooks/create',
69
+ async Component() {
70
+ const component = await import(
71
+ /* webpackChunkName: "webhook-edit-page" */ './pages/Webhooks/ProtectedCreateView'
72
+ );
73
+
74
+ return component;
75
+ },
76
+ to: '/settings/webhooks/create',
77
+ exact: true,
45
78
  },
46
79
  {
47
- component: React.lazy(() =>
48
- import(/* webpackChunkName: "webhook-edit-page" */ './pages/Webhooks/ProtectedEditView')
49
- ),
50
- path: '/settings/webhooks/:id',
80
+ async Component() {
81
+ const component = await import(
82
+ /* webpackChunkName: "webhook-edit-page" */ './pages/Webhooks/ProtectedEditView'
83
+ );
84
+
85
+ return component;
86
+ },
87
+ to: '/settings/webhooks/:id',
88
+ exact: true,
51
89
  },
52
90
  {
53
- component: React.lazy(() =>
54
- import(/* webpackChunkName: "webhook-list-page" */ './pages/Webhooks/ProtectedListView')
55
- ),
56
- path: '/settings/webhooks',
91
+ async Component() {
92
+ const component = await import(
93
+ /* webpackChunkName: "webhook-list-page" */ './pages/Webhooks/ProtectedListView'
94
+ );
95
+
96
+ return component;
97
+ },
98
+ to: '/settings/webhooks',
99
+ exact: true,
57
100
  },
58
101
  {
59
- component: React.lazy(() =>
60
- import(/* webpackChunkName: "api-tokens-list-page" */ './pages/ApiTokens/ProtectedListView')
61
- ),
62
- path: '/settings/api-tokens',
102
+ async Component() {
103
+ const component = await import(
104
+ /* webpackChunkName: "api-tokens-list-page" */ './pages/ApiTokens/ProtectedListView'
105
+ );
106
+
107
+ return component;
108
+ },
109
+ to: '/settings/api-tokens',
110
+ exact: true,
63
111
  },
64
112
  {
65
- component: React.lazy(() =>
66
- import(
113
+ async Component() {
114
+ const component = await import(
67
115
  /* webpackChunkName: "api-tokens-create-page" */ './pages/ApiTokens/ProtectedCreateView'
68
- )
69
- ),
70
- path: '/settings/api-tokens/create',
116
+ );
117
+
118
+ return component;
119
+ },
120
+ to: '/settings/api-tokens/create',
121
+ exact: true,
71
122
  },
72
123
  {
73
- component: React.lazy(() =>
74
- import(/* webpackChunkName: "api-tokens-edit-page" */ './pages/ApiTokens/ProtectedEditView')
75
- ),
76
- path: '/settings/api-tokens/:id',
124
+ async Component() {
125
+ const component = await import(
126
+ /* webpackChunkName: "api-tokens-edit-page" */ './pages/ApiTokens/ProtectedEditView'
127
+ );
128
+
129
+ return component;
130
+ },
131
+ to: '/settings/api-tokens/:id',
132
+ exact: true,
77
133
  },
78
134
  {
79
- component: React.lazy(() =>
80
- import(
135
+ async Component() {
136
+ const component = await import(
81
137
  /* webpackChunkName: "transfer-tokens-create-page" */ './pages/TransferTokens/ProtectedCreateView'
82
- )
83
- ),
84
- path: '/settings/transfer-tokens/create',
138
+ );
139
+
140
+ return component;
141
+ },
142
+ to: '/settings/transfer-tokens/create',
143
+ exact: true,
85
144
  },
86
145
  {
87
- component: React.lazy(() =>
88
- import(
146
+ async Component() {
147
+ const component = await import(
89
148
  /* webpackChunkName: "transfer-tokens-list-page" */ './pages/TransferTokens/ProtectedListView'
90
- )
91
- ),
92
- path: '/settings/transfer-tokens',
149
+ );
150
+
151
+ return component;
152
+ },
153
+ to: '/settings/transfer-tokens',
154
+ exact: true,
93
155
  },
94
156
  {
95
- component: React.lazy(() =>
96
- import(
157
+ async Component() {
158
+ const component = await import(
97
159
  /* webpackChunkName: "transfer-tokens-edit-page" */ './pages/TransferTokens/ProtectedEditView'
98
- )
99
- ),
100
- path: '/settings/transfer-tokens/:id',
160
+ );
161
+
162
+ return component;
163
+ },
164
+ to: '/settings/transfer-tokens/:id',
165
+ exact: true,
101
166
  },
102
167
  ];
@@ -1,4 +1,15 @@
1
- import * as React from 'react';
1
+ /**
2
+ *
3
+ * SettingsPage
4
+ *
5
+ */
6
+
7
+ // NOTE TO PLUGINS DEVELOPERS:
8
+ // If you modify this file you also need to update the documentation accordingly
9
+ // Here's the file: strapi/docs/3.0.0-beta.x/plugin-development/frontend-settings-api.md
10
+ // IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED
11
+
12
+ import React, { memo, useMemo } from 'react';
2
13
 
3
14
  import { Layout } from '@strapi/design-system';
4
15
  import { LoadingIndicatorPage, useStrapiApp } from '@strapi/helper-plugin';
@@ -8,21 +19,21 @@ import { Redirect, Route, Switch, useParams } from 'react-router-dom';
8
19
 
9
20
  import { useSettingsMenu } from '../../hooks';
10
21
  import { useEnterprise } from '../../hooks/useEnterprise';
11
- import { createRoute } from '../../utils/createRoute';
22
+ import { createRoute, makeUniqueRoutes } from '../../utils';
12
23
 
13
24
  import SettingsNav from './components/SettingsNav';
14
- import { SETTINGS_ROUTES_CE } from './constants';
25
+ import { ROUTES_CE } from './constants';
15
26
  import ApplicationInfosPage from './pages/ApplicationInfosPage';
27
+ import { createSectionsRoutes } from './utils';
16
28
 
17
- export function SettingsPage() {
29
+ function SettingsPage() {
18
30
  const { settingId } = useParams();
19
31
  const { settings } = useStrapiApp();
20
32
  const { formatMessage } = useIntl();
21
33
  const { isLoading, menu } = useSettingsMenu();
22
34
  const routes = useEnterprise(
23
- SETTINGS_ROUTES_CE,
24
- async () =>
25
- (await import('../../../../ee/admin/pages/SettingsPage/constants')).SETTINGS_ROUTES_EE,
35
+ ROUTES_CE,
36
+ async () => (await import('../../../../ee/admin/pages/SettingsPage/constants')).ROUTES_EE,
26
37
  {
27
38
  combine(ceRoutes, eeRoutes) {
28
39
  return [...ceRoutes, ...eeRoutes];
@@ -31,19 +42,14 @@ export function SettingsPage() {
31
42
  }
32
43
  );
33
44
 
34
- /**
35
- * `Component` is an async function, which is passed as property of the
36
- * addSettingsLink() API during the plugin bootstrap step.
37
- *
38
- * Because of that we can't just render <Route component={Component} />,
39
- * but have to await the function.
40
- *
41
- * This isn't a good React pattern and should be reconsidered.
42
- */
45
+ // Creates the admin routes
46
+ const adminRoutes = useMemo(() => {
47
+ return makeUniqueRoutes(
48
+ routes.map(({ to, Component, exact }) => createRoute(Component, to, exact))
49
+ );
50
+ }, [routes]);
43
51
 
44
- const pluginSettingsRoutes = Object.values(settings).flatMap((section) =>
45
- section.links.map((link) => createRoute(link.Component, link.to, link.exact || false))
46
- );
52
+ const pluginsRoutes = createSectionsRoutes(settings);
47
53
 
48
54
  // Since the useSettingsMenu hook can make API calls in order to check the links permissions
49
55
  // We need to add a loading state to prevent redirecting the user while permissions are being checked
@@ -55,24 +61,23 @@ export function SettingsPage() {
55
61
  return <Redirect to="/settings/application-infos" />;
56
62
  }
57
63
 
64
+ const settingTitle = formatMessage({
65
+ id: 'global.settings',
66
+ defaultMessage: 'Settings',
67
+ });
68
+
58
69
  return (
59
70
  <Layout sideNav={<SettingsNav menu={menu} />}>
60
- <Helmet
61
- title={formatMessage({
62
- id: 'global.settings',
63
- defaultMessage: 'Settings',
64
- })}
65
- />
71
+ <Helmet title={settingTitle} />
66
72
 
67
73
  <Switch>
68
74
  <Route path="/settings/application-infos" component={ApplicationInfosPage} exact />
69
-
70
- {routes.map(({ path, component }) => (
71
- <Route key={path} path={path} component={component} exact />
72
- ))}
73
-
74
- {pluginSettingsRoutes}
75
+ {adminRoutes}
76
+ {pluginsRoutes}
75
77
  </Switch>
76
78
  </Layout>
77
79
  );
78
80
  }
81
+
82
+ export default memo(SettingsPage);
83
+ export { SettingsPage };
@@ -19,7 +19,7 @@ import { useSelector } from 'react-redux';
19
19
  import { useHistory, useRouteMatch } from 'react-router-dom';
20
20
 
21
21
  import { ApiTokenPermissionsContextProvider } from '../../../../../contexts/ApiTokenPermissions';
22
- import { formatAPIErrors } from '../../../../../utils/formatAPIErrors';
22
+ import { formatAPIErrors } from '../../../../../utils';
23
23
  import { selectAdminPermissions } from '../../../../App/selectors';
24
24
  import { API_TOKEN_TYPE } from '../../../components/Tokens/constants';
25
25
  import FormHead from '../../../components/Tokens/FormHead';
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React, { useRef } from 'react';
2
2
 
3
3
  import {
4
4
  Button,
@@ -14,11 +14,8 @@ import {
14
14
  Typography,
15
15
  } from '@strapi/design-system';
16
16
  import {
17
- prefixFileUrlWithBackendUrl,
18
17
  SettingsPageTitle,
19
- useAPIErrorHandler,
20
18
  useAppInfo,
21
- useFetchClient,
22
19
  useFocusWhenNavigate,
23
20
  useNotification,
24
21
  useRBAC,
@@ -26,7 +23,7 @@ import {
26
23
  } from '@strapi/helper-plugin';
27
24
  import { Check, ExternalLink } from '@strapi/icons';
28
25
  import { useIntl } from 'react-intl';
29
- import { useMutation, useQuery } from 'react-query';
26
+ import { useMutation, useQuery, useQueryClient } from 'react-query';
30
27
  import { useSelector } from 'react-redux';
31
28
 
32
29
  import { useConfigurations } from '../../../../hooks';
@@ -34,20 +31,18 @@ import { useEnterprise } from '../../../../hooks/useEnterprise';
34
31
  import { selectAdminPermissions } from '../../../App/selectors';
35
32
 
36
33
  import CustomizationInfos from './components/CustomizationInfos';
34
+ import { fetchProjectSettings, postProjectSettings } from './utils/api';
37
35
  import getFormData from './utils/getFormData';
38
36
 
39
37
  const AdminSeatInfoCE = () => null;
40
38
 
41
39
  const ApplicationInfosPage = () => {
42
- const inputsRef = React.useRef();
40
+ const inputsRef = useRef();
43
41
  const toggleNotification = useNotification();
44
42
  const { trackUsage } = useTracking();
45
43
  const { formatMessage } = useIntl();
46
- const { get, post } = useFetchClient();
47
- const { updateProjectSettings } = useConfigurations();
48
- const permissions = useSelector(selectAdminPermissions);
49
- const { formatAPIError } = useAPIErrorHandler();
50
-
44
+ const queryClient = useQueryClient();
45
+ useFocusWhenNavigate();
51
46
  const {
52
47
  communityEdition,
53
48
  latestStrapiReleaseTag,
@@ -55,7 +50,8 @@ const ApplicationInfosPage = () => {
55
50
  shouldUpdateStrapi,
56
51
  strapiVersion,
57
52
  } = useAppInfo();
58
-
53
+ const { updateProjectSettings } = useConfigurations();
54
+ const permissions = useSelector(selectAdminPermissions);
59
55
  const AdminSeatInfo = useEnterprise(
60
56
  AdminSeatInfoCE,
61
57
  async () =>
@@ -69,68 +65,38 @@ const ApplicationInfosPage = () => {
69
65
  const {
70
66
  allowedActions: { canRead, canUpdate },
71
67
  } = useRBAC(permissions.settings['project-settings']);
68
+ const canSubmit = canRead && canUpdate;
72
69
 
73
- useFocusWhenNavigate();
70
+ const { data, isLoading } = useQuery('project-settings', fetchProjectSettings, {
71
+ enabled: canRead,
72
+ });
74
73
 
75
- const { data, isLoading } = useQuery(
76
- ['project-settings'],
77
- async () => {
78
- const { data } = await get('/admin/project-settings');
79
-
80
- return data;
74
+ const submitMutation = useMutation((body) => postProjectSettings(body), {
75
+ async onSuccess({ menuLogo, authLogo }) {
76
+ await queryClient.invalidateQueries('project-settings', { refetchActive: true });
77
+ updateProjectSettings({ menuLogo: menuLogo?.url, authLogo: authLogo?.url });
81
78
  },
82
- {
83
- cacheTime: 0,
84
- enabled: canRead,
85
- select(data) {
86
- return {
87
- ...data,
88
-
89
- authLogo: data.authLogo
90
- ? {
91
- ...data.authLogo,
92
- url: prefixFileUrlWithBackendUrl(data.authLogo.url),
93
- }
94
- : data.authLogo,
79
+ });
95
80
 
96
- menuLogo: data.menuLogo
97
- ? {
98
- ...data.menuLogo,
99
- url: prefixFileUrlWithBackendUrl(data.menuLogo.url),
100
- }
101
- : data.menuLogo,
102
- };
103
- },
104
- }
105
- );
81
+ const handleSubmit = (e) => {
82
+ e.preventDefault();
106
83
 
107
- const submitMutation = useMutation(
108
- (body) =>
109
- post('/admin/project-settings', body, {
110
- headers: {
111
- 'Content-Type': 'multipart/form-data',
112
- },
113
- }),
114
- {
115
- onError(error) {
116
- toggleNotification({
117
- type: 'warning',
118
- message: formatAPIError(error),
119
- });
120
- },
84
+ if (!canUpdate) return;
121
85
 
122
- async onSuccess(data) {
123
- const { menuLogo, authLogo } = data;
86
+ const inputValues = inputsRef.current.getValues();
87
+ const formData = getFormData(inputValues);
124
88
 
125
- updateProjectSettings({ menuLogo: menuLogo?.url, authLogo: authLogo?.url });
89
+ submitMutation.mutate(formData, {
90
+ onSuccess() {
91
+ const { menuLogo, authLogo } = inputValues;
126
92
 
127
- if (menuLogo?.rawFile) {
93
+ if (menuLogo.rawFile) {
128
94
  trackUsage('didChangeLogo', {
129
95
  logo: 'menu',
130
96
  });
131
97
  }
132
98
 
133
- if (authLogo?.rawFile) {
99
+ if (authLogo.rawFile) {
134
100
  trackUsage('didChangeLogo', {
135
101
  logo: 'auth',
136
102
  });
@@ -141,13 +107,13 @@ const ApplicationInfosPage = () => {
141
107
  message: formatMessage({ id: 'app', defaultMessage: 'Saved' }),
142
108
  });
143
109
  },
144
- }
145
- );
146
-
147
- const handleSubmit = (e) => {
148
- e.preventDefault();
149
-
150
- submitMutation.mutate(getFormData(inputsRef.current.getValues()));
110
+ onError() {
111
+ toggleNotification({
112
+ type: 'warning',
113
+ message: { id: 'notification.error', defaultMessage: 'An error occurred' },
114
+ });
115
+ },
116
+ });
151
117
  };
152
118
 
153
119
  // block rendering until the EE component is fully loaded
@@ -179,7 +145,7 @@ const ApplicationInfosPage = () => {
179
145
  defaultMessage: 'Administration panel’s global information',
180
146
  })}
181
147
  primaryAction={
182
- canUpdate && (
148
+ canSubmit && (
183
149
  <Button type="submit" startIcon={<Check />}>
184
150
  {formatMessage({ id: 'global.save', defaultMessage: 'Save' })}
185
151
  </Button>
@@ -0,0 +1,23 @@
1
+ import { getFetchClient } from '@strapi/helper-plugin';
2
+
3
+ import prefixAllUrls from './prefixAllUrls';
4
+
5
+ const fetchProjectSettings = async () => {
6
+ const { get } = getFetchClient();
7
+ const { data } = await get('/admin/project-settings');
8
+
9
+ return prefixAllUrls(data);
10
+ };
11
+
12
+ const postProjectSettings = async (body) => {
13
+ const { post } = getFetchClient();
14
+ const { data } = await post('/admin/project-settings', body, {
15
+ headers: {
16
+ 'Content-Type': 'multipart/form-data',
17
+ },
18
+ });
19
+
20
+ return prefixAllUrls(data);
21
+ };
22
+
23
+ export { fetchProjectSettings, postProjectSettings };
@@ -0,0 +1,17 @@
1
+ import { prefixFileUrlWithBackendUrl } from '@strapi/helper-plugin';
2
+ import transform from 'lodash/transform';
3
+
4
+ const prefixAllUrls = (data) =>
5
+ transform(
6
+ data,
7
+ (result, value, key) => {
8
+ if (value && value.url) {
9
+ result[key] = { ...value, url: prefixFileUrlWithBackendUrl(value.url) };
10
+ } else {
11
+ result[key] = value;
12
+ }
13
+ },
14
+ {}
15
+ );
16
+
17
+ export default prefixAllUrls;
@@ -19,7 +19,7 @@ import { useQuery } from 'react-query';
19
19
  import { useSelector } from 'react-redux';
20
20
  import { useHistory, useRouteMatch } from 'react-router-dom';
21
21
 
22
- import { formatAPIErrors } from '../../../../../utils/formatAPIErrors';
22
+ import { formatAPIErrors } from '../../../../../utils';
23
23
  import { selectAdminPermissions } from '../../../../App/selectors';
24
24
  import { TRANSFER_TOKEN_TYPE } from '../../../components/Tokens/constants';
25
25
  import FormHead from '../../../components/Tokens/FormHead';
@@ -34,8 +34,7 @@ import { useHistory, useRouteMatch } from 'react-router-dom';
34
34
 
35
35
  import { useAdminUsers } from '../../../../../hooks/useAdminUsers';
36
36
  import { useEnterprise } from '../../../../../hooks/useEnterprise';
37
- import { formatAPIErrors } from '../../../../../utils/formatAPIErrors';
38
- import { getFullName } from '../../../../../utils/getFullName';
37
+ import { formatAPIErrors, getFullName } from '../../../../../utils';
39
38
  import { MagicLinkCE } from '../components/MagicLink';
40
39
  import SelectRoles from '../components/SelectRoles';
41
40
  import { editValidation } from '../utils/validations/users';
@@ -16,7 +16,7 @@ import PropTypes from 'prop-types';
16
16
  import { useIntl } from 'react-intl';
17
17
  import { useHistory } from 'react-router-dom';
18
18
 
19
- import { getFullName } from '../../../../../../../utils/getFullName';
19
+ import { getFullName } from '../../../../../../../utils';
20
20
 
21
21
  const TableRows = ({
22
22
  canDelete,
@@ -0,0 +1,11 @@
1
+ import flatMap from 'lodash/flatMap';
2
+
3
+ import { createRoute } from '../../../utils';
4
+
5
+ const createSectionsRoutes = (settings) => {
6
+ const allLinks = flatMap(settings, (section) => section.links);
7
+
8
+ return allLinks.map((link) => createRoute(link.Component, link.to, link.exact || false));
9
+ };
10
+
11
+ export default createSectionsRoutes;
@@ -0,0 +1,5 @@
1
+ const getSectionsToDisplay = (menu) => {
2
+ return menu.filter((section) => !section.links.every((link) => link.isDisplayed === false));
3
+ };
4
+
5
+ export default getSectionsToDisplay;