This is an automated email from the ASF dual-hosted git repository. msyavuz pushed a commit to branch msyavuz/refactor/use-ant-tables in repository https://gitbox.apache.org/repos/asf/superset.git
commit e6b555aa128fbd9a58fda8e025d99d0ccfc35cd0 Author: Mehmet Salih Yavuz <[email protected]> AuthorDate: Tue Apr 1 18:55:12 2025 +0300 refactor(Table): first working iteration --- superset-frontend/src/components/Table/index.tsx | 3 +- .../src/components/TableCollection/index.tsx | 404 +++++++-------------- 2 files changed, 138 insertions(+), 269 deletions(-) diff --git a/superset-frontend/src/components/Table/index.tsx b/superset-frontend/src/components/Table/index.tsx index cf55b7e4b7..fef01289f1 100644 --- a/superset-frontend/src/components/Table/index.tsx +++ b/superset-frontend/src/components/Table/index.tsx @@ -50,6 +50,7 @@ export type OnChangeFunction<RecordType> = export enum TableSize { Small = 'small', Middle = 'middle', + Large = 'large', } export interface TableProps<RecordType> { @@ -76,7 +77,7 @@ export interface TableProps<RecordType> { /** * Controls the size of the table. */ - size: TableSize; + size?: TableSize; /** * Controls if table rows are selectable and if multiple select is supported. */ diff --git a/superset-frontend/src/components/TableCollection/index.tsx b/superset-frontend/src/components/TableCollection/index.tsx index dc97a09c02..7d25cea682 100644 --- a/superset-frontend/src/components/TableCollection/index.tsx +++ b/superset-frontend/src/components/TableCollection/index.tsx @@ -19,7 +19,7 @@ import { memo } from 'react'; import cx from 'classnames'; import { TableInstance } from 'react-table'; -import { styled } from '@superset-ui/core'; +import { Table, TableSize, ColumnsType } from 'src/components/Table'; import { Icons } from 'src/components/Icons'; interface TableCollectionProps { @@ -34,176 +34,28 @@ interface TableCollectionProps { columnsForWrapText?: string[]; } -export const Table = styled.table` - ${({ theme }) => ` - background-color: ${theme.colorBgContainer}; - border-collapse: separate; - border-radius: ${theme.borderRadius}px; - - thead > tr > th { - border: 0; - } - - tbody { - tr:first-of-type > td { - border-top: 0; - } - tr > td { - border-top: 1px solid ${theme.colorSplit}; - } - } - th { - position: sticky; - top: 0; - - &:first-of-type { - padding-left: ${theme.sizeUnit * 4}px; - } - - &.xs { - min-width: 25px; - } - &.sm { - min-width: 50px; - } - &.md { - min-width: 75px; - } - &.lg { - min-width: 100px; - } - &.xl { - min-width: 150px; - } - &.xxl { - min-width: 200px; - } - - span { - white-space: nowrap; - display: flex; - align-items: center; - line-height: 2; - } - - svg { - display: inline-block; - position: relative; - } - } - - td { - &.xs { - width: 25px; - } - &.sm { - width: 50px; - } - &.md { - width: 75px; - } - &.lg { - width: 100px; - } - &.xl { - width: 150px; - } - &.xxl { - width: 200px; - } - } - - .table-cell-loader { - position: relative; - - .loading-bar { - background-color: ${theme.colorBgTextHover}; - border-radius: 7px; - - span { - visibility: hidden; - } - } - - .empty-loading-bar { - display: inline-block; - width: 100%; - height: 1.2em; - } - } - - .actions { - white-space: nowrap; - min-width: 100px; - - svg, - i { - margin-right: 8px; - - &:hover { - path { - fill: ${theme.colorPrimary}; - } - } - } - } - - .table-row { - .actions { - opacity: 0; - font-size: ${theme.fontSizeXL}px; - display: flex; - } - - &:hover { - background-color: ${theme.colorBgTextHover}; - - .actions { - opacity: 1; - transition: opacity ease-in ${theme.motionDurationMid}; - } - } - } - - .table-row-selected { - background-color: ${theme.colorPrimaryBgHover}; - - &:hover { - background-color: ${theme.colorPrimaryBgHover}; - } - } - - .table-cell { - font-feature-settings: 'tnum' 1; - text-overflow: ellipsis; - overflow: hidden; - max-width: 320px; - line-height: 1; - vertical-align: middle; - &:first-of-type { - padding-left: ${theme.sizeUnit * 4}px; - } - &__wrap { - white-space: normal; - } - &__nowrap { - white-space: nowrap; - } - } - - @keyframes loading-shimmer { - 40% { - background-position: 100% 0; - } - - 100% { - background-position: 100% 0; - } - } - `} -`; - -Table.displayName = 'table'; +const mapColumns = (columns: TableInstance['columns']): ColumnsType => { + console.log({ columns }); + return columns.map((column: any) => ({ + title: column.Header, + dataIndex: column.accessor, + key: column.accessor, + hidden: column.hidden, + render: (val, record, index) => { + if (column.Cell) { + return column.Cell({ row: { original: record, id: index } }); + } + return val; + }, + })); +}; + +const mapRows = (rows: TableInstance['rows']): any[] => { + console.log({ rows }); + return rows.map(row => ({ + ...row.values, + })); +}; export default memo( ({ @@ -216,115 +68,131 @@ export default memo( loading, highlightRowId, columnsForWrapText, - }: TableCollectionProps) => ( - <Table - {...getTableProps()} - className="table table-hover" - data-test="listview-table" - > - <thead> - {headerGroups.map(headerGroup => ( - <tr {...headerGroup.getHeaderGroupProps()}> - {headerGroup.headers.map(column => { - let sortIcon = <Icons.Sort />; - if (column.isSorted && column.isSortedDesc) { - sortIcon = <Icons.SortDesc />; - } else if (column.isSorted && !column.isSortedDesc) { - sortIcon = <Icons.SortAsc />; - } - return column.hidden ? null : ( - <th - {...column.getHeaderProps( - column.canSort ? column.getSortByToggleProps() : {}, - )} - data-test="sort-header" - className={cx({ - [column.size || '']: column.size, - })} - > - <span> - {column.render('Header')} - {column.canSort && sortIcon} - </span> - </th> - ); - })} - </tr> - ))} - </thead> - <tbody {...getTableBodyProps()}> - {loading && - rows.length === 0 && - [...new Array(12)].map((_, i) => ( - <tr key={i}> - {columns.map((column, i2) => { - if (column.hidden) return null; - return ( - <td - key={i2} - className={cx('table-cell', { - 'table-cell-loader': loading, + }: TableCollectionProps) => { + console.log({ + mappedColumns: mapColumns(columns), + }); + + return ( + <Table + columns={mapColumns(columns)} + data={mapRows(rows)} + size={TableSize.Large} + /> + ); + return ( + <Table + {...getTableProps()} + className="table table-hover" + data-test="listview-table" + > + <thead> + {headerGroups.map(headerGroup => ( + <tr {...headerGroup.getHeaderGroupProps()}> + {headerGroup.headers.map(column => { + let sortIcon = <Icons.Sort />; + if (column.isSorted && column.isSortedDesc) { + sortIcon = <Icons.SortDesc />; + } else if (column.isSorted && !column.isSortedDesc) { + sortIcon = <Icons.SortAsc />; + } + return column.hidden ? null : ( + <th + {...column.getHeaderProps( + column.canSort ? column.getSortByToggleProps() : {}, + )} + data-test="sort-header" + className={cx({ + [column.size || '']: column.size, })} > - <span - className="loading-bar empty-loading-bar" - role="progressbar" - aria-label="loading" - /> - </td> + <span> + {column.render('Header')} + {column.canSort && sortIcon} + </span> + </th> ); })} </tr> ))} - {rows.length > 0 && - rows.map(row => { - prepareRow(row); - // @ts-ignore - const rowId = row.original.id; - return ( - <tr - data-test="table-row" - {...row.getRowProps()} - className={cx('table-row', { - 'table-row-selected': - row.isSelected || - (typeof rowId !== 'undefined' && rowId === highlightRowId), - })} - > - {row.cells.map(cell => { - if (cell.column.hidden) return null; - const columnCellProps = cell.column.cellProps || {}; - const isWrapText = columnsForWrapText?.includes( - cell.column.Header as string, - ); + </thead> + <tbody {...getTableBodyProps()}> + {loading && + rows.length === 0 && + [...new Array(12)].map((_, i) => ( + <tr key={i}> + {columns.map((column, i2) => { + if (column.hidden) return null; return ( <td - data-test="table-row-cell" - className={cx( - `table-cell table-cell__${ - isWrapText ? 'wrap' : 'nowrap' - }`, - { - 'table-cell-loader': loading, - [cell.column.size || '']: cell.column.size, - }, - )} - {...cell.getCellProps()} - {...columnCellProps} + key={i2} + className={cx('table-cell', { + 'table-cell-loader': loading, + })} > <span - className={cx({ 'loading-bar': loading })} - role={loading ? 'progressbar' : undefined} - > - <span data-test="cell-text">{cell.render('Cell')}</span> - </span> + className="loading-bar empty-loading-bar" + role="progressbar" + aria-label="loading" + /> </td> ); })} </tr> - ); - })} - </tbody> - </Table> - ), + ))} + {rows.length > 0 && + rows.map(row => { + prepareRow(row); + // @ts-ignore + const rowId = row.original.id; + return ( + <tr + data-test="table-row" + {...row.getRowProps()} + className={cx('table-row', { + 'table-row-selected': + row.isSelected || + (typeof rowId !== 'undefined' && + rowId === highlightRowId), + })} + > + {row.cells.map(cell => { + if (cell.column.hidden) return null; + const columnCellProps = cell.column.cellProps || {}; + const isWrapText = columnsForWrapText?.includes( + cell.column.Header as string, + ); + return ( + <td + data-test="table-row-cell" + className={cx( + `table-cell table-cell__${ + isWrapText ? 'wrap' : 'nowrap' + }`, + { + 'table-cell-loader': loading, + [cell.column.size || '']: cell.column.size, + }, + )} + {...cell.getCellProps()} + {...columnCellProps} + > + <span + className={cx({ 'loading-bar': loading })} + role={loading ? 'progressbar' : undefined} + > + <span data-test="cell-text"> + {cell.render('Cell')} + </span> + </span> + </td> + ); + })} + </tr> + ); + })} + </tbody> + </Table> + ); + }, );
