@strapi/admin 4.12.5 → 4.12.6
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.
- package/admin/src/StrapiApp.js +1 -1
- package/admin/src/components/AuthenticatedApp.js +229 -0
- package/admin/src/components/GuidedTour/Modal/index.js +1 -3
- package/admin/src/content-manager/pages/App/index.js +5 -16
- package/admin/src/content-manager/pages/EditView/Information/index.js +1 -1
- package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +2 -2
- package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
- package/admin/src/hooks/useSettingsForm/index.js +14 -3
- package/admin/src/hooks/useSettingsMenu/index.js +2 -2
- package/admin/src/hooks/useSettingsMenu/utils/formatLinks.js +1 -3
- package/admin/src/hooks/useSettingsMenu/utils/sortLinks.js +1 -3
- package/admin/src/index.js +1 -1
- package/admin/src/pages/Admin/Onboarding/index.js +1 -3
- package/admin/src/pages/Admin/index.js +80 -74
- package/admin/src/pages/App/constants.js +1 -1
- package/admin/src/pages/App/index.js +160 -122
- package/admin/src/pages/AuthPage/index.js +2 -4
- package/admin/src/pages/HomePage/index.js +1 -3
- package/admin/src/pages/InstalledPluginsPage/index.js +1 -3
- package/admin/src/pages/{InternalErrorPage/index.js → InternalErrorPage.js} +3 -4
- package/admin/src/pages/{NotFoundPage/index.js → NotFoundPage.js} +1 -3
- package/admin/src/pages/ProfilePage/index.js +2 -4
- package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +3 -3
- package/admin/src/pages/SettingsPage/constants.js +67 -132
- package/admin/src/pages/SettingsPage/index.js +31 -36
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +69 -35
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +2 -1
- package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
- package/admin/src/pages/UseCasePage.js +174 -0
- package/admin/src/utils/createRoute.js +5 -7
- package/admin/src/utils/formatAPIErrors.js +1 -3
- package/admin/src/utils/getFullName.js +1 -1
- package/admin/src/utils/sortLinks.js +1 -3
- package/admin/src/utils/uniqueAdminHash.js +2 -9
- package/build/{1049.f76cb14b.chunk.js → 1049.9d69d231.chunk.js} +1 -1
- package/build/1504.eff012f7.chunk.js +95 -0
- package/build/2166.c837469a.chunk.js +1 -0
- package/build/2225.33287e1b.chunk.js +79 -0
- package/build/2237.03792b63.chunk.js +114 -0
- package/build/2379.401f56f3.chunk.js +1 -0
- package/build/2395.e6a79fbb.chunk.js +26 -0
- package/build/{9806.5d5a0e8d.chunk.js → 2747.d1442a90.chunk.js} +72 -64
- package/build/2801.31393ffe.chunk.js +1 -0
- package/build/3483.8517171f.chunk.js +1 -0
- package/build/502.8dd074ff.chunk.js +1 -0
- package/build/5483.5bfbb00d.chunk.js +6 -0
- package/build/7464.592a9295.chunk.js +1 -0
- package/build/748.fd2e5afd.chunk.js +105 -0
- package/build/773.6381d62d.chunk.js +18 -0
- package/build/7826.399afe81.chunk.js +103 -0
- package/build/8261.2525d35c.chunk.js +7 -0
- package/build/8276.e519a707.chunk.js +26 -0
- package/build/8299.62b67c72.chunk.js +1 -0
- package/build/Admin-AuthPage.90d64342.chunk.js +35 -0
- package/build/Admin-AuthenticatedApp.379ac945.chunk.js +24 -0
- package/build/Admin-UseCasePage.1f757db5.chunk.js +13 -0
- package/build/Admin_GuidedTourModal.8ccf1fbc.chunk.js +12 -0
- package/build/Admin_InternalErrorPage.9de92c6d.chunk.js +9 -0
- package/build/Admin_NotFoundPage.21620424.chunk.js +9 -0
- package/build/Admin_Onboarding.dbfa32f6.chunk.js +43 -0
- package/build/Admin_homePage.2000cbe9.chunk.js +86 -0
- package/build/Admin_marketplace.ec80e29b.chunk.js +63 -0
- package/build/Admin_pluginsPage.0c6851f8.chunk.js +14 -0
- package/build/Admin_profilePage.78cd8495.chunk.js +21 -0
- package/build/Admin_settingsPage.1760c3ce.chunk.js +119 -0
- package/build/StrapiApp.221fac30.chunk.js +5 -0
- package/build/{admin-edit-roles-page.6d567273.chunk.js → admin-edit-roles-page.24bdf746.chunk.js} +1 -1
- package/build/admin-edit-users.5d10d444.chunk.js +10 -0
- package/build/{admin-users.00e20017.chunk.js → admin-users.2b3e4305.chunk.js} +2 -2
- package/build/{content-manager.b40f79c0.chunk.js → content-manager.fb0833bd.chunk.js} +78 -78
- package/build/{content-type-builder.cd999f6e.chunk.js → content-type-builder.66066281.chunk.js} +18 -18
- package/build/email-settings-page.2f7e35c0.chunk.js +11 -0
- package/build/index.html +1 -1
- package/build/main.ee3c1938.js +2859 -0
- package/build/review-workflows-settings-create-view.d24a32b9.chunk.js +1 -0
- package/build/review-workflows-settings-edit-view.6044b022.chunk.js +1 -0
- package/build/review-workflows-settings-list-view.3f0ef4bc.chunk.js +56 -0
- package/build/runtime~main.397ee447.js +2 -0
- package/build/{sso-settings-page.12b6d8ae.chunk.js → sso-settings-page.4dba0670.chunk.js} +1 -1
- package/build/users-advanced-settings-page.17052d72.chunk.js +9 -0
- package/build/users-email-settings-page.3de8ea50.chunk.js +9 -0
- package/build/users-providers-settings-page.0eaa916d.chunk.js +14 -0
- package/build/users-roles-settings-page.957ad48b.chunk.js +55 -0
- package/build/webhook-edit-page.665210af.chunk.js +33 -0
- package/ee/admin/hooks/useAuthProviders.js +25 -0
- package/ee/admin/hooks/{useLicenseLimitNotification/index.js → useLicenseLimitNotification.js} +2 -4
- package/ee/admin/hooks/{useLicenseLimits/useLicenseLimits.js → useLicenseLimits.js} +4 -1
- package/ee/admin/pages/App/constants.js +6 -5
- package/ee/admin/pages/AuthPage/components/Login/index.js +8 -4
- package/ee/admin/pages/AuthPage/components/Providers/index.js +8 -5
- package/ee/admin/pages/HomePage/index.js +1 -1
- package/ee/admin/pages/SettingsPage/constants.js +27 -42
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/CreateView.js +1 -1
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/EditView.js +1 -1
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/ListView.js +1 -1
- package/ee/admin/pages/SettingsPage/pages/Users/ListPage/CreateAction/index.js +1 -1
- package/ee/admin/pages/SettingsPage/pages/Users/ListPage/index.js +1 -1
- package/package.json +8 -8
- package/admin/src/components/AuthenticatedApp/index.js +0 -118
- package/admin/src/components/AuthenticatedApp/utils/api.js +0 -85
- package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +0 -11
- package/admin/src/components/PluginsInitializer/index.js +0 -68
- package/admin/src/components/PluginsInitializer/init.js +0 -11
- package/admin/src/components/PluginsInitializer/reducer.js +0 -22
- package/admin/src/layouts/AppLayout/index.js +0 -33
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +0 -23
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/prefixAllUrls.js +0 -17
- package/admin/src/pages/SettingsPage/utils/createSectionsRoutes.js +0 -11
- package/admin/src/pages/SettingsPage/utils/getSectionsToDisplay.js +0 -5
- package/admin/src/pages/SettingsPage/utils/index.js +0 -2
- package/admin/src/pages/UseCasePage/index.js +0 -175
- package/admin/src/utils/checkFormValidity.js +0 -15
- package/admin/src/utils/getAttributesToDisplay.js +0 -19
- package/admin/src/utils/getExistingActions.js +0 -32
- package/admin/src/utils/index.js +0 -9
- package/admin/src/utils/makeUniqueRoutes.js +0 -6
- package/build/1386.879bcd90.chunk.js +0 -7
- package/build/2225.c6244756.chunk.js +0 -79
- package/build/2379.f1641312.chunk.js +0 -1
- package/build/2395.46f8d0c1.chunk.js +0 -26
- package/build/2801.5cef5ec8.chunk.js +0 -1
- package/build/3483.03c24f96.chunk.js +0 -1
- package/build/3739.63e352f1.chunk.js +0 -103
- package/build/3929.5632f24d.chunk.js +0 -114
- package/build/448.829e1344.chunk.js +0 -1
- package/build/502.8ae8ef60.chunk.js +0 -1
- package/build/5483.6dd2e776.chunk.js +0 -6
- package/build/5542.2415a393.chunk.js +0 -63
- package/build/6691.4985ef22.chunk.js +0 -105
- package/build/7464.3e64a1d5.chunk.js +0 -1
- package/build/8276.10a3f883.chunk.js +0 -26
- package/build/9944.7af075a5.chunk.js +0 -26
- package/build/Admin-authenticatedApp.01fc56de.chunk.js +0 -79
- package/build/Admin_InternalErrorPage.f45f2462.chunk.js +0 -1
- package/build/Admin_homePage.ac9dfb86.chunk.js +0 -81
- package/build/Admin_marketplace.c94239f6.chunk.js +0 -55
- package/build/Admin_pluginsPage.bbe79434.chunk.js +0 -6
- package/build/Admin_profilePage.192edc52.chunk.js +0 -13
- package/build/Admin_settingsPage.97cb9d41.chunk.js +0 -111
- package/build/admin-app.91898385.chunk.js +0 -36
- package/build/admin-edit-users.acfd4128.chunk.js +0 -10
- package/build/email-settings-page.d494d1eb.chunk.js +0 -11
- package/build/main.9dbe4579.js +0 -2859
- package/build/review-workflows-settings-create-view.cb08cfa2.chunk.js +0 -1
- package/build/review-workflows-settings-edit-view.3c7cbe63.chunk.js +0 -1
- package/build/review-workflows-settings-list-view.1611dc1f.chunk.js +0 -56
- package/build/runtime~main.46a609e9.js +0 -2
- package/build/users-advanced-settings-page.f0760eb8.chunk.js +0 -9
- package/build/users-email-settings-page.ff4b32f3.chunk.js +0 -9
- package/build/users-providers-settings-page.48de0306.chunk.js +0 -14
- package/build/users-roles-settings-page.9d9a1eff.chunk.js +0 -30
- package/build/webhook-edit-page.6cb479ff.chunk.js +0 -33
- package/ee/admin/hooks/index.js +0 -4
- package/ee/admin/hooks/useAuthProviders/index.js +0 -50
- package/ee/admin/hooks/useAuthProviders/reducer.js +0 -26
- package/ee/admin/hooks/useLicenseLimits/index.js +0 -1
- /package/ee/admin/hooks/{useLicenseLimits/__mocks__/index.js → __mocks__/useLicenseLimits.js} +0 -0
package/admin/src/StrapiApp.js
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from './exposedHooks';
|
|
23
23
|
import favicon from './favicon.png';
|
|
24
24
|
import injectionZones from './injectionZones';
|
|
25
|
-
import App from './pages/App';
|
|
25
|
+
import { App } from './pages/App';
|
|
26
26
|
import languageNativeNames from './translations/languageNativeNames';
|
|
27
27
|
|
|
28
28
|
class StrapiApp {
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
AppInfoProvider,
|
|
5
|
+
auth,
|
|
6
|
+
LoadingIndicatorPage,
|
|
7
|
+
useFetchClient,
|
|
8
|
+
useGuidedTour,
|
|
9
|
+
useNotification,
|
|
10
|
+
useStrapiApp,
|
|
11
|
+
} from '@strapi/helper-plugin';
|
|
12
|
+
import { useQueries } from 'react-query';
|
|
13
|
+
import { valid, lt } from 'semver';
|
|
14
|
+
|
|
15
|
+
import packageJSON from '../../../package.json';
|
|
16
|
+
import { useConfigurations } from '../hooks';
|
|
17
|
+
import { Admin } from '../pages/Admin';
|
|
18
|
+
import { getFullName } from '../utils/getFullName';
|
|
19
|
+
import { hashAdminUserEmail } from '../utils/uniqueAdminHash';
|
|
20
|
+
|
|
21
|
+
import RBACProvider from './RBACProvider';
|
|
22
|
+
|
|
23
|
+
const strapiVersion = packageJSON.version;
|
|
24
|
+
|
|
25
|
+
const checkLatestStrapiVersion = (currentPackageVersion, latestPublishedVersion) => {
|
|
26
|
+
if (!valid(currentPackageVersion) || !valid(latestPublishedVersion)) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return lt(currentPackageVersion, latestPublishedVersion);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const AuthenticatedApp = () => {
|
|
34
|
+
const { setGuidedTourVisibility } = useGuidedTour();
|
|
35
|
+
const toggleNotification = useNotification();
|
|
36
|
+
const userInfo = auth.getUserInfo();
|
|
37
|
+
const { get } = useFetchClient();
|
|
38
|
+
// TODO: replace with getDisplayName()
|
|
39
|
+
const [userDisplayName, setUserDisplayName] = React.useState(
|
|
40
|
+
userInfo?.userName ?? getFullName(userInfo.firstname, userInfo.lastname)
|
|
41
|
+
);
|
|
42
|
+
const [userId, setUserId] = React.useState(null);
|
|
43
|
+
const { showReleaseNotification } = useConfigurations();
|
|
44
|
+
const { plugins: appPlugins = {} } = useStrapiApp();
|
|
45
|
+
const [plugins, setPlugins] = React.useState(appPlugins);
|
|
46
|
+
const [
|
|
47
|
+
{ data: appInfos, isLoading: isLoadingAppInfos },
|
|
48
|
+
{ data: tagName },
|
|
49
|
+
{ data: permissions, isLoading: isLoadingPermissions, refetch },
|
|
50
|
+
{ data: userRoles },
|
|
51
|
+
] = useQueries([
|
|
52
|
+
{
|
|
53
|
+
queryKey: 'information',
|
|
54
|
+
async queryFn() {
|
|
55
|
+
const {
|
|
56
|
+
data: { data },
|
|
57
|
+
} = await get('/admin/information');
|
|
58
|
+
|
|
59
|
+
return data;
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
{
|
|
64
|
+
queryKey: 'strapi-release',
|
|
65
|
+
async queryFn() {
|
|
66
|
+
const res = await fetch('https://api.github.com/repos/strapi/strapi/releases/latest');
|
|
67
|
+
|
|
68
|
+
if (!res.ok) {
|
|
69
|
+
throw new Error('Failed to fetch latest Strapi version.');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const { tag_name } = await res.json();
|
|
73
|
+
|
|
74
|
+
return tag_name;
|
|
75
|
+
},
|
|
76
|
+
enabled: showReleaseNotification,
|
|
77
|
+
initialData: strapiVersion,
|
|
78
|
+
onSuccess(data) {
|
|
79
|
+
const shouldUpdateStrapi = checkLatestStrapiVersion(strapiVersion, data.tag_name);
|
|
80
|
+
|
|
81
|
+
if (shouldUpdateStrapi && !JSON.parse(localStorage.getItem('STRAPI_UPDATE_NOTIF'))) {
|
|
82
|
+
toggleNotification({
|
|
83
|
+
type: 'info',
|
|
84
|
+
message: { id: 'notification.version.update.message' },
|
|
85
|
+
link: {
|
|
86
|
+
url: `https://github.com/strapi/strapi/releases/tag/${data.tag_name}`,
|
|
87
|
+
label: {
|
|
88
|
+
id: 'global.see-more',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
blockTransition: true,
|
|
92
|
+
onClose: () => localStorage.setItem('STRAPI_UPDATE_NOTIF', true),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
retry: false,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
queryKey: ['users', 'me', 'permissions'],
|
|
100
|
+
async queryFn() {
|
|
101
|
+
const {
|
|
102
|
+
data: { data },
|
|
103
|
+
} = await get('/admin/users/me/permissions');
|
|
104
|
+
|
|
105
|
+
return data;
|
|
106
|
+
},
|
|
107
|
+
initialData: [],
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
{
|
|
111
|
+
queryKey: ['users', 'me'],
|
|
112
|
+
async queryFn() {
|
|
113
|
+
const {
|
|
114
|
+
data: {
|
|
115
|
+
data: { roles },
|
|
116
|
+
},
|
|
117
|
+
} = await get('/admin/users/me');
|
|
118
|
+
|
|
119
|
+
return roles;
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
]);
|
|
123
|
+
|
|
124
|
+
// Display the guided tour conditionally for super admins in development mode
|
|
125
|
+
React.useEffect(() => {
|
|
126
|
+
if (userRoles) {
|
|
127
|
+
const isUserSuperAdmin = userRoles.find(({ code }) => code === 'strapi-super-admin');
|
|
128
|
+
|
|
129
|
+
if (isUserSuperAdmin && appInfos?.currentEnvironment === 'development') {
|
|
130
|
+
setGuidedTourVisibility(true);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}, [userRoles, appInfos, setGuidedTourVisibility]);
|
|
134
|
+
|
|
135
|
+
// Create a hash of the users email adress and use it as ID for tracking
|
|
136
|
+
React.useEffect(() => {
|
|
137
|
+
const generateUserId = async (userInfo) => {
|
|
138
|
+
const userId = await hashAdminUserEmail(userInfo);
|
|
139
|
+
setUserId(userId);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
if (userInfo) {
|
|
143
|
+
generateUserId(userInfo);
|
|
144
|
+
}
|
|
145
|
+
}, [userInfo]);
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
*
|
|
149
|
+
* I have spent some time trying to understand what is happening here, and wanted to
|
|
150
|
+
* leave that knowledge for my future me:
|
|
151
|
+
*
|
|
152
|
+
* `initializer` is an undocumented property of the `registerPlugin` API. At the time
|
|
153
|
+
* of writing it seems only to be used by the i18n plugin.
|
|
154
|
+
*
|
|
155
|
+
* How does it work?
|
|
156
|
+
*
|
|
157
|
+
* Every plugin that has an `initializer` component defined, receives the
|
|
158
|
+
* `setPlugin` function as a component prop. In the case of i18n the plugin fetches locales
|
|
159
|
+
* first and calls `setPlugin` with `pluginId` once they are loaded, which then triggers the
|
|
160
|
+
* reducer of the admin app defined above.
|
|
161
|
+
*
|
|
162
|
+
* Once all plugins are set to `isReady: true` the app renders.
|
|
163
|
+
*
|
|
164
|
+
* This API is used to block rendering of the admin app. We should remove that in v5 completely
|
|
165
|
+
* and make sure plugins can inject data into the global store before they are initialized, to avoid
|
|
166
|
+
* having a new prop-callback based communication channel between plugins and the core admin app.
|
|
167
|
+
*
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
const hasApluginNotReady = Object.values(plugins).some((plugin) => plugin.isReady === false);
|
|
171
|
+
|
|
172
|
+
if (
|
|
173
|
+
!userDisplayName ||
|
|
174
|
+
!userId ||
|
|
175
|
+
isLoadingAppInfos ||
|
|
176
|
+
isLoadingPermissions ||
|
|
177
|
+
hasApluginNotReady
|
|
178
|
+
) {
|
|
179
|
+
const initializers = Object.keys(plugins).reduce((acc, current) => {
|
|
180
|
+
const InitializerComponent = plugins[current].initializer;
|
|
181
|
+
|
|
182
|
+
if (InitializerComponent) {
|
|
183
|
+
const key = plugins[current].pluginId;
|
|
184
|
+
|
|
185
|
+
acc.push(
|
|
186
|
+
<InitializerComponent
|
|
187
|
+
key={key}
|
|
188
|
+
setPlugin={(pluginId) => {
|
|
189
|
+
setPlugins((prev) => ({
|
|
190
|
+
...prev,
|
|
191
|
+
[pluginId]: {
|
|
192
|
+
...prev[pluginId],
|
|
193
|
+
isReady: true,
|
|
194
|
+
},
|
|
195
|
+
}));
|
|
196
|
+
}}
|
|
197
|
+
/>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return acc;
|
|
202
|
+
}, []);
|
|
203
|
+
|
|
204
|
+
return (
|
|
205
|
+
<>
|
|
206
|
+
{initializers}
|
|
207
|
+
<LoadingIndicatorPage />
|
|
208
|
+
</>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<AppInfoProvider
|
|
214
|
+
{...appInfos}
|
|
215
|
+
userId={userId}
|
|
216
|
+
latestStrapiReleaseTag={tagName}
|
|
217
|
+
// TODO: setUserDisplayName should not exist and be removed, as it is only used
|
|
218
|
+
// to update the displayName immediately, in case a user updates their profile.
|
|
219
|
+
// This information should be derived from the state.
|
|
220
|
+
setUserDisplayName={setUserDisplayName}
|
|
221
|
+
shouldUpdateStrapi={checkLatestStrapiVersion(strapiVersion, tagName)}
|
|
222
|
+
userDisplayName={userDisplayName}
|
|
223
|
+
>
|
|
224
|
+
<RBACProvider permissions={permissions} refetchPermissions={refetch}>
|
|
225
|
+
<Admin />
|
|
226
|
+
</RBACProvider>
|
|
227
|
+
</AppInfoProvider>
|
|
228
|
+
);
|
|
229
|
+
};
|
|
@@ -9,7 +9,7 @@ import Modal from './components/Modal';
|
|
|
9
9
|
import StepperModal from './components/Stepper';
|
|
10
10
|
import reducer, { initialState } from './reducer';
|
|
11
11
|
|
|
12
|
-
const GuidedTourModal = () => {
|
|
12
|
+
export const GuidedTourModal = () => {
|
|
13
13
|
const {
|
|
14
14
|
currentStep,
|
|
15
15
|
guidedTourState,
|
|
@@ -90,5 +90,3 @@ const GuidedTourModal = () => {
|
|
|
90
90
|
|
|
91
91
|
return null;
|
|
92
92
|
};
|
|
93
|
-
|
|
94
|
-
export default GuidedTourModal;
|
|
@@ -61,7 +61,7 @@ function renderDraglayerItem({ type, item }) {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
const
|
|
64
|
+
export const ContentManger = () => {
|
|
65
65
|
const contentTypeMatch = useRouteMatch(`/content-manager/:kind/:uid`);
|
|
66
66
|
const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } =
|
|
67
67
|
useContentManagerInitData();
|
|
@@ -123,6 +123,10 @@ const App = () => {
|
|
|
123
123
|
|
|
124
124
|
return (
|
|
125
125
|
<Layout sideNav={<LeftMenu />}>
|
|
126
|
+
<Helmet
|
|
127
|
+
title={formatMessage({ id: getTrad('plugin.name'), defaultMessage: 'Content Manager' })}
|
|
128
|
+
/>
|
|
129
|
+
|
|
126
130
|
<DragLayer renderItem={renderDraglayerItem} />
|
|
127
131
|
<ModelsContext.Provider value={{ refetchData }}>
|
|
128
132
|
<Switch>
|
|
@@ -149,18 +153,3 @@ const App = () => {
|
|
|
149
153
|
</Layout>
|
|
150
154
|
);
|
|
151
155
|
};
|
|
152
|
-
|
|
153
|
-
export { App };
|
|
154
|
-
|
|
155
|
-
export default function () {
|
|
156
|
-
const { formatMessage } = useIntl();
|
|
157
|
-
|
|
158
|
-
return (
|
|
159
|
-
<>
|
|
160
|
-
<Helmet
|
|
161
|
-
title={formatMessage({ id: getTrad('plugin.name'), defaultMessage: 'Content Manager' })}
|
|
162
|
-
/>
|
|
163
|
-
<App />
|
|
164
|
-
</>
|
|
165
|
-
);
|
|
166
|
-
}
|
|
@@ -5,7 +5,7 @@ import { useCMEditViewDataManager } from '@strapi/helper-plugin';
|
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import { useIntl } from 'react-intl';
|
|
7
7
|
|
|
8
|
-
import { getFullName } from '../../../../utils';
|
|
8
|
+
import { getFullName } from '../../../../utils/getFullName';
|
|
9
9
|
import { getTrad } from '../../../utils';
|
|
10
10
|
|
|
11
11
|
import getUnits from './utils/getUnits';
|
|
@@ -32,7 +32,7 @@ import { useSelector } from 'react-redux';
|
|
|
32
32
|
import { Link, useHistory } from 'react-router-dom';
|
|
33
33
|
import styled from 'styled-components';
|
|
34
34
|
|
|
35
|
-
import
|
|
35
|
+
import { formatAPIErrors } from '../../../../../../utils/formatAPIErrors';
|
|
36
36
|
import { getTrad, createYupSchema } from '../../../../../utils';
|
|
37
37
|
import { listViewDomain } from '../../../selectors';
|
|
38
38
|
import { Body } from '../../Body';
|
|
@@ -301,7 +301,7 @@ const SelectedEntriesModalContent = ({
|
|
|
301
301
|
onError(error) {
|
|
302
302
|
toggleNotification({
|
|
303
303
|
type: 'warning',
|
|
304
|
-
message:
|
|
304
|
+
message: formatAPIErrors(error),
|
|
305
305
|
});
|
|
306
306
|
},
|
|
307
307
|
}
|
|
@@ -23,7 +23,7 @@ import { useIntl } from 'react-intl';
|
|
|
23
23
|
import { Link, useHistory } from 'react-router-dom';
|
|
24
24
|
|
|
25
25
|
import { useEnterprise } from '../../../../../hooks/useEnterprise';
|
|
26
|
-
import { getFullName } from '../../../../../utils';
|
|
26
|
+
import { getFullName } from '../../../../../utils/getFullName';
|
|
27
27
|
import { usePluginsQueryParams } from '../../../../hooks';
|
|
28
28
|
import { getTrad } from '../../../../utils';
|
|
29
29
|
import CellContent from '../CellContent';
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { useEffect, useReducer } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getYupInnerErrors,
|
|
5
|
+
useFetchClient,
|
|
6
|
+
useNotification,
|
|
7
|
+
useOverlayBlocker,
|
|
8
|
+
} from '@strapi/helper-plugin';
|
|
4
9
|
import omit from 'lodash/omit';
|
|
5
10
|
|
|
6
|
-
import {
|
|
11
|
+
import { formatAPIErrors } from '../../utils/formatAPIErrors';
|
|
7
12
|
|
|
8
13
|
import init from './init';
|
|
9
14
|
import { initialState, reducer } from './reducer';
|
|
@@ -76,7 +81,13 @@ const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
|
|
|
76
81
|
const handleSubmit = async (e) => {
|
|
77
82
|
e.preventDefault();
|
|
78
83
|
|
|
79
|
-
|
|
84
|
+
let errors = null;
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
await schema.validate(modifiedData, { abortEarly: false });
|
|
88
|
+
} catch (err) {
|
|
89
|
+
errors = getYupInnerErrors(err);
|
|
90
|
+
}
|
|
80
91
|
|
|
81
92
|
dispatch({
|
|
82
93
|
type: 'SET_ERRORS',
|
|
@@ -7,8 +7,8 @@ import { selectAdminPermissions } from '../../pages/App/selectors';
|
|
|
7
7
|
import { useEnterprise } from '../useEnterprise';
|
|
8
8
|
|
|
9
9
|
import { LINKS_CE } from './constants';
|
|
10
|
-
import formatLinks from './utils/formatLinks';
|
|
11
|
-
import sortLinks from './utils/sortLinks';
|
|
10
|
+
import { formatLinks } from './utils/formatLinks';
|
|
11
|
+
import { sortLinks } from './utils/sortLinks';
|
|
12
12
|
|
|
13
13
|
const useSettingsMenu = () => {
|
|
14
14
|
const [{ isLoading, menu }, setData] = useState({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const formatLinks = (menu) => {
|
|
1
|
+
export const formatLinks = (menu) => {
|
|
2
2
|
return menu.map((menuSection) => {
|
|
3
3
|
const formattedLinks = menuSection.links.map((link) => ({
|
|
4
4
|
...link,
|
|
@@ -8,5 +8,3 @@ const formatLinks = (menu) => {
|
|
|
8
8
|
return { ...menuSection, links: formattedLinks };
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
export default formatLinks;
|
package/admin/src/index.js
CHANGED
|
@@ -52,7 +52,7 @@ const run = async () => {
|
|
|
52
52
|
|
|
53
53
|
// We need to make sure to fetch the project type before importing the StrapiApp
|
|
54
54
|
// otherwise the strapi-babel-plugin does not work correctly
|
|
55
|
-
const StrapiApp = await import(/* webpackChunkName: "
|
|
55
|
+
const StrapiApp = await import(/* webpackChunkName: "StrapiApp" */ './StrapiApp');
|
|
56
56
|
|
|
57
57
|
const app = StrapiApp.default({
|
|
58
58
|
appPlugins: plugins,
|
|
@@ -75,7 +75,7 @@ const TextLink = styled(TypographyLineHeight)`
|
|
|
75
75
|
}
|
|
76
76
|
`;
|
|
77
77
|
|
|
78
|
-
const Onboarding = () => {
|
|
78
|
+
export const Onboarding = () => {
|
|
79
79
|
const triggerRef = useRef();
|
|
80
80
|
const [isOpen, setIsOpen] = useState(false);
|
|
81
81
|
const { formatMessage } = useIntl();
|
|
@@ -222,5 +222,3 @@ const Onboarding = () => {
|
|
|
222
222
|
</Box>
|
|
223
223
|
);
|
|
224
224
|
};
|
|
225
|
-
|
|
226
|
-
export default Onboarding;
|
|
@@ -4,80 +4,92 @@
|
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import * as React from 'react';
|
|
8
8
|
|
|
9
|
+
import { Box, Flex } from '@strapi/design-system';
|
|
9
10
|
import { LoadingIndicatorPage, useStrapiApp, useTracking } from '@strapi/helper-plugin';
|
|
10
11
|
import { DndProvider } from 'react-dnd';
|
|
11
12
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
12
13
|
import { useDispatch, useSelector } from 'react-redux';
|
|
13
14
|
import { Route, Switch } from 'react-router-dom';
|
|
14
15
|
|
|
15
|
-
import GuidedTourModal from '../../components/GuidedTour/Modal';
|
|
16
16
|
import LeftMenu from '../../components/LeftMenu';
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import { createRoute } from '../../utils';
|
|
17
|
+
import useConfigurations from '../../hooks/useConfigurations';
|
|
18
|
+
import useMenu from '../../hooks/useMenu';
|
|
19
|
+
import { createRoute } from '../../utils/createRoute';
|
|
20
20
|
import { SET_APP_RUNTIME_STATUS } from '../App/constants';
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
const CM = React.lazy(() =>
|
|
23
|
+
import(/* webpackChunkName: "content-manager" */ '../../content-manager/pages/App').then(
|
|
24
|
+
(module) => ({ default: module.ContentManger })
|
|
25
|
+
)
|
|
26
26
|
);
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
const GuidedTourModal = React.lazy(() =>
|
|
28
|
+
import(/* webpackChunkName: "Admin_GuidedTourModal" */ '../../components/GuidedTour/Modal').then(
|
|
29
|
+
(module) => ({ default: module.GuidedTourModal })
|
|
30
|
+
)
|
|
30
31
|
);
|
|
31
|
-
const
|
|
32
|
-
import(/* webpackChunkName: "
|
|
32
|
+
const HomePage = React.lazy(() =>
|
|
33
|
+
import(/* webpackChunkName: "Admin_homePage" */ '../HomePage').then((module) => ({
|
|
34
|
+
default: module.HomePage,
|
|
35
|
+
}))
|
|
33
36
|
);
|
|
34
|
-
const
|
|
35
|
-
import(/* webpackChunkName: "
|
|
37
|
+
const InstalledPluginsPage = React.lazy(() =>
|
|
38
|
+
import(/* webpackChunkName: "Admin_pluginsPage" */ '../InstalledPluginsPage').then((module) => ({
|
|
39
|
+
default: module.PluginsPage,
|
|
40
|
+
}))
|
|
36
41
|
);
|
|
37
|
-
const
|
|
38
|
-
import(/* webpackChunkName: "
|
|
42
|
+
const MarketplacePage = React.lazy(() =>
|
|
43
|
+
import(/* webpackChunkName: "Admin_marketplace" */ '../MarketplacePage')
|
|
39
44
|
);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
const Onboarding = React.lazy(() =>
|
|
46
|
+
import(/* webpackChunkName: "Admin_Onboarding" */ './Onboarding').then((module) => ({
|
|
47
|
+
default: module.Onboarding,
|
|
48
|
+
}))
|
|
49
|
+
);
|
|
50
|
+
const ProfilePage = React.lazy(() =>
|
|
51
|
+
import(/* webpackChunkName: "Admin_profilePage" */ '../ProfilePage').then((module) => ({
|
|
52
|
+
default: module.ProfilePage,
|
|
53
|
+
}))
|
|
43
54
|
);
|
|
44
|
-
const SettingsPage = lazy(() =>
|
|
45
|
-
import(/* webpackChunkName: "Admin_settingsPage" */ '../SettingsPage')
|
|
55
|
+
const SettingsPage = React.lazy(() =>
|
|
56
|
+
import(/* webpackChunkName: "Admin_settingsPage" */ '../SettingsPage').then((module) => ({
|
|
57
|
+
default: module.SettingsPage,
|
|
58
|
+
}))
|
|
46
59
|
);
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const useTrackUsage = () => {
|
|
61
|
+
export const Admin = () => {
|
|
62
|
+
const { isLoading, generalSectionLinks, pluginsSectionLinks } = useMenu();
|
|
63
|
+
const { menu } = useStrapiApp();
|
|
64
|
+
const { showTutorials } = useConfigurations();
|
|
53
65
|
const { trackUsage } = useTracking();
|
|
54
66
|
const dispatch = useDispatch();
|
|
55
67
|
const appStatus = useSelector((state) => state.admin_app.status);
|
|
56
68
|
|
|
57
|
-
useEffect(() => {
|
|
69
|
+
React.useEffect(() => {
|
|
58
70
|
// Make sure the event is only send once after accessing the admin panel
|
|
59
71
|
// and not at runtime for example when regenerating the permissions with the ctb
|
|
60
72
|
// or with i18n
|
|
61
73
|
if (appStatus === 'init') {
|
|
62
74
|
trackUsage('didAccessAuthenticatedAdministration');
|
|
63
|
-
|
|
64
75
|
dispatch({ type: SET_APP_RUNTIME_STATUS });
|
|
65
76
|
}
|
|
66
|
-
|
|
67
|
-
}, [appStatus]);
|
|
68
|
-
};
|
|
77
|
+
}, [appStatus, dispatch, trackUsage]);
|
|
69
78
|
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
const { isLoading, generalSectionLinks, pluginsSectionLinks } = useMenu();
|
|
73
|
-
const { menu } = useStrapiApp();
|
|
74
|
-
const { showTutorials } = useConfigurations();
|
|
79
|
+
const routes = menu
|
|
80
|
+
.filter((link) => link.Component)
|
|
75
81
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
/**
|
|
83
|
+
* `Component` is an async function, which is passed as property of the
|
|
84
|
+
* addMenuLink() API during the plugin registration step.
|
|
85
|
+
*
|
|
86
|
+
* Because of that we can't just render <Route component={Component} />,
|
|
87
|
+
* but have to await the function.
|
|
88
|
+
*
|
|
89
|
+
* This isn't a good React pattern and should be reconsidered.
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
.map(({ to, Component, exact }) => createRoute(Component, to, exact));
|
|
81
93
|
|
|
82
94
|
if (isLoading) {
|
|
83
95
|
return <LoadingIndicatorPage />;
|
|
@@ -85,40 +97,34 @@ const Admin = () => {
|
|
|
85
97
|
|
|
86
98
|
return (
|
|
87
99
|
<DndProvider backend={HTML5Backend}>
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
<Route path="" component={NotFoundPage} />
|
|
113
|
-
</Switch>
|
|
114
|
-
</Suspense>
|
|
100
|
+
<Flex alignItems="stretch">
|
|
101
|
+
<LeftMenu
|
|
102
|
+
generalSectionLinks={generalSectionLinks}
|
|
103
|
+
pluginsSectionLinks={pluginsSectionLinks}
|
|
104
|
+
/>
|
|
105
|
+
|
|
106
|
+
<Box flex="1">
|
|
107
|
+
<React.Suspense fallback={<LoadingIndicatorPage />}>
|
|
108
|
+
<Switch>
|
|
109
|
+
<Route path="/" component={HomePage} exact />
|
|
110
|
+
<Route path="/me" component={ProfilePage} exact />
|
|
111
|
+
<Route path="/content-manager" component={CM} />
|
|
112
|
+
{routes}
|
|
113
|
+
<Route path="/settings/:settingId" component={SettingsPage} />
|
|
114
|
+
<Route path="/settings" component={SettingsPage} exact />
|
|
115
|
+
<Route path="/marketplace" component={MarketplacePage} />
|
|
116
|
+
<Route path="/list-plugins" component={InstalledPluginsPage} exact />
|
|
117
|
+
</Switch>
|
|
118
|
+
</React.Suspense>
|
|
119
|
+
</Box>
|
|
120
|
+
|
|
121
|
+
{/* TODO: we should move the logic to determine whether the guided tour is displayed
|
|
122
|
+
or not out of the component, to make the code-splitting more effective
|
|
123
|
+
*/}
|
|
115
124
|
<GuidedTourModal />
|
|
116
125
|
|
|
117
126
|
{showTutorials && <Onboarding />}
|
|
118
|
-
</
|
|
127
|
+
</Flex>
|
|
119
128
|
</DndProvider>
|
|
120
129
|
);
|
|
121
130
|
};
|
|
122
|
-
|
|
123
|
-
export default Admin;
|
|
124
|
-
export { useTrackUsage };
|