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'
import IconButton from '@material-ui/core/IconButton'
import SettingsIcon from '@material-ui/icons/Settings'
import Popover from '@material-ui/core/Popover'
import FormControlLabel from '@material-ui/core/FormControlLabel'
import Checkbox from '@material-ui/core/Checkbox'
import ColumnConfigRow from './ColumnConfigRow.jsx'
import logger from '../../../common/logger.js'
const styles = () => ({
......@@ -28,7 +27,6 @@ class ColumnConfig extends React.Component {
}
this.handleOpen = this.handleOpen.bind(this)
this.handleClose = this.handleClose.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleOpen(event) {
......@@ -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() {
logger.log(logger.DEBUG, 'ColumnConfig.render')
const { classes, allColumns, visibleColumns } = this.props
const { classes, columns, onVisibleChange, onOrderChange } = this.props
const { el } = this.state
return (
......@@ -81,17 +66,12 @@ class ColumnConfig extends React.Component {
}}
>
<ol className={classes.columns}>
{allColumns.map(column => (
{columns.map(column => (
<li key={column.field}>
<FormControlLabel
control={
<Checkbox
value={column.field}
checked={visibleColumns.includes(column.field)}
onChange={this.handleChange}
/>
}
label={column.label || column.field}
<ColumnConfigRow
column={column}
onVisibleChange={onVisibleChange}
onOrderChange={onOrderChange}
/>
</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 {
const sortDefault = _.isFunction(props.data) ? false : true
this.columnsArray = props.columns.map(column => ({
let columns = props.columns.map(column => ({
...column,
label: column.label || _.upperFirst(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 = {
loaded: false,
filters: this.props.filters || {},
page: 0,
pageSize: 10,
visibleColumns: Object.keys(this.columnsMap),
columns: columns,
columnConfigEl: null
}
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.handlePageSizeChange = this.handlePageSizeChange.bind(this)
}
......@@ -140,8 +141,26 @@ class Grid extends React.Component {
if (gridSettings) {
let settings = JSON.parse(gridSettings.value)
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(() => ({
...settings
...settings,
columns: newColumns
}))
}
}
......@@ -150,11 +169,16 @@ class Grid extends React.Component {
}
saveSettings() {
let columns = this.state.columns.map(column => ({
field: column.field,
visible: column.visible
}))
let settings = {
pageSize: this.state.pageSize,
sort: this.state.sort,
sortDirection: this.state.sortDirection,
visibleColumns: this.state.visibleColumns
columns
}
let gridSettings = new dto.WebAppSettingCreation()
......@@ -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(
() => ({
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()
......@@ -254,9 +310,9 @@ class Grid extends React.Component {
return _.filter(objects, row => {
let matchesAll = true
this.state.visibleColumns.forEach(visibleColumn => {
let value = _.get(row, visibleColumn)
let filter = this.state.filters[visibleColumn]
this.state.columns.forEach(column => {
let value = _.get(row, column.field)
let filter = this.state.filters[column.field]
matchesAll = matchesAll && matches(value, filter)
})
return matchesAll
......@@ -267,9 +323,9 @@ class Grid extends React.Component {
const { sort, sortDirection } = this.state
if (sort) {
let column = _.find(this.state.columns, ['field', sort])
return objects.sort((t1, t2) => {
let sign = sortDirection === 'asc' ? 1 : -1
let column = this.columnsMap[sort]
let v1 = _.get(t1, column.field) || ''
let v2 = _.get(t2, column.field) || ''
return sign * v1.localeCompare(v2)
......@@ -295,7 +351,7 @@ class Grid extends React.Component {
}
const { classes } = this.props
const { page, pageSize, visibleColumns } = this.state
const { page, pageSize, columns } = this.state
let pagedObjects = null
let totalCount = null
......@@ -316,19 +372,17 @@ class Grid extends React.Component {
<Table classes={{ root: classes.table }}>
<TableHead classes={{ root: classes.tableHeader }}>
<TableRow>
{this.columnsArray.map(column => this.renderFilterCell(column))}
{columns.map(column => this.renderFilterCell(column))}
</TableRow>
<TableRow>
{this.columnsArray.map(column => this.renderHeaderCell(column))}
{columns.map(column => this.renderHeaderCell(column))}
</TableRow>
</TableHead>
<TableBody>
{pagedObjects.map(row => {
return (
<TableRow key={row.id} hover>
{this.columnsArray.map(column =>
this.renderRowCell(column, row)
)}
{columns.map(column => this.renderRowCell(column, row))}
</TableRow>
)
})}
......@@ -347,9 +401,9 @@ class Grid extends React.Component {
onPageSizeChange={this.handlePageSizeChange}
/>
<ColumnConfig
allColumns={this.columnsArray}
visibleColumns={visibleColumns}
onColumnsChange={this.handleColumnsChange}
columns={columns}
onVisibleChange={this.handleColumnVisibleChange}
onOrderChange={this.handleColumnOrderChange}
/>
</div>
</div>
......@@ -357,9 +411,9 @@ class Grid extends React.Component {
}
renderHeaderCell(column) {
const { visibleColumns, sort, sortDirection } = this.state
const { sort, sortDirection } = this.state
if (visibleColumns.includes(column.field)) {
if (column.visible) {
if (column.sort) {
return (
<TableCell key={column.field}>
......@@ -381,9 +435,9 @@ class Grid extends React.Component {
}
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 filterChange = filter => {
this.handleFilterChange(column.field, filter)
......@@ -399,9 +453,7 @@ class Grid extends React.Component {
}
renderRowCell(column, row) {
const { visibleColumns } = this.state
if (visibleColumns.includes(column.field)) {
if (column.visible) {
let rendered = column.render(row)
return (
<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