feat: add column sorting in table header

pull/237/head
kat 2026-09-17 12:52:09 +01:00
parent 1d67af1558
commit ee585d31eb
1 changed files with 50 additions and 10 deletions

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useMemo } from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
@ -12,7 +12,9 @@ import {
Typography, Typography,
Checkbox, Checkbox,
Loader, Loader,
Flex,
} from '@strapi/design-system'; } from '@strapi/design-system';
import { CaretDown, CaretUp } from '@strapi/icons';
import ConfigDiff from '../ConfigDiff'; import ConfigDiff from '../ConfigDiff';
import FirstExport from '../FirstExport'; import FirstExport from '../FirstExport';
@ -27,9 +29,20 @@ const ConfigList = ({ diff, isLoading }) => {
const [cName, setCname] = useState(''); const [cName, setCname] = useState('');
const [rows, setRows] = useState([]); const [rows, setRows] = useState([]);
const [checkedItems, setCheckedItems] = useState([]); const [checkedItems, setCheckedItems] = useState([]);
const [sortBy, setSortBy] = useState('configName');
const [sortOrder, setSortOrder] = useState('asc');
const dispatch = useDispatch(); const dispatch = useDispatch();
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const handleSort = (field) => {
if (sortBy === field) {
setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc');
} else {
setSortBy(field);
setSortOrder('asc');
}
};
const getConfigState = (configName) => { const getConfigState = (configName) => {
if ( if (
diff.fileConfig[configName] diff.fileConfig[configName]
@ -87,6 +100,19 @@ const ConfigList = ({ diff, isLoading }) => {
dispatch(setConfigPartialDiffInState(newPartialDiff)); dispatch(setConfigPartialDiffInState(newPartialDiff));
}, [checkedItems]); }, [checkedItems]);
const sortedRows = useMemo(() => {
const rowsWithIndex = rows.map((row, originalIndex) => ({ ...row, originalIndex }));
return rowsWithIndex.sort((a, b) => {
const aValue = (a[sortBy] || '').toLowerCase();
const bValue = (b[sortBy] || '').toLowerCase();
if (aValue < bValue) return sortOrder === 'asc' ? -1 : 1;
if (aValue > bValue) return sortOrder === 'asc' ? 1 : -1;
return 0;
});
}, [rows, sortBy, sortOrder]);
if (isLoading) { if (isLoading) {
return ( return (
<div style={{ textAlign: 'center', marginTop: 40 }}> <div style={{ textAlign: 'center', marginTop: 40 }}>
@ -106,6 +132,11 @@ const ConfigList = ({ diff, isLoading }) => {
const allChecked = checkedItems && checkedItems.every(Boolean); const allChecked = checkedItems && checkedItems.every(Boolean);
const isIndeterminate = checkedItems.some(Boolean) && !allChecked; const isIndeterminate = checkedItems.some(Boolean) && !allChecked;
const renderSortIcon = (field) => {
if (sortBy !== field) return null;
return sortOrder === 'asc' ? <CaretUp /> : <CaretDown />;
};
return ( return (
<div> <div>
<Table colCount={4} rowCount={rows.length + 1}> <Table colCount={4} rowCount={rows.length + 1}>
@ -118,19 +149,28 @@ const ConfigList = ({ diff, isLoading }) => {
onCheckedChange={(value) => setCheckedItems(checkedItems.map(() => value))} onCheckedChange={(value) => setCheckedItems(checkedItems.map(() => value))}
/> />
</Th> </Th>
<Th> <Th onClick={() => handleSort('configName')} style={{ cursor: 'pointer' }}>
<Flex gap={1}>
<Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.ConfigName' })}</Typography> <Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.ConfigName' })}</Typography>
{renderSortIcon('configName')}
</Flex>
</Th> </Th>
<Th> <Th onClick={() => handleSort('configType')} style={{ cursor: 'pointer' }}>
<Flex gap={1}>
<Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.ConfigType' })}</Typography> <Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.ConfigType' })}</Typography>
{renderSortIcon('configType')}
</Flex>
</Th> </Th>
<Th> <Th onClick={() => handleSort('state')} style={{ cursor: 'pointer' }}>
<Flex gap={1}>
<Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.State' })}</Typography> <Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.State' })}</Typography>
{renderSortIcon('state')}
</Flex>
</Th> </Th>
</Tr> </Tr>
</Thead> </Thead>
<Tbody> <Tbody>
{rows.map((row, index) => ( {sortedRows.map((row) => (
<ConfigDiff <ConfigDiff
key={row.configName} key={row.configName}
oldValue={originalConfig} oldValue={originalConfig}
@ -139,9 +179,9 @@ const ConfigList = ({ diff, isLoading }) => {
trigger={( trigger={(
<ConfigListRow <ConfigListRow
row={row} row={row}
checked={checkedItems[index]} checked={checkedItems[row.originalIndex]}
updateValue={() => { updateValue={() => {
checkedItems[index] = !checkedItems[index]; checkedItems[row.originalIndex] = !checkedItems[row.originalIndex];
setCheckedItems([...checkedItems]); setCheckedItems([...checkedItems]);
}} }}
/> />