Merge branch 'upgrade-plan' of https://github.com/strapi/strapi into upgrade-plan

This commit is contained in:
ronronscelestes 2021-09-06 10:50:13 +02:00
commit 0c0d8b940c
6 changed files with 240 additions and 0 deletions

View File

@ -0,0 +1,33 @@
<!--- UpgradePlanModal.stories.mdx --->
import { useState } from 'react';
import { ArgsTable, Meta, Canvas, Story } from '@storybook/addon-docs';
import { Button } from '@strapi/parts/Button';
import UpgradePlanModal from './index';
<Meta title="components/UpgradePlanModal" />
# UpgradePlanModal
TODO
## Usage
<Canvas>
<Story name="base">
{() => {
const [isVisible, setIsVisible] = useState(false);
const handleToggle = () => setIsVisible(prev => !prev);
return (
<>
<Button onClick={handleToggle}>Click me</Button>
<UpgradePlanModal isOpen={isVisible} onClose={handleToggle} />
</>
);
}}
</Story>
</Canvas>
### Props
<ArgsTable of={UpgradePlanModal} />

View File

@ -0,0 +1,127 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { useIntl } from 'react-intl';
import { setOpacity } from '../../utils/setOpacity';
import { useLockScroll } from '../../utils/useLockScroll';
import { Portal } from '@strapi/parts/Portal';
import { FocusTrap } from '@strapi/parts/FocusTrap';
import { IconButton } from '@strapi/parts/IconButton';
import { LinkButton } from '@strapi/parts/LinkButton';
import { Box } from '@strapi/parts/Box';
import { Row } from '@strapi/parts/Row';
import { Text, H1 } from '@strapi/parts/Text';
import { Stack } from '@strapi/parts/Stack';
import ExternalLink from '@strapi/icons/ExternalLink';
import CloseAlertIcon from '@strapi/icons/CloseAlertIcon';
import AirBalloon from './../../../../../admin/admin/src/assets/images/hot-air-balloon.png';
import BigArrow from './../../../../../admin/admin/src/assets/images/upgrade-details.png';
const UpragdeWrapper = styled.div`
position: absolute;
z-index: 3;
inset: 0;
background: ${({ theme }) => setOpacity(theme.colors.neutral800, 0.2)};
padding: 0 ${({ theme }) => theme.spaces[8]};
`;
const UpgradeContainer = styled(Row)`
position: relative;
max-width: ${830 / 16}rem;
height: ${415 / 16}rem;
margin: 0 auto;
overflow: hidden;
margin-top: 10%;
padding-left: ${64 / 16}rem;
img:first-of-type {
position: absolute;
right: 0;
top: 0;
max-width: ${360 / 16}rem;
}
img:not(:first-of-type) {
width: ${130 / 16}rem;
margin-left: 12%;
margin-right: ${20 / 16}rem;
z-index: 0;
}
`;
const TextBold = styled(Text)`
font-weight: bold;
`;
const StackFlexStart = styled(Stack)`
align-items: flex-start;
max-width: ${400 / 16}rem;
z-index: 0;
`;
const CloseButtonContainer = styled(Box)`
position: absolute;
right: ${({ theme }) => theme.spaces[4]};
top: ${({ theme }) => theme.spaces[4]};
`;
const UpgradePlanModal = ({ onClose, isOpen }) => {
useLockScroll(isOpen);
const { formatMessage } = useIntl();
if (!isOpen) {
return null;
}
return (
<Portal>
<UpragdeWrapper>
<FocusTrap onClose={onClose}>
<UpgradeContainer aria-labelledby="upgrade-plan" background="neutral0" hasRadius>
<img src={AirBalloon} />
<CloseButtonContainer>
<IconButton onClick={onClose} label="Close" icon={<CloseAlertIcon />} />
</CloseButtonContainer>
<StackFlexStart size={6}>
<TextBold textColor="primary600">
{formatMessage({
id: 'app.components.UpgradePlanModal.text-ce',
defaultMessage: 'COMMUNITY EDITION',
})}
</TextBold>
<Stack size={2}>
<H1 as="h2" id="upgrade-plan">
{formatMessage({
id: 'app.components.UpgradePlanModal.limit-reached',
defaultMessage: 'You have reached the limit',
})}
</H1>
<Text>
{formatMessage({
id: 'app.components.UpgradePlanModal.text-power',
defaultMessage:
'Unlock the full power of Strapi by upgrading your plan to the Enterprise Edition',
})}
</Text>
</Stack>
<LinkButton href="https://strapi.io/pricing-self-hosted" endIcon={<ExternalLink />}>
{formatMessage({
id: 'app.components.UpgradePlanModal.button',
defaultMessage: 'Learn more',
})}
</LinkButton>
</StackFlexStart>
<img src={BigArrow} />
</UpgradeContainer>
</FocusTrap>
</UpragdeWrapper>
</Portal>
);
};
UpgradePlanModal.propTypes = {
onClose: PropTypes.func.isRequired,
isOpen: PropTypes.bool.isRequired,
};
export default UpgradePlanModal;

View File

@ -0,0 +1,63 @@
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import { ThemeProvider, lightTheme } from '@strapi/parts';
import UpgradePlanModal from '../index';
const App = (
<ThemeProvider theme={lightTheme}>
<IntlProvider locale="en" messages={{ en: {} }} textComponent="span">
<UpgradePlanModal isOpen={true} onClose={jest.fn()} />
</IntlProvider>
</ThemeProvider>
);
describe('UpgradePlanModal', () => {
it('renders and matches the snapshot', async () => {
const {
container: { firstChild },
} = render(App);
expect(firstChild).toMatchInlineSnapshot(`
.c0 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
<div
class="c0"
>
<p
aria-live="polite"
id="live-region-log"
role="log"
/>
<p
aria-live="polite"
id="live-region-status"
role="status"
/>
<p
aria-live="assertive"
id="live-region-alert"
role="alert"
/>
</div>
`);
});
it('renders and matches the snapshot', async () => {
render(App);
await waitFor(() => {
expect(screen.getByText('You have reached the limit')).toBeInTheDocument();
});
});
});

View File

@ -186,6 +186,7 @@ export { default as LoadingIndicatorPage } from './components/LoadingIndicatorPa
export { default as SettingsPageTitle } from './components/SettingsPageTitle';
export { default as Search } from './components/Search';
export { default as Status } from './components/Status';
export { default as UpgradePlanModal } from './components/UpgradePlanModal';
// New icons
export { default as SortIcon } from './icons/SortIcon';

View File

@ -0,0 +1,4 @@
export const setOpacity = (hex, alpha) =>
`${hex}${Math.floor(alpha * 255)
.toString(16)
.padStart(2, 0)}`;

View File

@ -0,0 +1,12 @@
import { useEffect } from 'react';
export const useLockScroll = lockScroll => {
useEffect(() => {
if (lockScroll) {
document.body.classList.add('lock-body-scroll');
}
return () => {
document.body.classList.remove('lock-body-scroll');
};
}, [lockScroll]);
};