Skip to content
Snippets Groups Projects
Commit e65117b5 authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Added correct quantity name transformations for material queries.

parent 02b56b80
No related branches found
No related tags found
4 merge requests!548Release v1,!461Draft: remove owner key from the query,!407Fix a bug concerning outcar parser,!382Materials Search
...@@ -155,7 +155,7 @@ export const SearchContext = React.memo(({ ...@@ -155,7 +155,7 @@ export const SearchContext = React.memo(({
}) => { }) => {
const setQuery = useSetRecoilState(queryState) const setQuery = useSetRecoilState(queryState)
const api = useApi() const api = useApi()
const setInitialAggs = useSetRecoilState(initialAggs) const setInitialAggs = useSetRecoilState(initialAggsState)
// Reset the query when entering the search context for the first time // Reset the query when entering the search context for the first time
useEffect(() => { useEffect(() => {
...@@ -184,16 +184,16 @@ export const SearchContext = React.memo(({ ...@@ -184,16 +184,16 @@ export const SearchContext = React.memo(({
// Fetch initial aggregation data. We include all data here. // Fetch initial aggregation data. We include all data here.
useEffect(() => { useEffect(() => {
const aggRequest = {} let aggRequest = {}
for (const [quantity, agg] of Object.entries(quantityAggregations)) { for (const [quantity, agg] of Object.entries(quantityAggregations)) {
const key = resource === 'materials' ? quantityMaterialNames[quantity] : quantity aggRequest[quantity] = {
aggRequest[key] = {
[agg]: { [agg]: {
quantity: key, quantity: quantity,
size: 500 size: 500
} }
} }
} }
aggRequest = cleanAggRequest(aggRequest, resource)
const search = { const search = {
owner: 'visible', owner: 'visible',
query: {}, query: {},
...@@ -203,6 +203,7 @@ export const SearchContext = React.memo(({ ...@@ -203,6 +203,7 @@ export const SearchContext = React.memo(({
api.query(resource, search, false) api.query(resource, search, false)
.then(data => { .then(data => {
data = cleanAggResponse(data, resource)
setInitialAggs(data) setInitialAggs(data)
}) })
}, [api, setInitialAggs, resource]) }, [api, setInitialAggs, resource])
...@@ -526,7 +527,7 @@ function queryToQs(query) { ...@@ -526,7 +527,7 @@ function queryToQs(query) {
return qs.stringify(newQuery, {indices: false, encode: false}) return qs.stringify(newQuery, {indices: false, encode: false})
} }
export const initialAggs = atom({ export const initialAggsState = atom({
key: 'initialAggs', key: 'initialAggs',
default: undefined default: undefined
}) })
...@@ -537,12 +538,8 @@ export const initialAggs = atom({ ...@@ -537,12 +538,8 @@ export const initialAggs = atom({
* @returns {object} Object containing the search object. * @returns {object} Object containing the search object.
*/ */
export function useInitialAgg(quantity, agg) { export function useInitialAgg(quantity, agg) {
const aggs = useRecoilValue(initialAggs) const aggs = useRecoilValue(initialAggsState)
let data = aggs && aggs?.aggregations?.[quantity]?.[agg].data return getAggData(aggs, quantity, agg)
if (agg === 'min_max' && !data) {
data = [undefined, undefined]
}
return data
} }
/** /**
...@@ -564,7 +561,7 @@ export function useAgg(quantity, type, restrict = false, update = true, delay = ...@@ -564,7 +561,7 @@ export function useAgg(quantity, type, restrict = false, update = true, delay =
const api = useApi() const api = useApi()
const { resource } = useSearchContext() const { resource } = useSearchContext()
const [results, setResults] = useState(type === 'min_max' ? [undefined, undefined] : undefined) const [results, setResults] = useState(type === 'min_max' ? [undefined, undefined] : undefined)
const initialAgg = useInitialAgg(quantity, type) const initialAggs = useRecoilValue(initialAggsState)
const query = useQuery() const query = useQuery()
const exclusive = useExclusive() const exclusive = useExclusive()
const firstLoad = useRef(true) const firstLoad = useRef(true)
...@@ -580,32 +577,31 @@ export function useAgg(quantity, type, restrict = false, update = true, delay = ...@@ -580,32 +577,31 @@ export function useAgg(quantity, type, restrict = false, update = true, delay =
if (restrict && query && quantity in query) { if (restrict && query && quantity in query) {
queryCleaned[quantity] = undefined queryCleaned[quantity] = undefined
} }
queryCleaned = cleanQuery(queryCleaned, exclusive) queryCleaned = cleanQuery(queryCleaned, exclusive, resource)
const key = resource === 'materials' ? quantityMaterialNames[quantity] : quantity let aggRequest = {
const aggs = { [quantity]: {
[key]: {
[type]: { [type]: {
quantity: key, quantity: quantity,
size: 500 size: 500
} }
} }
} }
aggRequest = cleanAggRequest(aggRequest, resource)
const search = { const search = {
owner: query.owner || 'visible', owner: query.owner || 'visible',
query: queryCleaned, query: queryCleaned,
aggregations: resource === 'entries' ? aggs : undefined, aggregations: aggRequest,
pagination: {page_size: 0}, pagination: {page_size: 0},
required: { include: [] } required: { include: [] }
} }
api.query(resource, search, false) api.query(resource, search, false)
.then(data => { .then(data => {
let cleaned = data && data.aggregations[key][type].data data = cleanAggResponse(data, resource)
if (type === 'min_max' && !cleaned) { data = getAggData(data, quantity, type)
cleaned = [undefined, undefined]
}
firstLoad.current = false firstLoad.current = false
setResults(cleaned) setResults(data)
}) })
}, [api, quantity, restrict, type, resource]) }, [api, quantity, restrict, type, resource])
...@@ -622,7 +618,7 @@ export function useAgg(quantity, type, restrict = false, update = true, delay = ...@@ -622,7 +618,7 @@ export function useAgg(quantity, type, restrict = false, update = true, delay =
// Fetch the initial aggregation values if no query // Fetch the initial aggregation values if no query
// is specified. // is specified.
if (isEmpty(query)) { if (isEmpty(query)) {
setResults(initialAgg) setResults(getAggData(initialAggs, quantity, type))
// Make an immediate request for the aggregation values if query has been // Make an immediate request for the aggregation values if query has been
// specified. // specified.
} else { } else {
...@@ -631,7 +627,7 @@ export function useAgg(quantity, type, restrict = false, update = true, delay = ...@@ -631,7 +627,7 @@ export function useAgg(quantity, type, restrict = false, update = true, delay =
} else { } else {
debounced(query, exclusive) debounced(query, exclusive)
} }
}, [apiCall, quantity, debounced, query, exclusive, update, initialAgg]) }, [apiCall, quantity, debounced, query, exclusive, update, initialAggs])
return results return results
} }
...@@ -667,7 +663,7 @@ export function useScrollResults(pageSize, orderBy, order, exclusive, delay = 50 ...@@ -667,7 +663,7 @@ export function useScrollResults(pageSize, orderBy, order, exclusive, delay = 50
// one with the data. // one with the data.
const apiCall = useCallback((query, pageSize, orderBy, order, exclusive) => { const apiCall = useCallback((query, pageSize, orderBy, order, exclusive) => {
pageAfterValue.current = undefined pageAfterValue.current = undefined
const cleanedQuery = cleanQuery(query, exclusive) const cleanedQuery = cleanQuery(query, exclusive, resource)
const search = { const search = {
owner: query.owner || 'visible', owner: query.owner || 'visible',
query: cleanedQuery, query: cleanedQuery,
...@@ -749,7 +745,8 @@ export function useScrollResults(pageSize, orderBy, order, exclusive, delay = 50 ...@@ -749,7 +745,8 @@ export function useScrollResults(pageSize, orderBy, order, exclusive, delay = 50
/** /**
* Converts all sets to arrays and convert all Quantities into their SI unit * Converts all sets to arrays and convert all Quantities into their SI unit
* values. * values. Also remaps quantity names depending whether materials or entries are
* requested.
* *
* Should only be called when making the final API call, as during the * Should only be called when making the final API call, as during the
* construction of the query it is much more convenient to store filters within * construction of the query it is much more convenient to store filters within
...@@ -761,10 +758,11 @@ export function useScrollResults(pageSize, orderBy, order, exclusive, delay = 50 ...@@ -761,10 +758,11 @@ export function useScrollResults(pageSize, orderBy, order, exclusive, delay = 50
* @returns {object} A copy of the object with certain items cleaned into a * @returns {object} A copy of the object with certain items cleaned into a
* format that is supported by the API. * format that is supported by the API.
*/ */
export function cleanQuery(query, exclusive) { export function cleanQuery(query, exclusive, resource) {
let newQuery = {} let newQuery = {}
for (let [k, v] of Object.entries(query)) { for (let [k, v] of Object.entries(query)) {
let newValue let newValue
let postfix
// Some quantities are not included in the query, e.g. the owner. // Some quantities are not included in the query, e.g. the owner.
if (k === 'owner') { if (k === 'owner') {
...@@ -774,7 +772,7 @@ export function cleanQuery(query, exclusive) { ...@@ -774,7 +772,7 @@ export function cleanQuery(query, exclusive) {
if (v.size === 0) { if (v.size === 0) {
continue continue
} }
k = `${k}:all` postfix = 'all'
newValue = setToArray(v) newValue = setToArray(v)
// If an exlusive elements query is made, we sort the elements and // If an exlusive elements query is made, we sort the elements and
// concatenate them into a single string. This value we can then use to // concatenate them into a single string. This value we can then use to
...@@ -793,7 +791,7 @@ export function cleanQuery(query, exclusive) { ...@@ -793,7 +791,7 @@ export function cleanQuery(query, exclusive) {
} else { } else {
newValue = newValue.map((item) => item instanceof Quantity ? item.toSI() : item) newValue = newValue.map((item) => item instanceof Quantity ? item.toSI() : item)
} }
k = `${k}:any` postfix = 'any'
} else if (v instanceof Quantity) { } else if (v instanceof Quantity) {
newValue = v.toSI() newValue = v.toSI()
} else if (isArray(v)) { } else if (isArray(v)) {
...@@ -802,15 +800,69 @@ export function cleanQuery(query, exclusive) { ...@@ -802,15 +800,69 @@ export function cleanQuery(query, exclusive) {
} else { } else {
newValue = v.map((item) => item instanceof Quantity ? item.toSI() : item) newValue = v.map((item) => item instanceof Quantity ? item.toSI() : item)
} }
k = `${k}:any` postfix = 'any'
} else if (isPlainObject(v)) { } else if (isPlainObject(v)) {
newValue = cleanQuery(v, exclusive) newValue = cleanQuery(v, exclusive, resource)
} else { } else {
newValue = v newValue = v
} }
} }
console.log(k)
k = resource === 'materials' ? quantityMaterialNames[k] : k
k = postfix ? `${k}:${postfix}` : k
newQuery[k] = newValue newQuery[k] = newValue
} }
} }
return newQuery return newQuery
} }
/**
* Modified aggregation keys depending the the targeted resource. Should only
* be called when making the final API call.
*
* @returns {object} A copy of the object with certain items cleaned into a
* format that is supported by the API.
*/
function cleanAggRequest(aggs, resource) {
if (resource === 'materials') {
let newAggs = {}
for (let [label, agg] of Object.entries(aggs)) {
label = resource === 'materials' ? quantityMaterialNames[label] : label
for (let v of Object.values(agg)) {
v.quantity = label
}
newAggs[label] = agg
}
return newAggs
}
return aggs
}
/**
* Cleans the aggregation response into a format that is usable by the GUI.
*
* @returns {object} A copy of the object with the correct quantity names used
* by the GUI.
*/
function cleanAggResponse(response, resource) {
if (resource === 'materials') {
const newAggs = {}
for (let [label, agg] of Object.entries(response.aggregations)) {
label = resource === 'materials' ? quantityEntryNames[label] : label
for (let v of Object.values(agg)) {
v.quantity = label
}
newAggs[label] = agg
}
response.aggregations = newAggs
}
return response
}
function getAggData(aggs, quantity, type) {
let agg = aggs && aggs.aggregations?.[quantity]?.[type]?.data
if (type === 'min_max' && !agg) {
agg = [undefined, undefined]
}
return agg
}
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import React, { useCallback, useEffect, useState, useRef } from 'react' import React, { useCallback, useEffect, useState } from 'react'
import { makeStyles, useTheme } from '@material-ui/core/styles' import { makeStyles, useTheme } from '@material-ui/core/styles'
import { import {
Grid, Grid,
...@@ -55,7 +55,6 @@ const InputCheckboxes = React.memo(({ ...@@ -55,7 +55,6 @@ const InputCheckboxes = React.memo(({
const initialAgg = useInitialAgg(quantity, 'terms') const initialAgg = useInitialAgg(quantity, 'terms')
const availableOptions = useAgg(quantity, 'terms', true, visible) const availableOptions = useAgg(quantity, 'terms', true, visible)
const [filter, setFilter] = useFilterState(quantity) const [filter, setFilter] = useFilterState(quantity)
const firstFetch = useRef(true)
// Determine the description and units // Determine the description and units
const def = searchQuantities[quantity] const def = searchQuantities[quantity]
...@@ -66,7 +65,7 @@ const InputCheckboxes = React.memo(({ ...@@ -66,7 +65,7 @@ const InputCheckboxes = React.memo(({
// Save the available options when retrieved for the first time (without any // Save the available options when retrieved for the first time (without any
// filters) // filters)
useEffect(() => { useEffect(() => {
if (initialAgg && firstFetch.current) { if (initialAgg) {
const opt = {} const opt = {}
for (let option of initialAgg) { for (let option of initialAgg) {
if (option.count > 0) { if (option.count > 0) {
...@@ -80,7 +79,6 @@ const InputCheckboxes = React.memo(({ ...@@ -80,7 +79,6 @@ const InputCheckboxes = React.memo(({
} }
} }
setVisibleOptions(opt) setVisibleOptions(opt)
firstFetch.current = false
} }
}, [options, initialAgg]) }, [options, initialAgg])
......
...@@ -43,6 +43,7 @@ const InputRadio = React.memo(({ ...@@ -43,6 +43,7 @@ const InputRadio = React.memo(({
quantity, quantity,
label, label,
description, description,
initialValue,
options, options,
className, className,
classes, classes,
...@@ -58,7 +59,7 @@ const InputRadio = React.memo(({ ...@@ -58,7 +59,7 @@ const InputRadio = React.memo(({
return <div className={clsx(className, styles.root)} data-testid={testID}> return <div className={clsx(className, styles.root)} data-testid={testID}>
<InputLabel label={label} description={description}/> <InputLabel label={label} description={description}/>
<RadioGroup aria-label={label} name={label} value={filter || 'visible'} onChange={handleChange}> <RadioGroup aria-label={label} name={label} value={filter || initialValue} onChange={handleChange}>
{options && Object.entries(options).map(([key, value]) => {options && Object.entries(options).map(([key, value]) =>
<FormControlLabel key={key} value={key} control={<Radio disabled={value.disabled}/>} label={ <FormControlLabel key={key} value={key} control={<Radio disabled={value.disabled}/>} label={
<Tooltip placement="right" enterDelay={500} title={value.tooltip}> <Tooltip placement="right" enterDelay={500} title={value.tooltip}>
...@@ -74,6 +75,7 @@ InputRadio.propTypes = { ...@@ -74,6 +75,7 @@ InputRadio.propTypes = {
quantity: PropTypes.string.isRequired, quantity: PropTypes.string.isRequired,
label: PropTypes.string, label: PropTypes.string,
description: PropTypes.string, description: PropTypes.string,
initialValue: PropTypes.string,
options: PropTypes.object, // Mapping from option name to show label and tooltip options: PropTypes.object, // Mapping from option name to show label and tooltip
className: PropTypes.string, className: PropTypes.string,
classes: PropTypes.object, classes: PropTypes.object,
......
...@@ -36,6 +36,7 @@ const FilterSubMenuAccess = React.memo(({ ...@@ -36,6 +36,7 @@ const FilterSubMenuAccess = React.memo(({
quantity="owner" quantity="owner"
label="Visibility" label="Visibility"
description="The visibility of the calculation." description="The visibility of the calculation."
initialValue={authenticated ? 'visible' : 'public'}
options={{ options={{
all: {label: 'All', disabled: !authenticated, tooltip: 'Consider all entries.'}, all: {label: 'All', disabled: !authenticated, tooltip: 'Consider all entries.'},
public: {label: 'Public', disabled: false, tooltip: 'Consider all entries that can be publically downloaded, i.e. only published entries without embargo.'}, public: {label: 'Public', disabled: false, tooltip: 'Consider all entries that can be publically downloaded, i.e. only published entries without embargo.'},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment