Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
c55300df
Unverified
Commit
c55300df
authored
Nov 24, 2020
by
Lijiaoa
Committed by
GitHub
Nov 24, 2020
Browse files
[webui] Add Expanded icon for table (#3103)
parent
e9c62bac
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
153 additions
and
149 deletions
+153
-149
ts/webui/src/App.tsx
ts/webui/src/App.tsx
+1
-0
ts/webui/src/components/Overview.tsx
ts/webui/src/components/Overview.tsx
+4
-1
ts/webui/src/components/overview/count/EditExperimentParam.tsx
...bui/src/components/overview/count/EditExperimentParam.tsx
+3
-3
ts/webui/src/components/overview/table/Details.tsx
ts/webui/src/components/overview/table/Details.tsx
+0
-37
ts/webui/src/components/overview/table/SuccessTable.tsx
ts/webui/src/components/overview/table/SuccessTable.tsx
+102
-64
ts/webui/src/components/trial-detail/TableList.tsx
ts/webui/src/components/trial-detail/TableList.tsx
+4
-33
ts/webui/src/static/function.ts
ts/webui/src/static/function.ts
+26
-1
ts/webui/src/static/interface.ts
ts/webui/src/static/interface.ts
+8
-1
ts/webui/src/static/style/common.scss
ts/webui/src/static/style/common.scss
+5
-0
ts/webui/src/static/style/overview/count.scss
ts/webui/src/static/style/overview/count.scss
+0
-4
ts/webui/src/static/style/progress/progress.scss
ts/webui/src/static/style/progress/progress.scss
+0
-5
No files found.
ts/webui/src/App.tsx
View file @
c55300df
...
...
@@ -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
;
...
...
ts/webui/src/components/Overview.tsx
View file @
c55300df
...
...
@@ -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
/>
...
...
ts/webui/src/components/overview/count/EditExperimentParam.tsx
View file @
c55300df
...
...
@@ -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
>
...
...
ts/webui/src/components/overview/table/Details.tsx
deleted
100644 → 0
View file @
e9c62bac
import
*
as
React
from
'
react
'
;
import
{
DetailsRow
,
IDetailsRowBaseProps
}
from
'
@fluentui/react
'
;
import
OpenRow
from
'
../../public-child/OpenRow
'
;
interface
DetailsProps
{
detailsProps
:
IDetailsRowBaseProps
;
}
interface
DetailsState
{
isExpand
:
boolean
;
}
class
Details
extends
React
.
Component
<
DetailsProps
,
DetailsState
>
{
constructor
(
props
:
DetailsProps
)
{
super
(
props
);
this
.
state
=
{
isExpand
:
false
};
}
render
():
React
.
ReactNode
{
const
{
detailsProps
}
=
this
.
props
;
const
{
isExpand
}
=
this
.
state
;
return
(
<
div
>
<
div
onClick
=
{
():
void
=>
{
this
.
setState
(()
=>
({
isExpand
:
!
isExpand
}));
}
}
>
<
DetailsRow
{
...
detailsProps
}
/>
</
div
>
{
isExpand
&&
<
OpenRow
trialId
=
{
detailsProps
.
item
.
id
}
/>
}
</
div
>
);
}
}
export
default
Details
;
ts/webui/src/components/overview/table/SuccessTable.tsx
View file @
c55300df
...
...
@@ -3,6 +3,8 @@ import {
DetailsList
,
IDetailsListProps
,
IColumn
,
Icon
,
DetailsRow
,
IRenderFunction
,
IDetailsHeaderProps
,
Sticky
,
...
...
@@ -11,9 +13,10 @@ 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
'
;
...
...
@@ -21,12 +24,15 @@ 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
>
{
...
...
@@ -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
];
...
...
@@ -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
:
6
5
,
maxWidth
:
1
19
,
minWidth
:
6
0
,
maxWidth
:
1
00
,
isResizable
:
true
,
data
:
'
number
'
,
onColumnClick
:
this
.
onColumnClick
,
...
...
@@ -95,8 +144,8 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
name
:
'
ID
'
,
key
:
'
id
'
,
fieldName
:
'
id
'
,
minWidth
:
6
5
,
maxWidth
:
11
9
,
minWidth
:
6
0
,
maxWidth
:
11
8
,
isResizable
:
true
,
className
:
'
tableHead leftTitle
'
,
data
:
'
string
'
,
...
...
@@ -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
'
,
...
...
@@ -121,7 +170,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
{
name
:
'
Status
'
,
key
:
'
status
'
,
minWidth
:
10
8
,
minWidth
:
9
8
,
maxWidth
:
160
,
isResizable
:
true
,
fieldName
:
'
status
'
,
...
...
@@ -133,7 +182,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
name
:
'
Default metric
'
,
key
:
'
accuracy
'
,
fieldName
:
'
accuracy
'
,
minWidth
:
10
8
,
minWidth
:
10
0
,
maxWidth
:
166
,
isResizable
:
true
,
data
:
'
number
'
,
...
...
@@ -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
;
}
...
...
@@ -156,46 +205,35 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
);
};
setInnerWidth
=
():
void
=>
{
this
.
setState
(()
=>
({
innerWidth
:
window
.
innerWidth
}));
};
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
)
}));
}
}
render
():
React
.
ReactNode
{
const
{
columns
,
source
}
=
this
.
state
;
const
isNoneData
=
source
.
length
===
0
?
true
:
false
;
private
onRenderRow
:
IDetailsListProps
[
'
onRenderRow
'
]
=
props
=>
{
const
{
expandRowIdList
}
=
this
.
state
;
if
(
props
)
{
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
>
<
div
>
<
DetailsRow
{
...
props
}
/>
</
div
>
{
Array
.
from
(
expandRowIdList
).
map
(
item
=>
item
===
props
.
item
.
id
&&
<
OpenRow
key
=
{
item
}
trialId
=
{
item
}
/>
)
}
</
div
>
);
}
return
null
;
};
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
);
}
this
.
setState
(()
=>
({
expandRowIdList
:
copyExpandList
}));
updateOverviewPage
();
};
}
export
default
SuccessTable
;
ts/webui/src/components/trial-detail/TableList.tsx
View file @
c55300df
...
...
@@ -15,8 +15,8 @@ import {
import
React
from
'
react
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
TOOLTIP_BACKGROUND_COLOR
}
from
'
../../static/const
'
;
import
{
convertDuration
,
formatTimestamp
}
from
'
../../static/function
'
;
import
{
TableObj
}
from
'
../../static/interface
'
;
import
{
convertDuration
,
formatTimestamp
,
copyAndSort
}
from
'
../../static/function
'
;
import
{
TableObj
,
SortInfo
}
from
'
../../static/interface
'
;
import
'
../../static/style/search.scss
'
;
import
'
../../static/style/tableStatus.css
'
;
import
'
../../static/style/logPath.scss
'
;
...
...
@@ -56,36 +56,6 @@ const searchOptionLiterals = {
const
defaultDisplayedColumns
=
[
'
sequenceId
'
,
'
id
'
,
'
duration
'
,
'
status
'
,
'
latestAccuracy
'
];
interface
SortInfo
{
field
:
string
;
isDescend
?:
boolean
;
}
function
_copyAndSort
<
T
>
(
items
:
T
[],
columnKey
:
string
,
isSortedDescending
?:
boolean
):
any
{
const
key
=
columnKey
as
keyof
T
;
return
items
.
slice
(
0
).
sort
(
function
(
a
:
T
,
b
:
T
):
any
{
if
(
a
[
key
]
===
undefined
||
Object
.
is
(
a
[
key
],
NaN
)
||
Object
.
is
(
a
[
key
],
Infinity
)
||
Object
.
is
(
a
[
key
],
-
Infinity
)
||
typeof
a
[
key
]
===
'
object
'
)
{
return
1
;
}
if
(
b
[
key
]
===
undefined
||
Object
.
is
(
b
[
key
],
NaN
)
||
Object
.
is
(
b
[
key
],
Infinity
)
||
Object
.
is
(
b
[
key
],
-
Infinity
)
||
typeof
b
[
key
]
===
'
object
'
)
{
return
-
1
;
}
return
(
isSortedDescending
?
a
[
key
]
<
b
[
key
]
:
a
[
key
]
>
b
[
key
])
?
1
:
-
1
;
});
}
function
_inferColumnTitle
(
columnKey
:
string
):
string
{
if
(
columnKey
===
'
sequenceId
'
)
{
return
'
Trial No.
'
;
...
...
@@ -238,7 +208,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
const
{
sortInfo
}
=
this
.
state
;
if
(
sortInfo
.
field
!==
''
)
{
return
_
copyAndSort
(
items
,
sortInfo
.
field
,
sortInfo
.
isDescend
);
return
copyAndSort
(
items
,
sortInfo
.
field
,
sortInfo
.
isDescend
);
}
else
{
return
items
;
}
...
...
@@ -255,6 +225,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
<
Icon
aria
-
hidden
=
{
true
}
iconName
=
'ChevronRight'
className
=
'cursor'
styles
=
{
{
root
:
{
transition
:
'
all 0.2s
'
,
...
...
ts/webui/src/static/function.ts
View file @
c55300df
...
...
@@ -269,6 +269,30 @@ function caclMonacoEditorHeight(height): number {
return
height
-
178
;
}
function
copyAndSort
<
T
>
(
items
:
T
[],
columnKey
:
string
,
isSortedDescending
?:
boolean
):
any
{
const
key
=
columnKey
as
keyof
T
;
return
items
.
slice
(
0
).
sort
(
function
(
a
:
T
,
b
:
T
):
any
{
if
(
a
[
key
]
===
undefined
||
Object
.
is
(
a
[
key
],
NaN
)
||
Object
.
is
(
a
[
key
],
Infinity
)
||
Object
.
is
(
a
[
key
],
-
Infinity
)
||
typeof
a
[
key
]
===
'
object
'
)
{
return
1
;
}
if
(
b
[
key
]
===
undefined
||
Object
.
is
(
b
[
key
],
NaN
)
||
Object
.
is
(
b
[
key
],
Infinity
)
||
Object
.
is
(
b
[
key
],
-
Infinity
)
||
typeof
b
[
key
]
===
'
object
'
)
{
return
-
1
;
}
return
(
isSortedDescending
?
a
[
key
]
<
b
[
key
]
:
a
[
key
]
>
b
[
key
])
?
1
:
-
1
;
});
}
export
{
convertTime
,
convertDuration
,
...
...
@@ -288,5 +312,6 @@ export {
requestAxios
,
isNaNorInfinity
,
formatComplexTypeValue
,
caclMonacoEditorHeight
caclMonacoEditorHeight
,
copyAndSort
};
ts/webui/src/static/interface.ts
View file @
c55300df
...
...
@@ -212,6 +212,12 @@ interface EventMap {
[
key
:
string
]:
()
=>
void
;
}
// table column sort
interface
SortInfo
{
field
:
string
;
isDescend
?:
boolean
;
}
export
{
TableObj
,
TableRecord
,
...
...
@@ -233,5 +239,6 @@ export {
NNIManagerStatus
,
EventMap
,
SingleAxis
,
MultipleAxes
MultipleAxes
,
SortInfo
};
ts/webui/src/static/style/common.scss
0 → 100644
View file @
c55300df
.cursor
{
&
:hover
,
&
i
:hover
{
cursor
:
pointer
;
}
}
\ No newline at end of file
ts/webui/src/static/style/overview/count.scss
View file @
c55300df
...
...
@@ -3,10 +3,6 @@ $seriesIconMargin: 10px;
.ExpDuration
{
margin-top
:
20px
;
span
:hover
{
cursor
:
pointer
;
}
.maxTrialNum
{
margin-bottom
:
10px
;
}
...
...
ts/webui/src/static/style/progress/progress.scss
View file @
c55300df
...
...
@@ -64,8 +64,3 @@
.ms-ProgressIndicator-itemProgress
{
padding
:
0
;
}
.cursor
,
.cursor
:hover
{
cursor
:
pointer
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment