Add info box

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-09-20 09:03:22 +02:00
parent 2bbe7175c4
commit f12bda0e7b
4 changed files with 270 additions and 1 deletions

View File

@ -0,0 +1,63 @@
import React, { useRef } from 'react';
import { useIntl } from 'react-intl';
import { useContentManagerEditViewDataManager } from '@strapi/helper-plugin';
import { Box } from '@strapi/parts/Box';
import { Divider } from '@strapi/parts/Divider';
import { Text } from '@strapi/parts/Text';
import { Row } from '@strapi/parts/Row';
import { Stack } from '@strapi/parts/Stack';
import { getTrad } from '../../../utils';
import getUnits from './utils/getUnits';
const Informations = () => {
const { formatMessage, formatRelativeTime } = useIntl();
const { initialData, isCreatingEntry } = useContentManagerEditViewDataManager();
// TODO if timestamps are still configurable in the V4
const updatedAt = 'updated_at';
const updatedByFirstname = initialData.updated_by?.firstname || '';
const updatedByLastname = initialData.updated_by?.lastname || '';
const updatedByUsername = initialData.updated_by?.username;
const updatedBy = updatedByUsername || `${updatedByFirstname} ${updatedByLastname}`;
const currentTime = useRef(new Date().getTime());
const timestamp = initialData[updatedAt]
? new Date(initialData[updatedAt]).getTime()
: Date.now();
const elapsed = timestamp - currentTime.current;
const { unit, value } = getUnits(-elapsed);
return (
<Box>
<Text textColor="neutral600" bold small style={{ textTransform: 'uppercase' }}>
{formatMessage({
id: getTrad('containers.Edit.information'),
defaultMessage: 'Information',
})}
</Text>
<Box paddingTop={2} paddingBottom={6}>
<Divider />
</Box>
<Stack size={4}>
<Row justifyContent="space-between">
<Text bold>
{formatMessage({
id: getTrad('containers.Edit.information.lastUpdate'),
})}
</Text>
<Text>{formatRelativeTime(value, unit, { numeric: 'auto' })}</Text>
</Row>
<Row justifyContent="space-between">
<Text bold>
{formatMessage({
id: getTrad('containers.Edit.information.by'),
})}
</Text>
<Text>{isCreatingEntry ? '-' : updatedBy}</Text>
</Row>
</Stack>
</Box>
);
};
export default Informations;

View File

@ -0,0 +1,178 @@
/**
*
* Tests for Informations
*
*/
import React from 'react';
import { render } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import { useContentManagerEditViewDataManager } from '@strapi/helper-plugin';
import Theme from '../../../../../components/Theme';
import Informations from '../index';
jest.mock('@strapi/helper-plugin', () => ({
useContentManagerEditViewDataManager: jest.fn(),
}));
const makeApp = () => {
return (
<IntlProvider
locale="en"
defaultLocale="en"
messages={{ 'containers.Edit.information': 'Information' }}
>
<Theme>
<Informations />
</Theme>
</IntlProvider>
);
};
describe('CONTENT MANAGER | EditView | Header', () => {
const RealNow = Date.now;
beforeAll(() => {
global.Date.now = jest.fn(() => new Date('2021-09-20').getTime());
});
afterAll(() => {
global.Date.now = RealNow;
});
it('renders and matches the snaphsot', () => {
useContentManagerEditViewDataManager.mockImplementationOnce(() => ({
initialData: {},
isCreatingEntry: true,
}));
const {
container: { firstChild },
} = render(makeApp());
expect(firstChild).toMatchInlineSnapshot(`
.c1 {
padding-top: 8px;
padding-bottom: 24px;
}
.c2 {
background: #eaeaef;
}
.c3 {
height: 1px;
border: none;
margin: 0;
}
.c0 {
font-weight: 500;
font-size: 0.75rem;
line-height: 1.33;
color: #666687;
}
.c6 {
font-weight: 500;
font-size: 0.875rem;
line-height: 1.43;
color: #32324d;
}
.c7 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #32324d;
}
.c5 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c4 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.c4 > * {
margin-top: 0;
margin-bottom: 0;
}
.c4 > * + * {
margin-top: 16px;
}
<div
class=""
>
<span
class="c0"
style="text-transform: uppercase;"
>
Information
</span>
<div
class="c1"
>
<hr
class="c2 c3"
/>
</div>
<div
class="c4"
>
<div
class="c5"
>
<span
class="c6"
>
content-manager.containers.Edit.information.lastUpdate
</span>
<span
class="c7"
>
7 hours ago
</span>
</div>
<div
class="c5"
>
<span
class="c6"
>
content-manager.containers.Edit.information.by
</span>
<span
class="c7"
>
-
</span>
</div>
</div>
</div>
`);
});
});

View File

@ -0,0 +1,27 @@
const msPerMinute = 60 * 1000;
const msPerHour = msPerMinute * 60;
const msPerDay = msPerHour * 24;
const msPerMonth = msPerDay * 30;
const msPerYear = msPerDay * 365;
const getUnits = value => {
if (value < msPerMinute) {
return { unit: 'second', value: -Math.round(value / 1000) };
}
if (value < msPerHour) {
return { unit: 'minute', value: -Math.round(value / msPerMinute) };
}
if (value < msPerDay) {
return { unit: 'hour', value: -Math.round(value / msPerHour) };
}
if (value < msPerMonth) {
return { unit: 'day', value: -Math.round(value / msPerDay) };
}
if (value < msPerYear) {
return { unit: 'month', value: -Math.round(value / msPerMonth) };
}
return { unit: 'year', value: -Math.round(value / msPerYear) };
};
export default getUnits;

View File

@ -29,6 +29,7 @@ import CollectionTypeFormWrapper from '../../components/CollectionTypeFormWrappe
import EditViewDataManagerProvider from '../../components/EditViewDataManagerProvider'; import EditViewDataManagerProvider from '../../components/EditViewDataManagerProvider';
import SingleTypeFormWrapper from '../../components/SingleTypeFormWrapper'; import SingleTypeFormWrapper from '../../components/SingleTypeFormWrapper';
import DraftAndPublishBadge from './DraftAndPublishBadge'; import DraftAndPublishBadge from './DraftAndPublishBadge';
import Informations from './Informations';
import Header from './Header'; import Header from './Header';
import { import {
// createAttributesLayout, // createAttributesLayout,
@ -165,7 +166,7 @@ const EditView = ({
paddingRight={4} paddingRight={4}
paddingTop={6} paddingTop={6}
> >
infos + InjectionZone <Informations />
</Box> </Box>
</Stack> </Stack>
</GridItem> </GridItem>