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
72079f2c
Commit
72079f2c
authored
Sep 09, 2019
by
Markus Scheidgen
Browse files
Implemented Dataset page.
parent
e789b95e
Pipeline
#60303
passed with stages
in 31 minutes and 39 seconds
Changes
12
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
gui/src/components/App.js
View file @
72079f2c
...
...
@@ -22,13 +22,15 @@ import Calc from './entry/Calc'
import
About
from
'
./About
'
import
LoginLogout
from
'
./LoginLogout
'
import
{
genTheme
,
repoTheme
,
archiveTheme
,
appBase
}
from
'
../config
'
import
{
DomainProvider
}
from
'
./domains
'
import
{
DomainProvider
,
withDomain
}
from
'
./domains
'
import
{
help
as
metainfoHelp
,
default
as
MetaInfoBrowser
}
from
'
./metaInfoBrowser/MetaInfoBrowser
'
import
packageJson
from
'
../../package.json
'
import
{
Cookies
,
withCookies
}
from
'
react-cookie
'
import
Markdown
from
'
./Markdown
'
import
{
help
as
uploadHelp
,
default
as
Uploads
}
from
'
./uploads/Uploads
'
import
ResolvePID
from
'
./entry/ResolvePID
'
;
import
ResolvePID
from
'
./entry/ResolvePID
'
import
DatasetPage
from
'
./DatasetPage
'
import
{
capitalize
}
from
'
../utils
'
export
class
VersionMismatch
extends
Error
{
constructor
(
msg
)
{
...
...
@@ -39,27 +41,7 @@ export class VersionMismatch extends Error {
const
drawerWidth
=
200
const
toolbarTitles
=
{
'
/
'
:
'
About, Documentation, Getting Help
'
,
'
/search
'
:
'
Find and Download Data
'
,
'
/uploads
'
:
'
Upload and Publish Data
'
,
'
/metainfo
'
:
'
The NOMAD Meta Info
'
}
const
toolbarThemes
=
{
'
/
'
:
genTheme
,
'
/search
'
:
repoTheme
,
'
/uploads
'
:
repoTheme
,
'
/entry
'
:
repoTheme
,
'
/metainfo
'
:
archiveTheme
}
const
toolbarHelp
=
{
'
/
'
:
null
,
'
/search
'
:
{
title
:
'
How to find and download data
'
,
content
:
searchHelp
},
'
/uploads
'
:
{
title
:
'
How to upload data
'
,
content
:
uploadHelp
},
'
/metainfo
'
:
{
title
:
'
About the NOMAD meta-info
'
,
content
:
metainfoHelp
}
}
class
NavigationUnstyled
extends
React
.
Component
{
static
propTypes
=
{
...
...
@@ -177,6 +159,31 @@ class NavigationUnstyled extends React.Component {
}
}
toolbarTitles
=
{
'
/
'
:
'
About, Documentation, Getting Help
'
,
'
/search
'
:
'
Find and Download Data
'
,
'
/uploads
'
:
'
Upload and Publish Data
'
,
'
/metainfo
'
:
'
The NOMAD Meta Info
'
,
'
/entry
'
:
capitalize
(
this
.
props
.
domain
.
entryLabel
),
'
/dataset
'
:
'
Dataset
'
}
toolbarThemes
=
{
'
/
'
:
genTheme
,
'
/search
'
:
repoTheme
,
'
/uploads
'
:
repoTheme
,
'
/entry
'
:
repoTheme
,
'
/dataset
'
:
repoTheme
,
'
/metainfo
'
:
archiveTheme
}
toolbarHelp
=
{
'
/
'
:
null
,
'
/search
'
:
{
title
:
'
How to find and download data
'
,
content
:
searchHelp
},
'
/uploads
'
:
{
title
:
'
How to upload data
'
,
content
:
uploadHelp
},
'
/metainfo
'
:
{
title
:
'
About the NOMAD meta-info
'
,
content
:
metainfoHelp
}
}
componentDidMount
()
{
fetch
(
`
${
appBase
}
/meta.json`
)
.
then
((
response
)
=>
response
.
json
())
...
...
@@ -198,6 +205,7 @@ class NavigationUnstyled extends React.Component {
render
()
{
const
{
classes
,
children
,
location
:
{
pathname
},
loading
}
=
this
.
props
const
{
toolbarThemes
,
toolbarHelp
,
toolbarTitles
}
=
this
const
selected
=
dct
=>
{
const
key
=
Object
.
keys
(
dct
).
find
(
key
=>
{
...
...
@@ -299,7 +307,7 @@ class NavigationUnstyled extends React.Component {
}
}
const
Navigation
=
compose
(
withRouter
,
withErrors
,
withApi
(
false
),
withStyles
(
NavigationUnstyled
.
styles
))(
NavigationUnstyled
)
const
Navigation
=
compose
(
withRouter
,
withErrors
,
withApi
(
false
),
withDomain
,
withStyles
(
NavigationUnstyled
.
styles
))(
NavigationUnstyled
)
class
LicenseAgreementUnstyled
extends
React
.
Component
{
static
propTypes
=
{
...
...
@@ -392,7 +400,7 @@ export default class App extends React.Component {
},
'
entry
'
:
{
path
:
'
/entry/id/:uploadId/:calcId
'
,
key
:
(
props
)
=>
`entry/
${
props
.
match
.
params
.
uploadId
}
/
${
props
.
match
.
params
.
uploadId
}
`
,
key
:
(
props
)
=>
`entry/
id/
${
props
.
match
.
params
.
uploadId
}
/
${
props
.
match
.
params
.
uploadId
}
`
,
render
:
props
=>
{
const
{
match
,
...
rest
}
=
props
if
(
match
&&
match
.
params
.
uploadId
&&
match
.
params
.
calcId
)
{
...
...
@@ -402,6 +410,18 @@ export default class App extends React.Component {
}
}
},
'
dataset
'
:
{
path
:
'
/dataset/id/:datasetId
'
,
key
:
(
props
)
=>
`dataset/id/
${
props
.
match
.
params
.
datasetId
}
`
,
render
:
props
=>
{
const
{
match
,
...
rest
}
=
props
if
(
match
&&
match
.
params
.
datasetId
)
{
return
(
<
DatasetPage
{...
rest
}
datasetId
=
{
match
.
params
.
datasetId
}
/>
)
}
else
{
return
''
}
}
},
'
entry_pid
'
:
{
path
:
'
/entry/pid/:pid
'
,
key
:
(
props
)
=>
`entry/pid/
${
props
.
match
.
params
.
pid
}
`
,
...
...
gui/src/components/DatasetPage.js
0 → 100644
View file @
72079f2c
import
React
from
'
react
'
import
PropTypes
from
'
prop-types
'
import
{
withStyles
}
from
'
@material-ui/core/styles
'
import
{
compose
}
from
'
recompose
'
import
{
withErrors
}
from
'
./errors
'
import
{
withApi
}
from
'
./api
'
import
Search
from
'
./search/Search
'
import
{
Typography
,
Link
,
Fab
}
from
'
@material-ui/core
'
import
Download
from
'
./entry/Download
'
import
DownloadIcon
from
'
@material-ui/icons/CloudDownload
'
export
const
help
=
`
This page allows you to **inspect** and **download** NOMAD datasets. It alsow allows you
to explore a dataset with similar controls that the search page offers.
`
class
DatasetPage
extends
React
.
Component
{
static
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
api
:
PropTypes
.
object
.
isRequired
,
datasetId
:
PropTypes
.
string
.
isRequired
,
raiseError
:
PropTypes
.
func
.
isRequired
}
static
styles
=
theme
=>
({
root
:
{
},
description
:
{
padding
:
theme
.
spacing
.
unit
*
3
},
downloadFab
:
{
zIndex
:
1
,
right
:
32
,
top
:
56
+
32
,
position
:
'
fixed !important
'
}
})
state
=
{
dataset
:
{}
}
componentDidMount
()
{
const
{
datasetId
,
raiseError
,
api
}
=
this
.
props
api
.
search
({
owner
:
'
all
'
,
dataset_id
:
datasetId
,
page
:
1
,
per_page
:
1
}).
then
(
data
=>
{
const
entry
=
data
.
results
[
0
]
const
dataset
=
entry
?
entry
.
datasets
.
find
(
ds
=>
ds
.
id
+
''
===
datasetId
)
:
{}
this
.
setState
({
dataset
:
dataset
||
{}})
}).
catch
(
error
=>
{
this
.
setState
({
dataset
:
{}})
raiseError
(
error
)
})
}
render
()
{
const
{
classes
,
datasetId
}
=
this
.
props
const
{
dataset
}
=
this
.
state
return
(
<
div
className
=
{
classes
.
root
}
>
<
div
className
=
{
classes
.
description
}
>
<
Typography
variant
=
"
h4
"
>
{
dataset
.
name
||
'
loading ...
'
}
<
/Typography
>
<
Typography
>
dataset
{
dataset
.
doi
?
<
span
>
,
with
DOI
<
Link
href
=
{
dataset
.
doi
}
>
{
dataset
.
doi
}
<
/Link></
span
>
:
''
}
<
/Typography
>
<
/div
>
<
Search
searchParameters
=
{{
owner
:
'
all
'
,
dataset_id
:
datasetId
}}
/
>
<
Download
classes
=
{{
root
:
classes
.
downloadFab
}}
tooltip
=
"
download all rawfiles
"
component
=
{
Fab
}
className
=
{
classes
.
downloadFab
}
color
=
"
primary
"
size
=
"
medium
"
url
=
{
`raw/query?dataset_id=
${
datasetId
}
`
}
fileName
=
{
`
${
dataset
.
name
}
.json`
}
>
<
DownloadIcon
/>
<
/Download
>
<
/div
>
)
}
}
export
default
compose
(
withApi
(
false
),
withErrors
,
withStyles
(
DatasetPage
.
styles
))(
DatasetPage
)
gui/src/components/domains.js
View file @
72079f2c
...
...
@@ -54,7 +54,7 @@ class DomainProviderBase extends React.Component {
still be missing when you are exploring Nomad data using the new search and data
exploring capabilities (menu items on the left).
`
,
entryLabel
:
'
c
alculatio
n
'
,
entryLabel
:
'
c
ode ru
n
'
,
searchPlaceholder
:
'
enter atoms, codes, functionals, or other quantity values
'
,
/**
* A component that is used to render the search aggregations. The components needs
...
...
gui/src/components/entry/RepoEntryView.js
View file @
72079f2c
import
React
from
'
react
'
import
PropTypes
from
'
prop-types
'
import
{
withStyles
,
Divider
,
Card
,
CardContent
,
Grid
,
CardHeader
,
Fab
,
Typography
}
from
'
@material-ui/core
'
import
{
withStyles
,
Divider
,
Card
,
CardContent
,
Grid
,
CardHeader
,
Fab
,
Typography
,
Link
}
from
'
@material-ui/core
'
import
{
withApi
}
from
'
../api
'
import
{
compose
}
from
'
recompose
'
import
Download
from
'
./Download
'
...
...
@@ -8,6 +8,7 @@ import DownloadIcon from '@material-ui/icons/CloudDownload'
import
ApiDialogButton
from
'
../ApiDialogButton
'
import
Quantity
from
'
../Quantity
'
import
{
withDomain
}
from
'
../domains
'
import
{
Link
as
RouterLink
}
from
'
react-router-dom
'
class
RepoEntryView
extends
React
.
Component
{
static
styles
=
theme
=>
({
...
...
@@ -109,9 +110,11 @@ class RepoEntryView extends React.Component {
<
Quantity
column
>
<
Quantity
quantity
=
'
comment
'
placeholder
=
'
no comment
'
{...
quantityProps
}
/
>
<
Quantity
quantity
=
'
references
'
placeholder
=
'
no references
'
{...
quantityProps
}
>
{(
calcData
.
references
||
[]).
map
(
ref
=>
<
Typography
key
=
{
ref
}
noWrap
>
<
a
href
=
{
ref
}
>
{
ref
}
<
/a
>
<
/Typography>
)
}
<
div
>
{(
calcData
.
references
||
[]).
map
(
ref
=>
<
Typography
key
=
{
ref
}
noWrap
>
<
a
href
=
{
ref
}
>
{
ref
}
<
/a
>
<
/Typography>
)
}
<
/div
>
<
/Quantity
>
<
Quantity
quantity
=
'
authors
'
{...
quantityProps
}
>
<
Typography
>
...
...
@@ -119,9 +122,13 @@ class RepoEntryView extends React.Component {
<
/Typography
>
<
/Quantity
>
<
Quantity
quantity
=
'
datasets
'
placeholder
=
'
no datasets
'
{...
quantityProps
}
>
<
Typography
>
{(
calcData
.
datasets
||
[]).
map
(
ds
=>
`
${
ds
.
name
}${
ds
.
doi
?
` (
${
ds
.
doi
}
)`
:
''
}
`
).
join
(
'
,
'
)}
<
/Typography
>
<
div
>
{(
calcData
.
datasets
||
[]).
map
(
ds
=>
(
<
Typography
key
=
{
ds
.
id
}
>
<
Link
component
=
{
RouterLink
}
to
=
{
`/dataset/id/
${
ds
.
id
}
`
}
>
{
ds
.
name
}
<
/Link
>
{
ds
.
doi
?
<
span
>&
nbsp
;
(
<
Link
href
=
{
ds
.
doi
}
>
{
ds
.
doi
}
<
/Link>
)
</
span
>
:
''
}
<
/Typography>
))
}
<
/div
>
<
/Quantity
>
<
/Quantity
>
<
/CardContent
>
...
...
gui/src/components/search/Search.js
0 → 100644
View file @
72079f2c
import
React
from
'
react
'
import
PropTypes
from
'
prop-types
'
import
{
withStyles
}
from
'
@material-ui/core/styles
'
import
{
IconButton
,
Typography
,
Divider
,
Tooltip
,
Tabs
,
Tab
}
from
'
@material-ui/core
'
import
{
compose
}
from
'
recompose
'
import
{
withErrors
}
from
'
../errors
'
import
{
withApi
,
DisableOnLoading
}
from
'
../api
'
import
SearchBar
from
'
./SearchBar
'
import
EntryList
from
'
./EntryList
'
import
SearchAggregations
from
'
./SearchAggregations
'
import
ExpandMoreIcon
from
'
@material-ui/icons/ExpandMore
'
import
ExpandLessIcon
from
'
@material-ui/icons/ExpandLess
'
import
{
withDomain
}
from
'
../domains
'
import
DatasetList
from
'
./DatasetList
'
;
import
{
isEquivalent
}
from
'
../../utils
'
;
/**
* Component that comprises all search views: SearchBar, SearchAggregations (aka statistics),
* results (EntryList, DatasetList).
*/
class
Search
extends
React
.
Component
{
static
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
api
:
PropTypes
.
object
.
isRequired
,
raiseError
:
PropTypes
.
func
.
isRequired
,
domain
:
PropTypes
.
object
,
loading
:
PropTypes
.
number
,
searchParameters
:
PropTypes
.
object
,
showDetails
:
PropTypes
.
bool
}
static
styles
=
theme
=>
({
root
:
{
},
searchContainer
:
{
padding
:
theme
.
spacing
.
unit
*
3
},
resultsContainer
:
{
},
searchEntry
:
{
minWidth
:
500
,
maxWidth
:
900
,
margin
:
'
auto
'
,
width
:
'
100%
'
},
search
:
{
marginTop
:
theme
.
spacing
.
unit
*
4
,
marginBottom
:
theme
.
spacing
.
unit
*
8
,
display
:
'
flex
'
,
alignItems
:
'
center
'
,
minWidth
:
500
,
maxWidth
:
1000
,
margin
:
'
auto
'
,
width
:
'
100%
'
},
searchBar
:
{
width
:
'
100%
'
},
searchDivider
:
{
width
:
1
,
height
:
28
,
margin
:
theme
.
spacing
.
unit
*
0.5
},
searchButton
:
{
padding
:
10
},
searchResults
:
{}
})
static
emptySearchData
=
{
results
:
[],
pagination
:
{
total
:
0
},
datasets
:
{
after
:
null
,
values
:
[]
},
statistics
:
{
total
:
{
all
:
{
datasets
:
0
}
}
}
}
state
=
{
data
:
Search
.
emptySearchData
,
searchState
:
{
...
SearchAggregations
.
defaultState
},
entryListState
:
{
...
EntryList
.
defaultState
},
datasetListState
:
{
...
DatasetList
.
defaultState
},
showDetails
:
this
.
props
.
showDetails
,
resultTab
:
'
entries
'
}
constructor
(
props
)
{
super
(
props
)
this
.
updateEntryList
=
this
.
updateEntryList
.
bind
(
this
)
this
.
updateDatasetList
=
this
.
updateDatasetList
.
bind
(
this
)
this
.
updateSearch
=
this
.
updateSearch
.
bind
(
this
)
this
.
handleClickExpand
=
this
.
handleClickExpand
.
bind
(
this
)
this
.
_mounted
=
false
}
updateEntryList
(
changes
)
{
const
entryListState
=
{
...
this
.
state
.
entryListState
,
...
changes
}
this
.
update
({
entryListState
:
entryListState
})
}
updateDatasetList
(
changes
)
{
const
datasetListState
=
{
...
this
.
state
.
datasetListState
,
...
changes
}
this
.
update
({
datasetListState
:
datasetListState
})
}
updateSearch
(
changes
)
{
const
searchState
=
{
...
this
.
state
.
searchState
,
...
changes
}
this
.
update
({
searchState
:
searchState
})
}
update
(
changes
)
{
if
(
!
this
.
_mounted
)
{
return
}
changes
=
changes
||
{}
const
{
searchParameters
}
=
this
.
props
const
{
entryListState
,
datasetListState
,
searchState
}
=
{...
this
.
state
,
...
changes
}
const
{
searchValues
,
...
searchStateRest
}
=
searchState
this
.
setState
({...
changes
})
this
.
props
.
api
.
search
({
datasets
:
true
,
statistics
:
true
,
...
entryListState
,
...
datasetListState
,
...
searchValues
,
...
searchStateRest
,
...
searchParameters
}).
then
(
data
=>
{
this
.
setState
({
data
:
data
||
Search
.
emptySearchData
})
}).
catch
(
error
=>
{
if
(
error
.
name
===
'
NotAuthorized
'
&&
this
.
props
.
searchParameters
.
owner
!==
'
all
'
)
{
this
.
setState
({
data
:
Search
.
emptySearchData
})
}
else
{
this
.
setState
({
data
:
Search
.
emptySearchData
})
this
.
props
.
raiseError
(
error
)
}
})
}
componentDidMount
()
{
this
.
_mounted
=
true
this
.
update
()
}
componentWillUnmount
()
{
this
.
_mounted
=
false
}
componentDidUpdate
(
prevProps
)
{
// login/logout or changed search paraemters -> reload results
if
(
prevProps
.
api
!==
this
.
props
.
api
||
!
isEquivalent
(
prevProps
.
searchParameters
,
this
.
props
.
searchParameters
))
{
this
.
update
()
}
}
handleClickExpand
()
{
this
.
setState
({
showDetails
:
!
this
.
state
.
showDetails
})
}
render
()
{
const
{
classes
,
domain
,
loading
}
=
this
.
props
const
{
data
,
searchState
,
entryListState
,
datasetListState
,
showDetails
,
resultTab
}
=
this
.
state
const
{
searchValues
}
=
searchState
const
{
pagination
:
{
total
},
statistics
}
=
data
const
helperText
=
<
span
>
There
are
{
Object
.
keys
(
domain
.
searchMetrics
).
filter
(
key
=>
statistics
.
total
.
all
[
key
]).
map
(
key
=>
{
return
<
span
key
=
{
key
}
>
{
domain
.
searchMetrics
[
key
].
renderResultString
(
!
loading
&&
statistics
.
total
.
all
[
key
]
!==
undefined
?
statistics
.
total
.
all
[
key
]
:
'
...
'
)}
<
/span
>
})}{
Object
.
keys
(
searchValues
).
length
?
'
left
'
:
''
}.
<
/span
>
return
(
<
div
className
=
{
classes
.
root
}
>
<
div
className
=
{
classes
.
searchContainer
}
>
<
DisableOnLoading
>
<
div
className
=
{
classes
.
search
}
>
<
SearchBar
classes
=
{{
autosuggestRoot
:
classes
.
searchBar
}}
fullWidth
fullWidthInput
=
{
false
}
helperText
=
{
helperText
}
label
=
"
search
"
placeholder
=
{
domain
.
searchPlaceholder
}
data
=
{
data
}
searchValues
=
{
searchValues
}
InputLabelProps
=
{{
shrink
:
true
}}
onChanged
=
{
values
=>
this
.
updateSearch
({
searchValues
:
values
})}
/
>
<
Divider
className
=
{
classes
.
searchDivider
}
/
>
<
Tooltip
title
=
{
showDetails
?
'
Hide statistics
'
:
'
Show statistics
'
}
>
<
IconButton
className
=
{
classes
.
searchButton
}
color
=
"
secondary
"
onClick
=
{
this
.
handleClickExpand
}
>
{
showDetails
?
<
ExpandLessIcon
/>
:
<
ExpandMoreIcon
/>
}
<
/IconButton
>
<
/Tooltip
>
<
/div
>
<
div
className
=
{
classes
.
searchEntry
}
>
<
SearchAggregations
data
=
{
data
}
{...
searchState
}
onChange
=
{
this
.
updateSearch
}
showDetails
=
{
showDetails
}
/
>
<
/div
>
<
/DisableOnLoading
>
<
/div
>
<
div
className
=
{
classes
.
resultsContainer
}
>
<
Tabs
value
=
{
resultTab
}
indicatorColor
=
"
primary
"
textColor
=
"
primary
"
onChange
=
{(
event
,
value
)
=>
this
.
setState
({
resultTab
:
value
})}
>
<
Tab
label
=
"
Calculations
"
value
=
"
entries
"
/>
<
Tab
label
=
"
Datasets
"
value
=
"
datasets
"
/>
<
/Tabs
>
<
div
className
=
{
classes
.
searchResults
}
hidden
=
{
resultTab
!==
'
entries
'
}
>
<
Typography
variant
=
"
caption
"
style
=
{{
margin
:
12
}}
>
About
{
total
.
toLocaleString
()}
results
:
<
/Typography
>
<
EntryList
data
=
{
data
}
total
=
{
total
}
onChange
=
{
this
.
updateEntryList
}
{...
entryListState
}
/
>
<
/div
>
<
div
className
=
{
classes
.
searchResults
}
hidden
=
{
resultTab
!==
'
datasets
'
}
>
<
Typography
variant
=
"
caption
"
style
=
{{
margin
:
12
}}
>
About
{
statistics
.
total
.
all
.
datasets
.
toLocaleString
()}
datasets
:
<
/Typography
>
<
DatasetList
data
=
{
data
}
total
=
{
statistics
.
total
.
all
.
datasets
}
onChange
=
{
this
.
updateDatasetList
}
{...
datasetListState
}
/
>
<
/div
>
<
/div
>
<
/div
>
)
}
}
export
default
compose
(
withApi
(
false
),
withErrors
,
withDomain
,
withStyles
(
Search
.
styles
))(
Search
)
gui/src/components/search/SearchAggregations.js
View file @
72079f2c
...
...
@@ -44,7 +44,10 @@ class SearchAggregationsUnstyled extends React.Component {
const
firstRealQuantitiy
=
Object
.
keys
(
statistics
).
find
(
key
=>
key
!==
'
total
'
)
if
(
firstRealQuantitiy
)
{
const
firstValue
=
Object
.
keys
(
statistics
[
firstRealQuantitiy
])[
0
]
useMetric
=
Object
.
keys
(
statistics
[
firstRealQuantitiy
][
firstValue
]).
find
(
metric
=>
metric
!==
'
code_runs
'
)
||
'
code_runs
'
if
(
firstValue
)
{
useMetric
=
Object
.
keys
(
statistics
[
firstRealQuantitiy
][
firstValue
])
.
find
(
metric
=>
metric
!==
'
code_runs
'
)
||
'
code_runs
'
}
}
const
metricsDefinitions
=
domain
.
searchMetrics
...
...
gui/src/components/search/SearchPage.js
View file @
72079f2c
import
React
from
'
react
'
import
PropTypes
from
'
prop-types
'
import
{
withStyles
}
from
'
@material-ui/core/styles
'
import
{
FormControl
,
FormControlLabel
,
Checkbox
,
FormGroup
,
FormLabel
,
IconButton
,
Typography
,
Divider
,
Tooltip
,
Tabs
,
Tab
}
from
'
@material-ui/core
'
import
{
FormControl
,
FormControlLabel
,
Checkbox
,
FormGroup
,
FormLabel
,
Tooltip
}
from
'
@material-ui/core
'
import
{
compose
}
from
'
recompose
'
import
{
withErrors
}
from
'
../errors
'
import
{
withApi
,
DisableOnLoading
}
from
'
../api
'
import
SearchBar
from
'
./SearchBar
'
import
EntryList
from
'
./EntryList
'
import
SearchAggregations
from
'
./SearchAggregations
'
import
ExpandMoreIcon
from
'
@material-ui/icons/ExpandMore
'
import
ExpandLessIcon
from
'
@material-ui/icons/ExpandLess
'
import
{
withDomain
}
from
'
../domains
'
import
{
appBase
}
from
'
../../config
'
import
DatasetList
from
'
./DatasetList
'
;
import
Search
from
'
./Search
'
;
export
const
help
=
`
This page allows you to **search** in NOMAD's data. The upper part of this page
...
...
@@ -57,181 +50,26 @@ all parsed data. The *log* tab, will show you a log of the entry's processing.
class
SearchPage
extends
React
.
Component
{
static
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
match
:
PropTypes
.
any
,
api
:
PropTypes
.
object
.
isRequired
,
user
:
PropTypes
.
object
,
raiseError
:
PropTypes
.
func
.
isRequired
,
domain
:
PropTypes
.
object
,
loading
:
PropTypes
.
number
raiseError
:
PropTypes
.
func
.
isRequired
}
static
styles
=
theme
=>
({
root
:
{
},
searchContainer
:
{
padding
:
theme
.
spacing
.
unit
*
3
},