Files
SCM-Manager/scm-ui/ui-components/src/table/Table.tsx

112 lines
3.3 KiB
TypeScript
Raw Normal View History

2019-11-29 15:57:36 +01:00
import React, { FC, useState } from "react";
2019-11-29 17:13:39 +01:00
import styled from "styled-components";
2019-12-02 15:59:32 +01:00
import { Comparator } from "./table";
2019-12-02 13:58:56 +01:00
import SortIcon from "./SortIcon";
2019-11-29 17:13:39 +01:00
const StyledTable = styled.table.attrs(() => ({
className: "table content is-hoverable"
}))``;
2019-12-02 13:58:56 +01:00
type Props = {
2019-11-29 15:57:36 +01:00
data: any[];
2019-12-02 13:58:56 +01:00
sortable?: boolean;
2019-11-29 15:57:36 +01:00
};
// @ts-ignore
2019-12-02 13:58:56 +01:00
const Table: FC<Props> = ({ data, sortable, children }) => {
2019-11-29 15:57:36 +01:00
const [tableData, setTableData] = useState(data);
2019-11-29 17:13:39 +01:00
const [ascending, setAscending] = useState(false);
2019-12-02 13:58:56 +01:00
const [lastSortBy, setlastSortBy] = useState<number | undefined>();
2019-12-02 14:03:50 +01:00
const [hoveredColumnIndex, setHoveredColumnIndex] = useState<number | undefined>();
2019-11-29 15:57:36 +01:00
2019-12-02 13:58:56 +01:00
const isSortable = (child: any) => {
return sortable && child.props.createComparator;
};
const sortFunctions: Comparator | undefined[] = [];
React.Children.forEach(children, (child, index) => {
if (isSortable(child)) {
// @ts-ignore
sortFunctions.push(child.props.createComparator(child.props, index));
} else {
sortFunctions.push(undefined);
}
});
2019-11-29 15:57:36 +01:00
const mapDataToColumns = (row: any) => {
return (
<tr>
2019-12-02 13:58:56 +01:00
{React.Children.map(children, (child, columnIndex) => {
2019-11-29 15:57:36 +01:00
// @ts-ignore
2019-12-02 13:58:56 +01:00
return <td>{React.cloneElement(child, { ...child.props, columnIndex, row })}</td>;
2019-11-29 15:57:36 +01:00
})}
</tr>
);
};
const sortDescending = (sortAscending: (a: any, b: any) => number) => {
return (a: any, b: any) => {
return sortAscending(a, b) * -1;
};
};
const tableSort = (index: number) => {
const sortableData = [...tableData];
let sortOrder = ascending;
if (lastSortBy !== index) {
setAscending(true);
sortOrder = true;
}
2019-12-02 13:58:56 +01:00
// @ts-ignore
2019-11-29 15:57:36 +01:00
const sortFunction = sortOrder ? sortFunctions[index] : sortDescending(sortFunctions[index]);
sortableData.sort(sortFunction);
setTableData(sortableData);
setAscending(!sortOrder);
setlastSortBy(index);
};
2019-12-03 09:42:12 +01:00
const shouldShowIcon = (index: number) => {
return index === lastSortBy || index === hoveredColumnIndex;
};
2019-11-29 15:57:36 +01:00
return (
tableData.length > 0 && (
2019-11-29 17:13:39 +01:00
<StyledTable>
2019-11-29 15:57:36 +01:00
<thead>
<tr>
{React.Children.map(children, (child, index) => (
2019-11-29 17:13:39 +01:00
<th
2019-12-02 13:58:56 +01:00
className={isSortable(child) && "has-cursor-pointer"}
onClick={isSortable(child) ? () => tableSort(index) : undefined}
2019-12-02 14:03:50 +01:00
onMouseEnter={() => setHoveredColumnIndex(index)}
onMouseLeave={() => setHoveredColumnIndex(undefined)}
2019-11-29 17:13:39 +01:00
>
2019-12-03 09:37:52 +01:00
{
// @ts-ignore
child.props.header
}
2019-12-03 09:42:12 +01:00
{isSortable(child) && renderSortIcon(child, ascending, shouldShowIcon(index))}
2019-11-29 17:13:39 +01:00
</th>
2019-11-29 15:57:36 +01:00
))}
</tr>
</thead>
<tbody>{tableData.map(mapDataToColumns)}</tbody>
2019-11-29 17:13:39 +01:00
</StyledTable>
2019-11-29 15:57:36 +01:00
)
);
};
2019-12-02 13:58:56 +01:00
Table.defaultProps = {
sortable: true
};
const renderSortIcon = (child: any, ascending: boolean, showIcon: boolean) => {
if (child.props.ascendingIcon && child.props.descendingIcon) {
2019-12-02 14:03:50 +01:00
return <SortIcon name={ascending ? child.props.ascendingIcon : child.props.descendingIcon} isVisible={showIcon} />;
2019-11-29 17:13:39 +01:00
} else {
2019-12-02 14:03:50 +01:00
return <SortIcon name={ascending ? "sort-amount-down-alt" : "sort-amount-down"} isVisible={showIcon} />;
2019-11-29 17:13:39 +01:00
}
};
2019-11-29 15:57:36 +01:00
export default Table;