Skip to content

Commit

Permalink
UI: Sorting for Trials information table (kubeflow#1251)
Browse files Browse the repository at this point in the history
* Enable sort in Trials table

* Remove console log

* Modify cell width
  • Loading branch information
andreyvelich authored and sperlingxx committed Jul 7, 2020
1 parent 6c74c52 commit 45b597e
Showing 1 changed file with 94 additions and 34 deletions.
128 changes: 94 additions & 34 deletions pkg/ui/v1beta1/frontend/src/components/HP/Monitor/HPJobTable.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React from 'react';
import { connect } from 'react-redux';

import { withStyles } from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';
import TableSortLabel from '@material-ui/core/TableSortLabel';

import { connect } from 'react-redux';
import { fetchHPJobTrialInfo } from '../../../actions/hpMonitorActions';

import { HP_MONITOR_MODULE } from '../../../constants/constants';

const styles = theme => ({
Expand All @@ -21,10 +22,11 @@ const styles = theme => ({
table: {
minWidth: 700,
},
hover: {
trialName: {
'&:hover': {
cursor: 'pointer',
},
width: 300,
},
created: {
color: theme.colors.created,
Expand All @@ -44,48 +46,82 @@ const styles = theme => ({
});

class HPJobTable extends React.Component {
fetchAndOpenDialogTrial = trialName => event => {
fetchAndOpenDialogTrial = trialName => () => {
this.props.fetchHPJobTrialInfo(trialName, this.props.namespace);
};

constructor(props) {
super(props);
this.state = { orderByIdx: 1, order: 'asc' };
}

onChangeSortHeaderIndex = headerIndex => () => {
if (headerIndex !== undefined) {
const isAsc = this.state.orderByIdx === headerIndex && this.state.order === 'asc';
this.setState(isAsc ? { order: 'desc' } : { order: 'asc' });
this.setState({ orderByIdx: headerIndex });
}
};

descendingComparator = (a, b) => {
if (b[this.state.orderByIdx] < a[this.state.orderByIdx]) {
return -1;
}
if (b[this.state.orderByIdx] > a[this.state.orderByIdx]) {
return 1;
}
return 0;
};

getComparator = () => {
return this.state.order === 'desc'
? (a, b) => this.descendingComparator(a, b)
: (a, b) => -this.descendingComparator(a, b);
};

stableSort = (data, comparator) => {
const stabilizedData = data.map((el, index) => [el, index]);
stabilizedData.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) return order;
return a[1] - b[1];
});
return stabilizedData.map(el => el[0]);
};

render() {
const { classes } = this.props;

let header = [];
let data = [];
if (this.props.jobData && this.props.jobData.length > 1) {
header = this.props.jobData[0];
// TODO: Add sorting by each table column
// Sort jobData by Trial Status
data = this.props.jobData.slice(1).sort(function(a, b) {
if (a[1] < b[1]) {
return -1;
}
if (a[1] > b[1]) {
return 1;
}
return 0;
});
}
return (
<Paper className={classes.root}>
{this.props.jobData.length > 1 && (
<Table className={classes.table}>
<TableHead>
<TableRow>
{header.map(header => (
<TableCell>{header}</TableCell>
{this.props.headers.map((header, idx) => (
<TableCell
sortDirection={this.state.orderByIdx === idx ? this.state.order : false}
key={idx}
>
<TableSortLabel
active={this.state.orderByIdx === idx}
direction={this.state.orderByIdx === idx ? this.state.order : 'asc'}
onClick={this.onChangeSortHeaderIndex(idx)}
>
{header}
</TableSortLabel>
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{data.map((row, id) => (
<TableRow key={id}>
{this.stableSort(this.props.data, this.getComparator()).map((row, idx) => (
<TableRow key={idx}>
{row.map((element, index) => {
if (index === 0 && row[1] === 'Succeeded') {
return (
<TableCell
className={classes.hover}
className={classes.trialName}
component="th"
scope="row"
onClick={this.fetchAndOpenDialogTrial(element)}
Expand All @@ -96,18 +132,38 @@ class HPJobTable extends React.Component {
);
} else if (index === 1) {
if (element === 'Created') {
return <TableCell className={classes.created}>{element}</TableCell>;
return (
<TableCell className={classes.created} key={index}>
{element}
</TableCell>
);
} else if (element === 'Running') {
return <TableCell className={classes.running}>{element}</TableCell>;
return (
<TableCell className={classes.running} key={index}>
{element}
</TableCell>
);
} else if (element === 'Succeeded') {
return <TableCell className={classes.succeeded}>{element}</TableCell>;
return (
<TableCell className={classes.succeeded} key={index}>
{element}
</TableCell>
);
} else if (element === 'Killed') {
return <TableCell className={classes.killed}>{element}</TableCell>;
return (
<TableCell className={classes.killed} key={index}>
{element}
</TableCell>
);
} else if (element === 'Failed') {
return <TableCell className={classes.failed}>{element}</TableCell>;
return (
<TableCell className={classes.failed} key={index}>
{element}
</TableCell>
);
}
}
return <TableCell>{element}</TableCell>;
return <TableCell key={index}>{element}</TableCell>;
})}
</TableRow>
))}
Expand All @@ -119,8 +175,12 @@ class HPJobTable extends React.Component {
}
}

const mapStateToProps = state => ({
jobData: state[HP_MONITOR_MODULE].jobData,
});
const mapStateToProps = state => {
return {
jobData: state[HP_MONITOR_MODULE].jobData,
headers: state[HP_MONITOR_MODULE].jobData[0],
data: state[HP_MONITOR_MODULE].jobData.slice(1),
};
};

export default connect(mapStateToProps, { fetchHPJobTrialInfo })(withStyles(styles)(HPJobTable));

0 comments on commit 45b597e

Please sign in to comment.