Commit f1e29ac9 authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Removed dead code related to the old search interface, removed the...

Removed dead code related to the old search interface, removed the 'New'-prefix from the search components.
parent 7312e29c
Pipeline #109851 passed with stages
in 28 minutes and 37 seconds
......@@ -20,8 +20,8 @@ import PropTypes from 'prop-types'
import { Typography, makeStyles } from '@material-ui/core'
import { errorContext } from './errors'
import { useApi } from './apiV1'
import NewSearch from './search/NewSearch'
import { SearchContext } from './search/FilterContext'
import Search from './search/Search'
import { SearchContext } from './search/SearchContext'
import { DOI } from './search/results/DatasetList'
export const help = `
......@@ -60,7 +60,7 @@ const UserdataPage = React.memo(({match}) => {
resource="entries"
filtersLocked={datasetFilter}
>
<NewSearch header={
<Search header={
<div className={styles.header}>
<Typography variant="h4">
{dataset.name || (dataset.isEmpty && 'Empty or non existing dataset') || 'loading ...'}
......
......@@ -17,8 +17,8 @@
*/
import React from 'react'
import { withLoginRequired } from './apiV1'
import { SearchContext } from './search/FilterContext'
import NewSearch from './search/NewSearch'
import { SearchContext } from './search/SearchContext'
import Search from './search/Search'
export const help = `
This page allows you to **inspect** and **manage** you own data. It is similar to the
......@@ -78,7 +78,7 @@ const UserdataPage = React.memo(() => {
resource="entries"
filtersLocked={filtersLocked}
>
<NewSearch/>
<Search/>
</SearchContext>
})
......
/*
* Copyright The NOMAD Authors.
*
* This file is part of NOMAD. See https://nomad-lab.eu for further info.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useContext, useEffect } from 'react'
import PropTypes from 'prop-types'
import { Grid } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import QuantityHistogram from '../search/QuantityHistogram'
import { searchContext } from '../search/SearchContext'
import { resolveRef } from '../archive/metainfo'
import { nomadTheme } from '../../config'
import Markdown from '../Markdown'
export function DFTMethodVisualizations(props) {
const {info} = props
const {response: {statistics, metric}, setStatistics} = useContext(searchContext)
useEffect(() => {
setStatistics(['dft.code_name', 'dft.basis_set', 'dft.xc_functional'])
// eslint-disable-next-line
}, [])
if (statistics.code_name && info) {
// filter based on known codes, since elastic search might return 0 aggregations on
// obsolete code names
const filteredCodeNames = {}
const defaultValue = {
code_runs: 0
}
defaultValue[metric] = 0
info.codes.forEach(key => {
filteredCodeNames[key] = statistics.code_name[key] || defaultValue
})
statistics.code_name = filteredCodeNames
}
return (
<Grid container spacing={2}>
<Grid item xs={8}>
<QuantityHistogram quantity="dft.code_name" title="Code" initialScale={0.25} columns={2} />
</Grid>
<Grid item xs={4}>
<QuantityHistogram quantity="dft.basis_set" title="Basis set" initialScale={0.25} />
<QuantityHistogram quantity="dft.xc_functional" title="XC functionals" initialScale={0.5} />
</Grid>
</Grid>
)
}
DFTMethodVisualizations.propTypes = {
info: PropTypes.object
}
export function DFTSystemVisualizations(props) {
const {info} = props
const {response: {statistics, metric}, setStatistics} = useContext(searchContext)
useEffect(() => {
setStatistics(['dft.labels_springer_compound_class', 'dft.system', 'dft.crystal_system', 'dft.compound_type'])
// eslint-disable-next-line
}, [])
if (statistics.code_name && info) {
// filter based on known codes, since elastic search might return 0 aggregations on
// obsolete code names
const filteredCodeNames = {}
const defaultValue = {
code_runs: 0
}
defaultValue[metric] = 0
info.codes.forEach(key => {
filteredCodeNames[key] = statistics.code_name[key] || defaultValue
})
statistics.code_name = filteredCodeNames
}
return (
<Grid container spacing={2}>
<Grid item xs={4}>
<QuantityHistogram quantity="dft.system" title="System type" initialScale={0.25} />
<QuantityHistogram quantity="dft.crystal_system" title="Crystal system" />
</Grid>
<Grid item xs={4}>
<QuantityHistogram quantity="dft.compound_type" title="Compound type" initialScale={0.25} />
</Grid>
<Grid item xs={4}>
<QuantityHistogram quantity="dft.labels_springer_compound_class" title="Compound classification" />
</Grid>
</Grid>
)
}
DFTSystemVisualizations.propTypes = {
info: PropTypes.object
}
const useMetainfoTooltipStyles = makeStyles(theme => ({
root: {
display: 'flex',
flexDirection: 'column',
padding: 2
},
tooltipMarkdown: {
fontSize: nomadTheme.overrides.MuiTooltip.tooltip.fontSize,
color: 'white',
'& a': {
color: theme.palette.primary.light
}
}
}))
function MetaInfoTooltip({def, path}) {
const classes = useMetainfoTooltipStyles()
let description = def.description
if (!description && def.sub_section) {
description = resolveRef(def.sub_section)?.description
}
return <div className={classes.root} >
<Markdown
classes={{root: classes.tooltipMarkdown}}
>{`${description?.slice(0, description.indexOf('.') || undefined)}. Click [here](/metainfo/${path}) for full the definition.`}</Markdown>
</div>
}
MetaInfoTooltip.propTypes = {
def: PropTypes.object,
path: PropTypes.string
}
const workflowTypeLabels = {
'geometry_optimization': 'geometry optimization',
'phonon': 'phonons',
'elastic': 'elastic constants',
'molecular_dynamics': 'molecular dynamics'
}
export function DFTPropertyVisualizations(props) {
const {info} = props
const {response: {statistics, metric}, setStatistics} = useContext(searchContext)
useEffect(() => {
setStatistics([
'dft.searchable_quantities',
'dft.labels_springer_classification',
'dft.workflow.type'
])
// eslint-disable-next-line
}, [])
if (statistics.code_name && info) {
// filter based on known codes, since elastic search might return 0 aggregations on
// obsolete code names
const filteredCodeNames = {}
const defaultValue = {
code_runs: 0
}
defaultValue[metric] = 0
info.codes.forEach(key => {
filteredCodeNames[key] = statistics.code_name[key] || defaultValue
})
statistics.code_name = filteredCodeNames
}
return (
<Grid container spacing={2}>
<Grid item xs={12}>
<QuantityHistogram quantity="dft.labels_springer_classification" title="Functional classification" initialScale={1} multiple/>
</Grid>
<Grid item xs={12}>
<QuantityHistogram quantity="dft.workflow.type" title="Workflows" valueLabels={workflowTypeLabels} initialScale={0.25} />
</Grid>
</Grid>
)
}
DFTPropertyVisualizations.propTypes = {
info: PropTypes.object
}
......@@ -16,10 +16,6 @@
* limitations under the License.
*/
import React from 'react'
import {
DFTSystemVisualizations, DFTPropertyVisualizations, DFTMethodVisualizations
} from './dft/DFTVisualizations'
import EMSVisualizations from './ems/EMSVisualizations'
import { Link, Typography } from '@material-ui/core'
import { amber } from '@material-ui/core/colors'
......@@ -42,27 +38,6 @@ export const domainData = ({
? data.dft.code_name.charAt(0).toUpperCase() + data.dft.code_name.slice(1) + ' run'
: 'Code run',
searchPlaceholder: 'enter atoms, codes, functionals, or other quantity values',
/**
* A set of components and metadata that is used to present tabs of search visualizations
* in addition to the globally available elements and users view.
*/
searchVisualizations: {
'system': {
component: DFTSystemVisualizations,
label: 'System',
description: 'Shows histograms on system metadata'
},
'method': {
component: DFTMethodVisualizations,
label: 'Method',
description: 'Shows histograms on method metadata'
},
'properties': {
component: DFTPropertyVisualizations,
label: 'Properties',
description: 'Shows histograms on the availability of key properties'
}
},
searchMetrics: {
code_runs: {
label: 'Entries',
......@@ -178,13 +153,6 @@ export const domainData = ({
entryLabelPlural: 'entries',
entryTitle: () => 'Experiment',
searchPlaceholder: 'enter atoms, experimental methods, or other quantity values',
searchVisualizations: {
'metadata': {
component: EMSVisualizations,
label: 'Metadata',
description: 'Shows histograms on system metadata'
}
},
/**
* Metrics are used to show values for aggregations. Each metric has a key (used
* for API calls), a label (used in the select form), and result string (to show
......@@ -250,8 +218,6 @@ export const domainData = ({
entryLabelPlural: 'calculations',
entryTitle: () => 'Quantum-computer calculation',
searchPlaceholder: 'enter atoms',
searchVisualizations: {
},
/**
* Metrics are used to show values for aggregations. Each metric has a key (used
* for API calls), a label (used in the select form), and result string (to show
......
/*
* Copyright The NOMAD Authors.
*
* This file is part of NOMAD. See https://nomad-lab.eu for further info.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useContext, useEffect } from 'react'
import { Grid } from '@material-ui/core'
import QuantityHistogram from '../search/QuantityHistogram'
import { searchContext } from '../search/SearchContext'
export default function EMSVisualizations(props) {
const {setStatistics} = useContext(searchContext)
useEffect(() => {
setStatistics(['ems.method', 'ems.probing_method', 'ems.sample_microstructure', 'ems.sample_constituents'])
// eslint-disable-next-line
}, [])
return (
<Grid container spacing={2}>
<Grid item xs={6}>
<QuantityHistogram quantity="ems.method" title="Method" />
<QuantityHistogram quantity="ems.probing_method" title="Probing" />
</Grid>
<Grid item xs={6}>
<QuantityHistogram quantity="ems.sample_microstructure" title="Sample structure" />
<QuantityHistogram quantity="ems.sample_constituents" title="Sample constituents" />
</Grid>
</Grid>
)
}
......@@ -22,6 +22,10 @@ import LockIcon from '@material-ui/icons/Lock'
import { Chip } from '@material-ui/core'
import PropTypes from 'prop-types'
/**
* Thin wrapper for MUI Chip that is used for displaying (and possibly removing)
* filter values.
*/
const useStyles = makeStyles(theme => ({
root: {
padding: theme.spacing(0.5)
......
This diff is collapsed.
......@@ -22,13 +22,13 @@ import PropTypes from 'prop-types'
import clsx from 'clsx'
import { isNil, isPlainObject } from 'lodash'
import FilterChip from './FilterChip'
import { useFiltersState, useFiltersLockedState } from './FilterContext'
import { useFiltersState, useFiltersLockedState } from './SearchContext'
import { formatMeta } from '../../utils'
import { useUnits } from '../../units'
/**
* Displays an interactable summary for a given subset of filters
* (=searchQuantities).
* Displays a summary for the given subset of filters. Each filter value is
* displayed as a chip.
*/
const useStyles = makeStyles(theme => {
const padding = theme.spacing(2)
......
/*
* Copyright The NOMAD Authors.
*
* This file is part of NOMAD. See https://nomad-lab.eu for further info.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState } from 'react'
import clsx from 'clsx'
import PropTypes from 'prop-types'
import { makeStyles } from '@material-ui/core/styles'
import FilterMainMenu from './menus/FilterMainMenu'
import NewSearchBar from './NewSearchBar'
import SearchResults from './results/SearchResults'
import {
useMenuOpenState
} from './FilterContext'
const useStyles = makeStyles(theme => {
return {
root: {
display: 'flex',
height: '100%',
width: '100%',
overflow: 'hidden'
},
leftColumn: {
flexShrink: 0,
flexGrow: 0,
height: '100%',
zIndex: 2
},
leftColumnCollapsed: {
maxWidth: '4rem'
},
center: {
flex: `1 1 100%`,
display: 'flex',
flexDirection: 'column',
zIndex: 1,
paddingBottom: theme.spacing(2.5),
paddingLeft: theme.spacing(3),
paddingRight: theme.spacing(3),
paddingTop: theme.spacing(0.25)
},
container: {
},
resultList: {
flexGrow: 1,
minHeight: 0 // This makes sure that the flex item is not bigger than the parent.
},
spacer: {
flexGrow: 1
},
header: {
marginTop: theme.spacing(2)
},
searchBar: {
marginTop: theme.spacing(2),
display: 'flex',
flexGrow: 0,
zIndex: 1,
marginBottom: theme.spacing(2.0)
},
spacerBar: {
flex: `0 0 ${theme.spacing(3)}px`
},
nonInteractive: {
pointerEvents: 'none',
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
top: 0,
height: '100%',
width: '100%'
},
shadow: {
backgroundColor: 'black',
transition: 'opacity 200ms',
willChange: 'opacity',
zIndex: 1
},
hidden: {
display: 'none'
},
shadowHidden: {
opacity: 0
},
shadowVisible: {
opacity: 0.1
},
placeholderVisible: {
display: 'block'
}
}
})
const NewSearch = React.memo(({
collapsed,
header
}) => {
const styles = useStyles()
const [isMenuOpen, setIsMenuOpen] = useMenuOpenState(false)
const [isCollapsed, setIsCollapsed] = useState(collapsed)
return <div className={styles.root}>
<div className={clsx(styles.leftColumn, isCollapsed && styles.leftColumnCollapsed)}>
<FilterMainMenu
open={isMenuOpen}
onOpenChange={setIsMenuOpen}
collapsed={isCollapsed}
onCollapsedChange={setIsCollapsed}
/>
</div>
<div className={styles.center} onClick={() => setIsMenuOpen(false)}>
<div className={styles.header}>
{header}
</div>
<NewSearchBar
className={styles.searchBar}
/>
<SearchResults
className={styles.resultList}
/>
<div className={clsx(styles.nonInteractive, styles.shadow, styles.shadowHidden, isMenuOpen && styles.shadowVisible)}></div>
</div>
</div>
})
NewSearch.propTypes = {
collapsed: PropTypes.bool,
header: PropTypes.node
}
export default NewSearch
/*
* Copyright The NOMAD Authors.
*
* This file is part of NOMAD. See https://nomad-lab.eu for further info.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useCallback, useState, useMemo } from 'react'
import PropTypes from 'prop-types'
import clsx from 'clsx'
import { debounce, isNil } from 'lodash'
import Autocomplete from '@material-ui/lab/Autocomplete'
import { makeStyles } from '@material-ui/core/styles'
import SearchIcon from '@material-ui/icons/Search'
import CloseIcon from '@material-ui/icons/Close'
import {
TextField,
CircularProgress,
Paper,
Divider,
Tooltip,
Typography
} from '@material-ui/core'
import IconButton from '@material-ui/core/IconButton'
import { useApi } from '../apiV1'
import { useUnits } from '../../units'
import { isMetaNumber, isMetaTimestamp } from '../../utils'
import {
useSetFilters,
useFiltersLocked,
filterFullnames,
filterAbbreviations,
toGUIFilter,
filterData,
filters
} from './FilterContext'
import searchQuantities from '../../searchQuantities'
const opMap = {
'<=': 'lte',
'>=': 'gte',
'>': 'gt',
'<': 'lt'
}
const opMapReverse = {
'<=': 'gte',
'>=': 'lte',
'>': 'lt',
'<': 'gt'
}
// Decides which options are shown
const filterOptions = (options, {inputValue}) => {
const trimmed = inputValue.trim().toLowerCase()
return options.filter(option => {
// ES results do not need to be filtered at all
const category = option.category
if (category !== 'quantity name') {
return true
}
// Underscore can be replaced by a whitespace
const optionClean = option.value.trim().toLowerCase()
const matchUnderscore = optionClean.includes(trimmed)
const matchNoUnderscore = optionClean.replaceAll('_', ' ').includes(trimmed)
return matchUnderscore || matchNoUnderscore
})
}
// Customized paper component for the autocompletion options