Add D&P badge

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-09-16 08:55:29 +02:00
parent 53cc79b3dd
commit 5afb369da3
8 changed files with 393 additions and 5 deletions

View File

@ -0,0 +1,84 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import styled from 'styled-components';
import { Box } from '@strapi/parts/Box';
import { Row } from '@strapi/parts/Row';
import { Text } from '@strapi/parts/Text';
import Bullet from '@strapi/icons/Bullet';
import { pxToRem } from '@strapi/helper-plugin';
import { getTrad } from '../../../utils';
import { connect, select } from './utils';
const CustomBullet = styled(Bullet)`
width: ${pxToRem(6)};
height: ${pxToRem(6)};
* {
fill: ${({ theme, $bulletColor }) => theme.colors[$bulletColor]};
}
`;
const DraftAndPublishBadge = ({ hasDraftAndPublish, isPublished }) => {
const { formatMessage } = useIntl();
if (!hasDraftAndPublish) {
return null;
}
const colors = {
draft: {
textColor: 'secondary700',
bulletColor: 'secondary600',
box: {
background: 'secondary100',
borderColor: 'secondary200',
},
},
published: {
textColor: 'success700',
bullet: 'success600',
box: {
background: 'success100',
borderColor: 'success200',
},
},
};
const colorProps = isPublished ? colors.published : colors.draft;
return (
<Box hasRadius as="aside" paddingTop={4} paddingBottom={4} paddingLeft={5} {...colorProps.box}>
<Box as={Row}>
<CustomBullet $bulletColor={colorProps.bulletColor} />
<Box paddingLeft={3}>
<Text textColor={colorProps.textColor}>
{formatMessage({
id: getTrad('containers.Edit.information.editing'),
defaultMessage: 'Editing',
})}
&nbsp;
</Text>
<Text textColor={colorProps.textColor} bold>
{isPublished &&
formatMessage({
id: getTrad('containers.Edit.information.publishedVersion'),
defaultMessage: 'published version',
})}
{!isPublished &&
formatMessage({
id: getTrad('containers.Edit.information.draftVersion'),
defaultMessage: 'draft version',
})}
</Text>
</Box>
</Box>
</Box>
);
};
DraftAndPublishBadge.propTypes = {
hasDraftAndPublish: PropTypes.bool.isRequired,
isPublished: PropTypes.bool.isRequired,
};
export default connect(DraftAndPublishBadge, select);
export { DraftAndPublishBadge };

View File

@ -0,0 +1,225 @@
/**
*
* Tests for DraftAndPublishBadge
*
*/
/* eslint-disable no-irregular-whitespace */
import React from 'react';
import { render } from '@testing-library/react';
import { ThemeProvider, lightTheme } from '@strapi/parts';
import { IntlProvider } from 'react-intl';
import { DraftAndPublishBadge } from '../index';
const makeApp = props => (
<ThemeProvider theme={lightTheme}>
<IntlProvider locale="en" messages={{}} defaultLocale="en">
<DraftAndPublishBadge {...props} />
</IntlProvider>
</ThemeProvider>
);
describe('<DraftAndPublishBadge />', () => {
it('renders and matches the snapshot', () => {
const App = makeApp({ hasDraftAndPublish: true, isPublished: true });
const {
container: { firstChild },
} = render(App);
expect(firstChild).toMatchInlineSnapshot(`
.c0 {
background: #eafbe7;
padding-top: 16px;
padding-bottom: 16px;
padding-left: 20px;
border-radius: 4px;
border: 1px solid #c6f0c2;
}
.c3 {
padding-left: 12px;
}
.c1 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c4 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #2f6846;
}
.c5 {
font-weight: 500;
font-size: 0.875rem;
line-height: 1.43;
color: #2f6846;
}
.c2 {
width: 0.375rem;
height: 0.375rem;
}
<aside
class="c0"
>
<div
class="c1 "
>
<svg
class="c2"
fill="none"
height="1em"
viewBox="0 0 4 4"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<rect
fill="#A5A5BA"
height="4"
rx="2"
width="4"
/>
</svg>
<div
class="c3"
>
<span
class="c4"
>
Editing
 
</span>
<span
class="c5"
>
published version
</span>
</div>
</div>
</aside>
`);
});
it('should show the draft design when it is not published', () => {
const App = makeApp({ hasDraftAndPublish: true, isPublished: false });
const {
container: { firstChild },
} = render(App);
expect(firstChild).toMatchInlineSnapshot(`
.c0 {
background: #eaf5ff;
padding-top: 16px;
padding-bottom: 16px;
padding-left: 20px;
border-radius: 4px;
border: 1px solid #b8e1ff;
}
.c3 {
padding-left: 12px;
}
.c1 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c4 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #006096;
}
.c5 {
font-weight: 500;
font-size: 0.875rem;
line-height: 1.43;
color: #006096;
}
.c2 {
width: 0.375rem;
height: 0.375rem;
}
.c2 * {
fill: #0c75af;
}
<aside
class="c0"
>
<div
class="c1 "
>
<svg
class="c2"
fill="none"
height="1em"
viewBox="0 0 4 4"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<rect
fill="#A5A5BA"
height="4"
rx="2"
width="4"
/>
</svg>
<div
class="c3"
>
<span
class="c4"
>
Editing
 
</span>
<span
class="c5"
>
draft version
</span>
</div>
</div>
</aside>
`);
});
it('should show return null when hasDraftAndPublish is falsy', () => {
const App = makeApp({ hasDraftAndPublish: false, isPublished: false });
const { queryByText } = render(App);
expect(queryByText('Editing')).not.toBeInTheDocument();
});
});

