refactor making cell dynamic with CellContent

This commit is contained in:
Julie Plantey 2022-11-21 10:54:43 +01:00
parent a04305a2bb
commit a3ae1310ca
6 changed files with 185 additions and 94 deletions

View File

@ -0,0 +1,72 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import { getFileExtension } from '@strapi/helper-plugin';
import { Typography } from '@strapi/design-system/Typography';
import { PreviewCell } from './PreviewCell';
import { formatBytes } from '../../utils';
export const CellContent = ({
alternativeText,
content,
cellType,
elementType,
mime,
fileExtension,
thumbnailURL,
url,
}) => {
const { formatDate } = useIntl();
switch (cellType) {
case 'image':
return (
<PreviewCell
alternativeText={alternativeText}
fileExtension={fileExtension}
mime={mime}
type={elementType}
thumbnailURL={thumbnailURL}
url={url}
/>
);
case 'date':
return <Typography>{formatDate(content)}</Typography>;
case 'size':
if (elementType === 'folder') return <Typography>-</Typography>;
return <Typography>{formatBytes(content)}</Typography>;
case 'ext':
if (elementType === 'folder') return <Typography>-</Typography>;
return <Typography>{getFileExtension(content).toUpperCase()}</Typography>;
case 'text':
return <Typography>{content}</Typography>;
default:
return <Typography>-</Typography>;
}
};
CellContent.defaultProps = {
alternativeText: null,
content: '',
fileExtension: '',
mime: '',
thumbnailURL: null,
url: null,
};
CellContent.propTypes = {
alternativeText: PropTypes.string,
content: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
fileExtension: PropTypes.string,
mime: PropTypes.string,
thumbnailURL: PropTypes.string,
cellType: PropTypes.string.isRequired,
elementType: PropTypes.string.isRequired,
url: PropTypes.string,
};

View File

