diff --git a/packages/strapi-admin/admin/src/components/PluginCard/index.js b/packages/strapi-admin/admin/src/components/PluginCard/index.js index e8909684d4..42588427e4 100644 --- a/packages/strapi-admin/admin/src/components/PluginCard/index.js +++ b/packages/strapi-admin/admin/src/components/PluginCard/index.js @@ -80,7 +80,7 @@ class PluginCard extends React.Component { } else if (currentEnvironment !== 'development') { this.setState({ showModalEnv: true }); } else if (!isAlreadyInstalled) { - downloadPlugin(e); + downloadPlugin(id); } else { push('/list-plugins'); } @@ -152,6 +152,7 @@ class PluginCard extends React.Component { {}, + locale: 'en', }, }; @@ -240,6 +243,7 @@ Admin.propTypes = { }).isRequired, intl: PropTypes.shape({ formatMessage: PropTypes.func, + locale: PropTypes.string, }), location: PropTypes.object.isRequired, setAppError: PropTypes.func.isRequired, diff --git a/packages/strapi-admin/admin/src/containers/MarketplacePage/Wrapper.js b/packages/strapi-admin/admin/src/containers/MarketplacePage/Wrapper.js new file mode 100644 index 0000000000..985ae7780c --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/MarketplacePage/Wrapper.js @@ -0,0 +1,10 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div` + padding: 18px 30px !important; + > div:first-child { + margin-bottom: 11px; + } +`; + +export default Wrapper; diff --git a/packages/strapi-admin/admin/src/containers/MarketplacePage/index.js b/packages/strapi-admin/admin/src/containers/MarketplacePage/index.js new file mode 100644 index 0000000000..124bb087ff --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/MarketplacePage/index.js @@ -0,0 +1,106 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { + LoadingIndicatorPage, + useGlobalContext, + request, +} from 'strapi-helper-plugin'; +import { Header } from '@buffetjs/custom'; + +import PageTitle from '../../components/PageTitle'; +import PluginCard from '../../components/PluginCard'; +import Wrapper from './Wrapper'; +import useFetch from './useFetch'; + +const MarketPlacePage = ({ history }) => { + const { + autoReload, + currentEnvironment, + formatMessage, + plugins, + } = useGlobalContext(); + const { isLoading, data } = useFetch(); + + if (isLoading) { + return ; + } + + const handleDownloadPlugin = async pluginId => { + // Force the Overlayblocker to be displayed + const overlayblockerParams = { + enabled: true, + title: 'app.components.InstallPluginPage.Download.title', + description: 'app.components.InstallPluginPage.Download.description', + }; + // Lock the app + strapi.lockApp(overlayblockerParams); + + try { + const opts = { + method: 'POST', + body: { + plugin: pluginId, + port: window.location.port, + }, + }; + const response = await request( + '/admin/plugins/install', + opts, + overlayblockerParams + ); + + if (response.ok) { + // Reload the app + window.location.reload(); + } + } catch (err) { + strapi.unlockApp(); + strapi.notification.error('notification.error'); + } + }; + + return ( + + + + + + {data.map(plugin => { + return ( + + ); + })} + + + + ); +}; + +MarketPlacePage.propTypes = { + history: PropTypes.object.isRequired, +}; + +export default MarketPlacePage; diff --git a/packages/strapi-admin/admin/src/containers/MarketplacePage/useFetch.js b/packages/strapi-admin/admin/src/containers/MarketplacePage/useFetch.js new file mode 100644 index 0000000000..2461e05617 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/MarketplacePage/useFetch.js @@ -0,0 +1,52 @@ +import { useEffect, useState } from 'react'; +import axios from 'axios'; +import { useGlobalContext } from 'strapi-helper-plugin'; + +const useFetch = () => { + const { currentLocale } = useGlobalContext(); + const [state, setState] = useState({ + error: false, + isLoading: true, + data: null, + }); + + useEffect(() => { + const CancelToken = axios.CancelToken; + const source = CancelToken.source(); + + const getData = async () => { + try { + const { data } = await axios.get( + 'https://marketplace.strapi.io/plugins', + { + cancelToken: source.token, + params: { lang: currentLocale }, + } + ); + + setState({ + isLoading: false, + data, + error: false, + }); + } catch (err) { + if (axios.isCancel(err)) { + // Silent + } else { + // handle error + setState(prev => ({ ...prev, isLoading: false, error: true })); + } + } + }; + + getData(); + + return () => { + source.cancel(); + }; + }, [currentLocale]); + + return state; +}; + +export default useFetch;