Skip to content
This repository has been archived by the owner on Sep 18, 2024. It is now read-only.

Commit

Permalink
[webui] Add Expanded icon for table (#3103)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lijiaoa authored Nov 24, 2020
1 parent e9c62ba commit c55300d
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 150 deletions.
1 change: 1 addition & 0 deletions ts/webui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import NavCon from './components/NavCon';
import MessageInfo from './components/modals/MessageInfo';
import { SlideNavBtns } from './components/slideNav/SlideNavBtns';
import './App.scss';
import './static/style/common.scss';

interface AppState {
interval: number;
Expand Down
5 changes: 4 additions & 1 deletion ts/webui/src/components/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,11 @@ class Overview extends React.Component<{}, OverviewState> {
</Stack>
<div className='overviewChart'>
<Accuracy accuracyData={accuracyGraphData} accNodata={noDataMessage} />
<SuccessTable
trialIds={bestTrials.map(trial => trial.info.trialJobId)}
updateOverviewPage={updateOverviewPage}
/>
</div>
<SuccessTable trialIds={bestTrials.map(trial => trial.info.trialJobId)} />
</div>
<div className='overviewCommand1'>
<Command1 />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,16 @@ export const EditExperimentParam = (): any => {
/>
)}
{isShowPencil && (
<span className='edit' onClick={hidePencil}>
<span className='edit cursor' onClick={hidePencil}>
{Edit}
</span>
)}
{!isShowPencil && (
<span className='series'>
<span className='confirm' onClick={confirmEdit}>
<span className='confirm cursor' onClick={confirmEdit}>
{CheckMark}
</span>
<span className='cancel' onClick={cancelEdit}>
<span className='cancel cursor' onClick={cancelEdit}>
{Cancel}
</span>
</span>
Expand Down
37 changes: 0 additions & 37 deletions ts/webui/src/components/overview/table/Details.tsx

This file was deleted.

166 changes: 102 additions & 64 deletions ts/webui/src/components/overview/table/SuccessTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
DetailsList,
IDetailsListProps,
IColumn,
Icon,
DetailsRow,
IRenderFunction,
IDetailsHeaderProps,
Sticky,
Expand All @@ -11,22 +13,26 @@ import {
ScrollbarVisibility
} from '@fluentui/react';
import DefaultMetric from '../../public-child/DefaultMetric';
import Details from './Details';
import { convertDuration } from '../../../static/function';
import OpenRow from '../../public-child/OpenRow';
import { convertDuration, copyAndSort } from '../../../static/function';
import { TRIALS } from '../../../static/datamodel';
import { SortInfo } from '../../../static/interface';
import { DETAILTABS } from '../../stateless-component/NNItabs';
import '../../../static/style/succTable.scss';
import '../../../static/style/tableStatus.css';
import '../../../static/style/openRow.scss';

interface SuccessTableProps {
trialIds: string[];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
updateOverviewPage: () => void;
}

interface SuccessTableState {
columns: IColumn[];
source: Array<any>;
innerWidth: number;
expandRowIdList: Set<string>;
sortInfo: SortInfo;
}

class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> {
Expand All @@ -35,18 +41,42 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
this.state = {
columns: this.columns,
source: TRIALS.table(this.props.trialIds),
innerWidth: window.innerWidth
sortInfo: { field: '', isDescend: false },
expandRowIdList: new Set() // store expanded row's trial id
};
}

private onRenderRow: IDetailsListProps['onRenderRow'] = props => {
if (props) {
return <Details detailsProps={props} />;
componentDidUpdate(prevProps: SuccessTableProps): void {
if (this.props.trialIds !== prevProps.trialIds) {
const { trialIds } = this.props;
this.setState(() => ({ source: TRIALS.table(trialIds) }));
}
return null;
};
}

onColumnClick = (ev: React.MouseEvent<HTMLElement>, getColumn: IColumn): void => {
render(): React.ReactNode {
const { columns, source, sortInfo } = this.state;
const keepSortedSource = copyAndSort(source, sortInfo.field, sortInfo.isDescend);
const isNoneData = source.length === 0 ? true : false;
return (
<div id='succTable'>
<ScrollablePane className='scrollPanel' scrollbarVisibility={ScrollbarVisibility.auto}>
<DetailsList
columns={columns}
items={keepSortedSource}
setKey='set'
compact={true}
onRenderRow={this.onRenderRow}
onRenderDetailsHeader={this.onRenderDetailsHeader}
selectionMode={0} // close selector function
className='succTable'
/>
</ScrollablePane>
{isNoneData && <div className='succTable-tooltip'>{this.tooltipStr}</div>}
</div>
);
}

private onColumnClick = (_ev: React.MouseEvent<HTMLElement>, getColumn: IColumn): void => {
const { columns, source } = this.state;
const newColumns: IColumn[] = columns.slice();
const currColumn: IColumn = newColumns.filter(item => getColumn.key === item.key)[0];
Expand All @@ -60,32 +90,51 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
}
});
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const newItems = this.copyAndSort(source, currColumn.fieldName!, currColumn.isSortedDescending);
const newItems = copyAndSort(source, currColumn.fieldName!, currColumn.isSortedDescending);
this.setState({
columns: newColumns,
source: newItems
source: newItems,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
sortInfo: { field: currColumn.fieldName!, isDescend: currColumn.isSortedDescending }
});
};

private copyAndSort<T>(items: T[], columnKey: string, isSortedDescending?: boolean): T[] {
const key = columnKey as keyof T;
return items.slice(0).sort((a: T, b: T) => ((isSortedDescending ? a[key] < b[key] : a[key] > b[key]) ? 1 : -1));
}

tooltipStr = (
private tooltipStr = (
<React.Fragment>
The experiment is running, please wait for the final metric patiently. You could also find status of trial
job with <span>{DETAILTABS}</span> button.
</React.Fragment>
);

columns = [
private columns = [
{
key: '_expand',
name: '',
onRender: (item: any): any => (
<Icon
aria-hidden={true}
iconName='ChevronRight'
styles={{
root: {
transition: 'all 0.2s',
transform: `rotate(${this.state.expandRowIdList.has(item.id) ? 90 : 0}deg)`
}
}}
className='cursor'
onClick={this.expandTrialId.bind(this, Event, item.id)}
/>
),
fieldName: 'expand',
isResizable: false,
minWidth: 20,
maxWidth: 20
},
{
name: 'Trial No.',
key: 'sequenceId',
fieldName: 'sequenceId', // required!
minWidth: 65,
maxWidth: 119,
minWidth: 60,
maxWidth: 100,
isResizable: true,
data: 'number',
onColumnClick: this.onColumnClick,
Expand All @@ -95,8 +144,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
name: 'ID',
key: 'id',
fieldName: 'id',
minWidth: 65,
maxWidth: 119,
minWidth: 60,
maxWidth: 118,
isResizable: true,
className: 'tableHead leftTitle',
data: 'string',
Expand All @@ -106,7 +155,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
{
name: 'Duration',
key: 'duration',
minWidth: 90,
minWidth: 85,
maxWidth: 166,
isResizable: true,
fieldName: 'duration',
Expand All @@ -121,7 +170,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
{
name: 'Status',
key: 'status',
minWidth: 108,
minWidth: 98,
maxWidth: 160,
isResizable: true,
fieldName: 'status',
Expand All @@ -133,7 +182,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
name: 'Default metric',
key: 'accuracy',
fieldName: 'accuracy',
minWidth: 108,
minWidth: 100,
maxWidth: 166,
isResizable: true,
data: 'number',
Expand All @@ -142,7 +191,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
}
];

onRenderDetailsHeader: IRenderFunction<IDetailsHeaderProps> = (props, defaultRender) => {
private onRenderDetailsHeader: IRenderFunction<IDetailsHeaderProps> = (props, defaultRender) => {
if (!props) {
return null;
}
Expand All @@ -156,46 +205,35 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
);
};

setInnerWidth = (): void => {
this.setState(() => ({ innerWidth: window.innerWidth }));
private onRenderRow: IDetailsListProps['onRenderRow'] = props => {
const { expandRowIdList } = this.state;
if (props) {
return (
<div>
<div>
<DetailsRow {...props} />
</div>
{Array.from(expandRowIdList).map(
item => item === props.item.id && <OpenRow key={item} trialId={item} />
)}
</div>
);
}
return null;
};

componentDidMount(): void {
window.addEventListener('resize', this.setInnerWidth);
}
componentWillUnmount(): void {
window.removeEventListener('resize', this.setInnerWidth);
}

componentDidUpdate(prevProps: SuccessTableProps): void {
if (this.props.trialIds !== prevProps.trialIds) {
const { trialIds } = this.props;
this.setState(() => ({ source: TRIALS.table(trialIds) }));
private expandTrialId = (_event: any, id: string): void => {
const { expandRowIdList } = this.state;
const { updateOverviewPage } = this.props;
const copyExpandList = expandRowIdList;
if (copyExpandList.has(id)) {
copyExpandList.delete(id);
} else {
copyExpandList.add(id);
}
}

render(): React.ReactNode {
const { columns, source } = this.state;
const isNoneData = source.length === 0 ? true : false;

return (
<div id='succTable'>
<ScrollablePane className='scrollPanel' scrollbarVisibility={ScrollbarVisibility.auto}>
<DetailsList
columns={columns}
items={source}
setKey='set'
compact={true}
onRenderRow={this.onRenderRow}
onRenderDetailsHeader={this.onRenderDetailsHeader}
selectionMode={0} // close selector function
className='succTable'
/>
</ScrollablePane>
{isNoneData && <div className='succTable-tooltip'>{this.tooltipStr}</div>}
</div>
);
}
this.setState(() => ({ expandRowIdList: copyExpandList }));
updateOverviewPage();
};
}

export default SuccessTable;
Loading

0 comments on commit c55300d

Please sign in to comment.