@ -7,30 +7,17 @@ import { IconButton } from '@strapi/design-system/IconButton';
import { Tbody, Td, Tr } from '@strapi/design-system/Table'; import { Tbody, Td, Tr } from '@strapi/design-system/Table';
import Pencil from '@strapi/icons/Pencil'; import Pencil from '@strapi/icons/Pencil';
import { PreviewCell } from './PreviewCell'; import { CellContent } from './CellContent';
import { TextCell } from './TextCell'; import { AssetDefinition, FolderDefinition, tableHeaders as cells } from '../../constants';
import { AssetDefinition, FolderDefinition } from '../../constants'; import { getTrad } from '../../utils';
import { formatBytes, getTrad } from '../../utils';
export const TableRows = ({ onEditAsset, onEditFolder, onSelectOne, rows, selected }) => { export const TableRows = ({ onEditAsset, onEditFolder, onSelectOne, rows, selected }) => {
const { formatDate, formatMessage } = useIntl(); const { formatMessage } = useIntl();
return ( return (
<Tbody> <Tbody>
{rows.map((element) => { {rows.map((element) => {
const { const { alternativeText, id, name, ext, url, mime, formats, type: elementType } = element;
alternativeText,
id,
name,
ext,
size,
createdAt,
updatedAt,
url,
mime,
formats,
type,
} = element;
const isSelected = !!selected.find((currentRow) => currentRow.id === id); const isSelected = !!selected.find((currentRow) => currentRow.id === id);
@ -40,49 +27,43 @@ export const TableRows = ({ onEditAsset, onEditFolder, onSelectOne, rows, select
<BaseCheckbox <BaseCheckbox
aria-label={formatMessage( aria-label={formatMessage(
{ {
id: type === 'asset' ? 'list-assets-select' : 'list.folder.select', id: elementType === 'asset' ? 'list-assets-select' : 'list.folder.select',
defaultMessage: defaultMessage:
type === 'asset' ? 'Select {name} asset' : 'Select {name} folder', elementType === 'asset' ? 'Select {name} asset' : 'Select {name} folder',
}, },
{ name } { name }
)} )}
onValueChange={() => onSelectOne({ ...element, type })} onValueChange={() => onSelectOne({ ...element, elementType })}
checked={isSelected} checked={isSelected}
/> />
</Td> </Td>
<Td> {cells.map(({ name, type: cellType }) => {
<PreviewCell return (
alternativeText={alternativeText} <Td key={name}>
fileExtension={getFileExtension(ext)} <CellContent
mime={mime} alternativeText={alternativeText}
type={type} content={element[name]}
thumbnailURL={formats?.thumbnail?.url} fileExtension={getFileExtension(ext)}
url={url} mime={mime}
/> cellType={cellType}
</Td> elementType={elementType}
<Td> thumbnailURL={formats?.thumbnail?.url}
<TextCell content={name} /> url={url}
</Td> />
<Td> </Td>
<TextCell content={ext && getFileExtension(ext).toUpperCase()} /> );
</Td> })}
<Td> {((elementType === 'asset' && onEditAsset) ||
<TextCell content={size && formatBytes(size)} /> (elementType === 'folder' && onEditFolder)) && (
</Td>
<Td>
<TextCell content={formatDate(new Date(createdAt))} />
</Td>
<Td>
<TextCell content={formatDate(new Date(updatedAt))} />
</Td>
{((type === 'asset' && onEditAsset) || (type === 'folder' && onEditFolder)) && (
<Td> <Td>
<IconButton <IconButton
label={formatMessage({ label={formatMessage({
id: getTrad('control-card.edit'), id: getTrad('control-card.edit'),
defaultMessage: 'Edit', defaultMessage: 'Edit',
})} })}
onClick={() => (type === 'asset' ? onEditAsset(element) : onEditFolder(element))} onClick={() =>
elementType === 'asset' ? onEditAsset(element) : onEditFolder(element)
}
noBorder noBorder
> >
<Pencil /> <Pencil />

View File

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Typography } from '@strapi/design-system/Typography';
export const TextCell = ({ content }) => {
if (content) {
return <Typography>{content}</Typography>;
}
return <Typography>-</Typography>;
};
TextCell.defaultProps = {
content: '',
};
TextCell.propTypes = {
content: PropTypes.string,
};

View File

@ -0,0 +1,78 @@
import React from 'react';
import { IntlProvider } from 'react-intl';
import { render } from '@testing-library/react';
import { ThemeProvider, lightTheme } from '@strapi/design-system';
import { CellContent } from '../CellContent';
const PROPS_FIXTURE = {
alternativeText: 'alternative alt',
cellType: 'image',
elementType: 'asset',
content: 'michka-picture-url-default.jpeg',
fileExtension: '.jpeg',
mime: 'image/jpeg',
thumbnailURL: 'michka-picture-url-thumbnail.jpeg',
url: 'michka-picture-url-default.jpeg',
};
const ComponentFixture = (props) => {
const customProps = {
...PROPS_FIXTURE,
...props,
};
return (
<IntlProvider locale="en" messages={{}}>
<ThemeProvider theme={lightTheme}>
<CellContent {...PROPS_FIXTURE} {...customProps} />
</ThemeProvider>
</IntlProvider>
);
};
const setup = (props) => render(<ComponentFixture {...props} />);
describe('TableList | CellContent', () => {
it('should render image cell type when element type is asset and mime includes image', () => {
const { getByRole } = setup();
expect(getByRole('img', { name: 'alternative alt' })).toBeInTheDocument();
});
it('should render image cell type when element type is asset and mime does not include image', () => {
const { getByText } = setup({ mime: 'application/pdf', fileExtension: 'pdf' });
expect(getByText('pdf')).toBeInTheDocument();
});
it('should render image cell type when element type is folder', () => {
const { container } = setup({ elementType: 'folder' });
expect(container.querySelector('path')).toBeInTheDocument();
});
it('should render text cell type', () => {
const { getByText } = setup({ cellType: 'text', content: 'some text' });
expect(getByText('some text')).toBeInTheDocument();
});
it('should render extension cell type', () => {
const { getByText } = setup({ cellType: 'ext', content: '.pdf' });
expect(getByText('PDF')).toBeInTheDocument();
});
it('should render size cell type', () => {
const { getByText } = setup({ cellType: 'size', content: '20.5435' });
expect(getByText('21KB')).toBeInTheDocument();
});
it('should render date cell type', () => {
const { getByText } = setup({ cellType: 'date', content: '2022-11-18T12:08:02.202Z' });
expect(getByText('11/18/2022')).toBeInTheDocument();
});
});

View File

@ -1,27 +0,0 @@
import React from 'react';
import { render } from '@testing-library/react';
import { ThemeProvider, lightTheme } from '@strapi/design-system';
import { TextCell } from '../TextCell';
const ComponentFixture = (props) => (
<ThemeProvider theme={lightTheme}>
<TextCell {...props} />
</ThemeProvider>
);
const setup = (props) => render(<ComponentFixture {...props} />);
describe('TableList | TextCell', () => {
it('should render content', () => {
const { getByText } = setup({ content: 'michka' });
expect(getByText('michka')).toBeInTheDocument();
});
it('should render a default content', () => {
const { getByText } = setup();
expect(getByText('-')).toBeInTheDocument();
});
});

View File

@ -105,6 +105,7 @@ export const tableHeaders = [
label: { id: getTrad('list-table-header-preview'), defaultMessage: 'preview' }, label: { id: getTrad('list-table-header-preview'), defaultMessage: 'preview' },
sortable: false, sortable: false,
}, },
type: 'image',
}, },
{ {
name: 'name', name: 'name',
@ -113,6 +114,7 @@ export const tableHeaders = [
label: { id: getTrad('list-table-header-name'), defaultMessage: 'name' }, label: { id: getTrad('list-table-header-name'), defaultMessage: 'name' },
sortable: true, sortable: true,
}, },
type: 'text',
}, },
{ {
name: 'ext', name: 'ext',
@ -121,6 +123,7 @@ export const tableHeaders = [
label: { id: getTrad('list-table-header-ext'), defaultMessage: 'extension' }, label: { id: getTrad('list-table-header-ext'), defaultMessage: 'extension' },
sortable: false, sortable: false,
}, },
type: 'ext',
}, },
{ {
name: 'size', name: 'size',
@ -129,6 +132,7 @@ export const tableHeaders = [
label: { id: getTrad('list-table-header-size'), defaultMessage: 'size' }, label: { id: getTrad('list-table-header-size'), defaultMessage: 'size' },
sortable: false, sortable: false,
}, },
type: 'size',
}, },
{ {
name: 'createdAt', name: 'createdAt',
@ -137,6 +141,7 @@ export const tableHeaders = [
label: { id: getTrad('list-table-header-createdAt'), defaultMessage: 'created' }, label: { id: getTrad('list-table-header-createdAt'), defaultMessage: 'created' },
sortable: true, sortable: true,
}, },
type: 'date',
}, },
{ {
name: 'updatedAt', name: 'updatedAt',
@ -145,6 +150,7 @@ export const tableHeaders = [
label: { id: getTrad('list-table-header-updatedAt'), defaultMessage: 'last update' }, label: { id: getTrad('list-table-header-updatedAt'), defaultMessage: 'last update' },
sortable: true, sortable: true,
}, },
type: 'date',
}, },
]; ];