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