@strapi/admin 4.2.0-alpha.O → 4.2.0-beta.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.
- package/admin/src/app.js +7 -4
- package/admin/src/assets/images/icon_made-by-strapi.svg +5 -0
- package/admin/src/components/AuthenticatedApp/index.js +9 -2
- package/admin/src/components/AuthenticatedApp/utils/api.js +20 -1
- package/admin/src/components/GuidedTour/Homepage/index.js +13 -3
- package/admin/src/components/GuidedTour/Modal/index.js +4 -1
- package/admin/src/components/GuidedTour/layout.js +9 -0
- package/admin/src/components/PrivateRoute/index.js +23 -17
- package/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/index.js +4 -1
- package/admin/src/content-manager/components/Inputs/index.js +3 -4
- package/admin/src/content-manager/components/SelectWrapper/utils/getSelectStyles.js +2 -1
- package/admin/src/content-manager/pages/EditView/index.js +0 -188
- package/admin/src/hooks/index.js +0 -1
- package/admin/src/hooks/useFetchInstalledPlugins/index.js +23 -0
- package/admin/src/{pages/InstalledPluginsPage → hooks/useFetchInstalledPlugins}/utils/api.js +2 -4
- package/admin/src/hooks/useFetchMarketplacePlugins/index.js +23 -0
- package/admin/src/hooks/useFetchMarketplacePlugins/utils/api.js +17 -0
- package/admin/src/pages/Admin/index.js +1 -3
- package/admin/src/pages/AuthPage/index.js +28 -5
- package/admin/src/pages/InstalledPluginsPage/Plugins.js +6 -15
- package/admin/src/pages/MarketplacePage/components/EmptyPluginSearch/EmptyPluginGrid.js +27 -0
- package/admin/src/pages/MarketplacePage/components/EmptyPluginSearch/index.js +30 -0
- package/admin/src/pages/MarketplacePage/components/PluginCard/index.js +186 -0
- package/admin/src/pages/MarketplacePage/index.js +199 -107
- package/admin/src/pages/MarketplacePage/utils/api.js +9 -0
- package/admin/src/translations/en.json +18 -15
- package/admin/src/translations/ja.json +2 -2
- package/admin/src/translations/ko.json +2 -2
- package/admin/src/translations/vi.json +30 -4
- package/build/4362.b3d67035.chunk.js +1 -0
- package/build/90f49a385afb000fb1d4.svg +5 -0
- package/build/9260.4233fae2.chunk.js +2 -0
- package/build/{9260.fa40c7bd.chunk.js.LICENSE.txt → 9260.4233fae2.chunk.js.LICENSE.txt} +0 -0
- package/build/Admin-authenticatedApp.16bed71f.chunk.js +1 -0
- package/build/Admin_homePage.fd1fc572.chunk.js +1 -0
- package/build/Admin_marketplace.89a0a014.chunk.js +1 -0
- package/build/Admin_pluginsPage.97a514db.chunk.js +1 -0
- package/build/admin-users.2740c223.chunk.js +1 -0
- package/build/content-manager.f1c46a88.chunk.js +1 -0
- package/build/en-json.73a610d6.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/ja-json.e13f04e8.chunk.js +1 -0
- package/build/ko-json.2200c9c9.chunk.js +1 -0
- package/build/main.12d62562.js +2 -0
- package/build/{main.3e719c82.js.LICENSE.txt → main.12d62562.js.LICENSE.txt} +0 -0
- package/build/{runtime~main.66becdbd.js → runtime~main.21bf3a67.js} +1 -1
- package/build/{upload-translation-en-json.c3373c8d.chunk.js → upload-translation-en-json.c334dd82.chunk.js} +1 -1
- package/build/vi-json.1e850069.chunk.js +1 -0
- package/index.js +53 -244
- package/package.json +9 -7
- package/server/controllers/admin.js +12 -1
- package/server/routes/serve-admin-panel.js +1 -1
- package/utils/create-cache-dir.js +119 -0
- package/utils/get-custom-webpack-config.js +38 -0
- package/utils/index.js +13 -0
- package/utils/should-build-admin.js +51 -0
- package/utils/watch-admin-files.js +56 -0
- package/webpack.config.js +36 -3
- package/.env +0 -0
- package/admin/src/hooks/useFetchPluginsFromMarketPlace/index.js +0 -49
- package/admin/src/pages/MarketplacePage/MarketplaceBanner/Wrapper.js +0 -28
- package/admin/src/pages/MarketplacePage/MarketplaceBanner/index.js +0 -37
- package/admin/src/pages/MarketplacePage/PluginCard/Wrapper.js +0 -148
- package/admin/src/pages/MarketplacePage/PluginCard/index.js +0 -185
- package/admin/src/pages/MarketplacePage/Wrapper.js +0 -5
- package/admin/src/pages/MarketplacePage/assets/marketplace-coming-soon.png +0 -0
- package/build/01a600d9e6e0dea21e33.png +0 -0
- package/build/4362.86a4e939.chunk.js +0 -1
- package/build/9260.fa40c7bd.chunk.js +0 -2
- package/build/Admin-authenticatedApp.a5d2c5fa.chunk.js +0 -1
- package/build/Admin_homePage.d6754c66.chunk.js +0 -1
- package/build/Admin_marketplace.419010d8.chunk.js +0 -1
- package/build/Admin_pluginsPage.7d1bd7ce.chunk.js +0 -1
- package/build/admin-users.1fda1f27.chunk.js +0 -1
- package/build/content-manager.8412e024.chunk.js +0 -1
- package/build/en-json.b35c285f.chunk.js +0 -1
- package/build/ja-json.46e29f04.chunk.js +0 -1
- package/build/ko-json.dd36fdc0.chunk.js +0 -1
- package/build/main.3e719c82.js +0 -2
- package/build/vi-json.55a11ac0.chunk.js +0 -1
package/admin/src/app.js
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect x="3" y="3" width="18" height="18" rx="4" fill="#4945FF"/>
|
|
3
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.8075 7.625H9.03058V11.1792H12.2533C12.4977 11.1792 12.6958 11.3773 12.6958 11.6216V14.8444H16.25V8.06746C16.25 7.82309 16.0519 7.625 15.8075 7.625Z" fill="white"/>
|
|
4
|
+
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M9.0308 7.625V11.1792H6.01073C5.81364 11.1792 5.71494 10.9409 5.8543 10.8015L9.0308 7.625ZM13.0735 18.0209C12.9342 18.1603 12.6959 18.0616 12.6959 17.8645V14.8444H16.25L13.0735 18.0209ZM12.4746 11.1792H9.03058V14.4019C9.03058 14.6463 9.22868 14.8444 9.47304 14.8444H12.6958V11.4004C12.6958 11.2782 12.5968 11.1792 12.4746 11.1792Z" fill="#DAD9FF"/>
|
|
5
|
+
</svg>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import React, { useMemo, useState, useEffect, useRef } from 'react';
|
|
2
2
|
// TODO: DS add loader
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
auth,
|
|
5
|
+
LoadingIndicatorPage,
|
|
6
|
+
AppInfosContext,
|
|
7
|
+
useGuidedTour,
|
|
8
|
+
useNotification,
|
|
9
|
+
} from '@strapi/helper-plugin';
|
|
4
10
|
import { useQueries } from 'react-query';
|
|
5
11
|
import get from 'lodash/get';
|
|
6
12
|
import packageJSON from '../../../../package.json';
|
|
@@ -20,6 +26,7 @@ const strapiVersion = packageJSON.version;
|
|
|
20
26
|
|
|
21
27
|
const AuthenticatedApp = () => {
|
|
22
28
|
const { setGuidedTourVisibility } = useGuidedTour();
|
|
29
|
+
const toggleNotification = useNotification();
|
|
23
30
|
const setGuidedTourVisibilityRef = useRef(setGuidedTourVisibility);
|
|
24
31
|
const userInfo = auth.getUserInfo();
|
|
25
32
|
const userName = get(userInfo, 'username') || getFullName(userInfo.firstname, userInfo.lastname);
|
|
@@ -34,7 +41,7 @@ const AuthenticatedApp = () => {
|
|
|
34
41
|
{ queryKey: 'app-infos', queryFn: fetchAppInfo },
|
|
35
42
|
{
|
|
36
43
|
queryKey: 'strapi-release',
|
|
37
|
-
queryFn: fetchStrapiLatestRelease,
|
|
44
|
+
queryFn: () => fetchStrapiLatestRelease(toggleNotification),
|
|
38
45
|
enabled: showReleaseNotification,
|
|
39
46
|
initialData: strapiVersion,
|
|
40
47
|
},
|
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
+
import checkLatestStrapiVersion from './checkLatestStrapiVersion';
|
|
2
3
|
import { axiosInstance } from '../../../core/utils';
|
|
3
4
|
import packageJSON from '../../../../../package.json';
|
|
4
5
|
|
|
5
6
|
const strapiVersion = packageJSON.version;
|
|
7
|
+
const showUpdateNotif = !JSON.parse(localStorage.getItem('STRAPI_UPDATE_NOTIF'));
|
|
6
8
|
|
|
7
|
-
const fetchStrapiLatestRelease = async
|
|
9
|
+
const fetchStrapiLatestRelease = async toggleNotification => {
|
|
8
10
|
try {
|
|
9
11
|
const {
|
|
10
12
|
data: { tag_name },
|
|
11
13
|
} = await axios.get('https://api.github.com/repos/strapi/strapi/releases/latest');
|
|
12
14
|
|
|
15
|
+
const shouldUpdateStrapi = checkLatestStrapiVersion(strapiVersion, tag_name);
|
|
16
|
+
|
|
17
|
+
if (shouldUpdateStrapi && showUpdateNotif) {
|
|
18
|
+
toggleNotification({
|
|
19
|
+
type: 'info',
|
|
20
|
+
message: { id: 'notification.version.update.message' },
|
|
21
|
+
link: {
|
|
22
|
+
url: `https://github.com/strapi/strapi/releases/tag/${tag_name}`,
|
|
23
|
+
label: {
|
|
24
|
+
id: 'notification.version.update.link',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
blockTransition: true,
|
|
28
|
+
onClose: () => localStorage.setItem('STRAPI_UPDATE_NOTIF', true),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
13
32
|
return tag_name;
|
|
14
33
|
} catch (err) {
|
|
15
34
|
// Don't throw an error
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { useGuidedTour } from '@strapi/helper-plugin';
|
|
2
|
+
import { useGuidedTour, useTracking } from '@strapi/helper-plugin';
|
|
3
3
|
import { useIntl } from 'react-intl';
|
|
4
4
|
import { Stack } from '@strapi/design-system/Stack';
|
|
5
5
|
import { Flex } from '@strapi/design-system/Flex';
|
|
@@ -14,12 +14,17 @@ import layout from '../layout';
|
|
|
14
14
|
const GuidedTourHomepage = () => {
|
|
15
15
|
const { guidedTourState, setSkipped } = useGuidedTour();
|
|
16
16
|
const { formatMessage } = useIntl();
|
|
17
|
+
const { trackUsage } = useTracking();
|
|
17
18
|
|
|
18
19
|
const sections = Object.entries(layout).map(([key, val]) => ({
|
|
19
20
|
key,
|
|
20
21
|
title: val.home.title,
|
|
21
22
|
content: (
|
|
22
|
-
<LinkButton
|
|
23
|
+
<LinkButton
|
|
24
|
+
onClick={() => trackUsage(val.home.trackingEvent)}
|
|
25
|
+
to={val.home.cta.target}
|
|
26
|
+
endIcon={<ArrowRight />}
|
|
27
|
+
>
|
|
23
28
|
{formatMessage(val.home.cta.title)}
|
|
24
29
|
</LinkButton>
|
|
25
30
|
),
|
|
@@ -32,6 +37,11 @@ const GuidedTourHomepage = () => {
|
|
|
32
37
|
|
|
33
38
|
const activeSection = enrichedSections.find(section => !section.isDone)?.key;
|
|
34
39
|
|
|
40
|
+
const handleSkip = () => {
|
|
41
|
+
setSkipped(true);
|
|
42
|
+
trackUsage('didSkipGuidedtour');
|
|
43
|
+
};
|
|
44
|
+
|
|
35
45
|
return (
|
|
36
46
|
<Box
|
|
37
47
|
hasRadius
|
|
@@ -52,7 +62,7 @@ const GuidedTourHomepage = () => {
|
|
|
52
62
|
<StepperHomepage sections={sections} currentSectionKey={activeSection} />
|
|
53
63
|
</Stack>
|
|
54
64
|
<Flex justifyContent="flex-end">
|
|
55
|
-
<Button variant="tertiary" onClick={
|
|
65
|
+
<Button variant="tertiary" onClick={handleSkip}>
|
|
56
66
|
{formatMessage({ id: 'app.components.GuidedTour.skip', defaultMessage: 'Skip the tour' })}
|
|
57
67
|
</Button>
|
|
58
68
|
</Flex>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useState, useReducer } from 'react';
|
|
2
2
|
import at from 'lodash/at';
|
|
3
|
-
import { useGuidedTour } from '@strapi/helper-plugin';
|
|
3
|
+
import { useGuidedTour, useTracking } from '@strapi/helper-plugin';
|
|
4
4
|
import layout from '../layout';
|
|
5
5
|
import Modal from './components/Modal';
|
|
6
6
|
import reducer, { initialState } from './reducer';
|
|
@@ -20,6 +20,7 @@ const GuidedTourModal = () => {
|
|
|
20
20
|
{ stepContent, sectionIndex, stepIndex, hasSectionAfter, hasStepAfter },
|
|
21
21
|
dispatch,
|
|
22
22
|
] = useReducer(reducer, initialState);
|
|
23
|
+
const { trackUsage } = useTracking();
|
|
23
24
|
|
|
24
25
|
useEffect(() => {
|
|
25
26
|
if (!currentStep) {
|
|
@@ -56,6 +57,7 @@ const GuidedTourModal = () => {
|
|
|
56
57
|
|
|
57
58
|
const handleCtaClick = () => {
|
|
58
59
|
setStepState(currentStep, true);
|
|
60
|
+
trackUsage(stepContent.trackingEvent);
|
|
59
61
|
|
|
60
62
|
setCurrentStep(null);
|
|
61
63
|
};
|
|
@@ -63,6 +65,7 @@ const GuidedTourModal = () => {
|
|
|
63
65
|
const handleSkip = () => {
|
|
64
66
|
setSkipped(true);
|
|
65
67
|
setCurrentStep(null);
|
|
68
|
+
trackUsage('didSkipGuidedtour');
|
|
66
69
|
};
|
|
67
70
|
|
|
68
71
|
if (isVisible && stepContent) {
|
|
@@ -13,6 +13,7 @@ const layout = {
|
|
|
13
13
|
type: 'REDIRECT',
|
|
14
14
|
target: '/plugins/content-type-builder',
|
|
15
15
|
},
|
|
16
|
+
trackingEvent: 'didClickGuidedTourHomepageContentTypeBuilder',
|
|
16
17
|
},
|
|
17
18
|
create: {
|
|
18
19
|
title: {
|
|
@@ -31,6 +32,7 @@ const layout = {
|
|
|
31
32
|
},
|
|
32
33
|
type: 'CLOSE',
|
|
33
34
|
},
|
|
35
|
+
trackingEvent: 'didClickGuidedTourStep1CollectionType',
|
|
34
36
|
},
|
|
35
37
|
success: {
|
|
36
38
|
title: {
|
|
@@ -49,6 +51,7 @@ const layout = {
|
|
|
49
51
|
type: 'REDIRECT',
|
|
50
52
|
target: '/content-manager',
|
|
51
53
|
},
|
|
54
|
+
trackingEvent: 'didCreateGuidedTourCollectionType',
|
|
52
55
|
},
|
|
53
56
|
},
|
|
54
57
|
contentManager: {
|
|
@@ -65,6 +68,7 @@ const layout = {
|
|
|
65
68
|
type: 'REDIRECT',
|
|
66
69
|
target: '/content-manager',
|
|
67
70
|
},
|
|
71
|
+
trackingEvent: 'didClickGuidedTourHomepageContentManager',
|
|
68
72
|
},
|
|
69
73
|
create: {
|
|
70
74
|
title: {
|
|
@@ -83,6 +87,7 @@ const layout = {
|
|
|
83
87
|
},
|
|
84
88
|
type: 'CLOSE',
|
|
85
89
|
},
|
|
90
|
+
trackingEvent: 'didClickGuidedTourStep2ContentManager',
|
|
86
91
|
},
|
|
87
92
|
success: {
|
|
88
93
|
title: {
|
|
@@ -101,6 +106,7 @@ const layout = {
|
|
|
101
106
|
type: 'REDIRECT',
|
|
102
107
|
target: '/settings/api-tokens',
|
|
103
108
|
},
|
|
109
|
+
trackingEvent: 'didCreateGuidedTourEntry',
|
|
104
110
|
},
|
|
105
111
|
},
|
|
106
112
|
apiTokens: {
|
|
@@ -117,6 +123,7 @@ const layout = {
|
|
|
117
123
|
type: 'REDIRECT',
|
|
118
124
|
target: '/settings/api-tokens',
|
|
119
125
|
},
|
|
126
|
+
trackingEvent: 'didClickGuidedTourHomepageApiTokens',
|
|
120
127
|
},
|
|
121
128
|
create: {
|
|
122
129
|
title: {
|
|
@@ -135,6 +142,7 @@ const layout = {
|
|
|
135
142
|
},
|
|
136
143
|
type: 'CLOSE',
|
|
137
144
|
},
|
|
145
|
+
trackingEvent: 'didClickGuidedTourStep3ApiTokens',
|
|
138
146
|
},
|
|
139
147
|
success: {
|
|
140
148
|
title: {
|
|
@@ -146,6 +154,7 @@ const layout = {
|
|
|
146
154
|
defaultMessage:
|
|
147
155
|
"<p>See content in action by making an HTTP request:</p><ul><li><p>To this URL: <light>https://'<'YOUR_DOMAIN'>'/api/'<'YOUR_CT'>'</light></p></li><li><p>With the header: <light>Authorization: bearer '<'YOUR_API_TOKEN'>'</light></p></li></ul><p>For more ways to interact with content, see the <documentationLink>documentation</documentationLink>.</p>",
|
|
148
156
|
},
|
|
157
|
+
trackingEvent: 'didGenerateGuidedTourApiTokens',
|
|
149
158
|
},
|
|
150
159
|
},
|
|
151
160
|
};
|
|
@@ -8,28 +8,34 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import React, { memo } from 'react';
|
|
11
|
-
import { Redirect, Route } from 'react-router-dom';
|
|
11
|
+
import { Redirect, Route, useLocation } from 'react-router-dom';
|
|
12
12
|
import PropTypes from 'prop-types';
|
|
13
13
|
import { auth } from '@strapi/helper-plugin';
|
|
14
14
|
|
|
15
15
|
/* eslint-disable react/jsx-curly-newline */
|
|
16
16
|
|
|
17
|
-
const PrivateRoute = ({ component: Component, path, ...rest }) =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
const PrivateRoute = ({ component: Component, path, ...rest }) => {
|
|
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 !== '/' && `?redirectTo=${encodeURIComponent(`${pathname}${search}`)}`,
|
|
32
|
+
}}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
33
39
|
|
|
34
40
|
PrivateRoute.propTypes = {
|
|
35
41
|
component: PropTypes.any.isRequired,
|
|
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import { Accordion, AccordionToggle, AccordionContent } from '@strapi/design-system/Accordion';
|
|
4
4
|
import { Box } from '@strapi/design-system/Box';
|
|
5
5
|
import styled from 'styled-components';
|
|
6
|
+
import { useIntl } from 'react-intl';
|
|
6
7
|
import ComponentCard from './ComponentCard';
|
|
7
8
|
|
|
8
9
|
const Grid = styled.div`
|
|
@@ -12,6 +13,8 @@ const Grid = styled.div`
|
|
|
12
13
|
`;
|
|
13
14
|
|
|
14
15
|
const Category = ({ category, components, isOdd, isOpen, onAddComponent, onToggle }) => {
|
|
16
|
+
const { formatMessage } = useIntl();
|
|
17
|
+
|
|
15
18
|
const handleToggle = () => {
|
|
16
19
|
onToggle(category);
|
|
17
20
|
};
|
|
@@ -20,7 +23,7 @@ const Category = ({ category, components, isOdd, isOpen, onAddComponent, onToggl
|
|
|
20
23
|
<Accordion expanded={isOpen} onToggle={handleToggle} size="S">
|
|
21
24
|
<AccordionToggle
|
|
22
25
|
variant={isOdd ? 'primary' : 'secondary'}
|
|
23
|
-
title={category}
|
|
26
|
+
title={formatMessage({ id: category, defaultMessage: category })}
|
|
24
27
|
togglePosition="left"
|
|
25
28
|
/>
|
|
26
29
|
<AccordionContent>
|
|
@@ -224,6 +224,8 @@ function Inputs({
|
|
|
224
224
|
attribute={fieldSchema}
|
|
225
225
|
autoComplete="new-password"
|
|
226
226
|
intlLabel={{ id: label, defaultMessage: label }}
|
|
227
|
+
// in case the default value of the boolean is null, attribute.default doesn't exist
|
|
228
|
+
isNullable={inputType === 'bool' && [null, undefined].includes(fieldSchema.default)}
|
|
227
229
|
description={description ? { id: description, defaultMessage: description } : null}
|
|
228
230
|
disabled={shouldDisableField}
|
|
229
231
|
error={errorId}
|
|
@@ -279,7 +281,4 @@ Inputs.propTypes = {
|
|
|
279
281
|
|
|
280
282
|
const Memoized = memo(Inputs, isEqual);
|
|
281
283
|
|
|
282
|
-
export default connect(
|
|
283
|
-
Memoized,
|
|
284
|
-
select
|
|
285
|
-
);
|
|
284
|
+
export default connect(Memoized, select);
|
|
@@ -50,6 +50,7 @@ const getSelectStyles = theme => {
|
|
|
50
50
|
width: '100%',
|
|
51
51
|
marginTop: theme.spaces[1],
|
|
52
52
|
backgroundColor: theme.colors.neutral0,
|
|
53
|
+
color: theme.colors.neutral800,
|
|
53
54
|
borderRadius: '4px !important',
|
|
54
55
|
borderTopLeftRadius: '4px !important',
|
|
55
56
|
borderTopRightRadius: '4px !important',
|
|
@@ -77,7 +78,7 @@ const getSelectStyles = theme => {
|
|
|
77
78
|
return { ...base, lineHeight: theme.spaces[5], backgroundColor, borderRadius: 4 };
|
|
78
79
|
},
|
|
79
80
|
placeholder: base => ({ ...base, marginLeft: 0 }),
|
|
80
|
-
singleValue: base => ({ ...base, marginLeft: 0 }),
|
|
81
|
+
singleValue: base => ({ ...base, marginLeft: 0, color: theme.colors.neutral800 }),
|
|
81
82
|
valueContainer: base => ({
|
|
82
83
|
...base,
|
|
83
84
|
padding: 0,
|
|
@@ -364,194 +364,6 @@ const EditView = ({
|
|
|
364
364
|
}}
|
|
365
365
|
</DataManagementWrapper>
|
|
366
366
|
);
|
|
367
|
-
|
|
368
|
-
// return (
|
|
369
|
-
// <DataManagementWrapper allLayoutData={layout} slug={slug} id={id} origin={origin}>
|
|
370
|
-
// {({
|
|
371
|
-
// componentsDataStructure,
|
|
372
|
-
// contentTypeDataStructure,
|
|
373
|
-
// data,
|
|
374
|
-
// isCreatingEntry,
|
|
375
|
-
// isLoadingForData,
|
|
376
|
-
// onDelete,
|
|
377
|
-
// onDeleteSucceeded,
|
|
378
|
-
// onPost,
|
|
379
|
-
// onPublish,
|
|
380
|
-
// onPut,
|
|
381
|
-
// onUnpublish,
|
|
382
|
-
// redirectionLink,
|
|
383
|
-
// status,
|
|
384
|
-
// }) => {
|
|
385
|
-
// return (
|
|
386
|
-
// <EditViewDataManagerProvider
|
|
387
|
-
// allowedActions={allowedActions}
|
|
388
|
-
// allLayoutData={layout}
|
|
389
|
-
// createActionAllowedFields={createActionAllowedFields}
|
|
390
|
-
// componentsDataStructure={componentsDataStructure}
|
|
391
|
-
// contentTypeDataStructure={contentTypeDataStructure}
|
|
392
|
-
// from={redirectionLink}
|
|
393
|
-
// initialValues={data}
|
|
394
|
-
// isCreatingEntry={isCreatingEntry}
|
|
395
|
-
// isLoadingForData={isLoadingForData}
|
|
396
|
-
// isSingleType={isSingleType}
|
|
397
|
-
// onPost={onPost}
|
|
398
|
-
// onPublish={onPublish}
|
|
399
|
-
// onPut={onPut}
|
|
400
|
-
// onUnpublish={onUnpublish}
|
|
401
|
-
// readActionAllowedFields={readActionAllowedFields}
|
|
402
|
-
// redirectToPreviousPage={goBack}
|
|
403
|
-
// slug={slug}
|
|
404
|
-
// status={status}
|
|
405
|
-
// updateActionAllowedFields={updateActionAllowedFields}
|
|
406
|
-
// >
|
|
407
|
-
// <Container className="container-fluid">
|
|
408
|
-
// <Header allowedActions={allowedActions} />
|
|
409
|
-
// <div className="row" style={{ paddingTop: 3 }}>
|
|
410
|
-
// <div className="col-md-12 col-lg-9" style={{ marginBottom: 13 }}>
|
|
411
|
-
// {formattedContentTypeLayout.map((block, blockIndex) => {
|
|
412
|
-
// if (isDynamicZone(block)) {
|
|
413
|
-
// const {
|
|
414
|
-
// 0: {
|
|
415
|
-
// 0: { name, fieldSchema, metadatas, labelIcon },
|
|
416
|
-
// },
|
|
417
|
-
// } = block;
|
|
418
|
-
// const baselineAlignementSize = blockIndex === 0 ? '3px' : '0';
|
|
419
|
-
|
|
420
|
-
// return (
|
|
421
|
-
// <BaselineAlignment key={blockIndex} top size={baselineAlignementSize}>
|
|
422
|
-
// <DynamicZone
|
|
423
|
-
// name={name}
|
|
424
|
-
// fieldSchema={fieldSchema}
|
|
425
|
-
// labelIcon={labelIcon}
|
|
426
|
-
// metadatas={metadatas}
|
|
427
|
-
// />
|
|
428
|
-
// </BaselineAlignment>
|
|
429
|
-
// );
|
|
430
|
-
// }
|
|
431
|
-
|
|
432
|
-
// return (
|
|
433
|
-
// <FormWrapper key={blockIndex}>
|
|
434
|
-
// {block.map((fieldsBlock, fieldsBlockIndex) => {
|
|
435
|
-
// return (
|
|
436
|
-
// <div className="row" key={fieldsBlockIndex}>
|
|
437
|
-
// {fieldsBlock.map(
|
|
438
|
-
// ({ name, size, fieldSchema, labelIcon, metadatas }, fieldIndex) => {
|
|
439
|
-
// const isComponent = fieldSchema.type === 'component';
|
|
440
|
-
|
|
441
|
-
// if (isComponent) {
|
|
442
|
-
// const { component, max, min, repeatable = false } = fieldSchema;
|
|
443
|
-
// const componentUid = fieldSchema.component;
|
|
444
|
-
|
|
445
|
-
// return (
|
|
446
|
-
// <FieldComponent
|
|
447
|
-
// key={componentUid}
|
|
448
|
-
// componentUid={component}
|
|
449
|
-
// labelIcon={labelIcon}
|
|
450
|
-
// isRepeatable={repeatable}
|
|
451
|
-
// label={metadatas.label}
|
|
452
|
-
// max={max}
|
|
453
|
-
// min={min}
|
|
454
|
-
// name={name}
|
|
455
|
-
// />
|
|
456
|
-
// );
|
|
457
|
-
// }
|
|
458
|
-
|
|
459
|
-
// return (
|
|
460
|
-
// <div className={`col-${size}`} key={name}>
|
|
461
|
-
// <Inputs
|
|
462
|
-
// autoFocus={
|
|
463
|
-
// blockIndex === 0 &&
|
|
464
|
-
// fieldsBlockIndex === 0 &&
|
|
465
|
-
// fieldIndex === 0
|
|
466
|
-
// }
|
|
467
|
-
// fieldSchema={fieldSchema}
|
|
468
|
-
// keys={name}
|
|
469
|
-
// labelIcon={labelIcon}
|
|
470
|
-
// metadatas={metadatas}
|
|
471
|
-
// />
|
|
472
|
-
// </div>
|
|
473
|
-
// );
|
|
474
|
-
// }
|
|
475
|
-
// )}
|
|
476
|
-
// </div>
|
|
477
|
-
// );
|
|
478
|
-
// })}
|
|
479
|
-
// </FormWrapper>
|
|
480
|
-
// );
|
|
481
|
-
// })}
|
|
482
|
-
// </div>
|
|
483
|
-
// <div className="col-md-12 col-lg-3">
|
|
484
|
-
// <InformationCard />
|
|
485
|
-
// <Padded size="smd" top />
|
|
486
|
-
// {currentContentTypeLayoutData.layouts.editRelations.length > 0 && (
|
|
487
|
-
// <SubWrapper style={{ padding: '0 20px 1px', marginBottom: '25px' }}>
|
|
488
|
-
// <div style={{ paddingTop: '22px' }}>
|
|
489
|
-
// {currentContentTypeLayoutData.layouts.editRelations.map(
|
|
490
|
-
// ({ name, fieldSchema, labelIcon, metadatas, queryInfos }) => {
|
|
491
|
-
// return (
|
|
492
|
-
// <SelectWrapper
|
|
493
|
-
// {...fieldSchema}
|
|
494
|
-
// {...metadatas}
|
|
495
|
-
// key={name}
|
|
496
|
-
// labelIcon={labelIcon}
|
|
497
|
-
// name={name}
|
|
498
|
-
// relationsType={fieldSchema.relationType}
|
|
499
|
-
// queryInfos={queryInfos}
|
|
500
|
-
// />
|
|
501
|
-
// );
|
|
502
|
-
// }
|
|
503
|
-
// )}
|
|
504
|
-
// </div>
|
|
505
|
-
// </SubWrapper>
|
|
506
|
-
// )}
|
|
507
|
-
// <LinkWrapper>
|
|
508
|
-
// <ul>
|
|
509
|
-
// <CheckPermissions permissions={configurationPermissions}>
|
|
510
|
-
// <LiLink
|
|
511
|
-
// message={{
|
|
512
|
-
// id: 'app.links.configure-view',
|
|
513
|
-
// }}
|
|
514
|
-
// icon="layout"
|
|
515
|
-
// url={configurationsURL}
|
|
516
|
-
// onClick={() => {
|
|
517
|
-
// // trackUsage('willEditContentTypeLayoutFromEditView');
|
|
518
|
-
// }}
|
|
519
|
-
// />
|
|
520
|
-
// </CheckPermissions>
|
|
521
|
-
// {slug !== 'strapi::administrator' && (
|
|
522
|
-
// <CheckPermissions permissions={ctbPermissions}>
|
|
523
|
-
// <LiLink
|
|
524
|
-
// message={{
|
|
525
|
-
// id: getTrad('containers.Edit.Link.Fields'),
|
|
526
|
-
// }}
|
|
527
|
-
// onClick={() => {
|
|
528
|
-
// trackUsage('willEditEditLayout');
|
|
529
|
-
// }}
|
|
530
|
-
// icon="fa-cog"
|
|
531
|
-
// url={`/plugins/content-type-builder/content-types/${slug}`}
|
|
532
|
-
// />
|
|
533
|
-
// </CheckPermissions>
|
|
534
|
-
// )}
|
|
535
|
-
// {/* TODO add DOCUMENTATION */}
|
|
536
|
-
// <InjectionZone area="contentManager.editView.right-links" slug={slug} />
|
|
537
|
-
|
|
538
|
-
// {allowedActions.canDelete && (
|
|
539
|
-
// <DeleteLink
|
|
540
|
-
// isCreatingEntry={isCreatingEntry}
|
|
541
|
-
// onDelete={onDelete}
|
|
542
|
-
// onDeleteSucceeded={onDeleteSucceeded}
|
|
543
|
-
// />
|
|
544
|
-
// )}
|
|
545
|
-
// </ul>
|
|
546
|
-
// </LinkWrapper>
|
|
547
|
-
// </div>
|
|
548
|
-
// </div>
|
|
549
|
-
// </Container>
|
|
550
|
-
// </EditViewDataManagerProvider>
|
|
551
|
-
// );
|
|
552
|
-
// }}
|
|
553
|
-
// </DataManagementWrapper>
|
|
554
|
-
// );
|
|
555
367
|
};
|
|
556
368
|
|
|
557
369
|
EditView.defaultProps = {
|
package/admin/src/hooks/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { default as useConfigurations } from './useConfigurations';
|
|
2
2
|
export { default as useModels } from './useModels';
|
|
3
3
|
export { default as useFetchPermissionsLayout } from './useFetchPermissionsLayout';
|
|
4
|
-
export { default as useFetchPluginsFromMarketPlace } from './useFetchPluginsFromMarketPlace';
|
|
5
4
|
export { default as useFetchRole } from './useFetchRole';
|
|
6
5
|
export { default as useMenu } from './useMenu';
|
|
7
6
|
export { default as useRolesList } from './useRolesList';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useQuery } from 'react-query';
|
|
2
|
+
import { useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
import { fetchInstalledPlugins } from './utils/api';
|
|
4
|
+
|
|
5
|
+
const useFetchInstalledPlugins = notifyLoad => {
|
|
6
|
+
const toggleNotification = useNotification();
|
|
7
|
+
|
|
8
|
+
return useQuery('list-installed-plugins', () => fetchInstalledPlugins(), {
|
|
9
|
+
onSuccess: () => {
|
|
10
|
+
if (notifyLoad) {
|
|
11
|
+
notifyLoad();
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
onError: () => {
|
|
15
|
+
toggleNotification({
|
|
16
|
+
type: 'warning',
|
|
17
|
+
message: { id: 'notification.error', defaultMessage: 'An error occured' },
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default useFetchInstalledPlugins;
|
package/admin/src/{pages/InstalledPluginsPage → hooks/useFetchInstalledPlugins}/utils/api.js
RENAMED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { axiosInstance } from '../../../core/utils';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const fetchInstalledPlugins = async () => {
|
|
4
4
|
const { data } = await axiosInstance.get('/admin/plugins');
|
|
5
5
|
|
|
6
|
-
notify();
|
|
7
|
-
|
|
8
6
|
return data;
|
|
9
7
|
};
|
|
10
8
|
|
|
11
|
-
export {
|
|
9
|
+
export { fetchInstalledPlugins };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useQuery } from 'react-query';
|
|
2
|
+
import { useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
import { fetchMarketplacePlugins } from './utils/api';
|
|
4
|
+
|
|
5
|
+
const useFetchMarketplacePlugins = notifyLoad => {
|
|
6
|
+
const toggleNotification = useNotification();
|
|
7
|
+
|
|
8
|
+
return useQuery('list-marketplace-plugins', () => fetchMarketplacePlugins(), {
|
|
9
|
+
onSuccess: () => {
|
|
10
|
+
if (notifyLoad) {
|
|
11
|
+
notifyLoad();
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
onError: () => {
|
|
15
|
+
toggleNotification({
|
|
16
|
+
type: 'warning',
|
|
17
|
+
message: { id: 'notification.error', defaultMessage: 'An error occured' },
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default useFetchMarketplacePlugins;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
|
|
3
|
+
const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
|
|
4
|
+
|
|
5
|
+
const fetchMarketplacePlugins = async () => {
|
|
6
|
+
const { data: response } = await axios.get(`${MARKETPLACE_API_URL}/plugins`);
|
|
7
|
+
|
|
8
|
+
// Only keep v4 plugins
|
|
9
|
+
const filteredResponse = {
|
|
10
|
+
...response,
|
|
11
|
+
data: response.data.filter(plugin => plugin.attributes.strapiCompatibility === 'v4'),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return filteredResponse;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { fetchMarketplacePlugins };
|
|
@@ -12,7 +12,7 @@ import { DndProvider } from 'react-dnd';
|
|
|
12
12
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
13
13
|
import LeftMenu from '../../components/LeftMenu';
|
|
14
14
|
import AppLayout from '../../layouts/AppLayout';
|
|
15
|
-
import { useMenu
|
|
15
|
+
import { useMenu } from '../../hooks';
|
|
16
16
|
import Onboarding from './Onboarding';
|
|
17
17
|
import { createRoute } from '../../utils';
|
|
18
18
|
import GuidedTourModal from '../../components/GuidedTour/Modal';
|
|
@@ -48,8 +48,6 @@ const useTrackUsage = () => {
|
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
const Admin = () => {
|
|
51
|
-
// Show a notification when the current version of Strapi is not the latest one
|
|
52
|
-
useReleaseNotification();
|
|
53
51
|
useTrackUsage();
|
|
54
52
|
const { isLoading, generalSectionLinks, pluginsSectionLinks } = useMenu();
|
|
55
53
|
const { menu } = useStrapiApp();
|