mirror of
https://github.com/strapi/strapi.git
synced 2025-09-22 14:59:07 +00:00
refactor making cell dynamic with CellContent
This commit is contained in:
parent
a04305a2bb
commit
a3ae1310ca
@ -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,
|
||||||
|
};
|
@ -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 (
|
||||||
|
<Td key={name}>
|
||||||
|
<CellContent
|
||||||
alternativeText={alternativeText}
|
alternativeText={alternativeText}
|
||||||
|
content={element[name]}
|
||||||
fileExtension={getFileExtension(ext)}
|
fileExtension={getFileExtension(ext)}
|
||||||
mime={mime}
|
mime={mime}
|
||||||
type={type}
|
cellType={cellType}
|
||||||
|
elementType={elementType}
|
||||||
thumbnailURL={formats?.thumbnail?.url}
|
thumbnailURL={formats?.thumbnail?.url}
|
||||||
url={url}
|
url={url}
|
||||||
/>
|
/>
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
);
|
||||||
<TextCell content={name} />
|
})}
|
||||||
</Td>
|
{((elementType === 'asset' && onEditAsset) ||
|
||||||
<Td>
|
(elementType === 'folder' && onEditFolder)) && (
|
||||||
<TextCell content={ext && getFileExtension(ext).toUpperCase()} />
|
|
||||||
</Td>
|
|
||||||
<Td>
|
|
||||||
<TextCell content={size && formatBytes(size)} />
|
|
||||||
</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 />
|
||||||
|
@ -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,
|
|
||||||
};
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
@ -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',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user