View File

@ -0,0 +1,12 @@
import React from 'react';
function connect(WrappedComponent, select) {
return function(props) {
// eslint-disable-next-line react/prop-types
const selectors = select();
return <WrappedComponent {...props} {...selectors} />;
};
}
export default connect;

View File

@ -0,0 +1,2 @@
export { default as connect } from './connect';
export { default as select } from './select';

View File

@ -0,0 +1,14 @@
import { useContentManagerEditViewDataManager } from '@strapi/helper-plugin';
function useSelect() {
const { initialData, hasDraftAndPublish } = useContentManagerEditViewDataManager();
const isPublished = initialData.published_at !== undefined && initialData.published_at !== null;
return {
hasDraftAndPublish,
isPublished,
};
}
export default useSelect;

View File

@ -14,6 +14,7 @@ import { Row } from '@strapi/parts/Row';
import { Text } from '@strapi/parts/Text';
import { Stack } from '@strapi/parts/Stack';
import AlertWarningIcon from '@strapi/icons/AlertWarningIcon';
import CheckIcon from '@strapi/icons/CheckIcon';
import PropTypes from 'prop-types';
import isEqualFastCompare from 'react-fast-compare';
import { getTrad } from '../../../utils';
@ -104,7 +105,13 @@ const Header = ({
primaryAction = (
<Row>
{shouldShowPublishButton && (
<Button disabled={didChangeData} onClick={onClick} loading={isPublishButtonLoading}>
<Button
disabled={didChangeData}
loading={isPublishButtonLoading}
onClick={onClick}
startIcon={<CheckIcon />}
variant="secondary"
>
{formatMessage(pubishButtonLabel)}
</Button>
)}

View File

@ -10,7 +10,11 @@ import PropTypes from 'prop-types';
// CheckPermissions,
// useTracking,
// '@strapi/helper-plugin';
import { ContentLayout } from '@strapi/parts/Layout';
import { Box } from '@strapi/parts/Box';
import { Grid, GridItem } from '@strapi/parts/Grid';
import { Main } from '@strapi/parts/Main';
import { Stack } from '@strapi/parts/Stack';
// import { Padded } from '@buffetjs/core';
// import { InjectionZone } from '../../../shared/components';
@ -24,6 +28,7 @@ import { Main } from '@strapi/parts/Main';
import CollectionTypeFormWrapper from '../../components/CollectionTypeFormWrapper';
import EditViewDataManagerProvider from '../../components/EditViewDataManagerProvider';
import SingleTypeFormWrapper from '../../components/SingleTypeFormWrapper';
import DraftAndPublishBadge from './DraftAndPublishBadge';
import Header from './Header';
import {
// createAttributesLayout,
@ -132,6 +137,40 @@ const EditView = ({
>
<Main aria-busy={status !== 'resolved'}>
<Header allowedActions={allowedActions} />
<ContentLayout>
<Grid gap={4}>
<GridItem col={9} s={12}>
<Box
hasRadius
background="neutral0"
shadow="tableShadow"
paddingLeft={8}
paddingRight={8}
paddingTop={6}
paddingBottom={6}
>
inputs TODO
</Box>
</GridItem>
<GridItem col={3} s={12}>
<Stack size={2}>
<DraftAndPublishBadge />
<Box
as="aside"
background="neutral0"
borderColor="neutral150"
hasRadius
paddingBottom={4}
paddingLeft={4}
paddingRight={4}
paddingTop={6}
>
infos + InjectionZone
</Box>
</Stack>
</GridItem>
</Grid>
</ContentLayout>
</Main>
</EditViewDataManagerProvider>
);

View File

@ -6,6 +6,7 @@
import React from 'react';
import { render {{~#if useRedux}} as tlRender {{~/if}} } from '@testing-library/react';
import { ThemeProvider, lightTheme } from '@strapi/parts';
{{#if useRedux}}
import { Provider } from 'react-redux';
import { createStore, combineReducers } from 'redux';
@ -49,11 +50,15 @@ describe('<{{name}} />', () => {
container: { firstChild },
} = render(
{{#if useI18n}}
<IntlProvider locale="en" messages={messages} defaultLocale="en">
<{{name}} />
</IntlProvider>,
<ThemeProvider theme={lightTheme}>
<IntlProvider locale="en" messages={messages} defaultLocale="en">
<{{name}} />
</IntlProvider>
</ThemeProvider>
{{else}}
<{{name}} />
<ThemeProvider theme={lightTheme}>
<{{name}} />
</ThemeProvider>
{{/if}}
);