From 71b210a5aa248b7ff5e095cf7895a59ae42d24e9 Mon Sep 17 00:00:00 2001 From: pkupczyk <piotr.kupczyk@id.ethz.ch> Date: Wed, 19 Jan 2022 18:05:43 +0100 Subject: [PATCH] SSDM-12155 : Table Widget : Improve table usability - clean up of grid widget --- .../src/js/components/common/grid/Grid.jsx | 389 ++++++++++-------- 1 file changed, 216 insertions(+), 173 deletions(-) diff --git a/openbis_ng_ui/src/js/components/common/grid/Grid.jsx b/openbis_ng_ui/src/js/components/common/grid/Grid.jsx index 066128cacbd..e8ff8fa598f 100644 --- a/openbis_ng_ui/src/js/components/common/grid/Grid.jsx +++ b/openbis_ng_ui/src/js/components/common/grid/Grid.jsx @@ -5,6 +5,8 @@ import Loading from '@src/js/components/common/loading/Loading.jsx' import Table from '@material-ui/core/Table' import TableHead from '@material-ui/core/TableHead' import TableBody from '@material-ui/core/TableBody' +import TableRow from '@material-ui/core/TableRow' +import TableCell from '@material-ui/core/TableCell' import Header from '@src/js/components/common/form/Header.jsx' import GridController from '@src/js/components/common/grid/GridController.js' import GridFilters from '@src/js/components/common/grid/GridFilters.jsx' @@ -20,9 +22,7 @@ import logger from '@src/js/common/logger.js' const styles = theme => ({ container: { - height: '100%', - display: 'flex', - flexDirection: 'column' + height: '100%' }, loadingContainer: { flex: '1 1 auto' @@ -30,18 +30,11 @@ const styles = theme => ({ loading: { display: 'inline-block' }, - header: { - paddingBottom: 0 - }, tableContainer: { display: 'inline-block', minWidth: '100%', height: '100%' }, - tableHeaderAndBody: { - width: '100%', - flex: '1 1 auto' - }, table: { borderCollapse: 'unset' }, @@ -51,16 +44,20 @@ const styles = theme => ({ zIndex: '200', backgroundColor: theme.palette.background.paper }, - tableFooter: { - position: 'sticky', - bottom: 0, - paddingLeft: theme.spacing(2), - display: 'flex', - alignItems: 'center', - borderTopWidth: '1px', - borderTopStyle: 'solid', - borderTopColor: theme.palette.border.secondary, - backgroundColor: theme.palette.background.paper + titleCell: { + padding: 0, + border: 0 + }, + title: { + paddingTop: theme.spacing(1), + paddingBottom: 0 + }, + pagingAndConfigsAndExportsCell: { + padding: 0, + border: 0 + }, + pagingAndConfigsAndExports: { + display: 'flex' } }) @@ -103,173 +100,219 @@ class Grid extends React.PureComponent { return <Loading loading={true}></Loading> } - const { - header, - filterModes, - selectable, - multiselectable, - actions, - onRowClick, - classes - } = this.props - const { - loading, - filterMode, - filters, - globalFilter, - sortings, - page, - pageSize, - columnsVisibility, - rows, - selectedRow, - multiselectedRows, - totalCount, - exportOptions - } = this.state - - const allColumns = this.controller.getAllColumns() - const visibleColumns = this.controller.getVisibleColumns() + const { classes } = this.props + const { loading, rows } = this.state return ( <div onClick={this.handleClickContainer} className={classes.container}> <div className={classes.loadingContainer}> <Loading loading={loading} styles={{ root: classes.loading }}> <div className={classes.tableContainer}> - <div - className={classes.tableHeaderAndBodyAndFooter} + <Table + classes={{ root: classes.table }} onClick={this.handleClickTable} > - <div className={classes.tableHeaderAndBody}> - <Table classes={{ root: classes.table }}> - <TableHead classes={{ root: classes.tableHead }}> - <tr> - <td - colSpan={visibleColumns.length + 1} - style={{ paddingTop: '8px' }} - > - <div> - {header && ( - <Header styles={{ root: classes.header }}> - {header} - </Header> - )} - </div> - </td> - </tr> - <tr> - <td colSpan={visibleColumns.length + 1}> - <div style={{ display: 'flex' }}> - <GridPaging - count={totalCount} - page={page} - pageSize={pageSize} - onPageChange={this.controller.handlePageChange} - onPageSizeChange={ - this.controller.handlePageSizeChange - } - /> - <GridColumnsConfig - columns={allColumns} - columnsVisibility={columnsVisibility} - loading={loading} - onVisibleChange={ - this.controller.handleColumnVisibleChange - } - onOrderChange={ - this.controller.handleColumnOrderChange - } - /> - <GridFiltersConfig - filterModes={filterModes} - filterMode={filterMode} - loading={loading} - onFilterModeChange={ - this.controller.handleFilterModeChange - } - /> - <GridExports - disabled={rows.length === 0} - exportOptions={exportOptions} - multiselectable={multiselectable} - onExport={this.controller.handleExport} - onExportOptionsChange={ - this.controller.handleExportOptionsChange - } - /> - </div> - </td> - </tr> - <GridHeaders - columns={visibleColumns} - rows={rows} - sortings={sortings} - onSortChange={this.controller.handleSortChange} - onMultiselectAllRowsChange={ - this.controller.handleMultiselectAllRowsChange - } - multiselectable={multiselectable} - multiselectedRows={multiselectedRows} - /> - <GridFilters - columns={visibleColumns} - filterModes={filterModes} - filterMode={filterMode} - filters={filters} - onFilterChange={this.controller.handleFilterChange} - onFilterModeChange={ - this.controller.handleFilterModeChange - } - globalFilter={globalFilter} - onGlobalFilterChange={ - this.controller.handleGlobalFilterChange - } - multiselectable={multiselectable} - /> - <GridMultiselectionRow - columns={visibleColumns} - rows={rows} - actions={actions} - onExecuteAction={this.controller.handleExecuteAction} - onMultiselectionClear={ - this.controller.handleMultiselectionClear - } - multiselectable={multiselectable} - multiselectedRows={multiselectedRows} - /> - </TableHead> - <TableBody classes={{ root: classes.tableBody }}> - {rows.map(row => { - return ( - <GridRow - key={row.id} - columns={visibleColumns} - row={row} - clickable={onRowClick ? true : false} - selectable={selectable} - selected={ - selectedRow ? selectedRow.id === row.id : false - } - multiselectable={multiselectable} - multiselected={ - multiselectedRows && multiselectedRows[row.id] - } - onClick={this.controller.handleRowClick} - onSelect={this.controller.handleRowSelect} - onMultiselect={this.controller.handleRowMultiselect} - /> - ) - })} - </TableBody> - </Table> - </div> - </div> + <TableHead classes={{ root: classes.tableHead }}> + {this.renderTitle()} + {this.renderPagingAndConfigsAndExports()} + {this.renderHeaders()} + {this.renderFilters()} + {this.renderSelection()} + </TableHead> + <TableBody> + {rows.map(row => { + return this.renderRow(row) + })} + </TableBody> + </Table> </div> </Loading> </div> </div> ) } + + renderTitle() { + const { header, multiselectable, classes } = this.props + + if (header === null || header === undefined) { + return null + } + + const visibleColumns = this.controller.getVisibleColumns() + + return ( + <TableRow> + <TableCell + colSpan={visibleColumns.length + (multiselectable ? 1 : 0)} + classes={{ root: classes.titleCell }} + > + <div onClick={this.handleClickContainer}> + <Header styles={{ root: classes.title }}>{header}</Header> + </div> + </TableCell> + </TableRow> + ) + } + + renderPagingAndConfigsAndExports() { + const { multiselectable, classes } = this.props + + const visibleColumns = this.controller.getVisibleColumns() + + return ( + <TableRow> + <TableCell + colSpan={visibleColumns.length + (multiselectable ? 1 : 0)} + classes={{ root: classes.pagingAndConfigsAndExportsCell }} + > + <div className={classes.pagingAndConfigsAndExports}> + {this.renderPaging()} + {this.renderConfigs()} + {this.renderExports()} + </div> + </TableCell> + </TableRow> + ) + } + + renderPaging() { + const { page, pageSize, totalCount } = this.state + + return ( + <GridPaging + count={totalCount} + page={page} + pageSize={pageSize} + onPageChange={this.controller.handlePageChange} + onPageSizeChange={this.controller.handlePageSizeChange} + /> + ) + } + + renderConfigs() { + const { filterModes } = this.props + const { loading, filterMode, columnsVisibility } = this.state + + const allColumns = this.controller.getAllColumns() + + return ( + <React.Fragment> + <GridColumnsConfig + columns={allColumns} + columnsVisibility={columnsVisibility} + loading={loading} + onVisibleChange={this.controller.handleColumnVisibleChange} + onOrderChange={this.controller.handleColumnOrderChange} + /> + <GridFiltersConfig + filterModes={filterModes} + filterMode={filterMode} + loading={loading} + onFilterModeChange={this.controller.handleFilterModeChange} + /> + </React.Fragment> + ) + } + + renderExports() { + const { multiselectable } = this.props + const { rows, exportOptions } = this.state + + return ( + <GridExports + disabled={rows.length === 0} + exportOptions={exportOptions} + multiselectable={multiselectable} + onExport={this.controller.handleExport} + onExportOptionsChange={this.controller.handleExportOptionsChange} + /> + ) + } + + renderHeaders() { + const { multiselectable } = this.props + const { sortings, rows, multiselectedRows } = this.state + + const visibleColumns = this.controller.getVisibleColumns() + + return ( + <GridHeaders + columns={visibleColumns} + rows={rows} + sortings={sortings} + onSortChange={this.controller.handleSortChange} + onMultiselectAllRowsChange={ + this.controller.handleMultiselectAllRowsChange + } + multiselectable={multiselectable} + multiselectedRows={multiselectedRows} + /> + ) + } + + renderFilters() { + const { filterModes, multiselectable } = this.props + const { filterMode, filters, globalFilter } = this.state + + const visibleColumns = this.controller.getVisibleColumns() + + return ( + <GridFilters + columns={visibleColumns} + filterModes={filterModes} + filterMode={filterMode} + filters={filters} + onFilterChange={this.controller.handleFilterChange} + onFilterModeChange={this.controller.handleFilterModeChange} + globalFilter={globalFilter} + onGlobalFilterChange={this.controller.handleGlobalFilterChange} + multiselectable={multiselectable} + /> + ) + } + + renderSelection() { + const { multiselectable, actions } = this.props + const { rows, multiselectedRows } = this.state + + const visibleColumns = this.controller.getVisibleColumns() + + return ( + <GridMultiselectionRow + columns={visibleColumns} + rows={rows} + actions={actions} + onExecuteAction={this.controller.handleExecuteAction} + onMultiselectionClear={this.controller.handleMultiselectionClear} + multiselectable={multiselectable} + multiselectedRows={multiselectedRows} + /> + ) + } + + renderRow(row) { + const { selectable, multiselectable, onRowClick } = this.props + const { selectedRow, multiselectedRows } = this.state + + const visibleColumns = this.controller.getVisibleColumns() + + return ( + <GridRow + key={row.id} + columns={visibleColumns} + row={row} + clickable={onRowClick ? true : false} + selectable={selectable} + selected={selectedRow ? selectedRow.id === row.id : false} + multiselectable={multiselectable} + multiselected={multiselectedRows && multiselectedRows[row.id]} + onClick={this.controller.handleRowClick} + onSelect={this.controller.handleRowSelect} + onMultiselect={this.controller.handleRowMultiselect} + /> + ) + } } export default withStyles(styles)(Grid) -- GitLab