mirror of
https://github.com/strapi/strapi.git
synced 2025-09-25 16:29:34 +00:00
Add info box
Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
parent
2bbe7175c4
commit
f12bda0e7b
@ -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;
|
@ -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>
|
||||
`);
|
||||
});
|
||||
});
|
@ -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;
|
@ -29,6 +29,7 @@ import CollectionTypeFormWrapper from '../../components/CollectionTypeFormWrappe
|
||||
import EditViewDataManagerProvider from '../../components/EditViewDataManagerProvider';
|
||||
import SingleTypeFormWrapper from '../../components/SingleTypeFormWrapper';
|
||||
import DraftAndPublishBadge from './DraftAndPublishBadge';
|
||||
import Informations from './Informations';
|
||||
import Header from './Header';
|
||||
import {
|
||||
// createAttributesLayout,
|
||||
@ -165,7 +166,7 @@ const EditView = ({
|
||||
paddingRight={4}
|
||||
paddingTop={6}
|
||||
>
|
||||
infos + InjectionZone
|
||||
<Informations />
|
||||
</Box>
|
||||
</Stack>
|
||||
</GridItem>
|
||||
|
Loading…
x
Reference in New Issue
Block a user