mirror of
https://github.com/strapi/strapi.git
synced 2025-12-28 07:33:17 +00:00
Add D&P badge
Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
parent
53cc79b3dd
commit
5afb369da3
@ -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',
|
||||
})}
|
||||
|
||||
</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 };
|
||||
@ -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();
|
||||
});
|
||||
});
|
||||
@ -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;
|
||||
@ -0,0 +1,2 @@
|
||||
export { default as connect } from './connect';
|
||||
export { default as select } from './select';
|
||||
@ -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;
|
||||
@ -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>
|
||||
)}
|
||||
|
||||
@ -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>
|
||||
);
|
||||
|
||||
@ -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}}
|
||||
);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user