Skip to content
Snippets Groups Projects
Commit 1fb009f9 authored by piotr.kupczyk@id.ethz.ch's avatar piotr.kupczyk@id.ethz.ch
Browse files

SSDM-7594 : Grid - make it possible to configure column order

parent bcfcf896
No related branches found
No related tags found
No related merge requests found
...@@ -4,8 +4,7 @@ import { withStyles } from '@material-ui/core/styles' ...@@ -4,8 +4,7 @@ import { withStyles } from '@material-ui/core/styles'
import IconButton from '@material-ui/core/IconButton' import IconButton from '@material-ui/core/IconButton'
import SettingsIcon from '@material-ui/icons/Settings' import SettingsIcon from '@material-ui/icons/Settings'
import Popover from '@material-ui/core/Popover' import Popover from '@material-ui/core/Popover'
import FormControlLabel from '@material-ui/core/FormControlLabel' import ColumnConfigRow from './ColumnConfigRow.jsx'
import Checkbox from '@material-ui/core/Checkbox'
import logger from '../../../common/logger.js' import logger from '../../../common/logger.js'
const styles = () => ({ const styles = () => ({
...@@ -28,7 +27,6 @@ class ColumnConfig extends React.Component { ...@@ -28,7 +27,6 @@ class ColumnConfig extends React.Component {
} }
this.handleOpen = this.handleOpen.bind(this) this.handleOpen = this.handleOpen.bind(this)
this.handleClose = this.handleClose.bind(this) this.handleClose = this.handleClose.bind(this)
this.handleChange = this.handleChange.bind(this)
} }
handleOpen(event) { handleOpen(event) {
...@@ -43,23 +41,10 @@ class ColumnConfig extends React.Component { ...@@ -43,23 +41,10 @@ class ColumnConfig extends React.Component {
}) })
} }
handleChange(event) {
let columns = [...this.props.visibleColumns]
let column = event.target.value
if (columns.includes(column)) {
_.pull(columns, column)
} else {
columns.push(column)
}
this.props.onColumnsChange(columns)
}
render() { render() {
logger.log(logger.DEBUG, 'ColumnConfig.render') logger.log(logger.DEBUG, 'ColumnConfig.render')
const { classes, allColumns, visibleColumns } = this.props const { classes, columns, onVisibleChange, onOrderChange } = this.props
const { el } = this.state const { el } = this.state
return ( return (
...@@ -81,17 +66,12 @@ class ColumnConfig extends React.Component { ...@@ -81,17 +66,12 @@ class ColumnConfig extends React.Component {
}} }}
> >
<ol className={classes.columns}> <ol className={classes.columns}>
{allColumns.map(column => ( {columns.map(column => (
<li key={column.field}> <li key={column.field}>
<FormControlLabel <ColumnConfigRow
control={ column={column}
<Checkbox onVisibleChange={onVisibleChange}
value={column.field} onOrderChange={onOrderChange}
checked={visibleColumns.includes(column.field)}
onChange={this.handleChange}
/>
}
label={column.label || column.field}
/> />
</li> </li>
))} ))}
......
import _ from 'lodash'
import React from 'react'
import { DragSource } from 'react-dnd'
import { DropTarget } from 'react-dnd'
import FormControlLabel from '@material-ui/core/FormControlLabel'
import Checkbox from '@material-ui/core/Checkbox'
import DragHandleIcon from '@material-ui/icons/DragHandle'
import RootRef from '@material-ui/core/RootRef'
import { withStyles } from '@material-ui/core/styles'
import logger from '../../../common/logger.js'
const styles = () => ({
row: {
display: 'flex',
alignItems: 'center'
},
label: {
marginLeft: 0
},
drag: {
display: 'flex',
cursor: 'grab'
}
})
const source = {
beginDrag(props) {
return { column: props.column.field }
},
endDrag(props, monitor) {
if (monitor.getItem() && monitor.getDropResult()) {
const { column: sourceColumn } = monitor.getItem()
const { column: targetColumn } = monitor.getDropResult()
props.onOrderChange(sourceColumn, targetColumn)
}
}
}
function sourceCollect(connect, monitor) {
return {
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
isDragging: monitor.isDragging()
}
}
const target = {
drop(props) {
return { column: props.column.field }
}
}
function targetCollect(connect, monitor) {
return {
connectDropTarget: connect.dropTarget(),
isDragging: monitor.getItem() !== null
}
}
class ColumnConfigRow extends React.Component {
constructor(props) {
super(props)
this.handleRef = React.createRef()
this.rowRef = React.createRef()
this.handleVisibleChange = this.handleVisibleChange.bind(this)
}
componentDidMount() {
this.props.connectDragSource(this.handleRef.current)
this.props.connectDragPreview(this.rowRef.current)
this.props.connectDropTarget(this.rowRef.current)
}
handleVisibleChange() {
this.props.onVisibleChange(this.props.column.field)
}
render() {
logger.log(logger.DEBUG, 'ColumnConfigRow.render')
const { classes, column } = this.props
return (
<RootRef rootRef={this.rowRef}>
<div className={classes.row}>
<RootRef rootRef={this.handleRef}>
<div className={classes.drag}>
<DragHandleIcon />
</div>
</RootRef>
<FormControlLabel
classes={{ root: classes.label }}
control={
<Checkbox
checked={column.visible}
onChange={this.handleVisibleChange}
/>
}
label={column.label || column.field}
/>
</div>
</RootRef>
)
}
}
export default _.flow(
DragSource('column', source, sourceCollect),
DropTarget('column', target, targetCollect),
withStyles(styles)
)(ColumnConfigRow)
...@@ -67,25 +67,26 @@ class Grid extends React.Component { ...@@ -67,25 +67,26 @@ class Grid extends React.Component {
const sortDefault = _.isFunction(props.data) ? false : true const sortDefault = _.isFunction(props.data) ? false : true
this.columnsArray = props.columns.map(column => ({ let columns = props.columns.map(column => ({
...column, ...column,
label: column.label || _.upperFirst(column.field), label: column.label || _.upperFirst(column.field),
render: column.render || (row => _.get(row, column.field)), render: column.render || (row => _.get(row, column.field)),
sort: column.sort === undefined ? sortDefault : Boolean(column.sort) sort: column.sort === undefined ? sortDefault : Boolean(column.sort),
visible: true
})) }))
this.columnsMap = _.keyBy(props.columns, 'field')
this.state = { this.state = {
loaded: false, loaded: false,
filters: this.props.filters || {}, filters: this.props.filters || {},
page: 0, page: 0,
pageSize: 10, pageSize: 10,
visibleColumns: Object.keys(this.columnsMap), columns: columns,
columnConfigEl: null columnConfigEl: null
} }
this.handleFilterChange = this.handleFilterChange.bind(this) this.handleFilterChange = this.handleFilterChange.bind(this)
this.handleColumnsChange = this.handleColumnsChange.bind(this) this.handleColumnVisibleChange = this.handleColumnVisibleChange.bind(this)
this.handleColumnOrderChange = this.handleColumnOrderChange.bind(this)
this.handlePageChange = this.handlePageChange.bind(this) this.handlePageChange = this.handlePageChange.bind(this)
this.handlePageSizeChange = this.handlePageSizeChange.bind(this) this.handlePageSizeChange = this.handlePageSizeChange.bind(this)
} }
...@@ -140,8 +141,26 @@ class Grid extends React.Component { ...@@ -140,8 +141,26 @@ class Grid extends React.Component {
if (gridSettings) { if (gridSettings) {
let settings = JSON.parse(gridSettings.value) let settings = JSON.parse(gridSettings.value)
if (settings) { if (settings) {
let newColumns = [...this.state.columns]
newColumns.sort((c1, c2) => {
let index1 = _.findIndex(settings.columns, ['field', c1.field])
let index2 = _.findIndex(settings.columns, ['field', c2.field])
return index1 - index2
})
newColumns = newColumns.map(column => {
let setting = _.find(settings.columns, ['field', column.field])
if (setting) {
return {
...column,
visible: setting.visible
}
} else {
return column
}
})
this.setState(() => ({ this.setState(() => ({
...settings ...settings,
columns: newColumns
})) }))
} }
} }
...@@ -150,11 +169,16 @@ class Grid extends React.Component { ...@@ -150,11 +169,16 @@ class Grid extends React.Component {
} }
saveSettings() { saveSettings() {
let columns = this.state.columns.map(column => ({
field: column.field,
visible: column.visible
}))
let settings = { let settings = {
pageSize: this.state.pageSize, pageSize: this.state.pageSize,
sort: this.state.sort, sort: this.state.sort,
sortDirection: this.state.sortDirection, sortDirection: this.state.sortDirection,
visibleColumns: this.state.visibleColumns columns
} }
let gridSettings = new dto.WebAppSettingCreation() let gridSettings = new dto.WebAppSettingCreation()
...@@ -185,10 +209,42 @@ class Grid extends React.Component { ...@@ -185,10 +209,42 @@ class Grid extends React.Component {
) )
} }
handleColumnsChange(visibleColumns) { handleColumnVisibleChange(field) {
let columns = this.state.columns.map(column => {
if (column.field === field) {
return {
...column,
visible: !column.visible
}
} else {
return column
}
})
this.setState( this.setState(
() => ({ () => ({
visibleColumns columns
}),
() => {
this.saveSettings()
}
)
}
handleColumnOrderChange(sourceField, targetField) {
let columns = [...this.state.columns]
let sourceIndex = _.findIndex(columns, ['field', sourceField])
let targetIndex = _.findIndex(columns, ['field', targetField])
if (sourceIndex !== -1 && targetIndex !== -1) {
let temp = columns[sourceIndex]
columns[sourceIndex] = columns[targetIndex]
columns[targetIndex] = temp
}
this.setState(
() => ({
columns
}), }),
() => { () => {
this.saveSettings() this.saveSettings()
...@@ -254,9 +310,9 @@ class Grid extends React.Component { ...@@ -254,9 +310,9 @@ class Grid extends React.Component {
return _.filter(objects, row => { return _.filter(objects, row => {
let matchesAll = true let matchesAll = true
this.state.visibleColumns.forEach(visibleColumn => { this.state.columns.forEach(column => {
let value = _.get(row, visibleColumn) let value = _.get(row, column.field)
let filter = this.state.filters[visibleColumn] let filter = this.state.filters[column.field]
matchesAll = matchesAll && matches(value, filter) matchesAll = matchesAll && matches(value, filter)
}) })
return matchesAll return matchesAll
...@@ -267,9 +323,9 @@ class Grid extends React.Component { ...@@ -267,9 +323,9 @@ class Grid extends React.Component {
const { sort, sortDirection } = this.state const { sort, sortDirection } = this.state
if (sort) { if (sort) {
let column = _.find(this.state.columns, ['field', sort])
return objects.sort((t1, t2) => { return objects.sort((t1, t2) => {
let sign = sortDirection === 'asc' ? 1 : -1 let sign = sortDirection === 'asc' ? 1 : -1
let column = this.columnsMap[sort]
let v1 = _.get(t1, column.field) || '' let v1 = _.get(t1, column.field) || ''
let v2 = _.get(t2, column.field) || '' let v2 = _.get(t2, column.field) || ''
return sign * v1.localeCompare(v2) return sign * v1.localeCompare(v2)
...@@ -295,7 +351,7 @@ class Grid extends React.Component { ...@@ -295,7 +351,7 @@ class Grid extends React.Component {
} }
const { classes } = this.props const { classes } = this.props
const { page, pageSize, visibleColumns } = this.state const { page, pageSize, columns } = this.state
let pagedObjects = null let pagedObjects = null
let totalCount = null let totalCount = null
...@@ -316,19 +372,17 @@ class Grid extends React.Component { ...@@ -316,19 +372,17 @@ class Grid extends React.Component {
<Table classes={{ root: classes.table }}> <Table classes={{ root: classes.table }}>
<TableHead classes={{ root: classes.tableHeader }}> <TableHead classes={{ root: classes.tableHeader }}>
<TableRow> <TableRow>
{this.columnsArray.map(column => this.renderFilterCell(column))} {columns.map(column => this.renderFilterCell(column))}
</TableRow> </TableRow>
<TableRow> <TableRow>
{this.columnsArray.map(column => this.renderHeaderCell(column))} {columns.map(column => this.renderHeaderCell(column))}
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
{pagedObjects.map(row => { {pagedObjects.map(row => {
return ( return (
<TableRow key={row.id} hover> <TableRow key={row.id} hover>
{this.columnsArray.map(column => {columns.map(column => this.renderRowCell(column, row))}
this.renderRowCell(column, row)
)}
</TableRow> </TableRow>
) )
})} })}
...@@ -347,9 +401,9 @@ class Grid extends React.Component { ...@@ -347,9 +401,9 @@ class Grid extends React.Component {
onPageSizeChange={this.handlePageSizeChange} onPageSizeChange={this.handlePageSizeChange}
/> />
<ColumnConfig <ColumnConfig
allColumns={this.columnsArray} columns={columns}
visibleColumns={visibleColumns} onVisibleChange={this.handleColumnVisibleChange}
onColumnsChange={this.handleColumnsChange} onOrderChange={this.handleColumnOrderChange}
/> />
</div> </div>
</div> </div>
...@@ -357,9 +411,9 @@ class Grid extends React.Component { ...@@ -357,9 +411,9 @@ class Grid extends React.Component {
} }
renderHeaderCell(column) { renderHeaderCell(column) {
const { visibleColumns, sort, sortDirection } = this.state const { sort, sortDirection } = this.state
if (visibleColumns.includes(column.field)) { if (column.visible) {
if (column.sort) { if (column.sort) {
return ( return (
<TableCell key={column.field}> <TableCell key={column.field}>
...@@ -381,9 +435,9 @@ class Grid extends React.Component { ...@@ -381,9 +435,9 @@ class Grid extends React.Component {
} }
renderFilterCell(column) { renderFilterCell(column) {
const { visibleColumns, filters } = this.state const { filters } = this.state
if (visibleColumns.includes(column.field)) { if (column.visible) {
let filter = filters[column.field] || '' let filter = filters[column.field] || ''
let filterChange = filter => { let filterChange = filter => {
this.handleFilterChange(column.field, filter) this.handleFilterChange(column.field, filter)
...@@ -399,9 +453,7 @@ class Grid extends React.Component { ...@@ -399,9 +453,7 @@ class Grid extends React.Component {
} }
renderRowCell(column, row) { renderRowCell(column, row) {
const { visibleColumns } = this.state if (column.visible) {
if (visibleColumns.includes(column.field)) {
let rendered = column.render(row) let rendered = column.render(row)
return ( return (
<TableCell key={column.field}> <TableCell key={column.field}>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment