From 14786d7a1ad9a6957cf76818b0832af385cfd169 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Fri, 29 Nov 2019 15:57:36 +0100 Subject: [PATCH] create sortable table --- scm-ui/ui-components/src/table/Column.tsx | 12 ++++ .../ui-components/src/table/Table.stories.tsx | 19 ++++++ scm-ui/ui-components/src/table/Table.tsx | 64 +++++++++++++++++++ scm-ui/ui-components/src/table/TextColumn.tsx | 26 ++++++++ scm-ui/ui-components/src/table/types.ts | 9 +++ 5 files changed, 130 insertions(+) create mode 100644 scm-ui/ui-components/src/table/Column.tsx create mode 100644 scm-ui/ui-components/src/table/Table.stories.tsx create mode 100644 scm-ui/ui-components/src/table/Table.tsx create mode 100644 scm-ui/ui-components/src/table/TextColumn.tsx create mode 100644 scm-ui/ui-components/src/table/types.ts diff --git a/scm-ui/ui-components/src/table/Column.tsx b/scm-ui/ui-components/src/table/Column.tsx new file mode 100644 index 0000000000..e1e7a33156 --- /dev/null +++ b/scm-ui/ui-components/src/table/Column.tsx @@ -0,0 +1,12 @@ +import React, { FC, ReactNode } from "react"; +import { ColumnProps } from "./types"; + +type Props = ColumnProps & { + children: (row: any) => ReactNode; +}; + +const Column: FC = ({ row, children }) => { + return <>{children(row)}; +}; + +export default Column; diff --git a/scm-ui/ui-components/src/table/Table.stories.tsx b/scm-ui/ui-components/src/table/Table.stories.tsx new file mode 100644 index 0000000000..dafc60f5b6 --- /dev/null +++ b/scm-ui/ui-components/src/table/Table.stories.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import { storiesOf } from "@storybook/react"; +import Table from "./Table"; +import Column from "./Column"; +import TextColumn from "./TextColumn"; + +storiesOf("Table|Table", module) + .add("Default", () => ( + + {(row: any) =>

{row.first}

}
+ {(row: any) =>

{row.second}

}
+
+ )) + .add("TextColumn", () => ( + + + +
+ )); diff --git a/scm-ui/ui-components/src/table/Table.tsx b/scm-ui/ui-components/src/table/Table.tsx new file mode 100644 index 0000000000..766ebf9317 --- /dev/null +++ b/scm-ui/ui-components/src/table/Table.tsx @@ -0,0 +1,64 @@ +import React, { FC, useState } from "react"; + +type SortableTableProps = { + data: any[]; +}; + +// @ts-ignore +const Table: FC = ({ data, children }) => { + const [tableData, setTableData] = useState(data); + const [ascending, setAscending] = useState(true); + const [lastSortBy, setlastSortBy] = useState(0); + + // @ts-ignore + const sortFunctions = React.Children.map(children, child => child.props.createComparator(child.props)); + + const mapDataToColumns = (row: any) => { + return ( + + {React.Children.map(children, child => { + // @ts-ignore + return {React.cloneElement(child, { ...child.props, row })}; + })} + + ); + }; + + 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; + } + const sortFunction = sortOrder ? sortFunctions[index] : sortDescending(sortFunctions[index]); + sortableData.sort(sortFunction); + setTableData(sortableData); + setAscending(!sortOrder); + setlastSortBy(index); + }; + + return ( + tableData.length > 0 && ( + + + + {React.Children.map(children, (child, index) => ( + // @ts-ignore + + ))} + + + {tableData.map(mapDataToColumns)} +
tableSort(index)}>{child.props.header}
+ ) + ); +}; + +export default Table; diff --git a/scm-ui/ui-components/src/table/TextColumn.tsx b/scm-ui/ui-components/src/table/TextColumn.tsx new file mode 100644 index 0000000000..eeca01eea7 --- /dev/null +++ b/scm-ui/ui-components/src/table/TextColumn.tsx @@ -0,0 +1,26 @@ +import React, { FC } from "react"; +import {ColumnProps} from "./types"; + +type Props = ColumnProps & { + dataKey: string; +}; + +const TextColumn: FC = ({ row, dataKey }) => { + return row[dataKey]; +}; + +TextColumn.defaultProps = { + createComparator: (props: Props) => { + return (a: any, b: any) => { + if (a[props.dataKey] < b[props.dataKey]) { + return -1; + } else if (a[props.dataKey] > b[props.dataKey]) { + return 1; + } else { + return 0; + } + }; + } +}; + +export default TextColumn; diff --git a/scm-ui/ui-components/src/table/types.ts b/scm-ui/ui-components/src/table/types.ts new file mode 100644 index 0000000000..b05a402711 --- /dev/null +++ b/scm-ui/ui-components/src/table/types.ts @@ -0,0 +1,9 @@ +import { ReactNode } from "react"; + +export type Comparator = (a: any, b: any) => number; + +export type ColumnProps = { + header: ReactNode; + row?: any; + createComparator?: (props: any) => Comparator; +};