Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
nomad-lab
nomad-FAIR
Commits
9ff15d7e
Commit
9ff15d7e
authored
Nov 04, 2019
by
Markus Scheidgen
Browse files
Use EntryList for Upload component.
parent
aa196e76
Pipeline
#62939
passed with stages
in 15 minutes and 50 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
gui/src/components/search/EntryList.js
View file @
9ff15d7e
...
...
@@ -11,12 +11,11 @@ import MoreIcon from '@material-ui/icons/MoreHoriz'
import
DownloadIcon
from
'
@material-ui/icons/CloudDownload
'
import
EditUserMetadataDialog
from
'
../EditUserMetadataDialog
'
class
EntryListUnstyled
extends
React
.
Component
{
export
class
EntryListUnstyled
extends
React
.
Component
{
static
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
data
:
PropTypes
.
object
.
isRequired
,
query
:
PropTypes
.
object
.
isRequired
,
total
:
PropTypes
.
number
.
isRequired
,
onChange
:
PropTypes
.
func
,
history
:
PropTypes
.
any
.
isRequired
,
order_by
:
PropTypes
.
string
.
isRequired
,
...
...
@@ -24,7 +23,9 @@ class EntryListUnstyled extends React.Component {
page
:
PropTypes
.
number
.
isRequired
,
per_page
:
PropTypes
.
number
.
isRequired
,
domain
:
PropTypes
.
object
.
isRequired
,
editable
:
PropTypes
.
bool
editable
:
PropTypes
.
bool
,
columns
:
PropTypes
.
object
,
selectedColumns
:
PropTypes
.
arrayOf
(
PropTypes
.
string
)
}
static
styles
=
theme
=>
({
...
...
@@ -46,7 +47,7 @@ class EntryListUnstyled extends React.Component {
selected
:
[]
}
defaultRowConfig
=
{
static
defaultColumns
=
{
authors
:
{
label
:
'
Authors
'
,
render
:
entry
=>
entry
.
authors
.
map
(
author
=>
author
.
name
).
join
(
'
;
'
),
...
...
@@ -233,12 +234,12 @@ class EntryListUnstyled extends React.Component {
const
{
results
,
pagination
:
{
total
}
}
=
data
const
{
selected
}
=
this
.
state
const
columns
=
{
const
columns
=
this
.
props
.
columns
||
{
...
domain
.
searchResultColumns
,
...
this
.
defaultRowConfig
...
EntryListUnstyled
.
defaultColumns
}
const
defaultSelectedColumns
=
[
const
defaultSelectedColumns
=
this
.
props
.
selectedColumns
||
[
...
domain
.
defaultSearchResultColumns
,
'
datasets
'
,
'
authors
'
]
...
...
gui/src/components/search/Search.js
View file @
9ff15d7e
...
...
@@ -254,7 +254,7 @@ class Search extends React.Component {
<
EntryList
query
=
{{...
searchParameters
,
...
searchValues
}}
editable
=
{
keycloak
.
authenticated
&&
(
searchParameters
.
owner
===
'
staging
'
||
searchParameters
.
owner
===
'
user
'
)}
data
=
{
data
}
total
=
{
total
}
data
=
{
data
}
onChange
=
{
this
.
updateEntryList
}
{...
entryListState
}
/
>
...
...
gui/src/components/uploads/Upload.js
View file @
9ff15d7e
import
React
from
'
react
'
import
PropTypes
from
'
prop-types
'
import
{
withStyles
,
ExpansionPanel
,
ExpansionPanelSummary
,
Typography
,
ExpansionPanelDetails
,
Stepper
,
Step
,
StepLabel
,
Table
,
TableRow
,
TableCell
,
TableBody
,
Checkbox
,
FormControlLabel
,
TablePagination
,
TableHead
,
Tooltip
,
CircularProgress
,
TableSortLabel
}
from
'
@material-ui/core
'
ExpansionPanelDetails
,
Stepper
,
Step
,
StepLabel
,
Checkbox
,
FormControlLabel
,
Tooltip
,
CircularProgress
}
from
'
@material-ui/core
'
import
ExpandMoreIcon
from
'
@material-ui/icons/ExpandMore
'
import
ReactJson
from
'
react-json-view
'
import
{
compose
}
from
'
recompose
'
import
{
withErrors
}
from
'
../errors
'
import
{
withRouter
}
from
'
react-router
'
import
{
debug
}
from
'
../../config
'
import
EntryList
,
{
EntryListUnstyled
}
from
'
../search/EntryList
'
import
{
withDomain
}
from
'
../domains
'
class
Upload
extends
React
.
Component
{
static
propTypes
=
{
...
...
@@ -21,7 +22,8 @@ class Upload extends React.Component {
onCheckboxChanged
:
PropTypes
.
func
,
onDoesNotExist
:
PropTypes
.
func
,
onPublished
:
PropTypes
.
func
,
history
:
PropTypes
.
any
.
isRequired
history
:
PropTypes
.
any
.
isRequired
,
domain
:
PropTypes
.
object
.
isRequired
,
}
static
styles
=
theme
=>
({
...
...
@@ -84,20 +86,32 @@ class Upload extends React.Component {
}
})
static
defaultSelectedColumns
=
[
'
mainfile
'
,
'
parser
'
,
'
proc
'
,
'
tasks_status
'
]
state
=
{
upload
:
this
.
props
.
upload
,
params
:
{
page
:
1
,
per
P
age
:
10
,
order
B
y
:
'
tasks_status
'
,
order
:
'
desc
'
per
_p
age
:
10
,
order
_b
y
:
'
tasks_status
'
,
order
:
1
},
updating
:
true
// it is still not complete and continuously looking for updates
updating
:
true
,
// it is still not complete and continuously looking for updates
columns
:
{}
}
_unmounted
=
false
constructor
(
props
)
{
super
(
props
)
this
.
handleChange
=
this
.
handleChange
.
bind
(
this
)
}
componentDidUpdate
(
prevProps
,
prevState
)
{
if
(
prevProps
.
domain
!=
this
.
props
.
domain
)
{
this
.
updateColumns
()
}
if
(
this
.
state
.
updating
)
{
return
}
...
...
@@ -109,14 +123,78 @@ class Upload extends React.Component {
this
.
update
()
}
updateColumns
()
{
const
{
domain
}
=
this
.
props
const
domainColumns
=
domain
?
domain
.
searchResultColumns
:
{}
const
otherColumns
=
{...
domainColumns
,
...
EntryListUnstyled
.
defaultColumns
}
Object
.
keys
(
otherColumns
).
forEach
(
key
=>
{
otherColumns
[
key
]
=
{
...
otherColumns
[
key
],
supportsSort
:
false
}
})
const
columns
=
{
mainfile
:
{
label
:
'
Mainfile
'
,
supportsSort
:
true
,
description
:
'
The path to the main output of this entry in the upload.
'
},
parser
:
{
label
:
'
Parser
'
,
supportsSort
:
true
,
description
:
'
The parser that was used to process this entry.
'
,
render
:
entry
=>
entry
.
parser
.
replace
(
'
parsers/
'
,
''
)
},
proc
:
{
label
:
'
Processing
'
,
supportsSort
:
false
,
description
:
'
Details on the processing of this entry.
'
,
render
:
entry
=>
`
${
entry
.
current_task
}
[
${
entry
.
tasks
.
indexOf
(
entry
.
current_task
)
+
1
}
/
${
entry
.
tasks
.
length
}
]`
},
tasks_status
:
{
label
:
'
Status
'
,
supportsSort
:
true
,
descriptions
:
'
Entry processing status
'
,
render
:
entry
=>
{
const
{
tasks_status
,
errors
,
warnings
}
=
entry
const
label
=
tasks_status
.
toLowerCase
()
const
error
=
tasks_status
===
'
FAILURE
'
||
errors
.
length
>
0
||
warnings
.
length
>
0
let
tooltip
=
null
if
(
tasks_status
===
'
FAILURE
'
)
{
tooltip
=
`Calculation processing failed with errors:
${
errors
.
join
(
'
,
'
)}
`
}
if
(
errors
.
length
>
0
)
{
tooltip
=
`Calculation processed with errors:
${
errors
.
join
(
'
,
'
)}
`
}
if
(
warnings
.
length
>
0
)
{
tooltip
=
`Calculation processed with warnings:
${
warnings
.
join
(
'
,
'
)}
`
}
if
(
error
)
{
return
<
Tooltip
title
=
{
tooltip
}
>
<
Typography
color
=
"
error
"
>
{
label
}
<
/Typography
>
<
/Tooltip
>
}
else
{
return
label
}
}
},
...
otherColumns
}
this
.
setState
({
columns
:
columns
})
}
update
()
{
if
(
this
.
_unmounted
)
{
return
}
const
{
page
,
per
P
age
,
order
B
y
,
order
}
=
this
.
state
.
params
const
{
page
,
per
_p
age
,
order
_b
y
,
order
}
=
this
.
state
.
params
const
wasPublished
=
this
.
state
.
published
this
.
state
.
upload
.
get
(
page
,
per
P
age
,
order
B
y
,
order
===
'
asc
'
?
1
:
-
1
)
this
.
state
.
upload
.
get
(
page
,
per
_p
age
,
order
_b
y
,
order
)
.
then
(
upload
=>
{
const
{
tasks_running
,
process_running
,
current_task
,
published
}
=
upload
if
(
!
this
.
_unmounted
)
{
...
...
@@ -146,6 +224,7 @@ class Upload extends React.Component {
}
componentDidMount
()
{
this
.
updateColumns
()
this
.
update
()
}
...
...
@@ -153,30 +232,8 @@ class Upload extends React.Component {
this
.
_unmounted
=
true
}
handleChangePage
=
(
_
,
page
)
=>
{
this
.
setState
(
state
=>
({
params
:
{...
state
.
params
,
page
:
page
+
1
}}))
}
handleChangeRowsPerPage
=
event
=>
{
const
perPage
=
event
.
target
.
value
this
.
setState
(
state
=>
({
params
:
{...
state
.
params
,
perPage
:
perPage
}}))
}
handleSort
(
orderBy
)
{
this
.
setState
(
state
=>
{
let
order
=
'
desc
'
if
(
state
.
params
.
orderBy
===
orderBy
&&
state
.
params
.
order
===
'
desc
'
)
{
order
=
'
asc
'
}
return
{
params
:
{
...
state
.
params
,
orderBy
:
orderBy
,
order
:
order
,
page
:
1
}
}
})
handleChange
(
changes
)
{
this
.
setState
({
params
:
{...
this
.
state
.
params
,
...
changes
}})
}
onCheckboxChanged
(
_
,
checked
)
{
...
...
@@ -343,7 +400,7 @@ class Upload extends React.Component {
renderCalcTable
()
{
const
{
classes
}
=
this
.
props
const
{
page
,
perPage
,
orderBy
,
order
}
=
this
.
state
.
params
const
{
columns
}
=
this
.
state
const
{
calcs
,
tasks_status
,
waiting
}
=
this
.
state
.
upload
const
{
pagination
,
results
}
=
calcs
...
...
@@ -371,128 +428,22 @@ class Upload extends React.Component {
}
}
const
renderRow
=
(
calc
,
index
)
=>
{
const
{
mainfile
,
upload_id
,
calc_id
,
parser
,
tasks
,
current_task
,
tasks_status
,
errors
}
=
calc
let
tooltip_html
=
null
let
color
=
tasks_status
===
'
FAILURE
'
?
'
error
'
:
'
default
'
if
(
tasks_status
===
'
FAILURE
'
)
{
tooltip_html
=
`Calculation processing failed with errors:
${
errors
.
join
(
'
,
'
)}
`
color
=
'
error
'
}
if
(
calc
.
errors
.
length
>
0
)
{
color
=
'
error
'
tooltip_html
=
`Calculation processed with errors:
${
calc
.
errors
.
join
(
'
,
'
)}
`
}
if
(
calc
.
warnings
.
length
>
0
)
{
color
=
'
error
'
tooltip_html
=
`Calculation processed with warnings:
${
calc
.
warnings
.
join
(
'
,
'
)}
`
}
const
processed
=
tasks_status
===
'
FAILURE
'
||
tasks_status
===
'
SUCCESS
'
const
row
=
(
<
TableRow
key
=
{
index
}
hover
=
{
processed
}
onClick
=
{()
=>
this
.
props
.
history
.
push
(
`/entry/id/
${
upload_id
}
/
${
calc_id
}
`
)}
className
=
{
processed
?
classes
.
clickableRow
:
null
}
>
<
TableCell
>
<
Typography
color
=
{
color
}
>
{
mainfile
}
<
/Typography
>
<
Typography
variant
=
"
caption
"
color
=
{
color
}
>
{
upload_id
}
/{calc_id
}
<
/Typography
>
<
/TableCell
>
<
TableCell
>
<
Typography
color
=
{
color
}
>
{
parser
.
replace
(
'
parsers/
'
,
''
)}
<
/Typography
>
<
/TableCell
>
<
TableCell
>
<
Typography
color
=
{
color
}
>
{
current_task
}
<
/Typography
>
<
Typography
variant
=
"
caption
"
color
=
{
color
}
>
task
&
nbsp
;
<
b
>
[{
tasks
.
indexOf
(
current_task
)
+
1
}
/{tasks.length}
]
<
/b
>
<
/Typography
>
<
/TableCell
>
<
TableCell
>
<
Typography
color
=
{
color
}
>
{
tasks_status
.
toLowerCase
()}
<
/Typography
>
<
/TableCell
>
<
/TableRow
>
)
if
(
tooltip_html
)
{
return
(
<
Tooltip
key
=
{
calc_id
}
title
=
{
tooltip_html
}
>
{
row
}
<
/Tooltip
>
)
}
else
{
return
row
}
}
const
total
=
pagination
.
total
let
emptyRows
=
0
if
(
total
>
perPage
)
{
emptyRows
=
perPage
-
Math
.
min
(
perPage
,
total
-
(
page
-
1
)
*
perPage
)
const
data
=
{
pagination
:
calcs
.
pagination
,
results
:
calcs
.
results
.
map
(
calc
=>
({
...
calc
.
metadata
,
...
calc
}))
}
const
columns
=
[
{
id
:
'
mainfile
'
,
sort
:
true
,
label
:
'
mainfile
'
},
{
id
:
'
parser
'
,
sort
:
true
,
label
:
'
code
'
},
{
id
:
'
task
'
,
sort
:
false
,
label
:
'
task
'
},
{
id
:
'
tasks_status
'
,
sort
:
true
,
label
:
'
status
'
}
]
return
(
<
Table
>
<
TableHead
>
<
TableRow
>
{
columns
.
map
(
column
=>
(
<
TableCell
key
=
{
column
.
id
}
>
{
column
.
sort
?
<
Tooltip
title
=
"
Sort
"
placement
=
{
'
bottom-start
'
}
enterDelay
=
{
300
}
>
<
TableSortLabel
active
=
{
orderBy
===
column
.
id
}
direction
=
{
order
}
onClick
=
{()
=>
this
.
handleSort
(
column
.
id
)}
>
{
column
.
label
}
<
/TableSortLabel
>
<
/Tooltip
>
:
column
.
label
}
<
/TableCell
>
))}
<
/TableRow
>
<
/TableHead
>
<
TableBody
>
{
results
.
map
(
renderRow
)}
{
emptyRows
>
0
&&
(
<
TableRow
style
=
{{
height
:
57
*
emptyRows
}}
>
<
TableCell
colSpan
=
{
6
}
/
>
<
/TableRow
>
)}
<
TableRow
>
<
TablePagination
count
=
{
total
}
rowsPerPage
=
{
perPage
}
page
=
{
page
-
1
}
onChangePage
=
{
this
.
handleChangePage
}
onChangeRowsPerPage
=
{
this
.
handleChangeRowsPerPage
}
/
>
<
/TableRow
>
<
/TableBody
>
<
/Table
>
)
return
<
EntryList
query
=
{{
upload_id
:
this
.
props
.
upload_id
}}
columns
=
{
columns
}
selectedColumns
=
{
Upload
.
defaultSelectedColumns
}
editable
data
=
{
data
}
onChange
=
{
this
.
handleChange
}
{...
this
.
state
.
params
}
/
>
}
renderCheckBox
()
{
...
...
@@ -553,4 +504,4 @@ class Upload extends React.Component {
}
}
export
default
compose
(
withRouter
,
withErrors
,
withStyles
(
Upload
.
styles
))(
Upload
)
export
default
compose
(
withRouter
,
withErrors
,
withDomain
,
withStyles
(
Upload
.
styles
))(
Upload
)
nomad/app/api/upload.py
View file @
9ff15d7e
...
...
@@ -26,7 +26,7 @@ import os
import
io
from
functools
import
wraps
from
nomad
import
config
,
utils
,
files
from
nomad
import
config
,
utils
,
files
,
search
,
datamodel
from
nomad.processing
import
Upload
,
FAILURE
from
nomad.processing
import
ProcessAlreadyRunning
...
...
@@ -41,6 +41,12 @@ ns = api.namespace(
description
=
'Uploading data and tracing uploaded data and its processing.'
)
class
CalcMetadata
(
fields
.
Raw
):
def
format
(
self
,
value
):
calc_with_metadata
=
datamodel
.
CalcWithMetadata
(
**
value
)
return
search
.
Entry
.
from_calc_with_metadata
(
calc_with_metadata
).
to_dict
()
proc_model
=
api
.
model
(
'Processing'
,
{
'tasks'
:
fields
.
List
(
fields
.
String
),
'current_task'
:
fields
.
String
,
...
...
@@ -86,7 +92,8 @@ calc_model = api.inherit('UploadCalculationProcessing', proc_model, {
'calc_id'
:
fields
.
String
,
'mainfile'
:
fields
.
String
,
'upload_id'
:
fields
.
String
,
'parser'
:
fields
.
String
'parser'
:
fields
.
String
,
'metadata'
:
CalcMetadata
(
description
=
'The repository metadata for this entry.'
)
})
upload_with_calcs_model
=
api
.
inherit
(
'UploadWithPaginatedCalculations'
,
upload_model
,
{
...
...
Write
Preview
Supports
Markdown
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