mirror of
https://github.com/strapi/strapi.git
synced 2026-01-07 20:58:16 +00:00
integrated sort to table list view
This commit is contained in:
parent
1d8d318135
commit
f2fdfda42d
@ -2,9 +2,13 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox';
|
||||
import { IconButton } from '@strapi/design-system/IconButton';
|
||||
import { Table, Th, Thead, Tr } from '@strapi/design-system/Table';
|
||||
import { Tooltip } from '@strapi/design-system/Tooltip';
|
||||
import { Typography } from '@strapi/design-system/Typography';
|
||||
import { VisuallyHidden } from '@strapi/design-system/VisuallyHidden';
|
||||
import CarretDown from '@strapi/icons/CarretDown';
|
||||
import CarretUp from '@strapi/icons/CarretUp';
|
||||
|
||||
import { getTrad } from '../../utils';
|
||||
import { AssetDefinition, tableHeaders, FolderDefinition } from '../../constants';
|
||||
@ -14,14 +18,17 @@ export const TableList = ({
|
||||
assetCount,
|
||||
folderCount,
|
||||
indeterminate,
|
||||
onChangeSort,
|
||||
onEditAsset,
|
||||
onEditFolder,
|
||||
onSelectAll,
|
||||
onSelectOne,
|
||||
rows,
|
||||
selected,
|
||||
sortQuery,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const [sortBy, sortOrder] = sortQuery.split(':');
|
||||
|
||||
return (
|
||||
<Table colCount={tableHeaders.length + 2} rowCount={assetCount + folderCount + 1}>
|
||||
@ -40,12 +47,55 @@ export const TableList = ({
|
||||
}
|
||||
/>
|
||||
</Th>
|
||||
{tableHeaders.map(({ metadatas, key }) => {
|
||||
{tableHeaders.map(({ metadatas: { label, isSortable }, name, key }) => {
|
||||
const isSorted = sortBy === name;
|
||||
const isUp = sortOrder === 'ASC';
|
||||
const tableHeaderLabel = formatMessage(label);
|
||||
const sortLabel = formatMessage(
|
||||
{ id: 'list-table-header-sort', defaultMessage: 'Sort on {label}' },
|
||||
{ label: tableHeaderLabel }
|
||||
);
|
||||
|
||||
const handleClickSort = () => {
|
||||
if (isSortable) {
|
||||
const nextSortOrder = isSorted && sortOrder === 'ASC' ? 'DESC' : 'ASC';
|
||||
const nextSort = `${name}:${nextSortOrder}`;
|
||||
|
||||
onChangeSort(nextSort);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Th key={key}>
|
||||
<Typography textColor="neutral600" variant="sigma">
|
||||
{formatMessage(metadatas.label)}
|
||||
</Typography>
|
||||
<Th
|
||||
action={
|
||||
isSorted && (
|
||||
<IconButton
|
||||
label={sortLabel}
|
||||
onClick={handleClickSort}
|
||||
icon={isUp ? <CarretUp /> : <CarretDown />}
|
||||
noBorder
|
||||
/>
|
||||
)
|
||||
}
|
||||
key={key}
|
||||
>
|
||||
{isSortable ? (
|
||||
<Tooltip label={sortLabel}>
|
||||
<Typography
|
||||
onClick={() => handleClickSort(!isSorted)}
|
||||
as={isSorted ? 'span' : 'button'}
|
||||
label={!isSorted ? sortLabel : ''}
|
||||
textColor="neutral600"
|
||||
variant="sigma"
|
||||
>
|
||||
{tableHeaderLabel}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Typography textColor="neutral600" variant="sigma">
|
||||
{tableHeaderLabel}
|
||||
</Typography>
|
||||
)}
|
||||
</Th>
|
||||
);
|
||||
})}
|
||||
@ -74,20 +124,24 @@ TableList.defaultProps = {
|
||||
assetCount: 0,
|
||||
folderCount: 0,
|
||||
indeterminate: false,
|
||||
onChangeSort: null,
|
||||
onEditAsset: null,
|
||||
onEditFolder: null,
|
||||
rows: [],
|
||||
selected: [],
|
||||
sortQuery: '',
|
||||
};
|
||||
|
||||
TableList.propTypes = {
|
||||
assetCount: PropTypes.number,
|
||||
folderCount: PropTypes.number,
|
||||
indeterminate: PropTypes.bool,
|
||||
onChangeSort: PropTypes.func,
|
||||
onEditAsset: PropTypes.func,
|
||||
onEditFolder: PropTypes.func,
|
||||
onSelectAll: PropTypes.func.isRequired,
|
||||
onSelectOne: PropTypes.func.isRequired,
|
||||
rows: PropTypes.arrayOf(AssetDefinition, FolderDefinition),
|
||||
selected: PropTypes.arrayOf(AssetDefinition, FolderDefinition),
|
||||
sortQuery: PropTypes.string,
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { render } from '@testing-library/react';
|
||||
import { render, fireEvent } from '@testing-library/react';
|
||||
import { ThemeProvider, lightTheme } from '@strapi/design-system';
|
||||
|
||||
import { TableList } from '..';
|
||||
@ -71,6 +71,30 @@ describe('TableList', () => {
|
||||
expect(getByRole('columnheader', { name: 'actions' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onChangeSort callback when changing sort order', () => {
|
||||
const onChangeSortSpy = jest.fn();
|
||||
const { getByRole } = setup({ sortQuery: 'updatedAt:ASC', onChangeSort: onChangeSortSpy });
|
||||
|
||||
const sortButton = getByRole('button', { name: 'Sort on last update' });
|
||||
expect(sortButton).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(sortButton);
|
||||
|
||||
expect(onChangeSortSpy).toHaveBeenCalledWith('updatedAt:DESC');
|
||||
});
|
||||
|
||||
it('should call onChangeSort callback when changing sort by', () => {
|
||||
const onChangeSortSpy = jest.fn();
|
||||
const { getByRole } = setup({ sortQuery: 'updatedAt:ASC', onChangeSort: onChangeSortSpy });
|
||||
|
||||
const sortButton = getByRole('button', { name: 'Sort on name' });
|
||||
expect(sortButton).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(sortButton);
|
||||
|
||||
expect(onChangeSortSpy).toHaveBeenCalledWith('name:ASC');
|
||||
});
|
||||
|
||||
it('should render assets', () => {
|
||||
const { getByText } = setup();
|
||||
|
||||
|
||||
@ -103,7 +103,7 @@ export const tableHeaders = [
|
||||
key: 'preview',
|
||||
metadatas: {
|
||||
label: { id: getTrad('list-table-header-preview'), defaultMessage: 'preview' },
|
||||
sortable: false,
|
||||
isSortable: false,
|
||||
},
|
||||
type: 'image',
|
||||
},
|
||||
@ -112,7 +112,7 @@ export const tableHeaders = [
|
||||
key: 'name',
|
||||
metadatas: {
|
||||
label: { id: getTrad('list-table-header-name'), defaultMessage: 'name' },
|
||||
sortable: true,
|
||||
isSortable: true,
|
||||
},
|
||||
type: 'text',
|
||||
},
|
||||
@ -121,7 +121,7 @@ export const tableHeaders = [
|
||||
key: 'extension',
|
||||
metadatas: {
|
||||
label: { id: getTrad('list-table-header-ext'), defaultMessage: 'extension' },
|
||||
sortable: false,
|
||||
isSortable: false,
|
||||
},
|
||||
type: 'ext',
|
||||
},
|
||||
@ -130,7 +130,7 @@ export const tableHeaders = [
|
||||
key: 'size',
|
||||
metadatas: {
|
||||
label: { id: getTrad('list-table-header-size'), defaultMessage: 'size' },
|
||||
sortable: false,
|
||||
isSortable: false,
|
||||
},
|
||||
type: 'size',
|
||||
},
|
||||
@ -139,7 +139,7 @@ export const tableHeaders = [
|
||||
key: 'createdAt',
|
||||
metadatas: {
|
||||
label: { id: getTrad('list-table-header-createdAt'), defaultMessage: 'created' },
|
||||
sortable: true,
|
||||
isSortable: true,
|
||||
},
|
||||
type: 'date',
|
||||
},
|
||||
@ -148,7 +148,7 @@ export const tableHeaders = [
|
||||
key: 'updatedAt',
|
||||
metadatas: {
|
||||
label: { id: getTrad('list-table-header-updatedAt'), defaultMessage: 'last update' },
|
||||
sortable: true,
|
||||
isSortable: true,
|
||||
},
|
||||
type: 'date',
|
||||
},
|
||||
|
||||
@ -244,6 +244,7 @@ export const MediaLibrary = () => {
|
||||
assetCount={assetCount}
|
||||
folderCount={folderCount}
|
||||
indeterminate={indeterminateBulkSelect}
|
||||
onChangeSort={handleChangeSort}
|
||||
onEditAsset={setAssetToEdit}
|
||||
onEditFolder={handleEditFolder}
|
||||
onSelectOne={selectOne}
|
||||
@ -255,6 +256,7 @@ export const MediaLibrary = () => {
|
||||
!assetsLoading && !foldersLoading ? [...folders, ...assets] : []
|
||||
}
|
||||
selected={selected}
|
||||
sortQuery={query?.sort}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@ -119,8 +119,9 @@
|
||||
"list-table-header-name": "name",
|
||||
"list-table-header-ext": "extension",
|
||||
"list-table-header-size": "size",
|
||||
"list-table-header-createdAt": "Created",
|
||||
"list-table-header-updatedAt": "Last update",
|
||||
"list-table-header-createdAt": "created",
|
||||
"list-table-header-updatedAt": "last update",
|
||||
"list-table-header-sort": "Sort on {label}",
|
||||
"tabs.title": "How do you want to upload your assets?",
|
||||
"window.confirm.close-modal.file": "Are you sure? Your changes will be lost.",
|
||||
"window.confirm.close-modal.files": "Are you sure? You have some files that have not been uploaded yet."
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user