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

Improved the options displayed by FilterCheckboxes.

parent e65117b5
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
......@@ -627,7 +627,7 @@ export function useAgg(quantity, type, restrict = false, update = true, delay =
} else {
debounced(query, exclusive)
}
}, [apiCall, quantity, debounced, query, exclusive, update, initialAggs])
}, [apiCall, quantity, debounced, query, exclusive, update, initialAggs, type])
return results
}
......@@ -807,7 +807,6 @@ export function cleanQuery(query, exclusive, resource) {
newValue = v
}
}
console.log(k)
k = resource === 'materials' ? quantityMaterialNames[k] : k
k = postfix ? `${k}:${postfix}` : k
newQuery[k] = newValue
......@@ -817,11 +816,10 @@ export function cleanQuery(query, exclusive, resource) {
}
/**
* Modified aggregation keys depending the the targeted resource. Should only
* be called when making the final API call.
* Cleans the aggregation request into a format that is usable by the API.
*
* @returns {object} A copy of the object with certain items cleaned into a
* format that is supported by the API.
* @returns {object} A copy of the object with the correct quantity names used
* by the API.
*/
function cleanAggRequest(aggs, resource) {
if (resource === 'materials') {
......
......@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useCallback, useEffect, useState } from 'react'
import React, { useCallback, useEffect, useState, useMemo } from 'react'
import { makeStyles, useTheme } from '@material-ui/core/styles'
import {
Grid,
......@@ -27,6 +27,7 @@ import clsx from 'clsx'
import searchQuantities from '../../../searchQuantities'
import InputLabel from './InputLabel'
import { useFilterState, useAgg, useInitialAgg } from '../FilterContext'
import { isArray } from 'lodash'
const useStyles = makeStyles(theme => ({
root: {
......@@ -52,9 +53,33 @@ const InputCheckboxes = React.memo(({
const theme = useTheme()
const styles = useStyles({classes: classes, theme: theme})
const [visibleOptions, setVisibleOptions] = useState()
const initialAgg = useInitialAgg(quantity, 'terms')
const availableOptions = useAgg(quantity, 'terms', true, visible)
const initialAgg = useInitialAgg(quantity, 'terms')
const [filter, setFilter] = useFilterState(quantity)
const finalOptions = useMemo(() => {
// If explicit options provided, use them
if (options) {
return options
}
// If the metainfo has enumerable options, use them
const quantities = searchQuantities?.[quantity]?.type?.type_data
if (isArray(quantities) && quantities.length > 0) {
const opt = {}
for (const name of quantities) {
opt[name] = {label: name}
}
return opt
}
// As a last resort, use the initial aggregation results as options.
if (initialAgg) {
const opt = {}
for (const value of initialAgg) {
opt[value.value] = {label: value.value}
}
return opt
}
return {}
}, [options, quantity, initialAgg])
// Determine the description and units
const def = searchQuantities[quantity]
......@@ -62,60 +87,36 @@ const InputCheckboxes = React.memo(({
const name = label || def?.name
const title = name
// Save the available options when retrieved for the first time (without any
// filters)
// Modify the checkboxes according to changing filters, changing aggregation
// results or change in the available options.
useEffect(() => {
if (initialAgg) {
const opt = {}
for (let option of initialAgg) {
if (option.count > 0) {
if (!options || options[option.value]) {
opt[option.value] = {
checked: false,
disabled: false,
label: options && options[option.value].label
}
}
}
const opt = {}
for (let [key, value] of Object.entries(finalOptions)) {
opt[key] = {
checked: filter ? filter.has(key) : false,
label: value.label,
disabled: true
}
setVisibleOptions(opt)
}
}, [options, initialAgg])
// React to changing filters
useEffect(() => {
setVisibleOptions(old => {
const newOptions = {}
if (old === undefined) {
return old
}
for (let key of Object.keys(old)) {
newOptions[key] = old[key]
newOptions[key].checked = filter ? filter.has(key) : false
}
return newOptions
})
}, [filter])
// React to changes in aggregation results. Options which were not selected
// beforehand will be disabled/enabled according to the aggregation data.
useEffect(() => {
if (initialAgg && availableOptions) {
const valueSet = new Set()
if (availableOptions) {
for (let value of availableOptions) {
if (value.count) {
valueSet.add(value.value)
const key = value.value
const selected = filter ? filter.has(key) : false
const oldState = opt[key]
const disabled = selected ? false : value.count === 0
if (oldState) {
oldState.disabled = disabled
} else {
opt[key] = {
label: key,
checked: false,
disabled: disabled
}
}
}
setVisibleOptions(old => {
const newOptions = {...old}
for (let key of Object.keys(old)) {
newOptions[key].disabled = !newOptions[key].checked && !valueSet.has(key)
}
return newOptions
})
}
}, [availableOptions, initialAgg])
setVisibleOptions(opt)
}, [availableOptions, filter, finalOptions])
const handleChange = useCallback((event) => {
const newOptions = {...visibleOptions}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment