Unverified Commit de7b2685 authored by Lijiaoa's avatar Lijiaoa Committed by GitHub
Browse files

Support show trial details by clicking the point in trial results graph (#3352)


Co-authored-by: default avatarLijiao <Lijiaoa@outlook.com>
parent a9dcc006
...@@ -25,6 +25,7 @@ interface AppState { ...@@ -25,6 +25,7 @@ interface AppState {
expWarningMessage: string; expWarningMessage: string;
bestTrialEntries: string; // for overview page: best trial entreis bestTrialEntries: string; // for overview page: best trial entreis
isUpdate: boolean; isUpdate: boolean;
expandRowIDs: Set<string>;
} }
export const AppContext = React.createContext({ export const AppContext = React.createContext({
...@@ -35,6 +36,7 @@ export const AppContext = React.createContext({ ...@@ -35,6 +36,7 @@ export const AppContext = React.createContext({
metricGraphMode: 'max', metricGraphMode: 'max',
bestTrialEntries: '10', bestTrialEntries: '10',
maxDurationUnit: 'm', maxDurationUnit: 'm',
expandRowIDs: new Set(['']),
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
changeColumn: (_val: string[]): void => {}, changeColumn: (_val: string[]): void => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
...@@ -44,7 +46,9 @@ export const AppContext = React.createContext({ ...@@ -44,7 +46,9 @@ export const AppContext = React.createContext({
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
changeEntries: (_val: string): void => {}, changeEntries: (_val: string): void => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
updateOverviewPage: () => {} updateOverviewPage: () => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function
changeExpandRowIDs: (_val: string, _type?: string): void => {}
}); });
class App extends React.Component<{}, AppState> { class App extends React.Component<{}, AppState> {
...@@ -62,7 +66,8 @@ class App extends React.Component<{}, AppState> { ...@@ -62,7 +66,8 @@ class App extends React.Component<{}, AppState> {
isillegalFinal: false, isillegalFinal: false,
expWarningMessage: '', expWarningMessage: '',
bestTrialEntries: '10', bestTrialEntries: '10',
isUpdate: true isUpdate: true,
expandRowIDs: new Set()
}; };
} }
...@@ -94,6 +99,20 @@ class App extends React.Component<{}, AppState> { ...@@ -94,6 +99,20 @@ class App extends React.Component<{}, AppState> {
this.setState({ columnList: columnList }); this.setState({ columnList: columnList });
}; };
changeExpandRowIDs = (id: string, type?: string): void => {
const currentExpandRowIDs = this.state.expandRowIDs;
if (!currentExpandRowIDs.has(id)) {
currentExpandRowIDs.add(id);
} else {
if (!(type !== undefined && type === 'chart')) {
currentExpandRowIDs.delete(id);
}
}
this.setState({ expandRowIDs: currentExpandRowIDs });
};
changeMetricGraphMode = (val: 'max' | 'min'): void => { changeMetricGraphMode = (val: 'max' | 'min'): void => {
this.setState({ metricGraphMode: val }); this.setState({ metricGraphMode: val });
}; };
...@@ -132,7 +151,8 @@ class App extends React.Component<{}, AppState> { ...@@ -132,7 +151,8 @@ class App extends React.Component<{}, AppState> {
isillegalFinal, isillegalFinal,
expWarningMessage, expWarningMessage,
bestTrialEntries, bestTrialEntries,
maxDurationUnit maxDurationUnit,
expandRowIDs
} = this.state; } = this.state;
if (experimentUpdateBroadcast === 0 || trialsUpdateBroadcast === 0) { if (experimentUpdateBroadcast === 0 || trialsUpdateBroadcast === 0) {
return null; // TODO: render a loading page return null; // TODO: render a loading page
...@@ -186,7 +206,9 @@ class App extends React.Component<{}, AppState> { ...@@ -186,7 +206,9 @@ class App extends React.Component<{}, AppState> {
changeMetricGraphMode: this.changeMetricGraphMode, changeMetricGraphMode: this.changeMetricGraphMode,
bestTrialEntries, bestTrialEntries,
changeEntries: this.changeEntries, changeEntries: this.changeEntries,
updateOverviewPage: this.updateOverviewPage updateOverviewPage: this.updateOverviewPage,
expandRowIDs,
changeExpandRowIDs: this.changeExpandRowIDs
}} }}
> >
{this.props.children} {this.props.children}
......
...@@ -70,8 +70,10 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -70,8 +70,10 @@ class Overview extends React.Component<{}, OverviewState> {
metricGraphMode, metricGraphMode,
bestTrialEntries, bestTrialEntries,
maxDurationUnit, maxDurationUnit,
expandRowIDs,
updateOverviewPage, updateOverviewPage,
changeMaxDurationUnit changeMaxDurationUnit,
changeExpandRowIDs
} = value; } = value;
const maxActive = metricGraphMode === 'max' ? 'active' : ''; const maxActive = metricGraphMode === 'max' ? 'active' : '';
const minActive = metricGraphMode === 'min' ? 'active' : ''; const minActive = metricGraphMode === 'min' ? 'active' : '';
...@@ -169,10 +171,13 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -169,10 +171,13 @@ class Overview extends React.Component<{}, OverviewState> {
trialIds={bestTrials.map(trial => trial.info.trialJobId)} trialIds={bestTrials.map(trial => trial.info.trialJobId)}
chartHeight={300} chartHeight={300}
hasBestCurve={false} hasBestCurve={false}
changeExpandRowIDs={changeExpandRowIDs}
/> />
<SuccessTable <SuccessTable
trialIds={bestTrials.map(trial => trial.info.trialJobId)} trialIds={bestTrials.map(trial => trial.info.trialJobId)}
updateOverviewPage={updateOverviewPage} updateOverviewPage={updateOverviewPage}
expandRowIDs={expandRowIDs}
changeExpandRowIDs={changeExpandRowIDs}
/> />
</div> </div>
</div> </div>
...@@ -198,40 +203,6 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -198,40 +203,6 @@ class Overview extends React.Component<{}, OverviewState> {
} }
return bestTrials; return bestTrials;
} }
private generateAccuracyGraph(bestTrials: Trial[]): object {
const xSequence = bestTrials.map(trial => trial.sequenceId);
const ySequence = bestTrials.map(trial => trial.accuracy);
return {
// support max show 0.0000000
grid: {
x: 60,
y: 40
},
tooltip: {
trigger: 'item'
},
xAxis: {
name: 'Trial',
type: 'category',
data: xSequence
},
yAxis: {
name: 'Default metric',
type: 'value',
scale: true,
data: ySequence
},
series: [
{
symbolSize: 6,
type: 'scatter',
data: ySequence
}
]
};
}
} }
export default Overview; export default Overview;
...@@ -52,7 +52,12 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> { ...@@ -52,7 +52,12 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
{/* <PivotItem tab={this.titleOfacc} key="1"> doesn't work*/} {/* <PivotItem tab={this.titleOfacc} key="1"> doesn't work*/}
<PivotItem headerText='Default metric' itemIcon='HomeGroup' key='Default metric'> <PivotItem headerText='Default metric' itemIcon='HomeGroup' key='Default metric'>
<Stack className='graph'> <Stack className='graph'>
<DefaultPoint trialIds={trialIds} hasBestCurve={true} chartHeight={402} /> <DefaultPoint
trialIds={trialIds}
hasBestCurve={true}
chartHeight={402}
changeExpandRowIDs={_value.changeExpandRowIDs}
/>
</Stack> </Stack>
</PivotItem> </PivotItem>
{/* <PivotItem tab={this.titleOfhyper} key="2"> */} {/* <PivotItem tab={this.titleOfhyper} key="2"> */}
......
...@@ -24,14 +24,14 @@ import '../../../static/style/openRow.scss'; ...@@ -24,14 +24,14 @@ import '../../../static/style/openRow.scss';
interface SuccessTableProps { interface SuccessTableProps {
trialIds: string[]; trialIds: string[];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
updateOverviewPage: () => void; updateOverviewPage: () => void;
expandRowIDs: Set<string>;
changeExpandRowIDs: Function;
} }
interface SuccessTableState { interface SuccessTableState {
columns: IColumn[]; columns: IColumn[];
source: Array<any>; source: Array<any>;
expandRowIdList: Set<string>;
sortInfo: SortInfo; sortInfo: SortInfo;
} }
...@@ -41,8 +41,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> ...@@ -41,8 +41,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
this.state = { this.state = {
columns: this.columns, columns: this.columns,
source: TRIALS.table(this.props.trialIds), source: TRIALS.table(this.props.trialIds),
sortInfo: { field: '', isDescend: false }, sortInfo: { field: '', isDescend: false }
expandRowIdList: new Set() // store expanded row's trial id
}; };
} }
...@@ -57,6 +56,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> ...@@ -57,6 +56,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
const { columns, source, sortInfo } = this.state; const { columns, source, sortInfo } = this.state;
const keepSortedSource = copyAndSort(source, sortInfo.field, sortInfo.isDescend); const keepSortedSource = copyAndSort(source, sortInfo.field, sortInfo.isDescend);
const isNoneData = source.length === 0 ? true : false; const isNoneData = source.length === 0 ? true : false;
return ( return (
<div id='succTable'> <div id='succTable'>
<ScrollablePane className='scrollPanel' scrollbarVisibility={ScrollbarVisibility.auto}> <ScrollablePane className='scrollPanel' scrollbarVisibility={ScrollbarVisibility.auto}>
...@@ -117,7 +117,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> ...@@ -117,7 +117,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
styles={{ styles={{
root: { root: {
transition: 'all 0.2s', transition: 'all 0.2s',
transform: `rotate(${this.state.expandRowIdList.has(item.id) ? 90 : 0}deg)` transform: `rotate(${this.props.expandRowIDs.has(item.id) ? 90 : 0}deg)`
} }
}} }}
className='cursor' className='cursor'
...@@ -206,14 +206,14 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> ...@@ -206,14 +206,14 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
}; };
private onRenderRow: IDetailsListProps['onRenderRow'] = props => { private onRenderRow: IDetailsListProps['onRenderRow'] = props => {
const { expandRowIdList } = this.state; const { expandRowIDs } = this.props;
if (props) { if (props) {
return ( return (
<div> <div>
<div> <div>
<DetailsRow {...props} /> <DetailsRow {...props} />
</div> </div>
{Array.from(expandRowIdList).map( {Array.from(expandRowIDs).map(
item => item === props.item.id && <OpenRow key={item} trialId={item} /> item => item === props.item.id && <OpenRow key={item} trialId={item} />
)} )}
</div> </div>
...@@ -223,15 +223,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> ...@@ -223,15 +223,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
}; };
private expandTrialId = (_event: any, id: string): void => { private expandTrialId = (_event: any, id: string): void => {
const { expandRowIdList } = this.state; const { updateOverviewPage, changeExpandRowIDs } = this.props;
const { updateOverviewPage } = this.props; changeExpandRowIDs(id);
const copyExpandList = expandRowIdList;
if (copyExpandList.has(id)) {
copyExpandList.delete(id);
} else {
copyExpandList.add(id);
}
this.setState(() => ({ expandRowIdList: copyExpandList }));
updateOverviewPage(); updateOverviewPage();
}; };
} }
......
...@@ -26,6 +26,7 @@ interface DefaultPointProps { ...@@ -26,6 +26,7 @@ interface DefaultPointProps {
trialIds: string[]; trialIds: string[];
chartHeight: number; chartHeight: number;
hasBestCurve: boolean; hasBestCurve: boolean;
changeExpandRowIDs: Function;
} }
interface DefaultPointState { interface DefaultPointState {
...@@ -57,7 +58,13 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> ...@@ -57,7 +58,13 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
} }
}; };
generateGraphConfig(maxSequenceId: number): any { pointClick = (params: any): void => {
if (window.location.pathname === '/oview') {
this.props.changeExpandRowIDs(params.data[2], 'chart');
}
};
generateGraphConfig(_maxSequenceId: number): any {
const { startY, endY } = this.state; const { startY, endY } = this.state;
return { return {
grid: { grid: {
...@@ -67,10 +74,6 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> ...@@ -67,10 +74,6 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
trigger: 'item', trigger: 'item',
enterable: true, enterable: true,
confine: true, // confirm always show tooltip box rather than hidden by background confine: true, // confirm always show tooltip box rather than hidden by background
position: (point: number[], data: TooltipForAccuracy): number[] => [
data.data[0] < maxSequenceId ? point[0] : point[0] - 300,
80
],
formatter: (data: TooltipForAccuracy): React.ReactNode => { formatter: (data: TooltipForAccuracy): React.ReactNode => {
return ( return (
'<div class="tooldetailAccuracy">' + '<div class="tooldetailAccuracy">' +
...@@ -150,7 +153,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> ...@@ -150,7 +153,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
const { hasBestCurve, chartHeight } = this.props; const { hasBestCurve, chartHeight } = this.props;
const graph = this.generateGraph(); const graph = this.generateGraph();
const accNodata = graph === EmptyGraph ? 'No data' : ''; const accNodata = graph === EmptyGraph ? 'No data' : '';
const onEvents = { dataZoom: this.metricDataZoom }; const onEvents = { dataZoom: this.metricDataZoom, click: this.pointClick };
return ( return (
<div> <div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment