Commit d41056f3 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Added materials tab.

parent 0a5912bb
Pipeline #79803 failed with stages
in 55 minutes and 49 seconds
......@@ -59,7 +59,6 @@ export default function DatasetPage() {
return <div>loading...</div>
}
console.log('### DatasetPage', dataset)
return <div>
<div className={classes.header}>
<div className={classes.description}>
......
import React from 'react'
import { withApi } from './api'
import Search from './search/Search'
import { encyclopediaEnabled } from '../config'
export const help = `
This page allows you to **inspect** and **manage** you own data. It is similar to the
......@@ -58,7 +59,7 @@ function UserdataPage() {
initialOwner="user"
initialRequest={{order_by: 'upload_time', uploads_grouped: true}}
initialResultTab="uploads"
availableResultTabs={['uploads', 'datasets', 'entries']}
availableResultTabs={['uploads', 'datasets', 'entries', ...(encyclopediaEnabled ? ['materials'] : [])]}
resultListProps={{selectedColumnsKey: 'userEntries', selectedColumns: ['formula', 'upload_time', 'mainfile', 'published', 'co_authors', 'references', 'datasets']}}
/>
}
......
......@@ -72,6 +72,11 @@ export const domains = ({
tooltip: 'Aggregates the number of simulated system geometries in all entries.',
renderResultString: count => (<span> that simulate <b>{count.toLocaleString()}</b> unique geometrie{count === 1 ? '' : 's'}</span>)
},
'encyclopedia.material.materials': {
label: 'Materials',
tooltip: 'Shows statistics in terms of materials.',
renderResultString: count => (<span> of <b>{count.toLocaleString()}</b> material{count === 1 ? '' : 's'}</span>)
},
datasets: {
label: 'Datasets',
tooltip: 'Shows statistics in terms of datasets that entries belong to.',
......@@ -152,7 +157,7 @@ export const domains = ({
* the entry view. Needs to work with props: data (the entry data from the API),
* loading (a bool with api loading status).
*/
searchTabs: ['entries', 'datasets', 'groups', 'uploads']
searchTabs: ['entries', 'materials', 'datasets', 'groups', 'uploads']
},
ems: {
name: 'EMS',
......
import React from 'react'
import PropTypes from 'prop-types'
import { makeStyles, TableCell, Toolbar, IconButton, Tooltip } from '@material-ui/core'
import NextIcon from '@material-ui/icons/ChevronRight'
import StartIcon from '@material-ui/icons/SkipPrevious'
import DataTable from '../DataTable'
import DetailsIcon from '@material-ui/icons/MoreHoriz'
import { appBase } from '../../config'
const useStyles = makeStyles(theme => ({
root: {
overflow: 'auto',
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2)
},
scrollCell: {
padding: 0
},
scrollBar: {
minHeight: 56,
padding: 0
},
scrollSpacer: {
flexGrow: 1
},
clickableRow: {
cursor: 'pointer'
}
}))
const columns = {
formula: {
label: 'Formula',
render: entry => entry.encyclopedia.material.formula
},
material_name: {
label: 'Name',
render: entry => entry.encyclopedia.material.material_name
},
material_type: {
label: 'Type',
render: entry => entry.encyclopedia.material.material_type
},
spacegroup: {
label: 'Spacegroup',
render: entry => {
const bulk = entry.encyclopedia.material.bulk
return (bulk && bulk.space_group_international_short_symbol) || '-'
}
},
calculations: {
label: 'No calculations',
render: entry => entry.total
}
}
export default function MaterialsList(props) {
const { data, total, materials_after, per_page, onChange, actions } = props
const classes = useStyles()
const materials = data['encyclopedia.material.materials_grouped'] || {values: []}
const results = Object.keys(materials.values).map(id => {
return {
id: id,
total: materials.values[id].total,
...materials.values[id].examples[0]
}
})
const after = materials.after
const perPage = per_page || 10
let paginationText
if (materials_after) {
paginationText = `next ${results.length.toLocaleString()} of ${(total || 0).toLocaleString()}`
} else {
paginationText = `1-${results.length.toLocaleString()} of ${(total || 0).toLocaleString()}`
}
const pagination = <TableCell colSpan={1000} classes={{root: classes.scrollCell}}>
<Toolbar className={classes.scrollBar}>
<span className={classes.scrollSpacer}>&nbsp;</span>
<span>{paginationText}</span>
<IconButton disabled={!materials_after} onClick={() => onChange({materials_grouped_after: null})}>
<StartIcon />
</IconButton>
<IconButton disabled={results.length < perPage} onClick={() => onChange({materials_grouped_after: after})}>
<NextIcon />
</IconButton>
</Toolbar>
</TableCell>
const entryActions = entry => <Tooltip title="Open this material in the Encyclopedia.">
<IconButton href={`${appBase}/encyclopedia/#/material/${entry.encyclopedia.material.material_id}`}>
<DetailsIcon />
</IconButton>
</Tooltip>
return <DataTable
entityLabels={['material', 'materials']}
id={row => row.id}
total={total}
columns={columns}
selectedColumns={['formula', 'material_name', 'material_type', 'spacegroup', 'calculations']}
selectedColumnsKey="materials"
data={results}
rows={perPage}
actions={actions}
pagination={pagination}
entryActions={entryActions}
/>
}
MaterialsList.propTypes = ({
data: PropTypes.object,
total: PropTypes.number,
onChange: PropTypes.func.isRequired,
materials_after: PropTypes.string,
per_page: PropTypes.number,
actions: PropTypes.element
})
......@@ -19,6 +19,7 @@ import UploadsHistogram from './UploadsHistogram'
import QuantityHistogram from './QuantityHistogram'
import SearchContext, { searchContext } from './SearchContext'
import {objectFilter} from '../../utils'
import MaterialsList from './MaterialsList'
const resultTabs = {
'entries': {
......@@ -26,6 +27,11 @@ const resultTabs = {
groups: {},
component: SearchEntryList
},
'materials': {
label: 'Materials',
groups: {'encyclopedia.material.materials_grouped': true},
component: SearchMaterialsList
},
'groups': {
label: 'Grouped entries',
groups: {'dft.groups_grouped': true},
......@@ -607,3 +613,12 @@ function SearchUploadList(props) {
{...response} {...props} {...useScroll('uploads')}
/>
}
function SearchMaterialsList(props) {
const {response} = useContext(searchContext)
return <MaterialsList
data={response}
actions={<ReRunSearchButton/>}
{...response} {...props} {...useScroll('encyclopedia.material.materials', 'materials_after')}
/>
}
......@@ -2,6 +2,7 @@ import React, { useContext } from 'react'
import { apiContext } from '../api'
import Search from './Search'
import { domains } from '../domains'
import { encyclopediaEnabled } from '../../config'
export const help = `
This page allows you to **search** in NOMAD's data. The upper part of this page
......@@ -52,7 +53,7 @@ export default function SearchPage() {
return <Search
initialVisualizationTab="elements"
availableResultTabs={['entries', 'groups', 'datasets']}
availableResultTabs={['entries', ...(encyclopediaEnabled ? ['materials'] : []), 'groups', 'datasets']}
initialOwner="public"
ownerTypes={['public', 'visible'].filter(key => user || withoutLogin.indexOf(key) !== -1)}
/>
......
......@@ -315,7 +315,10 @@ class Material(MSection):
A fixed length, unique material identifier in the form of a hash
digest.
""",
a_search=Search()
a_search=Search(
group='materials_grouped',
metric='cardinality', metric_name='materials',
description='Search for a particular material by its id.')
)
material_name = Quantity(
type=str,
......
......@@ -88,7 +88,7 @@ gui:
## automatically gz based on header
gzip: true
## enable links to the 'new' encyclopedia
encyclopediaEnabled: false
encyclopediaEnabled: true
## Everything concerning the nginx that serves the gui, proxies the api
# It is run via NodePort service
......
......@@ -795,6 +795,7 @@ class TestRepo():
domain='dft', upload_id='example_upload_id', calc_id='0', upload_time=today_datetime)
entry_metadata.files = ['test/mainfile.txt']
entry_metadata.apply_domain_metadata(normalized)
entry_metadata.encyclopedia = normalized.entry_archive.section_metadata.encyclopedia
entry_metadata.m_update(datasets=[example_dataset.dataset_id])
......@@ -1029,6 +1030,7 @@ class TestRepo():
'metrics': metrics,
'group_statistics': True,
'dft.groups_grouped': True,
'encyclopedia.material.materials_grouped': True,
'datasets_grouped': True,
'uploads_grouped': True}, doseq=True))
......@@ -1044,7 +1046,7 @@ class TestRepo():
else:
assert len(metrics_result) == 1 # code_runs is the only metric for authors
for group in ['dft.groups_grouped', 'uploads_grouped', 'datasets_grouped']:
for group in ['dft.groups_grouped', 'uploads_grouped', 'datasets_grouped', 'encyclopedia.material.materials_grouped']:
assert group in data
assert 'after' in data[group]
assert 'values' in data[group]
......
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